Files
WebApp/Pods/SDWebImage/SDWebImage/Core/SDImageGraphics.m
2025-01-11 14:58:16 +08:00

128 lines
4.3 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "SDImageGraphics.h"
#import "NSImage+Compatibility.h"
#import "SDImageCoderHelper.h"
#import "objc/runtime.h"
#if SD_MAC
static void *kNSGraphicsContextScaleFactorKey;
static CGContextRef SDCGContextCreateBitmapContext(CGSize size, BOOL opaque, CGFloat scale) {
if (scale == 0) {
// Match `UIGraphicsBeginImageContextWithOptions`, reset to the scale factor of the devices main screen if scale is 0.
NSScreen *mainScreen = nil;
if (@available(macOS 10.12, *)) {
mainScreen = [NSScreen mainScreen];
} else {
mainScreen = [NSScreen screens].firstObject;
}
scale = mainScreen.backingScaleFactor ?: 1.0f;
}
size_t width = ceil(size.width * scale);
size_t height = ceil(size.height * scale);
if (width < 1 || height < 1) return NULL;
CGColorSpaceRef space = [SDImageCoderHelper colorSpaceGetDeviceRGB];
// kCGImageAlphaNone is not supported in CGBitmapContextCreate.
// Check #3330 for more detail about why this bitmap is choosen.
CGBitmapInfo bitmapInfo;
if (!opaque) {
// iPhone GPU prefer to use BGRA8888, see: https://forums.raywenderlich.com/t/why-mtlpixelformat-bgra8unorm/53489
// BGRA8888
bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
} else {
// BGR888 previously works on iOS 8~iOS 14, however, iOS 15+ will result a black image. FB9958017
// RGB888
bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast;
}
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, space, bitmapInfo);
if (!context) {
return NULL;
}
CGContextScaleCTM(context, scale, scale);
return context;
}
#endif
CGContextRef SDGraphicsGetCurrentContext(void) {
#if SD_UIKIT || SD_WATCH
return UIGraphicsGetCurrentContext();
#else
return NSGraphicsContext.currentContext.CGContext;
#endif
}
void SDGraphicsBeginImageContext(CGSize size) {
#if SD_UIKIT || SD_WATCH
UIGraphicsBeginImageContext(size);
#else
SDGraphicsBeginImageContextWithOptions(size, NO, 1.0);
#endif
}
void SDGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) {
#if SD_UIKIT || SD_WATCH
UIGraphicsBeginImageContextWithOptions(size, opaque, scale);
#else
CGContextRef context = SDCGContextCreateBitmapContext(size, opaque, scale);
if (!context) {
return;
}
NSGraphicsContext *graphicsContext = [NSGraphicsContext graphicsContextWithCGContext:context flipped:NO];
objc_setAssociatedObject(graphicsContext, &kNSGraphicsContextScaleFactorKey, @(scale), OBJC_ASSOCIATION_RETAIN);
CGContextRelease(context);
[NSGraphicsContext saveGraphicsState];
NSGraphicsContext.currentContext = graphicsContext;
#endif
}
void SDGraphicsEndImageContext(void) {
#if SD_UIKIT || SD_WATCH
UIGraphicsEndImageContext();
#else
[NSGraphicsContext restoreGraphicsState];
#endif
}
UIImage * SDGraphicsGetImageFromCurrentImageContext(void) {
#if SD_UIKIT || SD_WATCH
return UIGraphicsGetImageFromCurrentImageContext();
#else
NSGraphicsContext *context = NSGraphicsContext.currentContext;
CGContextRef contextRef = context.CGContext;
if (!contextRef) {
return nil;
}
CGImageRef imageRef = CGBitmapContextCreateImage(contextRef);
if (!imageRef) {
return nil;
}
CGFloat scale = 0;
NSNumber *scaleFactor = objc_getAssociatedObject(context, &kNSGraphicsContextScaleFactorKey);
if ([scaleFactor isKindOfClass:[NSNumber class]]) {
scale = scaleFactor.doubleValue;
}
if (!scale) {
// reset to the scale factor of the devices main screen if scale is 0.
NSScreen *mainScreen = nil;
if (@available(macOS 10.12, *)) {
mainScreen = [NSScreen mainScreen];
} else {
mainScreen = [NSScreen screens].firstObject;
}
scale = mainScreen.backingScaleFactor ?: 1.0f;
}
NSImage *image = [[NSImage alloc] initWithCGImage:imageRef scale:scale orientation:kCGImagePropertyOrientationUp];
CGImageRelease(imageRef);
return image;
#endif
}