/* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDGraphicsImageRenderer.h" #import "SDImageGraphics.h" @interface SDGraphicsImageRendererFormat () #if SD_UIKIT @property (nonatomic, strong) UIGraphicsImageRendererFormat *uiformat API_AVAILABLE(ios(10.0), tvos(10.0)); #endif @end @implementation SDGraphicsImageRendererFormat @synthesize scale = _scale; @synthesize opaque = _opaque; @synthesize preferredRange = _preferredRange; #pragma mark - Property - (CGFloat)scale { #if SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { return self.uiformat.scale; } else { return _scale; } #else return _scale; #endif } - (void)setScale:(CGFloat)scale { #if SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { self.uiformat.scale = scale; } else { _scale = scale; } #else _scale = scale; #endif } - (BOOL)opaque { #if SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { return self.uiformat.opaque; } else { return _opaque; } #else return _opaque; #endif } - (void)setOpaque:(BOOL)opaque { #if SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { self.uiformat.opaque = opaque; } else { _opaque = opaque; } #else _opaque = opaque; #endif } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - (SDGraphicsImageRendererFormatRange)preferredRange { #if SD_VISION return (SDGraphicsImageRendererFormatRange)self.uiformat.preferredRange; #elif SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { if (@available(iOS 12.0, tvOS 12.0, *)) { return (SDGraphicsImageRendererFormatRange)self.uiformat.preferredRange; } else { BOOL prefersExtendedRange = self.uiformat.prefersExtendedRange; if (prefersExtendedRange) { return SDGraphicsImageRendererFormatRangeExtended; } else { return SDGraphicsImageRendererFormatRangeStandard; } } } else { return _preferredRange; } #else return _preferredRange; #endif } - (void)setPreferredRange:(SDGraphicsImageRendererFormatRange)preferredRange { #if SD_VISION self.uiformat.preferredRange = (UIGraphicsImageRendererFormatRange)preferredRange; #elif SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { if (@available(iOS 12.0, tvOS 12.0, *)) { self.uiformat.preferredRange = (UIGraphicsImageRendererFormatRange)preferredRange; } else { switch (preferredRange) { case SDGraphicsImageRendererFormatRangeExtended: self.uiformat.prefersExtendedRange = YES; break; case SDGraphicsImageRendererFormatRangeStandard: self.uiformat.prefersExtendedRange = NO; default: // Automatic means default break; } } } else { _preferredRange = preferredRange; } #else _preferredRange = preferredRange; #endif } #pragma clang diagnostic pop - (instancetype)init { self = [super init]; if (self) { #if SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { UIGraphicsImageRendererFormat *uiformat = [[UIGraphicsImageRendererFormat alloc] init]; self.uiformat = uiformat; } else { #endif #if SD_VISION CGFloat screenScale = UITraitCollection.currentTraitCollection.displayScale; #elif SD_WATCH CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale; #elif SD_UIKIT CGFloat screenScale = [UIScreen mainScreen].scale; #elif SD_MAC NSScreen *mainScreen = nil; if (@available(macOS 10.12, *)) { mainScreen = [NSScreen mainScreen]; } else { mainScreen = [NSScreen screens].firstObject; } CGFloat screenScale = mainScreen.backingScaleFactor ?: 1.0f; #endif self.scale = screenScale; self.opaque = NO; #if SD_UIKIT } #endif } return self; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability" - (instancetype)initForMainScreen { self = [super init]; if (self) { #if SD_UIKIT if (@available(iOS 10.0, tvOS 10.0, *)) { UIGraphicsImageRendererFormat *uiformat; // iOS 11.0.0 GM does have `preferredFormat`, but iOS 11 betas did not (argh!) if ([UIGraphicsImageRenderer respondsToSelector:@selector(preferredFormat)]) { uiformat = [UIGraphicsImageRendererFormat preferredFormat]; } else { uiformat = [UIGraphicsImageRendererFormat defaultFormat]; } self.uiformat = uiformat; } else { #endif #if SD_VISION CGFloat screenScale = UITraitCollection.currentTraitCollection.displayScale; #elif SD_WATCH CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale; #elif SD_UIKIT CGFloat screenScale = [UIScreen mainScreen].scale; #elif SD_MAC NSScreen *mainScreen = nil; if (@available(macOS 10.12, *)) { mainScreen = [NSScreen mainScreen]; } else { mainScreen = [NSScreen screens].firstObject; } CGFloat screenScale = mainScreen.backingScaleFactor ?: 1.0f; #endif self.scale = screenScale; self.opaque = NO; #if SD_UIKIT } #endif } return self; } #pragma clang diagnostic pop + (instancetype)preferredFormat { SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] initForMainScreen]; return format; } @end @interface SDGraphicsImageRenderer () @property (nonatomic, assign) CGSize size; @property (nonatomic, strong) SDGraphicsImageRendererFormat *format; #if SD_UIKIT @property (nonatomic, strong) UIGraphicsImageRenderer *uirenderer API_AVAILABLE(ios(10.0), tvos(10.0)); #endif @end @implementation SDGraphicsImageRenderer - (instancetype)initWithSize:(CGSize)size { return [self initWithSize:size format:SDGraphicsImageRendererFormat.preferredFormat]; } - (instancetype)initWithSize:(CGSize)size format:(SDGraphicsImageRendererFormat *)format { NSParameterAssert(format); self = [super init]; if (self) { self.size = size; self.format = format; #if SD_UIKIT if (@available(iOS 10.0, tvOS 10.0, *)) { UIGraphicsImageRendererFormat *uiformat = format.uiformat; self.uirenderer = [[UIGraphicsImageRenderer alloc] initWithSize:size format:uiformat]; } #endif } return self; } - (UIImage *)imageWithActions:(NS_NOESCAPE SDGraphicsImageDrawingActions)actions { NSParameterAssert(actions); #if SD_UIKIT if (@available(iOS 10.0, tvOS 10.0, *)) { UIGraphicsImageDrawingActions uiactions = ^(UIGraphicsImageRendererContext *rendererContext) { if (actions) { actions(rendererContext.CGContext); } }; return [self.uirenderer imageWithActions:uiactions]; } else { #endif SDGraphicsBeginImageContextWithOptions(self.size, self.format.opaque, self.format.scale); CGContextRef context = SDGraphicsGetCurrentContext(); if (actions) { actions(context); } UIImage *image = SDGraphicsGetImageFromCurrentImageContext(); SDGraphicsEndImageContext(); return image; #if SD_UIKIT } #endif } @end