Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / MS / Internal / FontFace / CachedCompositeFamily.cs / 1 / CachedCompositeFamily.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: The CachedCompositeFamily class // // History: // 08/01/2003 : [....] - 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
- XmlTextAttribute.cs
- Solver.cs
- XmlComplianceUtil.cs
- DomainUpDown.cs
- TablePattern.cs
- METAHEADER.cs
- SecurityElement.cs
- RowToFieldTransformer.cs
- RegexTree.cs
- SettingsPropertyWrongTypeException.cs
- Emitter.cs
- SqlRowUpdatedEvent.cs
- SendSecurityHeaderElement.cs
- ThreadStateException.cs
- CssClassPropertyAttribute.cs
- TextAutomationPeer.cs
- LocalizabilityAttribute.cs
- Transform.cs
- DocumentScope.cs
- FormattedTextSymbols.cs
- ElementNotEnabledException.cs
- isolationinterop.cs
- ReferenceEqualityComparer.cs
- HTMLTextWriter.cs
- LockCookie.cs
- AssemblyAssociatedContentFileAttribute.cs
- Panel.cs
- ViewKeyConstraint.cs
- FixedSOMContainer.cs
- CellPartitioner.cs
- AudioStateChangedEventArgs.cs
- ProtectedConfiguration.cs
- XsdDateTime.cs
- IPAddressCollection.cs
- XamlFigureLengthSerializer.cs
- SymmetricKey.cs
- _SSPISessionCache.cs
- documentsequencetextview.cs
- CorrelationToken.cs
- ClaimTypes.cs
- CacheMode.cs
- TypeUsageBuilder.cs
- XmlSchemaSet.cs
- WebScriptMetadataFormatter.cs
- AssemblyName.cs
- MatrixTransform3D.cs
- ScriptDescriptor.cs
- LocationInfo.cs
- ReaderContextStackData.cs
- CodeSnippetCompileUnit.cs
- TaiwanLunisolarCalendar.cs
- DateTimeConstantAttribute.cs
- ImportedPolicyConversionContext.cs
- PageAdapter.cs
- MetadataItemEmitter.cs
- RegexInterpreter.cs
- ForceCopyBuildProvider.cs
- RuntimeConfig.cs
- Range.cs
- DesignerListAdapter.cs
- PageThemeParser.cs
- ResXDataNode.cs
- PageRequestManager.cs
- VirtualPath.cs
- ProcessThread.cs
- MSAAWinEventWrap.cs
- RectIndependentAnimationStorage.cs
- Win32PrintDialog.cs
- PropertyRecord.cs
- SocketElement.cs
- BinaryObjectInfo.cs
- XmlILAnnotation.cs
- TextServicesManager.cs
- XslCompiledTransform.cs
- CheckBox.cs
- TimeSpanValidator.cs
- ViewRendering.cs
- SafeProcessHandle.cs
- DesignerForm.cs
- RefreshEventArgs.cs
- LinkedResource.cs
- ItemsPanelTemplate.cs
- FontWeights.cs
- SqlUtils.cs
- EncryptedData.cs
- DataMisalignedException.cs
- WinFormsSpinner.cs
- PermissionSet.cs
- AddressAccessDeniedException.cs
- XmlSchemaComplexContentRestriction.cs
- WebServiceFault.cs
- ListDictionaryInternal.cs
- _BasicClient.cs
- X509Certificate.cs
- StrokeCollectionDefaultValueFactory.cs
- PerformanceCounterManager.cs
- CollectionViewProxy.cs
- xsdvalidator.cs
- ModelFactory.cs
- UserControlCodeDomTreeGenerator.cs