Improve units and fontSize implementation.

Implement support for units in strokewidth based on relativeOnOther.
This commit is contained in:
Mikael Sand
2017-07-19 23:35:34 +03:00
parent 3796b6a532
commit ebeb89beb5
6 changed files with 44 additions and 25 deletions
@@ -20,13 +20,6 @@ import com.facebook.react.uimanager.annotations.ReactProp;
*/ */
public class CircleShadowNode extends RenderableShadowNode { 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 mCx;
private String mCy; private String mCy;
private String mR; private String mR;
@@ -58,12 +51,9 @@ public class CircleShadowNode extends RenderableShadowNode {
float r; float r;
if (PropHelper.isPercentage(mR)) { if (PropHelper.isPercentage(mR)) {
r = PropHelper.fromRelativeToFloat(mR, 1, 0, 1, paint.getTextSize()); r = relativeOnOther(mR);
double powX = Math.pow((getCanvasWidth() * r), 2);
double powY = Math.pow((getCanvasHeight() * r), 2);
r = (float) (Math.sqrt(powX + powY) * M_SQRT1_2l);
} else { } else {
r = Float.parseFloat(mR) * mScale; r = Float.parseFloat(mR) * mScale;
} }
path.addCircle(cx, cy, r, Path.Direction.CW); path.addCircle(cx, cy, r, Path.Direction.CW);
@@ -72,7 +72,7 @@ class PropHelper {
} }
static private Pattern percentageRegExp = Pattern.compile("^(\\-?\\d+(?:\\.\\d+)?)%$"); 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 * Converts percentage or em string into actual based on a relative number
@@ -93,6 +93,9 @@ class PropHelper {
if (matched.matches()) { if (matched.matches()) {
return (float) (Float.valueOf(matched.group(1)) * scale * fontSize); return (float) (Float.valueOf(matched.group(1)) * scale * fontSize);
} else { } else {
if (percentage.endsWith("px")) {
percentage = percentage.substring(0, percentage.length() - 2);
}
return Float.valueOf(percentage) * scale + offset; return Float.valueOf(percentage) * scale + offset;
} }
} }
@@ -54,7 +54,7 @@ abstract public class RenderableShadowNode extends VirtualNode {
public @Nullable ReadableArray mStroke; public @Nullable ReadableArray mStroke;
public @Nullable float[] mStrokeDasharray; public @Nullable float[] mStrokeDasharray;
public float mStrokeWidth = 1; public String mStrokeWidth = "1";
public float mStrokeOpacity = 1; public float mStrokeOpacity = 1;
public float mStrokeMiterlimit = 4; public float mStrokeMiterlimit = 4;
public float mStrokeDashoffset = 0; public float mStrokeDashoffset = 0;
@@ -132,8 +132,8 @@ abstract public class RenderableShadowNode extends VirtualNode {
markUpdated(); markUpdated();
} }
@ReactProp(name = "strokeWidth", defaultFloat = 1f) @ReactProp(name = "strokeWidth")
public void setStrokeWidth(float strokeWidth) { public void setStrokeWidth(String strokeWidth) {
mStrokeWidth = strokeWidth; mStrokeWidth = strokeWidth;
markUpdated(); markUpdated();
} }
@@ -235,7 +235,8 @@ abstract public class RenderableShadowNode extends VirtualNode {
*/ */
protected boolean setupStrokePaint(Paint paint, float opacity) { protected boolean setupStrokePaint(Paint paint, float opacity) {
paint.reset(); paint.reset();
if (mStrokeWidth == 0 || mStroke == null || mStroke.size() == 0) { float strokeWidth = relativeOnOther(mStrokeWidth);
if (strokeWidth == 0 || mStroke == null || mStroke.size() == 0) {
return false; return false;
} }
@@ -244,7 +245,7 @@ abstract public class RenderableShadowNode extends VirtualNode {
paint.setStrokeCap(mStrokeLinecap); paint.setStrokeCap(mStrokeLinecap);
paint.setStrokeJoin(mStrokeLinejoin); paint.setStrokeJoin(mStrokeLinejoin);
paint.setStrokeMiter(mStrokeMiterlimit * mScale); paint.setStrokeMiter(mStrokeMiterlimit * mScale);
paint.setStrokeWidth(mStrokeWidth * mScale); paint.setStrokeWidth(strokeWidth);
setupPaint(paint, opacity, mStroke); setupPaint(paint, opacity, mStroke);
if (mStrokeDasharray != null && mStrokeDasharray.length > 0) { if (mStrokeDasharray != null && mStrokeDasharray.length > 0) {
@@ -29,6 +29,12 @@ import javax.annotation.Nullable;
import static com.horcrux.svg.GlyphContext.DEFAULT_FONT_SIZE; import static com.horcrux.svg.GlyphContext.DEFAULT_FONT_SIZE;
public abstract class VirtualNode extends LayoutShadowNode { 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; 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 mOpacity = 1f;
protected float mScaleX = 1f; protected float mScaleX = 1f;
protected float mScaleY = 1f; protected float mScaleY = 1f;
protected double mFontSize = -1;
protected double mParentFontSize = -1;
protected Matrix mMatrix = new Matrix(); protected Matrix mMatrix = new Matrix();
private int mClipRule; private int mClipRule;
@@ -126,19 +134,29 @@ public abstract class VirtualNode extends LayoutShadowNode {
} }
double getFontSizeFromContext() { double getFontSizeFromContext() {
if (mFontSize != -1) {
return mFontSize;
}
GroupShadowNode root = getTextRoot(); GroupShadowNode root = getTextRoot();
if (root == null) { if (root == null) {
return DEFAULT_FONT_SIZE; mFontSize = DEFAULT_FONT_SIZE;
} else {
mFontSize = root.getGlyphContext().getFontSize();
} }
return root.getGlyphContext().getFontSize(); return mFontSize;
} }
double getFontSizeFromParentContext() { double getFontSizeFromParentContext() {
if (mParentFontSize != -1) {
return mParentFontSize;
}
GroupShadowNode root = getParentTextRoot(); GroupShadowNode root = getParentTextRoot();
if (root == null) { 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); 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()); 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() { protected float getCanvasWidth() {
return getSvgShadowNode().getCanvasBounds().width(); return getSvgShadowNode().getCanvasBounds().width();
} }
+2 -2
View File
@@ -26,7 +26,7 @@ export default function(props, styleProperties) {
}); });
const {stroke} = props; const {stroke} = props;
const strokeWidth = +props.strokeWidth; const strokeWidth = props.strokeWidth;
let strokeDasharray = props.strokeDasharray; let strokeDasharray = props.strokeDasharray;
if (typeof strokeDasharray === 'string') { if (typeof strokeDasharray === 'string') {
@@ -44,7 +44,7 @@ export default function(props, styleProperties) {
strokeLinecap: caps[props.strokeLinecap] || 0, strokeLinecap: caps[props.strokeLinecap] || 0,
strokeLinejoin: joins[props.strokeLinejoin] || 0, strokeLinejoin: joins[props.strokeLinejoin] || 0,
strokeDasharray: strokeDasharray || null, strokeDasharray: strokeDasharray || null,
strokeWidth: strokeWidth || null, strokeWidth: strokeWidth || "1",
strokeDashoffset: strokeDasharray ? (+props.strokeDashoffset || 0) : null, strokeDashoffset: strokeDasharray ? (+props.strokeDashoffset || 0) : null,
strokeMiterlimit: props.strokeMiterlimit || 4 strokeMiterlimit: props.strokeMiterlimit || 4
}; };
+1 -1
View File
@@ -39,7 +39,7 @@ const definationProps = {
const strokeProps = { const strokeProps = {
stroke: PropTypes.string, stroke: PropTypes.string,
strokeWidth: numberProp, strokeWidth: PropTypes.string,
strokeOpacity: numberProp, strokeOpacity: numberProp,
strokeDasharray: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.string]), strokeDasharray: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.string]),
strokeDashoffset: numberProp, strokeDashoffset: numberProp,