FormattedTextSymbols.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / MS / Internal / TextFormatting / FormattedTextSymbols.cs / 1 / FormattedTextSymbols.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: 
//  Formatting a single style, single reading direction text symbols
// 
// History:
//  08/16/2004 : wchao - Created it
//
//--------------------------------------------------------------------------- 

using System; 
using System.Security; 
using System.Windows;
using System.Windows.Media; 
using System.Windows.Media.TextFormatting;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics; 
using MS.Internal;
using MS.Internal.Shaping; 
 

namespace MS.Internal.TextFormatting 
{
    /// 
    /// Formatted form of TextSymbols
    ///  
    internal sealed class FormattedTextSymbols
    { 
        private Glyphs[]    _glyphs; 
        private bool        _rightToLeft;
 
        /// 
        /// Construct a formatted run
        /// 
        ///  
        /// Critical - this method has unsafe blocks
        /// Safe     - it doesn't expose any critical data 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        public FormattedTextSymbols( 
            GlyphingCache glyphingCache,
            TextRun       textSymbols,
            bool          rightToLeft,
            double        scalingFactor 
            )
        { 
 
            ITextSymbols  symbols = textSymbols as ITextSymbols;
 
            Debug.Assert(symbols != null);

            // break down a single text run into pieces
            IList shapeables = symbols.GetTextShapeableSymbols( 
                glyphingCache,
                textSymbols.CharacterBufferReference, 
                textSymbols.Length, 
                rightToLeft,
                null, // cultureInfo 
                null  // textModifierScope
                );

            Debug.Assert(shapeables != null && shapeables.Count > 0); 

            _rightToLeft = rightToLeft; 
            _glyphs = new Glyphs[shapeables.Count]; 

            CharacterBuffer charBuffer = textSymbols.CharacterBufferReference.CharacterBuffer; 
            int offsetToFirstChar = textSymbols.CharacterBufferReference.OffsetToFirstChar;

            int i = 0;
            int ich = 0; 

            while (i < shapeables.Count) 
            { 
                TextShapeableSymbols current = shapeables[i] as TextShapeableSymbols;
                Debug.Assert(current != null); 

                int cch = current.Length;
                int j;
 
                // make a separate character buffer for glyphrun persistence
                char[] charArray = new char[cch]; 
                for (j = 0; j < cch; j++) 
                    charArray[j] = charBuffer[offsetToFirstChar + ich + j];
 
                if (current.IsShapingRequired)
                {
                    ushort[] clusterMap = new ushort[cch];
                    CharacterShapingProperties[] charProp = new CharacterShapingProperties[cch]; 

                    int glyphCount; 
                    ushort[] glyphIndices; 
                    GlyphShapingProperties[] glyphProp;
                    int[] glyphAdvances; 
                    GlyphOffset[] glyphOffsets;

                    // Note that we dont check for the chance of having multiple
                    // shapeables shaped together here since we're dealing with 
                    // single-style text. There is virtually no chance to require
                    // for adjacent runs to shape together. We rely on TextSymbols 
                    // to reduce duplication of the itemized shapeables for performance. 
                    unsafe
                    { 
                        fixed (char* fixedCharArray = &charArray[0])
                        fixed (ushort* fixedClusterMap = &clusterMap[0])
                        fixed (CharacterShapingProperties* fixedCharProp = &charProp[0])
                        { 
                            glyphIndices = current.GetGlyphs(
                                new CheckedCharPointer(fixedCharArray, cch), 
                                cch, 
                                ShapingOptions.None,
                                null,   // featureSet 
                                new CheckedUShortPointer(fixedClusterMap, cch),
                                new CheckedCharacterShapingPropertiesPointer(fixedCharProp,cch),
                                out glyphProp,
                                out glyphCount 
                                );
 
                            // Shaping is all done in ideal units. 
                            // Create int[] and GlyphOffset[] for shaping
                            glyphAdvances = new int[glyphCount]; 
                            glyphOffsets = new GlyphOffset[glyphCount];

                            fixed (ushort* fixedGlyphIndices = &glyphIndices[0])
                            fixed (GlyphShapingProperties* fixedGlyphProp = &glyphProp[0]) 
                            fixed (int* fixedGlyphAdvances = &glyphAdvances[0])
                            fixed (GlyphOffset * fixedGlyphOffsets = &glyphOffsets[0]) 
                            { 
                                current.GetGlyphPlacements(
                                    new CheckedUShortPointer(fixedGlyphIndices, glyphCount), 
                                    new CheckedGlyphShapingPropertiesPointer(fixedGlyphProp, glyphCount),
                                    glyphCount,
                                    new CheckedUShortPointer(fixedClusterMap, cch),
                                    new CheckedCharacterShapingPropertiesPointer(fixedCharProp, cch), 
                                    cch,
                                    ShapingOptions.None, 
                                    null,             // featureSet 
                                    scalingFactor,    // format resolution specified per em
                                    new CheckedIntPointer(fixedGlyphAdvances, glyphCount), 
                                    new CheckedGlyphOffsetPointer(fixedGlyphOffsets, glyphCount)
                                    );
                            }
                        } 

                        _glyphs[i] = new Glyphs( 
                            current, 
                            charArray,
                            glyphAdvances, 
                            clusterMap,
                            glyphIndices,
                            glyphProp,
                            glyphOffsets, 
                            scalingFactor
                            ); 
                    } 
                }
                else 
                {
                    // shaping not required,
                    // bypass glyphing process altogether
                    int[] nominalAdvances = new int[charArray.Length]; 

                    unsafe 
                    { 
                        fixed(char* fixedCharArray = &charArray[0])
                        fixed(int * fixedNominalAdvances = &nominalAdvances[0]) 
                        {
                            current.GetAdvanceWidthsUnshaped(
                                fixedCharArray,
                                cch, 
                                scalingFactor, // format resolution specified per em,
                                fixedNominalAdvances 
                                ); 
                        }
                    } 

                    _glyphs[i] = new Glyphs(
                        current,
                        charArray, 
                        nominalAdvances,
                        scalingFactor 
                        ); 
                }
 
                i++;
                ich += cch;
            }
        } 

 
        ///  
        /// Total formatted width
        ///  
        public double Width
        {
            get
            { 
                Debug.Assert(_glyphs != null);
 
                double width = 0; 
                foreach (Glyphs glyphs in _glyphs)
                { 
                    width += glyphs.Width;
                }
                return width;
            } 
        }
 
 
        /// 
        /// Draw all formatted glyphruns 
        /// 
        /// drawing bounding box
        public Rect Draw(
            DrawingContext drawingContext, 
            Point          currentOrigin
            ) 
        { 
            Rect inkBoundingBox = Rect.Empty;
 
            Debug.Assert(_glyphs != null);

            foreach (Glyphs glyphs in _glyphs)
            { 
                GlyphRun glyphRun = glyphs.CreateGlyphRun(currentOrigin, _rightToLeft);
                Rect boundingBox; 
 
                if (glyphRun != null)
                { 
                    boundingBox = glyphRun.ComputeInkBoundingBox();

                    if (drawingContext != null)
                    { 
                        // Emit glyph run background.
                        glyphRun.EmitBackground(drawingContext, glyphs.BackgroundBrush); 
 
                        drawingContext.PushGuidelineY1(currentOrigin.Y);
                        try 
                        {
                            drawingContext.DrawGlyphRun(glyphs.ForegroundBrush, glyphRun);
                        }
                        finally 
                        {
                            drawingContext.Pop(); 
                        } 
                    }
                } 
                else
                {
                    boundingBox = Rect.Empty;
                } 

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

                // accumulate overall ink bounding box 
                inkBoundingBox.Union(boundingBox);
 
                if (_rightToLeft) 
                {
                    currentOrigin.X -= glyphs.Width; 
                }
                else
                {
                    currentOrigin.X += glyphs.Width; 
                }
            } 
 
            return inkBoundingBox;
        } 


        /// 
        /// All glyph properties used during GlyphRun construction 
        /// 
        ///  
        /// We should be able to get rid off this type and just store GlyphRuns 
        /// once GlyphRun gets refactor'd so that it contains no drawing time
        /// positioning data inside. 
        /// 
        private sealed class Glyphs
        {
            private TextShapeableSymbols     _shapeable; 
            private char[]                   _charArray;
            private ushort[]                 _clusterMap; 
            private ushort[]                 _glyphIndices; 
            private GlyphShapingProperties[] _glyphProp;
            private double[]                 _glyphAdvances; 
            private IList             _glyphOffsets;
            private double                   _width;

 
            /// 
            /// Construct a nominal description of glyph data 
            ///  
            internal Glyphs(
                TextShapeableSymbols    shapeable, 
                char[]                  charArray,
                int[]                   nominalAdvances,
                double                  scalingFactor
                ) : 
                this(
                    shapeable, 
                    charArray, 
                    nominalAdvances,
                    null,   // clusterMap 
                    null,   // glyphIndices
                    null,   // glyphProp
                    null,   // glyphOffsets
                    scalingFactor 
                    )
            {} 
 

            ///  
            /// Construct a full description of glyph data
            /// 
            internal Glyphs(
                TextShapeableSymbols     shapeable, 
                char[]                   charArray,
                int[]                    glyphAdvances, 
                ushort[]                 clusterMap, 
                ushort[]                 glyphIndices,
                GlyphShapingProperties[] glyphProp, 
                GlyphOffset[]            glyphOffsets,
                double                   scalingFactor
                )
            { 
                _shapeable = shapeable;
                _charArray = charArray; 
 
                // create double array for glyph run creation, because Shaping is all done in
                // ideal units. FormattedTextSymbol is used to draw text collapsing symbols 
                // which usually contains very few glyphs. Using double[] and Point[] directly
                // is more efficient.
                _glyphAdvances = new double[glyphAdvances.Length];
 
                double ToReal = 1.0 / scalingFactor;
 
                for (int i = 0; i < glyphAdvances.Length; i++) 
                {
                    _glyphAdvances[i] = glyphAdvances[i] * ToReal; 
                    _width += _glyphAdvances[i];

                }
 
                if (glyphIndices != null)
                { 
                    _clusterMap = clusterMap; 

                    if (glyphOffsets != null) 
                    {
                        _glyphOffsets  = new PartialArray(new Point[glyphOffsets.Length]);

                        for (int i = 0; i < glyphOffsets.Length; i++) 
                        {
                            _glyphOffsets[i] = new Point( 
                                glyphOffsets[i].du * ToReal, 
                                glyphOffsets[i].dv * ToReal
                                ); 
                        }
                    }

                    Debug.Assert(glyphAdvances.Length <= glyphIndices.Length); 

                    if (glyphAdvances.Length != glyphIndices.Length) 
                    { 
                        _glyphIndices = new ushort[glyphAdvances.Length];
                        _glyphProp = new GlyphShapingProperties[glyphAdvances.Length]; 

                        for (int i = 0; i < glyphAdvances.Length; i++)
                        {
                            _glyphIndices[i] = glyphIndices[i]; 
                            _glyphProp[i] = glyphProp[i];
                        } 
                    } 
                    else
                    { 
                        _glyphIndices = glyphIndices;
                        _glyphProp = glyphProp;
                    }
                } 
            }
 
 
            /// 
            /// Total formatted width 
            /// 
            public double Width
            {
                get { return _width; } 
            }
 
 
            /// 
            /// Construct a GlyphRun object given the specified drawing origin 
            /// 
            internal GlyphRun CreateGlyphRun(
                Point       currentOrigin,
                bool        rightToLeft 
                )
            { 
                if (!_shapeable.IsShapingRequired) 
                {
                    return _shapeable.ComputeUnshapedGlyphRun( 
                        currentOrigin,
                        _charArray,
                        _glyphAdvances
                        ); 
                }
 
                return _shapeable.ComputeShapedGlyphRun( 
                    currentOrigin,
                    _charArray, 
                    _clusterMap,
                    _glyphIndices,
                    _glyphProp,
                    _glyphAdvances, 
                    _glyphOffsets,
                    rightToLeft, 
                    false   // sideways not yet supported 
                    );
            } 

            public Brush ForegroundBrush
            {
                get { return _shapeable.Properties.ForegroundBrush; } 
            }
 
            public Brush BackgroundBrush 
            {
                get { return _shapeable.Properties.BackgroundBrush; } 
            }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: 
//  Formatting a single style, single reading direction text symbols
// 
// History:
//  08/16/2004 : wchao - Created it
//
//--------------------------------------------------------------------------- 

using System; 
using System.Security; 
using System.Windows;
using System.Windows.Media; 
using System.Windows.Media.TextFormatting;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics; 
using MS.Internal;
using MS.Internal.Shaping; 
 

namespace MS.Internal.TextFormatting 
{
    /// 
    /// Formatted form of TextSymbols
    ///  
    internal sealed class FormattedTextSymbols
    { 
        private Glyphs[]    _glyphs; 
        private bool        _rightToLeft;
 
        /// 
        /// Construct a formatted run
        /// 
        ///  
        /// Critical - this method has unsafe blocks
        /// Safe     - it doesn't expose any critical data 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        public FormattedTextSymbols( 
            GlyphingCache glyphingCache,
            TextRun       textSymbols,
            bool          rightToLeft,
            double        scalingFactor 
            )
        { 
 
            ITextSymbols  symbols = textSymbols as ITextSymbols;
 
            Debug.Assert(symbols != null);

            // break down a single text run into pieces
            IList shapeables = symbols.GetTextShapeableSymbols( 
                glyphingCache,
                textSymbols.CharacterBufferReference, 
                textSymbols.Length, 
                rightToLeft,
                null, // cultureInfo 
                null  // textModifierScope
                );

            Debug.Assert(shapeables != null && shapeables.Count > 0); 

            _rightToLeft = rightToLeft; 
            _glyphs = new Glyphs[shapeables.Count]; 

            CharacterBuffer charBuffer = textSymbols.CharacterBufferReference.CharacterBuffer; 
            int offsetToFirstChar = textSymbols.CharacterBufferReference.OffsetToFirstChar;

            int i = 0;
            int ich = 0; 

            while (i < shapeables.Count) 
            { 
                TextShapeableSymbols current = shapeables[i] as TextShapeableSymbols;
                Debug.Assert(current != null); 

                int cch = current.Length;
                int j;
 
                // make a separate character buffer for glyphrun persistence
                char[] charArray = new char[cch]; 
                for (j = 0; j < cch; j++) 
                    charArray[j] = charBuffer[offsetToFirstChar + ich + j];
 
                if (current.IsShapingRequired)
                {
                    ushort[] clusterMap = new ushort[cch];
                    CharacterShapingProperties[] charProp = new CharacterShapingProperties[cch]; 

                    int glyphCount; 
                    ushort[] glyphIndices; 
                    GlyphShapingProperties[] glyphProp;
                    int[] glyphAdvances; 
                    GlyphOffset[] glyphOffsets;

                    // Note that we dont check for the chance of having multiple
                    // shapeables shaped together here since we're dealing with 
                    // single-style text. There is virtually no chance to require
                    // for adjacent runs to shape together. We rely on TextSymbols 
                    // to reduce duplication of the itemized shapeables for performance. 
                    unsafe
                    { 
                        fixed (char* fixedCharArray = &charArray[0])
                        fixed (ushort* fixedClusterMap = &clusterMap[0])
                        fixed (CharacterShapingProperties* fixedCharProp = &charProp[0])
                        { 
                            glyphIndices = current.GetGlyphs(
                                new CheckedCharPointer(fixedCharArray, cch), 
                                cch, 
                                ShapingOptions.None,
                                null,   // featureSet 
                                new CheckedUShortPointer(fixedClusterMap, cch),
                                new CheckedCharacterShapingPropertiesPointer(fixedCharProp,cch),
                                out glyphProp,
                                out glyphCount 
                                );
 
                            // Shaping is all done in ideal units. 
                            // Create int[] and GlyphOffset[] for shaping
                            glyphAdvances = new int[glyphCount]; 
                            glyphOffsets = new GlyphOffset[glyphCount];

                            fixed (ushort* fixedGlyphIndices = &glyphIndices[0])
                            fixed (GlyphShapingProperties* fixedGlyphProp = &glyphProp[0]) 
                            fixed (int* fixedGlyphAdvances = &glyphAdvances[0])
                            fixed (GlyphOffset * fixedGlyphOffsets = &glyphOffsets[0]) 
                            { 
                                current.GetGlyphPlacements(
                                    new CheckedUShortPointer(fixedGlyphIndices, glyphCount), 
                                    new CheckedGlyphShapingPropertiesPointer(fixedGlyphProp, glyphCount),
                                    glyphCount,
                                    new CheckedUShortPointer(fixedClusterMap, cch),
                                    new CheckedCharacterShapingPropertiesPointer(fixedCharProp, cch), 
                                    cch,
                                    ShapingOptions.None, 
                                    null,             // featureSet 
                                    scalingFactor,    // format resolution specified per em
                                    new CheckedIntPointer(fixedGlyphAdvances, glyphCount), 
                                    new CheckedGlyphOffsetPointer(fixedGlyphOffsets, glyphCount)
                                    );
                            }
                        } 

                        _glyphs[i] = new Glyphs( 
                            current, 
                            charArray,
                            glyphAdvances, 
                            clusterMap,
                            glyphIndices,
                            glyphProp,
                            glyphOffsets, 
                            scalingFactor
                            ); 
                    } 
                }
                else 
                {
                    // shaping not required,
                    // bypass glyphing process altogether
                    int[] nominalAdvances = new int[charArray.Length]; 

                    unsafe 
                    { 
                        fixed(char* fixedCharArray = &charArray[0])
                        fixed(int * fixedNominalAdvances = &nominalAdvances[0]) 
                        {
                            current.GetAdvanceWidthsUnshaped(
                                fixedCharArray,
                                cch, 
                                scalingFactor, // format resolution specified per em,
                                fixedNominalAdvances 
                                ); 
                        }
                    } 

                    _glyphs[i] = new Glyphs(
                        current,
                        charArray, 
                        nominalAdvances,
                        scalingFactor 
                        ); 
                }
 
                i++;
                ich += cch;
            }
        } 

 
        ///  
        /// Total formatted width
        ///  
        public double Width
        {
            get
            { 
                Debug.Assert(_glyphs != null);
 
                double width = 0; 
                foreach (Glyphs glyphs in _glyphs)
                { 
                    width += glyphs.Width;
                }
                return width;
            } 
        }
 
 
        /// 
        /// Draw all formatted glyphruns 
        /// 
        /// drawing bounding box
        public Rect Draw(
            DrawingContext drawingContext, 
            Point          currentOrigin
            ) 
        { 
            Rect inkBoundingBox = Rect.Empty;
 
            Debug.Assert(_glyphs != null);

            foreach (Glyphs glyphs in _glyphs)
            { 
                GlyphRun glyphRun = glyphs.CreateGlyphRun(currentOrigin, _rightToLeft);
                Rect boundingBox; 
 
                if (glyphRun != null)
                { 
                    boundingBox = glyphRun.ComputeInkBoundingBox();

                    if (drawingContext != null)
                    { 
                        // Emit glyph run background.
                        glyphRun.EmitBackground(drawingContext, glyphs.BackgroundBrush); 
 
                        drawingContext.PushGuidelineY1(currentOrigin.Y);
                        try 
                        {
                            drawingContext.DrawGlyphRun(glyphs.ForegroundBrush, glyphRun);
                        }
                        finally 
                        {
                            drawingContext.Pop(); 
                        } 
                    }
                } 
                else
                {
                    boundingBox = Rect.Empty;
                } 

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

                // accumulate overall ink bounding box 
                inkBoundingBox.Union(boundingBox);
 
                if (_rightToLeft) 
                {
                    currentOrigin.X -= glyphs.Width; 
                }
                else
                {
                    currentOrigin.X += glyphs.Width; 
                }
            } 
 
            return inkBoundingBox;
        } 


        /// 
        /// All glyph properties used during GlyphRun construction 
        /// 
        ///  
        /// We should be able to get rid off this type and just store GlyphRuns 
        /// once GlyphRun gets refactor'd so that it contains no drawing time
        /// positioning data inside. 
        /// 
        private sealed class Glyphs
        {
            private TextShapeableSymbols     _shapeable; 
            private char[]                   _charArray;
            private ushort[]                 _clusterMap; 
            private ushort[]                 _glyphIndices; 
            private GlyphShapingProperties[] _glyphProp;
            private double[]                 _glyphAdvances; 
            private IList             _glyphOffsets;
            private double                   _width;

 
            /// 
            /// Construct a nominal description of glyph data 
            ///  
            internal Glyphs(
                TextShapeableSymbols    shapeable, 
                char[]                  charArray,
                int[]                   nominalAdvances,
                double                  scalingFactor
                ) : 
                this(
                    shapeable, 
                    charArray, 
                    nominalAdvances,
                    null,   // clusterMap 
                    null,   // glyphIndices
                    null,   // glyphProp
                    null,   // glyphOffsets
                    scalingFactor 
                    )
            {} 
 

            ///  
            /// Construct a full description of glyph data
            /// 
            internal Glyphs(
                TextShapeableSymbols     shapeable, 
                char[]                   charArray,
                int[]                    glyphAdvances, 
                ushort[]                 clusterMap, 
                ushort[]                 glyphIndices,
                GlyphShapingProperties[] glyphProp, 
                GlyphOffset[]            glyphOffsets,
                double                   scalingFactor
                )
            { 
                _shapeable = shapeable;
                _charArray = charArray; 
 
                // create double array for glyph run creation, because Shaping is all done in
                // ideal units. FormattedTextSymbol is used to draw text collapsing symbols 
                // which usually contains very few glyphs. Using double[] and Point[] directly
                // is more efficient.
                _glyphAdvances = new double[glyphAdvances.Length];
 
                double ToReal = 1.0 / scalingFactor;
 
                for (int i = 0; i < glyphAdvances.Length; i++) 
                {
                    _glyphAdvances[i] = glyphAdvances[i] * ToReal; 
                    _width += _glyphAdvances[i];

                }
 
                if (glyphIndices != null)
                { 
                    _clusterMap = clusterMap; 

                    if (glyphOffsets != null) 
                    {
                        _glyphOffsets  = new PartialArray(new Point[glyphOffsets.Length]);

                        for (int i = 0; i < glyphOffsets.Length; i++) 
                        {
                            _glyphOffsets[i] = new Point( 
                                glyphOffsets[i].du * ToReal, 
                                glyphOffsets[i].dv * ToReal
                                ); 
                        }
                    }

                    Debug.Assert(glyphAdvances.Length <= glyphIndices.Length); 

                    if (glyphAdvances.Length != glyphIndices.Length) 
                    { 
                        _glyphIndices = new ushort[glyphAdvances.Length];
                        _glyphProp = new GlyphShapingProperties[glyphAdvances.Length]; 

                        for (int i = 0; i < glyphAdvances.Length; i++)
                        {
                            _glyphIndices[i] = glyphIndices[i]; 
                            _glyphProp[i] = glyphProp[i];
                        } 
                    } 
                    else
                    { 
                        _glyphIndices = glyphIndices;
                        _glyphProp = glyphProp;
                    }
                } 
            }
 
 
            /// 
            /// Total formatted width 
            /// 
            public double Width
            {
                get { return _width; } 
            }
 
 
            /// 
            /// Construct a GlyphRun object given the specified drawing origin 
            /// 
            internal GlyphRun CreateGlyphRun(
                Point       currentOrigin,
                bool        rightToLeft 
                )
            { 
                if (!_shapeable.IsShapingRequired) 
                {
                    return _shapeable.ComputeUnshapedGlyphRun( 
                        currentOrigin,
                        _charArray,
                        _glyphAdvances
                        ); 
                }
 
                return _shapeable.ComputeShapedGlyphRun( 
                    currentOrigin,
                    _charArray, 
                    _clusterMap,
                    _glyphIndices,
                    _glyphProp,
                    _glyphAdvances, 
                    _glyphOffsets,
                    rightToLeft, 
                    false   // sideways not yet supported 
                    );
            } 

            public Brush ForegroundBrush
            {
                get { return _shapeable.Properties.ForegroundBrush; } 
            }
 
            public Brush BackgroundBrush 
            {
                get { return _shapeable.Properties.BackgroundBrush; } 
            }
        }
    }
} 

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