Example #1
0
        /// <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);
        }
Example #2
0
        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);
        }