Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Media / Typeface.cs / 1 / Typeface.cs
//------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation // // File: Typeface.cs // // Contents: Typeface // // Created: 5-25-2003 Worachai Chaoweeraprasit (wchao) // //----------------------------------------------------------------------- using System; using System.Globalization; using System.Security.Permissions; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Security; using System.Windows; using System.Windows.Media.TextFormatting; using System.Runtime.InteropServices; using System.ComponentModel; using MS.Internal; using MS.Internal.FontFace; using MS.Internal.FontCache; using MS.Internal.Shaping; using MS.Internal.TextFormatting; namespace System.Windows.Media { ////// A Typeface is a combination of family, weight, style and stretch: /// public class Typeface { private FontFamily _fontFamily; // these _style, _weight and _stretch are only used for storing what was passed into the constructor. // Since FontFamily may change these values when it includes a style name implicitly, private FontStyle _style; private FontWeight _weight; private FontStretch _stretch; private FontFamily _fallbackFontFamily; // Cached canonical values of the typeface. private CachedTypeface _cachedTypeface; ////// Construct a typeface /// /// font typeface name public Typeface( string typefaceName ) // assume face name is family name until we get face name resolved properly. : this( new FontFamily(typefaceName), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal ) {} ////// Construct a typeface /// /// Font family /// Font style /// Boldness of font /// Width of characters public Typeface( FontFamily fontFamily, FontStyle style, FontWeight weight, FontStretch stretch ) : this( fontFamily, style, weight, stretch, FontFamily.FontFamilyGlobalUI ) {} ////// Construct a typeface /// /// Font family /// Font style /// Boldness of font /// Width of characters /// fallback font family public Typeface( FontFamily fontFamily, FontStyle style, FontWeight weight, FontStretch stretch, FontFamily fallbackFontFamily ) { if(fontFamily == null) { throw new ArgumentNullException("fontFamily"); } _fontFamily = fontFamily; _style = style; _weight = weight; _stretch = stretch; _fallbackFontFamily = fallbackFontFamily; } ////// Font family /// public FontFamily FontFamily { get { return _fontFamily; } } ////// Font weight (light, bold, etc.) /// public FontWeight Weight { get { return _weight; } } ////// Font style (italic, oblique) /// public FontStyle Style { get { return _style; } } ////// Font Stretch (narrow, wide, etc.) /// public FontStretch Stretch { get { return _stretch; } } ////// Returns true if FontStyle.Oblique is algorithmically simulated by /// slanting glyphs. Returns false otherwise. /// public bool IsObliqueSimulated { get { return (CachedTypeface.TypefaceMetrics.StyleSimulations & StyleSimulations.ItalicSimulation) != 0; } } ////// Returns true if FontStyle.Bold is algorithmically simulated by /// thickening glyphs. Returns false otherwise. /// public bool IsBoldSimulated { get { return (CachedTypeface.TypefaceMetrics.StyleSimulations & StyleSimulations.BoldSimulation) != 0; } } ////// Obtain a glyph typeface that corresponds to the Typeface object constructed from an OpenType font family. /// If the Typeface was constructed from a composite font family, returns null. /// /// GlyphTypeface object that corresponds to this Typeface, or null if the Typeface /// was constructed from a composite font. ///Whether glyphTypeface is not null. public bool TryGetGlyphTypeface(out GlyphTypeface glyphTypeface) { glyphTypeface = CachedTypeface.TypefaceMetrics as GlyphTypeface; return glyphTypeface != null; } ////// Fallback font family /// internal FontFamily FallbackFontFamily { get { return _fallbackFontFamily; } } ////// (Western) x-height relative to em size. /// public double XHeight { get { return CachedTypeface.TypefaceMetrics.XHeight; } } ////// Distance from baseline to top of English ----, relative to em size. /// public double CapsHeight { get { return CachedTypeface.TypefaceMetrics.CapsHeight; } } ////// Distance from baseline to underline position /// public double UnderlinePosition { get { return CachedTypeface.TypefaceMetrics.UnderlinePosition; } } ////// Underline thickness /// public double UnderlineThickness { get { return CachedTypeface.TypefaceMetrics.UnderlineThickness; } } ////// Distance from baseline to strike-through position /// public double StrikethroughPosition { get { return CachedTypeface.TypefaceMetrics.StrikethroughPosition; } } ////// strike-through thickness /// public double StrikethroughThickness { get { return CachedTypeface.TypefaceMetrics.StrikethroughThickness; } } ////// Collection of culture-dependant face names. /// public LanguageSpecificStringDictionary FaceNames { get { return new LanguageSpecificStringDictionary(CachedTypeface.TypefaceMetrics.AdjustedFaceNames); } } ////// Distance from character cell top to English baseline relative to em size. /// internal double Baseline { get { return CachedTypeface.FirstFontFamily.Baseline; } } ////// Baseline to baseline distance relative to em size /// internal double LineSpacing { get { return CachedTypeface.FirstFontFamily.LineSpacing; } } ////// Flag indicating if the typeface is of symbol type /// internal bool Symbol { get { return CachedTypeface.TypefaceMetrics.Symbol; } } internal bool NullFont { get { return CachedTypeface.NullFont; } } // Tries to get a GlyphTypeface based on the Typeface properties. The // return value can be null. However, if CheckFastPathNominalGlyphs // returns true, then one can expect this function to return a valid // GlyphTypeface that maps all the specified text. internal GlyphTypeface TryGetGlyphTypeface() { return CachedTypeface.TypefaceMetrics as GlyphTypeface; } internal FontStyle CanonicalStyle { get { return CachedTypeface.CanonicalStyle; } } internal FontWeight CanonicalWeight { get { return CachedTypeface.CanonicalWeight; } } internal FontStretch CanonicalStretch { get { return CachedTypeface.CanonicalStretch; } } ////// Scan through specified character string checking for valid character /// nominal glyph. /// /// character buffer range /// height of Em /// maximum width allowed /// do not stop arbitrarily in the middle of a word /// digits require complex shaping /// CultureInfo of the text /// number of character fit in given width ///whether the specified string can be optimized by nominal glyph lookup internal bool CheckFastPathNominalGlyphs( CharacterBufferRange charBufferRange, double emSize, double widthMax, bool keepAWord, bool numberSubstitution, CultureInfo cultureInfo, out int stringLengthFit ) { stringLengthFit = 0; if (CachedTypeface.NullFont) return false; GlyphTypeface glyphTypeface = TryGetGlyphTypeface(); if (glyphTypeface == null) return false; stringLengthFit = 0; IDictionarycmap = glyphTypeface.CharacterToGlyphMap; double totalWidth = 0; int i = 0; ushort blankGlyph = glyphTypeface.BlankGlyphIndex; ushort glyph = blankGlyph; ushort charFlagsMask = numberSubstitution ? (ushort)(CharacterAttributeFlags.CharacterComplex | CharacterAttributeFlags.CharacterDigit) : (ushort)CharacterAttributeFlags.CharacterComplex; ushort charFlags = 0; ushort charFastTextCheck = (ushort)(CharacterAttributeFlags.CharacterFastText | CharacterAttributeFlags.CharacterIdeo); bool symbolTypeface = glyphTypeface.Symbol; if (symbolTypeface) { // we don't care what code points are present if it's a non-Unicode font such as Symbol or Wingdings; // the code points don't have any standardized meanings, and we always want to bypass shaping charFlagsMask = 0; } if(keepAWord) { do { char ch = charBufferRange[i++]; int charClass = (int)Classification.GetUnicodeClassUTF16(ch); charFlags = Classification.CharAttributeOf(charClass).Flags; charFastTextCheck &= charFlags; cmap.TryGetValue(ch, out glyph); totalWidth += emSize * glyphTypeface.GetAdvanceWidth(glyph); } while( i < charBufferRange.Length && ((charFlags & charFlagsMask) == 0) && (glyph != 0 || symbolTypeface) && glyph != blankGlyph ); // i is now at a character immediately following a leading blank } while( i < charBufferRange.Length && totalWidth <= widthMax && ((charFlags & charFlagsMask) == 0) && (glyph != 0 || symbolTypeface) ) { char ch = charBufferRange[i++]; int charClass = (int)Classification.GetUnicodeClassUTF16(ch); charFlags = Classification.CharAttributeOf(charClass).Flags; charFastTextCheck &= charFlags; cmap.TryGetValue(ch, out glyph); totalWidth += emSize * glyphTypeface.GetAdvanceWidth(glyph); } if (symbolTypeface) { // always optimize for non-Unicode font as we don't support shaping or typographic features; // we also don't fall back from non-Unicode fonts so we don't care if there are missing glyphs stringLengthFit = i; return true; } if (glyph == 0) { // character is not supported by the font return false; } if ((charFlags & charFlagsMask) != 0) { // complex character encountered, exclude it Debug.Assert(i > 0); if(--i <= 0) { // first char is complex, fail the call return false; } } stringLengthFit = i; TypographyAvailabilities typography = glyphTypeface.FontFaceLayoutInfo.TypographyAvailabilities; if ((charFastTextCheck & (byte) CharacterAttributeFlags.CharacterFastText) != 0) { // all input code points are Fast Text if ((typography & ( TypographyAvailabilities.FastTextTypographyAvailable | TypographyAvailabilities.FastTextMajorLanguageLocalizedFormAvailable ) ) != 0 ) { // Considered too risky to optimize. It is either because the font // has required features or the font has 'locl' lookup for major languages. return false; } else if ((typography & TypographyAvailabilities.FastTextExtraLanguageLocalizedFormAvailable) != 0) { // The font has 'locl' lookup for FastText code points for non major languages. // Check whether the input is major langauge. If it is, we are still good to optimize. return MajorLanguages.Contains(cultureInfo); } else { // No FastText flags are present, safe to optimize return true; } } else if ((charFastTextCheck & (byte) CharacterAttributeFlags.CharacterIdeo) != 0) { // The input are all ideographs, check the IdeoTypographyAvailable bit. It is safe if // the bit is not set. return ((typography & TypographyAvailabilities.IdeoTypographyAvailable) == 0); } else { // for all the rest of the cases, just check whether there is any required typography // present at all. If none exists, it is optimizable. We might under-optimize here but // it will be non-major languages. return ((typography & TypographyAvailabilities.Available) == 0); } } /// /// Lookup characters nominal glyphs and width /// /// character buffer range /// height of Em /// scaling factor from real to ideal unit /// glyph nominal advances in ideal units /// total width in ideal units ///true for success ///This function is only used in fast path, and can only be called /// if CheckFastPathNominalGlyphs has previously returned true. internal void GetCharacterNominalWidthsAndIdealWidth( CharacterBufferRange charBufferRange, double emSize, double toIdeal, out int[] nominalWidths, out int idealWidth ) { // This function should only be called if CheckFastPathNominalGlyphs has // returned true so we can assume the ITypefaceMetrics is a GlyphTypeface. GlyphTypeface glyphTypeface = TryGetGlyphTypeface(); Invariant.Assert(glyphTypeface != null); IDictionarycmap = glyphTypeface.CharacterToGlyphMap; nominalWidths = new int[charBufferRange.Length]; idealWidth = 0; for (int i = 0; i < charBufferRange.Length; i++) { ushort glyphIndex; cmap.TryGetValue(charBufferRange[i], out glyphIndex); double advance = emSize * glyphTypeface.GetAdvanceWidth(glyphIndex); nominalWidths[i] = (int) Math.Round(advance * toIdeal); idealWidth += nominalWidths[i]; } } /// /// Create correspondent hash code for the object /// ///object hash code public override int GetHashCode() { int hash = _fontFamily.GetHashCode(); if (_fallbackFontFamily != null) hash = HashFn.HashMultiply(hash) + _fallbackFontFamily.GetHashCode(); hash = HashFn.HashMultiply(hash) + _style.GetHashCode(); hash = HashFn.HashMultiply(hash) + _weight.GetHashCode(); hash = HashFn.HashMultiply(hash) + _stretch.GetHashCode(); return HashFn.HashScramble(hash); } ////// Equality check /// public override bool Equals(object o) { Typeface t = o as Typeface; if(t == null) return false; return _style == t._style && _weight == t._weight && _stretch == t._stretch && _fontFamily.Equals(t._fontFamily) && CompareFallbackFontFamily(t._fallbackFontFamily); } internal bool CompareFallbackFontFamily(FontFamily fallbackFontFamily) { if (fallbackFontFamily == null || _fallbackFontFamily == null) return fallbackFontFamily == _fallbackFontFamily; return _fallbackFontFamily.Equals(fallbackFontFamily); } //---------------------------------------- // Private method //---------------------------------------- private CachedTypeface CachedTypeface { get { if (_cachedTypeface == null) { CachedTypeface cachedTypeface = TypefaceMetricsCache.ReadonlyLookup(this) as CachedTypeface; if (cachedTypeface == null) { cachedTypeface = ConstructCachedTypeface(); TypefaceMetricsCache.Add(this, cachedTypeface); } // For thread-safety, set the _cachedTypeface field only after we have a fully // initialized CachedTypeface object. _cachedTypeface = cachedTypeface; } return _cachedTypeface; } } private CachedTypeface ConstructCachedTypeface() { FontStyle canonicalStyle = _style; FontWeight canonicalWeight = _weight; FontStretch canonicalStretch = _stretch; // // We always call FontFamily.FindFirstFontFamilyAndFace() method to resolve the // canonical styles since the implied styles in FontFamily name will override // the given styles in the Typeface. But we don't always use the IFontFamily // instance returned from this method because an equal instance might already be // cached. // FontFamily sourceFontFamily = FontFamily; IFontFamily firstFontFamily = sourceFontFamily.FindFirstFontFamilyAndFace( ref canonicalStyle, ref canonicalWeight, ref canonicalStretch ); if (firstFontFamily == null) { if (FallbackFontFamily != null) { sourceFontFamily = FallbackFontFamily; firstFontFamily = sourceFontFamily.FindFirstFontFamilyAndFace( ref canonicalStyle, ref canonicalWeight, ref canonicalStretch ); } if (firstFontFamily == null) { sourceFontFamily = null; firstFontFamily = FontFamily.LookupFontFamily(FontFamily.NullFontFamilyCanonicalName); } } // If it's a named font, map all occurrences of the same name to one cached IFontFamily. if (sourceFontFamily != null && sourceFontFamily.Source != null) { // We lookup in the cache to see if there is cached IFontFamily instance of the source FontFamily. Otherwise, // this IFontFamily value is added to the TypefaceMetrics cache. IFontFamily cachedValue = TypefaceMetricsCache.ReadonlyLookup(sourceFontFamily.FamilyIdentifier) as IFontFamily; if (cachedValue != null) { firstFontFamily = cachedValue; } else { TypefaceMetricsCache.Add(sourceFontFamily.FamilyIdentifier, firstFontFamily); } } ITypefaceMetrics typefaceMetrics = firstFontFamily.GetTypefaceMetrics(canonicalStyle, canonicalWeight, canonicalStretch); return new CachedTypeface( canonicalStyle, canonicalWeight, canonicalStretch, firstFontFamily, typefaceMetrics, sourceFontFamily == null ); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation // // File: Typeface.cs // // Contents: Typeface // // Created: 5-25-2003 Worachai Chaoweeraprasit (wchao) // //----------------------------------------------------------------------- using System; using System.Globalization; using System.Security.Permissions; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Security; using System.Windows; using System.Windows.Media.TextFormatting; using System.Runtime.InteropServices; using System.ComponentModel; using MS.Internal; using MS.Internal.FontFace; using MS.Internal.FontCache; using MS.Internal.Shaping; using MS.Internal.TextFormatting; namespace System.Windows.Media { ////// A Typeface is a combination of family, weight, style and stretch: /// public class Typeface { private FontFamily _fontFamily; // these _style, _weight and _stretch are only used for storing what was passed into the constructor. // Since FontFamily may change these values when it includes a style name implicitly, private FontStyle _style; private FontWeight _weight; private FontStretch _stretch; private FontFamily _fallbackFontFamily; // Cached canonical values of the typeface. private CachedTypeface _cachedTypeface; ////// Construct a typeface /// /// font typeface name public Typeface( string typefaceName ) // assume face name is family name until we get face name resolved properly. : this( new FontFamily(typefaceName), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal ) {} ////// Construct a typeface /// /// Font family /// Font style /// Boldness of font /// Width of characters public Typeface( FontFamily fontFamily, FontStyle style, FontWeight weight, FontStretch stretch ) : this( fontFamily, style, weight, stretch, FontFamily.FontFamilyGlobalUI ) {} ////// Construct a typeface /// /// Font family /// Font style /// Boldness of font /// Width of characters /// fallback font family public Typeface( FontFamily fontFamily, FontStyle style, FontWeight weight, FontStretch stretch, FontFamily fallbackFontFamily ) { if(fontFamily == null) { throw new ArgumentNullException("fontFamily"); } _fontFamily = fontFamily; _style = style; _weight = weight; _stretch = stretch; _fallbackFontFamily = fallbackFontFamily; } ////// Font family /// public FontFamily FontFamily { get { return _fontFamily; } } ////// Font weight (light, bold, etc.) /// public FontWeight Weight { get { return _weight; } } ////// Font style (italic, oblique) /// public FontStyle Style { get { return _style; } } ////// Font Stretch (narrow, wide, etc.) /// public FontStretch Stretch { get { return _stretch; } } ////// Returns true if FontStyle.Oblique is algorithmically simulated by /// slanting glyphs. Returns false otherwise. /// public bool IsObliqueSimulated { get { return (CachedTypeface.TypefaceMetrics.StyleSimulations & StyleSimulations.ItalicSimulation) != 0; } } ////// Returns true if FontStyle.Bold is algorithmically simulated by /// thickening glyphs. Returns false otherwise. /// public bool IsBoldSimulated { get { return (CachedTypeface.TypefaceMetrics.StyleSimulations & StyleSimulations.BoldSimulation) != 0; } } ////// Obtain a glyph typeface that corresponds to the Typeface object constructed from an OpenType font family. /// If the Typeface was constructed from a composite font family, returns null. /// /// GlyphTypeface object that corresponds to this Typeface, or null if the Typeface /// was constructed from a composite font. ///Whether glyphTypeface is not null. public bool TryGetGlyphTypeface(out GlyphTypeface glyphTypeface) { glyphTypeface = CachedTypeface.TypefaceMetrics as GlyphTypeface; return glyphTypeface != null; } ////// Fallback font family /// internal FontFamily FallbackFontFamily { get { return _fallbackFontFamily; } } ////// (Western) x-height relative to em size. /// public double XHeight { get { return CachedTypeface.TypefaceMetrics.XHeight; } } ////// Distance from baseline to top of English ----, relative to em size. /// public double CapsHeight { get { return CachedTypeface.TypefaceMetrics.CapsHeight; } } ////// Distance from baseline to underline position /// public double UnderlinePosition { get { return CachedTypeface.TypefaceMetrics.UnderlinePosition; } } ////// Underline thickness /// public double UnderlineThickness { get { return CachedTypeface.TypefaceMetrics.UnderlineThickness; } } ////// Distance from baseline to strike-through position /// public double StrikethroughPosition { get { return CachedTypeface.TypefaceMetrics.StrikethroughPosition; } } ////// strike-through thickness /// public double StrikethroughThickness { get { return CachedTypeface.TypefaceMetrics.StrikethroughThickness; } } ////// Collection of culture-dependant face names. /// public LanguageSpecificStringDictionary FaceNames { get { return new LanguageSpecificStringDictionary(CachedTypeface.TypefaceMetrics.AdjustedFaceNames); } } ////// Distance from character cell top to English baseline relative to em size. /// internal double Baseline { get { return CachedTypeface.FirstFontFamily.Baseline; } } ////// Baseline to baseline distance relative to em size /// internal double LineSpacing { get { return CachedTypeface.FirstFontFamily.LineSpacing; } } ////// Flag indicating if the typeface is of symbol type /// internal bool Symbol { get { return CachedTypeface.TypefaceMetrics.Symbol; } } internal bool NullFont { get { return CachedTypeface.NullFont; } } // Tries to get a GlyphTypeface based on the Typeface properties. The // return value can be null. However, if CheckFastPathNominalGlyphs // returns true, then one can expect this function to return a valid // GlyphTypeface that maps all the specified text. internal GlyphTypeface TryGetGlyphTypeface() { return CachedTypeface.TypefaceMetrics as GlyphTypeface; } internal FontStyle CanonicalStyle { get { return CachedTypeface.CanonicalStyle; } } internal FontWeight CanonicalWeight { get { return CachedTypeface.CanonicalWeight; } } internal FontStretch CanonicalStretch { get { return CachedTypeface.CanonicalStretch; } } ////// Scan through specified character string checking for valid character /// nominal glyph. /// /// character buffer range /// height of Em /// maximum width allowed /// do not stop arbitrarily in the middle of a word /// digits require complex shaping /// CultureInfo of the text /// number of character fit in given width ///whether the specified string can be optimized by nominal glyph lookup internal bool CheckFastPathNominalGlyphs( CharacterBufferRange charBufferRange, double emSize, double widthMax, bool keepAWord, bool numberSubstitution, CultureInfo cultureInfo, out int stringLengthFit ) { stringLengthFit = 0; if (CachedTypeface.NullFont) return false; GlyphTypeface glyphTypeface = TryGetGlyphTypeface(); if (glyphTypeface == null) return false; stringLengthFit = 0; IDictionarycmap = glyphTypeface.CharacterToGlyphMap; double totalWidth = 0; int i = 0; ushort blankGlyph = glyphTypeface.BlankGlyphIndex; ushort glyph = blankGlyph; ushort charFlagsMask = numberSubstitution ? (ushort)(CharacterAttributeFlags.CharacterComplex | CharacterAttributeFlags.CharacterDigit) : (ushort)CharacterAttributeFlags.CharacterComplex; ushort charFlags = 0; ushort charFastTextCheck = (ushort)(CharacterAttributeFlags.CharacterFastText | CharacterAttributeFlags.CharacterIdeo); bool symbolTypeface = glyphTypeface.Symbol; if (symbolTypeface) { // we don't care what code points are present if it's a non-Unicode font such as Symbol or Wingdings; // the code points don't have any standardized meanings, and we always want to bypass shaping charFlagsMask = 0; } if(keepAWord) { do { char ch = charBufferRange[i++]; int charClass = (int)Classification.GetUnicodeClassUTF16(ch); charFlags = Classification.CharAttributeOf(charClass).Flags; charFastTextCheck &= charFlags; cmap.TryGetValue(ch, out glyph); totalWidth += emSize * glyphTypeface.GetAdvanceWidth(glyph); } while( i < charBufferRange.Length && ((charFlags & charFlagsMask) == 0) && (glyph != 0 || symbolTypeface) && glyph != blankGlyph ); // i is now at a character immediately following a leading blank } while( i < charBufferRange.Length && totalWidth <= widthMax && ((charFlags & charFlagsMask) == 0) && (glyph != 0 || symbolTypeface) ) { char ch = charBufferRange[i++]; int charClass = (int)Classification.GetUnicodeClassUTF16(ch); charFlags = Classification.CharAttributeOf(charClass).Flags; charFastTextCheck &= charFlags; cmap.TryGetValue(ch, out glyph); totalWidth += emSize * glyphTypeface.GetAdvanceWidth(glyph); } if (symbolTypeface) { // always optimize for non-Unicode font as we don't support shaping or typographic features; // we also don't fall back from non-Unicode fonts so we don't care if there are missing glyphs stringLengthFit = i; return true; } if (glyph == 0) { // character is not supported by the font return false; } if ((charFlags & charFlagsMask) != 0) { // complex character encountered, exclude it Debug.Assert(i > 0); if(--i <= 0) { // first char is complex, fail the call return false; } } stringLengthFit = i; TypographyAvailabilities typography = glyphTypeface.FontFaceLayoutInfo.TypographyAvailabilities; if ((charFastTextCheck & (byte) CharacterAttributeFlags.CharacterFastText) != 0) { // all input code points are Fast Text if ((typography & ( TypographyAvailabilities.FastTextTypographyAvailable | TypographyAvailabilities.FastTextMajorLanguageLocalizedFormAvailable ) ) != 0 ) { // Considered too risky to optimize. It is either because the font // has required features or the font has 'locl' lookup for major languages. return false; } else if ((typography & TypographyAvailabilities.FastTextExtraLanguageLocalizedFormAvailable) != 0) { // The font has 'locl' lookup for FastText code points for non major languages. // Check whether the input is major langauge. If it is, we are still good to optimize. return MajorLanguages.Contains(cultureInfo); } else { // No FastText flags are present, safe to optimize return true; } } else if ((charFastTextCheck & (byte) CharacterAttributeFlags.CharacterIdeo) != 0) { // The input are all ideographs, check the IdeoTypographyAvailable bit. It is safe if // the bit is not set. return ((typography & TypographyAvailabilities.IdeoTypographyAvailable) == 0); } else { // for all the rest of the cases, just check whether there is any required typography // present at all. If none exists, it is optimizable. We might under-optimize here but // it will be non-major languages. return ((typography & TypographyAvailabilities.Available) == 0); } } /// /// Lookup characters nominal glyphs and width /// /// character buffer range /// height of Em /// scaling factor from real to ideal unit /// glyph nominal advances in ideal units /// total width in ideal units ///true for success ///This function is only used in fast path, and can only be called /// if CheckFastPathNominalGlyphs has previously returned true. internal void GetCharacterNominalWidthsAndIdealWidth( CharacterBufferRange charBufferRange, double emSize, double toIdeal, out int[] nominalWidths, out int idealWidth ) { // This function should only be called if CheckFastPathNominalGlyphs has // returned true so we can assume the ITypefaceMetrics is a GlyphTypeface. GlyphTypeface glyphTypeface = TryGetGlyphTypeface(); Invariant.Assert(glyphTypeface != null); IDictionarycmap = glyphTypeface.CharacterToGlyphMap; nominalWidths = new int[charBufferRange.Length]; idealWidth = 0; for (int i = 0; i < charBufferRange.Length; i++) { ushort glyphIndex; cmap.TryGetValue(charBufferRange[i], out glyphIndex); double advance = emSize * glyphTypeface.GetAdvanceWidth(glyphIndex); nominalWidths[i] = (int) Math.Round(advance * toIdeal); idealWidth += nominalWidths[i]; } } /// /// Create correspondent hash code for the object /// ///object hash code public override int GetHashCode() { int hash = _fontFamily.GetHashCode(); if (_fallbackFontFamily != null) hash = HashFn.HashMultiply(hash) + _fallbackFontFamily.GetHashCode(); hash = HashFn.HashMultiply(hash) + _style.GetHashCode(); hash = HashFn.HashMultiply(hash) + _weight.GetHashCode(); hash = HashFn.HashMultiply(hash) + _stretch.GetHashCode(); return HashFn.HashScramble(hash); } ////// Equality check /// public override bool Equals(object o) { Typeface t = o as Typeface; if(t == null) return false; return _style == t._style && _weight == t._weight && _stretch == t._stretch && _fontFamily.Equals(t._fontFamily) && CompareFallbackFontFamily(t._fallbackFontFamily); } internal bool CompareFallbackFontFamily(FontFamily fallbackFontFamily) { if (fallbackFontFamily == null || _fallbackFontFamily == null) return fallbackFontFamily == _fallbackFontFamily; return _fallbackFontFamily.Equals(fallbackFontFamily); } //---------------------------------------- // Private method //---------------------------------------- private CachedTypeface CachedTypeface { get { if (_cachedTypeface == null) { CachedTypeface cachedTypeface = TypefaceMetricsCache.ReadonlyLookup(this) as CachedTypeface; if (cachedTypeface == null) { cachedTypeface = ConstructCachedTypeface(); TypefaceMetricsCache.Add(this, cachedTypeface); } // For thread-safety, set the _cachedTypeface field only after we have a fully // initialized CachedTypeface object. _cachedTypeface = cachedTypeface; } return _cachedTypeface; } } private CachedTypeface ConstructCachedTypeface() { FontStyle canonicalStyle = _style; FontWeight canonicalWeight = _weight; FontStretch canonicalStretch = _stretch; // // We always call FontFamily.FindFirstFontFamilyAndFace() method to resolve the // canonical styles since the implied styles in FontFamily name will override // the given styles in the Typeface. But we don't always use the IFontFamily // instance returned from this method because an equal instance might already be // cached. // FontFamily sourceFontFamily = FontFamily; IFontFamily firstFontFamily = sourceFontFamily.FindFirstFontFamilyAndFace( ref canonicalStyle, ref canonicalWeight, ref canonicalStretch ); if (firstFontFamily == null) { if (FallbackFontFamily != null) { sourceFontFamily = FallbackFontFamily; firstFontFamily = sourceFontFamily.FindFirstFontFamilyAndFace( ref canonicalStyle, ref canonicalWeight, ref canonicalStretch ); } if (firstFontFamily == null) { sourceFontFamily = null; firstFontFamily = FontFamily.LookupFontFamily(FontFamily.NullFontFamilyCanonicalName); } } // If it's a named font, map all occurrences of the same name to one cached IFontFamily. if (sourceFontFamily != null && sourceFontFamily.Source != null) { // We lookup in the cache to see if there is cached IFontFamily instance of the source FontFamily. Otherwise, // this IFontFamily value is added to the TypefaceMetrics cache. IFontFamily cachedValue = TypefaceMetricsCache.ReadonlyLookup(sourceFontFamily.FamilyIdentifier) as IFontFamily; if (cachedValue != null) { firstFontFamily = cachedValue; } else { TypefaceMetricsCache.Add(sourceFontFamily.FamilyIdentifier, firstFontFamily); } } ITypefaceMetrics typefaceMetrics = firstFontFamily.GetTypefaceMetrics(canonicalStyle, canonicalWeight, canonicalStretch); return new CachedTypeface( canonicalStyle, canonicalWeight, canonicalStretch, firstFontFamily, typefaceMetrics, sourceFontFamily == null ); } } } // 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
- Accessible.cs
- XmlSecureResolver.cs
- VirtualizingStackPanel.cs
- Cursor.cs
- HttpClientCertificate.cs
- BidPrivateBase.cs
- EdgeModeValidation.cs
- FileEnumerator.cs
- SpeechRecognitionEngine.cs
- FunctionDetailsReader.cs
- SignedInfo.cs
- DataColumnMappingCollection.cs
- SoapTypeAttribute.cs
- BitmapSourceSafeMILHandle.cs
- TextRangeEditLists.cs
- ViewBase.cs
- FormatConvertedBitmap.cs
- XmlSchemaComplexContentRestriction.cs
- PartialArray.cs
- CommandDevice.cs
- FrameworkContentElement.cs
- IDQuery.cs
- Button.cs
- FaultHandlingFilter.cs
- CLSCompliantAttribute.cs
- TextTreeExtractElementUndoUnit.cs
- ArgumentException.cs
- ProtectedConfiguration.cs
- PipelineDeploymentState.cs
- FormsAuthenticationUser.cs
- ICspAsymmetricAlgorithm.cs
- PageCatalogPart.cs
- DefaultTextStoreTextComposition.cs
- ExcludeFromCodeCoverageAttribute.cs
- IpcChannel.cs
- GiveFeedbackEventArgs.cs
- ObjectQuery.cs
- BlockUIContainer.cs
- OutputCacheSection.cs
- CheckBoxList.cs
- TrustSection.cs
- XPathNavigatorReader.cs
- HtmlInputHidden.cs
- ClusterRegistryConfigurationProvider.cs
- MenuItemStyle.cs
- DataBindingCollection.cs
- XmlNodeChangedEventManager.cs
- Binding.cs
- Boolean.cs
- InputMethodStateTypeInfo.cs
- SapiAttributeParser.cs
- ValidatedControlConverter.cs
- PerformanceCounter.cs
- DescendentsWalkerBase.cs
- BulletedList.cs
- EnvironmentPermission.cs
- EventWaitHandle.cs
- dataSvcMapFileLoader.cs
- DocumentPageView.cs
- RegexRunnerFactory.cs
- CachingHintValidation.cs
- SystemIcmpV4Statistics.cs
- DataTableMappingCollection.cs
- XComponentModel.cs
- XmlSchemaRedefine.cs
- SessionEndingEventArgs.cs
- EtwTrace.cs
- ContentTextAutomationPeer.cs
- SocketElement.cs
- PeerValidationBehavior.cs
- wgx_render.cs
- UnicastIPAddressInformationCollection.cs
- XamlRtfConverter.cs
- ChannelManager.cs
- precedingquery.cs
- TypeToken.cs
- StyleSheetRefUrlEditor.cs
- ChangeConflicts.cs
- ResXDataNode.cs
- ToolStripDropDownMenu.cs
- WbemProvider.cs
- Span.cs
- SqlServices.cs
- _FtpControlStream.cs
- IResourceProvider.cs
- OdbcParameter.cs
- TypedElement.cs
- FieldDescriptor.cs
- EntityDataSourceQueryBuilder.cs
- HtmlElement.cs
- CompilerError.cs
- DataGridComboBoxColumn.cs
- SolidColorBrush.cs
- PageAdapter.cs
- XmlUtf8RawTextWriter.cs
- SystemIcons.cs
- OciEnlistContext.cs
- FormsAuthenticationUserCollection.cs
- TransformConverter.cs
- ListViewGroupConverter.cs