LCOV - code coverage report
Current view: top level - layout/generic - nsPageFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 325 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsPageFrame.h"
       7             : 
       8             : #include "mozilla/gfx/2D.h"
       9             : #include "gfxContext.h"
      10             : #include "nsDeviceContext.h"
      11             : #include "nsFontMetrics.h"
      12             : #include "nsLayoutUtils.h"
      13             : #include "nsPresContext.h"
      14             : #include "nsGkAtoms.h"
      15             : #include "nsIPresShell.h"
      16             : #include "nsPageContentFrame.h"
      17             : #include "nsDisplayList.h"
      18             : #include "nsLayoutUtils.h" // for function BinarySearchForPosition
      19             : #include "nsSimplePageSequenceFrame.h" // for nsSharedPageData
      20             : #include "nsTextFormatter.h" // for page number localization formatting
      21             : #include "nsBidiUtils.h"
      22             : #include "nsIPrintSettings.h"
      23             : 
      24             : #include "mozilla/Logging.h"
      25             : extern mozilla::LazyLogModule gLayoutPrintingLog;
      26             : #define PR_PL(_p1)  MOZ_LOG(gLayoutPrintingLog, mozilla::LogLevel::Debug, _p1)
      27             : 
      28             : using namespace mozilla;
      29             : using namespace mozilla::gfx;
      30             : 
      31             : nsPageFrame*
      32           0 : NS_NewPageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      33             : {
      34           0 :   return new (aPresShell) nsPageFrame(aContext);
      35             : }
      36             : 
      37           0 : NS_IMPL_FRAMEARENA_HELPERS(nsPageFrame)
      38             : 
      39           0 : NS_QUERYFRAME_HEAD(nsPageFrame)
      40           0 :   NS_QUERYFRAME_ENTRY(nsPageFrame)
      41           0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
      42             : 
      43           0 : nsPageFrame::nsPageFrame(nsStyleContext* aContext)
      44           0 :   : nsContainerFrame(aContext, kClassID)
      45             : {
      46           0 : }
      47             : 
      48           0 : nsPageFrame::~nsPageFrame()
      49             : {
      50           0 : }
      51             : 
      52             : void
      53           0 : nsPageFrame::Reflow(nsPresContext*           aPresContext,
      54             :                                   ReflowOutput&     aDesiredSize,
      55             :                                   const ReflowInput& aReflowInput,
      56             :                                   nsReflowStatus&          aStatus)
      57             : {
      58           0 :   MarkInReflow();
      59           0 :   DO_GLOBAL_REFLOW_COUNT("nsPageFrame");
      60           0 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
      61           0 :   aStatus.Reset();  // initialize out parameter
      62             : 
      63           0 :   NS_ASSERTION(mFrames.FirstChild() &&
      64             :                mFrames.FirstChild()->IsPageContentFrame(),
      65             :                "pageFrame must have a pageContentFrame child");
      66             : 
      67             :   // Resize our frame allowing it only to be as big as we are
      68             :   // XXX Pay attention to the page's border and padding...
      69           0 :   if (mFrames.NotEmpty()) {
      70           0 :     nsIFrame* frame = mFrames.FirstChild();
      71             :     // When the reflow size is NS_UNCONSTRAINEDSIZE it means we are reflowing
      72             :     // a single page to print selection. So this means we want to use
      73             :     // NS_UNCONSTRAINEDSIZE without altering it
      74             :     nscoord avHeight;
      75           0 :     if (mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE) {
      76           0 :       avHeight = NS_UNCONSTRAINEDSIZE;
      77             :     } else {
      78           0 :       avHeight = mPD->mReflowSize.height;
      79             :     }
      80           0 :     nsSize  maxSize(mPD->mReflowSize.width, avHeight);
      81           0 :     float scale = aPresContext->GetPageScale();
      82           0 :     maxSize.width = NSToCoordCeil(maxSize.width / scale);
      83           0 :     if (maxSize.height != NS_UNCONSTRAINEDSIZE) {
      84           0 :       maxSize.height = NSToCoordCeil(maxSize.height / scale);
      85             :     }
      86             :     // Get the number of Twips per pixel from the PresContext
      87           0 :     nscoord onePixelInTwips = nsPresContext::CSSPixelsToAppUnits(1);
      88             :     // insurance against infinite reflow, when reflowing less than a pixel
      89             :     // XXX Shouldn't we do something more friendly when invalid margins
      90             :     //     are set?
      91           0 :     if (maxSize.width < onePixelInTwips || maxSize.height < onePixelInTwips) {
      92           0 :       aDesiredSize.ClearSize();
      93           0 :       NS_WARNING("Reflow aborted; no space for content");
      94           0 :       return;
      95             :     }
      96             : 
      97             :     ReflowInput kidReflowInput(aPresContext, aReflowInput, frame,
      98           0 :                                      LogicalSize(frame->GetWritingMode(),
      99           0 :                                                  maxSize));
     100           0 :     kidReflowInput.mFlags.mIsTopOfPage = true;
     101           0 :     kidReflowInput.mFlags.mTableIsSplittable = true;
     102             : 
     103             :     // Use the margins given in the @page rule.
     104             :     // If a margin is 'auto', use the margin from the print settings for that side.
     105           0 :     const nsStyleSides& marginStyle = kidReflowInput.mStyleMargin->mMargin;
     106           0 :     NS_FOR_CSS_SIDES(side) {
     107           0 :       if (marginStyle.GetUnit(side) == eStyleUnit_Auto) {
     108           0 :         mPageContentMargin.Side(side) = mPD->mReflowMargin.Side(side);
     109             :       } else {
     110           0 :         mPageContentMargin.Side(side) = kidReflowInput.ComputedPhysicalMargin().Side(side);
     111             :       }
     112             :     }
     113             : 
     114             : 
     115           0 :     nscoord maxWidth = maxSize.width - mPageContentMargin.LeftRight() / scale;
     116             :     nscoord maxHeight;
     117           0 :     if (maxSize.height == NS_UNCONSTRAINEDSIZE) {
     118           0 :       maxHeight = NS_UNCONSTRAINEDSIZE;
     119             :     } else {
     120           0 :       maxHeight = maxSize.height - mPageContentMargin.TopBottom() / scale;
     121             :     }
     122             : 
     123             :     // Check the width and height, if they're too small we reset the margins
     124             :     // back to the default.
     125           0 :     if (maxWidth < onePixelInTwips ||
     126           0 :        (maxHeight != NS_UNCONSTRAINEDSIZE && maxHeight < onePixelInTwips)) {
     127           0 :       NS_FOR_CSS_SIDES(side) {
     128           0 :         mPageContentMargin.Side(side) = mPD->mReflowMargin.Side(side);
     129             :       }
     130           0 :       maxWidth = maxSize.width - mPageContentMargin.LeftRight() / scale;
     131           0 :       if (maxHeight != NS_UNCONSTRAINEDSIZE) {
     132           0 :         maxHeight = maxSize.height - mPageContentMargin.TopBottom() / scale;
     133             :       }
     134             :     }
     135             : 
     136           0 :     kidReflowInput.SetComputedWidth(maxWidth);
     137           0 :     kidReflowInput.SetComputedHeight(maxHeight);
     138             : 
     139             :     // calc location of frame
     140           0 :     nscoord xc = mPageContentMargin.left;
     141           0 :     nscoord yc = mPageContentMargin.top;
     142             : 
     143             :     // Get the child's desired size
     144           0 :     ReflowChild(frame, aPresContext, aDesiredSize, kidReflowInput, xc, yc, 0, aStatus);
     145             : 
     146             :     // Place and size the child
     147           0 :     FinishReflowChild(frame, aPresContext, aDesiredSize, &kidReflowInput, xc, yc, 0);
     148             : 
     149           0 :     NS_ASSERTION(!aStatus.IsFullyComplete() ||
     150             :                  !frame->GetNextInFlow(), "bad child flow list");
     151             :   }
     152           0 :   PR_PL(("PageFrame::Reflow %p ", this));
     153           0 :   PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize.Width(), aDesiredSize.Height(),
     154             :          aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
     155             : 
     156             :   // Return our desired size
     157           0 :   WritingMode wm = aReflowInput.GetWritingMode();
     158           0 :   aDesiredSize.ISize(wm) = aReflowInput.AvailableISize();
     159           0 :   if (aReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE) {
     160           0 :     aDesiredSize.BSize(wm) = aReflowInput.AvailableBSize();
     161             :   }
     162             : 
     163           0 :   aDesiredSize.SetOverflowAreasToDesiredBounds();
     164           0 :   FinishAndStoreOverflow(&aDesiredSize);
     165             : 
     166           0 :   PR_PL(("PageFrame::Reflow %p ", this));
     167           0 :   PR_PL(("[%d,%d]\n", aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
     168             : 
     169           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     170             : }
     171             : 
     172             : #ifdef DEBUG_FRAME_DUMP
     173             : nsresult
     174           0 : nsPageFrame::GetFrameName(nsAString& aResult) const
     175             : {
     176           0 :   return MakeFrameName(NS_LITERAL_STRING("Page"), aResult);
     177             : }
     178             : #endif
     179             : 
     180             : void
     181           0 : nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
     182             : {
     183             : 
     184           0 :   aNewStr = aStr;
     185             : 
     186             :   // Search to see if the &D code is in the string
     187             :   // then subst in the current date/time
     188           0 :   NS_NAMED_LITERAL_STRING(kDate, "&D");
     189           0 :   if (aStr.Find(kDate) != kNotFound) {
     190           0 :     aNewStr.ReplaceSubstring(kDate, mPD->mDateTimeStr);
     191             :   }
     192             : 
     193             :   // NOTE: Must search for &PT before searching for &P
     194             :   //
     195             :   // Search to see if the "page number and page" total code are in the string
     196             :   // and replace the page number and page total code with the actual
     197             :   // values
     198           0 :   NS_NAMED_LITERAL_STRING(kPageAndTotal, "&PT");
     199           0 :   if (aStr.Find(kPageAndTotal) != kNotFound) {
     200           0 :     char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumAndTotalsFormat.get(), mPageNum, mTotNumPages);
     201           0 :     aNewStr.ReplaceSubstring(kPageAndTotal, nsDependentString(uStr));
     202           0 :     free(uStr);
     203             :   }
     204             : 
     205             :   // Search to see if the page number code is in the string
     206             :   // and replace the page number code with the actual value
     207           0 :   NS_NAMED_LITERAL_STRING(kPage, "&P");
     208           0 :   if (aStr.Find(kPage) != kNotFound) {
     209           0 :     char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat.get(), mPageNum);
     210           0 :     aNewStr.ReplaceSubstring(kPage, nsDependentString(uStr));
     211           0 :     free(uStr);
     212             :   }
     213             : 
     214           0 :   NS_NAMED_LITERAL_STRING(kTitle, "&T");
     215           0 :   if (aStr.Find(kTitle) != kNotFound) {
     216           0 :     aNewStr.ReplaceSubstring(kTitle, mPD->mDocTitle);
     217             :   }
     218             : 
     219           0 :   NS_NAMED_LITERAL_STRING(kDocURL, "&U");
     220           0 :   if (aStr.Find(kDocURL) != kNotFound) {
     221           0 :     aNewStr.ReplaceSubstring(kDocURL, mPD->mDocURL);
     222             :   }
     223             : 
     224           0 :   NS_NAMED_LITERAL_STRING(kPageTotal, "&L");
     225           0 :   if (aStr.Find(kPageTotal) != kNotFound) {
     226           0 :     char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat.get(), mTotNumPages);
     227           0 :     aNewStr.ReplaceSubstring(kPageTotal, nsDependentString(uStr));
     228           0 :     free(uStr);
     229             :   }
     230           0 : }
     231             : 
     232             : 
     233             : //------------------------------------------------------------------------------
     234           0 : nscoord nsPageFrame::GetXPosition(gfxContext&          aRenderingContext,
     235             :                                   nsFontMetrics&       aFontMetrics,
     236             :                                   const nsRect&        aRect,
     237             :                                   int32_t              aJust,
     238             :                                   const nsString&      aStr)
     239             : {
     240           0 :   nscoord width = nsLayoutUtils::AppUnitWidthOfStringBidi(aStr, this,
     241             :                                                           aFontMetrics,
     242           0 :                                                           aRenderingContext);
     243           0 :   nscoord x = aRect.x;
     244           0 :   switch (aJust) {
     245             :     case nsIPrintSettings::kJustLeft:
     246           0 :       x += mPD->mEdgePaperMargin.left;
     247           0 :       break;
     248             : 
     249             :     case nsIPrintSettings::kJustCenter:
     250           0 :       x += (aRect.width - width) / 2;
     251           0 :       break;
     252             : 
     253             :     case nsIPrintSettings::kJustRight:
     254           0 :       x += aRect.width - width - mPD->mEdgePaperMargin.right;
     255           0 :       break;
     256             :   } // switch
     257             : 
     258           0 :   return x;
     259             : }
     260             : 
     261             : // Draw a header or footer
     262             : // @param aRenderingContext - rendering content ot draw into
     263             : // @param aHeaderFooter - indicates whether it is a header or footer
     264             : // @param aStrLeft - string for the left header or footer; can be empty
     265             : // @param aStrCenter - string for the center header or footer; can be empty
     266             : // @param aStrRight - string for the right header or footer; can be empty
     267             : // @param aRect - the rect of the page
     268             : // @param aAscent - the ascent of the font
     269             : // @param aHeight - the height of the font
     270             : void
     271           0 : nsPageFrame::DrawHeaderFooter(gfxContext&          aRenderingContext,
     272             :                               nsFontMetrics&       aFontMetrics,
     273             :                               nsHeaderFooterEnum   aHeaderFooter,
     274             :                               const nsString&      aStrLeft,
     275             :                               const nsString&      aStrCenter,
     276             :                               const nsString&      aStrRight,
     277             :                               const nsRect&        aRect,
     278             :                               nscoord              aAscent,
     279             :                               nscoord              aHeight)
     280             : {
     281           0 :   int32_t numStrs = 0;
     282           0 :   if (!aStrLeft.IsEmpty()) numStrs++;
     283           0 :   if (!aStrCenter.IsEmpty()) numStrs++;
     284           0 :   if (!aStrRight.IsEmpty()) numStrs++;
     285             : 
     286           0 :   if (numStrs == 0) return;
     287           0 :   nscoord strSpace = aRect.width / numStrs;
     288             : 
     289           0 :   if (!aStrLeft.IsEmpty()) {
     290             :     DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
     291             :                      nsIPrintSettings::kJustLeft, aStrLeft, aRect, aAscent,
     292           0 :                      aHeight, strSpace);
     293             :   }
     294           0 :   if (!aStrCenter.IsEmpty()) {
     295             :     DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
     296             :                      nsIPrintSettings::kJustCenter, aStrCenter, aRect, aAscent,
     297           0 :                      aHeight, strSpace);
     298             :   }
     299           0 :   if (!aStrRight.IsEmpty()) {
     300             :     DrawHeaderFooter(aRenderingContext, aFontMetrics, aHeaderFooter,
     301             :                      nsIPrintSettings::kJustRight, aStrRight, aRect, aAscent,
     302           0 :                      aHeight, strSpace);
     303             :   }
     304             : }
     305             : 
     306             : // Draw a header or footer string
     307             : // @param aRenderingContext - rendering context to draw into
     308             : // @param aHeaderFooter - indicates whether it is a header or footer
     309             : // @param aJust - indicates where the string is located within the header/footer
     310             : // @param aStr - the string to be drawn
     311             : // @param aRect - the rect of the page
     312             : // @param aHeight - the height of the font
     313             : // @param aAscent - the ascent of the font
     314             : // @param aWidth - available width for the string
     315             : void
     316           0 : nsPageFrame::DrawHeaderFooter(gfxContext&          aRenderingContext,
     317             :                               nsFontMetrics&       aFontMetrics,
     318             :                               nsHeaderFooterEnum   aHeaderFooter,
     319             :                               int32_t              aJust,
     320             :                               const nsString&      aStr,
     321             :                               const nsRect&        aRect,
     322             :                               nscoord              aAscent,
     323             :                               nscoord              aHeight,
     324             :                               nscoord              aWidth)
     325             : {
     326             : 
     327           0 :   nscoord contentWidth = aWidth - (mPD->mEdgePaperMargin.left + mPD->mEdgePaperMargin.right);
     328             : 
     329           0 :   DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
     330             : 
     331           0 :   if ((aHeaderFooter == eHeader && aHeight < mPageContentMargin.top) ||
     332           0 :       (aHeaderFooter == eFooter && aHeight < mPageContentMargin.bottom)) {
     333           0 :     nsAutoString str;
     334           0 :     ProcessSpecialCodes(aStr, str);
     335             : 
     336             :     int32_t indx;
     337           0 :     int32_t textWidth = 0;
     338           0 :     const char16_t* text = str.get();
     339             : 
     340           0 :     int32_t len = (int32_t)str.Length();
     341           0 :     if (len == 0) {
     342           0 :       return; // bail is empty string
     343             :     }
     344             :     // find how much text fits, the "position" is the size of the available area
     345           0 :     if (nsLayoutUtils::BinarySearchForPosition(drawTarget, aFontMetrics, text,
     346             :                                                0, 0, 0, len,
     347             :                                                int32_t(contentWidth), indx,
     348             :                                                textWidth)) {
     349           0 :       if (indx < len-1 ) {
     350             :         // we can't fit in all the text
     351           0 :         if (indx > 3) {
     352             :           // But we can fit in at least 4 chars.  Show all but 3 of them, then
     353             :           // an ellipsis.
     354             :           // XXXbz for non-plane0 text, this may be cutting things in the
     355             :           // middle of a codepoint!  Also, we have no guarantees that the three
     356             :           // dots will fit in the space the three chars we removed took up with
     357             :           // these font metrics!
     358           0 :           str.Truncate(indx-3);
     359           0 :           str.AppendLiteral("...");
     360             :         } else {
     361             :           // We can only fit 3 or fewer chars.  Just show nothing
     362           0 :           str.Truncate();
     363             :         }
     364             :       }
     365             :     } else {
     366           0 :       return; // bail if couldn't find the correct length
     367             :     }
     368             : 
     369           0 :     if (HasRTLChars(str)) {
     370           0 :       PresContext()->SetBidiEnabled();
     371             :     }
     372             : 
     373             :     // cacl the x and y positions of the text
     374           0 :     nscoord x = GetXPosition(aRenderingContext, aFontMetrics, aRect, aJust, str);
     375             :     nscoord y;
     376           0 :     if (aHeaderFooter == eHeader) {
     377           0 :       y = aRect.y + mPD->mEdgePaperMargin.top;
     378             :     } else {
     379           0 :       y = aRect.YMost() - aHeight - mPD->mEdgePaperMargin.bottom;
     380             :     }
     381             : 
     382             :     // set up new clip and draw the text
     383           0 :     aRenderingContext.Save();
     384             :     aRenderingContext.Clip(
     385           0 :       NSRectToSnappedRect(aRect, PresContext()->AppUnitsPerDevPixel(), *drawTarget));
     386           0 :     aRenderingContext.SetColor(Color(0.f, 0.f, 0.f));
     387           0 :     nsLayoutUtils::DrawString(this, aFontMetrics, &aRenderingContext,
     388           0 :                               str.get(), str.Length(),
     389           0 :                               nsPoint(x, y + aAscent),
     390             :                               nullptr,
     391           0 :                               DrawStringFlags::eForceHorizontal);
     392           0 :     aRenderingContext.Restore();
     393             :   }
     394             : }
     395             : 
     396             : /**
     397             :  * Remove all leaf display items that are not for descendants of
     398             :  * aBuilder->GetReferenceFrame() from aList.
     399             :  * @param aPage the page we're constructing the display list for
     400             :  * @param aExtraPage the page we constructed aList for
     401             :  * @param aList the list that is modified in-place
     402             :  */
     403             : static void
     404           0 : PruneDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
     405             :                              nsPageFrame* aPage, nsIFrame* aExtraPage,
     406             :                              nsDisplayList* aList)
     407             : {
     408           0 :   nsDisplayList newList;
     409             : 
     410             :   while (true) {
     411           0 :     nsDisplayItem* i = aList->RemoveBottom();
     412           0 :     if (!i)
     413           0 :       break;
     414           0 :     nsDisplayList* subList = i->GetSameCoordinateSystemChildren();
     415           0 :     if (subList) {
     416           0 :       PruneDisplayListForExtraPage(aBuilder, aPage, aExtraPage, subList);
     417           0 :       i->UpdateBounds(aBuilder);
     418             :     } else {
     419           0 :       nsIFrame* f = i->Frame();
     420           0 :       if (!nsLayoutUtils::IsProperAncestorFrameCrossDoc(aPage, f)) {
     421             :         // We're throwing this away so call its destructor now. The memory
     422             :         // is owned by aBuilder which destroys all items at once.
     423           0 :         i->~nsDisplayItem();
     424           0 :         continue;
     425             :       }
     426             :     }
     427           0 :     newList.AppendToTop(i);
     428           0 :   }
     429           0 :   aList->AppendToTop(&newList);
     430           0 : }
     431             : 
     432             : static void
     433           0 : BuildDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
     434             :                              nsPageFrame* aPage, nsIFrame* aExtraPage,
     435             :                              const nsRect& aDirtyRect, nsDisplayList* aList)
     436             : {
     437             :   // The only content in aExtraPage we care about is out-of-flow content whose
     438             :   // placeholders have occurred in aPage. If
     439             :   // NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO is not set, then aExtraPage has
     440             :   // no such content.
     441           0 :   if (!aExtraPage->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
     442           0 :     return;
     443             :   }
     444           0 :   nsDisplayList list;
     445           0 :   aExtraPage->BuildDisplayListForStackingContext(aBuilder, aDirtyRect, &list);
     446           0 :   PruneDisplayListForExtraPage(aBuilder, aPage, aExtraPage, &list);
     447           0 :   aList->AppendToTop(&list);
     448             : }
     449             : 
     450             : static nsIFrame*
     451           0 : GetNextPage(nsIFrame* aPageContentFrame)
     452             : {
     453             :   // XXX ugh
     454           0 :   nsIFrame* pageFrame = aPageContentFrame->GetParent();
     455           0 :   NS_ASSERTION(pageFrame->IsPageFrame(),
     456             :                "pageContentFrame has unexpected parent");
     457           0 :   nsIFrame* nextPageFrame = pageFrame->GetNextSibling();
     458           0 :   if (!nextPageFrame)
     459           0 :     return nullptr;
     460           0 :   NS_ASSERTION(nextPageFrame->IsPageFrame(),
     461             :                "pageFrame's sibling is not a page frame...");
     462           0 :   nsIFrame* f = nextPageFrame->PrincipalChildList().FirstChild();
     463           0 :   NS_ASSERTION(f, "pageFrame has no page content frame!");
     464           0 :   NS_ASSERTION(f->IsPageContentFrame(),
     465             :                "pageFrame's child is not page content!");
     466           0 :   return f;
     467             : }
     468             : 
     469           0 : static gfx::Matrix4x4 ComputePageTransform(nsIFrame* aFrame, float aAppUnitsPerPixel)
     470             : {
     471           0 :   float scale = aFrame->PresContext()->GetPageScale();
     472           0 :   return gfx::Matrix4x4::Scaling(scale, scale, 1);
     473             : }
     474             : 
     475             : class nsDisplayHeaderFooter : public nsDisplayItem {
     476             : public:
     477           0 :   nsDisplayHeaderFooter(nsDisplayListBuilder* aBuilder, nsPageFrame *aFrame)
     478           0 :     : nsDisplayItem(aBuilder, aFrame)
     479           0 :     , mDisableSubpixelAA(false)
     480             :   {
     481           0 :     MOZ_COUNT_CTOR(nsDisplayHeaderFooter);
     482           0 :   }
     483             : #ifdef NS_BUILD_REFCNT_LOGGING
     484           0 :   virtual ~nsDisplayHeaderFooter() {
     485           0 :     MOZ_COUNT_DTOR(nsDisplayHeaderFooter);
     486           0 :   }
     487             : #endif
     488             : 
     489           0 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     490             :                      gfxContext* aCtx) override {
     491             : #ifdef DEBUG
     492           0 :     nsPageFrame* pageFrame = do_QueryFrame(mFrame);
     493           0 :     MOZ_ASSERT(pageFrame, "We should have an nsPageFrame");
     494             : #endif
     495           0 :     static_cast<nsPageFrame*>(mFrame)->
     496           0 :       PaintHeaderFooter(*aCtx, ToReferenceFrame(), mDisableSubpixelAA);
     497           0 :   }
     498           0 :   NS_DISPLAY_DECL_NAME("HeaderFooter", nsDisplayItem::TYPE_HEADER_FOOTER)
     499             : 
     500           0 :   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override {
     501             :     bool snap;
     502           0 :     return GetBounds(aBuilder, &snap);
     503             :   }
     504             : 
     505           0 :   virtual void DisableComponentAlpha() override {
     506           0 :     mDisableSubpixelAA = true;
     507           0 :   }
     508             : protected:
     509             :   bool mDisableSubpixelAA;
     510             : };
     511             : 
     512             : //------------------------------------------------------------------------------
     513             : void
     514           0 : nsPageFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     515             :                               const nsRect&           aDirtyRect,
     516             :                               const nsDisplayListSet& aLists)
     517             : {
     518           0 :   nsDisplayListCollection set;
     519             : 
     520           0 :   if (PresContext()->IsScreen()) {
     521           0 :     DisplayBorderBackgroundOutline(aBuilder, aLists);
     522             :   }
     523             : 
     524           0 :   nsIFrame *child = mFrames.FirstChild();
     525           0 :   float scale = PresContext()->GetPageScale();
     526           0 :   nsRect clipRect(nsPoint(0, 0), child->GetSize());
     527             :   // Note: this computation matches how we compute maxSize.height
     528             :   // in nsPageFrame::Reflow
     529           0 :   nscoord expectedPageContentHeight = NSToCoordCeil(GetSize().height / scale);
     530           0 :   if (clipRect.height > expectedPageContentHeight) {
     531             :     // We're doing print-selection, with one long page-content frame.
     532             :     // Clip to the appropriate page-content slice for the current page.
     533           0 :     NS_ASSERTION(mPageNum > 0, "page num should be positive");
     534             :     // Note: The pageContentFrame's y-position has been set such that a zero
     535             :     // y-value matches the top edge of the current page.  So, to clip to the
     536             :     // current page's content (in coordinates *relative* to the page content
     537             :     // frame), we just negate its y-position and add the top margin.
     538           0 :     clipRect.y = NSToCoordCeil((-child->GetRect().y +
     539           0 :                                 mPD->mReflowMargin.top) / scale);
     540           0 :     clipRect.height = expectedPageContentHeight;
     541           0 :     NS_ASSERTION(clipRect.y < child->GetSize().height,
     542             :                  "Should be clipping to region inside the page content bounds");
     543             :   }
     544           0 :   clipRect += aBuilder->ToReferenceFrame(child);
     545             : 
     546           0 :   nsDisplayList content;
     547             :   {
     548           0 :     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     549             : 
     550             :     // Overwrite current clip, since we're going to wrap in a transform
     551             :     // and the current clip is no longer meaningful.
     552           0 :     clipState.Clear();
     553           0 :     clipState.ClipContainingBlockDescendants(clipRect, nullptr);
     554             : 
     555           0 :     nsRect dirtyRect = child->GetVisualOverflowRectRelativeToSelf();
     556           0 :     child->BuildDisplayListForStackingContext(aBuilder, dirtyRect, &content);
     557             : 
     558             :     // We may need to paint out-of-flow frames whose placeholders are
     559             :     // on other pages. Add those pages to our display list. Note that
     560             :     // out-of-flow frames can't be placed after their placeholders so
     561             :     // we don't have to process earlier pages. The display lists for
     562             :     // these extra pages are pruned so that only display items for the
     563             :     // page we currently care about (which we would have reached by
     564             :     // following placeholders to their out-of-flows) end up on the list.
     565           0 :     nsIFrame* page = child;
     566           0 :     while ((page = GetNextPage(page)) != nullptr) {
     567             :       BuildDisplayListForExtraPage(aBuilder, this, page,
     568           0 :           dirtyRect + child->GetOffsetTo(page), &content);
     569             :     }
     570             : 
     571             :     // Invoke AutoBuildingDisplayList to ensure that the correct dirtyRect
     572             :     // is used to compute the visible rect if AddCanvasBackgroundColorItem
     573             :     // creates a display item.
     574             :     nsDisplayListBuilder::AutoBuildingDisplayList
     575           0 :       building(aBuilder, child, dirtyRect, true);
     576             : 
     577             :     // Add the canvas background color to the bottom of the list. This
     578             :     // happens after we've built the list so that AddCanvasBackgroundColorItem
     579             :     // can monkey with the contents if necessary.
     580             :     nsRect backgroundRect =
     581           0 :       nsRect(aBuilder->ToReferenceFrame(child), child->GetSize());
     582           0 :     PresContext()->GetPresShell()->AddCanvasBackgroundColorItem(
     583           0 :       *aBuilder, content, child, backgroundRect, NS_RGBA(0,0,0,0));
     584             :   }
     585             : 
     586           0 :   content.AppendNewToTop(new (aBuilder) nsDisplayTransform(aBuilder, child,
     587           0 :       &content, content.GetVisibleRect(), ::ComputePageTransform));
     588             : 
     589           0 :   set.Content()->AppendToTop(&content);
     590             : 
     591           0 :   if (PresContext()->IsRootPaginatedDocument()) {
     592           0 :     set.Content()->AppendNewToTop(new (aBuilder)
     593           0 :         nsDisplayHeaderFooter(aBuilder, this));
     594             :   }
     595             : 
     596           0 :   set.MoveTo(aLists);
     597           0 : }
     598             : 
     599             : //------------------------------------------------------------------------------
     600             : void
     601           0 : nsPageFrame::SetPageNumInfo(int32_t aPageNumber, int32_t aTotalPages)
     602             : {
     603           0 :   mPageNum     = aPageNumber;
     604           0 :   mTotNumPages = aTotalPages;
     605           0 : }
     606             : 
     607             : 
     608             : void
     609           0 : nsPageFrame::PaintHeaderFooter(gfxContext& aRenderingContext,
     610             :                                nsPoint aPt, bool aDisableSubpixelAA)
     611             : {
     612           0 :   nsPresContext* pc = PresContext();
     613             : 
     614           0 :   if (!mPD->mPrintSettings) {
     615           0 :     if (pc->Type() == nsPresContext::eContext_PrintPreview || pc->IsDynamic())
     616           0 :       mPD->mPrintSettings = pc->GetPrintSettings();
     617           0 :     if (!mPD->mPrintSettings)
     618           0 :       return;
     619             :   }
     620             : 
     621           0 :   nsRect rect(aPt, mRect.Size());
     622           0 :   aRenderingContext.SetColor(Color(0.f, 0.f, 0.f));
     623             : 
     624             :   DrawTargetAutoDisableSubpixelAntialiasing
     625           0 :     disable(aRenderingContext.GetDrawTarget(), aDisableSubpixelAA);
     626             : 
     627             :   // Get the FontMetrics to determine width.height of strings
     628           0 :   nsFontMetrics::Params params;
     629           0 :   params.userFontSet = pc->GetUserFontSet();
     630           0 :   params.textPerf = pc->GetTextPerfMetrics();
     631             :   RefPtr<nsFontMetrics> fontMet =
     632           0 :     pc->DeviceContext()->GetMetricsFor(mPD->mHeadFootFont, params);
     633             : 
     634           0 :   nscoord ascent = 0;
     635           0 :   nscoord visibleHeight = 0;
     636           0 :   if (fontMet) {
     637           0 :     visibleHeight = fontMet->MaxHeight();
     638           0 :     ascent = fontMet->MaxAscent();
     639             :   }
     640             : 
     641             :   // print document headers and footers
     642           0 :   nsXPIDLString headerLeft, headerCenter, headerRight;
     643           0 :   mPD->mPrintSettings->GetHeaderStrLeft(getter_Copies(headerLeft));
     644           0 :   mPD->mPrintSettings->GetHeaderStrCenter(getter_Copies(headerCenter));
     645           0 :   mPD->mPrintSettings->GetHeaderStrRight(getter_Copies(headerRight));
     646           0 :   DrawHeaderFooter(aRenderingContext, *fontMet, eHeader,
     647             :                    headerLeft, headerCenter, headerRight,
     648           0 :                    rect, ascent, visibleHeight);
     649             : 
     650           0 :   nsXPIDLString footerLeft, footerCenter, footerRight;
     651           0 :   mPD->mPrintSettings->GetFooterStrLeft(getter_Copies(footerLeft));
     652           0 :   mPD->mPrintSettings->GetFooterStrCenter(getter_Copies(footerCenter));
     653           0 :   mPD->mPrintSettings->GetFooterStrRight(getter_Copies(footerRight));
     654           0 :   DrawHeaderFooter(aRenderingContext, *fontMet, eFooter,
     655             :                    footerLeft, footerCenter, footerRight,
     656           0 :                    rect, ascent, visibleHeight);
     657             : }
     658             : 
     659             : void
     660           0 : nsPageFrame::SetSharedPageData(nsSharedPageData* aPD)
     661             : {
     662           0 :   mPD = aPD;
     663             :   // Set the shared data into the page frame before reflow
     664           0 :   nsPageContentFrame * pcf = static_cast<nsPageContentFrame*>(mFrames.FirstChild());
     665           0 :   if (pcf) {
     666           0 :     pcf->SetSharedPageData(mPD);
     667             :   }
     668             : 
     669           0 : }
     670             : 
     671             : void
     672           0 : nsPageFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
     673             : {
     674           0 :   MOZ_ASSERT(mFrames.FirstChild() &&
     675             :              mFrames.FirstChild()->IsPageContentFrame(),
     676             :              "pageFrame must have a pageContentFrame child");
     677           0 :   aResult.AppendElement(mFrames.FirstChild());
     678           0 : }
     679             : 
     680             : nsIFrame*
     681           0 : NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
     682             : {
     683           0 :   NS_PRECONDITION(aPresShell, "null PresShell");
     684             :   //check that we are only creating page break frames when printing
     685           0 :   NS_ASSERTION(aPresShell->GetPresContext()->IsPaginated(), "created a page break frame while not printing");
     686             : 
     687           0 :   return new (aPresShell) nsPageBreakFrame(aContext);
     688             : }
     689             : 
     690           0 : NS_IMPL_FRAMEARENA_HELPERS(nsPageBreakFrame)
     691             : 
     692           0 : nsPageBreakFrame::nsPageBreakFrame(nsStyleContext* aContext)
     693             :   : nsLeafFrame(aContext, kClassID)
     694           0 :   , mHaveReflowed(false)
     695             : {
     696           0 : }
     697             : 
     698           0 : nsPageBreakFrame::~nsPageBreakFrame()
     699             : {
     700           0 : }
     701             : 
     702             : nscoord
     703           0 : nsPageBreakFrame::GetIntrinsicISize()
     704             : {
     705           0 :   return nsPresContext::CSSPixelsToAppUnits(1);
     706             : }
     707             : 
     708             : nscoord
     709           0 : nsPageBreakFrame::GetIntrinsicBSize()
     710             : {
     711           0 :   return 0;
     712             : }
     713             : 
     714             : void
     715           0 : nsPageBreakFrame::Reflow(nsPresContext*           aPresContext,
     716             :                          ReflowOutput&     aDesiredSize,
     717             :                          const ReflowInput& aReflowInput,
     718             :                          nsReflowStatus&          aStatus)
     719             : {
     720           0 :   DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame");
     721           0 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     722             : 
     723             :   // Override reflow, since we don't want to deal with what our
     724             :   // computed values are.
     725           0 :   WritingMode wm = aReflowInput.GetWritingMode();
     726           0 :   LogicalSize finalSize(wm, GetIntrinsicISize(),
     727           0 :                         aReflowInput.AvailableBSize() == NS_UNCONSTRAINEDSIZE ?
     728           0 :                           0 : aReflowInput.AvailableBSize());
     729             :   // round the height down to the nearest pixel
     730           0 :   finalSize.BSize(wm) -=
     731           0 :     finalSize.BSize(wm) % nsPresContext::CSSPixelsToAppUnits(1);
     732           0 :   aDesiredSize.SetSize(wm, finalSize);
     733             : 
     734             :   // Note: not using NS_FRAME_FIRST_REFLOW here, since it's not clear whether
     735             :   // DidReflow will always get called before the next Reflow() call.
     736           0 :   mHaveReflowed = true;
     737           0 :   aStatus.Reset();
     738           0 : }
     739             : 
     740             : #ifdef DEBUG_FRAME_DUMP
     741             : nsresult
     742           0 : nsPageBreakFrame::GetFrameName(nsAString& aResult) const
     743             : {
     744           0 :   return MakeFrameName(NS_LITERAL_STRING("PageBreak"), aResult);
     745             : }
     746             : #endif

Generated by: LCOV version 1.13