| File: MS\Internal\PtsHost\BaseParagraph.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Description: BaseParagraph represents a paragraph corresponding to part // of a text based content. // using System.Windows; using System.Windows.Documents; using MS.Internal.Documents; using MS.Internal.Text; using MS.Internal.PtsHost.UnsafeNativeMethods; namespace MS.Internal.PtsHost { /// <summary> /// BaseParagraph represents a paragraph corresponding to part of a text /// based content. /// </summary> internal abstract class BaseParagraph : UnmanagedHandle { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors /// <summary> /// Constructor. /// </summary> /// <param name="element"> /// Element associated with paragraph. /// </param> /// <param name="structuralCache"> /// Content's structural cache /// </param> protected BaseParagraph(DependencyObject element, StructuralCache structuralCache) : base(structuralCache.PtsContext) { _element = element; _structuralCache = structuralCache; _changeType = PTS.FSKCHANGE.fskchNone; _stopAsking = false; UpdateLastFormatPositions(); } #endregion Constructors // ------------------------------------------------------------------ // // PTS callbacks // // ------------------------------------------------------------------ #region PTS callbacks /// <summary> /// UpdGetParaChange /// </summary> /// <param name="fskch"> /// OUT: kind of change /// </param> /// <param name="fNoFurtherChanges"> /// OUT: no changes after? /// </param> internal virtual void UpdGetParaChange( out PTS.FSKCHANGE fskch, out int fNoFurtherChanges) { fskch = _changeType; fNoFurtherChanges = PTS.FromBoolean(_stopAsking); #if TEXTPANELLAYOUTDEBUG if (StructuralCache.CurrentFormatContext.IncrementalUpdate) { TextPanelDebug.Log("Para.UpdGetParaChange, Para=" + this.GetType().Name + " Change=" + _changeType.ToString(), TextPanelDebug.Category.ContentChange); } #endif } /// <summary> /// Collapse margins /// </summary> /// <param name="paraClient"> /// IN: Paragraph's para client /// </param> /// <param name="mcs"> /// IN: input margin collapsing state /// </param> /// <param name="fswdir"> /// IN: current direction (of the track, in which margin collapsing is happening) /// </param> /// <param name="suppressTopSpace"> /// IN: suppress empty space at the top of page /// </param> /// <param name="dvr"> /// OUT: dvr, calculated based on margin collapsing state /// </param> internal virtual void CollapseMargin( BaseParaClient paraClient, MarginCollapsingState mcs, uint fswdir, bool suppressTopSpace, out int dvr) { // Suppress top space only in paginated scenarios. dvr = (mcs == null || (suppressTopSpace)) ? 0 : mcs.Margin; } /// <summary> /// Get Para Properties /// </summary> /// <param name="fspap"> /// OUT: paragraph properties /// </param> internal abstract void GetParaProperties( ref PTS.FSPAP fspap); /// <summary> /// CreateParaclient /// </summary> /// <param name="pfsparaclient"> /// OUT: opaque to PTS paragraph client /// </param> internal abstract void CreateParaclient( out IntPtr pfsparaclient); #endregion PTS callbacks // ------------------------------------------------------------------ // // Internal Methods // // ------------------------------------------------------------------ #region Internal Methods /// <summary> /// Set update info. Those flags are used later by PTS to decide /// if paragraph needs to be updated and when to stop asking for /// update information. /// </summary> /// <param name="fskch"> /// Type of change within the paragraph. /// </param> /// <param name="stopAsking"> /// Synchronization point is reached? /// </param> internal virtual void SetUpdateInfo(PTS.FSKCHANGE fskch, bool stopAsking) { _changeType = fskch; _stopAsking = stopAsking; } /// <summary> /// Clear previously accumulated update info. /// </summary> internal virtual void ClearUpdateInfo() { _changeType = PTS.FSKCHANGE.fskchNone; _stopAsking = true; } /// <summary> /// Invalidate content's structural cache. Returns: 'true' if entire paragraph /// is invalid. /// </summary> /// <param name="startPosition"> /// Position to start invalidation from. /// </param> internal virtual bool InvalidateStructure(int startPosition) { Debug.Assert(ParagraphEndCharacterPosition >= startPosition); int openEdgeCp = TextContainerHelper.GetCPFromElement(StructuralCache.TextContainer, Element, ElementEdge.BeforeStart); return (openEdgeCp == startPosition); } /// <summary> /// Invalidate accumulated format caches. /// </summary> internal virtual void InvalidateFormatCache() { } /// <summary> /// Update number of characters consumed by the paragraph. /// </summary> internal void UpdateLastFormatPositions() { _lastFormatCch = Cch; } #endregion Internal Methods //------------------------------------------------------------------- // // Protected Methods // //------------------------------------------------------------------- #region Protected Methods /// <summary> /// Retrieve PTS paragraph properties. /// </summary> /// <param name="fspap"> /// Paragraph properties to initialize. /// </param> /// <param name="ignoreElementProps"> /// Ignore element properties? /// </param> protected void GetParaProperties(ref PTS.FSPAP fspap, bool ignoreElementProps) { if (!ignoreElementProps) { fspap.fKeepWithNext = PTS.FromBoolean(DynamicPropertyReader.GetKeepWithNext(_element)); // Can be broken only if Block.BreakPageBefore is set fspap.fBreakPageBefore = _element is Block ? PTS.FromBoolean(StructuralCache.CurrentFormatContext.FinitePage && ((Block)_element).BreakPageBefore) : PTS.FromBoolean(false); // Can be broken only if Block.BreakColumnBefore is set fspap.fBreakColumnBefore = _element is Block ? PTS.FromBoolean(((Block)_element).BreakColumnBefore) : PTS.FromBoolean(false); } } #endregion Protected Methods //------------------------------------------------------------------- // // Properties / Fields // //------------------------------------------------------------------- #region Properties / Fields /// <summary> /// CharacterPosition at the start of paragraph. /// </summary> internal int ParagraphStartCharacterPosition { get { // This is done here, rather than deriving for two reasons - This is special cased for text paragraph - no other // paras should use their cps in this way, and this is also not a virtual method, so can be used from C'Tor. if(this is TextParagraph) { return TextContainerHelper.GetCPFromElement(StructuralCache.TextContainer, Element, ElementEdge.AfterStart); } else { return TextContainerHelper.GetCPFromElement(StructuralCache.TextContainer, Element, ElementEdge.BeforeStart); } } } /// <summary> /// CharacterPosition at the end of paragraph. The first character /// that does not belong to the paragraph. /// </summary> internal int ParagraphEndCharacterPosition { get { // This is done here, rather than deriving for two reasons - This is special cased for text paragraph - no other // paras should use their cps in this way, and this is also not a virtual method, so can be used from C'Tor. if(this is TextParagraph) { return TextContainerHelper.GetCPFromElement(StructuralCache.TextContainer, Element, ElementEdge.BeforeEnd); } else { return TextContainerHelper.GetCPFromElement(StructuralCache.TextContainer, Element, ElementEdge.AfterEnd); } } } /// <summary> /// Incremental update information for the paragraph. /// Those fields are used only during incremental update process. /// </summary> protected PTS.FSKCHANGE _changeType; protected bool _stopAsking; /// <summary> /// Number of characters consumed by the paragraph. /// </summary> internal int Cch { get { int cch = TextContainerHelper.GetCchFromElement(StructuralCache.TextContainer, Element); // This is done here, rather than deriving for two reasons - This is special cased for text paragraph - no other // paras should use their cps in this way, and this is also not a virtual method, so can be used from C'Tor. if (this is TextParagraph && Element is TextElement) { Invariant.Assert(cch >= 2); cch -= 2; } return cch; } } /// <summary> /// Cch paragraph had during last format /// </summary> internal int LastFormatCch { get { return _lastFormatCch; } } protected int _lastFormatCch; /// <summary> /// The next and previous sibling in paragraph list. /// </summary> internal BaseParagraph Next; internal BaseParagraph Previous; /// <summary> /// Content's structural cache. /// </summary> internal StructuralCache StructuralCache { get { return _structuralCache; } } protected readonly StructuralCache _structuralCache; /// <summary> /// Object associated with the paragraph. /// </summary> internal DependencyObject Element { get { return _element; } } protected readonly DependencyObject _element; #endregion Properties / Fields } }