//------------------------------------------------------------------- // // PTS callbacks // //------------------------------------------------------------------- #region PTS callbacks // ----------------------------------------------------------------- // UpdGetParaChange // ------------------------------------------------------------------ internal override void UpdGetParaChange( out PTS.FSKCHANGE fskch, // OUT: kind of change out int fNoFurtherChanges) // OUT: no changes after? { fskch = PTS.FSKCHANGE.fskchNew; fNoFurtherChanges = PTS.FromBoolean(_stopAsking); }
// ------------------------------------------------------------------ // UpdGetParaChange - Floater paragraph is always new // ------------------------------------------------------------------ internal override void UpdGetParaChange( out PTS.FSKCHANGE fskch, // OUT: kind of change out int fNoFurtherChanges) // OUT: no changes after? { base.UpdGetParaChange(out fskch, out fNoFurtherChanges); fskch = PTS.FSKCHANGE.fskchNew; }
//------------------------------------------------------------------- // // PTS callbacks // //------------------------------------------------------------------- #region PTS callbacks //------------------------------------------------------------------- // GetParaProperties //------------------------------------------------------------------- internal override void GetParaProperties( ref PTS.FSPAP fspap) // OUT: paragraph properties { GetParaProperties(ref fspap, false); fspap.idobj = PtsHost.SubpageParagraphId; // Create the main text segment if (_mainTextSegment == null) { _mainTextSegment = new ContainerParagraph(_element, _structuralCache); } }
internal ColumnResult(FlowDocumentPage page, ref PTS.FSTRACKDESCRIPTION trackDesc, Vector contentOffset) { _page = page; _columnHandle = trackDesc.pfstrack; _layoutBox = new Rect( TextDpi.FromTextDpi(trackDesc.fsrc.u), TextDpi.FromTextDpi(trackDesc.fsrc.v), TextDpi.FromTextDpi(trackDesc.fsrc.du), TextDpi.FromTextDpi(trackDesc.fsrc.dv)); _layoutBox.X += contentOffset.X; _layoutBox.Y += contentOffset.Y; _columnOffset = new Vector(TextDpi.FromTextDpi(trackDesc.fsrc.u), TextDpi.FromTextDpi(trackDesc.fsrc.v)); _hasTextContent = false; }
internal ColumnResult(BaseParaClient subpage, ref PTS.FSTRACKDESCRIPTION trackDesc, Vector contentOffset) { // Subpage must be figure, floater or subpage paraclient Invariant.Assert(subpage is SubpageParaClient || subpage is FigureParaClient || subpage is FloaterParaClient); _subpage = subpage; _columnHandle = trackDesc.pfstrack; _layoutBox = new Rect( TextDpi.FromTextDpi(trackDesc.fsrc.u), TextDpi.FromTextDpi(trackDesc.fsrc.v), TextDpi.FromTextDpi(trackDesc.fsrc.du), TextDpi.FromTextDpi(trackDesc.fsrc.dv)); _layoutBox.X += contentOffset.X; _layoutBox.Y += contentOffset.Y; _columnOffset = new Vector(TextDpi.FromTextDpi(trackDesc.fsrc.u), TextDpi.FromTextDpi(trackDesc.fsrc.v)); }
// ------------------------------------------------------------------ // // 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 }
internal void Arrange(IntPtr pfspara, PTS.FSRECT rcPara, int dvrTopSpace, uint fswdirParent) { // Make sure that paragraph handle (PFSPARA) is set. It is required to query paragraph content. Debug.Assert(_paraHandle.Value == IntPtr.Zero || _paraHandle.Value == pfspara); _paraHandle.Value = pfspara; // Set paragraph rectangle (relative to the page) _rect = rcPara; // Cache dvrTopSpace // Note: currently used only by tight geometry bound calculation code _dvrTopSpace = dvrTopSpace; // Current page context (used for mirroring and offsets) _pageContext = Paragraph.StructuralCache.CurrentArrangeContext.PageContext; // Cache flow directions _flowDirectionParent = PTS.FswdirToFlowDirection(fswdirParent); _flowDirection = (FlowDirection)Paragraph.Element.GetValue(FrameworkElement.FlowDirectionProperty); // Do paragraph specifc arrange OnArrange(); }
internal override void UpdateViewport(ref PTS.FSRECT viewport) { Debug.Assert( TableParagraph.Table != null && CalculatedColumns != null ); PTS.FSTABLEROWDESCRIPTION[] arrayTableRowDesc; PTS.FSKUPDATE fskupdTable; PTS.FSRECT rectTable; if (QueryTableDetails(out arrayTableRowDesc, out fskupdTable, out rectTable)) { for (int iR = 0; iR < arrayTableRowDesc.Length; ++iR) { PTS.FSKUPDATE[] arrayUpdate; IntPtr[] arrayFsCell; PTS.FSTABLEKCELLMERGE[] arrayTableCellMerge; QueryRowDetails( arrayTableRowDesc[iR].pfstablerow, out arrayFsCell, out arrayUpdate, out arrayTableCellMerge); for (int iC = 0; iC < arrayFsCell.Length; ++iC) { if (arrayFsCell[iC] == IntPtr.Zero) { // paginated case - cell may be null continue; } CellParaClient cellParaClient = (CellParaClient)(PtsContext.HandleToObject(arrayFsCell[iC])); cellParaClient.UpdateViewport(ref viewport); } } } }
internal override void ValidateVisual(PTS.FSKUPDATE fskupdInherited) { Invariant.Assert( fskupdInherited != PTS.FSKUPDATE.fskupdInherited ); Invariant.Assert( TableParagraph.Table != null && CalculatedColumns != null ); PTS.FSTABLEROWDESCRIPTION[] arrayTableRowDesc; PTS.FSKUPDATE fskupdTable; PTS.FSRECT rect; Table table = TableParagraph.Table; Visual.Clip = new RectangleGeometry(_columnRect.FromTextDpi()); if (!QueryTableDetails(out arrayTableRowDesc, out fskupdTable, out rect)) { // table has no rows thus no cell to validate _visual.Children.Clear(); return; } MbpInfo mbpInfo = MbpInfo.FromElement(TableParagraph.Element); if (ThisFlowDirection != PageFlowDirection) { mbpInfo.MirrorBP(); } if (fskupdTable == PTS.FSKUPDATE.fskupdInherited) { fskupdTable = fskupdInherited; } if (fskupdTable == PTS.FSKUPDATE.fskupdNoChange) { // no need to arrange because nothing changed return; } if (fskupdTable == PTS.FSKUPDATE.fskupdShifted) { fskupdTable = PTS.FSKUPDATE.fskupdNew; } VisualCollection rowVisualsCollection = _visual.Children; if (fskupdTable == PTS.FSKUPDATE.fskupdNew) { rowVisualsCollection.Clear(); } // Draw border and background info. Brush backgroundBrush = (Brush)Paragraph.Element.GetValue(TextElement.BackgroundProperty); using (DrawingContext dc = _visual.RenderOpen()) { Rect tableContentRect = GetTableContentRect(mbpInfo).FromTextDpi(); _visual.DrawBackgroundAndBorderIntoContext(dc, backgroundBrush, mbpInfo.BorderBrush, mbpInfo.Border, _rect.FromTextDpi(), IsFirstChunk, IsLastChunk); DrawColumnBackgrounds(dc, tableContentRect); DrawRowGroupBackgrounds(dc, arrayTableRowDesc, tableContentRect, mbpInfo); DrawRowBackgrounds(dc, arrayTableRowDesc, tableContentRect, mbpInfo); } TableRow rowPrevious = null; for (int iR = 0; iR < arrayTableRowDesc.Length; ++iR) { PTS.FSKUPDATE fskupdRow; RowParagraph rowParagraph; TableRow row; fskupdRow = (arrayTableRowDesc[iR].fsupdinf.fskupd != PTS.FSKUPDATE.fskupdInherited) ? arrayTableRowDesc[iR].fsupdinf.fskupd : fskupdTable; rowParagraph = (RowParagraph)(PtsContext.HandleToObject(arrayTableRowDesc[iR].fsnmRow)); row = rowParagraph.Row; // // STEP 1 SYNCHRONIZATION // --------------------------------------------------------- // synchronize rowVisualCollection. // for newly created rows visual is inserted; // otherwise for removed rows (if any) corresponding visuals are removed // if (fskupdRow == PTS.FSKUPDATE.fskupdNew) { RowVisual rowVisual = new RowVisual(row); rowVisualsCollection.Insert(iR, rowVisual); } else { SynchronizeRowVisualsCollection(rowVisualsCollection, iR, row); } Invariant.Assert(((RowVisual)rowVisualsCollection[iR]).Row == row); // // STEP 2 CELL VISUALS VALIDATION // --------------------------------------------------------- // for new or changed rows go inside and validate cells // if ( fskupdRow == PTS.FSKUPDATE.fskupdNew || fskupdRow == PTS.FSKUPDATE.fskupdChangeInside ) { // paginated case - if first row of a given rowgroup for this para client has foreign cells, they need to // be rendered regardless of merge state if(rowParagraph.Row.HasForeignCells && (rowPrevious == null || rowPrevious.RowGroup != row.RowGroup)) { ValidateRowVisualComplex( (RowVisual)(rowVisualsCollection[iR]), arrayTableRowDesc[iR].pfstablerow, CalculatedColumns.Length, fskupdRow, CalculatedColumns); } else { ValidateRowVisualSimple( (RowVisual)(rowVisualsCollection[iR]), arrayTableRowDesc[iR].pfstablerow, fskupdRow, CalculatedColumns); } } rowPrevious = row; } // // STEP 4 if (rowVisualsCollection.Count > arrayTableRowDesc.Length) { rowVisualsCollection.RemoveRange( arrayTableRowDesc.Length, rowVisualsCollection.Count - arrayTableRowDesc.Length); } }
/// <summary> /// Calculates actual row height, subtracting what was previously reported as dvrBeforeTopRow and dvrAfterBottomRow /// </summary> private double GetActualRowHeight(PTS.FSTABLEROWDESCRIPTION[] arrayTableRowDesc, int rowIndex, MbpInfo mbpInfo) { int dvAdjustment = 0; if(IsFirstChunk && rowIndex == 0) { dvAdjustment = -mbpInfo.BPTop; } if(IsLastChunk && rowIndex == arrayTableRowDesc.Length - 1) { dvAdjustment = -mbpInfo.BPBottom; } return TextDpi.FromTextDpi(arrayTableRowDesc[rowIndex].u.dvrRow + dvAdjustment); }
private void ValidateRowVisualSimple( RowVisual rowVisual, IntPtr pfstablerow, PTS.FSKUPDATE fskupdRow, CalculatedColumn[] calculatedColumns) { PTS.FSKUPDATE[] arrayUpdate; IntPtr[] arrayFsCell; PTS.FSTABLEKCELLMERGE[] arrayTableCellMerge; VisualCollection cellVisualsCollection; int sourceIndex; QueryRowDetails( pfstablerow, out arrayFsCell, out arrayUpdate, out arrayTableCellMerge); cellVisualsCollection = rowVisual.Children; sourceIndex = 0; for (int iC = 0; iC < arrayFsCell.Length; ++iC) { CellParaClient cellParaClient; double urCellOffset; PTS.FSKUPDATE fskupdCell; if ( // paginated case - cell may be null arrayFsCell[iC] == IntPtr.Zero // exclude hanging cells || arrayTableCellMerge[iC] == PTS.FSTABLEKCELLMERGE.fskcellmergeMiddle || arrayTableCellMerge[iC] == PTS.FSTABLEKCELLMERGE.fskcellmergeLast ) { continue; } fskupdCell = (arrayUpdate[iC] != PTS.FSKUPDATE.fskupdInherited) ? arrayUpdate[iC] : fskupdRow; if (fskupdCell != PTS.FSKUPDATE.fskupdNoChange) { cellParaClient = (CellParaClient)(PtsContext.HandleToObject(arrayFsCell[iC])); urCellOffset = calculatedColumns[cellParaClient.ColumnIndex].UrOffset; cellParaClient.ValidateVisual(); if ( fskupdCell == PTS.FSKUPDATE.fskupdNew // PTS bug is a suspect here - this is a temp workaround: || VisualTreeHelper.GetParent(cellParaClient.Visual) == null ) { Visual currentParent = VisualTreeHelper.GetParent(cellParaClient.Visual) as Visual; if(currentParent != null) { ContainerVisual parent = currentParent as ContainerVisual; Invariant.Assert(parent != null, "parent should always derives from ContainerVisual"); parent.Children.Remove(cellParaClient.Visual); } cellVisualsCollection.Insert(sourceIndex, cellParaClient.Visual); } else { Debug.Assert( cellParaClient.Visual != null // If the check below fails, then PTS cheats by reporting "ChangInside" for // a cell that in fact was re-Formatted. && VisualTreeHelper.GetParent(cellParaClient.Visual) != null ); SynchronizeCellVisualsCollection(cellVisualsCollection, sourceIndex, cellParaClient.Visual); } } sourceIndex++; } if (cellVisualsCollection.Count > sourceIndex) { cellVisualsCollection.RemoveRange( sourceIndex, cellVisualsCollection.Count - sourceIndex); } #if DEBUGDEBUG for (int iC = 0, sourceIndex = 0; iC < arrayFsCell.Length; ++iC) { if ( arrayFsCell[iC] != IntPtr.Zero && arrayTableCellMerge[iC] != PTS.FSTABLEKCELLMERGE.fskcellmergeMiddle && arrayTableCellMerge[iC] != PTS.FSTABLEKCELLMERGE.fskcellmergeLast ) { CellParaClient cellParaClient = (CellParaClient)(PtsContext.HandleToObject(arrayFsCell[iC])); Debug.Assert(rowVisual.Children.IndexOf(cellParaClient.Visual) == sourceIndex); sourceIndex++; } } #endif // DEBUGDEBUG }
private unsafe bool QueryTableDetails( out PTS.FSTABLEROWDESCRIPTION[] arrayTableRowDesc, out PTS.FSKUPDATE fskupdTable, out PTS.FSRECT rect) { PTS.FSTABLEOBJDETAILS tableObjDetails; PTS.FSTABLEDETAILS tableDetails; PTS.Validate(PTS.FsQueryTableObjDetails( PtsContext.Context, _paraHandle.Value, out tableObjDetails)); Debug.Assert(TableParagraph == (TableParagraph)(PtsContext.HandleToObject(tableObjDetails.fsnmTable))); fskupdTable = tableObjDetails.fskupdTableProper; rect = tableObjDetails.fsrcTableObj; PTS.Validate(PTS.FsQueryTableObjTableProperDetails( PtsContext.Context, tableObjDetails.pfstableProper, out tableDetails)); if (tableDetails.cRows == 0) { // table has no rows (thus no content) arrayTableRowDesc = null; return (false); } arrayTableRowDesc = new PTS.FSTABLEROWDESCRIPTION[tableDetails.cRows]; fixed (PTS.FSTABLEROWDESCRIPTION * rgTableRowDesc = arrayTableRowDesc) { int cRowsActual; PTS.Validate(PTS.FsQueryTableObjRowList( PtsContext.Context, tableObjDetails.pfstableProper, tableDetails.cRows, rgTableRowDesc, out cRowsActual)); Debug.Assert(tableDetails.cRows == cRowsActual); } return (true); }
private void ArrangeSection(ref PTS.FSSECTIONDESCRIPTION sectionDesc) { // Get section details PTS.FSSECTIONDETAILS sectionDetails; PTS.Validate(PTS.FsQuerySectionDetails(PtsContext.Context, sectionDesc.pfssection, out sectionDetails)); // There are 2 types of sections: // (1) with page notes - footnotes in section treated as endnotes // (2) with column notes - footnotes in section treated as column notes if (PTS.ToBoolean(sectionDetails.fFootnotesAsPagenotes)) { // (1) with page notes - footnotes in section treated as endnotes ErrorHandler.Assert(sectionDetails.u.withpagenotes.cEndnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // Debug.Assert(sectionDetails.u.withpagenotes.cSegmentDefinedColumnSpanAreas == 0); Debug.Assert(sectionDetails.u.withpagenotes.cHeightDefinedColumnSpanAreas == 0); // cBasicColumns == 0, means that section content is empty. // In such case there is nothing to render. if (sectionDetails.u.withpagenotes.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION [] arrayColumnDesc; PtsHelper.TrackListFromSection(PtsContext, sectionDesc.pfssection, ref sectionDetails, out arrayColumnDesc); // Arrange each column 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. _section.StructuralCache.CurrentArrangeContext.PushNewPageData(_pageContextOfThisPage, arrayColumnDesc[index].fsrc, _finitePage); PtsHelper.ArrangeTrack(PtsContext, ref arrayColumnDesc[index], sectionDetails.u.withpagenotes.fswdir); _section.StructuralCache.CurrentArrangeContext.PopPageData(); } } } else { // (2) with column notes - footnotes in section treated as column notes ErrorHandler.Assert(false, ErrorHandler.NotSupportedCompositeColumns); } }
// ----------------------------------------------------------------- // 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(); }
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); } } } } }
private List<Rect> GetRectanglesInSection( ContentElement e, int start, int length, ref PTS.FSSECTIONDESCRIPTION sectionDesc) { // Get section details PTS.FSSECTIONDETAILS sectionDetails; PTS.Validate(PTS.FsQuerySectionDetails(PtsContext.Context, sectionDesc.pfssection, out sectionDetails)); // Declare ArrayList to be returned List<Rect> rectangles = new List<Rect>(); // There are 2 types of sections: // (1) with page notes - footnotes in section treated as endnotes // (2) with column notes - footnotes in section treated as column notes if (PTS.ToBoolean(sectionDetails.fFootnotesAsPagenotes)) { // (1) with page notes - footnotes in section treated as endnotes ErrorHandler.Assert(sectionDetails.u.withpagenotes.cEndnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // Debug.Assert(sectionDetails.u.withpagenotes.cSegmentDefinedColumnSpanAreas == 0); Debug.Assert(sectionDetails.u.withpagenotes.cHeightDefinedColumnSpanAreas == 0); // cBasicColumns == 0, means that section content is empty. // In such case there is nothing to hit-test. if (sectionDetails.u.withpagenotes.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSection(PtsContext, sectionDesc.pfssection, ref sectionDetails, out arrayColumnDesc); // Check each column for element or part of element - element may span multiple // columns/tracks for (int index = 0; index < arrayColumnDesc.Length; index++) { // See if any rectangles for the element are found in this track List<Rect> trackRectangles = PtsHelper.GetRectanglesInTrack(PtsContext, e, start, length, ref arrayColumnDesc[index]); // For consistency, rectangles collection is never null, only empty Invariant.Assert(trackRectangles != null); if (trackRectangles.Count != 0) { // Add rectangles found in this track to rectangles for element rectangles.AddRange(trackRectangles); } } } } else { // (2) with column notes - footnotes in section treated as column notes ErrorHandler.Assert(false, ErrorHandler.NotSupportedCompositeColumns); } return rectangles; }
internal void UpdateViewport(ref PTS.FSRECT viewport) { if (!IsEmpty) { // Get page details PTS.FSPAGEDETAILS pageDetails; PTS.Validate(PTS.FsQueryPageDetails(PtsContext.Context, _ptsPage.Value, out pageDetails)); // Arrange page content. Page content may be simple or complex - // depending of set of features used in the content of the page. // (1) simple page (contains only one track) // (2) complex page (contains header, page body (list of sections), footnotes and footer) if (PTS.ToBoolean(pageDetails.fSimple)) { // (1) simple page (contains only one track) PtsHelper.UpdateViewportTrack(PtsContext, ref pageDetails.u.simple.trackdescr, ref viewport); } else { // (2) complex page (contains header, page body (list of sections), footnotes and footer) // NOTE: only page body (list of sections is currently supported). //ErrorHandler.Assert(!PTS.ToBoolean(pageDetails.u.complex.fTopBottomHeaderFooter), ErrorHandler.NotSupportedHeadersFooters); //ErrorHandler.Assert(!PTS.ToBoolean(pageDetails.u.complex.fJustified), ErrorHandler.NotSupportedVerticalJustify); ErrorHandler.Assert(pageDetails.u.complex.cFootnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // cSections == 0, means that page body content is empty. if (pageDetails.u.complex.cSections != 0) { // Retrieve description for each section. PTS.FSSECTIONDESCRIPTION[] arraySectionDesc; PtsHelper.SectionListFromPage(PtsContext, _ptsPage.Value, ref pageDetails, out arraySectionDesc); // Arrange each section for (int index = 0; index < arraySectionDesc.Length; index++) { UpdateViewportSection(ref arraySectionDesc[index], ref viewport); } } } } }
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; }
private unsafe void UpdateChunkInfo(PTS.FSTABLEROWDESCRIPTION[] arrayTableRowDesc) { PTS.FSTABLEROWDETAILS tableRowDetails; RowParagraph rowParagraph = (RowParagraph)(PtsContext.HandleToObject(arrayTableRowDesc[0].fsnmRow)); TableRow row = rowParagraph.Row; PTS.Validate(PTS.FsQueryTableObjRowDetails( PtsContext.Context, arrayTableRowDesc[0].pfstablerow, out tableRowDetails)); _isFirstChunk = (tableRowDetails.fskboundaryAbove == PTS.FSKTABLEROWBOUNDARY.fsktablerowboundaryOuter) && (row.Index == 0) && Table.IsFirstNonEmptyRowGroup(row.RowGroup.Index); row = ((RowParagraph)(PtsContext.HandleToObject(arrayTableRowDesc[arrayTableRowDesc.Length - 1].fsnmRow))).Row; PTS.Validate(PTS.FsQueryTableObjRowDetails( PtsContext.Context, arrayTableRowDesc[arrayTableRowDesc.Length - 1].pfstablerow, out tableRowDetails)); _isLastChunk = (tableRowDetails.fskboundaryBelow == PTS.FSKTABLEROWBOUNDARY.fsktablerowboundaryOuter) && (row.Index == row.RowGroup.Rows.Count - 1) && Table.IsLastNonEmptyRowGroup(row.RowGroup.Index); }
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); }
private unsafe void QueryRowDetails( IntPtr pfstablerow, out IntPtr[] arrayFsCell, out PTS.FSKUPDATE[] arrayUpdate, out PTS.FSTABLEKCELLMERGE[] arrayTableCellMerge) { PTS.FSTABLEROWDETAILS tableRowDetails; PTS.Validate(PTS.FsQueryTableObjRowDetails( PtsContext.Context, pfstablerow, out tableRowDetails)); arrayUpdate = new PTS.FSKUPDATE[tableRowDetails.cCells]; arrayFsCell = new IntPtr[tableRowDetails.cCells]; arrayTableCellMerge = new PTS.FSTABLEKCELLMERGE[tableRowDetails.cCells]; if (tableRowDetails.cCells > 0) { fixed (PTS.FSKUPDATE * rgUpdate = arrayUpdate) { fixed (IntPtr * rgFsCell = arrayFsCell) { fixed (PTS.FSTABLEKCELLMERGE * rgTableCellMerge = arrayTableCellMerge) { int cCellsActual; PTS.Validate(PTS.FsQueryTableObjCellList( PtsContext.Context, pfstablerow, tableRowDetails.cCells, rgUpdate, rgFsCell, rgTableCellMerge, out cCellsActual)); Debug.Assert(tableRowDetails.cCells == cCellsActual); } } } } }
// ------------------------------------------------------------------ // 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 void ValidateRowVisualComplex( RowVisual rowVisual, IntPtr pfstablerow, int tableColumnCount, PTS.FSKUPDATE fskupdRow, CalculatedColumn[] calculatedColumns) { PTS.FSKUPDATE[] arrayUpdate; IntPtr[] arrayFsCell; PTS.FSTABLEKCELLMERGE[] arrayTableCellMerge; CellParaClientEntry[] arrayCellParaClients; VisualCollection cellVisualsCollection; int sourceIndex; QueryRowDetails( pfstablerow, out arrayFsCell, out arrayUpdate, out arrayTableCellMerge); // arrayFsCell lists cells in order different from one we want to maintain in visual collection. // before going to update visual collection it is necessary to reorder ascending by cell's column index. // knowing the following facts: // * total number of columns the row holds (including row spanned cells from previous rows) less or equal to tableColumnCount; // * total number of cells (including row spanned cells from previous rows) is less or equal to tableColumnCount; // * cells do not overlap - no two cells have the same column index; // * cells' column indices fall into the range [0, tableColumnCount - 1]; // it is possible to write custom and optimized sorting routine: // * iterate through arrayFsCell; // * for each item record its CellParaClient value into arrayCellParaClients[CellParaClient.ColumnIndex]; // once complete, arrayCellParaClients will contain CellParaClients in correct order. some entries however will be null // due to potential column spanning of cells. arrayCellParaClients = new CellParaClientEntry[tableColumnCount]; for (int iC = 0; iC < arrayFsCell.Length; ++iC) { CellParaClient cellParaClient; PTS.FSKUPDATE fskupdCell; int columnIndex; if (arrayFsCell[iC] == IntPtr.Zero) { // paginated case - cell may be null continue; } fskupdCell = (arrayUpdate[iC] != PTS.FSKUPDATE.fskupdInherited) ? arrayUpdate[iC] : fskupdRow; cellParaClient = (CellParaClient)(PtsContext.HandleToObject(arrayFsCell[iC])); columnIndex = cellParaClient.ColumnIndex; arrayCellParaClients[columnIndex].cellParaClient = cellParaClient; arrayCellParaClients[columnIndex].fskupdCell = fskupdCell; } cellVisualsCollection = rowVisual.Children; sourceIndex = 0; for (int columnIndex = 0; columnIndex < arrayCellParaClients.Length; ++columnIndex) { CellParaClient cellParaClient; double urCellOffset; PTS.FSKUPDATE fskupdCell; cellParaClient = arrayCellParaClients[columnIndex].cellParaClient; if (cellParaClient == null) { // paginated case - cell may be null continue; } fskupdCell = arrayCellParaClients[columnIndex].fskupdCell; if (fskupdCell != PTS.FSKUPDATE.fskupdNoChange) { urCellOffset = calculatedColumns[columnIndex].UrOffset; cellParaClient.ValidateVisual(); if (fskupdCell == PTS.FSKUPDATE.fskupdNew) { cellVisualsCollection.Insert(sourceIndex, cellParaClient.Visual); } else { Debug.Assert( cellParaClient.Visual != null // If the check below fails, then PTS cheats by reporting "ChangInside" for // a cell that in fact was re-Formatted. && VisualTreeHelper.GetParent(cellParaClient.Visual) != null ); SynchronizeCellVisualsCollection(cellVisualsCollection, sourceIndex, cellParaClient.Visual); } } sourceIndex++; } if (cellVisualsCollection.Count > sourceIndex) { cellVisualsCollection.RemoveRange( sourceIndex, cellVisualsCollection.Count - sourceIndex); } #if DEBUGDEBUG for (int columnIndex = 0, sourceIndex = 0; columnIndex < arrayCellParaClients.Length; ++columnIndex) { CellParaClient cellParaClient = arrayCellParaClients[columnIndex].cellParaClient; if (cellParaClient != null) { Debug.Assert(rowVisual.Children.IndexOf(cellParaClient.Visual) == sourceIndex); sourceIndex++; } } #endif // DEBUGDEBUG }
private void UpdateViewportSection(ref PTS.FSSECTIONDESCRIPTION sectionDesc, ref PTS.FSRECT viewport) { // Get section details PTS.FSSECTIONDETAILS sectionDetails; PTS.Validate(PTS.FsQuerySectionDetails(PtsContext.Context, sectionDesc.pfssection, out sectionDetails)); // There are 2 types of sections: // (1) with page notes - footnotes in section treated as endnotes // (2) with column notes - footnotes in section treated as column notes if (PTS.ToBoolean(sectionDetails.fFootnotesAsPagenotes)) { // (1) with page notes - footnotes in section treated as endnotes ErrorHandler.Assert(sectionDetails.u.withpagenotes.cEndnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // Debug.Assert(sectionDetails.u.withpagenotes.cSegmentDefinedColumnSpanAreas == 0); Debug.Assert(sectionDetails.u.withpagenotes.cHeightDefinedColumnSpanAreas == 0); // cBasicColumns == 0, means that section content is empty. // In such case there is nothing to render. if (sectionDetails.u.withpagenotes.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION [] arrayColumnDesc; PtsHelper.TrackListFromSection(PtsContext, sectionDesc.pfssection, ref sectionDetails, out arrayColumnDesc); // Arrange each column for (int index = 0; index < arrayColumnDesc.Length; index++) { PtsHelper.UpdateViewportTrack(PtsContext, ref arrayColumnDesc[index], ref viewport); } } } else { // (2) with column notes - footnotes in section treated as column notes ErrorHandler.Assert(false, ErrorHandler.NotSupportedCompositeColumns); } }
private void DrawRowGroupBackgrounds(DrawingContext dc, PTS.FSTABLEROWDESCRIPTION[] arrayTableRowDesc, Rect tableContentRect, MbpInfo mbpInfo) { double rowGroupTop = tableContentRect.Y; double rowGroupHeight = 0; Rect rowRect = tableContentRect; Brush rowGroupBackgroundBrush; if(arrayTableRowDesc.Length > 0) { TableRow row = ((RowParagraph)(PtsContext.HandleToObject(arrayTableRowDesc[0].fsnmRow))).Row; TableRowGroup tableRowGroup = row.RowGroup; for (int iR = 0; iR < arrayTableRowDesc.Length; ++iR) { row = ((RowParagraph)(PtsContext.HandleToObject(arrayTableRowDesc[iR].fsnmRow))).Row; if (tableRowGroup != row.RowGroup) { rowGroupBackgroundBrush = (Brush)tableRowGroup.GetValue(TextElement.BackgroundProperty); if (rowGroupBackgroundBrush != null) { rowRect.Y = rowGroupTop; rowRect.Height = rowGroupHeight; dc.DrawRectangle(rowGroupBackgroundBrush, null, rowRect); } rowGroupTop += rowGroupHeight; tableRowGroup = row.RowGroup; rowGroupHeight = GetActualRowHeight(arrayTableRowDesc, iR, mbpInfo); } else { rowGroupHeight += GetActualRowHeight(arrayTableRowDesc, iR, mbpInfo); } } rowGroupBackgroundBrush = (Brush)tableRowGroup.GetValue(TextElement.BackgroundProperty); if (rowGroupBackgroundBrush != null) { rowRect.Y = rowGroupTop; rowRect.Height = rowGroupHeight; dc.DrawRectangle(rowGroupBackgroundBrush, null, rowRect); } } }
private void UpdateSectionVisuals( SectionVisual visual, PTS.FSKUPDATE fskupdInherited, ref PTS.FSSECTIONDESCRIPTION sectionDesc) { PTS.FSKUPDATE fskupd = sectionDesc.fsupdinf.fskupd; if (fskupd == PTS.FSKUPDATE.fskupdInherited) { fskupd = fskupdInherited; } ErrorHandler.Assert(fskupd != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); // If there is no change, visual information is valid if (fskupd == PTS.FSKUPDATE.fskupdNoChange) { return; } bool emptySection; // Get section details PTS.FSSECTIONDETAILS sectionDetails; PTS.Validate(PTS.FsQuerySectionDetails(PtsContext.Context, sectionDesc.pfssection, out sectionDetails)); // There are 2 types of sections: // (1) with page notes - footnotes in section treated as endnotes // (2) with column notes - footnotes in section treated as column notes if (PTS.ToBoolean(sectionDetails.fFootnotesAsPagenotes)) { // (1) with page notes - footnotes in section treated as endnotes ErrorHandler.Assert(sectionDetails.u.withpagenotes.cEndnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // Debug.Assert(sectionDetails.u.withpagenotes.cSegmentDefinedColumnSpanAreas == 0); Debug.Assert(sectionDetails.u.withpagenotes.cHeightDefinedColumnSpanAreas == 0); // cBasicColumns == 0, means that section content is empty. emptySection = (sectionDetails.u.withpagenotes.cBasicColumns == 0); if (!emptySection) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION [] arrayColumnDesc; PtsHelper.TrackListFromSection(PtsContext, sectionDesc.pfssection, ref sectionDetails, out arrayColumnDesc); emptySection = (arrayColumnDesc.Length == 0); if (!emptySection) { // Draw column rules. ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(_section.Element); visual.DrawColumnRules(ref arrayColumnDesc, TextDpi.FromTextDpi(sectionDesc.fsrc.v), TextDpi.FromTextDpi(sectionDesc.fsrc.dv), columnProperties); VisualCollection visualChildren = visual.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, fskupd, ref arrayColumnDesc[index]); } } } } else { // (2) with column notes - footnotes in section treated as column notes ErrorHandler.Assert(false, ErrorHandler.NotSupportedCompositeColumns); emptySection = true; } if (emptySection) { // There is no content, remove all existing visuals. visual.Children.Clear(); } }
private void DrawRowBackgrounds(DrawingContext dc, PTS.FSTABLEROWDESCRIPTION[] arrayTableRowDesc, Rect tableContentRect, MbpInfo mbpInfo) { double rowTop = tableContentRect.Y; Rect rowRect = tableContentRect; for (int iR = 0; iR < arrayTableRowDesc.Length; ++iR) { TableRow row = ((RowParagraph)(PtsContext.HandleToObject(arrayTableRowDesc[iR].fsnmRow))).Row; Brush rowBackgroundBrush = (Brush)row.GetValue(TextElement.BackgroundProperty); rowRect.Y = rowTop; rowRect.Height = GetActualRowHeight(arrayTableRowDesc, iR, mbpInfo); if (rowBackgroundBrush != null) { dc.DrawRectangle(rowBackgroundBrush, null, rowRect); } rowTop += rowRect.Height; // Adjust for top of next row } }
private IInputElement InputHitTestPage(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) { // Get page details PTS.FSPAGEDETAILS pageDetails; PTS.Validate(PTS.FsQueryPageDetails(PtsContext.Context, _ptsPage.Value, out pageDetails)); // Hittest page content. Page content may be simple or complex - // depending of set of features used in the content of the page. // (1) simple page (contains only one track) // (2) complex page (contains header, page body (list of sections), footnotes and footer) if (PTS.ToBoolean(pageDetails.fSimple)) { // (1) simple page (contains only one track) if (pageDetails.u.simple.trackdescr.fsrc.Contains(pt)) { ie = PtsHelper.InputHitTestTrack(PtsContext, pt, ref pageDetails.u.simple.trackdescr); } } else { // (2) complex page (contains header, page body (list of sections), footnotes and footer) // NOTE: only page body (list of sections is currently supported). //ErrorHandler.Assert(!PTS.ToBoolean(pageDetails.u.complex.fTopBottomHeaderFooter), ErrorHandler.NotSupportedHeadersFooters); //ErrorHandler.Assert(!PTS.ToBoolean(pageDetails.u.complex.fJustified), ErrorHandler.NotSupportedVerticalJustify); ErrorHandler.Assert(pageDetails.u.complex.cFootnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // cSections == 0, means that page body content is empty. // In such case there is nothing to render. if (pageDetails.u.complex.cSections != 0) { // Retrieve description for each section. PTS.FSSECTIONDESCRIPTION [] arraySectionDesc; PtsHelper.SectionListFromPage(PtsContext, _ptsPage.Value, ref pageDetails, out arraySectionDesc); // Hittest each section for (int index = 0; index < arraySectionDesc.Length && ie == null; index++) { if (arraySectionDesc[index].fsrc.Contains(pt)) { ie = InputHitTestSection(pt, ref arraySectionDesc[index]); } } } } } return ie; }
internal override IInputElement InputHitTest(PTS.FSPOINT pt) { Debug.Assert( TableParagraph.Table != null && CalculatedColumns != null ); IInputElement element = null; PTS.FSTABLEROWDESCRIPTION[] arrayTableRowDesc; PTS.FSKUPDATE fskupdTable; PTS.FSRECT rectTable; if (QueryTableDetails(out arrayTableRowDesc, out fskupdTable, out rectTable)) { // Start vrRowTop from 'true' v of table int vrRowTop = GetTableOffsetFirstRowTop() + rectTable.v; for (int iR = 0; iR < arrayTableRowDesc.Length; ++iR) { if (pt.v >= vrRowTop && pt.v <= (vrRowTop + arrayTableRowDesc[iR].u.dvrRow)) { PTS.FSKUPDATE[] arrayUpdate; IntPtr[] arrayFsCell; PTS.FSTABLEKCELLMERGE[] arrayTableCellMerge; QueryRowDetails( arrayTableRowDesc[iR].pfstablerow, out arrayFsCell, out arrayUpdate, out arrayTableCellMerge); for (int iC = 0; iC < arrayFsCell.Length; ++iC) { if (arrayFsCell[iC] == IntPtr.Zero) { // paginated case - cell may be null continue; } CellParaClient cellParaClient = (CellParaClient)(PtsContext.HandleToObject(arrayFsCell[iC])); PTS.FSRECT rect = cellParaClient.Rect; if (cellParaClient.Rect.Contains(pt)) { element = cellParaClient.InputHitTest(pt); break; } } break; } vrRowTop += arrayTableRowDesc[iR].u.dvrRow; } } if(element == null && _rect.Contains(pt)) { element = TableParagraph.Table; } return (element); }
private IInputElement InputHitTestSection( PTS.FSPOINT pt, ref PTS.FSSECTIONDESCRIPTION sectionDesc) { IInputElement ie = null; // Get section details PTS.FSSECTIONDETAILS sectionDetails; PTS.Validate(PTS.FsQuerySectionDetails(PtsContext.Context, sectionDesc.pfssection, out sectionDetails)); // There are 2 types of sections: // (1) with page notes - footnotes in section treated as endnotes // (2) with column notes - footnotes in section treated as column notes if (PTS.ToBoolean(sectionDetails.fFootnotesAsPagenotes)) { // (1) with page notes - footnotes in section treated as endnotes ErrorHandler.Assert(sectionDetails.u.withpagenotes.cEndnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // Debug.Assert(sectionDetails.u.withpagenotes.cSegmentDefinedColumnSpanAreas == 0); Debug.Assert(sectionDetails.u.withpagenotes.cHeightDefinedColumnSpanAreas == 0); // cBasicColumns == 0, means that section content is empty. // In such case there is nothing to hit-test. if (sectionDetails.u.withpagenotes.cBasicColumns != 0) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION [] arrayColumnDesc; PtsHelper.TrackListFromSection(PtsContext, sectionDesc.pfssection, ref sectionDetails, out arrayColumnDesc); // Hittest each column for (int index = 0; index < arrayColumnDesc.Length; index++) { if (arrayColumnDesc[index].fsrc.Contains(pt)) { ie = PtsHelper.InputHitTestTrack(PtsContext, pt, ref arrayColumnDesc[index]); break; } } } } else { // (2) with column notes - footnotes in section treated as column notes ErrorHandler.Assert(false, ErrorHandler.NotSupportedCompositeColumns); } return ie; }