summaryrefslogtreecommitdiffstats
path: root/layout/generic/nsPageFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic/nsPageFrame.cpp')
-rw-r--r--layout/generic/nsPageFrame.cpp84
1 files changed, 80 insertions, 4 deletions
diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp
index fb9cfa2e81..de573962af 100644
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -9,6 +9,7 @@
#include "mozilla/AppUnits.h"
#include "mozilla/PresShell.h"
#include "mozilla/StaticPrefs_layout.h"
+#include "mozilla/StaticPrefs_print.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/intl/Segmenter.h"
#include "gfxContext.h"
@@ -213,7 +214,6 @@ void nsPageFrame::Reflow(nsPresContext* aPresContext,
nsReflowStatus& aStatus) {
MarkInReflow();
DO_GLOBAL_REFLOW_COUNT("nsPageFrame");
- DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus);
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
MOZ_ASSERT(mPD, "Need a pointer to nsSharedPageData before reflow starts");
@@ -540,6 +540,69 @@ static std::tuple<uint32_t, uint32_t> GetRowAndColFromIdx(uint32_t aIdxOnSheet,
return {aIdxOnSheet / aNumCols, aIdxOnSheet % aNumCols};
}
+// The minimum ratio for which we will center the page on the sheet when using
+// auto-detect logic.
+// Note that this ratio is of the content's size to the sheet size scaled to be
+// in content space, and so the actual ratio will always be from 0.0 to 1.0,
+// with this marking the smallest ratio we consider a near-miss.
+// The ratio of A4 on Letter is 0.915034. A threshold of 0.9 will ensure that
+// A4 on Letter works, as well as other near-misses.
+//
+// The ratio is computed as so:
+// scale = min(1, sheetHeight / pageHeight, sheetWidth / pageWidth)
+//
+// Where pageSize is pageWidth or pageHeight, and sheetSize is sheetWidth or
+// sheetHeight, respectively:
+// scaledPageSize = pageSize * scale
+// ratio = scaledPageSize / sheetSize
+//
+// A4 (210mm x 297mm) on US Letter (215.9mm x 279.4mm) is derived as so:
+// scale = min(1, 215.9 / 210, 279.4 / 297) = 0.9407407407..
+//
+// Using the widths:
+// scaledPageSize = (210 * 0.940741) = 197.556
+// ratio = 197.556 / 215.9 = 0.915034
+//
+// See nsPageFrame::ComputeSinglePPSPageSizeScale for scale calculation, and
+// OffsetToCenterPage for ratio calculation.
+constexpr float kCenterPageRatioThreshold = 0.9f;
+
+// Numeric values for the pref "print.center_page_on_sheet"
+enum {
+ kPrintCenterPageOnSheetNever = 0,
+ kPrintCenterPageOnSheetAlways = 1,
+ kPrintCenterPageOnSheetAuto = 2
+};
+
+// Returns an offset to center the page on the sheet, with a given scale.
+// When no centering can/should happen, this will avoid extra calculations and
+// return 0.0f.
+// This takes into account the value of the pref "print.center_page_on_sheet".
+static float OffsetToCenterPage(nscoord aContentSize, nscoord aSheetSize,
+ float aScale, float aAppUnitsPerPixel) {
+ MOZ_ASSERT(aScale <= 1.0f && aScale > 0.0f,
+ "Scale must be in the range (0,1]");
+ const unsigned centerPagePref = StaticPrefs::print_center_page_on_sheet();
+ if (centerPagePref == kPrintCenterPageOnSheetNever) {
+ return 0.0f;
+ }
+
+ // Determine the ratio of scaled page to the sheet size.
+ const float sheetSize =
+ NSAppUnitsToFloatPixels(aSheetSize, aAppUnitsPerPixel);
+ const float scaledContentSize =
+ NSAppUnitsToFloatPixels(aContentSize, aAppUnitsPerPixel) * aScale;
+ const float ratio = scaledContentSize / sheetSize;
+
+ // If the ratio is within the threshold, or the pref indicates we should
+ // always center the page, return half the difference to form the offset.
+ if (centerPagePref == kPrintCenterPageOnSheetAlways ||
+ ratio >= kCenterPageRatioThreshold) {
+ return (sheetSize - scaledContentSize) * 0.5f;
+ }
+ return 0.0f;
+}
+
// Helper for BuildDisplayList:
static gfx::Matrix4x4 ComputePagesPerSheetAndPageSizeTransform(
const nsIFrame* aFrame, float aAppUnitsPerPixel) {
@@ -561,8 +624,8 @@ static gfx::Matrix4x4 ComputePagesPerSheetAndPageSizeTransform(
gfx::Matrix4x4 transform;
if (ppsInfo->mNumPages == 1) {
+ const nsSize sheetSize = sheetFrame->GetSizeForChildren();
if (rotation != 0.0) {
- const nsSize sheetSize = sheetFrame->GetSizeForChildren();
const bool sheetIsPortrait = sheetSize.width < sheetSize.height;
const bool rotatingClockwise = rotation > 0.0;
@@ -584,7 +647,21 @@ static gfx::Matrix4x4 ComputePagesPerSheetAndPageSizeTransform(
NSAppUnitsToFloatPixels(-y, aAppUnitsPerPixel), 0);
}
- float scale = pageFrame->ComputeSinglePPSPageSizeScale(contentPageSize);
+ // If the difference in horizontal size, after scaling, is relatively small
+ // then center the page on the sheet.
+ const float scale =
+ pageFrame->ComputeSinglePPSPageSizeScale(contentPageSize);
+ const float centeringOffset = OffsetToCenterPage(
+ contentPageSize.width, sheetSize.width, scale, aAppUnitsPerPixel);
+
+ // Only bother with the translation if it is at least one pixel.
+ // It's possible for a mismatch in the paper size reported by the print
+ // server and the paper size from Gecko to lead to small offsets, or
+ // even (in combination with floating point error) a very small negative
+ // offset. Do not apply an offset in those cases.
+ if (centeringOffset >= 1.0f) {
+ transform.PreTranslate(centeringOffset, 0, 0);
+ }
transform.PreScale(scale, scale, 1);
return transform;
}
@@ -937,7 +1014,6 @@ void nsPageBreakFrame::Reflow(nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame");
- DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus);
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
// Override reflow, since we don't want to deal with what our