Files
IJSVG/source/IJSVGShapeLayer.m
2019-03-14 20:11:49 +00:00

163 lines
4.9 KiB
Objective-C

//
// IJSVGShapeLayer.m
// IJSVGExample
//
// Created by Curtis Hard on 07/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGShapeLayer.h"
#import "IJSVGGroupLayer.h"
@implementation IJSVGShapeLayer
@synthesize gradientFillLayer;
@synthesize patternFillLayer;
@synthesize gradientStrokeLayer;
@synthesize patternStrokeLayer;
@synthesize strokeLayer;
@synthesize requiresBackingScaleHelp;
@synthesize backingScaleFactor;
@synthesize blendingMode;
@synthesize convertMasksToPaths;
@synthesize originalPathOrigin;
@synthesize renderQuality;
- (void)dealloc
{
[_maskingLayer release], _maskingLayer = nil;
[super dealloc];
}
- (void)addSublayer:(CALayer *)layer {
if([layer isKindOfClass:[IJSVGLayer class]] == NO &&
[layer isKindOfClass:[IJSVGShapeLayer class]] == NO) {
NSString * r = [NSString stringWithFormat:@"The layer must be an instance of IJSVGLayer, %@ given.",
[layer class]];
NSException * exception = [NSException exceptionWithName:@"IJSVGInvalidSublayerException"
reason:r
userInfo:nil];
@throw exception;
}
[super addSublayer:layer];
}
- (void)setBackingScaleFactor:(CGFloat)newFactor
{
if(self.backingScaleFactor == newFactor) {
return;
}
backingScaleFactor = newFactor;
self.contentsScale = newFactor;
self.rasterizationScale = newFactor;
[self setNeedsDisplay];
}
- (void)_customRenderInContext:(CGContextRef)ctx
{
if(self.convertMasksToPaths == YES && _maskingLayer != nil) {
CGContextSaveGState(ctx);
[self applySublayerMaskToContext:ctx
forSublayer:(IJSVGLayer *)self
withOffset:CGPointZero];
[super renderInContext:ctx];
CGContextRestoreGState(ctx);
return;
}
[super renderInContext:ctx];
}
- (void)setConvertMasksToPaths:(BOOL)flag
{
if(convertMasksToPaths == flag) {
return;
}
convertMasksToPaths = flag;
if(flag == YES) {
if(_maskingLayer != nil) {
[_maskingLayer release], _maskingLayer = nil;
}
_maskingLayer = [(IJSVGLayer *)self.mask retain];
self.mask = nil;
} else {
self.mask = _maskingLayer;
[_maskingLayer release], _maskingLayer = nil;
}
}
- (void)applySublayerMaskToContext:(CGContextRef)context
forSublayer:(IJSVGLayer *)sublayer
withOffset:(CGPoint)offset
{
// apply any transforms needed
CGPoint layerOffset = offset;
CGAffineTransform sublayerTransform = CATransform3DGetAffineTransform(sublayer.transform);
CGContextConcatCTM( context, CGAffineTransformInvert(sublayerTransform) );
// walk up the superlayer chain
CALayer * superlayer = self.superlayer;
if (IJSVGIsSVGLayer(superlayer) == YES) {
[(IJSVGLayer *)superlayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer *)self
withOffset:layerOffset];
}
// grab the masking layer
IJSVGShapeLayer * maskingLayer = [self maskingLayer];
// if its a group we need to get the lowest level children
// and walk up the chain again
if([maskingLayer isKindOfClass:[IJSVGGroupLayer class]]) {
NSArray * subs = [IJSVGLayer deepestSublayersOfLayer:maskingLayer];
for(IJSVGLayer * subLayer in subs) {
[subLayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer *)self
withOffset:layerOffset];
}
} else if ([maskingLayer isKindOfClass:[IJSVGShapeLayer class]]) {
// is a shape, go for it!
CGPathRef maskPath = maskingLayer.path;
CGContextTranslateCTM(context, -layerOffset.x, -layerOffset.y);
CGContextAddPath(context, maskPath);
CGContextClip(context);
CGContextTranslateCTM(context, layerOffset.x, layerOffset.y);
}
CGContextConcatCTM(context, sublayerTransform);
}
- (IJSVGShapeLayer *)maskingLayer
{
return (IJSVGShapeLayer *)_maskingLayer ?: nil;
}
- (void)renderInContext:(CGContextRef)ctx
{
if(self.blendingMode != kCGBlendModeNormal) {
CGContextSaveGState(ctx);
CGContextSetBlendMode(ctx, self.blendingMode);
[self _customRenderInContext:ctx];
CGContextRestoreGState(ctx);
return;
}
[self _customRenderInContext:ctx];
}
- (CGPoint)absoluteOrigin
{
CGPoint point = CGPointZero;
CALayer * pLayer = self;
while(pLayer != nil) {
point.x += pLayer.frame.origin.x;
point.y += pLayer.frame.origin.y;
pLayer = pLayer.superlayer;
}
return point;
}
- (id<CAAction>)actionForKey:(NSString *)event
{
return nil;
}
@end