DefaultShape.cs source code in C# .NET

Source code for the .NET framework in C#

                        

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 / DefaultShape.cs / 1 / DefaultShape.cs

                            //---------------------------------------------------------------------- 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2001
// 
//  File:      DefaultShape.cs
// 
//  Contents:  Implementation of default shaping engine and its factory 
//
//  Created:   12-25-2001 Worachai Chaoweeraprasit (wchao) 
//
//-----------------------------------------------------------------------

using System; 
using System.Collections;
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Globalization;
using MS.Internal.FontCache; 
using MS.Internal.FontFace;
using MS.Internal.TextFormatting;
using System.Security;
using System.Security.Permissions; 
using MS.Internal.PresentationCore;
using System.Windows.Media; 
using System.Windows.Media.TextFormatting; 

namespace MS.Internal.Shaping 
{
    /// 
    /// Default shaping engine implementation
    ///  
    /// 
    /// This engine does not utilize OpenType information. It provides the baseline 
    /// behavior of the shaping process. Most operations are based on font's CMAP, 
    /// HMTX and VMTX table.
    ///  
    internal class DefaultShape : IShapingEngine
    {
        internal DefaultShape() {}
 
        public ScriptTags[] SupportedScripts
        { 
            get { return Script.AllTags; } 
        }
 
        public bool OnLoadFont(
            ScriptTags          scriptTag,
            GlyphTypeface       fontFace,
            out object          shapeState 
            )
        { 
            shapeState = null; 
            return true;
        } 

        public IShaper this[ItemFlags flags]
        {
            get 
            {
                if((flags & ItemFlags.GlyphVariant) != 0) 
                { 
                    return DefaultShape.DefaultVariantShaper[(int)(flags & ItemFlags.GlyphVariant)];
                } 

                return  (flags & ItemFlags.HasExtendedCharacter) != 0 ?
                        DefaultShape.SurrogateShaper as IShaper :
                        DefaultShape.DefaultShaper as IShaper; 
            }
        } 
 
        // font independent static shapers, created once per process
        static public readonly IShaper DefaultShaper = new CmapShaper(); 
        static public readonly IShaper SurrogateShaper = new DefaultSurrogateShaper();

        static public readonly IShaper[] DefaultVariantShaper = new IShaper[]
        { 
            DefaultShaper,
            DefaultShaper,   //new DefaultVerticalShaper(), 
            DefaultShaper, 
        };
 

        //
        //  Associated shapers
        // 
        /// 
        /// Base implementation of IShaper 
        ///  
        internal class CmapShaper : IShaper
        { 
            internal CmapShaper()
            {
            }
 
            /// 
            ///     CmapShaper.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 unsafe virtual 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 
                )
            { 

                // unpack the pointer containers and keep track of our pointer
                char *pChars = chars.Probe(0, charCount);
                CharacterShapingProperties *pCharProps = charProperties.Probe(0, charCount); 
                ushort *pClusters = charClusterMap.Probe(0, charCount);
 
                // create output arrays 
                glyphIndices    = new ushort[charCount];
                glyphProperties = new GlyphShapingProperties[charCount]; 

                // fill the arrays
                for(ushort charIx = 0; charIx < charCount; charIx++)
                { 
                    // the character properties
                    bool canGlyphAlone = (Classification.CharAttributeOf( 
                        (int)Classification.GetUnicodeClassUTF16(pChars[charIx])).Flags & 
                        (ushort)CharacterAttributeFlags.CharacterSpace) != 0;
 
                    pCharProps[charIx].CanGlyphAlone = canGlyphAlone;
                    pCharProps[charIx].EngineReserved= 0;

                    // the cluster map (all clusters are one character) 
                    pClusters[charIx] = charIx;
 
                    // the glyphs and their properties 
                    ushort currGlyph;
                    currGlyph =  fontFace.CharacterToGlyphMap.TryGetValue(pChars[charIx], out currGlyph) ? 
                            currGlyph : (ushort)0;
                    ushort glyphFlags = ShapingWorkspace.GlyphFlagsBase;
                    if (currGlyph >= fontFace.GlyphCount)
                    { 
                         // invalid glyph index (too big to be valid), so just hide it.
                         glyphFlags |= (ushort)GlyphFlags.ZeroWidth; 
                         currGlyph = fontFace.BlankGlyphIndex; 
                    }
                    glyphIndices[charIx] =  currGlyph; 
                    glyphProperties[charIx] =
                        new GlyphShapingProperties( glyphFlags,
                                                     (ushort)(1 << 8));
                } 

                glyphCount = charCount ; 
                return true; 
            }
 
            /// 
            ///    DefaultShaper.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]
            public unsafe 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
                ) 
            { 
                 // get pointers to outputs
                ushort *pGlyphs = glyphIndices.Probe(0, glyphCount); 
                int *pGlyphAdvances = glyphAdvances.Probe(0, glyphCount);
                GlyphOffset *pGlyphOffsets = glyphOffsets.Probe(0, glyphCount);
                GlyphShapingProperties*     pGlyphProps = glyphProperties.Probe(0, glyphCount);
 
                for (ushort glyphIx = 0; glyphIx < glyphCount; ++glyphIx)
                { 
                    pGlyphOffsets[glyphIx].du = pGlyphOffsets[glyphIx].dv = 0; 
                    pGlyphAdvances[glyphIx] =  (pGlyphProps[glyphIx].GlyphFlags & (ushort)GlyphFlags.ZeroWidth) != 0 ?
                        0 : 
                        (int)Math.Round( fontFace.GetAdvanceWidthInDesignUnits(pGlyphs[glyphIx]) * scaleFactor);

                }
 
                return true;
            } 
        } 

        ///  
        /// Default shaper for surrogate characters
        /// 
        internal class DefaultSurrogateShaper : CmapShaper
        { 
            internal DefaultSurrogateShaper()
            { 
            } 

            ///  
            ///     DefaultSurrogateShaper.GetGlyphs - default implementation of the IShaper method.
            ///     This method returns a list of glyphs, a character-to-glyph map, and
            ///     a cluster map.
            ///  
            /// 
            ///     This differs from the base CmapShaper method in that it 
            ///     detects and processed surrogate characters in the stream. 
            /// 
            /// 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] 
            public unsafe override 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 
                )
            {

                int pairs = 0; 
                ushort currGlyph;
                ushort invalidGlyph = 
                    fontFace.CharacterToGlyphMap.TryGetValue(UnicodeCharacter.DottedCircle, out currGlyph) ? 
                    currGlyph : (ushort)0;
 
                // unpack the pointer containers and keep track of our pointer
                char *pChars = chars.Probe(0, charCount);
                CharacterShapingProperties *pCharProps = charProperties.Probe(0, charCount);
                ushort *pClusters = charClusterMap.Probe(0, charCount); 

                // create output arrays 
                glyphIndices    = new ushort[charCount]; 
                glyphProperties = new GlyphShapingProperties[charCount];
 
                // run through the text quickly, looking for surrogate pairs.
                // (Count them)
                for(int charIx = 0; charIx < charCount; charIx++)
                { 

                    // the glyphs and their properties 
                    char currChar = pChars[charIx]; 
                    bool isLowSurrogate;
                    int scalar; 

                    // check for surrogate pairs (looks for the second member in a pair before
                    // looking at the preceding char).  If a pair is found the glyph for
                    // the preceding character is updated, otherwise the character is treated 
                    // as a standalone.
                    if( (isLowSurrogate = IsLowSurrogate((int)currChar)) && 
                        charIx > 0  && 
                        IsHighSurrogate((int)pChars[charIx - 1]) &&
                        (scalar = MakeUnicodeScalar((int)pChars[charIx - 1], (int)currChar)) != 0) 
                    {
                        // we've found a surrogate pair (yeah!!)
                        pClusters[charIx] = pClusters[charIx - 1];
 
                        // this is ligated with the previous character
                        pCharProps[charIx].CanGlyphAlone = false; 
                        pCharProps[charIx].EngineReserved= 1; 

                        // update the previous char's glyph 
                        int glyphIx = (charIx - 1) - pairs;
                        fontFace.CharacterToGlyphMap.TryGetValue(scalar, out currGlyph);
                        glyphIndices[glyphIx] = (currGlyph < fontFace.GlyphCount) ? currGlyph : (ushort)0;
                        glyphProperties[glyphIx].EngineReserved = 2; 
                        ++pairs;
                    } 
                    else 
                    {
                        // this is a stand-alone character (1:1 char:glyph mapping) 
                        int glyphIx = charIx - pairs;
                        ushort glyphFlags = ShapingWorkspace.GlyphFlagsBase;
                        glyphIndices[glyphIx] =  isLowSurrogate  ? invalidGlyph :
                                fontFace.CharacterToGlyphMap.TryGetValue(currChar, out currGlyph) ? 
                                currGlyph : (ushort)0;
 
                        // make sure glyph id is valid 
                        if (currGlyph >= fontFace.GlyphCount)
                        { 
                             // invalid glyph index (too big to be valid), so just hide it.
                             glyphFlags |= (ushort)GlyphFlags.ZeroWidth;
                             currGlyph = fontFace.BlankGlyphIndex;
                             currChar = UnicodeCharacter.Space; 
                        }
 
                        // the character properties 
                        bool canGlyphAlone = (Classification.CharAttributeOf(
                            (int)Classification.GetUnicodeClassUTF16(currChar)).Flags & 
                            (ushort)CharacterAttributeFlags.CharacterSpace) != 0;

                        pCharProps[charIx].CanGlyphAlone = canGlyphAlone;
                        pCharProps[charIx].EngineReserved= 0; 

                        // the cluster map and glyph properties; 
                        pClusters[charIx] = (ushort)glyphIx; 
                        glyphProperties[glyphIx] =
                            new GlyphShapingProperties( glyphFlags, 
                                                         (ushort)(1 << 8));
                    }
                }
 
                glyphCount = charCount - pairs;
                if (glyphCount < charCount) 
                { 
                    // need to redimension glyphProperties and glyphIndices...
                    // (though I'm not sure I have to...maybe glyphCount is always 
                    // used to limit access to glyphProperties, glyphIndices)
                    ushort []redimGlyphIndices    = new ushort[glyphCount];
                    GlyphShapingProperties[] redimGlyphProperties = new GlyphShapingProperties[glyphCount];
 
                    Array.Copy(glyphIndices, redimGlyphIndices, glyphCount);
                    Array.Copy(glyphProperties, redimGlyphProperties, glyphCount); 
                    glyphIndices = redimGlyphIndices; 
                    glyphProperties = redimGlyphProperties;
                } 
                return true;
            }

            internal static bool IsHighSurrogate(int ch) 
            {
                return ch >= 0xd800 && ch < 0xdc00; 
            } 

            internal static bool IsLowSurrogate(int ch) 
            {
                return ch >= 0xdc00 && ch < 0xe000;
            }
 
            internal static bool IsSurrogate(int ch)
            { 
                return IsHighSurrogate(ch) || IsLowSurrogate(ch); 
            }
 
            internal static int MakeUnicodeScalar(int hi, int lo)
            {
                return ((hi & 0x03ff) << 10 | (lo & 0x03ff)) + 0x10000;
            } 
        }
    } 
 

 
    /// 
    /// shaping engine for mirrored glyph form
    /// 
    internal class MirroringShape : DefaultShape.CmapShaper, IShapingEngine 
    {
        internal MirroringShape() 
        { 
        }
 
        public ScriptTags[] SupportedScripts
        {
            get { return new ScriptTags[]{ Script.TagMirror }; }
        } 

        public IShaper this[ItemFlags flags] 
        { 
            get
            { 
                return (flags & ItemFlags.HasExtendedCharacter) != 0 ?
                        DefaultShape.SurrogateShaper as IShaper : this;
            }
        } 

        ///  
        /// MirroringShape.OnLoadFont - IShapingEngine method override. 
        /// 
        /// True if font supports script. 
        public bool OnLoadFont(ScriptTags scriptTag, GlyphTypeface fontFace, out object shapeState)
        {
            shapeState = null;
            return true; 
        }
 
        ///  
        ///     MirroringShape.GetGlyphs - Mirroring IShaper method.
        ///     This method returns a list of glyphs, a character-to-glyph map, and 
        ///     a cluster map.
        /// 
        /// 
        ///     This differs from the default CmapShaper method by looking up the 
        ///     mirrored codepoint for each character and uses that codepoint to
        ///     get the appropriate glyph. 
        ///  
        /// 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]
        public unsafe override 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
            ) 
        {

            // unpack the pointer containers and keep track of our pointer
            char *pChars = chars.Probe(0, charCount); 
            CharacterShapingProperties *pCharProps = charProperties.Probe(0, charCount);
            ushort *pClusters = charClusterMap.Probe(0, charCount); 
 
            // create output arrays
            glyphIndices    = new ushort[charCount]; 
            glyphProperties = new GlyphShapingProperties[charCount];

            // fill the arrays
            for(ushort charIx = 0; charIx < charCount; charIx++) 
            {
                char currChar = pChars[charIx]; 
                char mirroredChar = (char)Classification.GetMirroredCharacterUTF16(currChar); 
                // the character properties
                bool canGlyphAlone = (Classification.CharAttributeOf( 
                    (int)Classification.GetUnicodeClassUTF16(currChar)).Flags &
                    (ushort)CharacterAttributeFlags.CharacterSpace) != 0;

                pCharProps[charIx].CanGlyphAlone = canGlyphAlone; 
                pCharProps[charIx].EngineReserved= 0;
 
                // the cluster map (all clusters are one character) 
                pClusters[charIx] = charIx;
 
                // the glyphs and their properties
                ushort currGlyph;
                currGlyph =  fontFace.CharacterToGlyphMap.TryGetValue(mirroredChar, out currGlyph) ?
                        currGlyph : (ushort)0; 
                ushort glyphFlags = ShapingWorkspace.GlyphFlagsBase;
                if (currGlyph >= fontFace.GlyphCount) 
                { 
                     // invalid glyph index (too big to be valid), so just hide it.
                     glyphFlags |= (ushort)GlyphFlags.ZeroWidth; 
                     currGlyph = fontFace.BlankGlyphIndex;
                }
                glyphIndices[charIx] =  currGlyph;
                glyphProperties[charIx] = 
                    new GlyphShapingProperties( glyphFlags,
                                                 (ushort)(1 << 8)); 
            } 

            glyphCount = charCount ; 
            return true;
        }
    }
 

 
 
    /// 
    /// Default implementation of control code shape 
    /// 
    internal class ControlShape : DefaultShape.CmapShaper, IShapingEngine
    {
        internal ControlShape() 
        {
        } 
 
        public ScriptTags[] SupportedScripts
        { 
            get { return new ScriptTags[]{ Script.TagControl }; }
        }

        public IShaper this[ItemFlags flags] 
        {
            get 
            { 
                return (flags & ItemFlags.HasExtendedCharacter) != 0 ?
                        DefaultShape.SurrogateShaper as IShaper : this; 
            }
        }

        ///  
        /// ControlShape.OnLoadFont - IShapingEngine method override.
        ///  
        /// True if font supports script. 
        public bool OnLoadFont(ScriptTags scriptTag, GlyphTypeface fontFace, out object shapeState)
        { 
            shapeState = null;
            return true;
        }
 
        /// 
        ///     ControlShape.GetGlyphs - Mirroring IShaper method. 
        ///     This method returns a list of glyphs, a character-to-glyph map, and 
        ///     a cluster map.
        ///  
        /// 
        /// 
        /// 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]
        public unsafe override 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
            ) 
        {
            bool displayControlChars = ((shapingFlags & ShapingOptions.DisplayControlCode) != 0); 
 
            // unpack the pointer containers and keep track of our pointer
            char *pChars = chars.Probe(0, charCount); 
            CharacterShapingProperties *pCharProps = charProperties.Probe(0, charCount);
            ushort *pClusters = charClusterMap.Probe(0, charCount);

            // create output arrays 
            glyphIndices    = new ushort[charCount];
            glyphProperties = new GlyphShapingProperties[charCount]; 
 
            // these glyphs are used alot
            ushort currGlyph; 
            ushort blankGlyph;
            ushort zwnjGlyph;
            blankGlyph =
                fontFace.CharacterToGlyphMap.TryGetValue(UnicodeCharacter.Space, 
                                                         out currGlyph) ?
                currGlyph : (ushort) 0; 
            zwnjGlyph = 
                fontFace.CharacterToGlyphMap.TryGetValue(UnicodeCharacter.ZWNJ,
                                                         out currGlyph) ? 
                currGlyph : (ushort) 0;

            // fill the arrays
            for(ushort charIx = 0; charIx < charCount; charIx++) 
            {
                char currChar = pChars[charIx]; 
 
                // the character properties
                bool canGlyphAlone = (Classification.CharAttributeOf( 
                    (int)Classification.GetUnicodeClassUTF16(currChar)).Flags &
                    (ushort)CharacterAttributeFlags.CharacterSpace) != 0;

                pCharProps[charIx].CanGlyphAlone = canGlyphAlone; 
                pCharProps[charIx].EngineReserved= 0;
 
                // the cluster map (all clusters are one character) 
                pClusters[charIx] = charIx;
 
                // the glyphs and their properties
                ushort glyphFlags = (ushort)ShapingWorkspace.GlyphFlagsBase;
                if( IsC0( (int)currChar ) || displayControlChars )
                { 
                    // check for missing glyph
                    if (!fontFace.CharacterToGlyphMap.TryGetValue(currChar,out currGlyph)) 
                    { 
                        // IsDefaultHidden is true for some core control code that never
                        // display.  For other missing control codes, display with the 
                        // ZWNJ glyph.
                        currGlyph = IsDefaultHidden( (int)currChar ) ? blankGlyph : zwnjGlyph;
                        glyphFlags |= (ushort)GlyphFlags.ZeroWidth;
                    } 
                }
                else 
                { 
                    currGlyph = blankGlyph;      // default is to hide control chars
                    glyphFlags = (ushort)ShapingWorkspace.GlyphFlagsZeroWidth; 
                }
                if (currGlyph >= fontFace.GlyphCount)
                {
                     // invalid glyph index (too big to be valid), so just hide it. 
                     glyphFlags |= (ushort)GlyphFlags.ZeroWidth;
                     currGlyph = blankGlyph; 
                } 
                glyphIndices[charIx] =  currGlyph;
                glyphProperties[charIx] = 
                    new GlyphShapingProperties( glyphFlags,
                                                 (ushort)(1 << 8));
            }
 
            glyphCount = charCount ;
            return true; 
        } 

        private const int ZWNJ = 0x200c; 

        private bool IsC0(int ch)
        {
            return ch < 0x0020; 
        }
 
        private bool IsDefaultHidden(int ch) 
        {
            // For 0x001c...0x001f (FS, GS, RS, US), TAB, CR and LF, 
            // we'll never display them as missing glyph
            return IsC0(ch) && (ch >= 0x001c || ch == 9 || ch == 10 || ch == 13);
        }
    } 

} 

// 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:      DefaultShape.cs
// 
//  Contents:  Implementation of default shaping engine and its factory 
//
//  Created:   12-25-2001 Worachai Chaoweeraprasit (wchao) 
//
//-----------------------------------------------------------------------

using System; 
using System.Collections;
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Globalization;
using MS.Internal.FontCache; 
using MS.Internal.FontFace;
using MS.Internal.TextFormatting;
using System.Security;
using System.Security.Permissions; 
using MS.Internal.PresentationCore;
using System.Windows.Media; 
using System.Windows.Media.TextFormatting; 

namespace MS.Internal.Shaping 
{
    /// 
    /// Default shaping engine implementation
    ///  
    /// 
    /// This engine does not utilize OpenType information. It provides the baseline 
    /// behavior of the shaping process. Most operations are based on font's CMAP, 
    /// HMTX and VMTX table.
    ///  
    internal class DefaultShape : IShapingEngine
    {
        internal DefaultShape() {}
 
        public ScriptTags[] SupportedScripts
        { 
            get { return Script.AllTags; } 
        }
 
        public bool OnLoadFont(
            ScriptTags          scriptTag,
            GlyphTypeface       fontFace,
            out object          shapeState 
            )
        { 
            shapeState = null; 
            return true;
        } 

        public IShaper this[ItemFlags flags]
        {
            get 
            {
                if((flags & ItemFlags.GlyphVariant) != 0) 
                { 
                    return DefaultShape.DefaultVariantShaper[(int)(flags & ItemFlags.GlyphVariant)];
                } 

                return  (flags & ItemFlags.HasExtendedCharacter) != 0 ?
                        DefaultShape.SurrogateShaper as IShaper :
                        DefaultShape.DefaultShaper as IShaper; 
            }
        } 
 
        // font independent static shapers, created once per process
        static public readonly IShaper DefaultShaper = new CmapShaper(); 
        static public readonly IShaper SurrogateShaper = new DefaultSurrogateShaper();

        static public readonly IShaper[] DefaultVariantShaper = new IShaper[]
        { 
            DefaultShaper,
            DefaultShaper,   //new DefaultVerticalShaper(), 
            DefaultShaper, 
        };
 

        //
        //  Associated shapers
        // 
        /// 
        /// Base implementation of IShaper 
        ///  
        internal class CmapShaper : IShaper
        { 
            internal CmapShaper()
            {
            }
 
            /// 
            ///     CmapShaper.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 unsafe virtual 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 
                )
            { 

                // unpack the pointer containers and keep track of our pointer
                char *pChars = chars.Probe(0, charCount);
                CharacterShapingProperties *pCharProps = charProperties.Probe(0, charCount); 
                ushort *pClusters = charClusterMap.Probe(0, charCount);
 
                // create output arrays 
                glyphIndices    = new ushort[charCount];
                glyphProperties = new GlyphShapingProperties[charCount]; 

                // fill the arrays
                for(ushort charIx = 0; charIx < charCount; charIx++)
                { 
                    // the character properties
                    bool canGlyphAlone = (Classification.CharAttributeOf( 
                        (int)Classification.GetUnicodeClassUTF16(pChars[charIx])).Flags & 
                        (ushort)CharacterAttributeFlags.CharacterSpace) != 0;
 
                    pCharProps[charIx].CanGlyphAlone = canGlyphAlone;
                    pCharProps[charIx].EngineReserved= 0;

                    // the cluster map (all clusters are one character) 
                    pClusters[charIx] = charIx;
 
                    // the glyphs and their properties 
                    ushort currGlyph;
                    currGlyph =  fontFace.CharacterToGlyphMap.TryGetValue(pChars[charIx], out currGlyph) ? 
                            currGlyph : (ushort)0;
                    ushort glyphFlags = ShapingWorkspace.GlyphFlagsBase;
                    if (currGlyph >= fontFace.GlyphCount)
                    { 
                         // invalid glyph index (too big to be valid), so just hide it.
                         glyphFlags |= (ushort)GlyphFlags.ZeroWidth; 
                         currGlyph = fontFace.BlankGlyphIndex; 
                    }
                    glyphIndices[charIx] =  currGlyph; 
                    glyphProperties[charIx] =
                        new GlyphShapingProperties( glyphFlags,
                                                     (ushort)(1 << 8));
                } 

                glyphCount = charCount ; 
                return true; 
            }
 
            /// 
            ///    DefaultShaper.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]
            public unsafe 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
                ) 
            { 
                 // get pointers to outputs
                ushort *pGlyphs = glyphIndices.Probe(0, glyphCount); 
                int *pGlyphAdvances = glyphAdvances.Probe(0, glyphCount);
                GlyphOffset *pGlyphOffsets = glyphOffsets.Probe(0, glyphCount);
                GlyphShapingProperties*     pGlyphProps = glyphProperties.Probe(0, glyphCount);
 
                for (ushort glyphIx = 0; glyphIx < glyphCount; ++glyphIx)
                { 
                    pGlyphOffsets[glyphIx].du = pGlyphOffsets[glyphIx].dv = 0; 
                    pGlyphAdvances[glyphIx] =  (pGlyphProps[glyphIx].GlyphFlags & (ushort)GlyphFlags.ZeroWidth) != 0 ?
                        0 : 
                        (int)Math.Round( fontFace.GetAdvanceWidthInDesignUnits(pGlyphs[glyphIx]) * scaleFactor);

                }
 
                return true;
            } 
        } 

        ///  
        /// Default shaper for surrogate characters
        /// 
        internal class DefaultSurrogateShaper : CmapShaper
        { 
            internal DefaultSurrogateShaper()
            { 
            } 

            ///  
            ///     DefaultSurrogateShaper.GetGlyphs - default implementation of the IShaper method.
            ///     This method returns a list of glyphs, a character-to-glyph map, and
            ///     a cluster map.
            ///  
            /// 
            ///     This differs from the base CmapShaper method in that it 
            ///     detects and processed surrogate characters in the stream. 
            /// 
            /// 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] 
            public unsafe override 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 
                )
            {

                int pairs = 0; 
                ushort currGlyph;
                ushort invalidGlyph = 
                    fontFace.CharacterToGlyphMap.TryGetValue(UnicodeCharacter.DottedCircle, out currGlyph) ? 
                    currGlyph : (ushort)0;
 
                // unpack the pointer containers and keep track of our pointer
                char *pChars = chars.Probe(0, charCount);
                CharacterShapingProperties *pCharProps = charProperties.Probe(0, charCount);
                ushort *pClusters = charClusterMap.Probe(0, charCount); 

                // create output arrays 
                glyphIndices    = new ushort[charCount]; 
                glyphProperties = new GlyphShapingProperties[charCount];
 
                // run through the text quickly, looking for surrogate pairs.
                // (Count them)
                for(int charIx = 0; charIx < charCount; charIx++)
                { 

                    // the glyphs and their properties 
                    char currChar = pChars[charIx]; 
                    bool isLowSurrogate;
                    int scalar; 

                    // check for surrogate pairs (looks for the second member in a pair before
                    // looking at the preceding char).  If a pair is found the glyph for
                    // the preceding character is updated, otherwise the character is treated 
                    // as a standalone.
                    if( (isLowSurrogate = IsLowSurrogate((int)currChar)) && 
                        charIx > 0  && 
                        IsHighSurrogate((int)pChars[charIx - 1]) &&
                        (scalar = MakeUnicodeScalar((int)pChars[charIx - 1], (int)currChar)) != 0) 
                    {
                        // we've found a surrogate pair (yeah!!)
                        pClusters[charIx] = pClusters[charIx - 1];
 
                        // this is ligated with the previous character
                        pCharProps[charIx].CanGlyphAlone = false; 
                        pCharProps[charIx].EngineReserved= 1; 

                        // update the previous char's glyph 
                        int glyphIx = (charIx - 1) - pairs;
                        fontFace.CharacterToGlyphMap.TryGetValue(scalar, out currGlyph);
                        glyphIndices[glyphIx] = (currGlyph < fontFace.GlyphCount) ? currGlyph : (ushort)0;
                        glyphProperties[glyphIx].EngineReserved = 2; 
                        ++pairs;
                    } 
                    else 
                    {
                        // this is a stand-alone character (1:1 char:glyph mapping) 
                        int glyphIx = charIx - pairs;
                        ushort glyphFlags = ShapingWorkspace.GlyphFlagsBase;
                        glyphIndices[glyphIx] =  isLowSurrogate  ? invalidGlyph :
                                fontFace.CharacterToGlyphMap.TryGetValue(currChar, out currGlyph) ? 
                                currGlyph : (ushort)0;
 
                        // make sure glyph id is valid 
                        if (currGlyph >= fontFace.GlyphCount)
                        { 
                             // invalid glyph index (too big to be valid), so just hide it.
                             glyphFlags |= (ushort)GlyphFlags.ZeroWidth;
                             currGlyph = fontFace.BlankGlyphIndex;
                             currChar = UnicodeCharacter.Space; 
                        }
 
                        // the character properties 
                        bool canGlyphAlone = (Classification.CharAttributeOf(
                            (int)Classification.GetUnicodeClassUTF16(currChar)).Flags & 
                            (ushort)CharacterAttributeFlags.CharacterSpace) != 0;

                        pCharProps[charIx].CanGlyphAlone = canGlyphAlone;
                        pCharProps[charIx].EngineReserved= 0; 

                        // the cluster map and glyph properties; 
                        pClusters[charIx] = (ushort)glyphIx; 
                        glyphProperties[glyphIx] =
                            new GlyphShapingProperties( glyphFlags, 
                                                         (ushort)(1 << 8));
                    }
                }
 
                glyphCount = charCount - pairs;
                if (glyphCount < charCount) 
                { 
                    // need to redimension glyphProperties and glyphIndices...
                    // (though I'm not sure I have to...maybe glyphCount is always 
                    // used to limit access to glyphProperties, glyphIndices)
                    ushort []redimGlyphIndices    = new ushort[glyphCount];
                    GlyphShapingProperties[] redimGlyphProperties = new GlyphShapingProperties[glyphCount];
 
                    Array.Copy(glyphIndices, redimGlyphIndices, glyphCount);
                    Array.Copy(glyphProperties, redimGlyphProperties, glyphCount); 
                    glyphIndices = redimGlyphIndices; 
                    glyphProperties = redimGlyphProperties;
                } 
                return true;
            }

            internal static bool IsHighSurrogate(int ch) 
            {
                return ch >= 0xd800 && ch < 0xdc00; 
            } 

            internal static bool IsLowSurrogate(int ch) 
            {
                return ch >= 0xdc00 && ch < 0xe000;
            }
 
            internal static bool IsSurrogate(int ch)
            { 
                return IsHighSurrogate(ch) || IsLowSurrogate(ch); 
            }
 
            internal static int MakeUnicodeScalar(int hi, int lo)
            {
                return ((hi & 0x03ff) << 10 | (lo & 0x03ff)) + 0x10000;
            } 
        }
    } 
 

 
    /// 
    /// shaping engine for mirrored glyph form
    /// 
    internal class MirroringShape : DefaultShape.CmapShaper, IShapingEngine 
    {
        internal MirroringShape() 
        { 
        }
 
        public ScriptTags[] SupportedScripts
        {
            get { return new ScriptTags[]{ Script.TagMirror }; }
        } 

        public IShaper this[ItemFlags flags] 
        { 
            get
            { 
                return (flags & ItemFlags.HasExtendedCharacter) != 0 ?
                        DefaultShape.SurrogateShaper as IShaper : this;
            }
        } 

        ///  
        /// MirroringShape.OnLoadFont - IShapingEngine method override. 
        /// 
        /// True if font supports script. 
        public bool OnLoadFont(ScriptTags scriptTag, GlyphTypeface fontFace, out object shapeState)
        {
            shapeState = null;
            return true; 
        }
 
        ///  
        ///     MirroringShape.GetGlyphs - Mirroring IShaper method.
        ///     This method returns a list of glyphs, a character-to-glyph map, and 
        ///     a cluster map.
        /// 
        /// 
        ///     This differs from the default CmapShaper method by looking up the 
        ///     mirrored codepoint for each character and uses that codepoint to
        ///     get the appropriate glyph. 
        ///  
        /// 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]
        public unsafe override 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
            ) 
        {

            // unpack the pointer containers and keep track of our pointer
            char *pChars = chars.Probe(0, charCount); 
            CharacterShapingProperties *pCharProps = charProperties.Probe(0, charCount);
            ushort *pClusters = charClusterMap.Probe(0, charCount); 
 
            // create output arrays
            glyphIndices    = new ushort[charCount]; 
            glyphProperties = new GlyphShapingProperties[charCount];

            // fill the arrays
            for(ushort charIx = 0; charIx < charCount; charIx++) 
            {
                char currChar = pChars[charIx]; 
                char mirroredChar = (char)Classification.GetMirroredCharacterUTF16(currChar); 
                // the character properties
                bool canGlyphAlone = (Classification.CharAttributeOf( 
                    (int)Classification.GetUnicodeClassUTF16(currChar)).Flags &
                    (ushort)CharacterAttributeFlags.CharacterSpace) != 0;

                pCharProps[charIx].CanGlyphAlone = canGlyphAlone; 
                pCharProps[charIx].EngineReserved= 0;
 
                // the cluster map (all clusters are one character) 
                pClusters[charIx] = charIx;
 
                // the glyphs and their properties
                ushort currGlyph;
                currGlyph =  fontFace.CharacterToGlyphMap.TryGetValue(mirroredChar, out currGlyph) ?
                        currGlyph : (ushort)0; 
                ushort glyphFlags = ShapingWorkspace.GlyphFlagsBase;
                if (currGlyph >= fontFace.GlyphCount) 
                { 
                     // invalid glyph index (too big to be valid), so just hide it.
                     glyphFlags |= (ushort)GlyphFlags.ZeroWidth; 
                     currGlyph = fontFace.BlankGlyphIndex;
                }
                glyphIndices[charIx] =  currGlyph;
                glyphProperties[charIx] = 
                    new GlyphShapingProperties( glyphFlags,
                                                 (ushort)(1 << 8)); 
            } 

            glyphCount = charCount ; 
            return true;
        }
    }
 

 
 
    /// 
    /// Default implementation of control code shape 
    /// 
    internal class ControlShape : DefaultShape.CmapShaper, IShapingEngine
    {
        internal ControlShape() 
        {
        } 
 
        public ScriptTags[] SupportedScripts
        { 
            get { return new ScriptTags[]{ Script.TagControl }; }
        }

        public IShaper this[ItemFlags flags] 
        {
            get 
            { 
                return (flags & ItemFlags.HasExtendedCharacter) != 0 ?
                        DefaultShape.SurrogateShaper as IShaper : this; 
            }
        }

        ///  
        /// ControlShape.OnLoadFont - IShapingEngine method override.
        ///  
        /// True if font supports script. 
        public bool OnLoadFont(ScriptTags scriptTag, GlyphTypeface fontFace, out object shapeState)
        { 
            shapeState = null;
            return true;
        }
 
        /// 
        ///     ControlShape.GetGlyphs - Mirroring IShaper method. 
        ///     This method returns a list of glyphs, a character-to-glyph map, and 
        ///     a cluster map.
        ///  
        /// 
        /// 
        /// 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]
        public unsafe override 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
            ) 
        {
            bool displayControlChars = ((shapingFlags & ShapingOptions.DisplayControlCode) != 0); 
 
            // unpack the pointer containers and keep track of our pointer
            char *pChars = chars.Probe(0, charCount); 
            CharacterShapingProperties *pCharProps = charProperties.Probe(0, charCount);
            ushort *pClusters = charClusterMap.Probe(0, charCount);

            // create output arrays 
            glyphIndices    = new ushort[charCount];
            glyphProperties = new GlyphShapingProperties[charCount]; 
 
            // these glyphs are used alot
            ushort currGlyph; 
            ushort blankGlyph;
            ushort zwnjGlyph;
            blankGlyph =
                fontFace.CharacterToGlyphMap.TryGetValue(UnicodeCharacter.Space, 
                                                         out currGlyph) ?
                currGlyph : (ushort) 0; 
            zwnjGlyph = 
                fontFace.CharacterToGlyphMap.TryGetValue(UnicodeCharacter.ZWNJ,
                                                         out currGlyph) ? 
                currGlyph : (ushort) 0;

            // fill the arrays
            for(ushort charIx = 0; charIx < charCount; charIx++) 
            {
                char currChar = pChars[charIx]; 
 
                // the character properties
                bool canGlyphAlone = (Classification.CharAttributeOf( 
                    (int)Classification.GetUnicodeClassUTF16(currChar)).Flags &
                    (ushort)CharacterAttributeFlags.CharacterSpace) != 0;

                pCharProps[charIx].CanGlyphAlone = canGlyphAlone; 
                pCharProps[charIx].EngineReserved= 0;
 
                // the cluster map (all clusters are one character) 
                pClusters[charIx] = charIx;
 
                // the glyphs and their properties
                ushort glyphFlags = (ushort)ShapingWorkspace.GlyphFlagsBase;
                if( IsC0( (int)currChar ) || displayControlChars )
                { 
                    // check for missing glyph
                    if (!fontFace.CharacterToGlyphMap.TryGetValue(currChar,out currGlyph)) 
                    { 
                        // IsDefaultHidden is true for some core control code that never
                        // display.  For other missing control codes, display with the 
                        // ZWNJ glyph.
                        currGlyph = IsDefaultHidden( (int)currChar ) ? blankGlyph : zwnjGlyph;
                        glyphFlags |= (ushort)GlyphFlags.ZeroWidth;
                    } 
                }
                else 
                { 
                    currGlyph = blankGlyph;      // default is to hide control chars
                    glyphFlags = (ushort)ShapingWorkspace.GlyphFlagsZeroWidth; 
                }
                if (currGlyph >= fontFace.GlyphCount)
                {
                     // invalid glyph index (too big to be valid), so just hide it. 
                     glyphFlags |= (ushort)GlyphFlags.ZeroWidth;
                     currGlyph = blankGlyph; 
                } 
                glyphIndices[charIx] =  currGlyph;
                glyphProperties[charIx] = 
                    new GlyphShapingProperties( glyphFlags,
                                                 (ushort)(1 << 8));
            }
 
            glyphCount = charCount ;
            return true; 
        } 

        private const int ZWNJ = 0x200c; 

        private bool IsC0(int ch)
        {
            return ch < 0x0020; 
        }
 
        private bool IsDefaultHidden(int ch) 
        {
            // For 0x001c...0x001f (FS, GS, RS, US), TAB, CR and LF, 
            // we'll never display them as missing glyph
            return IsC0(ch) && (ch >= 0x001c || ch == 9 || ch == 10 || ch == 13);
        }
    } 

} 

// 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