LCOV - code coverage report
Current view: top level - layout/generic - nsSimplePageSequenceFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 401 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 29 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 "nsSimplePageSequenceFrame.h"
       7             : 
       8             : #include "DateTimeFormat.h"
       9             : #include "nsCOMPtr.h"
      10             : #include "nsDeviceContext.h"
      11             : #include "nsPresContext.h"
      12             : #include "gfxContext.h"
      13             : #include "nsGkAtoms.h"
      14             : #include "nsIPresShell.h"
      15             : #include "nsIPrintSettings.h"
      16             : #include "nsPageFrame.h"
      17             : #include "nsSubDocumentFrame.h"
      18             : #include "nsRegion.h"
      19             : #include "nsCSSFrameConstructor.h"
      20             : #include "nsContentUtils.h"
      21             : #include "nsDisplayList.h"
      22             : #include "nsHTMLCanvasFrame.h"
      23             : #include "mozilla/dom/HTMLCanvasElement.h"
      24             : #include "nsICanvasRenderingContextInternal.h"
      25             : #include "nsServiceManagerUtils.h"
      26             : #include <algorithm>
      27             : 
      28             : #define OFFSET_NOT_SET -1
      29             : 
      30             : using namespace mozilla;
      31             : using namespace mozilla::dom;
      32             : 
      33             : #include "mozilla/Logging.h"
      34             : mozilla::LazyLogModule gLayoutPrintingLog("printing-layout");
      35             : 
      36             : #define PR_PL(_p1)  MOZ_LOG(gLayoutPrintingLog, mozilla::LogLevel::Debug, _p1)
      37             : 
      38             : nsSimplePageSequenceFrame*
      39           0 : NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      40             : {
      41           0 :   return new (aPresShell) nsSimplePageSequenceFrame(aContext);
      42             : }
      43             : 
      44           0 : NS_IMPL_FRAMEARENA_HELPERS(nsSimplePageSequenceFrame)
      45             : 
      46           0 : nsSimplePageSequenceFrame::nsSimplePageSequenceFrame(nsStyleContext* aContext)
      47             :   : nsContainerFrame(aContext, kClassID)
      48             :   , mTotalPages(-1)
      49             :   , mSelectionHeight(-1)
      50             :   , mYSelOffset(0)
      51             :   , mCalledBeginPage(false)
      52           0 :   , mCurrentCanvasListSetup(false)
      53             : {
      54           0 :   nscoord halfInch = PresContext()->CSSTwipsToAppUnits(NS_INCHES_TO_TWIPS(0.5));
      55           0 :   mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch);
      56             : 
      57             :   // XXX Unsafe to assume successful allocation
      58           0 :   mPageData = new nsSharedPageData();
      59           0 :   mPageData->mHeadFootFont =
      60           0 :     *PresContext()->GetDefaultFont(kGenericFont_serif,
      61           0 :                                    aContext->StyleFont()->mLanguage);
      62           0 :   mPageData->mHeadFootFont.size = nsPresContext::CSSPointsToAppUnits(10);
      63             : 
      64             :   // Doing this here so we only have to go get these formats once
      65           0 :   SetPageNumberFormat("pagenumber",  "%1$d", true);
      66           0 :   SetPageNumberFormat("pageofpages", "%1$d of %2$d", false);
      67           0 : }
      68             : 
      69           0 : nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame()
      70             : {
      71           0 :   delete mPageData;
      72           0 :   ResetPrintCanvasList();
      73           0 : }
      74             : 
      75           0 : NS_QUERYFRAME_HEAD(nsSimplePageSequenceFrame)
      76           0 :   NS_QUERYFRAME_ENTRY(nsIPageSequenceFrame)
      77           0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
      78             : 
      79             : //----------------------------------------------------------------------
      80             : 
      81             : void
      82           0 : nsSimplePageSequenceFrame::SetDesiredSize(ReflowOutput& aDesiredSize,
      83             :                                           const ReflowInput& aReflowInput,
      84             :                                           nscoord aWidth,
      85             :                                           nscoord aHeight)
      86             : {
      87             :   // Aim to fill the whole size of the document, not only so we
      88             :   // can act as a background in print preview but also handle overflow
      89             :   // in child page frames correctly.
      90             :   // Use availableISize so we don't cause a needless horizontal scrollbar.
      91           0 :   WritingMode wm = aReflowInput.GetWritingMode();
      92           0 :   nscoord scaledWidth = aWidth * PresContext()->GetPrintPreviewScale();
      93           0 :   nscoord scaledHeight = aHeight * PresContext()->GetPrintPreviewScale();
      94             : 
      95           0 :   nscoord scaledISize = (wm.IsVertical() ? scaledHeight : scaledWidth);
      96           0 :   nscoord scaledBSize = (wm.IsVertical() ? scaledWidth : scaledHeight);
      97             : 
      98           0 :   aDesiredSize.ISize(wm) = std::max(scaledISize, aReflowInput.AvailableISize());
      99           0 :   aDesiredSize.BSize(wm) = std::max(scaledBSize, aReflowInput.ComputedBSize());
     100           0 : }
     101             : 
     102             : // Helper function to compute the offset needed to center a child
     103             : // page-frame's margin-box inside our content-box.
     104             : nscoord
     105           0 : nsSimplePageSequenceFrame::ComputeCenteringMargin(
     106             :   nscoord aContainerContentBoxWidth,
     107             :   nscoord aChildPaddingBoxWidth,
     108             :   const nsMargin& aChildPhysicalMargin)
     109             : {
     110             :   // We'll be centering our child's margin-box, so get the size of that:
     111             :   nscoord childMarginBoxWidth =
     112           0 :     aChildPaddingBoxWidth + aChildPhysicalMargin.LeftRight();
     113             : 
     114             :   // When rendered, our child's rect will actually be scaled up by the
     115             :   // print-preview scale factor, via ComputePageSequenceTransform().
     116             :   // We really want to center *that scaled-up rendering* inside of
     117             :   // aContainerContentBoxWidth.  So, we scale up its margin-box here...
     118           0 :   auto ppScale = PresContext()->GetPrintPreviewScale();
     119             :   nscoord scaledChildMarginBoxWidth =
     120           0 :     NSToCoordRound(childMarginBoxWidth * ppScale);
     121             : 
     122             :   // ...and see we how much space is left over, when we subtract that scaled-up
     123             :   // size from the container width:
     124             :   nscoord scaledExtraSpace =
     125           0 :     aContainerContentBoxWidth - scaledChildMarginBoxWidth;
     126             : 
     127           0 :   if (scaledExtraSpace <= 0) {
     128             :     // (Don't bother centering if there's zero/negative space.)
     129           0 :     return 0;
     130             :   }
     131             : 
     132             :   // To center the child, we want to give it an additional left-margin of half
     133             :   // of the extra space.  And then, we have to scale that space back down, so
     134             :   // that it'll produce the correct scaled-up amount when we render (because
     135             :   // rendering will scale it back up):
     136           0 :   return NSToCoordRound(scaledExtraSpace * 0.5 / ppScale);
     137             : }
     138             : 
     139             : /*
     140             :  * Note: we largely position/size out our children (page frames) using
     141             :  * \*physical\* x/y/width/height values, because the print preview UI is always
     142             :  * arranged in the same orientation, regardless of writing mode.
     143             :  */
     144             : void
     145           0 : nsSimplePageSequenceFrame::Reflow(nsPresContext*     aPresContext,
     146             :                                   ReflowOutput&      aDesiredSize,
     147             :                                   const ReflowInput& aReflowInput,
     148             :                                   nsReflowStatus&    aStatus)
     149             : {
     150           0 :   MarkInReflow();
     151           0 :   NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(),
     152             :                   "A Page Sequence is only for real pages");
     153           0 :   DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame");
     154           0 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     155           0 :   NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow");
     156             : 
     157           0 :   aStatus.Reset();  // we're always complete
     158             : 
     159             :   // Don't do incremental reflow until we've taught tables how to do
     160             :   // it right in paginated mode.
     161           0 :   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     162             :     // Return our desired size
     163           0 :     SetDesiredSize(aDesiredSize, aReflowInput, mSize.width, mSize.height);
     164           0 :     aDesiredSize.SetOverflowAreasToDesiredBounds();
     165           0 :     FinishAndStoreOverflow(&aDesiredSize);
     166             : 
     167           0 :     if (GetRect().Width() != aDesiredSize.Width()) {
     168             :       // Our width is changing; we need to re-center our children (our pages).
     169           0 :       for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
     170           0 :         nsIFrame* child = e.get();
     171           0 :         nsMargin pageCSSMargin = child->GetUsedMargin();
     172             :         nscoord centeringMargin =
     173           0 :           ComputeCenteringMargin(aReflowInput.ComputedWidth(),
     174           0 :                                  child->GetRect().Width(),
     175           0 :                                  pageCSSMargin);
     176           0 :         nscoord newX = pageCSSMargin.left + centeringMargin;
     177             : 
     178             :         // Adjust the child's x-position:
     179           0 :         child->MovePositionBy(nsPoint(newX - child->GetNormalPosition().x, 0));
     180             :       }
     181             :     }
     182           0 :     return;
     183             :   }
     184             : 
     185             :   // See if we can get a Print Settings from the Context
     186           0 :   if (!mPageData->mPrintSettings &&
     187           0 :       aPresContext->Medium() == nsGkAtoms::print) {
     188           0 :       mPageData->mPrintSettings = aPresContext->GetPrintSettings();
     189             :   }
     190             : 
     191             :   // now get out margins & edges
     192           0 :   if (mPageData->mPrintSettings) {
     193           0 :     nsIntMargin unwriteableTwips;
     194           0 :     mPageData->mPrintSettings->GetUnwriteableMarginInTwips(unwriteableTwips);
     195           0 :     NS_ASSERTION(unwriteableTwips.left  >= 0 && unwriteableTwips.top >= 0 &&
     196             :                  unwriteableTwips.right >= 0 && unwriteableTwips.bottom >= 0,
     197             :                  "Unwriteable twips should be non-negative");
     198             : 
     199           0 :     nsIntMargin marginTwips;
     200           0 :     mPageData->mPrintSettings->GetMarginInTwips(marginTwips);
     201           0 :     mMargin = aPresContext->CSSTwipsToAppUnits(marginTwips + unwriteableTwips);
     202             : 
     203             :     int16_t printType;
     204           0 :     mPageData->mPrintSettings->GetPrintRange(&printType);
     205           0 :     mPrintRangeType = printType;
     206             : 
     207           0 :     nsIntMargin edgeTwips;
     208           0 :     mPageData->mPrintSettings->GetEdgeInTwips(edgeTwips);
     209             : 
     210             :     // sanity check the values. three inches are sometimes needed
     211           0 :     int32_t inchInTwips = NS_INCHES_TO_INT_TWIPS(3.0);
     212           0 :     edgeTwips.top    = clamped(edgeTwips.top,    0, inchInTwips);
     213           0 :     edgeTwips.bottom = clamped(edgeTwips.bottom, 0, inchInTwips);
     214           0 :     edgeTwips.left   = clamped(edgeTwips.left,   0, inchInTwips);
     215           0 :     edgeTwips.right  = clamped(edgeTwips.right,  0, inchInTwips);
     216             : 
     217           0 :     mPageData->mEdgePaperMargin =
     218           0 :       aPresContext->CSSTwipsToAppUnits(edgeTwips + unwriteableTwips);
     219             :   }
     220             : 
     221             :   // *** Special Override ***
     222             :   // If this is a sub-sdoc (meaning it doesn't take the whole page)
     223             :   // and if this Document is in the upper left hand corner
     224             :   // we need to suppress the top margin or it will reflow too small
     225             : 
     226           0 :   nsSize pageSize = aPresContext->GetPageSize();
     227             : 
     228           0 :   mPageData->mReflowSize = pageSize;
     229             :   // If we're printing a selection, we need to reflow with
     230             :   // unconstrained height, to make sure we'll get to the selection
     231             :   // even if it's beyond the first page of content.
     232           0 :   if (nsIPrintSettings::kRangeSelection == mPrintRangeType) {
     233           0 :     mPageData->mReflowSize.height = NS_UNCONSTRAINEDSIZE;
     234             :   }
     235           0 :   mPageData->mReflowMargin = mMargin;
     236             : 
     237             :   // We use the CSS "margin" property on the -moz-page pseudoelement
     238             :   // to determine the space between each page in print preview.
     239             :   // Keep a running y-offset for each page.
     240           0 :   nscoord y = 0;
     241           0 :   nscoord maxXMost = 0;
     242             : 
     243             :   // Tile the pages vertically
     244           0 :   ReflowOutput kidSize(aReflowInput);
     245           0 :   for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
     246           0 :     nsIFrame* kidFrame = e.get();
     247             :     // Set the shared data into the page frame before reflow
     248           0 :     nsPageFrame * pf = static_cast<nsPageFrame*>(kidFrame);
     249           0 :     pf->SetSharedPageData(mPageData);
     250             : 
     251             :     // Reflow the page
     252             :     ReflowInput kidReflowInput(aPresContext, aReflowInput, kidFrame,
     253           0 :                                LogicalSize(kidFrame->GetWritingMode(),
     254           0 :                                                  pageSize));
     255           0 :     nsReflowStatus  status;
     256             : 
     257           0 :     kidReflowInput.SetComputedISize(kidReflowInput.AvailableISize());
     258             :     //kidReflowInput.SetComputedHeight(kidReflowInput.AvailableHeight());
     259           0 :     PR_PL(("AV ISize: %d   BSize: %d\n",
     260             :            kidReflowInput.AvailableISize(),
     261             :            kidReflowInput.AvailableBSize()));
     262             : 
     263           0 :     nsMargin pageCSSMargin = kidReflowInput.ComputedPhysicalMargin();
     264           0 :     y += pageCSSMargin.top;
     265             : 
     266           0 :     nscoord x = pageCSSMargin.left;
     267             : 
     268             :     // Place and size the page.
     269           0 :     ReflowChild(kidFrame, aPresContext, kidSize, kidReflowInput, x, y, 0, status);
     270             : 
     271             :     // If the page is narrower than our width, then center it horizontally:
     272           0 :     x += ComputeCenteringMargin(aReflowInput.ComputedWidth(),
     273           0 :                                 kidSize.Width(), pageCSSMargin);
     274             : 
     275           0 :     FinishReflowChild(kidFrame, aPresContext, kidSize, nullptr, x, y, 0);
     276           0 :     y += kidSize.Height();
     277           0 :     y += pageCSSMargin.bottom;
     278             : 
     279           0 :     maxXMost = std::max(maxXMost, x + kidSize.Width() + pageCSSMargin.right);
     280             : 
     281             :     // Is the page complete?
     282           0 :     nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
     283             : 
     284           0 :     if (status.IsFullyComplete()) {
     285           0 :       NS_ASSERTION(!kidNextInFlow, "bad child flow list");
     286           0 :     } else if (!kidNextInFlow) {
     287             :       // The page isn't complete and it doesn't have a next-in-flow, so
     288             :       // create a continuing page.
     289             :       nsIFrame* continuingPage = aPresContext->PresShell()->FrameConstructor()->
     290           0 :         CreateContinuingFrame(aPresContext, kidFrame, this);
     291             : 
     292             :       // Add it to our child list
     293           0 :       mFrames.InsertFrame(nullptr, kidFrame, continuingPage);
     294             :     }
     295             :   }
     296             : 
     297             :   // Get Total Page Count
     298             :   // XXXdholbert technically we could calculate this in the loop above,
     299             :   // instead of needing a separate walk.
     300           0 :   int32_t pageTot = mFrames.GetLength();
     301             : 
     302             :   // Set Page Number Info
     303           0 :   int32_t pageNum = 1;
     304           0 :   for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
     305           0 :     MOZ_ASSERT(e.get()->IsPageFrame(),
     306             :                "only expecting nsPageFrame children. Other children will make "
     307             :                "this static_cast bogus & probably violate other assumptions");
     308           0 :     nsPageFrame* pf = static_cast<nsPageFrame*>(e.get());
     309           0 :     pf->SetPageNumInfo(pageNum, pageTot);
     310           0 :     pageNum++;
     311             :   }
     312             : 
     313           0 :   nsAutoString formattedDateString;
     314             :   time_t ltime;
     315           0 :   time( &ltime );
     316           0 :   if (NS_SUCCEEDED(DateTimeFormat::FormatTime(kDateFormatShort,
     317             :                                               kTimeFormatNoSeconds,
     318             :                                               ltime,
     319             :                                               formattedDateString))) {
     320           0 :     SetDateTimeStr(formattedDateString);
     321             :   }
     322             : 
     323             :   // Return our desired size
     324             :   // Adjust the reflow size by PrintPreviewScale so the scrollbars end up the
     325             :   // correct size
     326           0 :   SetDesiredSize(aDesiredSize, aReflowInput, maxXMost, y);
     327             : 
     328           0 :   aDesiredSize.SetOverflowAreasToDesiredBounds();
     329           0 :   FinishAndStoreOverflow(&aDesiredSize);
     330             : 
     331             :   // cache the size so we can set the desired size
     332             :   // for the other reflows that happen
     333           0 :   mSize.width  = maxXMost;
     334           0 :   mSize.height = y;
     335             : 
     336           0 :   NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus);
     337           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     338             : }
     339             : 
     340             : //----------------------------------------------------------------------
     341             : 
     342             : #ifdef DEBUG_FRAME_DUMP
     343             : nsresult
     344           0 : nsSimplePageSequenceFrame::GetFrameName(nsAString& aResult) const
     345             : {
     346           0 :   return MakeFrameName(NS_LITERAL_STRING("SimplePageSequence"), aResult);
     347             : }
     348             : #endif
     349             : 
     350             : //====================================================================
     351             : //== Asynch Printing
     352             : //====================================================================
     353             : NS_IMETHODIMP
     354           0 : nsSimplePageSequenceFrame::GetCurrentPageNum(int32_t* aPageNum)
     355             : {
     356           0 :   NS_ENSURE_ARG_POINTER(aPageNum);
     357             : 
     358           0 :   *aPageNum = mPageNum;
     359           0 :   return NS_OK;
     360             : }
     361             : 
     362             : NS_IMETHODIMP
     363           0 : nsSimplePageSequenceFrame::GetNumPages(int32_t* aNumPages)
     364             : {
     365           0 :   NS_ENSURE_ARG_POINTER(aNumPages);
     366             : 
     367           0 :   *aNumPages = mTotalPages;
     368           0 :   return NS_OK;
     369             : }
     370             : 
     371             : NS_IMETHODIMP
     372           0 : nsSimplePageSequenceFrame::IsDoingPrintRange(bool* aDoing)
     373             : {
     374           0 :   NS_ENSURE_ARG_POINTER(aDoing);
     375             : 
     376           0 :   *aDoing = mDoingPageRange;
     377           0 :   return NS_OK;
     378             : }
     379             : 
     380             : NS_IMETHODIMP
     381           0 : nsSimplePageSequenceFrame::GetPrintRange(int32_t* aFromPage, int32_t* aToPage)
     382             : {
     383           0 :   NS_ENSURE_ARG_POINTER(aFromPage);
     384           0 :   NS_ENSURE_ARG_POINTER(aToPage);
     385             : 
     386           0 :   *aFromPage = mFromPageNum;
     387           0 :   *aToPage   = mToPageNum;
     388           0 :   return NS_OK;
     389             : }
     390             : 
     391             : // Helper Function
     392             : void
     393           0 : nsSimplePageSequenceFrame::SetPageNumberFormat(const char* aPropName, const char* aDefPropVal, bool aPageNumOnly)
     394             : {
     395             :   // Doing this here so we only have to go get these formats once
     396           0 :   nsXPIDLString pageNumberFormat;
     397             :   // Now go get the Localized Page Formating String
     398             :   nsresult rv =
     399             :     nsContentUtils::GetLocalizedString(nsContentUtils::ePRINTING_PROPERTIES,
     400           0 :                                        aPropName, pageNumberFormat);
     401           0 :   if (NS_FAILED(rv)) { // back stop formatting
     402           0 :     pageNumberFormat.AssignASCII(aDefPropVal);
     403             :   }
     404             : 
     405           0 :   SetPageNumberFormat(pageNumberFormat, aPageNumOnly);
     406           0 : }
     407             : 
     408             : NS_IMETHODIMP
     409           0 : nsSimplePageSequenceFrame::StartPrint(nsPresContext*    aPresContext,
     410             :                                       nsIPrintSettings* aPrintSettings,
     411             :                                       const nsAString&  aDocTitle,
     412             :                                       const nsAString&  aDocURL)
     413             : {
     414           0 :   NS_ENSURE_ARG_POINTER(aPresContext);
     415           0 :   NS_ENSURE_ARG_POINTER(aPrintSettings);
     416             : 
     417           0 :   if (!mPageData->mPrintSettings) {
     418           0 :     mPageData->mPrintSettings = aPrintSettings;
     419             :   }
     420             : 
     421           0 :   if (!aDocTitle.IsEmpty()) {
     422           0 :     mPageData->mDocTitle = aDocTitle;
     423             :   }
     424           0 :   if (!aDocURL.IsEmpty()) {
     425           0 :     mPageData->mDocURL = aDocURL;
     426             :   }
     427             : 
     428           0 :   aPrintSettings->GetStartPageRange(&mFromPageNum);
     429           0 :   aPrintSettings->GetEndPageRange(&mToPageNum);
     430           0 :   aPrintSettings->GetPageRanges(mPageRanges);
     431             : 
     432           0 :   mDoingPageRange = nsIPrintSettings::kRangeSpecifiedPageRange == mPrintRangeType ||
     433           0 :                     nsIPrintSettings::kRangeSelection == mPrintRangeType;
     434             : 
     435             :   // If printing a range of pages make sure at least the starting page
     436             :   // number is valid
     437           0 :   int32_t totalPages = mFrames.GetLength();
     438             : 
     439           0 :   if (mDoingPageRange) {
     440           0 :     if (mFromPageNum > totalPages) {
     441           0 :       return NS_ERROR_INVALID_ARG;
     442             :     }
     443             :   }
     444             : 
     445             :   // Begin printing of the document
     446           0 :   nsresult rv = NS_OK;
     447             : 
     448             :   // Determine if we are rendering only the selection
     449           0 :   aPresContext->SetIsRenderingOnlySelection(nsIPrintSettings::kRangeSelection == mPrintRangeType);
     450             : 
     451             : 
     452           0 :   if (mDoingPageRange) {
     453             :     // XXX because of the hack for making the selection all print on one page
     454             :     // we must make sure that the page is sized correctly before printing.
     455           0 :     nscoord height = aPresContext->GetPageSize().height;
     456             : 
     457           0 :     int32_t pageNum = 1;
     458           0 :     nscoord y = 0;//mMargin.top;
     459             : 
     460           0 :     for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
     461           0 :       nsIFrame* page = e.get();
     462           0 :       if (pageNum >= mFromPageNum && pageNum <= mToPageNum) {
     463           0 :         nsRect rect = page->GetRect();
     464           0 :         rect.y = y;
     465           0 :         rect.height = height;
     466           0 :         page->SetRect(rect);
     467           0 :         y += rect.height + mMargin.top + mMargin.bottom;
     468             :       }
     469           0 :       pageNum++;
     470             :     }
     471             : 
     472             :     // adjust total number of pages
     473           0 :     if (nsIPrintSettings::kRangeSelection != mPrintRangeType) {
     474           0 :       totalPages = pageNum - 1;
     475             :     }
     476             :   }
     477             : 
     478           0 :   mPageNum = 1;
     479             : 
     480           0 :   if (mTotalPages == -1) {
     481           0 :     mTotalPages = totalPages;
     482             :   }
     483             : 
     484           0 :   return rv;
     485             : }
     486             : 
     487             : void
     488           0 : GetPrintCanvasElementsInFrame(nsIFrame* aFrame, nsTArray<RefPtr<HTMLCanvasElement> >* aArr)
     489             : {
     490           0 :   if (!aFrame) {
     491           0 :     return;
     492             :   }
     493           0 :   for (nsIFrame::ChildListIterator childLists(aFrame);
     494           0 :     !childLists.IsDone(); childLists.Next()) {
     495             : 
     496           0 :     nsFrameList children = childLists.CurrentList();
     497           0 :     for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) {
     498           0 :       nsIFrame* child = e.get();
     499             : 
     500             :       // Check if child is a nsHTMLCanvasFrame.
     501           0 :       nsHTMLCanvasFrame* canvasFrame = do_QueryFrame(child);
     502             : 
     503             :       // If there is a canvasFrame, try to get actual canvas element.
     504           0 :       if (canvasFrame) {
     505             :         HTMLCanvasElement* canvas =
     506           0 :           HTMLCanvasElement::FromContentOrNull(canvasFrame->GetContent());
     507           0 :         if (canvas && canvas->GetMozPrintCallback()) {
     508           0 :           aArr->AppendElement(canvas);
     509           0 :           continue;
     510             :         }
     511             :       }
     512             : 
     513           0 :       if (!child->PrincipalChildList().FirstChild()) {
     514           0 :         nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(child);
     515           0 :         if (subdocumentFrame) {
     516             :           // Descend into the subdocument
     517           0 :           nsIFrame* root = subdocumentFrame->GetSubdocumentRootFrame();
     518           0 :           child = root;
     519             :         }
     520             :       }
     521             :       // The current child is not a nsHTMLCanvasFrame OR it is but there is
     522             :       // no HTMLCanvasElement on it. Check if children of `child` might
     523             :       // contain a HTMLCanvasElement.
     524           0 :       GetPrintCanvasElementsInFrame(child, aArr);
     525             :     }
     526             :   }
     527             : }
     528             : 
     529             : void
     530           0 : nsSimplePageSequenceFrame::DetermineWhetherToPrintPage()
     531             : {
     532             :   // See whether we should print this page
     533           0 :   mPrintThisPage = true;
     534             :   bool printEvenPages, printOddPages;
     535           0 :   mPageData->mPrintSettings->GetPrintOptions(nsIPrintSettings::kPrintEvenPages, &printEvenPages);
     536           0 :   mPageData->mPrintSettings->GetPrintOptions(nsIPrintSettings::kPrintOddPages, &printOddPages);
     537             : 
     538             :   // If printing a range of pages check whether the page number is in the
     539             :   // range of pages to print
     540           0 :   if (mDoingPageRange) {
     541           0 :     if (mPageNum < mFromPageNum) {
     542           0 :       mPrintThisPage = false;
     543           0 :     } else if (mPageNum > mToPageNum) {
     544           0 :       mPageNum++;
     545           0 :       mPrintThisPage = false;
     546           0 :       return;
     547             :     } else {
     548           0 :       int32_t length = mPageRanges.Length();
     549             : 
     550             :       // Page ranges are pairs (start, end)
     551           0 :       if (length && (length % 2 == 0)) {
     552           0 :         mPrintThisPage = false;
     553             : 
     554             :         int32_t i;
     555           0 :         for (i = 0; i < length; i += 2) {
     556           0 :           if (mPageRanges[i] <= mPageNum && mPageNum <= mPageRanges[i+1]) {
     557           0 :             mPrintThisPage = true;
     558           0 :             break;
     559             :           }
     560             :         }
     561             :       }
     562             :     }
     563             :   }
     564             : 
     565             :   // Check for printing of odd and even pages
     566           0 :   if (mPageNum & 0x1) {
     567           0 :     if (!printOddPages) {
     568           0 :       mPrintThisPage = false;  // don't print odd numbered page
     569             :     }
     570             :   } else {
     571           0 :     if (!printEvenPages) {
     572           0 :       mPrintThisPage = false;  // don't print even numbered page
     573             :     }
     574             :   }
     575             : 
     576           0 :   if (nsIPrintSettings::kRangeSelection == mPrintRangeType) {
     577           0 :     mPrintThisPage = true;
     578             :   }
     579             : }
     580             : 
     581             : nsIFrame*
     582           0 : nsSimplePageSequenceFrame::GetCurrentPageFrame()
     583             : {
     584           0 :   int32_t i = 1;
     585           0 :   for (nsFrameList::Enumerator childFrames(mFrames); !childFrames.AtEnd();
     586           0 :        childFrames.Next()) {
     587           0 :     if (i == mPageNum) {
     588           0 :       return childFrames.get();
     589             :     }
     590           0 :     ++i;
     591             :   }
     592           0 :   return nullptr;
     593             : }
     594             : 
     595             : NS_IMETHODIMP
     596           0 : nsSimplePageSequenceFrame::PrePrintNextPage(nsITimerCallback* aCallback, bool* aDone)
     597             : {
     598           0 :   nsIFrame* currentPage = GetCurrentPageFrame();
     599           0 :   if (!currentPage) {
     600           0 :     *aDone = true;
     601           0 :     return NS_ERROR_FAILURE;
     602             :   }
     603             : 
     604           0 :   DetermineWhetherToPrintPage();
     605             :   // Nothing to do if the current page doesn't get printed OR rendering to
     606             :   // preview. For preview, the `CallPrintCallback` is called from within the
     607             :   // HTMLCanvasElement::HandlePrintCallback.
     608           0 :   if (!mPrintThisPage || !PresContext()->IsRootPaginatedDocument()) {
     609           0 :     *aDone = true;
     610           0 :     return NS_OK;
     611             :   }
     612             : 
     613             :   // If the canvasList is null, then generate it and start the render
     614             :   // process for all the canvas.
     615           0 :   if (!mCurrentCanvasListSetup) {
     616           0 :     mCurrentCanvasListSetup = true;
     617           0 :     GetPrintCanvasElementsInFrame(currentPage, &mCurrentCanvasList);
     618             : 
     619           0 :     if (mCurrentCanvasList.Length() != 0) {
     620           0 :       nsresult rv = NS_OK;
     621             : 
     622             :       // Begin printing of the document
     623           0 :       nsDeviceContext *dc = PresContext()->DeviceContext();
     624           0 :       PR_PL(("\n"));
     625           0 :       PR_PL(("***************** BeginPage *****************\n"));
     626           0 :       rv = dc->BeginPage();
     627           0 :       NS_ENSURE_SUCCESS(rv, rv);
     628             : 
     629           0 :       mCalledBeginPage = true;
     630             : 
     631           0 :       RefPtr<gfxContext> renderingContext = dc->CreateRenderingContext();
     632           0 :       NS_ENSURE_TRUE(renderingContext, NS_ERROR_OUT_OF_MEMORY);
     633             : 
     634           0 :       DrawTarget* drawTarget = renderingContext->GetDrawTarget();
     635           0 :       if (NS_WARN_IF(!drawTarget)) {
     636           0 :         return NS_ERROR_FAILURE;
     637             :       }
     638             : 
     639           0 :       for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0 ; i--) {
     640           0 :         HTMLCanvasElement* canvas = mCurrentCanvasList[i];
     641           0 :         nsIntSize size = canvas->GetSize();
     642             : 
     643             :         RefPtr<DrawTarget> canvasTarget =
     644           0 :           drawTarget->CreateSimilarDrawTarget(size, drawTarget->GetFormat());
     645           0 :         if (!canvasTarget) {
     646           0 :           continue;
     647             :         }
     648             : 
     649           0 :         nsICanvasRenderingContextInternal* ctx = canvas->GetContextAtIndex(0);
     650           0 :         if (!ctx) {
     651           0 :           continue;
     652             :         }
     653             : 
     654             :         // Initialize the context with the new DrawTarget.
     655           0 :         ctx->InitializeWithDrawTarget(nullptr, WrapNotNull(canvasTarget));
     656             : 
     657             :         // Start the rendering process.
     658           0 :         AutoWeakFrame weakFrame = this;
     659           0 :         canvas->DispatchPrintCallback(aCallback);
     660           0 :         NS_ENSURE_STATE(weakFrame.IsAlive());
     661             :       }
     662             :     }
     663             :   }
     664           0 :   uint32_t doneCounter = 0;
     665           0 :   for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0 ; i--) {
     666           0 :     HTMLCanvasElement* canvas = mCurrentCanvasList[i];
     667             : 
     668           0 :     if (canvas->IsPrintCallbackDone()) {
     669           0 :       doneCounter++;
     670             :     }
     671             :   }
     672             :   // If all canvas have finished rendering, return true, otherwise false.
     673           0 :   *aDone = doneCounter == mCurrentCanvasList.Length();
     674             : 
     675           0 :   return NS_OK;
     676             : }
     677             : 
     678             : NS_IMETHODIMP
     679           0 : nsSimplePageSequenceFrame::ResetPrintCanvasList()
     680             : {
     681           0 :   for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0 ; i--) {
     682           0 :     HTMLCanvasElement* canvas = mCurrentCanvasList[i];
     683           0 :     canvas->ResetPrintCallback();
     684             :   }
     685             : 
     686           0 :   mCurrentCanvasList.Clear();
     687           0 :   mCurrentCanvasListSetup = false;
     688           0 :   return NS_OK;
     689             : }
     690             : 
     691             : NS_IMETHODIMP
     692           0 : nsSimplePageSequenceFrame::PrintNextPage()
     693             : {
     694             :   // This method would be very straightforward except that the
     695             :   // "Print Selection Only" functionality (which is a broken mess) is
     696             :   // integrated here.  The thing to understand is that if we're printing a
     697             :   // selection (which may contain multiple ranges) then we only enter this
     698             :   // function once since the content to print is laid out as one arbitrarily
     699             :   // long nsPageFrame instead of multiple nsPageFrames that are sized to fit
     700             :   // the printer paper size(!).  Each of the "pages" between the start and end
     701             :   // of the selection are printed by offsetting the nsPageContentFrame by the
     702             :   // index of the page being printed and then drawing the nsPageContentFrame.
     703             :   // This does not work for IFrames.
     704             :   //
     705             :   // Note: When print al the pages or a page range the printed page shows the
     706             :   // actual page number, when printing selection it prints the page number starting
     707             :   // with the first page of the selection. For example if the user has a
     708             :   // selection that starts on page 2 and ends on page 3, the page numbers when
     709             :   // print are 1 and then two (which is different than printing a page range, where
     710             :   // the page numbers would have been 2 and then 3)
     711             : 
     712           0 :   nsIFrame* currentPageFrame = GetCurrentPageFrame();
     713           0 :   if (!currentPageFrame) {
     714           0 :     return NS_ERROR_FAILURE;
     715             :   }
     716             : 
     717           0 :   nsresult rv = NS_OK;
     718             : 
     719           0 :   DetermineWhetherToPrintPage();
     720             : 
     721           0 :   if (mPrintThisPage) {
     722           0 :     nsDeviceContext* dc = PresContext()->DeviceContext();
     723             : 
     724           0 :     nsPageFrame * pf = static_cast<nsPageFrame*>(currentPageFrame);
     725           0 :     pf->SetPageNumInfo(mPageNum, mTotalPages);
     726           0 :     pf->SetSharedPageData(mPageData);
     727             : 
     728             :     // Only used if we're printing a selection:
     729           0 :     nsIFrame* selectionContentFrame = nullptr;
     730             :     nscoord pageContentHeight =
     731           0 :       PresContext()->GetPageSize().height - (mMargin.top + mMargin.bottom);
     732           0 :     nscoord selectionY = pageContentHeight;
     733           0 :     int32_t selectionCurrentPageNum = 1;
     734           0 :     bool haveUnfinishedSelectionToPrint = false;
     735             : 
     736           0 :     if (mSelectionHeight >= 0) {
     737           0 :       selectionContentFrame = currentPageFrame->PrincipalChildList().FirstChild();
     738           0 :       MOZ_ASSERT(selectionContentFrame->IsPageContentFrame() &&
     739             :                  !selectionContentFrame->GetNextSibling(),
     740             :                  "Unexpected frame tree");
     741             :       // To print a selection we reposition the page content frame for each
     742             :       // page.  We can do this (and not have to bother resetting the position
     743             :       // after we're done) because we are printing from a static clone document
     744             :       // that is thrown away after we finish printing.
     745           0 :       selectionContentFrame->SetPosition(selectionContentFrame->GetPosition() +
     746           0 :                                          nsPoint(0, -mYSelOffset));
     747           0 :       nsContainerFrame::PositionChildViews(selectionContentFrame);
     748             :     }
     749             : 
     750           0 :     do {
     751           0 :       if (PresContext()->IsRootPaginatedDocument()) {
     752           0 :         if (!mCalledBeginPage) {
     753             :           // We must make sure BeginPage() has been called since some printing
     754             :           // backends can't give us a valid rendering context for a [physical]
     755             :           // page otherwise.
     756           0 :           PR_PL(("\n"));
     757           0 :           PR_PL(("***************** BeginPage *****************\n"));
     758           0 :           rv = dc->BeginPage();
     759           0 :           NS_ENSURE_SUCCESS(rv, rv);
     760             :         }
     761             : 
     762             :         // Reset this flag. We reset it early here because if we loop around to
     763             :         // print another page's worth of selection we need to call BeginPage
     764             :         // again:
     765           0 :         mCalledBeginPage = false;
     766             :       }
     767             : 
     768           0 :       PR_PL(("SeqFr::PrintNextPage -> %p PageNo: %d", pf, mPageNum));
     769             : 
     770             :       // CreateRenderingContext can fail
     771           0 :       RefPtr<gfxContext> gCtx = dc->CreateRenderingContext();
     772           0 :       NS_ENSURE_TRUE(gCtx, NS_ERROR_OUT_OF_MEMORY);
     773             : 
     774           0 :       nsRect drawingRect(nsPoint(0, 0), currentPageFrame->GetSize());
     775           0 :       nsRegion drawingRegion(drawingRect);
     776           0 :       nsLayoutUtils::PaintFrame(gCtx, currentPageFrame,
     777             :                                 drawingRegion, NS_RGBA(0,0,0,0),
     778             :                                 nsDisplayListBuilderMode::PAINTING,
     779           0 :                                 nsLayoutUtils::PaintFrameFlags::PAINT_SYNC_DECODE_IMAGES);
     780             : 
     781           0 :       if (mSelectionHeight >= 0) {
     782           0 :         haveUnfinishedSelectionToPrint = (selectionY < mSelectionHeight);
     783           0 :         if (haveUnfinishedSelectionToPrint) {
     784           0 :           selectionY += pageContentHeight;
     785           0 :           selectionCurrentPageNum++;
     786           0 :           pf->SetPageNumInfo(selectionCurrentPageNum, mTotalPages);
     787           0 :           selectionContentFrame->SetPosition(selectionContentFrame->GetPosition() +
     788           0 :                                              nsPoint(0, -pageContentHeight));
     789           0 :           nsContainerFrame::PositionChildViews(selectionContentFrame);
     790             : 
     791             :           // We're going to loop and call BeginPage to print another page's worth
     792             :           // of selection so we need to call EndPage first.  (Otherwise, EndPage
     793             :           // is called in DoEndPage.)
     794           0 :           PR_PL(("***************** End Page (PrintNextPage) *****************\n"));
     795           0 :           rv = dc->EndPage();
     796           0 :           NS_ENSURE_SUCCESS(rv, rv);
     797             :         }
     798             :       }
     799             :     } while (haveUnfinishedSelectionToPrint);
     800             :   }
     801           0 :   return rv;
     802             : }
     803             : 
     804             : NS_IMETHODIMP
     805           0 : nsSimplePageSequenceFrame::DoPageEnd()
     806             : {
     807           0 :   nsresult rv = NS_OK;
     808           0 :   if (PresContext()->IsRootPaginatedDocument() && mPrintThisPage) {
     809           0 :     PR_PL(("***************** End Page (DoPageEnd) *****************\n"));
     810           0 :     rv = PresContext()->DeviceContext()->EndPage();
     811           0 :     NS_ENSURE_SUCCESS(rv, rv);
     812             :   }
     813             : 
     814           0 :   ResetPrintCanvasList();
     815             : 
     816           0 :   mPageNum++;
     817             : 
     818           0 :   return rv;
     819             : }
     820             : 
     821             : inline gfx::Matrix4x4
     822           0 : ComputePageSequenceTransform(nsIFrame* aFrame, float aAppUnitsPerPixel)
     823             : {
     824           0 :   float scale = aFrame->PresContext()->GetPrintPreviewScale();
     825           0 :   return gfx::Matrix4x4::Scaling(scale, scale, 1);
     826             : }
     827             : 
     828             : void
     829           0 : nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     830             :                                             const nsRect&           aDirtyRect,
     831             :                                             const nsDisplayListSet& aLists)
     832             : {
     833           0 :   DisplayBorderBackgroundOutline(aBuilder, aLists);
     834             : 
     835           0 :   nsDisplayList content;
     836             : 
     837             :   {
     838             :     // Clear clip state while we construct the children of the
     839             :     // nsDisplayTransform, since they'll be in a different coordinate system.
     840           0 :     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     841           0 :     clipState.Clear();
     842             : 
     843           0 :     nsIFrame* child = PrincipalChildList().FirstChild();
     844           0 :     nsRect dirty = aDirtyRect;
     845           0 :     dirty.ScaleInverseRoundOut(PresContext()->GetPrintPreviewScale());
     846             : 
     847           0 :     while (child) {
     848           0 :       if (child->GetVisualOverflowRectRelativeToParent().Intersects(dirty)) {
     849             :         child->BuildDisplayListForStackingContext(aBuilder,
     850           0 :             dirty - child->GetPosition(), &content);
     851           0 :         aBuilder->ResetMarkedFramesForDisplayList();
     852             :       }
     853           0 :       child = child->GetNextSibling();
     854             :     }
     855             :   }
     856             : 
     857           0 :   content.AppendNewToTop(new (aBuilder)
     858           0 :       nsDisplayTransform(aBuilder, this, &content, content.GetVisibleRect(),
     859           0 :                          ::ComputePageSequenceTransform));
     860             : 
     861           0 :   aLists.Content()->AppendToTop(&content);
     862           0 : }
     863             : 
     864             : //------------------------------------------------------------------------------
     865             : void
     866           0 : nsSimplePageSequenceFrame::SetPageNumberFormat(const nsAString& aFormatStr, bool aForPageNumOnly)
     867             : {
     868           0 :   NS_ASSERTION(mPageData != nullptr, "mPageData string cannot be null!");
     869             : 
     870           0 :   if (aForPageNumOnly) {
     871           0 :     mPageData->mPageNumFormat = aFormatStr;
     872             :   } else {
     873           0 :     mPageData->mPageNumAndTotalsFormat = aFormatStr;
     874             :   }
     875           0 : }
     876             : 
     877             : //------------------------------------------------------------------------------
     878             : void
     879           0 : nsSimplePageSequenceFrame::SetDateTimeStr(const nsAString& aDateTimeStr)
     880             : {
     881           0 :   NS_ASSERTION(mPageData != nullptr, "mPageData string cannot be null!");
     882             : 
     883           0 :   mPageData->mDateTimeStr = aDateTimeStr;
     884           0 : }
     885             : 
     886             : //------------------------------------------------------------------------------
     887             : // For Shrink To Fit
     888             : //
     889             : // Return the percentage that the page needs to shrink to
     890             : //
     891             : NS_IMETHODIMP
     892           0 : nsSimplePageSequenceFrame::GetSTFPercent(float& aSTFPercent)
     893             : {
     894           0 :   NS_ENSURE_TRUE(mPageData, NS_ERROR_UNEXPECTED);
     895           0 :   aSTFPercent = mPageData->mShrinkToFitRatio;
     896           0 :   return NS_OK;
     897             : }
     898             : 
     899             : void
     900           0 : nsSimplePageSequenceFrame::AppendDirectlyOwnedAnonBoxes(
     901             :   nsTArray<OwnedAnonBox>& aResult)
     902             : {
     903           0 :   if (mFrames.NotEmpty()) {
     904           0 :     aResult.AppendElement(mFrames.FirstChild());
     905             :   }
     906           0 : }

Generated by: LCOV version 1.13