LineServicesRun.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 / TextFormatting / LineServicesRun.cs / 1600529 / LineServicesRun.cs

                            //------------------------------------------------------------------------ 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2001
// 
//  File:      LSRun.cs
// 
//  Contents:  Text run in a full text line 
//
//  Created:   9-6-2001 Worachai Chaoweeraprasit (wchao) 
//
//-----------------------------------------------------------------------

using System; 
using System.Collections;
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Runtime.InteropServices;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
using System.Globalization;
 
using System.Security;
using System.Security.Permissions; 
using MS.Internal.Shaping; 
using MS.Internal.FontCache;
using MS.Utility; 

using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
 
using MS.Internal.Text.TextInterface;
 
namespace MS.Internal.TextFormatting 
{
    ///  
    /// Run represented by a plsrun value dispatched to LS during FetchRun
    /// 
    internal sealed class LSRun
    { 
        private TextRunInfo             _runInfo;                   // TextRun Info of the text
        private Plsrun                  _type;                      // Plsrun used as run type 
        private int                     _offsetToFirstCp;           // dcp from line's cpFirst 
        private int                     _textRunLength;             // textrun length
        private CharacterBufferRange    _charBufferRange;           // character buffer range 
        private int                     _baselineOffset;            // distance from top to baseline
        private int                     _height;                    // height
        private int                     _baselineMoveOffset;        // run is moved by this offset from baseline
        private int                     _emSize;                    // run ideal EM size 
        private TextShapeableSymbols    _shapeable;                 // shapeable run
        private ushort                  _charFlags;                 // character attribute flags 
        private byte                    _bidiLevel;                 // resolved bidi level 
        private IList       _textEffects;               // TextEffects that should be applied for this run
 

        /// 
        /// Construct an lsrun
        ///  
        internal LSRun(
            TextRunInfo             runInfo, 
            IList       textEffects, 
            Plsrun                  type,
            int                     offsetToFirstCp, 
            int                     textRunLength,
            int                     emSize,
            ushort                  charFlags,
            CharacterBufferRange    charBufferRange, 
            TextShapeableSymbols    shapeable,
            double                  realToIdeal, 
            byte                    bidiLevel 
            ) :
            this( 
                runInfo,
                textEffects,
                type,
                offsetToFirstCp, 
                textRunLength,
                emSize, 
                charFlags, 
                charBufferRange,
                (shapeable != null ? (int)Math.Round(shapeable.Baseline * realToIdeal) : 0), 
                (shapeable != null ? (int)Math.Round(shapeable.Height * realToIdeal) : 0),
                shapeable,
                bidiLevel
                ) 
        {}
 
 
        /// 
        /// Construct an lsrun 
        /// 
        private LSRun(
            TextRunInfo             runInfo,
            IList       textEffects, 
            Plsrun                  type,
            int                     offsetToFirstCp, 
            int                     textRunLength, 
            int                     emSize,
            ushort                  charFlags, 
            CharacterBufferRange    charBufferRange,
            int                     baselineOffset,
            int                     height,
            TextShapeableSymbols    shapeable, 
            byte                    bidiLevel
            ) 
        { 
            _runInfo = runInfo;
            _type = type; 
            _offsetToFirstCp = offsetToFirstCp;
            _textRunLength = textRunLength;
            _emSize = emSize;
            _charFlags = charFlags; 
            _charBufferRange = charBufferRange;
            _baselineOffset = baselineOffset; 
            _height = height; 
            _bidiLevel = bidiLevel;
            _shapeable = shapeable; 
            _textEffects = textEffects;
        }

 
        /// 
        /// Construct an lsrun for a constant control char 
        ///  
        internal LSRun(
            Plsrun      type, 
            IntPtr      controlChar
            ) :
            this(
                null,   // text run info 
                type,
                controlChar, 
                0,      // textRunLength 
                -1,     // offsetToFirstChar
                0 
                )
        {}

 
        /// 
        /// Construct an lsrun 
        ///  
        /// TextRunInfo
        /// plsrun type 
        /// control character
        /// text run length
        /// character offset to the first cp
        /// bidi level of this run 
        /// 
        ///     Critical: This has an unsafe code block 
        ///     TreatAsSafe: This code is ok to call since it does not expose the critical pointer 
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal LSRun(
            TextRunInfo             runInfo,
            Plsrun                  type,
            IntPtr                  controlChar, 
            int                     textRunLength,
            int                     offsetToFirstCp, 
            byte                    bidiLevel 
            )
        { 
            unsafe
            {
                _runInfo = runInfo;
                _type = type; 
                _charBufferRange = new CharacterBufferRange((char*)controlChar, 1);
                _textRunLength = textRunLength; 
                _offsetToFirstCp = offsetToFirstCp; 
                _bidiLevel = bidiLevel;
            } 
        }


        internal void Truncate(int newLength) 
        {
            _charBufferRange = new CharacterBufferRange( 
                _charBufferRange.CharacterBufferReference, 
                newLength
                ); 

            _textRunLength = newLength;
        }
 

        ///  
        /// A Boolean value indicates whether hit-testing is allowed within the run 
        /// 
        internal bool IsHitTestable 
        {
            get
            {
                return _type == Plsrun.Text; 
            }
        } 
 
        /// 
        /// A Boolean value indicates whether this run contains visible content. 
        /// 
        internal bool IsVisible
        {
            get 
            {
                return (_type == Plsrun.Text || _type == Plsrun.InlineObject); 
            } 
        }
 
        /// 
        /// A Boolean value indicates whether this run is End-Of-Line marker.
        /// 
        internal bool IsNewline 
        {
            get 
            { 
                return (_type == Plsrun.LineBreak || _type == Plsrun.ParaBreak);
            } 
        }

        /// 
        /// A Boolean value indicates whether additional info is required for caret positioning 
        /// 
        internal bool NeedsCaretInfo 
        { 
            get
            { 
                return _shapeable != null && _shapeable.NeedsCaretInfo;
            }
        }
 

        ///  
        /// A Boolean value indicates whether run has extended character 
        /// 
        internal bool HasExtendedCharacter 
        {
            get
            {
                return _shapeable != null && _shapeable.HasExtendedCharacter; 
            }
        } 
 

        ///  
        /// Draw glyphrun
        /// 
        /// The drawing context to draw into 
        ///  
        /// The foreground brush of the glyphrun. Pass in "null" to draw the
        /// glyph run with the foreground in TextRunProperties. 
        ///  
        /// The GlyphRun to be drawn 
        /// bounding rectangle of drawn glyphrun 
        /// 
        /// TextEffect drawing code may use a different foreground brush for the text.
        /// 
        internal Rect DrawGlyphRun( 
            DrawingContext  drawingContext,
            Brush           foregroundBrush, 
            GlyphRun        glyphRun 
            )
        { 
            Debug.Assert(_shapeable != null);

            Rect inkBoundingBox = glyphRun.ComputeInkBoundingBox();
 
            if (!inkBoundingBox.IsEmpty)
            { 
                // glyph run's ink bounding box is relative to its origin 
                inkBoundingBox.X += glyphRun.BaselineOrigin.X;
                inkBoundingBox.Y += glyphRun.BaselineOrigin.Y; 
            }

            if (drawingContext != null)
            { 
                int pushCount = 0;              // the number of push we do
                try 
                { 
                    if (_textEffects != null)
                    { 
                        // we need to push in the same order as they are set
                        for (int i = 0; i < _textEffects.Count; i++)
                        {
                            // get the text effect by its index 
                            TextEffect textEffect = _textEffects[i];
 
                            if (textEffect.Transform != null && textEffect.Transform != Transform.Identity) 
                            {
                                drawingContext.PushTransform(textEffect.Transform); 
                                pushCount++;
                            }

                            if (textEffect.Clip != null) 
                            {
                                drawingContext.PushClip(textEffect.Clip); 
                                pushCount++; 
                            }
 
                            if (textEffect.Foreground != null)
                            {
                                // remember the out-most non-null brush
                                // this brush will be used to draw the glyph run 
                                foregroundBrush = textEffect.Foreground;
                            } 
                        } 
                    }
 
                    _shapeable.Draw(drawingContext, foregroundBrush, glyphRun);
                }
                finally
                { 
                    for (int i = 0; i < pushCount; i++)
                    { 
                        drawingContext.Pop(); 
                    }
                } 
            }

            return inkBoundingBox;
        } 

 
        ///  
        /// Map a UV real coordinate to an XY real coordinate
        ///  
        /// line drawing origin XY
        /// vector to line origin UV
        /// real distance in text flow direction
        /// real distance in paragraph flow direction 
        /// container line
        internal static Point UVToXY( 
            Point                       origin, 
            Point                       vectorToOrigin,
            double                      u, 
            double                      v,
            TextMetrics.FullTextLine    line
            )
        { 
            Point xy;
            origin.Y += vectorToOrigin.Y; 
 
            if (line.RightToLeft)
            { 
                xy = new Point(line.Formatter.IdealToReal(line.ParagraphWidth) - vectorToOrigin.X - u + origin.X, v + origin.Y);
            }
            else
            { 
                xy = new Point(u + vectorToOrigin.X + origin.X, v + origin.Y);
            } 
 
            return xy;
        } 



        ///  
        /// Map a UV ideal coordinate to an XY real coordinate
        ///  
        /// line drawing origin 
        /// vector to line origin UV
        /// ideal distance in text flow direction 
        /// ideal distance in paragraph flow direction
        /// container line
        internal static Point UVToXY(
            Point           origin, 
            Point           vectorToOrigin,
            int             u, 
            int             v, 
            TextMetrics.FullTextLine    line
            ) 
        {
            Point xy;
            origin.Y += vectorToOrigin.Y;
 
            if (line.RightToLeft)
            { 
                xy = new Point(line.Formatter.IdealToReal(line.ParagraphWidth - u) - vectorToOrigin.X + origin.X, line.Formatter.IdealToReal(v) + origin.Y); 
            }
            else 
            {
                xy = new Point(line.Formatter.IdealToReal(u) + vectorToOrigin.X + origin.X, line.Formatter.IdealToReal(v) + origin.Y);
            }
 
            return xy;
        } 
 
        /// 
        /// Map a UV ideal coordinate to an XY ideal coordinate 
        /// 
        /// line drawing origin
        /// vector to line origin UV
        /// ideal distance in text flow direction 
        /// ideal distance in paragraph flow direction
        /// container line 
        /// ideal X origin 
        /// ideal Y origin
        internal static void UVToNominalXY( 
            Point origin,
            Point vectorToOrigin,
            int u,
            int v, 
            TextMetrics.FullTextLine line,
            out int nominalX, 
            out int nominalY 
            )
        { 
            origin.Y += vectorToOrigin.Y;

            if (line.RightToLeft)
            { 
                nominalX = line.ParagraphWidth - u + TextFormatterImp.RealToIdeal(-vectorToOrigin.X + origin.X);
            } 
            else 
            {
                nominalX = u + TextFormatterImp.RealToIdeal(vectorToOrigin.X + origin.X); 
            }

            nominalY = v + TextFormatterImp.RealToIdeal(origin.Y);
        } 

        ///  
        /// Create a rectangle of the two specified UV coordinates 
        /// 
        /// line drawing origin 
        /// logical top-left point
        /// logical bottom-right point
        /// container line
        internal static Rect RectUV( 
            Point           origin,
            LSPOINT         topLeft, 
            LSPOINT         bottomRight, 
            TextMetrics.FullTextLine    line
            ) 
        {
            int dx = topLeft.x - bottomRight.x;
            if(dx == 1 || dx == -1)
            { 
                // in certain situation LS can be off by 1
                bottomRight.x = topLeft.x; 
            } 

            Rect rect = new Rect( 
                new Point(line.Formatter.IdealToReal(topLeft.x), line.Formatter.IdealToReal(topLeft.y)),
                new Point(line.Formatter.IdealToReal(bottomRight.x), line.Formatter.IdealToReal(bottomRight.y))
                );
 
            if(DoubleUtil.AreClose(rect.TopLeft.X, rect.BottomRight.X))
            { 
                rect.Width = 0; 
            }
 
            if(DoubleUtil.AreClose(rect.TopLeft.Y, rect.BottomRight.Y))
            {
                rect.Height = 0;
            } 

            return rect; 
        } 

        ///  
        /// Move text run's baseline by the specified value
        /// 
        /// offset to be moved away from baseline
        internal void Move(int baselineMoveOffset) 
        {
            _baselineMoveOffset += baselineMoveOffset; 
        } 

        internal byte BidiLevel 
        {
            get { return _bidiLevel; }
        }
 
        internal bool IsSymbol
        { 
            get 
            {
                TextShapeableCharacters shapeable = _shapeable as TextShapeableCharacters; 
                return shapeable != null && shapeable.IsSymbol;
            }
        }
 
        internal int OffsetToFirstCp
        { 
            get { return _offsetToFirstCp; } 
        }
 
        internal int Length
        {
            get { return _textRunLength; }
        } 

        internal TextModifierScope TextModifierScope 
        { 
            get { return _runInfo.TextModifierScope; }
        } 

        internal Plsrun Type
        {
            get { return _type; } 
        }
 
        internal ushort CharacterAttributeFlags 
        {
            get { return _charFlags; } 
        }

        internal CharacterBuffer CharacterBuffer
        { 
            get { return _charBufferRange.CharacterBuffer; }
        } 
 
        internal int StringLength
        { 
            get { return _charBufferRange.Length; }
        }

        internal int OffsetToFirstChar 
        {
            get { return _charBufferRange.OffsetToFirstChar; } 
        } 

        internal TextRun TextRun 
        {
            get { return _runInfo.TextRun; }
        }
 
        internal TextShapeableSymbols Shapeable
        { 
            get { return _shapeable; } 
        }
 
        internal int BaselineOffset
        {
            get { return _baselineOffset; }
            set { _baselineOffset = value; } 
        }
 
        internal int Height 
        {
            get { return _height; } 
            set { _height = value; }
        }

        internal int Descent 
        {
            get { return Height - BaselineOffset; } 
        } 

        internal TextRunProperties RunProp 
        {
            get
            {
                return _runInfo.Properties; 
            }
        } 
 
        internal CultureInfo TextCulture
        { 
            get
            {
                return CultureMapper.GetSpecificCulture(RunProp != null ? RunProp.CultureInfo : null);
            } 
        }
 
        internal int EmSize 
        {
            get { return _emSize; } 
        }

        internal int BaselineMoveOffset
        { 
            get { return _baselineMoveOffset; }
        } 
 
        /// 
        /// required set of features that will be added to every feature set 
        /// It will be used if nothing is set in typogrpahy porperties
        /// 

        private enum CustomOpenTypeFeatures 
        {
            AlternativeFractions                     , 
            PetiteCapitalsFrom----s               , 
            SmallCapitalsFrom----s                ,
            ContextualAlternates                     , 
            CaseSensitiveForms                       ,
            ContextualLigatures                      ,
            CapitalSpacing                           ,
            ContextualSwash                          , 
            CursivePositioning                       ,
            DiscretionaryLigatures                   , 
            ExpertForms                              , 
            Fractions                                ,
            FullWidth                                , 
            HalfForms                                ,
            HalantForms                              ,
            AlternateHalfWidth                       ,
            HistoricalForms                          , 
            HorizontalKanaAlternates                 ,
            HistoricalLigatures                      , 
            HojoKanjiForms                           , 
            HalfWidth                                ,
            JIS78Forms                               , 
            JIS83Forms                               ,
            JIS90Forms                               ,
            JIS04Forms                               ,
            Kerning                                  , 
            StandardLigatures                        ,
            LiningFigures                            , 
            MathematicalGreek                        , 
            AlternateAnnotationForms                 ,
            NLCKanjiForms                            , 
            OldStyleFigures                          ,
            Ordinals                                 ,
            ProportionalAlternateWidth               ,
            PetiteCapitals                           , 
            ProportionalFigures                      ,
            ProportionalWidths                       , 
            QuarterWidths                            , 
            RubyNotationForms                        ,
            StylisticAlternates                      , 
            ScientificInferiors                      ,
            SmallCapitals                            ,
            SimplifiedForms                          ,
            StylisticSet1                            , 
            StylisticSet2                            ,
            StylisticSet3                            , 
            StylisticSet4                            , 
            StylisticSet5                            ,
            StylisticSet6                            , 
            StylisticSet7                            ,
            StylisticSet8                            ,
            StylisticSet9                            ,
            StylisticSet10                           , 
            StylisticSet11                           ,
            StylisticSet12                           , 
            StylisticSet13                           , 
            StylisticSet14                           ,
            StylisticSet15                           , 
            StylisticSet16                           ,
            StylisticSet17                           ,
            StylisticSet18                           ,
            StylisticSet19                           , 
            StylisticSet20                           ,
            Subscript                                , 
            Superscript                              , 
            Swash                                    ,
            Titling                                  , 
            TraditionalNameForms                     ,
            TabularFigures                           ,
            TraditionalForms                         ,
            ThirdWidths                              , 
            Unicase                                  ,
            SlashedZero                              , 
            Count 
        }
 
        private const ushort FeatureNotEnabled = 0xffff;

        private static DWriteFontFeature[] CreateDWriteFontFeatures(TextRunTypographyProperties textRunTypographyProperties)
        { 
            if (textRunTypographyProperties != null)
            { 
                if (textRunTypographyProperties.CachedFeatureSet != null) 
                {
                    return textRunTypographyProperties.CachedFeatureSet; 
                }
                else
                {
                    List fontFeatures = new List((int)CustomOpenTypeFeatures.Count); 

                    if (textRunTypographyProperties.CapitalSpacing) 
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.CapitalSpacing, 1));
                    } 
                    if (textRunTypographyProperties.CaseSensitiveForms)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.CaseSensitiveForms, 1));
                    } 
                    if (textRunTypographyProperties.ContextualAlternates)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualAlternates, 1)); 
                    }
                    if (textRunTypographyProperties.ContextualLigatures) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualLigatures, 1));
                    }
                    if (textRunTypographyProperties.DiscretionaryLigatures) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.DiscretionaryLigatures, 1)); 
                    } 
                    if (textRunTypographyProperties.HistoricalForms)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HistoricalForms, 1));
                    }
                    if (textRunTypographyProperties.HistoricalLigatures)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HistoricalLigatures, 1));
                    } 
                    if (textRunTypographyProperties.Kerning) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Kerning, 1)); 
                    }
                    if (textRunTypographyProperties.MathematicalGreek)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.MathematicalGreek, 1)); 
                    }
                    if (textRunTypographyProperties.SlashedZero) 
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SlashedZero, 1));
                    } 
                    if (textRunTypographyProperties.StandardLigatures)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StandardLigatures, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet1)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet1, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet10) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet10, 1));
                    }
                    if (textRunTypographyProperties.StylisticSet11) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet11, 1)); 
                    } 
                    if (textRunTypographyProperties.StylisticSet12)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet12, 1));
                    }
                    if (textRunTypographyProperties.StylisticSet13)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet13, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet14) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet14, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet15)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet15, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet16) 
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet16, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet17)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet17, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet18)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet18, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet19) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet19, 1));
                    }
                    if (textRunTypographyProperties.StylisticSet2) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet2, 1)); 
                    } 
                    if (textRunTypographyProperties.StylisticSet20)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet20, 1));
                    }
                    if (textRunTypographyProperties.StylisticSet3)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet3, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet4) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet4, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet5)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet5, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet6) 
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet6, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet7)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet7, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet8)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet8, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet9) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet9, 1));
                    }
                    if (textRunTypographyProperties.EastAsianExpertForms) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ExpertForms, 1)); 
                    } 

                    if (textRunTypographyProperties.AnnotationAlternates > 0) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternateAnnotationForms, checked((uint)textRunTypographyProperties.AnnotationAlternates)));
                    }
                    if (textRunTypographyProperties.ContextualSwashes > 0) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualSwash, checked((uint)textRunTypographyProperties.ContextualSwashes))); 
                    } 
                    if (textRunTypographyProperties.StylisticAlternates > 0)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticAlternates, checked((uint)textRunTypographyProperties.StylisticAlternates)));
                    }
                    if (textRunTypographyProperties.StandardSwashes > 0)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Swash, checked((uint)textRunTypographyProperties.StandardSwashes)));
                    } 
 
                    switch (textRunTypographyProperties.Capitals)
                    { 
                        case FontCapitals.AllPetiteCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitals, 1));
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitalsFrom----s, 1));
                            break;
                        case FontCapitals.AllSmallCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitals, 1)); 
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitalsFrom----s, 1));
                            break; 
                        case FontCapitals.PetiteCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitals, 1)); 
                            break;
                        case FontCapitals.SmallCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitals, 1)); 
                            break;
                        case FontCapitals.Titling: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Titling, 1));
                            break;
                        case FontCapitals.Unicase: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Unicase, 1)); 
                            break;
                    } 
 
                    switch (textRunTypographyProperties.EastAsianLanguage)
                    { 
                        case FontEastAsianLanguage.Simplified: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SimplifiedForms, 1));
                            break;
                        case FontEastAsianLanguage.Traditional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TraditionalForms, 1));
                            break; 
                        case FontEastAsianLanguage.TraditionalNames: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TraditionalNameForms, 1));
                            break; 
                        case FontEastAsianLanguage.NlcKanji: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.NLCKanjiForms, 1)); 
                            break;
                        case FontEastAsianLanguage.HojoKanji: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HojoKanjiForms, 1)); 
                            break;
                        case FontEastAsianLanguage.Jis78: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS78Forms, 1));
                            break;
                        case FontEastAsianLanguage.Jis83: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS83Forms, 1)); 
                            break;
                        case FontEastAsianLanguage.Jis90: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS90Forms, 1)); 
                            break; 
                        case FontEastAsianLanguage.Jis04: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS04Forms, 1));
                            break; 
                    }

                    switch (textRunTypographyProperties.Fraction)
                    { 
                        case FontFraction.Stacked: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternativeFractions, 1));
                            break; 
                        case FontFraction.Slashed: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Fractions, 1)); 
                            break;
                    } 

                    switch (textRunTypographyProperties.NumeralAlignment)
                    {
                        case FontNumeralAlignment.Proportional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalFigures, 1)); 
                            break;
                        case FontNumeralAlignment.Tabular: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TabularFigures, 1)); 
                            break; 
                    }
 
                    switch (textRunTypographyProperties.NumeralStyle)
                    {
                        case FontNumeralStyle.Lining: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.LiningFigures, 1));
                            break; 
                        case FontNumeralStyle.OldStyle: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.OldStyleFigures, 1));
                            break; 
                    } 

                    switch (textRunTypographyProperties.Variants) 
                    {
                        case FontVariants.Inferior: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ScientificInferiors, 1));
                            break;
                        case FontVariants.Ordinal: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Ordinals, 1)); 
                            break;
                        case FontVariants.Ruby: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.RubyNotationForms, 1)); 
                            break; 
                        case FontVariants.Subscript: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Subscript, 1));
                            break; 
                        case FontVariants.Superscript: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Superscript, 1));
                            break;
                    }
 
                    switch (textRunTypographyProperties.EastAsianWidths)
                    { 
                        case FontEastAsianWidths.Proportional: 
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalWidths, 1));
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalAlternateWidth, 1)); 
                            break;
                        case FontEastAsianWidths.Full: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.FullWidth, 1));
                            break;
                        case FontEastAsianWidths.Half: 
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HalfWidth, 1));
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternateHalfWidth, 1)); 
                            break; 
                        case FontEastAsianWidths.Third: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ThirdWidths, 1));
                            break; 
                        case FontEastAsianWidths.Quarter: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.QuarterWidths, 1));
                            break;
                    }
 
                    textRunTypographyProperties.CachedFeatureSet = fontFeatures.ToArray();
                    return textRunTypographyProperties.CachedFeatureSet; 
                } 

            } 
            return null;
        }

        ///  
        /// Compile feature set from the linked list of LSRuns.
        /// TypographyProperties should be either all null or all not-null. 
        /// First is used for internal purposes, also can be used by simple clients. 
        /// 
        ///  
        /// Critical - deals with unsafe int array
        /// 
        [SecurityCritical]
        internal static unsafe void CompileFeatureSet( 
            LSRun[]                   lsruns,
            int*                      pcchRuns, 
            uint                      totalLength, 
            out DWriteFontFeature[][] fontFeatures,
            out uint[]                fontFeatureRanges 
            )
        {
            Debug.Assert(lsruns != null && lsruns.Length > 0 && lsruns[0] != null);
 
            //
            //  Quick check for null properties 
            //  Run properties should be all null or all not null 
            //
            if (lsruns[0].RunProp.TypographyProperties == null) 
            {
                for (int i = 1; i < lsruns.Length; i++)
                {
                    if (lsruns[i].RunProp.TypographyProperties != null) 
                    {
                        throw new ArgumentException(SR.Get(SRID.CompileFeatureSet_InvalidTypographyProperties)); 
                    } 
                }
 
                fontFeatures      = null;
                fontFeatureRanges = null;
                return;
            } 
            //End of quick check. We will process custom features now.
 
 
            fontFeatures      = new DWriteFontFeature[lsruns.Length][];
            fontFeatureRanges = new uint[lsruns.Length]; 

            for (int i = 0; i < lsruns.Length; i++)
            {
                TextRunTypographyProperties properties = lsruns[i].RunProp.TypographyProperties; 
                fontFeatures[i] = CreateDWriteFontFeatures(properties);
                fontFeatureRanges[i] = checked((uint)pcchRuns[i]); 
            } 
        }
 
        /// 
        /// Compile feature set from the linked list of LSRuns.
        /// TypographyProperties should be either all null or all not-null.
        /// First is used for internal purposes, also can be used by simple clients. 
        /// 
        internal static void CompileFeatureSet( 
            TextRunTypographyProperties textRunTypographyProperties, 
            uint totalLength,
            out DWriteFontFeature[][] fontFeatures, 
            out uint[] fontFeatureRanges
            )
        {
            // 
            //  Quick check for null properties
            //  Run properties should be all null or all not null 
            // 
            if (textRunTypographyProperties == null)
            { 
                fontFeatures = null;
                fontFeatureRanges = null;
            }
            else 
            {
                // End of quick check. We will process custom features now. 
 
                fontFeatures = new DWriteFontFeature[1][];
                fontFeatureRanges = new uint[1]; 
                fontFeatures[0] = CreateDWriteFontFeatures(textRunTypographyProperties);
                fontFeatureRanges[0] = totalLength;
            }
        } 
    }
} 

// 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:      LSRun.cs
// 
//  Contents:  Text run in a full text line 
//
//  Created:   9-6-2001 Worachai Chaoweeraprasit (wchao) 
//
//-----------------------------------------------------------------------

using System; 
using System.Collections;
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Runtime.InteropServices;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
using System.Globalization;
 
using System.Security;
using System.Security.Permissions; 
using MS.Internal.Shaping; 
using MS.Internal.FontCache;
using MS.Utility; 

using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
 
using MS.Internal.Text.TextInterface;
 
namespace MS.Internal.TextFormatting 
{
    ///  
    /// Run represented by a plsrun value dispatched to LS during FetchRun
    /// 
    internal sealed class LSRun
    { 
        private TextRunInfo             _runInfo;                   // TextRun Info of the text
        private Plsrun                  _type;                      // Plsrun used as run type 
        private int                     _offsetToFirstCp;           // dcp from line's cpFirst 
        private int                     _textRunLength;             // textrun length
        private CharacterBufferRange    _charBufferRange;           // character buffer range 
        private int                     _baselineOffset;            // distance from top to baseline
        private int                     _height;                    // height
        private int                     _baselineMoveOffset;        // run is moved by this offset from baseline
        private int                     _emSize;                    // run ideal EM size 
        private TextShapeableSymbols    _shapeable;                 // shapeable run
        private ushort                  _charFlags;                 // character attribute flags 
        private byte                    _bidiLevel;                 // resolved bidi level 
        private IList       _textEffects;               // TextEffects that should be applied for this run
 

        /// 
        /// Construct an lsrun
        ///  
        internal LSRun(
            TextRunInfo             runInfo, 
            IList       textEffects, 
            Plsrun                  type,
            int                     offsetToFirstCp, 
            int                     textRunLength,
            int                     emSize,
            ushort                  charFlags,
            CharacterBufferRange    charBufferRange, 
            TextShapeableSymbols    shapeable,
            double                  realToIdeal, 
            byte                    bidiLevel 
            ) :
            this( 
                runInfo,
                textEffects,
                type,
                offsetToFirstCp, 
                textRunLength,
                emSize, 
                charFlags, 
                charBufferRange,
                (shapeable != null ? (int)Math.Round(shapeable.Baseline * realToIdeal) : 0), 
                (shapeable != null ? (int)Math.Round(shapeable.Height * realToIdeal) : 0),
                shapeable,
                bidiLevel
                ) 
        {}
 
 
        /// 
        /// Construct an lsrun 
        /// 
        private LSRun(
            TextRunInfo             runInfo,
            IList       textEffects, 
            Plsrun                  type,
            int                     offsetToFirstCp, 
            int                     textRunLength, 
            int                     emSize,
            ushort                  charFlags, 
            CharacterBufferRange    charBufferRange,
            int                     baselineOffset,
            int                     height,
            TextShapeableSymbols    shapeable, 
            byte                    bidiLevel
            ) 
        { 
            _runInfo = runInfo;
            _type = type; 
            _offsetToFirstCp = offsetToFirstCp;
            _textRunLength = textRunLength;
            _emSize = emSize;
            _charFlags = charFlags; 
            _charBufferRange = charBufferRange;
            _baselineOffset = baselineOffset; 
            _height = height; 
            _bidiLevel = bidiLevel;
            _shapeable = shapeable; 
            _textEffects = textEffects;
        }

 
        /// 
        /// Construct an lsrun for a constant control char 
        ///  
        internal LSRun(
            Plsrun      type, 
            IntPtr      controlChar
            ) :
            this(
                null,   // text run info 
                type,
                controlChar, 
                0,      // textRunLength 
                -1,     // offsetToFirstChar
                0 
                )
        {}

 
        /// 
        /// Construct an lsrun 
        ///  
        /// TextRunInfo
        /// plsrun type 
        /// control character
        /// text run length
        /// character offset to the first cp
        /// bidi level of this run 
        /// 
        ///     Critical: This has an unsafe code block 
        ///     TreatAsSafe: This code is ok to call since it does not expose the critical pointer 
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal LSRun(
            TextRunInfo             runInfo,
            Plsrun                  type,
            IntPtr                  controlChar, 
            int                     textRunLength,
            int                     offsetToFirstCp, 
            byte                    bidiLevel 
            )
        { 
            unsafe
            {
                _runInfo = runInfo;
                _type = type; 
                _charBufferRange = new CharacterBufferRange((char*)controlChar, 1);
                _textRunLength = textRunLength; 
                _offsetToFirstCp = offsetToFirstCp; 
                _bidiLevel = bidiLevel;
            } 
        }


        internal void Truncate(int newLength) 
        {
            _charBufferRange = new CharacterBufferRange( 
                _charBufferRange.CharacterBufferReference, 
                newLength
                ); 

            _textRunLength = newLength;
        }
 

        ///  
        /// A Boolean value indicates whether hit-testing is allowed within the run 
        /// 
        internal bool IsHitTestable 
        {
            get
            {
                return _type == Plsrun.Text; 
            }
        } 
 
        /// 
        /// A Boolean value indicates whether this run contains visible content. 
        /// 
        internal bool IsVisible
        {
            get 
            {
                return (_type == Plsrun.Text || _type == Plsrun.InlineObject); 
            } 
        }
 
        /// 
        /// A Boolean value indicates whether this run is End-Of-Line marker.
        /// 
        internal bool IsNewline 
        {
            get 
            { 
                return (_type == Plsrun.LineBreak || _type == Plsrun.ParaBreak);
            } 
        }

        /// 
        /// A Boolean value indicates whether additional info is required for caret positioning 
        /// 
        internal bool NeedsCaretInfo 
        { 
            get
            { 
                return _shapeable != null && _shapeable.NeedsCaretInfo;
            }
        }
 

        ///  
        /// A Boolean value indicates whether run has extended character 
        /// 
        internal bool HasExtendedCharacter 
        {
            get
            {
                return _shapeable != null && _shapeable.HasExtendedCharacter; 
            }
        } 
 

        ///  
        /// Draw glyphrun
        /// 
        /// The drawing context to draw into 
        ///  
        /// The foreground brush of the glyphrun. Pass in "null" to draw the
        /// glyph run with the foreground in TextRunProperties. 
        ///  
        /// The GlyphRun to be drawn 
        /// bounding rectangle of drawn glyphrun 
        /// 
        /// TextEffect drawing code may use a different foreground brush for the text.
        /// 
        internal Rect DrawGlyphRun( 
            DrawingContext  drawingContext,
            Brush           foregroundBrush, 
            GlyphRun        glyphRun 
            )
        { 
            Debug.Assert(_shapeable != null);

            Rect inkBoundingBox = glyphRun.ComputeInkBoundingBox();
 
            if (!inkBoundingBox.IsEmpty)
            { 
                // glyph run's ink bounding box is relative to its origin 
                inkBoundingBox.X += glyphRun.BaselineOrigin.X;
                inkBoundingBox.Y += glyphRun.BaselineOrigin.Y; 
            }

            if (drawingContext != null)
            { 
                int pushCount = 0;              // the number of push we do
                try 
                { 
                    if (_textEffects != null)
                    { 
                        // we need to push in the same order as they are set
                        for (int i = 0; i < _textEffects.Count; i++)
                        {
                            // get the text effect by its index 
                            TextEffect textEffect = _textEffects[i];
 
                            if (textEffect.Transform != null && textEffect.Transform != Transform.Identity) 
                            {
                                drawingContext.PushTransform(textEffect.Transform); 
                                pushCount++;
                            }

                            if (textEffect.Clip != null) 
                            {
                                drawingContext.PushClip(textEffect.Clip); 
                                pushCount++; 
                            }
 
                            if (textEffect.Foreground != null)
                            {
                                // remember the out-most non-null brush
                                // this brush will be used to draw the glyph run 
                                foregroundBrush = textEffect.Foreground;
                            } 
                        } 
                    }
 
                    _shapeable.Draw(drawingContext, foregroundBrush, glyphRun);
                }
                finally
                { 
                    for (int i = 0; i < pushCount; i++)
                    { 
                        drawingContext.Pop(); 
                    }
                } 
            }

            return inkBoundingBox;
        } 

 
        ///  
        /// Map a UV real coordinate to an XY real coordinate
        ///  
        /// line drawing origin XY
        /// vector to line origin UV
        /// real distance in text flow direction
        /// real distance in paragraph flow direction 
        /// container line
        internal static Point UVToXY( 
            Point                       origin, 
            Point                       vectorToOrigin,
            double                      u, 
            double                      v,
            TextMetrics.FullTextLine    line
            )
        { 
            Point xy;
            origin.Y += vectorToOrigin.Y; 
 
            if (line.RightToLeft)
            { 
                xy = new Point(line.Formatter.IdealToReal(line.ParagraphWidth) - vectorToOrigin.X - u + origin.X, v + origin.Y);
            }
            else
            { 
                xy = new Point(u + vectorToOrigin.X + origin.X, v + origin.Y);
            } 
 
            return xy;
        } 



        ///  
        /// Map a UV ideal coordinate to an XY real coordinate
        ///  
        /// line drawing origin 
        /// vector to line origin UV
        /// ideal distance in text flow direction 
        /// ideal distance in paragraph flow direction
        /// container line
        internal static Point UVToXY(
            Point           origin, 
            Point           vectorToOrigin,
            int             u, 
            int             v, 
            TextMetrics.FullTextLine    line
            ) 
        {
            Point xy;
            origin.Y += vectorToOrigin.Y;
 
            if (line.RightToLeft)
            { 
                xy = new Point(line.Formatter.IdealToReal(line.ParagraphWidth - u) - vectorToOrigin.X + origin.X, line.Formatter.IdealToReal(v) + origin.Y); 
            }
            else 
            {
                xy = new Point(line.Formatter.IdealToReal(u) + vectorToOrigin.X + origin.X, line.Formatter.IdealToReal(v) + origin.Y);
            }
 
            return xy;
        } 
 
        /// 
        /// Map a UV ideal coordinate to an XY ideal coordinate 
        /// 
        /// line drawing origin
        /// vector to line origin UV
        /// ideal distance in text flow direction 
        /// ideal distance in paragraph flow direction
        /// container line 
        /// ideal X origin 
        /// ideal Y origin
        internal static void UVToNominalXY( 
            Point origin,
            Point vectorToOrigin,
            int u,
            int v, 
            TextMetrics.FullTextLine line,
            out int nominalX, 
            out int nominalY 
            )
        { 
            origin.Y += vectorToOrigin.Y;

            if (line.RightToLeft)
            { 
                nominalX = line.ParagraphWidth - u + TextFormatterImp.RealToIdeal(-vectorToOrigin.X + origin.X);
            } 
            else 
            {
                nominalX = u + TextFormatterImp.RealToIdeal(vectorToOrigin.X + origin.X); 
            }

            nominalY = v + TextFormatterImp.RealToIdeal(origin.Y);
        } 

        ///  
        /// Create a rectangle of the two specified UV coordinates 
        /// 
        /// line drawing origin 
        /// logical top-left point
        /// logical bottom-right point
        /// container line
        internal static Rect RectUV( 
            Point           origin,
            LSPOINT         topLeft, 
            LSPOINT         bottomRight, 
            TextMetrics.FullTextLine    line
            ) 
        {
            int dx = topLeft.x - bottomRight.x;
            if(dx == 1 || dx == -1)
            { 
                // in certain situation LS can be off by 1
                bottomRight.x = topLeft.x; 
            } 

            Rect rect = new Rect( 
                new Point(line.Formatter.IdealToReal(topLeft.x), line.Formatter.IdealToReal(topLeft.y)),
                new Point(line.Formatter.IdealToReal(bottomRight.x), line.Formatter.IdealToReal(bottomRight.y))
                );
 
            if(DoubleUtil.AreClose(rect.TopLeft.X, rect.BottomRight.X))
            { 
                rect.Width = 0; 
            }
 
            if(DoubleUtil.AreClose(rect.TopLeft.Y, rect.BottomRight.Y))
            {
                rect.Height = 0;
            } 

            return rect; 
        } 

        ///  
        /// Move text run's baseline by the specified value
        /// 
        /// offset to be moved away from baseline
        internal void Move(int baselineMoveOffset) 
        {
            _baselineMoveOffset += baselineMoveOffset; 
        } 

        internal byte BidiLevel 
        {
            get { return _bidiLevel; }
        }
 
        internal bool IsSymbol
        { 
            get 
            {
                TextShapeableCharacters shapeable = _shapeable as TextShapeableCharacters; 
                return shapeable != null && shapeable.IsSymbol;
            }
        }
 
        internal int OffsetToFirstCp
        { 
            get { return _offsetToFirstCp; } 
        }
 
        internal int Length
        {
            get { return _textRunLength; }
        } 

        internal TextModifierScope TextModifierScope 
        { 
            get { return _runInfo.TextModifierScope; }
        } 

        internal Plsrun Type
        {
            get { return _type; } 
        }
 
        internal ushort CharacterAttributeFlags 
        {
            get { return _charFlags; } 
        }

        internal CharacterBuffer CharacterBuffer
        { 
            get { return _charBufferRange.CharacterBuffer; }
        } 
 
        internal int StringLength
        { 
            get { return _charBufferRange.Length; }
        }

        internal int OffsetToFirstChar 
        {
            get { return _charBufferRange.OffsetToFirstChar; } 
        } 

        internal TextRun TextRun 
        {
            get { return _runInfo.TextRun; }
        }
 
        internal TextShapeableSymbols Shapeable
        { 
            get { return _shapeable; } 
        }
 
        internal int BaselineOffset
        {
            get { return _baselineOffset; }
            set { _baselineOffset = value; } 
        }
 
        internal int Height 
        {
            get { return _height; } 
            set { _height = value; }
        }

        internal int Descent 
        {
            get { return Height - BaselineOffset; } 
        } 

        internal TextRunProperties RunProp 
        {
            get
            {
                return _runInfo.Properties; 
            }
        } 
 
        internal CultureInfo TextCulture
        { 
            get
            {
                return CultureMapper.GetSpecificCulture(RunProp != null ? RunProp.CultureInfo : null);
            } 
        }
 
        internal int EmSize 
        {
            get { return _emSize; } 
        }

        internal int BaselineMoveOffset
        { 
            get { return _baselineMoveOffset; }
        } 
 
        /// 
        /// required set of features that will be added to every feature set 
        /// It will be used if nothing is set in typogrpahy porperties
        /// 

        private enum CustomOpenTypeFeatures 
        {
            AlternativeFractions                     , 
            PetiteCapitalsFrom----s               , 
            SmallCapitalsFrom----s                ,
            ContextualAlternates                     , 
            CaseSensitiveForms                       ,
            ContextualLigatures                      ,
            CapitalSpacing                           ,
            ContextualSwash                          , 
            CursivePositioning                       ,
            DiscretionaryLigatures                   , 
            ExpertForms                              , 
            Fractions                                ,
            FullWidth                                , 
            HalfForms                                ,
            HalantForms                              ,
            AlternateHalfWidth                       ,
            HistoricalForms                          , 
            HorizontalKanaAlternates                 ,
            HistoricalLigatures                      , 
            HojoKanjiForms                           , 
            HalfWidth                                ,
            JIS78Forms                               , 
            JIS83Forms                               ,
            JIS90Forms                               ,
            JIS04Forms                               ,
            Kerning                                  , 
            StandardLigatures                        ,
            LiningFigures                            , 
            MathematicalGreek                        , 
            AlternateAnnotationForms                 ,
            NLCKanjiForms                            , 
            OldStyleFigures                          ,
            Ordinals                                 ,
            ProportionalAlternateWidth               ,
            PetiteCapitals                           , 
            ProportionalFigures                      ,
            ProportionalWidths                       , 
            QuarterWidths                            , 
            RubyNotationForms                        ,
            StylisticAlternates                      , 
            ScientificInferiors                      ,
            SmallCapitals                            ,
            SimplifiedForms                          ,
            StylisticSet1                            , 
            StylisticSet2                            ,
            StylisticSet3                            , 
            StylisticSet4                            , 
            StylisticSet5                            ,
            StylisticSet6                            , 
            StylisticSet7                            ,
            StylisticSet8                            ,
            StylisticSet9                            ,
            StylisticSet10                           , 
            StylisticSet11                           ,
            StylisticSet12                           , 
            StylisticSet13                           , 
            StylisticSet14                           ,
            StylisticSet15                           , 
            StylisticSet16                           ,
            StylisticSet17                           ,
            StylisticSet18                           ,
            StylisticSet19                           , 
            StylisticSet20                           ,
            Subscript                                , 
            Superscript                              , 
            Swash                                    ,
            Titling                                  , 
            TraditionalNameForms                     ,
            TabularFigures                           ,
            TraditionalForms                         ,
            ThirdWidths                              , 
            Unicase                                  ,
            SlashedZero                              , 
            Count 
        }
 
        private const ushort FeatureNotEnabled = 0xffff;

        private static DWriteFontFeature[] CreateDWriteFontFeatures(TextRunTypographyProperties textRunTypographyProperties)
        { 
            if (textRunTypographyProperties != null)
            { 
                if (textRunTypographyProperties.CachedFeatureSet != null) 
                {
                    return textRunTypographyProperties.CachedFeatureSet; 
                }
                else
                {
                    List fontFeatures = new List((int)CustomOpenTypeFeatures.Count); 

                    if (textRunTypographyProperties.CapitalSpacing) 
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.CapitalSpacing, 1));
                    } 
                    if (textRunTypographyProperties.CaseSensitiveForms)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.CaseSensitiveForms, 1));
                    } 
                    if (textRunTypographyProperties.ContextualAlternates)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualAlternates, 1)); 
                    }
                    if (textRunTypographyProperties.ContextualLigatures) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualLigatures, 1));
                    }
                    if (textRunTypographyProperties.DiscretionaryLigatures) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.DiscretionaryLigatures, 1)); 
                    } 
                    if (textRunTypographyProperties.HistoricalForms)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HistoricalForms, 1));
                    }
                    if (textRunTypographyProperties.HistoricalLigatures)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HistoricalLigatures, 1));
                    } 
                    if (textRunTypographyProperties.Kerning) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Kerning, 1)); 
                    }
                    if (textRunTypographyProperties.MathematicalGreek)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.MathematicalGreek, 1)); 
                    }
                    if (textRunTypographyProperties.SlashedZero) 
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SlashedZero, 1));
                    } 
                    if (textRunTypographyProperties.StandardLigatures)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StandardLigatures, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet1)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet1, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet10) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet10, 1));
                    }
                    if (textRunTypographyProperties.StylisticSet11) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet11, 1)); 
                    } 
                    if (textRunTypographyProperties.StylisticSet12)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet12, 1));
                    }
                    if (textRunTypographyProperties.StylisticSet13)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet13, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet14) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet14, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet15)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet15, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet16) 
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet16, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet17)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet17, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet18)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet18, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet19) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet19, 1));
                    }
                    if (textRunTypographyProperties.StylisticSet2) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet2, 1)); 
                    } 
                    if (textRunTypographyProperties.StylisticSet20)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet20, 1));
                    }
                    if (textRunTypographyProperties.StylisticSet3)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet3, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet4) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet4, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet5)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet5, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet6) 
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet6, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet7)
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet7, 1));
                    } 
                    if (textRunTypographyProperties.StylisticSet8)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet8, 1)); 
                    }
                    if (textRunTypographyProperties.StylisticSet9) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet9, 1));
                    }
                    if (textRunTypographyProperties.EastAsianExpertForms) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ExpertForms, 1)); 
                    } 

                    if (textRunTypographyProperties.AnnotationAlternates > 0) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternateAnnotationForms, checked((uint)textRunTypographyProperties.AnnotationAlternates)));
                    }
                    if (textRunTypographyProperties.ContextualSwashes > 0) 
                    {
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualSwash, checked((uint)textRunTypographyProperties.ContextualSwashes))); 
                    } 
                    if (textRunTypographyProperties.StylisticAlternates > 0)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticAlternates, checked((uint)textRunTypographyProperties.StylisticAlternates)));
                    }
                    if (textRunTypographyProperties.StandardSwashes > 0)
                    { 
                        fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Swash, checked((uint)textRunTypographyProperties.StandardSwashes)));
                    } 
 
                    switch (textRunTypographyProperties.Capitals)
                    { 
                        case FontCapitals.AllPetiteCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitals, 1));
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitalsFrom----s, 1));
                            break;
                        case FontCapitals.AllSmallCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitals, 1)); 
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitalsFrom----s, 1));
                            break; 
                        case FontCapitals.PetiteCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitals, 1)); 
                            break;
                        case FontCapitals.SmallCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitals, 1)); 
                            break;
                        case FontCapitals.Titling: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Titling, 1));
                            break;
                        case FontCapitals.Unicase: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Unicase, 1)); 
                            break;
                    } 
 
                    switch (textRunTypographyProperties.EastAsianLanguage)
                    { 
                        case FontEastAsianLanguage.Simplified: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SimplifiedForms, 1));
                            break;
                        case FontEastAsianLanguage.Traditional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TraditionalForms, 1));
                            break; 
                        case FontEastAsianLanguage.TraditionalNames: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TraditionalNameForms, 1));
                            break; 
                        case FontEastAsianLanguage.NlcKanji: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.NLCKanjiForms, 1)); 
                            break;
                        case FontEastAsianLanguage.HojoKanji: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HojoKanjiForms, 1)); 
                            break;
                        case FontEastAsianLanguage.Jis78: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS78Forms, 1));
                            break;
                        case FontEastAsianLanguage.Jis83: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS83Forms, 1)); 
                            break;
                        case FontEastAsianLanguage.Jis90: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS90Forms, 1)); 
                            break; 
                        case FontEastAsianLanguage.Jis04: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS04Forms, 1));
                            break; 
                    }

                    switch (textRunTypographyProperties.Fraction)
                    { 
                        case FontFraction.Stacked: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternativeFractions, 1));
                            break; 
                        case FontFraction.Slashed: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Fractions, 1)); 
                            break;
                    } 

                    switch (textRunTypographyProperties.NumeralAlignment)
                    {
                        case FontNumeralAlignment.Proportional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalFigures, 1)); 
                            break;
                        case FontNumeralAlignment.Tabular: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TabularFigures, 1)); 
                            break; 
                    }
 
                    switch (textRunTypographyProperties.NumeralStyle)
                    {
                        case FontNumeralStyle.Lining: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.LiningFigures, 1));
                            break; 
                        case FontNumeralStyle.OldStyle: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.OldStyleFigures, 1));
                            break; 
                    } 

                    switch (textRunTypographyProperties.Variants) 
                    {
                        case FontVariants.Inferior: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ScientificInferiors, 1));
                            break;
                        case FontVariants.Ordinal: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Ordinals, 1)); 
                            break;
                        case FontVariants.Ruby: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.RubyNotationForms, 1)); 
                            break; 
                        case FontVariants.Subscript: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Subscript, 1));
                            break; 
                        case FontVariants.Superscript: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Superscript, 1));
                            break;
                    }
 
                    switch (textRunTypographyProperties.EastAsianWidths)
                    { 
                        case FontEastAsianWidths.Proportional: 
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalWidths, 1));
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalAlternateWidth, 1)); 
                            break;
                        case FontEastAsianWidths.Full: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.FullWidth, 1));
                            break;
                        case FontEastAsianWidths.Half: 
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HalfWidth, 1));
                            fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternateHalfWidth, 1)); 
                            break; 
                        case FontEastAsianWidths.Third: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ThirdWidths, 1));
                            break; 
                        case FontEastAsianWidths.Quarter: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.QuarterWidths, 1));
                            break;
                    }
 
                    textRunTypographyProperties.CachedFeatureSet = fontFeatures.ToArray();
                    return textRunTypographyProperties.CachedFeatureSet; 
                } 

            } 
            return null;
        }

        ///  
        /// Compile feature set from the linked list of LSRuns.
        /// TypographyProperties should be either all null or all not-null. 
        /// First is used for internal purposes, also can be used by simple clients. 
        /// 
        ///  
        /// Critical - deals with unsafe int array
        /// 
        [SecurityCritical]
        internal static unsafe void CompileFeatureSet( 
            LSRun[]                   lsruns,
            int*                      pcchRuns, 
            uint                      totalLength, 
            out DWriteFontFeature[][] fontFeatures,
            out uint[]                fontFeatureRanges 
            )
        {
            Debug.Assert(lsruns != null && lsruns.Length > 0 && lsruns[0] != null);
 
            //
            //  Quick check for null properties 
            //  Run properties should be all null or all not null 
            //
            if (lsruns[0].RunProp.TypographyProperties == null) 
            {
                for (int i = 1; i < lsruns.Length; i++)
                {
                    if (lsruns[i].RunProp.TypographyProperties != null) 
                    {
                        throw new ArgumentException(SR.Get(SRID.CompileFeatureSet_InvalidTypographyProperties)); 
                    } 
                }
 
                fontFeatures      = null;
                fontFeatureRanges = null;
                return;
            } 
            //End of quick check. We will process custom features now.
 
 
            fontFeatures      = new DWriteFontFeature[lsruns.Length][];
            fontFeatureRanges = new uint[lsruns.Length]; 

            for (int i = 0; i < lsruns.Length; i++)
            {
                TextRunTypographyProperties properties = lsruns[i].RunProp.TypographyProperties; 
                fontFeatures[i] = CreateDWriteFontFeatures(properties);
                fontFeatureRanges[i] = checked((uint)pcchRuns[i]); 
            } 
        }
 
        /// 
        /// Compile feature set from the linked list of LSRuns.
        /// TypographyProperties should be either all null or all not-null.
        /// First is used for internal purposes, also can be used by simple clients. 
        /// 
        internal static void CompileFeatureSet( 
            TextRunTypographyProperties textRunTypographyProperties, 
            uint totalLength,
            out DWriteFontFeature[][] fontFeatures, 
            out uint[] fontFeatureRanges
            )
        {
            // 
            //  Quick check for null properties
            //  Run properties should be all null or all not null 
            // 
            if (textRunTypographyProperties == null)
            { 
                fontFeatures = null;
                fontFeatureRanges = null;
            }
            else 
            {
                // End of quick check. We will process custom features now. 
 
                fontFeatures = new DWriteFontFeature[1][];
                fontFeatureRanges = new uint[1]; 
                fontFeatures[0] = CreateDWriteFontFeatures(textRunTypographyProperties);
                fontFeatureRanges[0] = totalLength;
            }
        } 
    }
} 

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