public bool Equals(CanonicalFontFamilyReference other)
 {
     return(other != null &&
            other._absoluteLocationUri == _absoluteLocationUri &&
            other.EscapedFileName == EscapedFileName &&
            other._familyName == _familyName);
 }
Example #2
0
        internal static IFontFamily LookupFontFamilyAndFace(
            CanonicalFontFamilyReference canonicalFamilyReference, 
            ref FontStyle                style,
            ref FontWeight               weight, 
            ref FontStretch              stretch 
            )
        { 
            if (canonicalFamilyReference == null || object.ReferenceEquals(canonicalFamilyReference, CanonicalFontFamilyReference.Unresolved))
            {
                // no canonical name, e.g., because the friendly name was an empty string
                // or could not be canonicalized 
                return null;
            } 
 
            try
            { 
                FamilyCollection familyCollection;

                if (canonicalFamilyReference.LocationUri == null && canonicalFamilyReference.EscapedFileName == null)
                { 
                    // No explicit location; use the default family collection.
                    familyCollection = _defaultFamilyCollection; 
                } 
                else if (canonicalFamilyReference.LocationUri != null)
                { 
                    // Look in the location specified by the font family reference.
                    familyCollection = FamilyCollection.FromUri(canonicalFamilyReference.LocationUri);
                }
                else // canonicalFamilyReference.EscapedFileName != null 
                {
                    // Look in the specified file in the Windows Fonts folder 
                    // Note: CanonicalFamilyReference.EscapedFileName is safe to combine with Util.WindowsFontsUriObject because CanonicalFamilyReference guarantees that it will be a simple filename 
                    // without relative path or directory components.
                    Uri locationUri = new Uri(Util.WindowsFontsUriObject, canonicalFamilyReference.EscapedFileName); 
                    familyCollection = FamilyCollection.FromWindowsFonts(locationUri);
                }

                IFontFamily fontFamily = familyCollection.LookupFamily( 
                    canonicalFamilyReference.FamilyName,
                    ref style, 
                    ref weight, 
                    ref stretch
                ); 
                return fontFamily;
            }
            // The method returns null in case of malformed/non-existent fonts and we fall back to the next font.
            // Therefore, we can disable PreSharp warning about empty catch bodies. 
#pragma warning disable 6502
            catch (FileFormatException) 
            { 
                // malformed font file
            } 
            catch (IOException)
            {
                // canonical name points to a place that doesn't exist or can't be read for some reason
            } 
            catch (UnauthorizedAccessException)
            { 
                // canonical name points to a place caller doesn't have permission to access 
            }
            catch (ArgumentException) 
            {
                // canonical name points to a valid Uri that doesn't point to a well formed
                // OS local path
            } 
            catch (NotSupportedException)
            { 
                // canonical name points to a Uri that specifies an unregistered scheme 
            }
            catch (UriFormatException) 
            {
                // canonical name points to a malformed Uri
            }
#pragma warning restore 6502 
            // we want to fall back to the default fallback font instead of crashing
            return null; 
        } 
Example #3
0
        /// <summary> 
        /// Look up font family from canonical name
        /// </summary>
        /// <param name="canonicalName">font family canonical name</param>
        internal static IFontFamily LookupFontFamily(CanonicalFontFamilyReference canonicalName) 
        {
 
            FontStyle style     = FontStyles.Normal; 
            FontWeight weight   = FontWeights.Normal;
            FontStretch stretch = FontStretches.Normal; 

            return LookupFontFamilyAndFace(canonicalName, ref style, ref weight, ref stretch);
        }
Example #4
0
        /// <summary>
        /// Create font family from canonical family and ensure at least a 
        /// fallback family is created if the specified name cannot be resolved.
        /// </summary> 
        internal static IFontFamily SafeLookupFontFamily( 
            CanonicalFontFamilyReference canonicalName,
            out bool                     nullFont 
            )
        {
            nullFont = false;
 
            IFontFamily fontFamily = LookupFontFamily(canonicalName);
 
            if(fontFamily == null) 
            {
                nullFont = true; 
                fontFamily = LookupFontFamily(NullFontFamilyCanonicalName);
                Invariant.Assert(fontFamily != null, "Unable to create null font family");
            }
 
            return fontFamily;
        } 
Example #5
0
        /// <summary>
        /// Map characters by font family 
        /// </summary>
        /// <remarks>
        /// Advance:
        ///     number of characters not mapped to missing glyph 
        ///
        /// NextValid: 
        ///     Offset to the nearest first character not mapped to missing glyph 
        ///
        /// [Number of invalid characters following valid ones] = NextValid - Advance 
        ///
        ///         A B C D E F G H x x x x x F G H I J
        ///         --------------->
        ///             Advance 
        ///
        ///         -------------------------> 
        ///                NextValid 
        ///
        /// </remarks> 
        private int MapByFontFamily(
            CharacterBufferRange            unicodeString,
            CultureInfo                     culture,
            CultureInfo                     digitCulture, 
            IFontFamily                     fontFamily,
            CanonicalFontFamilyReference    canonicalFamilyReference, 
            FontStyle                       canonicalStyle, 
            FontWeight                      canonicalWeight,
            FontStretch                     canonicalStretch, 
            ref PhysicalFontFamily          firstValidFamily,
            ref int                         firstValidLength,
            IDeviceFont                     deviceFont,
            double                          scaleInEm, 
            int                             recursionDepth,
            SpanVector                      scaledTypefaceSpans, 
            int                             firstCharIndex, 
            out int                         nextValid
            ) 
        {
            // This is the *one* place where we check for the font mapping depths of the font linking
            // process. This protects the linking process against extremely long chain of linking or
            // circular dependencies in the composite fonts. 
            if (recursionDepth >= MaxTypefaceMapDepths)
            { 
                // Stop the recursion. In effect, this FontFamily does not map any of the input. 
                // Higher-level code must map the input text to some other FontFamily, or to the
                // "null font" if there is no valid FontFamily. 
                nextValid = 0;
                return 0;
            }
 
            // If a device font is not already specified higher up the stack, look for a device font
            // for this font family that matches the typeface style, weight, and stretch. 
            if (deviceFont == null) 
            {
                deviceFont = fontFamily.GetDeviceFont(_canonicalStyle, _canonicalWeight, _canonicalStretch); 
            }

            DigitMap digitMap = new DigitMap(digitCulture);
 
            int advance = 0;
            int cchAdvance; 
            int cchNextValid; 
            int ich = 0;
 
            nextValid = 0;

            bool terminated = false;
 
            while (ich < unicodeString.Length  &&  !terminated)
            { 
                // Determine length of run with consistent mapping. Start by assuming we'll be able to 
                // use the whole string, then reduce to the length that can be mapped consistently.
                int cchMap = unicodeString.Length - ich; 

                // Determine whether the run is using a device font, and limit the run to the
                // first boundary between device/non-device font usage.
                bool useDeviceFont = false; 
                if (deviceFont != null)
                { 
                    // Determine whether the first run uses a device font by inspecting the first character. 
                    // We do not support device fonts for codepoints >= U+10000 (aka surrogates), so we
                    // don't need to call Classification.UnicodeScalar. 
                    useDeviceFont = deviceFont.ContainsCharacter(digitMap[unicodeString[ich]]);

                    // Advance as long as 'useDeviceFont' remains unchanged.
                    int i = ich + 1; 
                    while (    (i < unicodeString.Length)
                           &&  (useDeviceFont == deviceFont.ContainsCharacter(digitMap[unicodeString[i]]))) 
                    { 
                        i++;
                    } 

                    cchMap = i - ich;
                }
 

                // Map as many characters to a family as we can up to the limit (cchMap) just determined. 
                string targetFamilyName; 
                double mapSizeInEm;
 
                bool isCompositeFontFamily = fontFamily.GetMapTargetFamilyNameAndScale(
                    new CharacterBufferRange(
                        unicodeString,
                        ich, 
                        cchMap
                        ), 
                    culture, 
                    digitCulture,
                    scaleInEm, 
                    out cchMap,
                    out targetFamilyName,
                    out mapSizeInEm
                    ); 

                Debug.Assert(cchMap <= unicodeString.Length - ich); 
 
                CharacterBufferRange mappedString = new CharacterBufferRange(
                    unicodeString, 
                    ich,
                    cchMap
                    );
 

                if (!isCompositeFontFamily) 
                { 
                    // not a composite font family
                    cchAdvance = MapByFontFaceFamily( 
                        mappedString,
                        culture,
                        digitCulture,
                        fontFamily, 
                        canonicalStyle,
                        canonicalWeight, 
                        canonicalStretch, 
                        ref firstValidFamily,
                        ref firstValidLength, 
                        useDeviceFont ? deviceFont : null,
                        false, // nullFont
                        mapSizeInEm,
                        scaledTypefaceSpans, 
                        firstCharIndex + ich,
                        false, // ignoreMissing 
                        out cchNextValid 
                        );
                } 
                else if (!string.IsNullOrEmpty(targetFamilyName))
                {
                    // The base Uri used for resolving target family names is the Uri of the composite font.
                    Uri baseUri = (canonicalFamilyReference != null) ? canonicalFamilyReference.LocationUri : null; 

                    // map to the target of the family map 
                    cchAdvance = MapByFontFamilyName( 
                        mappedString,
                        culture, 
                        digitCulture,
                        targetFamilyName,
                        baseUri,
                        ref firstValidFamily, 
                        ref firstValidLength,
                        useDeviceFont ? deviceFont : null, 
                        mapSizeInEm, 
                        recursionDepth + 1, // increment the depth
                        scaledTypefaceSpans, 
                        firstCharIndex + ich,
                        out cchNextValid
                        );
                } 
                else
                { 
                    // family map lookup returned no target family 
                    cchAdvance = 0;
                    cchNextValid = cchMap; 
                }

                int cchValid = cchMap;
                int cchInvalid = 0; 

                cchValid = cchAdvance; 
                cchInvalid = cchNextValid; 

                if(cchValid < cchMap) 
                {
                    terminated = true;
                }
 
                advance += cchValid;
                nextValid = ich + cchInvalid; 
 
                ich += cchValid;
            } 

            return advance;
        }
Example #6
0
        /// <summary>
        /// Create a FontFamilyIdentifier by concatenating two existing identifiers.
        /// </summary>
        internal FontFamilyIdentifier(FontFamilyIdentifier first, FontFamilyIdentifier second)
        {
            first.Canonicalize();
            second.Canonicalize();

            _friendlyName = null;
            _tokenCount = first._tokenCount + second._tokenCount;
            _baseUri = null;

            if (first._tokenCount == 0)
            {
                _canonicalReferences = second._canonicalReferences;
            }
            else if (second._tokenCount == 0)
            {
                _canonicalReferences = first._canonicalReferences;
            }
            else
            {
                _canonicalReferences = new CanonicalFontFamilyReference[_tokenCount];

                int i = 0;
                foreach (CanonicalFontFamilyReference family in first._canonicalReferences)
                {
                    _canonicalReferences[i++] = family;
                }
                foreach (CanonicalFontFamilyReference family in second._canonicalReferences)
                {
                    _canonicalReferences[i++] = family;
                }
            }
        }
Example #7
0
        internal void Canonicalize()
        {
            if (_canonicalReferences != null)
                return;
                
            int count = this.Count;
            if (count == 0)
                return;

            // First look up the entire friendly name in the cache; this may enable us to
            // save working set by sharing the same array of may equal FontFamilyIdentifier.
            BasedFriendlyName hashKey = new BasedFriendlyName(_baseUri, _friendlyName);
            CanonicalFontFamilyReference[] canonicalReferences = TypefaceMetricsCache.ReadonlyLookup(hashKey) as CanonicalFontFamilyReference[];

            if (canonicalReferences == null)
            {
                // We need to construct a new array.
                canonicalReferences = new CanonicalFontFamilyReference[count];

                // Add the first canonical family reference.
                int i, length;
                int j = FindToken(_friendlyName, 0, out i, out length);
                canonicalReferences[0] = GetCanonicalReference(i, length);

                // Add subsequent family references.
                for (int k = 1; k < count; ++k)
                {
                    j = FindToken(_friendlyName, j, out i, out length);
                    canonicalReferences[k] = GetCanonicalReference(i, length);
                }

                // Add the array to the cache.
                TypefaceMetricsCache.Add(hashKey, canonicalReferences);
            }

            // for thread safety, we assign to the field only after the array is fully initialized
            _canonicalReferences = canonicalReferences;
        }
 public bool Equals(CanonicalFontFamilyReference other)
 {
     return other != null &&
         other._absoluteLocationUri == _absoluteLocationUri &&
         other.EscapedFileName == EscapedFileName &&
         other._familyName == _familyName;
 }