SDGraphicsImageRenderer.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * This file is part of the SDWebImage package.
  3. * (c) Olivier Poitrey <rs@dailymotion.com>
  4. *
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. */
  8. #import "SDGraphicsImageRenderer.h"
  9. #import "SDImageGraphics.h"
  10. @interface SDGraphicsImageRendererFormat ()
  11. #if SD_UIKIT
  12. @property (nonatomic, strong) UIGraphicsImageRendererFormat *uiformat API_AVAILABLE(ios(10.0), tvos(10.0));
  13. #endif
  14. @end
  15. @implementation SDGraphicsImageRendererFormat
  16. @synthesize scale = _scale;
  17. @synthesize opaque = _opaque;
  18. @synthesize preferredRange = _preferredRange;
  19. #pragma mark - Property
  20. - (CGFloat)scale {
  21. #if SD_UIKIT
  22. if (@available(iOS 10.0, tvOS 10.10, *)) {
  23. return self.uiformat.scale;
  24. } else {
  25. return _scale;
  26. }
  27. #else
  28. return _scale;
  29. #endif
  30. }
  31. - (void)setScale:(CGFloat)scale {
  32. #if SD_UIKIT
  33. if (@available(iOS 10.0, tvOS 10.10, *)) {
  34. self.uiformat.scale = scale;
  35. } else {
  36. _scale = scale;
  37. }
  38. #else
  39. _scale = scale;
  40. #endif
  41. }
  42. - (BOOL)opaque {
  43. #if SD_UIKIT
  44. if (@available(iOS 10.0, tvOS 10.10, *)) {
  45. return self.uiformat.opaque;
  46. } else {
  47. return _opaque;
  48. }
  49. #else
  50. return _opaque;
  51. #endif
  52. }
  53. - (void)setOpaque:(BOOL)opaque {
  54. #if SD_UIKIT
  55. if (@available(iOS 10.0, tvOS 10.10, *)) {
  56. self.uiformat.opaque = opaque;
  57. } else {
  58. _opaque = opaque;
  59. }
  60. #else
  61. _opaque = opaque;
  62. #endif
  63. }
  64. #pragma clang diagnostic push
  65. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  66. - (SDGraphicsImageRendererFormatRange)preferredRange {
  67. #if SD_UIKIT
  68. if (@available(iOS 10.0, tvOS 10.10, *)) {
  69. if (@available(iOS 12.0, tvOS 12.0, *)) {
  70. return (SDGraphicsImageRendererFormatRange)self.uiformat.preferredRange;
  71. } else {
  72. BOOL prefersExtendedRange = self.uiformat.prefersExtendedRange;
  73. if (prefersExtendedRange) {
  74. return SDGraphicsImageRendererFormatRangeExtended;
  75. } else {
  76. return SDGraphicsImageRendererFormatRangeStandard;
  77. }
  78. }
  79. } else {
  80. return _preferredRange;
  81. }
  82. #else
  83. return _preferredRange;
  84. #endif
  85. }
  86. - (void)setPreferredRange:(SDGraphicsImageRendererFormatRange)preferredRange {
  87. #if SD_UIKIT
  88. if (@available(iOS 10.0, tvOS 10.10, *)) {
  89. if (@available(iOS 12.0, tvOS 12.0, *)) {
  90. self.uiformat.preferredRange = (UIGraphicsImageRendererFormatRange)preferredRange;
  91. } else {
  92. switch (preferredRange) {
  93. case SDGraphicsImageRendererFormatRangeExtended:
  94. self.uiformat.prefersExtendedRange = YES;
  95. break;
  96. case SDGraphicsImageRendererFormatRangeStandard:
  97. self.uiformat.prefersExtendedRange = NO;
  98. default:
  99. // Automatic means default
  100. break;
  101. }
  102. }
  103. } else {
  104. _preferredRange = preferredRange;
  105. }
  106. #else
  107. _preferredRange = preferredRange;
  108. #endif
  109. }
  110. #pragma clang diagnostic pop
  111. - (instancetype)init {
  112. self = [super init];
  113. if (self) {
  114. #if SD_UIKIT
  115. if (@available(iOS 10.0, tvOS 10.10, *)) {
  116. UIGraphicsImageRendererFormat *uiformat = [[UIGraphicsImageRendererFormat alloc] init];
  117. self.uiformat = uiformat;
  118. } else {
  119. #endif
  120. #if SD_WATCH
  121. CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale;
  122. #elif SD_UIKIT
  123. CGFloat screenScale = [UIScreen mainScreen].scale;
  124. #elif SD_MAC
  125. NSScreen *mainScreen = nil;
  126. if (@available(macOS 10.12, *)) {
  127. mainScreen = [NSScreen mainScreen];
  128. } else {
  129. mainScreen = [NSScreen screens].firstObject;
  130. }
  131. CGFloat screenScale = mainScreen.backingScaleFactor ?: 1.0f;
  132. #endif
  133. self.scale = screenScale;
  134. self.opaque = NO;
  135. self.preferredRange = SDGraphicsImageRendererFormatRangeStandard;
  136. #if SD_UIKIT
  137. }
  138. #endif
  139. }
  140. return self;
  141. }
  142. #pragma clang diagnostic push
  143. #pragma clang diagnostic ignored "-Wunguarded-availability"
  144. - (instancetype)initForMainScreen {
  145. self = [super init];
  146. if (self) {
  147. #if SD_UIKIT
  148. if (@available(iOS 10.0, tvOS 10.0, *)) {
  149. UIGraphicsImageRendererFormat *uiformat;
  150. // iOS 11.0.0 GM does have `preferredFormat`, but iOS 11 betas did not (argh!)
  151. if ([UIGraphicsImageRenderer respondsToSelector:@selector(preferredFormat)]) {
  152. uiformat = [UIGraphicsImageRendererFormat preferredFormat];
  153. } else {
  154. uiformat = [UIGraphicsImageRendererFormat defaultFormat];
  155. }
  156. self.uiformat = uiformat;
  157. } else {
  158. #endif
  159. #if SD_WATCH
  160. CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale;
  161. #elif SD_UIKIT
  162. CGFloat screenScale = [UIScreen mainScreen].scale;
  163. #elif SD_MAC
  164. NSScreen *mainScreen = nil;
  165. if (@available(macOS 10.12, *)) {
  166. mainScreen = [NSScreen mainScreen];
  167. } else {
  168. mainScreen = [NSScreen screens].firstObject;
  169. }
  170. CGFloat screenScale = mainScreen.backingScaleFactor ?: 1.0f;
  171. #endif
  172. self.scale = screenScale;
  173. self.opaque = NO;
  174. self.preferredRange = SDGraphicsImageRendererFormatRangeStandard;
  175. #if SD_UIKIT
  176. }
  177. #endif
  178. }
  179. return self;
  180. }
  181. #pragma clang diagnostic pop
  182. + (instancetype)preferredFormat {
  183. SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] initForMainScreen];
  184. return format;
  185. }
  186. @end
  187. @interface SDGraphicsImageRenderer ()
  188. @property (nonatomic, assign) CGSize size;
  189. @property (nonatomic, strong) SDGraphicsImageRendererFormat *format;
  190. #if SD_UIKIT
  191. @property (nonatomic, strong) UIGraphicsImageRenderer *uirenderer API_AVAILABLE(ios(10.0), tvos(10.0));
  192. #endif
  193. @end
  194. @implementation SDGraphicsImageRenderer
  195. - (instancetype)initWithSize:(CGSize)size {
  196. return [self initWithSize:size format:SDGraphicsImageRendererFormat.preferredFormat];
  197. }
  198. - (instancetype)initWithSize:(CGSize)size format:(SDGraphicsImageRendererFormat *)format {
  199. NSParameterAssert(format);
  200. self = [super init];
  201. if (self) {
  202. self.size = size;
  203. self.format = format;
  204. #if SD_UIKIT
  205. if (@available(iOS 10.0, tvOS 10.0, *)) {
  206. UIGraphicsImageRendererFormat *uiformat = format.uiformat;
  207. self.uirenderer = [[UIGraphicsImageRenderer alloc] initWithSize:size format:uiformat];
  208. }
  209. #endif
  210. }
  211. return self;
  212. }
  213. - (UIImage *)imageWithActions:(NS_NOESCAPE SDGraphicsImageDrawingActions)actions {
  214. NSParameterAssert(actions);
  215. #if SD_UIKIT
  216. if (@available(iOS 10.0, tvOS 10.0, *)) {
  217. UIGraphicsImageDrawingActions uiactions = ^(UIGraphicsImageRendererContext *rendererContext) {
  218. if (actions) {
  219. actions(rendererContext.CGContext);
  220. }
  221. };
  222. return [self.uirenderer imageWithActions:uiactions];
  223. } else {
  224. #endif
  225. SDGraphicsBeginImageContextWithOptions(self.size, self.format.opaque, self.format.scale);
  226. CGContextRef context = SDGraphicsGetCurrentContext();
  227. if (actions) {
  228. actions(context);
  229. }
  230. UIImage *image = SDGraphicsGetImageFromCurrentImageContext();
  231. SDGraphicsEndImageContext();
  232. return image;
  233. #if SD_UIKIT
  234. }
  235. #endif
  236. }
  237. @end