mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-21 06:15:15 +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 extractStroke from './extractStroke';
|
||||
import extractTransform, {props2transform, tp} from './extractTransform';
|
||||
import extractTransform, {props2transform} from './extractTransform';
|
||||
import extractClipPath from './extractClipPath';
|
||||
import extractResponder from './extractResponder';
|
||||
import extractOpacity from './extractOpacity';
|
||||
@@ -27,21 +27,6 @@ export default function(props, ref) {
|
||||
extractedProps.matrix = extractTransform(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));
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Matrix2D from '../Matrix2D';
|
||||
import _ from 'lodash';
|
||||
let pooledMatrix = new Matrix2D();
|
||||
import peg from 'pegjs';
|
||||
|
||||
function transformToMatrix(props, transform) {
|
||||
pooledMatrix.reset();
|
||||
@@ -13,73 +14,172 @@ function transformToMatrix(props, transform) {
|
||||
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) {
|
||||
if (transform) {
|
||||
const retval = {};
|
||||
let transLst = _.filter(
|
||||
transform.split(SPLIT_REGEX),
|
||||
(ele) => {
|
||||
return ele !== '';
|
||||
}
|
||||
);
|
||||
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;
|
||||
}
|
||||
const a = al * ar + cl * br;
|
||||
const c = al * cr + cl * dr;
|
||||
const e = al * er + cl * fr + el;
|
||||
const b = bl * ar + dl * br;
|
||||
const d = bl * cr + dl * dr;
|
||||
const f = bl * er + dl * fr + fl;
|
||||
|
||||
return [a, c, e, b, d, f];
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (transform) {
|
||||
if (typeof transform === 'string') {
|
||||
const transformParsed = tp.parse(transform);
|
||||
if (transformParsed.matrix) {
|
||||
pooledMatrix.append(...transformParsed.matrix);
|
||||
try {
|
||||
const [a, c, e, b, d, f] = transformParser.parse(transform);
|
||||
pooledMatrix.append(...[a, b, c, d, e, f]);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
else {
|
||||
let trans = props2transform(transformParsed);
|
||||
if (typeof trans !== 'string') {
|
||||
transform = trans;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof transform !== 'string') {
|
||||
} else {
|
||||
pooledMatrix
|
||||
.appendTransform(
|
||||
transform.x + transform.originX,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "eslint ./",
|
||||
"postinstall" : "node scripts/install.js"
|
||||
"postinstall": "node scripts/install.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-native": ">=0.50.0",
|
||||
@@ -29,8 +29,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"color": "^2.0.1",
|
||||
"github-download": "^0.5.0",
|
||||
"lodash": "^4.16.6",
|
||||
"github-download": "^0.5.0"
|
||||
"pegjs": "^0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^6.1.2",
|
||||
|
||||
Reference in New Issue
Block a user