Skip to content

Commit

Permalink
feat(android): implement marker rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
msand committed Sep 29, 2019
1 parent 589363d commit ceee5ff
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 7 deletions.
50 changes: 45 additions & 5 deletions android/src/main/java/com/horcrux/svg/MarkerView.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
package com.horcrux.svg;

import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;

import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReactContext;
Expand Down Expand Up @@ -109,16 +113,52 @@ public void setMeetOrSlice(int meetOrSlice) {
invalidate();
}


RectF getViewBox() {
return new RectF(mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale);
}

@Override
void saveDefinition() {
if (mName != null) {
SvgView svg = getSvgView();
svg.defineMarker(this, mName);
for (int i = 0; i < getChildCount(); i++) {
View node = getChildAt(i);
if (node instanceof VirtualView) {
((VirtualView)node).saveDefinition();
}
}
}
}

void renderMarker(Canvas canvas, Paint paint, float opacity, RNSVGMarkerPosition position, float strokeWidth) {
int count = saveAndSetupCanvas(canvas, mCTM);

Point origin = position.origin;
Matrix transform = new Matrix();
transform.setTranslate((float)origin.x, (float)origin.y);

double markerAngle = "auto".equals(mOrient) ? -1 : Double.parseDouble(mOrient);
transform.postRotate((float)(markerAngle == -1 ? position.angle : markerAngle));

boolean useStrokeWidth = "strokeWidth".equals(mMarkerUnits);
if (useStrokeWidth) {
transform.postScale(strokeWidth, strokeWidth);
}

canvas.concat(transform);

double width = relativeOnWidth(mMarkerWidth) / mScale;
double height = relativeOnHeight(mMarkerHeight) / mScale;
RectF eRect = new RectF(0, 0, (float)width, (float)height);
if (mAlign != null) {
RectF vbRect = new RectF(mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale);
Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice);
canvas.concat(viewBoxMatrix);
}

double x = relativeOnWidth(mRefX);
double y = relativeOnHeight(mRefY);
canvas.translate((float)-x, (float)-y);

drawGroup(canvas, paint, opacity);

restoreCanvas(canvas, count);
}
}
19 changes: 19 additions & 0 deletions android/src/main/java/com/horcrux/svg/PathParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@
import android.graphics.Path;
import android.graphics.RectF;

import java.util.ArrayList;

class PathElement {
ElementType type;
Point[] points;
PathElement(ElementType type, Point[] points) {
this.type = type;
this.points = points;
}
}

class PathParser {
static float mScale;

private static int i;
private static int l;
private static String s;
private static Path mPath;
static ArrayList<PathElement> elements;

private static float mPenX;
private static float mPenY;
Expand All @@ -20,6 +32,7 @@ class PathParser {
private static boolean mPenDown;

static Path parse(String d) {
elements = new ArrayList<>();
char prev_cmd = ' ';
mPath = new Path();
l = d.length();
Expand Down Expand Up @@ -189,6 +202,7 @@ private static void moveTo(float x, float y) {
mPenDownX = mPivotX = mPenX = x;
mPenDownY = mPivotY = mPenY = y;
mPath.moveTo(x * mScale, y * mScale);
elements.add(new PathElement(ElementType.kCGPathElementMoveToPoint, new Point[]{new Point(x,y)}));
}

private static void line(float x, float y) {
Expand All @@ -201,6 +215,7 @@ private static void lineTo(float x, float y) {
mPivotX = mPenX = x;
mPivotY = mPenY = y;
mPath.lineTo(x * mScale, y * mScale);
elements.add(new PathElement(ElementType.kCGPathElementAddLineToPoint, new Point[]{new Point(x,y)}));
}

private static void curve(float c1x, float c1y, float c2x, float c2y, float ex, float ey) {
Expand All @@ -219,6 +234,7 @@ private static void cubicTo(float c1x, float c1y, float c2x, float c2y, float ex
mPenX = ex;
mPenY = ey;
mPath.cubicTo(c1x * mScale, c1y * mScale, c2x * mScale, c2y * mScale, ex * mScale, ey * mScale);
elements.add(new PathElement(ElementType.kCGPathElementAddCurveToPoint, new Point[]{new Point(c1x, c1y), new Point(c2x, c2y), new Point(ex, ey)}));
}

private static void smoothCurve(float c1x, float c1y, float ex, float ey) {
Expand Down Expand Up @@ -364,6 +380,7 @@ private static void arcTo(float rx, float ry, float rotation, boolean outer, boo
(cy + rx) * mScale);

mPath.arcTo(oval, start, sweep);
elements.add(new PathElement(ElementType.kCGPathElementAddCurveToPoint, new Point[]{new Point(x, y)}));
}
}

Expand All @@ -373,6 +390,7 @@ private static void close() {
mPenY = mPenDownY;
mPenDown = false;
mPath.close();
elements.add(new PathElement(ElementType.kCGPathElementCloseSubpath, new Point[]{new Point(mPenX, mPenY)}));
}
}

Expand Down Expand Up @@ -420,6 +438,7 @@ private static void arcToBezier(float cx, float cy, float rx, float ry, float sa
float ey = (cy + xy * x + yy * y);

mPath.cubicTo(c1x * mScale, c1y * mScale, c2x * mScale, c2y * mScale, ex * mScale, ey * mScale);
elements.add(new PathElement(ElementType.kCGPathElementAddCurveToPoint, new Point[]{new Point(c1x, c1y), new Point(c2x, c2y), new Point(ex, ey)}));
}
}

Expand Down
1 change: 1 addition & 0 deletions android/src/main/java/com/horcrux/svg/PathView.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public PathView(ReactContext reactContext) {
@ReactProp(name = "d")
public void setD(String d) {
mPath = PathParser.parse(d);
elements = PathParser.elements;
invalidate();
}

Expand Down
30 changes: 29 additions & 1 deletion android/src/main/java/com/horcrux/svg/RenderableView.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
Expand Down Expand Up @@ -370,9 +369,38 @@ void draw(Canvas canvas, Paint paint, float opacity) {
}
canvas.drawPath(path, paint);
}
renderMarkers(canvas, paint, opacity);
}
}

void renderMarkers(Canvas canvas, Paint paint, float opacity) {
MarkerView markerStart = (MarkerView)getSvgView().getDefinedMarker(mMarkerStart);
MarkerView markerMid = (MarkerView)getSvgView().getDefinedMarker(mMarkerMid);
MarkerView markerEnd = (MarkerView)getSvgView().getDefinedMarker(mMarkerEnd);
if (elements != null && (markerStart != null || markerMid != null || markerEnd != null)) {
ArrayList<RNSVGMarkerPosition> positions = RNSVGMarkerPosition.fromPath(elements);
float width = (float)(this.strokeWidth != null ? relativeOnOther(this.strokeWidth) : 1);
for (RNSVGMarkerPosition position : positions) {
RNSVGMarkerType type = position.type;
switch (type) {
case kStartMarker:
if (markerStart != null) markerStart.renderMarker(canvas, paint, opacity, position, width);
break;

case kMidMarker:
if (markerMid != null) markerMid.renderMarker(canvas, paint, opacity, position, width);
break;

case kEndMarker:
if (markerEnd != null) markerEnd.renderMarker(canvas, paint, opacity, position, width);
break;

default:
break;
}
}
}
}
/**
* Sets up paint according to the props set on a view. Returns {@code true}
* if the fill should be drawn, {@code false} if not.
Expand Down
5 changes: 4 additions & 1 deletion android/src/main/java/com/horcrux/svg/VirtualView.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.view.ReactViewGroup;

import java.util.ArrayList;

import javax.annotation.Nullable;

import static com.horcrux.svg.FontData.DEFAULT_FONT_SIZE;
Expand Down Expand Up @@ -94,6 +96,7 @@ abstract public class VirtualView extends ReactViewGroup {
Region mStrokeRegion;
Region mClipRegion;
Path mClipRegionPath;
ArrayList<PathElement> elements;

@Override
public void invalidate() {
Expand Down Expand Up @@ -205,7 +208,7 @@ void render(Canvas canvas, Paint paint, float opacity) {
* drawing code should apply opacity recursively.
*
* @param canvas the canvas to set up
* @param ctm
* @param ctm current transformation matrix
*/
int saveAndSetupCanvas(Canvas canvas, Matrix ctm) {
int count = canvas.save();
Expand Down

0 comments on commit ceee5ff

Please sign in to comment.