From dcccc39dcbe4bbccdb05e030a02a726dada9951b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sat, 30 Jul 2011 00:38:30 +0100 Subject: [PATCH 01/33] Remove double equals to make script work on Debian's Dash shell too. --- build/docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/docs.sh b/build/docs.sh index 57f4098a..b55606a0 100755 --- a/build/docs.sh +++ b/build/docs.sh @@ -30,7 +30,7 @@ cd jsdoc-toolkit java -jar jsrun.jar app/run.js -c=conf/$MODE.conf -D="renderMode:$MODE" cd .. -if [ $MODE == "docs" ] +if [ $MODE = "docs" ] then # Build paper.js library for documentation ./preprocess.sh stripped ../src/paper.js ../dist/docs/resources/js/paper.js\ From 293399e5b9a2514c33a262ea5ac1e4ef0f13c054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sat, 30 Jul 2011 11:36:28 +0100 Subject: [PATCH 02/33] Add optional parameter 'squared' to Point#getLength() and #getDistance(). --- src/basic/Point.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/basic/Point.js b/src/basic/Point.js index f01c8fbd..b8d0dc1a 100644 --- a/src/basic/Point.js +++ b/src/basic/Point.js @@ -390,7 +390,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ * is not modified! * * @param {Matrix} matrix - * @return {Point} the transformed point + * @return {Point} The transformed point */ transform: function(matrix) { return matrix ? matrix._transformPoint(this) : this; @@ -402,13 +402,16 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ * Returns the distance between the point and another point. * * @param {Point} point + * @param {Boolean} squared Controls whether the distance should remain + * squared, or its square root should be calculated. * @return {Number} */ - getDistance: function(point) { + getDistance: function(point, squared) { point = Point.read(arguments); var x = point.x - this.x, - y = point.y - this.y; - return Math.sqrt(x * x + y * y); + y = point.y - this.y, + d = x * x + y * y; + return squared ? d : Math.sqrt(d); }, /** @@ -421,7 +424,11 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ * @bean */ getLength: function() { - return Math.sqrt(this.x * this.x + this.y * this.y); + // Supports a hidden parameter 'squared', which controls whether the + // squared length should be returned. Hide it so it produces a bean + // property called #length. + var l = this.x * this.x + this.y * this.y; + return arguments[0] ? l : Math.sqrt(l); }, setLength: function(length) { @@ -453,8 +460,8 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ * {@code length} parameter defines the length to normalize to. * The object itself is not modified! * - * @param {Number} [length=1] the length of the normalized vector - * @return {Point} the normalized vector of the vector that is represented + * @param {Number} [length=1] The length of the normalized vector + * @return {Point} The normalized vector of the vector that is represented * by this point's coordinates. */ normalize: function(length) { From 7d0db22b9b41b39ed15d1bab65653fd74e1e7752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sat, 30 Jul 2011 11:37:07 +0100 Subject: [PATCH 03/33] Use squared distances in nearest point algorithm. --- src/path/Curve.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index 1beb164e..a49cf6ae 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -840,19 +840,20 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{ // Also look at beginning and end of curve (t = 0 / 1) var roots = findRoots(w, 0).concat([0, 1]); var minDist = Infinity, - minPoint, - minRoot; + minT, + minPoint; // There are always roots, since we add [0, 1] above. for (var i = 0; i < roots.length; i++) { var pt = this.getPoint(roots[i]), - dist = point.getDistance(pt); + dist = point.getDistance(pt, true); + // We're comparing squared distances if (dist < minDist) { minDist = dist; - minRoot = roots[i]; + minT = roots[i]; minPoint = pt; } } - return new CurveLocation(this, minRoot, minPoint, minDist); + return new CurveLocation(this, minT, minPoint, Math.sqrt(minDist)); }, getNearestPoint: function(point, matrix) { From 7f811848488751390a37e4969552b176fe68d1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sat, 30 Jul 2011 11:38:17 +0100 Subject: [PATCH 04/33] Only intersect lines if their lengths are not conflicting with Numerical.EPSILON comparison of the cross product in Line#intersect(). --- src/path/Curve.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/path/Curve.js b/src/path/Curve.js index a49cf6ae..74b560a0 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -760,8 +760,15 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{ return [0.5 * (w[0].x + w[5].x)]; // Compute intersection of chord from first control point to last // with x-axis. - if (isFlatEnough(w)) - return [xAxis.intersect(new Line(w[0], w[5], true)).x]; + if (isFlatEnough(w)) { + var line = new Line(w[0], w[5], true); + // Compare the line's squared length with EPSILON. If we're + // below, #intersect() will return null because of division + // by near-zero. + return [ line.vector.getLength(true) < Numerical.EPSILON + ? line.point.x + : xAxis.intersect(line).x ]; + } } // Otherwise, solve recursively after From d3241f2540f66d0d10499293b6b2ab8d87314a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 12:11:22 +0100 Subject: [PATCH 05/33] Port back changes from Parse-js HEAD and merge changes back into non-unicdoe version. --- lib/parse-js-min.js | 20 +++---- lib/parse-js-unicode.js | 114 +++++++++++++++++++++++++--------------- lib/parse-js.js | 81 ++++++++++++++-------------- 3 files changed, 123 insertions(+), 92 deletions(-) diff --git a/lib/parse-js-min.js b/lib/parse-js-min.js index 7c5a538e..c0bdddac 100644 --- a/lib/parse-js-min.js +++ b/lib/parse-js-min.js @@ -1,14 +1,14 @@ /** - * A JavaScript tokenizer / parser / generator. - * - * Distributed under the BSD license. - * + * A JavaScript tokenizer / parser / generator, originally written in Lisp. + * Copyright (c) Marijn Haverbeke + * http://marijn.haverbeke.nl/parse-js/ + * + * Ported by to JavaScript by Mihai Bazon * Copyright (c) 2010, Mihai Bazon * http://mihai.bazon.net/blog/ - * - * Modifications and adaption to browser (c) 2011, Juerg Lehni + * + * Modifications and adaptions to browser (c) 2011, Juerg Lehni * http://lehni.org/ - * - * Based on parse-js, (c) Marijn Haverbeke - * http://marijn.haverbeke.nl/parse-js/ - */var parse_js=new function(){function W(a,b,c){var d=[];for(var e=0;e=0;)if(b[c]===a)return!0;return!1}function Q(a){return a.split("")}function P(a,b){return Array.prototype.slice.call(a,b||0)}function O(a){var b={};for(var c=0;c0;++b)arguments[b]();return a}function M(a){var b=P(arguments,1);return function(){return a.apply(this,b.concat(P(arguments)))}}function L(a,b){function z(a){var b=a[0],c=r[b];if(!c)throw new Error("Can't find generator for \""+b+'"');y.push(a);var d=c.apply(b,a.slice(1));y.pop();return d}function x(a){var b=a[0],c=a[1];c!=null&&(b=k([g(b),"=",m(c,"seq")]));return b}function w(a){if(!a)return";";if(a.length==0)return"{}";return"{"+e+j(function(){return u(a).join(e)})+e+h("}")}function v(a){var b=a.length;if(b==0)return"{}";return"{"+e+W(a,function(a,d){var f=a[1].length>0,g=j(function(){return h(a[0]?k(["case",z(a[0])+":"]):"default:")},.5)+(f?e+j(function(){return u(a[1]).join(e)}):"");!c&&f&&d0?h(a):a}).join(e)},block:w,"var":function(a){return"var "+l(W(a,x))+";"},"const":function(a){return"const "+l(W(a,x))+";"},"try":function(a,b,c){var d=["try",w(a)];b&&d.push("catch","("+b[0]+")",w(b[1])),c&&d.push("finally",w(c));return k(d)},"throw":function(a){return k(["throw",z(a)])+";"},"new":function(a,b){b=b.length>0?"("+l(W(b,z))+")":"";return k(["new",m(a,"seq","binary","conditional","assign",function(a){var b=G(),c={};try{b.with_walkers({call:function(){throw c},"function":function(){return this}},function(){b.walk(a)})}catch(d){if(d===c)return!0;throw d}})+b])},"switch":function(a,b){return k(["switch","("+z(a)+")",v(b)])},"break":function(a){var b="break";a!=null&&(b+=" "+g(a));return b+";"},"continue":function(a){var b="continue";a!=null&&(b+=" "+g(a));return b+";"},conditional:function(a,b,c){return k([m(a,"assign","seq","conditional"),"?",m(b,"seq"),":",m(c,"seq")])},assign:function(a,b,c){a&&a!==!0?a+="=":a="=";return k([z(b),a,m(c,"seq")])},dot:function(a){var b=z(a),c=1;a[0]=="num"?/\./.test(a[1])||(b+="."):o(a)&&(b="("+b+")");while(cB[b[1]])d="("+d+")";if(R(c[0],["assign","conditional","seq"])||c[0]=="binary"&&B[a]>=B[c[1]]&&(c[1]!=a||!R(a,["&&","||","*"])))e="("+e+")";return k([d,a,e])},"unary-prefix":function(a,b){var c=z(b);b[0]=="num"||b[0]=="unary-prefix"&&!V(i,a+b[1])||!o(b)||(c="("+c+")");return a+(p(a.charAt(0))?" ":"")+c},"unary-postfix":function(a,b){var c=z(b);b[0]=="num"||b[0]=="unary-postfix"&&!V(i,a+b[1])||!o(b)||(c="("+c+")");return c+a},sub:function(a,b){var c=z(a);o(a)&&(c="("+c+")");return c+"["+z(b)+"]"},object:function(a){if(a.length==0)return"{}";return"{"+e+j(function(){return W(a,function(a){if(a.length==3)return h(t(a[0],a[1][2],a[1][3],a[2]));var d=a[0],e=z(a[1]);b.quote_keys?d=J(d):(typeof d=="number"||!c&&+d+""==d)&&parseFloat(d)>=0?d=q(+d):U(d)||(d=J(d));return h(k(c&&b.space_colon?[d,":",e]:[d+":",e]))}).join(","+e)})+e+h("}")},regexp:function(a,b){return"/"+a+"/"+b},array:function(a){if(a.length==0)return"[]";return k(["[",l(W(a,function(a){if(!c&&a[0]=="atom"&&a[1]=="undefined")return"";return m(a,"seq")})),"]"])},stat:function(a){return z(a).replace(/;*\s*$/,";")},seq:function(){return l(W(P(arguments),z))},label:function(a,b){return k([g(a),":",z(b)])},"with":function(a,b){return k(["with","("+z(a)+")",z(b)])},atom:function(a){return g(a)}},y=[];return z(a)}function J(a){var b=0,c=0;a=a.replace(/[\\\b\f\n\r\t\x22\x27]/g,function(a){switch(a){case"\\":return"\\\\";case"\b":return"\\b";case"\f":return"\\f";case"\n":return"\\n";case"\r":return"\\r";case"\t":return"\\t";case'"':++b;return'"';case"'":++c;return"'"}return a});return b>c?"'"+a.replace(/\x27/g,"\\'")+"'":'"'+a.replace(/\x22/g,'\\"')+'"'}function H(a){return!a||a[0]=="block"&&(!a[1]||a[1].length==0)}function G(){function g(a,b){var c={},e;for(e in a)V(a,e)&&(c[e]=d[e],d[e]=a[e]);var f=b();for(e in c)V(c,e)&&(c[e]?d[e]=c[e]:delete d[e]);return f}function f(a){if(a==null)return null;try{e.push(a);var b=a[0],f=d[b];if(f){var g=f.apply(a,a.slice(1));if(g!=null)return g}f=c[b];return f.apply(a,a.slice(1))}finally{e.pop()}}function b(a){var b=[this[0]];a!=null&&b.push(W(a,f));return b}function a(a){return[this[0],W(a,function(a){var b=[a[0]];a.length>1&&(b[1]=f(a[1]));return b})]}var c={string:function(a){return[this[0],a]},num:function(a){return[this[0],a]},name:function(a){return[this[0],a]},toplevel:function(a){return[this[0],W(a,f)]},block:b,splice:b,"var":a,"const":a,"try":function(a,b,c){return[this[0],W(a,f),b!=null?[b[0],W(b[1],f)]:null,c!=null?W(c,f):null]},"throw":function(a){return[this[0],f(a)]},"new":function(a,b){return[this[0],f(a),W(b,f)]},"switch":function(a,b){return[this[0],f(a),W(b,function(a){return[a[0]?f(a[0]):null,W(a[1],f)]})]},"break":function(a){return[this[0],a]},"continue":function(a){return[this[0],a]},conditional:function(a,b,c){return[this[0],f(a),f(b),f(c)]},assign:function(a,b,c){return[this[0],a,f(b),f(c)]},dot:function(a){return[this[0],f(a)].concat(P(arguments,1))},call:function(a,b){return[this[0],f(a),W(b,f)]},"function":function(a,b,c){return[this[0],a,b.slice(),W(c,f)]},defun:function(a,b,c){return[this[0],a,b.slice(),W(c,f)]},"if":function(a,b,c){return[this[0],f(a),f(b),f(c)]},"for":function(a,b,c,d){return[this[0],f(a),f(b),f(c),f(d)]},"for-in":function(a,b,c,d){return[this[0],f(a),f(b),f(c),f(d)]},"while":function(a,b){return[this[0],f(a),f(b)]},"do":function(a,b){return[this[0],f(a),f(b)]},"return":function(a){return[this[0],f(a)]},binary:function(a,b,c){return[this[0],a,f(b),f(c)]},"unary-prefix":function(a,b){return[this[0],a,f(b)]},"unary-postfix":function(a,b){return[this[0],a,f(b)]},sub:function(a,b){return[this[0],f(a),f(b)]},object:function(a){return[this[0],W(a,function(a){return a.length==2?[a[0],f(a[1])]:[a[0],f(a[1]),a[2]]})]},regexp:function(a,b){return[this[0],a,b]},array:function(a){return[this[0],W(a,f)]},stat:function(a){return[this[0],f(a)]},seq:function(){return[this[0]].concat(W(P(arguments),f))},label:function(a,b){return[this[0],a,f(b)]},"with":function(a,b){return[this[0],f(a),f(b)]},atom:function(a){return[this[0],a]}},d={},e=[];return{walk:f,with_walkers:g,parent:function(){return e[e.length-2]},stack:function(){return e}}}function F(a,b,c){function bk(a){try{++d.in_loop;return a()}finally{--d.in_loop}}function bi(a){var b=bg(a),c=d.token.value;if(e("operator")&&V(A,c)){if(bh(b)){g();return p("assign",A[c],b,bi(a))}i("Invalid assignment")}return b}function bh(a){if(!b)return!0;switch(a[0]){case"dot":case"sub":case"new":case"call":return!0;case"name":return a[1]!="this"}}function bg(a){var b=bf(a);if(e("operator","?")){g();var c=bj(!1);m(":");return p("conditional",b,c,bj(!1,a))}return b}function bf(a){return be(Y(!0),0,a)}function be(a,b,c){var f=e("operator")?d.token.value:null;f&&f=="in"&&c&&(f=null);var h=f!=null?B[f]:null;if(h!=null&&h>b){g();var i=be(Y(!0),h,c);return be(p("binary",f,a,i),b,c)}return a}function bd(a,b,c){(b=="++"||b=="--")&&!bh(c)&&i("Invalid use of "+b+" operator");return p(a,b,c)}function bc(a,b){if(e("punc",".")){g();return bc(p("dot",a,bb()),b)}if(e("punc","[")){g();return bc(p("sub",a,N(bj,M(m,"]"))),b)}if(b&&e("punc","(")){g();return bc(p("call",a,Z(")")),!0)}if(b&&e("operator")&&V(z,d.token.value))return N(M(bd,"unary-postfix",d.token.value,a),g);return a}function bb(){switch(d.token.type){case"name":case"operator":case"keyword":case"atom":return N(d.token.value,g);default:k()}}function ba(){switch(d.token.type){case"num":case"string":return N(d.token.value,g)}return bb()}function _(){var a=!0,c=[];while(!e("punc","}")){a?a=!1:m(",");if(!b&&e("punc","}"))break;var f=d.token.type,h=ba();f!="name"||h!="get"&&h!="set"||!!e("punc",":")?(m(":"),c.push([h,bj(!1)])):c.push([bb(),K(!1),h])}g();return p("object",c)}function $(){return p("array",Z("]",!b,!0))}function Z(a,b,c){var d=!0,f=[];while(!e("punc",a)){d?d=!1:m(",");if(b&&e("punc",a))break;e("punc",",")&&c?f.push(["atom","undefined"]):f.push(bj(!1))}g();return f}function X(){var a=Y(!1),b;e("punc","(")?(g(),b=Z(")")):b=[];return bc(p("new",a,b),!0)}function W(){return p("const",T())}function U(a){return p("var",T(a))}function T(a){var b=[];for(;;){e("name")||k();var c=d.token.value;g(),e("operator","=")?(g(),b.push([c,bj(!1,a)])):b.push([c]);if(!e("punc",","))break;g()}return b}function S(){var a=O(),b,c;if(e("keyword","catch")){g(),m("("),e("name")||i("Name expected");var f=d.token.value;g(),m(")"),b=[f,O()]}e("keyword","finally")&&(g(),c=O()),!b&&!c&&i("Missing catch/finally blocks");return p("try",a,b,c)}function O(){m("{");var a=[];while(!e("punc","}"))e("eof")&&k(),a.push(t());g();return a}function L(){var a=q(),b=t(),c;e("keyword","else")&&(g(),c=t());return p("if",a,b,c)}function J(a){var b=a[0]=="var"?p("name",a[1][0]):a;g();var c=bj();m(")");return p("for-in",a,b,c,bk(t))}function I(a){m(";");var b=e("punc",";")?null:bj();m(";");var c=e("punc",")")?null:bj();m(")");return p("for",a,b,c,bk(t))}function H(){m("(");var a=null;if(!e("punc",";")){a=e("keyword","var")?(g(),U(!0)):bj(!0,!0);if(e("operator","in"))return J(a)}return I(a)}function G(a){var b;n()||(b=e("name")?d.token.value:null),b!=null?(g(),R(b,d.labels)||i("Label "+b+" without matching loop or statement")):d.in_loop==0&&i(a+" not inside a loop or switch"),o();return p(a,b)}function F(){return p("stat",N(bj,o))}function w(a){d.labels.push(a);var c=d.token,e=t();b&&!V(C,e[0])&&k(c),d.labels.pop();return p("label",a,e)}function s(a){return c?function(){var b=d.token,c=a.apply(this,arguments);c[0]=r(c[0],b,h());return c}:a}function r(a,b,c){return a instanceof E?a:new E(a,b,c)}function q(){m("(");var a=bj();m(")");return a}function p(){return P(arguments)}function o(){e("punc",";")?g():n()||k()}function n(){return!b&&(d.token.nlb||e("eof")||e("punc","}"))}function m(a){return l("punc",a)}function l(a,b){if(e(a,b))return g();j(d.token,"Unexpected token "+d.token.type+", expected "+a)}function k(a){a==null&&(a=d.token),j(a,"Unexpected token: "+a.type+" ("+a.value+")")}function j(a,b){i(b,a.line,a.col)}function i(a,b,c,e){var f=d.input.context();u(a,b!=null?b:f.tokline,c!=null?c:f.tokcol,e!=null?e:f.tokpos)}function h(){return d.prev}function g(){d.prev=d.token,d.peeked?(d.token=d.peeked,d.peeked=null):d.token=d.input();return d.token}function f(){return d.peeked||(d.peeked=d.input())}function e(a,b){return v(d.token,a,b)}var d={input:typeof a=="string"?x(a,!0):a,token:null,prev:null,peeked:null,in_function:0,in_loop:0,labels:[]};d.token=g();var t=s(function(){e("operator","/")&&(d.peeked=null,d.token=d.input(!0));switch(d.token.type){case"num":case"string":case"regexp":case"operator":case"atom":return F();case"name":return v(f(),"punc",":")?w(N(d.token.value,g,g)):F();case"punc":switch(d.token.value){case"{":return p("block",O());case"[":case"(":return F();case";":g();return p("block");default:k()};case"keyword":switch(N(d.token.value,g)){case"break":return G("break");case"continue":return G("continue");case"debugger":o();return p("debugger");case"do":return function(a){l("keyword","while");return p("do",N(q,o),a)}(bk(t));case"for":return H();case"function":return K(!0);case"if":return L();case"return":d.in_function==0&&i("'return' outside of function");return p("return",e("punc",";")?(g(),null):n()?null:N(bj,o));case"switch":return p("switch",q(),Q());case"throw":return p("throw",N(bj,o));case"try":return S();case"var":return N(U,o);case"const":return N(W,o);case"while":return p("while",q(),bk(t));case"with":return p("with",q(),t());default:k()}}}),K=s(function(a){var b=e("name")?N(d.token.value,g):null;a&&!b&&k(),m("(");return p(a?"defun":"function",b,function(a,b){while(!e("punc",")"))a?a=!1:m(","),e("name")||k(),b.push(d.token.value),g();g();return b}(!0,[]),function(){++d.in_function;var a=d.in_loop;d.in_loop=0;var b=O();--d.in_function,d.in_loop=a;return b}())}),Q=M(bk,function(){m("{");var a=[],b=null;while(!e("punc","}"))e("eof")&&k(),e("keyword","case")?(g(),b=[],a.push([bj(),b]),m(":")):e("keyword","default")?(g(),m(":"),b=[],a.push([null,b])):(b||k(),b.push(t()));g();return a}),Y=s(function(a){if(e("operator","new")){g();return X()}if(e("operator")&&V(y,d.token.value))return bd("unary-prefix",N(d.token.value,g),Y(a));if(e("punc")){switch(d.token.value){case"(":g();return bc(N(bj,M(m,")")),a);case"[":g();return bc($(),a);case"{":g();return bc(_(),a)}k()}if(e("keyword","function")){g();return bc(K(!1),a)}if(V(D,d.token.type)){var b=d.token.type=="regexp"?p("regexp",d.token.value[0],d.token.value[1]):p(d.token.type,d.token.value);return bc(N(b,g),a)}k()}),bj=s(function(a,b){arguments.length==0&&(a=!0);var c=bi(b);if(a&&e("punc",",")){g();return p("seq",c,bj(!0,b))}return c});return p("toplevel",function(a){while(!e("eof"))a.push(t());return a}([]))}function E(a,b,c){this.name=a,this.start=b,this.end=c}function x(b){function O(a){if(a)return I();y(),v();var b=g();if(!b)return x("eof");if(o(b))return C();if(b=='"'||b=="'")return F();if(V(l,b))return x("punc",h());if(b==".")return L();if(b=="/")return K();if(V(e,b))return J();if(b=="\\"||q(b))return M();B("Unexpected character '"+b+"'")}function N(a,b){try{return b()}catch(c){if(c===w)B(a);else throw c}}function M(){var b=A(r);return V(a,b)?V(i,b)?x("operator",b):V(d,b)?x("atom",b):x("keyword",b):x("name",b)}function L(){h();return o(g())?C("."):x("punc",".")}function K(){h();var a=f.regex_allowed;switch(g()){case"/":f.comments_before.push(G()),f.regex_allowed=a;return O();case"*":f.comments_before.push(H()),f.regex_allowed=a;return O()}return f.regex_allowed?I():J("/")}function J(a){function b(a){if(!g())return a;var c=a+g();if(V(i,c)){h();return b(c)}return a}return x("operator",b(a||h()))}function I(){return N("Unterminated regular expression",function(){var a=!1,b="",c,d=!1;while(c=h(!0))if(a)b+="\\"+c,a=!1;else if(c=="[")d=!0,b+=c;else if(c=="]"&&d)d=!1,b+=c;else{if(c=="/"&&!d)break;c=="\\"?a=!0:b+=c}var e=A(function(a){return V(m,a)});return x("regexp",[b,e])})}function H(){h();return N("Unterminated multiline comment",function(){var a=t("*/",!0),b=f.text.substring(f.pos,a),c=x("comment2",b,!0);f.pos=a+2,f.line+=b.split("\n").length-1,f.newline_before=b.indexOf("\n")>=0;return c})}function G(){h();var a=t("\n"),b;a==-1?(b=f.text.substr(f.pos),f.pos=f.text.length):(b=f.text.substring(f.pos,a),f.pos=a);return x("comment1",b,!0)}function F(){return N("Unterminated string constant",function(){var a=h(),b="";for(;;){var c=h(!0);if(c=="\\")c=D();else if(c==a)break;b+=c}return x("string",b)})}function E(a){var b=0;for(;a>0;--a){var c=parseInt(h(!0),16);isNaN(c)&&B("Invalid hex-character pattern in string"),b=b<<4|c}return b}function D(){var a=h(!0);switch(a){case"n":return"\n";case"r":return"\r";case"t":return"\t";case"b":return"\b";case"v":return" ";case"f":return"\f";case"0":return"";case"x":return String.fromCharCode(E(2));case"u":return String.fromCharCode(E(4));default:return a}}function C(a){var b=!1,c=!1,d=!1,e=a==".",f=A(function(f,g){if(f=="x"||f=="X"){if(d)return!1;return d=!0}if(!d&&(f=="E"||f=="e")){if(b)return!1;return b=c=!0}if(f=="-"){if(c||g==0&&!a)return!0;return!1}if(f=="+")return c;c=!1;if(f=="."){if(!e&&!d)return e=!0;return!1}return p(f)});a&&(f=a+f);var g=s(f);if(!isNaN(g))return x("num",g);B("Invalid syntax: "+f)}function B(a){u(a,f.tokline,f.tokcol,f.tokpos)}function A(a){var b="",c=g(),d=0;while(c&&a(c,d++))b+=h(),c=g();return b}function y(){while(V(j,g()))h()}function x(a,b,d){f.regex_allowed=a=="operator"&&!V(z,b)||a=="keyword"&&V(c,b)||a=="punc"&&V(k,b);var e={type:a,value:b,line:f.tokline,col:f.tokcol,pos:f.tokpos,nlb:f.newline_before};d||(e.comments_before=f.comments_before,f.comments_before=[]),f.newline_before=!1;return e}function v(){f.tokline=f.line,f.tokcol=f.col,f.tokpos=f.pos}function t(a,b){var c=f.text.indexOf(a,f.pos);if(b&&c==-1)throw w;return c}function n(){return!f.peek()}function h(a){var b=f.text.charAt(f.pos++);if(a&&!b)throw w;b=="\n"?(f.newline_before=!0,++f.line,f.col=0):++f.col;return b}function g(){return f.text.charAt(f.pos)}var f={text:b.replace(/\r\n?|[\n\u2028\u2029]/g,"\n").replace(/^\uFEFF/,""),pos:0,tokpos:0,line:0,tokline:0,col:0,tokcol:0,newline_before:!1,regex_allowed:!1,comments_before:[]};O.context=function(a){a&&(f=a);return f};return O}function v(a,b,c){return a.type==b&&(c==null||a.value==c)}function u(a,b,c,d){throw new t(a,b,c,d)}function t(a,b,c,d){this.message=a,this.line=b,this.col=c,this.pos=d}function s(a){if(f.test(a))return parseInt(a.substr(2),16);if(g.test(a))return parseInt(a.substr(1),8);if(h.test(a))return parseFloat(a)}function r(a){return q(a)||o(a)}function q(a){return a=="$"||a=="_"||n(a)}function p(a){return o(a)||n(a)}function o(a){a=a.charCodeAt(0);return a>=48&&a<=57}function n(a){a=a.charCodeAt(0);return a>=65&&a<=90||a>=97&&a<=122}var a=O(["break","case","catch","const","continue","default","delete","do","else","finally","for","function","if","in","instanceof","new","return","switch","throw","try","typeof","var","void","while","with"]),b=O(["abstract","boolean","byte","char","class","debugger","double","enum","export","extends","final","float","goto","implements","import","int","interface","long","native","package","private","protected","public","short","static","super","synchronized","throws","transient","volatile"]),c=O(["return","new","delete","throw","else","case"]),d=O(["false","null","true","undefined"]),e=O(Q("+-*&%=<>!?|~^")),f=/^0x[0-9a-f]+$/i,g=/^0[0-7]+$/,h=/^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i,i=O(["in","instanceof","typeof","new","void","delete","++","--","+","-","!","~","&","|","^","*","/","%",">>","<<",">>>","<",">","<=",">=","==","===","!=","!==","?","=","+=","-=","/=","*=","%=",">>=","<<=",">>>=","|=","^=","&=","&&","||"]),j=O(Q(" \n\r\t")),k=O(Q("[{}(,.;:")),l=O(Q("[]{}(),;:")),m=O(Q("gmsiy"));t.prototype.toString=function(){return this.message+" (line: "+this.line+", col: "+this.col+", pos: "+this.pos+")"};var w={},y=O(["typeof","void","delete","--","++","!","~","-","+"]),z=O(["--","++"]),A=function(a,b,c){while(c>=","<<=",">>>=","|=","^=","&="],{"=":!0},0),B=function(a,b){for(var c=0,d=1;c","<=",">=","in","instanceof"],[">>","<<",">>>"],["+","-"],["*","/","%"]],{}),C=O(["for","do","while","switch"]),D=O(["atom","num","string","regexp","name"]);E.prototype.toString=function(){return this.name};var I=O(["name","array","object","string","dot","sub","call","regexp"]),K=O(["if","while","do","for","for-in","with"]);return{parse:F,gen_code:L,tokenizer:x,ast_walker:G}} \ No newline at end of file + * + * Distributed under the BSD license. + */var parse_js=new function(){function W(a,b,c){var d=[];for(var e=0;e0,g=j(function(){return h(a[0]?k(["case",z(a[0])+":"]):"default:")},.5)+(f?e+j(function(){return u(a[1]).join(e)}):"");!c&&f&&d0?h(a):a}).join(e)},block:w,"var":function(a){return"var "+l(W(a,x))+";"},"const":function(a){return"const "+l(W(a,x))+";"},"try":function(a,b,c){var d=["try",w(a)];b&&d.push("catch","("+b[0]+")",w(b[1])),c&&d.push("finally",w(c));return k(d)},"throw":function(a){return k(["throw",z(a)])+";"},"new":function(a,b){b=b.length>0?"("+l(W(b,z))+")":"";return k(["new",m(a,"seq","binary","conditional","assign",function(a){var b=N(),c={};try{b.with_walkers({call:function(){throw c},"function":function(){return this}},function(){b.walk(a)})}catch(d){if(d===c)return!0;throw d}})+b])},"switch":function(a,b){return k(["switch","("+z(a)+")",v(b)])},"break":function(a){var b="break";a!=null&&(b+=" "+g(a));return b+";"},"continue":function(a){var b="continue";a!=null&&(b+=" "+g(a));return b+";"},conditional:function(a,b,c){return k([m(a,"assign","seq","conditional"),"?",m(b,"seq"),":",m(c,"seq")])},assign:function(a,b,c){a&&a!==!0?a+="=":a="=";return k([z(b),a,m(c,"seq")])},dot:function(a){var b=z(a),c=1;a[0]=="num"?/\./.test(a[1])||(b+="."):o(a)&&(b="("+b+")");while(cB[b[1]])d="("+d+")";if(L(c[0],["assign","conditional","seq"])||c[0]=="binary"&&B[a]>=B[c[1]]&&(c[1]!=a||!L(a,["&&","||","*"])))e="("+e+")";return k([d,a,e])},"unary-prefix":function(a,b){var c=z(b);b[0]=="num"||b[0]=="unary-prefix"&&!M(i,a+b[1])||!o(b)||(c="("+c+")");return a+(p(a.charAt(0))?" ":"")+c},"unary-postfix":function(a,b){var c=z(b);b[0]=="num"||b[0]=="unary-postfix"&&!M(i,a+b[1])||!o(b)||(c="("+c+")");return c+a},sub:function(a,b){var c=z(a);o(a)&&(c="("+c+")");return c+"["+z(b)+"]"},object:function(a){return a.length==0?"{}":"{"+e+j(function(){return W(a,function(a){if(a.length==3)return h(t(a[0],a[1][2],a[1][3],a[2]));var d=a[0],e=z(a[1]);b.quote_keys?d=Q(d):(typeof d=="number"||!c&&+d+""==d)&&parseFloat(d)>=0?d=q(+d):V(d)||(d=Q(d));return h(k(c&&b.space_colon?[d,":",e]:[d+":",e]))}).join(","+e)})+e+h("}")},regexp:function(a,b){return"/"+a+"/"+b},array:function(a){return a.length==0?"[]":k(["[",l(W(a,function(a){return!c&&a[0]=="atom"&&a[1]=="undefined"?"":m(a,"seq")})),"]"])},stat:function(a){return z(a).replace(/;*\s*$/,";")},seq:function(){return l(W(J(arguments),z))},label:function(a,b){return k([g(a),":",z(b)])},"with":function(a,b){return k(["with","("+z(a)+")",z(b)])},atom:function(a){return g(a)}},y=[];return z(a)}function Q(a){var b=0,c=0;a=a.replace(/[\\\b\f\n\r\t\x22\x27]/g,function(a){switch(a){case"\\":return"\\\\";case"\b":return"\\b";case"\f":return"\\f";case"\n":return"\\n";case"\r":return"\\r";case"\t":return"\\t";case'"':++b;return'"';case"'":++c;return"'"}return a});return b>c?"'"+a.replace(/\x27/g,"\\'")+"'":'"'+a.replace(/\x22/g,'\\"')+'"'}function O(a){return!a||a[0]=="block"&&(!a[1]||a[1].length==0)}function N(){function g(a,b){var c={},e;for(e in a)M(a,e)&&(c[e]=d[e],d[e]=a[e]);var f=b();for(e in c)M(c,e)&&(c[e]?d[e]=c[e]:delete d[e]);return f}function f(a){if(a==null)return null;try{e.push(a);var b=a[0],f=d[b];if(f){var g=f.apply(a,a.slice(1));if(g!=null)return g}f=c[b];return f.apply(a,a.slice(1))}finally{e.pop()}}function b(a){var b=[this[0]];a!=null&&b.push(W(a,f));return b}function a(a){return[this[0],W(a,function(a){var b=[a[0]];a.length>1&&(b[1]=f(a[1]));return b})]}var c={string:function(a){return[this[0],a]},num:function(a){return[this[0],a]},name:function(a){return[this[0],a]},toplevel:function(a){return[this[0],W(a,f)]},block:b,splice:b,"var":a,"const":a,"try":function(a,b,c){return[this[0],W(a,f),b!=null?[b[0],W(b[1],f)]:null,c!=null?W(c,f):null]},"throw":function(a){return[this[0],f(a)]},"new":function(a,b){return[this[0],f(a),W(b,f)]},"switch":function(a,b){return[this[0],f(a),W(b,function(a){return[a[0]?f(a[0]):null,W(a[1],f)]})]},"break":function(a){return[this[0],a]},"continue":function(a){return[this[0],a]},conditional:function(a,b,c){return[this[0],f(a),f(b),f(c)]},assign:function(a,b,c){return[this[0],a,f(b),f(c)]},dot:function(a){return[this[0],f(a)].concat(J(arguments,1))},call:function(a,b){return[this[0],f(a),W(b,f)]},"function":function(a,b,c){return[this[0],a,b.slice(),W(c,f)]},defun:function(a,b,c){return[this[0],a,b.slice(),W(c,f)]},"if":function(a,b,c){return[this[0],f(a),f(b),f(c)]},"for":function(a,b,c,d){return[this[0],f(a),f(b),f(c),f(d)]},"for-in":function(a,b,c,d){return[this[0],f(a),f(b),f(c),f(d)]},"while":function(a,b){return[this[0],f(a),f(b)]},"do":function(a,b){return[this[0],f(a),f(b)]},"return":function(a){return[this[0],f(a)]},binary:function(a,b,c){return[this[0],a,f(b),f(c)]},"unary-prefix":function(a,b){return[this[0],a,f(b)]},"unary-postfix":function(a,b){return[this[0],a,f(b)]},sub:function(a,b){return[this[0],f(a),f(b)]},object:function(a){return[this[0],W(a,function(a){return a.length==2?[a[0],f(a[1])]:[a[0],f(a[1]),a[2]]})]},regexp:function(a,b){return[this[0],a,b]},array:function(a){return[this[0],W(a,f)]},stat:function(a){return[this[0],f(a)]},seq:function(){return[this[0]].concat(W(J(arguments),f))},label:function(a,b){return[this[0],a,f(b)]},"with":function(a,b){return[this[0],f(a),f(b)]},atom:function(a){return[this[0],a]}},d={},e=[];return{walk:f,with_walkers:g,parent:function(){return e[e.length-2]},stack:function(){return e}}}function M(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function L(a,b){for(var c=b.length;--c>=0;)if(b[c]===a)return!0;return!1}function K(a){return a.split("")}function J(a,b){return Array.prototype.slice.call(a,b||0)}function I(a){var b={};for(var c=0;c0;++b)arguments[b]();return a}function G(a){var b=J(arguments,1);return function(){return a.apply(this,b.concat(J(arguments)))}}function F(a,b,c){function bk(a){try{++d.in_loop;return a()}finally{--d.in_loop}}function bi(a){var b=bg(a),c=d.token.value;if(e("operator")&&M(A,c)){if(bh(b)){g();return p("assign",A[c],b,bi(a))}i("Invalid assignment")}return b}function bh(a){if(!b)return!0;switch(a[0]){case"dot":case"sub":case"new":case"call":return!0;case"name":return a[1]!="this"}}function bg(a){var b=bf(a);if(e("operator","?")){g();var c=bj(!1);m(":");return p("conditional",b,c,bj(!1,a))}return b}function bf(a){return be(Y(!0),0,a)}function be(a,b,c){var f=e("operator")?d.token.value:null;f&&f=="in"&&c&&(f=null);var h=f!=null?B[f]:null;if(h!=null&&h>b){g();var i=be(Y(!0),h,c);return be(p("binary",f,a,i),b,c)}return a}function bd(a,b,c){(b=="++"||b=="--")&&!bh(c)&&i("Invalid use of "+b+" operator");return p(a,b,c)}function bc(a,b){if(e("punc",".")){g();return bc(p("dot",a,bb()),b)}if(e("punc","[")){g();return bc(p("sub",a,H(bj,G(m,"]"))),b)}if(b&&e("punc","(")){g();return bc(p("call",a,Z(")")),!0)}return b&&e("operator")&&M(z,d.token.value)?H(G(bd,"unary-postfix",d.token.value,a),g):a}function bb(){switch(d.token.type){case"name":case"operator":case"keyword":case"atom":return H(d.token.value,g);default:k()}}function ba(){switch(d.token.type){case"num":case"string":return H(d.token.value,g)}return bb()}function _(){var a=!0,c=[];while(!e("punc","}")){a?a=!1:m(",");if(!b&&e("punc","}"))break;var f=d.token.type,h=ba();f!="name"||h!="get"&&h!="set"||!!e("punc",":")?(m(":"),c.push([h,bj(!1)])):c.push([bb(),P(!1),h])}g();return p("object",c)}function $(){return p("array",Z("]",!b,!0))}function Z(a,b,c){var d=!0,f=[];while(!e("punc",a)){d?d=!1:m(",");if(b&&e("punc",a))break;e("punc",",")&&c?f.push(["atom","undefined"]):f.push(bj(!1))}g();return f}function X(){var a=Y(!1),b;e("punc","(")?(g(),b=Z(")")):b=[];return bc(p("new",a,b),!0)}function W(){return p("const",U())}function V(a){return p("var",U(a))}function U(a){var b=[];for(;;){e("name")||k();var c=d.token.value;g(),e("operator","=")?(g(),b.push([c,bj(!1,a)])):b.push([c]);if(!e("punc",","))break;g()}return b}function T(){var a=R(),b,c;if(e("keyword","catch")){g(),m("("),e("name")||i("Name expected");var f=d.token.value;g(),m(")"),b=[f,R()]}e("keyword","finally")&&(g(),c=R()),!b&&!c&&i("Missing catch/finally blocks");return p("try",a,b,c)}function R(){m("{");var a=[];while(!e("punc","}"))e("eof")&&k(),a.push(t());g();return a}function Q(){var a=q(),b=t(),c;e("keyword","else")&&(g(),c=t());return p("if",a,b,c)}function O(a){var b=a[0]=="var"?p("name",a[1][0]):a;g();var c=bj();m(")");return p("for-in",a,b,c,bk(t))}function N(a){m(";");var b=e("punc",";")?null:bj();m(";");var c=e("punc",")")?null:bj();m(")");return p("for",a,b,c,bk(t))}function K(){m("(");var a=null;if(!e("punc",";")){a=e("keyword","var")?(g(),V(!0)):bj(!0,!0);if(e("operator","in"))return O(a)}return N(a)}function I(a){var b;n()||(b=e("name")?d.token.value:null),b!=null?(g(),L(b,d.labels)||i("Label "+b+" without matching loop or statement")):d.in_loop==0&&i(a+" not inside a loop or switch"),o();return p(a,b)}function F(){return p("stat",H(bj,o))}function w(a){d.labels.push(a);var c=d.token,e=t();b&&!M(C,e[0])&&k(c),d.labels.pop();return p("label",a,e)}function s(a){return c?function(){var b=d.token,c=a.apply(this,arguments);c[0]=r(c[0],b,h());return c}:a}function r(a,b,c){return a instanceof E?a:new E(a,b,c)}function q(){m("(");var a=bj();m(")");return a}function p(){return J(arguments)}function o(){e("punc",";")?g():n()||k()}function n(){return!b&&(d.token.nlb||e("eof")||e("punc","}"))}function m(a){return l("punc",a)}function l(a,b){if(e(a,b))return g();j(d.token,"Unexpected token "+d.token.type+", expected "+a)}function k(a){a==null&&(a=d.token),j(a,"Unexpected token: "+a.type+" ("+a.value+")")}function j(a,b){i(b,a.line,a.col)}function i(a,b,c,e){var f=d.input.context();u(a,b!=null?b:f.tokline,c!=null?c:f.tokcol,e!=null?e:f.tokpos)}function h(){return d.prev}function g(){d.prev=d.token,d.peeked?(d.token=d.peeked,d.peeked=null):d.token=d.input();return d.token}function f(){return d.peeked||(d.peeked=d.input())}function e(a,b){return v(d.token,a,b)}var d={input:typeof a=="string"?x(a,!0):a,token:null,prev:null,peeked:null,in_function:0,in_loop:0,labels:[]};d.token=g();var t=s(function(){e("operator","/")&&(d.peeked=null,d.token=d.input(!0));switch(d.token.type){case"num":case"string":case"regexp":case"operator":case"atom":return F();case"name":return v(f(),"punc",":")?w(H(d.token.value,g,g)):F();case"punc":switch(d.token.value){case"{":return p("block",R());case"[":case"(":return F();case";":g();return p("block");default:k()};case"keyword":switch(H(d.token.value,g)){case"break":return I("break");case"continue":return I("continue");case"debugger":o();return p("debugger");case"do":return function(a){l("keyword","while");return p("do",H(q,o),a)}(bk(t));case"for":return K();case"function":return P(!0);case"if":return Q();case"return":d.in_function==0&&i("'return' outside of function");return p("return",e("punc",";")?(g(),null):n()?null:H(bj,o));case"switch":return p("switch",q(),S());case"throw":return p("throw",H(bj,o));case"try":return T();case"var":return H(V,o);case"const":return H(W,o);case"while":return p("while",q(),bk(t));case"with":return p("with",q(),t());default:k()}}}),P=s(function(a){var b=e("name")?H(d.token.value,g):null;a&&!b&&k(),m("(");return p(a?"defun":"function",b,function(a,b){while(!e("punc",")"))a?a=!1:m(","),e("name")||k(),b.push(d.token.value),g();g();return b}(!0,[]),function(){++d.in_function;var a=d.in_loop;d.in_loop=0;var b=R();--d.in_function,d.in_loop=a;return b}())}),S=G(bk,function(){m("{");var a=[],b=null;while(!e("punc","}"))e("eof")&&k(),e("keyword","case")?(g(),b=[],a.push([bj(),b]),m(":")):e("keyword","default")?(g(),m(":"),b=[],a.push([null,b])):(b||k(),b.push(t()));g();return a}),Y=s(function(a){if(e("operator","new")){g();return X()}if(e("operator")&&M(y,d.token.value))return bd("unary-prefix",H(d.token.value,g),Y(a));if(e("punc")){switch(d.token.value){case"(":g();return bc(H(bj,G(m,")")),a);case"[":g();return bc($(),a);case"{":g();return bc(_(),a)}k()}if(e("keyword","function")){g();return bc(P(!1),a)}if(M(D,d.token.type)){var b=d.token.type=="regexp"?p("regexp",d.token.value[0],d.token.value[1]):p(d.token.type,d.token.value);return bc(H(b,g),a)}k()}),bj=s(function(a,b){arguments.length==0&&(a=!0);var c=bi(b);if(a&&e("punc",",")){g();return p("seq",c,bj(!0,b))}return c});return p("toplevel",function(a){while(!e("eof"))a.push(t());return a}([]))}function E(a,b,c){this.name=a,this.start=b,this.end=c}function x(b){function P(a){if(a)return I();y(),v();var b=g();if(!b)return x("eof");if(o(b))return C();if(b=='"'||b=="'")return F();if(M(l,b))return x("punc",h());if(b==".")return L();if(b=="/")return K();if(M(e,b))return J();if(b=="\\"||q(b))return N();B("Unexpected character '"+b+"'")}function O(a,b){try{return b()}catch(c){if(c===w)B(a);else throw c}}function N(){var b=A(r);return M(a,b)?M(i,b)?x("operator",b):M(d,b)?x("atom",b):x("keyword",b):x("name",b)}function L(){h();return o(g())?C("."):x("punc",".")}function K(){h();var a=f.regex_allowed;switch(g()){case"/":f.comments_before.push(G()),f.regex_allowed=a;return P();case"*":f.comments_before.push(H()),f.regex_allowed=a;return P()}return f.regex_allowed?I():J("/")}function J(a){function b(a){if(!g())return a;var c=a+g();if(M(i,c)){h();return b(c)}return a}return x("operator",b(a||h()))}function I(){return O("Unterminated regular expression",function(){var a=!1,b="",c,d=!1;while(c=h(!0))if(a)b+="\\"+c,a=!1;else if(c=="[")d=!0,b+=c;else if(c=="]"&&d)d=!1,b+=c;else{if(c=="/"&&!d)break;c=="\\"?a=!0:b+=c}var e=A(function(a){return M(m,a)});return x("regexp",[b,e])})}function H(){h();return O("Unterminated multiline comment",function(){var a=t("*/",!0),b=f.text.substring(f.pos,a),c=x("comment2",b,!0);f.pos=a+2,f.line+=b.split("\n").length-1,f.newline_before=b.indexOf("\n")>=0;return c})}function G(){h();var a=t("\n"),b;a==-1?(b=f.text.substr(f.pos),f.pos=f.text.length):(b=f.text.substring(f.pos,a),f.pos=a);return x("comment1",b,!0)}function F(){return O("Unterminated string constant",function(){var a=h(),b="";for(;;){var c=h(!0);if(c=="\\")c=D();else if(c==a)break;b+=c}return x("string",b)})}function E(a){var b=0;for(;a>0;--a){var c=parseInt(h(!0),16);isNaN(c)&&B("Invalid hex-character pattern in string"),b=b<<4|c}return b}function D(){var a=h(!0);switch(a){case"n":return"\n";case"r":return"\r";case"t":return"\t";case"b":return"\b";case"v":return" ";case"f":return"\f";case"0":return"";case"x":return String.fromCharCode(E(2));case"u":return String.fromCharCode(E(4));case"\n":return"";default:return a}}function C(a){var b=!1,c=!1,d=!1,e=a==".",f=A(function(f,g){if(f=="x"||f=="X")return d?!1:d=!0;if(!d&&(f=="E"||f=="e"))return b?!1:b=c=!0;if(f=="-")return c||g==0&&!a?!0:!1;if(f=="+")return c;c=!1;if(f==".")return!e&&!d?e=!0:!1;return p(f)});a&&(f=a+f);var g=s(f);if(!isNaN(g))return x("num",g);B("Invalid syntax: "+f)}function B(a){u(a,f.tokline,f.tokcol,f.tokpos)}function A(a){var b="",c=g(),d=0;while(c&&a(c,d++))b+=h(),c=g();return b}function y(){while(M(j,g()))h()}function x(a,b,d){f.regex_allowed=a=="operator"&&!M(z,b)||a=="keyword"&&M(c,b)||a=="punc"&&M(k,b);var e={type:a,value:b,line:f.tokline,col:f.tokcol,pos:f.tokpos,nlb:f.newline_before};d||(e.comments_before=f.comments_before,f.comments_before=[]),f.newline_before=!1;return e}function v(){f.tokline=f.line,f.tokcol=f.col,f.tokpos=f.pos}function t(a,b){var c=f.text.indexOf(a,f.pos);if(b&&c==-1)throw w;return c}function n(){return!f.peek()}function h(a){var b=f.text.charAt(f.pos++);if(a&&!b)throw w;b=="\n"?(f.newline_before=!0,++f.line,f.col=0):++f.col;return b}function g(){return f.text.charAt(f.pos)}var f={text:b.replace(/\r\n?|[\n\u2028\u2029]/g,"\n").replace(/^\uFEFF/,""),pos:0,tokpos:0,line:0,tokline:0,col:0,tokcol:0,newline_before:!1,regex_allowed:!1,comments_before:[]};P.context=function(a){a&&(f=a);return f};return P}function v(a,b,c){return a.type==b&&(c==null||a.value==c)}function u(a,b,c,d){throw new t(a,b,c,d)}function t(a,b,c,d){this.message=a,this.line=b,this.col=c,this.pos=d}function s(a){if(f.test(a))return parseInt(a.substr(2),16);if(g.test(a))return parseInt(a.substr(1),8);if(h.test(a))return parseFloat(a)}function r(a){return q(a)||o(a)}function q(a){return a=="$"||a=="_"||n(a)}function p(a){return o(a)||n(a)}function o(a){a=a.charCodeAt(0);return a>=48&&a<=57}function n(a){a=a.charCodeAt(0);return a>=65&&a<=90||a>=97&&a<=122}var a=I(["break","case","catch","const","continue","default","delete","do","else","finally","for","function","if","in","instanceof","new","return","switch","throw","try","typeof","var","void","while","with"]),b=I(["abstract","boolean","byte","char","class","debugger","double","enum","export","extends","final","float","goto","implements","import","int","interface","long","native","package","private","protected","public","short","static","super","synchronized","throws","transient","volatile"]),c=I(["return","new","delete","throw","else","case"]),d=I(["false","null","true","undefined"]),e=I(K("+-*&%=<>!?|~^")),f=/^0x[0-9a-f]+$/i,g=/^0[0-7]+$/,h=/^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i,i=I(["in","instanceof","typeof","new","void","delete","++","--","+","-","!","~","&","|","^","*","/","%",">>","<<",">>>","<",">","<=",">=","==","===","!=","!==","?","=","+=","-=","/=","*=","%=",">>=","<<=",">>>=","|=","^=","&=","&&","||"]),j=I(K(" \n\r\t")),k=I(K("[{}(,.;:")),l=I(K("[]{}(),;:")),m=I(K("gmsiy"));t.prototype.toString=function(){return this.message+" (line: "+this.line+", col: "+this.col+", pos: "+this.pos+")"};var w={},y=I(["typeof","void","delete","--","++","!","~","-","+"]),z=I(["--","++"]),A=function(a,b,c){while(c>=","<<=",">>>=","|=","^=","&="],{"=":!0},0),B=function(a,b){for(var c=0,d=1;c","<=",">=","in","instanceof"],[">>","<<",">>>"],["+","-"],["*","/","%"]],{}),C=I(["for","do","while","switch"]),D=I(["atom","num","string","regexp","name"]);E.prototype.toString=function(){return this.name};var P=I(["name","array","object","string","dot","sub","call","regexp"]),R=I(["if","while","do","for","for-in","with"]);return{parse:F,gen_code:S,tokenizer:x,ast_walker:N}} \ No newline at end of file diff --git a/lib/parse-js-unicode.js b/lib/parse-js-unicode.js index eda2dba1..6baa67f3 100644 --- a/lib/parse-js-unicode.js +++ b/lib/parse-js-unicode.js @@ -362,6 +362,7 @@ function tokenizer($TEXT) { case "0" : return "\0"; case "x" : return String.fromCharCode(hex_bytes(2)); case "u" : return String.fromCharCode(hex_bytes(4)); + case "\n": return ""; default : return ch; } }; @@ -382,7 +383,24 @@ function tokenizer($TEXT) { var quote = next(), ret = ""; for (;;) { var ch = next(true); - if (ch == "\\") ch = read_escaped_char(); + if (ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = read_escaped_char(); + } else if (ch == quote) break; ret += ch; } @@ -1200,6 +1218,47 @@ function parse($TEXT, exigent_mode, embed_tokens) { }; +/* -----[ Utilities ]----- */ + +function curry(f) { + var args = slice(arguments, 1); + return function() { return f.apply(this, args.concat(slice(arguments))); }; +}; + +function prog1(ret) { + if (ret instanceof Function) + ret = ret(); + for (var i = 1, n = arguments.length; --n > 0; ++i) + arguments[i](); + return ret; +}; + +function array_to_hash(a) { + var ret = {}; + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] === name) + return true; + return false; +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + /* -----[ helper for AST traversal ]----- */ function ast_walker() { @@ -1441,7 +1500,8 @@ function gen_code(ast, options) { quote_keys : false, space_colon : false, beautify : false, - ascii_only : false + ascii_only : false, + inline_script: false }); var beautify = !!options.beautify; var indentation = 0, @@ -1449,7 +1509,10 @@ function gen_code(ast, options) { space = beautify ? " " : ""; function encode_string(str) { - return make_string(str, options.ascii_only); + var ret = make_string(str, options.ascii_only); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; }; function make_name(name) { @@ -1705,6 +1768,10 @@ function gen_code(ast, options) { !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { right = "(" + right + ")"; } + else if (!beautify && options.inline_script && (operator == "<" || operator == "<<") + && rvalue[0] == "regexp" && /^script/i.test(rvalue[1])) { + right = " " + right; + } return add_spaces([ left, operator, right ]); }, "unary-prefix": function(operator, expr) { @@ -1735,7 +1802,7 @@ function gen_code(ast, options) { // body in p[1][3] and type ("get" / "set") in p[2]. return indent(make_function(p[0], p[1][2], p[1][3], p[2])); } - var key = p[0], val = make(p[1]); + var key = p[0], val = parenthesize(p[1], "seq"); if (options.quote_keys) { key = encode_string(key); } else if ((typeof key == "number" || !beautify && +key + "" == key) @@ -1888,41 +1955,6 @@ function gen_code(ast, options) { /* -----[ Utilities ]----- */ -function curry(f) { - var args = slice(arguments, 1); - return function() { return f.apply(this, args.concat(slice(arguments))); }; -}; - -function prog1(ret) { - if (ret instanceof Function) - ret = ret(); - for (var i = 1, n = arguments.length; --n > 0; ++i) - arguments[i](); - return ret; -}; - -function array_to_hash(a) { - var ret = {}; - for (var i = 0; i < a.length; ++i) - ret[a[i]] = true; - return ret; -}; - -function slice(a, start) { - return Array.prototype.slice.call(a, start || 0); -}; - -function characters(str) { - return str.split(""); -}; - -function member(name, array) { - for (var i = array.length; --i >= 0;) - if (array[i] === name) - return true; - return false; -}; - function repeat_string(str, i) { return i < 1 ? "" : new Array(i + 1).join(str); }; @@ -1945,10 +1977,6 @@ function is_identifier(name) { && !HOP(KEYWORDS, name); }; -function HOP(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -}; - function MAP(a, f, o) { var ret = []; for (var i = 0; i < a.length; ++i) { diff --git a/lib/parse-js.js b/lib/parse-js.js index 23e78ce9..749b715b 100644 --- a/lib/parse-js.js +++ b/lib/parse-js.js @@ -342,6 +342,7 @@ function tokenizer($TEXT) { case "0" : return "\0"; case "x" : return String.fromCharCode(hex_bytes(2)); case "u" : return String.fromCharCode(hex_bytes(4)); + case "\n": return ""; default : return ch; } }; @@ -1163,6 +1164,47 @@ function parse($TEXT, exigent_mode, embed_tokens) { }; +/* -----[ Utilities ]----- */ + +function curry(f) { + var args = slice(arguments, 1); + return function() { return f.apply(this, args.concat(slice(arguments))); }; +}; + +function prog1(ret) { + if (ret instanceof Function) + ret = ret(); + for (var i = 1, n = arguments.length; --n > 0; ++i) + arguments[i](); + return ret; +}; + +function array_to_hash(a) { + var ret = {}; + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] === name) + return true; + return false; +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + /* -----[ helper for AST traversal ]----- */ function ast_walker() { @@ -1832,41 +1874,6 @@ function gen_code(ast, options) { /* -----[ Utilities ]----- */ -function curry(f) { - var args = slice(arguments, 1); - return function() { return f.apply(this, args.concat(slice(arguments))); }; -}; - -function prog1(ret) { - if (ret instanceof Function) - ret = ret(); - for (var i = 1, n = arguments.length; --n > 0; ++i) - arguments[i](); - return ret; -}; - -function array_to_hash(a) { - var ret = {}; - for (var i = 0; i < a.length; ++i) - ret[a[i]] = true; - return ret; -}; - -function slice(a, start) { - return Array.prototype.slice.call(a, start || 0); -}; - -function characters(str) { - return str.split(""); -}; - -function member(name, array) { - for (var i = array.length; --i >= 0;) - if (array[i] === name) - return true; - return false; -}; - function repeat_string(str, i) { return i < 1 ? "" : new Array(i + 1).join(str); }; @@ -1889,10 +1896,6 @@ function is_identifier(name) { && !HOP(KEYWORDS, name); }; -function HOP(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -}; - function MAP(a, f, o) { var ret = []; for (var i = 0; i < a.length; ++i) { From 3c20f31a282b20687948a2a70b12b42379a59ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 12:11:49 +0100 Subject: [PATCH 06/33] Fix parse-js.sh script to work with new Prepro.js --- build/parse-js.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/parse-js.sh b/build/parse-js.sh index cbc6358c..7410b68a 100755 --- a/build/parse-js.sh +++ b/build/parse-js.sh @@ -17,4 +17,4 @@ # through the seperate source files in the src directory. Very useful during # development of the library itself. -./preprocess.sh ../lib/parse-js.js ../lib/parse-js-min.js "" uglified +./preprocess.sh compressed ../lib/parse-js.js ../lib/parse-js-min.js '{}' From e1d90c921c855d5298d25b914c753b2be33d959e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 12:14:37 +0100 Subject: [PATCH 07/33] Do not parse PaperScript code in exigent mode. Relaxes requirements of semicolons, etc. --- src/core/PaperScript.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/PaperScript.js b/src/core/PaperScript.js index 2f879558..ccb1721c 100644 --- a/src/core/PaperScript.js +++ b/src/core/PaperScript.js @@ -100,7 +100,7 @@ var PaperScript = this.PaperScript = new function() { // Use parse-js to translate the code into a AST structure which is then // walked and parsed for operators to overload. The resulting AST is // translated back to code and evaluated. - var ast = parse_js.parse(code, true), + var ast = parse_js.parse(code), walker = parse_js.ast_walker(), walk = walker.walk; From d84f0d34cf6dd30a8ed7e664aabc5e7cabb6d6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 14:13:29 +0100 Subject: [PATCH 08/33] Fix errors in DomElement.getOffset() by using native #getBoundingClientRect() in DomElement.getBounds() and relying on that. Closes #29 --- src/browser/DomElement.js | 151 +++++++++++++++----------------------- src/browser/DomEvent.js | 4 +- src/ui/View.js | 11 +-- 3 files changed, 69 insertions(+), 97 deletions(-) diff --git a/src/browser/DomElement.js b/src/browser/DomElement.js index 913d00ac..009d4c30 100644 --- a/src/browser/DomElement.js +++ b/src/browser/DomElement.js @@ -14,96 +14,67 @@ * All rights reserved. */ -var DomElement = new function() { - function cumulateOffset(el, name, parent, test) { - var left = name + 'Left', - top = name + 'Top', - x = 0, - y = 0, - style; - // If we're asked to calculate positioned offset, stop at any parent - // element that has relative or absolute position. - while (el && el.style && (!test || !test.test( - style = DomElement.getComputedStyle(el, 'position')))) { - x += el[left] || 0; - y += el[top] || 0; - el = el[parent]; +var DomElement = { + getBounds: function(el, viewport) { + var rect = el.getBoundingClientRect(), + doc = el.ownerDocument, + body = doc.body, + docEl = doc.documentElement, + x = rect.left - (docEl.clientLeft || body.clientLeft || 0), + y = rect.top - (docEl.clientTop || body.clientTop || 0); + if (!viewport) { + var win = DomElement.getViewport(doc); + x += win.pageXOffset || docEl.scrollLeft || body.scrollLeft; + y += win.pageYOffset || docEl.scrollTop || body.scrollTop; } - return { - offset: Point.create(x, y), - element: el, - style: style - }; + return new Rectangle(x, y, rect.width, rect.height); + }, + + getOffset: function(el, viewport) { + return this.getBounds(el, viewport).getPoint(); + }, + + getSize: function(el) { + return this.getBounds(el, true).getSize(); + }, + + /** + * Checks if element is invisibile (display: none, ...) + */ + isInvisible: function(el) { + return this.getSize(el).equals([0, 0]); + }, + + /** + * Checks if element is visibile in current viewport + */ + isVisible: function(el) { + // See if the viewport bounds intersect with the windows rectangle + // which always starts at 0, 0 + return !this.isInvisible(el) && this.getViewportBounds(el).intersects( + this.getBounds(el, false, true)); + }, + + getViewport: function(doc) { + return doc.defaultView || doc.parentWindow; + }, + + getViewportBounds: function(el) { + var doc = el.ownerDocument, + view = this.getViewport(doc), + body = doc.getElementsByTagName( + doc.compatMode === 'CSS1Compat' ? 'html' : 'body')[0]; + return Rectangle.create(0, 0, + view.innerWidth || body.clientWidth, + view.innerHeight || body.clientHeight + ); + }, + + getComputedStyle: function(el, name) { + if (el.currentStyle) + return el.currentStyle[Base.camelize(name)]; + var style = this.getViewport(el.ownerDocument) + .getComputedStyle(el, null); + return style ? style.getPropertyValue(Base.hyphenate(name)) : null; } - - function getScrollOffset(el, test) { - return cumulateOffset(el, 'scroll', 'parentNode', test).offset; - } - - return { - getOffset: function(el, positioned, viewport) { - var res = cumulateOffset(el, 'offset', 'offsetParent', - positioned ? /^(relative|absolute|fixed)$/ : /^fixed$/); - // We need to handle fixed positioned elements seperately if we're - // asked to calculate offsets within the page (= not within - // viewport), by adding their scroll offset to the result. - if (res.style == 'fixed' && !viewport) - return res.offset.add(getScrollOffset(res.element)); - // Otherwise remove scrolling from the calculated offset if we asked - // for viewport coordinates - return viewport - ? res.offset.subtract(getScrollOffset(el, /^fixed$/)) - : res.offset; - }, - - getSize: function(el) { - return Size.create(el.offsetWidth, el.offsetHeight); - }, - - getBounds: function(el, positioned, viewport) { - return new Rectangle(this.getOffset(el, positioned, viewport), - this.getSize(el)); - }, - - /** - * Checks if element is invisibile (display: none, ...) - */ - isInvisible: function(el) { - return this.getSize(el).equals([0, 0]); - }, - - /** - * Checks if element is visibile in current viewport - */ - isVisible: function(el) { - // See if the viewport bounds intersect with the windows rectangle - // which always starts at 0, 0 - return !this.isInvisible(el) - && new Rectangle([0, 0], this.getViewportSize(el)) - .intersects(this.getBounds(el, false, true)); - }, - - getViewport: function(doc) { - return doc.defaultView || doc.parentWindow; - }, - - getViewportSize: function(el) { - var doc = el.ownerDocument, - view = this.getViewport(doc), - body = doc.getElementsByTagName( - doc.compatMode === 'CSS1Compat' ? 'html' : 'body')[0]; - return Size.create( - view.innerWidth || body.clientWidth, - view.innerHeight || body.clientHeight - ); - }, - - getComputedStyle: function(el, name) { - if (el.currentStyle) - return el.currentStyle[Base.camelize(name)]; - var style = this.getViewport(el.ownerDocument) - .getComputedStyle(el, null); - return style ? style.getPropertyValue(Base.hyphenate(name)) : null; - } - }; }; diff --git a/src/browser/DomEvent.js b/src/browser/DomEvent.js index 771c3ac6..0bf7541f 100644 --- a/src/browser/DomEvent.js +++ b/src/browser/DomEvent.js @@ -60,8 +60,8 @@ var DomEvent = { getOffset: function(event, target) { // Remove target offsets from page coordinates - return DomEvent.getPoint(event).subtract( - DomElement.getOffset(target || DomEvent.getTarget(event), true)); + return DomEvent.getPoint(event).subtract(DomElement.getOffset( + target || DomEvent.getTarget(event))); }, preventDefault: function(event) { diff --git a/src/ui/View.js b/src/ui/View.js index 8be21d2c..42134110 100644 --- a/src/ui/View.js +++ b/src/ui/View.js @@ -42,9 +42,10 @@ var View = this.View = Base.extend(/** @lends View# */{ if (PaperScript.hasAttribute(canvas, 'resize')) { // Subtract canvas' viewport offset from the total size, to // stretch it in - var offset = DomElement.getOffset(canvas, false, true), + var offset = DomElement.getOffset(canvas, true), that = this; - size = DomElement.getViewportSize(canvas).subtract(offset); + size = DomElement.getViewportBounds(canvas) + .getSize().subtract(offset); canvas.width = size.width; canvas.height = size.height; DomEvent.add(window, { @@ -52,11 +53,11 @@ var View = this.View = Base.extend(/** @lends View# */{ // Only update canvas offset if it's not invisible, as // otherwise the offset would be wrong. if (!DomElement.isInvisible(canvas)) - offset = DomElement.getOffset(canvas, false, true); + offset = DomElement.getOffset(canvas, true); // Set the size now, which internally calls onResize // and redraws the view - that.setViewSize(DomElement.getViewportSize(canvas) - .subtract(offset)); + that.setViewSize(DomElement.getViewportBounds(canvas) + .getSize().subtract(offset)); } }); } else { From 13ae51789fe0c7b1bfb148aa30e1236eb38728d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 14:25:23 +0100 Subject: [PATCH 09/33] Remove reduntant argument, fixing visibility check. --- src/browser/DomElement.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/DomElement.js b/src/browser/DomElement.js index 009d4c30..c4e51c43 100644 --- a/src/browser/DomElement.js +++ b/src/browser/DomElement.js @@ -52,7 +52,7 @@ var DomElement = { // See if the viewport bounds intersect with the windows rectangle // which always starts at 0, 0 return !this.isInvisible(el) && this.getViewportBounds(el).intersects( - this.getBounds(el, false, true)); + this.getBounds(el, true)); }, getViewport: function(doc) { From f5bfa8f566088aa0480d82b2a04a4d8a2e0c2b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 15:20:49 +0100 Subject: [PATCH 10/33] Update JsDoc. --- build/jsdoc-toolkit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jsdoc-toolkit b/build/jsdoc-toolkit index 0bf4e2d0..27cac189 160000 --- a/build/jsdoc-toolkit +++ b/build/jsdoc-toolkit @@ -1 +1 @@ -Subproject commit 0bf4e2d0a1b4f887fbe0058b3299fc26dded4501 +Subproject commit 27cac18958485b03d6392d80b3391c482ed5ef8c From b14a294430e52ef70a26f021b433c2dbd4ecc2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 15:23:26 +0100 Subject: [PATCH 11/33] Delcare DomElement and DomEvent as private namespaces. --- src/browser/DomElement.js | 5 +++++ src/browser/DomEvent.js | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/browser/DomElement.js b/src/browser/DomElement.js index c4e51c43..b78da03e 100644 --- a/src/browser/DomElement.js +++ b/src/browser/DomElement.js @@ -14,6 +14,11 @@ * All rights reserved. */ +/** + * @name DomElement + * @namespace + * @private + */ var DomElement = { getBounds: function(el, viewport) { var rect = el.getBoundingClientRect(), diff --git a/src/browser/DomEvent.js b/src/browser/DomEvent.js index 0bf7541f..4e142cfc 100644 --- a/src/browser/DomEvent.js +++ b/src/browser/DomEvent.js @@ -14,6 +14,11 @@ * All rights reserved. */ +/** + * @name DomEvent + * @namespace + * @private + */ var DomEvent = { add: function(el, events) { for (var type in events) { From 42c9f9127977e69ce03c7910656cfbd97edacda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 15:26:09 +0100 Subject: [PATCH 12/33] Rename internal Matrix transform parameters to (a, c, b, d, tx, ty), expoes values through Matrix#getValues() and improve documentation. --- src/basic/Matrix.js | 393 ++++++++++++++++++++++---------------------- 1 file changed, 198 insertions(+), 195 deletions(-) diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js index 309ff4cd..16bc87e7 100644 --- a/src/basic/Matrix.js +++ b/src/basic/Matrix.js @@ -32,9 +32,9 @@ * by considering them to be a column vector and multiplying the coordinate * vector by the matrix according to the following process: *
- *      [ x ]   [  m00  m01  m02  ] [ x ]   [ m00 * x + m01 * y + m02 ]
- *      [ y ] = [  m10  m11  m12  ] [ y ] = [ m10 * x + m11 * y + m12 ]
- *      [ 1 ]   [   0    0    1   ] [ 1 ]   [            1            ]
+ *      [ x ]   [ a  b  tx ] [ x ]   [ a * x + b * y + tx ]
+ *      [ y ] = [ c  d  ty ] [ y ] = [ c * x + d * y + ty ]
+ *      [ 1 ]   [ 0  0  1  ] [ 1 ]   [         1          ]
  * 
* * This class is optimized for speed and minimizes calculations based on its @@ -45,12 +45,12 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ /** * Creates a 2D affine transform. * - * @param {Number} m00 The m00 coordinate of the transform. - * @param {Number} m10 The m10 coordinate of the transform. - * @param {Number} m01 The m01 coordinate of the transform. - * @param {Number} m11 The m11 coordinate of the transform. - * @param {Number} m02 The m02 coordinate of the transform. - * @param {Number} m12 The m12 coordinate of the transform. + * @param {Number} a The scaleX coordinate of the transform + * @param {Number} c The shearY coordinate of the transform + * @param {Number} b The shearX coordinate of the transform + * @param {Number} d The scaleY coordinate of the transform + * @param {Number} tx The translateX coordinate of the transform + * @param {Number} ty The translateY coordinate of the transform */ initialize: function(arg) { var count = arguments.length, @@ -59,16 +59,15 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ this.set.apply(this, arguments); } else if (count == 1) { if (arg instanceof Matrix) { - this.set(arg._m00, arg._m10, arg._m01, - arg._m11, arg._m02, arg._m12); + this.set(arg._a, arg._c, arg._b, arg._d, arg._tx, arg._ty); } else if (Array.isArray(arg)) { this.set.apply(this, arg); } else { ok = false; } } else if (count == 0) { - this._m00 = this._m11 = 1; - this._m10 = this._m01 = this._m02 = this._m12 = 0; + this._a = this._d = 1; + this._c = this._b = this._tx = this._ty = 0; } else { ok = false; } @@ -80,28 +79,28 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * @return {Matrix} A copy of this transform. */ clone: function() { - return Matrix.create(this._m00, this._m10, this._m01, - this._m11, this._m02, this._m12); + return Matrix.create(this._a, this._c, this._b, this._d, + this._tx, this._ty); }, /** * Sets this transform to the matrix specified by the 6 values. * - * @param {Number} m00 The m00 coordinate of the transform. - * @param {Number} m10 The m10 coordinate of the transform. - * @param {Number} m01 The m01 coordinate of the transform. - * @param {Number} m11 The m11 coordinate of the transform. - * @param {Number} m02 The m02 coordinate of the transform. - * @param {Number} m12 The m12 coordinate of the transform. - * @return {Matrix} This affine transform. + * @param {Number} a The scaleX coordinate of the transform + * @param {Number} c The shearY coordinate of the transform + * @param {Number} b The shearX coordinate of the transform + * @param {Number} d The scaleY coordinate of the transform + * @param {Number} tx The translateX coordinate of the transform + * @param {Number} ty The translateY coordinate of the transform + * @return {Matrix} This affine transform */ - set: function(m00, m10, m01, m11, m02, m12) { - this._m00 = m00; - this._m10 = m10; - this._m01 = m01; - this._m11 = m11; - this._m02 = m02; - this._m12 = m12; + set: function(a, c, b, d, tx, ty) { + this._a = a; + this._c = c; + this._b = b; + this._d = d; + this._tx = tx; + this._ty = ty; return this; }, @@ -110,21 +109,19 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * * @name Matrix#scale * @function - * @param {Number} scale The scaling factor. - * @param {Point} [center] The center for the scaling - * transformation. - * @return {Matrix} This affine transform. + * @param {Number} scale The scaling factor + * @param {Point} [center] The center for the scaling transformation + * @return {Matrix} This affine transform */ /** * Concatentates this transform with a scaling transformation. * * @name Matrix#scale * @function - * @param {Number} hor The horizontal scaling factor. - * @param {Number} ver The vertical scaling factor. - * @param {Point} [center] The center for the scaling - * transformation. - * @return {Matrix} This affine transform. + * @param {Number} hor The horizontal scaling factor + * @param {Number} ver The vertical scaling factor + * @param {Point} [center] The center for the scaling transformation + * @return {Matrix} This affine transform */ scale: function(hor, ver /* | scale */, center) { if (arguments.length < 2 || typeof ver === 'object') { @@ -138,10 +135,10 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ } if (center) this.translate(center); - this._m00 *= hor; - this._m10 *= hor; - this._m01 *= ver; - this._m11 *= ver; + this._a *= hor; + this._c *= hor; + this._b *= ver; + this._d *= ver; if (center) this.translate(center.negate()); return this; @@ -152,23 +149,23 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * * @name Matrix#translate * @function - * @param {Point} point The vector to translate by. - * @return {Matrix} This affine transform. + * @param {Point} point The vector to translate by + * @return {Matrix} This affine transform */ /** * Concatentates this transform with a translate transformation. * * @name Matrix#translate * @function - * @param {Number} dx The distance to translate in the x direction. - * @param {Number} dy The distance to translate in the y direction. - * @return {Matrix} This affine transform. + * @param {Number} dx The distance to translate in the x direction + * @param {Number} dy The distance to translate in the y direction + * @return {Matrix} This affine transform */ translate: function(point) { point = Point.read(arguments); var x = point.x, y = point.y; - this._m02 += x * this._m00 + y * this._m01; - this._m12 += x * this._m10 + y * this._m11; + this._tx += x * this._a + y * this._b; + this._ty += x * this._c + y * this._d; return this; }, @@ -178,9 +175,9 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * * @name Matrix#rotate * @function - * @param {Number} angle The angle of rotation measured in degrees. - * @param {Point} center The anchor point to rotate around. - * @return {Matrix} This affine transform. + * @param {Number} angle The angle of rotation measured in degrees + * @param {Point} center The anchor point to rotate around + * @return {Matrix} This affine transform */ /** * Concatentates this transform with a rotation transformation around an @@ -188,10 +185,10 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * * @name Matrix#rotate * @function - * @param {Number} angle The angle of rotation measured in degrees. - * @param {Number} x The x coordinate of the anchor point. - * @param {Number} y The y coordinate of the anchor point. - * @return {Matrix} This affine transform. + * @param {Number} angle The angle of rotation measured in degrees + * @param {Number} x The x coordinate of the anchor point + * @param {Number} y The y coordinate of the anchor point + * @return {Matrix} This affine transform */ rotate: function(angle, center) { return this.concatenate( @@ -203,19 +200,19 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * * @name Matrix#shear * @function - * @param {Point} point The shear factor in x and y direction. - * @param {Point} [center] The center for the shear transformation. - * @return {Matrix} This affine transform. + * @param {Point} point The shear factor in x and y direction + * @param {Point} [center] The center for the shear transformation + * @return {Matrix} This affine transform */ /** * Concatentates this transform with a shear transformation. * * @name Matrix#shear * @function - * @param {Number} hor The horizontal shear factor. - * @param {Number} ver The vertical shear factor. - * @param {Point} [center] The center for the shear transformation. - * @return {Matrix} This affine transform. + * @param {Number} hor The horizontal shear factor + * @param {Number} ver The vertical shear factor + * @param {Point} [center] The center for the shear transformation + * @return {Matrix} This affine transform */ shear: function(hor, ver, center) { // See #scale() for explanation of this: @@ -227,12 +224,12 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ } if (center) this.translate(center); - var m00 = this._m00; - var m10 = this._m10; - this._m00 += ver * this._m01; - this._m10 += ver * this._m11; - this._m01 += hor * m00; - this._m11 += hor * m10; + var a = this._a, + c = this._c; + this._a += ver * this._b; + this._c += ver * this._d; + this._b += hor * a; + this._d += hor * c; if (center) this.translate(center.negate()); return this; @@ -243,96 +240,104 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ */ toString: function() { var format = Base.formatNumber; - return '[[' + [format(this._m00), format(this._m01), - format(this._m02)].join(', ') + '], [' - + [format(this._m10), format(this._m11), - format(this._m12)].join(', ') + ']]'; + return '[[' + [format(this._a), format(this._b), + format(this._tx)].join(', ') + '], [' + + [format(this._c), format(this._d), + format(this._ty)].join(', ') + ']]'; }, /** - * The scaling factor in the x-direction (m00). + * The scaling factor in the x-direction ({@code a}). * * @name Matrix#scaleX * @type Number */ /** - * The scaling factor in the y-direction (m11). + * The scaling factor in the y-direction ({@code d}). * * @name Matrix#scaleY * @type Number */ /** - * The translation in the x-direction (m02). - * - * @name Matrix#translateX - * @type Number - */ - - /** - * The translation in the y-direction (m12). - * - * @name Matrix#translateY - * @type Number - */ - - /** - * @return {Number} The shear factor in the x-direction (m01). + * @return {Number} The shear factor in the x-direction ({@code b}). * * @name Matrix#shearX * @type Number */ /** - * @return {Number} The shear factor in the y-direction (m10). + * @return {Number} The shear factor in the y-direction ({@code c}). * * @name Matrix#shearY * @type Number */ + /** + * The translation in the x-direction ({@code tx}). + * + * @name Matrix#translateX + * @type Number + */ + + /** + * The translation in the y-direction ({@code ty}). + * + * @name Matrix#translateY + * @type Number + */ + + /** + * The transform values as an array, in the same sequence as they are passed + * to {@link #initialize(a, c, b, d, tx, ty)}. + * + * @type Number[] + * @bean + */ + getValues: function() { + return [ this._a, this._c, this._b, this._d, this._tx, this._ty ]; + }, + /** * Concatenates an affine transform to this transform. * - * @param {Matrix} mx The transform to concatenate. - * @return {Matrix} This affine transform. + * @param {Matrix} mx The transform to concatenate + * @return {Matrix} This affine transform */ concatenate: function(mx) { - var m0 = this._m00, - m1 = this._m01; - this._m00 = mx._m00 * m0 + mx._m10 * m1; - this._m01 = mx._m01 * m0 + mx._m11 * m1; - this._m02 += mx._m02 * m0 + mx._m12 * m1; - - m0 = this._m10; - m1 = this._m11; - this._m10 = mx._m00 * m0 + mx._m10 * m1; - this._m11 = mx._m01 * m0 + mx._m11 * m1; - this._m12 += mx._m02 * m0 + mx._m12 * m1; + var a = this._a, + b = this._b, + c = this._c, + d = this._d; + this._a = mx._a * a + mx._c * b; + this._b = mx._b * a + mx._d * b; + this._tx += mx._tx * a + mx._ty * b; + this._c = mx._a * c + mx._c * d; + this._d = mx._b * c + mx._d * d; + this._ty += mx._tx * c + mx._ty * d; return this; }, /** * Pre-concatenates an affine transform to this transform. * - * @param {Matrix} mx The transform to preconcatenate. - * @return {Matrix} This affine transform. + * @param {Matrix} mx The transform to preconcatenate + * @return {Matrix} This affine transform */ preConcatenate: function(mx) { - var m0 = this._m00, - m1 = this._m10; - this._m00 = mx._m00 * m0 + mx._m01 * m1; - this._m10 = mx._m10 * m0 + mx._m11 * m1; - - m0 = this._m01; - m1 = this._m11; - this._m01 = mx._m00 * m0 + mx._m01 * m1; - this._m11 = mx._m10 * m0 + mx._m11 * m1; - - m0 = this._m02; - m1 = this._m12; - this._m02 = mx._m00 * m0 + mx._m01 * m1 + mx._m02; - this._m12 = mx._m10 * m0 + mx._m11 * m1 + mx._m12; + var a = this._a, + b = this._b, + c = this._c, + d = this._d, + tx = this._tx, + ty = this._ty; + this._a = mx._a * a + mx._b * c; + this._c = mx._c * a + mx._d * c; + this._b = mx._a * b + mx._b * d; + this._d = mx._c * b + mx._d * d; + this._tx = mx._a * tx + mx._b * ty + mx._tx; + this._ty = mx._c * tx + mx._d * ty + mx._ty; return this; }, @@ -341,16 +346,15 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * the result. If an array is transformed, the the result is stored into a * destination array. * - * @param {Point} point The point to be transformed. - * + * @param {Point} point The point to be transformed * @param {Number[]} src The array containing the source points - * as x, y value pairs. - * @param {Number} srcOff The offset to the first point to be transformed. + * as x, y value pairs + * @param {Number} srcOff The offset to the first point to be transformed * @param {Number[]} dst The array into which to store the transformed - * point pairs. + * point pairs * @param {Number} dstOff The offset of the location of the first - * transformed point in the destination array. - * @param {Number} numPts The number of points to tranform. + * transformed point in the destination array + * @param {Number} numPts The number of points to tranform */ transform: function(/* point | */ src, srcOff, dst, dstOff, numPts) { return arguments.length < 5 @@ -369,8 +373,8 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ if (!dest) dest = new Point(Point.dont); return dest.set( - x * this._m00 + y * this._m01 + this._m02, - x * this._m10 + y * this._m11 + this._m12, + x * this._a + y * this._b + this._tx, + x * this._c + y * this._d + this._ty, dontNotify ); }, @@ -381,8 +385,8 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ while (i < srcEnd) { var x = src[i++]; var y = src[i++]; - dst[j++] = x * this._m00 + y * this._m01 + this._m02; - dst[j++] = x * this._m10 + y * this._m11 + this._m12; + dst[j++] = x * this._a + y * this._b + this._tx; + dst[j++] = x * this._c + y * this._d + this._ty; } return dst; }, @@ -418,60 +422,61 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ }, /** - * @return {Number} The determinant of this transform. + * @return {Number} The determinant of this transform */ getDeterminant: function() { - return this._m00 * this._m11 - this._m01 * this._m10; + return this._a * this._d - this._b * this._c; }, getTranslation: function() { - return new Point(this._m02, this._m12); + return new Point(this._tx, this._ty); }, getScaling: function() { - var hor = Math.sqrt(this._m00 * this._m00 + this._m10 * this._m10), - ver = Math.sqrt(this._m01 * this._m01 + this._m11 * this._m11); - return new Point(this._m00 < 0 ? -hor : hor, this._m01 < 0 ? -ver : ver); + var hor = Math.sqrt(this._a * this._a + this._c * this._c), + ver = Math.sqrt(this._b * this._b + this._d * this._d); + return new Point(this._a < 0 ? -hor : hor, this._b < 0 ? -ver : ver); }, /** - * @return {Number} The rotation angle of the matrix. If a non-uniform + * Returns the rotation angle of the matrix. If a non-uniform * rotation is applied as a result of a shear() or scale() command, * undefined is returned, as the resulting transformation cannot be - * expressed in one rotation angle. + * expressed in one rotation angle + * @return {Number} The rotation angle of the matrix */ getRotation: function() { - var angle1 = -Math.atan2(this._m01, this._m11), - angle2 = Math.atan2(this._m10, this._m00); + var angle1 = -Math.atan2(this._b, this._d), + angle2 = Math.atan2(this._c, this._a); return Math.abs(angle1 - angle2) < Numerical.TOLERANCE ? angle1 * 180 / Math.PI : undefined; }, /** - * @return {Boolean} Whether this transform is the identity transform. + * @return {Boolean} Whether this transform is the identity transform */ isIdentity: function() { - return this._m00 == 1 && this._m10 == 0 && this._m01 == 0 && - this._m11 == 1 && this._m02 == 0 && this._m12 == 0; + return this._a == 1 && this._c == 0 && this._b == 0 && this._d == 1 + && this._tx == 0 && this._ty == 0; }, /** * Returns whether the transform is invertible. A transform is not * invertible if the determinant is 0 or any value is non-finite or NaN. * - * @return {Boolean} Whether the transform is invertible. + * @return {Boolean} Whether the transform is invertible */ isInvertible: function() { var det = this.getDeterminant(); - return isFinite(det) && det != 0 && isFinite(this._m02) - && isFinite(this._m12); + return isFinite(det) && det != 0 && isFinite(this._tx) + && isFinite(this._ty); }, /** * Checks whether the matrix is singular or not. Singular matrices cannot be * inverted. * - * @return {Boolean} Whether the matrix is singular. + * @return {Boolean} Whether the matrix is singular */ isSingular: function() { return !this.isInvertible(); @@ -483,33 +488,33 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * returned. * * @return {Matrix} The inverted matrix, or {@code null }, if the matrix is - * singular. + * singular */ createInverse: function() { var det = this.getDeterminant(); - if (isFinite(det) && det != 0 && isFinite(this._m02) - && isFinite(this._m12)) { + if (isFinite(det) && det != 0 && isFinite(this._tx) + && isFinite(this._ty)) { return Matrix.create( - this._m11 / det, - -this._m10 / det, - -this._m01 / det, - this._m00 / det, - (this._m01 * this._m12 - this._m11 * this._m02) / det, - (this._m10 * this._m02 - this._m00 * this._m12) / det); + this._d / det, + -this._c / det, + -this._b / det, + this._a / det, + (this._b * this._ty - this._d * this._tx) / det, + (this._c * this._tx - this._a * this._ty) / det); } return null; }, createShiftless: function() { - return Matrix.create(this._m00, this._m10, this._m01, this._m11, 0, 0); + return Matrix.create(this._a, this._c, this._b, this._d, 0, 0); }, /** * Sets this transform to a scaling transformation. * - * @param {Number} hor The horizontal scaling factor. - * @param {Number} ver The vertical scaling factor. - * @return {Matrix} This affine transform. + * @param {Number} hor The horizontal scaling factor + * @param {Number} ver The vertical scaling factor + * @return {Matrix} This affine transform */ setToScale: function(hor, ver) { return this.set(hor, 0, 0, ver, 0, 0); @@ -518,9 +523,9 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ /** * Sets this transform to a translation transformation. * - * @param {Number} dx The distance to translate in the x direction. - * @param {Number} dy The distance to translate in the y direction. - * @return {Matrix} This affine transform. + * @param {Number} dx The distance to translate in the x direction + * @param {Number} dy The distance to translate in the y direction + * @return {Matrix} This affine transform */ setToTranslation: function(delta) { delta = Point.read(arguments); @@ -530,9 +535,9 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ /** * Sets this transform to a shearing transformation. * - * @param {Number} hor The horizontal shear factor. - * @param {Number} ver The vertical shear factor. - * @return {Matrix} This affine transform. + * @param {Number} hor The horizontal shear factor + * @param {Number} ver The vertical shear factor + * @return {Matrix} This affine transform */ setToShear: function(hor, ver) { return this.set(1, ver, hor, 1, 0, 0); @@ -541,10 +546,10 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ /** * Sets this transform to a rotation transformation. * - * @param {Number} angle The angle of rotation measured in degrees. - * @param {Number} x The x coordinate of the anchor point. - * @param {Number} y The y coordinate of the anchor point. - * @return {Matrix} This affine transform. + * @param {Number} angle The angle of rotation measured in degrees + * @param {Number} x The x coordinate of the anchor point + * @param {Number} y The y coordinate of the anchor point + * @return {Matrix} This affine transform */ setToRotation: function(angle, center) { center = Point.read(arguments, 1); @@ -566,25 +571,23 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ */ applyToContext: function(ctx, reset) { ctx[reset ? 'setTransform' : 'transform']( - this._m00, this._m10, this._m01, - this._m11, this._m02, this._m12 - ); + this._a, this._c, this._b, this._d, this._tx, this._ty); return this; }, statics: /** @lends Matrix */{ // See Point.create() - create: function(m00, m10, m01, m11, m02, m12) { - return new Matrix(Matrix.dont).set(m00, m10, m01, m11, m02, m12); + create: function(a, c, b, d, tx, ty) { + return new Matrix(Matrix.dont).set(a, c, b, d, tx, ty); }, /** * Creates a transform representing a scaling transformation. * - * @param {Number} hor The horizontal scaling factor. - * @param {Number} ver The vertical scaling factor. + * @param {Number} hor The horizontal scaling factor + * @param {Number} ver The vertical scaling factor * @return {Matrix} A transform representing a scaling - * transformation. + * transformation */ getScaleInstance: function(hor, ver) { var mx = new Matrix(); @@ -594,10 +597,10 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ /** * Creates a transform representing a translation transformation. * - * @param {Number} dx The distance to translate in the x direction. - * @param {Number} dy The distance to translate in the y direction. + * @param {Number} dx The distance to translate in the x direction + * @param {Number} dy The distance to translate in the y direction * @return {Matrix} A transform representing a translation - * transformation. + * transformation */ getTranslateInstance: function(delta) { var mx = new Matrix(); @@ -607,9 +610,9 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ /** * Creates a transform representing a shearing transformation. * - * @param {Number} hor The horizontal shear factor. - * @param {Number} ver The vertical shear factor. - * @return {Matrix} A transform representing a shearing transformation. + * @param {Number} hor The horizontal shear factor + * @param {Number} ver The vertical shear factor + * @return {Matrix} A transform representing a shearing transformation */ getShearInstance: function(hor, ver, center) { var mx = new Matrix(); @@ -619,10 +622,10 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ /** * Creates a transform representing a rotation transformation. * - * @param {Number} angle The angle of rotation measured in degrees. - * @param {Number} x The x coordinate of the anchor point. - * @param {Number} y The y coordinate of the anchor point. - * @return {Matrix} A transform representing a rotation transformation. + * @param {Number} angle The angle of rotation measured in degrees + * @param {Number} x The x coordinate of the anchor point + * @param {Number} y The y coordinate of the anchor point + * @return {Matrix} A transform representing a rotation transformation */ getRotateInstance: function(angle, center) { var mx = new Matrix(); @@ -631,12 +634,12 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ } }, new function() { return Base.each({ - scaleX: '_m00', - scaleY: '_m11', - translateX: '_m02', - translateY: '_m12', - shearX: '_m01', - shearY: '_m10' + scaleX: '_a', + scaleY: '_d', + translateX: '_tx', + translateY: '_ty', + shearX: '_b', + shearY: '_c' }, function(prop, name) { name = Base.capitalize(name); this['get' + name] = function() { From fc7da5fa13bcd26fdfddab3ab4d989a92592d8bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 15:46:26 +0100 Subject: [PATCH 13/33] Docs: Improve HSL example. --- src/color/Color.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/color/Color.js b/src/color/Color.js index 2274b38c..eb568b56 100644 --- a/src/color/Color.js +++ b/src/color/Color.js @@ -747,7 +747,7 @@ var HSLColor = this.HSLColor = Color.extend(/** @lends HSLColor# */{ * * // Create an HSLColor with a hue of 90 degrees, a saturation * // 100% and a lightness of 100%: - * circle.fillColor = new HSLColor(90, 1, 1); + * circle.fillColor = new HSLColor(90, 1, 0.5); */ _colorType: 'hsl' From da6f9234631962abb771c33a6ac216c04d3a5ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Sun, 31 Jul 2011 15:47:23 +0100 Subject: [PATCH 14/33] Update JsDoc. --- build/jsdoc-toolkit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jsdoc-toolkit b/build/jsdoc-toolkit index 27cac189..678f1ac3 160000 --- a/build/jsdoc-toolkit +++ b/build/jsdoc-toolkit @@ -1 +1 @@ -Subproject commit 27cac18958485b03d6392d80b3391c482ed5ef8c +Subproject commit 678f1ac39d6f78dda0bee723d51d1e3a286e5fd2 From e73a2df6b253d9bf5dc75d39ac8b6367cfd6c478 Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Sun, 31 Jul 2011 22:07:10 +0200 Subject: [PATCH 15/33] Update JsDoc. --- build/jsdoc-toolkit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jsdoc-toolkit b/build/jsdoc-toolkit index 27cac189..17d8366c 160000 --- a/build/jsdoc-toolkit +++ b/build/jsdoc-toolkit @@ -1 +1 @@ -Subproject commit 27cac18958485b03d6392d80b3391c482ed5ef8c +Subproject commit 17d8366c4f91ce9fa98e948755a63590a7871378 From e0650cae73ac67b406144d6c9c2875cf7d3dca73 Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Sun, 31 Jul 2011 22:58:51 +0200 Subject: [PATCH 16/33] Document HitResult, Item#hitTest(point, options) and Project#hitTest(point, options). --- src/item/HitResult.js | 58 +++++++++++++++++++++++++++++++++++++++++- src/item/Item.js | 37 +++++++++++++++++++++++++++ src/project/Project.js | 34 +++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/src/item/HitResult.js b/src/item/HitResult.js index b7904628..3d75cf33 100644 --- a/src/item/HitResult.js +++ b/src/item/HitResult.js @@ -17,7 +17,8 @@ /** * @name HitResult * - * @class + * @class A HitResult object contains information about the results of a hit + * test. * * @extends CurveLocation */ @@ -34,6 +35,61 @@ HitResult = Base.extend(/** @lends HitResult# */{ } }, + /** + * Describes the type of the hit result. For example, if you hit a segment + * point, the type would be 'segment'. + * + * @property + * @name HitResult#type + * @type String('segment', 'handle-in', 'handle-out', 'stroke', 'fill', + * 'bounds', 'center') + */ + + /** + * If the HitResult has a {@link HitResult#type} of 'bounds', this property + * describes which corner of the bounding rectangle was hit. + * + * @property + * @name HitResult#name + * @type String('top-left', 'top-right', 'bottom-left', 'bottom-right', + * 'left-center', 'top-center', 'right-center', 'bottom-center') + */ + + /** + * The item that was hit. + * + * @property + * @name HitResult#item + * @type Item + */ + + /** + * If the HitResult has a type of 'stroke', this property gives more + * information about the exact position that was hit on the path. + * + * @property + * @name HitResult#location + * @type CurveLocation + */ + + /** + * If the HitResult has a type of 'stroke', 'segment', 'handle-in' or + * 'handle-out', this property refers to the Segment that was hit or that + * is closest to the hitResult.location on the curve. + * + * @property + * @name HitResult#segment + * @type Segment + */ + + /** + * The hit point. + * + * @property + * @name HitResult#point + * @type Point + */ + statics: { /** * Merges default options into options hash for #hitTest() calls, and diff --git a/src/item/Item.js b/src/item/Item.js index 938bc79a..c8ec2c2f 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -682,6 +682,43 @@ var Item = this.Item = Base.extend(/** @lends Item# */{ return raster; }, + + + /** + * Perform a hit test on the item (and its children, if it is a + * {@link Group} or {@link Layer}) at the location of the specified point. + * + * The optional options object allows you to control the specifics of the + * hit test and may contain a combination of the following values: + * tolerance: {@code Number} - The tolerance of the hit test in + * points. + * type: Only hit test again a certain item + * type: {@link PathItem}, {@link Raster}, {@link TextItem}, etc. + * fill: {@code Boolean} - Hit test the fill of items. + * stroke: {@code Boolean} - Hit test the curves of path items, + * taking into account stroke width. + * segment: {@code Boolean} - Hit test for {@link Segment#point} of + * {@link Path} items. + * handles: {@code Boolean} - Hit test for the handles + * ({@link Segment#handleIn} / {@link Segment#handleOut}) of path segments. + * ends: {@code Boolean} - Only hit test for the first or last + * segment points of open path items. + * bounds: {@code Boolean} - Hit test the corners and side-centers + * of the bounding rectangle of items ({@link Item#bounds}). + * center: {@code Boolean} - Hit test the {@link Rectangle#center} + * of the bounding rectangle of items ({@link Item#bounds}). + * guide: {@code Boolean} - Hit test items that have + * {@link Item#guide} set to {@code true}. + * selected: {@code Boolean} - Only hit selected items. + * + * @param {Point} point The point where the hit test should be performed + * @param {Object} [options={ fill: true, stroke: true, segments: true, + * tolerance: 2 }] + * @param {Matrix} [matrix] + * @return {HitResult|null} A hit result object that contains more + * information about what exactly was hit or {@code null} if nothing was + * hit. + */ hitTest: function(point, options, matrix) { options = HitResult.getOptions(point, options); point = options.point; diff --git a/src/project/Project.js b/src/project/Project.js index 53764300..f432a873 100644 --- a/src/project/Project.js +++ b/src/project/Project.js @@ -181,6 +181,40 @@ var Project = this.Project = Base.extend(/** @lends Project# */{ this._selectedItems[i].setSelected(false); }, + /** + * Perform a hit test on the items contained within the project at the + * location of the specified point. + * + * The optional options object allows you to control the specifics of the + * hit test and may contain a combination of the following values: + * tolerance: {@code Number} - The tolerance of the hit test in + * points. + * type: Only hit test again a certain item + * type: {@link PathItem}, {@link Raster}, {@link TextItem}, etc. + * fill: {@code Boolean} - Hit test the fill of items. + * stroke: {@code Boolean} - Hit test the curves of path items, + * taking into account stroke width. + * segment: {@code Boolean} - Hit test for {@link Segment#point} of + * {@link Path} items. + * handles: {@code Boolean} - Hit test for the handles + * ({@link Segment#handleIn} / {@link Segment#handleOut}) of path segments. + * ends: {@code Boolean} - Only hit test for the first or last + * segment points of open path items. + * bounds: {@code Boolean} - Hit test the corners and side-centers + * of the bounding rectangle of items ({@link Item#bounds}). + * center: {@code Boolean} - Hit test the {@link Rectangle#center} + * of the bounding rectangle of items ({@link Item#bounds}). + * guide: {@code Boolean} - Hit test items that have + * {@link Item#guide} set to {@code true}. + * selected: {@code Boolean} - Only hit selected items. + * + * @param {Point} point The point where the hit test should be performed + * @param {Object} [options={ fill: true, stroke: true, segments: true, + * tolerance: true }] + * @return {HitResult|null} A hit result object that contains more + * information about what exactly was hit or {@code null} if nothing was + * hit. + */ hitTest: function(point, options) { options = HitResult.getOptions(point, options); point = options.point; From c6cf4f9cf0a83db8eb2bd165e156b9685eb80378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 08:52:51 +0100 Subject: [PATCH 17/33] Only create an empty Project for a PaperScope if a canvas was provided for it. --- src/core/PaperScope.js | 18 ++++++++++-------- src/core/PaperScript.js | 3 +-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/core/PaperScope.js b/src/core/PaperScope.js index 0a8f43b7..9bbaca56 100644 --- a/src/core/PaperScope.js +++ b/src/core/PaperScope.js @@ -39,26 +39,24 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ /** - * Creates a PaperScope object and an empty {@link Project} for it. If a - * canvas is provided, it also creates a {@link View} for it. - * Both project and view are linked to this scope. + * Creates a PaperScope object. If a canvas is provided, it also creates a + * an empty {@link Project} and a {@link View} for it, both linked to this + * scope. * * @name PaperScope#initialize * @function * @param {HTMLCanvasElement} canvas The canvas this scope should be - * associated with. + * associated with. */ initialize: function(canvas, script) { // script is only used internally, when creating scopes for PaperScript. // Whenever a PaperScope is created, it automatically becomes the active // one. paper = this; - this.views = []; this.view = null; + this.views = []; + this.project = null; this.projects = []; - // Since the global paper variable points to this PaperScope, the - // created project and view are automatically associated with it. - this.project = new Project(); this.tool = null; this.tools = []; var obj = script || canvas; @@ -72,6 +70,10 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ script.setAttribute('id', this._id); PaperScope._scopes[this._id] = this; if (canvas) { + // Create an empty project for the scope. + // Since the global paper variable points to this PaperScope, the + // created project and view are automatically associated with it. + this.project = new Project(); // Create a view for the canvas. this.view = new View(canvas); } diff --git a/src/core/PaperScript.js b/src/core/PaperScript.js index ccb1721c..6e8b8b31 100644 --- a/src/core/PaperScript.js +++ b/src/core/PaperScript.js @@ -144,8 +144,7 @@ var PaperScript = this.PaperScript = new function() { /** * Evaluates parsed PaperScript code in the passed {@link PaperScope} - * object. It also handles canvas setup, tool creation and handlers - * automatically for us. + * object. It also installs handlers automatically for us. * * @name PaperScript.evaluate * @function From 5b963b13e183f39da9ea65b06e767d60a2262515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 08:53:07 +0100 Subject: [PATCH 18/33] Export classes through PaperScope in dev mode too. --- src/core/initialize.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/core/initialize.js b/src/core/initialize.js index 38b59a39..10a96b6d 100644 --- a/src/core/initialize.js +++ b/src/core/initialize.js @@ -19,13 +19,19 @@ // that allow us to use their names. // Setting Function#name is not possible, as that is read-only. Base.each(this, function(val, key) { - if (val && val.prototype instanceof Base) + if (val && val.prototype instanceof Base) { val._name = key; +/*#*/ if (options.version == 'dev') { + // If we're in dev mode, also export all classes through PaperScope, to + // mimick scoping behavior of the built library. + PaperScope.prototype[key] = val; +/*#*/ } // options.version == 'dev' + } }); /*#*/ if (options.version == 'dev') { -// We're already leaking into the global scope, so let's just assign the global -// paper object with a prepare scope. See paper.js for the non-dev version of -// this code. +// See paper.js for the non-dev version of this code. We cannot handle dev there +// due to the seperate loading of all source files, which are only availabe +// after the execution of paper.js paper = new PaperScope(); /*#*/ } // options.version == 'dev' From 0e6aeac28c0b73ab5e6bd05ffeca1398b5858d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 08:53:28 +0100 Subject: [PATCH 19/33] Fix HSLColor documentation. --- src/color/Color.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/color/Color.js b/src/color/Color.js index eb568b56..6e296653 100644 --- a/src/color/Color.js +++ b/src/color/Color.js @@ -746,7 +746,7 @@ var HSLColor = this.HSLColor = Color.extend(/** @lends HSLColor# */{ * var circle = new Path.Circle(new Point(80, 50), 30); * * // Create an HSLColor with a hue of 90 degrees, a saturation - * // 100% and a lightness of 100%: + * // 100% and a lightness of 50%: * circle.fillColor = new HSLColor(90, 1, 0.5); */ From 6b6d5909c1ea4c315e2abb6cf0ffea9f7321a413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 11:01:27 +0100 Subject: [PATCH 20/33] Revert back to PaperScope#setup() and keep #initialize0 simple. --- src/core/PaperScope.js | 40 +++++++++++++++++++++++----------------- src/core/PaperScript.js | 3 ++- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/core/PaperScope.js b/src/core/PaperScope.js index 9bbaca56..2cd65362 100644 --- a/src/core/PaperScope.js +++ b/src/core/PaperScope.js @@ -39,16 +39,12 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ /** - * Creates a PaperScope object. If a canvas is provided, it also creates a - * an empty {@link Project} and a {@link View} for it, both linked to this - * scope. + * Creates a PaperScope object. * * @name PaperScope#initialize * @function - * @param {HTMLCanvasElement} canvas The canvas this scope should be - * associated with. */ - initialize: function(canvas, script) { + initialize: function(script) { // script is only used internally, when creating scopes for PaperScript. // Whenever a PaperScope is created, it automatically becomes the active // one. @@ -59,9 +55,9 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ this.projects = []; this.tool = null; this.tools = []; - var obj = script || canvas; - this._id = obj && obj.getAttribute('id') - || script && script.src + // Assign an id to this canvas that's either extracted from the script + // or automatically generated. + this._id = script && (script.getAttribute('id') || script.src) || ('paperscope-' + (PaperScope._id++)); // Make sure the script tag also has this id now. If it already had an // id, we're not changing it, since it's the first option we're @@ -69,14 +65,6 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ if (script) script.setAttribute('id', this._id); PaperScope._scopes[this._id] = this; - if (canvas) { - // Create an empty project for the scope. - // Since the global paper variable points to this PaperScope, the - // created project and view are automatically associated with it. - this.project = new Project(); - // Create a view for the canvas. - this.view = new View(canvas); - } }, /** @@ -145,6 +133,24 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ }, scope); }, + /** + * Sets up an empty project for us. If a canvas is provided, it also creates + * a {@link View} for it, both linked to this scope. + * + * @param {HTMLCanvasElement} canvas The canvas this scope should be + * associated with. + */ + setup: function(canvas) { + // Create an empty project for the scope. + // Make sure this is the active scope, so the created project and view + // are automatically associated with it. + paper = this; + this.project = new Project(); + // Create a view for the canvas. + if (canvas) + this.view = new View(canvas); + }, + clear: function() { // Remove all projects, views and tools. for (var i = this.projects.length - 1; i >= 0; i--) diff --git a/src/core/PaperScript.js b/src/core/PaperScript.js index 6e8b8b31..606aa832 100644 --- a/src/core/PaperScript.js +++ b/src/core/PaperScript.js @@ -239,7 +239,8 @@ var PaperScript = this.PaperScript = new function() { // so a project is created for it now. var canvas = PaperScript.getAttribute(script, 'canvas'); canvas = canvas && document.getElementById(canvas); - var scope = new PaperScope(canvas, script); + var scope = new PaperScope(script); + scope.setup(canvas); if (script.src) { // If we're loading from a source, request that first and then // run later. From 3fc21cd4b66c1ff8bfe3fa2f1c9266e36404df01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 11:02:00 +0100 Subject: [PATCH 21/33] Always call View#draw() since it won't redraw internally if nothing has changed. --- src/core/PaperScript.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/core/PaperScript.js b/src/core/PaperScript.js index 606aa832..d9b91dda 100644 --- a/src/core/PaperScript.js +++ b/src/core/PaperScript.js @@ -193,12 +193,9 @@ var PaperScript = this.PaperScript = new function() { } if (view) { view.onResize = onResize; - if (onFrame) { - view.setOnFrame(onFrame); - } else { - // Automatically draw view at the end. - view.draw(); - } + view.setOnFrame(onFrame); + // Automatically draw view at the end. + view.draw(); } }).call(scope); } From 8cdc5ea2aa4e4a24dc017e7ee35315bd7f61835f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 11:21:22 +0100 Subject: [PATCH 22/33] Change PaperScope#install() to be clever about project, view and tool references and link them through a getter to their current state in PaperScope. --- src/core/PaperScope.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/core/PaperScope.js b/src/core/PaperScope.js index 2cd65362..d9f3efe8 100644 --- a/src/core/PaperScope.js +++ b/src/core/PaperScope.js @@ -126,10 +126,22 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ * paper.install(window); */ install: function(scope) { + // Define project, view and tool as getters, so they are kept up to date + var that = this; + Base.each(['project', 'view', 'tool'], function(key) { + Base.define(scope, key, { + configurable: true, + writable: true, + get: function() { + return that[key]; + } + }); + }); // Use scope as side-car (= 'this' inside iterator), and have it // returned at the end. return Base.each(this, function(value, key) { - this[key] = value; + if (!(key in this)) + this[key] = value; }, scope); }, From 884ea96a29cd5d3e864d96d0bc7a85034701138c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 11:47:08 +0100 Subject: [PATCH 23/33] Docs: Link HitResult back to #hitTest() functions. --- src/item/HitResult.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/item/HitResult.js b/src/item/HitResult.js index 3d75cf33..cfa58b24 100644 --- a/src/item/HitResult.js +++ b/src/item/HitResult.js @@ -18,7 +18,8 @@ * @name HitResult * * @class A HitResult object contains information about the results of a hit - * test. + * test. It is returned by {@link Item#hitTest(point)} and + * {@link Project#hitTest(point)}. * * @extends CurveLocation */ From 31cc571e8a8fe9292977238e5bdf592b1923ad9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 11:47:42 +0100 Subject: [PATCH 24/33] Docs: Hide matrix parameter in Item#hitTest() and add "options." in front of each options property. --- src/item/Item.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/item/Item.js b/src/item/Item.js index c8ec2c2f..d31c15fd 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -692,30 +692,31 @@ var Item = this.Item = Base.extend(/** @lends Item# */{ * hit test and may contain a combination of the following values: * tolerance: {@code Number} - The tolerance of the hit test in * points. - * type: Only hit test again a certain item + * options.type: Only hit test again a certain item * type: {@link PathItem}, {@link Raster}, {@link TextItem}, etc. - * fill: {@code Boolean} - Hit test the fill of items. - * stroke: {@code Boolean} - Hit test the curves of path items, + * options.fill: {@code Boolean} - Hit test the fill of items. + * options.stroke: {@code Boolean} - Hit test the curves of path items, * taking into account stroke width. - * segment: {@code Boolean} - Hit test for {@link Segment#point} of + * options.segment: {@code Boolean} - Hit test for {@link Segment#point} of * {@link Path} items. - * handles: {@code Boolean} - Hit test for the handles + * options.handles: {@code Boolean} - Hit test for the handles * ({@link Segment#handleIn} / {@link Segment#handleOut}) of path segments. - * ends: {@code Boolean} - Only hit test for the first or last + * options.ends: {@code Boolean} - Only hit test for the first or last * segment points of open path items. - * bounds: {@code Boolean} - Hit test the corners and side-centers + * options.bounds: {@code Boolean} - Hit test the corners and side-centers * of the bounding rectangle of items ({@link Item#bounds}). - * center: {@code Boolean} - Hit test the {@link Rectangle#center} + * options.center: {@code Boolean} - Hit test the {@link Rectangle#center} * of the bounding rectangle of items ({@link Item#bounds}). - * guide: {@code Boolean} - Hit test items that have + * options.guide: {@code Boolean} - Hit test items that have * {@link Item#guide} set to {@code true}. - * selected: {@code Boolean} - Only hit selected items. + * options.selected: {@code Boolean} - Only hit selected items. * + * @name Item#hitTest + * @function * @param {Point} point The point where the hit test should be performed * @param {Object} [options={ fill: true, stroke: true, segments: true, * tolerance: 2 }] - * @param {Matrix} [matrix] - * @return {HitResult|null} A hit result object that contains more + * @return {HitResult} A hit result object that contains more * information about what exactly was hit or {@code null} if nothing was * hit. */ From c8578658ae3ce69e07b9792567bc581f7bc76735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 11:48:07 +0100 Subject: [PATCH 25/33] Docs: Remove |null from @return, since it's verbally described, and null can also be a HitResult. --- src/project/Project.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project/Project.js b/src/project/Project.js index f432a873..dc340494 100644 --- a/src/project/Project.js +++ b/src/project/Project.js @@ -211,7 +211,7 @@ var Project = this.Project = Base.extend(/** @lends Project# */{ * @param {Point} point The point where the hit test should be performed * @param {Object} [options={ fill: true, stroke: true, segments: true, * tolerance: true }] - * @return {HitResult|null} A hit result object that contains more + * @return {HitResult} A hit result object that contains more * information about what exactly was hit or {@code null} if nothing was * hit. */ From a8c08b33019654a3921c6ce9b68a8ac54edacce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 11:48:27 +0100 Subject: [PATCH 26/33] Docs: Document Path#getNearestLocation() and #getNearestPoint(). --- src/path/Path.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/path/Path.js b/src/path/Path.js index 1638b5b3..adacd97c 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -1174,6 +1174,15 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ return loc && loc.getNormal(); }, + /** + * Returns the nearest location on the path to the specified point. + * + * @name Path#getNearestLocation + * @function + * @param point {Point} The point for which we search the nearest location + * @return {CurveLocation} The location on the path that's the closest to + * the specified point + */ getNearestLocation: function(point, matrix) { var curves = this.getCurves(), minDist = Infinity, @@ -1188,6 +1197,15 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ return minLoc; }, + /** + * Returns the nearest point on the path to the specified point. + * + * @name Path#getNearestPoint + * @function + * @param point {Point} The point for which we search the nearest point + * @return {Point} The point on the path that's the closest to the specified + * point + */ getNearestPoint: function(point, matrix) { return this.getNearestLocation(point, matrix).getPoint(); }, From 14895f412c41deabbf8dabb95d702e8df0752e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 12:02:50 +0100 Subject: [PATCH 27/33] Fix PaperScope#install() so classes actually get injected. --- src/core/PaperScope.js | 15 +++++++++------ src/paper.js | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/core/PaperScope.js b/src/core/PaperScope.js index d9f3efe8..c430647e 100644 --- a/src/core/PaperScope.js +++ b/src/core/PaperScope.js @@ -137,12 +137,15 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ } }); }); - // Use scope as side-car (= 'this' inside iterator), and have it - // returned at the end. - return Base.each(this, function(value, key) { - if (!(key in this)) - this[key] = value; - }, scope); + // Copy over all fields from this scope to the destination. + // Do not use Base.each, since we also want to enumerate over + // fields on PaperScope.prototype, e.g. all classes + for (var key in this) { + if (!/^(version|_id|load)/.test(key) && !(key in scope)) { + console.log(key); + scope[key] = this[key]; + } + } }, /** diff --git a/src/paper.js b/src/paper.js index 051d025f..3e970546 100644 --- a/src/paper.js +++ b/src/paper.js @@ -127,6 +127,9 @@ var paper = new function() { // the first PaperScope and return it, all in one statement. // The version for 'dev' of this happens in core/initialize.js, since it depends // on sequentiality of include() loading. +// Mark this object as enumerable, so all the injected classes can be enumerated +// again in PaperScope#install(). +this.enumerable = true; return new (PaperScope.inject(this)); /*#*/ } // options.version != 'dev' }; From ea629fefda973bebf25925412a00eaca88a5fa2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 12:03:23 +0100 Subject: [PATCH 28/33] Remove debug log. --- src/core/PaperScope.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/PaperScope.js b/src/core/PaperScope.js index c430647e..17278285 100644 --- a/src/core/PaperScope.js +++ b/src/core/PaperScope.js @@ -141,10 +141,8 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{ // Do not use Base.each, since we also want to enumerate over // fields on PaperScope.prototype, e.g. all classes for (var key in this) { - if (!/^(version|_id|load)/.test(key) && !(key in scope)) { - console.log(key); + if (!/^(version|_id|load)/.test(key) && !(key in scope)) scope[key] = this[key]; - } } }, From 4fa6ffeb01bad27e8da1158c91a50b28c92c7e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 1 Aug 2011 12:05:06 +0100 Subject: [PATCH 29/33] Update docs and dist version to 0.2. --- dist/docs/classes/CharacterStyle.html | 1 + dist/docs/classes/Color.html | 1 + dist/docs/classes/CompoundPath.html | 78 + dist/docs/classes/Curve.html | 1 + dist/docs/classes/CurveLocation.html | 1 + dist/docs/classes/Event.html | 1 + dist/docs/classes/Gradient.html | 1 + dist/docs/classes/GradientColor.html | 1 + dist/docs/classes/GradientStop.html | 1 + dist/docs/classes/GrayColor.html | 1 + dist/docs/classes/Group.html | 78 + dist/docs/classes/HSBColor.html | 1 + dist/docs/classes/HSLColor.html | 5 +- dist/docs/classes/HitResult.html | 225 +- dist/docs/classes/Item.html | 78 + dist/docs/classes/Key.html | 1 + dist/docs/classes/KeyEvent.html | 1 + dist/docs/classes/Layer.html | 78 + dist/docs/classes/Line.html | 1 + dist/docs/classes/Matrix.html | 462 +++- dist/docs/classes/PaperScope.html | 475 ++++ dist/docs/classes/PaperScript.html | 137 + dist/docs/classes/ParagraphStyle.html | 1 + dist/docs/classes/Path.html | 168 ++ dist/docs/classes/PathItem.html | 78 + dist/docs/classes/PathStyle.html | 1 + dist/docs/classes/PlacedItem.html | 78 + dist/docs/classes/PlacedSymbol.html | 78 + dist/docs/classes/Point.html | 27 +- dist/docs/classes/PointText.html | 78 + dist/docs/classes/Project.html | 94 +- dist/docs/classes/RGBColor.html | 1 + dist/docs/classes/Raster.html | 78 + dist/docs/classes/Rectangle.html | 1 + dist/docs/classes/Segment.html | 1 + dist/docs/classes/Size.html | 1 + dist/docs/classes/Symbol.html | 1 + dist/docs/classes/TextItem.html | 78 + dist/docs/classes/Tool.html | 49 +- dist/docs/classes/ToolEvent.html | 36 + dist/docs/classes/View.html | 1 + dist/docs/classes/global.html | 82 +- dist/docs/classes/index.html | 10 + dist/docs/index.html | 1 + dist/docs/resources/js/paper.js | 3590 +++++++++++++++---------- dist/docs/resources/js/reference.js | 9 +- dist/paper.js | 578 ++-- 47 files changed, 4846 insertions(+), 1903 deletions(-) create mode 100644 dist/docs/classes/PaperScope.html create mode 100644 dist/docs/classes/PaperScript.html diff --git a/dist/docs/classes/CharacterStyle.html b/dist/docs/classes/CharacterStyle.html index 7b2ea6e5..b1692846 100644 --- a/dist/docs/classes/CharacterStyle.html +++ b/dist/docs/classes/CharacterStyle.html @@ -1,6 +1,7 @@ + CharacterStyle diff --git a/dist/docs/classes/Color.html b/dist/docs/classes/Color.html index 0bb10a72..55f39f9c 100644 --- a/dist/docs/classes/Color.html +++ b/dist/docs/classes/Color.html @@ -1,6 +1,7 @@ + Color diff --git a/dist/docs/classes/CompoundPath.html b/dist/docs/classes/CompoundPath.html index 7f9a8154..c946fad8 100644 --- a/dist/docs/classes/CompoundPath.html +++ b/dist/docs/classes/CompoundPath.html @@ -1,6 +1,7 @@ + CompoundPath @@ -2554,6 +2555,83 @@ raster.scale(5); + + + + + +
+ +
diff --git a/dist/docs/classes/Curve.html b/dist/docs/classes/Curve.html index 60a92a9b..97d51079 100644 --- a/dist/docs/classes/Curve.html +++ b/dist/docs/classes/Curve.html @@ -1,6 +1,7 @@ + Curve diff --git a/dist/docs/classes/CurveLocation.html b/dist/docs/classes/CurveLocation.html index cdea7328..86dbcaae 100644 --- a/dist/docs/classes/CurveLocation.html +++ b/dist/docs/classes/CurveLocation.html @@ -1,6 +1,7 @@ + CurveLocation diff --git a/dist/docs/classes/Event.html b/dist/docs/classes/Event.html index 519e7240..d0848eb9 100644 --- a/dist/docs/classes/Event.html +++ b/dist/docs/classes/Event.html @@ -1,6 +1,7 @@ + Event diff --git a/dist/docs/classes/Gradient.html b/dist/docs/classes/Gradient.html index 39f40ac1..f95530ea 100644 --- a/dist/docs/classes/Gradient.html +++ b/dist/docs/classes/Gradient.html @@ -1,6 +1,7 @@ + Gradient diff --git a/dist/docs/classes/GradientColor.html b/dist/docs/classes/GradientColor.html index f37eccdb..76f32a67 100644 --- a/dist/docs/classes/GradientColor.html +++ b/dist/docs/classes/GradientColor.html @@ -1,6 +1,7 @@ + GradientColor diff --git a/dist/docs/classes/GradientStop.html b/dist/docs/classes/GradientStop.html index 2d878d1d..97b43e0f 100644 --- a/dist/docs/classes/GradientStop.html +++ b/dist/docs/classes/GradientStop.html @@ -1,6 +1,7 @@ + GradientStop diff --git a/dist/docs/classes/GrayColor.html b/dist/docs/classes/GrayColor.html index 684c063c..0f3239e4 100644 --- a/dist/docs/classes/GrayColor.html +++ b/dist/docs/classes/GrayColor.html @@ -1,6 +1,7 @@ + GrayColor diff --git a/dist/docs/classes/Group.html b/dist/docs/classes/Group.html index 0fb07293..09964e3b 100644 --- a/dist/docs/classes/Group.html +++ b/dist/docs/classes/Group.html @@ -1,6 +1,7 @@ + Group @@ -1759,6 +1760,83 @@ raster.scale(5); + + + + + +
+ +
diff --git a/dist/docs/classes/HSBColor.html b/dist/docs/classes/HSBColor.html index 24842775..906ad8f2 100644 --- a/dist/docs/classes/HSBColor.html +++ b/dist/docs/classes/HSBColor.html @@ -1,6 +1,7 @@ + HSBColor diff --git a/dist/docs/classes/HSLColor.html b/dist/docs/classes/HSLColor.html index 30d50b4c..e36bfce4 100644 --- a/dist/docs/classes/HSLColor.html +++ b/dist/docs/classes/HSLColor.html @@ -1,6 +1,7 @@ + HSLColor @@ -92,8 +93,8 @@ between 0 and 1 var circle = new Path.Circle(new Point(80, 50), 30); // Create an HSLColor with a hue of 90 degrees, a saturation -// 100% and a lightness of 100%: -circle.fillColor = new HSLColor(90, 1, 1); +// 100% and a lightness of 50%: +circle.fillColor = new HSLColor(90, 1, 0.5);
diff --git a/dist/docs/classes/HitResult.html b/dist/docs/classes/HitResult.html index b3354ab4..a4d54a81 100644 --- a/dist/docs/classes/HitResult.html +++ b/dist/docs/classes/HitResult.html @@ -1,6 +1,7 @@ + HitResult @@ -18,7 +19,9 @@

Extends CurveLocation

- +

A HitResult object contains information about the results of a hit +test. It is returned by item.hitTest(point) and +project.hitTest(point).

@@ -26,15 +29,142 @@ +

Properties

+ + +
+ + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ +
-

The segment of the curve which is closer to the described location.

+

If the HitResult has a type of 'stroke', 'segment', 'handle-in' or +'handle-out', this property refers to the Segment that was hit or that +is closest to the hitResult.location on the curve.

    Type: @@ -65,6 +197,48 @@
+ + +
+ + +
+ +
+ + + + + + + +

Properties inherited from CurveLocation

@@ -264,39 +438,6 @@ the curve).

-
- - -
- -
+
+
+
+ + +
+ +
diff --git a/dist/docs/classes/Key.html b/dist/docs/classes/Key.html index b097b523..4f5f511f 100644 --- a/dist/docs/classes/Key.html +++ b/dist/docs/classes/Key.html @@ -1,6 +1,7 @@ + Key diff --git a/dist/docs/classes/KeyEvent.html b/dist/docs/classes/KeyEvent.html index 94501c50..3a19161f 100644 --- a/dist/docs/classes/KeyEvent.html +++ b/dist/docs/classes/KeyEvent.html @@ -1,6 +1,7 @@ + KeyEvent diff --git a/dist/docs/classes/Layer.html b/dist/docs/classes/Layer.html index baff005a..c9bfc7b2 100644 --- a/dist/docs/classes/Layer.html +++ b/dist/docs/classes/Layer.html @@ -1,6 +1,7 @@ + Layer @@ -1718,6 +1719,83 @@ raster.scale(5); + + + + + +
+ +
diff --git a/dist/docs/classes/Line.html b/dist/docs/classes/Line.html index ae89985f..fc195f83 100644 --- a/dist/docs/classes/Line.html +++ b/dist/docs/classes/Line.html @@ -1,6 +1,7 @@ + Line diff --git a/dist/docs/classes/Matrix.html b/dist/docs/classes/Matrix.html index 7d66bc14..586e9433 100644 --- a/dist/docs/classes/Matrix.html +++ b/dist/docs/classes/Matrix.html @@ -1,6 +1,7 @@ + Matrix @@ -25,9 +26,9 @@ transforms source coordinates (x,y) into destination coordinates (x',y') by considering them to be a column vector and multiplying the coordinate vector by the matrix according to the following process:

-     [ x']   [  m00  m01  m02  ] [ x ]   [ m00x + m01y + m02 ]
-     [ y'] = [  m10  m11  m12  ] [ y ] = [ m10x + m11y + m12 ]
-     [ 1 ]   [   0    0    1   ] [ 1 ]   [         1         ]
+     [ x ]   [ a  b  tx ] [ x ]   [ a * x + b * y + tx ]
+     [ y ] = [ c  d  ty ] [ y ] = [ c * x + d * y + ty ]
+     [ 1 ]   [ 0  0  1  ] [ 1 ]   [         1          ]
 

This class is optimized for speed and minimizes calculations based on its knowledge of the underlying matrix (as opposed to say simply performing @@ -39,18 +40,18 @@ matrix multiplication).

Constructors

-
- +
+
+ + +
+ +
diff --git a/dist/docs/classes/PathStyle.html b/dist/docs/classes/PathStyle.html index 6b8c6e6f..5e29a64b 100644 --- a/dist/docs/classes/PathStyle.html +++ b/dist/docs/classes/PathStyle.html @@ -1,6 +1,7 @@ + PathStyle diff --git a/dist/docs/classes/PlacedItem.html b/dist/docs/classes/PlacedItem.html index f4d533a9..18e366cf 100644 --- a/dist/docs/classes/PlacedItem.html +++ b/dist/docs/classes/PlacedItem.html @@ -1,6 +1,7 @@ + PlacedItem @@ -1665,6 +1666,83 @@ raster.scale(5); + + + + + +
+ +
diff --git a/dist/docs/classes/PlacedSymbol.html b/dist/docs/classes/PlacedSymbol.html index cc462023..de697a13 100644 --- a/dist/docs/classes/PlacedSymbol.html +++ b/dist/docs/classes/PlacedSymbol.html @@ -1,6 +1,7 @@ + PlacedSymbol @@ -1751,6 +1752,83 @@ raster.scale(5); + + + + + +
+ +
diff --git a/dist/docs/classes/Point.html b/dist/docs/classes/Point.html index d34f442c..16e29e6a 100644 --- a/dist/docs/classes/Point.html +++ b/dist/docs/classes/Point.html @@ -1,6 +1,7 @@ + Point @@ -1146,7 +1147,7 @@ is not modified!

    Returns:
  • -Point — the transformed point +Point — The transformed point
@@ -1160,18 +1161,18 @@ is not modified!

Distance & Length

-
- +
+ + +
+ +
diff --git a/dist/docs/classes/RGBColor.html b/dist/docs/classes/RGBColor.html index a5250e80..8af19b1a 100644 --- a/dist/docs/classes/RGBColor.html +++ b/dist/docs/classes/RGBColor.html @@ -1,6 +1,7 @@ + RGBColor diff --git a/dist/docs/classes/Raster.html b/dist/docs/classes/Raster.html index c7bf411d..bbe7eae3 100644 --- a/dist/docs/classes/Raster.html +++ b/dist/docs/classes/Raster.html @@ -1,6 +1,7 @@ + Raster @@ -2335,6 +2336,83 @@ raster.scale(5); + + + + + +
+ +
diff --git a/dist/docs/classes/Rectangle.html b/dist/docs/classes/Rectangle.html index c0ea7c8d..34eb81b2 100644 --- a/dist/docs/classes/Rectangle.html +++ b/dist/docs/classes/Rectangle.html @@ -1,6 +1,7 @@ + Rectangle diff --git a/dist/docs/classes/Segment.html b/dist/docs/classes/Segment.html index 4885b11f..6075d937 100644 --- a/dist/docs/classes/Segment.html +++ b/dist/docs/classes/Segment.html @@ -1,6 +1,7 @@ + Segment diff --git a/dist/docs/classes/Size.html b/dist/docs/classes/Size.html index 708a3a1e..30c692d1 100644 --- a/dist/docs/classes/Size.html +++ b/dist/docs/classes/Size.html @@ -1,6 +1,7 @@ + Size diff --git a/dist/docs/classes/Symbol.html b/dist/docs/classes/Symbol.html index ca995e70..1da24cec 100644 --- a/dist/docs/classes/Symbol.html +++ b/dist/docs/classes/Symbol.html @@ -1,6 +1,7 @@ + Symbol diff --git a/dist/docs/classes/TextItem.html b/dist/docs/classes/TextItem.html index d73a932b..afc089b0 100644 --- a/dist/docs/classes/TextItem.html +++ b/dist/docs/classes/TextItem.html @@ -1,6 +1,7 @@ + TextItem @@ -1772,6 +1773,83 @@ raster.scale(5); + + + + + +
+ +
diff --git a/dist/docs/classes/Tool.html b/dist/docs/classes/Tool.html index dac90d05..4a07cfce 100644 --- a/dist/docs/classes/Tool.html +++ b/dist/docs/classes/Tool.html @@ -1,6 +1,7 @@ + Tool @@ -49,54 +50,6 @@ function onMouseDrag(event) { - -

Constructors

- - -
- - -
- -
- diff --git a/dist/docs/classes/ToolEvent.html b/dist/docs/classes/ToolEvent.html index fef8e0f5..cc13b2dd 100644 --- a/dist/docs/classes/ToolEvent.html +++ b/dist/docs/classes/ToolEvent.html @@ -1,6 +1,7 @@ + ToolEvent @@ -273,6 +274,41 @@ difference to the mousedown position is returned.

+ + + + + + +
+ + diff --git a/dist/docs/classes/View.html b/dist/docs/classes/View.html index 1ba0d1d6..ad23c19a 100644 --- a/dist/docs/classes/View.html +++ b/dist/docs/classes/View.html @@ -1,6 +1,7 @@ + View diff --git a/dist/docs/classes/global.html b/dist/docs/classes/global.html index c4f63c7f..76ed322d 100644 --- a/dist/docs/classes/global.html +++ b/dist/docs/classes/global.html @@ -1,6 +1,7 @@ + _global_ @@ -27,28 +28,28 @@

Properties

-
-