mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-04 07:25:53 +00:00
Clear cached data in tree when changing properties on root svg element.
Fixes staleness issues when changing width and height.
This commit is contained in:
@@ -53,58 +53,82 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
private int mMeetOrSlice;
|
private int mMeetOrSlice;
|
||||||
private Matrix mInvViewBoxMatrix = new Matrix();
|
private Matrix mInvViewBoxMatrix = new Matrix();
|
||||||
private boolean mInvertible = true;
|
private boolean mInvertible = true;
|
||||||
|
private boolean mRendered = false;
|
||||||
|
|
||||||
|
|
||||||
public SvgViewShadowNode() {
|
public SvgViewShadowNode() {
|
||||||
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void releaseCachedPath() {
|
||||||
|
if (!mRendered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mRendered = false;
|
||||||
|
traverseChildren(new VirtualNode.NodeRunnable() {
|
||||||
|
public void run(ReactShadowNode node) {
|
||||||
|
if (node instanceof VirtualNode) {
|
||||||
|
VirtualNode n = ((VirtualNode)node);
|
||||||
|
n.releaseCachedPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@ReactProp(name = "minX")
|
@ReactProp(name = "minX")
|
||||||
public void setMinX(float minX) {
|
public void setMinX(float minX) {
|
||||||
mMinX = minX;
|
mMinX = minX;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
releaseCachedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "minY")
|
@ReactProp(name = "minY")
|
||||||
public void setMinY(float minY) {
|
public void setMinY(float minY) {
|
||||||
mMinY = minY;
|
mMinY = minY;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
releaseCachedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "vbWidth")
|
@ReactProp(name = "vbWidth")
|
||||||
public void setVbWidth(float vbWidth) {
|
public void setVbWidth(float vbWidth) {
|
||||||
mVbWidth = vbWidth;
|
mVbWidth = vbWidth;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
releaseCachedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "vbHeight")
|
@ReactProp(name = "vbHeight")
|
||||||
public void setVbHeight(float vbHeight) {
|
public void setVbHeight(float vbHeight) {
|
||||||
mVbHeight = vbHeight;
|
mVbHeight = vbHeight;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
releaseCachedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "bbWidth")
|
@ReactProp(name = "bbWidth")
|
||||||
public void setVbWidth(String bbWidth) {
|
public void setVbWidth(String bbWidth) {
|
||||||
mbbWidth = bbWidth;
|
mbbWidth = bbWidth;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
releaseCachedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "bbHeight")
|
@ReactProp(name = "bbHeight")
|
||||||
public void setVbHeight(String bbHeight) {
|
public void setVbHeight(String bbHeight) {
|
||||||
mbbHeight = bbHeight;
|
mbbHeight = bbHeight;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
releaseCachedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "align")
|
@ReactProp(name = "align")
|
||||||
public void setAlign(String align) {
|
public void setAlign(String align) {
|
||||||
mAlign = align;
|
mAlign = align;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
releaseCachedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "meetOrSlice")
|
@ReactProp(name = "meetOrSlice")
|
||||||
public void setMeetOrSlice(int meetOrSlice) {
|
public void setMeetOrSlice(int meetOrSlice) {
|
||||||
mMeetOrSlice = meetOrSlice;
|
mMeetOrSlice = meetOrSlice;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
releaseCachedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,6 +154,7 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bitmap drawOutput() {
|
Bitmap drawOutput() {
|
||||||
|
mRendered = true;
|
||||||
float width = getLayoutWidth();
|
float width = getLayoutWidth();
|
||||||
float height = getLayoutHeight();
|
float height = getLayoutHeight();
|
||||||
boolean early = Float.isNaN(width) || Float.isNaN(height) || width * height == 0 || (Math.log10(width) + Math.log10(height) > 42);
|
boolean early = Float.isNaN(width) || Float.isNaN(height) || width * height == 0 || (Math.log10(width) + Math.log10(height) > 42);
|
||||||
|
|||||||
@@ -185,16 +185,6 @@ class TextShadowNode extends GroupShadowNode {
|
|||||||
return mBaselineShift;
|
return mBaselineShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
void releaseCachedPath() {
|
|
||||||
traverseChildren(new NodeRunnable() {
|
|
||||||
public void run(ReactShadowNode node) {
|
|
||||||
if (node instanceof TextShadowNode) {
|
|
||||||
((TextShadowNode)node).releaseCachedPath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Path getGroupPath(Canvas canvas, Paint paint) {
|
Path getGroupPath(Canvas canvas, Paint paint) {
|
||||||
pushGlyphContext();
|
pushGlyphContext();
|
||||||
Path groupPath = super.getPath(canvas, paint);
|
Path groupPath = super.getPath(canvas, paint);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
Matrix mMatrix = new Matrix();
|
Matrix mMatrix = new Matrix();
|
||||||
Matrix mInvMatrix = new Matrix();
|
Matrix mInvMatrix = new Matrix();
|
||||||
boolean mInvertible = true;
|
boolean mInvertible = true;
|
||||||
RectF mClientRect;
|
private RectF mClientRect;
|
||||||
|
|
||||||
private int mClipRule;
|
private int mClipRule;
|
||||||
private @Nullable String mClipPath;
|
private @Nullable String mClipPath;
|
||||||
@@ -99,6 +99,10 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
@Override
|
@Override
|
||||||
public void markUpdated() {
|
public void markUpdated() {
|
||||||
super.markUpdated();
|
super.markUpdated();
|
||||||
|
clearPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearPath() {
|
||||||
canvasHeight = -1;
|
canvasHeight = -1;
|
||||||
canvasWidth = -1;
|
canvasWidth = -1;
|
||||||
mRegion = null;
|
mRegion = null;
|
||||||
@@ -106,6 +110,17 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
mBox = null;
|
mBox = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void releaseCachedPath() {
|
||||||
|
clearPath();
|
||||||
|
traverseChildren(new NodeRunnable() {
|
||||||
|
public void run(ReactShadowNode node) {
|
||||||
|
if (node instanceof VirtualNode) {
|
||||||
|
((VirtualNode)node).releaseCachedPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
GroupShadowNode getTextRoot() {
|
GroupShadowNode getTextRoot() {
|
||||||
VirtualNode node = this;
|
VirtualNode node = this;
|
||||||
@@ -156,7 +171,7 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
public abstract void draw(Canvas canvas, Paint paint, float opacity);
|
public abstract void draw(Canvas canvas, Paint paint, float opacity);
|
||||||
public void render(Canvas canvas, Paint paint, float opacity) {
|
public void render(Canvas canvas, Paint paint, float opacity) {
|
||||||
draw(canvas, paint, opacity);
|
draw(canvas, paint, opacity);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the transform matrix on the canvas before an element is drawn.
|
* Sets up the transform matrix on the canvas before an element is drawn.
|
||||||
|
|||||||
@@ -19,16 +19,18 @@
|
|||||||
NSMutableDictionary<NSString *, RNSVGNode *> *_masks;
|
NSMutableDictionary<NSString *, RNSVGNode *> *_masks;
|
||||||
CGAffineTransform _viewBoxTransform;
|
CGAffineTransform _viewBoxTransform;
|
||||||
CGAffineTransform _invviewBoxTransform;
|
CGAffineTransform _invviewBoxTransform;
|
||||||
|
bool rendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(CGRect)frame
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
if (self = [super initWithFrame:frame]) {
|
if (self = [super initWithFrame:frame]) {
|
||||||
// This is necessary to ensure that [self setNeedsDisplay] actually triggers
|
// This is necessary to ensure that [self setNeedsDisplay] actually triggers
|
||||||
// a redraw when our parent transitions between hidden and visible.
|
// a redraw when our parent transitions between hidden and visible.
|
||||||
self.contentMode = UIViewContentModeRedraw;
|
self.contentMode = UIViewContentModeRedraw;
|
||||||
}
|
}
|
||||||
return self;
|
rendered = false;
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
|
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
|
||||||
@@ -49,6 +51,20 @@
|
|||||||
// Do nothing, as subviews are inserted by insertReactSubview:
|
// Do nothing, as subviews are inserted by insertReactSubview:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)releaseCachedPath
|
||||||
|
{
|
||||||
|
if (!rendered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rendered = false;
|
||||||
|
for (UIView *node in self.subviews) {
|
||||||
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
|
RNSVGNode *n = (RNSVGNode *)node;
|
||||||
|
[n releaseCachedPath];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
- (void)invalidate
|
- (void)invalidate
|
||||||
{
|
{
|
||||||
[self setNeedsDisplay];
|
[self setNeedsDisplay];
|
||||||
@@ -61,6 +77,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
|
[self releaseCachedPath];
|
||||||
_minX = minX;
|
_minX = minX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +88,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
|
[self releaseCachedPath];
|
||||||
_minY = minY;
|
_minY = minY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +99,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
|
[self releaseCachedPath];
|
||||||
_vbWidth = vbWidth;
|
_vbWidth = vbWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,26 +110,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
|
[self releaseCachedPath];
|
||||||
_vbHeight = vbHeight;
|
_vbHeight = vbHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setBBWidth:(NSString *)bbWidth
|
- (void)setBbWidth:(NSString *)bbWidth
|
||||||
{
|
{
|
||||||
if ([bbWidth isEqualToString:_bbWidth]) {
|
if ([bbWidth isEqualToString:_bbWidth]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
|
[self releaseCachedPath];
|
||||||
_bbWidth = bbWidth;
|
_bbWidth = bbWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setBBHeight:(NSString *)bbHeight
|
- (void)setBbHeight:(NSString *)bbHeight
|
||||||
{
|
{
|
||||||
if ([bbHeight isEqualToString:_bbHeight]) {
|
if ([bbHeight isEqualToString:_bbHeight]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
|
[self releaseCachedPath];
|
||||||
_bbHeight = bbHeight;
|
_bbHeight = bbHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +143,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
|
[self releaseCachedPath];
|
||||||
_align = align;
|
_align = align;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +154,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
|
[self releaseCachedPath];
|
||||||
_meetOrSlice = meetOrSlice;
|
_meetOrSlice = meetOrSlice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,6 +184,7 @@
|
|||||||
|
|
||||||
- (void)drawRect:(CGRect)rect
|
- (void)drawRect:(CGRect)rect
|
||||||
{
|
{
|
||||||
|
rendered = true;
|
||||||
_clipPaths = nil;
|
_clipPaths = nil;
|
||||||
_templates = nil;
|
_templates = nil;
|
||||||
_painters = nil;
|
_painters = nil;
|
||||||
|
|||||||
+2
-4
@@ -91,10 +91,6 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
|||||||
|
|
||||||
- (CGFloat)getContextHeight;
|
- (CGFloat)getContextHeight;
|
||||||
|
|
||||||
- (CGFloat)getContextLeft;
|
|
||||||
|
|
||||||
- (CGFloat)getContextTop;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* save element`s reference into svg element.
|
* save element`s reference into svg element.
|
||||||
*/
|
*/
|
||||||
@@ -106,4 +102,6 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
|||||||
|
|
||||||
- (void)traverseSubviews:(BOOL (^)(__kindof UIView *node))block;
|
- (void)traverseSubviews:(BOOL (^)(__kindof UIView *node))block;
|
||||||
|
|
||||||
|
- (void)releaseCachedPath;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
+27
-27
@@ -58,6 +58,11 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
{
|
{
|
||||||
id<RNSVGContainer> container = (id<RNSVGContainer>)self.superview;
|
id<RNSVGContainer> container = (id<RNSVGContainer>)self.superview;
|
||||||
[container invalidate];
|
[container invalidate];
|
||||||
|
[self clearPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)clearPath
|
||||||
|
{
|
||||||
if (_path) {
|
if (_path) {
|
||||||
CGPathRelease(_path);
|
CGPathRelease(_path);
|
||||||
_path = nil;
|
_path = nil;
|
||||||
@@ -123,7 +128,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
if ([name isEqualToString:_name]) {
|
if ([name isEqualToString:_name]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
_name = name;
|
_name = name;
|
||||||
}
|
}
|
||||||
@@ -338,8 +343,9 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
|
|
||||||
- (CGFloat)relativeOnOther:(NSString *)length
|
- (CGFloat)relativeOnOther:(NSString *)length
|
||||||
{
|
{
|
||||||
CGFloat width = [self getContextWidth];
|
CGRect bounds = [self getContextBounds];
|
||||||
CGFloat height = [self getContextHeight];
|
CGFloat width = CGRectGetWidth(bounds);
|
||||||
|
CGFloat height = CGRectGetHeight(bounds);
|
||||||
CGFloat powX = width * width;
|
CGFloat powX = width * width;
|
||||||
CGFloat powY = height * height;
|
CGFloat powY = height * height;
|
||||||
CGFloat r = sqrt(powX + powY) * RNSVG_M_SQRT1_2l;
|
CGFloat r = sqrt(powX + powY) * RNSVG_M_SQRT1_2l;
|
||||||
@@ -350,36 +356,19 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
fontSize:[self getFontSizeFromContext]];
|
fontSize:[self getFontSizeFromContext]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (CGRect)getContextBounds
|
||||||
|
{
|
||||||
|
return CGContextGetClipBoundingBox(UIGraphicsGetCurrentContext());
|
||||||
|
}
|
||||||
|
|
||||||
- (CGFloat)getContextWidth
|
- (CGFloat)getContextWidth
|
||||||
{
|
{
|
||||||
RNSVGGroup * root = self.textRoot;
|
return CGRectGetWidth([self getContextBounds]);
|
||||||
RNSVGGlyphContext * gc = [root getGlyphContext];
|
|
||||||
if (root == nil || gc == nil) {
|
|
||||||
return CGRectGetWidth([self.svgView getContextBounds]);
|
|
||||||
} else {
|
|
||||||
return [gc getWidth];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)getContextHeight
|
- (CGFloat)getContextHeight
|
||||||
{
|
{
|
||||||
RNSVGGroup * root = self.textRoot;
|
return CGRectGetHeight([self getContextBounds]);
|
||||||
RNSVGGlyphContext * gc = [root getGlyphContext];
|
|
||||||
if (root == nil || gc == nil) {
|
|
||||||
return CGRectGetHeight([self.svgView getContextBounds]);
|
|
||||||
} else {
|
|
||||||
return [gc getHeight];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGFloat)getContextLeft
|
|
||||||
{
|
|
||||||
return CGRectGetMinX([self.svgView getContextBounds]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGFloat)getContextTop
|
|
||||||
{
|
|
||||||
return CGRectGetMinY([self.svgView getContextBounds]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)parseReference
|
- (void)parseReference
|
||||||
@@ -399,6 +388,17 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)releaseCachedPath
|
||||||
|
{
|
||||||
|
[self clearPath];
|
||||||
|
[self traverseSubviews:^BOOL(__kindof RNSVGNode *node) {
|
||||||
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
|
[node releaseCachedPath];
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
CGPathRelease(_cachedClipPath);
|
CGPathRelease(_cachedClipPath);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
@property (nonatomic, strong) NSArray<NSString *> *positionY;
|
@property (nonatomic, strong) NSArray<NSString *> *positionY;
|
||||||
@property (nonatomic, strong) NSArray<NSString *> *rotate;
|
@property (nonatomic, strong) NSArray<NSString *> *rotate;
|
||||||
|
|
||||||
- (void)releaseCachedPath;
|
|
||||||
- (CGPathRef)getGroupPath:(CGContextRef)context;
|
- (CGPathRef)getGroupPath:(CGContextRef)context;
|
||||||
- (CTFontRef)getFontFromContext;
|
- (CTFontRef)getFontFromContext;
|
||||||
|
|
||||||
|
|||||||
+6
-12
@@ -124,18 +124,12 @@
|
|||||||
|
|
||||||
- (void)setupGlyphContext:(CGContextRef)context
|
- (void)setupGlyphContext:(CGContextRef)context
|
||||||
{
|
{
|
||||||
_glyphContext = [[RNSVGGlyphContext alloc] initWithScale:1 width:[self getContextWidth]
|
CGRect bounds = CGContextGetClipBoundingBox(context);
|
||||||
height:[self getContextHeight]];
|
CGSize size = bounds.size;
|
||||||
}
|
_glyphContext = [[RNSVGGlyphContext alloc]
|
||||||
|
initWithScale:1
|
||||||
// release the cached CGPathRef for RNSVGTSpan
|
width:size.width
|
||||||
- (void)releaseCachedPath
|
height:size.height];
|
||||||
{
|
|
||||||
[self traverseSubviews:^BOOL(__kindof RNSVGNode *node) {
|
|
||||||
RNSVGText *text = node;
|
|
||||||
[text releaseCachedPath];
|
|
||||||
return YES;
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGPathRef)getGroupPath:(CGContextRef)context
|
- (CGPathRef)getGroupPath:(CGContextRef)context
|
||||||
|
|||||||
Reference in New Issue
Block a user