diff --git a/widget/cocoa/MOZIconHelper.h b/widget/cocoa/MOZIconHelper.h index be26c6d11d6d..16f03573fc68 100644 --- a/widget/cocoa/MOZIconHelper.h +++ b/widget/cocoa/MOZIconHelper.h @@ -12,6 +12,10 @@ class imgIContainer; +namespace mozilla { +class ComputedStyle; +} + @interface MOZIconHelper : NSObject // Returns an autoreleased empty NSImage. @@ -20,6 +24,7 @@ class imgIContainer; // Returns an autoreleased NSImage. + (NSImage*)iconImageFromImageContainer:(imgIContainer*)aImage withSize:(NSSize)aSize + 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 fce5f3bdb6c4..f8fad8e7a14f 100644 --- a/widget/cocoa/MOZIconHelper.mm +++ b/widget/cocoa/MOZIconHelper.mm @@ -22,17 +22,19 @@ // Returns an autoreleased NSImage. + (NSImage*)iconImageFromImageContainer:(imgIContainer*)aImage withSize:(NSSize)aSize + computedStyle:(const mozilla::ComputedStyle*)aComputedStyle subrect:(const nsIntRect&)aSubRect scaleFactor:(CGFloat)aScaleFactor { bool isEntirelyBlack = false; NSImage* retainedImage = nil; nsresult rv; if (aScaleFactor != 0.0f) { - rv = nsCocoaUtils::CreateNSImageFromImageContainer( - aImage, imgIContainer::FRAME_CURRENT, &retainedImage, aScaleFactor, &isEntirelyBlack); + rv = nsCocoaUtils::CreateNSImageFromImageContainer(aImage, imgIContainer::FRAME_CURRENT, + aComputedStyle, &retainedImage, aScaleFactor, + &isEntirelyBlack); } else { rv = nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer( - aImage, imgIContainer::FRAME_CURRENT, &retainedImage, &isEntirelyBlack); + aImage, imgIContainer::FRAME_CURRENT, aComputedStyle, &retainedImage, &isEntirelyBlack); } NSImage* image = [retainedImage autorelease]; diff --git a/widget/cocoa/OSXNotificationCenter.mm b/widget/cocoa/OSXNotificationCenter.mm index 73e52f2603eb..bd19cfb23197 100644 --- a/widget/cocoa/OSXNotificationCenter.mm +++ b/widget/cocoa/OSXNotificationCenter.mm @@ -507,8 +507,9 @@ OSXNotificationCenter::OnImageReady(nsISupports* aUserData, imgIRequest* aReques } NSImage* cocoaImage = nil; + // TODO: Pass ComputedStyle here to support context paint properties nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(image, imgIContainer::FRAME_FIRST, - &cocoaImage); + nullptr, &cocoaImage); (osxni->mPendingNotification).contentImage = cocoaImage; [cocoaImage release]; ShowPendingNotification(osxni); diff --git a/widget/cocoa/nsCocoaUtils.h b/widget/cocoa/nsCocoaUtils.h index f5794be998c1..4494bd473931 100644 --- a/widget/cocoa/nsCocoaUtils.h +++ b/widget/cocoa/nsCocoaUtils.h @@ -257,6 +257,8 @@ class nsCocoaUtils { Combines the two methods above. The caller owns the NSImage. @param aImage the image to extract a frame from @param aWhichFrame the frame to extract (see imgIContainer FRAME_*) + @param aComputedStyle the ComputedStyle of the element that the image is for, to support SVG + context paint properties, can be null @param aResult the resulting NSImage @param scaleFactor the desired scale factor of the NSImage (2 for a retina display) @param aIsEntirelyBlack an outparam that, if non-null, will be set to a @@ -265,6 +267,7 @@ class nsCocoaUtils { @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise */ static nsresult CreateNSImageFromImageContainer(imgIContainer* aImage, uint32_t aWhichFrame, + const mozilla::ComputedStyle* aComputedStyle, NSImage** aResult, CGFloat scaleFactor, bool* aIsEntirelyBlack = nullptr); @@ -273,6 +276,8 @@ class nsCocoaUtils { The caller owns the NSImage. @param aImage the image to extract a frame from @param aWhichFrame the frame to extract (see imgIContainer FRAME_*) + @param aComputedStyle the ComputedStyle of the element that the image is for, to support SVG + context paint properties, can be null @param aResult the resulting NSImage @param aIsEntirelyBlack an outparam that, if non-null, will be set to a bool that indicates whether the RGB values on all @@ -280,8 +285,8 @@ class nsCocoaUtils { @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise */ static nsresult CreateDualRepresentationNSImageFromImageContainer( - imgIContainer* aImage, uint32_t aWhichFrame, NSImage** aResult, - bool* aIsEntirelyBlack = nullptr); + imgIContainer* aImage, uint32_t aWhichFrame, 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 30634aabd905..f9e77301ba90 100644 --- a/widget/cocoa/nsCocoaUtils.mm +++ b/widget/cocoa/nsCocoaUtils.mm @@ -388,6 +388,7 @@ nsresult nsCocoaUtils::CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage* } nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, uint32_t aWhichFrame, + const ComputedStyle* aComputedStyle, NSImage** aResult, CGFloat scaleFactor, bool* aIsEntirelyBlack) { RefPtr surface; @@ -396,7 +397,7 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, ui aImage->GetHeight(&height); // Render a vector image at the correct resolution on a retina display - if (aImage->GetType() == imgIContainer::TYPE_VECTOR && scaleFactor != 1.0f) { + if (aImage->GetType() == imgIContainer::TYPE_VECTOR) { IntSize scaledSize = IntSize::Ceil(width * scaleFactor, height * scaleFactor); RefPtr drawTarget = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( @@ -409,9 +410,13 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, ui RefPtr context = gfxContext::CreateOrNull(drawTarget); MOZ_ASSERT(context); - mozilla::image::ImgDrawResult res = aImage->Draw( - context, scaledSize, ImageRegion::Create(scaledSize), aWhichFrame, SamplingFilter::POINT, - /* no SVGImageContext */ Nothing(), imgIContainer::FLAG_SYNC_DECODE, 1.0); + Maybe svgContext; + if (aComputedStyle) { + SVGImageContext::MaybeStoreContextPaint(svgContext, aComputedStyle, aImage); + } + mozilla::image::ImgDrawResult res = + aImage->Draw(context, scaledSize, ImageRegion::Create(scaledSize), aWhichFrame, + SamplingFilter::POINT, svgContext, imgIContainer::FLAG_SYNC_DECODE, 1.0); if (res != mozilla::image::ImgDrawResult::SUCCESS) { return NS_ERROR_FAILURE; @@ -444,10 +449,9 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, ui return NS_OK; } -nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(imgIContainer* aImage, - uint32_t aWhichFrame, - NSImage** aResult, - bool* aIsEntirelyBlack) { +nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer( + imgIContainer* aImage, uint32_t aWhichFrame, const ComputedStyle* aComputedStyle, + NSImage** aResult, bool* aIsEntirelyBlack) { int32_t width = 0, height = 0; aImage->GetWidth(&width); aImage->GetHeight(&height); @@ -457,7 +461,7 @@ nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(imgICon NSImage* newRepresentation = nil; nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer( - aImage, aWhichFrame, &newRepresentation, 1.0f, aIsEntirelyBlack); + aImage, aWhichFrame, aComputedStyle, &newRepresentation, 1.0f, aIsEntirelyBlack); if (NS_FAILED(rv) || !newRepresentation) { return NS_ERROR_FAILURE; } @@ -467,8 +471,8 @@ nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(imgICon [newRepresentation release]; newRepresentation = nil; - rv = nsCocoaUtils::CreateNSImageFromImageContainer(aImage, aWhichFrame, &newRepresentation, 2.0f, - aIsEntirelyBlack); + rv = nsCocoaUtils::CreateNSImageFromImageContainer(aImage, aWhichFrame, 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 558d7b3534f2..7b3251240774 100644 --- a/widget/cocoa/nsCursorManager.mm +++ b/widget/cocoa/nsCursorManager.mm @@ -265,7 +265,7 @@ static const nsCursor sCustomCursor = eCursorCount; NSImage* cursorImage; nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer( - aCursorImage, imgIContainer::FRAME_FIRST, &cursorImage, scaleFactor); + aCursorImage, imgIContainer::FRAME_FIRST, 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 050c0af3027d..dca07a8fd481 100644 --- a/widget/cocoa/nsMenuItemIconX.h +++ b/widget/cocoa/nsMenuItemIconX.h @@ -10,6 +10,8 @@ #ifndef nsMenuItemIconX_h_ #define nsMenuItemIconX_h_ +#import + #include "mozilla/widget/IconLoader.h" class nsIconLoaderService; @@ -19,7 +21,9 @@ class nsIPrincipal; class imgRequestProxy; class nsMenuParentX; -#import +namespace mozilla { +class ComputedStyle; +} class nsMenuItemIconX final : public mozilla::widget::IconLoader::Listener { public: @@ -57,6 +61,7 @@ class nsMenuItemIconX final : public mozilla::widget::IconLoader::Listener { nsCOMPtr mContent; // always non-null Listener* mListener; // [weak] nsIntRect mImageRegionRect; + RefPtr mComputedStyle; NSImage* mIconImage = nil; // [strong] RefPtr mIconLoader; }; diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm index 9221ea49c945..ef61c4a018c7 100644 --- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -149,6 +149,8 @@ already_AddRefed nsMenuItemIconX::GetIconURI(nsIContent* aContent) { } else { mImageRegionRect = r.ToNearestPixels(mozilla::AppUnitsPerCSSPixel()); } + mComputedStyle = std::move(sc); + return iconURI.forget(); } @@ -166,8 +168,11 @@ nsresult nsMenuItemIconX::OnComplete(imgIContainer* aImage) { mIconImage = [[MOZIconHelper iconImageFromImageContainer:aImage withSize:NSMakeSize(kIconSize, kIconSize) + computedStyle:mComputedStyle subrect:mImageRegionRect scaleFactor:0.0f] retain]; + mComputedStyle = nullptr; + if (mListener) { mListener->IconUpdated(); } diff --git a/widget/cocoa/nsTouchBarInputIcon.mm b/widget/cocoa/nsTouchBarInputIcon.mm index 767d25bd964b..1d1b82dd0f09 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(kIconSize, kIconSize) + computedStyle:nullptr subrect:mImageRegionRect scaleFactor:kHiDPIScalingFactor]; [mButton setImage:image];