From 6ff83fde6bba99491a78096cdbc8ac5711f4666b Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sun, 15 Dec 2019 15:54:15 +0800 Subject: [PATCH] Added SDGraphicsImageRenderer (which bridge to UIGraphicsImageRenderer on iOS 10+), prepare to replace old CGContext create code --- SDWebImage.xcodeproj/project.pbxproj | 12 ++ SDWebImage/Core/SDGraphicsImageRenderer.h | 44 +++++++ SDWebImage/Core/SDGraphicsImageRenderer.m | 140 ++++++++++++++++++++++ WebImage/SDWebImage.h | 1 + 4 files changed, 197 insertions(+) create mode 100644 SDWebImage/Core/SDGraphicsImageRenderer.h create mode 100644 SDWebImage/Core/SDGraphicsImageRenderer.m diff --git a/SDWebImage.xcodeproj/project.pbxproj b/SDWebImage.xcodeproj/project.pbxproj index fefb9564..39537274 100644 --- a/SDWebImage.xcodeproj/project.pbxproj +++ b/SDWebImage.xcodeproj/project.pbxproj @@ -52,6 +52,9 @@ 3244062C2296C5F400A36084 /* SDWebImageOptionsProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 324406292296C5F400A36084 /* SDWebImageOptionsProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3244062D2296C5F400A36084 /* SDWebImageOptionsProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 3244062A2296C5F400A36084 /* SDWebImageOptionsProcessor.m */; }; 3244062E2296C5F400A36084 /* SDWebImageOptionsProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 3244062A2296C5F400A36084 /* SDWebImageOptionsProcessor.m */; }; + 3246A70323A567AC00FBEA10 /* SDGraphicsImageRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3246A70123A567AC00FBEA10 /* SDGraphicsImageRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3246A70423A567AC00FBEA10 /* SDGraphicsImageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3246A70223A567AC00FBEA10 /* SDGraphicsImageRenderer.m */; }; + 3246A70523A567AC00FBEA10 /* SDGraphicsImageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3246A70223A567AC00FBEA10 /* SDGraphicsImageRenderer.m */; }; 3248475D201775F600AF9E5A /* SDAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32484757201775F600AF9E5A /* SDAnimatedImageView.m */; }; 3248475F201775F600AF9E5A /* SDAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32484757201775F600AF9E5A /* SDAnimatedImageView.m */; }; 32484765201775F600AF9E5A /* SDAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 32484758201775F600AF9E5A /* SDAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -121,6 +124,7 @@ 328BB6CF2082581100760D6C /* SDMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 328BB6BF2082581100760D6C /* SDMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; 328BB6D32082581100760D6C /* SDMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 328BB6C02082581100760D6C /* SDMemoryCache.m */; }; 328BB6D52082581100760D6C /* SDMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 328BB6C02082581100760D6C /* SDMemoryCache.m */; }; + 328E9DE523A61DD30051C893 /* SDGraphicsImageRenderer.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3246A70123A567AC00FBEA10 /* SDGraphicsImageRenderer.h */; }; 3290FA061FA478AF0047D20C /* SDImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 3290FA021FA478AF0047D20C /* SDImageFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3290FA0A1FA478AF0047D20C /* SDImageFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 3290FA031FA478AF0047D20C /* SDImageFrame.m */; }; 3290FA0C1FA478AF0047D20C /* SDImageFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 3290FA031FA478AF0047D20C /* SDImageFrame.m */; }; @@ -308,6 +312,7 @@ dstPath = include/SDWebImage; dstSubfolderSpec = 16; files = ( + 328E9DE523A61DD30051C893 /* SDGraphicsImageRenderer.h in Copy Headers */, 325F7CCD2389467800AEDFCC /* UIImage+ExtendedCacheData.h in Copy Headers */, 326E2F36236F1E30006F847F /* SDAnimatedImagePlayer.h in Copy Headers */, 3250C9F12355E3DF0093A896 /* SDWebImageDownloaderDecryptor.h in Copy Headers */, @@ -394,6 +399,8 @@ 3240BB6723968FE6003BA07D /* SDAssociatedObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDAssociatedObject.m; sourceTree = ""; }; 324406292296C5F400A36084 /* SDWebImageOptionsProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SDWebImageOptionsProcessor.h; path = Core/SDWebImageOptionsProcessor.h; sourceTree = ""; }; 3244062A2296C5F400A36084 /* SDWebImageOptionsProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDWebImageOptionsProcessor.m; path = Core/SDWebImageOptionsProcessor.m; sourceTree = ""; }; + 3246A70123A567AC00FBEA10 /* SDGraphicsImageRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SDGraphicsImageRenderer.h; path = Core/SDGraphicsImageRenderer.h; sourceTree = ""; }; + 3246A70223A567AC00FBEA10 /* SDGraphicsImageRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDGraphicsImageRenderer.m; path = Core/SDGraphicsImageRenderer.m; sourceTree = ""; }; 32484757201775F600AF9E5A /* SDAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDAnimatedImageView.m; path = Core/SDAnimatedImageView.m; sourceTree = ""; }; 32484758201775F600AF9E5A /* SDAnimatedImageView+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SDAnimatedImageView+WebCache.h"; path = "Core/SDAnimatedImageView+WebCache.h"; sourceTree = ""; }; 32484759201775F600AF9E5A /* SDAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDAnimatedImageView.h; path = Core/SDAnimatedImageView.h; sourceTree = ""; }; @@ -577,6 +584,8 @@ 32CF1C061FA496B000004BD1 /* SDImageCoderHelper.m */, 3257EAF721898AED0097B271 /* SDImageGraphics.h */, 3257EAF821898AED0097B271 /* SDImageGraphics.m */, + 3246A70123A567AC00FBEA10 /* SDGraphicsImageRenderer.h */, + 3246A70223A567AC00FBEA10 /* SDGraphicsImageRenderer.m */, ); name = Decoder; sourceTree = ""; @@ -905,6 +914,7 @@ 4A2CAE1D1AB4BB6800B6BC39 /* SDWebImageDownloaderOperation.h in Headers */, 4A2CAE2B1AB4BB7500B6BC39 /* UIButton+WebCache.h in Headers */, 4A2CAE251AB4BB7000B6BC39 /* SDWebImagePrefetcher.h in Headers */, + 3246A70323A567AC00FBEA10 /* SDGraphicsImageRenderer.h in Headers */, 328BB6CF2082581100760D6C /* SDMemoryCache.h in Headers */, 325C460F223394D8004CAE11 /* SDImageCachesManagerOperation.h in Headers */, 321E60881F38E8C800405457 /* SDImageCoder.h in Headers */, @@ -1125,6 +1135,7 @@ 3290FA0C1FA478AF0047D20C /* SDImageFrame.m in Sources */, 325C46232233A02E004CAE11 /* UIColor+HexString.m in Sources */, 325F7CCB238942AB00AEDFCC /* UIImage+ExtendedCacheData.m in Sources */, + 3246A70523A567AC00FBEA10 /* SDGraphicsImageRenderer.m in Sources */, 321E60C61F38E91700405457 /* UIImage+ForceDecode.m in Sources */, 3244062E2296C5F400A36084 /* SDWebImageOptionsProcessor.m in Sources */, 3250C9F02355D9DA0093A896 /* SDWebImageDownloaderDecryptor.m in Sources */, @@ -1198,6 +1209,7 @@ 3290FA0A1FA478AF0047D20C /* SDImageFrame.m in Sources */, 325C46222233A02E004CAE11 /* UIColor+HexString.m in Sources */, 321E60C41F38E91700405457 /* UIImage+ForceDecode.m in Sources */, + 3246A70423A567AC00FBEA10 /* SDGraphicsImageRenderer.m in Sources */, 3244062D2296C5F400A36084 /* SDWebImageOptionsProcessor.m in Sources */, 3250C9EF2355D9DA0093A896 /* SDWebImageDownloaderDecryptor.m in Sources */, 3240BB6523968FA1003BA07D /* SDFileAttributeHelper.m in Sources */, diff --git a/SDWebImage/Core/SDGraphicsImageRenderer.h b/SDWebImage/Core/SDGraphicsImageRenderer.h new file mode 100644 index 00000000..2899b3b4 --- /dev/null +++ b/SDWebImage/Core/SDGraphicsImageRenderer.h @@ -0,0 +1,44 @@ +/* +* 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 "SDWebImageCompat.h" + +typedef void (^SDGraphicsImageDrawingActions)(CGContextRef _Nonnull context); + +typedef NS_ENUM(NSInteger, SDGraphicsImageRendererFormatRange) { + SDGraphicsImageRendererFormatRangeUnspecified = -1, + SDGraphicsImageRendererFormatRangeAutomatic = 0, + SDGraphicsImageRendererFormatRangeExtended, + SDGraphicsImageRendererFormatRangeStandard +}; + +@interface SDGraphicsImageRendererFormat : NSObject + +@property (nonatomic) CGFloat scale; +@property (nonatomic) BOOL opaque; + +/** + For iOS 12+, the value is from system API + For iOS 10-11, the value is from `prefersExtendedRange` property + For iOS 9, the value is `.unspecified` + */ +@property (nonatomic) SDGraphicsImageRendererFormatRange preferredRange; + +- (nonnull instancetype)init; ++ (nonnull instancetype)preferredFormat; + +@end + +@interface SDGraphicsImageRenderer : NSObject + +- (nonnull instancetype)initWithSize:(CGSize)size; +- (nonnull instancetype)initWithSize:(CGSize)size format:(nonnull SDGraphicsImageRendererFormat *)format; + +- (nonnull UIImage *)imageWithActions:(nonnull NS_NOESCAPE SDGraphicsImageDrawingActions)actions; + +@end diff --git a/SDWebImage/Core/SDGraphicsImageRenderer.m b/SDWebImage/Core/SDGraphicsImageRenderer.m new file mode 100644 index 00000000..980ef2b4 --- /dev/null +++ b/SDWebImage/Core/SDGraphicsImageRenderer.m @@ -0,0 +1,140 @@ +/* +* 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 () +@property (nonatomic, strong) UIGraphicsImageRendererFormat *uiformat API_AVAILABLE(ios(10.0)); +@end + +@implementation SDGraphicsImageRendererFormat + +- (instancetype)init { + self = [super init]; + if (self) { + if (@available(iOS 10.0, *)) { + UIGraphicsImageRendererFormat *uiformat = [[UIGraphicsImageRendererFormat alloc] init]; + self.uiformat = uiformat; + self.scale = uiformat.scale; + self.opaque = uiformat.opaque; + if (@available(iOS 12.0, *)) { + self.preferredRange = (SDGraphicsImageRendererFormatRange)uiformat.preferredRange; + } else { + if (uiformat.prefersExtendedRange) { + self.preferredRange = SDGraphicsImageRendererFormatRangeExtended; + } else { + self.preferredRange = SDGraphicsImageRendererFormatRangeStandard; + } + } + } else { + self.scale = 1.0; + self.opaque = NO; + self.preferredRange = SDGraphicsImageRendererFormatRangeUnspecified; + } + } + return self; +} + +- (instancetype)initForMainScreen { + self = [super init]; + if (self) { + if (@available(iOS 10.0, *)) { + UIGraphicsImageRendererFormat *uiformat; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + // 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; + self.scale = uiformat.scale; + self.opaque = uiformat.opaque; + if (@available(iOS 12.0, *)) { + self.preferredRange = (SDGraphicsImageRendererFormatRange)uiformat.preferredRange; + } else { + if (uiformat.prefersExtendedRange) { + self.preferredRange = SDGraphicsImageRendererFormatRangeExtended; + } else { + self.preferredRange = SDGraphicsImageRendererFormatRangeStandard; + } + } +#pragma clang diagnostic pop + } else { +#if SD_WATCH + CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale; +#elif SD_UIKIT + CGFloat screenScale = [UIScreen mainScreen].scale; +#elif SD_MAC + CGFloat screenScale = [NSScreen mainScreen].backingScaleFactor; +#endif + self.scale = screenScale; + self.opaque = NO; + self.preferredRange = SDGraphicsImageRendererFormatRangeUnspecified; + } + } + return self; +} + ++ (instancetype)preferredFormat { + SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] initForMainScreen]; + return format; +} + +@end + +@interface SDGraphicsImageRenderer () +@property (nonatomic, assign) CGSize size; +@property (nonatomic, strong) SDGraphicsImageRendererFormat *format; +@property (nonatomic, strong) UIGraphicsImageRenderer *uirenderer API_AVAILABLE(ios(10.0)); +@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 (@available(iOS 10.0, *)) { + UIGraphicsImageRendererFormat *uiformat = format.uiformat; + self.uirenderer = [[UIGraphicsImageRenderer alloc] initWithSize:size format:uiformat]; + } + } + return self; +} + +- (UIImage *)imageWithActions:(NS_NOESCAPE SDGraphicsImageDrawingActions)actions { + NSParameterAssert(actions); + if (@available(iOS 10.0, *)) { + UIGraphicsImageDrawingActions uiactions = ^(UIGraphicsImageRendererContext *rendererContext) { + if (actions) { + actions(rendererContext.CGContext); + } + }; + return [self.uirenderer imageWithActions:uiactions]; + } else { + SDGraphicsBeginImageContextWithOptions(self.size, self.format.opaque, self.format.scale); + CGContextRef context = SDGraphicsGetCurrentContext(); + if (actions) { + actions(context); + } + UIImage *image = SDGraphicsGetImageFromCurrentImageContext(); + SDGraphicsEndImageContext(); + return image; + } +} + +@end diff --git a/WebImage/SDWebImage.h b/WebImage/SDWebImage.h index ab0f43e5..f219978e 100644 --- a/WebImage/SDWebImage.h +++ b/WebImage/SDWebImage.h @@ -65,6 +65,7 @@ FOUNDATION_EXPORT const unsigned char WebImageVersionString[]; #import #import #import +#import #import #import #import