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

                            //---------------------------------------------------------------------- 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2003
// 
//  File:      TibetanShape.cs
// 
//  Contents:  Implementation of Tibetan shaping engine and its factory 
//
//  Created:   02-15-2004 Nick Beal (nbeal) 
//
//-----------------------------------------------------------------------

// #define VALIDATE_CLUSTER_PARAMETERS 

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

    ///  
    /// TibetanCharClass - enumeration of Tibetan classification flags
    /// ordinal position 
    ///  
    internal enum TibetanCharClass : byte
    { 
        UnknownCharClass,     // Unknown class --
        Other,
        HeadlinePunct,        // HeadlinePunct -- accepts vowel sign
        Birga,                // Birga -- accepts no marks 
        HeadConsonant,        // HeadConsonant -- accepts many marks
        SubjoinedCons,        // SubjoinedCons -- 
        LenitionMark,         // LenitionMark -- 
        HeadConsWithFlag,     // HeadConsWithFlag -- accepts many marks
        SubjoinedConsWithFlag,// SubjoinedConsWithFlag -- 
        Achung,              // Achung --
        Shapkyu,              // Shapkyu --
        Halanta,              // Halanta
        UnderlineMark,        // UnderlineMark 
        Padma,                // Padma
        AboveVowel,           // AboveVowel -- 
        VowelSign,            // VowelSign 
        Visarga,
        TerminalPunct, 
        Digit,
        PreDigitMark,
        BelowDigitMark,
        WireDigitMark, 
        PostDigitMark,
        UnicodeZWControl, 
        NumberOfTibetanCharClasses, 

        CharClassMask = 0x1F, 
        SpecialHandlingRequired = 0x80,
        CompositeToVowel = 0x40,
        CompositeToShapkyu = 0x20,
        CompositeSubjoinedVowel = CompositeToVowel + SubjoinedCons + SpecialHandlingRequired, 
        CompositeSubjoinedShapkyu = CompositeToShapkyu + SubjoinedCons + SpecialHandlingRequired,
 
        CompositeAchungVowel = CompositeToVowel + Achung, 
        CompositeAchungShapkyu =  CompositeToShapkyu + Achung,
 
//        DecomposableFlag    = 0x80,
//        ComposedAchung = DecomposableFlag + Achung,
//        ComposedSubjoined = DecomposableFlag + SubjoinedCons
 
    };
 
    ///  
    /// The Tibetan Shaping Engine - (shapes Tibetan text)
    ///  
    /// 
    /// The IShaper and IShapingEngine interfaces are implemented to
    /// provide the shaping methods for Tibetan Scripts.
    /// There are four Tibetan private types defined/used in this class: 
    /// 1.) TibetanShapeInfo - this class manages the shape information
    /// 2.) TibetanClusterCop - this class manages the canonical ordering 
    /// 3.) TibetanFontInfo - this class manages the font interface 
    /// 4.) TibetanCharClassInfo - contains the char classification tables
    /// 
    internal sealed class TibetanShape : BaseShape
    {
        //
        // See static TibetanShape() constructor for notes and initialization. 
        //
        private static readonly Feature[]          _tibetanSubstitutionFeatures; 
        private static readonly Feature[]          _tibetanPositioningFeatures; 
        private static readonly ScriptTags[]      _supportedScripts;
 
        //--------------------------------------
        //
        //  Constructors
        // 
        //--------------------------------------
 
#region Constructors 
        /// 
        /// Static (type) constructor for the Tibetan Open Type Shaping Engine. 
        /// 
        /// 
        /// All the static members are initialized in the context of this
        /// function. 
        ///
        static TibetanShape() 
        { 
            // Tibetan Script required substitution features
            // 
            _tibetanSubstitutionFeatures =  new Feature[]
            {
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.GlyphCompositionDecomposition,1),
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.BelowBaseSubstitutions,1), 
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.AboveBaseSubstitutions,1),
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.ContextualAlternates,1), 
            }; 

 

            //
            // Positioning Features for Tibetan Script.  Note order is important (see call to
            // OpenTypeLayout.PositionGlyphs in GetGlyphPlacements below). 
            //
            _tibetanPositioningFeatures = new Feature[] 
            { 
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.BelowBaseMarkPositioning,1),
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.AboveBaseMarkPositioning,1), 
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.Kerning,1),
            };

            // 
            // Tibetan Script is only supported scripts
            // 
            _supportedScripts = new ScriptTags[] {ScriptTags.Tibetan}; 

 
        }

        /// 
        /// Constructor for the Tibetan Open Type Shaping Engine. 
        /// 
        internal TibetanShape() 
        { 
            _forceDiacriticsToZeroWidth = false;
        } 

#endregion

        //-------------------------------------- 
        //
        //  Internal Methods 
        // 
        //--------------------------------------
 
#region Internal methods
        /// 
        /// TibetanShape.SupportedScripts -
        ///  IShapingEngine member override 
        /// 
        /// Our supported scripts (Tibetan, Lao). 
        public override ScriptTags[] SupportedScripts 
        {
            get 
            {
                return _supportedScripts;
            }
        } 

        ///  
        /// MongolianShape.GetCharClassifier - Base shape 
        /// 
        ///  
        ///     This will normally be overridden by derived shapers. It is used in OnLoadFont
        /// 
        protected override ShaperCharacterClassifier GetCharClassifier(ScriptTags scriptTag, GlyphTypeface fontFace)
        { 
            return new TibetanCharClassifier (scriptTag, fontFace);
        } 
 
        /// 
        ///     TibetanShape.GetGlyphs - Tibetan implementation of the GetGlyphs() helper function. 
        /// 
        /// shaping currentRun
        /// Text item
        /// number of glyphs 
        /// 
        /// Critical - calls critical code, uses unsafe accessors and methods 
        ///  
        [SecurityCritical]
        unsafe protected override int GetGlyphs ( ref ShapingWorkspace currentRun, Item item ) 
        {

            TibetanShapeFSM stateMachine = new TibetanShapeFSM();
            stateMachine.SetStartState(); 

            // Shape and initialize the glyph list 
            // process the char stream, creating shape info 
            CharShapeInfo currShape;
            while ( currentRun.GetNextShape (out currShape) ) 
            {
                CharShapeInfo newShape = stateMachine.StepToNextState( currShape );
                if ((newShape &
                    (CharShapeInfo.RequiresInsertedBase | CharShapeInfo.RequiresSpecialHandling)) 
                                            ==  CharShapeInfo.RequiresSpecialHandling)
                { 
                    TibetanCharClass currClass = (TibetanCharClass)currShape; 

                    if ((currClass & (TibetanCharClass.CompositeToShapkyu | TibetanCharClass.CompositeToVowel)) != 0) 
                    {
                        // special handling required (this must be a "composed" achung or subjoined consonant)
                        Debug.Assert ((currClass & TibetanCharClass.CharClassMask) == TibetanCharClass.Achung ||
                                    (currClass & TibetanCharClass.CharClassMask) == TibetanCharClass.SubjoinedCons); 

                        // This character is a decomposition candidate.  We need to 
                        // break it up into 2 or 3 glyphs (depending on the unicode 
                        // char).  So, add the glyphs...
                        char currChar = currentRun.CurrentChar; 
                        ushort toBeAddedCount = (ushort)((currChar == '\u0F77' || currChar == '\u0F79') ? 2 : 1);
                        currentRun.AddGlyphs(toBeAddedCount);

                        // fill in the decomposition info for this character. 
                        switch (currChar)
                        { 
                          case '\u0f73': 
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0f71');
                              currChar = '\u0f72'; 
                              break;
                          case '\u0f75':
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0f71');
                              currChar = '\u0f74'; 
                              break;
                          case '\u0f76': 
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0fb2'); 
                              currChar = '\u0f80';
                              break; 
                          case '\u0f77':
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0fb2');
                              currentRun.SetGlyphProperties(currentRun.CharConverter.ToGlyph('\u0f71'));
                              currChar = '\u0f80'; 
                              break;
                          case '\u0f78': 
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0fb3'); 
                              currChar = '\u0f80';
                              break; 
                          case '\u0f79':
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0fb3');
                              currentRun.SetGlyphProperties(currentRun.CharConverter.ToGlyph('\u0f71'));
                              currChar = '\u0f80'; 
                              break;
                          case '\u0f81': 
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0f71'); 
                              currChar = '\u0f80';
                              break; 
                          default:
                              Debug.Assert(false,"TibetanShape - illegal decomposite char");
                              break;
                        } 

                        currentRun.SetGlyphProperties(currentRun.CharConverter.ToGlyph(currChar)); 
                        continue; 
                    }
                    else if (currClass == TibetanCharClass.PreDigitMark) 
                    {
                        // we need to swap this predigit mark with the preceding
                        // digit char.
                        ushort digitGlyph = currentRun.PreviousGlyph; 
                        if (digitGlyph != '\u0000')
                        { 
                            currentRun.PreviousGlyph = currentRun.CurrentGlyph; 
                            currentRun.SetGlyphPropertiesUsingGlyph(newShape, digitGlyph);
                            continue; 
                        }
                    }
                }
 
                // normal character to glyph processing
                currentRun.SetGlyphPropertiesUsingShapeInfo(newShape); 
            } 

            return currentRun.GlyphsCount;    // we're done 

        }

        ///  
        ///     TibetanShape.ApplySubstitutionFeatures - default implementation of the GetGlyphs() helper function.
        ///  
        /// shaping currentRun 
        /// Set of gsub features to be applied to the unicode run.
        /// result of applying features 
        /// 
        /// Critical - this method calls unsafe methods.
        /// 
        [SecurityCritical] 
        protected override OpenTypeLayoutResult ApplySubstitutionFeatures(
                                                        ref ShapingWorkspace currentRun, 
                                                        FeatureSet       featureSet  ) 
        {
            ShaperFontClient fontClient = currentRun.FontClient; 
            return fontClient.SubstituteGlyphs(
                        ref currentRun,
                        _tibetanSubstitutionFeatures,     // In: List of features to apply
                        _tibetanSubstitutionFeatures.Length ); 
        }
 
 

        ///  
        ///    TibetanShape.ApplyPositioningFeatures - generic implementation of the GetGlyphPlacement helper.
        ///     This method goes through a list of glyphs and adds placement information.
        /// 
        /// the wrapper for glyph advances, offset arrays 
        /// metrics for all the positioning features
        /// Set of gpos features to be applied to the unicode run. 
        /// result of applying features 
        /// 
        /// Critical - calls critical code 
        /// 
        [SecurityCritical]
        protected override OpenTypeLayoutResult ApplyPositioningFeatures(
                ref PlacementWorkspace   placementInfo, 
                ref LayoutMetrics   layoutMetrics,
                FeatureSet          featureSet ) 
        { 
            ShaperFontClient fontClient = placementInfo.FontClient;
            OpenTypeLayoutResult layoutResult = fontClient.PositionGlyphs( 
                        ref placementInfo,
                        ref layoutMetrics,
                        _tibetanPositioningFeatures,     // In: List of features to apply
                        _tibetanPositioningFeatures.Length ); 

            return layoutResult; 
        } 
#endregion
    } 

    /// 
    /// Class TibetanShapeFSM:
    ///  The Tibetam state machine 
    /// 
    ///  
    /// This class implements the Tibetan state machine.  The GetNextShape() routine 
    /// is the most important method, returning the corresponding shape flags for each
    /// unicode char in the text stream. 
    /// 
    internal struct TibetanShapeFSM
    {
        TibetanClusterState _previousState; 
        TibetanClusterState _currentState;
 
        CharShapeInfo       _stateShape; 

        bool             _isSubjoinedConsInCluster ; 


        internal CharShapeInfo StateShapeFlags
        { 
            get { return _stateShape; }
        } 
 
        /// 
        ///   TibetanShapeFSM.ForceInvalidBaseState - force state machine to state 
        /// 
        /// 
        ///     Tibetan state machine resets to start state when an invalid character
        ///     is detected. 
        /// 
        internal CharShapeInfo ForceInvalidBaseState () 
        { 
            _previousState = _currentState = TibetanClusterState.StartState;
            _stateShape = CharShapeInfo.RequiresInsertedBase; 

            return _stateShape;
        }
 
        internal void SetStartState()
        { 
            _previousState = _currentState = TibetanClusterState.StartState; 
            _stateShape = CharShapeInfo.NoFlagsSet;
            _isSubjoinedConsInCluster = false; 
        }

        /// 
        ///   TibetanShapeFSM.StepToNextState - process the latest character. 
        /// 
        ///  
        ///   This routine steps the state machine to its next state 
        ///   based on the current state, the last character that caused a
        ///   state change and the next char.  The current shapeState can 
        ///   be changed in some cases (thus the 'ref' designation)
        /// 
        /// state flags for current character appropriate to new state
        internal CharShapeInfo StepToNextState ( CharShapeInfo  nextCharShape ) 
        {
            TibetanCharClass tibetanCharShape = (TibetanCharClass)nextCharShape; 
            TibetanCharClass tibetanCharClass = (tibetanCharShape & TibetanCharClass.CharClassMask); 
            Debug.Assert (tibetanCharClass < TibetanCharClass.NumberOfTibetanCharClasses, "invalid tibetan char class index");
 
            _previousState = _currentState;     // save current state.

            // tableEntry is found at stateTable [ (clusterState - 1) * 24 + charClass].
            // tableIxSeed is used to facilitate the multiply by 24 (it is "(clusterState-1) X 8" 
            // and "tableIxSeed << 1" is "(clusterState-1) X 16")
            int tableIxSeed = ((int)_previousState - 1) << 3; // state index * 8 
            _stateShape = (CharShapeInfo) 
                TibetanClusterStateTable[tableIxSeed + (tableIxSeed << 1) + (int)tibetanCharClass];   // 24 entries per state.
            TibetanClusterState nextState = (TibetanClusterState)(_stateShape & CharShapeInfo.ShaperClassMask); 
            if (nextState == TibetanClusterState.NoChange)
            {
                // Since we're not changing state, we need to validate this
                // new character. 
                if (tibetanCharClass == TibetanCharClass.UnicodeZWControl ||
                    tibetanCharClass == TibetanCharClass.TerminalPunct) 
                { 
                    // this is ok, keep going
                    _stateShape = nextCharShape; 
                }
                else if (tibetanCharClass != TibetanCharClass.Shapkyu || !_isSubjoinedConsInCluster)
                {
                    // can't have multiple shapkyu chars before subjoined consonant 
                    // (we're happy to have them after the subjoined conaonant),
                    // nor any other character (if nextState == NoChange) 
                    ForceInvalidBaseState(); 
                }
            } 
            else
            {
                _currentState = nextState;
 
                if (tibetanCharShape > TibetanCharClass.NumberOfTibetanCharClasses)
                { 
                    _stateShape |= CharShapeInfo.RequiresSpecialHandling; 

                    // special cases.  The current character is a "composite" event; 
                    // it acts like a set of two characters.
                    if ((tibetanCharShape & TibetanCharClass.CompositeToShapkyu) != 0)
                    {
                        _currentState = TibetanClusterState.ConsonantWithShapkyuState; 
                    }
                    else if ((tibetanCharShape & TibetanCharClass.CompositeToVowel) != 0) 
                    { 
                        _currentState = TibetanClusterState.VowelState;
                    } 
                    else if (tibetanCharClass == TibetanCharClass.SubjoinedCons ||
                                tibetanCharClass == TibetanCharClass.SubjoinedConsWithFlag)
                    {
                        _isSubjoinedConsInCluster = true; 
                    }
                } 
            } 

            if ((_stateShape & CharShapeInfo.IsStartOfCluster) != 0) 
            {
                _isSubjoinedConsInCluster = false;
            }
 

            return _stateShape; // & CharShapeInfo.ShapeFlagsMask; 
        } 

        ///  
        /// TibetanClusterState - enumeration of Tibetan cluster states
        /// ordinal position
        /// 
        private enum TibetanClusterState : byte 
        {
            NoChange, 
            StartState, 
            HeadlineLeaderState,
            BirgaLeaderState, 
            HeadlineConsonantState,
            HeadlineConsonantWithFlagState,
                ConsonantWithAchungState,
                ConsonantWithShapkyuState, 
                SubjoinedConsonantState,
                SubjoinedConsonantWithFlagState, 
                HalantaState, 
                UnderlineMarkState,
                PadmaState, 
                VowelState,
            TerminalState,
            OtherState,
            DigitState, 
                PreDigitState,
                BelowDigitState, 
                WireDigitState, 
            NumberOfTibetanClusterStates
        }; 

        // These values are used to populate the state tables.  Each entry is a packed
        // value with the next state in the lower bits, and the shape flags in the higher
        // bits.  The GetNextShape routine unpacks these entries. 
        private const ushort NoChange      = (ushort )TibetanClusterState.NoChange;
        private const ushort InvalidBase   = (ushort)CharShapeInfo.RequiresInsertedBase; 
        private const ushort StartOfCluster = (ushort) CharShapeInfo.IsStartOfCluster; 
        private const ushort ToStartState  = (ushort )TibetanClusterState.StartState;
        private const ushort StartState  = ToStartState + StartOfCluster; 
        private const ushort HeadlineLeaderState  =
                  (ushort )TibetanClusterState.HeadlineLeaderState + StartOfCluster;
        private const ushort BirgaLeaderState  =
                  (ushort )TibetanClusterState.BirgaLeaderState + StartOfCluster; 
        private const ushort HeadlineConsonantState =
                  (ushort )TibetanClusterState.HeadlineConsonantState + StartOfCluster; 
        private const ushort HeadlineConsonantWithFlagState = 
                  (ushort )TibetanClusterState.HeadlineConsonantWithFlagState + StartOfCluster;
        private const ushort ToHeadlineConsonantState = 
                  (ushort )TibetanClusterState.HeadlineConsonantState;
        private const ushort ToHeadlineConsonantWithFlagState =
                  (ushort )TibetanClusterState.HeadlineConsonantWithFlagState;
        private const ushort ConsonantWithAchungState  = 
                  (ushort)TibetanClusterState.ConsonantWithAchungState;
        private const ushort ConsonantWithShapkyuState  = 
                  (ushort)TibetanClusterState.ConsonantWithShapkyuState; 
        private const ushort SubjoinedConsonantState  =
                  (ushort)TibetanClusterState.SubjoinedConsonantState; 
        private const ushort SubjoinedConsonantWithFlagState  =
                  (ushort)TibetanClusterState.SubjoinedConsonantState;
        private const ushort HalantaState  = (ushort )TibetanClusterState.HalantaState;
        private const ushort UnderlineMarkState  = (ushort )TibetanClusterState.UnderlineMarkState; 
        private const ushort PadmaState  = (ushort )TibetanClusterState.PadmaState;
        private const ushort VowelState  = (ushort )TibetanClusterState.VowelState; 
 
        private const ushort DigitState  =
                (ushort )TibetanClusterState.DigitState + StartOfCluster; 
        private const ushort PreDigitState  = (ushort )TibetanClusterState.PreDigitState;
        private const ushort BelowDigitState  = (ushort )TibetanClusterState.BelowDigitState;
        private const ushort WireDigitState  = (ushort )TibetanClusterState.WireDigitState;
 
        private const ushort OtherState  =
                (ushort )TibetanClusterState.OtherState + StartOfCluster; 
        private const ushort TerminalState  = 
                (ushort )TibetanClusterState.TerminalState + StartOfCluster;
 
        // The syllable state machine state table.  For each current state
        // there are 24 entries - one for each char class - so that the first
        // entry for any current state can be found at "current state / 24 "
        private static readonly ushort[] TibetanClusterStateTable  = //new TibetanSyllableState[] 
        {
            // State Table Entry            Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign 
            StartState | InvalidBase,    // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 
            // HeadlineLeaderState          Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark 
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            ToStartState,                // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // BirgaLeaderState          Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark 
            ToStartState,                // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // HeadlineConsonantState     Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            ToHeadlineConsonantWithFlagState, // LenitionMark
            HeadlineConsonantWithFlagState,   // HeadConsWithFlag 
            SubjoinedConsonantState,     // SubjoinedConsWithFlag
            ConsonantWithAchungState,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu 
            HalantaState,                // Halanta
            UnderlineMarkState,          // UnderlineMark 
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign
            ToStartState,                // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // HeadlineConsonantWithFlagState     Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantWithFlagState,   // HeadConsWithFlag 
            SubjoinedConsonantState,     // SubjoinedConsWithFlag
            ConsonantWithAchungState,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu 
            HalantaState,                // Halanta
            UnderlineMarkState,          // UnderlineMark 
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign
            ToStartState,                // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // ConsonantWIthAchungState     Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            SubjoinedConsonantState,     // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu 
            HalantaState,                // Halanta
            UnderlineMarkState,          // UnderlineMark 
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign
            ToStartState,                // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // ConsonantWithShapkyuState     Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            SubjoinedConsonantState,     // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            NoChange,                    // Shapkyu 
            HalantaState,                // Halanta
            UnderlineMarkState,          // UnderlineMark 
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign
            ToStartState,                // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 

            // SubjoinedConsonantState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            SubjoinedConsonantWithFlagState,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            SubjoinedConsonantState,     // SubjoinedConsWithFlag 
            ConsonantWithAchungState,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu
            HalantaState,                // Halanta 
            UnderlineMarkState,          // UnderlineMark
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // SubjoinedConsonantWithFlagState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            SubjoinedConsonantWithFlagState, // SubjoinedConsWithFlag 
            ConsonantWithAchungState,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu
            HalantaState,                // Halanta 
            UnderlineMarkState,          // UnderlineMark
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // HalantaState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            UnderlineMarkState,          // UnderlineMark
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // UnderlineMarkState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,          // UnderlineMark
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // PadmaState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,          // UnderlineMark
            StartState | InvalidBase,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // VowelState                 Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // TerminalState                Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign 
            StartState | InvalidBase,    // Visarga
            NoChange,                    // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

 
            // OtherState                 Input Char Class 
            StartState,                  // Unknown
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons 
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark
            ToStartState,                // Padma
            StartState | InvalidBase,    // AboveVowel 
            StartState | InvalidBase,    // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl 

 
 
            // DigitState                 Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant 
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma 
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign 
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            PreDigitState,               // PreDigitMark
            BelowDigitState,             // BelowDigitMark
            WireDigitState,              // WireDigitMark
            ToStartState,                // PostDigitMark 
            NoChange,                    // UnicodeZWControl
 
            // PreDigitState                 Input Char Class 
            StartState,                  // Unknown
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons 
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel 
            StartState | InvalidBase,    // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit
            StartState | InvalidBase,    // PreDigitMark 
            BelowDigitState,             // BelowDigitMark
            WireDigitState,              // WireDigitMark
            ToStartState,                // PostDigitMark
            NoChange,                    // UnicodeZWControl 

            // BelowDigitState                 Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign 
            StartState | InvalidBase,    // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            BelowDigitState,             // BelowDigitMark 
            WireDigitState,              // WireDigitMark
            ToStartState,                // PostDigitMark
            NoChange,                    // UnicodeZWControl
 
            // WireDigitState                 Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark 
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            ToStartState,                // PostDigitMark
            NoChange,                    // UnicodeZWControl

        }; 
    }
 
    ///  
    /// TibetanCharClassifier -
    ///  
    internal class TibetanCharClassifier : ShaperCharacterClassifier
    {

 
        public TibetanCharClassifier(ScriptTags scriptTag, GlyphTypeface fontFace) : base(scriptTag, fontFace)
        { 
          _unknownClass =    (byte)TibetanCharClass.UnknownCharClass; 
          _spaceClass =      (byte)TibetanCharClass.Other;
          _zwControlClass =  (byte)TibetanCharClass.UnicodeZWControl; 
          _zwjClass =        (byte)TibetanCharClass.UnicodeZWControl;
          _zwnjClass =       (byte)TibetanCharClass.UnicodeZWControl;
          _shyClass =        (byte)TibetanCharClass.UnknownCharClass;
 
          _firstChar     = '\u0F00';     // this is the first Tibetan Unicode char
          _lastChar      = '\u0FCF';     // this is the last Tibetan Unicode char 
          _xorMask       = 0x0F00;     // this mask is used in GetCharShapeInfo 
          _xorRange      = 0x0D0;     // this is used in GetCharShapeInfo
 
          _charClassTable = _tibetanCharClasses;

        }
        ///  
        /// Returns the shape info for the unicode character
        ///  
        public override 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)_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)_unknownClass;
        }
 

#region Classification Tables 
 
        // these consts are so the tables below will be more readable
        private const byte UnknownCharClass = (byte)TibetanCharClass.UnknownCharClass; 
        private const byte Headline = (byte)TibetanCharClass.HeadlinePunct;
        private const byte Birga = (byte)TibetanCharClass.Birga;
        private const byte Consonant = (byte)TibetanCharClass.HeadConsonant;
        private const byte ConsWithFlag = (byte)TibetanCharClass.HeadConsWithFlag; 
        private const byte Subjoined = (byte)(TibetanCharClass.SubjoinedCons | TibetanCharClass.SpecialHandlingRequired);
        private const byte SubjWithFlag = (byte)(TibetanCharClass.SubjoinedConsWithFlag | TibetanCharClass.SpecialHandlingRequired); 
        private const byte Lenition = (byte)TibetanCharClass.LenitionMark; 
        private const byte Achung = (byte)TibetanCharClass.Achung;
        private const byte Shapkyu = (byte)TibetanCharClass.Shapkyu; 
        private const byte Vowel = (byte)TibetanCharClass.AboveVowel;
        private const byte VowelSign = (byte)TibetanCharClass.VowelSign;
        private const byte Halanta = (byte)TibetanCharClass.Halanta;
        private const byte Underline = (byte)TibetanCharClass.UnderlineMark; 
        private const byte Padma = (byte)TibetanCharClass.Padma;
        private const byte Visarga = (byte)TibetanCharClass.Visarga; 
        private const byte Terminal = (byte)TibetanCharClass.TerminalPunct; 
        private const byte Digit = (byte)TibetanCharClass.Digit;
        private const byte PreDigit = (byte)(TibetanCharClass.PreDigitMark | TibetanCharClass.SpecialHandlingRequired); 
        private const byte BelowDigit = (byte)TibetanCharClass.BelowDigitMark;
        private const byte DigitWire = (byte)TibetanCharClass.WireDigitMark;
        private const byte PostDigit = (byte)TibetanCharClass.PostDigitMark;
        private const byte Other = (byte)TibetanCharClass.Other; 
        private const byte CompositeSubjoinedVowel = (byte)TibetanCharClass.CompositeSubjoinedVowel;
        private const byte CompositeSubjoinedShapkyu = (byte)TibetanCharClass.CompositeSubjoinedShapkyu; 
        private const byte CompositeAchungVowel = (byte)TibetanCharClass.CompositeAchungVowel; 
        private const byte CompositeAchungShapkyu = (byte)TibetanCharClass.CompositeAchungShapkyu;
 
        // All the Tibetan Unicode chars (U+F00 - U+FCF) classified
         private static readonly byte[] _tibetanCharClasses  = //new TibetanCharClass[]
         {
            // U+F00 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Headline,      Headline,         Headline,         Headline, 
               Birga,         Birga,            Headline,         Headline, 
               Headline,      Headline,         Headline,         Terminal,
               Terminal,      Terminal,         Terminal,         Terminal, 

            // U+F10 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Terminal,      Terminal,         Terminal,         Terminal, 
               Terminal,      Other,            Other,            Other,
               DigitWire,     BelowDigit,       Other,            Other, 
               Other,         Other,            Other,            Other, 

            // U+F20 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Digit,         Digit,            Digit,            Digit,
               Digit,         Digit,            Digit,            Digit,
               Digit,         Digit,            Digit,            Digit, 
               Digit,         Digit,            Digit,            Digit,
 
            // U+F30 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Digit,         Digit,            Digit,            Digit, 
               Other,         Underline,        Other,            Underline,
               Other,         Lenition,         Other,            Other,
               Other,         Other,            PostDigit,        PreDigit,
 
            // U+F40 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Consonant,     Consonant,        Consonant,        Consonant, 
               Consonant,     Consonant,        Consonant,        Consonant,
               UnknownCharClass,Consonant,      Consonant,        Consonant, 
               Consonant,     Consonant,        Consonant,        Consonant,

            // U+F50 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Consonant,     Consonant,        Consonant,        Consonant,
               Consonant,     Consonant,        Consonant,        Consonant, 
               Consonant,     ConsWithFlag,     ConsWithFlag,     ConsWithFlag, 
               ConsWithFlag,  Consonant,        Consonant,        Consonant,
 
            // U+F60 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Consonant,     Consonant,        Consonant,        Consonant,
               Consonant,     Consonant,        Consonant,        Consonant, 
               Consonant,     Consonant,        Consonant,        UnknownCharClass,
               UnknownCharClass,UnknownCharClass,UnknownCharClass,Other, 
 

            // U+F70 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               UnknownCharClass,Achung,        Vowel,            CompositeAchungVowel,
               Shapkyu,       CompositeAchungShapkyu,  CompositeSubjoinedVowel,CompositeSubjoinedShapkyu,
               CompositeSubjoinedShapkyu,CompositeSubjoinedShapkyu,Vowel,         Vowel, 
               Vowel,         Vowel,            VowelSign,        Visarga,
 
            // U+F80 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Vowel,         CompositeAchungShapkyu,  VowelSign,        VowelSign, 
               Halanta,       Other,            VowelSign,        VowelSign,
               Consonant,     Consonant,        Consonant,        Consonant,
               UnknownCharClass,UnknownCharClass,UnknownCharClass,UnknownCharClass,
 
            // U+F90 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Subjoined,     Subjoined,        Subjoined,        Subjoined, 
               Subjoined,     Subjoined,        Subjoined,        Subjoined,
               Other,         Subjoined,        Subjoined,        Subjoined, 
               Subjoined,     Subjoined,        Subjoined,        Subjoined,

            // U+FA0 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Subjoined,     Subjoined,        Subjoined,        Subjoined,
               Subjoined,     Subjoined,        Subjoined,        Subjoined, 
               Subjoined,     SubjWithFlag,     SubjWithFlag,     SubjWithFlag, 
               SubjWithFlag,  Subjoined,        Subjoined,        Subjoined,
 
            // U+FB0 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Subjoined,     Subjoined,        Subjoined,        Subjoined,
               Subjoined,     Subjoined,        Subjoined,        Subjoined, 
               Subjoined,     Subjoined,        Subjoined,        Subjoined,
               Subjoined,     UnknownCharClass, Other,            Other, 
 
            // U+FC0 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Other,         Other,            Other,            Other,
               Other,         Other,            Padma,            Other,
               Other,         Other,            Other,            Other,
               Other,         UnknownCharClass, UnknownCharClass, Other 

         }; 
 
#endregion  // end of Classification Tables
    } 
}


// 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, 2003
// 
//  File:      TibetanShape.cs
// 
//  Contents:  Implementation of Tibetan shaping engine and its factory 
//
//  Created:   02-15-2004 Nick Beal (nbeal) 
//
//-----------------------------------------------------------------------

// #define VALIDATE_CLUSTER_PARAMETERS 

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

    ///  
    /// TibetanCharClass - enumeration of Tibetan classification flags
    /// ordinal position 
    ///  
    internal enum TibetanCharClass : byte
    { 
        UnknownCharClass,     // Unknown class --
        Other,
        HeadlinePunct,        // HeadlinePunct -- accepts vowel sign
        Birga,                // Birga -- accepts no marks 
        HeadConsonant,        // HeadConsonant -- accepts many marks
        SubjoinedCons,        // SubjoinedCons -- 
        LenitionMark,         // LenitionMark -- 
        HeadConsWithFlag,     // HeadConsWithFlag -- accepts many marks
        SubjoinedConsWithFlag,// SubjoinedConsWithFlag -- 
        Achung,              // Achung --
        Shapkyu,              // Shapkyu --
        Halanta,              // Halanta
        UnderlineMark,        // UnderlineMark 
        Padma,                // Padma
        AboveVowel,           // AboveVowel -- 
        VowelSign,            // VowelSign 
        Visarga,
        TerminalPunct, 
        Digit,
        PreDigitMark,
        BelowDigitMark,
        WireDigitMark, 
        PostDigitMark,
        UnicodeZWControl, 
        NumberOfTibetanCharClasses, 

        CharClassMask = 0x1F, 
        SpecialHandlingRequired = 0x80,
        CompositeToVowel = 0x40,
        CompositeToShapkyu = 0x20,
        CompositeSubjoinedVowel = CompositeToVowel + SubjoinedCons + SpecialHandlingRequired, 
        CompositeSubjoinedShapkyu = CompositeToShapkyu + SubjoinedCons + SpecialHandlingRequired,
 
        CompositeAchungVowel = CompositeToVowel + Achung, 
        CompositeAchungShapkyu =  CompositeToShapkyu + Achung,
 
//        DecomposableFlag    = 0x80,
//        ComposedAchung = DecomposableFlag + Achung,
//        ComposedSubjoined = DecomposableFlag + SubjoinedCons
 
    };
 
    ///  
    /// The Tibetan Shaping Engine - (shapes Tibetan text)
    ///  
    /// 
    /// The IShaper and IShapingEngine interfaces are implemented to
    /// provide the shaping methods for Tibetan Scripts.
    /// There are four Tibetan private types defined/used in this class: 
    /// 1.) TibetanShapeInfo - this class manages the shape information
    /// 2.) TibetanClusterCop - this class manages the canonical ordering 
    /// 3.) TibetanFontInfo - this class manages the font interface 
    /// 4.) TibetanCharClassInfo - contains the char classification tables
    /// 
    internal sealed class TibetanShape : BaseShape
    {
        //
        // See static TibetanShape() constructor for notes and initialization. 
        //
        private static readonly Feature[]          _tibetanSubstitutionFeatures; 
        private static readonly Feature[]          _tibetanPositioningFeatures; 
        private static readonly ScriptTags[]      _supportedScripts;
 
        //--------------------------------------
        //
        //  Constructors
        // 
        //--------------------------------------
 
#region Constructors 
        /// 
        /// Static (type) constructor for the Tibetan Open Type Shaping Engine. 
        /// 
        /// 
        /// All the static members are initialized in the context of this
        /// function. 
        ///
        static TibetanShape() 
        { 
            // Tibetan Script required substitution features
            // 
            _tibetanSubstitutionFeatures =  new Feature[]
            {
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.GlyphCompositionDecomposition,1),
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.BelowBaseSubstitutions,1), 
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.AboveBaseSubstitutions,1),
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.ContextualAlternates,1), 
            }; 

 

            //
            // Positioning Features for Tibetan Script.  Note order is important (see call to
            // OpenTypeLayout.PositionGlyphs in GetGlyphPlacements below). 
            //
            _tibetanPositioningFeatures = new Feature[] 
            { 
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.BelowBaseMarkPositioning,1),
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.AboveBaseMarkPositioning,1), 
                new Feature(0,ushort.MaxValue,(uint)FeatureTags.Kerning,1),
            };

            // 
            // Tibetan Script is only supported scripts
            // 
            _supportedScripts = new ScriptTags[] {ScriptTags.Tibetan}; 

 
        }

        /// 
        /// Constructor for the Tibetan Open Type Shaping Engine. 
        /// 
        internal TibetanShape() 
        { 
            _forceDiacriticsToZeroWidth = false;
        } 

#endregion

        //-------------------------------------- 
        //
        //  Internal Methods 
        // 
        //--------------------------------------
 
#region Internal methods
        /// 
        /// TibetanShape.SupportedScripts -
        ///  IShapingEngine member override 
        /// 
        /// Our supported scripts (Tibetan, Lao). 
        public override ScriptTags[] SupportedScripts 
        {
            get 
            {
                return _supportedScripts;
            }
        } 

        ///  
        /// MongolianShape.GetCharClassifier - Base shape 
        /// 
        ///  
        ///     This will normally be overridden by derived shapers. It is used in OnLoadFont
        /// 
        protected override ShaperCharacterClassifier GetCharClassifier(ScriptTags scriptTag, GlyphTypeface fontFace)
        { 
            return new TibetanCharClassifier (scriptTag, fontFace);
        } 
 
        /// 
        ///     TibetanShape.GetGlyphs - Tibetan implementation of the GetGlyphs() helper function. 
        /// 
        /// shaping currentRun
        /// Text item
        /// number of glyphs 
        /// 
        /// Critical - calls critical code, uses unsafe accessors and methods 
        ///  
        [SecurityCritical]
        unsafe protected override int GetGlyphs ( ref ShapingWorkspace currentRun, Item item ) 
        {

            TibetanShapeFSM stateMachine = new TibetanShapeFSM();
            stateMachine.SetStartState(); 

            // Shape and initialize the glyph list 
            // process the char stream, creating shape info 
            CharShapeInfo currShape;
            while ( currentRun.GetNextShape (out currShape) ) 
            {
                CharShapeInfo newShape = stateMachine.StepToNextState( currShape );
                if ((newShape &
                    (CharShapeInfo.RequiresInsertedBase | CharShapeInfo.RequiresSpecialHandling)) 
                                            ==  CharShapeInfo.RequiresSpecialHandling)
                { 
                    TibetanCharClass currClass = (TibetanCharClass)currShape; 

                    if ((currClass & (TibetanCharClass.CompositeToShapkyu | TibetanCharClass.CompositeToVowel)) != 0) 
                    {
                        // special handling required (this must be a "composed" achung or subjoined consonant)
                        Debug.Assert ((currClass & TibetanCharClass.CharClassMask) == TibetanCharClass.Achung ||
                                    (currClass & TibetanCharClass.CharClassMask) == TibetanCharClass.SubjoinedCons); 

                        // This character is a decomposition candidate.  We need to 
                        // break it up into 2 or 3 glyphs (depending on the unicode 
                        // char).  So, add the glyphs...
                        char currChar = currentRun.CurrentChar; 
                        ushort toBeAddedCount = (ushort)((currChar == '\u0F77' || currChar == '\u0F79') ? 2 : 1);
                        currentRun.AddGlyphs(toBeAddedCount);

                        // fill in the decomposition info for this character. 
                        switch (currChar)
                        { 
                          case '\u0f73': 
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0f71');
                              currChar = '\u0f72'; 
                              break;
                          case '\u0f75':
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0f71');
                              currChar = '\u0f74'; 
                              break;
                          case '\u0f76': 
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0fb2'); 
                              currChar = '\u0f80';
                              break; 
                          case '\u0f77':
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0fb2');
                              currentRun.SetGlyphProperties(currentRun.CharConverter.ToGlyph('\u0f71'));
                              currChar = '\u0f80'; 
                              break;
                          case '\u0f78': 
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0fb3'); 
                              currChar = '\u0f80';
                              break; 
                          case '\u0f79':
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0fb3');
                              currentRun.SetGlyphProperties(currentRun.CharConverter.ToGlyph('\u0f71'));
                              currChar = '\u0f80'; 
                              break;
                          case '\u0f81': 
                              currentRun.SetGlyphPropertiesUsingChar(newShape,'\u0f71'); 
                              currChar = '\u0f80';
                              break; 
                          default:
                              Debug.Assert(false,"TibetanShape - illegal decomposite char");
                              break;
                        } 

                        currentRun.SetGlyphProperties(currentRun.CharConverter.ToGlyph(currChar)); 
                        continue; 
                    }
                    else if (currClass == TibetanCharClass.PreDigitMark) 
                    {
                        // we need to swap this predigit mark with the preceding
                        // digit char.
                        ushort digitGlyph = currentRun.PreviousGlyph; 
                        if (digitGlyph != '\u0000')
                        { 
                            currentRun.PreviousGlyph = currentRun.CurrentGlyph; 
                            currentRun.SetGlyphPropertiesUsingGlyph(newShape, digitGlyph);
                            continue; 
                        }
                    }
                }
 
                // normal character to glyph processing
                currentRun.SetGlyphPropertiesUsingShapeInfo(newShape); 
            } 

            return currentRun.GlyphsCount;    // we're done 

        }

        ///  
        ///     TibetanShape.ApplySubstitutionFeatures - default implementation of the GetGlyphs() helper function.
        ///  
        /// shaping currentRun 
        /// Set of gsub features to be applied to the unicode run.
        /// result of applying features 
        /// 
        /// Critical - this method calls unsafe methods.
        /// 
        [SecurityCritical] 
        protected override OpenTypeLayoutResult ApplySubstitutionFeatures(
                                                        ref ShapingWorkspace currentRun, 
                                                        FeatureSet       featureSet  ) 
        {
            ShaperFontClient fontClient = currentRun.FontClient; 
            return fontClient.SubstituteGlyphs(
                        ref currentRun,
                        _tibetanSubstitutionFeatures,     // In: List of features to apply
                        _tibetanSubstitutionFeatures.Length ); 
        }
 
 

        ///  
        ///    TibetanShape.ApplyPositioningFeatures - generic implementation of the GetGlyphPlacement helper.
        ///     This method goes through a list of glyphs and adds placement information.
        /// 
        /// the wrapper for glyph advances, offset arrays 
        /// metrics for all the positioning features
        /// Set of gpos features to be applied to the unicode run. 
        /// result of applying features 
        /// 
        /// Critical - calls critical code 
        /// 
        [SecurityCritical]
        protected override OpenTypeLayoutResult ApplyPositioningFeatures(
                ref PlacementWorkspace   placementInfo, 
                ref LayoutMetrics   layoutMetrics,
                FeatureSet          featureSet ) 
        { 
            ShaperFontClient fontClient = placementInfo.FontClient;
            OpenTypeLayoutResult layoutResult = fontClient.PositionGlyphs( 
                        ref placementInfo,
                        ref layoutMetrics,
                        _tibetanPositioningFeatures,     // In: List of features to apply
                        _tibetanPositioningFeatures.Length ); 

            return layoutResult; 
        } 
#endregion
    } 

    /// 
    /// Class TibetanShapeFSM:
    ///  The Tibetam state machine 
    /// 
    ///  
    /// This class implements the Tibetan state machine.  The GetNextShape() routine 
    /// is the most important method, returning the corresponding shape flags for each
    /// unicode char in the text stream. 
    /// 
    internal struct TibetanShapeFSM
    {
        TibetanClusterState _previousState; 
        TibetanClusterState _currentState;
 
        CharShapeInfo       _stateShape; 

        bool             _isSubjoinedConsInCluster ; 


        internal CharShapeInfo StateShapeFlags
        { 
            get { return _stateShape; }
        } 
 
        /// 
        ///   TibetanShapeFSM.ForceInvalidBaseState - force state machine to state 
        /// 
        /// 
        ///     Tibetan state machine resets to start state when an invalid character
        ///     is detected. 
        /// 
        internal CharShapeInfo ForceInvalidBaseState () 
        { 
            _previousState = _currentState = TibetanClusterState.StartState;
            _stateShape = CharShapeInfo.RequiresInsertedBase; 

            return _stateShape;
        }
 
        internal void SetStartState()
        { 
            _previousState = _currentState = TibetanClusterState.StartState; 
            _stateShape = CharShapeInfo.NoFlagsSet;
            _isSubjoinedConsInCluster = false; 
        }

        /// 
        ///   TibetanShapeFSM.StepToNextState - process the latest character. 
        /// 
        ///  
        ///   This routine steps the state machine to its next state 
        ///   based on the current state, the last character that caused a
        ///   state change and the next char.  The current shapeState can 
        ///   be changed in some cases (thus the 'ref' designation)
        /// 
        /// state flags for current character appropriate to new state
        internal CharShapeInfo StepToNextState ( CharShapeInfo  nextCharShape ) 
        {
            TibetanCharClass tibetanCharShape = (TibetanCharClass)nextCharShape; 
            TibetanCharClass tibetanCharClass = (tibetanCharShape & TibetanCharClass.CharClassMask); 
            Debug.Assert (tibetanCharClass < TibetanCharClass.NumberOfTibetanCharClasses, "invalid tibetan char class index");
 
            _previousState = _currentState;     // save current state.

            // tableEntry is found at stateTable [ (clusterState - 1) * 24 + charClass].
            // tableIxSeed is used to facilitate the multiply by 24 (it is "(clusterState-1) X 8" 
            // and "tableIxSeed << 1" is "(clusterState-1) X 16")
            int tableIxSeed = ((int)_previousState - 1) << 3; // state index * 8 
            _stateShape = (CharShapeInfo) 
                TibetanClusterStateTable[tableIxSeed + (tableIxSeed << 1) + (int)tibetanCharClass];   // 24 entries per state.
            TibetanClusterState nextState = (TibetanClusterState)(_stateShape & CharShapeInfo.ShaperClassMask); 
            if (nextState == TibetanClusterState.NoChange)
            {
                // Since we're not changing state, we need to validate this
                // new character. 
                if (tibetanCharClass == TibetanCharClass.UnicodeZWControl ||
                    tibetanCharClass == TibetanCharClass.TerminalPunct) 
                { 
                    // this is ok, keep going
                    _stateShape = nextCharShape; 
                }
                else if (tibetanCharClass != TibetanCharClass.Shapkyu || !_isSubjoinedConsInCluster)
                {
                    // can't have multiple shapkyu chars before subjoined consonant 
                    // (we're happy to have them after the subjoined conaonant),
                    // nor any other character (if nextState == NoChange) 
                    ForceInvalidBaseState(); 
                }
            } 
            else
            {
                _currentState = nextState;
 
                if (tibetanCharShape > TibetanCharClass.NumberOfTibetanCharClasses)
                { 
                    _stateShape |= CharShapeInfo.RequiresSpecialHandling; 

                    // special cases.  The current character is a "composite" event; 
                    // it acts like a set of two characters.
                    if ((tibetanCharShape & TibetanCharClass.CompositeToShapkyu) != 0)
                    {
                        _currentState = TibetanClusterState.ConsonantWithShapkyuState; 
                    }
                    else if ((tibetanCharShape & TibetanCharClass.CompositeToVowel) != 0) 
                    { 
                        _currentState = TibetanClusterState.VowelState;
                    } 
                    else if (tibetanCharClass == TibetanCharClass.SubjoinedCons ||
                                tibetanCharClass == TibetanCharClass.SubjoinedConsWithFlag)
                    {
                        _isSubjoinedConsInCluster = true; 
                    }
                } 
            } 

            if ((_stateShape & CharShapeInfo.IsStartOfCluster) != 0) 
            {
                _isSubjoinedConsInCluster = false;
            }
 

            return _stateShape; // & CharShapeInfo.ShapeFlagsMask; 
        } 

        ///  
        /// TibetanClusterState - enumeration of Tibetan cluster states
        /// ordinal position
        /// 
        private enum TibetanClusterState : byte 
        {
            NoChange, 
            StartState, 
            HeadlineLeaderState,
            BirgaLeaderState, 
            HeadlineConsonantState,
            HeadlineConsonantWithFlagState,
                ConsonantWithAchungState,
                ConsonantWithShapkyuState, 
                SubjoinedConsonantState,
                SubjoinedConsonantWithFlagState, 
                HalantaState, 
                UnderlineMarkState,
                PadmaState, 
                VowelState,
            TerminalState,
            OtherState,
            DigitState, 
                PreDigitState,
                BelowDigitState, 
                WireDigitState, 
            NumberOfTibetanClusterStates
        }; 

        // These values are used to populate the state tables.  Each entry is a packed
        // value with the next state in the lower bits, and the shape flags in the higher
        // bits.  The GetNextShape routine unpacks these entries. 
        private const ushort NoChange      = (ushort )TibetanClusterState.NoChange;
        private const ushort InvalidBase   = (ushort)CharShapeInfo.RequiresInsertedBase; 
        private const ushort StartOfCluster = (ushort) CharShapeInfo.IsStartOfCluster; 
        private const ushort ToStartState  = (ushort )TibetanClusterState.StartState;
        private const ushort StartState  = ToStartState + StartOfCluster; 
        private const ushort HeadlineLeaderState  =
                  (ushort )TibetanClusterState.HeadlineLeaderState + StartOfCluster;
        private const ushort BirgaLeaderState  =
                  (ushort )TibetanClusterState.BirgaLeaderState + StartOfCluster; 
        private const ushort HeadlineConsonantState =
                  (ushort )TibetanClusterState.HeadlineConsonantState + StartOfCluster; 
        private const ushort HeadlineConsonantWithFlagState = 
                  (ushort )TibetanClusterState.HeadlineConsonantWithFlagState + StartOfCluster;
        private const ushort ToHeadlineConsonantState = 
                  (ushort )TibetanClusterState.HeadlineConsonantState;
        private const ushort ToHeadlineConsonantWithFlagState =
                  (ushort )TibetanClusterState.HeadlineConsonantWithFlagState;
        private const ushort ConsonantWithAchungState  = 
                  (ushort)TibetanClusterState.ConsonantWithAchungState;
        private const ushort ConsonantWithShapkyuState  = 
                  (ushort)TibetanClusterState.ConsonantWithShapkyuState; 
        private const ushort SubjoinedConsonantState  =
                  (ushort)TibetanClusterState.SubjoinedConsonantState; 
        private const ushort SubjoinedConsonantWithFlagState  =
                  (ushort)TibetanClusterState.SubjoinedConsonantState;
        private const ushort HalantaState  = (ushort )TibetanClusterState.HalantaState;
        private const ushort UnderlineMarkState  = (ushort )TibetanClusterState.UnderlineMarkState; 
        private const ushort PadmaState  = (ushort )TibetanClusterState.PadmaState;
        private const ushort VowelState  = (ushort )TibetanClusterState.VowelState; 
 
        private const ushort DigitState  =
                (ushort )TibetanClusterState.DigitState + StartOfCluster; 
        private const ushort PreDigitState  = (ushort )TibetanClusterState.PreDigitState;
        private const ushort BelowDigitState  = (ushort )TibetanClusterState.BelowDigitState;
        private const ushort WireDigitState  = (ushort )TibetanClusterState.WireDigitState;
 
        private const ushort OtherState  =
                (ushort )TibetanClusterState.OtherState + StartOfCluster; 
        private const ushort TerminalState  = 
                (ushort )TibetanClusterState.TerminalState + StartOfCluster;
 
        // The syllable state machine state table.  For each current state
        // there are 24 entries - one for each char class - so that the first
        // entry for any current state can be found at "current state / 24 "
        private static readonly ushort[] TibetanClusterStateTable  = //new TibetanSyllableState[] 
        {
            // State Table Entry            Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign 
            StartState | InvalidBase,    // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 
            // HeadlineLeaderState          Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark 
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            ToStartState,                // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // BirgaLeaderState          Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark 
            ToStartState,                // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // HeadlineConsonantState     Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            ToHeadlineConsonantWithFlagState, // LenitionMark
            HeadlineConsonantWithFlagState,   // HeadConsWithFlag 
            SubjoinedConsonantState,     // SubjoinedConsWithFlag
            ConsonantWithAchungState,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu 
            HalantaState,                // Halanta
            UnderlineMarkState,          // UnderlineMark 
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign
            ToStartState,                // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // HeadlineConsonantWithFlagState     Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantWithFlagState,   // HeadConsWithFlag 
            SubjoinedConsonantState,     // SubjoinedConsWithFlag
            ConsonantWithAchungState,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu 
            HalantaState,                // Halanta
            UnderlineMarkState,          // UnderlineMark 
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign
            ToStartState,                // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // ConsonantWIthAchungState     Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            SubjoinedConsonantState,     // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu 
            HalantaState,                // Halanta
            UnderlineMarkState,          // UnderlineMark 
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign
            ToStartState,                // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 
            // ConsonantWithShapkyuState     Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            SubjoinedConsonantState,     // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            NoChange,                    // Shapkyu 
            HalantaState,                // Halanta
            UnderlineMarkState,          // UnderlineMark 
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign
            ToStartState,                // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl

 

            // SubjoinedConsonantState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            SubjoinedConsonantWithFlagState,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            SubjoinedConsonantState,     // SubjoinedConsWithFlag 
            ConsonantWithAchungState,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu
            HalantaState,                // Halanta 
            UnderlineMarkState,          // UnderlineMark
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // SubjoinedConsonantWithFlagState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            SubjoinedConsonantState,     // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            SubjoinedConsonantWithFlagState, // SubjoinedConsWithFlag 
            ConsonantWithAchungState,    // Achung 
            ConsonantWithShapkyuState,   // Shapkyu
            HalantaState,                // Halanta 
            UnderlineMarkState,          // UnderlineMark
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // HalantaState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            UnderlineMarkState,          // UnderlineMark
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // UnderlineMarkState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,          // UnderlineMark
            PadmaState,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // PadmaState     Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,          // UnderlineMark
            StartState | InvalidBase,                  // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // VowelState                 Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            VowelState,                  // AboveVowel
            VowelState,                  // VowelSign 
            ToStartState,                // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

            // TerminalState                Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign 
            StartState | InvalidBase,    // Visarga
            NoChange,                    // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            StartState | InvalidBase,    // BelowDigitMark 
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl
 

 
            // OtherState                 Input Char Class 
            StartState,                  // Unknown
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons 
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark
            ToStartState,                // Padma
            StartState | InvalidBase,    // AboveVowel 
            StartState | InvalidBase,    // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark
            StartState | InvalidBase,    // PostDigitMark
            NoChange,                    // UnicodeZWControl 

 
 
            // DigitState                 Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant 
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma 
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign 
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            PreDigitState,               // PreDigitMark
            BelowDigitState,             // BelowDigitMark
            WireDigitState,              // WireDigitMark
            ToStartState,                // PostDigitMark 
            NoChange,                    // UnicodeZWControl
 
            // PreDigitState                 Input Char Class 
            StartState,                  // Unknown
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons 
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel 
            StartState | InvalidBase,    // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit
            StartState | InvalidBase,    // PreDigitMark 
            BelowDigitState,             // BelowDigitMark
            WireDigitState,              // WireDigitMark
            ToStartState,                // PostDigitMark
            NoChange,                    // UnicodeZWControl 

            // BelowDigitState                 Input Char Class 
            StartState,                  // Unknown 
            OtherState,                  // Other
            HeadlineLeaderState,         // HeadlinePunct 
            BirgaLeaderState,            // Birga
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark 
            HeadlineConsonantState,      // HeadConsWithFlag
            StartState | InvalidBase,    // SubjoinedConsWithFlag 
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu
            StartState | InvalidBase,    // Halanta 
            StartState | InvalidBase,    // UnderlineMark
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign 
            StartState | InvalidBase,    // Visarga
            TerminalState,               // TerminalPunct 
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark
            BelowDigitState,             // BelowDigitMark 
            WireDigitState,              // WireDigitMark
            ToStartState,                // PostDigitMark
            NoChange,                    // UnicodeZWControl
 
            // WireDigitState                 Input Char Class
            StartState,                  // Unknown 
            OtherState,                  // Other 
            HeadlineLeaderState,         // HeadlinePunct
            BirgaLeaderState,            // Birga 
            HeadlineConsonantState,      // HeadConsonant
            StartState | InvalidBase,    // SubjoinedCons
            StartState | InvalidBase,    // LenitionMark
            HeadlineConsonantState,      // HeadConsWithFlag 
            StartState | InvalidBase,    // SubjoinedConsWithFlag
            StartState | InvalidBase,    // Achung 
            StartState | InvalidBase,    // Shapkyu 
            StartState | InvalidBase,    // Halanta
            StartState | InvalidBase,    // UnderlineMark 
            StartState | InvalidBase,    // Padma
            StartState | InvalidBase,    // AboveVowel
            StartState | InvalidBase,    // VowelSign
            StartState | InvalidBase,    // Visarga 
            TerminalState,               // TerminalPunct
            DigitState,                  // Digit 
            StartState | InvalidBase,    // PreDigitMark 
            StartState | InvalidBase,    // BelowDigitMark
            StartState | InvalidBase,    // WireDigitMark 
            ToStartState,                // PostDigitMark
            NoChange,                    // UnicodeZWControl

        }; 
    }
 
    ///  
    /// TibetanCharClassifier -
    ///  
    internal class TibetanCharClassifier : ShaperCharacterClassifier
    {

 
        public TibetanCharClassifier(ScriptTags scriptTag, GlyphTypeface fontFace) : base(scriptTag, fontFace)
        { 
          _unknownClass =    (byte)TibetanCharClass.UnknownCharClass; 
          _spaceClass =      (byte)TibetanCharClass.Other;
          _zwControlClass =  (byte)TibetanCharClass.UnicodeZWControl; 
          _zwjClass =        (byte)TibetanCharClass.UnicodeZWControl;
          _zwnjClass =       (byte)TibetanCharClass.UnicodeZWControl;
          _shyClass =        (byte)TibetanCharClass.UnknownCharClass;
 
          _firstChar     = '\u0F00';     // this is the first Tibetan Unicode char
          _lastChar      = '\u0FCF';     // this is the last Tibetan Unicode char 
          _xorMask       = 0x0F00;     // this mask is used in GetCharShapeInfo 
          _xorRange      = 0x0D0;     // this is used in GetCharShapeInfo
 
          _charClassTable = _tibetanCharClasses;

        }
        ///  
        /// Returns the shape info for the unicode character
        ///  
        public override 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)_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)_unknownClass;
        }
 

#region Classification Tables 
 
        // these consts are so the tables below will be more readable
        private const byte UnknownCharClass = (byte)TibetanCharClass.UnknownCharClass; 
        private const byte Headline = (byte)TibetanCharClass.HeadlinePunct;
        private const byte Birga = (byte)TibetanCharClass.Birga;
        private const byte Consonant = (byte)TibetanCharClass.HeadConsonant;
        private const byte ConsWithFlag = (byte)TibetanCharClass.HeadConsWithFlag; 
        private const byte Subjoined = (byte)(TibetanCharClass.SubjoinedCons | TibetanCharClass.SpecialHandlingRequired);
        private const byte SubjWithFlag = (byte)(TibetanCharClass.SubjoinedConsWithFlag | TibetanCharClass.SpecialHandlingRequired); 
        private const byte Lenition = (byte)TibetanCharClass.LenitionMark; 
        private const byte Achung = (byte)TibetanCharClass.Achung;
        private const byte Shapkyu = (byte)TibetanCharClass.Shapkyu; 
        private const byte Vowel = (byte)TibetanCharClass.AboveVowel;
        private const byte VowelSign = (byte)TibetanCharClass.VowelSign;
        private const byte Halanta = (byte)TibetanCharClass.Halanta;
        private const byte Underline = (byte)TibetanCharClass.UnderlineMark; 
        private const byte Padma = (byte)TibetanCharClass.Padma;
        private const byte Visarga = (byte)TibetanCharClass.Visarga; 
        private const byte Terminal = (byte)TibetanCharClass.TerminalPunct; 
        private const byte Digit = (byte)TibetanCharClass.Digit;
        private const byte PreDigit = (byte)(TibetanCharClass.PreDigitMark | TibetanCharClass.SpecialHandlingRequired); 
        private const byte BelowDigit = (byte)TibetanCharClass.BelowDigitMark;
        private const byte DigitWire = (byte)TibetanCharClass.WireDigitMark;
        private const byte PostDigit = (byte)TibetanCharClass.PostDigitMark;
        private const byte Other = (byte)TibetanCharClass.Other; 
        private const byte CompositeSubjoinedVowel = (byte)TibetanCharClass.CompositeSubjoinedVowel;
        private const byte CompositeSubjoinedShapkyu = (byte)TibetanCharClass.CompositeSubjoinedShapkyu; 
        private const byte CompositeAchungVowel = (byte)TibetanCharClass.CompositeAchungVowel; 
        private const byte CompositeAchungShapkyu = (byte)TibetanCharClass.CompositeAchungShapkyu;
 
        // All the Tibetan Unicode chars (U+F00 - U+FCF) classified
         private static readonly byte[] _tibetanCharClasses  = //new TibetanCharClass[]
         {
            // U+F00 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Headline,      Headline,         Headline,         Headline, 
               Birga,         Birga,            Headline,         Headline, 
               Headline,      Headline,         Headline,         Terminal,
               Terminal,      Terminal,         Terminal,         Terminal, 

            // U+F10 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Terminal,      Terminal,         Terminal,         Terminal, 
               Terminal,      Other,            Other,            Other,
               DigitWire,     BelowDigit,       Other,            Other, 
               Other,         Other,            Other,            Other, 

            // U+F20 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Digit,         Digit,            Digit,            Digit,
               Digit,         Digit,            Digit,            Digit,
               Digit,         Digit,            Digit,            Digit, 
               Digit,         Digit,            Digit,            Digit,
 
            // U+F30 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Digit,         Digit,            Digit,            Digit, 
               Other,         Underline,        Other,            Underline,
               Other,         Lenition,         Other,            Other,
               Other,         Other,            PostDigit,        PreDigit,
 
            // U+F40 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Consonant,     Consonant,        Consonant,        Consonant, 
               Consonant,     Consonant,        Consonant,        Consonant,
               UnknownCharClass,Consonant,      Consonant,        Consonant, 
               Consonant,     Consonant,        Consonant,        Consonant,

            // U+F50 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Consonant,     Consonant,        Consonant,        Consonant,
               Consonant,     Consonant,        Consonant,        Consonant, 
               Consonant,     ConsWithFlag,     ConsWithFlag,     ConsWithFlag, 
               ConsWithFlag,  Consonant,        Consonant,        Consonant,
 
            // U+F60 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Consonant,     Consonant,        Consonant,        Consonant,
               Consonant,     Consonant,        Consonant,        Consonant, 
               Consonant,     Consonant,        Consonant,        UnknownCharClass,
               UnknownCharClass,UnknownCharClass,UnknownCharClass,Other, 
 

            // U+F70 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               UnknownCharClass,Achung,        Vowel,            CompositeAchungVowel,
               Shapkyu,       CompositeAchungShapkyu,  CompositeSubjoinedVowel,CompositeSubjoinedShapkyu,
               CompositeSubjoinedShapkyu,CompositeSubjoinedShapkyu,Vowel,         Vowel, 
               Vowel,         Vowel,            VowelSign,        Visarga,
 
            // U+F80 (Tibetan Unicode) 
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Vowel,         CompositeAchungShapkyu,  VowelSign,        VowelSign, 
               Halanta,       Other,            VowelSign,        VowelSign,
               Consonant,     Consonant,        Consonant,        Consonant,
               UnknownCharClass,UnknownCharClass,UnknownCharClass,UnknownCharClass,
 
            // U+F90 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Subjoined,     Subjoined,        Subjoined,        Subjoined, 
               Subjoined,     Subjoined,        Subjoined,        Subjoined,
               Other,         Subjoined,        Subjoined,        Subjoined, 
               Subjoined,     Subjoined,        Subjoined,        Subjoined,

            // U+FA0 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Subjoined,     Subjoined,        Subjoined,        Subjoined,
               Subjoined,     Subjoined,        Subjoined,        Subjoined, 
               Subjoined,     SubjWithFlag,     SubjWithFlag,     SubjWithFlag, 
               SubjWithFlag,  Subjoined,        Subjoined,        Subjoined,
 
            // U+FB0 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F
               Subjoined,     Subjoined,        Subjoined,        Subjoined,
               Subjoined,     Subjoined,        Subjoined,        Subjoined, 
               Subjoined,     Subjoined,        Subjoined,        Subjoined,
               Subjoined,     UnknownCharClass, Other,            Other, 
 
            // U+FC0 (Tibetan Unicode)
            // 0, 4, 8, C     1, 5, 9, D        2, 6, A, E        3, 7, B, F 
               Other,         Other,            Other,            Other,
               Other,         Other,            Padma,            Other,
               Other,         Other,            Other,            Other,
               Other,         UnknownCharClass, UnknownCharClass, Other 

         }; 
 
#endregion  // end of Classification Tables
    } 
}


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