gecko-dev/layout/generic/nsPageSequenceFrame.h
Jonathan Watt 56ad2d82c5 Bug 1830900. Move multiple pages-per-sheet grid calculations to be per-sheet, not per-print. r=AlaskanEmily
To support mixed sheet orientations when printing, these calculations need to
be per-sheet. (This change will also be necessary further in the future when we
support saving to PDF with different sheet sizes.)

Differential Revision: https://phabricator.services.mozilla.com/D176914
2023-05-04 22:49:01 +00:00

192 lines
6.8 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsPageSequenceFrame_h___
#define nsPageSequenceFrame_h___
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "nsContainerFrame.h"
#include "nsIPrintSettings.h"
namespace mozilla {
class PresShell;
class PrintedSheetFrame;
namespace dom {
class HTMLCanvasElement;
} // namespace dom
} // namespace mozilla
//-----------------------------------------------
// This class is used to manage some static data about the layout
// characteristics of our various "Pages Per Sheet" options.
struct nsPagesPerSheetInfo {
static const nsPagesPerSheetInfo& LookupInfo(int32_t aPPS);
uint16_t mNumPages;
// This is the larger of the row-count vs. column-count for this layout
// (if they aren't the same). We'll aim to stack this number of pages
// in the sheet's longer axis.
uint16_t mLargerNumTracks;
};
/**
* This class maintains various shared data that is used by printing-related
* frames. The nsPageSequenceFrame strongly owns an instance of this class,
* which lives for as long as the nsPageSequenceFrame does.
*/
class nsSharedPageData {
public:
nsString mDateTimeStr;
nsString mPageNumFormat;
nsString mPageNumAndTotalsFormat;
nsString mDocTitle;
nsString mDocURL;
nsFont mHeadFootFont;
// Total number of pages (populated by PrintedSheetFrame when it determines
// that it's reflowed the final page):
int32_t mRawNumPages = 0;
// If there's more than one page-range, then its components are stored here
// as pairs of (start,end). They're stored in the order provided (not
// necessarily in ascending order).
nsTArray<int32_t> mPageRanges;
// Margin for headers and footers; it defaults to 4/100 of an inch on UNIX
// and 0 elsewhere; I think it has to do with some inconsistency in page size
// computations
nsMargin mEdgePaperMargin;
nsCOMPtr<nsIPrintSettings> mPrintSettings;
// The scaling ratio we need to apply to make all pages fit horizontally. It's
// the minimum "ComputedWidth / OverflowWidth" ratio of all page content
// frames that overflowed. It's 1.0 if none overflowed horizontally.
float mShrinkToFitRatio = 1.0f;
// Lazy getter, to look up our pages-per-sheet info based on mPrintSettings
// (if it's available). The result is stored in our mPagesPerSheetInfo
// member-var to speed up subsequent lookups.
// This API is infallible; in failure cases, it just returns the info struct
// that corresponds to 1 page per sheet.
const nsPagesPerSheetInfo* PagesPerSheetInfo();
private:
const nsPagesPerSheetInfo* mPagesPerSheetInfo = nullptr;
};
// Page sequence frame class. Manages a series of pages, in paginated mode.
// (Strictly speaking, this frame's direct children are PrintedSheetFrame
// instances, and each of those will usually contain one nsPageFrame, depending
// on the "pages-per-sheet" setting and whether the print operation is
// restricted to a custom page range.)
class nsPageSequenceFrame final : public nsContainerFrame {
using LogicalSize = mozilla::LogicalSize;
public:
friend nsPageSequenceFrame* NS_NewPageSequenceFrame(
mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsPageSequenceFrame)
// nsIFrame
void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
// For Shrink To Fit
float GetSTFPercent() const { return mPageData->mShrinkToFitRatio; }
// Gets the final print preview scale that we're applying to the previewed
// sheets of paper.
float GetPrintPreviewScale() const;
// Async Printing
nsresult StartPrint(nsPresContext* aPresContext,
nsIPrintSettings* aPrintSettings,
const nsAString& aDocTitle, const nsAString& aDocURL);
nsresult PrePrintNextSheet(nsITimerCallback* aCallback, bool* aDone);
nsresult PrintNextSheet();
void ResetPrintCanvasList();
uint32_t GetCurrentSheetIdx() const { return mCurrentSheetIdx; }
int32_t GetRawNumPages() const { return mPageData->mRawNumPages; }
uint32_t GetPagesInFirstSheet() const;
nsresult DoPageEnd();
ComputeTransformFunction GetTransformGetter() const override;
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override;
#endif
protected:
nsPageSequenceFrame(ComputedStyle*, nsPresContext*);
virtual ~nsPageSequenceFrame();
void SetPageNumberFormat(const char* aPropName, const char* aDefPropVal,
bool aPageNumOnly);
// SharedPageData Helper methods
void SetDateTimeStr(const nsAString& aDateTimeStr);
void SetPageNumberFormat(const nsAString& aFormatStr, bool aForPageNumOnly);
// Print scaling is applied in this function.
void PopulateReflowOutput(ReflowOutput&, const ReflowInput&);
// Helper function to compute the offset needed to center a child
// page-frame's margin-box inside our content-box.
nscoord ComputeCenteringMargin(nscoord aContainerContentBoxWidth,
nscoord aChildPaddingBoxWidth,
const nsMargin& aChildPhysicalMargin);
mozilla::PrintedSheetFrame* GetCurrentSheetFrame();
nsSize mSize;
// These next two LogicalSize members are used when we're in print-preview to
// ensure that each previewed sheet will fit in the print-preview scrollport:
// -------
// Each component of this LogicalSize represents the maximum length of all
// our print-previewed sheets in that axis, plus a little extra for the
// print-preview margin. Note that this LogicalSize doesn't necessarily
// correspond to any one particular sheet's size (especially if our sheets
// have different sizes), since the components are tracked independently such
// that we end up storing the maximum in each dimension.
LogicalSize mMaxSheetSize;
// The size of the scrollport where we're print-previewing sheets.
LogicalSize mScrollportSize;
// Data shared by all the nsPageFrames:
mozilla::UniquePtr<nsSharedPageData> mPageData;
// The zero-based index of the PrintedSheetFrame child that is being printed
// (or about-to-be-printed), in an async print operation.
// This is an index into our PrincipalChildList, effectively.
uint32_t mCurrentSheetIdx = 0;
nsTArray<RefPtr<mozilla::dom::HTMLCanvasElement> > mCurrentCanvasList;
bool mCalledBeginPage;
bool mCurrentCanvasListSetup;
};
#endif /* nsPageSequenceFrame_h___ */