FontClient.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / MS / Internal / Shaping / FontClient.cs / 1 / FontClient.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
{

    ///  
    ///     OpenTypeFontClient  provides the shaping engines' font/OTLS interface
    ///  
    ///  
    ///     Provides IOpenTypeFont interface for shaping engine.  Also keeps
    ///     some basic char-to-glyph mappings as well as exposes the font's 
    ///     cmap via an indexer.
    /// 
    internal class OpenTypeFontClient : IOpenTypeFont
    { 
        public OpenTypeFontClient(GlyphTypeface fontFace)
        { 
            Invariant.Assert(fontFace != null, "Null font face."); 

            _fontFace = fontFace; 
            _cmap   = _fontFace.CharacterToGlyphMap;
            Invariant.Assert(_cmap != null, "Null char map");

            _maxValidGlyphIx = _fontFace.GlyphCount > 1 ? _fontFace.GlyphCount - 1 : 0; 
        }
 
 
        internal IDictionary CMap
        { 
            get { return _cmap; }
        }

        internal GlyphTypeface             FontFace 
        {
            get { return _fontFace; } 
        } 

        internal ushort                    GetMaxGlyphId 
        {
            get { return (ushort)_maxValidGlyphIx; }
        }
 
        /// 
        /// IOpenTypeFont implemention - Returns array containing font table data 
        /// Return empty array if table does not exist. 
        /// 
        ///  
        /// Critical - as this accesses FontFaceLayoutInfo.Gdef which exposes font info.
        /// 
        [SecurityCritical]
        public unsafe FontTable GetFontTable(OpenTypeTags TableTag) 
        {
            switch (TableTag) 
            { 
                case OpenTypeTags.GDEF:
                    if (_GdefTable == null) _GdefTable = new FontTable(_fontFace.FontFaceLayoutInfo.Gdef()); 
                    return _GdefTable;
                case OpenTypeTags.GSUB:
                    if (_GsubTable == null) _GsubTable = new FontTable(_fontFace.FontFaceLayoutInfo.Gsub());
                    return _GsubTable; 
                case OpenTypeTags.GPOS:
                    if (_GposTable == null) _GposTable = new FontTable(_fontFace.FontFaceLayoutInfo.Gpos()); 
                    return _GposTable; 
            }
 
            Invariant.Assert(false,"Unexpected OpenTypeLayout table tag");
            return null;
        }
 
        /// 
        /// IOpenTypeFont implementation - Returns glyph coordinate 
        ///  
        public LayoutOffset GetGlyphPointCoord(ushort Glyph, ushort PointIndex)
        { 
            return new LayoutOffset(0,0);
        }

        ///  
        /// Returns cache for layout table. If cache not found, return null Checked pointer
        ///  
        /// Tag for the table requested 
        /// 
        ///   Critical:    Calls critical code 
        ///  
        [SecurityCritical]
        public CheckedPointer GetTableCache(OpenTypeTags tableTag)
        { 
            return _fontFace.FontFaceLayoutInfo.GetTableCache(tableTag);
        } 
 
        /// 
        /// Allocate space for layout table cache. If space is not available 
        /// return null checked pointer.
        /// Only font cache implementation need to implement this interface.
        /// Normal layout funcitons will not call it.
        ///  
        /// 
        ///   Critical:    Calls critical code 
        ///   
        [SecurityCritical]
        public CheckedPointer AllocateTableCache(OpenTypeTags tableTag, int size) 
        {
            return _fontFace.FontFaceLayoutInfo.AllocateTableCache(tableTag, size);
        }
 
        // private data
        private GlyphTypeface _fontFace; 
        private FontTable     _GposTable; 
        private FontTable     _GsubTable;
        private FontTable     _GdefTable; 

        private int            _maxValidGlyphIx;

        private IDictionary _cmap; 

 
    } 

 
    /// 
    ///     DependentCharacterList - used to define any decompositions needed for composite chars in a script
    /// 
    ///  
    /// 
    internal struct DependentCharacterList 
    { 
        char _keyChar;
        char[] _listElements; 

        public DependentCharacterList (char keyChar, char[] dependentElements)
        {
            _keyChar = keyChar; 
            _listElements = dependentElements;
        } 
 
        public char BaseChar
        { 
            get { return _keyChar; }
        }

        public char[] DependentCharacters 
        {
            get { return _listElements; } 
        } 

 
    };


    ///  
    ///     ShaperCharMapper - each font/script has its own char classifier
    ///  
    ///  
    ///     A ShaperCharacterClassifier is created during the IShapingEngine.OnLoadFont interface
    ///     methods and is then passed as a parameter for all IShaper methods. 
    /// 
    internal class ShaperCharacterClassifier : IScriptCharConverter
    {
 

        protected char   _firstChar; // this should be set to the scirpt's first Unicode char 
        protected char   _lastChar; // this should be set to the script's last Unicode char 
        protected ushort _xorMask; // this mask is used in GetCharShapeInfo (0x7f is the most common value)
        protected ushort _xorRange; // this is used in GetCharShapeInfo (0x80 is the most common value) 

        protected byte[]  _charClassTable; // this shaper's character classification table

        protected byte _spaceClass; 
        protected byte _shyClass;
        protected byte _zwjClass; 
        protected byte _zwnjClass; 
        protected byte _zwControlClass;
        protected byte _unknownClass; 

        private ScriptTags _scriptTag;
        private GlyphTypeface _fontFace;
 
        // these glyphs might be used to find/suppress Unicode control chars.
//            private ushort _noBreakSpaceGlyph;// UnicodeNoBreakSpace  =   '\u00A0'; // space character 
//            private ushort _zwspGlyph;        // UnicodeZWSP          =   '\u200B'; // zero-width non-joining mark 
        private ushort _shyGlyph;         // UnicodeSHY           =   '\u00AD'; // soft hyphen character
        private ushort _zwnjGlyph;        // UnicodeZWNJ          =   '\u200C'; // zero-width non-joining mark 
        private ushort _zwjGlyph;         // UnicodeZWJ           =   '\u200D'; // zero-width joining mark
        private ushort _lrmGlyph;         // UnicodeLRM           =   '\u200E'; // left to right mark
        private ushort _rlmGlyph;         // UnicodeRLM           =   '\u200F'; // right to left mark
 

 
        public ShaperCharacterClassifier(ScriptTags scriptTag, GlyphTypeface fontFace) 
        {
            _scriptTag = scriptTag; 
            _fontFace = fontFace;
        }

 
        /// 
        /// ToGlyph - returns the glyph for the requested unicode 
        ///  
        public ushort ToGlyph ( char unicodeChar )
        { 
            ushort glyphIndex;
            return _fontFace.CharacterToGlyphMap.TryGetValue(unicodeChar, out glyphIndex) ?
                    glyphIndex : (ushort)0;
        } 

 
        ///  
        /// Returns the shape info for the unicode character
        ///  
        public virtual CharShapeInfo ToShapeInfo (char unicodeChar)
        {
            if (_charClassTable != null && ((ushort)unicodeChar ^ _xorMask) < _xorRange)
            { 
                return  (CharShapeInfo)_charClassTable[unicodeChar - _firstChar];
            } 
            else if (unicodeChar == UnicodeCharacter.Space || unicodeChar == UnicodeCharacter.NoBreakSpace) 
            {
                return CharShapeInfo.IsStartOfCluster | (CharShapeInfo)_spaceClass; 
            }
            else if ( (unicodeChar ^ UnicodeCharacter.RLM) < 5 ||  unicodeChar == '\ufeff')
            {
                return (CharShapeInfo.IsUnicodeLayoutControl | (CharShapeInfo) 
                         (unicodeChar == UnicodeCharacter.ZWNJ ? _zwnjClass :
                          (unicodeChar == UnicodeCharacter.ZWJ ? _zwjClass : _zwControlClass))) ; 
            } 
            else if ( unicodeChar == UnicodeCharacter.SHY)
            { 
                return (CharShapeInfo)_shyClass;
            }

 
            return CharShapeInfo.IsStartOfCluster | (CharShapeInfo)_unknownClass;
        } 
 

        ///  
        /// SetUnicodeControlGlyph - called to save local copy of pertinent glyph ids
        /// 
        /// 
        ///            This function is called by ShapingWorkspace (via ShaperFontClient) 
        ///            when a Unicode control character is detected in the text run.
        ///            This allows us to cache the glyph id for use in IsUnicodeControlGlyph 
        ///            (which may be used to suppress the display of Unicode control 
        ///            characters).  This function may be overridden for those scripts
        ///            that have a more extensive list of control characters 
        ///            (see MongolianCharacterClassifier)
        /// 
        public virtual void SetUnicodeControlGlyph (char unicodeChar, ushort glyph)
        { 

            if (glyph != 0) 
            { 
              switch (unicodeChar)
              { 
                case UnicodeCharacter.LRM:
                    _lrmGlyph = glyph;
                    break;
                case UnicodeCharacter.RLM: 
                    _rlmGlyph = glyph;
                    break; 
                case UnicodeCharacter.ZWJ: 
                    _zwjGlyph = glyph;
                    break; 
                case UnicodeCharacter.ZWNJ:
                    _zwnjGlyph = glyph;
                    break;
                case UnicodeCharacter.SHY: 
                    _shyGlyph = glyph;
                    break; 
                default: 
                    break;
              } 
            }

        }
 
        /// 
        /// IsUnicodeControlGlyph - called to determine of the glyph is a recognized Unicode control 
        ///  
        /// 
        ///            This function is called by ShapingWorkspace when it is desired to 
        ///            suppress the display of Unicode control characters.  This
        ///            function may be overridden for those scripts that have a more
        ///            extensive list of control characters (see MongolianCharacterClassifier)
        ///  
        public virtual bool IsUnicodeControlGlyph( ushort glyph )
        { 
            if (glyph != 0) 
            {
                if (glyph == _zwjGlyph || 
                    glyph == _zwnjGlyph ||
                    glyph == _rlmGlyph ||
                    glyph == _lrmGlyph)
                { 
                    return true;
                } 
            } 

            return false; 
        }

        /// 
        /// GetDependentCharacterList - returns the character list by the base key character 
        ///     (if one exists)
        ///  
        protected char[] GetDependentCharacterList ( char unicodeChar, DependentCharacterList[] componentList ) 
        {
            if (componentList!= null) 
            {
                for (int i = 0; i < componentList.Length; ++i)
                {
                    if (componentList[i].BaseChar == unicodeChar) 
                    {
                        return componentList[i].DependentCharacters; 
                    } 
                }
            } 

            return null;
        }
 
    }
 
    ///  
    ///     ShaperFontClient -instantiates the font/OTLS interface and the char classifier
    ///  
    /// 
    ///     A ShaperFontClient is created during the IShapingEngine.OnLoadFont interface
    ///     methods and is then passed as a parameter for all IShaper methods.  This
    ///     extension of the OpenTypeFontClient class contains all the properties and 
    ///     methods a shaping engine will need from the font.
    ///  
    internal class ShaperFontClient : OpenTypeFontClient 
    {
        private ShaperCharacterClassifier   _charConverter; 
        private bool                        _isScriptSupportedByFont;
        private OpenTypeLayoutResult        _initResult;
        private OpenTypeLayoutWorkspace     _layoutWorkspace;
 
        private uint                        _langSysTag;
        protected uint                      _scriptTag; 
 
        private ushort _spaceGlyph;         // UnicodeSpace =   '\u0020'; // space character
        private ushort _dottedCircleGlyph;  // UnicodeDottedCircle  =   '\u25CC'; // inserted base character 


        internal ShaperFontClient(GlyphTypeface fontFace) : base(fontFace)
        { 
            // This constructor is used by shapers that don't care whether
            // the font support the script  (ie, DefaultShape) because they 
            // don't use the OpenType tables 
            _charConverter = new ShaperCharacterClassifier ((ScriptTags)0, fontFace);
            _isScriptSupportedByFont = false; 

            _scriptTag   = (uint) ScriptTags.Default;
            _langSysTag  = (uint) LanguageTags.Default;
 
        }
 
        internal ShaperFontClient(GlyphTypeface fontFace, ShaperCharacterClassifier charConverter) : base(fontFace) 
        {
            // This constructor is used by all the complex script shapers that 
            // require the use of OpenType tables to shape text in the script
            _charConverter = charConverter;
            _isScriptSupportedByFont = true;
 
            _scriptTag   = (uint) ScriptTags.Default;
            _langSysTag  = (uint) LanguageTags.Default; 
 
        }
 
        internal IScriptCharConverter       CharConverter
        {
            get { return _charConverter; }
        } 

        ///  
        /// Critical - calls critical code, passes pointer parameters 
        /// 
        public ushort                               DottedCircleGlyph 
        {
            [SecurityCritical]
            get {  if (_dottedCircleGlyph == 0)
                   { 
                      _dottedCircleGlyph =  CharConverter.ToGlyph(UnicodeCharacter.DottedCircle);
                   } 
                   return _dottedCircleGlyph; 
                }
 
        }

        public virtual ScriptTags ToScriptTag (ScriptID scriptID)
        { 

            return Script.ToTag(scriptID); 
        } 

          ///  
          /// ShaperFontClient.Initialize - initializer
          /// 
          /// 
          /// Critical - The method reads raw font table bits (i.e. FindLangSys()). 
          /// 
          [SecurityCritical] 
          public virtual bool Initialize( 
                          OpenTypeLayoutWorkspace layoutWorkspace,
                          OpenTypeTags            featureType, 
                          ScriptID                scriptID,
                          LanguageTags            langSysTag
                          )
          { 
              //  Get the language & script ID to be used for the shaping process. If defined values are null
              //  default tags for language and script id are used. 
              _scriptTag   = (uint) ToScriptTag(scriptID); 
              _langSysTag  = (uint) langSysTag;
 
              _initResult = OpenTypeLayoutResult.Success;

              if (_isScriptSupportedByFont)
              { 
                  TagInfoFlags featureClass = (featureType == OpenTypeTags.GSUB ?
                      TagInfoFlags.Substitution : TagInfoFlags.Positioning); 
 
                  if( (OpenTypeLayout.FindLangSys(this, _scriptTag, _langSysTag) &
                           featureClass)  != featureClass ) 
                  {
                      _langSysTag  = (uint)LanguageTags.Default;

                      //  Check font for language system, if not supported, try to check for Default Language system 
                      if((OpenTypeLayout.FindLangSys(this, _scriptTag, _langSysTag) & featureClass)
                               != featureClass) 
                      { 
                          _initResult = OpenTypeLayoutResult.LangSysNotFound;
                      } 
                  }

                  if (_initResult == OpenTypeLayoutResult.Success)
                  { 
                    _layoutWorkspace = layoutWorkspace;
                    _initResult = layoutWorkspace.Init( this, 
                                                     featureType, 
                                                     _scriptTag,
                                                     _langSysTag ); 
                  }

              }
 
              return (_initResult == OpenTypeLayoutResult.Success);
          } 
 
         public bool                         IsScriptSupportedByFont
         { 
             get { return _isScriptSupportedByFont; }
             set { _isScriptSupportedByFont = value; }
         }
 
         public bool                         IsFeatureTypeSupportedByFont
         { 
             get { return _isScriptSupportedByFont && _initResult == OpenTypeLayoutResult.Success; } 
         }
 
         public bool IsUnicodeControlGlyph( ushort glyph )
         {
            return _charConverter.IsUnicodeControlGlyph(glyph);
         } 

         ///  
         /// Critical - calls critical code, passes pointer parameters 
         /// 
         [SecurityCritical] 
         public bool IsUnicodeSpaceGlyph( ushort glyph )
         {
            if (_spaceGlyph == 0)
            { 
                _spaceGlyph = _charConverter.ToGlyph(UnicodeCharacter.Space);
            } 
 
            return (glyph != 0 && _spaceGlyph == glyph);
         } 

         /// 
         ///    ShaperFontClient.PositionGlyphs - 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.
         /// count of gpos features in array to be applied. 
         /// result of applying features 
         /// 
         /// Critical - calls critical code, passes pointer parameters 
         /// 
         [SecurityCritical]
         unsafe public OpenTypeLayoutResult PositionGlyphs(
                 ref PlacementWorkspace   placementInfo, 
                 ref LayoutMetrics   layoutMetrics,
                 Feature[]           features, 
                 int                 featuresCount ) 
         {
            if ( !IsFeatureTypeSupportedByFont ) 
            {
                return _initResult;
            }
 
             UshortList charMap = placementInfo.CharMap;
 
             OpenTypeLayoutResult layoutResult = OpenTypeLayout.PositionGlyphs( 
                         this,       // In: Font access interface
                         _layoutWorkspace,  // In/out: Workspace for OTL internal use 
                         _scriptTag,        // In: Script tag
                         _langSysTag,       // In: LangSys tag
                         layoutMetrics,
                         features,          // In: List of features to apply 
                         featuresCount,
                         0, 
                         charMap.Length,       // Char count (i.e. charmaps Length); 
                         charMap,          // In/out: Char to glyph mapping
                         placementInfo.GlyphInfoList,    // In/out: List of GlyphInfo structs 
                         placementInfo.GlyphAdvances,
                         (LayoutOffset *)placementInfo.GlyphOffsets);

             return layoutResult; 
         }
 
          public uint ScriptTag 
          {
              get { return _scriptTag; } 
          }

          public void SetUnicodeControlGlyph (char unicodeChar, ushort glyph)
          { 
              _charConverter.SetUnicodeControlGlyph(unicodeChar, glyph);
          } 
 
          /// 
          /// Critical - calls critical code, passes pointer parameters 
          /// 
          public ushort                               SpaceGlyph
          {
              [SecurityCritical] 
              get {  if (_spaceGlyph == 0)
                     { 
                        _spaceGlyph =  CharConverter.ToGlyph(UnicodeCharacter.Space); 
                     }
                     return _spaceGlyph; 
                  }

          }
 

          ///  
          ///     ShaperFontClient.SubstituteGlyphs - GetGlyphs() helper function. 
          /// 
          ///  
          /// 
          /// current run of glyphs.
          /// Set of gsub features.
          /// count of gpos features in array to be applied. 
          /// result of applying features
          ///  
          /// Critical - calls critical code 
          /// 
          [SecurityCritical] 
          public OpenTypeLayoutResult SubstituteGlyphs(
                      ref ShapingWorkspace currentRun,
                      Feature[]           features,
                      int                 featuresCount ) 
          {
 
              return SubstituteGlyphs(features, 
                                      featuresCount,
                                      currentRun.CharMap, 
                                      currentRun.GlyphInfoList);
          }

          ///  
          ///     ShaperFontClient.SubstituteGlyphs - GetGlyphs() helper function.
          ///  
          ///  
          /// 
          /// Set of gsub features. 
          /// count of gpos features in array to be applied.
          /// current charMap (mapping a glyph to each character).
          /// current run of glyphs.
          /// result of applying features 
          /// 
          /// Critical - calls critical code 
          ///  
          [SecurityCritical]
          public OpenTypeLayoutResult SubstituteGlyphs( 
                      Feature[]           features,
                      int                 featuresCount,
                      UshortList          charMap,
                      GlyphInfoList       glyphs) 
          {
              if ( !IsFeatureTypeSupportedByFont) 
              { 
                  return _initResult;
              } 


              OpenTypeLayoutResult layoutResult = OpenTypeLayout.SubstituteGlyphs(
                          this,        // In: Font access interface 
                          _layoutWorkspace,   // In/out: Workspace for OTL internal use
                          _scriptTag,         // In: Script tag 
                          _langSysTag,        // In: LangSys tag 
                          features,           // In: List of features to apply
                          featuresCount, 
                          0,
                          charMap.Length,     // Char count (i.e. charmaps Length);
                          charMap,            // In/out: Char to glyph mapping
                          glyphs);            // In/out: List of GlyphInfo structs 

 
              return layoutResult; 
          }
 

    }

} 


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

    ///  
    ///     OpenTypeFontClient  provides the shaping engines' font/OTLS interface
    ///  
    ///  
    ///     Provides IOpenTypeFont interface for shaping engine.  Also keeps
    ///     some basic char-to-glyph mappings as well as exposes the font's 
    ///     cmap via an indexer.
    /// 
    internal class OpenTypeFontClient : IOpenTypeFont
    { 
        public OpenTypeFontClient(GlyphTypeface fontFace)
        { 
            Invariant.Assert(fontFace != null, "Null font face."); 

            _fontFace = fontFace; 
            _cmap   = _fontFace.CharacterToGlyphMap;
            Invariant.Assert(_cmap != null, "Null char map");

            _maxValidGlyphIx = _fontFace.GlyphCount > 1 ? _fontFace.GlyphCount - 1 : 0; 
        }
 
 
        internal IDictionary CMap
        { 
            get { return _cmap; }
        }

        internal GlyphTypeface             FontFace 
        {
            get { return _fontFace; } 
        } 

        internal ushort                    GetMaxGlyphId 
        {
            get { return (ushort)_maxValidGlyphIx; }
        }
 
        /// 
        /// IOpenTypeFont implemention - Returns array containing font table data 
        /// Return empty array if table does not exist. 
        /// 
        ///  
        /// Critical - as this accesses FontFaceLayoutInfo.Gdef which exposes font info.
        /// 
        [SecurityCritical]
        public unsafe FontTable GetFontTable(OpenTypeTags TableTag) 
        {
            switch (TableTag) 
            { 
                case OpenTypeTags.GDEF:
                    if (_GdefTable == null) _GdefTable = new FontTable(_fontFace.FontFaceLayoutInfo.Gdef()); 
                    return _GdefTable;
                case OpenTypeTags.GSUB:
                    if (_GsubTable == null) _GsubTable = new FontTable(_fontFace.FontFaceLayoutInfo.Gsub());
                    return _GsubTable; 
                case OpenTypeTags.GPOS:
                    if (_GposTable == null) _GposTable = new FontTable(_fontFace.FontFaceLayoutInfo.Gpos()); 
                    return _GposTable; 
            }
 
            Invariant.Assert(false,"Unexpected OpenTypeLayout table tag");
            return null;
        }
 
        /// 
        /// IOpenTypeFont implementation - Returns glyph coordinate 
        ///  
        public LayoutOffset GetGlyphPointCoord(ushort Glyph, ushort PointIndex)
        { 
            return new LayoutOffset(0,0);
        }

        ///  
        /// Returns cache for layout table. If cache not found, return null Checked pointer
        ///  
        /// Tag for the table requested 
        /// 
        ///   Critical:    Calls critical code 
        ///  
        [SecurityCritical]
        public CheckedPointer GetTableCache(OpenTypeTags tableTag)
        { 
            return _fontFace.FontFaceLayoutInfo.GetTableCache(tableTag);
        } 
 
        /// 
        /// Allocate space for layout table cache. If space is not available 
        /// return null checked pointer.
        /// Only font cache implementation need to implement this interface.
        /// Normal layout funcitons will not call it.
        ///  
        /// 
        ///   Critical:    Calls critical code 
        ///   
        [SecurityCritical]
        public CheckedPointer AllocateTableCache(OpenTypeTags tableTag, int size) 
        {
            return _fontFace.FontFaceLayoutInfo.AllocateTableCache(tableTag, size);
        }
 
        // private data
        private GlyphTypeface _fontFace; 
        private FontTable     _GposTable; 
        private FontTable     _GsubTable;
        private FontTable     _GdefTable; 

        private int            _maxValidGlyphIx;

        private IDictionary _cmap; 

 
    } 

 
    /// 
    ///     DependentCharacterList - used to define any decompositions needed for composite chars in a script
    /// 
    ///  
    /// 
    internal struct DependentCharacterList 
    { 
        char _keyChar;
        char[] _listElements; 

        public DependentCharacterList (char keyChar, char[] dependentElements)
        {
            _keyChar = keyChar; 
            _listElements = dependentElements;
        } 
 
        public char BaseChar
        { 
            get { return _keyChar; }
        }

        public char[] DependentCharacters 
        {
            get { return _listElements; } 
        } 

 
    };


    ///  
    ///     ShaperCharMapper - each font/script has its own char classifier
    ///  
    ///  
    ///     A ShaperCharacterClassifier is created during the IShapingEngine.OnLoadFont interface
    ///     methods and is then passed as a parameter for all IShaper methods. 
    /// 
    internal class ShaperCharacterClassifier : IScriptCharConverter
    {
 

        protected char   _firstChar; // this should be set to the scirpt's first Unicode char 
        protected char   _lastChar; // this should be set to the script's last Unicode char 
        protected ushort _xorMask; // this mask is used in GetCharShapeInfo (0x7f is the most common value)
        protected ushort _xorRange; // this is used in GetCharShapeInfo (0x80 is the most common value) 

        protected byte[]  _charClassTable; // this shaper's character classification table

        protected byte _spaceClass; 
        protected byte _shyClass;
        protected byte _zwjClass; 
        protected byte _zwnjClass; 
        protected byte _zwControlClass;
        protected byte _unknownClass; 

        private ScriptTags _scriptTag;
        private GlyphTypeface _fontFace;
 
        // these glyphs might be used to find/suppress Unicode control chars.
//            private ushort _noBreakSpaceGlyph;// UnicodeNoBreakSpace  =   '\u00A0'; // space character 
//            private ushort _zwspGlyph;        // UnicodeZWSP          =   '\u200B'; // zero-width non-joining mark 
        private ushort _shyGlyph;         // UnicodeSHY           =   '\u00AD'; // soft hyphen character
        private ushort _zwnjGlyph;        // UnicodeZWNJ          =   '\u200C'; // zero-width non-joining mark 
        private ushort _zwjGlyph;         // UnicodeZWJ           =   '\u200D'; // zero-width joining mark
        private ushort _lrmGlyph;         // UnicodeLRM           =   '\u200E'; // left to right mark
        private ushort _rlmGlyph;         // UnicodeRLM           =   '\u200F'; // right to left mark
 

 
        public ShaperCharacterClassifier(ScriptTags scriptTag, GlyphTypeface fontFace) 
        {
            _scriptTag = scriptTag; 
            _fontFace = fontFace;
        }

 
        /// 
        /// ToGlyph - returns the glyph for the requested unicode 
        ///  
        public ushort ToGlyph ( char unicodeChar )
        { 
            ushort glyphIndex;
            return _fontFace.CharacterToGlyphMap.TryGetValue(unicodeChar, out glyphIndex) ?
                    glyphIndex : (ushort)0;
        } 

 
        ///  
        /// Returns the shape info for the unicode character
        ///  
        public virtual CharShapeInfo ToShapeInfo (char unicodeChar)
        {
            if (_charClassTable != null && ((ushort)unicodeChar ^ _xorMask) < _xorRange)
            { 
                return  (CharShapeInfo)_charClassTable[unicodeChar - _firstChar];
            } 
            else if (unicodeChar == UnicodeCharacter.Space || unicodeChar == UnicodeCharacter.NoBreakSpace) 
            {
                return CharShapeInfo.IsStartOfCluster | (CharShapeInfo)_spaceClass; 
            }
            else if ( (unicodeChar ^ UnicodeCharacter.RLM) < 5 ||  unicodeChar == '\ufeff')
            {
                return (CharShapeInfo.IsUnicodeLayoutControl | (CharShapeInfo) 
                         (unicodeChar == UnicodeCharacter.ZWNJ ? _zwnjClass :
                          (unicodeChar == UnicodeCharacter.ZWJ ? _zwjClass : _zwControlClass))) ; 
            } 
            else if ( unicodeChar == UnicodeCharacter.SHY)
            { 
                return (CharShapeInfo)_shyClass;
            }

 
            return CharShapeInfo.IsStartOfCluster | (CharShapeInfo)_unknownClass;
        } 
 

        ///  
        /// SetUnicodeControlGlyph - called to save local copy of pertinent glyph ids
        /// 
        /// 
        ///            This function is called by ShapingWorkspace (via ShaperFontClient) 
        ///            when a Unicode control character is detected in the text run.
        ///            This allows us to cache the glyph id for use in IsUnicodeControlGlyph 
        ///            (which may be used to suppress the display of Unicode control 
        ///            characters).  This function may be overridden for those scripts
        ///            that have a more extensive list of control characters 
        ///            (see MongolianCharacterClassifier)
        /// 
        public virtual void SetUnicodeControlGlyph (char unicodeChar, ushort glyph)
        { 

            if (glyph != 0) 
            { 
              switch (unicodeChar)
              { 
                case UnicodeCharacter.LRM:
                    _lrmGlyph = glyph;
                    break;
                case UnicodeCharacter.RLM: 
                    _rlmGlyph = glyph;
                    break; 
                case UnicodeCharacter.ZWJ: 
                    _zwjGlyph = glyph;
                    break; 
                case UnicodeCharacter.ZWNJ:
                    _zwnjGlyph = glyph;
                    break;
                case UnicodeCharacter.SHY: 
                    _shyGlyph = glyph;
                    break; 
                default: 
                    break;
              } 
            }

        }
 
        /// 
        /// IsUnicodeControlGlyph - called to determine of the glyph is a recognized Unicode control 
        ///  
        /// 
        ///            This function is called by ShapingWorkspace when it is desired to 
        ///            suppress the display of Unicode control characters.  This
        ///            function may be overridden for those scripts that have a more
        ///            extensive list of control characters (see MongolianCharacterClassifier)
        ///  
        public virtual bool IsUnicodeControlGlyph( ushort glyph )
        { 
            if (glyph != 0) 
            {
                if (glyph == _zwjGlyph || 
                    glyph == _zwnjGlyph ||
                    glyph == _rlmGlyph ||
                    glyph == _lrmGlyph)
                { 
                    return true;
                } 
            } 

            return false; 
        }

        /// 
        /// GetDependentCharacterList - returns the character list by the base key character 
        ///     (if one exists)
        ///  
        protected char[] GetDependentCharacterList ( char unicodeChar, DependentCharacterList[] componentList ) 
        {
            if (componentList!= null) 
            {
                for (int i = 0; i < componentList.Length; ++i)
                {
                    if (componentList[i].BaseChar == unicodeChar) 
                    {
                        return componentList[i].DependentCharacters; 
                    } 
                }
            } 

            return null;
        }
 
    }
 
    ///  
    ///     ShaperFontClient -instantiates the font/OTLS interface and the char classifier
    ///  
    /// 
    ///     A ShaperFontClient is created during the IShapingEngine.OnLoadFont interface
    ///     methods and is then passed as a parameter for all IShaper methods.  This
    ///     extension of the OpenTypeFontClient class contains all the properties and 
    ///     methods a shaping engine will need from the font.
    ///  
    internal class ShaperFontClient : OpenTypeFontClient 
    {
        private ShaperCharacterClassifier   _charConverter; 
        private bool                        _isScriptSupportedByFont;
        private OpenTypeLayoutResult        _initResult;
        private OpenTypeLayoutWorkspace     _layoutWorkspace;
 
        private uint                        _langSysTag;
        protected uint                      _scriptTag; 
 
        private ushort _spaceGlyph;         // UnicodeSpace =   '\u0020'; // space character
        private ushort _dottedCircleGlyph;  // UnicodeDottedCircle  =   '\u25CC'; // inserted base character 


        internal ShaperFontClient(GlyphTypeface fontFace) : base(fontFace)
        { 
            // This constructor is used by shapers that don't care whether
            // the font support the script  (ie, DefaultShape) because they 
            // don't use the OpenType tables 
            _charConverter = new ShaperCharacterClassifier ((ScriptTags)0, fontFace);
            _isScriptSupportedByFont = false; 

            _scriptTag   = (uint) ScriptTags.Default;
            _langSysTag  = (uint) LanguageTags.Default;
 
        }
 
        internal ShaperFontClient(GlyphTypeface fontFace, ShaperCharacterClassifier charConverter) : base(fontFace) 
        {
            // This constructor is used by all the complex script shapers that 
            // require the use of OpenType tables to shape text in the script
            _charConverter = charConverter;
            _isScriptSupportedByFont = true;
 
            _scriptTag   = (uint) ScriptTags.Default;
            _langSysTag  = (uint) LanguageTags.Default; 
 
        }
 
        internal IScriptCharConverter       CharConverter
        {
            get { return _charConverter; }
        } 

        ///  
        /// Critical - calls critical code, passes pointer parameters 
        /// 
        public ushort                               DottedCircleGlyph 
        {
            [SecurityCritical]
            get {  if (_dottedCircleGlyph == 0)
                   { 
                      _dottedCircleGlyph =  CharConverter.ToGlyph(UnicodeCharacter.DottedCircle);
                   } 
                   return _dottedCircleGlyph; 
                }
 
        }

        public virtual ScriptTags ToScriptTag (ScriptID scriptID)
        { 

            return Script.ToTag(scriptID); 
        } 

          ///  
          /// ShaperFontClient.Initialize - initializer
          /// 
          /// 
          /// Critical - The method reads raw font table bits (i.e. FindLangSys()). 
          /// 
          [SecurityCritical] 
          public virtual bool Initialize( 
                          OpenTypeLayoutWorkspace layoutWorkspace,
                          OpenTypeTags            featureType, 
                          ScriptID                scriptID,
                          LanguageTags            langSysTag
                          )
          { 
              //  Get the language & script ID to be used for the shaping process. If defined values are null
              //  default tags for language and script id are used. 
              _scriptTag   = (uint) ToScriptTag(scriptID); 
              _langSysTag  = (uint) langSysTag;
 
              _initResult = OpenTypeLayoutResult.Success;

              if (_isScriptSupportedByFont)
              { 
                  TagInfoFlags featureClass = (featureType == OpenTypeTags.GSUB ?
                      TagInfoFlags.Substitution : TagInfoFlags.Positioning); 
 
                  if( (OpenTypeLayout.FindLangSys(this, _scriptTag, _langSysTag) &
                           featureClass)  != featureClass ) 
                  {
                      _langSysTag  = (uint)LanguageTags.Default;

                      //  Check font for language system, if not supported, try to check for Default Language system 
                      if((OpenTypeLayout.FindLangSys(this, _scriptTag, _langSysTag) & featureClass)
                               != featureClass) 
                      { 
                          _initResult = OpenTypeLayoutResult.LangSysNotFound;
                      } 
                  }

                  if (_initResult == OpenTypeLayoutResult.Success)
                  { 
                    _layoutWorkspace = layoutWorkspace;
                    _initResult = layoutWorkspace.Init( this, 
                                                     featureType, 
                                                     _scriptTag,
                                                     _langSysTag ); 
                  }

              }
 
              return (_initResult == OpenTypeLayoutResult.Success);
          } 
 
         public bool                         IsScriptSupportedByFont
         { 
             get { return _isScriptSupportedByFont; }
             set { _isScriptSupportedByFont = value; }
         }
 
         public bool                         IsFeatureTypeSupportedByFont
         { 
             get { return _isScriptSupportedByFont && _initResult == OpenTypeLayoutResult.Success; } 
         }
 
         public bool IsUnicodeControlGlyph( ushort glyph )
         {
            return _charConverter.IsUnicodeControlGlyph(glyph);
         } 

         ///  
         /// Critical - calls critical code, passes pointer parameters 
         /// 
         [SecurityCritical] 
         public bool IsUnicodeSpaceGlyph( ushort glyph )
         {
            if (_spaceGlyph == 0)
            { 
                _spaceGlyph = _charConverter.ToGlyph(UnicodeCharacter.Space);
            } 
 
            return (glyph != 0 && _spaceGlyph == glyph);
         } 

         /// 
         ///    ShaperFontClient.PositionGlyphs - 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.
         /// count of gpos features in array to be applied. 
         /// result of applying features 
         /// 
         /// Critical - calls critical code, passes pointer parameters 
         /// 
         [SecurityCritical]
         unsafe public OpenTypeLayoutResult PositionGlyphs(
                 ref PlacementWorkspace   placementInfo, 
                 ref LayoutMetrics   layoutMetrics,
                 Feature[]           features, 
                 int                 featuresCount ) 
         {
            if ( !IsFeatureTypeSupportedByFont ) 
            {
                return _initResult;
            }
 
             UshortList charMap = placementInfo.CharMap;
 
             OpenTypeLayoutResult layoutResult = OpenTypeLayout.PositionGlyphs( 
                         this,       // In: Font access interface
                         _layoutWorkspace,  // In/out: Workspace for OTL internal use 
                         _scriptTag,        // In: Script tag
                         _langSysTag,       // In: LangSys tag
                         layoutMetrics,
                         features,          // In: List of features to apply 
                         featuresCount,
                         0, 
                         charMap.Length,       // Char count (i.e. charmaps Length); 
                         charMap,          // In/out: Char to glyph mapping
                         placementInfo.GlyphInfoList,    // In/out: List of GlyphInfo structs 
                         placementInfo.GlyphAdvances,
                         (LayoutOffset *)placementInfo.GlyphOffsets);

             return layoutResult; 
         }
 
          public uint ScriptTag 
          {
              get { return _scriptTag; } 
          }

          public void SetUnicodeControlGlyph (char unicodeChar, ushort glyph)
          { 
              _charConverter.SetUnicodeControlGlyph(unicodeChar, glyph);
          } 
 
          /// 
          /// Critical - calls critical code, passes pointer parameters 
          /// 
          public ushort                               SpaceGlyph
          {
              [SecurityCritical] 
              get {  if (_spaceGlyph == 0)
                     { 
                        _spaceGlyph =  CharConverter.ToGlyph(UnicodeCharacter.Space); 
                     }
                     return _spaceGlyph; 
                  }

          }
 

          ///  
          ///     ShaperFontClient.SubstituteGlyphs - GetGlyphs() helper function. 
          /// 
          ///  
          /// 
          /// current run of glyphs.
          /// Set of gsub features.
          /// count of gpos features in array to be applied. 
          /// result of applying features
          ///  
          /// Critical - calls critical code 
          /// 
          [SecurityCritical] 
          public OpenTypeLayoutResult SubstituteGlyphs(
                      ref ShapingWorkspace currentRun,
                      Feature[]           features,
                      int                 featuresCount ) 
          {
 
              return SubstituteGlyphs(features, 
                                      featuresCount,
                                      currentRun.CharMap, 
                                      currentRun.GlyphInfoList);
          }

          ///  
          ///     ShaperFontClient.SubstituteGlyphs - GetGlyphs() helper function.
          ///  
          ///  
          /// 
          /// Set of gsub features. 
          /// count of gpos features in array to be applied.
          /// current charMap (mapping a glyph to each character).
          /// current run of glyphs.
          /// result of applying features 
          /// 
          /// Critical - calls critical code 
          ///  
          [SecurityCritical]
          public OpenTypeLayoutResult SubstituteGlyphs( 
                      Feature[]           features,
                      int                 featuresCount,
                      UshortList          charMap,
                      GlyphInfoList       glyphs) 
          {
              if ( !IsFeatureTypeSupportedByFont) 
              { 
                  return _initResult;
              } 


              OpenTypeLayoutResult layoutResult = OpenTypeLayout.SubstituteGlyphs(
                          this,        // In: Font access interface 
                          _layoutWorkspace,   // In/out: Workspace for OTL internal use
                          _scriptTag,         // In: Script tag 
                          _langSysTag,        // In: LangSys tag 
                          features,           // In: List of features to apply
                          featuresCount, 
                          0,
                          charMap.Length,     // Char count (i.e. charmaps Length);
                          charMap,            // In/out: Char to glyph mapping
                          glyphs);            // In/out: List of GlyphInfo structs 

 
              return layoutResult; 
          }
 

    }

} 


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