/// <summary> /// Get family name correspondent to the first n-characters of the specified character string /// </summary> /// <param name="unicodeString">character string</param> /// <param name="culture">text culture info</param> /// <param name="digitCulture">culture used for digit subsitution or null</param> /// <param name="defaultSizeInEm">default size relative to em</param> /// <param name="cchAdvance">number of characters advanced</param> /// <param name="targetFamilyName">target family name</param> /// <param name="scaleInEm">size relative to em</param> /// <returns>number of character sharing the same family name and size</returns> /// <remarks> /// /// Null target family name returned indicates that the font family cannot find target /// name of the character range being advanced. /// /// Return value false indicates that the font family has no character map. /// It is a font face family. /// /// </remarks> unsafe bool IFontFamily.GetMapTargetFamilyNameAndScale( CharacterBufferRange unicodeString, CultureInfo culture, CultureInfo digitCulture, double defaultSizeInEm, out int cchAdvance, out string targetFamilyName, out double scaleInEm ) { Invariant.Assert(unicodeString.CharacterBuffer != null && unicodeString.Length > 0); Invariant.Assert(culture != null); // Get the family map. This will find the first family map that matches // the specified culture, an ancestor neutral culture, or "any" culture. FamilyCollection.CachedFamilyMap *familyMap = GetCachedFamilyMap( unicodeString, culture, digitCulture, out cchAdvance ); if (familyMap == null) { targetFamilyName = null; scaleInEm = 1; } else { int *sizePrefix = (int *)((byte *)familyMap + familyMap->targetFamilyNameOffset); targetFamilyName = Util.StringCopyFromUncheckedPointer(sizePrefix + 1, *sizePrefix); scaleInEm = familyMap->scaleInEm; } return(true); }
private unsafe FamilyCollection.CachedFamilyMap *GetCachedFamilyMap( CharacterBufferRange unicodeString, CultureInfo culture, CultureInfo digitCulture, out int cchAdvance ) { cchAdvance = 0; DigitMap digitMap = new DigitMap(digitCulture); int lengthOfRanges; ushort *ranges = _cachedFamily.FamilyCollection.GetFamilyMapRanges( _cachedFamily.CompositeFamily, culture, out lengthOfRanges ); Debug.Assert(ranges != null); int sizeofChar = 0; int ch = 0; cchAdvance = Classification.AdvanceWhile(unicodeString, ItemClass.JoinerClass); if (cchAdvance >= unicodeString.Length) { // It is rare that the run only contains joiner characters. // If it really happens, just map them to the initial family map. return(_cachedFamily.FamilyCollection.GetFamilyMapOfChar( _cachedFamily.CompositeFamily, ranges, lengthOfRanges, Classification.UnicodeScalar(unicodeString, out sizeofChar) )); } // // If the run starts with combining marks, we will not be able to find base characters for them // within the run. These combining marks will be mapped to their best fonts as normal characters. // ch = Classification.UnicodeScalar( new CharacterBufferRange(unicodeString, cchAdvance, unicodeString.Length - cchAdvance), out sizeofChar ); bool hasBaseChar = !Classification.IsCombining(ch); ch = digitMap[ch]; FamilyCollection.CachedFamilyMap *familyMap = _cachedFamily.FamilyCollection.GetFamilyMapOfChar(_cachedFamily.CompositeFamily, ranges, lengthOfRanges, ch); for (cchAdvance += sizeofChar; cchAdvance < unicodeString.Length; cchAdvance += sizeofChar) { ch = Classification.UnicodeScalar( new CharacterBufferRange(unicodeString, cchAdvance, unicodeString.Length - cchAdvance), out sizeofChar ); if (Classification.IsJoiner(ch)) { continue; // continue to advance if current char is a joiner } if (!Classification.IsCombining(ch)) { hasBaseChar = true; } else if (hasBaseChar) { continue; // continue to advance for combining mark with base char } ch = digitMap[ch]; if (_cachedFamily.FamilyCollection.GetFamilyMapOfChar(_cachedFamily.CompositeFamily, ranges, lengthOfRanges, ch) != familyMap) { break; } } return(familyMap); }