diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 8bd9c886333c..96af7f35b76c 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -4038,10 +4038,10 @@ void nsTextPaintStyle::InitCommonColors() { return; } - nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(mFrame); - NS_ASSERTION(bgFrame, "Cannot find NonTransparentBackgroundFrame."); - nscolor bgColor = - bgFrame->GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor); + auto bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(mFrame); + NS_ASSERTION(bgFrame.mFrame, "Cannot find NonTransparentBackgroundFrame."); + nscolor bgColor = bgFrame.mFrame->GetVisitedDependentColor( + &nsStyleBackground::mBackgroundColor); nscolor defaultBgColor = mPresContext->DefaultBackgroundColor(); mFrameBackgroundColor = NS_ComposeColors(defaultBgColor, bgColor); @@ -4051,7 +4051,7 @@ void nsTextPaintStyle::InitCommonColors() { mSystemFieldBackgroundColor = LookAndFeel::Color(LookAndFeel::ColorID::Field, mFrame); - if (bgFrame->IsThemed()) { + if (bgFrame.mIsThemed) { // Assume a native widget has sufficient contrast always mSufficientContrast = 0; mInitCommonColors = true; diff --git a/layout/painting/nsCSSRendering.cpp b/layout/painting/nsCSSRendering.cpp index f26fe220fc2a..69a3b53d0eb8 100644 --- a/layout/painting/nsCSSRendering.cpp +++ b/layout/painting/nsCSSRendering.cpp @@ -1123,38 +1123,34 @@ void nsImageRenderer::ComputeObjectAnchorPoint(const Position& aPos, aImageSize.height, &aTopLeft->y, &aAnchorPoint->y); } -nsIFrame* nsCSSRendering::FindNonTransparentBackgroundFrame( - nsIFrame* aFrame, bool aStartAtParent /*= false*/) { +auto nsCSSRendering::FindNonTransparentBackgroundFrame(nsIFrame* aFrame, + bool aStopAtThemed) + -> NonTransparentBackgroundFrame { NS_ASSERTION(aFrame, "Cannot find NonTransparentBackgroundFrame in a null frame"); - nsIFrame* frame = nullptr; - if (aStartAtParent) { - frame = nsLayoutUtils::GetParentOrPlaceholderFor(aFrame); - } - if (!frame) { - frame = aFrame; - } - - while (frame) { - // No need to call GetVisitedDependentColor because it always uses - // this alpha component anyway. - if (NS_GET_A(frame->StyleBackground()->BackgroundColor(frame)) > 0) { - break; + for (nsIFrame* frame = aFrame; frame; + frame = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(frame)) { + // No need to call GetVisitedDependentColor because it always uses this + // alpha component anyway. + if (NS_GET_A(frame->StyleBackground()->BackgroundColor(frame))) { + return {frame, false, false}; } - if (frame->IsThemed()) { - break; + if (aStopAtThemed && frame->IsThemed()) { + return {frame, true, false}; } - nsIFrame* parent = nsLayoutUtils::GetParentOrPlaceholderFor(frame); - if (!parent) { - break; + if (IsCanvasFrame(frame)) { + nsIFrame* bgFrame = nullptr; + if (FindBackgroundFrame(frame, &bgFrame) && + NS_GET_A(bgFrame->StyleBackground()->BackgroundColor(bgFrame))) { + return {bgFrame, false, true}; + } } - - frame = parent; } - return frame; + + return {}; } // Returns true if aFrame is a canvas frame. diff --git a/layout/painting/nsCSSRendering.h b/layout/painting/nsCSSRendering.h index 968eac042c06..17d06f2cd00c 100644 --- a/layout/painting/nsCSSRendering.h +++ b/layout/painting/nsCSSRendering.h @@ -331,16 +331,18 @@ struct nsCSSRendering { } /** - * Find a frame which draws a non-transparent background, - * for various table-related and HR-related backwards-compatibility hacks. - * This function will also stop if it finds themed frame which might draw - * background. - * - * Be very hesitant if you're considering calling this function -- it's - * usually not what you want. + * Find a frame which draws a non-transparent background, for various contrast + * checks. Note that this only accounts for background-color and might stop at + * themed frames (depending on the argument), so it might not be what you + * want. */ - static nsIFrame* FindNonTransparentBackgroundFrame( - nsIFrame* aFrame, bool aStartAtParent = false); + struct NonTransparentBackgroundFrame { + nsIFrame* mFrame = nullptr; + bool mIsThemed = false; + bool mIsForCanvas = false; + }; + static NonTransparentBackgroundFrame FindNonTransparentBackgroundFrame( + nsIFrame* aFrame, bool aStopAtThemed = true); /** * Determine the background color to draw taking into account print settings. diff --git a/widget/nsNativeTheme.cpp b/widget/nsNativeTheme.cpp index fc5bf0a48338..3c53d84e965d 100644 --- a/widget/nsNativeTheme.cpp +++ b/widget/nsNativeTheme.cpp @@ -612,47 +612,48 @@ static nsIFrame* GetBodyFrame(nsIFrame* aCanvasFrame) { return body->GetPrimaryFrame(); } -static const ComputedStyle* GetBackgroundStyle(nsIFrame* aFrame) { - if (nsCSSRendering::IsCanvasFrame(aFrame)) { +/* static */ +bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) { + // Try to find the scrolled frame. Note that for stuff like xul there + // might be none. + { + nsIFrame* frame = aFrame; + nsIScrollableFrame* scrollFrame = nullptr; + while (!scrollFrame && frame) { + scrollFrame = frame->GetScrollTargetFrame(); + frame = frame->GetParent(); + } + if (scrollFrame) { + aFrame = scrollFrame->GetScrolledFrame(); + } else { + // Leave aFrame untouched. + } + } + + auto backgroundFrame = nsCSSRendering::FindNonTransparentBackgroundFrame( + aFrame, /* aStopAtThemed = */ false); + if (!backgroundFrame.mFrame) { + return false; + } + + nscolor color = backgroundFrame.mFrame->StyleBackground()->BackgroundColor( + backgroundFrame.mFrame); + + if (backgroundFrame.mIsForCanvas) { // For canvas frames, prefer to look at the body first, because the body // background color is most likely what will be visible as the background // color of the page, even if the html element has a different background // color which prevents that of the body frame to propagate to the viewport. if (nsIFrame* bodyFrame = GetBodyFrame(aFrame)) { - if (!bodyFrame->StyleBackground()->IsTransparent(bodyFrame->Style())) { - return bodyFrame->Style(); + nscolor bodyColor = + bodyFrame->StyleBackground()->BackgroundColor(bodyFrame); + if (NS_GET_A(bodyColor)) { + color = bodyColor; } } } - ComputedStyle* bgSC = nullptr; - if (nsCSSRendering::FindBackground(aFrame, &bgSC) && - !bgSC->StyleBackground()->IsTransparent(bgSC)) { - return bgSC; - } - nsIFrame* backgroundFrame = - nsCSSRendering::FindNonTransparentBackgroundFrame(aFrame, true); - if (!backgroundFrame) { - return nullptr; - } - return backgroundFrame->Style(); -} - -/* static */ -bool nsNativeTheme::IsDarkBackground(nsIFrame* aFrame) { - nsIScrollableFrame* scrollFrame = nullptr; - while (!scrollFrame && aFrame) { - scrollFrame = aFrame->GetScrollTargetFrame(); - aFrame = aFrame->GetParent(); - } - if (!scrollFrame) { - return false; - } - - if (const auto* style = GetBackgroundStyle(scrollFrame->GetScrolledFrame())) { - return IsDarkColor(style->StyleBackground()->BackgroundColor(style)); - } - return false; + return IsDarkColor(color); } /*static*/