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
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "cairo.h"
|
||||
#include "cairo-quartz.h"
|
||||
#include "mozilla/gfx/HelpersCairo.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIOutputStream.h"
|
||||
@@ -218,7 +219,15 @@ nsresult PrintTargetCG::BeginPage(const IntSize& aSizeInPoints) {
|
||||
CGContextBeginPage(mPrintToStreamContext, nullptr);
|
||||
context = mPrintToStreamContext;
|
||||
} else {
|
||||
// XXX Why are we calling this if we don't check the return value?
|
||||
PMSessionError(mPrintSession);
|
||||
|
||||
if (StaticPrefs::layout_css_page_orientation_enabled()) {
|
||||
::PMOrientation pageOrientation =
|
||||
aSizeInPoints.width < aSizeInPoints.height ? kPMPortrait : kPMLandscape;
|
||||
::PMSetOrientation(mPageFormat, pageOrientation, kPMUnlocked);
|
||||
// We don't need to reset the orientation, since we set it for every page.
|
||||
}
|
||||
OSStatus status = ::PMSessionBeginPageNoDialog(mPrintSession, mPageFormat, nullptr);
|
||||
if (status != noErr) {
|
||||
return NS_ERROR_ABORT;
|
||||
@@ -233,8 +242,15 @@ nsresult PrintTargetCG::BeginPage(const IntSize& aSizeInPoints) {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int width = static_cast<unsigned int>(mSize.width);
|
||||
unsigned int height = static_cast<unsigned int>(mSize.height);
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
if (StaticPrefs::layout_css_page_orientation_enabled()) {
|
||||
width = static_cast<unsigned int>(aSizeInPoints.width);
|
||||
height = static_cast<unsigned int>(aSizeInPoints.height);
|
||||
} else {
|
||||
width = static_cast<unsigned int>(mSize.width);
|
||||
height = static_cast<unsigned int>(mSize.height);
|
||||
}
|
||||
|
||||
// Initially, origin is at bottom-left corner of the paper.
|
||||
// Here, we translate it to top-left corner of the paper.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "cairo.h"
|
||||
#include "cairo-pdf.h"
|
||||
#include "mozilla/AppShutdown.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsString.h"
|
||||
|
||||
@@ -74,6 +75,17 @@ already_AddRefed<PrintTargetPDF> PrintTargetPDF::CreateOrNull(
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
nsresult PrintTargetPDF::BeginPage(const IntSize& aSizeInPoints) {
|
||||
if (StaticPrefs::layout_css_page_orientation_enabled()) {
|
||||
cairo_pdf_surface_set_size(mCairoSurface, aSizeInPoints.width,
|
||||
aSizeInPoints.height);
|
||||
if (cairo_surface_status(mCairoSurface)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return PrintTarget::BeginPage(aSizeInPoints);
|
||||
}
|
||||
|
||||
nsresult PrintTargetPDF::EndPage() {
|
||||
cairo_surface_show_page(mCairoSurface);
|
||||
return PrintTarget::EndPage();
|
||||
|
||||
@@ -21,6 +21,7 @@ class PrintTargetPDF final : public PrintTarget {
|
||||
static already_AddRefed<PrintTargetPDF> CreateOrNull(
|
||||
nsIOutputStream* aStream, const IntSize& aSizeInPoints);
|
||||
|
||||
nsresult BeginPage(const IntSize& aSizeInPoints) override;
|
||||
nsresult EndPage() override;
|
||||
void Finish() override;
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/StaticPrefs_print.h"
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "nsPageContentFrame.h"
|
||||
#include "nsPageFrame.h"
|
||||
#include "nsPageSequenceFrame.h"
|
||||
|
||||
@@ -64,6 +66,19 @@ static bool TagIfSkippedByCustomRange(nsPageFrame* aPageFrame, int32_t aPageNum,
|
||||
|
||||
void PrintedSheetFrame::ClaimPageFrameFromPrevInFlow() {
|
||||
MoveOverflowToChildList();
|
||||
if (!GetPrevContinuation()) {
|
||||
// The first page content frame of each document will not yet have its page
|
||||
// style set yet. This is because normally page style is set either from
|
||||
// the previous page content frame, or using the new page name when named
|
||||
// pages cause a page break in block reflow. Ensure that, for the first
|
||||
// page, it is set here so that all nsPageContentFrames have their page
|
||||
// style set before reflow.
|
||||
auto* firstChild = PrincipalChildList().FirstChild();
|
||||
MOZ_ASSERT(firstChild && firstChild->IsPageFrame(),
|
||||
"PrintedSheetFrame only has nsPageFrame children");
|
||||
auto* pageFrame = static_cast<nsPageFrame*>(firstChild);
|
||||
pageFrame->PageContentFrame()->EnsurePageName();
|
||||
}
|
||||
}
|
||||
|
||||
void PrintedSheetFrame::Reflow(nsPresContext* aPresContext,
|
||||
@@ -80,6 +95,24 @@ void PrintedSheetFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
const WritingMode wm = aReflowInput.GetWritingMode();
|
||||
|
||||
// See the comments for GetSizeForChildren.
|
||||
// Note that nsPageFrame::ComputeSinglePPSPageSizeScale depends on this value
|
||||
// and is currently called while reflowing a single nsPageFrame child (i.e.
|
||||
// before we've finished reflowing ourself). Ideally our children wouldn't be
|
||||
// accessing our dimensions until after we've finished reflowing ourself -
|
||||
// see bug 1835782.
|
||||
mSizeForChildren =
|
||||
nsSize(aReflowInput.AvailableISize(), aReflowInput.AvailableBSize());
|
||||
if (mPD->PagesPerSheetInfo()->mNumPages == 1) {
|
||||
auto* firstChild = PrincipalChildList().FirstChild();
|
||||
MOZ_ASSERT(firstChild && firstChild->IsPageFrame(),
|
||||
"PrintedSheetFrame only has nsPageFrame children");
|
||||
if (static_cast<nsPageFrame*>(firstChild)
|
||||
->GetPageOrientationRotation(mPD) != 0.0) {
|
||||
std::swap(mSizeForChildren.width, mSizeForChildren.height);
|
||||
}
|
||||
}
|
||||
|
||||
// Count the number of pages that are displayed on this sheet (i.e. how many
|
||||
// child frames we end up laying out, excluding any pages that are skipped
|
||||
// due to not being in the user's page-range selection).
|
||||
@@ -89,8 +122,7 @@ void PrintedSheetFrame::Reflow(nsPresContext* aPresContext,
|
||||
const uint32_t desiredPagesPerSheet = mPD->PagesPerSheetInfo()->mNumPages;
|
||||
|
||||
if (desiredPagesPerSheet > 1) {
|
||||
ComputePagesPerSheetGridMetrics(
|
||||
nsSize(aReflowInput.AvailableISize(), aReflowInput.AvailableBSize()));
|
||||
ComputePagesPerSheetGridMetrics(mSizeForChildren);
|
||||
}
|
||||
|
||||
// NOTE: I'm intentionally *not* using a range-based 'for' loop here, since
|
||||
@@ -225,13 +257,68 @@ void PrintedSheetFrame::Reflow(nsPresContext* aPresContext,
|
||||
FinishAndStoreOverflow(&aReflowOutput);
|
||||
}
|
||||
|
||||
nsSize PrintedSheetFrame::PrecomputeSheetSize(
|
||||
const nsPresContext* aPresContext) {
|
||||
mPrecomputedSize = aPresContext->GetPageSize();
|
||||
if (mPD->mPrintSettings->HasOrthogonalSheetsAndPages()) {
|
||||
std::swap(mPrecomputedSize.width, mPrecomputedSize.height);
|
||||
nsSize PrintedSheetFrame::ComputeSheetSize(const nsPresContext* aPresContext) {
|
||||
// We use the user selected page (sheet) dimensions, and default to the
|
||||
// orientation as specified by the user.
|
||||
nsSize sheetSize = aPresContext->GetPageSize();
|
||||
|
||||
// Don't waste cycles changing the orientation of a square.
|
||||
if (sheetSize.width == sheetSize.height) {
|
||||
return sheetSize;
|
||||
}
|
||||
return mPrecomputedSize;
|
||||
|
||||
if (!StaticPrefs::layout_css_page_orientation_enabled()) {
|
||||
if (mPD->mPrintSettings->HasOrthogonalSheetsAndPages()) {
|
||||
std::swap(sheetSize.width, sheetSize.height);
|
||||
}
|
||||
return sheetSize;
|
||||
}
|
||||
|
||||
auto* firstChild = PrincipalChildList().FirstChild();
|
||||
MOZ_ASSERT(firstChild->IsPageFrame(),
|
||||
"PrintedSheetFrame only has nsPageFrame children");
|
||||
auto* sheetsFirstPageFrame = static_cast<nsPageFrame*>(firstChild);
|
||||
|
||||
nsSize pageSize = sheetsFirstPageFrame->ComputePageSize();
|
||||
|
||||
// Don't waste cycles changing the orientation of a square.
|
||||
if (pageSize.width == pageSize.height) {
|
||||
return sheetSize;
|
||||
}
|
||||
|
||||
const bool pageIsRotated =
|
||||
sheetsFirstPageFrame->GetPageOrientationRotation(mPD) != 0.0;
|
||||
|
||||
if (pageIsRotated && pageSize.width == pageSize.height) {
|
||||
// Straighforward rotation without needing sheet orientation optimization.
|
||||
std::swap(sheetSize.width, sheetSize.height);
|
||||
return sheetSize;
|
||||
}
|
||||
|
||||
// Try to orient the sheet optimally based on the physical orientation of the
|
||||
// first/sole page on the sheet. (In the multiple pages-per-sheet case, the
|
||||
// first page is the only one that exists at this point in the code, so it is
|
||||
// the only one we can reason about. Any other pages may, or may not, have
|
||||
// the same physical orientation.)
|
||||
|
||||
if (pageIsRotated) {
|
||||
// Fix up for its physical orientation:
|
||||
std::swap(pageSize.width, pageSize.height);
|
||||
}
|
||||
|
||||
const bool pageIsPortrait = pageSize.width < pageSize.height;
|
||||
const bool sheetIsPortrait = sheetSize.width < sheetSize.height;
|
||||
|
||||
// Switch the sheet orientation if the page orientation is different, or
|
||||
// if we need to switch it because the number of pages-per-sheet demands
|
||||
// orthogonal sheet layout, but not if both are true since then we'd
|
||||
// actually need to double switch.
|
||||
if ((sheetIsPortrait != pageIsPortrait) !=
|
||||
mPD->mPrintSettings->HasOrthogonalSheetsAndPages()) {
|
||||
std::swap(sheetSize.width, sheetSize.height);
|
||||
}
|
||||
|
||||
return sheetSize;
|
||||
}
|
||||
|
||||
void PrintedSheetFrame::ComputePagesPerSheetGridMetrics(
|
||||
|
||||
@@ -29,6 +29,7 @@ class PrintedSheetFrame final : public nsContainerFrame {
|
||||
|
||||
void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
|
||||
|
||||
// XXX: this needs a better name, since it also updates style.
|
||||
// Invokes MoveOverflowToChildList.
|
||||
// This is intended for use by callers that need to be able to get our first/
|
||||
// only nsPageFrame from our child list to examine its computed style just
|
||||
@@ -58,21 +59,22 @@ class PrintedSheetFrame final : public nsContainerFrame {
|
||||
nscoord GetGridCellWidth() const { return mGridCellWidth; }
|
||||
nscoord GetGridCellHeight() const { return mGridCellHeight; }
|
||||
|
||||
nsSize ComputeSheetSize(const nsPresContext* aPresContext);
|
||||
|
||||
/**
|
||||
* A helper that is called just prior to this frame being relfowed to
|
||||
* pre-compute and cache the size that the sheet should be given. This is
|
||||
* called before any child nsPageFrames are reflowed, and it is cached so
|
||||
* that those nsPageFrames can obtain their sheet frame's size while they're
|
||||
* reflowing (the normal reflow code doesn't give the sheet frame its size
|
||||
* until after the nsPageFrames have been reflowed).
|
||||
* If we get rid of nsPageFrame::ComputeSinglePPSPageSizeScale (bug 1835782),
|
||||
* which is the only consumer of GetPrecomputedSheetSize, then we can get rid
|
||||
* of GetPrecomputedSheetSize and the member variable and rename
|
||||
* PrecomputeSheetSize to ComputeSheetSize, which will then only be called
|
||||
* once during reflow.
|
||||
* When we're printing one page-per-sheet and `page-orientation` on our
|
||||
* single nsPageFrame child should cause the page to rotate, then we want to
|
||||
* essentially rotate the sheet. We implement that by switching the
|
||||
* dimensions of this sheet (changing its orientation), sizing the
|
||||
* nsPageFrame to the original dimensions, and then applying the rotation to
|
||||
* the nsPageFrame child.
|
||||
*
|
||||
* This returns the dimensions that this frame would have without any
|
||||
* dimension swap we may have done to implement `page-orientation`. If
|
||||
* there is no rotation caused by `page-orientation`, then the value returned
|
||||
* and mRect.Size() are identical.
|
||||
*/
|
||||
nsSize PrecomputeSheetSize(const nsPresContext* aPresContext);
|
||||
nsSize GetPrecomputedSheetSize() const { return mPrecomputedSize; }
|
||||
nsSize GetSizeForChildren() const { return mSizeForChildren; }
|
||||
|
||||
/**
|
||||
* This method returns the dimensions of the physical page that the target
|
||||
@@ -110,7 +112,8 @@ class PrintedSheetFrame final : public nsContainerFrame {
|
||||
// a sensible amount of spacing between pages.)
|
||||
void ComputePagesPerSheetGridMetrics(const nsSize& aSheetSize);
|
||||
|
||||
nsSize mPrecomputedSize;
|
||||
// See GetSizeForChildren.
|
||||
nsSize mSizeForChildren;
|
||||
|
||||
// Note: this will be set before reflow, and it's strongly owned by our
|
||||
// nsPageSequenceFrame, which outlives us.
|
||||
|
||||
@@ -550,21 +550,47 @@ static gfx::Matrix4x4 ComputePagesPerSheetAndPageSizeTransform(
|
||||
nsSharedPageData* pd = pageFrame->GetSharedPageData();
|
||||
const auto* ppsInfo = pd->PagesPerSheetInfo();
|
||||
|
||||
const nsContainerFrame* const parentFrame = pageFrame->GetParent();
|
||||
MOZ_ASSERT(parentFrame->IsPrintedSheetFrame(),
|
||||
"Parent of nsPageFrame should be PrintedSheetFrame");
|
||||
const auto* sheetFrame = static_cast<const PrintedSheetFrame*>(parentFrame);
|
||||
|
||||
const double rotation =
|
||||
pageFrame->GetPageOrientationRotation(pageFrame->GetSharedPageData());
|
||||
|
||||
gfx::Matrix4x4 transform;
|
||||
|
||||
if (ppsInfo->mNumPages == 1) {
|
||||
if (rotation != 0.0) {
|
||||
const nsSize sheetSize = sheetFrame->GetSizeForChildren();
|
||||
const bool sheetIsPortrait = sheetSize.width < sheetSize.height;
|
||||
const bool rotatingClockwise = rotation > 0.0;
|
||||
|
||||
// rotation point:
|
||||
int32_t x, y;
|
||||
if (rotatingClockwise != sheetIsPortrait) {
|
||||
// rotating portrait clockwise, or landscape counterclockwise
|
||||
x = y = std::min(sheetSize.width, sheetSize.height) / 2;
|
||||
} else {
|
||||
// rotating portrait counterclockwise, or landscape clockwise
|
||||
x = y = std::max(sheetSize.width, sheetSize.height) / 2;
|
||||
}
|
||||
|
||||
transform = gfx::Matrix4x4::Translation(
|
||||
NSAppUnitsToFloatPixels(x, aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(y, aAppUnitsPerPixel), 0);
|
||||
transform.RotateZ(rotation);
|
||||
transform.PreTranslate(NSAppUnitsToFloatPixels(-x, aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(-y, aAppUnitsPerPixel), 0);
|
||||
}
|
||||
|
||||
float scale = pageFrame->ComputeSinglePPSPageSizeScale(contentPageSize);
|
||||
transform = gfx::Matrix4x4::Scaling(scale, scale, 1);
|
||||
transform.PreScale(scale, scale, 1);
|
||||
return transform;
|
||||
}
|
||||
|
||||
// The multiple pages-per-sheet case.
|
||||
|
||||
const nsContainerFrame* const parentFrame = pageFrame->GetParent();
|
||||
MOZ_ASSERT(parentFrame->IsPrintedSheetFrame(),
|
||||
"Parent of nsPageFrame should be PrintedSheetFrame");
|
||||
auto* sheetFrame = static_cast<const PrintedSheetFrame*>(parentFrame);
|
||||
|
||||
// Begin with the translation of the page to its pages-per-sheet grid "cell"
|
||||
// (the grid origin accounts for the sheet's unwriteable margins):
|
||||
const nsPoint gridOrigin = sheetFrame->GetGridOrigin();
|
||||
@@ -604,47 +630,46 @@ static gfx::Matrix4x4 ComputePagesPerSheetAndPageSizeTransform(
|
||||
transform.PreTranslate(dx, dy, 0.0f);
|
||||
transform.PreScale(scale, scale, 1.0f);
|
||||
|
||||
// Apply 'page-orientation' to any applicable pages:
|
||||
if (StaticPrefs::layout_css_page_orientation_enabled()) {
|
||||
const StylePageOrientation& orientation =
|
||||
pageFrame->PageContentFrame()->StylePage()->mPageOrientation;
|
||||
// Apply 'page-orientation' rotation, if applicable:
|
||||
if (rotation != 0.0) {
|
||||
// We've already translated and scaled the page to fit the cell, ignoring
|
||||
// rotation. Here we rotate the page around its center and, if necessary,
|
||||
// also scale it to fit it to its cell for its orientation change.
|
||||
|
||||
double angle = 0.0;
|
||||
if (orientation == StylePageOrientation::RotateLeft) {
|
||||
angle = -M_PI / 2.0;
|
||||
} else if (orientation == StylePageOrientation::RotateRight) {
|
||||
angle = M_PI / 2.0;
|
||||
}
|
||||
|
||||
if (angle != 0.0) {
|
||||
float cellRatio = float(sheetFrame->GetGridCellWidth()) /
|
||||
float(sheetFrame->GetGridCellHeight());
|
||||
float fitScale = 1.0f;
|
||||
if (MOZ_LIKELY(cellWidth != cellHeight &&
|
||||
contentPageSize.width != contentPageSize.height)) {
|
||||
// If neither the cell nor the page are square, the scale must change.
|
||||
float cellRatio = float(cellWidth) / float(cellHeight);
|
||||
float pageRatio =
|
||||
float(contentPageSize.width) / float(contentPageSize.height);
|
||||
// To fit into the available space on a sheet, a page typically needs to
|
||||
// be scaled. If rotated 90 degrees, the scale will be different (assuming
|
||||
// the page size is rectangular, not square). This variable flags whether
|
||||
// the scale at the default rotation is the smaller of the two scales.
|
||||
bool isSmallerOfRotatedScales = floor(cellRatio) != floor(pageRatio);
|
||||
float fitScale = cellRatio;
|
||||
if (isSmallerOfRotatedScales != bool(floor(fitScale))) {
|
||||
fitScale = 1.0f / cellRatio;
|
||||
const bool orientationWillMatchAfterRotation =
|
||||
floor(cellRatio) != floor(pageRatio);
|
||||
if (cellRatio > 1.0f) {
|
||||
cellRatio = 1.0f / cellRatio; // normalize
|
||||
}
|
||||
if (pageRatio > 1.0f) {
|
||||
pageRatio = 1.0f / pageRatio; // normalize
|
||||
}
|
||||
fitScale = std::max(cellRatio, pageRatio);
|
||||
if (orientationWillMatchAfterRotation) {
|
||||
// Scale up, not down
|
||||
fitScale = 1.0f / fitScale;
|
||||
}
|
||||
|
||||
transform.PreTranslate(
|
||||
NSAppUnitsToFloatPixels(contentPageSize.width / 2, aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(contentPageSize.height / 2,
|
||||
aAppUnitsPerPixel),
|
||||
0);
|
||||
transform.PreScale(fitScale, fitScale, 1.0f);
|
||||
transform.RotateZ(angle);
|
||||
transform.PreTranslate(
|
||||
NSAppUnitsToFloatPixels(-contentPageSize.width / 2,
|
||||
aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(-contentPageSize.height / 2,
|
||||
aAppUnitsPerPixel),
|
||||
0);
|
||||
}
|
||||
|
||||
transform.PreTranslate(
|
||||
NSAppUnitsToFloatPixels(contentPageSize.width / 2, aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(contentPageSize.height / 2, aAppUnitsPerPixel),
|
||||
0);
|
||||
if (MOZ_LIKELY(fitScale != 1.0f)) {
|
||||
transform.PreScale(fitScale, fitScale, 1.0f);
|
||||
}
|
||||
transform.RotateZ(rotation);
|
||||
transform.PreTranslate(
|
||||
NSAppUnitsToFloatPixels(-contentPageSize.width / 2, aAppUnitsPerPixel),
|
||||
NSAppUnitsToFloatPixels(-contentPageSize.height / 2, aAppUnitsPerPixel),
|
||||
0);
|
||||
}
|
||||
|
||||
return transform;
|
||||
@@ -734,7 +759,7 @@ float nsPageFrame::ComputeSinglePPSPageSizeScale(
|
||||
// content uses "@page {size: ...}" to specify a page size for the content.
|
||||
float scale = 1.0f;
|
||||
|
||||
const nsSize sheetSize = sheet->GetPrecomputedSheetSize();
|
||||
const nsSize sheetSize = sheet->GetSizeForChildren();
|
||||
nscoord contentPageHeight = aContentPageSize.height;
|
||||
// Scale down if the target is too wide.
|
||||
if (aContentPageSize.width > sheetSize.width) {
|
||||
@@ -751,6 +776,32 @@ float nsPageFrame::ComputeSinglePPSPageSizeScale(
|
||||
return scale;
|
||||
}
|
||||
|
||||
double nsPageFrame::GetPageOrientationRotation(nsSharedPageData* aPD) const {
|
||||
if (!StaticPrefs::layout_css_page_orientation_enabled()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (aPD->PagesPerSheetInfo()->mNumPages == 1 && !PresContext()->IsScreen() &&
|
||||
aPD->mPrintSettings->GetOutputFormat() !=
|
||||
nsIPrintSettings::kOutputFormatPDF) {
|
||||
// In the single page-per-sheet case we rotate the page by essentially
|
||||
// rotating the entire sheet. But we can't do that when the output device
|
||||
// doesn't support mixed sheet orientations.
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
const StylePageOrientation& orientation =
|
||||
PageContentFrame()->StylePage()->mPageOrientation;
|
||||
|
||||
if (orientation == StylePageOrientation::RotateLeft) {
|
||||
return -M_PI / 2.0;
|
||||
}
|
||||
if (orientation == StylePageOrientation::RotateRight) {
|
||||
return M_PI / 2.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
nsIFrame* nsPageFrame::FirstContinuation() const {
|
||||
// Walk up to our grandparent, and then to down the grandparent's first
|
||||
// child, and then that frame's first child.
|
||||
|
||||
@@ -77,6 +77,14 @@ class nsPageFrame final : public nsContainerFrame {
|
||||
// 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.
|
||||
|
||||
@@ -344,7 +344,7 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
||||
// frame, we need to call this:
|
||||
sheet->ClaimPageFrameFromPrevInFlow();
|
||||
|
||||
const nsSize sheetSize = sheet->PrecomputeSheetSize(aPresContext);
|
||||
const nsSize sheetSize = sheet->ComputeSheetSize(aPresContext);
|
||||
|
||||
// Reflow the sheet
|
||||
ReflowInput kidReflowInput(
|
||||
@@ -372,7 +372,7 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
||||
FinishReflowChild(kidFrame, aPresContext, kidReflowOutput, &kidReflowInput,
|
||||
x, y, ReflowChildFlags::Default);
|
||||
MOZ_ASSERT(kidFrame->GetSize() == sheetSize,
|
||||
"PrintedSheetFrame::PrecomputeSheetSize gave the wrong size!");
|
||||
"PrintedSheetFrame::ComputeSheetSize() gave the wrong size!");
|
||||
y += kidReflowOutput.Height();
|
||||
y += pageCSSMargin.bottom;
|
||||
|
||||
|
||||
@@ -194,12 +194,12 @@ pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-4.htm
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-4b.html inline-block-slice-4b-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-4c.html inline-block-slice-4c-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-5.html inline-block-slice-5-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-5b.html inline-block-slice-5b-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-5c.html inline-block-slice-5c-ref.html
|
||||
fuzzy-if(useDrawSnapshot&>kWidget,0-102,0-49) pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-5b.html inline-block-slice-5b-ref.html
|
||||
fuzzy-if(useDrawSnapshot&>kWidget,0-102,0-48) pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-5c.html inline-block-slice-5c-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-6.html inline-block-slice-6-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-6b.html inline-block-slice-6b-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-6c.html inline-block-slice-6c-ref.html
|
||||
fuzzy-if(useDrawSnapshot&>kWidget,0-21,0-36) pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-6b.html inline-block-slice-6b-ref.html
|
||||
fuzzy-if(useDrawSnapshot&>kWidget,0-102,0-48) pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-6c.html inline-block-slice-6c-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) != inline-block-slice-7.html inline-block-slice-7-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-8.html inline-block-slice-8-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-8b.html inline-block-slice-8b-ref.html
|
||||
pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-8c.html inline-block-slice-8c-ref.html
|
||||
fuzzy-if(useDrawSnapshot&>kWidget,0-102,0-13) pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-8b.html inline-block-slice-8b-ref.html
|
||||
fuzzy-if(useDrawSnapshot&>kWidget,0-102,0-12) pref(layout.display-list.improve-fragmentation,true) == inline-block-slice-8c.html inline-block-slice-8c-ref.html
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
[page-size-006-print.html]
|
||||
expected: FAIL
|
||||
expected:
|
||||
if os == "mac": PASS
|
||||
FAIL
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[page-size-009-print.html]
|
||||
expected: FAIL
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1849648
|
||||
|
||||
Reference in New Issue
Block a user