mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-21 14:25:14 +00:00
Implement correct transform parser (#507)
This commit is contained in:
committed by
Dustin Savery
parent
7ddbf2a73b
commit
f94e17e3be
@@ -1,6 +1,6 @@
|
|||||||
import extractFill from './extractFill';
|
import extractFill from './extractFill';
|
||||||
import extractStroke from './extractStroke';
|
import extractStroke from './extractStroke';
|
||||||
import extractTransform, {props2transform, tp} from './extractTransform';
|
import extractTransform, {props2transform} 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';
|
||||||
@@ -27,21 +27,6 @@ export default function(props, ref) {
|
|||||||
extractedProps.matrix = extractTransform(props);
|
extractedProps.matrix = extractTransform(props);
|
||||||
|
|
||||||
Object.assign(extractedProps, props2transform(props));
|
Object.assign(extractedProps, props2transform(props));
|
||||||
let transform = props.transform;
|
|
||||||
if (transform) {
|
|
||||||
if (typeof transform === 'string') {
|
|
||||||
const 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));
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import Matrix2D from '../Matrix2D';
|
import Matrix2D from '../Matrix2D';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
let pooledMatrix = new Matrix2D();
|
let pooledMatrix = new Matrix2D();
|
||||||
|
import peg from 'pegjs';
|
||||||
|
|
||||||
function transformToMatrix(props, transform) {
|
function transformToMatrix(props, transform) {
|
||||||
pooledMatrix.reset();
|
pooledMatrix.reset();
|
||||||
@@ -13,73 +14,172 @@ function transformToMatrix(props, transform) {
|
|||||||
return pooledMatrix.toArray();
|
return pooledMatrix.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPLIT_REGEX = /[\s*()|,]/;
|
const transformParser = peg.generate(`
|
||||||
|
{
|
||||||
|
const deg2rad = Math.PI / 180;
|
||||||
|
|
||||||
class TransformParser {
|
/*
|
||||||
|
╔═ ═╗ ╔═ ═╗ ╔═ ═╗
|
||||||
|
║ al cl el ║ ║ ar cr er ║ ║ a c e ║
|
||||||
|
║ bl dl fl ║ * ║ br dr fr ║ = ║ b d f ║
|
||||||
|
║ 0 0 1 ║ ║ 0 0 1 ║ ║ 0 0 1 ║
|
||||||
|
╚═ ═╝ ╚═ ═╝ ╚═ ═╝
|
||||||
|
*/
|
||||||
|
function multiply_matrices(l, r) {
|
||||||
|
const [al, cl, el, bl, dl, fl] = l;
|
||||||
|
const [ar, cr, er, br, dr, fr] = r;
|
||||||
|
|
||||||
parse(transform) {
|
const a = al * ar + cl * br;
|
||||||
if (transform) {
|
const c = al * cr + cl * dr;
|
||||||
const retval = {};
|
const e = al * er + cl * fr + el;
|
||||||
let transLst = _.filter(
|
const b = bl * ar + dl * br;
|
||||||
transform.split(SPLIT_REGEX),
|
const d = bl * cr + dl * dr;
|
||||||
(ele) => {
|
const f = bl * er + dl * fr + fl;
|
||||||
return ele !== '';
|
|
||||||
}
|
return [a, c, e, b, d, f];
|
||||||
);
|
|
||||||
for (let i = 0; i < transLst.length; i++) {
|
|
||||||
let trans = transLst[i];
|
|
||||||
switch (trans) {
|
|
||||||
case 'matrix':
|
|
||||||
if (i + 7 <= transLst.length) {
|
|
||||||
retval.matrix = _.map((transLst.slice(i + 1,i + 7)), parseFloat);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'translate':
|
|
||||||
retval.translateX = transLst[i + 1];
|
|
||||||
retval.translateY = (transLst.length === 3) ? transLst[i + 2] : 0;
|
|
||||||
break;
|
|
||||||
case 'scale':
|
|
||||||
retval.scaleX = transLst[i + 1];
|
|
||||||
retval.scaleY = (transLst.length === 3) ? transLst[i + 2] : retval.scaleX;
|
|
||||||
break;
|
|
||||||
case 'rotate':
|
|
||||||
retval.rotation = transLst[i + 1];
|
|
||||||
retval.originX = (transLst.length > 2) ? transLst[i + 2] : retval.originX;
|
|
||||||
retval.originY = (transLst.length > 3) ? transLst[i + 3] : retval.originY;
|
|
||||||
break;
|
|
||||||
case 'skewX':
|
|
||||||
retval.skewX = transLst[i + 1];
|
|
||||||
break;
|
|
||||||
case 'skewY':
|
|
||||||
retval.skewY = transLst[i + 1];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tp = new TransformParser();
|
transformList
|
||||||
|
= wsp* ts:transforms? wsp* { return ts; }
|
||||||
|
|
||||||
|
transforms
|
||||||
|
= t:transform commaWsp+ ts:transforms
|
||||||
|
{
|
||||||
|
return multiply_matrices(t, ts);
|
||||||
|
}
|
||||||
|
/ t:transform
|
||||||
|
|
||||||
|
transform
|
||||||
|
= matrix
|
||||||
|
/ translate
|
||||||
|
/ scale
|
||||||
|
/ rotate
|
||||||
|
/ skewX
|
||||||
|
/ skewY
|
||||||
|
|
||||||
|
matrix
|
||||||
|
= "matrix" wsp* "(" wsp*
|
||||||
|
a:number commaWsp
|
||||||
|
b:number commaWsp
|
||||||
|
c:number commaWsp
|
||||||
|
d:number commaWsp
|
||||||
|
e:number commaWsp
|
||||||
|
f:number wsp* ")"
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
a, c, e,
|
||||||
|
b, d, f
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
translate
|
||||||
|
= "translate" wsp* "(" wsp* tx:number ty:commaWspNumber? wsp* ")"
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
1, 0, tx,
|
||||||
|
0, 1, ty || 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
scale
|
||||||
|
= "scale" wsp* "(" wsp* sx:number sy:commaWspNumber? wsp* ")"
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
sx, 0, 0,
|
||||||
|
0, sy === null ? sx : sy, 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate
|
||||||
|
= "rotate" wsp* "(" wsp* angle:number c:commaWspTwoNumbers? wsp* ")"
|
||||||
|
{
|
||||||
|
const cos = Math.cos(deg2rad * angle);
|
||||||
|
const sin = Math.sin(deg2rad * angle);
|
||||||
|
if (c !== null) {
|
||||||
|
const [x, y] = c;
|
||||||
|
return [
|
||||||
|
cos, -sin, cos * -x + -sin * -y + x,
|
||||||
|
sin, cos, sin * -x + cos * -y + y
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
cos, -sin, 0,
|
||||||
|
sin, cos, 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
skewX
|
||||||
|
= "skewX" wsp* "(" wsp* angle:number wsp* ")"
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
1, Math.tan(deg2rad * angle), 0,
|
||||||
|
0, 1, 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
skewY
|
||||||
|
= "skewY" wsp* "(" wsp* angle:number wsp* ")"
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
1, 0, 0,
|
||||||
|
Math.tan(deg2rad * angle), 1, 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
number
|
||||||
|
= f:(sign? floatingPointConstant) { return parseFloat(f.join("")); }
|
||||||
|
/ i:(sign? integerConstant) { return parseInt(i.join("")); }
|
||||||
|
|
||||||
|
commaWspNumber
|
||||||
|
= commaWsp n:number { return n; }
|
||||||
|
|
||||||
|
commaWspTwoNumbers
|
||||||
|
= commaWsp n1:number commaWsp n2:number { return [n1, n2]; }
|
||||||
|
|
||||||
|
commaWsp
|
||||||
|
= (wsp+ comma? wsp*) / (comma wsp*)
|
||||||
|
|
||||||
|
comma
|
||||||
|
= ","
|
||||||
|
|
||||||
|
integerConstant
|
||||||
|
= ds:digitSequence { return ds.join(""); }
|
||||||
|
|
||||||
|
floatingPointConstant
|
||||||
|
= fractionalConstant exponent?
|
||||||
|
/ digitSequence exponent
|
||||||
|
|
||||||
|
fractionalConstant "fractionalConstant"
|
||||||
|
= d1:digitSequence? "." d2:digitSequence { return [d1 ? d1.join("") : null, ".", d2.join("")].join(""); }
|
||||||
|
/ d:digitSequence "." { return d.join(""); }
|
||||||
|
|
||||||
|
exponent
|
||||||
|
= [eE] sign? digitSequence
|
||||||
|
|
||||||
|
sign
|
||||||
|
= [+-]
|
||||||
|
|
||||||
|
digitSequence
|
||||||
|
= digit+
|
||||||
|
|
||||||
|
digit
|
||||||
|
= [0-9]
|
||||||
|
|
||||||
|
wsp
|
||||||
|
= [\\u0020\\u0009\\u000D\\u000A]
|
||||||
|
`);
|
||||||
|
|
||||||
function appendTransform(transform) {
|
function appendTransform(transform) {
|
||||||
if (transform) {
|
if (transform) {
|
||||||
if (typeof transform === 'string') {
|
if (typeof transform === 'string') {
|
||||||
const transformParsed = tp.parse(transform);
|
try {
|
||||||
if (transformParsed.matrix) {
|
const [a, c, e, b, d, f] = transformParser.parse(transform);
|
||||||
pooledMatrix.append(...transformParsed.matrix);
|
pooledMatrix.append(...[a, b, c, d, e, f]);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
let trans = props2transform(transformParsed);
|
|
||||||
if (typeof trans !== 'string') {
|
|
||||||
transform = trans;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (typeof transform !== 'string') {
|
|
||||||
pooledMatrix
|
pooledMatrix
|
||||||
.appendTransform(
|
.appendTransform(
|
||||||
transform.x + transform.originX,
|
transform.x + transform.originX,
|
||||||
|
|||||||
@@ -29,8 +29,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color": "^2.0.1",
|
"color": "^2.0.1",
|
||||||
|
"github-download": "^0.5.0",
|
||||||
"lodash": "^4.16.6",
|
"lodash": "^4.16.6",
|
||||||
"github-download": "^0.5.0"
|
"pegjs": "^0.10.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-eslint": "^6.1.2",
|
"babel-eslint": "^6.1.2",
|
||||||
|
|||||||
Reference in New Issue
Block a user