diff options
Diffstat (limited to 'layout/generic/nsPageFrame.cpp')
-rw-r--r-- | layout/generic/nsPageFrame.cpp | 84 |
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 |