static bool CheckIfNotOverlap(UnicodeRangeInfo test, List <UnicodeRangeInfo> others, int exceptIndex, int exceptIndex2 = -1) { int count = others.Count; for (int i = 0; i < count; ++i) { if (i == exceptIndex) { continue; } if (exceptIndex2 > -1 && i == exceptIndex2) { continue; } UnicodeRangeInfo rng = others[i]; int b_begin = rng.StartCodePoint; int b_end = rng.EndCodePoint; if ((test.StartCodePoint >= b_begin && test.StartCodePoint <= b_end) || (test.EndCodePoint >= b_begin && test.EndCodePoint <= b_begin)) { //overlap found return(false); } } return(true); }
static IEnumerable <ushort> GetGlyphIndexIter(Typeface typeface, params UnicodeLangBits[] rangeBits) { //temp fixed GlyphIndexCollector collector = new GlyphIndexCollector(); int j = rangeBits.Length; for (int i = 0; i < j; ++i) { UnicodeRangeInfo rangeInfo = rangeBits[i].ToUnicodeRangeInfo(); //get start and end bit int startChar = rangeInfo.StartAt; int startGlyphIndex = typeface.LookupIndex((char)startChar); while (startGlyphIndex < 1) { startChar++; startGlyphIndex = typeface.LookupIndex((char)startChar); } for (int gindex = startGlyphIndex; gindex < startGlyphIndex + 125; ++gindex) { yield return((ushort)gindex); } //char endAt = (char)rangeInfo.EndAt; //for (char c = (char)rangeInfo.StartAt; c <= endAt; ++c) //{ // typeface.CollectGlyphIndexListFromSampleChar(c, collector); //} } }
internal SpanBreakInfo(UnicodeRangeInfo unicodeRange, bool isRightToLeft, uint scriptTag, uint langTag = 0) { UnicodeRange = unicodeRange; //can be null RightToLeft = isRightToLeft; ScriptTag = scriptTag; LangTag = 0; }
public static bool GetUniCodeRangeFor(int c1, out UnicodeRangeInfo unicodeRangeInfo, out SpanBreakInfo spanBreakInfo) { if (Unicode13RangeInfoList.TryGetUnicodeRangeInfo(c1, out unicodeRangeInfo) && s_registerSpanBreakInfo.TryGetValue(unicodeRangeInfo, out spanBreakInfo)) { return(true); } //we may found unicodeRange info //but may not found register spanbreak info spanBreakInfo = null; return(false); }
public static bool TryGetUnicodeRangeInfo(int sampleCodepoint, out UnicodeRangeInfo found) { int foundAt = Array.BinarySearch(s_beginAt_list, sampleCodepoint); foundAt = foundAt < 0 ? ~foundAt - 1 : foundAt; found = s_list[foundAt]; if (sampleCodepoint <= found.EndCodepoint) { return(true); } found = null; return(false); }
public static void CollectAllAssociateGlyphIndex(this Typeface typeface, List <ushort> outputGlyphIndexList, ScriptLang scLang, UnicodeLangBits[] selectedRangs = null) { //----------- //general glyph index in the unicode range //if user dose not specific the unicode lanf bit ranges //the we try to select it ourself. UnicodeLangBits[] unicodeLangBitsRanges; if (ScriptLangs.TryGenUnicodeLangBitsArray(scLang.shortname, out unicodeLangBitsRanges)) { //one lang may contains may ranges if (selectedRangs != null) { //select only in range unicodeLangBitsRanges = FilterOnlySelectedRange(unicodeLangBitsRanges, selectedRangs); } foreach (UnicodeLangBits unicodeLangBits in unicodeLangBitsRanges) { UnicodeRangeInfo rngInfo = unicodeLangBits.ToUnicodeRangeInfo(); int endAt = rngInfo.EndAt; for (int codePoint = rngInfo.StartAt; codePoint <= endAt; ++codePoint) { ushort glyghIndex = typeface.LookupIndex(codePoint); if (glyghIndex > 0) { //add this glyph index outputGlyphIndexList.Add(glyghIndex); } } } } //----------- if (typeface.GSUBTable != null) { var gsub = new GlyphSubstitution(typeface, scLang.shortname); gsub.CollectAdditionalSubstitutionGlyphIndices(outputGlyphIndexList); } }
void LoadUnicode13Ranges() { //https://www.unicode.org/versions/Unicode13.0.0/UnicodeStandard-13.0.pdf //generate unicode ranges string[] allLines = File.ReadAllLines("unicode13_ranges.txt"); //skip 1st line _unicode13Ranges = new List <UnicodeRangeInfo>(); _unicode13Dic = new Dictionary <string, UnicodeRangeInfo>(); for (int i = 1; i < allLines.Length; ++i) { string line = allLines[i].Trim(); if (line.Length == 0 || line.StartsWith("#")) { continue; } //skip blank line or comment line // string[] fields = line.Split(','); if (fields.Length != 3) { throw new NotSupportedException(); } var rangeInfo = new UnicodeRangeInfo { RangeName = fields[0].Trim(), StartCodePoint = int.Parse(fields[1].Trim(), System.Globalization.NumberStyles.HexNumber), EndCodePoint = int.Parse(fields[2].Trim(), System.Globalization.NumberStyles.HexNumber) }; _unicode13Ranges.Add(rangeInfo); _unicode13Dic.Add(rangeInfo.RangeName, rangeInfo); } //---------------------- //from https://www.unicode.org/faq/blocks_ranges.html //Q: Can blocks overlap? //A: No.Every Unicode block is discrete, and cannot overlap with any other block. //Also, every assigned character in the Unicode Standard has to be in a block(and only one block, of course). //This ensures that when code charts are printed, no characters are omitted simply because they aren't in a block //---------------------- //***ensure no overlap unicode range*** int count = _unicode13Ranges.Count; for (int i = 0; i < count; ++i) { if (!CheckIfNotOverlap(_unicode13Ranges[i], _unicode13Ranges, i)) { //found overlap! throw new NotSupportedException("unicode overlap found!"); } } { //ensure that code points are arranged ascending int latest_codepoint = -1; for (int i = 0; i < count; ++i) { int cp = _unicode13Ranges[i].StartCodePoint; if (latest_codepoint > cp) { throw new NotSupportedException(); } latest_codepoint = cp; } } //---------------------- //example 1 //since the range is not overlap each other //we can simply search it with binary search { int[] beginAt_list = new int[count]; for (int i = 0; i < count; ++i) { beginAt_list[i] = _unicode13Ranges[i].StartCodePoint; } //test int test_char = '+'; int foundAt = Array.BinarySearch(beginAt_list, test_char); foundAt = foundAt < 0 ? ~foundAt - 1 : foundAt; UnicodeRangeInfo rangeInfo = _unicode13Ranges[foundAt]; } //---------------------- { //generate code StringBuilder sb = new StringBuilder(); for (int i = 0; i < count; ++i) { UnicodeRangeInfo rng = _unicode13Ranges[i]; sb.AppendLine(GetProperFieldName(rng.RangeName) + $"=_(\"{ rng.RangeName }\",0x{rng.StartCodePoint.ToString("X4")}/*{rng.StartCodePoint}*/,0x{rng.EndCodePoint.ToString("X4")}/*{rng.StartCodePoint}*/),"); } sb.AppendLine(); sb.AppendLine(); for (int i = 0; i < count; ++i) { UnicodeRangeInfo rng = _unicode13Ranges[i]; sb.AppendLine(GetProperFieldName(rng.RangeName) + ","); } } }
public override SelectedTypeface Select(List <InstalledTypeface> choices, UnicodeRangeInfo unicodeRangeInfo, int hintCodePoint) { //request font may have hint for typeface if (_reqFont != null) { for (int i = 0; i < _reqFont.OtherChoicesCount; ++i) { RequestFont.Choice choice = _reqFont.GetOtherChoice(i); ResolvedFont resolvedFont = _textService.ResolveFont(choice); //check if resolvedFont support specific unicodeRange info or not Typeface typeface = resolvedFont.Typeface; ushort codepoint = typeface.GetGlyphIndex(unicodeRangeInfo.StartCodepoint); if (codepoint > 0) { //use this return(new SelectedTypeface(typeface)); } } } List <PreferredTypeface> list = null; if (unicodeRangeInfo == Unicode13RangeInfoList.Emoticons) { list = _emojiPreferList; } else if (_dics.TryGetValue(unicodeRangeInfo.Name, out PreferredTypefaceList foundList)) { list = foundList; } if (list != null) { int j = list.Count; for (int i = 0; i < j; ++i) { //select that first one PreferredTypeface p = list[i]; if (p.InstalledTypeface == null && !p.ResolvedInstalledTypeface) { //find int choice_count = choices.Count; for (int m = 0; m < choice_count; ++m) { InstalledTypeface instTypeface = choices[m]; if (p.RequestTypefaceName == instTypeface.FontName) { //TODO: review here again p.InstalledTypeface = instTypeface; break; } } p.ResolvedInstalledTypeface = true; } //------- if (p.InstalledTypeface != null) { return(new SelectedTypeface(p.InstalledTypeface)); } } } //still not found if (choices.Count > 0) { //choose default return(new SelectedTypeface(choices[0])); } return(new SelectedTypeface());//empty }
public void SetPreferredTypefaces(UnicodeRangeInfo unicodeRangeInfo, PreferredTypefaceList typefaceNames) { _dics[unicodeRangeInfo.Name] = typefaceNames; }
public abstract SelectedTypeface Select(List <InstalledTypeface> choices, UnicodeRangeInfo unicodeRangeInfo, int codepoint);
static void RegisterSpanBreakInfo(UnicodeRangeInfo unicodeRangeInfo, uint scriptTag, bool rightToLeft = false) { s_registerSpanBreakInfo.Add(unicodeRangeInfo, new SpanBreakInfo(unicodeRangeInfo, rightToLeft, scriptTag)); }