FontFamily.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / FontFamily.cs / 1599981 / FontFamily.cs

                            //------------------------------------------------------------------------ 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2002
// 
//  File:      FontFamily.cs
// 
//  Contents:  FontFamily 
//
//  Created  :   5-25-2003 Worachai Chaoweeraprasit (wchao) 
//  Modified :   8-08-2008 [....] - Integrating with DWrite.
//
//-----------------------------------------------------------------------
 
using System;
using System.Text; 
using System.IO; 
using System.Globalization;
using System.Collections; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Markup;    // for XmlLanguage 
using System.ComponentModel;
using System.ComponentModel.Design; 
 
using MS.Utility;
using MS.Internal; 
using MS.Internal.FontCache;
using MS.Internal.FontFace;
using MS.Internal.Shaping;
using System.Security; 

using SR = MS.Internal.PresentationCore.SR; 
using SRID = MS.Internal.PresentationCore.SRID; 

// Since we disable PreSharp warnings in this file, we first need to disable warnings about unknown message numbers and unknown pragmas. 
#pragma warning disable 1634, 1691

namespace System.Windows.Media
{ 
    /// 
    /// Represents a family of related fonts. Fonts in a FontFamily differ only in style, 
    /// weight, or stretch. 
    /// 
    [TypeConverter(typeof(FontFamilyConverter))] 
    [ValueSerializer(typeof(FontFamilyValueSerializer))]
    [Localizability(LocalizationCategory.Font)]
    public class FontFamily
    { 
        /// 
        /// Family name originally passed to by user and information derived from it. 
        ///  
        private FontFamilyIdentifier _familyIdentifier;
 
        /// 
        /// The first valid font family. If no valid font family can be resolved from
        /// the given name, this will point to a NullFontFamily object.
        ///  
        private IFontFamily _firstFontFamily;
 
        ///  
        /// Null font is the font that has metrics but logically does not support any Unicode codepoint
        /// so whatever text we throw at it would result in being mapped to missing glyph. 
        /// 
        internal static readonly CanonicalFontFamilyReference NullFontFamilyCanonicalName = CanonicalFontFamilyReference.Create(null, "#ARIAL");

        internal const string GlobalUI = "#GLOBAL USER INTERFACE"; 

        internal static FontFamily FontFamilyGlobalUI = new FontFamily(GlobalUI); 
 
        private static volatile FamilyCollection _defaultFamilyCollection = PreCreateDefaultFamilyCollection();
 
        private static FontFamilyMapCollection _emptyFamilyMaps = null;


        ///  
        /// Constructs FontFamily from a string.
        ///  
        /// Specifies one or more comma-separated family names, each 
        /// of which may be either a regular family name string (e.g., "Arial") or a URI
        /// (e.g., "file:///c:/windows/fonts/#Arial"). 
        public FontFamily(string familyName) : this(null, familyName)
        {}

        ///  
        /// Constructs FontFamily from a string and an optional base URI.
        ///  
        /// Specifies the base URI used to resolve family names, typically 
        /// the URI of the document or element that refers to the font family. Can be null.
        /// Specifies one or more comma-separated family names, each 
        /// of which may be either a regular family name string (e.g., "Arial") or a URI
        /// (e.g., "file:///c:/windows/fonts/#Arial").
        public FontFamily(Uri baseUri, string familyName)
        { 
            if (familyName == null)
                throw new ArgumentNullException("familyName"); 
 
            if (baseUri != null && !baseUri.IsAbsoluteUri)
                throw new ArgumentException(SR.Get(SRID.UriNotAbsolute), "baseUri"); 

            _familyIdentifier = new FontFamilyIdentifier(familyName, baseUri);
        }
 
        internal FontFamily(FontFamilyIdentifier familyIdentifier)
        { 
            _familyIdentifier = familyIdentifier; 
        }
 
        /// 
        /// Construct an anonymous font family, i.e., a composite font that is created
        /// programatically instead of referenced by name or URI.
        ///  
        public FontFamily()
        { 
            _familyIdentifier = new FontFamilyIdentifier(null, null); 
            _firstFontFamily = new CompositeFontFamily();
        } 

        /// 
        /// Collection of culture-dependant family names.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public LanguageSpecificStringDictionary FamilyNames 
        { 
            get
            { 
                CompositeFontFamily compositeFont = FirstFontFamily as CompositeFontFamily;
                if (compositeFont != null)
                {
                    // Return the read/write dictionary of family names. 
                    return compositeFont.FamilyNames;
                } 
                else 
                {
                    // Return a wrapper for the cached family's read-only dictionary. 
                    return new LanguageSpecificStringDictionary(FirstFontFamily.Names);
                }
            }
        } 

        ///  
        /// List of FamilyTypeface objects. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
        public FamilyTypefaceCollection FamilyTypefaces
        {
            get
            { 
                CompositeFontFamily compositeFont = FirstFontFamily as CompositeFontFamily;
                if (compositeFont != null) 
                { 
                    // Return the read/write list of typefaces for the font.
                    return compositeFont.FamilyTypefaces; 
                }
                else
                {
                    // Return a wrapper for the read-only collection of typefaces. 
                    return new FamilyTypefaceCollection(FirstFontFamily.GetTypefaces(_familyIdentifier));
                } 
            } 
        }
 
        /// 
        /// Collection of FontFamilyMap objects for an anonymous font family. For named font
        /// families, this property returns an empty, read-only list.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public FontFamilyMapCollection FamilyMaps 
        { 
            get
            { 
                CompositeFontFamily compositeFont = FirstFontFamily as CompositeFontFamily;
                if (compositeFont != null)
                {
                    // Read the read/write list of family maps for the font. 
                    return compositeFont.FamilyMaps;
                } 
                else 
                {
                    // Return an empty, read-only collection of FamilyMaps. 
                    if (_emptyFamilyMaps == null)
                    {
                        _emptyFamilyMaps = new FontFamilyMapCollection(null);
                    } 
                    return _emptyFamilyMaps;
                } 
            } 
        }
 
        /// 
        /// Family names and/or URIs used to construct the font family.
        /// 
        public string Source 
        {
            get { return _familyIdentifier.Source; } 
        } 

        ///  
        /// Base URI used to resolve family names, typically the URI of the document or element
        /// that refers to the font family.
        /// 
        ///  
        /// Family names are interpreted first relative to the base URI (if not null) and then
        /// relative to the default folder for installed fonts. 
        ///  
        public Uri BaseUri
        { 
            get { return _familyIdentifier.BaseUri; }
        }

        ///  
        /// Return Source if there is one or String.Empty for unnamed
        /// font family. 
        ///  
        public override string ToString()
        { 
            string source = _familyIdentifier.Source;
            return source != null ? source : string.Empty;
        }
 

        internal FontFamilyIdentifier FamilyIdentifier 
        { 
            get { return _familyIdentifier; }
        } 


        /// 
        /// Distance from character cell top to English baseline relative to em size. 
        /// 
        public double Baseline 
        { 
            get
            { 
                return FirstFontFamily.BaselineDesign;
            }

            set 
            {
                VerifyMutable().SetBaseline(value); 
            } 
        }
 

        /// 
        /// Recommended baseline-to-baseline distance for the text in this font relative to em size.
        ///  
        public double LineSpacing
        { 
            get 
            {
                return FirstFontFamily.LineSpacingDesign; 
            }

            set
            { 
                VerifyMutable().SetLineSpacing(value);
            } 
        } 

        internal double GetLineSpacingForDisplayMode(double emSize) 
        {
            return FirstFontFamily.LineSpacing(emSize, 1, Util.PixelsPerDip, TextFormattingMode.Display);
        }
 
        /// 
        /// Font families from the default system font location. 
        ///  
        /// Collection of FontFamly objects from the default system font location.
        [CLSCompliant(false)] 
        public ICollection GetTypefaces()
        {
            return FirstFontFamily.GetTypefaces(_familyIdentifier);
        } 

 
        ///  
        /// Create correspondent hash code for the object
        ///  
        /// object hash code
        public override int GetHashCode()
        {
            if (_familyIdentifier.Source != null) 
            {
                // named font family: hash based on canonical name 
                return _familyIdentifier.GetHashCode(); 
            }
            else 
            {
                // unnamed family: hash is based on object identity
                return base.GetHashCode();
            } 
        }
 
 
        /// 
        /// Equality check 
        /// 
        public override bool Equals(object o)
        {
            FontFamily f = o as FontFamily; 
            if (f == null)
            { 
                // different types or o == null 
                return false;
            } 
            else if (_familyIdentifier.Source != null)
            {
                // named font family; compare canonical names
                return _familyIdentifier.Equals(f._familyIdentifier); 
            }
            else 
            { 
                // unnamed font families are equal only if they're the same instance
                return base.Equals(o); 
            }
        }

 
        /// 
        /// Verifies that the FontFamily can be changed and returns a CompositeFontFamily 
        ///  
        private CompositeFontFamily VerifyMutable()
        { 
            CompositeFontFamily mutableFamily = _firstFontFamily as CompositeFontFamily;

            if (mutableFamily == null)
            { 
                throw new NotSupportedException(SR.Get(SRID.FontFamily_ReadOnly));
            } 
 
            return mutableFamily;
        } 


        /// 
        /// First font family 
        /// 
        internal IFontFamily FirstFontFamily 
        { 
            get
            { 
                IFontFamily family = _firstFontFamily;

                if (family == null)
                { 
                    // Call Canonicalize() directly so it won't just be called on the boxed object.
                    _familyIdentifier.Canonicalize(); 
 
                    // Look up first font family from cache. If not found, construct a new one.
                    family = TypefaceMetricsCache.ReadonlyLookup(FamilyIdentifier) as IFontFamily; 

                    if (family == null)
                    {
                        FontStyle style     = FontStyles.Normal; 
                        FontWeight weight   = FontWeights.Normal;
                        FontStretch stretch = FontStretches.Normal; 
                        family = FindFirstFontFamilyAndFace(ref style, ref weight, ref stretch); 

                        if (family == null) 
                        {
                            // fall back to null font
                            family = LookupFontFamily(NullFontFamilyCanonicalName);
                            Invariant.Assert(family != null); 
                        }
 
                        TypefaceMetricsCache.Add(FamilyIdentifier, family); 
                    }
 
                    _firstFontFamily = family;
                }

                return family; 
            }
        } 
 

        #region Resolving family name to font family 

        /// 
        /// Scan the friendly name string finding the first valid font family
        ///  
        internal static IFontFamily FindFontFamilyFromFriendlyNameList(string friendlyNameList)
        { 
            IFontFamily firstFontFamily = null; 

            // Split limits the number of tokens in a family name. 
            FontFamilyIdentifier identifier = new FontFamilyIdentifier(friendlyNameList, null);
            for (int i = 0, c = identifier.Count; firstFontFamily == null && i < c; i++)
            {
                firstFontFamily = LookupFontFamily(identifier[i]); 
            }
 
            if (firstFontFamily == null) 
            {
                // cannot find first font family, assume null font for first font family 
                firstFontFamily = LookupFontFamily(NullFontFamilyCanonicalName);

                // null font family should always exist
                Invariant.Assert(firstFontFamily != null); 

            } 
 
            return firstFontFamily;
        } 


        /// 
        /// Create font family from canonical family and ensure at least a 
        /// fallback family is created if the specified name cannot be resolved.
        ///  
        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;
        } 
 

        ///  
        /// Look up font family from canonical name
        /// 
        /// font family canonical name
        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);
        }
 
        #endregion
 
 
        #region Resolving face name into font family and implied face
 
        /// 
        /// Precreates family collection for Windows Fonts folder, so that we don't have to repeat lookup
        /// every time for it.
        ///  
        /// 
        ///  
        /// Critical - Exposes windows font information. 
        /// Safe     - as this doesn't expose sensitive font directly
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private static FamilyCollection PreCreateDefaultFamilyCollection()
        {
            FamilyCollection familyCollection = FamilyCollection.FromWindowsFonts(Util.WindowsFontsUriObject); 
            return familyCollection;
        } 
 

        ///  
        /// Find the first valid IFontFamily, if any, for this FontFamily and sets the style, weight,
        /// and stretch to valies implied by the font family (e.g., "Arial Bold" implies FontWeight.Bold).
        /// 
        internal IFontFamily FindFirstFontFamilyAndFace( 
            ref FontStyle   style,
            ref FontWeight  weight, 
            ref FontStretch stretch 
            )
        { 

            if (_familyIdentifier.Source == null)
            {
                Invariant.Assert(_firstFontFamily != null, "Unnamed FontFamily should have a non-null first font family"); 
                return _firstFontFamily;
            } 
 
            IFontFamily firstFontFamily = null;
 
            _familyIdentifier.Canonicalize();

            for (int i = 0, c = _familyIdentifier.Count; firstFontFamily == null && i < c; ++i)
            { 
                firstFontFamily = LookupFontFamilyAndFace(
                    _familyIdentifier[i], 
                    ref style, 
                    ref weight,
                    ref stretch); 
            }

            return firstFontFamily;
        } 

 
        ///  
        /// Lookup font family from canonical name.
        ///  
        /// font face canonical name
        /// FontStyle implied by the font family.
        /// FontWeight implied by the font family.
        /// FontStretch implied by the font family. 
        /// The font family object.
        ///  
        /// Critical - This method accesses the Util.WindowsFontsUriObject which is privileged information 
        ///            and looks up from the font cache which is a critical operation.
        /// Safe     - This method returns a IFontFamily which is safe to passed around. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        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; 
        } 

        #endregion 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK