Bug 1660166 part 2: Let nsPageFrame determine its own page number, and store total number of pages in one central spot. r=hiro
authorDaniel Holbert <dholbert@cs.stanford.edu>
Thu, 20 Aug 2020 06:12:33 +0000
changeset 545468 d64d22e3048348c28a3a5ebedc24bac49f87be60
parent 545467 5fe1dd9f3badae5b6c8de9bee3fc3bb901074451
child 545469 c3fe601df6e12cf7801ac4f6ab5dd5f623fb44f4
push id37714
push userabutkovits@mozilla.com
push dateThu, 20 Aug 2020 15:32:45 +0000
treeherdermozilla-central@920ef04bf423 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1660166
milestone81.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1660166 part 2: Let nsPageFrame determine its own page number, and store total number of pages in one central spot. r=hiro Depends on D87695 Differential Revision: https://phabricator.services.mozilla.com/D87696
layout/generic/PrintedSheetFrame.cpp
layout/generic/nsPageFrame.cpp
layout/generic/nsPageFrame.h
layout/generic/nsPageSequenceFrame.cpp
layout/generic/nsPageSequenceFrame.h
--- a/layout/generic/PrintedSheetFrame.cpp
+++ b/layout/generic/PrintedSheetFrame.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 /* Rendering object for a printed or print-previewed sheet of paper */
 
 #include "PrintedSheetFrame.h"
 
 #include "nsCSSFrameConstructor.h"
 #include "nsPageFrame.h"
+#include "nsPageSequenceFrame.h"
 
 using namespace mozilla;
 
 PrintedSheetFrame* NS_NewPrintedSheetFrame(PresShell* aPresShell,
                                            ComputedStyle* aStyle) {
   return new (aPresShell)
       PrintedSheetFrame(aStyle, aPresShell->GetPresContext());
 }
@@ -64,18 +65,20 @@ void PrintedSheetFrame::Reflow(nsPresCon
   // is trivial & will will run exactly once, for now.
   MOZ_ASSERT(mFrames.GetLength() == 1,
              "how did we get more than one page per sheet");
   for (auto* childFrame : mFrames) {
     MOZ_ASSERT(childFrame->IsPageFrame(),
                "we're only expecting page frames as children");
     auto* pageFrame = static_cast<nsPageFrame*>(childFrame);
 
-    // Be sure our child has a pointer to the nsSharedPageData:
+    // Be sure our child has a pointer to the nsSharedPageData and knows its
+    // page number:
     pageFrame->SetSharedPageData(mPD);
+    pageFrame->DeterminePageNum();
 
     ReflowInput pageReflowInput(aPresContext, aReflowInput, pageFrame,
                                 pageSize);
     // For now, we'll always position the pageFrame at our origin.  (This will
     // change in bug 1631452 when we support more than 1 page per sheet.)
     LogicalPoint pagePos(wm);
 
     // Outparams for reflow:
@@ -88,16 +91,20 @@ void PrintedSheetFrame::Reflow(nsPresCon
     FinishReflowChild(pageFrame, aPresContext, pageReflowOutput,
                       &pageReflowInput, wm, pagePos, physPageSize,
                       ReflowChildFlags::Default);
 
     // Did this page complete the document, or do we need to generate
     // another page frame?
     nsIFrame* pageNextInFlow = pageFrame->GetNextInFlow();
     if (status.IsFullyComplete()) {
+      // The page we just reflowed is the final page! Record its page number
+      // as the number of pages:
+      mPD->mTotNumPages = pageFrame->GetPageNum();
+
       // Normally, we (the parent frame) would be responsible for deleting the
       // next-in-flow of our fully-complete children. But since we don't
       // support dynamic changes / incremental reflow for printing (and since
       // the reflow operation is single-pass at this level of granularity), our
       // child *shouldn't have had any opportunities* to end up with a
       // next-in-flow that would need cleaning up here.
       NS_ASSERTION(!pageNextInFlow, "bad child flow list");
     } else {
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -203,17 +203,17 @@ void nsPageFrame::ProcessSpecialCodes(co
   //
   // Search to see if the "page number and page" total code are in the string
   // and replace the page number and page total code with the actual
   // values
   constexpr auto kPageAndTotal = u"&PT"_ns;
   if (aStr.Find(kPageAndTotal) != kNotFound) {
     nsAutoString uStr;
     nsTextFormatter::ssprintf(uStr, mPD->mPageNumAndTotalsFormat.get(),
-                              mPageNum, mTotNumPages);
+                              mPageNum, mPD->mTotNumPages);
     aNewStr.ReplaceSubstring(kPageAndTotal, uStr);
   }
 
   // Search to see if the page number code is in the string
   // and replace the page number code with the actual value
   constexpr auto kPage = u"&P"_ns;
   if (aStr.Find(kPage) != kNotFound) {
     nsAutoString uStr;
@@ -229,17 +229,18 @@ void nsPageFrame::ProcessSpecialCodes(co
   constexpr auto kDocURL = u"&U"_ns;
   if (aStr.Find(kDocURL) != kNotFound) {
     aNewStr.ReplaceSubstring(kDocURL, mPD->mDocURL);
   }
 
   constexpr auto kPageTotal = u"&L"_ns;
   if (aStr.Find(kPageTotal) != kNotFound) {
     nsAutoString uStr;
-    nsTextFormatter::ssprintf(uStr, mPD->mPageNumFormat.get(), mTotNumPages);
+    nsTextFormatter::ssprintf(uStr, mPD->mPageNumFormat.get(),
+                              mPD->mTotNumPages);
     aNewStr.ReplaceSubstring(kPageTotal, uStr);
   }
 }
 
 //------------------------------------------------------------------------------
 nscoord nsPageFrame::GetXPosition(gfxContext& aRenderingContext,
                                   nsFontMetrics& aFontMetrics,
                                   const nsRect& aRect, int32_t aJust,
@@ -637,19 +638,21 @@ void nsPageFrame::BuildDisplayList(nsDis
       }
     }
   }
 
   set.MoveTo(aLists);
 }
 
 //------------------------------------------------------------------------------
-void nsPageFrame::SetPageNumInfo(int32_t aPageNumber, int32_t aTotalPages) {
-  mPageNum = aPageNumber;
-  mTotNumPages = aTotalPages;
+void nsPageFrame::DeterminePageNum() {
+  // If we have no previous continuation, we're page 1. Otherwise, we're
+  // just one more than our previous continuation's page number.
+  auto* prevContinuation = static_cast<nsPageFrame*>(GetPrevContinuation());
+  mPageNum = prevContinuation ? prevContinuation->GetPageNum() + 1 : 1;
 }
 
 void nsPageFrame::PaintHeaderFooter(gfxContext& aRenderingContext, nsPoint aPt,
                                     bool aDisableSubpixelAA) {
   nsPresContext* pc = PresContext();
 
   if (!mPD->mPrintSettings) {
     if (pc->Type() == nsPresContext::eContext_PrintPreview || pc->IsDynamic())
--- a/layout/generic/nsPageFrame.h
+++ b/layout/generic/nsPageFrame.h
@@ -36,18 +36,20 @@ class nsPageFrame final : public nsConta
 #ifdef DEBUG_FRAME_DUMP
   nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   //////////////////
   // For Printing
   //////////////////
 
-  // Tell the page which page number it is out of how many
-  void SetPageNumInfo(int32_t aPageNumber, int32_t aTotalPages);
+  // Determine this page's page-number, based on its previous continuation
+  // (whose page number is presumed to already be known).
+  void DeterminePageNum();
+  int32_t GetPageNum() { return mPageNum; }
 
   void SetSharedPageData(nsSharedPageData* aPD);
   nsSharedPageData* GetSharedPageData() const { return mPD; }
 
   // We must allow Print Preview UI to have a background, no matter what the
   // user's settings
   bool HonorPrintBackgroundSettings() override { return false; }
 
@@ -83,19 +85,17 @@ class nsPageFrame final : public nsConta
                         nsHeaderFooterEnum aHeaderFooter,
                         const nsString& aStrLeft, const nsString& aStrRight,
                         const nsString& aStrCenter, const nsRect& aRect,
                         nscoord aAscent, nscoord aHeight);
 
   void ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr);
 
   static constexpr int32_t kPageNumUnset = -1;
-
   int32_t mPageNum = kPageNumUnset;
-  int32_t mTotNumPages = kPageNumUnset;
 
   // Note: this will be set before reflow, and it's strongly owned by our
   // nsPageSequenceFrame, which outlives us.
   nsSharedPageData* mPD = nullptr;
 
   nsMargin mPageContentMargin;
 };
 
--- a/layout/generic/nsPageSequenceFrame.cpp
+++ b/layout/generic/nsPageSequenceFrame.cpp
@@ -302,41 +302,16 @@ void nsPageSequenceFrame::Reflow(nsPresC
           PresShell()->FrameConstructor()->CreateContinuingFrame(kidFrame,
                                                                  this);
 
       // Add it to our child list
       mFrames.InsertFrame(nullptr, kidFrame, continuingSheet);
     }
   }
 
-  // Get Total Page Count
-  // XXXdholbert When we support multiple pages-per-sheet in bug 1631452,
-  // we'll need to be sure to update this computation to account for the
-  // sheet-vs-page distinction.
-  // XXXdholbert technically we could calculate this in the loop above,
-  // instead of needing a separate walk.
-  int32_t pageTot = mFrames.GetLength();
-
-  // Set Page Number Info
-  int32_t pageNum = 1;
-  for (nsIFrame* sheetFrame : mFrames) {
-    MOZ_ASSERT(sheetFrame->IsPrintedSheetFrame(),
-               "only expecting PrintedSheetFrame children");
-    for (nsIFrame* pageFrame : sheetFrame->PrincipalChildList()) {
-      MOZ_ASSERT(
-          pageFrame->IsPageFrame(),
-          "only expecting nsPageFrame grandchildren. Other types will make "
-          "this static_cast bogus & probably violate other assumptions");
-      static_cast<nsPageFrame*>(pageFrame)->SetPageNumInfo(pageNum, pageTot);
-      // XXXdholbert Perhaps we'll need to keep track of the page count *and*
-      // the printed sheet count?
-      pageNum++;
-    }
-  }
-
   nsAutoString formattedDateString;
   PRTime now = PR_Now();
   if (NS_SUCCEEDED(DateTimeFormat::FormatPRTime(
           kDateFormatShort, kTimeFormatNoSeconds, now, formattedDateString))) {
     SetDateTimeStr(formattedDateString);
   }
 
   // cache the size so we can set the desired size for the other reflows that
--- a/layout/generic/nsPageSequenceFrame.h
+++ b/layout/generic/nsPageSequenceFrame.h
@@ -34,16 +34,19 @@ class nsSharedPageData {
 
   nsString mDateTimeStr;
   nsString mPageNumFormat;
   nsString mPageNumAndTotalsFormat;
   nsString mDocTitle;
   nsString mDocURL;
   nsFont mHeadFootFont;
 
+  // Total number of pages:
+  int32_t mTotNumPages = 0;
+
   // Margin for headers and footers; it defaults to 4/100 of an inch on UNIX
   // and 0 elsewhere; I think it has to do with some inconsistency in page size
   // computations
   nsMargin mEdgePaperMargin;
 
   nsCOMPtr<nsIPrintSettings> mPrintSettings;
 
   // The scaling ratio we need to apply to make all pages fit horizontally. It's