Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / 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 /// IDictionaryIFontFamily.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; } } ICollectionIFontFamily.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 /// IDictionaryIFontFamily.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; } } ICollectionIFontFamily.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
- DataFormats.cs
- SelectionPattern.cs
- ResXResourceReader.cs
- NativeWindow.cs
- CharacterString.cs
- HttpCachePolicy.cs
- Attachment.cs
- RectValueSerializer.cs
- LinqDataSourceHelper.cs
- Baml6ConstructorInfo.cs
- SectionInput.cs
- AggregateNode.cs
- TextElementEnumerator.cs
- WebScriptServiceHostFactory.cs
- ColumnMapVisitor.cs
- DesignerActionGlyph.cs
- TextElementEnumerator.cs
- PropertyPathConverter.cs
- ModelVisual3D.cs
- PreloadHost.cs
- FontEmbeddingManager.cs
- SafeArrayRankMismatchException.cs
- SerializerProvider.cs
- ActivityScheduledQuery.cs
- ArrangedElement.cs
- webeventbuffer.cs
- oledbmetadatacolumnnames.cs
- DiscriminatorMap.cs
- PartialCachingAttribute.cs
- Documentation.cs
- State.cs
- UserControl.cs
- VectorCollectionConverter.cs
- EntitySqlQueryCacheKey.cs
- CommentEmitter.cs
- PageRanges.cs
- ConversionContext.cs
- Rotation3D.cs
- Documentation.cs
- AppDomain.cs
- CheckableControlBaseAdapter.cs
- ToolboxItemCollection.cs
- ClientBuildManagerCallback.cs
- glyphs.cs
- RegionData.cs
- Lock.cs
- ClosureBinding.cs
- COM2IDispatchConverter.cs
- ConsoleCancelEventArgs.cs
- TemplateBamlTreeBuilder.cs
- XmlSchemaAnnotation.cs
- CodeCatchClause.cs
- TextPointerBase.cs
- SafeEventLogWriteHandle.cs
- TranslateTransform.cs
- WorkflowTimerService.cs
- SQLDecimalStorage.cs
- HttpContextWrapper.cs
- QuerySettings.cs
- RegistrationServices.cs
- InternalsVisibleToAttribute.cs
- KnownIds.cs
- HwndMouseInputProvider.cs
- CreatingCookieEventArgs.cs
- TouchesOverProperty.cs
- TouchDevice.cs
- CopyNodeSetAction.cs
- EntityDataSourceContainerNameConverter.cs
- DragStartedEventArgs.cs
- BitmapPalette.cs
- MachineKeyValidationConverter.cs
- PeerPresenceInfo.cs
- StringPropertyBuilder.cs
- GridEntry.cs
- RawStylusActions.cs
- DeviceContexts.cs
- IIS7WorkerRequest.cs
- WebServiceErrorEvent.cs
- SHA256Cng.cs
- CleanUpVirtualizedItemEventArgs.cs
- PointLight.cs
- FixUp.cs
- InstanceNotReadyException.cs
- PenLineCapValidation.cs
- HttpChannelHelper.cs
- ByteStorage.cs
- FrameworkContentElement.cs
- dbenumerator.cs
- XmlSchemaAll.cs
- DesignTimeType.cs
- Translator.cs
- EntityDataSourceDataSelectionPanel.cs
- input.cs
- WSSecureConversation.cs
- StickyNote.cs
- HtmlDocument.cs
- CreateUserWizardAutoFormat.cs
- IsolatedStorageFileStream.cs
- TriggerAction.cs
- LocalFileSettingsProvider.cs