From 20b8aec4d52b5c1da2ac85d367a0eda24e3ab1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 17 Apr 2022 20:38:01 +0000 Subject: [PATCH] Bug 1764354 - Propagate color-scheme preference to SVG images on chrome documents. r=aosmond This allows favicons to respect the user theme even when it doesn't match the content theme. Differential Revision: https://phabricator.services.mozilla.com/D143639 --- dom/base/Document.cpp | 1 + image/AutoRestoreSVGState.h | 28 +++++++++---- image/imgLoader.cpp | 5 +++ layout/base/nsLayoutUtils.cpp | 3 +- layout/base/nsPresContext.cpp | 30 ++++++++------ layout/base/nsPresContext.h | 5 +++ .../prefers-color-scheme-dark.svg | 6 +++ .../prefers-color-scheme-light.svg | 6 +++ .../prefers-color-scheme-svg-image-ref.html | 7 ++++ .../prefers-color-scheme-svg-image.html | 7 ++++ .../color-scheme/prefers-color-scheme.svg | 9 +++++ layout/reftests/color-scheme/reftest.list | 2 + layout/svg/SVGImageContext.cpp | 40 ++++++++++++------- layout/svg/SVGImageContext.h | 29 ++++++++++---- layout/tools/reftest/jar.mn | 1 + layout/xul/tree/nsTreeBodyFrame.cpp | 7 ++-- widget/cocoa/MOZIconHelper.h | 2 + widget/cocoa/MOZIconHelper.mm | 8 ++-- widget/cocoa/OSXNotificationCenter.mm | 4 +- widget/cocoa/nsCocoaUtils.h | 6 ++- widget/cocoa/nsCocoaUtils.mm | 20 +++++----- widget/cocoa/nsCursorManager.mm | 2 +- widget/cocoa/nsMenuItemIconX.h | 3 +- widget/cocoa/nsMenuItemIconX.mm | 4 ++ widget/cocoa/nsTouchBarInputIcon.mm | 1 + 25 files changed, 170 insertions(+), 66 deletions(-) create mode 100644 layout/reftests/color-scheme/prefers-color-scheme-dark.svg create mode 100644 layout/reftests/color-scheme/prefers-color-scheme-light.svg create mode 100644 layout/reftests/color-scheme/prefers-color-scheme-svg-image-ref.html create mode 100644 layout/reftests/color-scheme/prefers-color-scheme-svg-image.html create mode 100644 layout/reftests/color-scheme/prefers-color-scheme.svg diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index f188bec341b2..db6d1f5cd0a6 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -205,6 +205,7 @@ #include "mozilla/dom/PromiseNativeHandler.h" #include "mozilla/dom/ResizeObserverController.h" #include "mozilla/dom/SVGElement.h" +#include "mozilla/dom/SVGDocument.h" #include "mozilla/dom/SVGSVGElement.h" #include "mozilla/dom/SVGUseElement.h" #include "mozilla/dom/ScriptLoader.h" diff --git a/image/AutoRestoreSVGState.h b/image/AutoRestoreSVGState.h index 9bb4ff6b97b4..147e839db00c 100644 --- a/image/AutoRestoreSVGState.h +++ b/image/AutoRestoreSVGState.h @@ -10,11 +10,14 @@ #include "mozilla/AutoRestore.h" #include "mozilla/SVGContextPaint.h" #include "mozilla/dom/SVGSVGElement.h" +#include "nsPresContext.h" #include "SVGDrawingParameters.h" #include "SVGDocumentWrapper.h" +#include "mozilla/dom/DocumentInlines.h" +#include "mozilla/dom/SVGDocument.h" +#include "mozilla/dom/BrowsingContextBinding.h" -namespace mozilla { -namespace image { +namespace mozilla::image { class MOZ_STACK_CLASS AutoRestoreSVGState final { public: @@ -28,17 +31,27 @@ class MOZ_STACK_CLASS AutoRestoreSVGState final { float aAnimationTime, SVGDocumentWrapper* aSVGDocumentWrapper, bool aContextPaint) - : mIsDrawing(aSVGDocumentWrapper->mIsDrawing) + : mIsDrawing(aSVGDocumentWrapper->mIsDrawing), // Apply any 'preserveAspectRatio' override (if specified) to the root // element: - , - mPAR(aSVGContext, aSVGDocumentWrapper->GetRootSVGElem()) + mPAR(aSVGContext, aSVGDocumentWrapper->GetRootSVGElem()), // Set the animation time: - , mTime(aSVGDocumentWrapper->GetRootSVGElem(), aAnimationTime) { MOZ_ASSERT(!mIsDrawing.SavedValue()); MOZ_ASSERT(aSVGDocumentWrapper->GetDocument()); + if (auto* pc = aSVGDocumentWrapper->GetDocument()->GetPresContext()) { + pc->SetColorSchemeOverride([&] { + if (aSVGContext && aSVGContext->GetColorScheme()) { + auto scheme = *aSVGContext->GetColorScheme(); + return scheme == ColorScheme::Light + ? dom::PrefersColorSchemeOverride::Light + : dom::PrefersColorSchemeOverride::Dark; + } + return dom::PrefersColorSchemeOverride::None; + }()); + } + aSVGDocumentWrapper->mIsDrawing = true; // Set context paint (if specified) on the document: @@ -56,7 +69,6 @@ class MOZ_STACK_CLASS AutoRestoreSVGState final { Maybe mContextPaint; }; -} // namespace image -} // namespace mozilla +} // namespace mozilla::image #endif // mozilla_image_AutoRestoreSVGState_h diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index bf369f22f6c8..6f8090713442 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -450,6 +450,11 @@ class imgMemoryReporter final : public nsIMemoryReporter { LossyAppendUTF16toASCII(aspect, surfacePathPrefix); surfacePathPrefix.AppendLiteral(") "); } + if (auto scheme = context.GetColorScheme()) { + surfacePathPrefix.AppendLiteral("colorScheme="); + surfacePathPrefix.AppendInt(int32_t(*scheme)); + surfacePathPrefix.AppendLiteral(" "); + } if (context.GetContextPaint()) { const SVGEmbeddingContextPaint* paint = context.GetContextPaint(); surfacePathPrefix.AppendLiteral("contextPaint=("); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 2faeafe7c6a0..35f3b91dffc4 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -6706,7 +6706,8 @@ ImgDrawResult nsLayoutUtils::DrawImage( const nsRect& aFill, const nsPoint& aAnchor, const nsRect& aDirty, uint32_t aImageFlags, float aOpacity) { Maybe svgContext; - SVGImageContext::MaybeStoreContextPaint(svgContext, aComputedStyle, aImage); + SVGImageContext::MaybeStoreContextPaint(svgContext, *aPresContext, + *aComputedStyle, aImage); return DrawImageInternal(aContext, aPresContext, aImage, aSamplingFilter, aDest, aFill, aAnchor, aDirty, svgContext, diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index e13523fd3f5b..b3170f5fbf23 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -887,6 +887,22 @@ Maybe nsPresContext::GetOverriddenOrEmbedderColorScheme() const { return Nothing(); } +void nsPresContext::SetColorSchemeOverride( + PrefersColorSchemeOverride aOverride) { + auto oldScheme = mDocument->PreferredColorScheme(); + + mOverriddenOrEmbedderColorScheme = aOverride; + + if (mDocument->PreferredColorScheme() != oldScheme) { + // We need to restyle because not only media queries have changed, system + // colors may as well via the prefers-color-scheme meta tag / effective + // color-scheme property value. + MediaFeatureValuesChanged({RestyleHint::RecascadeSubtree(), nsChangeHint(0), + MediaFeatureChangeReason::SystemMetricsChange}, + MediaFeatureChangePropagation::JustThisDocument); + } +} + void nsPresContext::RecomputeBrowsingContextDependentData() { MOZ_ASSERT(mDocument); dom::Document* doc = mDocument; @@ -905,9 +921,8 @@ void nsPresContext::RecomputeBrowsingContextDependentData() { SetTextZoom(browsingContext->TextZoom()); SetOverrideDPPX(browsingContext->OverrideDPPX()); - auto oldScheme = mDocument->PreferredColorScheme(); auto* top = browsingContext->Top(); - mOverriddenOrEmbedderColorScheme = [&] { + SetColorSchemeOverride([&] { auto overriden = top->PrefersColorSchemeOverride(); if (overriden != PrefersColorSchemeOverride::None) { return overriden; @@ -919,16 +934,7 @@ void nsPresContext::RecomputeBrowsingContextDependentData() { } } return PrefersColorSchemeOverride::None; - }(); - - if (mDocument->PreferredColorScheme() != oldScheme) { - // We need to restyle because not only media queries have changed, system - // colors may as well via the prefers-color-scheme meta tag / effective - // color-scheme property value. - MediaFeatureValuesChanged({RestyleHint::RecascadeSubtree(), nsChangeHint(0), - MediaFeatureChangeReason::SystemMetricsChange}, - MediaFeatureChangePropagation::JustThisDocument); - } + }()); if (doc == mDocument) { // Medium doesn't apply to resource documents, etc. diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 67112f29828a..3e07747821e7 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -592,6 +592,11 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr { */ void RecomputeBrowsingContextDependentData(); + /** + * Sets the effective color scheme override, and invalidate stuff as needed. + */ + void SetColorSchemeOverride(mozilla::dom::PrefersColorSchemeOverride); + mozilla::CSSCoord GetAutoQualityMinFontSize() const { return DevPixelsToFloatCSSPixels(mAutoQualityMinFontSizePixelsPref); } diff --git a/layout/reftests/color-scheme/prefers-color-scheme-dark.svg b/layout/reftests/color-scheme/prefers-color-scheme-dark.svg new file mode 100644 index 000000000000..f65fce76ecbd --- /dev/null +++ b/layout/reftests/color-scheme/prefers-color-scheme-dark.svg @@ -0,0 +1,6 @@ + + + + diff --git a/layout/reftests/color-scheme/prefers-color-scheme-light.svg b/layout/reftests/color-scheme/prefers-color-scheme-light.svg new file mode 100644 index 000000000000..23ac2ad94960 --- /dev/null +++ b/layout/reftests/color-scheme/prefers-color-scheme-light.svg @@ -0,0 +1,6 @@ + + + + diff --git a/layout/reftests/color-scheme/prefers-color-scheme-svg-image-ref.html b/layout/reftests/color-scheme/prefers-color-scheme-svg-image-ref.html new file mode 100644 index 000000000000..6551eaffae0a --- /dev/null +++ b/layout/reftests/color-scheme/prefers-color-scheme-svg-image-ref.html @@ -0,0 +1,7 @@ + +
+ +
+
+ +
diff --git a/layout/reftests/color-scheme/prefers-color-scheme-svg-image.html b/layout/reftests/color-scheme/prefers-color-scheme-svg-image.html new file mode 100644 index 000000000000..73bb9fe06c3e --- /dev/null +++ b/layout/reftests/color-scheme/prefers-color-scheme-svg-image.html @@ -0,0 +1,7 @@ + +
+ +
+
+ +
diff --git a/layout/reftests/color-scheme/prefers-color-scheme.svg b/layout/reftests/color-scheme/prefers-color-scheme.svg new file mode 100644 index 000000000000..5523ff39fa49 --- /dev/null +++ b/layout/reftests/color-scheme/prefers-color-scheme.svg @@ -0,0 +1,9 @@ + + + + diff --git a/layout/reftests/color-scheme/reftest.list b/layout/reftests/color-scheme/reftest.list index a70157630b41..37dc3d79716a 100644 --- a/layout/reftests/color-scheme/reftest.list +++ b/layout/reftests/color-scheme/reftest.list @@ -2,3 +2,5 @@ defaults pref(layout.css.color-scheme.enabled,true) != color-scheme-basic.html color-scheme-basic-notref.html != color-scheme-themed-button.html color-scheme-themed-button-notref.html + +== chrome://reftest/content/color-scheme/prefers-color-scheme-svg-image.html chrome://reftest/content/color-scheme/prefers-color-scheme-svg-image-ref.html diff --git a/layout/svg/SVGImageContext.cpp b/layout/svg/SVGImageContext.cpp index 32238550ecf4..981c68637f4e 100644 --- a/layout/svg/SVGImageContext.cpp +++ b/layout/svg/SVGImageContext.cpp @@ -10,6 +10,8 @@ // Keep others in (case-insensitive) order: #include "gfxUtils.h" #include "mozilla/Preferences.h" +#include "mozilla/LookAndFeel.h" +#include "mozilla/dom/Document.h" #include "nsIFrame.h" #include "nsPresContext.h" #include "nsStyleStruct.h" @@ -20,23 +22,33 @@ namespace mozilla { void SVGImageContext::MaybeStoreContextPaint(Maybe& aContext, nsIFrame* aFromFrame, imgIContainer* aImgContainer) { - return MaybeStoreContextPaint(aContext, aFromFrame->Style(), aImgContainer); + return MaybeStoreContextPaint(aContext, *aFromFrame->PresContext(), + *aFromFrame->Style(), aImgContainer); } /* static */ -void SVGImageContext::MaybeStoreContextPaint( - Maybe& aContext, const ComputedStyle* aFromComputedStyle, - imgIContainer* aImgContainer) { - const nsStyleSVG* style = aFromComputedStyle->StyleSVG(); - - if (!style->ExposesContextProperties()) { - // Content must have '-moz-context-properties' set to the names of the - // properties it wants to expose to images it links to. +void SVGImageContext::MaybeStoreContextPaint(Maybe& aContext, + const nsPresContext& aPresContext, + const ComputedStyle& aStyle, + imgIContainer* aImgContainer) { + if (aImgContainer->GetType() != imgIContainer::TYPE_VECTOR) { + // Avoid this overhead for raster images. return; } - if (aImgContainer->GetType() != imgIContainer::TYPE_VECTOR) { - // Avoid this overhead for raster images. + if (aPresContext.Document()->IsDocumentURISchemeChrome()) { + if (!aContext) { + aContext.emplace(); + } + auto scheme = LookAndFeel::ColorSchemeForStyle( + *aPresContext.Document(), aStyle.StyleUI()->mColorScheme.bits); + aContext->SetColorScheme(Some(scheme)); + } + + const nsStyleSVG* style = aStyle.StyleSVG(); + if (!style->ExposesContextProperties()) { + // Content must have '-moz-context-properties' set to the names of the + // properties it wants to expose to images it links to. return; } @@ -47,14 +59,12 @@ void SVGImageContext::MaybeStoreContextPaint( if ((style->mMozContextProperties.bits & StyleContextPropertyBits::FILL) && style->mFill.kind.IsColor()) { haveContextPaint = true; - contextPaint->SetFill( - style->mFill.kind.AsColor().CalcColor(*aFromComputedStyle)); + contextPaint->SetFill(style->mFill.kind.AsColor().CalcColor(aStyle)); } if ((style->mMozContextProperties.bits & StyleContextPropertyBits::STROKE) && style->mStroke.kind.IsColor()) { haveContextPaint = true; - contextPaint->SetStroke( - style->mStroke.kind.AsColor().CalcColor(*aFromComputedStyle)); + contextPaint->SetStroke(style->mStroke.kind.AsColor().CalcColor(aStyle)); } if (style->mMozContextProperties.bits & StyleContextPropertyBits::FILL_OPACITY) { diff --git a/layout/svg/SVGImageContext.h b/layout/svg/SVGImageContext.h index 24173a3d916e..9e3f934c4ef8 100644 --- a/layout/svg/SVGImageContext.h +++ b/layout/svg/SVGImageContext.h @@ -16,11 +16,12 @@ class nsIFrame; namespace mozilla { +enum class ColorScheme : uint8_t; class ComputedStyle; // SVG image-specific rendering context. For imgIContainer::Draw. // Used to pass information such as -// - viewport information from CSS, and +// - viewport and color-scheme information from CSS, and // - overridden attributes from an SVG element // to the image's internal SVG document when it's drawn. class SVGImageContext { @@ -45,17 +46,19 @@ class SVGImageContext { */ explicit SVGImageContext( const Maybe& aViewportSize, - const Maybe& aPreserveAspectRatio = Nothing()) + const Maybe& aPreserveAspectRatio = Nothing(), + const Maybe& aColorScheme = Nothing()) : mViewportSize(aViewportSize), - mPreserveAspectRatio(aPreserveAspectRatio) {} + mPreserveAspectRatio(aPreserveAspectRatio), + mColorScheme(aColorScheme) {} static void MaybeStoreContextPaint(Maybe& aContext, nsIFrame* aFromFrame, imgIContainer* aImgContainer); static void MaybeStoreContextPaint(Maybe& aContext, - const ComputedStyle* aFromComputedStyle, - imgIContainer* aImgContainer); + const nsPresContext&, const ComputedStyle&, + imgIContainer*); const Maybe& GetViewportSize() const { return mViewportSize; } @@ -63,6 +66,12 @@ class SVGImageContext { mViewportSize = aSize; } + const Maybe& GetColorScheme() const { return mColorScheme; } + + void SetColorScheme(const Maybe& aScheme) { + mColorScheme = aScheme; + } + const Maybe& GetPreserveAspectRatio() const { return mPreserveAspectRatio; } @@ -86,7 +95,8 @@ class SVGImageContext { *mContextPaint == *aOther.mContextPaint); return contextPaintIsEqual && mViewportSize == aOther.mViewportSize && - mPreserveAspectRatio == aOther.mPreserveAspectRatio; + mPreserveAspectRatio == aOther.mPreserveAspectRatio && + mColorScheme == aOther.mColorScheme; } bool operator!=(const SVGImageContext& aOther) const { @@ -99,7 +109,8 @@ class SVGImageContext { hash = HashGeneric(hash, mContextPaint->Hash()); } return HashGeneric(hash, mViewportSize.map(HashSize).valueOr(0), - mPreserveAspectRatio.map(HashPAR).valueOr(0)); + mPreserveAspectRatio.map(HashPAR).valueOr(0), + mColorScheme.map(HashColorScheme).valueOr(0)); } private: @@ -109,11 +120,15 @@ class SVGImageContext { static PLDHashNumber HashPAR(const SVGPreserveAspectRatio& aPAR) { return aPAR.Hash(); } + static PLDHashNumber HashColorScheme(ColorScheme aScheme) { + return HashGeneric(uint8_t(aScheme)); + } // NOTE: When adding new member-vars, remember to update Hash() & operator==. RefPtr mContextPaint; Maybe mViewportSize; Maybe mPreserveAspectRatio; + Maybe mColorScheme; }; } // namespace mozilla diff --git a/layout/tools/reftest/jar.mn b/layout/tools/reftest/jar.mn index f31e15bf40cc..d5b5f5e8a32d 100644 --- a/layout/tools/reftest/jar.mn +++ b/layout/tools/reftest/jar.mn @@ -12,6 +12,7 @@ reftest.jar: content/forms/placeholder (../../reftests/forms/placeholder/*) content/forms/textbox (../../reftests/forms/textbox/*) content/image-region (../../reftests/image-region/*) + content/color-scheme (../../reftests/color-scheme/*) content/invalidation (../../reftests/invalidation/*) content/native-theme (../../reftests/native-theme/*) content/reftest-sanity (../../reftests/reftest-sanity/*) diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp index eb70b5289acd..88f775a97962 100644 --- a/layout/xul/tree/nsTreeBodyFrame.cpp +++ b/layout/xul/tree/nsTreeBodyFrame.cpp @@ -3219,8 +3219,8 @@ ImgDrawResult nsTreeBodyFrame::PaintTwisty( // Apply context paint if applicable Maybe svgContext; - SVGImageContext::MaybeStoreContextPaint(svgContext, twistyContext, - image); + SVGImageContext::MaybeStoreContextPaint(svgContext, *aPresContext, + *twistyContext, image); // Paint the image. result &= nsLayoutUtils::DrawSingleUnscaledImage( @@ -3593,7 +3593,8 @@ ImgDrawResult nsTreeBodyFrame::PaintCheckbox(int32_t aRowIndex, // Apply context paint if applicable Maybe svgContext; - SVGImageContext::MaybeStoreContextPaint(svgContext, checkboxContext, image); + SVGImageContext::MaybeStoreContextPaint(svgContext, *aPresContext, + *checkboxContext, image); // Paint the image. result &= nsLayoutUtils::DrawSingleUnscaledImage( aRenderingContext, aPresContext, image, SamplingFilter::POINT, pt, diff --git a/widget/cocoa/MOZIconHelper.h b/widget/cocoa/MOZIconHelper.h index 16f03573fc68..940768f56de9 100644 --- a/widget/cocoa/MOZIconHelper.h +++ b/widget/cocoa/MOZIconHelper.h @@ -11,6 +11,7 @@ #include "nsRect.h" class imgIContainer; +class nsPresContext; namespace mozilla { class ComputedStyle; @@ -24,6 +25,7 @@ class ComputedStyle; // Returns an autoreleased NSImage. + (NSImage*)iconImageFromImageContainer:(imgIContainer*)aImage withSize:(NSSize)aSize + presContext:(const nsPresContext*)aPresContext computedStyle:(const mozilla::ComputedStyle*)aComputedStyle subrect:(const nsIntRect&)aSubRect scaleFactor:(CGFloat)aScaleFactor; diff --git a/widget/cocoa/MOZIconHelper.mm b/widget/cocoa/MOZIconHelper.mm index f8fad8e7a14f..b7cbac5b6806 100644 --- a/widget/cocoa/MOZIconHelper.mm +++ b/widget/cocoa/MOZIconHelper.mm @@ -22,6 +22,7 @@ // Returns an autoreleased NSImage. + (NSImage*)iconImageFromImageContainer:(imgIContainer*)aImage withSize:(NSSize)aSize + presContext:(const nsPresContext*)aPresContext computedStyle:(const mozilla::ComputedStyle*)aComputedStyle subrect:(const nsIntRect&)aSubRect scaleFactor:(CGFloat)aScaleFactor { @@ -30,11 +31,12 @@ nsresult rv; if (aScaleFactor != 0.0f) { rv = nsCocoaUtils::CreateNSImageFromImageContainer(aImage, imgIContainer::FRAME_CURRENT, - aComputedStyle, &retainedImage, aScaleFactor, - &isEntirelyBlack); + aPresContext, aComputedStyle, &retainedImage, + aScaleFactor, &isEntirelyBlack); } else { rv = nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer( - aImage, imgIContainer::FRAME_CURRENT, aComputedStyle, &retainedImage, &isEntirelyBlack); + aImage, imgIContainer::FRAME_CURRENT, aPresContext, aComputedStyle, &retainedImage, + &isEntirelyBlack); } NSImage* image = [retainedImage autorelease]; diff --git a/widget/cocoa/OSXNotificationCenter.mm b/widget/cocoa/OSXNotificationCenter.mm index 6d79a65c21bf..ea0c49328f21 100644 --- a/widget/cocoa/OSXNotificationCenter.mm +++ b/widget/cocoa/OSXNotificationCenter.mm @@ -509,9 +509,9 @@ OSXNotificationCenter::OnImageReady(nsISupports* aUserData, imgIRequest* aReques } NSImage* cocoaImage = nil; - // TODO: Pass ComputedStyle here to support context paint properties + // TODO: Pass pres context / ComputedStyle here to support context paint properties nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(image, imgIContainer::FRAME_FIRST, - nullptr, &cocoaImage); + nullptr, nullptr, &cocoaImage); (osxni->mPendingNotification).contentImage = cocoaImage; [cocoaImage release]; ShowPendingNotification(osxni); diff --git a/widget/cocoa/nsCocoaUtils.h b/widget/cocoa/nsCocoaUtils.h index b39c32717298..f454a65e08a6 100644 --- a/widget/cocoa/nsCocoaUtils.h +++ b/widget/cocoa/nsCocoaUtils.h @@ -266,6 +266,7 @@ class nsCocoaUtils { @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise */ static nsresult CreateNSImageFromImageContainer(imgIContainer* aImage, uint32_t aWhichFrame, + const nsPresContext* aPresContext, const mozilla::ComputedStyle* aComputedStyle, NSImage** aResult, CGFloat scaleFactor, bool* aIsEntirelyBlack = nullptr); @@ -284,8 +285,9 @@ class nsCocoaUtils { @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise */ static nsresult CreateDualRepresentationNSImageFromImageContainer( - imgIContainer* aImage, uint32_t aWhichFrame, const mozilla::ComputedStyle* aComputedStyle, - NSImage** aResult, bool* aIsEntirelyBlack = nullptr); + imgIContainer* aImage, uint32_t aWhichFrame, const nsPresContext* aPresContext, + const mozilla::ComputedStyle* aComputedStyle, NSImage** aResult, + bool* aIsEntirelyBlack = nullptr); /** * Returns nsAString for aSrc. diff --git a/widget/cocoa/nsCocoaUtils.mm b/widget/cocoa/nsCocoaUtils.mm index 847a43eac166..df78e6dd6747 100644 --- a/widget/cocoa/nsCocoaUtils.mm +++ b/widget/cocoa/nsCocoaUtils.mm @@ -44,10 +44,8 @@ using namespace mozilla; using namespace mozilla::widget; using mozilla::dom::Promise; -using mozilla::gfx::BackendType; using mozilla::gfx::DataSourceSurface; using mozilla::gfx::DrawTarget; -using mozilla::gfx::Factory; using mozilla::gfx::SamplingFilter; using mozilla::gfx::IntPoint; using mozilla::gfx::IntRect; @@ -55,7 +53,6 @@ using mozilla::gfx::IntSize; using mozilla::gfx::SurfaceFormat; using mozilla::gfx::SourceSurface; using mozilla::image::ImageRegion; -using std::ceil; LazyLogModule gCocoaUtilsLog("nsCocoaUtils"); #undef LOG @@ -389,6 +386,7 @@ nsresult nsCocoaUtils::CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage* } nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, uint32_t aWhichFrame, + const nsPresContext* aPresContext, const ComputedStyle* aComputedStyle, NSImage** aResult, CGFloat scaleFactor, bool* aIsEntirelyBlack) { @@ -412,8 +410,8 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, ui MOZ_ASSERT(context); Maybe svgContext; - if (aComputedStyle) { - SVGImageContext::MaybeStoreContextPaint(svgContext, aComputedStyle, aImage); + if (aPresContext && aComputedStyle) { + SVGImageContext::MaybeStoreContextPaint(svgContext, *aPresContext, *aComputedStyle, aImage); } mozilla::image::ImgDrawResult res = aImage->Draw(context, scaledSize, ImageRegion::Create(scaledSize), aWhichFrame, @@ -451,8 +449,8 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, ui } nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer( - imgIContainer* aImage, uint32_t aWhichFrame, const ComputedStyle* aComputedStyle, - NSImage** aResult, bool* aIsEntirelyBlack) { + imgIContainer* aImage, uint32_t aWhichFrame, const nsPresContext* aPresContext, + const ComputedStyle* aComputedStyle, NSImage** aResult, bool* aIsEntirelyBlack) { int32_t width = 0, height = 0; aImage->GetWidth(&width); aImage->GetHeight(&height); @@ -461,8 +459,8 @@ nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer( [*aResult setSize:size]; NSImage* newRepresentation = nil; - nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer( - aImage, aWhichFrame, aComputedStyle, &newRepresentation, 1.0f, aIsEntirelyBlack); + nsresult rv = CreateNSImageFromImageContainer(aImage, aWhichFrame, aPresContext, aComputedStyle, + &newRepresentation, 1.0f, aIsEntirelyBlack); if (NS_FAILED(rv) || !newRepresentation) { return NS_ERROR_FAILURE; } @@ -472,8 +470,8 @@ nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer( [newRepresentation release]; newRepresentation = nil; - rv = nsCocoaUtils::CreateNSImageFromImageContainer(aImage, aWhichFrame, aComputedStyle, - &newRepresentation, 2.0f, aIsEntirelyBlack); + rv = CreateNSImageFromImageContainer(aImage, aWhichFrame, aPresContext, aComputedStyle, + &newRepresentation, 2.0f, aIsEntirelyBlack); if (NS_FAILED(rv) || !newRepresentation) { return NS_ERROR_FAILURE; } diff --git a/widget/cocoa/nsCursorManager.mm b/widget/cocoa/nsCursorManager.mm index 0eadadfa6ff0..16f7dcb91681 100644 --- a/widget/cocoa/nsCursorManager.mm +++ b/widget/cocoa/nsCursorManager.mm @@ -262,7 +262,7 @@ static constexpr nsCursor kCustomCursor = eCursorCount; NSImage* cursorImage; nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer( - aCursor.mContainer, imgIContainer::FRAME_FIRST, nullptr, &cursorImage, scaleFactor); + aCursor.mContainer, imgIContainer::FRAME_FIRST, nullptr, nullptr, &cursorImage, scaleFactor); if (NS_FAILED(rv) || !cursorImage) { return NS_ERROR_FAILURE; } diff --git a/widget/cocoa/nsMenuItemIconX.h b/widget/cocoa/nsMenuItemIconX.h index dca07a8fd481..c5dc7cf064ec 100644 --- a/widget/cocoa/nsMenuItemIconX.h +++ b/widget/cocoa/nsMenuItemIconX.h @@ -20,6 +20,7 @@ class nsIContent; class nsIPrincipal; class imgRequestProxy; class nsMenuParentX; +class nsPresContext; namespace mozilla { class ComputedStyle; @@ -58,10 +59,10 @@ class nsMenuItemIconX final : public mozilla::widget::IconLoader::Listener { // GetIconURI returns null if the item should not have any icon. already_AddRefed GetIconURI(nsIContent* aContent); - nsCOMPtr mContent; // always non-null Listener* mListener; // [weak] nsIntRect mImageRegionRect; RefPtr mComputedStyle; + RefPtr mPresContext; NSImage* mIconImage = nil; // [strong] RefPtr mIconLoader; }; diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm index 7e446c8dabe8..92ece11acfa5 100644 --- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -23,6 +23,7 @@ #include "MOZIconHelper.h" #include "mozilla/dom/Document.h" +#include "mozilla/dom/DocumentInlines.h" #include "nsCocoaUtils.h" #include "nsComputedDOMStyle.h" #include "nsContentUtils.h" @@ -150,6 +151,7 @@ already_AddRefed nsMenuItemIconX::GetIconURI(nsIContent* aContent) { mImageRegionRect = r.ToNearestPixels(mozilla::AppUnitsPerCSSPixel()); } mComputedStyle = std::move(sc); + mPresContext = document->GetPresContext(); return iconURI.forget(); } @@ -168,10 +170,12 @@ nsresult nsMenuItemIconX::OnComplete(imgIContainer* aImage) { mIconImage = [[MOZIconHelper iconImageFromImageContainer:aImage withSize:NSMakeSize(kIconSize, kIconSize) + presContext:mPresContext computedStyle:mComputedStyle subrect:mImageRegionRect scaleFactor:0.0f] retain]; mComputedStyle = nullptr; + mPresContext = nullptr; if (mListener) { mListener->IconUpdated(); diff --git a/widget/cocoa/nsTouchBarInputIcon.mm b/widget/cocoa/nsTouchBarInputIcon.mm index 3a5c5b0c58a8..a99002c50519 100644 --- a/widget/cocoa/nsTouchBarInputIcon.mm +++ b/widget/cocoa/nsTouchBarInputIcon.mm @@ -119,6 +119,7 @@ nsresult nsTouchBarInputIcon::OnComplete(imgIContainer* aImage) { // displays and we have no need for icons @1x. NSImage* image = [MOZIconHelper iconImageFromImageContainer:aImage withSize:NSMakeSize(kIconHeight, kIconHeight) + presContext:nullptr computedStyle:nullptr subrect:mImageRegionRect scaleFactor:kHiDPIScalingFactor];