Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / 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;
IDictionary cmap = 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);
IDictionary cmap = 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;
IDictionary cmap = 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);
IDictionary cmap = 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
- MetaModel.cs
- InnerItemCollectionView.cs
- TextWriterTraceListener.cs
- PageCatalogPart.cs
- SystemNetworkInterface.cs
- TextModifier.cs
- WpfKnownType.cs
- HostingEnvironment.cs
- XmlLoader.cs
- ZipIOBlockManager.cs
- DropShadowBitmapEffect.cs
- PreDigestedSignedInfo.cs
- RemotingHelper.cs
- CompareValidator.cs
- BrowserDefinitionCollection.cs
- HttpCapabilitiesEvaluator.cs
- DebugHandleTracker.cs
- ConnectionInterfaceCollection.cs
- URLIdentityPermission.cs
- UniqueID.cs
- OleDbPropertySetGuid.cs
- StateMachineHelpers.cs
- PlanCompilerUtil.cs
- UriTemplateDispatchFormatter.cs
- TypeSystem.cs
- UIInitializationException.cs
- Transform3DGroup.cs
- AssemblyCollection.cs
- ADMembershipUser.cs
- DnsPermission.cs
- documentsequencetextview.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- DataGridViewTextBoxColumn.cs
- ControlBuilder.cs
- StateWorkerRequest.cs
- SplitContainerDesigner.cs
- Nullable.cs
- Matrix.cs
- CodeTypeMemberCollection.cs
- Error.cs
- EventPrivateKey.cs
- TypeUtil.cs
- IgnoreFlushAndCloseStream.cs
- EntityDataSourceReferenceGroup.cs
- ProjectionCamera.cs
- ParseNumbers.cs
- ACL.cs
- UInt64Converter.cs
- XmlTextReader.cs
- RawMouseInputReport.cs
- Solver.cs
- TableDetailsRow.cs
- DbConnectionStringCommon.cs
- ParenthesizePropertyNameAttribute.cs
- CssTextWriter.cs
- mongolianshape.cs
- AssemblyNameProxy.cs
- WindowsFormsHelpers.cs
- HtmlControlPersistable.cs
- DecoderReplacementFallback.cs
- InstanceDataCollection.cs
- SequentialWorkflowRootDesigner.cs
- WebPartEditorApplyVerb.cs
- TextTreeText.cs
- ListDictionary.cs
- ValidationError.cs
- WebPartConnection.cs
- HideDisabledControlAdapter.cs
- BaseValidator.cs
- StringArrayConverter.cs
- CollectionViewProxy.cs
- NamespaceMapping.cs
- MessageQueueTransaction.cs
- X509Utils.cs
- GlyphsSerializer.cs
- Filter.cs
- DesignerForm.cs
- Win32KeyboardDevice.cs
- DataGridViewToolTip.cs
- CreatingCookieEventArgs.cs
- ZipIORawDataFileBlock.cs
- GridLengthConverter.cs
- PeerDuplexChannel.cs
- SqlBulkCopyColumnMapping.cs
- WS2007FederationHttpBindingElement.cs
- SizeChangedEventArgs.cs
- XD.cs
- WeakReadOnlyCollection.cs
- WebCategoryAttribute.cs
- NativeMethods.cs
- SynchronizationLockException.cs
- ApplicationServiceManager.cs
- SessionStateUtil.cs
- CustomTokenProvider.cs
- DesignerWithHeader.cs
- TraceUtility.cs
- COM2ExtendedUITypeEditor.cs
- PrePostDescendentsWalker.cs
- OdbcCommand.cs
- EmptyControlCollection.cs