TextFormatterContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Media / textformatting / TextFormatterContext.cs / 1 / TextFormatterContext.cs

                            //+------------------------------------------------------------------------ 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation
// 
//  File:      TextFormatterContext.cs
// 
//  Contents:  Implementation of TextFormatter context 
//
//  Created:   9-1-2001 [....] ([....]) 
//
//-----------------------------------------------------------------------

 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Windows.Threading; 
using System.Security;
using System.Security.Permissions;
using System.Reflection;
using System.Runtime.InteropServices; 
using System.Windows;
using System.Windows.Media; 
 
using MS.Internal;
using MS.Internal.PresentationCore; 
using MS.Internal.TextFormatting;

using IndexedGlyphRun = System.Windows.Media.TextFormatting.IndexedGlyphRun;
using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;
 
 
namespace System.Windows.Media.TextFormatting
{ 
    /// 
    /// TextFormatter context. This class encapsulates the unit of reentrancy of TextFormatter.
    /// 
    ///  
    /// We do not want to make this class finalizable because its lifetime already ties
    /// to TextFormatterImp which is finalizable. It is not efficient to have too many 
    /// finalizable object around in the GC heap. 
    /// 
#if OPTIMALBREAK_API 
    public class TextFormatterContext
#else
    [FriendAccessAllowed]   // used by Framework
    internal class TextFormatterContext 
#endif
    { 
        private SecurityCriticalDataForSet  _ploc;              // Line Services context 
        private LineServicesCallbacks               _callbacks;         // object to hold all delegates for callback
        private State                               _state;             // internal state flags 
        private BreakStrategies                     _breaking;          // context's breaking strategy


        ///  
        /// Critical - as this calls the constructor for  SecurityCriticalDataForSet.
        /// Safe - as this just initializes it with the default value. 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        public TextFormatterContext() 
        {
            _ploc =  new SecurityCriticalDataForSet(IntPtr.Zero);
            Init();
        } 

 
        ///  
        /// Critical - as this calls Critical functions - LoCreateContext, setter for _ploc.Value,
        /// Safe - as this doesn't take any random parameters that can be passed along 
        ///        and cause random memory to be written to.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void Init() 
        {
            if(_ploc.Value == System.IntPtr.Zero) 
            { 
                // Initializing context
                LsErr lserr = LsErr.None; 

                LsContextInfo contextInfo = new LsContextInfo();
                LscbkRedefined lscbkRedef = new LscbkRedefined();
 
                _callbacks = new LineServicesCallbacks();
                _callbacks.PopulateContextInfo(ref contextInfo, ref lscbkRedef); 
 

                contextInfo.version = 4;            // we should set this right, they might check it in the future 
                contextInfo.pols  = IntPtr.Zero;    // This will be filled in the un-managed code
                contextInfo.cEstimatedCharsPerLine  = TextStore.TypicalCharactersPerLine;
                contextInfo.fDontReleaseRuns        = 1; // dont waste time
 
                // There are 3 justification priorities right now with one considered good
                // and the other two provided for emergency expansion. 
                // Future development to enable international justification will likely change this. 
                // e.g. Kashida justification would require more than one good priorities.
                contextInfo.cJustPriorityLim        = 3; 

                // Fill up text configuration
                contextInfo.wchNull                 = '\u0000';
                contextInfo.wchUndef                = '\u0001'; 
                contextInfo.wchTab                  = '\u0009';
                contextInfo.wchPosTab               = contextInfo.wchUndef; 
                contextInfo.wchEndPara1             = TextStore.CharParaSeparator;  // Unicode para separator 
                contextInfo.wchEndPara2             = contextInfo.wchUndef;
                contextInfo.wchSpace                = '\u0020'; 

                contextInfo.wchHyphen               = TextStore.CharHyphen;
                contextInfo.wchNonReqHyphen         = '\u00AD';
                contextInfo.wchNonBreakHyphen       = '\u2011'; 
                contextInfo.wchEnDash               = '\u2013';
                contextInfo.wchEmDash               = '\u2014'; 
                contextInfo.wchEnSpace              = '\u2002'; 
                contextInfo.wchEmSpace              = '\u2003';
                contextInfo.wchNarrowSpace          = '\u2009'; 
                contextInfo.wchJoiner               = '\u200D';
                contextInfo.wchNonJoiner            = '\u200C';
                contextInfo.wchVisiNull             = '\u2050';
                contextInfo.wchVisiAltEndPara       = '\u2051'; 
                contextInfo.wchVisiEndLineInPara    = '\u2052';
                contextInfo.wchVisiEndPara          = '\u2053'; 
                contextInfo.wchVisiSpace            = '\u2054'; 
                contextInfo.wchVisiNonBreakSpace    = '\u2055';
                contextInfo.wchVisiNonBreakHyphen   = '\u2056'; 
                contextInfo.wchVisiNonReqHyphen     = '\u2057';
                contextInfo.wchVisiTab              = '\u2058';
                contextInfo.wchVisiPosTab           = contextInfo.wchUndef;
                contextInfo.wchVisiEmSpace          = '\u2059'; 
                contextInfo.wchVisiEnSpace          = '\u205A';
                contextInfo.wchVisiNarrowSpace      = '\u205B'; 
                contextInfo.wchVisiOptBreak         = '\u205C'; 
                contextInfo.wchVisiNoBreak          = '\u205D';
                contextInfo.wchVisiFESpace          = '\u205E'; 
                contextInfo.wchFESpace              = '\u3000';
                contextInfo.wchEscAnmRun            = TextStore.CharParaSeparator;
                contextInfo.wchAltEndPara           = contextInfo.wchUndef;
                contextInfo.wchEndLineInPara        = TextStore.CharLineSeparator; 
                contextInfo.wchSectionBreak         = contextInfo.wchUndef;
                contextInfo.wchNonBreakSpace        = '\u00A0'; 
                contextInfo.wchNoBreak              = contextInfo.wchUndef; 
                contextInfo.wchColumnBreak          = contextInfo.wchUndef;
                contextInfo.wchPageBreak            = contextInfo.wchUndef; 
                contextInfo.wchOptBreak             = contextInfo.wchUndef;
                contextInfo.wchToReplace            = contextInfo.wchUndef;
                contextInfo.wchReplace              = contextInfo.wchUndef;
 
                IntPtr ploc = IntPtr.Zero;
                IntPtr ppenaltyModule = IntPtr.Zero; 
 
                lserr = UnsafeNativeMethods.LoCreateContext(
                    ref contextInfo, 
                    ref lscbkRedef,
                    out ploc
                    );
 
                if (lserr != LsErr.None)
                { 
                    ThrowExceptionFromLsError(SR.Get(SRID.CreateContextFailure, lserr), lserr); 
                }
 
                _ploc.Value = ploc;
                GC.KeepAlive(contextInfo);

                //  There is a trick here to pass in this resolution as in twips 
                //  (1/1440 an inch).
                // 
                //  LSCreateLine assumes the max width passed in is in twips so to 
                //  allow its client to express their width in page unit. However
                //  it asks client to set up the real device resolution here so 
                //  that it can internally translate the "twips" width into client
                //  actual device unit.
                //
                //  We are not device dependent anyway, so instead of following the 
                //  rule which will cause us to validate the context every time. We
                //  choose to cheat LS to think that our unit is twips. 
                // 
                LsDevRes devRes;
                devRes.dxpInch = devRes.dxrInch = TwipsPerInch; 
                devRes.dypInch = devRes.dyrInch = TwipsPerInch;

                SetDoc(
                    true,           // Yes, we will be displaying 
                    true,           // Yes, reference and presentation are the same device
                    ref devRes      // Device resolutions 
                    ); 

                SetBreaking(BreakStrategies.BreakCJK); 
            }
        }

 
        /// 
        /// Client to get the text penalty module. 
        ///  
        internal TextPenaltyModule GetTextPenaltyModule()
        { 
            Invariant.Assert(_ploc.Value != System.IntPtr.Zero);
            return new TextPenaltyModule(_ploc);
        }
 

        ///  
        /// Unclaim the ownership of the context, release it back to the context pool 
        /// 
        ///  
        /// Critical - this sets exception and owner which are critical
        /// 
        [SecurityCritical]
        internal void Release() 
        {
            this.CallbackException = null; 
            this.Owner = null; 
        }
 

        /// 
        /// context's owner
        ///  
        /// 
        /// Critical - Owner object is critical 
        ///  
        internal object Owner
        { 
            [SecurityCritical]
            get { return _callbacks.Owner; }
            [SecurityCritical]
            set { _callbacks.Owner = value; } 
        }
 
 
        /// 
        /// Exception thrown during LS callback 
        /// 
        /// 
        /// Critical - Exception and its message are critical
        ///  
        internal Exception CallbackException
        { 
            [SecurityCritical] 
            get { return _callbacks.Exception; }
            [SecurityCritical] 
            set { _callbacks.Exception = value; }
        }

 
        /// 
        /// Make min/max empty 
        ///  
        internal void EmptyBoundingBox()
        { 
            _callbacks.EmptyBoundingBox();
        }

 
        /// 
        /// Bounding box of whole black of line 
        ///  
        internal Rect BoundingBox
        { 
            get { return _callbacks.BoundingBox; }
        }

 
        /// 
        /// Clear the indexed glyphruns 
        ///  
        internal void ClearIndexedGlyphRuns()
        { 
            _callbacks.ClearIndexedGlyphRuns();
        }

 
        /// 
        /// Indexed glyphruns of the line 
        ///  
        internal ICollection IndexedGlyphRuns
        { 
            get { return _callbacks.IndexedGlyphRuns; }
        }

 
        /// 
        /// Destroy LS context 
        ///  
        /// 
        /// Critical - as this calls Critical function LoDestroyContext. 
        /// Safe - as this can't be used pass in arbitrary parameters.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void Destroy() 
        {
            if(_ploc.Value != System.IntPtr.Zero) 
            { 
                UnsafeNativeMethods.LoDestroyContext(_ploc.Value);
                _ploc.Value = IntPtr.Zero; 
            }
        }

 
        /// 
        /// Set LS breaking strategy 
        ///  
        /// 
        /// Critical - as this calls LoSetBreaking which is a Crtical function. 
        /// Safe - as this doesn't take any parameters that are passed on without validation.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void SetBreaking(BreakStrategies breaking) 
        {
            if (_state == State.Uninitialized ||  breaking != _breaking) 
            { 
                Invariant.Assert(_ploc.Value != System.IntPtr.Zero);
                LsErr lserr = UnsafeNativeMethods.LoSetBreaking(_ploc.Value, (int) breaking); 

                if (lserr != LsErr.None)
                {
                    ThrowExceptionFromLsError(SR.Get(SRID.SetBreakingFailure, lserr), lserr); 
                }
 
                _breaking = breaking; 
            }
            _state = State.Initialized; 
        }


        // 
        //  Line Services managed API
        // 
        // 
        /// 
        /// Critical - as this calls Critical function LoCreateLine. 
        /// Safe - as this can't be used to pass in arbitrary pointer parameters
        ///        that can be written to.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal LsErr CreateLine(
            int                 cpFirst, 
            int                 lineLength, 
            int                 maxWidth,
            LineFlags           lineFlags, 
            IntPtr              previousLineBreakRecord,
            out IntPtr          ploline,
            out LsLInfo         plslineInfo,
            out int             maxDepth, 
            out LsLineWidths    lineWidths
            ) 
        { 
            Invariant.Assert(_ploc.Value != System.IntPtr.Zero);
 
            return UnsafeNativeMethods.LoCreateLine(
                _ploc.Value,
                cpFirst,
                lineLength, 
                maxWidth,
                (uint)lineFlags,    // line flags 
                previousLineBreakRecord, 
                out plslineInfo,
                out ploline, 
                out maxDepth,
                out lineWidths
                );
        } 

 
        ///  
        /// Critical - as it calls into unsafe function LoCreateBreaks
        /// Safe - as this can't be used to pass in arbitrary pointer parameters 
        ///        that can be written to.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal LsErr CreateBreaks( 
            int             cpFirst,
            IntPtr          previousLineBreakRecord, 
            IntPtr          ploparabreak, 
            IntPtr          ptslinevariantRestriction,
            ref LsBreaks    lsbreaks, 
            out int         bestFitIndex
            )
        {
            Invariant.Assert(_ploc.Value != System.IntPtr.Zero); 

            return UnsafeNativeMethods.LoCreateBreaks( 
                _ploc.Value, 
                cpFirst,
                previousLineBreakRecord, 
                ploparabreak,
                ptslinevariantRestriction,
                ref lsbreaks,
                out bestFitIndex 
                );
        } 
 

        ///  
        /// Critical - as it calls into unsafe function LoCreateParaBreakingSession
        /// Safe - as this can't be used to pass in arbitrary pointer parameters
        ///        that can be written to.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal LsErr CreateParaBreakingSession( 
            int             cpFirst, 
            int             maxWidth,
            IntPtr          previousLineBreakRecord, 
            ref IntPtr      ploparabreak,
            ref bool        penalizedAsJustified
            )
        { 
            Invariant.Assert(_ploc.Value != System.IntPtr.Zero);
 
            return UnsafeNativeMethods.LoCreateParaBreakingSession( 
                _ploc.Value,
                cpFirst, 
                maxWidth,
                previousLineBreakRecord,
                ref ploparabreak,
                ref penalizedAsJustified 
                );
        } 
 

        ///  
        /// Critical - as this call LoSetDoc which is a Critical function.  It doesn't
        ///            pass any IntPtrs directly without validation.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void SetDoc(
            bool            isDisplay, 
            bool            isReferencePresentationEqual, 
            ref LsDevRes    deviceInfo
            ) 
        {
            Invariant.Assert(_ploc.Value != System.IntPtr.Zero);
            LsErr lserr = UnsafeNativeMethods.LoSetDoc(
                _ploc.Value, 
                isDisplay ? 1 : 0,
                isReferencePresentationEqual ? 1 : 0, 
                ref deviceInfo 
                );
 
            if(lserr != LsErr.None)
            {
                ThrowExceptionFromLsError(SR.Get(SRID.SetDocFailure, lserr), lserr);
            } 
        }
 
        ///  
        /// Critical - as this calls LoSetTabs which is a Critical function.  This
        ///            is not safe as this takes tabStopCount parameter, a random 
        ///            value of which could cause data to written past the array pointed
        ///            to by tabStops.
        /// 
        [SecurityCritical] 
        internal unsafe void SetTabs(
            int         incrementalTab, 
            LsTbd*      tabStops, 
            int         tabStopCount
            ) 
        {
            Invariant.Assert(_ploc.Value != System.IntPtr.Zero);
            LsErr lserr = UnsafeNativeMethods.LoSetTabs(
                _ploc.Value, 
                incrementalTab,
                tabStopCount, 
                tabStops 
                );
 
            if(lserr != LsErr.None)
            {
                ThrowExceptionFromLsError(SR.Get(SRID.SetTabsFailure, lserr), lserr);
            } 
        }
 
 
        static internal void ThrowExceptionFromLsError(string message, LsErr lserr)
        { 
            if (lserr == LsErr.OutOfMemory)
                throw new OutOfMemoryException (message);

            throw new Exception(message); 
        }
 
 
        #region Enumerations & constants
        private enum State : byte 
        {
            Uninitialized = 0,
            Initialized
        } 

        private const uint TwipsPerInch = 1440; 
 

        #endregion 

        #region Properties

        ///  
        /// Actual LS unmanaged context
        ///  
        internal SecurityCriticalDataForSet Ploc 
        {
            get { return _ploc; } 
        }

        #endregion
    } 

 
    internal enum BreakStrategies 
    {
        BreakCJK, 
        KeepCJK,
        Max
    }
} 

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