mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-07 08:45:00 +00:00
Fix ClipPath with Text
This commit is contained in:
@@ -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
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user