Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / MS / Internal / Shaping / PlacementWorkspace.cs / 1 / PlacementWorkspace.cs
//---------------------------------------------------------------------- // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation, 2005 // // File: PlacementWorkspace.cs // // Contents: support for all the shaping engines - all the local variable // for IShaper.GetGlyphPlacements and helpers are wrapped and // all unsafe pointer manipulation is done in this class. // // Created: 08-24-2005 by Nick Beal // //----------------------------------------------------------------------- using System; using System.Security; using System.Security.Permissions; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using MS.Internal.FontCache; using MS.Internal.FontFace; using System.Windows.Media; using System.Windows.Media.TextFormatting; using MS.Internal.PresentationCore; using MS.Utility; namespace MS.Internal.Shaping { ////// PlacementWorkspace provides safe interactions with the various buffers /// used by GetGlyphPlacement. /// ////// This struct is created every time a shaping engine's /// GetGlyphPlacement() method is called. /// /// All interaction on the unsafe buffers used for text characters and their related /// buffers (char map, cluster map, etc) done during IShaper.GetGlyphPlacement /// are done through this struct's accessors and methods. /// internal struct PlacementWorkspace { ////// PlacementWorkspace - initializer for GetGlyphPlacements currentRun /// ////// This function is always called from IShaper.GetGlyphPlacements. /// ////// Critical: This code accepts checked pointers and extracts /// unsafe pointers. /// [SecurityCritical] unsafe public PlacementWorkspace ( ShapingOptions shapingFlags, ShaperFontClient shaperFontClient, ShaperBuffers shaperBuffers, CheckedCharacterShapingPropertiesPointer charProperties, CheckedUShortPointer charClusterMap, int charCount, CheckedUShortPointer glyphIndices, CheckedGlyphShapingPropertiesPointer glyphProperties, int glyphCount, CheckedIntPointer glyphAdvances, CheckedGlyphOffsetPointer glyphOffsets, bool fontHasScriptGposFeatures, TextFlowDirection textFlowDirection) { Invariant.Assert(charCount > 0,"PlacementWorkspace: invalid char count"); // initialize our shaper buffers and set up our local references shaperBuffers.Initialize( (ushort)charCount, (ushort) glyphCount ); _charMap = shaperBuffers.CharMap; _glyphInfoList = shaperBuffers.GlyphInfoList; // keep track of our font client _fontClient = shaperFontClient; // positioning-specific members _pGlyphAdvances = glyphAdvances.Probe(0, glyphCount); _pGlyphOffsets = glyphOffsets.Probe(0, glyphCount); // initialize our various counts _nextGlyphIx = 0; _glyphCount = (ushort)glyphCount; // initialize our local booleans _inited = true; _finished = false; _fontHasScriptGposFeatures = fontHasScriptGposFeatures; _textFlowIsRTL = (textFlowDirection == TextFlowDirection.RTL); // unload the properties to our local representation DecompileShapingProperties( charProperties, charClusterMap, charCount, glyphIndices, glyphProperties, glyphCount ); } public UshortList CharMap { get { return _charMap; } } ////// CurrentGlyph - sets/gets current glyph /// public ushort CurrentGlyph { get { return _glyphInfoList.Glyphs[ _nextGlyphIx ]; } set { _glyphInfoList.Glyphs[ _nextGlyphIx ] = value; } } ////// CurrentGlyphAdvance - sets/gets current glyph advance /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphAdvance { [SecurityCritical] get { return _pGlyphAdvances[ _nextGlyphIx ]; } [SecurityCritical] set { _pGlyphAdvances [ _nextGlyphIx ] = value; } } ////// CurrentGlyphFlags - sets/gets current glyph flags /// public ushort CurrentGlyphFlags { get { return _glyphInfoList.GlyphFlags[ _nextGlyphIx ]; } } ////// CurrentGlyphIx - returns current glyphIx /// public ushort CurrentGlyphIx { get { return _nextGlyphIx; } } ////// CurrentGlyphOffsetDu - sets/gets current glyph offset.du /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphOffsetDu { [SecurityCritical] get { return _pGlyphOffsets[ _nextGlyphIx ].du; } [SecurityCritical] set { _pGlyphOffsets [ _nextGlyphIx ].du = value; } } ////// CurrentGlyphOffsetDv - sets/gets current glyph offset.du /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphOffsetDv { [SecurityCritical] get { return _pGlyphOffsets[ _nextGlyphIx ].dv; } [SecurityCritical] set { _pGlyphOffsets [ _nextGlyphIx ].dv = value; } } ////// Critical: This code is unsafe /// [SecurityCritical] unsafe private void DecompileShapingProperties ( CheckedCharacterShapingPropertiesPointer charProperties, CheckedUShortPointer charClusterMap, int charCount, CheckedUShortPointer glyphIndices, CheckedGlyphShapingPropertiesPointer glyphProperties, int glyphCount ) { Debug.Assert(charCount < ushort.MaxValue); Debug.Assert(glyphCount < ushort.MaxValue); ushort* pClusterMap = charClusterMap.Probe(0, charCount); CharacterShapingProperties* pCharProps = charProperties.Probe(0, charCount); ushort* pGlyphs = glyphIndices.Probe(0, glyphCount); GlyphShapingProperties* pGlyphProps = glyphProperties.Probe(0, glyphCount); ushort firstClusterGlyph = 0; ushort firstClusterChar = 0; ushort afterClusterGlyph; ushort afterClusterChar; // Fill glyphs array for(int i= 0; i < _glyphInfoList.Length; i++) { _glyphInfoList.Glyphs[i] = pGlyphs[i]; } // Compile shaping properties. Mapping is local to cluster, so doing every cluster as a whole for(int iChar = 1; iChar <= charCount; iChar++) { if (iChar < charCount && pClusterMap[iChar] == firstClusterGlyph) { //We are still inside same cluster continue; } // New cluster found. Get boundaries afterClusterChar = (ushort)iChar; afterClusterGlyph = (iChar < charCount) ? pClusterMap[iChar] : (ushort)glyphCount; //Cluster map should come valid from shaping engine Debug.Assert(firstClusterGlyph < afterClusterGlyph); for(int iClusterChar = firstClusterChar; iClusterChar < afterClusterChar; iClusterChar++) { byte localMap = pCharProps[iClusterChar].EngineReserved; // Clusters should be independent, otherwise they should be merged by shaping engine // Debug.Assert(localMap < (afterClusterGlyph - firstClusterGlyph)); CharMap[iClusterChar] = (ushort)(firstClusterGlyph + localMap); } for(int iClusterGlyph = firstClusterGlyph; iClusterGlyph < afterClusterGlyph; iClusterGlyph++) { ushort mappingStorage = pGlyphProps[iClusterGlyph].EngineReserved; int firstChar = mappingStorage & 0xFF; int ligaCount = mappingStorage >> 8; // Clusters should be independent, otherwise they should be merged by shaping engine // Debug.Assert(firstChar < (afterClusterChar - firstClusterChar)); _glyphInfoList.Glyphs[iClusterGlyph] = pGlyphs[iClusterGlyph]; _glyphInfoList.GlyphFlags[iClusterGlyph] = pGlyphProps[iClusterGlyph].GlyphFlags; _glyphInfoList.FirstChars[iClusterGlyph] = (ushort)(firstClusterChar + firstChar); _glyphInfoList.LigatureCounts[iClusterGlyph] = (ushort)ligaCount; } firstClusterChar = afterClusterChar; firstClusterGlyph = afterClusterGlyph; } } public ShaperFontClient FontClient { get { return _fontClient; } } ////// GlyphAdvances - returns glyph advance pointer /// ////// Critical - The method reads into an unvalidated unsafe array /// [SecurityCritical] unsafe public int * GlyphAdvances { [SecurityCritical] get { return _pGlyphAdvances; } } public GlyphInfoList GlyphInfoList { get { return _glyphInfoList; } } ////// GlyphOffsets - returns glyph offsets pointer /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public GlyphOffset * GlyphOffsets { [SecurityCritical] get { return _pGlyphOffsets; } } ////// PlacementWorkspace.InitializeGlyphInfoWidths - helper function for GetGlyphsPlacement. /// ////// This function populates the glyph run's advance and offset values /// with each glyph's default value (offsets always start zero'ed and /// the advance value comes from the font). /// Shapers that are using GPOS features in the font will call this method /// with scalingFactor set to zero which is interpretted as meaning, /// "no scaling now" (ie, font supports this script, so we're going to let /// the font set the advance). Such shaping engines will apply scaling after /// the after all the features have been applied by calling ScaleGlyphInfoWidths(). /// If a shaping engine has no GPOS features, then the caller (ie, /// GetGlyphsPlacement()) can pass in the appropriate scaling factor. /// ////// Critical: This code accesses critical methods. /// [SecurityCritical] public void InitializeGlyphInfoWidths () { Invariant.Assert (_glyphCount == _glyphInfoList.Length); GlyphTypeface fontFace = FontClient.FontFace; // Init the advance width for all the glyphs. while ( ToNextGlyph() ) { int glyphAdvance = 0; // All diacritics get a zero'ed advance width // All non-diacritics get advance width from the font if ((CurrentGlyphFlags & (ushort)GlyphFlags.ZeroWidth) == 0) { glyphAdvance = (int)Math.Round(fontFace.GetAdvanceWidthInDesignUnits(CurrentGlyph)); } // set the initial start values CurrentGlyphAdvance = glyphAdvance; CurrentGlyphOffsetDu = 0; CurrentGlyphOffsetDv = 0; } } ////// ToNextGlyph - increments index, returns false if finished /// public bool ToNextGlyph() { if (_inited) { // if this is the first character, don't increment the // index (so we can use this in a while (ToNextGlyph){...} // loop _inited = false; } else if (_nextGlyphIx + 1 < _glyphCount) { ++_nextGlyphIx; } else { _finished = true; } return !_finished; } ////// PlacementWorkspace.Reset - used to re-initial the ToNextGlyph mechanism /// (our iterator function, if you please!) /// public void Reset( ) { _nextGlyphIx = 0; _inited = true; _finished = false; } ////// PlacementWorkspace.ScaleGlyphInfoWidths - helper function for GetGlyphsPlacement. /// ////// This function scales the glyph run's advance and offset values. /// Shapers that are using GPOS features in the font will call this method /// after applying the font's GPOS feaures. /// ////// Critical: This code accesses critical methods. /// [SecurityCritical] public void ScaleGlyphInfoWidths( double scalingFactor ) { // Some fonts have assigned an advance value for the dicritic glyphs. // We have to zero the advance width on any diacritic, and add the value // to the du width. int cumulativeAdvance = 0; // go through all the glyphs and adjust any diacritics so that their advance // widths are zero'ed and the advance width is included in the offset du value. Reset(); while ( ToNextGlyph() ) { ushort currentGlyphFlags = CurrentGlyphFlags; int currentAdvanceWidth = CurrentGlyphAdvance; int currentOffsetDu = CurrentGlyphOffsetDu; // This is used for Arabic/Hebrew fonts that don't have GPOS support... if ( !_fontHasScriptGposFeatures ) { // for fonts without script GPOS support, if this is a suppressed ZWJ/ZWNJ // remove its advance width. if (( currentGlyphFlags & (ushort)GlyphFlags.ClusterStart ) != 0 ) { // for ZWJ/ZWNJ if ( FontClient.IsUnicodeSpaceGlyph(CurrentGlyph) && ( currentGlyphFlags & (ushort)GlyphFlags.ZeroWidth ) != 0) { // treat zwj as zero-width base if (_textFlowIsRTL) { // this adjustment is to "undo" the // adjustment made below for all RTL scripts. currentOffsetDu -= currentAdvanceWidth; } currentAdvanceWidth = 0; currentGlyphFlags = (ushort)GlyphFlags.ClusterStart; } } } if ( (currentGlyphFlags & (ushort)GlyphFlags.ZeroWidth) != 0 ) { // For zero-width glyphs, move any advance width to the offset // du value before clearing the advance width (we want to leave // zero-width glyphs with zero advance). Also keep track of // cumulative advance for adjacent diacritics, adding the // updated advance to the offset du for each diacritic. if (_textFlowIsRTL) { cumulativeAdvance += currentAdvanceWidth; currentOffsetDu -= cumulativeAdvance; } else { currentOffsetDu += cumulativeAdvance; cumulativeAdvance += currentAdvanceWidth; } currentAdvanceWidth = 0; } else { cumulativeAdvance = 0; } // update the current glyph's advance/offset... // Make sure there is no negative advance width after applying positioning. CurrentGlyphAdvance = Math.Max(0, currentAdvanceWidth); CurrentGlyphOffsetDu = currentOffsetDu; } // For RTL scripts, go through all the glyphs and adjust thd du value so that it // takes into account any change in the glyph's advance width due to feature application. // This adjustment is necessary for fixed pitch fonts (like Courier New) which has // a fixed advance width for ALL glyphs (including zero-width diacritics) and this // adjustment is necessary when kerning has been applied. // NOTE: This adjustment is unique to Avalon - the unmanaged code (Uniscribe) doesn't // need this adjustment. if (_textFlowIsRTL) { // go through all the glyphs and adjust any diacritics so that their advance // widths are zero'ed and the advance width is included in the offset du value. Reset(); while ( ToNextGlyph() ) { int originalAdvanceWidth = (int)Math.Round(FontClient.FontFace.GetAdvanceWidthInDesignUnits(CurrentGlyph)); int offsetAdjustment = CurrentGlyphAdvance - originalAdvanceWidth; if (offsetAdjustment != 0) // if du is zero, nothing to do { CurrentGlyphOffsetDu -= offsetAdjustment; } } } // Finally, go through all the glyphs and scale them. if (scalingFactor != 0) { Reset(); while ( ToNextGlyph() ) { CurrentGlyphAdvance = (int)Math.Round((CurrentGlyphAdvance * scalingFactor)); int currentOffsetDu = CurrentGlyphOffsetDu; CurrentGlyphOffsetDu = (int)Math.Round((_textFlowIsRTL ? -currentOffsetDu : currentOffsetDu)*scalingFactor); CurrentGlyphOffsetDv = (int)Math.Round(CurrentGlyphOffsetDv*scalingFactor); } } } private UshortList _charMap; private bool _finished; private ShaperFontClient _fontClient; private ushort _glyphCount; private GlyphInfoList _glyphInfoList; private bool _inited; private ushort _nextGlyphIx; private bool _fontHasScriptGposFeatures; private bool _textFlowIsRTL; [SecurityCritical] private unsafe int* _pGlyphAdvances; [SecurityCritical] private unsafe GlyphOffset * _pGlyphOffsets; // private ShaperBuffers _shaperWorkspace; } } // 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, 2005 // // File: PlacementWorkspace.cs // // Contents: support for all the shaping engines - all the local variable // for IShaper.GetGlyphPlacements and helpers are wrapped and // all unsafe pointer manipulation is done in this class. // // Created: 08-24-2005 by Nick Beal // //----------------------------------------------------------------------- using System; using System.Security; using System.Security.Permissions; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using MS.Internal.FontCache; using MS.Internal.FontFace; using System.Windows.Media; using System.Windows.Media.TextFormatting; using MS.Internal.PresentationCore; using MS.Utility; namespace MS.Internal.Shaping { ////// PlacementWorkspace provides safe interactions with the various buffers /// used by GetGlyphPlacement. /// ////// This struct is created every time a shaping engine's /// GetGlyphPlacement() method is called. /// /// All interaction on the unsafe buffers used for text characters and their related /// buffers (char map, cluster map, etc) done during IShaper.GetGlyphPlacement /// are done through this struct's accessors and methods. /// internal struct PlacementWorkspace { ////// PlacementWorkspace - initializer for GetGlyphPlacements currentRun /// ////// This function is always called from IShaper.GetGlyphPlacements. /// ////// Critical: This code accepts checked pointers and extracts /// unsafe pointers. /// [SecurityCritical] unsafe public PlacementWorkspace ( ShapingOptions shapingFlags, ShaperFontClient shaperFontClient, ShaperBuffers shaperBuffers, CheckedCharacterShapingPropertiesPointer charProperties, CheckedUShortPointer charClusterMap, int charCount, CheckedUShortPointer glyphIndices, CheckedGlyphShapingPropertiesPointer glyphProperties, int glyphCount, CheckedIntPointer glyphAdvances, CheckedGlyphOffsetPointer glyphOffsets, bool fontHasScriptGposFeatures, TextFlowDirection textFlowDirection) { Invariant.Assert(charCount > 0,"PlacementWorkspace: invalid char count"); // initialize our shaper buffers and set up our local references shaperBuffers.Initialize( (ushort)charCount, (ushort) glyphCount ); _charMap = shaperBuffers.CharMap; _glyphInfoList = shaperBuffers.GlyphInfoList; // keep track of our font client _fontClient = shaperFontClient; // positioning-specific members _pGlyphAdvances = glyphAdvances.Probe(0, glyphCount); _pGlyphOffsets = glyphOffsets.Probe(0, glyphCount); // initialize our various counts _nextGlyphIx = 0; _glyphCount = (ushort)glyphCount; // initialize our local booleans _inited = true; _finished = false; _fontHasScriptGposFeatures = fontHasScriptGposFeatures; _textFlowIsRTL = (textFlowDirection == TextFlowDirection.RTL); // unload the properties to our local representation DecompileShapingProperties( charProperties, charClusterMap, charCount, glyphIndices, glyphProperties, glyphCount ); } public UshortList CharMap { get { return _charMap; } } ////// CurrentGlyph - sets/gets current glyph /// public ushort CurrentGlyph { get { return _glyphInfoList.Glyphs[ _nextGlyphIx ]; } set { _glyphInfoList.Glyphs[ _nextGlyphIx ] = value; } } ////// CurrentGlyphAdvance - sets/gets current glyph advance /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphAdvance { [SecurityCritical] get { return _pGlyphAdvances[ _nextGlyphIx ]; } [SecurityCritical] set { _pGlyphAdvances [ _nextGlyphIx ] = value; } } ////// CurrentGlyphFlags - sets/gets current glyph flags /// public ushort CurrentGlyphFlags { get { return _glyphInfoList.GlyphFlags[ _nextGlyphIx ]; } } ////// CurrentGlyphIx - returns current glyphIx /// public ushort CurrentGlyphIx { get { return _nextGlyphIx; } } ////// CurrentGlyphOffsetDu - sets/gets current glyph offset.du /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphOffsetDu { [SecurityCritical] get { return _pGlyphOffsets[ _nextGlyphIx ].du; } [SecurityCritical] set { _pGlyphOffsets [ _nextGlyphIx ].du = value; } } ////// CurrentGlyphOffsetDv - sets/gets current glyph offset.du /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphOffsetDv { [SecurityCritical] get { return _pGlyphOffsets[ _nextGlyphIx ].dv; } [SecurityCritical] set { _pGlyphOffsets [ _nextGlyphIx ].dv = value; } } ////// Critical: This code is unsafe /// [SecurityCritical] unsafe private void DecompileShapingProperties ( CheckedCharacterShapingPropertiesPointer charProperties, CheckedUShortPointer charClusterMap, int charCount, CheckedUShortPointer glyphIndices, CheckedGlyphShapingPropertiesPointer glyphProperties, int glyphCount ) { Debug.Assert(charCount < ushort.MaxValue); Debug.Assert(glyphCount < ushort.MaxValue); ushort* pClusterMap = charClusterMap.Probe(0, charCount); CharacterShapingProperties* pCharProps = charProperties.Probe(0, charCount); ushort* pGlyphs = glyphIndices.Probe(0, glyphCount); GlyphShapingProperties* pGlyphProps = glyphProperties.Probe(0, glyphCount); ushort firstClusterGlyph = 0; ushort firstClusterChar = 0; ushort afterClusterGlyph; ushort afterClusterChar; // Fill glyphs array for(int i= 0; i < _glyphInfoList.Length; i++) { _glyphInfoList.Glyphs[i] = pGlyphs[i]; } // Compile shaping properties. Mapping is local to cluster, so doing every cluster as a whole for(int iChar = 1; iChar <= charCount; iChar++) { if (iChar < charCount && pClusterMap[iChar] == firstClusterGlyph) { //We are still inside same cluster continue; } // New cluster found. Get boundaries afterClusterChar = (ushort)iChar; afterClusterGlyph = (iChar < charCount) ? pClusterMap[iChar] : (ushort)glyphCount; //Cluster map should come valid from shaping engine Debug.Assert(firstClusterGlyph < afterClusterGlyph); for(int iClusterChar = firstClusterChar; iClusterChar < afterClusterChar; iClusterChar++) { byte localMap = pCharProps[iClusterChar].EngineReserved; // Clusters should be independent, otherwise they should be merged by shaping engine // Debug.Assert(localMap < (afterClusterGlyph - firstClusterGlyph)); CharMap[iClusterChar] = (ushort)(firstClusterGlyph + localMap); } for(int iClusterGlyph = firstClusterGlyph; iClusterGlyph < afterClusterGlyph; iClusterGlyph++) { ushort mappingStorage = pGlyphProps[iClusterGlyph].EngineReserved; int firstChar = mappingStorage & 0xFF; int ligaCount = mappingStorage >> 8; // Clusters should be independent, otherwise they should be merged by shaping engine // Debug.Assert(firstChar < (afterClusterChar - firstClusterChar)); _glyphInfoList.Glyphs[iClusterGlyph] = pGlyphs[iClusterGlyph]; _glyphInfoList.GlyphFlags[iClusterGlyph] = pGlyphProps[iClusterGlyph].GlyphFlags; _glyphInfoList.FirstChars[iClusterGlyph] = (ushort)(firstClusterChar + firstChar); _glyphInfoList.LigatureCounts[iClusterGlyph] = (ushort)ligaCount; } firstClusterChar = afterClusterChar; firstClusterGlyph = afterClusterGlyph; } } public ShaperFontClient FontClient { get { return _fontClient; } } ////// GlyphAdvances - returns glyph advance pointer /// ////// Critical - The method reads into an unvalidated unsafe array /// [SecurityCritical] unsafe public int * GlyphAdvances { [SecurityCritical] get { return _pGlyphAdvances; } } public GlyphInfoList GlyphInfoList { get { return _glyphInfoList; } } ////// GlyphOffsets - returns glyph offsets pointer /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public GlyphOffset * GlyphOffsets { [SecurityCritical] get { return _pGlyphOffsets; } } ////// PlacementWorkspace.InitializeGlyphInfoWidths - helper function for GetGlyphsPlacement. /// ////// This function populates the glyph run's advance and offset values /// with each glyph's default value (offsets always start zero'ed and /// the advance value comes from the font). /// Shapers that are using GPOS features in the font will call this method /// with scalingFactor set to zero which is interpretted as meaning, /// "no scaling now" (ie, font supports this script, so we're going to let /// the font set the advance). Such shaping engines will apply scaling after /// the after all the features have been applied by calling ScaleGlyphInfoWidths(). /// If a shaping engine has no GPOS features, then the caller (ie, /// GetGlyphsPlacement()) can pass in the appropriate scaling factor. /// ////// Critical: This code accesses critical methods. /// [SecurityCritical] public void InitializeGlyphInfoWidths () { Invariant.Assert (_glyphCount == _glyphInfoList.Length); GlyphTypeface fontFace = FontClient.FontFace; // Init the advance width for all the glyphs. while ( ToNextGlyph() ) { int glyphAdvance = 0; // All diacritics get a zero'ed advance width // All non-diacritics get advance width from the font if ((CurrentGlyphFlags & (ushort)GlyphFlags.ZeroWidth) == 0) { glyphAdvance = (int)Math.Round(fontFace.GetAdvanceWidthInDesignUnits(CurrentGlyph)); } // set the initial start values CurrentGlyphAdvance = glyphAdvance; CurrentGlyphOffsetDu = 0; CurrentGlyphOffsetDv = 0; } } ////// ToNextGlyph - increments index, returns false if finished /// public bool ToNextGlyph() { if (_inited) { // if this is the first character, don't increment the // index (so we can use this in a while (ToNextGlyph){...} // loop _inited = false; } else if (_nextGlyphIx + 1 < _glyphCount) { ++_nextGlyphIx; } else { _finished = true; } return !_finished; } ////// PlacementWorkspace.Reset - used to re-initial the ToNextGlyph mechanism /// (our iterator function, if you please!) /// public void Reset( ) { _nextGlyphIx = 0; _inited = true; _finished = false; } ////// PlacementWorkspace.ScaleGlyphInfoWidths - helper function for GetGlyphsPlacement. /// ////// This function scales the glyph run's advance and offset values. /// Shapers that are using GPOS features in the font will call this method /// after applying the font's GPOS feaures. /// ////// Critical: This code accesses critical methods. /// [SecurityCritical] public void ScaleGlyphInfoWidths( double scalingFactor ) { // Some fonts have assigned an advance value for the dicritic glyphs. // We have to zero the advance width on any diacritic, and add the value // to the du width. int cumulativeAdvance = 0; // go through all the glyphs and adjust any diacritics so that their advance // widths are zero'ed and the advance width is included in the offset du value. Reset(); while ( ToNextGlyph() ) { ushort currentGlyphFlags = CurrentGlyphFlags; int currentAdvanceWidth = CurrentGlyphAdvance; int currentOffsetDu = CurrentGlyphOffsetDu; // This is used for Arabic/Hebrew fonts that don't have GPOS support... if ( !_fontHasScriptGposFeatures ) { // for fonts without script GPOS support, if this is a suppressed ZWJ/ZWNJ // remove its advance width. if (( currentGlyphFlags & (ushort)GlyphFlags.ClusterStart ) != 0 ) { // for ZWJ/ZWNJ if ( FontClient.IsUnicodeSpaceGlyph(CurrentGlyph) && ( currentGlyphFlags & (ushort)GlyphFlags.ZeroWidth ) != 0) { // treat zwj as zero-width base if (_textFlowIsRTL) { // this adjustment is to "undo" the // adjustment made below for all RTL scripts. currentOffsetDu -= currentAdvanceWidth; } currentAdvanceWidth = 0; currentGlyphFlags = (ushort)GlyphFlags.ClusterStart; } } } if ( (currentGlyphFlags & (ushort)GlyphFlags.ZeroWidth) != 0 ) { // For zero-width glyphs, move any advance width to the offset // du value before clearing the advance width (we want to leave // zero-width glyphs with zero advance). Also keep track of // cumulative advance for adjacent diacritics, adding the // updated advance to the offset du for each diacritic. if (_textFlowIsRTL) { cumulativeAdvance += currentAdvanceWidth; currentOffsetDu -= cumulativeAdvance; } else { currentOffsetDu += cumulativeAdvance; cumulativeAdvance += currentAdvanceWidth; } currentAdvanceWidth = 0; } else { cumulativeAdvance = 0; } // update the current glyph's advance/offset... // Make sure there is no negative advance width after applying positioning. CurrentGlyphAdvance = Math.Max(0, currentAdvanceWidth); CurrentGlyphOffsetDu = currentOffsetDu; } // For RTL scripts, go through all the glyphs and adjust thd du value so that it // takes into account any change in the glyph's advance width due to feature application. // This adjustment is necessary for fixed pitch fonts (like Courier New) which has // a fixed advance width for ALL glyphs (including zero-width diacritics) and this // adjustment is necessary when kerning has been applied. // NOTE: This adjustment is unique to Avalon - the unmanaged code (Uniscribe) doesn't // need this adjustment. if (_textFlowIsRTL) { // go through all the glyphs and adjust any diacritics so that their advance // widths are zero'ed and the advance width is included in the offset du value. Reset(); while ( ToNextGlyph() ) { int originalAdvanceWidth = (int)Math.Round(FontClient.FontFace.GetAdvanceWidthInDesignUnits(CurrentGlyph)); int offsetAdjustment = CurrentGlyphAdvance - originalAdvanceWidth; if (offsetAdjustment != 0) // if du is zero, nothing to do { CurrentGlyphOffsetDu -= offsetAdjustment; } } } // Finally, go through all the glyphs and scale them. if (scalingFactor != 0) { Reset(); while ( ToNextGlyph() ) { CurrentGlyphAdvance = (int)Math.Round((CurrentGlyphAdvance * scalingFactor)); int currentOffsetDu = CurrentGlyphOffsetDu; CurrentGlyphOffsetDu = (int)Math.Round((_textFlowIsRTL ? -currentOffsetDu : currentOffsetDu)*scalingFactor); CurrentGlyphOffsetDv = (int)Math.Round(CurrentGlyphOffsetDv*scalingFactor); } } } private UshortList _charMap; private bool _finished; private ShaperFontClient _fontClient; private ushort _glyphCount; private GlyphInfoList _glyphInfoList; private bool _inited; private ushort _nextGlyphIx; private bool _fontHasScriptGposFeatures; private bool _textFlowIsRTL; [SecurityCritical] private unsafe int* _pGlyphAdvances; [SecurityCritical] private unsafe GlyphOffset * _pGlyphOffsets; // private ShaperBuffers _shaperWorkspace; } } // 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
- WebPartTransformerAttribute.cs
- XmlCustomFormatter.cs
- ExtensionsSection.cs
- GroupBoxRenderer.cs
- DesignerWithHeader.cs
- ToolBar.cs
- DeflateEmulationStream.cs
- DataService.cs
- ToolboxBitmapAttribute.cs
- CompilerTypeWithParams.cs
- ErrorWrapper.cs
- __ConsoleStream.cs
- MultiBindingExpression.cs
- WebBrowser.cs
- ApplicationFileParser.cs
- _BufferOffsetSize.cs
- TreeViewDataItemAutomationPeer.cs
- PointConverter.cs
- SizeConverter.cs
- shaperfactoryquerycacheentry.cs
- EraserBehavior.cs
- ScrollBar.cs
- FileSystemInfo.cs
- Serializer.cs
- PersonalizablePropertyEntry.cs
- NamespaceDisplay.xaml.cs
- ErrorWebPart.cs
- XmlDocumentViewSchema.cs
- AssemblyResourceLoader.cs
- HttpListenerRequest.cs
- CryptoConfig.cs
- FormatConvertedBitmap.cs
- DrawingDrawingContext.cs
- OleDbParameter.cs
- DocumentGrid.cs
- ServiceDocument.cs
- BreadCrumbTextConverter.cs
- XmlAggregates.cs
- MetabaseSettings.cs
- streamingZipPartStream.cs
- ListView.cs
- XmlILOptimizerVisitor.cs
- WebPartManager.cs
- XmlBoundElement.cs
- PinnedBufferMemoryStream.cs
- ClientScriptItem.cs
- DetailsViewDeletedEventArgs.cs
- DictionaryBase.cs
- HtmlButton.cs
- OleDbPermission.cs
- EncoderFallback.cs
- KeyedHashAlgorithm.cs
- IncrementalHitTester.cs
- GeneralTransform3D.cs
- ApplicationServicesHostFactory.cs
- AccessedThroughPropertyAttribute.cs
- CryptographicAttribute.cs
- StylusDownEventArgs.cs
- LeaseManager.cs
- OpenFileDialog.cs
- DataBoundControlAdapter.cs
- WmlSelectionListAdapter.cs
- initElementDictionary.cs
- BitmapFrame.cs
- RightsManagementPermission.cs
- SystemException.cs
- TimeSpanSecondsConverter.cs
- ObjectDataSourceFilteringEventArgs.cs
- PrintPreviewDialog.cs
- BufferedWebEventProvider.cs
- StyleHelper.cs
- HandleRef.cs
- DataSetUtil.cs
- SafePointer.cs
- FrameDimension.cs
- StrokeFIndices.cs
- TransformPattern.cs
- IntSecurity.cs
- RelativeSource.cs
- CommandConverter.cs
- FontInfo.cs
- DbConvert.cs
- LongValidatorAttribute.cs
- ConstrainedDataObject.cs
- RsaKeyIdentifierClause.cs
- UrlPath.cs
- UrlMapping.cs
- EntityParameterCollection.cs
- FormsAuthenticationUser.cs
- EntityDataSourceUtil.cs
- DataGridViewCellValueEventArgs.cs
- ScrollChrome.cs
- DataContractAttribute.cs
- TransformerInfo.cs
- PrintPreviewDialog.cs
- ToolboxItemWrapper.cs
- LexicalChunk.cs
- CurrentTimeZone.cs
- AutoGeneratedField.cs
- FormViewInsertedEventArgs.cs