diff --git a/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java b/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java index cec9266a..219616ce 100644 --- a/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java @@ -104,7 +104,7 @@ public class TSpanShadowNode extends TextShadowNode { } private Path getLinePath(Canvas canvas, String line, Paint paint) { - ReadableMap font = applyTextPropertiesToPaint(paint); + ReadableMap font = applyTextPropertiesToPaint(paint, canvas); int length = line.length(); Path path = new Path(); @@ -207,7 +207,7 @@ public class TSpanShadowNode extends TextShadowNode { return path; } - private ReadableMap applyTextPropertiesToPaint(Paint paint) { + private ReadableMap applyTextPropertiesToPaint(Paint paint, Canvas canvas) { ReadableMap font = getFontFromContext(); paint.setTextAlign(Paint.Align.LEFT); @@ -217,6 +217,18 @@ public class TSpanShadowNode extends TextShadowNode { float ch = getCanvasHeight(); float heightScale = height / ch; + SvgViewShadowNode svg = getSvgShadowNode(); + ReactShadowNode node = this; + while (node != null && !node.equals(svg)) { + + if (node instanceof VirtualNode) { + VirtualNode v = ((VirtualNode) node); + heightScale /= v.getScaleY(); + } + + node = node.getParent(); + } + float fontSize = (float)font.getDouble(PROP_FONT_SIZE) * mScale * heightScale; float letterSpacing = (float)font.getDouble(PROP_LETTER_SPACING) * mScale * heightScale; diff --git a/android/src/main/java/com/horcrux/svg/VirtualNode.java b/android/src/main/java/com/horcrux/svg/VirtualNode.java index a2635e8c..c0737b9d 100644 --- a/android/src/main/java/com/horcrux/svg/VirtualNode.java +++ b/android/src/main/java/com/horcrux/svg/VirtualNode.java @@ -33,6 +33,8 @@ public abstract class VirtualNode extends LayoutShadowNode { private static final float[] sMatrixData = new float[9]; private static final float[] sRawMatrix = new float[9]; protected float mOpacity = 1f; + protected float mScaleX = 1f; + protected float mScaleY = 1f; protected Matrix mMatrix = new Matrix(); private int mClipRule; @@ -109,6 +111,18 @@ public abstract class VirtualNode extends LayoutShadowNode { markUpdated(); } + @ReactProp(name = "scaleX", defaultFloat = 1f) + public void setScaleX(float scaleX) { + mScaleX = scaleX; + markUpdated(); + } + + @ReactProp(name = "scaleY", defaultFloat = 1f) + public void setScaleY(float scaleY) { + mScaleY = scaleY; + markUpdated(); + } + @ReactProp(name = "matrix") public void setMatrix(@Nullable ReadableArray matrixArray) { if (matrixArray != null) { @@ -134,6 +148,18 @@ public abstract class VirtualNode extends LayoutShadowNode { markUpdated(); } + public Matrix getMatrix() { + return mMatrix; + } + + public float getScaleX() { + return mScaleX; + } + + public float getScaleY() { + return mScaleY; + } + @ReactProp(name = "responsible", defaultBoolean = false) public void setResponsible(boolean responsible) { mResponsible = responsible; diff --git a/lib/Matrix2D.js b/lib/Matrix2D.js index e9760796..1fba91c0 100644 --- a/lib/Matrix2D.js +++ b/lib/Matrix2D.js @@ -215,7 +215,7 @@ export default class Matrix2D { // TODO: can this be combined into a single append operation? skewX *= DEG_TO_RAD; skewY *= DEG_TO_RAD; - this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y); + this.append(Math.cos(skewY), Math.sin(skewY), Math.sin(skewX), Math.cos(skewX), x, y); this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, 0, 0); } else { this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y); diff --git a/lib/attributes.js b/lib/attributes.js index 68cb285a..5185a53e 100644 --- a/lib/attributes.js +++ b/lib/attributes.js @@ -42,6 +42,8 @@ const NodeAttributes = { matrix: { diff: arrayDiffer }, + scaleX: true, + scaleY: true, opacity: true, clipRule: true, clipPath: true, diff --git a/lib/extract/extractProps.js b/lib/extract/extractProps.js index c632eb63..1fd574b0 100644 --- a/lib/extract/extractProps.js +++ b/lib/extract/extractProps.js @@ -1,6 +1,6 @@ import extractFill from './extractFill'; import extractStroke from './extractStroke'; -import extractTransform from './extractTransform'; +import extractTransform, {props2transform, tp} from './extractTransform'; import extractClipPath from './extractClipPath'; import extractResponder from './extractResponder'; import extractOpacity from './extractOpacity'; @@ -26,6 +26,23 @@ export default function(props, ref) { extractedProps.matrix = extractTransform(props); + Object.assign(extractedProps, props2transform(props)); + let transform = props.transform; + if (transform) { + if (typeof transform === 'string') { + var transformParsed = tp.parse(transform); + if (transformParsed.matrix) { + // TODO: Extract scaling values for coordinate system + // Especially scaleY for calculating scaling of fontSize + } else { + let trans = props2transform(transformParsed); + if (typeof trans === 'object') { + Object.assign(extractedProps, trans); + } + } + } + } + Object.assign(extractedProps, extractResponder(props, ref)); return extractedProps; diff --git a/lib/extract/extractTransform.js b/lib/extract/extractTransform.js index afaa8aeb..1b0ab535 100644 --- a/lib/extract/extractTransform.js +++ b/lib/extract/extractTransform.js @@ -50,11 +50,11 @@ class TransformParser { break; case 'translate': retval.translateX = transLst[i + 1]; - retval.translateY = (i + 2 <= transLst.length) ? transLst[i + 2] : 0; + retval.translateY = (3 === transLst.length) ? transLst[i + 2] : 0; break; case 'scale': retval.scaleX = transLst[i + 1]; - retval.scaleY = (i + 2 <= transLst.length) ? transLst[i + 2] : retval.scaleX; + retval.scaleY = (3 === transLst.length) ? transLst[i + 2] : retval.scaleX; break; case 'rotate': retval.rotation = transLst[i + 1]; @@ -85,7 +85,7 @@ class TransformParser { } } -const tp = new TransformParser(); +export const tp = new TransformParser(); function appendTransform(transform) { @@ -147,7 +147,7 @@ function universal2axis(universal, axisX, axisY, defaultValue) { return [x || defaultValue || 0, y || defaultValue || 0]; } -function props2transform(props) { +export function props2transform(props) { if (props && (typeof props === 'string')) { return props; }