Bug 1701121 - Support SVG context paint properties for native menu icons. r=emilio

The context paint properties are used by the "New Container Tab" container icons.

Differential Revision: https://phabricator.services.mozilla.com/D109823
This commit is contained in:
Markus Stange 2021-03-26 02:11:14 +00:00
parent a28f1eda7b
commit 31b7df19ba
9 changed files with 47 additions and 19 deletions

View File

@ -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;

View File

@ -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];

View File

@ -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);

View File

@ -257,6 +257,8 @@ class nsCocoaUtils {
Combines the two methods above. The caller owns the <code>NSImage</code>.
@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 <code>NSImage</code>.
@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.

View File

@ -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<SourceSurface> 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> drawTarget = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
@ -409,9 +410,13 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, ui
RefPtr<gfxContext> 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<SVGImageContext> 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;
}

View File

@ -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;
}

View File

@ -10,6 +10,8 @@
#ifndef nsMenuItemIconX_h_
#define nsMenuItemIconX_h_
#import <Cocoa/Cocoa.h>
#include "mozilla/widget/IconLoader.h"
class nsIconLoaderService;
@ -19,7 +21,9 @@ class nsIPrincipal;
class imgRequestProxy;
class nsMenuParentX;
#import <Cocoa/Cocoa.h>
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<nsIContent> mContent; // always non-null
Listener* mListener; // [weak]
nsIntRect mImageRegionRect;
RefPtr<mozilla::ComputedStyle> mComputedStyle;
NSImage* mIconImage = nil; // [strong]
RefPtr<mozilla::widget::IconLoader> mIconLoader;
};

View File

@ -149,6 +149,8 @@ already_AddRefed<nsIURI> 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();
}

View File

@ -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];