Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / System / Windows / Media / GlyphTypeface.cs / 1 / GlyphTypeface.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: GlyphTypeface implementation // // History: // 06/04/2003 : mleonov - Moved GlyphTypeface from GlyphRun.cs // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Windows; using System.Windows.Media.Composition; using System.Windows.Media.TextFormatting; using System.Windows.Markup; using MS.Internal.FontRasterization; using MS.Internal; using MS.Internal.FontCache; using MS.Internal.FontFace; using MS.Internal.PresentationCore; namespace System.Windows.Media { ////// Physical font face corresponds to a font file on the disk /// public class GlyphTypeface : ITypefaceMetrics, ISupportInitialize { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors ////// Creates an uninitialized GlyphTypeface object. Caller should call ISupportInitialize.BeginInit() /// to begin initializing the object and call ISupportInitialize.EndInit() to finish the initialization. /// public GlyphTypeface() { } ////// Creates a new GlyphTypeface object from a .otf, .ttf or .ttc font face specified by typefaceSource. /// The constructed GlyphTypeface does not use style simulations. /// /// Specifies the URI of a font file used by the newly created GlyphTypeface. public GlyphTypeface(Uri typefaceSource) : this(typefaceSource, StyleSimulations.None) {} ////// Creates a new GlyphTypeface object from a .otf, .ttf or .ttc font face specified by typefaceSource. /// The constructed GlyphTypeface uses style simulations specified by styleSimulations parameter. /// /// Specifies the URI of a font file used by the newly created GlyphTypeface. /// Specifies style simulations to be applied to the newly created GlyphTypeface. ////// Critical - as this calls the internal constructor that's critical. /// Safe - as the internal constructor does a Demand for FileIO for file /// Uris for the case where fromPublic is true. We block constructing /// GlyphTypeface directly in SEE since this'd allow guessing fonts on /// a machine by trying to create a GlyphTypeface object. /// /// [SecurityCritical] public GlyphTypeface(Uri typefaceSource, StyleSimulations styleSimulations) : this (typefaceSource, styleSimulations, /* fromPublic = */ true) {} ////// Creates a new GlyphTypeface object from a .otf, .ttf or .ttc font face specified by typefaceSource. /// The constructed GlyphTypeface uses style simulations specified by styleSimulations parameter. /// /// Specifies the URI of a font file used by the newly created GlyphTypeface. /// Specifies style simulations to be applied to the newly created GlyphTypeface. /// Specifies if the call to the constructor is from a public constructor /// or if its from an internal method. For public constructor we demand FileIO for all files whereas /// for internal calls we don't demand in the constructor. ////// Critical - as the instance of GlyphTypeface created with this constructor can /// expose font information for the case where fromPublic is false. /// [SecurityCritical] internal GlyphTypeface(Uri typefaceSource, StyleSimulations styleSimulations, bool fromPublic) { Initialize(typefaceSource, styleSimulations, fromPublic); } ////// Critical - this method calls into other critical method. /// [SecurityCritical] private void Initialize(Uri typefaceSource, StyleSimulations styleSimulations, bool fromPublic) { if (typefaceSource == null) throw new ArgumentNullException("typefaceSource"); if (!typefaceSource.IsAbsoluteUri) throw new ArgumentException(SR.Get(SRID.UriNotAbsolute), "typefaceSource"); // remember the original Uri that contains face index _originalUri = new SecurityCriticalDataClass(typefaceSource); // split the Uri into the font source Uri and face index Uri fontSourceUri; int faceIndex; Util.SplitFontFaceIndex(typefaceSource, out fontSourceUri, out faceIndex); _fileIOPermObj = new SecurityCriticalDataForSet ( SecurityHelper.CreateUriReadPermission(fontSourceUri) ); // This permission demand is here so that untrusted callers are unable to check for file existence using GlyphTypeface ctor. // Sensitive font data is protected by demands as the user tries to access it. // The demand below is skipped for non-public calls, because in such cases // fonts are exposed as logical fonts to the end user. if (fromPublic) DemandPermissionsForFontInformation(); // We skip permission demands for FontSource because the above line already demands them for the right callers. _fontFace = new FontFaceLayoutInfo(new FontSource(fontSourceUri, true), faceIndex); CacheManager.Lookup(_fontFace); if ((styleSimulations & ~StyleSimulations.BoldItalicSimulation) != 0) throw new InvalidEnumArgumentException("styleSimulations", (int)styleSimulations, typeof(StyleSimulations)); _styleSimulations = styleSimulations; _initializationState = InitializationState.IsInitialized; // fully initialized } #endregion Constructors //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods /// /// Return hash code for this GlyphTypeface. /// ///Hash code. ////// Critical - as this accesses _originalUri. /// Safe - as this only does this to compute the hash code. /// [SecurityCritical] public override int GetHashCode() { CheckInitialized(); return _originalUri.Value.GetHashCode() ^ (int)StyleSimulations; } ////// Compares this GlyphTypeface with another object. /// /// Object to compare with. ///Whether this object is equal to the input object. ////// Critical - as this accesses _originalUri. /// Safe - as this only does this to perform a comparison with another object. /// [SecurityCritical] public override bool Equals(object o) { CheckInitialized(); GlyphTypeface t = o as GlyphTypeface; if (t == null) return false; return StyleSimulations == t.StyleSimulations && _originalUri.Value == t._originalUri.Value; } ////// Returns a geometry describing the path for a single glyph in the font. /// The path represents the glyph /// without grid fitting applied for rendering at a specific resolution. /// /// Index of the glyph to get outline for. /// Font size in drawing surface units. /// Size to hint for in points. ///[CLSCompliant(false)] public Geometry GetGlyphOutline(ushort glyphIndex, double renderingEmSize, double hintingEmSize) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface // NOTE: This parameter is unused, and should be deleted. Not worth a breaking change just for this though. return ComputeGlyphOutline(glyphIndex, false, renderingEmSize); } /// /// Returns the binary image of font subset. /// /// Collection of glyph indices to be included into the subset. ///Binary image of font subset. ////// Callers must have UnmanagedCode permission to call this API. /// Callers must have FileIOPermission or WebPermission to font location to call this API. /// ////// Critical - returns raw font data. /// Safe - (1) unmanaged code demand. This ensures PT callers can't directly access the TrueType subsetter in V1. /// (2) fileIO or web permission demand for location of font. This ensures that even brokered access /// via print dialog (which asserts unmanaged code) only succeeds if user has access to font source location. /// [SecurityCritical] [CLSCompliant(false)] public byte[] ComputeSubset(ICollectionglyphs) { SecurityHelper.DemandUnmanagedCode(); DemandPermissionsForFontInformation(); CheckInitialized(); // This can only be called on fully initialized GlyphTypeface if (glyphs == null) throw new ArgumentNullException("glyphs"); if (glyphs.Count <= 0) throw new ArgumentException(SR.Get(SRID.CollectionNumberOfElementsMustBeGreaterThanZero), "glyphs"); if (glyphs.Count > ushort.MaxValue) throw new ArgumentException(SR.Get(SRID.CollectionNumberOfElementsMustBeLessOrEqualTo, ushort.MaxValue), "glyphs"); UnmanagedMemoryStream pinnedFontSource = FontSource.GetUnmanagedStream(); try { TrueTypeFontDriver trueTypeDriver = new TrueTypeFontDriver(pinnedFontSource, _originalUri.Value); trueTypeDriver.SetFace(FaceIndex); return trueTypeDriver.ComputeFontSubset(glyphs); } catch (SEHException e) { throw Util.ConvertInPageException(FontSource, e); } finally { pinnedFontSource.Close(); } } /// /// Returns a font file stream represented by this GlyphTypeface. /// ///A font file stream represented by this GlyphTypeface. ////// Critical - returns raw font data. /// Safe - does a demand before it gives out the information asked. /// [SecurityCritical] public Stream GetFontStream() { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return FontSource.GetStream(); } ////// Exposed to allow printing code to access GetFontStream() in partial trust /// ////// Critical - returns a permission allowing access to GetFontStream in partial trust. /// Caller must make sure there is no font data leak /// [FriendAccessAllowed] internal CodeAccessPermission CriticalFileReadPermission { [SecurityCritical] get { CheckInitialized(); return _fileIOPermObj.Value; } } ////// Exposed to allow printing code to access FontUri in partial trust /// ////// Critical - returns a permission allowing access to FontUri /// Caller must make sure there is no data leak /// [FriendAccessAllowed] internal CodeAccessPermission CriticalUriDiscoveryPermission { [SecurityCritical] get { CheckInitialized(); return SecurityHelper.CreateUriDiscoveryPermission(_originalUri.Value); } } #endregion Public Methods //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ #region Public Properties ////// Returns the original Uri of this glyph typeface object. /// ///The Uri glyph typeface was constructed with. ////// Callers must have FileIOPermission(FileIOPermissionAccess.PathDiscovery) for the given Uri to call this API. /// ////// Critical - as this obtains Uri that can reveal local file system information. /// Safe - as this does a discovery demand before it gives out the information asked. /// public Uri FontUri { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface SecurityHelper.DemandUriDiscoveryPermission(_originalUri.Value); return _originalUri.Value; } [SecurityCritical] set { CheckInitializing(); // This can only be called in initialization if (value == null) throw new ArgumentNullException("value"); if (!value.IsAbsoluteUri) throw new ArgumentException(SR.Get(SRID.UriNotAbsolute), "value"); _originalUri = new SecurityCriticalDataClass(value); } } /// /// This property is indexed by a Culture Identifier. /// It returns the family name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the family name in English. /// The family name excludes weight, style and stretch. /// public IDictionaryFamilyNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GetFamilyNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// It returns the face name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the face name in English. /// The face name may identify weight, style and/or stretch. /// public IDictionaryFaceNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GetFaceNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// It returns the family name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the family name in English. /// The Win32FamilyName name excludes regular or bold weights and style, /// but includes other weights and stretch. /// public IDictionaryWin32FamilyNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GetWin32FamilyNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// It returns the face name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the face name in English. /// The face name may identify weight, style and/or stretch. /// IDictionaryITypefaceMetrics.AdjustedFaceNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface IDictionary adjustedFaceNames = _fontFace.GetAdjustedFaceNameDictionary(); IDictionary adjustedLanguageFaceNames = new Dictionary (adjustedFaceNames.Count); foreach (KeyValuePair pair in adjustedFaceNames) { adjustedLanguageFaceNames[XmlLanguage.GetLanguage(pair.Key.IetfLanguageTag)] = pair.Value; } if (_styleSimulations != StyleSimulations.None) { adjustedLanguageFaceNames = FontDifferentiator.AppendSimulationsToFaceNames(adjustedLanguageFaceNames, _styleSimulations); } return adjustedLanguageFaceNames; } } /// /// This property is indexed by a Culture Identifier. /// It returns the face name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the face name in English. /// The Win32Face name may identify weights other than regular or bold and/or style, /// but may not identify stretch or other weights. /// public IDictionaryWin32FaceNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GetWin32FaceNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Version string in the fonts NAME table. /// Version strings vary significantly in format - to obtain the version /// as a numeric value use the 'Version' property, /// do not attempt to parse the VersionString. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryVersionStrings { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetVersionStringDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Copyright notice. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryCopyrights { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetCopyrightDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Manufacturer Name. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryManufacturerNames { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetManufacturerNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// This is used to save any trademark notice/information for this font. /// Such information should be based on legal advice. /// This is distinctly separate from the copyright. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryTrademarks { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetTrademarkDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Name of the designer of the typeface. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryDesignerNames { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetDesignerNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Description of the typeface. Can contain revision information, /// usage recommendations, history, features, etc. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryDescriptions { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetDescriptionDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// URL of font vendor (with protocol, e.g., `http://, `ftp://). /// If a unique serial number is embedded in the URL, /// it can be used to register the font. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryVendorUrls { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetVendorUrlDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// URL of typeface designer (with protocol, e.g., `http://, `ftp://). /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryDesignerUrls { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetDesignerUrlDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Description of how the font may be legally used, /// or different example scenarios for licensed use. /// This field should be written in plain language, not legalese. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryLicenseDescriptions { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetLicenseDescriptionDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// This can be the font name, or any other text that the designer /// thinks is the best sample to display the font in. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionarySampleTexts { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetSampleTextDictionary(); } } /// /// Returns designed style (regular/italic/oblique) of this font face /// ///Designed style of this font face. public FontStyle Style { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.Style; } } ////// Returns designed weight of this font face. /// ///Designed weight of this font face. public FontWeight Weight { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.Weight; } } ////// Returns designed stretch of this font face. /// ///Designed stretch of this font face. public FontStretch Stretch { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.Stretch; } } ////// Font face version interpreted from the font's 'NAME' table. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public double Version { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.Version; } } ////// Height of character cell relative to em size. /// public double Height { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)(_fontFace.DesignCellAscent + _fontFace.DesignCellDescent) / DesignEmHeight; } } ////// Distance from cell top to English baseline relative to em size. /// public double Baseline { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.DesignCellAscent / DesignEmHeight; } } ////// Distance from baseline to top of English ----, relative to em size. /// public double CapsHeight { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.CapsHeight / DesignEmHeight; } } ////// Western x-height relative to em size. /// public double XHeight { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.xHeight / DesignEmHeight; } } ////// Returns true if this font does not conform to Unicode encoding: /// it may be considered as a simple collection of symbols indexed by a codepoint. /// public bool Symbol { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.Symbol; } } ////// Position of underline relative to baseline relative to em size. /// The value is usually negative, to place the underline below the baseline. /// public double UnderlinePosition { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.UnderlinePosition / DesignEmHeight; } } ////// Thickness of underline relative to em size. /// public double UnderlineThickness { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.UnderlineThickness / DesignEmHeight; } } ////// Position of strikeThrough relative to baseline relative to em size. /// The value is usually positive, to place the Strikethrough above the baseline. /// public double StrikethroughPosition { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.StrikethroughPosition / DesignEmHeight; } } ////// Thickness of Strikethrough relative to em size. /// public double StrikethroughThickness { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.StrikethroughThickness / DesignEmHeight; } } ////// EmbeddingRights property describes font embedding permissions /// specified in this glyph typeface. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public FontEmbeddingRight EmbeddingRights { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.EmbeddingRights; } } #region ITypefaceMetrics implementation ////// Distance from baseline to top of English ----, relative to em size. /// double ITypefaceMetrics.CapsHeight { get { return CapsHeight; } } ////// Western x-height relative to em size. /// double ITypefaceMetrics.XHeight { get { return XHeight; } } ////// Returns true if this font does not conform to Unicode encoding: /// it may be considered as a simple collection of symbols indexed by a codepoint. /// bool ITypefaceMetrics.Symbol { get { return Symbol; } } ////// Position of underline relative to baseline relative to em size. /// The value is usually negative, to place the underline below the baseline. /// double ITypefaceMetrics.UnderlinePosition { get { return UnderlinePosition; } } ////// Thickness of underline relative to em size. /// double ITypefaceMetrics.UnderlineThickness { get { return UnderlineThickness; } } ////// Position of strikeThrough relative to baseline relative to em size. /// The value is usually positive, to place the Strikethrough above the baseline. /// double ITypefaceMetrics.StrikethroughPosition { get { return StrikethroughPosition; } } ////// Thickness of Strikethrough relative to em size. /// double ITypefaceMetrics.StrikethroughThickness { get { return StrikethroughThickness; } } #endregion // The next several properties return non CLS-compliant types. This is // tracked by bug 1792236. For now, suppress the compiler warning. // #pragma warning disable 3003 ////// Returns advance width for a given glyph. /// public IDictionaryAdvanceWidths { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetAdvanceWidth, _fontFace.GlyphCount); } } /// /// Returns Advance height for a given glyph (Used for example in vertical layout). /// public IDictionaryAdvanceHeights { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetAdvanceHeight, _fontFace.GlyphCount); } } /// /// Distance from leading end of advance vector to left edge of black box. /// Positive when left edge of black box is within the alignment rectangle /// defined by the advance width and font cell height. /// Negative when left edge of black box overhangs the alignment rectangle. /// public IDictionaryLeftSideBearings { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetLeftSidebearing, _fontFace.GlyphCount); } } /// /// Distance from right edge of black box to right end of advance vector. /// Positive when trailing edge of black box is within the alignment rectangle /// defined by the advance width and font cell height. /// Negative when right edge of black box overhangs the alignment rectangle. /// public IDictionaryRightSideBearings { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetRightSidebearing, _fontFace.GlyphCount); } } /// /// Distance from top end of (vertical) advance vector to top edge of black box. /// Positive when top edge of black box is within the alignment rectangle /// defined by the advance height and font cell height. /// (The font cell height is a horizontal dimension in vertical layout). /// Negative when top edge of black box overhangs the alignment rectangle. /// public IDictionaryTopSideBearings { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetTopSidebearing, _fontFace.GlyphCount); } } /// /// Distance from bottom edge of black box to bottom end of advance vector. /// Positive when bottom edge of black box is within the alignment rectangle /// defined by the advance width and font cell height. /// (The font cell height is a horizontal dimension in vertical layout). /// Negative when bottom edge of black box overhangs the alignment rectangle. /// public IDictionaryBottomSideBearings { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetBottomSidebearing, _fontFace.GlyphCount); } } /// /// Offset down from horizontal Western baseline to bottom of glyph black box. /// public IDictionaryDistancesFromHorizontalBaselineToBlackBoxBottom { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetBaseline, _fontFace.GlyphCount); } } /// /// Returns nominal mapping of Unicode codepoint to glyph index as defined by the font 'CMAP' table. /// ////// Critical: May potentially leak a writeable cmap. /// Safe: The cmap IDictionary exposure is read only. /// public IDictionaryCharacterToGlyphMap { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.CharacterMap; } } #pragma warning restore 3003 /// /// Returns algorithmic font style simulations to be applied to the GlyphTypeface. /// public StyleSimulations StyleSimulations { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _styleSimulations; } set { CheckInitializing(); _styleSimulations = value; } } ////// Obtains the number of glyphs in the glyph typeface. /// ///The number of glyphs in the glyph typeface. public int GlyphCount { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GlyphCount; } } #endregion Public Properties //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods ////// Returns the nominal advance width for a glyph. /// /// Glyph index in the font. ///The nominal advance width for the glyph relative to the em size of the font. ////// Critical - as this has unsafe block. /// Safe - as this only gives width information which is safe to give out. /// [SecurityCritical, SecurityTreatAsSafe] internal double GetAdvanceWidth(ushort glyph) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface // We manually expand GetGlyphMetrics call because GetAdvanceWidth is a very frequently used function. // When we get to using GetAdvanceHeight for vertical writing, we need to consider doing the same optimization there. unsafe { FontFaceLayoutInfo.GlyphMetrics * cachedGlyphMetrics = _fontFace.Metrics(glyph); double aw = (double)cachedGlyphMetrics->advanceWidth / DesignEmHeight; if ((_styleSimulations & StyleSimulations.BoldSimulation) != 0) { // Bold simulation increases advance width and advance height by 2% of em size, // except for glyphs that are empty or have zero advance widths. // So, we compensate for the simulation when aw != 0 && left < right && ah != 0 && bottom > top if (cachedGlyphMetrics->advanceWidth != 0 && cachedGlyphMetrics->lsb < cachedGlyphMetrics->advanceWidth - cachedGlyphMetrics->rsb && cachedGlyphMetrics->advanceHeight != 0 && cachedGlyphMetrics->advanceHeight - cachedGlyphMetrics->tsb - cachedGlyphMetrics->bsb > 0) { aw += 0.02; } } return aw; } } ////// Returns the nominal advance width for a glyph in font design units. /// /// Glyph index in the font. ///The nominal advance width for the glyph in font design units. internal double GetAdvanceWidthInDesignUnits(ushort glyph) { return GetAdvanceWidth(glyph) * DesignEmHeight; } ////// This function will demand appropriate permissions depending on what /// the source of the font information is. The value of _fileIOPermObj /// is set correctly whenever _originalUri gets set. /// internal void DemandPermissionsForFontInformation() { if (_fileIOPermObj.Value != null) { _fileIOPermObj.Value.Demand(); } } private double GetAdvanceHeight(ushort glyph) { double aw, ah, lsb, rsb, tsb, bsb, baseline; GetGlyphMetrics( glyph, 1.0, out aw, out ah, out lsb, out rsb, out tsb, out bsb, out baseline ); return ah; } private double GetLeftSidebearing(ushort glyph) { return (double)_fontFace.GetLeftSidebearing(glyph) / DesignEmHeight; } private double GetRightSidebearing(ushort glyph) { return (double)_fontFace.GetRightSidebearing(glyph) / DesignEmHeight; } private double GetTopSidebearing(ushort glyph) { return (double)_fontFace.GetTopSidebearing(glyph) / DesignEmHeight; } private double GetBottomSidebearing(ushort glyph) { return (double)_fontFace.GetBottomSidebearing(glyph) / DesignEmHeight; } private double GetBaseline(ushort glyph) { return (double)_fontFace.GetBaseline(glyph) / DesignEmHeight; } ////// Optimized version of obtaining all of glyph metrics from font cache at once /// without repeated checks and divisions. /// ////// Critical - as this uses unsafe code. /// Safe - as this only gives information which is safe to give out. /// [SecurityCritical, SecurityTreatAsSafe] internal void GetGlyphMetrics( ushort glyph, double renderingEmSize, out double aw, out double ah, out double lsb, out double rsb, out double tsb, out double bsb, out double baseline ) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface unsafe { FontFaceLayoutInfo.GlyphMetrics * cachedGlyphMetrics = _fontFace.Metrics(glyph); double designToEm = renderingEmSize / DesignEmHeight; aw = designToEm * cachedGlyphMetrics->advanceWidth; ah = designToEm * cachedGlyphMetrics->advanceHeight; lsb = designToEm * cachedGlyphMetrics->lsb; rsb = designToEm * cachedGlyphMetrics->rsb; tsb = designToEm * cachedGlyphMetrics->tsb; bsb = designToEm * cachedGlyphMetrics->bsb; baseline = designToEm * cachedGlyphMetrics->baseline; if ((_styleSimulations & StyleSimulations.BoldSimulation) != 0) { // Bold simulation increases advance width and advance height by 2% of em size, // except for glyphs that are empty or have zero advance widths. // So, we compensate for the simulation when aw != 0 && left < right && ah != 0 && bottom > top if (cachedGlyphMetrics->advanceWidth != 0 && cachedGlyphMetrics->lsb < cachedGlyphMetrics->advanceWidth - cachedGlyphMetrics->rsb && cachedGlyphMetrics->advanceHeight != 0 && cachedGlyphMetrics->advanceHeight - cachedGlyphMetrics->tsb - cachedGlyphMetrics->bsb > 0) { aw += 0.02 * renderingEmSize; ah += 0.02 * renderingEmSize; } } } } ////// Returns a geometry describing the path for a single glyph in the font. /// The path represents the glyph /// without grid fitting applied for rendering at a specific resolution. /// /// Index of the glyph to get outline for. /// Specifies whether the glyph should be rotated sideways. /// Font size in drawing surface units. ///Geometry containing glyph outline. ////// Critical - as this calls GetGlyphs() which is critical. /// Safe - as this doesn't expose font information but just gives out a Geometry. /// [SecurityCritical, SecurityTreatAsSafe] internal Geometry ComputeGlyphOutline(ushort glyphIndex, bool sideways, double renderingEmSize) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface using (GlyphPathElement pathElement = new GlyphPathElement( FaceIndex, FontSource, GetRenderingFlags(sideways), DesignEmHeight )) { PathGeometry pathGeometry; unsafe { void*[] glyphOutlines = new void*[1]; FontCacheAccessor fontCacheAccessor = new FontCacheAccessor(); ushort[] glyphIndices = new ushort[1] { glyphIndex }; fontCacheAccessor.GetGlyphs( pathElement, glyphIndices, glyphOutlines ); void * outline = glyphOutlines[0]; Debug.Assert(outline != null); if (FontTechnology == FontTechnology.PostscriptOpenType) ConvertPostscriptOutline(outline, renderingEmSize, sideways, out pathGeometry); else ConvertTrueTypeOutline(outline, renderingEmSize, sideways, out pathGeometry); // Make sure fontCacheAccessor doesn't go out of scope before the outlines get converted. GC.KeepAlive(fontCacheAccessor); } // Make sure to always return Geometry.Empty from public methods for empty geometries. if (pathGeometry == null || pathGeometry.IsEmpty()) return Geometry.Empty; return pathGeometry; } } ////// Critical - unsafe code, accepts pointer parameters, etc. /// [SecurityCritical] private unsafe void ConvertTrueTypeOutline(void* trueTypeOutline, double renderingEmSize, bool sideways, out PathGeometry pathGeometry) { GlyphPathData * outline = (GlyphPathData *)trueTypeOutline; // scale factor from design units to user coordinate system double designToUserScale = renderingEmSize / DesignEmHeight; Matrix designToUser = new Matrix(designToUserScale, 0, 0, -designToUserScale, 0, 0); if (sideways) { designToUser.Rotate(-90.0); designToUser.Translate(outline->verOriginY * designToUserScale, outline->verOriginX * designToUserScale); } ushort* endp = GlyphPathData.EndPointNumbers(outline); short* x = GlyphPathData.X(outline); short* y = GlyphPathData.Y(outline); byte* flags = GlyphPathData.Flags(outline); // k is the index of the first point of the current contour int k = 0; pathGeometry = null; // j is the index of the current contour for (int j = 0; j < outline->numberOfContours; ++j) { int lastPointIndex = endp[j]; if (lastPointIndex <= k) { k = lastPointIndex + 1; continue; // empty contour } Point startPoint; PathFigure figure = new PathFigure(); // The first point on the curve if (OnCurve(flags[k])) { // Easy case startPoint = designToUser.Transform(new Point(x[k], y[k])); ++k; } else { // Is last contour point on the curve if (OnCurve(flags[lastPointIndex])) { // Make the last point the first point and decrement the last point startPoint = designToUser.Transform(new Point(x[lastPointIndex], y[lastPointIndex])); --lastPointIndex; } else { // First and last point are off the countour, fake a mid point Point firstPoint = designToUser.Transform(new Point(x[k], y[k])); Point lastPoint = designToUser.Transform(new Point(x[lastPointIndex], y[lastPointIndex])); startPoint = new Point( (firstPoint.X + lastPoint.X) / 2, (firstPoint.Y + lastPoint.Y) / 2 ); } } figure.StartPoint = startPoint; bool inBezier = false; Point bezierB = new Point(); while (k <= lastPointIndex) { Point currentPoint = designToUser.Transform(new Point(x[k], y[k])); if (OnCurve(flags[k])) { if (!inBezier) { figure.Segments.Add(new LineSegment(currentPoint, true)); } else { figure.Segments.Add(new QuadraticBezierSegment(bezierB, currentPoint, true)); inBezier = false; } } else { if (inBezier) { figure.Segments.Add(new QuadraticBezierSegment( bezierB, new Point( (bezierB.X + currentPoint.X) / 2, (bezierB.Y + currentPoint.Y) / 2 ), true) ); } inBezier = true; bezierB = currentPoint; } ++k; } // explicitly set k to the start point of the next contour // since in some cases lastPointIndex is not equal to endp[j] k = endp[j] + 1; // close the figure, assume start point is always on curve if (inBezier) { figure.Segments.Add(new QuadraticBezierSegment(bezierB, startPoint, true)); } figure.IsClosed = true; if (pathGeometry == null) { pathGeometry = new PathGeometry(); pathGeometry.FillRule = FillRule.Nonzero; } pathGeometry.Figures.Add(figure); } } ////// Critical - unsafe code, accepts pointer parameters, etc. /// [SecurityCritical] private unsafe void ConvertPostscriptOutline(void * outline, double renderingEmSize, bool sideways, out PathGeometry pathGeometry) { int * postscriptOutline = (int *)outline; // scale factor from design units to user coordinate system double designToUserScale = renderingEmSize / DesignEmHeight; Matrix designToUser = new Matrix(designToUserScale, 0, 0, -designToUserScale, 0, 0); if (sideways) { int verOriginX = postscriptOutline[0]; int verOriginY = postscriptOutline[1]; designToUser.Rotate(-90.0); designToUser.Translate(verOriginY * designToUserScale, verOriginX * designToUserScale); } // Skip vertical origin and length to get to the actual contour data. int * p = postscriptOutline + 3; Debug.Assert(postscriptOutline[2] % sizeof(int) == 0); int * end = p + (postscriptOutline[2] / sizeof(int)); pathGeometry = null; // Current figure. PathFigure figure = null; for (;;) { if (p >= end) break; int tokenValue = *p; switch ((OutlineTokenType)tokenValue) { case OutlineTokenType.MoveTo: { ++p; if (p + 1 >= end) throw new FileFormatException(_originalUri.Value); Point point = designToUser.Transform( new Point(p[0] * CFFConversionFactor, p[1] * CFFConversionFactor) ); if (figure == null) figure = new PathFigure(); figure.StartPoint = point; p += 2; break; } case OutlineTokenType.LineTo: { ++p; if (p + 1 >= end) throw new FileFormatException(_originalUri.Value); Point point = designToUser.Transform( new Point(p[0] * CFFConversionFactor, p[1] * CFFConversionFactor) ); if (figure == null) throw new FileFormatException(_originalUri.Value); figure.Segments.Add(new LineSegment(point, true)); p += 2; break; } case OutlineTokenType.CurveTo: { ++p; if (p + 5 >= end) throw new FileFormatException(_originalUri.Value); Point point0 = designToUser.Transform( new Point(p[0] * CFFConversionFactor, p[1] * CFFConversionFactor) ); Point point1 = designToUser.Transform( new Point(p[2] * CFFConversionFactor, p[3] * CFFConversionFactor) ); Point point2 = designToUser.Transform( new Point(p[4] * CFFConversionFactor, p[5] * CFFConversionFactor) ); if (figure == null) throw new FileFormatException(_originalUri.Value); figure.Segments.Add(new BezierSegment(point0, point1, point2, true)); p += 6; break; } case OutlineTokenType.ClosePath: if (figure == null) throw new FileFormatException(_originalUri.Value); figure.IsClosed = true; if (pathGeometry == null) { pathGeometry = new PathGeometry(); pathGeometry.FillRule = FillRule.Nonzero; } pathGeometry.Figures.Add(figure); figure = null; ++p; break; default: throw new FileFormatException(_originalUri.Value); } } } ////// Get advance widths of unshaped characters /// /// character string /// character length /// character em size /// unshaped advance widths /// true if all characters map to missing glyph ///array of character advance widths ////// Critical - takes unsafe char string and returns information in an unsafe int array /// [SecurityCritical] internal unsafe void GetAdvanceWidthsUnshaped( char* unsafeCharString, int stringLength, double emSize, int* advanceWidthsUnshaped, bool nullFont ) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface Invariant.Assert(stringLength > 0); if (!nullFont) { IDictionarycmap = CharacterToGlyphMap; for (int i = 0; i < stringLength; i++) { ushort glyphIndex; cmap.TryGetValue(unsafeCharString[i], out glyphIndex); advanceWidthsUnshaped[i] = (int)Math.Round(emSize * GetAdvanceWidth(glyphIndex)); } } else { int missingGlyphWidth = (int)Math.Round(emSize * GetAdvanceWidth(0)); for (int i = 0; i < stringLength; i++) { advanceWidthsUnshaped[i] = missingGlyphWidth; } } } /// /// Compute an unshaped glyphrun object from specified character-based info /// internal GlyphRun ComputeUnshapedGlyphRun( Point origin, CharacterBufferRange charBufferRange, IListcharWidths, double emSize, double emHintingSize, bool nullGlyph, CultureInfo cultureInfo, string deviceFontName ) { Debug.Assert(charBufferRange.Length > 0); CheckInitialized(); // This can only be called on fully initialized GlyphTypeface ushort[] nominalGlyphs = new ushort[charBufferRange.Length]; // compute glyph positions if (nullGlyph) { for (int i = 0; i < charBufferRange.Length; i++) { nominalGlyphs[i] = 0; } } else { IDictionary cmap = CharacterToGlyphMap; for (int i = 0; i < charBufferRange.Length; i++) { ushort glyphIndex; cmap.TryGetValue(charBufferRange[i], out glyphIndex); nominalGlyphs[i] = glyphIndex; } } return GlyphRun.TryCreate( this, 0, // bidiLevel false, // sideway emSize, nominalGlyphs, origin, charWidths, null, // glyphOffsets new PartialList (charBufferRange.CharacterBuffer, charBufferRange.OffsetToFirstChar, charBufferRange.Length), deviceFontName, // device font null, // 1:1 mapping null, // caret stops at every codepoint XmlLanguage.GetLanguage(cultureInfo.IetfLanguageTag) ); } #endregion Internal Methods //----------------------------------------------------- // // Internal Properties // //----------------------------------------------------- #region Internal Properties internal FontSource FontSource { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.FontSource; } } /// /// 0 for TTF files /// Face index within TrueType font collection for TTC files /// internal int FaceIndex { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.FaceIndex; } } internal FontFaceLayoutInfo FontFaceLayoutInfo { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace; } } internal ushort BlankGlyphIndex { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.BlankGlyph; } } internal FontFaceLayoutInfo.RenderingHints RenderingHints { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.FontRenderingHints; } } internal FontTechnology FontTechnology { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.FontTechnology; } } internal short FontContrastAdjustment { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface Debug.Assert(-3 <= _fontFace.FontContrastAdjustment && _fontFace.FontContrastAdjustment <= 4); return _fontFace.FontContrastAdjustment; } } internal ushort DesignEmHeight { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.DesignEmHeight; } } #endregion Internal Properties //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ #region Private Methods private static bool OnCurve(byte flag) { return (flag & 0x01) != 0; } private ushort GetRenderingFlags(bool sideways) { ushort renderingFlags = 0; if ((_styleSimulations & StyleSimulations.BoldSimulation) != 0) renderingFlags |= (ushort)RenderingFlags.BoldSimulation; if ((_styleSimulations & StyleSimulations.ItalicSimulation) != 0) { renderingFlags |= (ushort)RenderingFlags.ItalicSimulation; if (sideways) renderingFlags |= (ushort)RenderingFlags.SidewaysItalicSimulation; } if (FontTechnology != FontTechnology.PostscriptOpenType) renderingFlags |= (ushort)MilGlyphRun.IsTrueType; return renderingFlags; } #endregion Private Methods #region ISupportInitialize interface void ISupportInitialize.BeginInit() { if (_initializationState == InitializationState.IsInitialized) { // Cannont initialize a GlyphRun this is completely initialized. throw new InvalidOperationException(SR.Get(SRID.OnlyOneInitialization)); } if (_initializationState == InitializationState.IsInitializing) { // Cannot initialize a GlyphRun this already being initialized. throw new InvalidOperationException(SR.Get(SRID.InInitialization)); } _initializationState = InitializationState.IsInitializing; } ////// Critical - this method calls into critical method. /// [SecurityCritical] void ISupportInitialize.EndInit() { if (_initializationState != InitializationState.IsInitializing) { // Cannot EndInit a GlyphRun that is not being initialized. throw new InvalidOperationException(SR.Get(SRID.NotInInitialization)); } Initialize( (_originalUri == null ? null : _originalUri.Value), _styleSimulations, true ); } private void CheckInitialized() { if (_initializationState != InitializationState.IsInitialized) { throw new InvalidOperationException(SR.Get(SRID.InitializationIncomplete)); } } private void CheckInitializing() { if (_initializationState != InitializationState.IsInitializing) { throw new InvalidOperationException(SR.Get(SRID.NotInInitialization)); } } #endregion //----------------------------------------------------- // // Private Nested Classes // //------------------------------------------------------ #region Private Nested Classes private delegate double GlyphAccessor(ushort glyphIndex); ////// This class is a helper to implement named indexers /// for glyph metrics. /// private class GlyphIndexer : IDictionary{ internal GlyphIndexer(GlyphAccessor accessor, ushort numberOfGlyphs) { _accessor = accessor; _numberOfGlyphs = numberOfGlyphs; } #region IDictionary Members public void Add(ushort key, double value) { throw new NotSupportedException(); } public bool ContainsKey(ushort key) { return (key < _numberOfGlyphs); } public ICollection Keys { get { return new SequentialUshortCollection(_numberOfGlyphs); } } public bool Remove(ushort key) { throw new NotSupportedException(); } public bool TryGetValue(ushort key, out double value) { if (ContainsKey(key)) { value = this[key]; return true; } else { value = new double(); return false; } } public ICollection Values { get { return new ValueCollection(this); } } public double this[ushort key] { get { return _accessor(key); } set { throw new NotSupportedException(); } } #endregion #region ICollection > Members public void Add(KeyValuePair item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public bool Contains(KeyValuePair item) { return ContainsKey(item.Key); } public void CopyTo(KeyValuePair [] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (array.Rank != 1) { throw new ArgumentException(SR.Get(SRID.Collection_BadRank)); } // The extra "arrayIndex >= array.Length" check in because even if _collection.Count // is 0 the index is not allowed to be equal or greater than the length // (from the MSDN ICollection docs) if (arrayIndex < 0 || arrayIndex >= array.Length || (arrayIndex + Count) > array.Length) { throw new ArgumentOutOfRangeException("arrayIndex"); } for (ushort i = 0; i < Count; ++i) array[arrayIndex + i] = new KeyValuePair (i, this[i]); } public int Count { get { return _numberOfGlyphs; } } public bool IsReadOnly { get { return true; } } public bool Remove(KeyValuePair item) { throw new NotSupportedException(); } #endregion #region IEnumerable > Members public IEnumerator > GetEnumerator() { for (ushort i = 0; i < Count; ++i) yield return new KeyValuePair (i, this[i]); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable >)this).GetEnumerator(); } #endregion private class ValueCollection : ICollection { public ValueCollection(GlyphIndexer glyphIndexer) { _glyphIndexer = glyphIndexer; } #region ICollection Members public void Add(double item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public bool Contains(double item) { foreach (double d in this) { if (d == item) return true; } return false; } public void CopyTo(double[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (array.Rank != 1) { throw new ArgumentException(SR.Get(SRID.Collection_BadRank)); } // The extra "arrayIndex >= array.Length" check in because even if _collection.Count // is 0 the index is not allowed to be equal or greater than the length // (from the MSDN ICollection docs) if (arrayIndex < 0 || arrayIndex >= array.Length || (arrayIndex + Count) > array.Length) { throw new ArgumentOutOfRangeException("arrayIndex"); } for (ushort i = 0; i < Count; ++i) array[arrayIndex + i] = _glyphIndexer[i]; } public int Count { get { return _glyphIndexer._numberOfGlyphs; } } public bool IsReadOnly { get { return true; } } public bool Remove(double item) { throw new NotSupportedException(); } #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { for (ushort i = 0; i < Count; ++i) yield return _glyphIndexer[i]; } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable )this).GetEnumerator(); } #endregion private GlyphIndexer _glyphIndexer; } private GlyphAccessor _accessor; private ushort _numberOfGlyphs; } #endregion Private Nested Classes //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- #region Private Fields private FontFaceLayoutInfo _fontFace; private StyleSimulations _styleSimulations; /// /// The Uri that was passed in to constructor. /// ////// This is critical as we do a demand based on this value public functions. /// Only setting this Uri is critical, getting is fine. Hence using the /// SecurityCriticalDataForSet object. Note that the object itself does not /// need to be Critical, it's just setting it that makes it Critical. /// private SecurityCriticalDataClass_originalUri; /// /// Critical - as this object controls the Demand that'll be made before accessssing the /// security sensitive contents of the font file. This also only Critical /// for set. This should be correctly whenever _originalUri is set. /// /// Caching object for perf reasons. /// private SecurityCriticalDataForSet_fileIOPermObj; private const double CFFConversionFactor = 1.0 / 65536.0; private InitializationState _initializationState; /// /// Initialization states of GlyphTypeface object. /// private enum InitializationState { ////// The state in which the GlyphTypeface has not been initialized. /// At this state, all operations on the object would cause InvalidOperationException. /// The object can only transit to 'IsInitializing' state with BeginInit() call. /// Uninitialized, ////// The state in which the GlyphTypeface is being initialized. At this state, user can /// set values into the required properties. The object can only transit to 'IsInitialized' state /// with EndInit() call. /// IsInitializing, ////// The state in which the GlyphTypeface object is fully initialized. At this state the object /// is fully functional. There is no valid transition out of the state. /// IsInitialized, } #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: GlyphTypeface implementation // // History: // 06/04/2003 : mleonov - Moved GlyphTypeface from GlyphRun.cs // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Windows; using System.Windows.Media.Composition; using System.Windows.Media.TextFormatting; using System.Windows.Markup; using MS.Internal.FontRasterization; using MS.Internal; using MS.Internal.FontCache; using MS.Internal.FontFace; using MS.Internal.PresentationCore; namespace System.Windows.Media { ////// Physical font face corresponds to a font file on the disk /// public class GlyphTypeface : ITypefaceMetrics, ISupportInitialize { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors ////// Creates an uninitialized GlyphTypeface object. Caller should call ISupportInitialize.BeginInit() /// to begin initializing the object and call ISupportInitialize.EndInit() to finish the initialization. /// public GlyphTypeface() { } ////// Creates a new GlyphTypeface object from a .otf, .ttf or .ttc font face specified by typefaceSource. /// The constructed GlyphTypeface does not use style simulations. /// /// Specifies the URI of a font file used by the newly created GlyphTypeface. public GlyphTypeface(Uri typefaceSource) : this(typefaceSource, StyleSimulations.None) {} ////// Creates a new GlyphTypeface object from a .otf, .ttf or .ttc font face specified by typefaceSource. /// The constructed GlyphTypeface uses style simulations specified by styleSimulations parameter. /// /// Specifies the URI of a font file used by the newly created GlyphTypeface. /// Specifies style simulations to be applied to the newly created GlyphTypeface. ////// Critical - as this calls the internal constructor that's critical. /// Safe - as the internal constructor does a Demand for FileIO for file /// Uris for the case where fromPublic is true. We block constructing /// GlyphTypeface directly in SEE since this'd allow guessing fonts on /// a machine by trying to create a GlyphTypeface object. /// /// [SecurityCritical] public GlyphTypeface(Uri typefaceSource, StyleSimulations styleSimulations) : this (typefaceSource, styleSimulations, /* fromPublic = */ true) {} ////// Creates a new GlyphTypeface object from a .otf, .ttf or .ttc font face specified by typefaceSource. /// The constructed GlyphTypeface uses style simulations specified by styleSimulations parameter. /// /// Specifies the URI of a font file used by the newly created GlyphTypeface. /// Specifies style simulations to be applied to the newly created GlyphTypeface. /// Specifies if the call to the constructor is from a public constructor /// or if its from an internal method. For public constructor we demand FileIO for all files whereas /// for internal calls we don't demand in the constructor. ////// Critical - as the instance of GlyphTypeface created with this constructor can /// expose font information for the case where fromPublic is false. /// [SecurityCritical] internal GlyphTypeface(Uri typefaceSource, StyleSimulations styleSimulations, bool fromPublic) { Initialize(typefaceSource, styleSimulations, fromPublic); } ////// Critical - this method calls into other critical method. /// [SecurityCritical] private void Initialize(Uri typefaceSource, StyleSimulations styleSimulations, bool fromPublic) { if (typefaceSource == null) throw new ArgumentNullException("typefaceSource"); if (!typefaceSource.IsAbsoluteUri) throw new ArgumentException(SR.Get(SRID.UriNotAbsolute), "typefaceSource"); // remember the original Uri that contains face index _originalUri = new SecurityCriticalDataClass(typefaceSource); // split the Uri into the font source Uri and face index Uri fontSourceUri; int faceIndex; Util.SplitFontFaceIndex(typefaceSource, out fontSourceUri, out faceIndex); _fileIOPermObj = new SecurityCriticalDataForSet ( SecurityHelper.CreateUriReadPermission(fontSourceUri) ); // This permission demand is here so that untrusted callers are unable to check for file existence using GlyphTypeface ctor. // Sensitive font data is protected by demands as the user tries to access it. // The demand below is skipped for non-public calls, because in such cases // fonts are exposed as logical fonts to the end user. if (fromPublic) DemandPermissionsForFontInformation(); // We skip permission demands for FontSource because the above line already demands them for the right callers. _fontFace = new FontFaceLayoutInfo(new FontSource(fontSourceUri, true), faceIndex); CacheManager.Lookup(_fontFace); if ((styleSimulations & ~StyleSimulations.BoldItalicSimulation) != 0) throw new InvalidEnumArgumentException("styleSimulations", (int)styleSimulations, typeof(StyleSimulations)); _styleSimulations = styleSimulations; _initializationState = InitializationState.IsInitialized; // fully initialized } #endregion Constructors //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods /// /// Return hash code for this GlyphTypeface. /// ///Hash code. ////// Critical - as this accesses _originalUri. /// Safe - as this only does this to compute the hash code. /// [SecurityCritical] public override int GetHashCode() { CheckInitialized(); return _originalUri.Value.GetHashCode() ^ (int)StyleSimulations; } ////// Compares this GlyphTypeface with another object. /// /// Object to compare with. ///Whether this object is equal to the input object. ////// Critical - as this accesses _originalUri. /// Safe - as this only does this to perform a comparison with another object. /// [SecurityCritical] public override bool Equals(object o) { CheckInitialized(); GlyphTypeface t = o as GlyphTypeface; if (t == null) return false; return StyleSimulations == t.StyleSimulations && _originalUri.Value == t._originalUri.Value; } ////// Returns a geometry describing the path for a single glyph in the font. /// The path represents the glyph /// without grid fitting applied for rendering at a specific resolution. /// /// Index of the glyph to get outline for. /// Font size in drawing surface units. /// Size to hint for in points. ///[CLSCompliant(false)] public Geometry GetGlyphOutline(ushort glyphIndex, double renderingEmSize, double hintingEmSize) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface // NOTE: This parameter is unused, and should be deleted. Not worth a breaking change just for this though. return ComputeGlyphOutline(glyphIndex, false, renderingEmSize); } /// /// Returns the binary image of font subset. /// /// Collection of glyph indices to be included into the subset. ///Binary image of font subset. ////// Callers must have UnmanagedCode permission to call this API. /// Callers must have FileIOPermission or WebPermission to font location to call this API. /// ////// Critical - returns raw font data. /// Safe - (1) unmanaged code demand. This ensures PT callers can't directly access the TrueType subsetter in V1. /// (2) fileIO or web permission demand for location of font. This ensures that even brokered access /// via print dialog (which asserts unmanaged code) only succeeds if user has access to font source location. /// [SecurityCritical] [CLSCompliant(false)] public byte[] ComputeSubset(ICollectionglyphs) { SecurityHelper.DemandUnmanagedCode(); DemandPermissionsForFontInformation(); CheckInitialized(); // This can only be called on fully initialized GlyphTypeface if (glyphs == null) throw new ArgumentNullException("glyphs"); if (glyphs.Count <= 0) throw new ArgumentException(SR.Get(SRID.CollectionNumberOfElementsMustBeGreaterThanZero), "glyphs"); if (glyphs.Count > ushort.MaxValue) throw new ArgumentException(SR.Get(SRID.CollectionNumberOfElementsMustBeLessOrEqualTo, ushort.MaxValue), "glyphs"); UnmanagedMemoryStream pinnedFontSource = FontSource.GetUnmanagedStream(); try { TrueTypeFontDriver trueTypeDriver = new TrueTypeFontDriver(pinnedFontSource, _originalUri.Value); trueTypeDriver.SetFace(FaceIndex); return trueTypeDriver.ComputeFontSubset(glyphs); } catch (SEHException e) { throw Util.ConvertInPageException(FontSource, e); } finally { pinnedFontSource.Close(); } } /// /// Returns a font file stream represented by this GlyphTypeface. /// ///A font file stream represented by this GlyphTypeface. ////// Critical - returns raw font data. /// Safe - does a demand before it gives out the information asked. /// [SecurityCritical] public Stream GetFontStream() { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return FontSource.GetStream(); } ////// Exposed to allow printing code to access GetFontStream() in partial trust /// ////// Critical - returns a permission allowing access to GetFontStream in partial trust. /// Caller must make sure there is no font data leak /// [FriendAccessAllowed] internal CodeAccessPermission CriticalFileReadPermission { [SecurityCritical] get { CheckInitialized(); return _fileIOPermObj.Value; } } ////// Exposed to allow printing code to access FontUri in partial trust /// ////// Critical - returns a permission allowing access to FontUri /// Caller must make sure there is no data leak /// [FriendAccessAllowed] internal CodeAccessPermission CriticalUriDiscoveryPermission { [SecurityCritical] get { CheckInitialized(); return SecurityHelper.CreateUriDiscoveryPermission(_originalUri.Value); } } #endregion Public Methods //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ #region Public Properties ////// Returns the original Uri of this glyph typeface object. /// ///The Uri glyph typeface was constructed with. ////// Callers must have FileIOPermission(FileIOPermissionAccess.PathDiscovery) for the given Uri to call this API. /// ////// Critical - as this obtains Uri that can reveal local file system information. /// Safe - as this does a discovery demand before it gives out the information asked. /// public Uri FontUri { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface SecurityHelper.DemandUriDiscoveryPermission(_originalUri.Value); return _originalUri.Value; } [SecurityCritical] set { CheckInitializing(); // This can only be called in initialization if (value == null) throw new ArgumentNullException("value"); if (!value.IsAbsoluteUri) throw new ArgumentException(SR.Get(SRID.UriNotAbsolute), "value"); _originalUri = new SecurityCriticalDataClass(value); } } /// /// This property is indexed by a Culture Identifier. /// It returns the family name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the family name in English. /// The family name excludes weight, style and stretch. /// public IDictionaryFamilyNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GetFamilyNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// It returns the face name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the face name in English. /// The face name may identify weight, style and/or stretch. /// public IDictionaryFaceNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GetFaceNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// It returns the family name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the family name in English. /// The Win32FamilyName name excludes regular or bold weights and style, /// but includes other weights and stretch. /// public IDictionaryWin32FamilyNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GetWin32FamilyNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// It returns the face name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the face name in English. /// The face name may identify weight, style and/or stretch. /// IDictionaryITypefaceMetrics.AdjustedFaceNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface IDictionary adjustedFaceNames = _fontFace.GetAdjustedFaceNameDictionary(); IDictionary adjustedLanguageFaceNames = new Dictionary (adjustedFaceNames.Count); foreach (KeyValuePair pair in adjustedFaceNames) { adjustedLanguageFaceNames[XmlLanguage.GetLanguage(pair.Key.IetfLanguageTag)] = pair.Value; } if (_styleSimulations != StyleSimulations.None) { adjustedLanguageFaceNames = FontDifferentiator.AppendSimulationsToFaceNames(adjustedLanguageFaceNames, _styleSimulations); } return adjustedLanguageFaceNames; } } /// /// This property is indexed by a Culture Identifier. /// It returns the face name in the specified language, or, /// if the font does not provide a name for the specified language, /// it returns the face name in English. /// The Win32Face name may identify weights other than regular or bold and/or style, /// but may not identify stretch or other weights. /// public IDictionaryWin32FaceNames { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GetWin32FaceNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Version string in the fonts NAME table. /// Version strings vary significantly in format - to obtain the version /// as a numeric value use the 'Version' property, /// do not attempt to parse the VersionString. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryVersionStrings { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetVersionStringDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Copyright notice. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryCopyrights { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetCopyrightDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Manufacturer Name. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryManufacturerNames { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetManufacturerNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// This is used to save any trademark notice/information for this font. /// Such information should be based on legal advice. /// This is distinctly separate from the copyright. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryTrademarks { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetTrademarkDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Name of the designer of the typeface. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryDesignerNames { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetDesignerNameDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Description of the typeface. Can contain revision information, /// usage recommendations, history, features, etc. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryDescriptions { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetDescriptionDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// URL of font vendor (with protocol, e.g., `http://, `ftp://). /// If a unique serial number is embedded in the URL, /// it can be used to register the font. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryVendorUrls { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetVendorUrlDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// URL of typeface designer (with protocol, e.g., `http://, `ftp://). /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryDesignerUrls { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetDesignerUrlDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// Description of how the font may be legally used, /// or different example scenarios for licensed use. /// This field should be written in plain language, not legalese. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionaryLicenseDescriptions { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetLicenseDescriptionDictionary(); } } /// /// This property is indexed by a Culture Identifier. /// This can be the font name, or any other text that the designer /// thinks is the best sample to display the font in. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public IDictionarySampleTexts { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.GetSampleTextDictionary(); } } /// /// Returns designed style (regular/italic/oblique) of this font face /// ///Designed style of this font face. public FontStyle Style { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.Style; } } ////// Returns designed weight of this font face. /// ///Designed weight of this font face. public FontWeight Weight { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.Weight; } } ////// Returns designed stretch of this font face. /// ///Designed stretch of this font face. public FontStretch Stretch { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.Stretch; } } ////// Font face version interpreted from the font's 'NAME' table. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public double Version { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.Version; } } ////// Height of character cell relative to em size. /// public double Height { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)(_fontFace.DesignCellAscent + _fontFace.DesignCellDescent) / DesignEmHeight; } } ////// Distance from cell top to English baseline relative to em size. /// public double Baseline { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.DesignCellAscent / DesignEmHeight; } } ////// Distance from baseline to top of English ----, relative to em size. /// public double CapsHeight { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.CapsHeight / DesignEmHeight; } } ////// Western x-height relative to em size. /// public double XHeight { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.xHeight / DesignEmHeight; } } ////// Returns true if this font does not conform to Unicode encoding: /// it may be considered as a simple collection of symbols indexed by a codepoint. /// public bool Symbol { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.Symbol; } } ////// Position of underline relative to baseline relative to em size. /// The value is usually negative, to place the underline below the baseline. /// public double UnderlinePosition { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.UnderlinePosition / DesignEmHeight; } } ////// Thickness of underline relative to em size. /// public double UnderlineThickness { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.UnderlineThickness / DesignEmHeight; } } ////// Position of strikeThrough relative to baseline relative to em size. /// The value is usually positive, to place the Strikethrough above the baseline. /// public double StrikethroughPosition { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.StrikethroughPosition / DesignEmHeight; } } ////// Thickness of Strikethrough relative to em size. /// public double StrikethroughThickness { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return (double)_fontFace.StrikethroughThickness / DesignEmHeight; } } ////// EmbeddingRights property describes font embedding permissions /// specified in this glyph typeface. /// ////// Critical - as this accesses _fontFace which can reveal Windows font information. /// Safe - as this does a demand before it gives out the information asked. /// public FontEmbeddingRight EmbeddingRights { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface DemandPermissionsForFontInformation(); return _fontFace.EmbeddingRights; } } #region ITypefaceMetrics implementation ////// Distance from baseline to top of English ----, relative to em size. /// double ITypefaceMetrics.CapsHeight { get { return CapsHeight; } } ////// Western x-height relative to em size. /// double ITypefaceMetrics.XHeight { get { return XHeight; } } ////// Returns true if this font does not conform to Unicode encoding: /// it may be considered as a simple collection of symbols indexed by a codepoint. /// bool ITypefaceMetrics.Symbol { get { return Symbol; } } ////// Position of underline relative to baseline relative to em size. /// The value is usually negative, to place the underline below the baseline. /// double ITypefaceMetrics.UnderlinePosition { get { return UnderlinePosition; } } ////// Thickness of underline relative to em size. /// double ITypefaceMetrics.UnderlineThickness { get { return UnderlineThickness; } } ////// Position of strikeThrough relative to baseline relative to em size. /// The value is usually positive, to place the Strikethrough above the baseline. /// double ITypefaceMetrics.StrikethroughPosition { get { return StrikethroughPosition; } } ////// Thickness of Strikethrough relative to em size. /// double ITypefaceMetrics.StrikethroughThickness { get { return StrikethroughThickness; } } #endregion // The next several properties return non CLS-compliant types. This is // tracked by bug 1792236. For now, suppress the compiler warning. // #pragma warning disable 3003 ////// Returns advance width for a given glyph. /// public IDictionaryAdvanceWidths { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetAdvanceWidth, _fontFace.GlyphCount); } } /// /// Returns Advance height for a given glyph (Used for example in vertical layout). /// public IDictionaryAdvanceHeights { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetAdvanceHeight, _fontFace.GlyphCount); } } /// /// Distance from leading end of advance vector to left edge of black box. /// Positive when left edge of black box is within the alignment rectangle /// defined by the advance width and font cell height. /// Negative when left edge of black box overhangs the alignment rectangle. /// public IDictionaryLeftSideBearings { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetLeftSidebearing, _fontFace.GlyphCount); } } /// /// Distance from right edge of black box to right end of advance vector. /// Positive when trailing edge of black box is within the alignment rectangle /// defined by the advance width and font cell height. /// Negative when right edge of black box overhangs the alignment rectangle. /// public IDictionaryRightSideBearings { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetRightSidebearing, _fontFace.GlyphCount); } } /// /// Distance from top end of (vertical) advance vector to top edge of black box. /// Positive when top edge of black box is within the alignment rectangle /// defined by the advance height and font cell height. /// (The font cell height is a horizontal dimension in vertical layout). /// Negative when top edge of black box overhangs the alignment rectangle. /// public IDictionaryTopSideBearings { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetTopSidebearing, _fontFace.GlyphCount); } } /// /// Distance from bottom edge of black box to bottom end of advance vector. /// Positive when bottom edge of black box is within the alignment rectangle /// defined by the advance width and font cell height. /// (The font cell height is a horizontal dimension in vertical layout). /// Negative when bottom edge of black box overhangs the alignment rectangle. /// public IDictionaryBottomSideBearings { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetBottomSidebearing, _fontFace.GlyphCount); } } /// /// Offset down from horizontal Western baseline to bottom of glyph black box. /// public IDictionaryDistancesFromHorizontalBaselineToBlackBoxBottom { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return new GlyphIndexer(this.GetBaseline, _fontFace.GlyphCount); } } /// /// Returns nominal mapping of Unicode codepoint to glyph index as defined by the font 'CMAP' table. /// ////// Critical: May potentially leak a writeable cmap. /// Safe: The cmap IDictionary exposure is read only. /// public IDictionaryCharacterToGlyphMap { [SecurityCritical] get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.CharacterMap; } } #pragma warning restore 3003 /// /// Returns algorithmic font style simulations to be applied to the GlyphTypeface. /// public StyleSimulations StyleSimulations { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _styleSimulations; } set { CheckInitializing(); _styleSimulations = value; } } ////// Obtains the number of glyphs in the glyph typeface. /// ///The number of glyphs in the glyph typeface. public int GlyphCount { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.GlyphCount; } } #endregion Public Properties //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods ////// Returns the nominal advance width for a glyph. /// /// Glyph index in the font. ///The nominal advance width for the glyph relative to the em size of the font. ////// Critical - as this has unsafe block. /// Safe - as this only gives width information which is safe to give out. /// [SecurityCritical, SecurityTreatAsSafe] internal double GetAdvanceWidth(ushort glyph) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface // We manually expand GetGlyphMetrics call because GetAdvanceWidth is a very frequently used function. // When we get to using GetAdvanceHeight for vertical writing, we need to consider doing the same optimization there. unsafe { FontFaceLayoutInfo.GlyphMetrics * cachedGlyphMetrics = _fontFace.Metrics(glyph); double aw = (double)cachedGlyphMetrics->advanceWidth / DesignEmHeight; if ((_styleSimulations & StyleSimulations.BoldSimulation) != 0) { // Bold simulation increases advance width and advance height by 2% of em size, // except for glyphs that are empty or have zero advance widths. // So, we compensate for the simulation when aw != 0 && left < right && ah != 0 && bottom > top if (cachedGlyphMetrics->advanceWidth != 0 && cachedGlyphMetrics->lsb < cachedGlyphMetrics->advanceWidth - cachedGlyphMetrics->rsb && cachedGlyphMetrics->advanceHeight != 0 && cachedGlyphMetrics->advanceHeight - cachedGlyphMetrics->tsb - cachedGlyphMetrics->bsb > 0) { aw += 0.02; } } return aw; } } ////// Returns the nominal advance width for a glyph in font design units. /// /// Glyph index in the font. ///The nominal advance width for the glyph in font design units. internal double GetAdvanceWidthInDesignUnits(ushort glyph) { return GetAdvanceWidth(glyph) * DesignEmHeight; } ////// This function will demand appropriate permissions depending on what /// the source of the font information is. The value of _fileIOPermObj /// is set correctly whenever _originalUri gets set. /// internal void DemandPermissionsForFontInformation() { if (_fileIOPermObj.Value != null) { _fileIOPermObj.Value.Demand(); } } private double GetAdvanceHeight(ushort glyph) { double aw, ah, lsb, rsb, tsb, bsb, baseline; GetGlyphMetrics( glyph, 1.0, out aw, out ah, out lsb, out rsb, out tsb, out bsb, out baseline ); return ah; } private double GetLeftSidebearing(ushort glyph) { return (double)_fontFace.GetLeftSidebearing(glyph) / DesignEmHeight; } private double GetRightSidebearing(ushort glyph) { return (double)_fontFace.GetRightSidebearing(glyph) / DesignEmHeight; } private double GetTopSidebearing(ushort glyph) { return (double)_fontFace.GetTopSidebearing(glyph) / DesignEmHeight; } private double GetBottomSidebearing(ushort glyph) { return (double)_fontFace.GetBottomSidebearing(glyph) / DesignEmHeight; } private double GetBaseline(ushort glyph) { return (double)_fontFace.GetBaseline(glyph) / DesignEmHeight; } ////// Optimized version of obtaining all of glyph metrics from font cache at once /// without repeated checks and divisions. /// ////// Critical - as this uses unsafe code. /// Safe - as this only gives information which is safe to give out. /// [SecurityCritical, SecurityTreatAsSafe] internal void GetGlyphMetrics( ushort glyph, double renderingEmSize, out double aw, out double ah, out double lsb, out double rsb, out double tsb, out double bsb, out double baseline ) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface unsafe { FontFaceLayoutInfo.GlyphMetrics * cachedGlyphMetrics = _fontFace.Metrics(glyph); double designToEm = renderingEmSize / DesignEmHeight; aw = designToEm * cachedGlyphMetrics->advanceWidth; ah = designToEm * cachedGlyphMetrics->advanceHeight; lsb = designToEm * cachedGlyphMetrics->lsb; rsb = designToEm * cachedGlyphMetrics->rsb; tsb = designToEm * cachedGlyphMetrics->tsb; bsb = designToEm * cachedGlyphMetrics->bsb; baseline = designToEm * cachedGlyphMetrics->baseline; if ((_styleSimulations & StyleSimulations.BoldSimulation) != 0) { // Bold simulation increases advance width and advance height by 2% of em size, // except for glyphs that are empty or have zero advance widths. // So, we compensate for the simulation when aw != 0 && left < right && ah != 0 && bottom > top if (cachedGlyphMetrics->advanceWidth != 0 && cachedGlyphMetrics->lsb < cachedGlyphMetrics->advanceWidth - cachedGlyphMetrics->rsb && cachedGlyphMetrics->advanceHeight != 0 && cachedGlyphMetrics->advanceHeight - cachedGlyphMetrics->tsb - cachedGlyphMetrics->bsb > 0) { aw += 0.02 * renderingEmSize; ah += 0.02 * renderingEmSize; } } } } ////// Returns a geometry describing the path for a single glyph in the font. /// The path represents the glyph /// without grid fitting applied for rendering at a specific resolution. /// /// Index of the glyph to get outline for. /// Specifies whether the glyph should be rotated sideways. /// Font size in drawing surface units. ///Geometry containing glyph outline. ////// Critical - as this calls GetGlyphs() which is critical. /// Safe - as this doesn't expose font information but just gives out a Geometry. /// [SecurityCritical, SecurityTreatAsSafe] internal Geometry ComputeGlyphOutline(ushort glyphIndex, bool sideways, double renderingEmSize) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface using (GlyphPathElement pathElement = new GlyphPathElement( FaceIndex, FontSource, GetRenderingFlags(sideways), DesignEmHeight )) { PathGeometry pathGeometry; unsafe { void*[] glyphOutlines = new void*[1]; FontCacheAccessor fontCacheAccessor = new FontCacheAccessor(); ushort[] glyphIndices = new ushort[1] { glyphIndex }; fontCacheAccessor.GetGlyphs( pathElement, glyphIndices, glyphOutlines ); void * outline = glyphOutlines[0]; Debug.Assert(outline != null); if (FontTechnology == FontTechnology.PostscriptOpenType) ConvertPostscriptOutline(outline, renderingEmSize, sideways, out pathGeometry); else ConvertTrueTypeOutline(outline, renderingEmSize, sideways, out pathGeometry); // Make sure fontCacheAccessor doesn't go out of scope before the outlines get converted. GC.KeepAlive(fontCacheAccessor); } // Make sure to always return Geometry.Empty from public methods for empty geometries. if (pathGeometry == null || pathGeometry.IsEmpty()) return Geometry.Empty; return pathGeometry; } } ////// Critical - unsafe code, accepts pointer parameters, etc. /// [SecurityCritical] private unsafe void ConvertTrueTypeOutline(void* trueTypeOutline, double renderingEmSize, bool sideways, out PathGeometry pathGeometry) { GlyphPathData * outline = (GlyphPathData *)trueTypeOutline; // scale factor from design units to user coordinate system double designToUserScale = renderingEmSize / DesignEmHeight; Matrix designToUser = new Matrix(designToUserScale, 0, 0, -designToUserScale, 0, 0); if (sideways) { designToUser.Rotate(-90.0); designToUser.Translate(outline->verOriginY * designToUserScale, outline->verOriginX * designToUserScale); } ushort* endp = GlyphPathData.EndPointNumbers(outline); short* x = GlyphPathData.X(outline); short* y = GlyphPathData.Y(outline); byte* flags = GlyphPathData.Flags(outline); // k is the index of the first point of the current contour int k = 0; pathGeometry = null; // j is the index of the current contour for (int j = 0; j < outline->numberOfContours; ++j) { int lastPointIndex = endp[j]; if (lastPointIndex <= k) { k = lastPointIndex + 1; continue; // empty contour } Point startPoint; PathFigure figure = new PathFigure(); // The first point on the curve if (OnCurve(flags[k])) { // Easy case startPoint = designToUser.Transform(new Point(x[k], y[k])); ++k; } else { // Is last contour point on the curve if (OnCurve(flags[lastPointIndex])) { // Make the last point the first point and decrement the last point startPoint = designToUser.Transform(new Point(x[lastPointIndex], y[lastPointIndex])); --lastPointIndex; } else { // First and last point are off the countour, fake a mid point Point firstPoint = designToUser.Transform(new Point(x[k], y[k])); Point lastPoint = designToUser.Transform(new Point(x[lastPointIndex], y[lastPointIndex])); startPoint = new Point( (firstPoint.X + lastPoint.X) / 2, (firstPoint.Y + lastPoint.Y) / 2 ); } } figure.StartPoint = startPoint; bool inBezier = false; Point bezierB = new Point(); while (k <= lastPointIndex) { Point currentPoint = designToUser.Transform(new Point(x[k], y[k])); if (OnCurve(flags[k])) { if (!inBezier) { figure.Segments.Add(new LineSegment(currentPoint, true)); } else { figure.Segments.Add(new QuadraticBezierSegment(bezierB, currentPoint, true)); inBezier = false; } } else { if (inBezier) { figure.Segments.Add(new QuadraticBezierSegment( bezierB, new Point( (bezierB.X + currentPoint.X) / 2, (bezierB.Y + currentPoint.Y) / 2 ), true) ); } inBezier = true; bezierB = currentPoint; } ++k; } // explicitly set k to the start point of the next contour // since in some cases lastPointIndex is not equal to endp[j] k = endp[j] + 1; // close the figure, assume start point is always on curve if (inBezier) { figure.Segments.Add(new QuadraticBezierSegment(bezierB, startPoint, true)); } figure.IsClosed = true; if (pathGeometry == null) { pathGeometry = new PathGeometry(); pathGeometry.FillRule = FillRule.Nonzero; } pathGeometry.Figures.Add(figure); } } ////// Critical - unsafe code, accepts pointer parameters, etc. /// [SecurityCritical] private unsafe void ConvertPostscriptOutline(void * outline, double renderingEmSize, bool sideways, out PathGeometry pathGeometry) { int * postscriptOutline = (int *)outline; // scale factor from design units to user coordinate system double designToUserScale = renderingEmSize / DesignEmHeight; Matrix designToUser = new Matrix(designToUserScale, 0, 0, -designToUserScale, 0, 0); if (sideways) { int verOriginX = postscriptOutline[0]; int verOriginY = postscriptOutline[1]; designToUser.Rotate(-90.0); designToUser.Translate(verOriginY * designToUserScale, verOriginX * designToUserScale); } // Skip vertical origin and length to get to the actual contour data. int * p = postscriptOutline + 3; Debug.Assert(postscriptOutline[2] % sizeof(int) == 0); int * end = p + (postscriptOutline[2] / sizeof(int)); pathGeometry = null; // Current figure. PathFigure figure = null; for (;;) { if (p >= end) break; int tokenValue = *p; switch ((OutlineTokenType)tokenValue) { case OutlineTokenType.MoveTo: { ++p; if (p + 1 >= end) throw new FileFormatException(_originalUri.Value); Point point = designToUser.Transform( new Point(p[0] * CFFConversionFactor, p[1] * CFFConversionFactor) ); if (figure == null) figure = new PathFigure(); figure.StartPoint = point; p += 2; break; } case OutlineTokenType.LineTo: { ++p; if (p + 1 >= end) throw new FileFormatException(_originalUri.Value); Point point = designToUser.Transform( new Point(p[0] * CFFConversionFactor, p[1] * CFFConversionFactor) ); if (figure == null) throw new FileFormatException(_originalUri.Value); figure.Segments.Add(new LineSegment(point, true)); p += 2; break; } case OutlineTokenType.CurveTo: { ++p; if (p + 5 >= end) throw new FileFormatException(_originalUri.Value); Point point0 = designToUser.Transform( new Point(p[0] * CFFConversionFactor, p[1] * CFFConversionFactor) ); Point point1 = designToUser.Transform( new Point(p[2] * CFFConversionFactor, p[3] * CFFConversionFactor) ); Point point2 = designToUser.Transform( new Point(p[4] * CFFConversionFactor, p[5] * CFFConversionFactor) ); if (figure == null) throw new FileFormatException(_originalUri.Value); figure.Segments.Add(new BezierSegment(point0, point1, point2, true)); p += 6; break; } case OutlineTokenType.ClosePath: if (figure == null) throw new FileFormatException(_originalUri.Value); figure.IsClosed = true; if (pathGeometry == null) { pathGeometry = new PathGeometry(); pathGeometry.FillRule = FillRule.Nonzero; } pathGeometry.Figures.Add(figure); figure = null; ++p; break; default: throw new FileFormatException(_originalUri.Value); } } } ////// Get advance widths of unshaped characters /// /// character string /// character length /// character em size /// unshaped advance widths /// true if all characters map to missing glyph ///array of character advance widths ////// Critical - takes unsafe char string and returns information in an unsafe int array /// [SecurityCritical] internal unsafe void GetAdvanceWidthsUnshaped( char* unsafeCharString, int stringLength, double emSize, int* advanceWidthsUnshaped, bool nullFont ) { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface Invariant.Assert(stringLength > 0); if (!nullFont) { IDictionarycmap = CharacterToGlyphMap; for (int i = 0; i < stringLength; i++) { ushort glyphIndex; cmap.TryGetValue(unsafeCharString[i], out glyphIndex); advanceWidthsUnshaped[i] = (int)Math.Round(emSize * GetAdvanceWidth(glyphIndex)); } } else { int missingGlyphWidth = (int)Math.Round(emSize * GetAdvanceWidth(0)); for (int i = 0; i < stringLength; i++) { advanceWidthsUnshaped[i] = missingGlyphWidth; } } } /// /// Compute an unshaped glyphrun object from specified character-based info /// internal GlyphRun ComputeUnshapedGlyphRun( Point origin, CharacterBufferRange charBufferRange, IListcharWidths, double emSize, double emHintingSize, bool nullGlyph, CultureInfo cultureInfo, string deviceFontName ) { Debug.Assert(charBufferRange.Length > 0); CheckInitialized(); // This can only be called on fully initialized GlyphTypeface ushort[] nominalGlyphs = new ushort[charBufferRange.Length]; // compute glyph positions if (nullGlyph) { for (int i = 0; i < charBufferRange.Length; i++) { nominalGlyphs[i] = 0; } } else { IDictionary cmap = CharacterToGlyphMap; for (int i = 0; i < charBufferRange.Length; i++) { ushort glyphIndex; cmap.TryGetValue(charBufferRange[i], out glyphIndex); nominalGlyphs[i] = glyphIndex; } } return GlyphRun.TryCreate( this, 0, // bidiLevel false, // sideway emSize, nominalGlyphs, origin, charWidths, null, // glyphOffsets new PartialList (charBufferRange.CharacterBuffer, charBufferRange.OffsetToFirstChar, charBufferRange.Length), deviceFontName, // device font null, // 1:1 mapping null, // caret stops at every codepoint XmlLanguage.GetLanguage(cultureInfo.IetfLanguageTag) ); } #endregion Internal Methods //----------------------------------------------------- // // Internal Properties // //----------------------------------------------------- #region Internal Properties internal FontSource FontSource { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.FontSource; } } /// /// 0 for TTF files /// Face index within TrueType font collection for TTC files /// internal int FaceIndex { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.FaceIndex; } } internal FontFaceLayoutInfo FontFaceLayoutInfo { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace; } } internal ushort BlankGlyphIndex { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.BlankGlyph; } } internal FontFaceLayoutInfo.RenderingHints RenderingHints { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.FontRenderingHints; } } internal FontTechnology FontTechnology { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.FontTechnology; } } internal short FontContrastAdjustment { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface Debug.Assert(-3 <= _fontFace.FontContrastAdjustment && _fontFace.FontContrastAdjustment <= 4); return _fontFace.FontContrastAdjustment; } } internal ushort DesignEmHeight { get { CheckInitialized(); // This can only be called on fully initialized GlyphTypeface return _fontFace.DesignEmHeight; } } #endregion Internal Properties //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ #region Private Methods private static bool OnCurve(byte flag) { return (flag & 0x01) != 0; } private ushort GetRenderingFlags(bool sideways) { ushort renderingFlags = 0; if ((_styleSimulations & StyleSimulations.BoldSimulation) != 0) renderingFlags |= (ushort)RenderingFlags.BoldSimulation; if ((_styleSimulations & StyleSimulations.ItalicSimulation) != 0) { renderingFlags |= (ushort)RenderingFlags.ItalicSimulation; if (sideways) renderingFlags |= (ushort)RenderingFlags.SidewaysItalicSimulation; } if (FontTechnology != FontTechnology.PostscriptOpenType) renderingFlags |= (ushort)MilGlyphRun.IsTrueType; return renderingFlags; } #endregion Private Methods #region ISupportInitialize interface void ISupportInitialize.BeginInit() { if (_initializationState == InitializationState.IsInitialized) { // Cannont initialize a GlyphRun this is completely initialized. throw new InvalidOperationException(SR.Get(SRID.OnlyOneInitialization)); } if (_initializationState == InitializationState.IsInitializing) { // Cannot initialize a GlyphRun this already being initialized. throw new InvalidOperationException(SR.Get(SRID.InInitialization)); } _initializationState = InitializationState.IsInitializing; } ////// Critical - this method calls into critical method. /// [SecurityCritical] void ISupportInitialize.EndInit() { if (_initializationState != InitializationState.IsInitializing) { // Cannot EndInit a GlyphRun that is not being initialized. throw new InvalidOperationException(SR.Get(SRID.NotInInitialization)); } Initialize( (_originalUri == null ? null : _originalUri.Value), _styleSimulations, true ); } private void CheckInitialized() { if (_initializationState != InitializationState.IsInitialized) { throw new InvalidOperationException(SR.Get(SRID.InitializationIncomplete)); } } private void CheckInitializing() { if (_initializationState != InitializationState.IsInitializing) { throw new InvalidOperationException(SR.Get(SRID.NotInInitialization)); } } #endregion //----------------------------------------------------- // // Private Nested Classes // //------------------------------------------------------ #region Private Nested Classes private delegate double GlyphAccessor(ushort glyphIndex); ////// This class is a helper to implement named indexers /// for glyph metrics. /// private class GlyphIndexer : IDictionary{ internal GlyphIndexer(GlyphAccessor accessor, ushort numberOfGlyphs) { _accessor = accessor; _numberOfGlyphs = numberOfGlyphs; } #region IDictionary Members public void Add(ushort key, double value) { throw new NotSupportedException(); } public bool ContainsKey(ushort key) { return (key < _numberOfGlyphs); } public ICollection Keys { get { return new SequentialUshortCollection(_numberOfGlyphs); } } public bool Remove(ushort key) { throw new NotSupportedException(); } public bool TryGetValue(ushort key, out double value) { if (ContainsKey(key)) { value = this[key]; return true; } else { value = new double(); return false; } } public ICollection Values { get { return new ValueCollection(this); } } public double this[ushort key] { get { return _accessor(key); } set { throw new NotSupportedException(); } } #endregion #region ICollection > Members public void Add(KeyValuePair item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public bool Contains(KeyValuePair item) { return ContainsKey(item.Key); } public void CopyTo(KeyValuePair [] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (array.Rank != 1) { throw new ArgumentException(SR.Get(SRID.Collection_BadRank)); } // The extra "arrayIndex >= array.Length" check in because even if _collection.Count // is 0 the index is not allowed to be equal or greater than the length // (from the MSDN ICollection docs) if (arrayIndex < 0 || arrayIndex >= array.Length || (arrayIndex + Count) > array.Length) { throw new ArgumentOutOfRangeException("arrayIndex"); } for (ushort i = 0; i < Count; ++i) array[arrayIndex + i] = new KeyValuePair (i, this[i]); } public int Count { get { return _numberOfGlyphs; } } public bool IsReadOnly { get { return true; } } public bool Remove(KeyValuePair item) { throw new NotSupportedException(); } #endregion #region IEnumerable > Members public IEnumerator > GetEnumerator() { for (ushort i = 0; i < Count; ++i) yield return new KeyValuePair (i, this[i]); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable >)this).GetEnumerator(); } #endregion private class ValueCollection : ICollection { public ValueCollection(GlyphIndexer glyphIndexer) { _glyphIndexer = glyphIndexer; } #region ICollection Members public void Add(double item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public bool Contains(double item) { foreach (double d in this) { if (d == item) return true; } return false; } public void CopyTo(double[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (array.Rank != 1) { throw new ArgumentException(SR.Get(SRID.Collection_BadRank)); } // The extra "arrayIndex >= array.Length" check in because even if _collection.Count // is 0 the index is not allowed to be equal or greater than the length // (from the MSDN ICollection docs) if (arrayIndex < 0 || arrayIndex >= array.Length || (arrayIndex + Count) > array.Length) { throw new ArgumentOutOfRangeException("arrayIndex"); } for (ushort i = 0; i < Count; ++i) array[arrayIndex + i] = _glyphIndexer[i]; } public int Count { get { return _glyphIndexer._numberOfGlyphs; } } public bool IsReadOnly { get { return true; } } public bool Remove(double item) { throw new NotSupportedException(); } #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { for (ushort i = 0; i < Count; ++i) yield return _glyphIndexer[i]; } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable )this).GetEnumerator(); } #endregion private GlyphIndexer _glyphIndexer; } private GlyphAccessor _accessor; private ushort _numberOfGlyphs; } #endregion Private Nested Classes //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- #region Private Fields private FontFaceLayoutInfo _fontFace; private StyleSimulations _styleSimulations; /// /// The Uri that was passed in to constructor. /// ////// This is critical as we do a demand based on this value public functions. /// Only setting this Uri is critical, getting is fine. Hence using the /// SecurityCriticalDataForSet object. Note that the object itself does not /// need to be Critical, it's just setting it that makes it Critical. /// private SecurityCriticalDataClass_originalUri; /// /// Critical - as this object controls the Demand that'll be made before accessssing the /// security sensitive contents of the font file. This also only Critical /// for set. This should be correctly whenever _originalUri is set. /// /// Caching object for perf reasons. /// private SecurityCriticalDataForSet_fileIOPermObj; private const double CFFConversionFactor = 1.0 / 65536.0; private InitializationState _initializationState; /// /// Initialization states of GlyphTypeface object. /// private enum InitializationState { ////// The state in which the GlyphTypeface has not been initialized. /// At this state, all operations on the object would cause InvalidOperationException. /// The object can only transit to 'IsInitializing' state with BeginInit() call. /// Uninitialized, ////// The state in which the GlyphTypeface is being initialized. At this state, user can /// set values into the required properties. The object can only transit to 'IsInitialized' state /// with EndInit() call. /// IsInitializing, ////// The state in which the GlyphTypeface object is fully initialized. At this state the object /// is fully functional. There is no valid transition out of the state. /// IsInitialized, } #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AppDomainManager.cs
- TransformGroup.cs
- PagedDataSource.cs
- TailCallAnalyzer.cs
- ColorInterpolationModeValidation.cs
- XmlCharType.cs
- SByteStorage.cs
- InputLanguageManager.cs
- TaskFormBase.cs
- PageParserFilter.cs
- TaiwanCalendar.cs
- PageContentCollection.cs
- TextTreeInsertUndoUnit.cs
- Figure.cs
- Polyline.cs
- XamlParser.cs
- OletxCommittableTransaction.cs
- Highlights.cs
- DataKey.cs
- ExtendedPropertyDescriptor.cs
- X509Extension.cs
- InternalTypeHelper.cs
- ErrorWebPart.cs
- ProcessThreadDesigner.cs
- SinglePageViewer.cs
- HostedElements.cs
- HandleCollector.cs
- BitmapEffectInput.cs
- WebPartActionVerb.cs
- SynchronizedDispatch.cs
- ReflectPropertyDescriptor.cs
- ValueExpressions.cs
- DataRowComparer.cs
- IChannel.cs
- AssertUtility.cs
- TimerTable.cs
- CollectionContainer.cs
- RuleConditionDialog.Designer.cs
- HtmlFormWrapper.cs
- JumpPath.cs
- EllipseGeometry.cs
- BufferedConnection.cs
- CodeIndexerExpression.cs
- XmlDataSource.cs
- DesignerForm.cs
- GacUtil.cs
- BindingEntityInfo.cs
- RequestResizeEvent.cs
- HorizontalAlignConverter.cs
- SiteOfOriginPart.cs
- ComplexPropertyEntry.cs
- IdentityHolder.cs
- PseudoWebRequest.cs
- PassportPrincipal.cs
- ObjectCacheHost.cs
- CodeMethodInvokeExpression.cs
- CharacterBufferReference.cs
- LostFocusEventManager.cs
- CodeGeneratorOptions.cs
- LinearKeyFrames.cs
- StaticExtension.cs
- TextSimpleMarkerProperties.cs
- Imaging.cs
- ObjectToIdCache.cs
- AspNetSynchronizationContext.cs
- BamlLocalizer.cs
- SchemaConstraints.cs
- MDIControlStrip.cs
- PartBasedPackageProperties.cs
- TypeSource.cs
- DefaultObjectMappingItemCollection.cs
- StandardToolWindows.cs
- ValidatorCompatibilityHelper.cs
- TemplateField.cs
- SettingsPropertyCollection.cs
- SmiConnection.cs
- Constant.cs
- Faults.cs
- DrawingAttributeSerializer.cs
- HybridDictionary.cs
- StylusDownEventArgs.cs
- HybridDictionary.cs
- SQLInt64Storage.cs
- DropShadowBitmapEffect.cs
- Region.cs
- XPathScanner.cs
- BitSet.cs
- ETagAttribute.cs
- Evidence.cs
- MetaType.cs
- DataTemplateSelector.cs
- TemplateField.cs
- TogglePatternIdentifiers.cs
- ProxyGenerationError.cs
- TargetControlTypeAttribute.cs
- ItemsPresenter.cs
- WebPartZoneCollection.cs
- SctClaimDictionary.cs
- ProjectionNode.cs
- IntranetCredentialPolicy.cs