SVGKImageRep.m 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. //
  2. // SVGKitImageRep.m
  3. // SVGKit
  4. //
  5. // Created by C.W. Betts on 12/5/12.
  6. //
  7. //
  8. #import "SVGKit.h"
  9. #if SVGKIT_MAC
  10. #import "SVGKSourceNSData.h"
  11. #import "SVGKSourceLocalFile.h"
  12. #import "SVGKSourceURL.h"
  13. #import "SVGKSourceString.h"
  14. #import "SVGKImageRep.h"
  15. #import "SVGKImage+CGContext.h"
  16. #include <tgmath.h>
  17. @interface SVGKImageRep ()
  18. @property (nonatomic, strong, readwrite, setter = setTheSVG:) SVGKImage *image;
  19. @property (nonatomic, assign) BOOL antiAlias;
  20. @property (nonatomic, assign) CGFloat curveFlatness;
  21. @property (nonatomic, assign) CGInterpolationQuality interpolationQuality;
  22. @end
  23. @implementation SVGKImageRep
  24. - (NSData *)TIFFRepresentationWithSize:(NSSize)theSize
  25. {
  26. self.image.size = theSize;
  27. NSImageRep *imageRep = self.image.NSImage.representations.firstObject;
  28. if (![imageRep isKindOfClass:[NSBitmapImageRep class]]) {
  29. return nil;
  30. }
  31. return [(NSBitmapImageRep *)imageRep TIFFRepresentation];
  32. }
  33. - (NSData *)TIFFRepresentation
  34. {
  35. return [self TIFFRepresentationWithSize:self.size];
  36. }
  37. - (NSData *)TIFFRepresentationUsingCompression:(NSTIFFCompression)comp factor:(float)factor
  38. {
  39. return [self TIFFRepresentationUsingCompression:comp factor:factor size:self.size];
  40. }
  41. - (NSData *)TIFFRepresentationUsingCompression:(NSTIFFCompression)comp factor:(float)factor size:(NSSize)asize
  42. {
  43. self.image.size = asize;
  44. NSImageRep *imageRep = self.image.NSImage.representations.firstObject;
  45. if (![imageRep isKindOfClass:[NSBitmapImageRep class]]) {
  46. return nil;
  47. }
  48. return [(NSBitmapImageRep *)imageRep TIFFRepresentation];
  49. }
  50. + (NSArray<NSString *> *)imageUnfilteredTypes {
  51. static NSArray *UTItypes;
  52. if (UTItypes == nil) {
  53. UTItypes = @[@"public.svg-image"];
  54. }
  55. return UTItypes;
  56. }
  57. + (BOOL)canInitWithData:(NSData *)d
  58. {
  59. SVGKParseResult *parseResult;
  60. @autoreleasepool {
  61. parseResult = [SVGKParser parseSourceUsingDefaultSVGKParser:[SVGKSourceNSData sourceFromData:d URLForRelativeLinks:nil]];
  62. }
  63. if (parseResult == nil) {
  64. return NO;
  65. }
  66. if (!parseResult.parsedDocument) {
  67. return NO;
  68. }
  69. return YES;
  70. }
  71. + (instancetype)imageRepWithData:(NSData *)d
  72. {
  73. return [[self alloc] initWithData:d];
  74. }
  75. + (instancetype)imageRepWithContentsOfFile:(NSString *)filename
  76. {
  77. return [[self alloc] initWithContentsOfFile:filename];
  78. }
  79. + (instancetype)imageRepWithContentsOfURL:(NSURL *)url
  80. {
  81. return [[self alloc] initWithContentsOfURL:url];
  82. }
  83. + (instancetype)imageRepWithSVGSource:(SVGKSource*)theSource
  84. {
  85. return [[self alloc] initWithSVGSource:theSource];
  86. }
  87. + (instancetype)imageRepWithSVGImage:(SVGKImage*)theImage
  88. {
  89. return [[self alloc] initWithSVGImage:theImage];
  90. }
  91. + (void)load
  92. {
  93. [self loadSVGKImageRep];
  94. }
  95. - (instancetype)initWithData:(NSData *)theData
  96. {
  97. return [self initWithSVGImage:[[SVGKImage alloc] initWithData:theData] copy:NO];
  98. }
  99. - (instancetype)initWithContentsOfURL:(NSURL *)theURL
  100. {
  101. return [self initWithSVGImage:[SVGKImage imageWithContentsOfURL:theURL] copy:NO];
  102. }
  103. - (instancetype)initWithContentsOfFile:(NSString *)thePath
  104. {
  105. return [self initWithSVGImage:[[SVGKImage alloc] initWithContentsOfFile:thePath] copy:NO];
  106. }
  107. - (instancetype)initWithSVGString:(NSString *)theString
  108. {
  109. return [self initWithSVGSource:[SVGKSourceString sourceFromContentsOfString:theString]];
  110. }
  111. - (instancetype)initWithSVGSource:(SVGKSource*)theSource
  112. {
  113. return [self initWithSVGImage:[[SVGKImage alloc] initWithSource:theSource] copy:NO];
  114. }
  115. - (instancetype)initWithSVGImage:(SVGKImage*)theImage copy:(BOOL)copyImage
  116. {
  117. if (self = [super init]) {
  118. if (theImage == nil) {
  119. return nil;
  120. }
  121. SVGKImage *tmpImage;
  122. if (copyImage) {
  123. tmpImage = [theImage copy];
  124. if (tmpImage) {
  125. theImage = tmpImage;
  126. }
  127. }
  128. self.image = theImage;
  129. if (![self.image hasSize]) {
  130. self.image.size = CGSizeMake(32, 32);
  131. }
  132. self.colorSpaceName = NSCalibratedRGBColorSpace;
  133. self.alpha = YES;
  134. self.opaque = NO;
  135. [self setSize:self.image.size sizeImage:NO];
  136. self.interpolationQuality = kCGInterpolationDefault;
  137. self.antiAlias = YES;
  138. self.curveFlatness = 1.0;
  139. // Setting these to zero will tell NSImage that this image is resolution-independant.
  140. self.pixelsHigh = 0;
  141. self.pixelsWide = 0;
  142. self.bitsPerSample = 0;
  143. }
  144. return self;
  145. }
  146. - (instancetype)init
  147. {
  148. NSAssert(NO, @"init not supported, use initWithData:");
  149. return nil;
  150. }
  151. - (void)setSize:(NSSize)aSize
  152. {
  153. [self setSize:aSize sizeImage:YES];
  154. }
  155. - (void)setSize:(NSSize)aSize sizeImage:(BOOL)theSize
  156. {
  157. [super setSize:aSize];
  158. if (theSize) {
  159. self.image.size = aSize;
  160. }
  161. }
  162. + (void)loadSVGKImageRep
  163. {
  164. [NSImageRep registerImageRepClass:[SVGKImageRep class]];
  165. }
  166. + (void)unloadSVGKImageRep
  167. {
  168. [NSImageRep unregisterImageRepClass:[SVGKImageRep class]];
  169. }
  170. - (instancetype)initWithSVGImage:(SVGKImage*)theImage
  171. {
  172. //Copy over the image, just in case
  173. return [self initWithSVGImage:theImage copy:YES];
  174. }
  175. - (BOOL)drawInRect:(NSRect)rect
  176. {
  177. NSSize scaledSize = rect.size;
  178. if (!CGSizeEqualToSize(self.image.size, scaledSize)) {
  179. //For when we're at the full size.
  180. if (CGSizeEqualToSize(self.size, scaledSize)) {
  181. return [super drawInRect:rect];
  182. } else {
  183. [self.image scaleToFitInside:scaledSize];
  184. }
  185. } else if (CGSizeEqualToSize(self.size, scaledSize) &&
  186. CGSizeEqualToSize(self.image.size, self.size)) {
  187. return [super drawInRect:rect];
  188. }
  189. CGContextRef imRepCtx = [[NSGraphicsContext currentContext] graphicsPort];
  190. CGLayerRef layerRef = CGLayerCreateWithContext(imRepCtx, rect.size, NULL);
  191. if (!layerRef) {
  192. return NO;
  193. }
  194. CGContextRef layerCont = CGLayerGetContext(layerRef);
  195. CGContextSaveGState(layerCont);
  196. [self.image renderToContext:layerCont antiAliased:_antiAlias curveFlatnessFactor:_curveFlatness interpolationQuality:_interpolationQuality flipYaxis:YES];
  197. CGContextRestoreGState(layerCont);
  198. CGContextDrawLayerInRect(imRepCtx, rect, layerRef);
  199. CGLayerRelease(layerRef);
  200. return YES;
  201. }
  202. - (BOOL)draw
  203. {
  204. //Just in case someone resized the image rep.
  205. NSSize scaledSize = self.size;
  206. if (!CGSizeEqualToSize(self.image.size, scaledSize)) {
  207. self.image.size = scaledSize;
  208. }
  209. CGContextRef imRepCtx = [[NSGraphicsContext currentContext] graphicsPort];
  210. CGLayerRef layerRef = CGLayerCreateWithContext(imRepCtx, scaledSize, NULL);
  211. if (!layerRef) {
  212. return NO;
  213. }
  214. CGContextRef layerCont = CGLayerGetContext(layerRef);
  215. CGContextSaveGState(layerCont);
  216. [self.image renderToContext:layerCont antiAliased:_antiAlias curveFlatnessFactor:_curveFlatness interpolationQuality:_interpolationQuality flipYaxis:YES];
  217. CGContextRestoreGState(layerCont);
  218. CGContextDrawLayerAtPoint(imRepCtx, CGPointZero, layerRef);
  219. CGLayerRelease(layerRef);
  220. return YES;
  221. }
  222. #pragma mark - Inherited protocols
  223. #pragma mark NSCopying
  224. - (id)copyWithZone:(NSZone *)zone
  225. {
  226. SVGKImageRep *toRet = [[SVGKImageRep alloc] initWithSVGImage:self.image];
  227. return toRet;
  228. }
  229. #pragma mark NSCoding
  230. - (instancetype)initWithCoder:(NSCoder *)coder
  231. {
  232. if (self = [super initWithCoder:coder]) {
  233. }
  234. return self;
  235. }
  236. - (void)encodeWithCoder:(NSCoder *)aCoder
  237. {
  238. [super encodeWithCoder:aCoder];
  239. }
  240. @end
  241. #endif /* SVGKIT_MAC */