SDWebImage/SDWebImage/SDImageGraphics.m

106 lines
3.5 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 "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.
scale = [NSScreen mainScreen].backingScaleFactor;
}
size_t width = ceil(size.width * scale);
size_t height = ceil(size.height * scale);
if (width < 1 || height < 1) return NULL;
//pre-multiplied BGRA for non-opaque, BGRX for opaque, 8-bits per component, as Apple's doc
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGImageAlphaInfo alphaInfo = kCGBitmapByteOrder32Host | (opaque ? kCGImageAlphaNoneSkipFirst : kCGImageAlphaPremultipliedFirst);
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, space, kCGBitmapByteOrderDefault | alphaInfo);
CGColorSpaceRelease(space);
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.
scale = [NSScreen mainScreen].backingScaleFactor;
}
NSImage *image = [[NSImage alloc] initWithCGImage:imageRef scale:scale orientation:kCGImagePropertyOrientationUp];
CGImageRelease(imageRef);
return image;
#endif
}