public void GetLastElement_OneElement() { IVwLayoutStream stream = VwLayoutStreamClass.Create(); using (DummyDivisionMgr division = new DummyDivisionMgr(stream, false)) { using (DummyPublication dummyPub = new DummyPublication(null, division, DateTime.Now)) { using (DummyPage page = new DummyPage(dummyPub)) { PageElement element = new PageElement(division, stream, false, new Rectangle(720, 1440, (int)(6.5 * 720), (int)(9 * 1440)), 0, true, 1, 1, 0, 9 * 1440, 0, false); page.PageElements.Add(element); int xd; PageElement lastElement = page.CallGetLastElement(division, out xd); Assert.AreEqual(element.LocationOnPage.Right, xd); Debug.WriteLine("GetLastElement_OneElement xd: " + xd); Assert.AreEqual(element, lastElement); } } } }
public void GetLastElement_TwoElementsRtoLStandard() { IVwLayoutStream stream = VwLayoutStreamClass.Create(); using (DummyDivisionMgr division = new DummyDivisionMgr(stream, true)) using (DummyPublication dummyPub = new DummyPublication(null, division, DateTime.Now)) using (DummyPage page = new DummyPage(dummyPub)) { PageElement leftColumnElement = new PageElement(division, stream, false, new Rectangle(0, 1440, (int)(3 * 720), (int)(5 * 1440)), 0, true, 1, 2, 0, 5 * 1440, 0, true); PageElement rightColumnElement = new PageElement(division, stream, false, new Rectangle(3 * 720 + 360, 1440, (int)(3 * 720), (int)(9 * 1440)), 0, true, 2, 2, 0, 9 * 1440, 0, true); page.PageElements.Add(leftColumnElement); page.PageElements.Add(rightColumnElement); int xd; PageElement lastElement = page.CallGetLastElement(division, out xd); Debug.WriteLine("GetLastElement_TwoElementsRtoLStandard xd: " + xd); Assert.AreEqual(leftColumnElement, lastElement, "The left-most column should be the last element in a right-to-left writing system"); Assert.AreEqual(0, xd); } }
public void PagesWithFootnotes() { CheckDisposed(); // Need VC with footnotes for this test, so we recreate one ConfigurePublication(true); // Add a footnote in the last book, last section, last paragraph IScripture scr = Cache.LangProject.TranslatedScriptureOA; ScrBook deut = (ScrBook)scr.ScriptureBooksOS[scr.ScriptureBooksOS.Count - 1]; IScrSection section = (IScrSection)deut.SectionsOS[deut.SectionsOS.Count - 1]; StFootnote footnote = m_scrInMemoryCache.AddFootnote(deut, (StTxtPara)section.ContentOA.ParagraphsOS[section.ContentOA.ParagraphsOS.Count - 1], 10); StTxtPara para = m_scrInMemoryCache.AddParaToMockedText(footnote.Hvo, ScrStyleNames.NormalFootnoteParagraph); m_scrInMemoryCache.AddRunToMockedPara(para, "This is the footnote", 0); // Set up the publication m_pub.PageHeight = 72000 * 11; // 11 inches m_pub.PageWidth = (int)(72000 * 8.5); // 8.5 inches m_division.TopMargin = 36000; // Half inch m_division.BottomMargin = 18000; // Quarter inch m_division.InsideMargin = 9000; // 1/8 inch m_division.OutsideMargin = 4500; // 1/16 inch DummyMainLazyViewVc vc = m_division.MainVc as DummyMainLazyViewVc; vc.m_estBookHeight = 2000; vc.m_estSectionHeight = 2000; m_pub.Width = 3 * 96; // represents a window that is 3" wide at 96 DPI m_pub.CreatePages(); Assert.AreEqual(14, m_pub.Pages.Count, "Our estimate of book should try to fit all of Scripture on 14 pages."); // expand the last page m_pub.ScrollPosition = new Point(-m_pub.ScrollPosition.X, m_pub.AutoScrollMinSize.Height - 10); m_pub.PrepareToDrawPages(0, 100); // now expand all of the pages m_pub.ScrollPosition = new Point(0, 0); m_pub.PrepareToDrawPages(0, m_pub.AutoScrollMinSize.Height * 2); Page lastPage = (Page)m_pub.Pages[m_pub.Pages.Count - 1]; PageElement peMain = lastPage.GetFirstElementForStream(m_division.MainLayoutStream); Assert.IsTrue(m_division.m_testPageFootnoteInfo.ContainsKey(lastPage.Handle)); Assert.AreEqual(2, lastPage.PageElements.Count, "Main and footnote streams should be laid out on page " + lastPage.PageNumber); int cFoonotesOnThisPage = (int)m_division.m_testPageFootnoteInfo[lastPage.Handle]; Assert.Greater(cFoonotesOnThisPage, 0, "Should display at least one footnote on last page"); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Checks that the page elements don't overlap. /// </summary> /// <param name="page">The page.</param> /// ------------------------------------------------------------------------------------ private static void CheckThatPageElementsDontOverlap(Page page) { for (int i = 0; i < page.PageElements.Count; i++) { PageElement pe = page.PageElements[i]; for (int j = i + 1; j < page.PageElements.Count; j++) { PageElement otherPe = page.PageElements[j]; Assert.IsFalse(pe.LocationOnPage.IntersectsWith(otherPe.LocationOnPage)); } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adds a page element, representing a layout stream in a particular location on the /// page. /// </summary> /// <param name="division">The division</param> /// <param name="stream">The stream (rootbox) which supplies data for this element</param> /// <param name="fPageElementOwnsStream"><c>true</c> if this element is responsible for /// closing its stream when it is destoyed</param> /// <param name="locationOnPage">Location where this stream is laid out, in printer /// pixels, relative to the top left of the physical page</param> /// <param name="dypOffsetToTopOfDataOnPage">Offset in stream to top of data being shown /// on this page, in printer pixels</param> /// <param name="fMainStream"><c>true</c> if this element is for a "main" stream; /// <c>false</c> if it's for a subordinate stream or a Header/Footer stream</param> /// <param name="currentColumn">The current column (1-based).</param> /// <param name="totalColumns">The total columns in the specified stream.</param> /// <param name="columnGap">The gap between the columns.</param> /// <param name="columnHeight">The height of the current column.</param> /// <param name="dypOverlapWithPreviousElement"></param> /// <param name="isRightToLeft">if set to <c>true</c> the stream is right-to-left. /// Otherwise, it is left-to-right.</param> /// <param name="fReducesFreeSpaceFromTop">Flag indicating whether additoin of this /// element reduces the free space from top or bottom.</param> /// ------------------------------------------------------------------------------------ internal protected void AddPageElement(DivisionLayoutMgr division, IVwLayoutStream stream, bool fPageElementOwnsStream, Rectangle locationOnPage, int dypOffsetToTopOfDataOnPage, bool fMainStream, int currentColumn, int totalColumns, int columnGap, int columnHeight, int dypOverlapWithPreviousElement, bool isRightToLeft, bool fReducesFreeSpaceFromTop) { CheckDisposed(); PageElement newElement = new PageElement(division, stream, fPageElementOwnsStream, locationOnPage, dypOffsetToTopOfDataOnPage, fMainStream, currentColumn, totalColumns, columnGap, columnHeight, dypOverlapWithPreviousElement, isRightToLeft); InsertPageElement(newElement); AdjustFreeSpace(locationOnPage, fReducesFreeSpaceFromTop, newElement); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determines the pe is more toward the trailing edge than the current lastMainElement. /// </summary> /// <param name="pe">The page element.</param> /// <param name="lastMainElement">The current last main element on this page.</param> /// <param name="fIsRightToLeft">if set to <c>true</c> if the main stream is /// right-to-left, or <c>false</c> for left-to-right.</param> /// <returns><c>true</c> if the pe is more toward the trailing edge of the page than /// the current lastMainElement; <c>false</c> otherwise</returns> /// ------------------------------------------------------------------------------------ private bool TowardsTrailingEdge(PageElement pe, PageElement lastMainElement, bool fIsRightToLeft) { if (fIsRightToLeft) return pe.LocationOnPage.Left < lastMainElement.LocationOnPage.Left; return pe.LocationOnPage.Right > lastMainElement.LocationOnPage.Right; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets the clip rectangle for the element depending on the whether the stream is /// left-to-right or right-to-left, and whether the next column has contents. /// </summary> /// <remarks>The clip rectangle for the element contains more then the element bounds /// so that we erase the surrounding background.</remarks> /// <param name="element">The element</param> /// <param name="rectElement">The rectangle element (in screen pixels).</param> /// <returns>rectangle representing the bounds for the page element</returns> /// ------------------------------------------------------------------------------------ private Rectangle GetElementClipBounds(PageElement element, Rectangle rectElement) { Rectangle rectClipElt; // ENHANCE (EberhardB/TimS): the current algorithm here doesn't work if we have // more then two columns and the gap between the columns is less then the left and // right margins. // Note: we can do a slightly easier calculation then when we calculate // the element bounds since we want to cover the entire page width with the columns. int columnWidth = PubControl.Width / element.m_totalColumns; // width of column, including column gap // For a left-to-right writing system, layout columns from left side of page. // Otherwise, in a right-to-left writing system, layout columns from the right. int xLoc = !element.m_fInRightToLeftStream ? columnWidth * (element.m_column - 1) : (columnWidth * element.m_totalColumns) - (element.m_column * columnWidth); if (NextColumnIsEmpty(element)) { // The next column does not have a page element, so we need to expand the // element bounds across the remaining columns. int numberColumnsToBound = element.m_totalColumns - element.m_column + 1; Debug.Assert(numberColumnsToBound > 1); // if we are in a right-to-left writing system then we need to adjust the X location // of the rectangle to be the position for the last (left-most) column. if (element.m_fInRightToLeftStream) xLoc = xLoc - numberColumnsToBound * columnWidth; rectClipElt = new Rectangle(rectElement.X + xLoc, rectElement.Y, numberColumnsToBound * columnWidth, rectElement.Height); } else { // The next column is not empty. Set up the clip rectangle for this column only. //rectClipElt = new Rectangle(xLoc, rectElement.Y, columnWidth - element.m_columnGap, // rectElement.Height); rectClipElt = new Rectangle(xLoc, rectElement.Y, columnWidth, rectElement.Height + 1); } return rectClipElt; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determines if the next column from the specified column has a page element. /// </summary> /// <param name="element">The page element.</param> /// <returns> /// True if a page element was found in the next page column; false otherwise /// </returns> /// ------------------------------------------------------------------------------------ private bool NextColumnIsEmpty(PageElement element) { if (element.m_column + 1 > element.m_totalColumns) return false; for (int i = 0; i < m_pageElements.Count; i++) { if (m_pageElements[i] == element && i < m_pageElements.Count - 1) return m_pageElements[i + 1].m_totalColumns != element.m_totalColumns; } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adds the separator for dependent stream. /// </summary> /// <param name="gr">The graphics.</param> /// <param name="element">The page element.</param> /// <param name="rectElement">The bounding rectangle of the page element.</param> /// <param name="rectDst">A "rectangle" that represents the DPI and scroll offsets. /// </param> /// ------------------------------------------------------------------------------------ private void AddSeparatorForDependentStream(Graphics gr, PageElement element, Rectangle rectElement, Rectangle rectDst) { // Make a separator line the width indicated in the publication. int lineWidth = PubControl.Publication.FootnoteSepWidth * rectElement.Width / 1000; int lineHeight = PubControl.Publication.FootnoteSepThickness * rectDst.Height / MiscUtils.kdzmpInch; lineHeight = Math.Max(lineHeight, 1); // make sure we don't have a 0 height rectangle int verticalOffset = (element.Division.VerticalGapBetweenElements * rectDst.Height / MiscUtils.kdzmpInch + lineHeight) / 2; Rectangle separatorRect = new Rectangle( rectElement.Left + (rectElement.Width - lineWidth) / 2, rectElement.Top - verticalOffset, lineWidth, lineHeight); gr.FillRectangle(new SolidBrush(Color.Black), separatorRect); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Insert a page element (at it's proper position so they are ordered top to bottom) /// </summary> /// <param name="newElement">The new element.</param> /// ------------------------------------------------------------------------------------ private void InsertPageElement(PageElement newElement) { int i; for (i = 0; i < m_pageElements.Count; i++) { PageElement pe = m_pageElements[i]; if (pe.LocationOnPage.Top > newElement.LocationOnPage.Top) { // insert before it. m_pageElements.Insert(i, newElement); break; } } if (i >= m_pageElements.Count || m_pageElements.Count == 0) { // Biggest top yet...add to end. m_pageElements.Add(newElement); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Return coordinate transformation suitable for screen drawing in the specified /// element of the specified page. /// </summary> /// <param name="page"></param> /// <param name="pe"></param> /// <param name="rcSrcRoot"></param> /// <param name="rcDstRoot"></param> /// ------------------------------------------------------------------------------------ protected void GetCoordRectsForElt(Page page, PageElement pe, out Rect rcSrcRoot, out Rect rcDstRoot) { // The origin of this rectangle is the offset from the origin of this rootbox's // data to the origin of this element (in printer pixels). Size is DPI. Rectangle rectSrc = new Rectangle(0, pe.OffsetToTopPageBoundary - pe.OverlapWithPreviousElement, (int)(DpiXPrinter), (int)(DpiYPrinter)); rcSrcRoot = new Rect(rectSrc.Left, rectSrc.Top, rectSrc.Right, rectSrc.Bottom); Rectangle rectElement = pe.PositionInLayoutForScreen(IndexOfPage(page), this, DpiXScreen, DpiYScreen); // The origin of this rectangle is the offset from the origin of this element // to the origin of the clip rectangle (the part of the rc that // actually pertains to this element) (in screen pixels) Rectangle rectDst = new Rectangle(rectElement.Left, rectElement.Top, (int)(DpiXScreen * Zoom), (int)(DpiYScreen * Zoom)); rcDstRoot = new Rect(rectDst.Left, rectDst.Top, rectDst.Right, rectDst.Bottom); }
public void SmallEstimates() { CheckDisposed(); m_pub.PageHeight = 72000 * 5; // 5 inches m_pub.PageWidth = 72000 * 3; // 3 inches m_division.TopMargin = 36000; // Half inch m_division.BottomMargin = 18000; // Quarter inch m_division.InsideMargin = 9000; // 1/8 inch m_division.OutsideMargin = 4500; // 1/16 inch DummyMainLazyViewVc vc = m_division.MainVc as DummyMainLazyViewVc; vc.m_estBookHeight = 100; vc.m_estSectionHeight = 50; m_pub.Width = 3 * 96; // represents a window that is 3" wide at 96 DPI m_pub.CreatePages(); Assert.AreEqual(2, m_pub.Pages.Count, "Our estimate of book size is low, so it should try to fit all of Scripture on 2 pages."); Page firstPage = ((Page)m_pub.Pages[0]); Assert.AreEqual(0, firstPage.FirstDivOnPage); Assert.AreEqual(0, firstPage.OffsetFromTopOfDiv(m_division)); // UNTIL we prepare to draw pages, the three books of Scripture are represented by // a lazy box that is three times the estimated height of a scripture book. // Compute the height of the first line BEFORE we layout any pages. int numberOfBooksInTestLangProj = m_scr.ScriptureBooksOS.Count; int dysHeightOfLiteralLineOfText = m_division.MainRootBox.Height - vc.m_estBookHeight * m_pub.DpiYPrinter / 72 * numberOfBooksInTestLangProj; List <Page> pagesToBeDrawn = m_pub.PrepareToDrawPages(0, 400); Assert.AreEqual(1, pagesToBeDrawn.Count, "First page should be ready to be drawn"); // Tests for TE-1413: As lazy boxes are expanded, add additional pages if necessary Assert.IsTrue(m_pub.Pages.Count > 2, "Expanding lazy boxes for page 1 should increase the estimated number of pages"); // Technically it is possible that the division comes out exactly and we don't need to add 1, // but it's too unlikely to bother with in a test. Assert.AreEqual(m_division.MainRootBox.Height / m_division.AvailablePageHeightInPrinterPixels + 1, m_pub.Pages.Count, "document should fill pages exactly"); // Each paragraph should take exactly one inch. we should be able to fit the one // line of literal text, plus 4 paragraphs on the first page (4.25" high). int dysExpectedP1DataHeight = m_pub.DpiYPrinter * 4 + dysHeightOfLiteralLineOfText; PageElement peMain = firstPage.GetFirstElementForStream(m_division.MainLayoutStream); int dysHeightOfDataOnPage1 = peMain.LocationOnPage.Height; Assert.AreEqual(dysExpectedP1DataHeight, dysHeightOfDataOnPage1, "Wrong amount of data on page 1."); // We should have added enough pages for anything that was expanded pagesToBeDrawn = m_pub.PrepareToDrawPages(401, 801); int dysNewEstHeight = m_division.MainRootBox.Height; int dysAvailPageHeight = m_pub.PageHeightInPrinterPixels - m_division.TopMarginInPrinterPixels - m_division.BottomMarginInPrinterPixels; Assert.IsTrue(dysNewEstHeight <= m_pub.Pages.Count * dysAvailPageHeight, "The page count should be increased to cover new estimated document height"); Assert.IsTrue(dysNewEstHeight > (m_pub.Pages.Count - 1) * dysAvailPageHeight, "The page count should not be increased too much"); }
public void CalcPageElementWindowRectangle() { int dpiScreen = 96; int dpiXPrinter = m_pub.DpiXPrinter; int pdiYPrinter = m_pub.DpiYPrinter; m_pub.PageHeight = (int)(11 * MiscUtils.kdzmpInch); m_pub.PageWidth = (int)(8.5 * MiscUtils.kdzmpInch); m_pub.Width = (int)(8.5 * dpiScreen); Assert.AreEqual(1, m_pub.Zoom, "Physical Page and window should both be 8.5 inches wide"); using (PageElement element = new PageElement(m_firstDivision, null, false, new Rectangle(dpiXPrinter, pdiYPrinter, (int)(6.5 * dpiXPrinter), (int)(9 * pdiYPrinter)), 0, true, 1, 1, 0, 9 * pdiYPrinter,0, false)) { Rectangle expected = new Rectangle(dpiScreen, dpiScreen, (int)(6.5 * dpiScreen), (int)(9 * dpiScreen)); int pageIndex = 0; Assert.AreEqual(expected, element.PositionInLayoutForScreen(pageIndex, m_pub, dpiScreen, dpiScreen)); pageIndex = 1; expected.Location = new Point(expected.Left, expected.Top + (int)(11 * dpiScreen) + m_pub.Gap); Assert.AreEqual(expected, element.PositionInLayoutForScreen(pageIndex, m_pub, dpiScreen, dpiScreen)); // Can't seem to test this because we can't adjust the scroll position, even // though we set the AutoScrollMinSize, tried showing m_pub, gave it a Height, ... // m_pub.AutoScrollPosition = new Point(50, 100); // expected.Location = new Point(expected.Left - 50, expected.Top - 100); // Assert.AreEqual(expected, element.PositionInWindow(pageIndex, m_pub)); m_pub.Width = (int)(4.25 * dpiScreen); // Now we should be zoomed to 50%, so each real-world inch is now only a half-inch // on the screen. Assert.AreEqual(0.5, m_pub.Zoom); expected = new Rectangle(48, (int)(12 * 48) + m_pub.Gap, (int)(6.5 * 48), (int)(9 * 48)); Assert.AreEqual(expected, element.PositionInLayoutForScreen(pageIndex, m_pub, dpiScreen, dpiScreen)); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adjusts the free space. /// </summary> /// <param name="locationOnPage">The location on page.</param> /// <param name="fReducesFreeSpaceFromTop">reduces free space from top</param> /// <param name="element">The page element.</param> /// ------------------------------------------------------------------------------------ private void AdjustFreeSpace(Rectangle locationOnPage, bool fReducesFreeSpaceFromTop, PageElement element) { // Adjust free space if (element.m_column == element.m_totalColumns && locationOnPage.Top >= m_freeSpace.Top && locationOnPage.Top <= m_freeSpace.Bottom) { if (fReducesFreeSpaceFromTop) { m_freeSpace.Height = Math.Max(0, m_freeSpace.Bottom - locationOnPage.Bottom); if (m_freeSpace.Height > 0) m_freeSpace.Y = locationOnPage.Bottom; } else { m_freeSpace.Height = Math.Max(0, locationOnPage.Top - m_freeSpace.Top); } } }
public void HeaderFooterLayout() { m_pub.PageHeight = 72000 * 6; // 6 inches m_pub.PageWidth = 72000 * 6; // 6 inches m_division.TopMargin = 72000; // inch m_division.BottomMargin = 72000; // inch m_division.InsideMargin = 9000; // 1/8 inch m_division.OutsideMargin = 4500; // 1/16 inch m_division.HeaderPosition = 72000 * 3 / 4; m_division.FooterPosition = 72000 * 3 / 4; m_pub.Width = 6 * 96; // represents a window that is 6" wide at 96 DPI m_pub.CreatePages(); Assert.IsTrue(m_pub.Pages.Count >= 2, "For this test, we want to check at least two pages."); Page firstPage = ((Page)m_pub.Pages[0]); Assert.AreEqual(0, firstPage.PageElements.Count, "Nothing should be laid out on page yet."); // Lay out all the pages List <Page> pagesToBeDrawn = m_pub.PrepareToDrawPages(0, m_pub.Pages.Count * 6 * 96); Assert.AreEqual(m_pub.Pages.Count, pagesToBeDrawn.Count, "All pages should be ready to be drawn"); foreach (Page page in pagesToBeDrawn) { Assert.AreEqual(3, page.PageElements.Count, "Header/Footer elements should be included on page " + page.PageNumber); PageElement peMain = page.GetFirstElementForStream(m_division.MainLayoutStream); Assert.IsNotNull(peMain); bool fFoundHeaderElement = false; bool fFoundFooterElement = false; foreach (PageElement pe in page.PageElements) { if (pe != peMain) { Assert.AreEqual(0, pe.OffsetToTopPageBoundary); if (page.PageNumber % 2 == 1) { Assert.AreEqual(m_pub.DpiXPrinter / 8, pe.LocationOnPage.X, "Odd page should have 1/8 inch left margin"); } else { Assert.AreEqual(m_pub.DpiXPrinter / 16, pe.LocationOnPage.X, "Even page should have 1/16 inch left margin"); } if (pe.LocationOnPage.Y == m_pub.DpiYPrinter / 2) { Assert.AreEqual(m_pub.DpiYPrinter / 4, pe.LocationOnPage.Height, "Header element should be a 1/4-inch rectangle"); Assert.IsFalse(fFoundHeaderElement); fFoundHeaderElement = true; } else { Assert.AreEqual(Math.Round(m_pub.DpiYPrinter * 5.25, MidpointRounding.AwayFromZero), pe.LocationOnPage.Y, "Found element that isn't in the correct header or footer position"); Assert.AreEqual(m_pub.DpiYPrinter * 3 / 4, pe.LocationOnPage.Height, "Footer element height should have been limited to 3/4 inch"); Assert.IsFalse(fFoundFooterElement); fFoundFooterElement = true; } } } Assert.IsTrue(fFoundFooterElement); Assert.IsTrue(fFoundHeaderElement); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adjusts the location and height of the page element as well as the available free /// space on the page. /// </summary> /// <param name="element">The element.</param> /// <param name="newLocation">The new location.</param> /// <param name="fReducesFreeSpaceFromTop"><c>true</c> to reduce free space from top</param> /// ------------------------------------------------------------------------------------ internal void AdjustPageElement(PageElement element, Rectangle newLocation, bool fReducesFreeSpaceFromTop) { // Increase size of/move location element.LocationOnPage = newLocation; element.ColumnHeight = newLocation.Height; AdjustFreeSpace(newLocation, fReducesFreeSpaceFromTop, element); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Sets the offset to top of data, effectively breaking this page. This can be used /// on a page that may or may not have been laid out. Depending on the value of the /// page element parameter passed in, this can affect either the first division on the /// page or some subsequent division. /// </summary> /// <param name="pe">The page element corresponding to the division we care about /// (if known). If this is null, we will assume we're adjusting the offset of the first /// division on this page and try to find the appropriate page element for that division, /// if any.</param> /// <param name="ypNewOffset">The number of printer pixels (source/layout units) from /// the top of the (first) division to the top of this page</param> /// ------------------------------------------------------------------------------------ internal void AdjustOffsetFromTopOfDiv(PageElement pe, int ypNewOffset) { CheckDisposed(); if (!NeedsLayout) // if broken, ignore any existing elements. { if (pe == null) { pe = GetFirstElementForStream(PubControl.Divisions[FirstDivOnPage].MainLayoutStream); if (pe == null) { Debug.Fail("We should have found an element for the stream of the first division on this page"); return; } } if (pe.OffsetToTopPageBoundary == ypNewOffset) return; pe.OffsetToTopPageBoundary = ypNewOffset; // Make sure we don't adjust the starting offset for the main stream if the // adjust is not for the main stream if (pe.m_fMainStream) { if (pe.Division == PubControl.Divisions[FirstDivOnPage]) m_ypOffsetFromTopOfDiv = ypNewOffset; Broken = true; // make sure the other (subordinate) page elements know to rebuild themselves. foreach (PageElement element in PageElements) { if (element.IsSubordinateStream) element.m_stream.DiscardPage(Handle); } } return; } // We need to make sure we don't adjust the offset for the page if the // page element isn't for the main stream, even if the page is broken (this case). if (ypNewOffset != m_ypOffsetFromTopOfDiv && (pe == null || (pe.m_fMainStream && pe.Division == PubControl.Divisions[FirstDivOnPage]))) { // Don't need to set the m_fBroken flag because we are already broken or // we haven't laid out at all yet. Debug.Assert(m_ypOffsetFromTopOfDiv != 0, "Should not adjust offset on the first page that has content for the stream."); m_ypOffsetFromTopOfDiv = ypNewOffset; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets the number of printer pixels (source/layout units) from the top of the given /// division's main layout stream to the top of the data represented by the first page /// element on this page for that stream. This may only be an estimate, particularly if: /// <list type="normal"> /// <item>this page has no elements (at least for the given division)</item> /// <item>this page is broken</item> /// <item>there are previous pages that are not fully laid out (or broken)</item> /// </list> /// </summary> /// <param name="stream">The stream whose offset we want (may or may not be the main /// layout stream for the given division, but must not be null).</param> /// <param name="div">The division layout manager (can be null if the stream is not /// a main layout stream).</param> /// <param name="pe">The first page element on this page for the given stream.</param> /// <returns>The offset</returns> /// ------------------------------------------------------------------------------------ internal int OffsetFromTopOfDiv(IVwLayoutStream stream, DivisionLayoutMgr div, out PageElement pe) { CheckDisposed(); pe = GetFirstElementForStream(stream); if (pe != null) return pe.OffsetToTopPageBoundary; return (div == PubControl.Divisions[FirstDivOnPage]) ? m_ypOffsetFromTopOfDiv : 0; }