gecko-dev/layout/generic/nsPageFrame.h
Jonathan Watt b0c778ba81 Bug 1833244 p2. Implement sheet orientation switching/rotation for page-orientation. r=AlaskanEmily,dholbert
Where supported (print preview and print-to-PDF), this implements changing the
orientation and/or rotation of print sheets, as appropriate, in response to CSS
`page-orientation`. When supported we:

- in the single page-per-sheet case, rotate the sheet in order to implement
  any `page-orientation` rotation on the sheet. Rotating the sheet is necessary
  so that when we output PDF files the pages visually have the correct
  orientation.

- in the multiple pages-per-sheet case, we already rotate individual pages in
  their grid cell. This commit keeps such pages rotated, as appropriate, but
  augments that behavior by switching the orientation of the sheet (based on
  the first page on the sheet), if necessary, to make best use of the space on
  the sheet. (We can't know what orientation any subsequent pages on the sheet
  will have, so we assume the same orientation as the first one.)

Depends on D179423

Differential Revision: https://phabricator.services.mozilla.com/D179448
2023-08-22 10:57:55 +00:00

181 lines
7.0 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 nsPageFrame_h___
#define nsPageFrame_h___
#include "mozilla/Attributes.h"
#include "nsContainerFrame.h"
#include "nsLeafFrame.h"
class nsFontMetrics;
class nsPageContentFrame;
class nsSharedPageData;
namespace mozilla {
class PresShell;
} // namespace mozilla
// Page frame class. Represents an individual page, in paginated mode.
class nsPageFrame final : public nsContainerFrame {
public:
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsPageFrame)
friend nsPageFrame* NS_NewPageFrame(mozilla::PresShell* aPresShell,
ComputedStyle* aStyle);
void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override;
#endif
//////////////////
// For Printing
//////////////////
// Determine this page's page-number, based on its previous continuation
// (whose page number is presumed to already be known).
void DeterminePageNum();
int32_t GetPageNum() const { return mPageNum; }
void SetSharedPageData(nsSharedPageData* aPD);
nsSharedPageData* GetSharedPageData() const { return mPD; }
void PaintHeaderFooter(gfxContext& aRenderingContext, nsPoint aPt,
bool aSubpixelAA);
const nsMargin& GetUsedPageContentMargin() const {
return mPageContentMargin;
}
uint32_t IndexOnSheet() const { return mIndexOnSheet; }
void SetIndexOnSheet(uint32_t aIndexOnSheet) {
mIndexOnSheet = aIndexOnSheet;
}
ComputeTransformFunction GetTransformGetter() const override;
nsPageContentFrame* PageContentFrame() const;
nsSize ComputePageSize() const;
// Computes the scaling factor to fit the page to the sheet in the single
// page-per-sheet case. (The multiple pages-per-sheet case is currently
// different - see the comment for
// PrintedSheetFrame::ComputePagesPerSheetGridMetrics and code in
// ComputePagesPerSheetAndPageSizeTransform.) The page and sheet dimensions
// may be different due to a CSS page-size that gives the page a size that is
// too large to fit on the sheet that we are printing to.
float ComputeSinglePPSPageSizeScale(const nsSize aContentPageSize) const;
// Returns the rotation from CSS `page-orientation` property, if set, and if
// it applies. Note: the single page-per-sheet case is special since in that
// case we effectively rotate the sheet (as opposed to rotating pages in
// their pages-per-sheet grid cell). In this case we return zero if the
// output medium does not support changing the dimensions (orientation) of
// the sheet (i.e. only print preview and save-to-PDF are supported).
double GetPageOrientationRotation(nsSharedPageData* aPD) const;
// The default implementation of FirstContinuation in nsSplittableFrame is
// implemented in linear time, walking back through the linked list of
// continuations via mPrevContinuation.
// For nsPageFrames, we can find the first continuation through the frame
// tree structure in constant time.
nsIFrame* FirstContinuation() const final;
protected:
explicit nsPageFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
virtual ~nsPageFrame();
typedef enum { eHeader, eFooter } nsHeaderFooterEnum;
nscoord GetXPosition(gfxContext& aRenderingContext,
nsFontMetrics& aFontMetrics, const nsRect& aRect,
int32_t aJust, const nsString& aStr);
nsReflowStatus ReflowPageContent(nsPresContext*,
const ReflowInput& aPageReflowInput);
void DrawHeaderFooter(gfxContext& aRenderingContext,
nsFontMetrics& aFontMetrics,
nsHeaderFooterEnum aHeaderFooter, int32_t aJust,
const nsString& sStr, const nsRect& aRect,
nscoord aHeight, nscoord aAscent, nscoord aWidth);
void DrawHeaderFooter(gfxContext& aRenderingContext,
nsFontMetrics& aFontMetrics,
nsHeaderFooterEnum aHeaderFooter,
const nsString& aStrLeft, const nsString& aStrRight,
const nsString& aStrCenter, const nsRect& aRect,
nscoord aAscent, nscoord aHeight);
void ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr);
static constexpr int32_t kPageNumUnset = -1;
// 1-based page-num
int32_t mPageNum = kPageNumUnset;
// 0-based index on the sheet that we belong to. Unused/meaningless if this
// page has frame state bit NS_PAGE_SKIPPED_BY_CUSTOM_RANGE.
uint32_t mIndexOnSheet = 0;
// Note: this will be set before reflow, and it's strongly owned by our
// nsPageSequenceFrame, which outlives us.
nsSharedPageData* mPD = nullptr;
// Computed page content margins.
//
// This is the amount of space from the edges of the content to the edges,
// measured in the content coordinate space. This is as opposed to the
// coordinate space of the physical paper. This might be different due to
// a CSS page-size that is too large to fit on the paper, causing content to
// be scaled to fit.
//
// These margins take into account:
// * CSS-defined margins (content units)
// * User-supplied margins (physical units)
// * Unwriteable-supplied margins (physical units)
//
// When computing these margins, all physical units have the inverse of the
// scaling factor caused by CSS page-size downscaling applied. This ensures
// that even if the content will be downscaled, it will respect the (now
// upscaled) physical unwriteable margins required by the printer.
// For user-supplied margins, it isn't immediately obvious to the user what
// the intended page-size of the document is, so we consider these margins to
// be in the physical space of the paper.
nsMargin mPageContentMargin;
};
class nsPageBreakFrame final : public nsLeafFrame {
NS_DECL_FRAMEARENA_HELPERS(nsPageBreakFrame)
explicit nsPageBreakFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
~nsPageBreakFrame();
void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override;
#endif
protected:
nscoord GetIntrinsicISize() override;
nscoord GetIntrinsicBSize() override;
friend nsIFrame* NS_NewPageBreakFrame(mozilla::PresShell* aPresShell,
ComputedStyle* aStyle);
};
#endif /* nsPageFrame_h___ */