Fix ClipPath with Text

This commit is contained in:
Horcrux
2017-01-11 18:18:51 +08:00
parent 1381cd8fca
commit d7daee343c
6 changed files with 70 additions and 44 deletions
+1 -1
View File
@@ -27,7 +27,6 @@
@property (nonatomic, assign) CGFloat strokeMiterlimit; @property (nonatomic, assign) CGFloat strokeMiterlimit;
@property (nonatomic, assign) RNSVGCGFloatArray strokeDasharray; @property (nonatomic, assign) RNSVGCGFloatArray strokeDasharray;
@property (nonatomic, assign) CGFloat strokeDashoffset; @property (nonatomic, assign) CGFloat strokeDashoffset;
@property (nonatomic, assign) CGPathRef hitArea;
@property (nonatomic, copy) NSArray<NSString *> *propList; @property (nonatomic, copy) NSArray<NSString *> *propList;
@property (nonatomic, strong) NSArray<NSString *> *attributeList; @property (nonatomic, strong) NSArray<NSString *> *attributeList;
@@ -39,5 +38,6 @@
- (CGFloat)getHeightRelatedValue:(NSString *)string; - (CGFloat)getHeightRelatedValue:(NSString *)string;
- (RNSVGPercentageConverter *)getWidthConverter; - (RNSVGPercentageConverter *)getWidthConverter;
- (RNSVGPercentageConverter *)getHeightConverter; - (RNSVGPercentageConverter *)getHeightConverter;
- (void)setHitArea:(CGPathRef)path;
@end @end
+23 -27
View File
@@ -17,6 +17,7 @@
CGRect _contextBoundingBox; CGRect _contextBoundingBox;
CGRect _renderBoundingBox; CGRect _renderBoundingBox;
BOOL _fillEvenodd; BOOL _fillEvenodd;
CGPathRef _hitArea;
} }
- (id)init - (id)init
@@ -132,17 +133,6 @@
_strokeDashoffset = strokeDashoffset; _strokeDashoffset = strokeDashoffset;
} }
- (void)setHitArea:(CGPathRef)hitArea
{
if (hitArea == _hitArea) {
return;
}
[self invalidate];
CGPathRelease(_hitArea);
_hitArea = CGPathRetain(hitArea);
}
- (void)setPropList:(NSArray<NSString *> *)propList - (void)setPropList:(NSArray<NSString *> *)propList
{ {
if (propList == _propList) { if (propList == _propList) {
@@ -175,6 +165,7 @@
CGContextRestoreGState(context); CGContextRestoreGState(context);
} }
- (void)renderLayerTo:(CGContextRef)context - (void)renderLayerTo:(CGContextRef)context
{ {
BOOL shouldStroke = self.stroke && self.strokeWidth; BOOL shouldStroke = self.stroke && self.strokeWidth;
@@ -184,21 +175,7 @@
} }
CGPathRef path = [self getPath:context]; CGPathRef path = [self getPath:context];
[self setHitArea:path];
if ([self getSvgView].responsible) {
// Add path to hitArea
CGMutablePathRef hitArea = CGPathCreateMutableCopy(path);
if (self.stroke && self.strokeWidth) {
// Add stroke to hitArea
CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, self.strokeWidth, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit);
CGPathAddPath(hitArea, nil, strokePath);
CGPathRelease(strokePath);
}
self.hitArea = CFAutorelease(CGPathCreateCopy(hitArea));
CGPathRelease(hitArea);
}
if (self.opacity == 0) { if (self.opacity == 0) {
return; return;
@@ -261,6 +238,25 @@
CGContextDrawPath(context, mode); CGContextDrawPath(context, mode);
} }
- (void)setHitArea:(CGPathRef)path
{
CGPathRelease(_hitArea);
if ([self getSvgView].responsible) {
// Add path to hitArea
CGMutablePathRef hitArea = CGPathCreateMutableCopy(path);
if (self.stroke && self.strokeWidth) {
// Add stroke to hitArea
CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, self.strokeWidth, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit);
CGPathAddPath(hitArea, nil, strokePath);
CGPathRelease(strokePath);
}
_hitArea = CGPathRetain(CGPathCreateCopy(hitArea));
CGPathRelease(hitArea);
}
}
// hitTest delagate // hitTest delagate
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
@@ -278,7 +274,7 @@
} }
CGAffineTransform matrix = CGAffineTransformConcat(self.matrix, transform); CGAffineTransform matrix = CGAffineTransformConcat(self.matrix, transform);
CGPathRef hitArea = CGPathCreateCopyByTransformingPath(self.hitArea, &matrix); CGPathRef hitArea = CGPathCreateCopyByTransformingPath(_hitArea, &matrix);
BOOL contains = CGPathContainsPoint(hitArea, nil, point, NO); BOOL contains = CGPathContainsPoint(hitArea, nil, point, NO);
CGPathRelease(hitArea); CGPathRelease(hitArea);
+11 -10
View File
@@ -42,10 +42,10 @@
NSString *text = self.content; NSString *text = self.content;
if (!text) { if (!text) {
return [super getPath:context]; return [self getGroupPath:context];
} }
[self initialTextPath]; [self setupTextPath];
[self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; [self setContextBoundingBox:CGContextGetClipBoundingBox(context)];
CGMutablePathRef path = CGPathCreateMutable(); CGMutablePathRef path = CGPathCreateMutable();
@@ -53,7 +53,9 @@
// append spacing // append spacing
text = [text stringByAppendingString:@" "]; text = [text stringByAppendingString:@" "];
[self pushGlyphContext];
CTFontRef font = [self getFontFromContext]; CTFontRef font = [self getFontFromContext];
// Create a dictionary for this font // Create a dictionary for this font
CFDictionaryRef attributes = (__bridge CFDictionaryRef)@{ CFDictionaryRef attributes = (__bridge CFDictionaryRef)@{
(NSString *)kCTFontAttributeName: (__bridge id)font, (NSString *)kCTFontAttributeName: (__bridge id)font,
@@ -67,20 +69,20 @@
CGMutablePathRef linePath = [self getLinePath:line]; CGMutablePathRef linePath = [self getLinePath:line];
CGAffineTransform offset = CGAffineTransformMakeTranslation(0, _bezierTransformer ? 0 : CTFontGetSize(font) * 1.1); CGAffineTransform offset = CGAffineTransformMakeTranslation(0, _bezierTransformer ? 0 : CTFontGetSize(font) * 1.1);
CGPathAddPath(path, &offset, linePath); CGPathAddPath(path, &offset, linePath);
_cache = CGPathRetain(CGPathCreateCopy(path));
[self popGlyphContext];
// clean up // clean up
CFRelease(attrString); CFRelease(attrString);
CFRelease(line); CFRelease(line);
CGPathRelease(linePath); CGPathRelease(linePath);
_cache = CGPathRetain(CGPathCreateCopy(path));
return (CGPathRef)CFAutorelease(path); return (CGPathRef)CFAutorelease(path);
} }
- (CGMutablePathRef)getLinePath:(CTLineRef)line - (CGMutablePathRef)getLinePath:(CTLineRef)line
{ {
[self pushGlyphContext];
CTRunRef run = CFArrayGetValueAtIndex(CTLineGetGlyphRuns(line), 0); CTRunRef run = CFArrayGetValueAtIndex(CTLineGetGlyphRuns(line), 0);
CFIndex runGlyphCount = CTRunGetGlyphCount(run); CFIndex runGlyphCount = CTRunGetGlyphCount(run);
@@ -98,7 +100,7 @@
for(CFIndex i = 0; i < runGlyphCount; i++) { for(CFIndex i = 0; i < runGlyphCount; i++) {
CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyphs[i], nil); CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyphs[i], nil);
glyphPoint = [self getGlyphPointFromContext:positions[i] glyphWidth:CGPathGetBoundingBox(letter).size.width]; glyphPoint = [self getGlyphPointFromContext:positions[i] glyphWidth:CGRectGetWidth(CGPathGetBoundingBox(letter))];
CGAffineTransform textPathTransform = [self getTextPathTransform:glyphPoint.x]; CGAffineTransform textPathTransform = [self getTextPathTransform:glyphPoint.x];
@@ -121,11 +123,10 @@
CGPathRelease(letter); CGPathRelease(letter);
} }
[self popGlyphContext];
return path; return path;
} }
- (void)initialTextPath - (void)setupTextPath
{ {
__block RNSVGBezierTransformer *bezierTransformer; __block RNSVGBezierTransformer *bezierTransformer;
[self traverseTextSuperviews:^(__kindof RNSVGText *node) { [self traverseTextSuperviews:^(__kindof RNSVGText *node) {
@@ -136,7 +137,7 @@
} }
return YES; return YES;
}]; }];
_bezierTransformer = bezierTransformer; _bezierTransformer = bezierTransformer;
} }
+1
View File
@@ -26,6 +26,7 @@
- (RNSVGText *)getTextRoot; - (RNSVGText *)getTextRoot;
- (void)releaseCachedPath; - (void)releaseCachedPath;
- (CGPathRef)getGroupPath:(CGContextRef)context;
- (RNSVGGlyphContext *)getGlyphContext; - (RNSVGGlyphContext *)getGlyphContext;
- (void)pushGlyphContext; - (void)pushGlyphContext;
+19 -6
View File
@@ -26,12 +26,9 @@
- (void)renderLayerTo:(CGContextRef)context - (void)renderLayerTo:(CGContextRef)context
{ {
[self setContextBoundingBox:CGContextGetClipBoundingBox(context)];
_glyphContext = [[RNSVGGlyphContext alloc] initWithConverters:[self getWidthConverter]
heightConverter:[self getHeightConverter]];
[self clip:context]; [self clip:context];
CGContextSaveGState(context); CGContextSaveGState(context);
[self setupGlyphContext:context];
CGAffineTransform transform = [self getAlignTransform:context]; CGAffineTransform transform = [self getAlignTransform:context];
CGContextConcatCTM(context, transform); CGContextConcatCTM(context, transform);
[self renderGroupTo:context]; [self renderGroupTo:context];
@@ -39,6 +36,14 @@
CGContextRestoreGState(context); CGContextRestoreGState(context);
} }
- (void)setupGlyphContext:(CGContextRef)context
{
[self setContextBoundingBox:CGContextGetClipBoundingBox(context)];
_glyphContext = [[RNSVGGlyphContext alloc] initWithConverters:[self getWidthConverter]
heightConverter:[self getHeightConverter]];
}
// release the cached CGPathRef for RNSVGTSpan
- (void)releaseCachedPath - (void)releaseCachedPath
{ {
[self traverseSubviews:^BOOL(__kindof RNSVGNode *node) { [self traverseSubviews:^BOOL(__kindof RNSVGNode *node) {
@@ -48,14 +53,22 @@
}]; }];
} }
- (CGPathRef)getPath:(CGContextRef)context - (CGPathRef)getGroupPath:(CGContextRef)context
{ {
[self pushGlyphContext]; [self pushGlyphContext];
CGPathRef groupPath = [super getPath:context]; CGPathRef groupPath = [super getPath:context];
[self popGlyphContext]; [self popGlyphContext];
return groupPath;
}
- (CGPathRef)getPath:(CGContextRef)context
{
[self setupGlyphContext:context];
CGPathRef groupPath = [self getGroupPath:context];
CGAffineTransform transform = [self getAlignTransform:context path:groupPath]; CGAffineTransform transform = [self getAlignTransform:context path:groupPath];
CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(groupPath, &transform); CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(groupPath, &transform);
[self releaseCachedPath];
return transformedPath; return transformedPath;
} }
@@ -69,7 +82,7 @@
- (CGAffineTransform)getAlignTransform:(CGContextRef)context - (CGAffineTransform)getAlignTransform:(CGContextRef)context
{ {
return [self getAlignTransform:context path:[self getPath:context]]; return [self getAlignTransform:context path:[self getGroupPath:context]];
} }
- (CGAffineTransform)getAlignTransform:(CGContextRef)context path:(CGPathRef)path - (CGAffineTransform)getAlignTransform:(CGContextRef)context path:(CGPathRef)path
+15
View File
@@ -34,4 +34,19 @@
startOffset:startOffset]; startOffset:startOffset];
} }
- (CGPathRef)getPath:(CGContextRef)context
{
return [self getGroupPath:context];
}
- (void)pushGlyphContext
{
// TextPath do not affect the glyphContext
}
- (void)popGlyphContext
{
// TextPath do not affect the glyphContext
}
@end @end