Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / MS / Internal / 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
- BitmapEffectInputData.cs
- HostAdapter.cs
- TextEffectCollection.cs
- FontFamilyConverter.cs
- KeysConverter.cs
- DbConnectionStringBuilder.cs
- DefaultHttpHandler.cs
- DbParameterHelper.cs
- QueryExpr.cs
- DataTableNewRowEvent.cs
- LogExtent.cs
- UnSafeCharBuffer.cs
- Convert.cs
- XmlRawWriter.cs
- AutoCompleteStringCollection.cs
- TreeViewImageGenerator.cs
- _BufferOffsetSize.cs
- CriticalFinalizerObject.cs
- RoleGroupCollection.cs
- SerializationInfo.cs
- JoinCqlBlock.cs
- ListView.cs
- XsltSettings.cs
- FocusChangedEventArgs.cs
- XmlCountingReader.cs
- SoapAttributeAttribute.cs
- TextBounds.cs
- QueryCursorEventArgs.cs
- ProgressPage.cs
- XPathDocument.cs
- CapacityStreamGeometryContext.cs
- TypedReference.cs
- WsdlParser.cs
- FilterableAttribute.cs
- PreloadedPackages.cs
- ListView.cs
- SequentialOutput.cs
- ErrorHandler.cs
- ZipIOBlockManager.cs
- CqlGenerator.cs
- DBParameter.cs
- HostingPreferredMapPath.cs
- DesignerCategoryAttribute.cs
- FloaterParaClient.cs
- TimeoutStream.cs
- InheritanceUI.cs
- OleDbReferenceCollection.cs
- ProfileSettingsCollection.cs
- ResXFileRef.cs
- TemplateControl.cs
- MimeParameterWriter.cs
- MemberListBinding.cs
- GenericTransactionFlowAttribute.cs
- PermissionSet.cs
- DependencyObject.cs
- SetterBaseCollection.cs
- Profiler.cs
- WebPartConnection.cs
- WindowsSecurityToken.cs
- FloaterBaseParaClient.cs
- DataGridTableCollection.cs
- SizeValueSerializer.cs
- SoapAttributeOverrides.cs
- HttpRequestTraceRecord.cs
- Geometry3D.cs
- SymbolPair.cs
- CodePageUtils.cs
- FormViewRow.cs
- VectorCollectionConverter.cs
- CollectionEditorDialog.cs
- RelOps.cs
- RowsCopiedEventArgs.cs
- Grid.cs
- Animatable.cs
- XmlNode.cs
- BroadcastEventHelper.cs
- ExpressionParser.cs
- IntegerValidatorAttribute.cs
- PropertyGeneratedEventArgs.cs
- UpdateManifestForBrowserApplication.cs
- IconHelper.cs
- EditBehavior.cs
- xml.cs
- SharedUtils.cs
- MeasureItemEvent.cs
- WebResourceUtil.cs
- XmlValidatingReaderImpl.cs
- CollectionView.cs
- PlatformCulture.cs
- DropSource.cs
- ServiceModelEnumValidator.cs
- MailWebEventProvider.cs
- FileStream.cs
- XmlElement.cs
- PrtTicket_Public_Simple.cs
- OutputCacheSection.cs
- OracleCommandSet.cs
- TreeNodeBinding.cs
- LocatorPart.cs
- IfAction.cs