diff --git a/Framework/IJSVG/IJSVG/Source/Core/IJSVG.h b/Framework/IJSVG/IJSVG/Source/Core/IJSVG.h index 6edbaf5..160a512 100644 --- a/Framework/IJSVG/IJSVG/Source/Core/IJSVG.h +++ b/Framework/IJSVG/IJSVG/Source/Core/IJSVG.h @@ -11,6 +11,7 @@ #import #import #import +#import #import #import #import @@ -43,11 +44,8 @@ withSVGString:(NSString*)subSVGString; CGFloat _scale; CGFloat _clipScale; id _delegate; - CALayer* _layerTree; + IJSVGLayerTree* _layerTree; CGRect _viewBox; - CGFloat _backingScaleFactor; - CGFloat _lastProposedBackingScale; - IJSVGRenderQuality _lastProposedRenderQuality; CGFloat _backingScale; NSMutableDictionary* _replacementColors; @@ -70,7 +68,8 @@ withSVGString:(NSString*)subSVGString; @property (nonatomic, readonly) IJSVGUnitSize * intrinsicSize; @property (nonatomic, copy) NSString* title; @property (nonatomic, copy) NSString* desc; -@property (nonatomic, retain) IJSVGRootLayer* layer; +@property (nonatomic, retain) IJSVGLayerTree* layerTree; +@property (nonatomic, retain) IJSVGRootLayer* rootLayer; - (void)prepForDrawingInView:(NSView*)view; - (BOOL)isFont; @@ -78,14 +77,11 @@ withSVGString:(NSString*)subSVGString; - (NSRect)viewBox; - (NSArray*)glyphs; - (NSString*)identifier; -- (IJSVGLayer*)layerWithTree:(IJSVGLayerTree*)tree; - (NSArray*)subSVGs:(BOOL)recursive; - (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options; - (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions; -- (CGFloat)computeBackingScale:(CGFloat)scale; - + (id)svgNamed:(NSString*)string; + (id)svgNamed:(NSString*)string delegate:(id)delegate; @@ -162,9 +158,6 @@ withSVGString:(NSString*)subSVGString; - (NSData*)PDFDataWithRect:(NSRect)rect error:(NSError**)error; -- (void)beginVectorDraw; -- (void)endVectorDraw; - - (NSRect)computeOriginalDrawingFrameWithSize:(NSSize)aSize; - (void)setNeedsDisplay; diff --git a/Framework/IJSVG/IJSVG/Source/Core/IJSVG.m b/Framework/IJSVG/IJSVG/Source/Core/IJSVG.m index 887cdba..ac982d7 100644 --- a/Framework/IJSVG/IJSVG/Source/Core/IJSVG.m +++ b/Framework/IJSVG/IJSVG/Source/Core/IJSVG.m @@ -27,7 +27,7 @@ (void)([_intrinsicSize release]), _intrinsicSize = nil; (void)([_title release]), _title = nil; (void)([_desc release]), _desc = nil; - (void)([_layer release]), _layer = nil; + (void)([_rootLayer release]), _rootLayer = nil; // kill any memory that has been around (void)([_layerTree release]), _layerTree = nil; @@ -131,7 +131,6 @@ // this completely bypasses passing of files if ((self = [super init]) != nil) { // keep the layer tree - _layerTree = [group retain]; _viewBox = viewBox; // any setups @@ -312,7 +311,6 @@ self.renderQuality = kIJSVGRenderQualityFullResolution; // setup low level backing scale - _lastProposedBackingScale = 0.f; self.renderingBackingScaleHelper = ^CGFloat { return NSScreen.mainScreen.backingScaleFactor; }; @@ -444,7 +442,7 @@ [self _beginDraw:rect]; // make sure we setup the scale based on the backing scale factor - CGFloat scale = [self backingScaleFactor:NULL]; + CGFloat scale = [self backingScaleFactor]; // create the context and colorspace CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); @@ -534,10 +532,10 @@ CGContextTranslateCTM(context, 0, -box.size.height); // make sure we set the masks to path bits n bobs - [self _beginVectorDraw]; +// [self _beginVectorDraw]; // draw the icon [self _drawInRect:(NSRect)box context:context error:error]; - [self _endVectorDraw]; +// [self _endVectorDraw]; CGContextEndPage(context); @@ -548,39 +546,39 @@ return data; } -- (void)endVectorDraw -{ - [self _endVectorDraw]; -} +//- (void)endVectorDraw +//{ +// [self _endVectorDraw]; +//} +// +//- (void)beginVectorDraw +//{ +// [self _beginVectorDraw]; +//} -- (void)beginVectorDraw -{ - [self _beginVectorDraw]; -} - -- (void)_beginVectorDraw -{ - // turn on converts masks to PDF's - // as PDF context and layer masks dont work - void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) = - ^void(CALayer* layer, BOOL isMask, BOOL* stop) { - ((IJSVGLayer*)layer).convertMasksToPaths = YES; - }; - [IJSVGLayer recursivelyWalkLayer:self.layer - withBlock:block]; -} - -- (void)_endVectorDraw -{ - // turn of convert masks to paths as not - // needed for generic rendering - void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) = - ^void(CALayer* layer, BOOL isMask, BOOL* stop) { - ((IJSVGLayer*)layer).convertMasksToPaths = NO; - }; - [IJSVGLayer recursivelyWalkLayer:self.layer - withBlock:block]; -} +//- (void)_beginVectorDraw +//{ +// // turn on converts masks to PDF's +// // as PDF context and layer masks dont work +// void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) = +// ^void(CALayer* layer, BOOL isMask, BOOL* stop) { +// ((IJSVGLayer*)layer).convertMasksToPaths = YES; +// }; +// [IJSVGLayer recursivelyWalkLayer:self.layer +// withBlock:block]; +//} +// +//- (void)_endVectorDraw +//{ +// // turn of convert masks to paths as not +// // needed for generic rendering +// void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) = +// ^void(CALayer* layer, BOOL isMask, BOOL* stop) { +// ((IJSVGLayer*)layer).convertMasksToPaths = NO; +// }; +// [IJSVGLayer recursivelyWalkLayer:self.layer +// withBlock:block]; +//} - (void)prepForDrawingInView:(NSView*)view { @@ -591,7 +589,7 @@ } // construct the layer before drawing - [self layer]; + [self rootLayer]; // set the scale __block NSView* weakView = view; @@ -637,12 +635,6 @@ error:error]; } -- (CGFloat)computeBackingScale:(CGFloat)actualScale -{ - _backingScale = actualScale; - return (CGFloat)(_scale + actualScale); -} - - (NSRect)computeRectDrawingInRect:(NSRect)rect isValid:(BOOL*)valid { @@ -755,106 +747,44 @@ error:(NSError**)error { CGContextSaveGState(ref); - if(_layer != nil) { - (void)[_layer release], _layer = nil; - } - // make sure we setup a transaction IJSVGBeginTransaction(); - - // create a new tree view the current viewport we are trying to - // render into, this effects how the viewbox aspect ratio's work - CGFloat backingScale = [self backingScaleFactor:NULL]; - IJSVGLayerTree* tree = [[[IJSVGLayerTree alloc] initWithViewPortRect:rect - backingScale:backingScale] autorelease]; - - // grab the layer and make sure we set the backing scale factor onto it - _layer = [[tree rootLayerForRootNode:_rootNode] retain]; - [_layer renderInContext:ref]; + CGFloat backingScale = [self backingScaleFactor]; + [self.rootLayer renderInContext:ref + viewPort:rect + backingScale:backingScale + quality:_renderQuality]; IJSVGEndTransaction(); CGContextRestoreGState(ref); return YES; } -- (CGFloat)backingScaleFactor:(CGFloat* _Nullable)proposedBackingScale +- (IJSVGLayerTree*)layerTree +{ + if(_layerTree == nil) { + _layerTree = [[IJSVGLayerTree alloc] init]; + } + return _layerTree; +} + +- (IJSVGRootLayer*)rootLayer +{ + if(_rootLayer == nil) { + _rootLayer = [self.layerTree rootLayerForRootNode:_rootNode].retain; + } + return _rootLayer; +} + +- (CGFloat)backingScaleFactor { __block CGFloat scale = 1.f; scale = (self.renderingBackingScaleHelper)(); if (scale < 1.f) { scale = 1.f; } - _backingScaleFactor = scale; - - // make sure we multiple the scale by the scale of the rendered clip - // or it will be blurry for gradients and other bitmap drawing -// scale = (_scale * scale); - - // dont do anything, nothing has changed, no point of iterating over - // every layer for no reason! - if (scale == _lastProposedBackingScale && _renderQuality == _lastProposedRenderQuality) { - return _backingScaleFactor; - } - - IJSVGRenderQuality quality = self.renderQuality; - _lastProposedBackingScale = scale; - _lastProposedRenderQuality = quality; - if (proposedBackingScale != nil && proposedBackingScale != NULL) { - *proposedBackingScale = scale; - } - - // walk the tree - void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) = - ^void(CALayer* layer, BOOL isMask, BOOL* stop) { - IJSVGLayer* propLayer = ((IJSVGLayer*)layer); - propLayer.renderQuality = quality; - if (propLayer.requiresBackingScaleHelp == YES) { - NSLog(@"%@",propLayer); - propLayer.backingScaleFactor = scale; - } - }; - - // gogogo - BOOL hasTransaction = IJSVGBeginTransaction(); - [IJSVGLayer recursivelyWalkLayer:self.layer withBlock:block]; - if (hasTransaction == YES) { - IJSVGEndTransaction(); - } - return _backingScaleFactor; + return _backingScale = scale; } -//- (CALayer*)layerWithTree:(IJSVGLayerTree*)tree -//{ -// // clear memory -// BOOL hasTransaction = IJSVGBeginTransaction(); -// if (_layerTree != nil) { -// (void)([_layerTree release]), _layerTree = nil; -// } -// -// // force rebuild of the tree -// _layerTree = [[tree drawableLayerForNode:_rootNode] retain]; -// if (hasTransaction == YES) { -// IJSVGEndTransaction(); -// } -// -// return _layerTree; -//} -// -//- (CALayer*)layer -//{ -// if (_layerTree != nil) { -// return _layerTree; -// } -// -// // create the renderer and assign default values -// // from this SVG object -// IJSVGLayerTree* renderer = [[[IJSVGLayerTree alloc] init] autorelease]; -// renderer.viewBox = self.viewBox; -// renderer.style = self.renderingStyle; -// -// // return the rendered layer -// return [self layerWithTree:renderer]; -//} - - (void)setRenderingStyle:(IJSVGRenderingStyle*)style { (void)([_renderingStyle release]), _renderingStyle = nil; @@ -885,12 +815,12 @@ - (IJSVGColorList*)colorList { IJSVGColorList* sheet = [[[IJSVGColorList alloc] init] autorelease]; - void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) = - ^void(CALayer* layer, BOOL isMask, BOOL* stop) { + void (^block)(CALayer* layer, BOOL* stop) = + ^void(CALayer* layer, BOOL* stop) { // dont do anything - if(([layer isKindOfClass:IJSVGShapeLayer.class] && isMask == NO && - layer.isHidden == NO) == false) { + if(([layer isKindOfClass:IJSVGShapeLayer.class] && + layer.isHidden == NO) == NO) { return; } @@ -946,7 +876,7 @@ }; // gogogo! - [IJSVGLayer recursivelyWalkLayer:self.layer + [IJSVGLayer recursivelyWalkLayer:self.rootLayer withBlock:block]; return sheet; } diff --git a/Framework/IJSVG/IJSVG/Source/Exporter/IJSVGExporter.m b/Framework/IJSVG/IJSVG/Source/Exporter/IJSVGExporter.m index afee32a..18224b4 100644 --- a/Framework/IJSVG/IJSVG/Source/Exporter/IJSVGExporter.m +++ b/Framework/IJSVG/IJSVG/Source/Exporter/IJSVGExporter.m @@ -396,7 +396,7 @@ NSString* IJSVGHash(NSString* key) _dom.characterEncoding = XML_DOC_CHARSET; // sort out stuff, so here we go... - [self _recursiveParseFromLayer:_svg.layer + [self _recursiveParseFromLayer:_svg.rootLayer intoElement:nestedRoot]; // this needs to be added incase it needs to be cleaned diff --git a/Framework/IJSVG/IJSVG/Source/Layers/IJSVGLayer.h b/Framework/IJSVG/IJSVG/Source/Layers/IJSVGLayer.h index b351f7d..daf355b 100644 --- a/Framework/IJSVG/IJSVG/Source/Layers/IJSVGLayer.h +++ b/Framework/IJSVG/IJSVG/Source/Layers/IJSVGLayer.h @@ -91,7 +91,7 @@ typedef NS_OPTIONS(NSUInteger, IJSVGLayerTraits) { + (NSArray*)deepestSublayersOfLayer:(CALayer*)layer; + (void)recursivelyWalkLayer:(CALayer*)layer - withBlock:(void (^)(CALayer* layer, BOOL isMask, BOOL* stop))block; + withBlock:(void (^)(CALayer* layer, BOOL* stop))block; - (void)applySublayerMaskToContext:(CGContextRef)context forSublayer:(IJSVGLayer*)sublayer diff --git a/Framework/IJSVG/IJSVG/Source/Layers/IJSVGLayer.m b/Framework/IJSVG/IJSVG/Source/Layers/IJSVGLayer.m index ffa7f93..85a7a55 100644 --- a/Framework/IJSVG/IJSVG/Source/Layers/IJSVGLayer.m +++ b/Framework/IJSVG/IJSVG/Source/Layers/IJSVGLayer.m @@ -246,23 +246,15 @@ } + (void)recursivelyWalkLayer:(CALayer*)layer - withBlock:(void (^)(CALayer* layer, BOOL isMask, BOOL* stop))block + withBlock:(void (^)(CALayer* layer, BOOL* stop))block { // call for layer and mask if there is one BOOL stop = NO; - block(layer, NO, &stop); + block(layer, &stop); if(stop == YES) { return; } -// // do the mask too! -// if (layer.mask != nil) { -// block(layer.mask, YES, &stop); -// if(stop == YES) { -// return; -// } -// } - // sublayers!! for (CALayer* aLayer in layer.sublayers) { [self recursivelyWalkLayer:aLayer diff --git a/Framework/IJSVG/IJSVG/Source/Layers/IJSVGRootLayer.h b/Framework/IJSVG/IJSVG/Source/Layers/IJSVGRootLayer.h index 1d9dfca..c099728 100644 --- a/Framework/IJSVG/IJSVG/Source/Layers/IJSVGRootLayer.h +++ b/Framework/IJSVG/IJSVG/Source/Layers/IJSVGRootLayer.h @@ -8,6 +8,16 @@ #import -@interface IJSVGRootLayer : IJSVGGroupLayer +@interface IJSVGRootLayer : IJSVGGroupLayer { + +@private + BOOL _disableBackingScalePropagation; + +} + +- (void)renderInContext:(CGContextRef)ctx + viewPort:(CGRect)viewPort + backingScale:(CGFloat)backingScale + quality:(IJSVGRenderQuality)quality; @end diff --git a/Framework/IJSVG/IJSVG/Source/Layers/IJSVGRootLayer.m b/Framework/IJSVG/IJSVG/Source/Layers/IJSVGRootLayer.m index 867c35a..96fa0c6 100644 --- a/Framework/IJSVG/IJSVG/Source/Layers/IJSVGRootLayer.m +++ b/Framework/IJSVG/IJSVG/Source/Layers/IJSVGRootLayer.m @@ -35,13 +35,38 @@ - (void)setBackingScaleFactor:(CGFloat)backingScaleFactor { [super setBackingScaleFactor:backingScaleFactor]; + if(_disableBackingScalePropagation == YES) { + return; + } + [self propagateBackingScalePropertiesToSublayers]; +} + +- (void)propagateBackingScalePropertiesToSublayers +{ + __block IJSVGRootLayer* weakSelf = self; for(CALayer* layer in self.sublayers) { [IJSVGLayer recursivelyWalkLayer:layer - withBlock:^(CALayer *layer, BOOL isMask, BOOL *stop) { + withBlock:^(CALayer *layer, BOOL *stop) { IJSVGLayer* propLayer = (IJSVGLayer*)layer; - propLayer.backingScaleFactor = backingScaleFactor; + propLayer.renderQuality = weakSelf.renderQuality; + propLayer.backingScaleFactor = weakSelf.backingScaleFactor; }]; } } +- (void)renderInContext:(CGContextRef)ctx + viewPort:(CGRect)viewPort + backingScale:(CGFloat)backingScale + quality:(IJSVGRenderQuality)quality +{ + CGRect frame = viewPort; + self.frame = frame; + _disableBackingScalePropagation = YES; + self.backingScaleFactor = backingScale; + self.renderQuality = quality; + _disableBackingScalePropagation = NO; + [self propagateBackingScalePropertiesToSublayers]; + [self renderInContext:ctx]; +} + @end diff --git a/IJSVGExample/IJSVGExample.xcodeproj/project.xcworkspace/xcuserdata/curtishard.xcuserdatad/UserInterfaceState.xcuserstate b/IJSVGExample/IJSVGExample.xcodeproj/project.xcworkspace/xcuserdata/curtishard.xcuserdatad/UserInterfaceState.xcuserstate index b6c56d9..4fa3692 100644 Binary files a/IJSVGExample/IJSVGExample.xcodeproj/project.xcworkspace/xcuserdata/curtishard.xcuserdatad/UserInterfaceState.xcuserstate and b/IJSVGExample/IJSVGExample.xcodeproj/project.xcworkspace/xcuserdata/curtishard.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/IJSVGExample/IJSVGExample/SVGView.m b/IJSVGExample/IJSVGExample/SVGView.m index 7d272c5..39901e1 100644 --- a/IJSVGExample/IJSVGExample/SVGView.m +++ b/IJSVGExample/IJSVGExample/SVGView.m @@ -31,7 +31,7 @@ - (IJSVG *)svg { - return [IJSVG svgNamed:@"home"]; + return [IJSVG svgNamed:@"NewTux"]; } - (void)drawRect:(NSRect)dirtyRect