IndicFontClient.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / MS / Internal / Shaping / IndicFontClient.cs / 1 / IndicFontClient.cs

                            //---------------------------------------------------------------------- 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2003
// 
//  File:      IndicCharClassifier.cs
// 
//  Contents:  Implementation of Indic shaping engine and its factory 
//
//  Created:   03-04-2007 [....] ([....]) 
//
//-----------------------------------------------------------------------

// #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
{
 
    /// 
    /// IndicFontClient - 
    ///  
    internal class IndicFontClient : ShaperFontClient
    { 
        private bool _useV2ScriptTag;
        private bool _isFormsDiscoveryDone;
//        private bool _areConsonantFormsCached;
//        private byte[] _charFormsInfo; 
        private ushort _halantGlyph;
 
        private IndicCharClassifier   _indicCharConverter; 

        public IndicFontClient( GlyphTypeface fontFace, 
                                    IndicCharClassifier indicCharConverter ) : base(fontFace, indicCharConverter)
        {
          _halantGlyph  = 0;
 
          _useV2ScriptTag = true;
          _isFormsDiscoveryDone = false; 
//          _areConsonantFormsCached = false; 

          _indicCharConverter = indicCharConverter; 
        }

        /// 
        /// IndicFontClient.Initialize - initializer 
        /// 
        ///  
        /// Critical - The method reads raw font table bits (i.e. FindLangSys()). 
        /// 
        [SecurityCritical] 
        public override bool Initialize(
                      OpenTypeLayoutWorkspace layoutWorkspace,
                      OpenTypeTags            featureType,
                      ScriptID                scriptID, 
                      LanguageTags            langSysTag
                      ) 
        { 
            bool success = base.Initialize(layoutWorkspace,featureType,scriptID,langSysTag);
            if (success && !_isFormsDiscoveryDone) 
            {
                IndicCharConverter.GetFontCharacterFormsInfo(this);
            }
 
            return success;
        } 
 
        /// 
        /// OpenType script tag supported by this shaping engine 
        /// 
        public bool IsIndicV2Font
        {
            get{ return _useV2ScriptTag; } 
        }
 
        internal IndicCharClassifier       IndicCharConverter 
        {
            get { return _indicCharConverter; } 
        }

        public uint[] ScriptGsubFeaturesList
        { 
            get { return GetGsubFeaturesList(); }
        } 
 
//        public uint[] ScriptSubstitutionFeaturesList
//        { 
//            get { return _indicSubstitutionFeatures; }
//        }

        ///  
        /// Critical - calls critical code, passes pointer parameters
        ///  
        public ushort                               HalantGlyph 
        {
          [SecurityCritical] 
          get {  if (_halantGlyph == 0)
                 {
                    _halantGlyph =  IndicCharConverter.ToGlyph(IndicCharConverter.HalantCharacter);
                 } 
                 return _halantGlyph;
              } 
 
        }
 

        /// 
        /// Returns the font's script tag
        ///  
        public override ScriptTags ToScriptTag (ScriptID scriptID)
        { 
            if (_useV2ScriptTag) 
            {
                switch (scriptID) 
                {
                    case ScriptID.Devanagari:
                        return ScriptTags.Devanagari_v2;
                    case ScriptID.Bengali: 
                        return ScriptTags.Bengali_v2;
                    case ScriptID.Gurmukhi: 
                        return ScriptTags.Gurmukhi_v2; 
                    case ScriptID.Gujarati:
                        return ScriptTags.Gujarati_v2; 
                    case ScriptID.Oriya:
                        return ScriptTags.Oriya_v2;
                    case ScriptID.Tamil:
                        return ScriptTags.Tamil_v2; 
                    case ScriptID.Telugu:
                        return ScriptTags.Telugu_v2; 
                    case ScriptID.Kannada: 
                        return ScriptTags.Kannada_v2;
                    case ScriptID.Malayalam: 
                        return ScriptTags.Malayalam_v2;
                    default:
                        break;
                } 
            }
 
            return Script.ToTag(scriptID); 
        }
 
        /// 
        /// Critical - The method reads raw font table bits (i.e. FindLangSys()).
        /// 
        [SecurityCritical] 
        public bool ValidateScriptTag (ScriptTags scriptTag)
        { 
            bool isScriptTagValid = false; 

            if (_useV2ScriptTag) 
            {
                ScriptTags v2Tag = 0;

                // convert script tags to version 2... 
                switch (scriptTag)
                { 
                    case ScriptTags.Devanagari: 
                        v2Tag = ScriptTags.Devanagari_v2;
                        break; 
                    case ScriptTags.Bengali:
                        v2Tag = ScriptTags.Bengali_v2;
                        break;
                    case ScriptTags.Gurmukhi: 
                        v2Tag = ScriptTags.Gurmukhi_v2;
                        break; 
                    case ScriptTags.Gujarati: 
                        v2Tag = ScriptTags.Gujarati_v2;
                        break; 
                    case ScriptTags.Oriya:
                        v2Tag = ScriptTags.Oriya_v2;
                        break;
                    case ScriptTags.Tamil: 
                        v2Tag = ScriptTags.Tamil_v2;
                        break; 
                    case ScriptTags.Telugu: 
                        v2Tag = ScriptTags.Telugu_v2;
                        break; 
                    case ScriptTags.Kannada:
                        v2Tag = ScriptTags.Kannada_v2;
                        break;
                    case ScriptTags.Malayalam: 
                        v2Tag = ScriptTags.Malayalam_v2;
                        break; 
                    default: 
                        Debug.Assert(false, "Script tag is not Indic tag.");
                        return false; 
                }

                if (OpenTypeLayout.FindScript(this,(uint)v2Tag) != TagInfoFlags.None)
                { 
                    isScriptTagValid = true; // v2 script tag exists in this font
                } 
                else 
                {
                    _useV2ScriptTag = false; 
                }

            }
 
            if (OpenTypeLayout.FindScript(this,(uint)scriptTag) != TagInfoFlags.None)
            { 
                isScriptTagValid = true; // v1 script tag exists in this font 
            }
 
            return isScriptTagValid;
        }

        private uint[] GetGsubFeaturesList () 
        {
            switch (IndicCharConverter.ScriptIx) 
            { 
                case IndicScriptIndices.Devanagari:
                    return _hindiGsubFeatures; 

                case IndicScriptIndices.Bengali:
                    return _bengaliGsubFeatures;
 
                case IndicScriptIndices.Gurmukhi:
                    return _gurmukhiGsubFeatures; 
 
                case IndicScriptIndices.Gujarati:
                    return _gujaratiGsubFeatures; 

                case IndicScriptIndices.Oriya:
                    return _oriyaGsubFeatures;
 
                case IndicScriptIndices.Tamil:
                    return _tamilGsubFeatures; 
 
                case IndicScriptIndices.Telugu:
                    return _teluguGsubFeatures; 

                case IndicScriptIndices.Kannada:
                    return _kannadaGsubFeatures;
 
                case IndicScriptIndices.Malayalam:
                    return _malayalamGsubFeatures; 
 
                default:
                    throw new NotSupportedException(); 

            }

        } 

 
        ///  
        /// Critical - calls critical code
        ///  
        [SecurityCritical]
        public bool GetCachedCharacterFormsInfo ( byte[] charFormsInfo )
        {
            return false; 
        }
 
        private const CharShapeInfo IndicCharClassMask = (CharShapeInfo)IndicCharClass.CharClassMask; 

        ///  
        ///IndicCharClassifier.GetFontFormsInfo - gets the consonant forms features that this font supports
        /// 
        /// 
        /// Critical - calls critical code 
        /// 
        [SecurityCritical] 
        public bool GetCharacterFormsInfo ( byte[] formsInfo ) 
        {
 
            if ( !_useV2ScriptTag && IndicCharConverter.ScriptIx == IndicScriptIndices.Tamil )
            {
                return false;
            } 

            bool isFontFormInfoValidated = GetCachedCharacterFormsInfo(formsInfo); 
            if ( !isFontFormInfoValidated ) 
            {
                // forms info isn't cached for this font, so do the work now... 

                ushort halantGlyph = HalantGlyph;
                CharShapeInfo halantShape = IndicCharConverter.ToShapeInfo(IndicCharConverter.HalantCharacter);
 
                GlyphInfoList glyphs = new GlyphInfoList(2,1,false);
                UshortList charMap = new UshortList(2,1); 
                glyphs.SetRange(0,2); 
                charMap.SetRange(0,2);
 
                uint[] featureTags = GetGsubFeaturesList();

                bool isOldStyleKartikaFont = !_useV2ScriptTag && IndicCharConverter.ScriptIx == IndicScriptIndices.Malayalam;
 
                Feature[] fontFeatures = new Feature[1];
                fontFeatures[0] = new Feature(0,2,(uint)FeatureTags.RephForm,1); 
 
                // test font for various consonant forms
                for (int i = 0; i < IndicCharClassifier.CharsPerIndicScript; ++i) 
                {
                    char consonantChar = (char)(IndicCharConverter.FirstCharacterInScriptRange + i);
                    CharShapeInfo charShape = IndicCharConverter.ToShapeInfo(consonantChar);
                    IndicCharClass charClass = 
                        (IndicCharClass)(charShape & IndicCharClassMask);
 
                    // copy over non-consonant form info without modifying it 
                    // (assume this is a non-consonant)
                    formsInfo[i] = (byte)IndicCharConverter.ToFormInfo(consonantChar); 

                    // now check if this is an interesting consonant
                    if (charClass == IndicCharClass.Consonant ||
                        charClass == IndicCharClass.Ra || 
                        charClass == IndicCharClass.NuktaConsonant)
                    { 
                        // clear any unverified consonant form info except bengali init form 
                        // (keep that flag because we're not going to try to validate 'init')
                        formsInfo[i] = (byte)(formsInfo[i] & (byte)(IndicFormFlags.InitForm | 
                            (isOldStyleKartikaFont ?
                                    (IndicFormFlags.SubForm |
                                     IndicFormFlags.PostForm |
                                     IndicFormFlags.DravidianBase | 
                                     IndicFormFlags.PostbaseReph ) : 0)));
 
                        // apply features 
                        for (ushort tagIx = 0; tagIx < featureTags.Length; ++tagIx)
                        { 
                            IndicFormFlags   consonantFormFlags;
                            bool isPostMainForm = true;
                            bool useVCOrder = _useV2ScriptTag;  // if v2 fonts, expect features to work with h+C, not C+h
 
                            switch ( featureTags[tagIx] )
                            { 
                                case (uint)FeatureTags.PrebaseForms: 
                                    if (isOldStyleKartikaFont)
                                    { 
                                        continue;
                                    }
                                    consonantFormFlags = IndicFormFlags.PostbaseReph;
                                    break; 
                                case (uint)FeatureTags.BelowBaseForms:
                                    consonantFormFlags = IndicFormFlags.SubForm; 
                                    if (isOldStyleKartikaFont) 
                                    {
                                        if (((byte)consonantFormFlags & formsInfo[i]) != 0) 
                                        {
                                             isFontFormInfoValidated = true;
                                        }
                                        continue; 
                                    }
                                    break; 
                                case (uint)FeatureTags.PostbaseForms: 
                                    consonantFormFlags = IndicFormFlags.PostForm;
                                    if (isOldStyleKartikaFont) 
                                    {
                                        if (((byte)consonantFormFlags & formsInfo[i]) != 0)
                                        {
                                             isFontFormInfoValidated = true; 
                                        }
                                        continue; 
                                    } 
                                    break;
                                case (uint)FeatureTags.VattuVariants: 
                                    consonantFormFlags = IndicFormFlags.VattuForm;
                                    if (!_useV2ScriptTag &&
                                        i == IndicCharClassifier.RaOffset &&
                                        (IndicCharConverter.ToFormInfo(consonantChar) & IndicFormFlags.VattuForm) != 0) 
                                    {
                                        // for XP-style fonts, if the static table says the ra has a 
                                        // vattu form, then assume that its so. 
                                        formsInfo[i] |= (byte)consonantFormFlags;
                                        continue; 
                                    }
                                    break;

                                case (uint)FeatureTags.HalfForms: 
                                    consonantFormFlags = IndicFormFlags.HalfForm;
                                    isPostMainForm = useVCOrder = false; 
                                    break; 
                                case (uint)FeatureTags.RephForm:
                                    consonantFormFlags = IndicFormFlags.RephForm; 
                                    isPostMainForm = useVCOrder = false;
                                    break;

                                 default: 
                                    continue;
 
                            } 

                            fontFeatures[0].Tag = featureTags[tagIx]; 

                            // initialize glyphs, charMap
                            for (ushort ix = 0; ix < 2; ++ix)
                            { 
                                glyphs.LigatureCounts[ix] = 1;
                                glyphs.GlyphFlags[ix] = (ushort)GlyphFlags.Unresolved; 
                                glyphs.FirstChars[ix] = ix; 
                                glyphs.Glyphs[ix] = HalantGlyph;
                                charMap[ix] = ix; 
                            }
                            glyphs.Glyphs[useVCOrder ? 1 : 0] = IndicCharConverter.ToGlyph(consonantChar);

                            //  Apply the Indic Text Features from currentRun 
                            SubstituteGlyphs( fontFeatures,
                                              1, 
                                              charMap, 
                                              glyphs);
 
                            if (glyphs.Length == 1) // if the 2 characters became one glyph...
                            {
                                 formsInfo[i] |= (byte)consonantFormFlags;
                                 if (isPostMainForm) 
                                 {
                                    // we found a virama+consonant lookup! 
                                    // (must be a good font!) 
                                     isFontFormInfoValidated = true;
                                 } 

                                glyphs.SetLength(2);
                            }
 
                            }
                        } 
 
                    }
 

                }

            // now would be a great time to cache the font's character form information 
            _isFormsDiscoveryDone = true;
            return isFontFormInfoValidated; 
        } 

        // Indic (all scripts) required substitution presentation forms 
//        private static readonly uint[] _indicSubstitutionFeatures =
//        {
//            (uint)FeatureTags.PrebaseSubstitutions,
//            (uint)FeatureTags.AboveBaseSubstitutions, 
//            (uint)FeatureTags.BelowBaseSubstitutions,
//            (uint)FeatureTags.PostbaseSubstitutions, 
//            (uint)FeatureTags.HalantForms, 
//            (uint)FeatureTags.ContextualAlternates,
//        }; 

            // Bengali Script required substitution form features
            //
        private static readonly uint[] _bengaliGsubFeatures = 
        {
            (uint)FeatureTags.LocalizedForms, 
            (uint)FeatureTags.NuktaForms, 
            (uint)FeatureTags.RephForm,
            (uint)FeatureTags.Akhands, 
            (uint)FeatureTags.BelowBaseForms,
            (uint)FeatureTags.HalfForms,
            (uint)FeatureTags.PostbaseForms,
            (uint)FeatureTags.VattuVariants, 
            (uint)FeatureTags.Conjuncts,
            (uint)FeatureTags.InitialForms, 
        }; 

 
        // Gujarati Script required substitution form features
        //
        private static readonly uint[] _gujaratiGsubFeatures =
        { 
            (uint)FeatureTags.LocalizedForms,
            (uint)FeatureTags.NuktaForms, 
            (uint)FeatureTags.RephForm, 
            (uint)FeatureTags.Akhands,
            (uint)FeatureTags.RakarForms, 
            (uint)FeatureTags.BelowBaseForms,
            (uint)FeatureTags.HalfForms,
            (uint)FeatureTags.VattuVariants,
            (uint)FeatureTags.Conjuncts, 
        };
 
        // Gurmukhi Script required substitution form features 
        //
        private static readonly uint[] _gurmukhiGsubFeatures = 
        {
            (uint)FeatureTags.LocalizedForms,
            (uint)FeatureTags.NuktaForms,
            (uint)FeatureTags.Akhands, 
            (uint)FeatureTags.RephForm,
            (uint)FeatureTags.BelowBaseForms, 
            (uint)FeatureTags.HalfForms, 
            (uint)FeatureTags.PostbaseForms,
            (uint)FeatureTags.VattuVariants, 
            (uint)FeatureTags.Conjuncts,
        };

        // Hindi (Devanagari) Script required substitution form features 
        //
        private static readonly uint[] _hindiGsubFeatures = 
        { 
            (uint)FeatureTags.LocalizedForms,
            (uint)FeatureTags.NuktaForms, 
            (uint)FeatureTags.RephForm,
            (uint)FeatureTags.Akhands,
            (uint)FeatureTags.RakarForms,
            (uint)FeatureTags.BelowBaseForms, 
            (uint)FeatureTags.HalfForms,
            (uint)FeatureTags.VattuVariants, 
            (uint)FeatureTags.Conjuncts, 
        };
 
        // Kannada Script required substitution form features
        //
        private static readonly uint[] _kannadaGsubFeatures =
        { 
            (uint)FeatureTags.LocalizedForms,
            (uint)FeatureTags.NuktaForms, 
            (uint)FeatureTags.RephForm, 
            (uint)FeatureTags.Akhands,
            (uint)FeatureTags.PrebaseForms, 
            (uint)FeatureTags.BelowBaseForms,
            (uint)FeatureTags.HalfForms,
            (uint)FeatureTags.PostbaseForms,
            (uint)FeatureTags.Conjuncts, 
        };
 
        // Malayalam Script required substitution form features 
        //
        private static readonly uint[] _malayalamGsubFeatures = 
        {
            (uint)FeatureTags.LocalizedForms,
            (uint)FeatureTags.NuktaForms,
            (uint)FeatureTags.RephForm, 
            (uint)FeatureTags.Akhands,
            (uint)FeatureTags.PrebaseForms, 
            (uint)FeatureTags.BelowBaseForms, 
            (uint)FeatureTags.HalfForms,
            (uint)FeatureTags.PostbaseForms, 
            (uint)FeatureTags.Conjuncts,
        };

 
        // Oriya Script required substitution form features
        // 
        private static readonly uint[] _oriyaGsubFeatures = 
        {
            (uint)FeatureTags.LocalizedForms, 
            (uint)FeatureTags.NuktaForms,
            (uint)FeatureTags.RephForm,
            (uint)FeatureTags.Akhands,
            (uint)FeatureTags.BelowBaseForms, 
            (uint)FeatureTags.PostbaseForms,
            (uint)FeatureTags.Conjuncts, 
        }; 

 
        // Tamil Script required substitution form features
        //
        private static readonly uint[] _tamilGsubFeatures =
        { 
            (uint)FeatureTags.LocalizedForms,
            (uint)FeatureTags.NuktaForms, 
            (uint)FeatureTags.RephForm, 
            (uint)FeatureTags.Akhands,
            (uint)FeatureTags.PrebaseForms, 
            (uint)FeatureTags.HalfForms,
        };

 
        // Telugu Script required substitution form features
        // 
        private static readonly uint[] _teluguGsubFeatures = 
        {
            (uint)FeatureTags.LocalizedForms, 
            (uint)FeatureTags.RephForm,
            (uint)FeatureTags.Akhands,
            (uint)FeatureTags.PrebaseForms,
            (uint)FeatureTags.BelowBaseForms, 
            (uint)FeatureTags.HalfForms,
            (uint)FeatureTags.PostbaseForms, 
            (uint)FeatureTags.Conjuncts, 
        };
 

    }
}
 

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