зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1465403 - Support loading icons @2x in macOS menu bars. r=mstange
Differential Revision: https://phabricator.services.mozilla.com/D41391 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
d77cbfd825
Коммит
2413c70932
|
@ -262,10 +262,29 @@ class nsCocoaUtils {
|
||||||
@param aWhichFrame the frame to extract (see imgIContainer FRAME_*)
|
@param aWhichFrame the frame to extract (see imgIContainer FRAME_*)
|
||||||
@param aResult the resulting NSImage
|
@param aResult the resulting NSImage
|
||||||
@param scaleFactor the desired scale factor of the NSImage (2 for a retina display)
|
@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
|
||||||
|
bool that indicates whether the RGB values on all
|
||||||
|
pixels are zero
|
||||||
@return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
|
@return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
|
||||||
*/
|
*/
|
||||||
static nsresult CreateNSImageFromImageContainer(imgIContainer* aImage, uint32_t aWhichFrame,
|
static nsresult CreateNSImageFromImageContainer(imgIContainer* aImage, uint32_t aWhichFrame,
|
||||||
NSImage** aResult, CGFloat scaleFactor);
|
NSImage** aResult, CGFloat scaleFactor,
|
||||||
|
bool* aIsEntirelyBlack = nullptr);
|
||||||
|
|
||||||
|
/** Creates a Cocoa <code>NSImage</code> from a frame of an <code>imgIContainer</code>.
|
||||||
|
The new <code>NSImage</code> will have both a regular and HiDPI representation.
|
||||||
|
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 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
|
||||||
|
pixels are zero
|
||||||
|
@return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
|
||||||
|
*/
|
||||||
|
static nsresult CreateDualRepresentationNSImageFromImageContainer(
|
||||||
|
imgIContainer* aImage, uint32_t aWhichFrame, NSImage** aResult,
|
||||||
|
bool* aIsEntirelyBlack = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns nsAString for aSrc.
|
* Returns nsAString for aSrc.
|
||||||
|
|
|
@ -469,7 +469,8 @@ nsresult nsCocoaUtils::CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage*
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, uint32_t aWhichFrame,
|
nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, uint32_t aWhichFrame,
|
||||||
NSImage** aResult, CGFloat scaleFactor) {
|
NSImage** aResult, CGFloat scaleFactor,
|
||||||
|
bool* aIsEntirelyBlack) {
|
||||||
RefPtr<SourceSurface> surface;
|
RefPtr<SourceSurface> surface;
|
||||||
int32_t width = 0, height = 0;
|
int32_t width = 0, height = 0;
|
||||||
aImage->GetWidth(&width);
|
aImage->GetWidth(&width);
|
||||||
|
@ -505,7 +506,7 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, ui
|
||||||
NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
CGImageRef imageRef = NULL;
|
CGImageRef imageRef = NULL;
|
||||||
nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef);
|
nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef, aIsEntirelyBlack);
|
||||||
if (NS_FAILED(rv) || !imageRef) {
|
if (NS_FAILED(rv) || !imageRef) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -523,6 +524,41 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer* aImage, ui
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(imgIContainer* aImage,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
NSImage** aResult,
|
||||||
|
bool* aIsEntirelyBlack) {
|
||||||
|
int32_t width = 0, height = 0;
|
||||||
|
aImage->GetWidth(&width);
|
||||||
|
aImage->GetHeight(&height);
|
||||||
|
NSSize size = NSMakeSize(width, height);
|
||||||
|
*aResult = [[NSImage alloc] init];
|
||||||
|
[*aResult setSize:size];
|
||||||
|
|
||||||
|
NSImage* newRepresentation = nil;
|
||||||
|
nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer(
|
||||||
|
aImage, aWhichFrame, &newRepresentation, 1.0f, aIsEntirelyBlack);
|
||||||
|
if (NS_FAILED(rv) || !newRepresentation) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[[newRepresentation representations] objectAtIndex:0] setSize:size];
|
||||||
|
[*aResult addRepresentation:[[newRepresentation representations] objectAtIndex:0]];
|
||||||
|
[newRepresentation release];
|
||||||
|
newRepresentation = nil;
|
||||||
|
|
||||||
|
rv = nsCocoaUtils::CreateNSImageFromImageContainer(aImage, aWhichFrame, &newRepresentation, 2.0f,
|
||||||
|
aIsEntirelyBlack);
|
||||||
|
if (NS_FAILED(rv) || !newRepresentation) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[[newRepresentation representations] objectAtIndex:0] setSize:size];
|
||||||
|
[*aResult addRepresentation:[[newRepresentation representations] objectAtIndex:0]];
|
||||||
|
[newRepresentation release];
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void nsCocoaUtils::GetStringForNSString(const NSString* aSrc, nsAString& aDist) {
|
void nsCocoaUtils::GetStringForNSString(const NSString* aSrc, nsAString& aDist) {
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||||
|
|
|
@ -23,9 +23,11 @@ class imgRequestProxy;
|
||||||
|
|
||||||
class nsIconLoaderService : public imgINotificationObserver {
|
class nsIconLoaderService : public imgINotificationObserver {
|
||||||
public:
|
public:
|
||||||
|
// If aScaleFactor is not specified, then an image with both regular and
|
||||||
|
// HiDPI representations will be loaded.
|
||||||
nsIconLoaderService(nsIContent* aContent, nsIntRect* aImageRegionRect,
|
nsIconLoaderService(nsIContent* aContent, nsIntRect* aImageRegionRect,
|
||||||
RefPtr<nsIconLoaderObserver> aObserver,
|
RefPtr<nsIconLoaderObserver> aObserver, uint32_t aIconHeight,
|
||||||
uint32_t aIconHeight, uint32_t aIconWidth);
|
uint32_t aIconWidth, CGFloat aScaleFactor = 0.0f);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
@ -55,6 +57,7 @@ class nsIconLoaderService : public imgINotificationObserver {
|
||||||
NSImage* mNativeIconImage;
|
NSImage* mNativeIconImage;
|
||||||
uint32_t mIconHeight;
|
uint32_t mIconHeight;
|
||||||
uint32_t mIconWidth;
|
uint32_t mIconWidth;
|
||||||
|
CGFloat mScaleFactor;
|
||||||
RefPtr<nsIconLoaderObserver> mCompletionHandler;
|
RefPtr<nsIconLoaderObserver> mCompletionHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,8 @@ NS_IMPL_ISUPPORTS(nsIconLoaderService, imgINotificationObserver)
|
||||||
|
|
||||||
nsIconLoaderService::nsIconLoaderService(nsIContent* aContent, nsIntRect* aImageRegionRect,
|
nsIconLoaderService::nsIconLoaderService(nsIContent* aContent, nsIntRect* aImageRegionRect,
|
||||||
RefPtr<nsIconLoaderObserver> aObserver,
|
RefPtr<nsIconLoaderObserver> aObserver,
|
||||||
uint32_t aIconHeight, uint32_t aIconWidth)
|
uint32_t aIconHeight, uint32_t aIconWidth,
|
||||||
|
CGFloat aScaleFactor)
|
||||||
: mContent(aContent),
|
: mContent(aContent),
|
||||||
mContentType(nsIContentPolicy::TYPE_INTERNAL_IMAGE),
|
mContentType(nsIContentPolicy::TYPE_INTERNAL_IMAGE),
|
||||||
mImageRegionRect(aImageRegionRect),
|
mImageRegionRect(aImageRegionRect),
|
||||||
|
@ -53,6 +54,7 @@ nsIconLoaderService::nsIconLoaderService(nsIContent* aContent, nsIntRect* aImage
|
||||||
mNativeIconImage(nil),
|
mNativeIconImage(nil),
|
||||||
mIconHeight(aIconHeight),
|
mIconHeight(aIconHeight),
|
||||||
mIconWidth(aIconWidth),
|
mIconWidth(aIconWidth),
|
||||||
|
mScaleFactor(aScaleFactor),
|
||||||
mCompletionHandler(aObserver) {}
|
mCompletionHandler(aObserver) {}
|
||||||
|
|
||||||
nsIconLoaderService::~nsIconLoaderService() { Destroy(); }
|
nsIconLoaderService::~nsIconLoaderService() { Destroy(); }
|
||||||
|
@ -195,45 +197,46 @@ nsresult nsIconLoaderService::OnFrameComplete(imgIRequest* aRequest) {
|
||||||
mImageRegionRect->SetRect(0, 0, origWidth, origHeight);
|
mImageRegionRect->SetRect(0, 0, origWidth, origHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<SourceSurface> surface =
|
bool isEntirelyBlack = false;
|
||||||
imageContainer->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
|
NSImage* newImage = nil;
|
||||||
if (!surface) {
|
nsresult rv;
|
||||||
|
if (mScaleFactor != 0.0f) {
|
||||||
|
rv = nsCocoaUtils::CreateNSImageFromImageContainer(imageContainer, imgIContainer::FRAME_CURRENT,
|
||||||
|
&newImage, mScaleFactor, &isEntirelyBlack);
|
||||||
|
} else {
|
||||||
|
rv = nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(
|
||||||
|
imageContainer, imgIContainer::FRAME_CURRENT, &newImage, &isEntirelyBlack);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(rv) || !newImage) {
|
||||||
mNativeIconImage = nil;
|
mNativeIconImage = nil;
|
||||||
|
[newImage release];
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGImageRef origImage = NULL;
|
NSSize origSize = NSMakeSize(mIconWidth, mIconHeight);
|
||||||
bool isEntirelyBlack = false;
|
|
||||||
nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &origImage, &isEntirelyBlack);
|
|
||||||
if (NS_FAILED(rv) || !origImage) {
|
|
||||||
mNativeIconImage = nil;
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool createSubImage =
|
bool createSubImage =
|
||||||
!(mImageRegionRect->x == 0 && mImageRegionRect->y == 0 &&
|
!(mImageRegionRect->x == 0 && mImageRegionRect->y == 0 &&
|
||||||
mImageRegionRect->width == origWidth && mImageRegionRect->height == origHeight);
|
mImageRegionRect->width == origWidth && mImageRegionRect->height == origHeight);
|
||||||
|
|
||||||
CGImageRef finalImage = origImage;
|
|
||||||
if (createSubImage) {
|
if (createSubImage) {
|
||||||
// if mImageRegionRect is set using CSS, we need to slice a piece out of the overall
|
// If mImageRegionRect is set using CSS, we need to slice a piece out of the overall
|
||||||
// image to use as the icon
|
// image to use as the icon.
|
||||||
finalImage = ::CGImageCreateWithImageInRect(
|
NSImage* subImage =
|
||||||
origImage, ::CGRectMake(mImageRegionRect->x, mImageRegionRect->y, mImageRegionRect->width,
|
[NSImage imageWithSize:origSize
|
||||||
mImageRegionRect->height));
|
flipped:NO
|
||||||
::CGImageRelease(origImage);
|
drawingHandler:^BOOL(NSRect subImageRect) {
|
||||||
if (!finalImage) {
|
[newImage drawInRect:NSMakeRect(0, 0, mIconWidth, mIconHeight)
|
||||||
mNativeIconImage = nil;
|
fromRect:NSMakeRect(mImageRegionRect->x, mImageRegionRect->y,
|
||||||
return NS_ERROR_FAILURE;
|
mImageRegionRect->width, mImageRegionRect->height)
|
||||||
}
|
operation:NSCompositeCopy
|
||||||
}
|
fraction:1.0f];
|
||||||
|
return YES;
|
||||||
NSImage* newImage = nil;
|
}];
|
||||||
rv = nsCocoaUtils::CreateNSImageFromCGImage(finalImage, &newImage);
|
[newImage release];
|
||||||
if (NS_FAILED(rv) || !newImage) {
|
newImage = [subImage retain];
|
||||||
mNativeIconImage = nil;
|
subImage = nil;
|
||||||
::CGImageRelease(finalImage);
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all the color channels in the image are black, treat the image as a
|
// If all the color channels in the image are black, treat the image as a
|
||||||
|
@ -244,11 +247,9 @@ nsresult nsIconLoaderService::OnFrameComplete(imgIRequest* aRequest) {
|
||||||
// filled with white.
|
// filled with white.
|
||||||
[newImage setTemplate:isEntirelyBlack];
|
[newImage setTemplate:isEntirelyBlack];
|
||||||
|
|
||||||
[newImage setSize:NSMakeSize(mIconWidth, mIconHeight)];
|
[newImage setSize:origSize];
|
||||||
mNativeIconImage = newImage;
|
mNativeIconImage = newImage;
|
||||||
|
|
||||||
::CGImageRelease(finalImage);
|
|
||||||
|
|
||||||
mLoadedIcon = true;
|
mLoadedIcon = true;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче