Bug 1833733 - Properly detect page sequence background from FindEffectiveBackgroundColor. r=dholbert

And specify it since we don't look at gradients.

Differential Revision: https://phabricator.services.mozilla.com/D178476
This commit is contained in:
Emilio Cobos Álvarez 2023-05-30 11:25:36 +00:00
Родитель 8e34734a72
Коммит 67b6c8dad6
7 изменённых файлов: 69 добавлений и 114 удалений

Просмотреть файл

@ -5288,15 +5288,6 @@ void AddDisplayItemToBottom(nsDisplayListBuilder* aBuilder,
aList->AppendToTop(&list);
}
void PresShell::AddPrintPreviewBackgroundItem(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
nsIFrame* aFrame,
const nsRect& aBounds) {
nsDisplayItem* item = MakeDisplayItem<nsDisplaySolidColor>(
aBuilder, aFrame, aBounds, NS_RGB(115, 115, 115));
AddDisplayItemToBottom(aBuilder, aList, item);
}
static bool AddCanvasBackgroundColor(const nsDisplayList* aList,
nsIFrame* aCanvasFrame, nscolor aColor,
bool aCSSBackgroundColor) {
@ -5451,33 +5442,28 @@ PresShell::CanvasBackground PresShell::ComputeCanvasBackground() const {
// If we have a frame tree and it has style information that
// specifies the background color of the canvas, update our local
// cache of that color.
nsIFrame* rootStyleFrame = FrameConstructor()->GetRootElementStyleFrame();
if (!rootStyleFrame) {
nsIFrame* canvas = GetCanvasFrame();
if (!canvas) {
// If the root element of the document (ie html) has style 'display: none'
// then the document's background color does not get drawn; return the color
// we actually draw.
return {GetDefaultBackgroundColorToDraw(), false};
}
const ComputedStyle* bgStyle =
nsCSSRendering::FindRootFrameBackground(rootStyleFrame);
// XXX We should really be passing the canvasframe, not the root element
// style frame but we don't have access to the canvasframe here. It isn't
// a problem because only a few frames can return something other than true
// and none of them would be a canvas frame or root element style frame.
const nsIFrame* bgFrame = nsCSSRendering::FindBackgroundFrame(canvas);
nscolor color = NS_RGBA(0, 0, 0, 0);
bool drawBackgroundImage = false;
bool drawBackgroundColor = false;
const nsStyleDisplay* disp = rootStyleFrame->StyleDisplay();
const nsStyleDisplay* disp = bgFrame->StyleDisplay();
StyleAppearance appearance = disp->EffectiveAppearance();
if (rootStyleFrame->IsThemed(disp) &&
if (bgFrame->IsThemed(disp) &&
appearance != StyleAppearance::MozWinBorderlessGlass) {
// Ignore the CSS background-color if -moz-appearance is used and it is
// not one of the glass values. (Windows 7 Glass has traditionally not
// overridden background colors, so we preserve that behavior for now.)
} else {
color = nsCSSRendering::DetermineBackgroundColor(
mPresContext, bgStyle, rootStyleFrame, drawBackgroundImage,
mPresContext, bgFrame->Style(), canvas, drawBackgroundImage,
drawBackgroundColor);
}
if (!IsTransparentContainerElement()) {

Просмотреть файл

@ -905,15 +905,6 @@ class PresShell final : public nsStubDocumentObserver,
CanvasBackground ComputeCanvasBackground() const;
void UpdateCanvasBackground();
/**
* Add a solid color item to the bottom of aList with frame aFrame and
* bounds aBounds representing the dark grey background behind the page of a
* print preview presentation.
*/
void AddPrintPreviewBackgroundItem(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList, nsIFrame* aFrame,
const nsRect& aBounds);
/**
* Computes the backstop color for the view: transparent if in a transparent
* widget, otherwise the PresContext default background color. This color is

Просмотреть файл

@ -2849,36 +2849,23 @@ void nsLayoutUtils::AddExtraBackgroundItems(nsDisplayListBuilder* aBuilder,
const nsRect& aCanvasArea,
const nsRegion& aVisibleRegion,
nscolor aBackstop) {
LayoutFrameType frameType = aFrame->Type();
nsPresContext* presContext = aFrame->PresContext();
PresShell* presShell = presContext->PresShell();
// For the viewport frame in print preview/page layout we want to paint
// the grey background behind the page, not the canvas color.
if (frameType == LayoutFrameType::Viewport &&
nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
nsRect bounds =
nsRect(aBuilder->ToReferenceFrame(aFrame), aFrame->GetSize());
nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(
aBuilder, aFrame, bounds, bounds);
presShell->AddPrintPreviewBackgroundItem(aBuilder, aList, aFrame, bounds);
} else if (frameType != LayoutFrameType::Page) {
if (aFrame->IsPageFrame()) {
// For printing, this function is first called on an nsPageFrame, which
// creates a display list with a PageContent item. The PageContent item's
// paint function calls this function on the nsPageFrame's child which is
// an nsPageContentFrame. We only want to add the canvas background color
// item once, for the nsPageContentFrame.
// Add the canvas background color to the bottom of the list. This
// happens after we've built the list so that AddCanvasBackgroundColorItem
// can monkey with the contents if necessary.
nsRect canvasArea = aVisibleRegion.GetBounds();
canvasArea.IntersectRect(aCanvasArea, canvasArea);
nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(
aBuilder, aFrame, canvasArea, canvasArea);
presShell->AddCanvasBackgroundColorItem(aBuilder, aList, aFrame, canvasArea,
aBackstop);
// paint function calls this function on the nsPageFrame's child which is an
// nsPageContentFrame. We only want to add the canvas background color item
// once, for the nsPageContentFrame.
return;
}
// Add the canvas background color to the bottom of the list. This
// happens after we've built the list so that AddCanvasBackgroundColorItem
// can monkey with the contents if necessary.
nsRect canvasArea = aVisibleRegion.GetBounds();
canvasArea.IntersectRect(aCanvasArea, canvasArea);
nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(
aBuilder, aFrame, canvasArea, canvasArea);
aFrame->PresShell()->AddCanvasBackgroundColorItem(aBuilder, aList, aFrame,
canvasArea, aBackstop);
}
// #define PRINT_HITTESTINFO_STATS
@ -8557,12 +8544,6 @@ bool nsLayoutUtils::IsNonWrapperBlock(nsIFrame* aFrame) {
return aFrame->IsBlockFrameOrSubclass() && !aFrame->IsBlockWrapper();
}
bool nsLayoutUtils::NeedsPrintPreviewBackground(nsPresContext* aPresContext) {
return aPresContext->IsRootPaginatedDocument() &&
(aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
aPresContext->Type() == nsPresContext::eContext_PageLayout);
}
AutoMaybeDisableFontInflation::AutoMaybeDisableFontInflation(nsIFrame* aFrame) {
// FIXME: Now that inflation calculations are based on the flow
// root's NCA's (nearest common ancestor of its inflatable

Просмотреть файл

@ -485,21 +485,13 @@ void nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
bounds = bounds.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD);
}
// If we are in print preview/page layout we want to paint the grey
// background behind the page, not the canvas color. The canvas color gets
// painted on the page itself.
if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
presShell->AddPrintPreviewBackgroundItem(aBuilder, &childItems, frame,
bounds);
} else {
// Add the canvas background color to the bottom of the list. This
// happens after we've built the list so that
// AddCanvasBackgroundColorItem can monkey with the contents if
// necessary.
presShell->AddCanvasBackgroundColorItem(
aBuilder, &childItems, frame, bounds, NS_RGBA(0, 0, 0, 0),
AddCanvasBackgroundColorFlags::ForceDraw);
}
// Add the canvas background color to the bottom of the list. This
// happens after we've built the list so that
// AddCanvasBackgroundColorItem can monkey with the contents if
// necessary.
presShell->AddCanvasBackgroundColorItem(
aBuilder, &childItems, frame, bounds, NS_RGBA(0, 0, 0, 0),
AddCanvasBackgroundColorFlags::ForceDraw);
}
}

Просмотреть файл

@ -30,10 +30,12 @@
#include "skia/include/core/SkTextBlob.h"
#include "BorderConsts.h"
#include "nsCanvasFrame.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsIFrame.h"
#include "nsIFrameInlines.h"
#include "nsPageSequenceFrame.h"
#include "nsPoint.h"
#include "nsRect.h"
#include "nsFrameManager.h"
@ -1127,13 +1129,32 @@ void nsImageRenderer::ComputeObjectAnchorPoint(const Position& aPos,
aImageSize.height, &aTopLeft->y, &aAnchorPoint->y);
}
// In print / print preview we have multiple canvas frames (one for each page,
// and one for the document as a whole). For the topmost one, we really want the
// page sequence page background, not the root or body's background.
static nsIFrame* GetPageSequenceForCanvas(const nsIFrame* aCanvasFrame) {
MOZ_ASSERT(aCanvasFrame->IsCanvasFrame(), "not a canvas frame");
nsPresContext* pc = aCanvasFrame->PresContext();
if (!pc->IsPrintingOrPrintPreview()) {
return nullptr;
}
auto* ps = pc->PresShell()->GetPageSequenceFrame();
if (!ps) {
return nullptr;
}
if (ps->GetParent() != aCanvasFrame) {
return nullptr;
}
return ps;
}
auto nsCSSRendering::FindEffectiveBackgroundColor(nsIFrame* aFrame,
bool aStopAtThemed,
bool aPreferBodyToCanvas)
-> EffectiveBackgroundColor {
MOZ_ASSERT(aFrame);
auto BgColorIfNotTransparent = [](nsIFrame* aFrame) -> Maybe<nscolor> {
nsPresContext* pc = aFrame->PresContext();
auto BgColorIfNotTransparent = [&](nsIFrame* aFrame) -> Maybe<nscolor> {
nscolor c =
aFrame->GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
if (NS_GET_A(c) == 255) {
@ -1143,7 +1164,7 @@ auto nsCSSRendering::FindEffectiveBackgroundColor(nsIFrame* aFrame,
// TODO(emilio): We should maybe just blend with ancestor bg colors and
// such, but this is probably good enough for now, matches pre-existing
// behavior.
const nscolor defaultBg = aFrame->PresContext()->DefaultBackgroundColor();
const nscolor defaultBg = pc->DefaultBackgroundColor();
MOZ_ASSERT(NS_GET_A(defaultBg) == 255, "PreferenceSheet guarantees this");
return Some(NS_ComposeColors(defaultBg, c));
}
@ -1161,8 +1182,8 @@ auto nsCSSRendering::FindEffectiveBackgroundColor(nsIFrame* aFrame,
}
if (frame->IsCanvasFrame()) {
if (aPreferBodyToCanvas) {
if (auto* body = frame->PresContext()->Document()->GetBodyElement()) {
if (aPreferBodyToCanvas && !GetPageSequenceForCanvas(frame)) {
if (auto* body = pc->Document()->GetBodyElement()) {
if (nsIFrame* f = body->GetPrimaryFrame()) {
if (auto bg = BgColorIfNotTransparent(f)) {
return {*bg};
@ -1178,7 +1199,7 @@ auto nsCSSRendering::FindEffectiveBackgroundColor(nsIFrame* aFrame,
}
}
return {aFrame->PresContext()->DefaultBackgroundColor()};
return {pc->DefaultBackgroundColor()};
}
nsIFrame* nsCSSRendering::FindBackgroundStyleFrame(nsIFrame* aForFrame) {
@ -1251,6 +1272,20 @@ ComputedStyle* nsCSSRendering::FindRootFrameBackground(nsIFrame* aForFrame) {
return FindBackgroundStyleFrame(aForFrame)->Style();
}
static nsIFrame* FindCanvasBackgroundFrame(const nsIFrame* aForFrame,
nsIFrame* aRootElementFrame) {
MOZ_ASSERT(aForFrame->IsCanvasFrame(), "not a canvas frame");
if (auto* ps = GetPageSequenceForCanvas(aForFrame)) {
return ps;
}
if (aRootElementFrame) {
return nsCSSRendering::FindBackgroundStyleFrame(aRootElementFrame);
}
// This should always give transparent, so we'll fill it in with the default
// color if needed. This seems to happen a bit while a page is being loaded.
return const_cast<nsIFrame*>(aForFrame);
}
// Helper for FindBackgroundFrame. Returns true if aForFrame has a meaningful
// background that it should draw (i.e. that it hasn't propagated to another
// frame). See documentation for FindBackground.

Просмотреть файл

@ -296,36 +296,6 @@ struct nsCSSRendering {
*/
static mozilla::ComputedStyle* FindRootFrameBackground(nsIFrame* aForFrame);
/**
* Returns background style information for the canvas.
*
* @param aForFrame
* the frame used to represent the canvas, in the CSS sense (i.e.
* aForFrame->IsCanvasFrame() must be true)
* @param aRootElementFrame
* the frame representing the root element of the document
* @param aBackground
* contains background style information for the canvas on return
*/
static nsIFrame* FindCanvasBackgroundFrame(const nsIFrame* aForFrame,
nsIFrame* aRootElementFrame) {
MOZ_ASSERT(aForFrame->IsCanvasFrame(), "not a canvas frame");
if (aRootElementFrame) {
return FindBackgroundStyleFrame(aRootElementFrame);
}
// This should always give transparent, so we'll fill it in with the
// default color if needed. This seems to happen a bit while a page is
// being loaded.
return const_cast<nsIFrame*>(aForFrame);
}
static mozilla::ComputedStyle* FindCanvasBackground(
nsIFrame* aForFrame, nsIFrame* aRootElementFrame) {
return FindCanvasBackgroundFrame(aForFrame, aRootElementFrame)->Style();
}
/**
* Find a non-transparent background color on an ancestor, for various
* contrast checks. Note that this only accounts for background-color and

Просмотреть файл

@ -301,7 +301,7 @@
/* Collection of pages in print/print preview. Visual styles may only appear
* in print preview. */
display: block;
background: linear-gradient(#606060, #8a8a8a) fixed;
background: #606060 linear-gradient(#606060, #8a8a8a) fixed;
print-color-adjust: exact;
/* We always fill the available space in both directions */
height: 100%;