ShaperBuffers.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / MS / Internal / Shaping / ShaperBuffers.cs / 1305600 / ShaperBuffers.cs

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

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

 
namespace MS.Internal.Shaping
{
    /// 
    ///     ShaperBuffers encapsulates the shapers non-volatile, non-shareabld buffers 
    /// 
    ///  
    ///     This class owns several buffers that need to live as long as there's a 
    ///     shaping engine that uses them.  Each shaping engine "owns" one of these, but
    ///     the actual mapping/number of ShaperBuffers instances depends 
    ///     on the THREAD_SAFE_SHAPERS constant in BaseShape.cs.  If THREAD_SAFE_SHAPERS
    ///     is defined, there's one ShaperBuffers for each thread created in the
    ///     WCP process space.  If not defined, each shaping engine has its own
    ///     ShaperBuffers object.  In this latter case, the owner of the ShapeManager 
    ///     that owns the shaping engine is responsible for guaranteeing thread safety (everything
    ///     else in the shape engines is reentrant, but each ShaperBuffers is not. 
    /// 
    ///     A ShaperBuffers is created whenever a IShaper interface method of a
    ///     shaper is called and its member ShaperBuffers is null (ie, the first time 
    ///     a shaper's IShaper interface is invoked).  It exists till the shaper is destroyed.
    /// 
    internal class ShaperBuffers
    { 

        ///  
        /// ShaperBuffers - constructor 
        /// 
        ///  
        ///     Critical: This code accepts checked pointers and extracts
        ///         unsafe pointers.
        /// 
        public ShaperBuffers(ushort charCount, ushort glyphCount) 
        {
 
            // the charCount is used to provide an initial size for the 
            // various buffers used by the shaper(s).  These may
            // grow over the shaper's life 
            _glyphInfoList = new GlyphInfoList((glyphCount > charCount ? glyphCount : charCount), 16, false);
            _charMap = new UshortList(charCount, 16);
            _layoutWorkspace = new OpenTypeLayoutWorkspace();
 
            _charMap.SetRange(0,charCount);
            if (glyphCount > 0) 
            { 
                _glyphInfoList.SetRange(0,glyphCount);
            } 

        }

         ~ShaperBuffers() 
         {
             _glyphInfoList = null; 
             _charMap = null; 
             _layoutWorkspace = null;
             _textFeatures = null; 
         }

         // I have laid these out alphabetically.  If a particular variable has
         // an accessor with a different name than the variable, I've added a 
         // comment in the position of the variable...
 
        public UshortList                       CharMap 
        {
            get { return _charMap; } 
        }


        public GlyphInfoList                    GlyphInfoList 
        {
            get { return _glyphInfoList; } 
            set { _glyphInfoList = value; } 
        }
 

        /// 
        /// ShaperBuffers.Initialize - initializer for GetGlyphs.
        ///  
        /// 
        ///   Called by every shaper's GetGlyph method (indirectly - 
        ///   this function is actually called by the ShapingWorkspace.Initialize 
        ///   method (which is called from IShaper.GetGlyphs)).
        ///  
        public bool Initialize(ushort charCount, ushort glyphCount)
        {
            if (charCount <= 0)
            { 
                return false;
            } 
 
            // clear charmap and resize it
            if (_charMap.Length > 0) 
            {
                _charMap.Remove(0, _charMap.Length);
            }
            _charMap.Insert(0, charCount); 
            Debug.Assert(_charMap.Length == charCount);
 
            // clear glyphinfolist 
            if (_glyphInfoList.Length > 0)
            { 
                _glyphInfoList.Remove(0, _glyphInfoList.Length);
            }
            if (glyphCount > 0)
            { 
                _glyphInfoList.Insert(0, glyphCount);
            } 
            Debug.Assert(_glyphInfoList.Length == glyphCount); 

            return true; 
        }


         ///  
         /// ShaperBuffers.InitializeFeatureList - initializer for GetGlyphs.
         ///  
         /// Requested new array size 
         /// number of features to copy into new array
         ///  
         ///   Called by pertinent shaper's GetGlyph method; ie, those shapers
         ///   that need to create a text dependent list of features
         ///   (e.g. Arabic, Mongolian).
         ///   The "keep" count takes priority over "size" if there's already an 
         ///   array, so if size size is less than keep, the resized array has at
         ///    least keep elements.  It is possible to create a 0 sized array. 
         ///  
         public bool InitializeFeatureList(ushort size, ushort keep)
         { 
            if (_textFeatures == null)
            {
                _textFeatures = new ShaperFeaturesList();
                if (_textFeatures == null) 
                {
                    return false; 
                } 

                _textFeatures.Initialize(size); 
            }
            else
            {
                _textFeatures.Resize(size, keep); 
            }
 
            return true; 
         }
 

         public OpenTypeLayoutWorkspace            LayoutWorkspace
         {
             get { return _layoutWorkspace; } 
         }
 
         //                                          NextIx; see CurrentCharIx 

 
        public ShaperFeaturesList                  TextFeatures
        {
            get { return _textFeatures; }
        } 

 
        // these are one per shaping engine (or per thread) and are kept around 
        // between calls (ie, we allocate these once for the lifetime of this
        // ShapingWorkspace instance) 
        private UshortList                  _charMap;
        private GlyphInfoList               _glyphInfoList;
        private OpenTypeLayoutWorkspace     _layoutWorkspace;
        private ShaperFeaturesList          _textFeatures; 

 
    } 

    internal class ShaperFeaturesList 
    {

        public int                                FeaturesCount
        { 
            get { return _featuresCount; }
        } 
 
        public Feature[]                          Features
        { 
            get { return _features; }
        }

        public int                                NextIx 
        {
            get { return _featuresCount; } 
        } 

        public uint                               CurrentTag 
        {
            get { return _featuresCount == 0 ? 0 : _features[_featuresCount - 1].Tag;}
        }
 
        public int                                Length
        { 
            get { return _featuresCount; } 
        }
 
        public void SetFeatureParameter (ushort featureIx, uint paramValue)
        {
            Invariant.Assert ( _featuresCount > featureIx );
            _features[featureIx].Parameter = paramValue; 
        }
 
        ///  
        /// ShaperFeateruList.Initialize - initializer for GetGlyphs.
        ///  
        /// 
        ///   Called by pertinent shaper's GetGlyph method (indirectly -
        ///   this function is actually called by the
        ///   ShaperBuffers.InitializeFeatureList method which is 
        ///   called by those shapers that need to create a text dependent
        ///   list of features (e.g. Arabic, Mongolian). 
        ///  
        internal bool Initialize (ushort newSize)
        { 
            if (_features == null ||
                newSize > _features.Length ||
                newSize == 0)
            { 
                Feature[] newArray = new Feature[newSize];
                if (newArray != null) 
                { 
                    _features = newArray;
                } 
            }

            _featuresCount = 0;
            _minimumAddCount = 3;       // add space for init,med,final whenever we need to actually resize array 
            return _features != null;
        } 
 
        /// 
        /// ShaperFeateruList.Resize - used to change the size of the features array 
        /// 
        /// Requested new array size
        /// number of features to copy into new array
        ///  
        ///   Used locally for each AddFeature, and by ShaperBuffers.InitializeFeatureList.
        ///   May be called from a shaping engine. 
        ///   The "keepCount" count takes priority over "newSize" if there's already an 
        ///   array, so if size is less than keep, the resized array has at least keep elements.
        ///  
        internal bool Resize (ushort newSize, ushort keepCount)
        {
            _featuresCount = keepCount;     //
 
            if (_features != null &&
                _features.Length != 0 && 
                keepCount > 0 && 
                _features.Length >= keepCount)
            { 
                // make sure keep count is no bigger than current
                // array size
                ushort currentLength = (ushort)_features.Length;
 
                // make sure new size is at least as big as keep count
                if (newSize < keepCount) 
                { 
                    newSize = keepCount;
                } 

                // if new size is bigger than the current array, create
                // a new array
                if (newSize > currentLength) 
                {
                    // always use minimum leap for adding to array 
                    if (newSize < (currentLength + _minimumAddCount)) 
                    {
                       newSize = (ushort)(currentLength + _minimumAddCount); 
                    }

                    Feature[] newArray = new Feature[newSize];
                    if (newArray == null) 
                    {
                        // can't create new array, leave (at least we still 
                        // have our current array) 
                        return false;
                    } 

                    // Our client wants us to keep the first "keepCount" entries.
                    // so copy them now.
                    for (int i = 0; i < keepCount; ++i) 
                    {
                        newArray[i] = _features[i]; 
                    } 

                    _features = newArray; 
                }
            }
            else
            { 
                // nothing to keep, or currently no array so initialize
                return Initialize(newSize); 
            } 

            return true; 

        }

        ///  
        /// ShaperFeateruList.AddFeature - add a feature to the array
        ///  
        /// new feature to add 
        /// 
        ///     This is aimed at allowing shaping engines to add features 
        ///     to the array (generally used for required, all character
        ///     features added at the start of shaping)
        /// 
        internal void AddFeature (Feature feature) 
        {
            if ( _featuresCount == _features.Length ) 
            { 
                // need more space, so resize the array
               if (!Resize((ushort)(_featuresCount + 1),_featuresCount)) 
               {
                    return; // can't resize array, fail quietly (not going
                            // to apply this feature!)
               } 
            }
 
            _features[_featuresCount] = feature; 
            ++_featuresCount;
        } 

        /// 
        /// ShaperFeateruList.AddFeature - add a feature to the array
        ///  
        /// 
        ///     An alternative to adding an already created feature. 
        ///  
        internal void AddFeature (ushort startIndex, ushort length, uint featureTag, uint parameter)
        { 
            if ( _featuresCount == _features.Length )
            {
                // need more space
               if (!Resize((ushort)(_featuresCount + 1),_featuresCount)) 
               {
                    return; 
               } 
            }
 
            if (_features[_featuresCount] != null)
            {
                _features[_featuresCount].Tag = featureTag;
                _features[_featuresCount].StartIndex = startIndex; 
                _features[_featuresCount].Length = length;
                _features[_featuresCount].Parameter = parameter; 
            } 
            else
            { 
                _features[_featuresCount] = new Feature(startIndex,length,featureTag,parameter);
            }

            ++_featuresCount; 
        }
 
        ///  
        /// ShaperFeateruList.AddFeature - add a feature to the array
        ///  
        /// 
        ///     This variation of "AddFeature" is used by the shaper state
        ///     machines for adding each new feature.
        ///  
        internal void AddFeature (ushort charIx, uint featureTag )
        { 
            if (featureTag == 1)     // "NotShaped" 
            {
                return; 
            }

            if (_featuresCount > 0)     // if previous feature exists
            { 
                // see if this feature can just be subsumed in the latest feature
                ushort latestFeatureIx = (ushort)(_featuresCount - 1); 
                if ((featureTag == 0 || featureTag == _features[latestFeatureIx].Tag) && 
                     (_features[latestFeatureIx].StartIndex +
                      _features[latestFeatureIx].Length) == charIx) 
                {
                    _features[latestFeatureIx].Length += 1;
                }
                else 
                {
                    // can't be added to previous feature, so add one. 
                    AddFeature(charIx, 
                               1,
                               (featureTag == 0 ? _features[latestFeatureIx].Tag : featureTag), 
                               1);
                }
            }
            else if (featureTag != 0)        // cant' be "Same" (there's no feature yet) 
            {
                AddFeature(charIx,1,featureTag,1); 
            } 

        } 

        /// 
        /// ShaperFeateruList.UpdatePreviousShapedChar - adjust previous char's tag
        ///  
        /// 
        ///     This is used by the shaper state machines for modifying the 
        ///     feature tag of the previous character. 
        /// 
        internal void UpdatePreviousShapedChar (uint featureTag) 
        {
            if (featureTag <= 1)     // nothing to do if "NotShaped" or "Same"
            {
                return; 
            }
 
            if (_featuresCount > 0) 
            {
                // see if this feature can just be subsumed in the latest feature 
                ushort latestFeatureIx = (ushort)(_featuresCount - 1);

                if (_features[latestFeatureIx].Tag != featureTag)
                { 
                    // the previous char's feature just applied to
                    // it, so update its tag and we're done 
                    _features[latestFeatureIx].Tag = featureTag; 
                }
            } 
        }

        private ushort                            _minimumAddCount;
        private ushort                            _featuresCount; 
        private Feature[]                         _features;
    } 
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------- 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2001
// 
//  File:      ShaperBuffers.cs
// 
//  Contents:  base shaping engine buffers 
//
//  Created:   10-22-2003 
//
//-----------------------------------------------------------------------

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

 
namespace MS.Internal.Shaping
{
    /// 
    ///     ShaperBuffers encapsulates the shapers non-volatile, non-shareabld buffers 
    /// 
    ///  
    ///     This class owns several buffers that need to live as long as there's a 
    ///     shaping engine that uses them.  Each shaping engine "owns" one of these, but
    ///     the actual mapping/number of ShaperBuffers instances depends 
    ///     on the THREAD_SAFE_SHAPERS constant in BaseShape.cs.  If THREAD_SAFE_SHAPERS
    ///     is defined, there's one ShaperBuffers for each thread created in the
    ///     WCP process space.  If not defined, each shaping engine has its own
    ///     ShaperBuffers object.  In this latter case, the owner of the ShapeManager 
    ///     that owns the shaping engine is responsible for guaranteeing thread safety (everything
    ///     else in the shape engines is reentrant, but each ShaperBuffers is not. 
    /// 
    ///     A ShaperBuffers is created whenever a IShaper interface method of a
    ///     shaper is called and its member ShaperBuffers is null (ie, the first time 
    ///     a shaper's IShaper interface is invoked).  It exists till the shaper is destroyed.
    /// 
    internal class ShaperBuffers
    { 

        ///  
        /// ShaperBuffers - constructor 
        /// 
        ///  
        ///     Critical: This code accepts checked pointers and extracts
        ///         unsafe pointers.
        /// 
        public ShaperBuffers(ushort charCount, ushort glyphCount) 
        {
 
            // the charCount is used to provide an initial size for the 
            // various buffers used by the shaper(s).  These may
            // grow over the shaper's life 
            _glyphInfoList = new GlyphInfoList((glyphCount > charCount ? glyphCount : charCount), 16, false);
            _charMap = new UshortList(charCount, 16);
            _layoutWorkspace = new OpenTypeLayoutWorkspace();
 
            _charMap.SetRange(0,charCount);
            if (glyphCount > 0) 
            { 
                _glyphInfoList.SetRange(0,glyphCount);
            } 

        }

         ~ShaperBuffers() 
         {
             _glyphInfoList = null; 
             _charMap = null; 
             _layoutWorkspace = null;
             _textFeatures = null; 
         }

         // I have laid these out alphabetically.  If a particular variable has
         // an accessor with a different name than the variable, I've added a 
         // comment in the position of the variable...
 
        public UshortList                       CharMap 
        {
            get { return _charMap; } 
        }


        public GlyphInfoList                    GlyphInfoList 
        {
            get { return _glyphInfoList; } 
            set { _glyphInfoList = value; } 
        }
 

        /// 
        /// ShaperBuffers.Initialize - initializer for GetGlyphs.
        ///  
        /// 
        ///   Called by every shaper's GetGlyph method (indirectly - 
        ///   this function is actually called by the ShapingWorkspace.Initialize 
        ///   method (which is called from IShaper.GetGlyphs)).
        ///  
        public bool Initialize(ushort charCount, ushort glyphCount)
        {
            if (charCount <= 0)
            { 
                return false;
            } 
 
            // clear charmap and resize it
            if (_charMap.Length > 0) 
            {
                _charMap.Remove(0, _charMap.Length);
            }
            _charMap.Insert(0, charCount); 
            Debug.Assert(_charMap.Length == charCount);
 
            // clear glyphinfolist 
            if (_glyphInfoList.Length > 0)
            { 
                _glyphInfoList.Remove(0, _glyphInfoList.Length);
            }
            if (glyphCount > 0)
            { 
                _glyphInfoList.Insert(0, glyphCount);
            } 
            Debug.Assert(_glyphInfoList.Length == glyphCount); 

            return true; 
        }


         ///  
         /// ShaperBuffers.InitializeFeatureList - initializer for GetGlyphs.
         ///  
         /// Requested new array size 
         /// number of features to copy into new array
         ///  
         ///   Called by pertinent shaper's GetGlyph method; ie, those shapers
         ///   that need to create a text dependent list of features
         ///   (e.g. Arabic, Mongolian).
         ///   The "keep" count takes priority over "size" if there's already an 
         ///   array, so if size size is less than keep, the resized array has at
         ///    least keep elements.  It is possible to create a 0 sized array. 
         ///  
         public bool InitializeFeatureList(ushort size, ushort keep)
         { 
            if (_textFeatures == null)
            {
                _textFeatures = new ShaperFeaturesList();
                if (_textFeatures == null) 
                {
                    return false; 
                } 

                _textFeatures.Initialize(size); 
            }
            else
            {
                _textFeatures.Resize(size, keep); 
            }
 
            return true; 
         }
 

         public OpenTypeLayoutWorkspace            LayoutWorkspace
         {
             get { return _layoutWorkspace; } 
         }
 
         //                                          NextIx; see CurrentCharIx 

 
        public ShaperFeaturesList                  TextFeatures
        {
            get { return _textFeatures; }
        } 

 
        // these are one per shaping engine (or per thread) and are kept around 
        // between calls (ie, we allocate these once for the lifetime of this
        // ShapingWorkspace instance) 
        private UshortList                  _charMap;
        private GlyphInfoList               _glyphInfoList;
        private OpenTypeLayoutWorkspace     _layoutWorkspace;
        private ShaperFeaturesList          _textFeatures; 

 
    } 

    internal class ShaperFeaturesList 
    {

        public int                                FeaturesCount
        { 
            get { return _featuresCount; }
        } 
 
        public Feature[]                          Features
        { 
            get { return _features; }
        }

        public int                                NextIx 
        {
            get { return _featuresCount; } 
        } 

        public uint                               CurrentTag 
        {
            get { return _featuresCount == 0 ? 0 : _features[_featuresCount - 1].Tag;}
        }
 
        public int                                Length
        { 
            get { return _featuresCount; } 
        }
 
        public void SetFeatureParameter (ushort featureIx, uint paramValue)
        {
            Invariant.Assert ( _featuresCount > featureIx );
            _features[featureIx].Parameter = paramValue; 
        }
 
        ///  
        /// ShaperFeateruList.Initialize - initializer for GetGlyphs.
        ///  
        /// 
        ///   Called by pertinent shaper's GetGlyph method (indirectly -
        ///   this function is actually called by the
        ///   ShaperBuffers.InitializeFeatureList method which is 
        ///   called by those shapers that need to create a text dependent
        ///   list of features (e.g. Arabic, Mongolian). 
        ///  
        internal bool Initialize (ushort newSize)
        { 
            if (_features == null ||
                newSize > _features.Length ||
                newSize == 0)
            { 
                Feature[] newArray = new Feature[newSize];
                if (newArray != null) 
                { 
                    _features = newArray;
                } 
            }

            _featuresCount = 0;
            _minimumAddCount = 3;       // add space for init,med,final whenever we need to actually resize array 
            return _features != null;
        } 
 
        /// 
        /// ShaperFeateruList.Resize - used to change the size of the features array 
        /// 
        /// Requested new array size
        /// number of features to copy into new array
        ///  
        ///   Used locally for each AddFeature, and by ShaperBuffers.InitializeFeatureList.
        ///   May be called from a shaping engine. 
        ///   The "keepCount" count takes priority over "newSize" if there's already an 
        ///   array, so if size is less than keep, the resized array has at least keep elements.
        ///  
        internal bool Resize (ushort newSize, ushort keepCount)
        {
            _featuresCount = keepCount;     //
 
            if (_features != null &&
                _features.Length != 0 && 
                keepCount > 0 && 
                _features.Length >= keepCount)
            { 
                // make sure keep count is no bigger than current
                // array size
                ushort currentLength = (ushort)_features.Length;
 
                // make sure new size is at least as big as keep count
                if (newSize < keepCount) 
                { 
                    newSize = keepCount;
                } 

                // if new size is bigger than the current array, create
                // a new array
                if (newSize > currentLength) 
                {
                    // always use minimum leap for adding to array 
                    if (newSize < (currentLength + _minimumAddCount)) 
                    {
                       newSize = (ushort)(currentLength + _minimumAddCount); 
                    }

                    Feature[] newArray = new Feature[newSize];
                    if (newArray == null) 
                    {
                        // can't create new array, leave (at least we still 
                        // have our current array) 
                        return false;
                    } 

                    // Our client wants us to keep the first "keepCount" entries.
                    // so copy them now.
                    for (int i = 0; i < keepCount; ++i) 
                    {
                        newArray[i] = _features[i]; 
                    } 

                    _features = newArray; 
                }
            }
            else
            { 
                // nothing to keep, or currently no array so initialize
                return Initialize(newSize); 
            } 

            return true; 

        }

        ///  
        /// ShaperFeateruList.AddFeature - add a feature to the array
        ///  
        /// new feature to add 
        /// 
        ///     This is aimed at allowing shaping engines to add features 
        ///     to the array (generally used for required, all character
        ///     features added at the start of shaping)
        /// 
        internal void AddFeature (Feature feature) 
        {
            if ( _featuresCount == _features.Length ) 
            { 
                // need more space, so resize the array
               if (!Resize((ushort)(_featuresCount + 1),_featuresCount)) 
               {
                    return; // can't resize array, fail quietly (not going
                            // to apply this feature!)
               } 
            }
 
            _features[_featuresCount] = feature; 
            ++_featuresCount;
        } 

        /// 
        /// ShaperFeateruList.AddFeature - add a feature to the array
        ///  
        /// 
        ///     An alternative to adding an already created feature. 
        ///  
        internal void AddFeature (ushort startIndex, ushort length, uint featureTag, uint parameter)
        { 
            if ( _featuresCount == _features.Length )
            {
                // need more space
               if (!Resize((ushort)(_featuresCount + 1),_featuresCount)) 
               {
                    return; 
               } 
            }
 
            if (_features[_featuresCount] != null)
            {
                _features[_featuresCount].Tag = featureTag;
                _features[_featuresCount].StartIndex = startIndex; 
                _features[_featuresCount].Length = length;
                _features[_featuresCount].Parameter = parameter; 
            } 
            else
            { 
                _features[_featuresCount] = new Feature(startIndex,length,featureTag,parameter);
            }

            ++_featuresCount; 
        }
 
        ///  
        /// ShaperFeateruList.AddFeature - add a feature to the array
        ///  
        /// 
        ///     This variation of "AddFeature" is used by the shaper state
        ///     machines for adding each new feature.
        ///  
        internal void AddFeature (ushort charIx, uint featureTag )
        { 
            if (featureTag == 1)     // "NotShaped" 
            {
                return; 
            }

            if (_featuresCount > 0)     // if previous feature exists
            { 
                // see if this feature can just be subsumed in the latest feature
                ushort latestFeatureIx = (ushort)(_featuresCount - 1); 
                if ((featureTag == 0 || featureTag == _features[latestFeatureIx].Tag) && 
                     (_features[latestFeatureIx].StartIndex +
                      _features[latestFeatureIx].Length) == charIx) 
                {
                    _features[latestFeatureIx].Length += 1;
                }
                else 
                {
                    // can't be added to previous feature, so add one. 
                    AddFeature(charIx, 
                               1,
                               (featureTag == 0 ? _features[latestFeatureIx].Tag : featureTag), 
                               1);
                }
            }
            else if (featureTag != 0)        // cant' be "Same" (there's no feature yet) 
            {
                AddFeature(charIx,1,featureTag,1); 
            } 

        } 

        /// 
        /// ShaperFeateruList.UpdatePreviousShapedChar - adjust previous char's tag
        ///  
        /// 
        ///     This is used by the shaper state machines for modifying the 
        ///     feature tag of the previous character. 
        /// 
        internal void UpdatePreviousShapedChar (uint featureTag) 
        {
            if (featureTag <= 1)     // nothing to do if "NotShaped" or "Same"
            {
                return; 
            }
 
            if (_featuresCount > 0) 
            {
                // see if this feature can just be subsumed in the latest feature 
                ushort latestFeatureIx = (ushort)(_featuresCount - 1);

                if (_features[latestFeatureIx].Tag != featureTag)
                { 
                    // the previous char's feature just applied to
                    // it, so update its tag and we're done 
                    _features[latestFeatureIx].Tag = featureTag; 
                }
            } 
        }

        private ushort                            _minimumAddCount;
        private ushort                            _featuresCount; 
        private Feature[]                         _features;
    } 
 
}

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