baseshape.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / MS / Internal / Shaping / baseshape.cs / 1 / baseshape.cs

                            //---------------------------------------------------------------------- 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2001
// 
//  File:      BaseShape.cs
// 
//  Contents:  base shaping engine classes 
//
//  Created:   10-22-2003 
//
//-----------------------------------------------------------------------

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
{

    ///  
    /// Base implementation of IShaper
    ///  
    internal class BaseShaper : IShaper 
    {
        protected ShaperBuffers _shaperBuffers; 
        protected TextFlowDirection _textFlowDirection;
        protected bool _forceDiacriticsToZeroWidth;

        internal BaseShaper () 
        {
            // the shaper's persistent buffers will be created at the first InitializeFontClient 
            // call. 
            _shaperBuffers = null;
 
            // default text flow direction is left-to-right.  Some shapers
            // (e.g., Arabic, Hebrew) will need to override this
            _textFlowDirection = TextFlowDirection.LTR;
 
            // Most shapers don't want diacritics to have any width, so this needn't be changed.
            // Overriding this to false will cause the GetGlyphs helper, PopulateClusterMap to 
            // not flag diacritics as zero-width 
            _forceDiacriticsToZeroWidth = true;
        } 

        // required substitution features. The optional ligature features are not applied
        // if the shaper client passes in a custom set of features to apply
        // 
        private static readonly Feature[] _defaultSubstitutionFeatures =  new Feature[]
        { 
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.LocalizedForms,1), 
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.GlyphCompositionDecomposition,1),
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.RequiredLigatures,1), 
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.ContextualAlternates,1),
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.StandardLigatures,1),   // optional
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.ContextualLigatures,1)  // optional
        }; 
        private const int _countOfInhibitableLigatureFeatures = 2;
 
        // 
        //
        protected static readonly Feature[] _defaultPositioningFeatures = new Feature[] 
        {
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.MarkPositioning,1),
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.MarktoMarkPositioning,1),
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.Kerning,1) 
        };
 
        private bool _isTracingEnabled = false; 
        protected void RecordTraceEvent (byte eventType, String traceString )
        { 
                if (_isTracingEnabled)

                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.GENERICSTRINGGUID), 
                                                        eventType,
                                                        traceString); 
                } 
        }
 
        /// 
        ///     BaseShaper.ApplyFinalSubstitutionFeatures - default implementation of the GetGlyphs() helper function.
        /// 
        /// shaping currentRun 
        /// Set of gsub features to be applied to the unicode run.
        /// result of applying features 
        ///  
        /// Critical - this method calls unsafe methods.
        ///  
        [SecurityCritical]
        protected virtual OpenTypeLayoutResult ApplyFinalSubstitutionFeatures(
                                                            ref ShapingWorkspace currentRun,
                                                            FeatureSet       featureSet  ) 
        {
            return OpenTypeLayoutResult.Success; 
        } 

        ///  
        ///    BaseShaper.ApplyPositioningFeatures - default implementation of the GetGlyphPlacement helper.
        ///     This method goes through a list of glyphs and fills the glyph advances and offsets
        ///     arrays.
        ///  
        /// 
        ///     Most shape engines will override this method.  If not overridden, this implementation 
        ///     will attempt to apply the featureSet passed in, if the current font provides OpenType 
        ///     GPOS support for the current script.
        ///  
        /// the wrapper for glyph advances, offset arrays
        /// metrics for all the positioning features
        /// Set of gpos features to be applied to the unicode run.
        /// result of applying features 
        /// 
        /// Critical - this method calls unsafe methods. 
        ///  
        [SecurityCritical]
        protected virtual OpenTypeLayoutResult ApplyPositioningFeatures( 
                ref PlacementWorkspace   placementInfo,
                ref LayoutMetrics   layoutMetrics,
                FeatureSet          featureSet )
        { 
            ShaperFontClient fontClient = placementInfo.FontClient;
            OpenTypeLayoutResult layoutResult; 
 
            if (featureSet != null && featureSet.FeatureCount > 0)
            { 
                layoutResult = fontClient.PositionGlyphs(
                            ref placementInfo,
                            ref layoutMetrics,
                            featureSet.Features,     // In: List of features to apply 
                            featureSet.FeatureCount );
            } 
            else 
            {
                layoutResult = fontClient.PositionGlyphs( 
                            ref placementInfo,
                            ref layoutMetrics,
                            _defaultPositioningFeatures,     // In: List of features to apply
                            _defaultPositioningFeatures.Length ); 
            }
 
            return layoutResult; 
        }
 
        /// 
        ///     BaseShaper.ApplySubstitutionFeatures - default implementation of the GetGlyphs() helper function.
        ///                     This is called after every cluster (or whatever shaping "chunk" is applicable for
        ///                     the script shaper). 
        /// 
        /// shaping currentRun 
        /// Set of gsub features to be applied to the unicode run. 
        /// result of applying features
        ///  
        /// Critical - this method calls unsafe methods.
        /// 
        [SecurityCritical]
        protected virtual OpenTypeLayoutResult ApplySubstitutionFeatures( 
                                                        ref ShapingWorkspace currentRun,
                                                        FeatureSet       featureSet  ) 
        { 

            ShaperFontClient fontClient = currentRun.FontClient; 
            OpenTypeLayoutResult layoutResult;

            if (featureSet != null && featureSet.FeatureCount > 0)
            { 
                layoutResult = fontClient.SubstituteGlyphs(
                            ref currentRun, 
                            featureSet.Features,     // In: List of features to apply 
                            featureSet.FeatureCount );
            } 
            else
            {
                int featureCount = _defaultSubstitutionFeatures.Length;
                if (currentRun.AreLigaturesInhibited) 
                {
                    // no ligature features to be applied (except required) if inhibited 
                    // flag is set, or if featureSet exists... 
                    featureCount -= _countOfInhibitableLigatureFeatures;
                } 

                layoutResult = fontClient.SubstituteGlyphs(
                            ref currentRun,
                            _defaultSubstitutionFeatures,     // In: List of features to apply 
                            featureCount);
            } 
 
            return layoutResult;
        } 

        /// 
        ///     BaseShaper.GetGlyphs - default implementation of the IShaper method.
        ///     This method returns a list of glyphs, a character-to-glyph map, and 
        ///     a cluster map.
        ///  
        ///  
        ///     Most shape engines will not override this method, but rather its helper
        ///     function, GetGlyphsList.  This base implementation will call GetGlyphsList 
        ///     if the font supports OpenType GSUB features.
        ///     The shapers in DefaultShape.cs do implement override for this function.
        /// 
        /// Text item 
        /// text culture info
        /// font face layout info 
        /// OpenType features 
        /// Controlling flags
        /// Shaping engine font specific data 
        /// Incoming text
        /// text length
        /// properties of text
        /// Character to glyph map 
        /// Result glyph info array
        /// glyph properties array 
        /// number of glyphs produced 
        /// true if succeeds
        ///  
        /// Critical - this method calls unsafe methods.
        /// Safe     - this method returns glyph indices and shaping properties which are safe.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        public bool GetGlyphs(
            Item                                        item, 
            CultureInfo                                 culture, 
            GlyphTypeface                               fontFace,
            FeatureSet                                  featureSet, 
            ShapingOptions                              shapingFlags,

            object                                      shapeFontInfo,
 
            CheckedCharPointer                          chars,
            int                                         charCount, 
 
            CheckedCharacterShapingPropertiesPointer    charProperties,
            CheckedUShortPointer                        charClusterMap, 

            out ushort[]                                glyphIndices,
            out GlyphShapingProperties[]                glyphProperties,
            out int                                     glyphCount 
            )
        { 
 
            _isTracingEnabled =
                EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); 

            RecordTraceEvent(MS.Utility.EventType.StartEvent,
                            "BaseShaper GetGlyphs Start");
            RecordTraceEvent(MS.Utility.EventType.StartEvent, 
                            "BaseShaper Init Start");
 
            if (charCount <= 0) 
            {
                glyphCount = 0; 
                glyphIndices = null;
                glyphProperties = null;
                return false;
            } 

            ShaperFontClient fontClient = InitializeFontClient( item, 
                                                            culture, 
                                                            fontFace,
                                                            OpenTypeTags.GSUB, 
                                                            shapeFontInfo);

            Invariant.Assert(_shaperBuffers != null && fontClient != null);
 
            // initialize wrapper for managing the unsafe arrays.
            ShapingWorkspace currentRun = new ShapingWorkspace( item, 
                                                                shapingFlags, 

                                                                fontClient, 
                                                                _shaperBuffers,

                                                                chars,
                                                                charCount, 

                                                                charProperties, 
                                                                charClusterMap); 

 
            OpenTypeLayoutResult layoutResult;
            RecordTraceEvent(MS.Utility.EventType.EndEvent,
                            "BaseShaper Init End");
 

            // get character shapes and the glyphs... 
            while (!currentRun.IsFinished) 
            {
                int glyphsCount = GetGlyphs ( ref currentRun, item ); 
                Invariant.Assert( glyphsCount > 0 );

                // We've successfully created our initial list of glyphs.
                // Now apply the appropriate features if this is a font client 
                // that supports this script/lang.   Normally, the typographic
                // properties in featureSet are not applied now, but rather 
                // in the ApplyFinalSubstitutionFeatures function (after processing 
                // all the characters.
                layoutResult = ApplySubstitutionFeatures ( ref currentRun, featureSet ); 
                if ( layoutResult != OpenTypeLayoutResult.Success )
                {
                    // we can't successfully apply our substitution features so
                    // get glyph info for every character - no pre-substitution shaping, 
                    // just cmap lookup.
                    return  DefaultShape.DefaultShaper.GetGlyphs( 
                                                        item, 
                                                        culture,
                                                        fontFace, 
                                                        featureSet,
                                                        shapingFlags,

                                                        shapeFontInfo, 

                                                        chars, 
                                                        charCount, 

                                                        charProperties, 
                                                        charClusterMap,

                                                        out glyphIndices,
                                                        out glyphProperties, 
                                                        out glyphCount
                                                      ); 
                } 
            }
 
            // normally, the client's featureSet will be applied now to the entire glyph list.
            layoutResult = ApplyFinalSubstitutionFeatures ( ref currentRun, featureSet );
            if ( layoutResult != OpenTypeLayoutResult.Success )
            { 
                // we can't successfully apply our substitution features so
                // get glyph info for every character - no pre-substitution shaping, 
                // just cmap lookup. 
                return DefaultShape.DefaultShaper.GetGlyphs(
                                                    item, 
                                                    culture,
                                                    fontFace,
                                                    featureSet,
                                                    shapingFlags, 

                                                    shapeFontInfo, 
 
                                                    chars,
                                                    charCount, 

                                                    charProperties,
                                                    charClusterMap,
 
                                                    out glyphIndices,
                                                    out glyphProperties, 
                                                    out glyphCount 
                                                  );
            } 

            RecordTraceEvent(MS.Utility.EventType.StartEvent,
                            "BaseShaper PopulateClusterMap Start");
            //  Define the Clusters for the unicode text and set up the returned arrays. 
            currentRun.PopulateClusterMap();
 
            RecordTraceEvent(MS.Utility.EventType.EndEvent, 
                            "BaseShaper PopulateClusterMap End");
            RecordTraceEvent(MS.Utility.EventType.StartEvent, 
                            "BaseShaper CompileShapingProperties Start");

            currentRun.CompileShapingProperties( _forceDiacriticsToZeroWidth,
                                                out glyphCount, 
                                                out glyphIndices,
                                                out glyphProperties ); 
 
            RecordTraceEvent(MS.Utility.EventType.EndEvent,
                            "BaseShaper CompileShapingProperties End"); 

            RecordTraceEvent(MS.Utility.EventType.EndEvent,
                            "BaseShaper GetGlyphs End");
 
            return (glyphCount > 0);
        } 
 

 
        /// 
        ///     BaseShaper.GetGlyphs - default implementation of the GetGlyphs() helper function.
        /// 
        ///  
        ///     Most shape engines will override this method.  If successful, the function
        ///     will return true and will have filled the glyphInfo class, the character map, 
        ///     and the shapes list.  Note that a class that wants to override this function 
        ///     must also initialize the openTypeLayoutWorkspace class member.
        ///  
        /// shaping currentRun
        /// Text item
        /// number of glyphs
        ///  
        /// Critical - this method calls unsafe methods.
        ///  
        [SecurityCritical] 
        protected virtual int GetGlyphs ( ref ShapingWorkspace currentRun, Item item )
        { 
            // get glyph info for every character
            // no pre-substitution shaping, just cmap lookup.
            CharShapeInfo currShape;
            while ( currentRun.SetNextGlyphProperties (out currShape) ); 

 
            return currentRun.GlyphsCount;    // we're done 
        }
 
        /// 
        ///    BaseShaper.GetGlyphPlacements - default implementation of the IShaper method.
        ///     This method goes through a list of glyphs and adds placement information.
        ///  
        /// 
        ///     Most shape engines will not override this method, but instead its helper function - 
        ///     GetGlyphPositions.  This base implementation will call GetGlyphsList 
        ///     if the font supports OpenType GPOS features.
        ///  
        /// Text item
        /// text culture info
        /// font face layout info
        /// OpenType features 
        /// Controlling flags
        /// Shaping engine font specific data 
        /// properties of text 
        /// Character to glyph map
        /// text length 
        /// Result glyph info array
        /// glyph properties array
        /// number of glyphs produced
        /// scale factor from font design unit 
        /// List of glyph advance width
        /// List of glyph positioning offset 
        /// true if succeeds 
        /// 
        /// Critical - this method calls unsafe methods. 
        /// Safe     - this method returns glyph indices and shaping properties which are safe.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        public bool GetGlyphPlacements( 
            Item                                        item,
            CultureInfo                                 culture, 
            GlyphTypeface                               fontFace, 
            FeatureSet                                  featureSet,
            ShapingOptions                              shapingFlags, 

            object                                      shapeFontInfo,

            CheckedCharacterShapingPropertiesPointer    charProperties, 
            CheckedUShortPointer                        charClusterMap,
            int                                         charCount, 
 
            CheckedUShortPointer                        glyphIndices,
            CheckedGlyphShapingPropertiesPointer        glyphProperties, 
            int                                         glyphCount,

            double                                      scaleFactor,
            CheckedIntPointer                           glyphAdvances, 
            CheckedGlyphOffsetPointer                   glyphOffsets
            ) 
        { 
            if (charCount <= 0 || glyphCount <= 0)
            { 
                return false;
            }

            _isTracingEnabled = 
                EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose);
            RecordTraceEvent(MS.Utility.EventType.StartEvent, 
                            "BaseShaper GetGlyphPlacements Start"); 

            ShaperFontClient fontClient = InitializeFontClient( item, 
                                                            culture,
                                                            fontFace,
                                                            OpenTypeTags.GPOS,
                                                            shapeFontInfo); 
            bool fontSupportsScript = fontClient.IsFeatureTypeSupportedByFont;
 
            //  initialize currentRun 
            PlacementWorkspace placementInfo =
                                    new PlacementWorkspace( shapingFlags, 
                                                            fontClient,
                                                            _shaperBuffers,
                                                            charProperties,
                                                            charClusterMap, 
                                                            charCount,
                                                            glyphIndices, 
                                                            glyphProperties, 
                                                            glyphCount,
                                                            glyphAdvances, 
                                                            glyphOffsets,
                                                            fontSupportsScript,
                                                            _textFlowDirection);
 

            // this is the "basic" positioning step.  We just set all spacing glyphs to 
            // the glpyh's "default" width and set all diacritics to zero width. 
            placementInfo.InitializeGlyphInfoWidths();
 
            // if we have a font client for this shaping engine, then check that
            // we support this script/language (ie, check if layoutResult from the
            // shapingWorkspace initialization was "success").  If so, apply the features.
            if ( fontSupportsScript ) 
            {
 
                LayoutMetrics layoutMetrics = new LayoutMetrics(_textFlowDirection,0,0,0); 
                OpenTypeLayoutResult layoutResult = ApplyPositioningFeatures ( ref placementInfo,
                                                          ref layoutMetrics, 
                                                          featureSet );
                if (layoutResult != OpenTypeLayoutResult.Success)
                {
                    return false;       // something's wrong, can't get glyph positions 
                }
 
            } 

            placementInfo.ScaleGlyphInfoWidths( scaleFactor ); 

            RecordTraceEvent(MS.Utility.EventType.EndEvent,
                            "BaseShaper GetGlyphPlacements End");
            return true; 
        }
 
 

        ///  
        ///     BaseShaper.InitializeFontClient -IShaper methods helper.
        /// 
        /// 
        ///     This function is called from GetGlyphs and GetGlyphPlacements 
        ///     (IShaper methods) to do the necessary shaper initialization
        ///  
        ///  
        /// Critical - this method calls critical methods.
        /// Safe     - this method doesn't expose anything unsafe to the world. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        protected virtual ShaperFontClient InitializeFontClient ( Item item,
                                                      CultureInfo culture, 
                                                      GlyphTypeface fontFace,
                                                      OpenTypeTags featureType, 
                                                      object shapeFontInfo  ) 
        {
            ShaperFontClient fontClient = shapeFontInfo as ShaperFontClient; 

            if (fontClient != null)
            {
                if (_shaperBuffers == null) 
                {
                    // if there's no buffer set created for this shaper, create one. 
                    _shaperBuffers = new ShaperBuffers( 16, 0 ); 
                    if (_shaperBuffers == null)
                    { 
                        return null;
                    }
                }
 
                fontClient.Initialize ( _shaperBuffers.LayoutWorkspace,
                                         featureType, 
                                         item.Script, 
                                         LanguageTags.Default );
            } 

            return  fontClient;

        } 

        internal ShaperBuffers ShaperBuffers // also 
        { 
            get { return _shaperBuffers; }
        } 

    }

    ///  
    /// Base implementation of shaping engine with single shaper based on BaseShaper
    ///  
    internal abstract class BaseShape : BaseShaper, IShapingEngine 
    {
 
        internal BaseShape()
        {
        }
 
        /// 
        /// BaseShape.this[] - returns IShaper interface for this object 
        ///  
        /// 
        ///     This will normally not be overridden by derived shapers 
        /// 
        /// run description
        /// this object's interface
        public virtual IShaper this[ItemFlags flags] 
        {
            get 
            { 
                return (flags & ItemFlags.HasExtendedCharacter) != 0 ?
                        DefaultShape.SurrogateShaper as IShaper : this; 
            }
        }

        ///  
        /// BaseShaper.GetCharClassifier - IShapingEngine.OnLoadFont helper
        ///  
        ///  
        ///     This will normally be overridden by derived shapers.
        ///  
        protected virtual ShaperCharacterClassifier GetCharClassifier(ScriptTags scriptTag, GlyphTypeface fontFace)
        {
            return new ShaperCharacterClassifier(scriptTag, fontFace);
        } 

        ///  
        /// BaseShape.OnLoadFont - IShapingEngine method override. 
        /// 
        ///  
        ///     This should normally be sufficient for most shapers - the only
        ///     exceptions are those shapers that want to always return true
        /// 
        /// Script of interest. 
        /// Font face being loaded
        /// the font client 
        /// True if font supports script. 
        /// 
        /// Critical - This method reads into raw font table bits. 
        /// Safe     - This method doesn't expose any critical data.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        public virtual bool OnLoadFont( 
            ScriptTags          scriptTag,
            GlyphTypeface       fontFace, 
            out object          shaperFontClient 
            )
        { 
            // create the font client for this font/script
            ShaperFontClient fontClient = new ShaperFontClient( fontFace, GetCharClassifier (scriptTag, fontFace) );

            // if font is happy with this script, return true and give caller the ShaperFontClient 
            // to use in all method calls to us.
            if (OpenTypeLayout.FindScript(fontClient,(uint)scriptTag) != TagInfoFlags.None) 
            { 
                shaperFontClient = fontClient;
                return true; 
            }
            else
            {
                shaperFontClient = null; 
                return false;
 
            } 
        }
 
        /// 
        /// BaseShape.SupportedScripts - IShapingEngine method override.
        /// 
        ///  
        ///     This will normally be overridden by derived shapers
        ///  
        public virtual ScriptTags[] SupportedScripts 
        {
            get { return Script.AllTags; } 
        }

    }
 

} 
 

// 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, 2001
// 
//  File:      BaseShape.cs
// 
//  Contents:  base shaping engine classes 
//
//  Created:   10-22-2003 
//
//-----------------------------------------------------------------------

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
{

    ///  
    /// Base implementation of IShaper
    ///  
    internal class BaseShaper : IShaper 
    {
        protected ShaperBuffers _shaperBuffers; 
        protected TextFlowDirection _textFlowDirection;
        protected bool _forceDiacriticsToZeroWidth;

        internal BaseShaper () 
        {
            // the shaper's persistent buffers will be created at the first InitializeFontClient 
            // call. 
            _shaperBuffers = null;
 
            // default text flow direction is left-to-right.  Some shapers
            // (e.g., Arabic, Hebrew) will need to override this
            _textFlowDirection = TextFlowDirection.LTR;
 
            // Most shapers don't want diacritics to have any width, so this needn't be changed.
            // Overriding this to false will cause the GetGlyphs helper, PopulateClusterMap to 
            // not flag diacritics as zero-width 
            _forceDiacriticsToZeroWidth = true;
        } 

        // required substitution features. The optional ligature features are not applied
        // if the shaper client passes in a custom set of features to apply
        // 
        private static readonly Feature[] _defaultSubstitutionFeatures =  new Feature[]
        { 
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.LocalizedForms,1), 
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.GlyphCompositionDecomposition,1),
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.RequiredLigatures,1), 
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.ContextualAlternates,1),
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.StandardLigatures,1),   // optional
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.ContextualLigatures,1)  // optional
        }; 
        private const int _countOfInhibitableLigatureFeatures = 2;
 
        // 
        //
        protected static readonly Feature[] _defaultPositioningFeatures = new Feature[] 
        {
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.MarkPositioning,1),
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.MarktoMarkPositioning,1),
            new Feature(0,ushort.MaxValue,(uint)FeatureTags.Kerning,1) 
        };
 
        private bool _isTracingEnabled = false; 
        protected void RecordTraceEvent (byte eventType, String traceString )
        { 
                if (_isTracingEnabled)

                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.GENERICSTRINGGUID), 
                                                        eventType,
                                                        traceString); 
                } 
        }
 
        /// 
        ///     BaseShaper.ApplyFinalSubstitutionFeatures - default implementation of the GetGlyphs() helper function.
        /// 
        /// shaping currentRun 
        /// Set of gsub features to be applied to the unicode run.
        /// result of applying features 
        ///  
        /// Critical - this method calls unsafe methods.
        ///  
        [SecurityCritical]
        protected virtual OpenTypeLayoutResult ApplyFinalSubstitutionFeatures(
                                                            ref ShapingWorkspace currentRun,
                                                            FeatureSet       featureSet  ) 
        {
            return OpenTypeLayoutResult.Success; 
        } 

        ///  
        ///    BaseShaper.ApplyPositioningFeatures - default implementation of the GetGlyphPlacement helper.
        ///     This method goes through a list of glyphs and fills the glyph advances and offsets
        ///     arrays.
        ///  
        /// 
        ///     Most shape engines will override this method.  If not overridden, this implementation 
        ///     will attempt to apply the featureSet passed in, if the current font provides OpenType 
        ///     GPOS support for the current script.
        ///  
        /// the wrapper for glyph advances, offset arrays
        /// metrics for all the positioning features
        /// Set of gpos features to be applied to the unicode run.
        /// result of applying features 
        /// 
        /// Critical - this method calls unsafe methods. 
        ///  
        [SecurityCritical]
        protected virtual OpenTypeLayoutResult ApplyPositioningFeatures( 
                ref PlacementWorkspace   placementInfo,
                ref LayoutMetrics   layoutMetrics,
                FeatureSet          featureSet )
        { 
            ShaperFontClient fontClient = placementInfo.FontClient;
            OpenTypeLayoutResult layoutResult; 
 
            if (featureSet != null && featureSet.FeatureCount > 0)
            { 
                layoutResult = fontClient.PositionGlyphs(
                            ref placementInfo,
                            ref layoutMetrics,
                            featureSet.Features,     // In: List of features to apply 
                            featureSet.FeatureCount );
            } 
            else 
            {
                layoutResult = fontClient.PositionGlyphs( 
                            ref placementInfo,
                            ref layoutMetrics,
                            _defaultPositioningFeatures,     // In: List of features to apply
                            _defaultPositioningFeatures.Length ); 
            }
 
            return layoutResult; 
        }
 
        /// 
        ///     BaseShaper.ApplySubstitutionFeatures - default implementation of the GetGlyphs() helper function.
        ///                     This is called after every cluster (or whatever shaping "chunk" is applicable for
        ///                     the script shaper). 
        /// 
        /// shaping currentRun 
        /// Set of gsub features to be applied to the unicode run. 
        /// result of applying features
        ///  
        /// Critical - this method calls unsafe methods.
        /// 
        [SecurityCritical]
        protected virtual OpenTypeLayoutResult ApplySubstitutionFeatures( 
                                                        ref ShapingWorkspace currentRun,
                                                        FeatureSet       featureSet  ) 
        { 

            ShaperFontClient fontClient = currentRun.FontClient; 
            OpenTypeLayoutResult layoutResult;

            if (featureSet != null && featureSet.FeatureCount > 0)
            { 
                layoutResult = fontClient.SubstituteGlyphs(
                            ref currentRun, 
                            featureSet.Features,     // In: List of features to apply 
                            featureSet.FeatureCount );
            } 
            else
            {
                int featureCount = _defaultSubstitutionFeatures.Length;
                if (currentRun.AreLigaturesInhibited) 
                {
                    // no ligature features to be applied (except required) if inhibited 
                    // flag is set, or if featureSet exists... 
                    featureCount -= _countOfInhibitableLigatureFeatures;
                } 

                layoutResult = fontClient.SubstituteGlyphs(
                            ref currentRun,
                            _defaultSubstitutionFeatures,     // In: List of features to apply 
                            featureCount);
            } 
 
            return layoutResult;
        } 

        /// 
        ///     BaseShaper.GetGlyphs - default implementation of the IShaper method.
        ///     This method returns a list of glyphs, a character-to-glyph map, and 
        ///     a cluster map.
        ///  
        ///  
        ///     Most shape engines will not override this method, but rather its helper
        ///     function, GetGlyphsList.  This base implementation will call GetGlyphsList 
        ///     if the font supports OpenType GSUB features.
        ///     The shapers in DefaultShape.cs do implement override for this function.
        /// 
        /// Text item 
        /// text culture info
        /// font face layout info 
        /// OpenType features 
        /// Controlling flags
        /// Shaping engine font specific data 
        /// Incoming text
        /// text length
        /// properties of text
        /// Character to glyph map 
        /// Result glyph info array
        /// glyph properties array 
        /// number of glyphs produced 
        /// true if succeeds
        ///  
        /// Critical - this method calls unsafe methods.
        /// Safe     - this method returns glyph indices and shaping properties which are safe.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        public bool GetGlyphs(
            Item                                        item, 
            CultureInfo                                 culture, 
            GlyphTypeface                               fontFace,
            FeatureSet                                  featureSet, 
            ShapingOptions                              shapingFlags,

            object                                      shapeFontInfo,
 
            CheckedCharPointer                          chars,
            int                                         charCount, 
 
            CheckedCharacterShapingPropertiesPointer    charProperties,
            CheckedUShortPointer                        charClusterMap, 

            out ushort[]                                glyphIndices,
            out GlyphShapingProperties[]                glyphProperties,
            out int                                     glyphCount 
            )
        { 
 
            _isTracingEnabled =
                EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); 

            RecordTraceEvent(MS.Utility.EventType.StartEvent,
                            "BaseShaper GetGlyphs Start");
            RecordTraceEvent(MS.Utility.EventType.StartEvent, 
                            "BaseShaper Init Start");
 
            if (charCount <= 0) 
            {
                glyphCount = 0; 
                glyphIndices = null;
                glyphProperties = null;
                return false;
            } 

            ShaperFontClient fontClient = InitializeFontClient( item, 
                                                            culture, 
                                                            fontFace,
                                                            OpenTypeTags.GSUB, 
                                                            shapeFontInfo);

            Invariant.Assert(_shaperBuffers != null && fontClient != null);
 
            // initialize wrapper for managing the unsafe arrays.
            ShapingWorkspace currentRun = new ShapingWorkspace( item, 
                                                                shapingFlags, 

                                                                fontClient, 
                                                                _shaperBuffers,

                                                                chars,
                                                                charCount, 

                                                                charProperties, 
                                                                charClusterMap); 

 
            OpenTypeLayoutResult layoutResult;
            RecordTraceEvent(MS.Utility.EventType.EndEvent,
                            "BaseShaper Init End");
 

            // get character shapes and the glyphs... 
            while (!currentRun.IsFinished) 
            {
                int glyphsCount = GetGlyphs ( ref currentRun, item ); 
                Invariant.Assert( glyphsCount > 0 );

                // We've successfully created our initial list of glyphs.
                // Now apply the appropriate features if this is a font client 
                // that supports this script/lang.   Normally, the typographic
                // properties in featureSet are not applied now, but rather 
                // in the ApplyFinalSubstitutionFeatures function (after processing 
                // all the characters.
                layoutResult = ApplySubstitutionFeatures ( ref currentRun, featureSet ); 
                if ( layoutResult != OpenTypeLayoutResult.Success )
                {
                    // we can't successfully apply our substitution features so
                    // get glyph info for every character - no pre-substitution shaping, 
                    // just cmap lookup.
                    return  DefaultShape.DefaultShaper.GetGlyphs( 
                                                        item, 
                                                        culture,
                                                        fontFace, 
                                                        featureSet,
                                                        shapingFlags,

                                                        shapeFontInfo, 

                                                        chars, 
                                                        charCount, 

                                                        charProperties, 
                                                        charClusterMap,

                                                        out glyphIndices,
                                                        out glyphProperties, 
                                                        out glyphCount
                                                      ); 
                } 
            }
 
            // normally, the client's featureSet will be applied now to the entire glyph list.
            layoutResult = ApplyFinalSubstitutionFeatures ( ref currentRun, featureSet );
            if ( layoutResult != OpenTypeLayoutResult.Success )
            { 
                // we can't successfully apply our substitution features so
                // get glyph info for every character - no pre-substitution shaping, 
                // just cmap lookup. 
                return DefaultShape.DefaultShaper.GetGlyphs(
                                                    item, 
                                                    culture,
                                                    fontFace,
                                                    featureSet,
                                                    shapingFlags, 

                                                    shapeFontInfo, 
 
                                                    chars,
                                                    charCount, 

                                                    charProperties,
                                                    charClusterMap,
 
                                                    out glyphIndices,
                                                    out glyphProperties, 
                                                    out glyphCount 
                                                  );
            } 

            RecordTraceEvent(MS.Utility.EventType.StartEvent,
                            "BaseShaper PopulateClusterMap Start");
            //  Define the Clusters for the unicode text and set up the returned arrays. 
            currentRun.PopulateClusterMap();
 
            RecordTraceEvent(MS.Utility.EventType.EndEvent, 
                            "BaseShaper PopulateClusterMap End");
            RecordTraceEvent(MS.Utility.EventType.StartEvent, 
                            "BaseShaper CompileShapingProperties Start");

            currentRun.CompileShapingProperties( _forceDiacriticsToZeroWidth,
                                                out glyphCount, 
                                                out glyphIndices,
                                                out glyphProperties ); 
 
            RecordTraceEvent(MS.Utility.EventType.EndEvent,
                            "BaseShaper CompileShapingProperties End"); 

            RecordTraceEvent(MS.Utility.EventType.EndEvent,
                            "BaseShaper GetGlyphs End");
 
            return (glyphCount > 0);
        } 
 

 
        /// 
        ///     BaseShaper.GetGlyphs - default implementation of the GetGlyphs() helper function.
        /// 
        ///  
        ///     Most shape engines will override this method.  If successful, the function
        ///     will return true and will have filled the glyphInfo class, the character map, 
        ///     and the shapes list.  Note that a class that wants to override this function 
        ///     must also initialize the openTypeLayoutWorkspace class member.
        ///  
        /// shaping currentRun
        /// Text item
        /// number of glyphs
        ///  
        /// Critical - this method calls unsafe methods.
        ///  
        [SecurityCritical] 
        protected virtual int GetGlyphs ( ref ShapingWorkspace currentRun, Item item )
        { 
            // get glyph info for every character
            // no pre-substitution shaping, just cmap lookup.
            CharShapeInfo currShape;
            while ( currentRun.SetNextGlyphProperties (out currShape) ); 

 
            return currentRun.GlyphsCount;    // we're done 
        }
 
        /// 
        ///    BaseShaper.GetGlyphPlacements - default implementation of the IShaper method.
        ///     This method goes through a list of glyphs and adds placement information.
        ///  
        /// 
        ///     Most shape engines will not override this method, but instead its helper function - 
        ///     GetGlyphPositions.  This base implementation will call GetGlyphsList 
        ///     if the font supports OpenType GPOS features.
        ///  
        /// Text item
        /// text culture info
        /// font face layout info
        /// OpenType features 
        /// Controlling flags
        /// Shaping engine font specific data 
        /// properties of text 
        /// Character to glyph map
        /// text length 
        /// Result glyph info array
        /// glyph properties array
        /// number of glyphs produced
        /// scale factor from font design unit 
        /// List of glyph advance width
        /// List of glyph positioning offset 
        /// true if succeeds 
        /// 
        /// Critical - this method calls unsafe methods. 
        /// Safe     - this method returns glyph indices and shaping properties which are safe.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        public bool GetGlyphPlacements( 
            Item                                        item,
            CultureInfo                                 culture, 
            GlyphTypeface                               fontFace, 
            FeatureSet                                  featureSet,
            ShapingOptions                              shapingFlags, 

            object                                      shapeFontInfo,

            CheckedCharacterShapingPropertiesPointer    charProperties, 
            CheckedUShortPointer                        charClusterMap,
            int                                         charCount, 
 
            CheckedUShortPointer                        glyphIndices,
            CheckedGlyphShapingPropertiesPointer        glyphProperties, 
            int                                         glyphCount,

            double                                      scaleFactor,
            CheckedIntPointer                           glyphAdvances, 
            CheckedGlyphOffsetPointer                   glyphOffsets
            ) 
        { 
            if (charCount <= 0 || glyphCount <= 0)
            { 
                return false;
            }

            _isTracingEnabled = 
                EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose);
            RecordTraceEvent(MS.Utility.EventType.StartEvent, 
                            "BaseShaper GetGlyphPlacements Start"); 

            ShaperFontClient fontClient = InitializeFontClient( item, 
                                                            culture,
                                                            fontFace,
                                                            OpenTypeTags.GPOS,
                                                            shapeFontInfo); 
            bool fontSupportsScript = fontClient.IsFeatureTypeSupportedByFont;
 
            //  initialize currentRun 
            PlacementWorkspace placementInfo =
                                    new PlacementWorkspace( shapingFlags, 
                                                            fontClient,
                                                            _shaperBuffers,
                                                            charProperties,
                                                            charClusterMap, 
                                                            charCount,
                                                            glyphIndices, 
                                                            glyphProperties, 
                                                            glyphCount,
                                                            glyphAdvances, 
                                                            glyphOffsets,
                                                            fontSupportsScript,
                                                            _textFlowDirection);
 

            // this is the "basic" positioning step.  We just set all spacing glyphs to 
            // the glpyh's "default" width and set all diacritics to zero width. 
            placementInfo.InitializeGlyphInfoWidths();
 
            // if we have a font client for this shaping engine, then check that
            // we support this script/language (ie, check if layoutResult from the
            // shapingWorkspace initialization was "success").  If so, apply the features.
            if ( fontSupportsScript ) 
            {
 
                LayoutMetrics layoutMetrics = new LayoutMetrics(_textFlowDirection,0,0,0); 
                OpenTypeLayoutResult layoutResult = ApplyPositioningFeatures ( ref placementInfo,
                                                          ref layoutMetrics, 
                                                          featureSet );
                if (layoutResult != OpenTypeLayoutResult.Success)
                {
                    return false;       // something's wrong, can't get glyph positions 
                }
 
            } 

            placementInfo.ScaleGlyphInfoWidths( scaleFactor ); 

            RecordTraceEvent(MS.Utility.EventType.EndEvent,
                            "BaseShaper GetGlyphPlacements End");
            return true; 
        }
 
 

        ///  
        ///     BaseShaper.InitializeFontClient -IShaper methods helper.
        /// 
        /// 
        ///     This function is called from GetGlyphs and GetGlyphPlacements 
        ///     (IShaper methods) to do the necessary shaper initialization
        ///  
        ///  
        /// Critical - this method calls critical methods.
        /// Safe     - this method doesn't expose anything unsafe to the world. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        protected virtual ShaperFontClient InitializeFontClient ( Item item,
                                                      CultureInfo culture, 
                                                      GlyphTypeface fontFace,
                                                      OpenTypeTags featureType, 
                                                      object shapeFontInfo  ) 
        {
            ShaperFontClient fontClient = shapeFontInfo as ShaperFontClient; 

            if (fontClient != null)
            {
                if (_shaperBuffers == null) 
                {
                    // if there's no buffer set created for this shaper, create one. 
                    _shaperBuffers = new ShaperBuffers( 16, 0 ); 
                    if (_shaperBuffers == null)
                    { 
                        return null;
                    }
                }
 
                fontClient.Initialize ( _shaperBuffers.LayoutWorkspace,
                                         featureType, 
                                         item.Script, 
                                         LanguageTags.Default );
            } 

            return  fontClient;

        } 

        internal ShaperBuffers ShaperBuffers // also 
        { 
            get { return _shaperBuffers; }
        } 

    }

    ///  
    /// Base implementation of shaping engine with single shaper based on BaseShaper
    ///  
    internal abstract class BaseShape : BaseShaper, IShapingEngine 
    {
 
        internal BaseShape()
        {
        }
 
        /// 
        /// BaseShape.this[] - returns IShaper interface for this object 
        ///  
        /// 
        ///     This will normally not be overridden by derived shapers 
        /// 
        /// run description
        /// this object's interface
        public virtual IShaper this[ItemFlags flags] 
        {
            get 
            { 
                return (flags & ItemFlags.HasExtendedCharacter) != 0 ?
                        DefaultShape.SurrogateShaper as IShaper : this; 
            }
        }

        ///  
        /// BaseShaper.GetCharClassifier - IShapingEngine.OnLoadFont helper
        ///  
        ///  
        ///     This will normally be overridden by derived shapers.
        ///  
        protected virtual ShaperCharacterClassifier GetCharClassifier(ScriptTags scriptTag, GlyphTypeface fontFace)
        {
            return new ShaperCharacterClassifier(scriptTag, fontFace);
        } 

        ///  
        /// BaseShape.OnLoadFont - IShapingEngine method override. 
        /// 
        ///  
        ///     This should normally be sufficient for most shapers - the only
        ///     exceptions are those shapers that want to always return true
        /// 
        /// Script of interest. 
        /// Font face being loaded
        /// the font client 
        /// True if font supports script. 
        /// 
        /// Critical - This method reads into raw font table bits. 
        /// Safe     - This method doesn't expose any critical data.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        public virtual bool OnLoadFont( 
            ScriptTags          scriptTag,
            GlyphTypeface       fontFace, 
            out object          shaperFontClient 
            )
        { 
            // create the font client for this font/script
            ShaperFontClient fontClient = new ShaperFontClient( fontFace, GetCharClassifier (scriptTag, fontFace) );

            // if font is happy with this script, return true and give caller the ShaperFontClient 
            // to use in all method calls to us.
            if (OpenTypeLayout.FindScript(fontClient,(uint)scriptTag) != TagInfoFlags.None) 
            { 
                shaperFontClient = fontClient;
                return true; 
            }
            else
            {
                shaperFontClient = null; 
                return false;
 
            } 
        }
 
        /// 
        /// BaseShape.SupportedScripts - IShapingEngine method override.
        /// 
        ///  
        ///     This will normally be overridden by derived shapers
        ///  
        public virtual ScriptTags[] SupportedScripts 
        {
            get { return Script.AllTags; } 
        }

    }
 

} 
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK