linebase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / MS / Internal / PtsHost / linebase.cs / 1 / linebase.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: LineBase.cs 
//
// Description: Text line formatter. 
// 
// History:
//  02/07/2005 : ghermann - Split from Line.cs 
//
//---------------------------------------------------------------------------
using System;
using System.Diagnostics; 
using System.Collections;
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls;
using System.Windows.Documents; 
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
using MS.Internal.Text;
using MS.Internal.Documents; 

using MS.Internal.PtsHost.UnsafeNativeMethods; 
 
#pragma warning disable 1634, 1691  // avoid generating warnings about unknown
                                    // message numbers and unknown pragmas for PRESharp contol 

namespace MS.Internal.PtsHost
{
    internal abstract class LineBase : UnmanagedHandle 
    {
 
        internal LineBase(BaseParaClient paraClient) : base(paraClient.PtsContext) 
        {
            _paraClient = paraClient; 
        }

        // -----------------------------------------------------------------
        // 
        //  TextSource Implementation
        // 
        // ----------------------------------------------------------------- 

        #region TextSource Implementation 

        /// 
        /// Get a text run at specified text source position.
        ///  
        /// 
        /// dcp of specified position relative to start of line 
        ///  
        internal abstract TextRun GetTextRun(int dcp);
 
        /// 
        /// Get text immediately before specified text source position.
        /// 
        ///  
        /// dcp of specified position relative to start of line
        ///  
        internal abstract TextSpan GetPrecedingText(int dcp); 

        ///  
        /// Get Text effect index from text source character index
        /// 
        /// 
        /// dcp of specified position relative to start of line 
        /// 
        internal abstract int GetTextEffectCharacterIndexFromTextSourceCharacterIndex(int dcp); 
 
        #endregion TextSource Implementation
 

        //--------------------------------------------------------------------
        //
        //  Protected Methods 
        //
        //------------------------------------------------------------------- 
 
        #region Protected Methods
 
        /// 
        /// Fetch the next run at text position.
        /// 
        ///  
        /// Current position in text array
        ///  
        ///  
        protected TextRun HandleText(StaticTextPointer position)
        { 
            DependencyObject element;
            StaticTextPointer endOfRunPosition;

            Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text, "TextPointer does not point to characters."); 

            if (position.Parent != null) 
            { 
                element = position.Parent;
            } 
            else
            {
                element = _paraClient.Paragraph.Element;
            } 

            // Extract the aggregated properties into something that the textrun can use. 
            // 

 
            TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */);

            // Calculate the end of the run by finding either:
            //      a) the next intersection of highlight ranges, or 
            //      b) the natural end of this textrun
            endOfRunPosition = position.TextContainer.Highlights.GetNextPropertyChangePosition(position, LogicalDirection.Forward); 
 
            // Clamp the text run at an arbitrary limit, so we don't make
            // an unbounded allocation. 
            if (position.GetOffsetToPosition(endOfRunPosition) > 4096)
            {
                endOfRunPosition = position.CreatePointer(4096);
            } 

            // Get character buffer for the text run. 
            char[] textBuffer = new char[position.GetOffsetToPosition(endOfRunPosition)]; 

            // Copy characters from text run into buffer. Note the actual number of characters copied, 
            // which may be different than the buffer's length. Buffer length only specifies the maximum
            // number of characters
            int charactersCopied = position.GetTextInRun(LogicalDirection.Forward, textBuffer, 0, textBuffer.Length);
 
            // Create text run using the actual number of characters copied
            return new TextCharacters(textBuffer, 0, charactersCopied, textProps); 
        } 

        ///  
        /// Return next TextRun at element edge start position
        /// 
        /// 
        /// Current position in text array 
        /// 
        protected TextRun HandleElementStartEdge(StaticTextPointer position) 
        { 
            Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart, "TextPointer does not point to element start edge.");
 
            //

            TextRun run = null;
            TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); 
            Debug.Assert(element != null, "Cannot use ITextContainer that does not provide TextElement instances.");
 
            Invariant.Assert(!(element is Block), "We do not expect any Blocks inside Paragraphs"); 

            // Treat figure and floaters as special hidden runs. 
            if (element is Figure || element is Floater)
            {
                // Get the length of the element
                int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); 
                // Create special hidden run.
                run = new FloatingRun(cch, element is Figure); 
                if (element is Figure) 
                {
                    _hasFigures = true; 
                }
                else
                {
                    _hasFloaters = true; 
                }
            } 
            else if (element is LineBreak) 
            {
                int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); 
                run = new LineBreakRun(cch, PTS.FSFLRES.fsflrSoftBreak);
            }
            else if (element.IsEmpty)
            { 
                // Empty TextElement should affect line metrics.
                // TextFormatter does not support this feature right now, so as workaround 
                // TextRun with ZERO WIDTH NO-BREAK SPACE is used. 
                TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */);
 
                char[] textBuffer = new char[_elementEdgeCharacterLength * 2];

                // Assert that _elementEdgeCharacterLength is 1 before we use hard-coded indices
                Invariant.Assert(_elementEdgeCharacterLength == 1, "Expected value of _elementEdgeCharacterLength is 1"); 

                textBuffer[0] = (char)0xFEFF; 
                textBuffer[1] = (char)0xFEFF; 

                run = new TextCharacters(textBuffer, 0, textBuffer.Length, textProps); 
            }
            else
            {
                Inline inline = (Inline) element; 
                DependencyObject parent = inline.Parent;
 
                FlowDirection inlineFlowDirection = inline.FlowDirection; 
                FlowDirection parentFlowDirection = inlineFlowDirection;
 
                TextDecorationCollection inlineTextDecorations = DynamicPropertyReader.GetTextDecorations(inline);

                if(parent != null)
                { 
                    parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty);
                } 
 
                if (inlineFlowDirection != parentFlowDirection)
                { 
                    // Inline's flow direction is different from its parent. Need to create new TextSpanModifier with flow direction
                    if (inlineTextDecorations == null || inlineTextDecorations.Count == 0)
                    {
                        run = new TextSpanModifier( 
                            _elementEdgeCharacterLength,
                            null, 
                            null, 
                            inlineFlowDirection
                            ); 
                    }
                    else
                    {
                        run = new TextSpanModifier( 
                            _elementEdgeCharacterLength,
                            inlineTextDecorations, 
                            inline.Foreground, 
                            inlineFlowDirection
                            ); 
                    }
                }
                else
                { 
                    if (inlineTextDecorations == null || inlineTextDecorations.Count == 0)
                    { 
                        run = new TextHidden(_elementEdgeCharacterLength); 
                    }
                    else 
                    {
                        run = new TextSpanModifier(
                            _elementEdgeCharacterLength,
                            inlineTextDecorations, 
                            inline.Foreground
                            ); 
                    } 
                }
            } 
            return run;
        }

        ///  
        /// Fetch the next run at element end edge position.
        /// ElementEndEdge; we can have 2 possibilities: 
        /// (1) Close edge of element associated with the text paragraph, 
        ///     create synthetic LineBreak run to end the current line.
        /// (2) End of inline element, hide CloseEdge character and continue 
        /// 
        /// 
        /// Position in current text array
        protected TextRun HandleElementEndEdge(StaticTextPointer position) 
        {
            Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd, "TextPointer does not point to element end edge."); 
 
            TextRun run;
            if (position.Parent == _paraClient.Paragraph.Element) 
            {
                // (1) Close edge of element associated with the text paragraph,
                //     create synthetic LineBreak run to end the current line.
                run = new ParagraphBreakRun(_syntheticCharacterLength, PTS.FSFLRES.fsflrEndOfParagraph); 
            }
            else 
            { 
                TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward);
                Debug.Assert(element != null, "Element should be here."); 
                Inline inline = (Inline) element;
                DependencyObject parent = inline.Parent;
                FlowDirection parentFlowDirection = inline.FlowDirection;
 
                if(parent != null)
                { 
                    parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); 
                }
 
                if (inline.FlowDirection != parentFlowDirection)
                {
                    run = new TextEndOfSegment(_elementEdgeCharacterLength);
                } 
                else
                { 
                    TextDecorationCollection textDecorations = DynamicPropertyReader.GetTextDecorations(inline); 
                    if (textDecorations == null || textDecorations.Count == 0)
                    { 
                        // (2) End of inline element, hide CloseEdge character and continue
                        run = new TextHidden(_elementEdgeCharacterLength);
                    }
                    else 
                    {
                        run = new TextEndOfSegment(_elementEdgeCharacterLength); 
                    } 
                }
            } 
            return run;
        }

        ///  
        /// Fetch the next run at embedded object position.
        ///  
        ///  
        /// Character offset of this run.
        ///  
        /// 
        /// Current position in the text array.
        /// 
        protected TextRun HandleEmbeddedObject(int dcp, StaticTextPointer position) 
        {
            Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement, "TextPointer does not point to embedded object."); 
 
            TextRun run = null;
            DependencyObject embeddedObject = position.GetAdjacentElement(LogicalDirection.Forward) as DependencyObject; 
            if (embeddedObject is UIElement)
            {
                // Extract the aggregated properties into something that the textrun can use.
                TextRunProperties textProps = new TextProperties(embeddedObject, position, true /* inline objects */, true /* get background */); 

                // Create inline object run. 
                run = new InlineObjectRun(TextContainerHelper.EmbeddedObjectLength, (UIElement)embeddedObject, textProps, _paraClient.Paragraph as TextParagraph); 
            }
            else 
            {
                // If the embedded object is of an unknown type, treat it as hidden content.
                run = new TextHidden(TextContainerHelper.EmbeddedObjectLength);
            } 
            return run;
        } 
 
        #endregion Protected Methods
 

        #region Internal Methods

        ///  
        /// Synthetic character length.
        ///  
        internal static int SyntheticCharacterLength 
        {
            get 
            {
                return _syntheticCharacterLength;
            }
        } 

        ///  
        /// Returns true if any figure runs have been handled by this text source - Only valid after line is formatted. 
        /// 
        internal bool HasFigures 
        {
            get { return _hasFigures; }
        }
 
        /// 
        /// Returns true if any floater runs have been handled by this text source - Only valid after line is formatted. 
        ///  
        internal bool HasFloaters
        { 
            get { return _hasFloaters; }
        }

        #endregion Internal Methods 

 
        #region Protected Fields 

        ///  
        /// Owner of the line
        /// 
        protected readonly BaseParaClient _paraClient;
 
        /// 
        /// Has any figures? 
        ///  
        protected bool _hasFigures;
 
        /// 
        /// Has any floaters?
        /// 
        protected bool _hasFloaters; 

 
        protected static int _syntheticCharacterLength = 1; 

        ///  
        /// Element edge character length.
        ///

 

        protected static int _elementEdgeCharacterLength = 1; 
 

        #endregion Protected Fields 
    }
}

#pragma warning enable 1634, 1691 


// 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.
//
// File: LineBase.cs 
//
// Description: Text line formatter. 
// 
// History:
//  02/07/2005 : ghermann - Split from Line.cs 
//
//---------------------------------------------------------------------------
using System;
using System.Diagnostics; 
using System.Collections;
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls;
using System.Windows.Documents; 
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
using MS.Internal.Text;
using MS.Internal.Documents; 

using MS.Internal.PtsHost.UnsafeNativeMethods; 
 
#pragma warning disable 1634, 1691  // avoid generating warnings about unknown
                                    // message numbers and unknown pragmas for PRESharp contol 

namespace MS.Internal.PtsHost
{
    internal abstract class LineBase : UnmanagedHandle 
    {
 
        internal LineBase(BaseParaClient paraClient) : base(paraClient.PtsContext) 
        {
            _paraClient = paraClient; 
        }

        // -----------------------------------------------------------------
        // 
        //  TextSource Implementation
        // 
        // ----------------------------------------------------------------- 

        #region TextSource Implementation 

        /// 
        /// Get a text run at specified text source position.
        ///  
        /// 
        /// dcp of specified position relative to start of line 
        ///  
        internal abstract TextRun GetTextRun(int dcp);
 
        /// 
        /// Get text immediately before specified text source position.
        /// 
        ///  
        /// dcp of specified position relative to start of line
        ///  
        internal abstract TextSpan GetPrecedingText(int dcp); 

        ///  
        /// Get Text effect index from text source character index
        /// 
        /// 
        /// dcp of specified position relative to start of line 
        /// 
        internal abstract int GetTextEffectCharacterIndexFromTextSourceCharacterIndex(int dcp); 
 
        #endregion TextSource Implementation
 

        //--------------------------------------------------------------------
        //
        //  Protected Methods 
        //
        //------------------------------------------------------------------- 
 
        #region Protected Methods
 
        /// 
        /// Fetch the next run at text position.
        /// 
        ///  
        /// Current position in text array
        ///  
        ///  
        protected TextRun HandleText(StaticTextPointer position)
        { 
            DependencyObject element;
            StaticTextPointer endOfRunPosition;

            Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text, "TextPointer does not point to characters."); 

            if (position.Parent != null) 
            { 
                element = position.Parent;
            } 
            else
            {
                element = _paraClient.Paragraph.Element;
            } 

            // Extract the aggregated properties into something that the textrun can use. 
            // 

 
            TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */);

            // Calculate the end of the run by finding either:
            //      a) the next intersection of highlight ranges, or 
            //      b) the natural end of this textrun
            endOfRunPosition = position.TextContainer.Highlights.GetNextPropertyChangePosition(position, LogicalDirection.Forward); 
 
            // Clamp the text run at an arbitrary limit, so we don't make
            // an unbounded allocation. 
            if (position.GetOffsetToPosition(endOfRunPosition) > 4096)
            {
                endOfRunPosition = position.CreatePointer(4096);
            } 

            // Get character buffer for the text run. 
            char[] textBuffer = new char[position.GetOffsetToPosition(endOfRunPosition)]; 

            // Copy characters from text run into buffer. Note the actual number of characters copied, 
            // which may be different than the buffer's length. Buffer length only specifies the maximum
            // number of characters
            int charactersCopied = position.GetTextInRun(LogicalDirection.Forward, textBuffer, 0, textBuffer.Length);
 
            // Create text run using the actual number of characters copied
            return new TextCharacters(textBuffer, 0, charactersCopied, textProps); 
        } 

        ///  
        /// Return next TextRun at element edge start position
        /// 
        /// 
        /// Current position in text array 
        /// 
        protected TextRun HandleElementStartEdge(StaticTextPointer position) 
        { 
            Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart, "TextPointer does not point to element start edge.");
 
            //

            TextRun run = null;
            TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); 
            Debug.Assert(element != null, "Cannot use ITextContainer that does not provide TextElement instances.");
 
            Invariant.Assert(!(element is Block), "We do not expect any Blocks inside Paragraphs"); 

            // Treat figure and floaters as special hidden runs. 
            if (element is Figure || element is Floater)
            {
                // Get the length of the element
                int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); 
                // Create special hidden run.
                run = new FloatingRun(cch, element is Figure); 
                if (element is Figure) 
                {
                    _hasFigures = true; 
                }
                else
                {
                    _hasFloaters = true; 
                }
            } 
            else if (element is LineBreak) 
            {
                int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); 
                run = new LineBreakRun(cch, PTS.FSFLRES.fsflrSoftBreak);
            }
            else if (element.IsEmpty)
            { 
                // Empty TextElement should affect line metrics.
                // TextFormatter does not support this feature right now, so as workaround 
                // TextRun with ZERO WIDTH NO-BREAK SPACE is used. 
                TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */);
 
                char[] textBuffer = new char[_elementEdgeCharacterLength * 2];

                // Assert that _elementEdgeCharacterLength is 1 before we use hard-coded indices
                Invariant.Assert(_elementEdgeCharacterLength == 1, "Expected value of _elementEdgeCharacterLength is 1"); 

                textBuffer[0] = (char)0xFEFF; 
                textBuffer[1] = (char)0xFEFF; 

                run = new TextCharacters(textBuffer, 0, textBuffer.Length, textProps); 
            }
            else
            {
                Inline inline = (Inline) element; 
                DependencyObject parent = inline.Parent;
 
                FlowDirection inlineFlowDirection = inline.FlowDirection; 
                FlowDirection parentFlowDirection = inlineFlowDirection;
 
                TextDecorationCollection inlineTextDecorations = DynamicPropertyReader.GetTextDecorations(inline);

                if(parent != null)
                { 
                    parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty);
                } 
 
                if (inlineFlowDirection != parentFlowDirection)
                { 
                    // Inline's flow direction is different from its parent. Need to create new TextSpanModifier with flow direction
                    if (inlineTextDecorations == null || inlineTextDecorations.Count == 0)
                    {
                        run = new TextSpanModifier( 
                            _elementEdgeCharacterLength,
                            null, 
                            null, 
                            inlineFlowDirection
                            ); 
                    }
                    else
                    {
                        run = new TextSpanModifier( 
                            _elementEdgeCharacterLength,
                            inlineTextDecorations, 
                            inline.Foreground, 
                            inlineFlowDirection
                            ); 
                    }
                }
                else
                { 
                    if (inlineTextDecorations == null || inlineTextDecorations.Count == 0)
                    { 
                        run = new TextHidden(_elementEdgeCharacterLength); 
                    }
                    else 
                    {
                        run = new TextSpanModifier(
                            _elementEdgeCharacterLength,
                            inlineTextDecorations, 
                            inline.Foreground
                            ); 
                    } 
                }
            } 
            return run;
        }

        ///  
        /// Fetch the next run at element end edge position.
        /// ElementEndEdge; we can have 2 possibilities: 
        /// (1) Close edge of element associated with the text paragraph, 
        ///     create synthetic LineBreak run to end the current line.
        /// (2) End of inline element, hide CloseEdge character and continue 
        /// 
        /// 
        /// Position in current text array
        protected TextRun HandleElementEndEdge(StaticTextPointer position) 
        {
            Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd, "TextPointer does not point to element end edge."); 
 
            TextRun run;
            if (position.Parent == _paraClient.Paragraph.Element) 
            {
                // (1) Close edge of element associated with the text paragraph,
                //     create synthetic LineBreak run to end the current line.
                run = new ParagraphBreakRun(_syntheticCharacterLength, PTS.FSFLRES.fsflrEndOfParagraph); 
            }
            else 
            { 
                TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward);
                Debug.Assert(element != null, "Element should be here."); 
                Inline inline = (Inline) element;
                DependencyObject parent = inline.Parent;
                FlowDirection parentFlowDirection = inline.FlowDirection;
 
                if(parent != null)
                { 
                    parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); 
                }
 
                if (inline.FlowDirection != parentFlowDirection)
                {
                    run = new TextEndOfSegment(_elementEdgeCharacterLength);
                } 
                else
                { 
                    TextDecorationCollection textDecorations = DynamicPropertyReader.GetTextDecorations(inline); 
                    if (textDecorations == null || textDecorations.Count == 0)
                    { 
                        // (2) End of inline element, hide CloseEdge character and continue
                        run = new TextHidden(_elementEdgeCharacterLength);
                    }
                    else 
                    {
                        run = new TextEndOfSegment(_elementEdgeCharacterLength); 
                    } 
                }
            } 
            return run;
        }

        ///  
        /// Fetch the next run at embedded object position.
        ///  
        ///  
        /// Character offset of this run.
        ///  
        /// 
        /// Current position in the text array.
        /// 
        protected TextRun HandleEmbeddedObject(int dcp, StaticTextPointer position) 
        {
            Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement, "TextPointer does not point to embedded object."); 
 
            TextRun run = null;
            DependencyObject embeddedObject = position.GetAdjacentElement(LogicalDirection.Forward) as DependencyObject; 
            if (embeddedObject is UIElement)
            {
                // Extract the aggregated properties into something that the textrun can use.
                TextRunProperties textProps = new TextProperties(embeddedObject, position, true /* inline objects */, true /* get background */); 

                // Create inline object run. 
                run = new InlineObjectRun(TextContainerHelper.EmbeddedObjectLength, (UIElement)embeddedObject, textProps, _paraClient.Paragraph as TextParagraph); 
            }
            else 
            {
                // If the embedded object is of an unknown type, treat it as hidden content.
                run = new TextHidden(TextContainerHelper.EmbeddedObjectLength);
            } 
            return run;
        } 
 
        #endregion Protected Methods
 

        #region Internal Methods

        ///  
        /// Synthetic character length.
        ///  
        internal static int SyntheticCharacterLength 
        {
            get 
            {
                return _syntheticCharacterLength;
            }
        } 

        ///  
        /// Returns true if any figure runs have been handled by this text source - Only valid after line is formatted. 
        /// 
        internal bool HasFigures 
        {
            get { return _hasFigures; }
        }
 
        /// 
        /// Returns true if any floater runs have been handled by this text source - Only valid after line is formatted. 
        ///  
        internal bool HasFloaters
        { 
            get { return _hasFloaters; }
        }

        #endregion Internal Methods 

 
        #region Protected Fields 

        ///  
        /// Owner of the line
        /// 
        protected readonly BaseParaClient _paraClient;
 
        /// 
        /// Has any figures? 
        ///  
        protected bool _hasFigures;
 
        /// 
        /// Has any floaters?
        /// 
        protected bool _hasFloaters; 

 
        protected static int _syntheticCharacterLength = 1; 

        ///  
        /// Element edge character length.
        ///

 

        protected static int _elementEdgeCharacterLength = 1; 
 

        #endregion Protected Fields 
    }
}

#pragma warning enable 1634, 1691 


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