diff --git a/android/src/main/java/com/horcrux/svg/CircleShadowNode.java b/android/src/main/java/com/horcrux/svg/CircleShadowNode.java index d11a9f61..00b88517 100644 --- a/android/src/main/java/com/horcrux/svg/CircleShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/CircleShadowNode.java @@ -45,14 +45,15 @@ public class CircleShadowNode extends RenderableShadowNode { @Override protected Path getPath(Canvas canvas, Paint paint) { Path path = new Path(); - float cx = PropHelper.fromPercentageToFloat(mCx, mCanvasWidth, 0, mScale); - float cy = PropHelper.fromPercentageToFloat(mCy, mCanvasHeight, 0, mScale); + + float cx = relativeOnWidth(mCx); + float cy = relativeOnHeight(mCy); float r; if (PropHelper.isPercentage(mR)) { r = PropHelper.fromPercentageToFloat(mR, 1, 0, 1); - float powX = (float)Math.pow((mCanvasWidth * r), 2); - float powY = (float)Math.pow((mCanvasHeight * r), 2); + float powX = (float)Math.pow((getCanvasWidth() * r), 2); + float powY = (float)Math.pow((getCanvasHeight() * r), 2); r = (float)Math.sqrt(powX + powY) / (float)Math.sqrt(2); } else { r = Float.parseFloat(mR) * mScale; diff --git a/android/src/main/java/com/horcrux/svg/EllipseShadowNode.java b/android/src/main/java/com/horcrux/svg/EllipseShadowNode.java index 120922e4..c4a3532c 100644 --- a/android/src/main/java/com/horcrux/svg/EllipseShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/EllipseShadowNode.java @@ -53,10 +53,10 @@ public class EllipseShadowNode extends RenderableShadowNode { @Override protected Path getPath(Canvas canvas, Paint paint) { Path path = new Path(); - float cx = PropHelper.fromPercentageToFloat(mCx, mCanvasWidth, 0, mScale); - float cy = PropHelper.fromPercentageToFloat(mCy, mCanvasHeight, 0, mScale); - float rx = PropHelper.fromPercentageToFloat(mRx, mCanvasWidth, 0, mScale); - float ry = PropHelper.fromPercentageToFloat(mRy, mCanvasHeight, 0, mScale); + float cx = relativeOnWidth(mCx); + float cy = relativeOnHeight(mCy); + float rx = relativeOnWidth(mRx); + float ry = relativeOnHeight(mRy); RectF oval = new RectF(cx - rx, cy - ry, cx + rx, cy + ry); path.addOval(oval, Path.Direction.CW); diff --git a/android/src/main/java/com/horcrux/svg/GroupShadowNode.java b/android/src/main/java/com/horcrux/svg/GroupShadowNode.java index 57b5462d..86b81e69 100644 --- a/android/src/main/java/com/horcrux/svg/GroupShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/GroupShadowNode.java @@ -27,10 +27,8 @@ public class GroupShadowNode extends RenderableShadowNode { public void draw(final Canvas canvas, final Paint paint, final float opacity) { if (opacity > MIN_OPACITY_FOR_DRAW) { - int count = saveAndSetupCanvas(canvas); clip(canvas, paint); drawGroup(canvas, paint, opacity); - restoreCanvas(canvas, count); } } @@ -39,10 +37,10 @@ public class GroupShadowNode extends RenderableShadowNode { final VirtualNode self = this; traverseChildren(new NodeRunnable() { public boolean run(VirtualNode node) { - node.setupDimensions(canvas); - node.mergeProperties(self, mAttributeList, true); + int count = node.saveAndSetupCanvas(canvas); node.draw(canvas, paint, opacity * mOpacity); + node.restoreCanvas(canvas, count); node.markUpdateSeen(); if (node.isResponsible()) { @@ -63,7 +61,6 @@ public class GroupShadowNode extends RenderableShadowNode { traverseChildren(new NodeRunnable() { public boolean run(VirtualNode node) { - node.setupDimensions(canvas); path.addPath(node.getPath(canvas, paint)); return true; } diff --git a/android/src/main/java/com/horcrux/svg/ImageShadowNode.java b/android/src/main/java/com/horcrux/svg/ImageShadowNode.java index abb3437c..8303c3a2 100644 --- a/android/src/main/java/com/horcrux/svg/ImageShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/ImageShadowNode.java @@ -107,11 +107,8 @@ public class ImageShadowNode extends RenderableShadowNode { @Override public void draw(final Canvas canvas, final Paint paint, final float opacity) { - mPath = getPath(canvas, paint); - if (!mLoading.get()) { final ImageRequest request = ImageRequestBuilder.newBuilderWithSource(mUri).build(); - if (Fresco.getImagePipeline().isInBitmapMemoryCache(request)) { tryRender(request, canvas, paint, opacity * mOpacity); } else { @@ -153,18 +150,15 @@ public class ImageShadowNode extends RenderableShadowNode { @Nonnull private Rect getRect() { - float x = PropHelper.fromPercentageToFloat(mX, mCanvasWidth, 0, mScale); - float y = PropHelper.fromPercentageToFloat(mY, mCanvasHeight, 0, mScale); - float w = PropHelper.fromPercentageToFloat(mW, mCanvasWidth, 0, mScale); - float h = PropHelper.fromPercentageToFloat(mH, mCanvasHeight, 0, mScale); + float x = relativeOnWidth(mX); + float y = relativeOnHeight(mY); + float w = relativeOnWidth(mW); + float h = relativeOnHeight(mH); return new Rect((int) x, (int) y, (int) (x + w), (int) (y + h)); } private void doRender(Canvas canvas, Paint paint, Bitmap bitmap, float opacity) { - final int count = saveAndSetupCanvas(canvas); - canvas.concat(mMatrix); - Paint alphaPaint = new Paint(); alphaPaint.setAlpha((int) (opacity * 255)); @@ -185,17 +179,9 @@ public class ImageShadowNode extends RenderableShadowNode { renderRect = new RectF(0, 0, (int)rectWidth, (int)(rectWidth / mImageRatio)); } - ViewBoxShadowNode viewBox = new ViewBoxShadowNode(); - viewBox.setMinX("0"); - viewBox.setMinY("0"); - viewBox.setVbWidth(renderRect.width() / mScale + ""); - viewBox.setVbHeight(renderRect.height() / mScale + ""); - viewBox.setWidth(rectWidth / mScale + ""); - viewBox.setHeight(rectHeight / mScale + ""); - viewBox.setAlign(mAlign); - viewBox.setMeetOrSlice(mMeetOrSlice); - viewBox.setupDimensions(new Rect(0, 0, (int) rectWidth, (int) rectHeight)); - Matrix transform = viewBox.getTransform(); + RectF vbRect = new RectF(0, 0, renderRect.width() / mScale, renderRect.height() / mScale); + RectF eRect = new RectF(getCanvasLeft(), getCanvasTop(), rectWidth / mScale + getCanvasLeft(), rectHeight / mScale + getCanvasTop()); + Matrix transform = ViewBoxShadowNode.getTransform(vbRect, eRect, mAlign, mMeetOrSlice, false); transform.mapRect(renderRect); Matrix translation = new Matrix(); @@ -205,30 +191,28 @@ public class ImageShadowNode extends RenderableShadowNode { Path clip = new Path(); Path clipPath = getClipPath(canvas, paint); - + Path path = getPath(canvas, paint); if (clipPath != null) { // clip by the common area of clipPath and mPath clip.setFillType(Path.FillType.INVERSE_EVEN_ODD); Path inverseWindingPath = new Path(); inverseWindingPath.setFillType(Path.FillType.INVERSE_WINDING); - inverseWindingPath.addPath(mPath); + inverseWindingPath.addPath(path); inverseWindingPath.addPath(clipPath); Path evenOddPath = new Path(); evenOddPath.setFillType(Path.FillType.EVEN_ODD); - evenOddPath.addPath(mPath); + evenOddPath.addPath(path); evenOddPath.addPath(clipPath); canvas.clipPath(evenOddPath, Region.Op.DIFFERENCE); canvas.clipPath(inverseWindingPath, Region.Op.DIFFERENCE); } else { - canvas.clipPath(mPath, Region.Op.REPLACE); + canvas.clipPath(path, Region.Op.REPLACE); } canvas.drawBitmap(bitmap, null, renderRect, alphaPaint); - restoreCanvas(canvas, count); - markUpdateSeen(); } private void tryRender(ImageRequest request, Canvas canvas, Paint paint, float opacity) { diff --git a/android/src/main/java/com/horcrux/svg/LineShadowNode.java b/android/src/main/java/com/horcrux/svg/LineShadowNode.java index 03470dd0..ce2c0e9a 100644 --- a/android/src/main/java/com/horcrux/svg/LineShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/LineShadowNode.java @@ -51,10 +51,10 @@ public class LineShadowNode extends RenderableShadowNode { @Override protected Path getPath(Canvas canvas, Paint paint) { Path path = new Path(); - float x1 = PropHelper.fromPercentageToFloat(mX1, mCanvasWidth, 0, mScale); - float y1 = PropHelper.fromPercentageToFloat(mY1, mCanvasHeight, 0, mScale); - float x2 = PropHelper.fromPercentageToFloat(mX2, mCanvasWidth, 0, mScale); - float y2 = PropHelper.fromPercentageToFloat(mY2, mCanvasHeight, 0, mScale); + float x1 = relativeOnWidth(mX1); + float y1 = relativeOnHeight(mY1); + float x2 = relativeOnWidth(mX2); + float y2 = relativeOnHeight(mY2); path.moveTo(x1, y1); path.lineTo(x2, y2); diff --git a/android/src/main/java/com/horcrux/svg/RectShadowNode.java b/android/src/main/java/com/horcrux/svg/RectShadowNode.java index 961e0d6d..a6e8bc28 100644 --- a/android/src/main/java/com/horcrux/svg/RectShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RectShadowNode.java @@ -69,12 +69,12 @@ public class RectShadowNode extends RenderableShadowNode { @Override protected Path getPath(Canvas canvas, Paint paint) { Path path = new Path(); - float x = PropHelper.fromPercentageToFloat(mX, mCanvasWidth, 0, mScale); - float y = PropHelper.fromPercentageToFloat(mY, mCanvasHeight, 0, mScale); - float w = PropHelper.fromPercentageToFloat(mW, mCanvasWidth, 0, mScale); - float h = PropHelper.fromPercentageToFloat(mH, mCanvasHeight, 0, mScale); - float rx = PropHelper.fromPercentageToFloat(mRx, mCanvasWidth, 0, mScale); - float ry = PropHelper.fromPercentageToFloat(mRy, mCanvasHeight, 0, mScale); + float x = relativeOnWidth(mX); + float y = relativeOnHeight(mY); + float w = relativeOnWidth(mW); + float h = relativeOnHeight(mH); + float rx = relativeOnWidth(mRx); + float ry = relativeOnHeight(mRy); if (rx != 0 || ry != 0) { if (rx == 0) { diff --git a/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java b/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java index c70a4ed5..d3bd09f6 100644 --- a/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java @@ -201,18 +201,12 @@ abstract public class RenderableShadowNode extends VirtualNode { @Override public void draw(Canvas canvas, Paint paint, float opacity) { - if (mPath == null) { - mPath = getPath(canvas, paint); - mPath.setFillType(mFillRule); - } - opacity *= mOpacity; if (opacity > MIN_OPACITY_FOR_DRAW) { - int count = saveAndSetupCanvas(canvas); if (mPath == null) { - throw new JSApplicationIllegalArgumentException( - "Paths should have a valid path (d) prop"); + mPath = getPath(canvas, paint); + mPath.setFillType(mFillRule); } clip(canvas, paint); @@ -222,9 +216,6 @@ abstract public class RenderableShadowNode extends VirtualNode { if (setupStrokePaint(paint, opacity * mStrokeOpacity, null)) { canvas.drawPath(mPath, paint); } - - restoreCanvas(canvas, count); - markUpdateSeen(); } } @@ -303,39 +294,39 @@ abstract public class RenderableShadowNode extends VirtualNode { return -1; } - Bitmap bitmap = Bitmap.createBitmap( - mCanvasWidth, - mCanvasHeight, - Bitmap.Config.ARGB_8888); - - Canvas canvas = new Canvas(bitmap); - - if (matrix != null) { - canvas.concat(matrix); - } - - canvas.concat(mMatrix); - - Paint paint = new Paint(); - clip(canvas, paint); - setHitTestFill(paint); - canvas.drawPath(mPath, paint); - - if (setHitTestStroke(paint)) { - canvas.drawPath(mPath, paint); - } - - canvas.setBitmap(bitmap); - try { - if (bitmap.getPixel(point.x, point.y) != 0) { - return getReactTag(); - } - } catch (Exception e) { - - return -1; - } finally { - bitmap.recycle(); - } +// Bitmap bitmap = Bitmap.createBitmap( +// mCanvasWidth, +// mCanvasHeight, +// Bitmap.Config.ARGB_8888); +// +// Canvas canvas = new Canvas(bitmap); +// +// if (matrix != null) { +// canvas.concat(matrix); +// } +// +// canvas.concat(mMatrix); +// +// Paint paint = new Paint(); +// clip(canvas, paint); +// setHitTestFill(paint); +// canvas.drawPath(mPath, paint); +// +// if (setHitTestStroke(paint)) { +// canvas.drawPath(mPath, paint); +// } +// +// canvas.setBitmap(bitmap); +// try { +// if (bitmap.getPixel(point.x, point.y) != 0) { +// return getReactTag(); +// } +// } catch (Exception e) { +// +// return -1; +// } finally { +// bitmap.recycle(); +// } return -1; } @@ -377,15 +368,14 @@ abstract public class RenderableShadowNode extends VirtualNode { String fieldName = mergeList.getString(i); Field field = getClass().getField(fieldName); Object value = field.get(target); + mOriginProperties.add(field.get(this)); if (inherited) { if (!hasOwnProperty(fieldName)) { mAttributeList.pushString(fieldName); - mOriginProperties.add(field.get(this)); field.set(this, value); } } else { - mOriginProperties.add(field.get(this)); field.set(this, value); } } catch (Exception e) { diff --git a/android/src/main/java/com/horcrux/svg/SvgViewShadowNode.java b/android/src/main/java/com/horcrux/svg/SvgViewShadowNode.java index 4e63d818..2ad43b94 100644 --- a/android/src/main/java/com/horcrux/svg/SvgViewShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/SvgViewShadowNode.java @@ -13,6 +13,8 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.SurfaceTexture; import android.support.annotation.Nullable; import android.util.Base64; @@ -42,6 +44,7 @@ public class SvgViewShadowNode extends LayoutShadowNode { private final Map mDefinedClipPaths = new HashMap<>(); private final Map mDefinedTemplates = new HashMap<>(); private final Map mDefinedBrushes = new HashMap<>(); + private Canvas mCanvas; @Override public boolean isVirtual() { @@ -71,12 +74,18 @@ public class SvgViewShadowNode extends LayoutShadowNode { (int) getLayoutHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - drawChildren(canvas); + mCanvas = new Canvas(bitmap); + drawChildren(mCanvas); + mCanvas = null; return bitmap; } + public Rect getCanvasBounds() { + return mCanvas.getClipBounds(); + } + private void drawChildren(Canvas canvas) { + canvas.getClipBounds(); canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); Paint paint = new Paint(); @@ -86,9 +95,11 @@ public class SvgViewShadowNode extends LayoutShadowNode { } VirtualNode child = (VirtualNode) getChildAt(i); - child.setupDimensions(canvas); child.saveDefinition(); + + int count = child.saveAndSetupCanvas(canvas); child.draw(canvas, paint, 1f); + child.restoreCanvas(canvas, count); child.markUpdateSeen(); if (child.isResponsible() && !mResponsible) { diff --git a/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java b/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java index d16c9631..005fcfbb 100644 --- a/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java @@ -75,8 +75,6 @@ public class TSpanShadowNode extends TextShadowNode { } setupTextPath(); - setupDimensions(canvas); - Path path = new Path(); pushGlyphContext(); diff --git a/android/src/main/java/com/horcrux/svg/TextPathShadowNode.java b/android/src/main/java/com/horcrux/svg/TextPathShadowNode.java index b852618b..0da0afee 100644 --- a/android/src/main/java/com/horcrux/svg/TextPathShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/TextPathShadowNode.java @@ -51,8 +51,7 @@ public class TextPathShadowNode extends TextShadowNode { } PathShadowNode path = (PathShadowNode)template; - - return new BezierTransformer(path.getBezierCurves(), PropHelper.fromPercentageToFloat(mStartOffset, mCanvasWidth, 0, mScale)); + return new BezierTransformer(path.getBezierCurves(), relativeOnWidth(mStartOffset)); } @Override diff --git a/android/src/main/java/com/horcrux/svg/TextShadowNode.java b/android/src/main/java/com/horcrux/svg/TextShadowNode.java index 09c58291..f9214b9c 100644 --- a/android/src/main/java/com/horcrux/svg/TextShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/TextShadowNode.java @@ -90,42 +90,30 @@ public class TextShadowNode extends GroupShadowNode { @Override public void draw(Canvas canvas, Paint paint, float opacity) { if (opacity > MIN_OPACITY_FOR_DRAW) { + setupGlyphContext(); clip(canvas, paint); - - int count = canvas.save(); - setupGlyphContext(canvas); - Path path = getGroupPath(canvas, paint); Matrix matrix = getAlignMatrix(path); canvas.concat(matrix); drawGroup(canvas, paint, opacity); releaseCachedPath(); - - mPath = path; - restoreCanvas(canvas, count); - markUpdateSeen(); } } @Override protected Path getPath(Canvas canvas, Paint paint) { - setupGlyphContext(canvas); + setupGlyphContext(); Path groupPath = getGroupPath(canvas, paint); Matrix matrix = getAlignMatrix(groupPath); - groupPath.transform(mMatrix); groupPath.transform(matrix); releaseCachedPath(); return groupPath; } - @Override protected void drawGroup(Canvas canvas, Paint paint, float opacity) { pushGlyphContext(); - int count = canvas.save(); - canvas.concat(mMatrix); super.drawGroup(canvas, paint, opacity); - restoreCanvas(canvas, count); popGlyphContext(); } @@ -170,9 +158,8 @@ public class TextShadowNode extends GroupShadowNode { return mTextRoot; } - protected void setupGlyphContext(Canvas canvas) { - setupDimensions(canvas); - mGlyphContext = new GlyphContext(mScale, mCanvasWidth, mCanvasHeight); + protected void setupGlyphContext() { + mGlyphContext = new GlyphContext(mScale, getCanvasWidth(), getCanvasHeight()); } protected void releaseCachedPath() { diff --git a/android/src/main/java/com/horcrux/svg/UseShadowNode.java b/android/src/main/java/com/horcrux/svg/UseShadowNode.java index 40931d00..14a4ac70 100644 --- a/android/src/main/java/com/horcrux/svg/UseShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/UseShadowNode.java @@ -57,15 +57,12 @@ public class UseShadowNode extends RenderableShadowNode { VirtualNode template = getSvgShadowNode().getDefinedTemplate(mHref); if (template != null) { - int count = saveAndSetupCanvas(canvas); - - clip(canvas, paint); template.mergeProperties(this, mAttributeList, true); + int count = template.saveAndSetupCanvas(canvas); + clip(canvas, paint); template.draw(canvas, paint, opacity * mOpacity); + template.restoreCanvas(canvas, count); template.resetProperties(); - - restoreCanvas(canvas, count); - markUpdateSeen(); } else { FLog.w(ReactConstants.TAG, "`Use` element expected a pre-defined svg template as `href` prop, " + "template named: " + mHref + " is not defined."); diff --git a/android/src/main/java/com/horcrux/svg/ViewBoxShadowNode.java b/android/src/main/java/com/horcrux/svg/ViewBoxShadowNode.java index deadb22b..3dbc2230 100644 --- a/android/src/main/java/com/horcrux/svg/ViewBoxShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/ViewBoxShadowNode.java @@ -12,6 +12,7 @@ package com.horcrux.svg; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; +import android.graphics.RectF; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.annotations.ReactProp; @@ -85,26 +86,42 @@ public class ViewBoxShadowNode extends GroupShadowNode { } @Override - public void draw(Canvas canvas, Paint paint, float opacity) { - setupDimensions(canvas); - mMatrix = getTransform(); - super.draw(canvas, paint, opacity); + protected int saveAndSetupCanvas(Canvas canvas) { + mMatrix = getTransformFromProps(); + return super.saveAndSetupCanvas(canvas); } - public Matrix getTransform() { + private Matrix getTransformFromProps() { + + float vbX = relativeOnWidth(mMinX); + float vbY = relativeOnHeight(mMinY); + float vbWidth = relativeOnWidth(mVbWidth); + float vbHeight = relativeOnHeight(mVbHeight); + + + float eX = getCanvasLeft(); + float eY = getCanvasTop(); + float eWidth = mBoxWidth != null ? relativeOnWidth(mBoxWidth) : getCanvasWidth(); + float eHeight = mBoxHeight != null ? relativeOnHeight(mBoxHeight) : getCanvasHeight(); + + return getTransform(new RectF(vbX, vbY, vbWidth + vbX, vbHeight + vbY), new RectF(eX, eY, eWidth + eX, eHeight + eY), mAlign, mMeetOrSlice, mFromSymbol); + } + + static public Matrix getTransform(RectF vbRect, RectF eRect, String align, int meetOrSlice, boolean fromSymbol) { // based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform // Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the viewBox attribute respectively. - float vbX = PropHelper.fromPercentageToFloat(mMinX, mCanvasWidth, 0, mScale); - float vbY = PropHelper.fromPercentageToFloat(mMinY, mCanvasHeight, 0, mScale); - float vbWidth = PropHelper.fromPercentageToFloat(mVbWidth, mCanvasWidth, 0, mScale); - float vbHeight = PropHelper.fromPercentageToFloat(mVbHeight, mCanvasHeight, 0, mScale); + float vbX = vbRect.left; + float vbY = vbRect.top; + float vbWidth = vbRect.width(); + float vbHeight = vbRect.height(); // Let e-x, e-y, e-width, e-height be the position and size of the element respectively. - float eX = mCanvasX; - float eY = mCanvasY; - float eWidth = mBoxWidth != null ? PropHelper.fromPercentageToFloat(mBoxWidth, mCanvasWidth, 0, mScale) : mCanvasWidth; - float eHeight = mBoxHeight != null ? PropHelper.fromPercentageToFloat(mBoxHeight, mCanvasHeight, 0, mScale) : mCanvasHeight; + float eX = eRect.left; + float eY = eRect.top; + float eWidth = eRect.width(); + float eHeight = eRect.height(); + // Initialize scale-x to e-width/vb-width. float scaleX = eWidth / vbWidth; @@ -118,7 +135,7 @@ public class ViewBoxShadowNode extends GroupShadowNode { float translateY = vbY - eY; // If align is 'none' - if (mMeetOrSlice == MOS_NONE) { + if (meetOrSlice == MOS_NONE) { // Let scale be set the smaller value of scale-x and scale-y. // Assign scale-x and scale-y to scale. float scale = scaleX = scaleY = Math.min(scaleX, scaleY); @@ -137,29 +154,29 @@ public class ViewBoxShadowNode extends GroupShadowNode { // If align is not 'none' and meetOrSlice is 'meet', set the larger of scale-x and scale-y to the smaller. // Otherwise, if align is not 'none' and meetOrSlice is 'slice', set the smaller of scale-x and scale-y to the larger. - if (!mAlign.equals("none") && mMeetOrSlice == MOS_MEET) { + if (!align.equals("none") && meetOrSlice == MOS_MEET) { scaleX = scaleY = Math.min(scaleX, scaleY); - } else if (!mAlign.equals("none") && mMeetOrSlice == MOS_SLICE) { + } else if (!align.equals("none") && meetOrSlice == MOS_SLICE) { scaleX = scaleY = Math.max(scaleX, scaleY); } // If align contains 'xMid', minus (e-width / scale-x - vb-width) / 2 from transform-x. - if (mAlign.contains("xMid")) { + if (align.contains("xMid")) { translateX -= (eWidth / scaleX - vbWidth) / 2; } // If align contains 'xMax', minus (e-width / scale-x - vb-width) from transform-x. - if (mAlign.contains("xMax")) { + if (align.contains("xMax")) { translateX -= eWidth / scaleX - vbWidth; } // If align contains 'yMid', minus (e-height / scale-y - vb-height) / 2 from transform-y. - if (mAlign.contains("YMid")) { + if (align.contains("YMid")) { translateY -= (eHeight / scaleY - vbHeight) / 2; } // If align contains 'yMax', minus (e-height / scale-y - vb-height) from transform-y. - if (mAlign.contains("YMax")) { + if (align.contains("YMax")) { translateY -= eHeight / scaleY - vbHeight; } @@ -168,7 +185,7 @@ public class ViewBoxShadowNode extends GroupShadowNode { // The transform applied to content contained by the element is given by // translate(translate-x, translate-y) scale(scale-x, scale-y). Matrix transform = new Matrix(); - transform.postTranslate(-translateX * (mFromSymbol ? scaleX : 1), -translateY * (mFromSymbol ? scaleY : 1)); + transform.postTranslate(-translateX * (fromSymbol ? scaleX : 1), -translateY * (fromSymbol ? scaleY : 1)); transform.postScale(scaleX, scaleY); return transform; } diff --git a/android/src/main/java/com/horcrux/svg/VirtualNode.java b/android/src/main/java/com/horcrux/svg/VirtualNode.java index d22960be..0a5bb928 100644 --- a/android/src/main/java/com/horcrux/svg/VirtualNode.java +++ b/android/src/main/java/com/horcrux/svg/VirtualNode.java @@ -37,23 +37,14 @@ public abstract class VirtualNode extends LayoutShadowNode { protected float mOpacity = 1f; protected Matrix mMatrix = new Matrix(); + private int mClipRule; protected @Nullable String mClipPath; - private static final int PATH_TYPE_CLOSE = 1; - private static final int PATH_TYPE_CURVETO = 3; - private static final int PATH_TYPE_LINETO = 2; - private static final int PATH_TYPE_MOVETO = 0; - private static final int CLIP_RULE_EVENODD = 0; private static final int CLIP_RULE_NONZERO = 1; protected final float mScale; - private int mClipRule; protected boolean mResponsible; - protected int mCanvasX; - protected int mCanvasY; - protected int mCanvasWidth; - protected int mCanvasHeight; protected String mName; private SvgViewShadowNode mSvgShadowNode; @@ -78,8 +69,8 @@ public abstract class VirtualNode extends LayoutShadowNode { * * @param canvas the canvas to set up */ - protected final int saveAndSetupCanvas(Canvas canvas) { - final int count = canvas.save(); + protected int saveAndSetupCanvas(Canvas canvas) { + int count = canvas.save(); canvas.concat(mMatrix); return count; } @@ -124,7 +115,16 @@ public abstract class VirtualNode extends LayoutShadowNode { if (matrixArray != null) { int matrixSize = PropHelper.toFloatArray(matrixArray, sMatrixData); if (matrixSize == 6) { - setupMatrix(); + sRawMatrix[0] = sMatrixData[0]; + sRawMatrix[1] = sMatrixData[2]; + sRawMatrix[2] = sMatrixData[4] * mScale; + sRawMatrix[3] = sMatrixData[1]; + sRawMatrix[4] = sMatrixData[3]; + sRawMatrix[5] = sMatrixData[5] * mScale; + sRawMatrix[6] = 0; + sRawMatrix[7] = 0; + sRawMatrix[8] = 1; + mMatrix.setValues(sRawMatrix); } else if (matrixSize != -1) { FLog.w(ReactConstants.TAG, "RNSVG: Transform matrices must be of size 6"); } @@ -141,19 +141,6 @@ public abstract class VirtualNode extends LayoutShadowNode { markUpdated(); } - protected void setupMatrix() { - sRawMatrix[0] = sMatrixData[0]; - sRawMatrix[1] = sMatrixData[2]; - sRawMatrix[2] = sMatrixData[4] * mScale; - sRawMatrix[3] = sMatrixData[1]; - sRawMatrix[4] = sMatrixData[3]; - sRawMatrix[5] = sMatrixData[5] * mScale; - sRawMatrix[6] = 0; - sRawMatrix[7] = 0; - sRawMatrix[8] = 1; - mMatrix.setValues(sRawMatrix); - } - protected @Nullable Path getClipPath(Canvas canvas, Paint paint) { if (mClipPath != null) { VirtualNode node = getSvgShadowNode().getDefinedClipPath(mClipPath); @@ -169,7 +156,6 @@ public abstract class VirtualNode extends LayoutShadowNode { default: FLog.w(ReactConstants.TAG, "RNSVG: clipRule: " + mClipRule + " unrecognized"); } - return clipPath; } else { FLog.w(ReactConstants.TAG, "RNSVG: Undefined clipPath: " + mClipPath); @@ -206,26 +192,39 @@ public abstract class VirtualNode extends LayoutShadowNode { ReactShadowNode parent = getParent(); - while (!(parent instanceof SvgViewShadowNode)) { - if (parent == null) { - return null; - } else { - parent = parent.getParent(); - } + if (parent instanceof SvgViewShadowNode) { + mSvgShadowNode = (SvgViewShadowNode)parent; + } else if (parent instanceof VirtualNode) { + mSvgShadowNode = ((VirtualNode) parent).getSvgShadowNode(); + } else { + FLog.e(ReactConstants.TAG, "RNSVG: " + getClass().getName() + " should be descendant of a SvgViewShadow."); } - mSvgShadowNode = (SvgViewShadowNode) parent; + return mSvgShadowNode; } - protected void setupDimensions(Canvas canvas) { - setupDimensions(canvas.getClipBounds()); + protected float relativeOnWidth(String position) { + return PropHelper.fromPercentageToFloat(position, getCanvasWidth(), 0, mScale); } - protected void setupDimensions(Rect rect) { - mCanvasX = rect.left; - mCanvasY = rect.top; - mCanvasWidth = rect.width(); - mCanvasHeight = rect.height(); + protected float relativeOnHeight(String position) { + return PropHelper.fromPercentageToFloat(position, getCanvasHeight(), 0, mScale); + } + + protected float getCanvasWidth() { + return getSvgShadowNode().getCanvasBounds().width(); + } + + protected float getCanvasHeight() { + return getSvgShadowNode().getCanvasBounds().height(); + } + + protected float getCanvasLeft() { + return getSvgShadowNode().getCanvasBounds().left; + } + + protected float getCanvasTop() { + return getSvgShadowNode().getCanvasBounds().top; } protected void saveDefinition() {