/// <summary> /// Cache index to the list of scaled shapeable typeface /// </summary> private void CacheScaledTypefaceMap( CharacterBufferRange unicodeString, CultureInfo culture, CultureInfo digitCulture, SpanVector scaledTypefaceSpans, ref SpanVector<int> cachedScaledTypefaceIndexSpans, int ichItem ) { IntMap map; if (!_intMaps.TryGetValue(culture, out map)) { map = new IntMap(); _intMaps.Add(culture, map); } DigitMap digitMap = new DigitMap(digitCulture); SpanRider typefaceSpanRider = new SpanRider(scaledTypefaceSpans); int ich = 0; while(ich < unicodeString.Length) { typefaceSpanRider.At(ich); int cch = Math.Min(unicodeString.Length - ich, typefaceSpanRider.Length); int index = IndexOfScaledTypeface((ScaledShapeTypeface)typefaceSpanRider.CurrentElement); Debug.Assert(index >= 0, "Invalid scaled shapeable typeface index spans"); cachedScaledTypefaceIndexSpans.Set(ichItem + ich, cch, index); // we keep index + 1 in the map, so that we leave map entry zero // to indicate uninitialized entry. index++; int sizeofChar; for (int c = 0; c < cch; c += sizeofChar) { int ch = digitMap[ Classification.UnicodeScalar( new CharacterBufferRange(unicodeString, ich + c, unicodeString.Length - ich - c), out sizeofChar ) ]; // only cache typeface map index for base characters if(!Classification.IsCombining(ch) && !Classification.IsJoiner(ch)) { // Dump values of local variables when the condition fails for better debuggability. // We use "if" to avoid the expensive string.Format() in normal case. if (map[ch] != 0 && map[ch] != index) { Invariant.Assert( false, string.Format( CultureInfo.InvariantCulture, "shapeable cache stores conflicting info, ch = {0}, map[ch] = {1}, index = {2}", ch, map[ch], index ) ); } map[ch] = (ushort)index; } } ich += cch; } }
/// <summary> /// Get spans of index to the list of scaled shapeable typeface of the specified /// character string from the map table /// </summary> private bool GetCachedScaledTypefaceMap( CharacterBufferRange unicodeString, CultureInfo culture, CultureInfo digitCulture, ref SpanVector<int> cachedScaledTypefaceIndexSpans, int ichItem ) { IntMap map; if (!_intMaps.TryGetValue(culture, out map)) { return false; } DigitMap digitMap = new DigitMap(digitCulture); int ich = 0; while (ich < unicodeString.Length) { // Get map entry for first character. int sizeofChar; int ch = digitMap[ Classification.UnicodeScalar( new CharacterBufferRange(unicodeString, ich, unicodeString.Length - ich), out sizeofChar ) ]; ushort firstIndex = map[ch]; if (firstIndex == 0) return false; // Advance past subsequent characters with the same mapping. int cchSpan = sizeofChar; for (; ich + cchSpan < unicodeString.Length; cchSpan += sizeofChar) { ch = digitMap[ Classification.UnicodeScalar( new CharacterBufferRange(unicodeString, ich + cchSpan, unicodeString.Length - ich - cchSpan), out sizeofChar ) ]; if (map[ch] != firstIndex && !Classification.IsCombining(ch) && !Classification.IsJoiner(ch)) break; } // map entry is stored in index+1, since 0 indicates uninitialized entry cachedScaledTypefaceIndexSpans.Set(ichItem + ich, cchSpan, firstIndex - 1); ich += cchSpan; } return true; }