Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / PtsHost / FloaterParaClient.cs / 1305600 / FloaterParaClient.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: FloaterParaClient class is responsible for handling display // related data of paragraphs associated with floaters. // // History: // 05/05/2003 : [....] - moving from Avalon branch. // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Security; using System.Windows; using System.Windows.Media; using System.Windows.Documents; using MS.Internal.Documents; using MS.Internal.Text; using MS.Internal.PtsHost.UnsafeNativeMethods; namespace MS.Internal.PtsHost { // --------------------------------------------------------------------- // FloaterParaClient class is responsible for handling display related // data of paragraphs associated with nested floaters. // --------------------------------------------------------------------- internal sealed class FloaterParaClient : FloaterBaseParaClient { //-------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors // ------------------------------------------------------------------ // Constructor. // // paragraph - Paragraph associated with this object. // ------------------------------------------------------------------ internal FloaterParaClient(FloaterParagraph paragraph) : base(paragraph) { } // ----------------------------------------------------------------- // IDisposable.Dispose // ------------------------------------------------------------------ ////// Critical - as this calls the Critical function PTS.FsDestroySubpage. /// Safe - as the parameters passed in, PtsContext.Context and _paraHandle are /// both marked Critical for set. SubpageHandle parameter just returns /// _paraHandle. /// [SecurityCritical, SecurityTreatAsSafe] public override void Dispose() { if(_pageContext != null) { _pageContext.RemoveFloatingParaClient(this); } base.Dispose(); } #endregion Constructors ////// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails, /// PtsHelper.ArrangeTrack and PtsHelper.TrackListFromSubpage. /// Safe - as this can't be used to pass random parameters. PtsContext.Context /// is marked Critical for set and _paraHandle is readonly data for this /// function. /// [SecurityCritical, SecurityTreatAsSafe] protected override void OnArrange() { base.OnArrange(); ((FloaterParagraph)Paragraph).UpdateSegmentLastFormatPositions(); // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); _pageContext.AddFloatingParaClient(this); // Arrange subpage content. Subpage content may be simple or complex - // depending of set of features used in the content of the subpage. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { _pageContextOfThisPage.PageRect = new PTS.FSRECT(subpageDetails.u.simple.trackdescr.fsrc); // (1) simple subpage (contains only one track) // Exceptions don't need to pop, as the top level arrange context will be nulled out if thrown. Paragraph.StructuralCache.CurrentArrangeContext.PushNewPageData(_pageContextOfThisPage, subpageDetails.u.simple.trackdescr.fsrc, Paragraph.StructuralCache.CurrentArrangeContext.FinitePage); PtsHelper.ArrangeTrack(PtsContext, ref subpageDetails.u.simple.trackdescr, subpageDetails.u.simple.fswdir); Paragraph.StructuralCache.CurrentArrangeContext.PopPageData(); } else { _pageContextOfThisPage.PageRect = new PTS.FSRECT(subpageDetails.u.complex.fsrc); // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty if (subpageDetails.u.complex.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); // Arrange each track for (int index = 0; index < arrayColumnDesc.Length; index++) { // Exceptions don't need to pop, as the top level arrange context will be nulled out if thrown. Paragraph.StructuralCache.CurrentArrangeContext.PushNewPageData(_pageContextOfThisPage, arrayColumnDesc[index].fsrc, Paragraph.StructuralCache.CurrentArrangeContext.FinitePage); PtsHelper.ArrangeTrack(PtsContext, ref arrayColumnDesc[index], subpageDetails.u.complex.fswdir); Paragraph.StructuralCache.CurrentArrangeContext.PopPageData(); } } } } // ----------------------------------------------------------------- // Updates viewport // ----------------------------------------------------------------- ////// Critical - as this calls Critical functions PTS.FsQuerySubpageDetails, /// PtsHelper.TrackListFromSubpage and PtsHelper.UpdateViewportTrack /// Safe - The IntPtr parameters passed to PTS.FsQuerySubpageDetails, PtsHelper.TrackListFromSubpage and PtsHelper.UpdateViewportTrack /// are SecurityCriticalDataForSet which ensures that partial trust code won't be able to set it to a random value. /// The subpageDetails parameter passed to other methods is generated securely in this function. /// [SecurityCritical, SecurityTreatAsSafe] internal override void UpdateViewport(ref PTS.FSRECT viewport) { // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); PTS.FSRECT viewportSubpage = new PTS.FSRECT(); viewportSubpage.u = viewport.u - ContentRect.u; viewportSubpage.v = viewport.v - ContentRect.v; viewportSubpage.du = viewport.du; viewportSubpage.dv = viewport.dv; // Subpage content may be simple or complex - // depending of set of features used in the content of the subpage. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { PtsHelper.UpdateViewportTrack(PtsContext, ref subpageDetails.u.simple.trackdescr, ref viewportSubpage); } else { // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty bool emptySubpage = (subpageDetails.u.complex.cBasicColumns == 0); if (!emptySubpage) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); emptySubpage = (arrayColumnDesc.Length == 0); if (!emptySubpage) { for (int index = 0; index < arrayColumnDesc.Length; index++) { PtsHelper.UpdateViewportTrack(PtsContext, ref arrayColumnDesc[index], ref viewportSubpage); } } } } } // ----------------------------------------------------------------- // Arrange floater // // rcFloater - rectangle of the floater // rcHostPara - rectangle of the host text paragraph. // ------------------------------------------------------------------ internal override void ArrangeFloater(PTS.FSRECT rcFloater, PTS.FSRECT rcHostPara, uint fswdirParent, PageContext pageContext) { // If alignment is set to Stretch and floater width is less than para width, center it if (IsFloaterHorizontallyCentered(rcFloater, rcHostPara)) { rcFloater.u = rcHostPara.u + (rcHostPara.du - rcFloater.du) / 2; } // Set paragraph rectangle (relative to the page) _rect = rcFloater; // Adjust rect to account for margins // Add margin values to rect offsets and subtract them from rect widths MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element); _rect.v += mbp.MarginTop; _rect.dv -= mbp.MarginTop + mbp.MarginBottom; _rect.u += mbp.MarginLeft; _rect.du -= mbp.MarginLeft + mbp.MarginRight; _flowDirectionParent = PTS.FswdirToFlowDirection(fswdirParent); _flowDirection = (FlowDirection)Paragraph.Element.GetValue(FrameworkElement.FlowDirectionProperty); _pageContext = pageContext; if(ThisFlowDirection != PageFlowDirection) { mbp.MirrorBP(); } _contentRect.u = _rect.u + mbp.BPLeft; _contentRect.du = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.du - mbp.BPRight - mbp.BPLeft); _contentRect.v = _rect.v + mbp.BPTop; _contentRect.dv = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.dv - mbp.BPBottom - mbp.BPTop); _paddingRect.u = _rect.u + mbp.BorderLeft; _paddingRect.du = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.du - mbp.BorderRight - mbp.BorderLeft); _paddingRect.v = _rect.v + mbp.BorderTop; _paddingRect.dv = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.dv - mbp.BorderBottom - mbp.BorderTop); // Do paragraph specifc arrange OnArrange(); } // ----------------------------------------------------------------- // Hit tests to the correct IInputElement within the paragraph // that the mouse is over. // ------------------------------------------------------------------ ////// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails /// and some PtsHelper functions. /// Safe - as this can't be used to pass random parameters. PtsContext.Context /// is marked Critical for set and _paraHandle is readonly data for this /// function. /// [SecurityCritical, SecurityTreatAsSafe] internal override IInputElement InputHitTest(PTS.FSPOINT pt) { IInputElement ie = null; if(_pageContextOfThisPage.FloatingElementList != null) { for(int index = 0; index < _pageContextOfThisPage.FloatingElementList.Count && ie == null; index++) { BaseParaClient floatingElement = _pageContextOfThisPage.FloatingElementList[index]; ie = floatingElement.InputHitTest(pt); } } if(ie == null) { // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); if(Rect.Contains(pt)) { if(ContentRect.Contains(pt)) { pt = new PTS.FSPOINT(pt.u - ContentRect.u, pt.v - ContentRect.v); // Hittest subpage content. Subpage content may be simple or complex - // depending of set of features used in the content of the page. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { ie = PtsHelper.InputHitTestTrack(PtsContext, pt, ref subpageDetails.u.simple.trackdescr); } else { // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty if (subpageDetails.u.complex.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); // Arrange each track for (int index = 0; index < arrayColumnDesc.Length && ie == null; index++) { ie = PtsHelper.InputHitTestTrack(PtsContext, pt, ref arrayColumnDesc[index]); } } } } if(ie == null) { ie = Paragraph.Element as IInputElement; } } } return ie; } // ------------------------------------------------------------------ // Returns ArrayList of rectangles for the given ContentElement // if it is found. Returns null otherwise. // start: int representing start offset of e. // length: int representing number of positions occupied by e. // ----------------------------------------------------------------- ////// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails /// and some PtsHelper functions. /// Safe - as this can't be used to pass random parameters. PtsContext.Context /// is marked Critical for set and _paraHandle is readonly data for this /// function. /// [SecurityCritical, SecurityTreatAsSafe] internal override ListGetRectangles(ContentElement e, int start, int length) { List rectangles = new List (); if (Paragraph.Element as ContentElement == e) { // We have found the element. Return rectangles for this paragraph. GetRectanglesForParagraphElement(out rectangles); } else { // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); // Check subpage content for element. Subpage content may be simple or complex - // depending of set of features used in the content of the page. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { // (1) simple subpage (contains only one track) rectangles = PtsHelper.GetRectanglesInTrack(PtsContext, e, start, length, ref subpageDetails.u.simple.trackdescr); } else { // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty if (subpageDetails.u.complex.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); // Arrange each track for (int index = 0; index < arrayColumnDesc.Length; index++) { List trackRectangles = PtsHelper.GetRectanglesInTrack(PtsContext, e, start, length, ref arrayColumnDesc[index]); Invariant.Assert(trackRectangles != null); if (trackRectangles.Count != 0) { // Add rectangles found in this track to all rectangles rectangles.AddRange(trackRectangles); } } } } rectangles = PtsHelper.OffsetRectangleList(rectangles, TextDpi.FromTextDpi(ContentRect.u), TextDpi.FromTextDpi(ContentRect.v)); } Invariant.Assert(rectangles != null); return rectangles; } // ------------------------------------------------------------------ // Validate visual node associated with paragraph. // // fskupdInherited - inherited update info // fswdir - inherited flow direction // ----------------------------------------------------------------- /// /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails and /// some PtsHelper functions. /// Safe - as this can't be used to pass random parameters. PtsContext.Context /// is marked Critical for set and _paraHandle is readonly data for this /// function. /// [SecurityCritical, SecurityTreatAsSafe] internal override void ValidateVisual(PTS.FSKUPDATE fskupdInherited) { // Floater is always reported as NEW. Override PTS inherited value. fskupdInherited = PTS.FSKUPDATE.fskupdNew; // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); // Obtain all mbd info MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element); if(ThisFlowDirection != PageFlowDirection) { mbp.MirrorBP(); } Brush backgroundBrush = (Brush)Paragraph.Element.GetValue(TextElement.BackgroundProperty); Visual.DrawBackgroundAndBorder(backgroundBrush, mbp.BorderBrush, mbp.Border, _rect.FromTextDpi(), IsFirstChunk, IsLastChunk); ContainerVisual pageContentVisual; ContainerVisual floatingElementsVisual; if(_visual.Children.Count != 2) { _visual.Children.Clear(); _visual.Children.Add(new ContainerVisual()); _visual.Children.Add(new ContainerVisual()); } pageContentVisual = (ContainerVisual)_visual.Children[0]; floatingElementsVisual = (ContainerVisual)_visual.Children[1]; // Subpage content may be simple or complex - // depending of set of features used in the content of the subpage. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { // (1) simple subpage (contains only one track) PTS.FSKUPDATE fskupd = subpageDetails.u.simple.trackdescr.fsupdinf.fskupd; if (fskupd == PTS.FSKUPDATE.fskupdInherited) { fskupd = fskupdInherited; } VisualCollection visualChildren = pageContentVisual.Children; if (fskupd == PTS.FSKUPDATE.fskupdNew) { visualChildren.Clear(); visualChildren.Add(new ContainerVisual()); } // For complex subpage SectionVisual is added. So, when morphing // complex subpage to simple one, remove SectionVisual. else if (visualChildren.Count == 1 && !(visualChildren[0] is ContainerVisual)) { visualChildren.Clear(); visualChildren.Add(new ContainerVisual()); } Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is ContainerVisual); ContainerVisual trackVisual = (ContainerVisual)visualChildren[0]; PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref subpageDetails.u.simple.trackdescr); } else { // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty bool emptySubpage = (subpageDetails.u.complex.cBasicColumns == 0); if (!emptySubpage) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); emptySubpage = (arrayColumnDesc.Length == 0); if (!emptySubpage) { PTS.FSKUPDATE fskupd = fskupdInherited; ErrorHandler.Assert(fskupd != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); Debug.Assert(fskupd != PTS.FSKUPDATE.fskupdNoChange); // For complex subpage SectionVisual is added. So, when morphing // simple subpage to complex one, remove ParagraphVisual. VisualCollection visualChildren = pageContentVisual.Children; if (visualChildren.Count == 0) { visualChildren.Add(new SectionVisual()); } else if (!(visualChildren[0] is SectionVisual)) { visualChildren.Clear(); visualChildren.Add(new SectionVisual()); } Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is SectionVisual); SectionVisual sectionVisual = (SectionVisual)visualChildren[0]; // Draw column rules. ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(Paragraph.Element); sectionVisual.DrawColumnRules(ref arrayColumnDesc, TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.v), TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.dv), columnProperties); visualChildren = sectionVisual.Children; if (fskupd == PTS.FSKUPDATE.fskupdNew) { visualChildren.Clear(); for (int index = 0; index < arrayColumnDesc.Length; index++) { visualChildren.Add(new ContainerVisual()); } } ErrorHandler.Assert(visualChildren.Count == arrayColumnDesc.Length, ErrorHandler.ColumnVisualCountMismatch); for (int index = 0; index < arrayColumnDesc.Length; index++) { ContainerVisual trackVisual = (ContainerVisual)visualChildren[index]; PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref arrayColumnDesc[index]); } } } if (emptySubpage) { // There is no content, remove all existing visuals. _visual.Children.Clear(); } } pageContentVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi(); floatingElementsVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi(); PTS.FSRECT clipRect = new PTS.FSRECT(_paddingRect.u - _contentRect.u, _paddingRect.v - _contentRect.v, _paddingRect.du, _paddingRect.dv); PtsHelper.ClipChildrenToRect(_visual, clipRect.FromTextDpi()); PtsHelper.UpdateFloatingElementVisuals(floatingElementsVisual, _pageContextOfThisPage.FloatingElementList); } // ----------------------------------------------------------------- // Create paragraph result representing this paragraph. // ----------------------------------------------------------------- internal override ParagraphResult CreateParagraphResult() { return new FloaterParagraphResult(this); } // ------------------------------------------------------------------ // Return TextContentRange for the content of the paragraph. // ----------------------------------------------------------------- ////// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails /// and some PtsHelper functions. /// Safe - as this can't be used to pass random parameters. PtsContext.Context /// is marked Critical for set and _paraHandle is readonly data for this /// function. /// [SecurityCritical, SecurityTreatAsSafe] internal override TextContentRange GetTextContentRange() { TextContentRange textContentRange; // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); // Subpage content may be simple or complex - // depending of set of features used in the content of the page. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { // (1) simple subpage (contains only one track) textContentRange = PtsHelper.TextContentRangeFromTrack(PtsContext, subpageDetails.u.simple.trackdescr.pfstrack); } else { textContentRange = new TextContentRange(); // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty if (subpageDetails.u.complex.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); // Arrange each track for (int index = 0; index < arrayColumnDesc.Length; index++) { // Merge TextContentRanges for all columns textContentRange.Merge(PtsHelper.TextContentRangeFromTrack(PtsContext, arrayColumnDesc[index].pfstrack)); } } } // Beginning and end tags should be consumed by host para. // If the first paragraph is the first paragraph in the paraclient and it is the first chunk, // include start position of this element. if (IsFirstChunk) { textContentRange.Merge(TextContainerHelper.GetTextContentRangeForTextElementEdge( Paragraph.Element as TextElement, ElementEdge.BeforeStart)); } // If the last paragraph is the last paragraph in the paraclient and it is the last chunk, // include end position of this element. if (IsLastChunk) { textContentRange.Merge(TextContainerHelper.GetTextContentRangeForTextElementEdge( Paragraph.Element as TextElement, ElementEdge.AfterEnd)); } return textContentRange; } // ------------------------------------------------------------------ // Returns a new colleciton of ParagraphResults for the contained paragraphs. // ------------------------------------------------------------------ ////// Critical - as this calls the Critical functions PTS.FsQuerySubpageDetails, /// PTS.FsQueryTrackDetails and some PtsHelper functions. /// Safe - as this can't be used to pass random parameters. PtsContext.Context /// is marked Critical for set and _paraHandle is readonly data for this /// function. /// [SecurityCritical, SecurityTreatAsSafe] private ReadOnlyCollectionGetChildrenParagraphResults(out bool hasTextContent) { List paragraphResults; // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); // hasTextContent is set to true if any of the children paragraphs has text content, not just attached objects hasTextContent = false; // Subpage content may be simple or complex - // depending of set of features used in the content of the page. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { // (1) simple subpage (contains only one track) // Get track details PTS.FSTRACKDETAILS trackDetails; PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, subpageDetails.u.simple.trackdescr.pfstrack, out trackDetails)); hasTextContent = true; if (trackDetails.cParas == 0) { return new ReadOnlyCollection (new List (0)); } // Get list of paragraphs PTS.FSPARADESCRIPTION[] arrayParaDesc; PtsHelper.ParaListFromTrack(PtsContext, subpageDetails.u.simple.trackdescr.pfstrack, ref trackDetails, out arrayParaDesc); paragraphResults = new List (arrayParaDesc.Length); for (int i = 0; i < arrayParaDesc.Length; i++) { BaseParaClient paraClient = PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient; PTS.ValidateHandle(paraClient); ParagraphResult paragraphResult = paraClient.CreateParagraphResult(); if (paragraphResult.HasTextContent) { hasTextContent = true; } paragraphResults.Add(paragraphResult); } } else { // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty if (subpageDetails.u.complex.cBasicColumns == 0) { return new ReadOnlyCollection (new List (0)); } // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); Debug.Assert(arrayColumnDesc.Length == 1); // Get track details PTS.FSTRACKDETAILS trackDetails; PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, arrayColumnDesc[0].pfstrack, out trackDetails)); if (trackDetails.cParas == 0) { return new ReadOnlyCollection (new List (0)); } // Get list of paragraphs PTS.FSPARADESCRIPTION[] arrayParaDesc; PtsHelper.ParaListFromTrack(PtsContext, arrayColumnDesc[0].pfstrack, ref trackDetails, out arrayParaDesc); paragraphResults = new List (arrayParaDesc.Length); for (int i = 0; i < arrayParaDesc.Length; i++) { BaseParaClient paraClient = PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient; PTS.ValidateHandle(paraClient); ParagraphResult paragraphResult = paraClient.CreateParagraphResult(); if (paragraphResult.HasTextContent) { hasTextContent = true; } paragraphResults.Add(paragraphResult); } } return new ReadOnlyCollection (paragraphResults); } /// /// Returns a new collection of ColumnResults for the subpage. Will always /// have at least one column. /// /// /// True if any column in the floater has text content, i.e. does not contain only figures/floaters /// ////// Critical - as this calls the Critical functions PTS.FsQuerySubpageDetails /// and PTS.FsQueryTrackDetails. /// Safe - as this can't be used to pass random parameters. PtsContext.Context /// is marked Critical for set and _paraHandle is readonly data for this /// function. /// [SecurityCritical, SecurityTreatAsSafe] internal ReadOnlyCollectionGetColumnResults(out bool hasTextContent) { List columnResults = new List (0); Vector contentOffset = new Vector(); // hasTextContent is set to true if any of the columns has text content, not just attached objects. A column has text content if any of // it's paragraph results has text content hasTextContent = false; // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); // Subpage content may be simple or complex - // depending of set of features used in the content of the page. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { // (1) simple subpage (contains only one track) PTS.FSTRACKDETAILS trackDetails; PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, subpageDetails.u.simple.trackdescr.pfstrack, out trackDetails)); if (trackDetails.cParas > 0) { columnResults = new List (1); ColumnResult columnResult = new ColumnResult(this, ref subpageDetails.u.simple.trackdescr, contentOffset); columnResults.Add(columnResult); if (columnResult.HasTextContent) { hasTextContent = true; } } } else { // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty if (subpageDetails.u.complex.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); // Floaters are held at one column; just add the first one columnResults = new List (1); PTS.FSTRACKDETAILS trackDetails; PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, arrayColumnDesc[0].pfstrack, out trackDetails)); if (trackDetails.cParas > 0) { ColumnResult columnResult = new ColumnResult(this, ref arrayColumnDesc[0], contentOffset); columnResults.Add(columnResult); if (columnResult.HasTextContent) { hasTextContent = true; } } } } return new ReadOnlyCollection (columnResults); } // ----------------------------------------------------------------- // Returns a collection of ParagraphResults for the column's paragraphs. // // pfstrack - Pointer to PTS track representing a column. // parentOffset - Parent offset from the top of the page. // hasTextContent - true if any paragraph has text content // ------------------------------------------------------------------ internal ReadOnlyCollection GetParagraphResultsFromColumn(IntPtr pfstrack, Vector parentOffset, out bool hasTextContent) { // Floater has only one column. This is the same as getting children paragraphs. return GetChildrenParagraphResults(out hasTextContent); } // ----------------------------------------------------------------- // Retrieves text range for contents of the column represented by // 'pfstrack'. // // pfstrack - Pointer to PTS track representing a column. // ----------------------------------------------------------------- internal TextContentRange GetTextContentRangeFromColumn(IntPtr pfstrack) { // Floater has only one column. return GetTextContentRange(); } /// /// Returns tight bounding path geometry. /// internal Geometry GetTightBoundingGeometryFromTextPositions(ReadOnlyCollectioncolumns, ReadOnlyCollection floatingElements, ITextPointer startPosition, ITextPointer endPosition, Rect visibleRect) { Geometry geometry = null; // Floater always has one column, so we can skip getting a column from the text position range Invariant.Assert(columns != null && columns.Count <= 1, "Columns collection is null."); Invariant.Assert(floatingElements != null, "Floating element collection is null."); ReadOnlyCollection paragraphs = (columns.Count > 0) ? columns[0].Paragraphs : new ReadOnlyCollection (new List (0)); if (paragraphs.Count > 0 || floatingElements.Count > 0) { geometry = TextDocumentView.GetTightBoundingGeometryFromTextPositionsHelper(paragraphs, floatingElements, startPosition, endPosition, TextDpi.FromTextDpi(_dvrTopSpace), visibleRect); // restrict geometry to the floater's content rect boundary. // because of end-of-line / end-of-para simulation calculated geometry could be larger. Rect viewport = new Rect(0, 0, TextDpi.FromTextDpi(_contentRect.du), TextDpi.FromTextDpi(_contentRect.dv)); CaretElement.ClipGeometryByViewport(ref geometry, viewport); } return (geometry); } // ----------------------------------------------------------------- // Handle to PTS subpage object. // ------------------------------------------------------------------ /// /// Critical - setter is Critical as _paraHandle.Value is Critical for set. /// internal IntPtr SubpageHandle { // getter removed (unused internal API). If needed, recall from history. [SecurityCritical] set { _paraHandle.Value = value; } } // ----------------------------------------------------------------- // Rect of content in page coordinate system // ------------------------------------------------------------------ internal PTS.FSRECT ContentRect { get { return _contentRect; } } // Floating element list internal ReadOnlyCollectionFloatingElementResults { get { List floatingElements = new List (0); List floatingElementList = _pageContextOfThisPage.FloatingElementList; if (floatingElementList != null) { for (int i = 0; i < floatingElementList.Count; i++) { ParagraphResult paragraphResult = floatingElementList[i].CreateParagraphResult(); floatingElements.Add(paragraphResult); } } return new ReadOnlyCollection (floatingElements); } } // ------------------------------------------------------------------ // Returns whether a floater should be horizontally centered // ----------------------------------------------------------------- private bool IsFloaterHorizontallyCentered(PTS.FSRECT rcFloater, PTS.FSRECT rcHostPara) { Floater floater = Paragraph.Element as Floater; if(floater == null) { return false; } if(floater.HorizontalAlignment != HorizontalAlignment.Stretch) { return false; } if(rcFloater.du >= rcHostPara.du) { return false; } return true; } private PTS.FSRECT _contentRect; private PTS.FSRECT _paddingRect; // Page context this para client provides. private PageContext _pageContextOfThisPage = new PageContext(); } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Resources.Designer.cs
- RenameRuleObjectDialog.cs
- Int64AnimationBase.cs
- WebControlsSection.cs
- dataprotectionpermission.cs
- WindowsListViewGroup.cs
- SwitchCase.cs
- KeyboardNavigation.cs
- AutomationElement.cs
- CellTreeSimplifier.cs
- DynamicRenderer.cs
- XslAstAnalyzer.cs
- ServiceContractGenerationContext.cs
- NumberFormatter.cs
- HttpListenerRequest.cs
- HwndAppCommandInputProvider.cs
- BinaryConverter.cs
- HebrewNumber.cs
- NetworkCredential.cs
- DesignerAttribute.cs
- ClientRuntimeConfig.cs
- TextTreeNode.cs
- PublisherIdentityPermission.cs
- NullReferenceException.cs
- CodeGenerator.cs
- StylusShape.cs
- CFStream.cs
- StateDesigner.cs
- GuidelineSet.cs
- DataGridViewCellCancelEventArgs.cs
- InputLanguageManager.cs
- EntityDescriptor.cs
- ReversePositionQuery.cs
- SerializationAttributes.cs
- TreeNode.cs
- XPathSingletonIterator.cs
- InkSerializer.cs
- mda.cs
- EntityDataSourceDesigner.cs
- EdmMember.cs
- ClassDataContract.cs
- TileModeValidation.cs
- DetailsViewPagerRow.cs
- SystemColors.cs
- ScriptIgnoreAttribute.cs
- DbConnectionHelper.cs
- FilterableData.cs
- AnnotationDocumentPaginator.cs
- X509Chain.cs
- XmlILConstructAnalyzer.cs
- CheckableControlBaseAdapter.cs
- XXXInfos.cs
- OleDbMetaDataFactory.cs
- Calendar.cs
- StringHandle.cs
- XmlILAnnotation.cs
- DeferredElementTreeState.cs
- Knowncolors.cs
- PlatformNotSupportedException.cs
- Keyboard.cs
- FixedSOMPageConstructor.cs
- DiscoveryOperationContext.cs
- IdentityElement.cs
- CompletionCallbackWrapper.cs
- autovalidator.cs
- SqlDataReader.cs
- AutoResetEvent.cs
- CatalogPart.cs
- SystemMulticastIPAddressInformation.cs
- GenericsInstances.cs
- UntrustedRecipientException.cs
- SamlAction.cs
- ConfigurationValidatorBase.cs
- GeneralTransformGroup.cs
- UTF7Encoding.cs
- SqlResolver.cs
- NullReferenceException.cs
- MenuItemCollection.cs
- AtomicFile.cs
- ComboBoxItem.cs
- ProcessHostServerConfig.cs
- StrokeSerializer.cs
- CodeCommentStatementCollection.cs
- DesignerTransaction.cs
- TextBoxBase.cs
- DataGridViewColumn.cs
- ExpressionBindingCollection.cs
- RequiredFieldValidator.cs
- hresults.cs
- IntSecurity.cs
- XmlValidatingReader.cs
- GridItemPattern.cs
- SecUtil.cs
- arc.cs
- ListViewUpdateEventArgs.cs
- PerformanceCounterPermissionAttribute.cs
- TextParagraphProperties.cs
- LogConverter.cs
- ObjectCacheHost.cs
- WindowsFormsHostPropertyMap.cs