Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / MS / Internal / FontFace / CachedCompositeFamily.cs / 1 / CachedCompositeFamily.cs
//----------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
//
// Description: The CachedCompositeFamily class
//
// History:
// 08/01/2003 : mleonov - Created
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Windows;
using System.Windows.Markup; // for XmlLanguage
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
// External Team
using MS.Utility;
using MS.Internal;
using MS.Internal.FontCache;
using MS.Internal.Shaping;
using MS.Internal.TextFormatting;
namespace MS.Internal.FontFace
{
///
/// CachedCompositeFamily class represents a composite font family obtained from .CompositeFont file.
///
internal class CachedCompositeFamily : IFontFamily
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Critical - takes in canonical name and unsafe struct of CachedFontFamily
///
[SecurityCritical]
internal unsafe CachedCompositeFamily(CachedFontFamily cachedFamily)
{
Debug.Assert(!cachedFamily.IsNull);
_cachedFamily = cachedFamily;
}
#endregion Constructors
//------------------------------------------------------
//
// Internal Methods
//
//-----------------------------------------------------
#region Internal Methods
///
/// Get typeface metrics of the specified style
///
///
/// Critical: This accesses a pointer uses unsafe code. The risk here is in derefrencing pointers.
/// TreatAsSafe: This information is ok to return also the call to the pointers to get CompositeFace has
/// checking to ensure that you are not dereferencing a null pointer
///
[SecurityCritical,SecurityTreatAsSafe]
ITypefaceMetrics IFontFamily.GetTypefaceMetrics(
FontStyle style,
FontWeight weight,
FontStretch stretch
)
{
CachedFontFace bestFace = FindNearestTypeface(style, weight, stretch);
if (!bestFace.IsNull)
{
unsafe
{
return new CompositeTypefaceMetrics(
bestFace.CompositeFace->underlinePosition,
bestFace.CompositeFace->underlineThickness,
bestFace.CompositeFace->strikeThroughPosition,
bestFace.CompositeFace->strikeThroughThickness,
bestFace.CompositeFace->capsHeight,
bestFace.CompositeFace->xHeight,
bestFace.CompositeFace->fontStyle,
bestFace.CompositeFace->fontWeight,
bestFace.CompositeFace->fontStretch
);
}
}
else
{
return new CompositeTypefaceMetrics();
}
}
///
/// Look up device font for the typeface.
///
///
/// Critical - as it contains unsafe code
/// TreatAsSafe - because it only returns an IDeviceFont which is safe
///
[SecurityCritical,SecurityTreatAsSafe]
IDeviceFont IFontFamily.GetDeviceFont(FontStyle style, FontWeight weight, FontStretch stretch)
{
CachedFontFace bestFace = FindExactTypeface(style, weight, stretch);
if (!bestFace.IsNull)
{
unsafe
{
int offsetToDeviceFont = bestFace.CompositeFace->offsetToDeviceFont;
if (offsetToDeviceFont != 0)
{
return new DeviceFont(
_cachedFamily,
bestFace.CheckedPointer + offsetToDeviceFont
);
}
}
}
return null;
}
///
/// Find the face exactly matching the specified style, weight and stretch.
/// Returns CachedFontFace.Null if there is no matching face.
///
private CachedFontFace FindExactTypeface(FontStyle style, FontWeight weight, FontStretch stretch)
{
MatchingStyle target = new MatchingStyle(style, weight, stretch);
for (int i = 0; i < _cachedFamily.NumberOfFaces; i++)
{
CachedFontFace currentFace = _cachedFamily.FamilyCollection.GetCachedFace(_cachedFamily, i);
if (currentFace.MatchingStyle == target)
{
return currentFace;
}
}
return CachedFontFace.Null;
}
///
/// Find the face most closely matching the specified style, weight and stretch.
/// Returns CachedFontFace.Null if there is no available face.
///
private CachedFontFace FindNearestTypeface(FontStyle style, FontWeight weight, FontStretch stretch)
{
if (_cachedFamily.NumberOfFaces == 0)
{
return CachedFontFace.Null;
}
MatchingStyle target = new MatchingStyle(style, weight, stretch);
CachedFontFace bestFace = _cachedFamily.FamilyCollection.GetCachedFace(_cachedFamily, 0);
MatchingStyle bestMatch = bestFace.MatchingStyle;
for (int i = 1; i < _cachedFamily.NumberOfFaces; i++)
{
CachedFontFace currentFace = _cachedFamily.FamilyCollection.GetCachedFace(_cachedFamily, i);
MatchingStyle currentMatch = currentFace.MatchingStyle;
if (MatchingStyle.IsBetterMatch(target, bestMatch, ref currentMatch))
{
bestMatch = currentMatch;
bestFace = currentFace;
}
}
return bestFace;
}
///
/// Get family name correspondent to the first n-characters of the specified character string
///
/// character string
/// text culture info
/// culture used for digit subsitution or null
/// default size relative to em
/// number of characters advanced
/// target family name
/// size relative to em
/// number of character sharing the same family name and size
///
///
/// Null target family name returned indicates that the font family cannot find target
/// name of the character range being advanced.
///
/// Return value false indicates that the font family has no character map.
/// It is a font face family.
///
///
///
/// Critical: This code calls into GetCachedFamilyMap which returns a pointer
/// TreatAsSafe: It does not expose the pointer and this information is ok to expose
///
[SecurityCritical,SecurityTreatAsSafe]
unsafe bool IFontFamily.GetMapTargetFamilyNameAndScale(
CharacterBufferRange unicodeString,
CultureInfo culture,
CultureInfo digitCulture,
double defaultSizeInEm,
out int cchAdvance,
out string targetFamilyName,
out double scaleInEm
)
{
Invariant.Assert(unicodeString.CharacterBuffer != null && unicodeString.Length > 0);
Invariant.Assert(culture != null);
// Get the family map. This will find the first family map that matches
// the specified culture, an ancestor neutral culture, or "any" culture.
FamilyCollection.CachedFamilyMap * familyMap = GetCachedFamilyMap(
unicodeString,
culture,
digitCulture,
out cchAdvance
);
if (familyMap == null)
{
targetFamilyName = null;
scaleInEm = 1;
}
else
{
int* sizePrefix = (int*)((byte*)familyMap + familyMap->targetFamilyNameOffset);
targetFamilyName = Util.StringCopyFromUncheckedPointer(sizePrefix + 1, *sizePrefix);
scaleInEm = familyMap->scaleInEm;
}
return true;
}
///
/// Critical: This code calls utilizes unsafe code blocks to extract the CachedFamilyMap.
/// The pointer checking for the unicode string is done in the UnicodeScalar. At the same time
/// GetFamilyMapRange takes _cachedFamily which cannot be instantiated with a null value.And its value
/// cannot be set outside of the constructor. It is critical because it exposes a pointer
///
[SecurityCritical]
private unsafe FamilyCollection.CachedFamilyMap *GetCachedFamilyMap(
CharacterBufferRange unicodeString,
CultureInfo culture,
CultureInfo digitCulture,
out int cchAdvance
)
{
cchAdvance = 0;
DigitMap digitMap = new DigitMap(digitCulture);
int lengthOfRanges;
ushort* ranges = _cachedFamily.FamilyCollection.GetFamilyMapRanges(
_cachedFamily.CompositeFamily,
culture,
out lengthOfRanges
);
Debug.Assert(ranges != null);
int sizeofChar = 0;
int ch = 0;
cchAdvance = Classification.AdvanceWhile(unicodeString, ItemClass.JoinerClass);
if (cchAdvance >= unicodeString.Length)
{
// It is rare that the run only contains joiner characters.
// If it really happens, just map them to the initial family map.
return _cachedFamily.FamilyCollection.GetFamilyMapOfChar(
_cachedFamily.CompositeFamily,
ranges,
lengthOfRanges,
Classification.UnicodeScalar(unicodeString, out sizeofChar)
);
}
//
// If the run starts with combining marks, we will not be able to find base characters for them
// within the run. These combining marks will be mapped to their best fonts as normal characters.
//
ch = Classification.UnicodeScalar(
new CharacterBufferRange(unicodeString, cchAdvance, unicodeString.Length - cchAdvance),
out sizeofChar
);
bool hasBaseChar = !Classification.IsCombining(ch);
ch = digitMap[ch];
FamilyCollection.CachedFamilyMap* familyMap =
_cachedFamily.FamilyCollection.GetFamilyMapOfChar(_cachedFamily.CompositeFamily, ranges, lengthOfRanges, ch);
for (cchAdvance += sizeofChar; cchAdvance < unicodeString.Length; cchAdvance += sizeofChar)
{
ch = Classification.UnicodeScalar(
new CharacterBufferRange(unicodeString, cchAdvance, unicodeString.Length - cchAdvance),
out sizeofChar
);
if (Classification.IsJoiner(ch))
continue; // continue to advance if current char is a joiner
if (!Classification.IsCombining(ch))
{
hasBaseChar = true;
}
else if (hasBaseChar)
{
continue; // continue to advance for combining mark with base char
}
ch = digitMap[ch];
if (_cachedFamily.FamilyCollection.GetFamilyMapOfChar(_cachedFamily.CompositeFamily, ranges, lengthOfRanges, ch) != familyMap)
{
break;
}
}
return familyMap;
}
#endregion Internal Methods
//------------------------------------------------------
//
// Internal Properties
//
//------------------------------------------------------
#region IFontFamily Properties
///
/// Font family name table indexed by culture
///
IDictionary IFontFamily.Names
{
get
{
return _cachedFamily.Names;
}
}
///
/// Distance from character cell top to English baseline relative to em size.
///
double IFontFamily.Baseline
{
get
{
if (_cachedFamily.Baseline != 0)
return _cachedFamily.Baseline;
return GetFirstFontFamily().Baseline;
}
}
///
/// Recommended baseline-to-baseline distance for text in this font
///
double IFontFamily.LineSpacing
{
get
{
if (_cachedFamily.LineSpacing != 0)
return _cachedFamily.LineSpacing;
return GetFirstFontFamily().LineSpacing;
}
}
ICollection IFontFamily.GetTypefaces(FontFamilyIdentifier familyIdentifier)
{
return new TypefaceCollection(new FontFamily(familyIdentifier), _cachedFamily);
}
#endregion Internal Properties
//-----------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region Private Methods
///
/// Get the first font family of the first target family name
///
private IFontFamily GetFirstFontFamily()
{
if(_firstFontFamily == null)
{
_firstFontFamily = FontFamily.FindFontFamilyFromFriendlyNameList(GetFirstTargetFamilyName());
Debug.Assert(_firstFontFamily != null);
}
return _firstFontFamily;
}
///
/// Critical: This code calls into CompositeFamily which returns a pointer
/// TreatAsSafe: This returns a string with the target family name
///
[SecurityCritical,SecurityTreatAsSafe]
private string GetFirstTargetFamilyName()
{
unsafe
{
return Util.StringAndLengthCopyFromCheckedPointer(
_cachedFamily.CheckedPointer + _cachedFamily.CompositeFamily->OffsetToTargetFamilyNameStrings
);
}
}
#endregion Private Methods
#region Private Classes
private class DeviceFont : IDeviceFont
{
///
/// Critical - as we assume the caller is giving us a valid pointer
///
[SecurityCritical]
internal DeviceFont(CachedFontFamily cachedFamily, CheckedPointer deviceFont)
{
unsafe
{
_cachedFamily = cachedFamily;
_deviceFont = (FamilyCollection.CachedDeviceFont*)deviceFont.Probe(0, sizeof(FamilyCollection.CachedDeviceFont));
_sizeInBytes = deviceFont.Size;
}
}
string IDeviceFont.Name
{
get
{
return Util.StringAndLengthCopyFromCheckedPointer(
CheckedPointer + FamilyCollection.CachedDeviceFont.OffsetToLengthPrefixedName
);
}
}
///
/// Critical - as it calls a critical method that returns a pointer
/// TreatAsSafe - because it does not expose the pointer
///
[SecurityCritical, SecurityTreatAsSafe]
bool IDeviceFont.ContainsCharacter(int unicodeScalar)
{
unsafe
{
return LookupMetrics(unicodeScalar) != null;
}
}
///
/// Critical - As it uses raw pointers.
///
[SecurityCritical]
unsafe void IDeviceFont.GetAdvanceWidths(
char* characterString,
int characterLength,
double emSize,
int* pAdvances
)
{
unsafe
{
for (int i = 0; i < characterLength; ++i)
{
FamilyCollection.CachedCharacterMetrics* metrics = LookupMetrics(characterString[i]);
if (metrics != null)
{
// Side bearings are included in the advance width but are not used as offsets for glyph positioning.
pAdvances[i] = Math.Max(0, (int)((metrics->blackBoxWidth + metrics->leftSideBearing + metrics->rightSideBearing) * emSize));
}
else
{
pAdvances[i] = 0;
}
}
}
}
///
/// Critical - as it accesses a critical field, performs pointer arithmetic, and returns a pointer.
///
[SecurityCritical]
private unsafe FamilyCollection.CachedCharacterMetrics* LookupMetrics(int unicodeScalar)
{
if (unicodeScalar >= 0 && unicodeScalar <= FontFamilyMap.LastUnicodeScalar)
{
int pageTableOffset = _deviceFont->OffsetToCharacterMap;
int* pageTable = (int*)CheckedPointer.Probe(
pageTableOffset,
CharacterMetricsDictionary.PageCount * sizeof(int)
);
int i = pageTable[unicodeScalar >> CharacterMetricsDictionary.PageShift];
if (i != 0)
{
int* page = (int*)CheckedPointer.Probe(
pageTableOffset + (i * sizeof(int)),
CharacterMetricsDictionary.PageSize * sizeof(int)
);
int offset = page[unicodeScalar & CharacterMetricsDictionary.PageMask];
if (offset != 0)
{
return (FamilyCollection.CachedCharacterMetrics*)CheckedPointer.Probe(
offset,
sizeof(FamilyCollection.CachedCharacterMetrics)
);
}
}
}
return null;
}
///
/// Critical - constructs a CheckedPointer which is a critical operation
/// TreatAsSafe - the pointer and size fields used to construct the CheckedPointer are tracked and
/// the CheckedPointer itself is safe to use
///
private CheckedPointer CheckedPointer
{
[SecurityCritical,SecurityTreatAsSafe]
get
{
unsafe
{
return new CheckedPointer(_deviceFont, _sizeInBytes);
}
}
}
private CachedFontFamily _cachedFamily;
///
/// Critical - as this field is a pointer and therefore unsafe.
///
[SecurityCritical]
private unsafe FamilyCollection.CachedDeviceFont* _deviceFont;
///
/// Critical - used for bounds checking via CheckedPointer
///
[SecurityCritical]
private int _sizeInBytes;
}
#endregion
//-----------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
#region Private Fields
private CachedFontFamily _cachedFamily;
private IFontFamily _firstFontFamily;
#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: The CachedCompositeFamily class
//
// History:
// 08/01/2003 : mleonov - Created
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Windows;
using System.Windows.Markup; // for XmlLanguage
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
// External Team
using MS.Utility;
using MS.Internal;
using MS.Internal.FontCache;
using MS.Internal.Shaping;
using MS.Internal.TextFormatting;
namespace MS.Internal.FontFace
{
///
/// CachedCompositeFamily class represents a composite font family obtained from .CompositeFont file.
///
internal class CachedCompositeFamily : IFontFamily
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Critical - takes in canonical name and unsafe struct of CachedFontFamily
///
[SecurityCritical]
internal unsafe CachedCompositeFamily(CachedFontFamily cachedFamily)
{
Debug.Assert(!cachedFamily.IsNull);
_cachedFamily = cachedFamily;
}
#endregion Constructors
//------------------------------------------------------
//
// Internal Methods
//
//-----------------------------------------------------
#region Internal Methods
///
/// Get typeface metrics of the specified style
///
///
/// Critical: This accesses a pointer uses unsafe code. The risk here is in derefrencing pointers.
/// TreatAsSafe: This information is ok to return also the call to the pointers to get CompositeFace has
/// checking to ensure that you are not dereferencing a null pointer
///
[SecurityCritical,SecurityTreatAsSafe]
ITypefaceMetrics IFontFamily.GetTypefaceMetrics(
FontStyle style,
FontWeight weight,
FontStretch stretch
)
{
CachedFontFace bestFace = FindNearestTypeface(style, weight, stretch);
if (!bestFace.IsNull)
{
unsafe
{
return new CompositeTypefaceMetrics(
bestFace.CompositeFace->underlinePosition,
bestFace.CompositeFace->underlineThickness,
bestFace.CompositeFace->strikeThroughPosition,
bestFace.CompositeFace->strikeThroughThickness,
bestFace.CompositeFace->capsHeight,
bestFace.CompositeFace->xHeight,
bestFace.CompositeFace->fontStyle,
bestFace.CompositeFace->fontWeight,
bestFace.CompositeFace->fontStretch
);
}
}
else
{
return new CompositeTypefaceMetrics();
}
}
///
/// Look up device font for the typeface.
///
///
/// Critical - as it contains unsafe code
/// TreatAsSafe - because it only returns an IDeviceFont which is safe
///
[SecurityCritical,SecurityTreatAsSafe]
IDeviceFont IFontFamily.GetDeviceFont(FontStyle style, FontWeight weight, FontStretch stretch)
{
CachedFontFace bestFace = FindExactTypeface(style, weight, stretch);
if (!bestFace.IsNull)
{
unsafe
{
int offsetToDeviceFont = bestFace.CompositeFace->offsetToDeviceFont;
if (offsetToDeviceFont != 0)
{
return new DeviceFont(
_cachedFamily,
bestFace.CheckedPointer + offsetToDeviceFont
);
}
}
}
return null;
}
///
/// Find the face exactly matching the specified style, weight and stretch.
/// Returns CachedFontFace.Null if there is no matching face.
///
private CachedFontFace FindExactTypeface(FontStyle style, FontWeight weight, FontStretch stretch)
{
MatchingStyle target = new MatchingStyle(style, weight, stretch);
for (int i = 0; i < _cachedFamily.NumberOfFaces; i++)
{
CachedFontFace currentFace = _cachedFamily.FamilyCollection.GetCachedFace(_cachedFamily, i);
if (currentFace.MatchingStyle == target)
{
return currentFace;
}
}
return CachedFontFace.Null;
}
///
/// Find the face most closely matching the specified style, weight and stretch.
/// Returns CachedFontFace.Null if there is no available face.
///
private CachedFontFace FindNearestTypeface(FontStyle style, FontWeight weight, FontStretch stretch)
{
if (_cachedFamily.NumberOfFaces == 0)
{
return CachedFontFace.Null;
}
MatchingStyle target = new MatchingStyle(style, weight, stretch);
CachedFontFace bestFace = _cachedFamily.FamilyCollection.GetCachedFace(_cachedFamily, 0);
MatchingStyle bestMatch = bestFace.MatchingStyle;
for (int i = 1; i < _cachedFamily.NumberOfFaces; i++)
{
CachedFontFace currentFace = _cachedFamily.FamilyCollection.GetCachedFace(_cachedFamily, i);
MatchingStyle currentMatch = currentFace.MatchingStyle;
if (MatchingStyle.IsBetterMatch(target, bestMatch, ref currentMatch))
{
bestMatch = currentMatch;
bestFace = currentFace;
}
}
return bestFace;
}
///
/// Get family name correspondent to the first n-characters of the specified character string
///
/// character string
/// text culture info
/// culture used for digit subsitution or null
/// default size relative to em
/// number of characters advanced
/// target family name
/// size relative to em
/// number of character sharing the same family name and size
///
///
/// Null target family name returned indicates that the font family cannot find target
/// name of the character range being advanced.
///
/// Return value false indicates that the font family has no character map.
/// It is a font face family.
///
///
///
/// Critical: This code calls into GetCachedFamilyMap which returns a pointer
/// TreatAsSafe: It does not expose the pointer and this information is ok to expose
///
[SecurityCritical,SecurityTreatAsSafe]
unsafe bool IFontFamily.GetMapTargetFamilyNameAndScale(
CharacterBufferRange unicodeString,
CultureInfo culture,
CultureInfo digitCulture,
double defaultSizeInEm,
out int cchAdvance,
out string targetFamilyName,
out double scaleInEm
)
{
Invariant.Assert(unicodeString.CharacterBuffer != null && unicodeString.Length > 0);
Invariant.Assert(culture != null);
// Get the family map. This will find the first family map that matches
// the specified culture, an ancestor neutral culture, or "any" culture.
FamilyCollection.CachedFamilyMap * familyMap = GetCachedFamilyMap(
unicodeString,
culture,
digitCulture,
out cchAdvance
);
if (familyMap == null)
{
targetFamilyName = null;
scaleInEm = 1;
}
else
{
int* sizePrefix = (int*)((byte*)familyMap + familyMap->targetFamilyNameOffset);
targetFamilyName = Util.StringCopyFromUncheckedPointer(sizePrefix + 1, *sizePrefix);
scaleInEm = familyMap->scaleInEm;
}
return true;
}
///
/// Critical: This code calls utilizes unsafe code blocks to extract the CachedFamilyMap.
/// The pointer checking for the unicode string is done in the UnicodeScalar. At the same time
/// GetFamilyMapRange takes _cachedFamily which cannot be instantiated with a null value.And its value
/// cannot be set outside of the constructor. It is critical because it exposes a pointer
///
[SecurityCritical]
private unsafe FamilyCollection.CachedFamilyMap *GetCachedFamilyMap(
CharacterBufferRange unicodeString,
CultureInfo culture,
CultureInfo digitCulture,
out int cchAdvance
)
{
cchAdvance = 0;
DigitMap digitMap = new DigitMap(digitCulture);
int lengthOfRanges;
ushort* ranges = _cachedFamily.FamilyCollection.GetFamilyMapRanges(
_cachedFamily.CompositeFamily,
culture,
out lengthOfRanges
);
Debug.Assert(ranges != null);
int sizeofChar = 0;
int ch = 0;
cchAdvance = Classification.AdvanceWhile(unicodeString, ItemClass.JoinerClass);
if (cchAdvance >= unicodeString.Length)
{
// It is rare that the run only contains joiner characters.
// If it really happens, just map them to the initial family map.
return _cachedFamily.FamilyCollection.GetFamilyMapOfChar(
_cachedFamily.CompositeFamily,
ranges,
lengthOfRanges,
Classification.UnicodeScalar(unicodeString, out sizeofChar)
);
}
//
// If the run starts with combining marks, we will not be able to find base characters for them
// within the run. These combining marks will be mapped to their best fonts as normal characters.
//
ch = Classification.UnicodeScalar(
new CharacterBufferRange(unicodeString, cchAdvance, unicodeString.Length - cchAdvance),
out sizeofChar
);
bool hasBaseChar = !Classification.IsCombining(ch);
ch = digitMap[ch];
FamilyCollection.CachedFamilyMap* familyMap =
_cachedFamily.FamilyCollection.GetFamilyMapOfChar(_cachedFamily.CompositeFamily, ranges, lengthOfRanges, ch);
for (cchAdvance += sizeofChar; cchAdvance < unicodeString.Length; cchAdvance += sizeofChar)
{
ch = Classification.UnicodeScalar(
new CharacterBufferRange(unicodeString, cchAdvance, unicodeString.Length - cchAdvance),
out sizeofChar
);
if (Classification.IsJoiner(ch))
continue; // continue to advance if current char is a joiner
if (!Classification.IsCombining(ch))
{
hasBaseChar = true;
}
else if (hasBaseChar)
{
continue; // continue to advance for combining mark with base char
}
ch = digitMap[ch];
if (_cachedFamily.FamilyCollection.GetFamilyMapOfChar(_cachedFamily.CompositeFamily, ranges, lengthOfRanges, ch) != familyMap)
{
break;
}
}
return familyMap;
}
#endregion Internal Methods
//------------------------------------------------------
//
// Internal Properties
//
//------------------------------------------------------
#region IFontFamily Properties
///
/// Font family name table indexed by culture
///
IDictionary IFontFamily.Names
{
get
{
return _cachedFamily.Names;
}
}
///
/// Distance from character cell top to English baseline relative to em size.
///
double IFontFamily.Baseline
{
get
{
if (_cachedFamily.Baseline != 0)
return _cachedFamily.Baseline;
return GetFirstFontFamily().Baseline;
}
}
///
/// Recommended baseline-to-baseline distance for text in this font
///
double IFontFamily.LineSpacing
{
get
{
if (_cachedFamily.LineSpacing != 0)
return _cachedFamily.LineSpacing;
return GetFirstFontFamily().LineSpacing;
}
}
ICollection IFontFamily.GetTypefaces(FontFamilyIdentifier familyIdentifier)
{
return new TypefaceCollection(new FontFamily(familyIdentifier), _cachedFamily);
}
#endregion Internal Properties
//-----------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region Private Methods
///
/// Get the first font family of the first target family name
///
private IFontFamily GetFirstFontFamily()
{
if(_firstFontFamily == null)
{
_firstFontFamily = FontFamily.FindFontFamilyFromFriendlyNameList(GetFirstTargetFamilyName());
Debug.Assert(_firstFontFamily != null);
}
return _firstFontFamily;
}
///
/// Critical: This code calls into CompositeFamily which returns a pointer
/// TreatAsSafe: This returns a string with the target family name
///
[SecurityCritical,SecurityTreatAsSafe]
private string GetFirstTargetFamilyName()
{
unsafe
{
return Util.StringAndLengthCopyFromCheckedPointer(
_cachedFamily.CheckedPointer + _cachedFamily.CompositeFamily->OffsetToTargetFamilyNameStrings
);
}
}
#endregion Private Methods
#region Private Classes
private class DeviceFont : IDeviceFont
{
///
/// Critical - as we assume the caller is giving us a valid pointer
///
[SecurityCritical]
internal DeviceFont(CachedFontFamily cachedFamily, CheckedPointer deviceFont)
{
unsafe
{
_cachedFamily = cachedFamily;
_deviceFont = (FamilyCollection.CachedDeviceFont*)deviceFont.Probe(0, sizeof(FamilyCollection.CachedDeviceFont));
_sizeInBytes = deviceFont.Size;
}
}
string IDeviceFont.Name
{
get
{
return Util.StringAndLengthCopyFromCheckedPointer(
CheckedPointer + FamilyCollection.CachedDeviceFont.OffsetToLengthPrefixedName
);
}
}
///
/// Critical - as it calls a critical method that returns a pointer
/// TreatAsSafe - because it does not expose the pointer
///
[SecurityCritical, SecurityTreatAsSafe]
bool IDeviceFont.ContainsCharacter(int unicodeScalar)
{
unsafe
{
return LookupMetrics(unicodeScalar) != null;
}
}
///
/// Critical - As it uses raw pointers.
///
[SecurityCritical]
unsafe void IDeviceFont.GetAdvanceWidths(
char* characterString,
int characterLength,
double emSize,
int* pAdvances
)
{
unsafe
{
for (int i = 0; i < characterLength; ++i)
{
FamilyCollection.CachedCharacterMetrics* metrics = LookupMetrics(characterString[i]);
if (metrics != null)
{
// Side bearings are included in the advance width but are not used as offsets for glyph positioning.
pAdvances[i] = Math.Max(0, (int)((metrics->blackBoxWidth + metrics->leftSideBearing + metrics->rightSideBearing) * emSize));
}
else
{
pAdvances[i] = 0;
}
}
}
}
///
/// Critical - as it accesses a critical field, performs pointer arithmetic, and returns a pointer.
///
[SecurityCritical]
private unsafe FamilyCollection.CachedCharacterMetrics* LookupMetrics(int unicodeScalar)
{
if (unicodeScalar >= 0 && unicodeScalar <= FontFamilyMap.LastUnicodeScalar)
{
int pageTableOffset = _deviceFont->OffsetToCharacterMap;
int* pageTable = (int*)CheckedPointer.Probe(
pageTableOffset,
CharacterMetricsDictionary.PageCount * sizeof(int)
);
int i = pageTable[unicodeScalar >> CharacterMetricsDictionary.PageShift];
if (i != 0)
{
int* page = (int*)CheckedPointer.Probe(
pageTableOffset + (i * sizeof(int)),
CharacterMetricsDictionary.PageSize * sizeof(int)
);
int offset = page[unicodeScalar & CharacterMetricsDictionary.PageMask];
if (offset != 0)
{
return (FamilyCollection.CachedCharacterMetrics*)CheckedPointer.Probe(
offset,
sizeof(FamilyCollection.CachedCharacterMetrics)
);
}
}
}
return null;
}
///
/// Critical - constructs a CheckedPointer which is a critical operation
/// TreatAsSafe - the pointer and size fields used to construct the CheckedPointer are tracked and
/// the CheckedPointer itself is safe to use
///
private CheckedPointer CheckedPointer
{
[SecurityCritical,SecurityTreatAsSafe]
get
{
unsafe
{
return new CheckedPointer(_deviceFont, _sizeInBytes);
}
}
}
private CachedFontFamily _cachedFamily;
///
/// Critical - as this field is a pointer and therefore unsafe.
///
[SecurityCritical]
private unsafe FamilyCollection.CachedDeviceFont* _deviceFont;
///
/// Critical - used for bounds checking via CheckedPointer
///
[SecurityCritical]
private int _sizeInBytes;
}
#endregion
//-----------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
#region Private Fields
private CachedFontFamily _cachedFamily;
private IFontFamily _firstFontFamily;
#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
- RecordsAffectedEventArgs.cs
- PreviousTrackingServiceAttribute.cs
- SQlBooleanStorage.cs
- EntityDataSourceDataSelection.cs
- Empty.cs
- InvalidFilterCriteriaException.cs
- Errors.cs
- PrintPreviewDialog.cs
- Transform.cs
- HotCommands.cs
- HitTestDrawingContextWalker.cs
- ProcessHostMapPath.cs
- XPathBuilder.cs
- SecurityKeyIdentifier.cs
- PreProcessInputEventArgs.cs
- OracleConnection.cs
- XsltLoader.cs
- TextRangeEdit.cs
- SymbolType.cs
- HttpCacheVaryByContentEncodings.cs
- XmlNodeChangedEventManager.cs
- wgx_exports.cs
- LoginDesignerUtil.cs
- WaitHandleCannotBeOpenedException.cs
- SystemEvents.cs
- TerminateSequence.cs
- TransactionManagerProxy.cs
- UIElementHelper.cs
- WhereQueryOperator.cs
- SecurityKeyType.cs
- XmlSchemaComplexContentRestriction.cs
- BlurBitmapEffect.cs
- MLangCodePageEncoding.cs
- ColumnResizeUndoUnit.cs
- CollaborationHelperFunctions.cs
- DesignerDataConnection.cs
- CacheSection.cs
- NullToBooleanConverter.cs
- HttpFileCollection.cs
- RemotingServices.cs
- FileDialogPermission.cs
- WorkflowMarkupSerializationException.cs
- Simplifier.cs
- ColumnMapTranslator.cs
- SpecialFolderEnumConverter.cs
- PatternMatcher.cs
- ObjectCacheHost.cs
- IncrementalHitTester.cs
- InstanceHandle.cs
- GridItemCollection.cs
- InitializationEventAttribute.cs
- IndexedGlyphRun.cs
- ApplicationSecurityManager.cs
- NopReturnReader.cs
- PageContentCollection.cs
- X509CertificateInitiatorServiceCredential.cs
- HiddenFieldPageStatePersister.cs
- VerificationException.cs
- RunInstallerAttribute.cs
- Viewport3DAutomationPeer.cs
- ObjectAnimationBase.cs
- VectorAnimationUsingKeyFrames.cs
- DataSpaceManager.cs
- DataGridPagerStyle.cs
- Rule.cs
- TextBoxLine.cs
- SoapExtensionImporter.cs
- PrePrepareMethodAttribute.cs
- HTMLTagNameToTypeMapper.cs
- FixedSOMTableRow.cs
- SymmetricKey.cs
- AsyncPostBackTrigger.cs
- CuspData.cs
- InProcStateClientManager.cs
- ExtenderControl.cs
- MarshalByValueComponent.cs
- SrgsText.cs
- UnionCqlBlock.cs
- NativeRecognizer.cs
- EntityDataSourceDesignerHelper.cs
- Char.cs
- AutomationElementIdentifiers.cs
- ToolStripSplitButton.cs
- RoutedEventArgs.cs
- LocalValueEnumerator.cs
- DbDeleteCommandTree.cs
- WindowShowOrOpenTracker.cs
- TokenBasedSet.cs
- WebPartRestoreVerb.cs
- BuildResultCache.cs
- connectionpool.cs
- SharedPerformanceCounter.cs
- ServiceOperationParameter.cs
- CollectionCodeDomSerializer.cs
- SqlFacetAttribute.cs
- ZoomPercentageConverter.cs
- AmbientValueAttribute.cs
- SectionRecord.cs
- Utils.cs
- ObjectDesignerDataSourceView.cs