mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-05-23 03:06:28 +00:00
Fix ClipPath with Text
This commit is contained in:
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
- (RNSVGText *)getTextRoot;
|
||||
- (void)releaseCachedPath;
|
||||
- (CGPathRef)getGroupPath:(CGContextRef)context;
|
||||
|
||||
- (RNSVGGlyphContext *)getGlyphContext;
|
||||
- (void)pushGlyphContext;
|
||||
|
||||
+19
-6
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user