From ebeb89beb596ad1511664aebfcb8e5962c240f60 Mon Sep 17 00:00:00 2001 From: Mikael Sand Date: Wed, 19 Jul 2017 23:35:34 +0300 Subject: [PATCH] Improve units and fontSize implementation. Implement support for units in strokewidth based on relativeOnOther. --- .../com/horcrux/svg/CircleShadowNode.java | 14 ++------ .../main/java/com/horcrux/svg/PropHelper.java | 5 ++- .../com/horcrux/svg/RenderableShadowNode.java | 11 ++++--- .../java/com/horcrux/svg/VirtualNode.java | 33 ++++++++++++++++--- lib/extract/extractStroke.js | 4 +-- lib/props.js | 2 +- 6 files changed, 44 insertions(+), 25 deletions(-) diff --git a/android/src/main/java/com/horcrux/svg/CircleShadowNode.java b/android/src/main/java/com/horcrux/svg/CircleShadowNode.java index a8a0cf12..50919435 100644 --- a/android/src/main/java/com/horcrux/svg/CircleShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/CircleShadowNode.java @@ -20,13 +20,6 @@ import com.facebook.react.uimanager.annotations.ReactProp; */ public class CircleShadowNode extends RenderableShadowNode { - /* - N[1/Sqrt[2], 36] - The inverse of the square root of 2. - Provide enough digits for the 128-bit IEEE quad (36 significant digits). - */ - private static final double M_SQRT1_2l = 0.707106781186547524400844362104849039; - private String mCx; private String mCy; private String mR; @@ -58,12 +51,9 @@ public class CircleShadowNode extends RenderableShadowNode { float r; if (PropHelper.isPercentage(mR)) { - r = PropHelper.fromRelativeToFloat(mR, 1, 0, 1, paint.getTextSize()); - double powX = Math.pow((getCanvasWidth() * r), 2); - double powY = Math.pow((getCanvasHeight() * r), 2); - r = (float) (Math.sqrt(powX + powY) * M_SQRT1_2l); + r = relativeOnOther(mR); } else { - r = Float.parseFloat(mR) * mScale; + r = Float.parseFloat(mR) * mScale; } path.addCircle(cx, cy, r, Path.Direction.CW); diff --git a/android/src/main/java/com/horcrux/svg/PropHelper.java b/android/src/main/java/com/horcrux/svg/PropHelper.java index 6cc37475..89841a02 100644 --- a/android/src/main/java/com/horcrux/svg/PropHelper.java +++ b/android/src/main/java/com/horcrux/svg/PropHelper.java @@ -72,7 +72,7 @@ class PropHelper { } static private Pattern percentageRegExp = Pattern.compile("^(\\-?\\d+(?:\\.\\d+)?)%$"); - static private Pattern emRegExp = Pattern.compile("^(\\-?\\d+(?:\\.\\d+)?)em$"); + static private Pattern emRegExp = Pattern.compile("^(\\-?\\.?\\d+(?:\\.\\d+)?)em$"); /** * Converts percentage or em string into actual based on a relative number @@ -93,6 +93,9 @@ class PropHelper { if (matched.matches()) { return (float) (Float.valueOf(matched.group(1)) * scale * fontSize); } else { + if (percentage.endsWith("px")) { + percentage = percentage.substring(0, percentage.length() - 2); + } return Float.valueOf(percentage) * scale + offset; } } diff --git a/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java b/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java index 90f16b7c..0e3ed086 100644 --- a/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java @@ -54,7 +54,7 @@ abstract public class RenderableShadowNode extends VirtualNode { public @Nullable ReadableArray mStroke; public @Nullable float[] mStrokeDasharray; - public float mStrokeWidth = 1; + public String mStrokeWidth = "1"; public float mStrokeOpacity = 1; public float mStrokeMiterlimit = 4; public float mStrokeDashoffset = 0; @@ -132,8 +132,8 @@ abstract public class RenderableShadowNode extends VirtualNode { markUpdated(); } - @ReactProp(name = "strokeWidth", defaultFloat = 1f) - public void setStrokeWidth(float strokeWidth) { + @ReactProp(name = "strokeWidth") + public void setStrokeWidth(String strokeWidth) { mStrokeWidth = strokeWidth; markUpdated(); } @@ -235,7 +235,8 @@ abstract public class RenderableShadowNode extends VirtualNode { */ protected boolean setupStrokePaint(Paint paint, float opacity) { paint.reset(); - if (mStrokeWidth == 0 || mStroke == null || mStroke.size() == 0) { + float strokeWidth = relativeOnOther(mStrokeWidth); + if (strokeWidth == 0 || mStroke == null || mStroke.size() == 0) { return false; } @@ -244,7 +245,7 @@ abstract public class RenderableShadowNode extends VirtualNode { paint.setStrokeCap(mStrokeLinecap); paint.setStrokeJoin(mStrokeLinejoin); paint.setStrokeMiter(mStrokeMiterlimit * mScale); - paint.setStrokeWidth(mStrokeWidth * mScale); + paint.setStrokeWidth(strokeWidth); setupPaint(paint, opacity, mStroke); if (mStrokeDasharray != null && mStrokeDasharray.length > 0) { diff --git a/android/src/main/java/com/horcrux/svg/VirtualNode.java b/android/src/main/java/com/horcrux/svg/VirtualNode.java index fe19d942..1a543eba 100644 --- a/android/src/main/java/com/horcrux/svg/VirtualNode.java +++ b/android/src/main/java/com/horcrux/svg/VirtualNode.java @@ -29,6 +29,12 @@ import javax.annotation.Nullable; import static com.horcrux.svg.GlyphContext.DEFAULT_FONT_SIZE; public abstract class VirtualNode extends LayoutShadowNode { + /* + N[1/Sqrt[2], 36] + The inverse of the square root of 2. + Provide enough digits for the 128-bit IEEE quad (36 significant digits). + */ + private static final double M_SQRT1_2l = 0.707106781186547524400844362104849039; protected static final float MIN_OPACITY_FOR_DRAW = 0.01f; @@ -37,6 +43,8 @@ public abstract class VirtualNode extends LayoutShadowNode { protected float mOpacity = 1f; protected float mScaleX = 1f; protected float mScaleY = 1f; + protected double mFontSize = -1; + protected double mParentFontSize = -1; protected Matrix mMatrix = new Matrix(); private int mClipRule; @@ -126,19 +134,29 @@ public abstract class VirtualNode extends LayoutShadowNode { } double getFontSizeFromContext() { + if (mFontSize != -1) { + return mFontSize; + } GroupShadowNode root = getTextRoot(); if (root == null) { - return DEFAULT_FONT_SIZE; + mFontSize = DEFAULT_FONT_SIZE; + } else { + mFontSize = root.getGlyphContext().getFontSize(); } - return root.getGlyphContext().getFontSize(); + return mFontSize; } double getFontSizeFromParentContext() { + if (mParentFontSize != -1) { + return mParentFontSize; + } GroupShadowNode root = getParentTextRoot(); if (root == null) { - return DEFAULT_FONT_SIZE; + mParentFontSize = DEFAULT_FONT_SIZE; + } else { + mParentFontSize = root.getGlyphContext().getFontSize(); } - return root.getGlyphContext().getFontSize(); + return mParentFontSize; } public abstract void draw(Canvas canvas, Paint paint, float opacity); @@ -318,6 +336,13 @@ public abstract class VirtualNode extends LayoutShadowNode { return PropHelper.fromRelativeToFloat(length, getCanvasHeight(), 0, mScale, getFontSizeFromContext()); } + protected float relativeOnOther(String length) { + double powX = Math.pow((getCanvasWidth()), 2); + double powY = Math.pow((getCanvasHeight()), 2); + float r = (float) (Math.sqrt(powX + powY) * M_SQRT1_2l); + return PropHelper.fromRelativeToFloat(length, r, 0, mScale, getFontSizeFromContext()); + } + protected float getCanvasWidth() { return getSvgShadowNode().getCanvasBounds().width(); } diff --git a/lib/extract/extractStroke.js b/lib/extract/extractStroke.js index 270f76db..a4c1ebdc 100644 --- a/lib/extract/extractStroke.js +++ b/lib/extract/extractStroke.js @@ -26,7 +26,7 @@ export default function(props, styleProperties) { }); const {stroke} = props; - const strokeWidth = +props.strokeWidth; + const strokeWidth = props.strokeWidth; let strokeDasharray = props.strokeDasharray; if (typeof strokeDasharray === 'string') { @@ -44,7 +44,7 @@ export default function(props, styleProperties) { strokeLinecap: caps[props.strokeLinecap] || 0, strokeLinejoin: joins[props.strokeLinejoin] || 0, strokeDasharray: strokeDasharray || null, - strokeWidth: strokeWidth || null, + strokeWidth: strokeWidth || "1", strokeDashoffset: strokeDasharray ? (+props.strokeDashoffset || 0) : null, strokeMiterlimit: props.strokeMiterlimit || 4 }; diff --git a/lib/props.js b/lib/props.js index b5b4ea42..6e8d6bdb 100644 --- a/lib/props.js +++ b/lib/props.js @@ -39,7 +39,7 @@ const definationProps = { const strokeProps = { stroke: PropTypes.string, - strokeWidth: numberProp, + strokeWidth: PropTypes.string, strokeOpacity: numberProp, strokeDasharray: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.string]), strokeDashoffset: numberProp,