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) RNSVGCGFloatArray strokeDasharray;
@property (nonatomic, assign) CGFloat strokeDashoffset;
@property (nonatomic, assign) CGPathRef hitArea;
@property (nonatomic, copy) NSArray<NSString *> *propList;
@property (nonatomic, strong) NSArray<NSString *> *attributeList;
@@ -39,5 +38,6 @@
- (CGFloat)getHeightRelatedValue:(NSString *)string;
- (RNSVGPercentageConverter *)getWidthConverter;
- (RNSVGPercentageConverter *)getHeightConverter;
- (void)setHitArea:(CGPathRef)path;
@end
+23 -27
View File
@@ -17,6 +17,7 @@
CGRect _contextBoundingBox;
CGRect _renderBoundingBox;
BOOL _fillEvenodd;
CGPathRef _hitArea;
}
- (id)init
@@ -132,17 +133,6 @@
_strokeDashoffset = strokeDashoffset;
}
- (void)setHitArea:(CGPathRef)hitArea
{
if (hitArea == _hitArea) {
return;
}
[self invalidate];
CGPathRelease(_hitArea);
_hitArea = CGPathRetain(hitArea);
}
- (void)setPropList:(NSArray<NSString *> *)propList
{
if (propList == _propList) {
@@ -175,6 +165,7 @@
CGContextRestoreGState(context);
}
- (void)renderLayerTo:(CGContextRef)context
{
BOOL shouldStroke = self.stroke && self.strokeWidth;
@@ -184,21 +175,7 @@
}
CGPathRef path = [self getPath:context];
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);
}
[self setHitArea:path];
if (self.opacity == 0) {
return;
@@ -261,6 +238,25 @@
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
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
@@ -278,7 +274,7 @@
}
CGAffineTransform matrix = CGAffineTransformConcat(self.matrix, transform);
CGPathRef hitArea = CGPathCreateCopyByTransformingPath(self.hitArea, &matrix);
CGPathRef hitArea = CGPathCreateCopyByTransformingPath(_hitArea, &matrix);
BOOL contains = CGPathContainsPoint(hitArea, nil, point, NO);
CGPathRelease(hitArea);
+11 -10
View File
@@ -42,10 +42,10 @@
NSString *text = self.content;
if (!text) {
return [super getPath:context];
return [self getGroupPath:context];
}
[self initialTextPath];
[self setupTextPath];
[self setContextBoundingBox:CGContextGetClipBoundingBox(context)];
CGMutablePathRef path = CGPathCreateMutable();
@@ -53,7 +53,9 @@
// append spacing
text = [text stringByAppendingString:@" "];
[self pushGlyphContext];
CTFontRef font = [self getFontFromContext];
// Create a dictionary for this font
CFDictionaryRef attributes = (__bridge CFDictionaryRef)@{
(NSString *)kCTFontAttributeName: (__bridge id)font,
@@ -67,20 +69,20 @@
CGMutablePathRef linePath = [self getLinePath:line];
CGAffineTransform offset = CGAffineTransformMakeTranslation(0, _bezierTransformer ? 0 : CTFontGetSize(font) * 1.1);
CGPathAddPath(path, &offset, linePath);
_cache = CGPathRetain(CGPathCreateCopy(path));
[self popGlyphContext];
// clean up
CFRelease(attrString);
CFRelease(line);
CGPathRelease(linePath);
_cache = CGPathRetain(CGPathCreateCopy(path));
return (CGPathRef)CFAutorelease(path);
}
- (CGMutablePathRef)getLinePath:(CTLineRef)line
{
[self pushGlyphContext];
CTRunRef run = CFArrayGetValueAtIndex(CTLineGetGlyphRuns(line), 0);
CFIndex runGlyphCount = CTRunGetGlyphCount(run);
@@ -98,7 +100,7 @@
for(CFIndex i = 0; i < runGlyphCount; i++) {
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];
@@ -121,11 +123,10 @@
CGPathRelease(letter);
}
[self popGlyphContext];
return path;
}
- (void)initialTextPath
- (void)setupTextPath
{
__block RNSVGBezierTransformer *bezierTransformer;
[self traverseTextSuperviews:^(__kindof RNSVGText *node) {
@@ -136,7 +137,7 @@
}
return YES;
}];
_bezierTransformer = bezierTransformer;
}
+1
View File
@@ -26,6 +26,7 @@
- (RNSVGText *)getTextRoot;
- (void)releaseCachedPath;
- (CGPathRef)getGroupPath:(CGContextRef)context;
- (RNSVGGlyphContext *)getGlyphContext;
- (void)pushGlyphContext;
+19 -6
View File
@@ -26,12 +26,9 @@
- (void)renderLayerTo:(CGContextRef)context
{
[self setContextBoundingBox:CGContextGetClipBoundingBox(context)];
_glyphContext = [[RNSVGGlyphContext alloc] initWithConverters:[self getWidthConverter]
heightConverter:[self getHeightConverter]];
[self clip:context];
CGContextSaveGState(context);
[self setupGlyphContext:context];
CGAffineTransform transform = [self getAlignTransform:context];
CGContextConcatCTM(context, transform);
[self renderGroupTo:context];
@@ -39,6 +36,14 @@
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
{
[self traverseSubviews:^BOOL(__kindof RNSVGNode *node) {
@@ -48,14 +53,22 @@
}];
}
- (CGPathRef)getPath:(CGContextRef)context
- (CGPathRef)getGroupPath:(CGContextRef)context
{
[self pushGlyphContext];
CGPathRef groupPath = [super getPath:context];
[self popGlyphContext];
return groupPath;
}
- (CGPathRef)getPath:(CGContextRef)context
{
[self setupGlyphContext:context];
CGPathRef groupPath = [self getGroupPath:context];
CGAffineTransform transform = [self getAlignTransform:context path:groupPath];
CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(groupPath, &transform);
[self releaseCachedPath];
return transformedPath;
}
@@ -69,7 +82,7 @@
- (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
+15
View File
@@ -34,4 +34,19 @@
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