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
- File.cs
- SettingsPropertyValueCollection.cs
- CqlWriter.cs
- SettingsProviderCollection.cs
- CodeMethodInvokeExpression.cs
- SimpleHandlerBuildProvider.cs
- FlowDocumentPaginator.cs
- TextBlockAutomationPeer.cs
- CompositeFontFamily.cs
- MatrixAnimationUsingKeyFrames.cs
- TreeNodeCollection.cs
- UIElementIsland.cs
- ApplicationFileParser.cs
- ToolboxItemLoader.cs
- IisTraceWebEventProvider.cs
- EventLogException.cs
- HandlerFactoryCache.cs
- CodeStatement.cs
- CollectionContainer.cs
- FixedHyperLink.cs
- EditingMode.cs
- MemberHolder.cs
- DeploymentSectionCache.cs
- HtmlControlPersistable.cs
- ManualResetEvent.cs
- HandoffBehavior.cs
- DataBindingExpressionBuilder.cs
- GridViewRowPresenter.cs
- Int32AnimationBase.cs
- SchemaCollectionCompiler.cs
- DataObjectPastingEventArgs.cs
- LayoutEditorPart.cs
- ContextMenuAutomationPeer.cs
- _KerberosClient.cs
- XmlHierarchicalDataSourceView.cs
- TypeHelper.cs
- CodeAttributeDeclarationCollection.cs
- WebConvert.cs
- COM2EnumConverter.cs
- Tablet.cs
- Ticks.cs
- LayoutEvent.cs
- OrderedDictionary.cs
- DataGridViewButtonCell.cs
- ContractValidationHelper.cs
- WebPartExportVerb.cs
- __FastResourceComparer.cs
- TimelineGroup.cs
- FileIOPermission.cs
- SmiEventSink_DeferedProcessing.cs
- TypeUsage.cs
- ToolStripPanel.cs
- NetNamedPipeBinding.cs
- UnicastIPAddressInformationCollection.cs
- SafeUserTokenHandle.cs
- CircleHotSpot.cs
- WindowsGrip.cs
- Math.cs
- WindowsListBox.cs
- DrawingBrush.cs
- ConfigurationValues.cs
- ContextStaticAttribute.cs
- HighlightVisual.cs
- KnownTypeAttribute.cs
- CorrelationManager.cs
- EntityDataSourceWrapper.cs
- AppearanceEditorPart.cs
- UTF32Encoding.cs
- CompilerWrapper.cs
- DelegatingTypeDescriptionProvider.cs
- XmlSchemaChoice.cs
- ApplicationManager.cs
- CustomTypeDescriptor.cs
- recordstatescratchpad.cs
- Drawing.cs
- CapabilitiesRule.cs
- RegionData.cs
- IsolatedStoragePermission.cs
- MergeFilterQuery.cs
- EditingMode.cs
- DesignerRegionMouseEventArgs.cs
- AppDomainAttributes.cs
- updatecommandorderer.cs
- LocationUpdates.cs
- UnconditionalPolicy.cs
- TemplateControlParser.cs
- __Filters.cs
- TableItemPatternIdentifiers.cs
- DataGrid.cs
- MenuCommands.cs
- MenuEventArgs.cs
- SectionInput.cs
- GrowingArray.cs
- ProcessHostServerConfig.cs
- TypePropertyEditor.cs
- AuthenticationModuleElement.cs
- KeyTimeConverter.cs
- BaseAsyncResult.cs
- DataMemberListEditor.cs
- FormConverter.cs