FullTextBreakpoint.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / MS / Internal / TextFormatting / FullTextBreakpoint.cs / 1305600 / FullTextBreakpoint.cs

                            //------------------------------------------------------------------------ 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation
// 
//  File:      FullTextBreakpoint.cs
// 
//  Contents:  Full text implementation of the specialized text line representing 
//             state of line up to the point where line break may occur
// 
//  Spec:      http://team/sites/Avalon/Specs/Text%20Formatting%20API.doc
//
//  Created:   1-1-2005 Worachai Chaoweeraprasit (wchao)
// 
//-----------------------------------------------------------------------
 
 
using System;
using System.Security; 
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Media.TextFormatting; 
 
using MS.Internal.PresentationCore;
using SR = MS.Internal.PresentationCore.SR; 
using SRID = MS.Internal.PresentationCore.SRID;


namespace MS.Internal.TextFormatting 
{
    ///  
    /// Full text implementation of the specialized text line representing state 
    /// of line up to the point where line break may occur. Unlike a more tangible
    /// type like text line , breakpoint could not draw or performs hit-testing 
    /// operation. It could only reflect formatting result back to the client.
    /// 
    internal sealed class FullTextBreakpoint : TextBreakpoint
    { 
        private TextMetrics                         _metrics;           // full text metrics
        private SecurityCriticalDataForSet  _ploline;           // native object representing this break 
        private SecurityCriticalDataForSet  _penaltyResource;   // unsafe handle to the internal factors used to determines penalty of the break. By default, the lifetime of this resource is managed by _ploline. 
        private bool                                _isDisposed;        // flag indicates whether this object is disposed
        private bool                                _isLineTruncated;   // flag indicates whether the line produced at this breakpoint is truncated. 


        /// 
        /// Construct a list of potential breakpoints starting from the specified firstCharIndex 
        /// 
        /// cache of paragraph content of all possible breaks within 
        /// index to first character where formatting starts 
        /// max format ideal width of the line being built
        /// LineBreak property of the previous text line, or null if this is the first line in the paragraph 
        /// constraint on what breakpoint is returned based on its implied calculated penalty
        /// index of the best fit breakpoint in the returned collection
        /// a list of potential breakpoints starting from firstCharIndex
        ///  
        /// Critical - as this reads critical property callback exception.
        /// Safe - as it reads the exception for the purpose of error reporting. 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal static IList CreateMultiple( 
            TextParagraphCache          paragraphCache,
            int                         firstCharIndex,
            int                         maxLineWidth,
            TextLineBreak               previousLineBreak, 
            IntPtr                      penaltyRestriction,
            out int                     bestFitIndex 
            ) 
        {
            Invariant.Assert(paragraphCache != null); 

            // grab full text state from paragraph cache
            FullTextState fullText = paragraphCache.FullText;
            Invariant.Assert(fullText != null); 

            FormatSettings settings = fullText.TextStore.Settings; 
            Invariant.Assert(settings != null); 

            // update formatting parameters at line start 
            settings.UpdateSettingsForCurrentLine(
                maxLineWidth,
                previousLineBreak,
                (firstCharIndex == fullText.TextStore.CpFirst) 
                );
 
            Invariant.Assert(settings.Formatter != null); 

            // acquiring LS context 
            TextFormatterContext context = settings.Formatter.AcquireContext(fullText, IntPtr.Zero);

            IntPtr previousBreakRecord = IntPtr.Zero;
            if (settings.PreviousLineBreak != null) 
                previousBreakRecord = settings.PreviousLineBreak.BreakRecord.Value;
 
            // need not consider marker as tab since marker does not affect line metrics and it wasnt drawn. 
            fullText.SetTabs(context);
 
            LsBreaks lsbreaks = new LsBreaks();

            LsErr lserr = context.CreateBreaks(
                fullText.GetBreakpointInternalCp(firstCharIndex), 
                previousBreakRecord,
                paragraphCache.Ploparabreak.Value,  // para breaking session 
                penaltyRestriction, 
                ref lsbreaks,
                out bestFitIndex 
                );

            // get the exception in context before it is released
            Exception callbackException = context.CallbackException; 

            // release the context 
            context.Release(); 

            if(lserr != LsErr.None) 
            {
                if(callbackException != null)
                {
                    // rethrow exception thrown in callbacks 
                    throw callbackException;
                } 
                else 
                {
                    // throw with LS error codes 
                    TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.CreateBreaksFailure, lserr), lserr);
                }
            }
 
            // keep context alive at least till here
            GC.KeepAlive(context); 
 
            TextBreakpoint[] breakpoints = new TextBreakpoint[lsbreaks.cBreaks];
 
            for (int i = 0; i < lsbreaks.cBreaks; i++)
            {
                breakpoints[i] = new FullTextBreakpoint(
                    fullText, 
                    firstCharIndex,
                    maxLineWidth, 
                    ref lsbreaks, 
                    i   // the current break
                    ); 
            }

            return breakpoints;
        } 

 
        ///  
        /// Construct breakpoint from full text info
        ///  
        /// 
        /// Critical - as this calls critical method TextMetrics.Compute and it accesses unsafe pointer
        /// Safe - as it does not expose critical data
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private FullTextBreakpoint( 
            FullTextState           fullText, 
            int                     firstCharIndex,
            int                     maxLineWidth, 
            ref LsBreaks            lsbreaks,
            int                     breakIndex
            ) : this()
        { 
            // According to antons: PTS only uses the width of a feasible break to avoid
            // clipping in subpage. At the moment, there is no good solution as of how 
            // PTS client would be able to compute this width efficiently using LS. 
            // The work around - although could be conceived would simply be too slow.
            // The width should therefore be set to the paragraph width for the time being. 
            //
            // Client of text formatter would simply pass the value of TextBreakpoint.Width
            // back to PTS pfnFormatLineVariants call.
            LsLineWidths lineWidths = new LsLineWidths(); 
            lineWidths.upLimLine = maxLineWidth;
            lineWidths.upStartMainText = fullText.TextStore.Settings.TextIndent; 
            lineWidths.upStartMarker = lineWidths.upStartMainText; 
            lineWidths.upStartTrailing = lineWidths.upLimLine;
            lineWidths.upMinStartTrailing = lineWidths.upStartTrailing; 

            // construct the correspondent text metrics
            unsafe
            { 
                _metrics.Compute(
                    fullText, 
                    firstCharIndex, 
                    maxLineWidth,
                    null,   // collapsingSymbol 
                    ref lineWidths,
                    &lsbreaks.plslinfoArray[breakIndex]
                    );
 
                _ploline = new SecurityCriticalDataForSet(lsbreaks.pplolineArray[breakIndex]);
 
                // keep the line penalty handle 
                _penaltyResource = new SecurityCriticalDataForSet(lsbreaks.plinepenaltyArray[breakIndex]);
 
                if (lsbreaks.plslinfoArray[breakIndex].fForcedBreak != 0)
                    _isLineTruncated = true;
            }
        } 

 
        ///  
        /// Empty private constructor
        ///  
        private FullTextBreakpoint()
        {
            _metrics = new TextMetrics();
        } 

 
        ///  
        /// Finalizing the break
        ///  
        ~FullTextBreakpoint()
        {
            Dispose(false);
        } 

 
        ///  
        /// Disposing LS unmanaged memory for text line
        ///  
        /// 
        /// Critical - as this sets critical data _ploline.
        /// Safe - as it does not set the critical data thru input parameters.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        protected override void Dispose(bool disposing) 
        { 
            if(_ploline.Value != IntPtr.Zero)
            { 
                UnsafeNativeMethods.LoDisposeLine(_ploline.Value, !disposing);
                _ploline.Value = IntPtr.Zero;
                _penaltyResource.Value = IntPtr.Zero;
                _isDisposed = true; 
                GC.KeepAlive(this);
            } 
        } 

        #region TextBreakpoint 

        /// 
        /// Client to acquire a state at the point where breakpoint is determined by line breaking process;
        /// can be null when the line ends by the ending of the paragraph. Client may pass this 
        /// value back to TextFormatter as an input argument to TextFormatter.FormatParagraphBreakpoints when
        /// formatting the next set of breakpoints within the same paragraph. 
        ///  
        /// 
        /// Critical - as this calls TextMetrics.GetTextLineBreak. 
        /// Safe - as it does not take parameter that being passed to the critical method or
        ///        return sensitive data from the critical method.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        public override TextLineBreak GetTextLineBreak()
        { 
            if (_isDisposed) 
            {
                throw new ObjectDisposedException(SR.Get(SRID.TextBreakpointHasBeenDisposed)); 
            }
            return _metrics.GetTextLineBreak(_ploline.Value);
        }
 

        ///  
        /// Client to get the handle of the internal factors that are used to determine penalty of this breakpoint. 
        /// 
        ///  
        /// Calling this method means that the client will now manage the lifetime of this unmanaged resource themselves using unsafe penalty handler.
        /// We would make a correspondent call to notify our unmanaged wrapper to release them from duty of managing this
        /// resource.
        ///  
        /// 
        ///  Critical - as this method returns unmanaged resource to the client. 
        ///  
        [SecurityCritical]
        internal override SecurityCriticalDataForSet GetTextPenaltyResource() 
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(SR.Get(SRID.TextBreakpointHasBeenDisposed)); 
            }
 
            LsErr lserr = UnsafeNativeMethods.LoRelievePenaltyResource(_ploline.Value); 
            if (lserr != LsErr.None)
            { 
                TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.RelievePenaltyResourceFailure, lserr), lserr);
            }

            return _penaltyResource; 
        }
 
 
        /// 
        /// Client to get a Boolean flag indicating whether the line is truncated in the 
        /// middle of a word. This flag is set only when TextParagraphProperties.TextWrapping
        /// is set to TextWrapping.Wrap and a single word is longer than the formatting
        /// paragraph width. In such situation, TextFormatter truncates the line in the middle
        /// of the word to honor the desired behavior specified by TextWrapping.Wrap setting. 
        /// 
        public override bool IsTruncated 
        { 
            get { return _isLineTruncated; }
        } 


        #endregion
 
        #region TextMetrics
 
        ///  
        /// Client to get the number of text source positions of this line
        ///  
        public override int Length
        {
            get { return _metrics.Length; }
        } 

 
        ///  
        /// Client to get the number of characters following the last character
        /// of the line that may trigger reformatting of the current line. 
        /// 
        public override int DependentLength
        {
            get { return _metrics.DependentLength; } 
        }
 
 
        /// 
        /// Client to get the number of newline characters at line end 
        /// 
        public override int NewlineLength
        {
            get { return _metrics.NewlineLength; } 
        }
 
 
        /// 
        /// Client to get distance from paragraph start to line start 
        /// 
        public override double Start
        {
            get { return _metrics.Start; } 
        }
 
 
        /// 
        /// Client to get the total width of this line 
        /// 
        public override double Width
        {
            get { return _metrics.Width; } 
        }
 
 
        /// 
        /// Client to get the total width of this line including width of whitespace characters at the end of the line. 
        /// 
        public override double WidthIncludingTrailingWhitespace
        {
            get { return _metrics.WidthIncludingTrailingWhitespace; } 
        }
 
 
        /// 
        /// Client to get the height of the line 
        /// 
        public override double Height
        {
            get { return _metrics.Height; } 
        }
 
 
        /// 
        /// Client to get the height of the text (or other content) in the line; this property may differ from the Height 
        /// property if the client specified the line height
        /// 
        public override double TextHeight
        { 
            get { return _metrics.TextHeight; }
        } 
 

        ///  
        /// Client to get the distance from top to baseline of this text line
        /// 
        public override double Baseline
        { 
            get { return _metrics.Baseline; }
        } 
 

        ///  
        /// Client to get the distance from the top of the text (or other content) to the baseline of this text line;
        /// this property may differ from the Baseline property if the client specified the line height
        /// 
        public override double TextBaseline 
        {
            get { return _metrics.TextBaseline; } 
        } 

 
        /// 
        /// Client to get the distance from the before edge of line height
        /// to the baseline of marker of the line if any.
        ///  
        public override double MarkerBaseline
        { 
            get { return _metrics.MarkerBaseline; } 
        }
 

        /// 
        /// Client to get the overall height of the list items marker of the line if any.
        ///  
        public override double MarkerHeight
        { 
            get { return _metrics.MarkerHeight; } 
        }
 
        #endregion
    }
}

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