fix: marker onPress & gestures

This commit is contained in:
Mikael Sand
2019-10-03 16:49:56 +03:00
parent 0c127dc6bc
commit bff92f0bdf
8 changed files with 63 additions and 28 deletions
@@ -37,6 +37,8 @@ class MarkerView extends GroupView {
String mAlign; String mAlign;
int mMeetOrSlice; int mMeetOrSlice;
Matrix markerTransform = new Matrix();
public MarkerView(ReactContext reactContext) { public MarkerView(ReactContext reactContext) {
super(reactContext); super(reactContext);
} }
@@ -130,21 +132,19 @@ class MarkerView extends GroupView {
void renderMarker(Canvas canvas, Paint paint, float opacity, RNSVGMarkerPosition position, float strokeWidth) { void renderMarker(Canvas canvas, Paint paint, float opacity, RNSVGMarkerPosition position, float strokeWidth) {
int count = saveAndSetupCanvas(canvas, mCTM); int count = saveAndSetupCanvas(canvas, mCTM);
markerTransform.reset();
Point origin = position.origin; Point origin = position.origin;
Matrix transform = new Matrix(); markerTransform.setTranslate((float)origin.x * mScale, (float)origin.y * mScale);
transform.setTranslate((float)origin.x * mScale, (float)origin.y * mScale);
double markerAngle = "auto".equals(mOrient) ? -1 : Double.parseDouble(mOrient); double markerAngle = "auto".equals(mOrient) ? -1 : Double.parseDouble(mOrient);
float degrees = 180 + (float) (markerAngle == -1 ? position.angle : markerAngle); float degrees = 180 + (float) (markerAngle == -1 ? position.angle : markerAngle);
transform.preRotate(degrees); markerTransform.preRotate(degrees);
boolean useStrokeWidth = "strokeWidth".equals(mMarkerUnits); boolean useStrokeWidth = "strokeWidth".equals(mMarkerUnits);
if (useStrokeWidth) { if (useStrokeWidth) {
transform.preScale(strokeWidth, strokeWidth); markerTransform.preScale(strokeWidth, strokeWidth);
} }
canvas.concat(transform);
double width = relativeOnWidth(mMarkerWidth) / mScale; double width = relativeOnWidth(mMarkerWidth) / mScale;
double height = relativeOnHeight(mMarkerHeight) / mScale; double height = relativeOnHeight(mMarkerHeight) / mScale;
RectF eRect = new RectF(0, 0, (float)width, (float)height); RectF eRect = new RectF(0, 0, (float)width, (float)height);
@@ -153,12 +153,14 @@ class MarkerView extends GroupView {
Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice); Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice);
float[] values = new float[9]; float[] values = new float[9];
viewBoxMatrix.getValues(values); viewBoxMatrix.getValues(values);
canvas.scale(values[Matrix.MSCALE_X], values[Matrix.MSCALE_Y]); markerTransform.preScale(values[Matrix.MSCALE_X], values[Matrix.MSCALE_Y]);
} }
double x = relativeOnWidth(mRefX); double x = relativeOnWidth(mRefX);
double y = relativeOnHeight(mRefY); double y = relativeOnHeight(mRefY);
canvas.translate((float)-x, (float)-y); markerTransform.preTranslate((float)-x, (float)-y);
canvas.concat(markerTransform);
drawGroup(canvas, paint, opacity); drawGroup(canvas, paint, opacity);
@@ -12,6 +12,7 @@ package com.horcrux.svg;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.DashPathEffect; import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
@@ -382,24 +383,29 @@ abstract public class RenderableView extends VirtualView {
contextElement = this; contextElement = this;
ArrayList<RNSVGMarkerPosition> positions = RNSVGMarkerPosition.fromPath(elements); ArrayList<RNSVGMarkerPosition> positions = RNSVGMarkerPosition.fromPath(elements);
float width = (float)(this.strokeWidth != null ? relativeOnOther(this.strokeWidth) : 1); float width = (float)(this.strokeWidth != null ? relativeOnOther(this.strokeWidth) : 1);
mMarkerPath = new Path();
for (RNSVGMarkerPosition position : positions) { for (RNSVGMarkerPosition position : positions) {
RNSVGMarkerType type = position.type; RNSVGMarkerType type = position.type;
MarkerView marker = null;
switch (type) { switch (type) {
case kStartMarker: case kStartMarker:
if (markerStart != null) markerStart.renderMarker(canvas, paint, opacity, position, width); marker = markerStart;
break; break;
case kMidMarker: case kMidMarker:
if (markerMid != null) markerMid.renderMarker(canvas, paint, opacity, position, width); marker = markerMid;
break; break;
case kEndMarker: case kEndMarker:
if (markerEnd != null) markerEnd.renderMarker(canvas, paint, opacity, position, width); marker = markerEnd;
break;
default:
break; break;
} }
if (marker == null) {
continue;
}
marker.renderMarker(canvas, paint, opacity, position, width);
Matrix transform = marker.markerTransform;
mMarkerPath.addPath(marker.getPath(canvas, paint), transform);
} }
contextElement = null; contextElement = null;
} }
@@ -520,9 +526,13 @@ abstract public class RenderableView extends VirtualView {
if (mStrokeRegion == null && mStrokePath != null) { if (mStrokeRegion == null && mStrokePath != null) {
mStrokeRegion = getRegion(mStrokePath); mStrokeRegion = getRegion(mStrokePath);
} }
if (mMarkerRegion == null && mMarkerPath != null) {
mMarkerRegion = getRegion(mMarkerPath);
}
if ( if (
(mRegion == null || !mRegion.contains(x, y)) && (mRegion == null || !mRegion.contains(x, y)) &&
(mStrokeRegion == null || !mStrokeRegion.contains(x, y)) (mStrokeRegion == null || !mStrokeRegion.contains(x, y) &&
(mMarkerRegion == null || !mMarkerRegion.contains(x, y)))
) { ) {
return -1; return -1;
} }
@@ -91,8 +91,10 @@ abstract public class VirtualView extends ReactViewGroup {
Path mPath; Path mPath;
Path mFillPath; Path mFillPath;
Path mStrokePath; Path mStrokePath;
Path mMarkerPath;
RectF mBox; RectF mBox;
Region mRegion; Region mRegion;
Region mMarkerRegion;
Region mStrokeRegion; Region mStrokeRegion;
Region mClipRegion; Region mClipRegion;
Path mClipRegionPath; Path mClipRegionPath;
@@ -114,6 +116,7 @@ abstract public class VirtualView extends ReactViewGroup {
canvasWidth = -1; canvasWidth = -1;
fontSize = -1; fontSize = -1;
mStrokeRegion = null; mStrokeRegion = null;
mMarkerRegion = null;
mRegion = null; mRegion = null;
mPath = null; mPath = null;
} }
+1
View File
@@ -140,6 +140,7 @@
if ([node isKindOfClass:[RNSVGNode class]] && ![node isKindOfClass:[RNSVGMask class]]) { if ([node isKindOfClass:[RNSVGNode class]] && ![node isKindOfClass:[RNSVGMask class]]) {
CGAffineTransform transform = CGAffineTransformConcat(node.matrix, node.transforms); CGAffineTransform transform = CGAffineTransformConcat(node.matrix, node.transforms);
CGPathAddPath(path, &transform, [node getPath:context]); CGPathAddPath(path, &transform, [node getPath:context]);
CGPathAddPath(path, &transform, [node markerPath]);
node.dirty = false; node.dirty = false;
} }
return YES; return YES;
+5 -4
View File
@@ -173,8 +173,6 @@ double deg2rad(CGFloat deg) {
transform = CGAffineTransformScale(transform, strokeWidth, strokeWidth); transform = CGAffineTransformScale(transform, strokeWidth, strokeWidth);
} }
CGContextConcatCTM(context, transform);
CGFloat width = [self relativeOnWidth:self.markerWidth]; CGFloat width = [self relativeOnWidth:self.markerWidth];
CGFloat height = [self relativeOnHeight:self.markerHeight]; CGFloat height = [self relativeOnHeight:self.markerHeight];
CGRect eRect = CGRectMake(0, 0, width, height); CGRect eRect = CGRectMake(0, 0, width, height);
@@ -183,12 +181,15 @@ double deg2rad(CGFloat deg) {
eRect:eRect eRect:eRect
align:self.align align:self.align
meetOrSlice:self.meetOrSlice]; meetOrSlice:self.meetOrSlice];
CGContextScaleCTM(context, viewBoxTransform.a, viewBoxTransform.d); transform = CGAffineTransformScale(transform, viewBoxTransform.a, viewBoxTransform.d);
} }
CGFloat x = [self relativeOnWidth:self.refX]; CGFloat x = [self relativeOnWidth:self.refX];
CGFloat y = [self relativeOnHeight:self.refY]; CGFloat y = [self relativeOnHeight:self.refY];
CGContextTranslateCTM(context, -x, -y); transform = CGAffineTransformTranslate(transform, -x, -y);
self.transform = transform;
CGContextConcatCTM(context, transform);
[self renderGroupTo:context rect:eRect]; [self renderGroupTo:context rect:eRect];
+2
View File
@@ -45,8 +45,10 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
@property (nonatomic, assign) BOOL skip; @property (nonatomic, assign) BOOL skip;
@property (nonatomic, assign) CGPathRef path; @property (nonatomic, assign) CGPathRef path;
@property (nonatomic, assign) CGPathRef strokePath; @property (nonatomic, assign) CGPathRef strokePath;
@property (nonatomic, assign) CGPathRef markerPath;
@property (nonatomic, assign) CGRect clientRect; @property (nonatomic, assign) CGRect clientRect;
@property (nonatomic, assign) CGRect pathBounds; @property (nonatomic, assign) CGRect pathBounds;
@property (nonatomic, assign) CGRect markerBounds;
@property (nonatomic, copy) RCTDirectEventBlock onLayout; @property (nonatomic, copy) RCTDirectEventBlock onLayout;
+1
View File
@@ -30,6 +30,7 @@
@property (nonatomic, assign) CGFloat strokeDashoffset; @property (nonatomic, assign) CGFloat strokeDashoffset;
@property (nonatomic, assign) RNSVGVectorEffect vectorEffect; @property (nonatomic, assign) RNSVGVectorEffect vectorEffect;
@property (nonatomic, copy) NSArray<NSString *> *propList; @property (nonatomic, copy) NSArray<NSString *> *propList;
@property (nonatomic, assign) CGPathRef hitArea;
- (void)setHitArea:(CGPathRef)path; - (void)setHitArea:(CGPathRef)path;
+24 -9
View File
@@ -23,7 +23,6 @@
NSArray<RNSVGLength *> *_sourceStrokeDashArray; NSArray<RNSVGLength *> *_sourceStrokeDashArray;
CGFloat *_strokeDashArrayData; CGFloat *_strokeDashArrayData;
CGPathRef _srcHitPath; CGPathRef _srcHitPath;
CGPathRef _hitArea;
} }
static RNSVGRenderable * _contextElement; static RNSVGRenderable * _contextElement;
@@ -311,25 +310,39 @@ UInt32 saturate(CGFloat value) {
_contextElement = self; _contextElement = self;
NSArray<RNSVGMarkerPosition*>* positions = [RNSVGMarkerPosition fromCGPath:path]; NSArray<RNSVGMarkerPosition*>* positions = [RNSVGMarkerPosition fromCGPath:path];
CGFloat width = self.strokeWidth ? [self relativeOnOther:self.strokeWidth] : 1; CGFloat width = self.strokeWidth ? [self relativeOnOther:self.strokeWidth] : 1;
__block CGRect bounds = CGRectNull;
CGMutablePathRef markerPath = CGPathCreateMutable();
for (RNSVGMarkerPosition* position in positions) { for (RNSVGMarkerPosition* position in positions) {
RNSVGMarkerType type = [position type]; RNSVGMarkerType type = [position type];
RNSVGMarker *marker;
switch (type) { switch (type) {
case kStartMarker: case kStartMarker:
[markerStart renderMarker:context rect:*rect position:position strokeWidth:width]; marker = markerStart;
break; break;
case kMidMarker: case kMidMarker:
[markerMid renderMarker:context rect:*rect position:position strokeWidth:width]; marker = markerMid;
break; break;
case kEndMarker: case kEndMarker:
[markerEnd renderMarker:context rect:*rect position:position strokeWidth:width]; marker = markerEnd;
break;
default:
break; break;
} }
if (!marker) {
continue;
}
[marker renderMarker:context rect:*rect position:position strokeWidth:width];
CGAffineTransform transform = marker.transform;
CGPathRef hitArea = marker.hitArea;
CGPathAddPath(markerPath, &transform, hitArea);
CGRect nodeRect = marker.pathBounds;
if (!CGRectIsEmpty(nodeRect)) {
bounds = CGRectUnion(bounds, CGRectApplyAffineTransform(nodeRect, transform));
}
} }
self.markerBounds = bounds;
self.markerPath = markerPath;
_contextElement = nil; _contextElement = nil;
} }
} }
@@ -513,13 +526,15 @@ UInt32 saturate(CGFloat value) {
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix); CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
transformed = CGPointApplyAffineTransform(transformed, self.invTransform); transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
if (!CGRectContainsPoint(self.pathBounds, transformed)) { if (!CGRectContainsPoint(self.pathBounds, transformed) &&
!CGRectContainsPoint(self.markerBounds, transformed)) {
return nil; return nil;
} }
BOOL evenodd = self.fillRule == kRNSVGCGFCRuleEvenodd; BOOL evenodd = self.fillRule == kRNSVGCGFCRuleEvenodd;
if (!CGPathContainsPoint(_hitArea, nil, transformed, evenodd) && if (!CGPathContainsPoint(_hitArea, nil, transformed, evenodd) &&
!CGPathContainsPoint(self.strokePath, nil, transformed, NO)) { !CGPathContainsPoint(self.strokePath, nil, transformed, NO) &&
!CGPathContainsPoint(self.markerPath, nil, transformed, NO)) {
return nil; return nil;
} }