diff --git a/UnicodeCharacterInspector/App.xaml b/UnicodeCharacterInspector/App.xaml
index 44d587c..281b4f0 100644
--- a/UnicodeCharacterInspector/App.xaml
+++ b/UnicodeCharacterInspector/App.xaml
@@ -7,7 +7,9 @@
-
+
+
+
diff --git a/UnicodeCharacterInspector/CharacterInfoViewModel.cs b/UnicodeCharacterInspector/CharacterInfoViewModel.cs
index 0f9d631..6b92310 100644
--- a/UnicodeCharacterInspector/CharacterInfoViewModel.cs
+++ b/UnicodeCharacterInspector/CharacterInfoViewModel.cs
@@ -67,6 +67,7 @@ namespace UnicodeCharacterInspector
NotifyPropertyChanged(nameof(NumericValue));
NotifyPropertyChanged(nameof(ContributoryProperties));
NotifyPropertyChanged(nameof(CoreProperties));
+ NotifyPropertyChanged(nameof(RadicalStrokeCounts));
NotifyPropertyChanged(nameof(CrossReferences));
NotifyPropertyChanged(nameof(MandarinReading));
NotifyPropertyChanged(nameof(CantoneseReading));
@@ -173,6 +174,11 @@ namespace UnicodeCharacterInspector
get { return character != null ? characterInfo.CoreProperties : null as CoreProperties?; }
}
+ public UnicodeRadicalStrokeCountCollection RadicalStrokeCounts
+ {
+ get { return character != null ? characterInfo.UnicodeRadicalStrokeCounts : new UnicodeRadicalStrokeCountCollection(); }
+ }
+
public UnicodeCrossReferenceCollection CrossReferences
{
get { return character != null ? characterInfo.CrossRerefences : new UnicodeCrossReferenceCollection(); }
diff --git a/UnicodeCharacterInspector/MainWindow.xaml b/UnicodeCharacterInspector/MainWindow.xaml
index 80cfb98..601871f 100644
--- a/UnicodeCharacterInspector/MainWindow.xaml
+++ b/UnicodeCharacterInspector/MainWindow.xaml
@@ -87,6 +87,7 @@
+
@@ -105,52 +106,64 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
- • “” U+
+ Radical (), strokes
+
+
+
+
+
+
+ “” U+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ “” U+
diff --git a/UnicodeCharacterInspector/RadicalStrokeCountToCharConverter.cs b/UnicodeCharacterInspector/RadicalStrokeCountToCharConverter.cs
new file mode 100644
index 0000000..9aee325
--- /dev/null
+++ b/UnicodeCharacterInspector/RadicalStrokeCountToCharConverter.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Globalization;
+using System.Unicode;
+using System.Windows.Data;
+
+namespace UnicodeCharacterInspector
+{
+ internal sealed class RadicalStrokeCountToCharConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value == null) return null;
+
+ var radicalStrokeCount = (UnicodeRadicalStrokeCount)value;
+ var radical = UnicodeInfo.GetCjkRadicalInfo(radicalStrokeCount.Radical);
+
+ return radicalStrokeCount.IsSimplified ? radical.TraditionalRadicalCodePoint : radical.SimplifiedRadicalCodePoint;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/UnicodeCharacterInspector/StringToUtf32Converter.cs b/UnicodeCharacterInspector/StringToUtf32Converter.cs
new file mode 100644
index 0000000..d6c6b36
--- /dev/null
+++ b/UnicodeCharacterInspector/StringToUtf32Converter.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace UnicodeCharacterInspector
+{
+ internal class StringToUtf32Converter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ string text = value as string;
+
+ if (!string.IsNullOrEmpty(text)) return char.ConvertToUtf32(text, 0);
+ else return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/UnicodeCharacterInspector/UnicodeCharacterInspector.csproj b/UnicodeCharacterInspector/UnicodeCharacterInspector.csproj
index e622ee6..7dc17f9 100644
--- a/UnicodeCharacterInspector/UnicodeCharacterInspector.csproj
+++ b/UnicodeCharacterInspector/UnicodeCharacterInspector.csproj
@@ -77,6 +77,8 @@
Placeholder.cs
+
+
diff --git a/UnicodeInformation.Builder/Program.cs b/UnicodeInformation.Builder/Program.cs
index 68af15e..31e0359 100644
--- a/UnicodeInformation.Builder/Program.cs
+++ b/UnicodeInformation.Builder/Program.cs
@@ -21,6 +21,7 @@ namespace System.Unicode.Builder
"UnicodeData.txt",
"PropList.txt",
"DerivedCoreProperties.txt",
+ "CJKRadicals.txt",
//"Jamo.txt", // Not used right now, as the hangul syllable algorithm implementation takes care of this.
"NameAliases.txt",
"NamesList.txt",
diff --git a/UnicodeInformation.Builder/UnicodeCharacterDataBuilder.cs b/UnicodeInformation.Builder/UnicodeCharacterDataBuilder.cs
index ac33310..d818f73 100644
--- a/UnicodeInformation.Builder/UnicodeCharacterDataBuilder.cs
+++ b/UnicodeInformation.Builder/UnicodeCharacterDataBuilder.cs
@@ -37,7 +37,7 @@ namespace System.Unicode.Builder
set { name = value; }
}
- public ICollection NameAliases { get { return nameAliases; } }
+ public IList NameAliases { get { return nameAliases; } }
public UnicodeCategory Category
{
@@ -124,7 +124,7 @@ namespace System.Unicode.Builder
set { coreProperties = value; }
}
- public ICollection CrossRerefences { get { return crossRerefences; } }
+ public IList CrossRerefences { get { return crossRerefences; } }
public UnicodeCharacterDataBuilder(int codePoint)
: this(new UnicodeCharacterRange(codePoint))
diff --git a/UnicodeInformation.Builder/UnicodeDataProcessor.cs b/UnicodeInformation.Builder/UnicodeDataProcessor.cs
index bd1abc3..fb8ccd7 100644
--- a/UnicodeInformation.Builder/UnicodeDataProcessor.cs
+++ b/UnicodeInformation.Builder/UnicodeDataProcessor.cs
@@ -13,6 +13,7 @@ namespace System.Unicode.Builder
public const string UnicodeDataFileName = "UnicodeData.txt";
public const string PropListFileName = "PropList.txt";
public const string DerivedCorePropertiesFileName = "DerivedCoreProperties.txt";
+ public const string CjkRadicalsFileName = "CJKRadicals.txt";
public const string NameAliasesFileName = "NameAliases.txt";
public const string NamesListFileName = "NamesList.txt";
public const string BlocksFileName = "Blocks.txt";
@@ -40,6 +41,7 @@ namespace System.Unicode.Builder
await ProcessUnicodeDataFile(ucdSource, builder).ConfigureAwait(false);
await ProcessPropListFile(ucdSource, builder).ConfigureAwait(false);
await ProcessDerivedCorePropertiesFile(ucdSource, builder).ConfigureAwait(false);
+ await ProcessCjkRadicalsFile(ucdSource, builder).ConfigureAwait(false);
await ProcessNameAliasesFile(ucdSource, builder).ConfigureAwait(false);
await ProcessNamesListFile(ucdSource, builder).ConfigureAwait(false);
await ProcessBlocksFile(ucdSource, builder).ConfigureAwait(false);
@@ -202,6 +204,53 @@ namespace System.Unicode.Builder
}
}
+ private static async Task ProcessCjkRadicalsFile(IDataSource ucdSource, UnicodeInfoBuilder builder)
+ {
+ using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(CjkRadicalsFileName).ConfigureAwait(false), ';'))
+ {
+ int lastReadRadical = 0;
+
+ while (reader.MoveToNextLine())
+ {
+ string radicalIndexText = reader.ReadField();
+ bool isSimplified = radicalIndexText[radicalIndexText.Length - 1] == '\'';
+ int radicalIndex = int.Parse(isSimplified ? radicalIndexText.Substring(0, radicalIndexText.Length - 1) : radicalIndexText);
+
+ if (isSimplified ? radicalIndex != lastReadRadical : lastReadRadical + 1 != (lastReadRadical = radicalIndex))
+ throw new InvalidDataException("Did not expect radical number " + radicalIndexText + ".");
+
+ char radicalCodePoint = checked((char)int.Parse(reader.ReadTrimmedField(), NumberStyles.HexNumber));
+ char characterCodePoint = checked((char)int.Parse(reader.ReadTrimmedField(), NumberStyles.HexNumber));
+
+ if (!isSimplified && (radicalCodePoint & 0x8000) != 0)
+ throw new InvalidOperationException("Did not expect the radical code point to be higher than U+8000 for radical " + radicalIndex.ToString() + ".");
+
+ if (isSimplified)
+ {
+ builder.SetRadicalInfo(radicalIndex, UpdateRadicalData(builder.GetRadicalInfo(radicalIndex), radicalCodePoint, characterCodePoint));
+ }
+ else
+ {
+ builder.SetRadicalInfo(radicalIndex, new CjkRadicalData(radicalCodePoint, characterCodePoint));
+ }
+ }
+
+ if (lastReadRadical != UnicodeInfoBuilder.CjkRadicalCount)
+ throw new InvalidOperationException("There was not enough data for the 214 CJK radicals.");
+ }
+ }
+
+ private static CjkRadicalData UpdateRadicalData(CjkRadicalData traditionalData, char simplifiedRadicalCodePoint, char simplifiedCharacterCodePoint)
+ {
+ return new CjkRadicalData
+ (
+ traditionalData.TraditionalRadicalCodePoint,
+ traditionalData.TraditionalCharacterCodePoint,
+ simplifiedRadicalCodePoint,
+ simplifiedCharacterCodePoint
+ );
+ }
+
private static async Task ProcessNameAliasesFile(IDataSource ucdSource, UnicodeInfoBuilder builder)
{
using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(NameAliasesFileName).ConfigureAwait(false), ';'))
@@ -475,7 +524,7 @@ namespace System.Unicode.Builder
SeparatorFound: ;
entry.UnicodeRadicalStrokeCounts.Add(new UnicodeRadicalStrokeCount(byte.Parse(value.Substring(0, index), NumberStyles.None), byte.Parse(value.Substring(index + (isSimplified ? 2 : 1)), NumberStyles.None), isSimplified));
}
- break;
+ break;
default:
// Ignore unhandled properties for now.
break;
diff --git a/UnicodeInformation.Builder/UnicodeInfoBuilder.cs b/UnicodeInformation.Builder/UnicodeInfoBuilder.cs
index 91bdc42..5baf51d 100644
--- a/UnicodeInformation.Builder/UnicodeInfoBuilder.cs
+++ b/UnicodeInformation.Builder/UnicodeInfoBuilder.cs
@@ -9,12 +9,15 @@ namespace System.Unicode.Builder
{
internal class UnicodeInfoBuilder
{
+ public const int CjkRadicalCount = 214; // The number of radicals (214) shouldn't change in the near future…
+
private readonly Version unicodeVersion;
private UnicodeCharacterDataBuilder[] ucdEntries = new UnicodeCharacterDataBuilder[10000];
private int ucdEntryCount;
private UnihanCharacterDataBuilder[] unihanEntries = new UnihanCharacterDataBuilder[10000];
private int unihanEntryCount;
- private List blockEntries = new List(100);
+ private readonly List blockEntries = new List(100);
+ private readonly CjkRadicalData[] cjkRadicals = new CjkRadicalData[CjkRadicalCount];
public UnicodeInfoBuilder(Version unicodeVersion)
{
@@ -238,6 +241,20 @@ namespace System.Unicode.Builder
}
}
+ public void SetRadicalInfo(int radicalIndex, CjkRadicalData data)
+ {
+ if (radicalIndex < 1 || radicalIndex > CjkRadicalCount) throw new ArgumentOutOfRangeException(nameof(radicalIndex));
+
+ cjkRadicals[radicalIndex - 1] = data;
+ }
+
+ public CjkRadicalData GetRadicalInfo(int radicalIndex)
+ {
+ if (radicalIndex < 1 || radicalIndex > CjkRadicalCount) throw new ArgumentOutOfRangeException(nameof(radicalIndex));
+
+ return cjkRadicals[radicalIndex - 1];
+ }
+
public void AddBlockEntry(UnicodeBlock block)
{
blockEntries.Add(block);
@@ -283,6 +300,20 @@ namespace System.Unicode.Builder
{
WriteUnicodeBlockToFile(writer, blockEntries[i]);
}
+ writer.Write((byte)CjkRadicalCount);
+ for (int i = 0; i < cjkRadicals.Length; ++i)
+ {
+ var radical = cjkRadicals[i];
+
+ writer.Write((ushort)(radical.HasSimplifiedForm ? 0x8000 | radical.TraditionalRadicalCodePoint : radical.TraditionalRadicalCodePoint));
+ writer.Write((ushort)radical.TraditionalCharacterCodePoint);
+
+ if (radical.HasSimplifiedForm)
+ {
+ writer.Write((ushort)radical.SimplifiedRadicalCodePoint);
+ writer.Write((ushort)radical.SimplifiedCharacterCodePoint);
+ }
+ }
writer.WriteCodePoint(unihanEntryCount);
for (int i = 0; i < unihanEntryCount; ++i)
{
diff --git a/UnicodeInformation.Builder/UnihanCharacterDataBuilder.cs b/UnicodeInformation.Builder/UnihanCharacterDataBuilder.cs
index 4e805f8..f102994 100644
--- a/UnicodeInformation.Builder/UnihanCharacterDataBuilder.cs
+++ b/UnicodeInformation.Builder/UnihanCharacterDataBuilder.cs
@@ -38,7 +38,7 @@ namespace System.Unicode.Builder
public string VietnameseReading { get { return vietnameseReading; } set { vietnameseReading = value; } }
public string SimplifiedVariant { get { return simplifiedVariant; } set { simplifiedVariant = value; } }
public string TraditionalVariant { get { return traditionalVariant; } set { traditionalVariant = value; } }
- public ICollection UnicodeRadicalStrokeCounts { get { return unicodeRadicalStrokeCounts; } }
+ public IList UnicodeRadicalStrokeCounts { get { return unicodeRadicalStrokeCounts; } }
internal UnihanCharacterDataBuilder(int codePoint)
{
@@ -77,7 +77,7 @@ namespace System.Unicode.Builder
{
if (unicodeRadicalStrokeCounts.Count == 1) fields |= UnihanFields.UnicodeRadicalStrokeCount;
else if (unicodeRadicalStrokeCounts.Count == 2) fields |= UnihanFields.UnicodeRadicalStrokeCountTwice;
- else fields |= UnihanFields.UnicodeRadicalStrokeCount | UnihanFields.UnicodeRadicalStrokeCountTwice;
+ else fields |= UnihanFields.UnicodeRadicalStrokeCountMore;
}
if (Definition != null) fields |= UnihanFields.Definition;
if (MandarinReading != null) fields |= UnihanFields.MandarinReading;
@@ -93,6 +93,8 @@ namespace System.Unicode.Builder
writer.Write((ushort)fields);
writer.WriteCodePoint(UnihanCharacterData.PackCodePoint(codePoint));
+ if ((fields & UnihanFields.OtherNumeric) != 0) writer.Write(numericValue);
+
if ((fields & UnihanFields.UnicodeRadicalStrokeCountMore) != 0)
{
if ((fields & (UnihanFields.UnicodeRadicalStrokeCountMore)) == UnihanFields.UnicodeRadicalStrokeCountMore)
@@ -104,7 +106,7 @@ namespace System.Unicode.Builder
writer.Write((byte)(radicalStrokeCount.StrokeCount | (radicalStrokeCount.IsSimplified ? 0x80 : 0)));
}
}
- if ((fields & UnihanFields.OtherNumeric) != 0) writer.Write(numericValue);
+
if ((fields & UnihanFields.Definition) != 0) writer.Write(Definition);
if ((fields & UnihanFields.MandarinReading) != 0) writer.Write(MandarinReading);
if ((fields & UnihanFields.CantoneseReading) != 0) writer.Write(CantoneseReading);
diff --git a/UnicodeInformation.Tests/UnicodeInfoTests.cs b/UnicodeInformation.Tests/UnicodeInfoTests.cs
index 830c248..d13d361 100644
--- a/UnicodeInformation.Tests/UnicodeInfoTests.cs
+++ b/UnicodeInformation.Tests/UnicodeInfoTests.cs
@@ -153,6 +153,47 @@ namespace UnicodeInformation.Tests
Assert.AreEqual("Miscellaneous Symbols and Pictographs", UnicodeInfo.GetBlockName(0x1F574));
}
+ [TestMethod]
+ public void RadicalStrokeCountTest()
+ {
+ var char5E7A = UnicodeInfo.GetCharInfo(0x5E7A);
+
+ Assert.AreNotEqual(0, char5E7A.UnicodeRadicalStrokeCounts);
+ Assert.AreEqual(false, char5E7A.UnicodeRadicalStrokeCounts[0].IsSimplified);
+ Assert.AreEqual(char5E7A.UnicodeRadicalStrokeCounts[0].Radical, 52);
+ Assert.AreEqual(char5E7A.UnicodeRadicalStrokeCounts[0].StrokeCount, 0);
+
+ var char2A6D6 = UnicodeInfo.GetCharInfo(0x2A6D6);
+
+ Assert.AreNotEqual(0, char2A6D6.UnicodeRadicalStrokeCounts);
+ Assert.AreEqual(false, char2A6D6.UnicodeRadicalStrokeCounts[0].IsSimplified);
+ Assert.AreEqual(char2A6D6.UnicodeRadicalStrokeCounts[0].Radical, 214);
+ Assert.AreEqual(char2A6D6.UnicodeRadicalStrokeCounts[0].StrokeCount, 20);
+ }
+
+ [TestMethod]
+ public void RadicalInfoTest()
+ {
+ var radical1 = UnicodeInfo.GetCjkRadicalInfo(1);
+
+ Assert.AreEqual(false, radical1.HasSimplifiedForm);
+ Assert.AreEqual('\u2F00', radical1.TraditionalRadicalCodePoint);
+ Assert.AreEqual('\u4E00', radical1.TraditionalCharacterCodePoint);
+ Assert.AreEqual('\u2F00', radical1.SimplifiedRadicalCodePoint);
+ Assert.AreEqual('\u4E00', radical1.SimplifiedCharacterCodePoint);
+
+ var radical214 = UnicodeInfo.GetCjkRadicalInfo(214);
+
+ Assert.AreEqual(false, radical214.HasSimplifiedForm);
+ Assert.AreEqual('\u2FD5', radical214.TraditionalRadicalCodePoint);
+ Assert.AreEqual('\u9FA0', radical214.TraditionalCharacterCodePoint);
+ Assert.AreEqual('\u2FD5', radical214.SimplifiedRadicalCodePoint);
+ Assert.AreEqual('\u9FA0', radical214.SimplifiedCharacterCodePoint);
+
+ AssertEx.ThrowsExactly(() => UnicodeInfo.GetCjkRadicalInfo(0), nameof(UnicodeInfo.GetCjkRadicalInfo));
+ AssertEx.ThrowsExactly(() => UnicodeInfo.GetCjkRadicalInfo(215), nameof(UnicodeInfo.GetCjkRadicalInfo));
+ }
+
#if DEBUG
[TestMethod]
public void UnihanCodePointPackingTest()
diff --git a/UnicodeInformation/CjkRadicalData.cs b/UnicodeInformation/CjkRadicalData.cs
new file mode 100644
index 0000000..d673b9c
--- /dev/null
+++ b/UnicodeInformation/CjkRadicalData.cs
@@ -0,0 +1,28 @@
+namespace System.Unicode
+{
+ internal struct CjkRadicalData
+ {
+ public readonly char TraditionalRadicalCodePoint;
+ public readonly char TraditionalCharacterCodePoint;
+ public readonly char SimplifiedRadicalCodePoint;
+ public readonly char SimplifiedCharacterCodePoint;
+
+ internal CjkRadicalData(char radicalCodePoint, char characterCodePoint)
+ {
+ TraditionalRadicalCodePoint = radicalCodePoint;
+ TraditionalCharacterCodePoint = characterCodePoint;
+ SimplifiedRadicalCodePoint = radicalCodePoint;
+ SimplifiedCharacterCodePoint = characterCodePoint;
+ }
+
+ internal CjkRadicalData(char traditionalRadicalCodePoint, char traditionalCharacterCodePoint, char simplifiedRadicalCodePoint, char simplifiedCharacterCodePoint)
+ {
+ TraditionalRadicalCodePoint = traditionalRadicalCodePoint;
+ TraditionalCharacterCodePoint = traditionalCharacterCodePoint;
+ SimplifiedRadicalCodePoint = simplifiedCharacterCodePoint;
+ SimplifiedCharacterCodePoint = simplifiedCharacterCodePoint;
+ }
+
+ public bool HasSimplifiedForm { get { return SimplifiedRadicalCodePoint != TraditionalRadicalCodePoint || SimplifiedCharacterCodePoint != TraditionalCharacterCodePoint; } }
+ }
+}
diff --git a/UnicodeInformation/CjkRadicalInfo.cs b/UnicodeInformation/CjkRadicalInfo.cs
new file mode 100644
index 0000000..892d7ea
--- /dev/null
+++ b/UnicodeInformation/CjkRadicalInfo.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace System.Unicode
+{
+ public struct CjkRadicalInfo
+ {
+ private readonly byte radicalIndex;
+ private readonly CjkRadicalData radicalData;
+
+ public byte RadicalIndex { get { return radicalIndex; } }
+
+ public char TraditionalRadicalCodePoint { get { return radicalData.TraditionalRadicalCodePoint; } }
+ public char TraditionalCharacterCodePoint { get { return radicalData.TraditionalCharacterCodePoint; } }
+ public char SimplifiedRadicalCodePoint { get { return radicalData.SimplifiedRadicalCodePoint; } }
+ public char SimplifiedCharacterCodePoint { get { return radicalData.SimplifiedCharacterCodePoint; } }
+
+ public bool HasSimplifiedForm { get { return radicalData.HasSimplifiedForm; } }
+
+ internal CjkRadicalInfo(byte radicalIndex, CjkRadicalData radicalData)
+ {
+ this.radicalIndex = radicalIndex;
+ this.radicalData = radicalData;
+ }
+ }
+}
diff --git a/UnicodeInformation/UnicodeInfo.cs b/UnicodeInformation/UnicodeInfo.cs
index b72d6f4..fed813a 100644
--- a/UnicodeInformation/UnicodeInfo.cs
+++ b/UnicodeInformation/UnicodeInfo.cs
@@ -18,17 +18,18 @@ namespace System.Unicode
private static readonly UnicodeCharacterData[] unicodeCharacterData;
private static readonly UnihanCharacterData[] unihanCharacterData;
private static readonly UnicodeBlock[] blocks;
+ private static readonly CjkRadicalData[] radicals;
private static readonly int maxContiguousIndex;
static UnicodeInfo()
{
using (var stream = new DeflateStream(typeof(UnicodeInfo).GetTypeInfo().Assembly.GetManifestResourceStream("ucd.dat"), CompressionMode.Decompress, false))
{
- ReadFromStream(stream, out unicodeVersion, out unicodeCharacterData, out unihanCharacterData, out blocks, out maxContiguousIndex);
+ ReadFromStream(stream, out unicodeVersion, out unicodeCharacterData, out unihanCharacterData, out radicals, out blocks, out maxContiguousIndex);
}
}
- internal static void ReadFromStream(Stream stream, out Version unicodeVersion, out UnicodeCharacterData[] unicodeCharacterData, out UnihanCharacterData[] unihanCharacterData, out UnicodeBlock[] blocks, out int maxContiguousIndex)
+ internal static void ReadFromStream(Stream stream, out Version unicodeVersion, out UnicodeCharacterData[] unicodeCharacterData, out UnihanCharacterData[] unihanCharacterData, out CjkRadicalData[] radicals, out UnicodeBlock[] blocks, out int maxContiguousIndex)
{
using (var reader = new BinaryReader(stream, Encoding.UTF8))
{
@@ -73,6 +74,13 @@ namespace System.Unicode
blockEntries[i] = ReadBlockEntry(reader);
}
+ var cjkRadicalEntries = new CjkRadicalData[reader.ReadByte()];
+
+ for (i = 0; i < cjkRadicalEntries.Length; ++i)
+ {
+ cjkRadicalEntries[i] = ReadCjkRadicalInfo(reader);
+ }
+
var unihanCharacterDataEntries = new UnihanCharacterData[ReadCodePoint(reader)];
for (i = 0; i < unihanCharacterDataEntries.Length; ++i)
@@ -83,6 +91,7 @@ namespace System.Unicode
unicodeVersion = fileUnicodeVersion;
unicodeCharacterData = unicodeCharacterDataEntries;
unihanCharacterData = unihanCharacterDataEntries;
+ radicals = cjkRadicalEntries;
blocks = blockEntries;
}
}
@@ -227,6 +236,17 @@ namespace System.Unicode
);
}
+ private static CjkRadicalData ReadCjkRadicalInfo(BinaryReader reader)
+ {
+ char tr;
+ char tc;
+
+ tr = (char)reader.ReadUInt16();
+ tc = (char)reader.ReadUInt16();
+
+ return (tr & 0x8000) == 0 ? new CjkRadicalData(tr, tc) : new CjkRadicalData((char)(tr & 0x7FFF), tc, (char)reader.ReadUInt16(), (char)reader.ReadUInt16());
+ }
+
private static UnicodeBlock ReadBlockEntry(BinaryReader reader)
{
return new UnicodeBlock(new UnicodeCharacterRange(ReadCodePoint(reader), ReadCodePoint(reader)), reader.ReadString());
@@ -302,7 +322,7 @@ namespace System.Unicode
int minIndex;
int maxIndex;
- if (unihanCharacterData.Length == 0 || codePoint < unihanCharacterData[minIndex = 0].CodePoint || codePoint > unihanCharacterData[maxIndex = unicodeCharacterData.Length - 1].CodePoint)
+ if (unihanCharacterData.Length == 0 || codePoint < unihanCharacterData[minIndex = 0].CodePoint || codePoint > unihanCharacterData[maxIndex = unihanCharacterData.Length - 1].CodePoint)
{
return null;
}
@@ -340,6 +360,10 @@ namespace System.Unicode
return -1;
}
+ /// Gets the name of the Unicode block containing the character.
+ /// If the character has not been assigned to a block, the value of will be returned.
+ /// The Unicode code point whose block should be retrieved.
+ /// The name of the block the code point was assigned to.
public static string GetBlockName(int codePoint)
{
int i = FindBlockIndex(codePoint);
@@ -347,11 +371,43 @@ namespace System.Unicode
return i >= 0 ? blocks[i].Name : DefaultBlock;
}
+ /// Gets Unicode information on the specified code point.
+ ///
+ /// This method will consolidate the data from a few different sources.
+ /// There are more efficient way of retrieving the data for some properties if only one of those is needed at a time:
+ ///
+ ///
+ /// Property
+ /// Method
+ ///
+ /// -
+ /// Name
+ ///
+ ///
+ /// -
+ /// Category
+ ///
+ ///
+ /// -
+ /// Block
+ ///
+ ///
+ ///
+ ///
+ /// The Unicode code point for which the data must be retrieved.
+ /// The name of the code point, if defined; otherwise.
public static UnicodeCharInfo GetCharInfo(int codePoint)
{
return new UnicodeCharInfo(codePoint, FindUnicodeCodePoint(codePoint), FindUnihanCodePoint(codePoint), GetBlockName(codePoint));
}
+ /// Gets the category of the specified code point.
+ ///
+ /// The name referred to is the unicode General_Category property.
+ /// If you only need the category of a character, calling this method is faster than calling and retrieving , because there is less information to lookup.
+ ///
+ /// The Unicode code point for which the category must be retrieved.
+ /// The category of the code point.
public static UnicodeCategory GetCategory(int codePoint)
{
var charData = FindUnicodeCodePoint(codePoint);
@@ -359,6 +415,9 @@ namespace System.Unicode
return charData != null ? charData.Category : UnicodeCategory.OtherNotAssigned;
}
+ /// Gets a display text for the specified code point.
+ /// The information for the code point.
+ /// A display text for the code point, which may be the representation of the code point itself.
public static string GetDisplayText(UnicodeCharInfo charInfo)
{
if (charInfo.CodePoint <= 0x0020) return ((char)(0x2400 + charInfo.CodePoint)).ToString();
@@ -366,6 +425,9 @@ namespace System.Unicode
else return char.ConvertFromUtf32(charInfo.CodePoint);
}
+ /// Gets a display text for the specified code point.
+ /// The Unicode code point, for which a display text should be returned.
+ /// A display text for the code point, which may be the representation of the code point itself.
public static string GetDisplayText(int codePoint)
{
if (codePoint <= 0x0020) return ((char)(0x2400 + codePoint)).ToString();
@@ -373,6 +435,13 @@ namespace System.Unicode
else return char.ConvertFromUtf32(codePoint);
}
+ /// Gets the name of the specified code point.
+ ///
+ /// The name referred to is the unicode Name property.
+ /// If you only need the name of a character, calling this method is faster than calling and retrieving , because there is less information to lookup.
+ ///
+ /// The Unicode code point for which the name must be retrieved.
+ /// The name of the code point, if defined; otherwise.
public static string GetName(int codePoint)
{
if (HangulInfo.IsHangul(codePoint)) return HangulInfo.GetHangulName((char)codePoint);
@@ -387,6 +456,22 @@ namespace System.Unicode
else return null;
}
+ /// Returns information for a CJK radical.
+ /// The index of the radical. Must be between 1 and .
+ /// Information on the specified radical.
+ /// The parameter is out of range.
+ public static CjkRadicalInfo GetCjkRadicalInfo(int radicalIndex)
+ {
+ return new CjkRadicalInfo(checked((byte)radicalIndex), radicals[radicalIndex - 1]);
+ }
+
+ /// Returns the number of CJK radicals in the Unicode data.
+ /// This value will be 214 for the foreseeable future.
+ public static int CjkRadicalCount { get { return radicals.Length; } }
+
+ /// Gets all the blocks defined in the Unicode data.
+ /// is not the name of a block, but only a value indicating the abscence of block information for a given code point.
+ /// An array containing an entry for every block defined in the Unicode data.
public static UnicodeBlock[] GetBlocks()
{
return (UnicodeBlock[])blocks.Clone();
diff --git a/UnicodeInformation/UnicodeInformation.csproj b/UnicodeInformation/UnicodeInformation.csproj
index 6d2ccf7..7b8e294 100644
--- a/UnicodeInformation/UnicodeInformation.csproj
+++ b/UnicodeInformation/UnicodeInformation.csproj
@@ -32,6 +32,8 @@
prompt
4
false
+
+
pdbonly
@@ -40,6 +42,8 @@
TRACE
prompt
4
+
+
true
@@ -59,6 +63,8 @@
+
+
diff --git a/UnicodeInformation/UnicodeRadicalStrokeCount.cs b/UnicodeInformation/UnicodeRadicalStrokeCount.cs
index 9dcc55b..77b7c72 100644
--- a/UnicodeInformation/UnicodeRadicalStrokeCount.cs
+++ b/UnicodeInformation/UnicodeRadicalStrokeCount.cs
@@ -22,13 +22,12 @@ namespace System.Unicode
internal UnicodeRadicalStrokeCount(byte radical, byte strokeCount, bool isSimplified)
{
this.radical = radical;
+ if (isSimplified) strokeCount |= 0x80;
this.strokeCount = strokeCount;
-
- if (isSimplified) this.strokeCount |= 0x80;
}
public byte Radical { get { return radical; } }
- public byte StrokeCount { get { return strokeCount; } }
+ public byte StrokeCount { get { return (byte)(strokeCount & 0x7F); } }
public bool IsSimplified { get { return (strokeCount & 0x80) != 0; } }
}
}
diff --git a/UnicodeInformation/ucd.dat b/UnicodeInformation/ucd.dat
index 6117a71..91c6357 100644
Binary files a/UnicodeInformation/ucd.dat and b/UnicodeInformation/ucd.dat differ