mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-21 06:15:15 +00:00
Improve coordinate system calculations for font-size, letter-spacing etc.
Fix parsing of transform to account for single parameter scale and translate correctly. Fix skewX, had opposite of intended effect. https://www.w3.org/TR/SVG/coords.html https://www.w3.org/TR/SVG2/coords.html https://www.w3.org/TR/SVGTiny12/coords.html https://www.w3.org/TR/SVG/coords.html#TransformAttribute https://www.w3.org/TR/SVG/coords.html#SkewXDefined
This commit is contained in:
@@ -104,7 +104,7 @@ public class TSpanShadowNode extends TextShadowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Path getLinePath(Canvas canvas, String line, Paint paint) {
|
private Path getLinePath(Canvas canvas, String line, Paint paint) {
|
||||||
ReadableMap font = applyTextPropertiesToPaint(paint);
|
ReadableMap font = applyTextPropertiesToPaint(paint, canvas);
|
||||||
int length = line.length();
|
int length = line.length();
|
||||||
Path path = new Path();
|
Path path = new Path();
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ public class TSpanShadowNode extends TextShadowNode {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReadableMap applyTextPropertiesToPaint(Paint paint) {
|
private ReadableMap applyTextPropertiesToPaint(Paint paint, Canvas canvas) {
|
||||||
ReadableMap font = getFontFromContext();
|
ReadableMap font = getFontFromContext();
|
||||||
|
|
||||||
paint.setTextAlign(Paint.Align.LEFT);
|
paint.setTextAlign(Paint.Align.LEFT);
|
||||||
@@ -217,6 +217,18 @@ public class TSpanShadowNode extends TextShadowNode {
|
|||||||
float ch = getCanvasHeight();
|
float ch = getCanvasHeight();
|
||||||
float heightScale = height / ch;
|
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 fontSize = (float)font.getDouble(PROP_FONT_SIZE) * mScale * heightScale;
|
||||||
float letterSpacing = (float)font.getDouble(PROP_LETTER_SPACING) * mScale * heightScale;
|
float letterSpacing = (float)font.getDouble(PROP_LETTER_SPACING) * mScale * heightScale;
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
private static final float[] sMatrixData = new float[9];
|
private static final float[] sMatrixData = new float[9];
|
||||||
private static final float[] sRawMatrix = new float[9];
|
private static final float[] sRawMatrix = new float[9];
|
||||||
protected float mOpacity = 1f;
|
protected float mOpacity = 1f;
|
||||||
|
protected float mScaleX = 1f;
|
||||||
|
protected float mScaleY = 1f;
|
||||||
protected Matrix mMatrix = new Matrix();
|
protected Matrix mMatrix = new Matrix();
|
||||||
|
|
||||||
private int mClipRule;
|
private int mClipRule;
|
||||||
@@ -109,6 +111,18 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
markUpdated();
|
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")
|
@ReactProp(name = "matrix")
|
||||||
public void setMatrix(@Nullable ReadableArray matrixArray) {
|
public void setMatrix(@Nullable ReadableArray matrixArray) {
|
||||||
if (matrixArray != null) {
|
if (matrixArray != null) {
|
||||||
@@ -134,6 +148,18 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
markUpdated();
|
markUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Matrix getMatrix() {
|
||||||
|
return mMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScaleX() {
|
||||||
|
return mScaleX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScaleY() {
|
||||||
|
return mScaleY;
|
||||||
|
}
|
||||||
|
|
||||||
@ReactProp(name = "responsible", defaultBoolean = false)
|
@ReactProp(name = "responsible", defaultBoolean = false)
|
||||||
public void setResponsible(boolean responsible) {
|
public void setResponsible(boolean responsible) {
|
||||||
mResponsible = responsible;
|
mResponsible = responsible;
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ export default class Matrix2D {
|
|||||||
// TODO: can this be combined into a single append operation?
|
// TODO: can this be combined into a single append operation?
|
||||||
skewX *= DEG_TO_RAD;
|
skewX *= DEG_TO_RAD;
|
||||||
skewY *= 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);
|
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y);
|
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y);
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ const NodeAttributes = {
|
|||||||
matrix: {
|
matrix: {
|
||||||
diff: arrayDiffer
|
diff: arrayDiffer
|
||||||
},
|
},
|
||||||
|
scaleX: true,
|
||||||
|
scaleY: true,
|
||||||
opacity: true,
|
opacity: true,
|
||||||
clipRule: true,
|
clipRule: true,
|
||||||
clipPath: true,
|
clipPath: true,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import extractFill from './extractFill';
|
import extractFill from './extractFill';
|
||||||
import extractStroke from './extractStroke';
|
import extractStroke from './extractStroke';
|
||||||
import extractTransform from './extractTransform';
|
import extractTransform, {props2transform, tp} from './extractTransform';
|
||||||
import extractClipPath from './extractClipPath';
|
import extractClipPath from './extractClipPath';
|
||||||
import extractResponder from './extractResponder';
|
import extractResponder from './extractResponder';
|
||||||
import extractOpacity from './extractOpacity';
|
import extractOpacity from './extractOpacity';
|
||||||
@@ -26,6 +26,23 @@ export default function(props, ref) {
|
|||||||
|
|
||||||
extractedProps.matrix = extractTransform(props);
|
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));
|
Object.assign(extractedProps, extractResponder(props, ref));
|
||||||
|
|
||||||
return extractedProps;
|
return extractedProps;
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ class TransformParser {
|
|||||||
break;
|
break;
|
||||||
case 'translate':
|
case 'translate':
|
||||||
retval.translateX = transLst[i + 1];
|
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;
|
break;
|
||||||
case 'scale':
|
case 'scale':
|
||||||
retval.scaleX = transLst[i + 1];
|
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;
|
break;
|
||||||
case 'rotate':
|
case 'rotate':
|
||||||
retval.rotation = transLst[i + 1];
|
retval.rotation = transLst[i + 1];
|
||||||
@@ -85,7 +85,7 @@ class TransformParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tp = new TransformParser();
|
export const tp = new TransformParser();
|
||||||
|
|
||||||
|
|
||||||
function appendTransform(transform) {
|
function appendTransform(transform) {
|
||||||
@@ -147,7 +147,7 @@ function universal2axis(universal, axisX, axisY, defaultValue) {
|
|||||||
return [x || defaultValue || 0, y || defaultValue || 0];
|
return [x || defaultValue || 0, y || defaultValue || 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
function props2transform(props) {
|
export function props2transform(props) {
|
||||||
if (props && (typeof props === 'string')) {
|
if (props && (typeof props === 'string')) {
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user