more attributes
diff --git a/extension/css/svgImporter.css b/extension/css/svgImporter.css
index 491c319..acef9ae 100644
--- a/extension/css/svgImporter.css
+++ b/extension/css/svgImporter.css
@@ -1,4 +1,29 @@
-#svgImporter{
+
+.references{
+ background-color: #484043;
+ background-color: rgb(72, 64, 67);
+ background-color: #6E6568;
+ background-color: rgb(110, 101, 104);
+ background-color: #EAD3A8;
+ background-color: rgb(234, 211, 168);
+ background-color: #D23641;
+ background-color: rgb(210, 54, 65);
+ background-color: #FFFFFF;
+ background-color: rgb(255, 255, 255);
+}
+
+#svgImporter .buttons{
+ margin-top: 10px;
+}
+
+
+#svgImporter .buttons.center{
+ text-align: center;
+}
+
+#svgImporter h1{
+ text-align: center;
+ color: #D23641;
}
#svgContainer{
@@ -9,4 +34,9 @@
color: #876678;
stroke-width:0;
stroke-opacity:0;
+}
+
+#svgImporter .description{
+ text-align: center;
+ font-size: 12px;
}
\ No newline at end of file
diff --git a/extension/index.html b/extension/index.html
index 9ff15c8..2ce41ba 100644
--- a/extension/index.html
+++ b/extension/index.html
@@ -149,8 +149,16 @@
</div>
</div>
<div id="svgImporter">
- <div id='svgContainer'></div>
- HOLA
+ <div class='buttons'>
+ <button class='generalButton return'>Back</button>
+ </div>
+ <div id='svgContainer'></div>
+ <h1>This is a first version.</h1>
+ <div class="description"><p>It only supports some tags.</p><p>If it doesn't work with your file please open it in illustrator, save it as a .AI file and import it.</p><p>But if it works you'll be in a world of happiness. Directly imported as shapes, supports strokes and no unnecessary extra stuff.</p></div>
+ <div class='buttons center'>
+ <button class='generalButton import'>Import</button>
+ </div>
+
</div>
</div>
@@ -177,6 +185,7 @@
<script src="js/libs/bodymovin.js"></script>
<script src="js/libs/bm.js"></script>
<script src="js/libs/mustache.js"></script>
+ <script src="js/libs/matrix.js"></script>
<script src="js/animations/radio.js"></script>
<script src="js/animations/alert.js"></script>
diff --git a/extension/js/controllers/importSVGController.js b/extension/js/controllers/importSVGController.js
index 35b9069..a395c5f 100644
--- a/extension/js/controllers/importSVGController.js
+++ b/extension/js/controllers/importSVGController.js
@@ -1,5 +1,5 @@
/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
-/*global $, alertData, successData, bodymovin */
+/*global $, alertData, successData, bodymovin, mainController */
var importSVGController = (function () {
'use strict';
var ob = {};
@@ -139,6 +139,13 @@
return null;
}
+ function getTransformationMatrix(elem, matr){
+ var transform = getComputedStyle(elem, null).transform;
+ var transformAttr = elem.getAttribute('transform');
+ console.log('transformtransform: ',transform);
+ console.log('transformAttrtransformAttr: ',transformAttr);
+ }
+
function exportStyleAttributes(elem, ob){
ob.co = getColor(elem);
ob.fop = getFillOpacity(elem);
@@ -235,7 +242,13 @@
var ob = {};
ob.ty = 'g';
exportStyleAttributes(elem,ob);
+ var m = new Matrix();
+ var transform = getComputedStyle(elem, null).transform;
+ var transformAttr = elem.getAttribute('transform');
+ console.log('transform: ',transform);
+ console.log('transformAttr: ',transformAttr);
ob.elems = iterateElems(elem);
+
return ob;
}
@@ -333,7 +346,6 @@
function getSegmentData(elem){
var ob = {};
- console.log(elem.pathSegType);
switch(elem.pathSegType) {
case 1:
return exportCloseSegment(elem);
@@ -373,7 +385,7 @@
return ob;
}
- function iterateElems(elem) {
+ function iterateElems(elem,m) {
var arr = [];
var children = elem.childNodes;
var i, len = children.length, child, elemData;
@@ -408,13 +420,14 @@
break;
}
if(elemData){
+ elemData.tr = getTransformationMatrix(elem, m);
arr.push(elemData);
}
}
return arr;
}
- function addToDOM(data) {
+ function addToDOM(data, name) {
//data = '<style type="text/css">*{opacity:0.91232123}</style>' + data;
svgContainer.html(data);
var svgSelector = svgContainer.find('svg');
@@ -435,25 +448,26 @@
var svgData = {
w: w,
h: h,
+ name: name,
elems: []
};
- svgData.elems = iterateElems(svgElem);
- console.log(svgData);
+ var mat = new Matrix();
+ svgData.elems = iterateElems(svgElem, mat);
var eScript = 'bm_svgImporter.createSvg(' + JSON.stringify(svgData) + ')';
csInterface.evalScript(eScript);
}
- function loadSVG(path) {
+ function loadSVG(path, name) {
var xhr = new XMLHttpRequest();
xhr.open('GET', path, true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
- addToDOM(xhr.responseText);
+ addToDOM(xhr.responseText, name);
} else {
try {
- addToDOM(xhr.responseText);
+ addToDOM(xhr.responseText, name);
} catch (err) {
}
}
@@ -462,12 +476,12 @@
}
function handleFileUri(ev) {
- loadSVG(ev.data);
+ console.log(ev.data);
+ loadSVG(ev.data.path, ev.data.name);
}
function show(){
csInterface.addEventListener('bm:file:uri', handleFileUri);
- importSVG();
view.show();
}
@@ -476,6 +490,10 @@
view.hide();
}
+ function showSelection() {
+ mainController.showView('selection');
+ }
+
function init(csI) {
view = $("#svgImporter");
view.hide();
@@ -484,8 +502,10 @@
svgContainer.on('click', function(){
svgContainer.html('');
})
- /*var button = $('#compsSelection .buttons .import');
- button.on('click', importSVG);*/
+ var button = $('#svgImporter .buttons .import');
+ button.on('click', importSVG);
+ var backButton = $('#svgImporter .buttons .return');
+ backButton.on('click', showSelection);
}
return ob;
diff --git a/extension/js/controllers/snapshotController.js b/extension/js/controllers/snapshotController.js
index 71ac431..f586a5f 100644
--- a/extension/js/controllers/snapshotController.js
+++ b/extension/js/controllers/snapshotController.js
@@ -103,7 +103,7 @@
}
function handleFileUri(ev) {
- loadAnimation(ev.data);
+ loadAnimation(ev.data.path);
}
function frameChangeHandler() {
diff --git a/extension/js/libs/matrix.js b/extension/js/libs/matrix.js
new file mode 100644
index 0000000..0c8fe67
--- /dev/null
+++ b/extension/js/libs/matrix.js
@@ -0,0 +1,908 @@
+/*!
+ 2D Transformation Matrix v2.3.2
+ (c) Epistemex.com 2014-2016
+ License: MIT, header required.
+*/
+
+/* --- To see contributors: please see readme.md and Change.log --- */
+
+/**
+ * 2D transformation matrix object initialized with identity matrix.
+ *
+ * The matrix can synchronize a canvas 2D context by supplying the context
+ * as an argument, or later apply current absolute transform to an
+ * existing context.
+ *
+ * To synchronize a DOM element you can use [`toCSS()`]{@link Matrix#toCSS} or [`toCSS3D()`]{@link Matrix#toCSS3D}.
+ *
+ * @param {CanvasRenderingContext2D} [context] - Optional context to sync with Matrix
+ * @prop {number} a - scale x
+ * @prop {number} b - shear y
+ * @prop {number} c - shear x
+ * @prop {number} d - scale y
+ * @prop {number} e - translate x
+ * @prop {number} f - translate y
+ * @prop {CanvasRenderingContext2D|null} [context=null] - set or get current canvas context
+ * @constructor
+ * @license MIT license (header required)
+ * @copyright Epistemex.com 2014-2016
+ */
+function Matrix(context) {
+
+ var me = this;
+ me._t = me.transform;
+
+ me.a = me.d = 1;
+ me.b = me.c = me.e = me.f = 0;
+
+ // reset canvas to enable 100% sync.
+ if (context)
+ (me.context = context).setTransform(1, 0, 0, 1, 0, 0);
+}
+
+/**
+ * Returns a new matrix that transforms a triangle `t1` into another triangle
+ * `t2`, or throws an exception if it is impossible.
+ *
+ * Note: the method can take both arrays as well as literal objects.
+ * Just make sure that both arguments (`t1`, `t2`) are of the same type.
+ *
+ * @param {{px: number, py: number, qx: number, qy: number, rx: number, ry: number}|Array} t1 - Object or array containing the three points for the triangle.
+ * For object use obj.px, obj.py, obj.qx, obj.qy, obj.rx and obj.ry. For arrays provide the points in the order [px, py, qx, qy, rx, ry]
+ * @param {{px: number, py: number, qx: number, qy: number, rx: number, ry: number}|Array} t2 - See description for t1.
+ * @param {CanvasRenderingContext2D} [context] - optional canvas 2D context to use for the matrix
+ * @returns {Matrix}
+ * @throws Exception is matrix becomes not invertible
+ * @static
+ */
+Matrix.fromTriangles = function(t1, t2, context) {
+
+ var m1 = new Matrix(),
+ m2 = new Matrix(context),
+ r1, r2;
+
+ if (Array.isArray(t1)) {
+ var rx1 = t1[4], ry1 = t1[5], rx2 = t2[4], ry2 = t2[5];
+ r1 = [t1[0] - rx1, t1[1] - ry1, t1[2] - rx1, t1[3] - ry1, rx1, ry1];
+ r2 = [t2[0] - rx2, t2[1] - ry2, t2[2] - rx2, t2[3] - ry2, rx2, ry2]
+ }
+ else {
+ r1 = [t1.px - t1.rx, t1.py - t1.ry, t1.qx - t1.rx, t1.qy - t1.ry, t1.rx, t1.ry];
+ r2 = [t2.px - t2.rx, t2.py - t2.ry, t2.qx - t2.rx, t2.qy - t2.ry, t2.rx, t2.ry]
+ }
+
+ m1.setTransform.apply(m1, r1);
+ m2.setTransform.apply(m2, r2);
+
+ return m2.multiply(m1.inverse())
+};
+
+/**
+ * Create a new matrix from a SVGMatrix
+ *
+ * @param {SVGMatrix} svgMatrix - source SVG Matrix
+ * @param {CanvasRenderingContext2D} [context] - optional canvas 2D context to use for the matrix
+ * @returns {Matrix}
+ * @static
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix|MDN / SVGMatrix}
+ */
+Matrix.fromSVGMatrix = function(svgMatrix, context) {
+ return new Matrix(context).multiply(svgMatrix)
+};
+
+/**
+ * Create a matrix from a transform list from an SVG shape. The list
+ * can be for example baseVal (i.e. `shape.transform.baseVal`).
+ *
+ * The resulting matrix has all transformations from that list applied
+ * in the same order as the list.
+ *
+ * @param {SVGTransformList} tList - transform list from an SVG shape.
+ * @param {CanvasRenderingContext2D} [context] - optional canvas 2D context to use for the matrix
+ * @returns {Matrix}
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGTransformList|MDN / SVGTransformList}
+ */
+Matrix.fromSVGTransformList = function(tList, context) {
+
+ var m = new Matrix(context),
+ i = 0;
+
+ while(i < tList.length)
+ m.multiply(tList[i++].matrix);
+
+ return m
+};
+
+Matrix.prototype = {
+
+ /**
+ * Concatenates transforms of this matrix onto the given child matrix and
+ * returns a new matrix. This instance is used on left side.
+ *
+ * @param {Matrix} cm - child matrix to apply concatenation to
+ * @returns {Matrix} - new Matrix instance
+ */
+ concat: function(cm) {
+ return this.clone().multiply(cm)
+ },
+
+ /**
+ * Flips the horizontal values.
+ * @returns {Matrix}
+ */
+ flipX: function() {
+ return this._t(-1, 0, 0, 1, 0, 0)
+ },
+
+ /**
+ * Flips the vertical values.
+ * @returns {Matrix}
+ */
+ flipY: function() {
+ return this._t(1, 0, 0, -1, 0, 0)
+ },
+
+ /**
+ * Reflects incoming (velocity) vector on the normal which will be the
+ * current transformed x axis. Call when a trigger condition is met.
+ *
+ * @param {number} x - vector end point for x (start = 0)
+ * @param {number} y - vector end point for y (start = 0)
+ * @returns {{x: number, y: number}}
+ */
+ reflectVector: function(x, y) {
+
+ var v = this.applyToPoint(0, 1),
+ d = (v.x * x + v.y * y) * 2;
+
+ x -= d * v.x;
+ y -= d * v.y;
+
+ return {x: x, y: y}
+ },
+
+ /**
+ * Short-hand to reset current matrix to an identity matrix.
+ * @returns {Matrix}
+ */
+ reset: function() {
+ return this.setTransform(1, 0, 0, 1, 0, 0)
+ },
+
+ /**
+ * Rotates current matrix by angle (accumulative).
+ * @param {number} angle - angle in radians
+ * @returns {Matrix}
+ */
+ rotate: function(angle) {
+ var cos = Math.cos(angle),
+ sin = Math.sin(angle);
+ return this._t(cos, sin, -sin, cos, 0, 0)
+ },
+
+ /**
+ * Converts a vector given as `x` and `y` to angle, and
+ * rotates (accumulative).
+ * @param x
+ * @param y
+ * @returns {Matrix}
+ */
+ rotateFromVector: function(x, y) {
+ return this.rotate(Math.atan2(y, x))
+ },
+
+ /**
+ * Helper method to make a rotation based on an angle in degrees.
+ * @param {number} angle - angle in degrees
+ * @returns {Matrix}
+ */
+ rotateDeg: function(angle) {
+ return this.rotate(angle * Math.PI / 180)
+ },
+
+ /**
+ * Scales current matrix uniformly and accumulative.
+ * @param {number} f - scale factor for both x and y (1 does nothing)
+ * @returns {Matrix}
+ */
+ scaleU: function(f) {
+ return this._t(f, 0, 0, f, 0, 0)
+ },
+
+ /**
+ * Scales current matrix accumulative.
+ * @param {number} sx - scale factor x (1 does nothing)
+ * @param {number} sy - scale factor y (1 does nothing)
+ * @returns {Matrix}
+ */
+ scale: function(sx, sy) {
+ return this._t(sx, 0, 0, sy, 0, 0)
+ },
+
+ /**
+ * Scales current matrix on x axis accumulative.
+ * @param {number} sx - scale factor x (1 does nothing)
+ * @returns {Matrix}
+ */
+ scaleX: function(sx) {
+ return this._t(sx, 0, 0, 1, 0, 0)
+ },
+
+ /**
+ * Scales current matrix on y axis accumulative.
+ * @param {number} sy - scale factor y (1 does nothing)
+ * @returns {Matrix}
+ */
+ scaleY: function(sy) {
+ return this._t(1, 0, 0, sy, 0, 0)
+ },
+
+ /**
+ * Apply shear to the current matrix accumulative.
+ * @param {number} sx - amount of shear for x
+ * @param {number} sy - amount of shear for y
+ * @returns {Matrix}
+ */
+ shear: function(sx, sy) {
+ return this._t(1, sy, sx, 1, 0, 0)
+ },
+
+ /**
+ * Apply shear for x to the current matrix accumulative.
+ * @param {number} sx - amount of shear for x
+ * @returns {Matrix}
+ */
+ shearX: function(sx) {
+ return this._t(1, 0, sx, 1, 0, 0)
+ },
+
+ /**
+ * Apply shear for y to the current matrix accumulative.
+ * @param {number} sy - amount of shear for y
+ * @returns {Matrix}
+ */
+ shearY: function(sy) {
+ return this._t(1, sy, 0, 1, 0, 0)
+ },
+
+ /**
+ * Apply skew to the current matrix accumulative.
+ * @param {number} ax - angle of skew for x
+ * @param {number} ay - angle of skew for y
+ * @returns {Matrix}
+ */
+ skew: function(ax, ay) {
+ return this.shear(Math.tan(ax), Math.tan(ay))
+ },
+
+ /**
+ * Apply skew for x to the current matrix accumulative.
+ * @param {number} ax - angle of skew for x
+ * @returns {Matrix}
+ */
+ skewX: function(ax) {
+ return this.shearX(Math.tan(ax))
+ },
+
+ /**
+ * Apply skew for y to the current matrix accumulative.
+ * @param {number} ay - angle of skew for y
+ * @returns {Matrix}
+ */
+ skewY: function(ay) {
+ return this.shearY(Math.tan(ay))
+ },
+
+ /**
+ * Set current matrix to new absolute matrix.
+ * @param {number} a - scale x
+ * @param {number} b - shear y
+ * @param {number} c - shear x
+ * @param {number} d - scale y
+ * @param {number} e - translate x
+ * @param {number} f - translate y
+ * @returns {Matrix}
+ */
+ setTransform: function(a, b, c, d, e, f) {
+ var me = this;
+ me.a = a;
+ me.b = b;
+ me.c = c;
+ me.d = d;
+ me.e = e;
+ me.f = f;
+ return me._x()
+ },
+
+ /**
+ * Translate current matrix accumulative.
+ * @param {number} tx - translation for x
+ * @param {number} ty - translation for y
+ * @returns {Matrix}
+ */
+ translate: function(tx, ty) {
+ return this._t(1, 0, 0, 1, tx, ty)
+ },
+
+ /**
+ * Translate current matrix on x axis accumulative.
+ * @param {number} tx - translation for x
+ * @returns {Matrix}
+ */
+ translateX: function(tx) {
+ return this._t(1, 0, 0, 1, tx, 0)
+ },
+
+ /**
+ * Translate current matrix on y axis accumulative.
+ * @param {number} ty - translation for y
+ * @returns {Matrix}
+ */
+ translateY: function(ty) {
+ return this._t(1, 0, 0, 1, 0, ty)
+ },
+
+ /**
+ * Multiplies current matrix with new matrix values. Also see [`multiply()`]{@link Matrix#multiply}.
+ *
+ * @param {number} a2 - scale x
+ * @param {number} b2 - shear y
+ * @param {number} c2 - shear x
+ * @param {number} d2 - scale y
+ * @param {number} e2 - translate x
+ * @param {number} f2 - translate y
+ * @returns {Matrix}
+ */
+ transform: function(a2, b2, c2, d2, e2, f2) {
+
+ var me = this,
+ a1 = me.a,
+ b1 = me.b,
+ c1 = me.c,
+ d1 = me.d,
+ e1 = me.e,
+ f1 = me.f;
+
+ /* matrix order (canvas compatible):
+ * ace
+ * bdf
+ * 001
+ */
+ me.a = a1 * a2 + c1 * b2;
+ me.b = b1 * a2 + d1 * b2;
+ me.c = a1 * c2 + c1 * d2;
+ me.d = b1 * c2 + d1 * d2;
+ me.e = a1 * e2 + c1 * f2 + e1;
+ me.f = b1 * e2 + d1 * f2 + f1;
+
+ return me._x()
+ },
+
+ /**
+ * Multiplies current matrix with source matrix.
+ * @param {Matrix|SVGMatrix} m - source matrix to multiply with.
+ * @returns {Matrix}
+ */
+ multiply: function(m) {
+ return this._t(m.a, m.b, m.c, m.d, m.e, m.f)
+ },
+
+ /**
+ * Divide this matrix on input matrix which must be invertible.
+ * @param {Matrix} m - matrix to divide on (divisor)
+ * @throws Exception is input matrix is not invertible
+ * @returns {Matrix}
+ */
+ divide: function(m) {
+
+ if (!m.isInvertible())
+ throw "Matrix not invertible";
+
+ return this.multiply(m.inverse())
+ },
+
+ /**
+ * Divide current matrix on scalar value != 0.
+ * @param {number} d - divisor (can not be 0)
+ * @returns {Matrix}
+ */
+ divideScalar: function(d) {
+
+ var me = this;
+ me.a /= d;
+ me.b /= d;
+ me.c /= d;
+ me.d /= d;
+ me.e /= d;
+ me.f /= d;
+
+ return me._x()
+ },
+
+ /**
+ * Get an inverse matrix of current matrix. The method returns a new
+ * matrix with values you need to use to get to an identity matrix.
+ * Context from parent matrix is not applied to the returned matrix.
+ *
+ * @param {boolean} [cloneContext=false] - clone current context to resulting matrix
+ * @throws Exception is input matrix is not invertible
+ * @returns {Matrix} - new Matrix instance
+ */
+ inverse: function(cloneContext) {
+
+ var me = this,
+ m = new Matrix(cloneContext ? me.context : null),
+ dt = me.determinant();
+
+ if (me._q(dt, 0))
+ throw "Matrix not invertible.";
+
+ m.a = me.d / dt;
+ m.b = -me.b / dt;
+ m.c = -me.c / dt;
+ m.d = me.a / dt;
+ m.e = (me.c * me.f - me.d * me.e) / dt;
+ m.f = -(me.a * me.f - me.b * me.e) / dt;
+
+ return m
+ },
+
+ /**
+ * Interpolate this matrix with another and produce a new matrix.
+ * `t` is a value in the range [0.0, 1.0] where 0 is this instance and
+ * 1 is equal to the second matrix. The `t` value is not clamped.
+ *
+ * Context from parent matrix is not applied to the returned matrix.
+ *
+ * Note: this interpolation is naive. For animation containing rotation,
+ * shear or skew use the [`interpolateAnim()`]{@link Matrix#interpolateAnim} method instead
+ * to avoid unintended flipping.
+ *
+ * @param {Matrix} m2 - the matrix to interpolate with.
+ * @param {number} t - interpolation [0.0, 1.0]
+ * @param {CanvasRenderingContext2D} [context] - optional context to affect
+ * @returns {Matrix} - new Matrix instance with the interpolated result
+ */
+ interpolate: function(m2, t, context) {
+
+ var me = this,
+ m = context ? new Matrix(context) : new Matrix();
+
+ m.a = me.a + (m2.a - me.a) * t;
+ m.b = me.b + (m2.b - me.b) * t;
+ m.c = me.c + (m2.c - me.c) * t;
+ m.d = me.d + (m2.d - me.d) * t;
+ m.e = me.e + (m2.e - me.e) * t;
+ m.f = me.f + (m2.f - me.f) * t;
+
+ return m._x()
+ },
+
+ /**
+ * Interpolate this matrix with another and produce a new matrix.
+ * `t` is a value in the range [0.0, 1.0] where 0 is this instance and
+ * 1 is equal to the second matrix. The `t` value is not constrained.
+ *
+ * Context from parent matrix is not applied to the returned matrix.
+ *
+ * To obtain easing `t` can be preprocessed using easing-functions
+ * before being passed to this method.
+ *
+ * Note: this interpolation method uses decomposition which makes
+ * it suitable for animations (in particular where rotation takes
+ * places).
+ *
+ * @param {Matrix} m2 - the matrix to interpolate with.
+ * @param {number} t - interpolation [0.0, 1.0]
+ * @param {CanvasRenderingContext2D} [context] - optional context to affect
+ * @returns {Matrix} - new Matrix instance with the interpolated result
+ */
+ interpolateAnim: function(m2, t, context) {
+
+ var m = new Matrix(context ? context : null),
+ d1 = this.decompose(),
+ d2 = m2.decompose(),
+ t1 = d1.translate,
+ t2 = d2.translate,
+ s1 = d1.scale,
+ rotation = d1.rotation + (d2.rotation - d1.rotation) * t,
+ translateX = t1.x + (t2.x - t1.x) * t,
+ translateY = t1.y + (t2.y - t1.y) * t,
+ scaleX = s1.x + (d2.scale.x - s1.x) * t,
+ scaleY = s1.y + (d2.scale.y - s1.y) * t
+ ;
+
+ // QR order (t-r-s-sk)
+ m.translate(translateX, translateY);
+ m.rotate(rotation);
+ m.scale(scaleX, scaleY);
+ //todo test skew scenarios
+
+ return m._x()
+ },
+
+ /**
+ * Decompose the current matrix into simple transforms using either
+ * QR (default) or LU decomposition.
+ *
+ * The result must be applied in the following order to reproduce the current matrix:
+ *
+ * QR: translate -> rotate -> scale -> skew
+ * LU: translate -> skew -> scale -> skew
+ *
+ * @param {boolean} [useLU=false] - set to true to use LU rather than QR algorithm
+ * @returns {*} - an object containing current decomposed values (rotate, skew, scale, translate)
+ * @see {@link http://www.maths-informatique-jeux.com/blog/frederic/?post/2013/12/01/Decomposition-of-2D-transform-matrices|Adoption based on this code}
+ */
+ decompose: function(useLU) {
+
+ var me = this,
+ a = me.a,
+ b = me.b,
+ c = me.c,
+ d = me.d,
+ acos = Math.acos,
+ atan = Math.atan,
+ sqrt = Math.sqrt,
+ pi = Math.PI,
+
+ translate = {x: me.e, y: me.f},
+ rotation = 0,
+ scale = {x: 1, y: 1},
+ skew = {x: 0, y: 0},
+
+ determ = a * d - b * c; // determinant(), skip DRY here...
+
+ if (useLU) {
+ if (a) {
+ skew = {x: atan(c / a), y: atan(b / a)};
+ scale = {x: a, y: determ / a};
+ }
+ else if (b) {
+ rotation = pi * 0.5;
+ scale = {x: b, y: determ / b};
+ skew.x = atan(d / b);
+ }
+ else { // a = b = 0
+ scale = {x: c, y: d};
+ skew.x = pi * 0.25;
+ }
+ }
+ else {
+ // Apply the QR-like decomposition.
+ if (a || b) {
+ var r = sqrt(a * a + b * b);
+ rotation = b > 0 ? acos(a / r) : -acos(a / r);
+ scale = {x: r, y: determ / r};
+ skew.x = atan((a * c + b * d) / (r * r));
+ }
+ else if (c || d) {
+ var s = sqrt(c * c + d * d);
+ rotation = pi * 0.5 - (d > 0 ? acos(-c / s) : -acos(c / s));
+ scale = {x: determ / s, y: s};
+ skew.y = atan((a * c + b * d) / (s * s));
+ }
+ else { // a = b = c = d = 0
+ scale = {x: 0, y: 0}; // = invalid matrix
+ }
+ }
+
+ return {
+ scale : scale,
+ translate: translate,
+ rotation : rotation,
+ skew : skew
+ }
+ },
+
+ /**
+ * Returns the determinant of the current matrix.
+ * @returns {number}
+ */
+ determinant: function() {
+ return this.a * this.d - this.b * this.c
+ },
+
+ /**
+ * Apply current matrix to `x` and `y` of a point.
+ * Returns a point object.
+ *
+ * @param {number} x - value for x
+ * @param {number} y - value for y
+ * @returns {{x: number, y: number}} A new transformed point object
+ */
+ applyToPoint: function(x, y) {
+
+ var me = this;
+
+ return {
+ x: x * me.a + y * me.c + me.e,
+ y: x * me.b + y * me.d + me.f
+ }
+ },
+
+ /**
+ * Apply current matrix to array with point objects or point pairs.
+ * Returns a new array with points in the same format as the input array.
+ *
+ * A point object is an object literal:
+ *
+ * {x: x, y: y}
+ *
+ * so an array would contain either:
+ *
+ * [{x: x1, y: y1}, {x: x2, y: y2}, ... {x: xn, y: yn}]
+ *
+ * or
+ *
+ * [x1, y1, x2, y2, ... xn, yn]
+ *
+ * @param {Array} points - array with point objects or pairs
+ * @returns {Array} A new array with transformed points
+ */
+ applyToArray: function(points) {
+
+ var i = 0, p, l,
+ mxPoints = [];
+
+ if (typeof points[0] === 'number') {
+
+ l = points.length;
+
+ while(i < l) {
+ p = this.applyToPoint(points[i++], points[i++]);
+ mxPoints.push(p.x, p.y);
+ }
+ }
+ else {
+ while(p = points[i++]) {
+ mxPoints.push(this.applyToPoint(p.x, p.y));
+ }
+ }
+
+ return mxPoints
+ },
+
+ /**
+ * Apply current matrix to a typed array with point pairs. Although
+ * the input array may be an ordinary array, this method is intended
+ * for more performant use where typed arrays are used. The returned
+ * array is regardless always returned as a `Float32Array`.
+ *
+ * @param {*} points - (typed) array with point pairs [x1, y1, ..., xn, yn]
+ * @param {boolean} [use64=false] - use Float64Array instead of Float32Array
+ * @returns {*} A new typed array with transformed points
+ */
+ applyToTypedArray: function(points, use64) {
+
+ var i = 0, p,
+ l = points.length,
+ mxPoints = use64 ? new Float64Array(l) : new Float32Array(l);
+
+ while(i < l) {
+ p = this.applyToPoint(points[i], points[i + 1]);
+ mxPoints[i++] = p.x;
+ mxPoints[i++] = p.y;
+ }
+
+ return mxPoints
+ },
+
+ /**
+ * Apply to any canvas 2D context object. This does not affect the
+ * context that optionally was referenced in constructor unless it is
+ * the same context.
+ *
+ * @param {CanvasRenderingContext2D} context - target context
+ * @returns {Matrix}
+ */
+ applyToContext: function(context) {
+ var me = this;
+ context.setTransform(me.a, me.b, me.c, me.d, me.e, me.f);
+ return me
+ },
+
+ /**
+ * Returns true if matrix is an identity matrix (no transforms applied).
+ * @returns {boolean}
+ */
+ isIdentity: function() {
+ var me = this;
+ return me._q(me.a, 1) &&
+ me._q(me.b, 0) &&
+ me._q(me.c, 0) &&
+ me._q(me.d, 1) &&
+ me._q(me.e, 0) &&
+ me._q(me.f, 0)
+ },
+
+ /**
+ * Returns true if matrix is invertible
+ * @returns {boolean}
+ */
+ isInvertible: function() {
+ return !this._q(this.determinant(), 0)
+ },
+
+ /**
+ * Test if matrix is valid (here meaning the scale values are non-zero).
+ * @returns {boolean}
+ */
+ isValid: function() {
+ return !(this.a * this.d)
+ },
+
+ /**
+ * Compares current matrix with another matrix. Returns true if equal
+ * (within epsilon tolerance).
+ * @param {Matrix} m - matrix to compare this matrix with
+ * @returns {boolean}
+ */
+ isEqual: function(m) {
+
+ var me = this,
+ q = me._q;
+
+ return q(me.a, m.a) &&
+ q(me.b, m.b) &&
+ q(me.c, m.c) &&
+ q(me.d, m.d) &&
+ q(me.e, m.e) &&
+ q(me.f, m.f)
+ },
+
+ /**
+ * Clones current instance and returning a new matrix.
+ * @param {boolean} [noContext=false] don't clone context reference if true
+ * @returns {Matrix} - a new Matrix instance with identical transformations as this instance
+ */
+ clone: function(noContext) {
+ return new Matrix(noContext ? null : this.context).multiply(this)
+ },
+
+ /**
+ * Returns an array with current matrix values.
+ * @returns {Array}
+ */
+ toArray: function() {
+ var me = this;
+ return [me.a, me.b, me.c, me.d, me.e, me.f]
+ },
+
+ /**
+ * Returns a binary typed array, either as 32-bit (default) or
+ * 64-bit.
+ * @param {boolean} [use64=false] chose whether to use 32-bit or 64-bit typed array
+ * @returns {*}
+ */
+ toTypedArray: function(use64) {
+
+ var a = use64 ? new Float64Array(6) : new Float32Array(6),
+ me = this;
+
+ a[0] = me.a;
+ a[1] = me.b;
+ a[2] = me.c;
+ a[3] = me.d;
+ a[4] = me.e;
+ a[5] = me.f;
+
+ return a
+ },
+
+ /**
+ * Generates a string that can be used with CSS `transform`.
+ * @example
+ * element.style.transform = m.toCSS();
+ * @returns {string}
+ */
+ toCSS: function() {
+ return "matrix(" + this.toArray() + ")"
+ },
+
+ /**
+ * Generates a `matrix3d()` string that can be used with CSS `transform`.
+ * Although the matrix is for 2D use you may see performance benefits
+ * on some devices using a 3D CSS transform instead of a 2D.
+ * @example
+ * element.style.transform = m.toCSS3D();
+ * @returns {string}
+ */
+ toCSS3D: function() {
+ var me = this;
+ return "matrix3d(" + me.a + "," + me.b + ",0,0," + me.c + "," + me.d + ",0,0,0,0,1,0," + me.e + "," + me.f + ",0,1)"
+ },
+
+ /**
+ * Returns a JSON compatible string of current matrix.
+ * @returns {string}
+ */
+ toJSON: function() {
+ var me = this;
+ return '{"a":' + me.a + ',"b":' + me.b + ',"c":' + me.c + ',"d":' + me.d + ',"e":' + me.e + ',"f":' + me.f + '}'
+ },
+
+ /**
+ * Returns a string with current matrix as comma-separated list.
+ * @param {number} [fixLen=4] - truncate decimal values to number of digits
+ * @returns {string}
+ */
+ toString: function(fixLen) {
+ var me = this;
+ fixLen = fixLen || 4;
+ return "a=" + me.a.toFixed(fixLen) +
+ " b=" + me.b.toFixed(fixLen) +
+ " c=" + me.c.toFixed(fixLen) +
+ " d=" + me.d.toFixed(fixLen) +
+ " e=" + me.e.toFixed(fixLen) +
+ " f=" + me.f.toFixed(fixLen)
+ },
+
+ /**
+ * Returns a string with current matrix as comma-separated values
+ * string with line-end (CR+LF).
+ * @returns {string}
+ */
+ toCSV: function() {
+ return this.toArray().join() + "\r\n"
+ },
+
+ /**
+ * Convert current matrix into a `SVGMatrix`. If `SVGMatrix` is not
+ * supported, a `null` is returned.
+ *
+ * Note: BETA
+ *
+ * @returns {SVGMatrix}
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix|MDN / SVGMatrix}
+ */
+ toSVGMatrix: function() {
+
+ // as we can not set transforms directly on SVG matrices we need
+ // to decompose our own matrix first:
+ var dc = this.decompose(),
+ translate = dc.translate,
+ scale = dc.scale,
+ skew = dc.skew,
+ eq = this._q,
+ svgMatrix = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix();
+
+ if (!svgMatrix) return null;
+
+ // apply transformations in the correct order (see decompose()), QR: translate -> rotate -> scale -> skew
+ svgMatrix = svgMatrix.translate(translate.x, translate.y);
+ svgMatrix = svgMatrix.rotate(dc.rotation / Math.PI * 180); // SVGMatrix uses degrees
+ svgMatrix = svgMatrix.scaleNonUniform(scale.x, scale.y);
+
+ if (!eq(0, skew.x))
+ svgMatrix = svgMatrix.skewX(skew.x);
+
+ if (!eq(0, skew.y))
+ svgMatrix = svgMatrix.skewY(skew.y);
+
+ return svgMatrix
+ },
+
+ /**
+ * Compares floating point values with some tolerance (epsilon)
+ * @param {number} f1 - float 1
+ * @param {number} f2 - float 2
+ * @returns {boolean}
+ * @private
+ */
+ _q: function(f1, f2) {
+ return Math.abs(f1 - f2) < 1e-14
+ },
+
+ /**
+ * Apply current absolute matrix to context if defined, to sync it.
+ * @returns {Matrix}
+ * @private
+ */
+ _x: function() {
+ var me = this;
+ if (me.context)
+ me.context.setTransform(me.a, me.b, me.c, me.d, me.e, me.f);
+ return me
+ }
+};
diff --git a/extension/jsx/hostscript.jsx b/extension/jsx/hostscript.jsx
index 2c01fbe..fd86b1f 100644
--- a/extension/jsx/hostscript.jsx
+++ b/extension/jsx/hostscript.jsx
@@ -9,7 +9,7 @@
var f = new File(Folder.desktop.absoluteURI);
var openFileData = f.openDlg();
if (openFileData !== null) {
- bm_eventDispatcher.sendEvent('bm:file:uri', openFileData.fsName);
+ bm_eventDispatcher.sendEvent('bm:file:uri', {path: openFileData.fsName, name: openFileData.name});
}
}
diff --git a/extension/jsx/svgImporter.jsx b/extension/jsx/svgImporter.jsx
index baebb5f..f289948 100644
--- a/extension/jsx/svgImporter.jsx
+++ b/extension/jsx/svgImporter.jsx
@@ -308,6 +308,7 @@
function createSvg(data) {
var comp = app.project.items.addComp('svg', data.w, data.h, 1, 1, 1);
+ comp.name = data.name;
//var shapeLayer = comp.layers.addShape();
var inheritedData = {
co: "#000000",