* 'master' of https://github.com/paperjs/paper.js: (56 commits)
  Fix regressions in Raster caused by faulty merge.
  Store data in _data rather than on the image itself.
  Clean up @trankek's fix for node a bit.
  Explain compact = true in Project#_serialize()
  Properly fix issue with Project#exportJSON() creating separate projects on import.
  Update straps.js to version 1.1.0
  Rename options.server to options.node
  Remove all create() constructors for basic types since new constructors are now faster.
  Make sure project we import into is active.
  Unbox project data in Project#importJSON(), as we don't want to create a new project object.
  Remove need for _needsRedraw() calls by replacing it with a boolean flag.
  Apply "pending" matrix in group when it receives content.
  Move main Item insertion code from #insertChild() to #insertChildren().
  Fix documentation warning.
  Handle exporting of Numerical and PaperScript in export.js
  Update straps.js to latest version.
  Accessors cannot define the writable property.
  Properly export Numerical and PaperScript again.
  Only reset matrices in Groups when it could actually be applied to the content.
  Set options.stats = false for build.sh and Node.js
  ...
This commit is contained in:
hkrish 2013-05-29 19:09:07 +02:00
commit cdaab794f2
63 changed files with 834 additions and 893 deletions

View file

@ -31,4 +31,4 @@ then
fi
./preprocess.sh $MODE ../src/paper.js "-d '{ \"browser\": true }' -i '../src/constants.js'" ../dist/paper.js
#./preprocess.sh $MODE ../src/paper.js "-d '{ \"server\": true }' -i '../src/constants.js'" ../dist/paper-server.js
#./preprocess.sh $MODE ../src/paper.js "-d '{ \"node\": true }' -i '../src/constants.js'" ../dist/paper-node.js

View file

@ -24,10 +24,19 @@
# commented Preprocessed, still formated and commented
# stripped Preprocessed, formated but without comments
VERSION=0.8
# Get the date from the git log:
DATE=$(git log -1 --pretty=format:%ad)
COMMAND="./prepro.js -d '{ \"version\": $VERSION, \"date\": \"$DATE\", \"parser\": \"acorn\", \"svg\": true, \"fatline\": false }' $3 $2"
# Extract the paper.js version from package.json:
VERSION=$(node -e "
process.stdout.write(require('../package.json').version)
")
# Load and evaluate the options from options.js, and convert it an escaped json:
OPTIONS=$(printf '%q' $(node -e "
eval(require('fs').readFileSync('../src/options.js', 'utf8'));
process.stdout.write(JSON.stringify(options));
"))
# Build the prepo.js command out of it, passing on version and date as defines:
COMMAND="./prepro.js -d $OPTIONS -d '{ \"version\": \"$VERSION\", \"date\": \"$DATE\", \"stats\": false }' $3 $2"
case $1 in
commented)

View file

@ -1,4 +1,5 @@
// Uncomment this to turn on fatline clipping in paper.js too
options.fatline = true;
paper.install(window);
/**
@ -235,40 +236,40 @@ function runTests() {
prepareTest('Results - Boolean tests (Time taken per test)', container, 'big');
var x = 80.5, y = 15.5, width = 500, height = 190, i, txt, ny,
yy = y + height, xx = x + width;
var ppaperfill = new Path(), pfatfill = new Path();
var ppaper = new Path(), pfat = new Path();
var max = testdata.reduce(function(a, b) { return Math.max(a, b.paperTime + b.fatTime); }, 0) + 20;
var ppaper = new Path(),
pfat = new Path();
var max = testdata.reduce(function(a, b) {
return Math.max(a, b.paperTime + b.fatTime);
}, 0) + 20;
var vscale = height / max, hscale = width / testdata.length;
var caxes = '#999', ctxt = '#222', ctxt2 = '#555', cpaper = '#268BD2', cpaperfill ='#B5E1FF',
cfat = '#D33682', cfatfill = '#FFADD4';
new Path.Line(x, yy, xx, yy).style.strokeColor = caxes;
new Path.Line(x, yy, x, y).style.strokeColor = caxes;
new Path.Line(x, yy, xx, yy).strokeColor = caxes;
new Path.Line(x, yy, x, y).strokeColor = caxes;
for (i = 0; i < 10 ; i++) {
ny = yy - vscale * max * i / 10;
new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes;
new Path.Line(x, ny, x-5, ny).strokeColor = caxes;
txt = new PointText([x-10, ny]);
txt.justification = 'right';
txt.fillColor = (i%2)? ctxt: ctxt2;
txt.content = (max * i / 10).toFixed(1) + ((!i)? ' ms' : '');
}
ppaperfill.add(new Segment(x, yy));
pfatfill.add(new Segment(x, yy));
ppaper.add(x, yy);
pfat.add(x, yy);
var vx = x, clr = ctxt;
var coords = [], avgPaper = 0, avgFat = 0,
maxSpeedup = -Infinity, minSpeedup = Infinity, avgSpeedup = 0;
testdata.map(function(data) {
avgPaper += data.paperTime;
ny = yy - (data.paperTime + data.fatTime) * vscale;
ppaper.add(new Segment([vx, ny]));
ppaperfill.add(new Segment([vx, ny]));
ny = yy - (data.paperTime /*+ data.fatTime */) * vscale;
ppaper.add(vx, ny);
var np = new Point(vx, ny);
np._data = data;
np._datatype = 'paper';
coords.push(np);
avgFat += data.fatTime;
ny = yy - (data.fatTime) * vscale;
pfat.add(new Segment([vx, ny]));
pfatfill.add(new Segment([vx, ny]));
pfat.add(vx, ny);
np = new Point(vx, ny);
np._data = data;
np._datatype = 'fat';
@ -279,7 +280,7 @@ function runTests() {
if (speedup < minSpeedup) minSpeedup = speedup;
avgSpeedup += speedup;
new Path.Line(vx, yy, vx, yy + 5).style.strokeColor = caxes;
new Path.Line(vx, yy, vx, yy + 5).strokeColor = caxes;
txt = new PointText([vx, yy+18]);
txt.justification = 'left';
txt.fillColor = clr;
@ -288,23 +289,25 @@ function runTests() {
if (!data.success) {
var p = new Path.Line(vx, y, vx, yy);
p.style.strokeWidth = 5;
p.style.strokeColor = '#f00';
p.strokeWidth = 5;
p.strokeColor = '#f00';
}
clr = (clr === ctxt)? ctxt2 : ctxt;
vx += hscale;
});
ppaper.style.strokeWidth = 2;
ppaper.style.strokeColor = cpaper;
ppaperfill.add(new Segment(vx-hscale, yy));
ppaperfill.closed = true;
ppaperfill.style.fillColor = cpaperfill;
pfat.style.strokeWidth = 2;
pfat.style.strokeColor = cfat;
pfatfill.add(new Segment(vx-hscale, yy));
pfatfill.closed = true;
pfatfill.style.fillColor = cfatfill;
ppaper.strokeWidth = 2;
ppaper.strokeColor = cpaper;
ppaper.add(vx-hscale, yy);
ppaper.closed = true;
ppaper.fillColor = cpaperfill;
ppaper.opacity = 0.75;
pfat.strokeWidth = 2;
pfat.strokeColor = cfat;
pfat.add(vx-hscale, yy);
pfat.closed = true;
pfat.fillColor = cfatfill;
pfat.opacity = 0.75;
avgPaper/= testdata.length;
avgFat/= testdata.length;
@ -312,13 +315,13 @@ function runTests() {
maxSpeedup = Math.round(maxSpeedup);
minSpeedup = Math.round(minSpeedup);
ny = Math.round(yy - avgPaper * vscale) + 0.5;
new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper;
new Path.Line(x, ny, xx, ny).strokeColor = cpaper;
txt = new PointText([xx, ny]);
txt.justification = 'right';
txt.fillColor = cpaper;
txt.content = avgPaper.toFixed(1);
ny = Math.round(yy - avgFat * vscale) + 0.5;
new Path.Line(x, ny, xx, ny).style.strokeColor = cfat;
new Path.Line(x, ny, xx, ny).strokeColor = cfat;
txt = new PointText([xx, ny]);
txt.justification = 'right';
txt.fillColor = cfat;
@ -358,10 +361,10 @@ function runTests() {
if (dist > 500) { return; }
if (pnt && data) {
var p = new Path.Line(pnt.x+0.5, y, pnt.x+0.5, yy);
p.style.strokeColor = '#000';
p.strokeColor = '#000';
p.removeOnMove();
p = new Path.Circle(pnt, 3);
p.style.fillColor = (type === 'fat')? '#D33682' :'#268BD2';
p.fillColor = (type === 'fat')? '#D33682' :'#268BD2';
p.removeOnMove();
var txt = new PointText([ 500, 20 ]);
txt.content = 'subdiv : ' + data.paperTime.toFixed(1) + ' ms';
@ -563,8 +566,8 @@ function markPoint(pnt, t, c, tc, remove) {
c = c || '#000';
if (remove === undefined) { remove = true; }
var cir = new Path.Circle(pnt, 2);
cir.style.fillColor = c;
cir.style.strokeColor = tc;
cir.fillColor = c;
cir.strokeColor = tc;
if (t !== undefined || t !== null) {
var text = new PointText(pnt.add([0, -3]));
text.justification = 'center';
@ -588,7 +591,7 @@ function markCurve(crv, c, flag) {
new Segment([crv[0], crv[1]], null, [crv[2] - crv[0], crv[3] - crv[1]]),
new Segment([crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null)
);
window.__p1.style.strokeColor = c;
window.__p1.strokeColor = c;
// window.__p1.fullySelected = true;
} else {
if (window.__p2) window.__p2.remove();
@ -596,7 +599,7 @@ function markCurve(crv, c, flag) {
new Segment([crv[0], crv[1]], null, [crv[2] - crv[0], crv[3] - crv[1]]),
new Segment([crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null)
);
window.__p2.style.strokeColor = c;
window.__p2.strokeColor = c;
// window.__p2.fullySelected = true;
}
view.draw();
@ -624,8 +627,8 @@ function annotateSegment(s, t, c, tc, remove, skipCurves) {
var t1 = crv.getNormal(0).normalize(10);
var p = s.point.clone().add(t1);
var cir = new Path.Circle(s.point, 2);
cir.style.fillColor = c;
cir.style.strokeColor = tc;
cir.fillColor = c;
cir.strokeColor = tc;
var text = new PointText(p);
text.justification = 'center';
text.fillColor = c;
@ -657,8 +660,8 @@ function annotateCurve(crv, t, c, tc, remove) {
text.justification = 'center';
text.fillColor = tc;
text.content = t;
l.style.strokeColor = l2.style.strokeColor = c;
cir.style.fillColor = c;
l.strokeColor = l2.strokeColor = c;
cir.fillColor = c;
if (remove) {
l.removeOnMove();
l2.removeOnMove();
@ -677,11 +680,11 @@ function plotDataRandom(testdata) {
testdata.sort(function(a,b) { return a.ratio - b.ratio; });
var vscale = height / max, hscale = width / testdata.length;
var caxes = '#999', ctxt = '#222', cpaper = '#268BD2', cfat = '#D33682';
new Path.Line(x, yy, xx, yy).style.strokeColor = caxes;
new Path.Line(x, yy, x, y).style.strokeColor = caxes;
new Path.Line(x, yy, xx, yy).strokeColor = caxes;
new Path.Line(x, yy, x, y).strokeColor = caxes;
for (i = 0; i < 10 ; i++) {
ny = yy - vscale * max * i / 10;
new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes;
new Path.Line(x, ny, x-5, ny).strokeColor = caxes;
txt = new PointText([x-10, ny]);
txt.justification = 'right';
txt.fillColor = ctxt;
@ -699,13 +702,13 @@ function plotDataRandom(testdata) {
var avgPaper = 0, avgFat = 0;
testdata.map(function(data) {
avgPaper += data.paperTime;
ny = yy - (data.paperTime + data.fatTime) * vscale;
ppaper.add(new Segment([vx, ny]));
ny = yy - (data.paperTime /* + data.fatTime*/) * vscale;
ppaper.add(vx, ny);
avgFat += data.fatTime;
ny = yy - (data.fatTime) * vscale;
pfat.add(new Segment([vx, ny]));
pfat.add(vx, ny);
new Path.Line(vx, yy, vx, yy + 5 + ((count%2)? step:0)).style.strokeColor = caxes;
new Path.Line(vx, yy, vx, yy + 5 + ((count%2)? step:0)).strokeColor = caxes;
txt = new PointText([vx, yy+18 + ((count%2)? step:0) ]);
txt.justification = 'center';
txt.fillColor = ctxt;
@ -718,29 +721,31 @@ function plotDataRandom(testdata) {
if (!data.success) {
var p = new Path.Line(vx, y, vx, yy);
p.style.strokeWidth = 5;
p.style.strokeColor = '#f00';
p.strokeWidth = 5;
p.strokeColor = '#f00';
}
++count;
vx += hscale;
});
ppaper.smooth();
ppaper.style.strokeWidth = 2;
ppaper.style.strokeColor = cpaper;
pfat.smooth();
pfat.style.strokeWidth = 2;
pfat.style.strokeColor = cfat;
// ppaper.smooth();
ppaper.strokeWidth = 2;
ppaper.strokeColor = cpaper;
ppaper.opacity = 0.75;
// pfat.smooth();
pfat.strokeWidth = 2;
pfat.strokeColor = cfat;
pfat.opacity = 0.75;
avgPaper/= testdata.length;
avgFat/= testdata.length;
ny = Math.round(yy - avgPaper * vscale) + 0.5;
new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper;
new Path.Line(x, ny, xx, ny).strokeColor = cpaper;
txt = new PointText([xx, ny]);
txt.justification = 'right';
txt.fillColor = cpaper;
txt.content = avgPaper.toFixed(1);
ny = Math.round(yy - avgFat * vscale) + 0.5;
new Path.Line(x, ny, xx, ny).style.strokeColor = cfat;
new Path.Line(x, ny, xx, ny).strokeColor = cfat;
txt = new PointText([xx, ny]);
txt.justification = 'right';
txt.fillColor = cfat;
@ -749,80 +754,78 @@ function plotDataRandom(testdata) {
view.draw();
}
function drawFatline(v1) {
function signum(num) {
return (num > 0)? 1 : (num < 0)? -1 : 0;
}
var l = new Line([v1[0], v1[1]], [v1[6], v1[7]], false);
var p1 = new Point(v1[2], v1[3]), p2 = new Point(v1[4], v1[5]);
var d1 = l.getSide(p1) * l.getDistance(p1) || 0;
var d2 = l.getSide(p2) * l.getDistance(p2) || 0;
var dmin, dmax;
if (d1 * d2 > 0) {
// 3/4 * min{0, d1, d2}
dmin = 0.75 * Math.min(0, d1, d2);
dmax = 0.75 * Math.max(0, d1, d2);
} else {
// 4/9 * min{0, d1, d2}
dmin = 4 * Math.min(0, d1, d2) / 9.0;
dmax = 4 * Math.max(0, d1, d2) / 9.0;
}
var ll = new Path.Line(v1[0], v1[1], v1[6], v1[7]);
window.__p3.push(ll);
window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9, 0.8);
var lp1 = ll.segments[0].point;
var lp2 = ll.segments[1].point;
var pm = l.vector, pm1 = pm.rotate(signum(dmin) * -90), pm2 = pm.rotate(signum(dmax) * -90);
var p11 = lp1.add(pm1.normalize(Math.abs(dmin)));
var p12 = lp2.add(pm1.normalize(Math.abs(dmin)));
var p21 = lp1.add(pm2.normalize(Math.abs(dmax)));
var p22 = lp2.add(pm2.normalize(Math.abs(dmax)));
window.__p3.push(new Path.Line(p11, p12));
window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9);
window.__p3.push(new Path.Line(p21, p22));
window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9);
function signum(num) {
return (num > 0)? 1 : (num < 0)? -1 : 0;
}
var l = new Line([v1[0], v1[1]], [v1[6], v1[7]], false);
var p1 = new Point(v1[2], v1[3]), p2 = new Point(v1[4], v1[5]);
var d1 = l.getSide(p1) * l.getDistance(p1) || 0;
var d2 = l.getSide(p2) * l.getDistance(p2) || 0;
var dmin, dmax;
if (d1 * d2 > 0) {
// 3/4 * min{0, d1, d2}
dmin = 0.75 * Math.min(0, d1, d2);
dmax = 0.75 * Math.max(0, d1, d2);
} else {
// 4/9 * min{0, d1, d2}
dmin = 4 * Math.min(0, d1, d2) / 9.0;
dmax = 4 * Math.max(0, d1, d2) / 9.0;
}
var ll = new Path.Line(v1[0], v1[1], v1[6], v1[7]);
window.__p3.push(ll);
window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9, 0.8);
var lp1 = ll.segments[0].point;
var lp2 = ll.segments[1].point;
var pm = l.vector, pm1 = pm.rotate(signum(dmin) * -90), pm2 = pm.rotate(signum(dmax) * -90);
var p11 = lp1.add(pm1.normalize(Math.abs(dmin)));
var p12 = lp2.add(pm1.normalize(Math.abs(dmin)));
var p21 = lp1.add(pm2.normalize(Math.abs(dmax)));
var p22 = lp2.add(pm2.normalize(Math.abs(dmax)));
window.__p3.push(new Path.Line(p11, p12));
window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9);
window.__p3.push(new Path.Line(p21, p22));
window.__p3[window.__p3.length-1].strokeColor = new Color(0,0,0.9);
}
function plotD_vs_t(x, y, arr, arr2, v, dmin, dmax, tmin, tmax, yscale, tvalue) {
yscale = yscale || 1;
new Path.Line(x, y-100, x, y+100).style.strokeColor = '#aaa';
new Path.Line(x, y, x + 200, y).style.strokeColor = '#aaa';
yscale = yscale || 1;
new Path.Line(x, y-100, x, y+100).strokeColor = '#aaa';
new Path.Line(x, y, x + 200, y).strokeColor = '#aaa';
var clr = (tvalue)? '#a00' : '#00a';
if (window.__p3) window.__p3.map(function(a) {a.remove();});
var clr = (tvalue)? '#a00' : '#00a';
if (window.__p3) window.__p3.map(function(a) {a.remove();});
window.__p3 = [];
window.__p3 = [];
drawFatline(v);
drawFatline(v);
window.__p3.push(new Path.Line(x, y + dmin * yscale, x + 200, y + dmin * yscale));
window.__p3[window.__p3.length-1].style.strokeColor = '#000';
window.__p3.push(new Path.Line(x, y + dmax * yscale, x + 200, y + dmax * yscale));
window.__p3[window.__p3.length-1].style.strokeColor = '#000';
window.__p3.push(new Path.Line(x + tmin * 190, y-100, x + tmin * 190, y+100));
window.__p3[window.__p3.length-1].style.strokeColor = clr;
window.__p3.push(new Path.Line(x + tmax * 190, y-100, x + tmax * 190, y+100));
window.__p3[window.__p3.length-1].style.strokeColor = clr;
window.__p3.push(new Path.Line(x, y + dmin * yscale, x + 200, y + dmin * yscale));
window.__p3[window.__p3.length-1].strokeColor = '#000';
window.__p3.push(new Path.Line(x, y + dmax * yscale, x + 200, y + dmax * yscale));
window.__p3[window.__p3.length-1].strokeColor = '#000';
window.__p3.push(new Path.Line(x + tmin * 190, y-100, x + tmin * 190, y+100));
window.__p3[window.__p3.length-1].strokeColor = clr;
window.__p3.push(new Path.Line(x + tmax * 190, y-100, x + tmax * 190, y+100));
window.__p3[window.__p3.length-1].strokeColor = clr;
for (var i = 0; i < arr.length; i++) {
window.__p3.push(new Path.Line(new Point(x + arr[i][0] * 190, y + arr[i][1] * yscale),
new Point(x + arr[i][2] * 190, y + arr[i][3] * yscale)));
window.__p3[window.__p3.length-1].style.strokeColor = '#999';
}
var pnt = [];
var arr2x = [ 0.0, 0.333333333, 0.6666666666, 1.0 ];
for (var i = 0; i < arr2.length; i++) {
pnt.push(new Point(x + arr2x[i] * 190, y + arr2[i] * yscale));
window.__p3.push(new Path.Circle(pnt[pnt.length-1], 2));
window.__p3[window.__p3.length-1].style.fillColor = '#000';
}
// var pth = new Path(pnt[0], pnt[1], pnt[2], pnt[3]);
// pth.closed = true;
window.__p3.push(new Path(
new Segment(pnt[0], null, pnt[1].subtract(pnt[0])),
new Segment(pnt[3], pnt[2].subtract(pnt[3]), null)));
window.__p3[window.__p3.length-1].style.strokeColor = clr;
view.draw();
for (var i = 0; i < arr.length; i++) {
window.__p3.push(new Path.Line(new Point(x + arr[i][0] * 190, y + arr[i][1] * yscale),
new Point(x + arr[i][2] * 190, y + arr[i][3] * yscale)));
window.__p3[window.__p3.length-1].strokeColor = '#999';
}
var pnt = [];
var arr2x = [ 0.0, 0.333333333, 0.6666666666, 1.0 ];
for (var i = 0; i < arr2.length; i++) {
pnt.push(new Point(x + arr2x[i] * 190, y + arr2[i] * yscale));
window.__p3.push(new Path.Circle(pnt[pnt.length-1], 2));
window.__p3[window.__p3.length-1].fillColor = '#000';
}
// var pth = new Path(pnt[0], pnt[1], pnt[2], pnt[3]);
// pth.closed = true;
window.__p3.push(new Path(
new Segment(pnt[0], null, pnt[1].subtract(pnt[0])),
new Segment(pnt[3], pnt[2].subtract(pnt[3]), null)));
window.__p3[window.__p3.length-1].strokeColor = clr;
view.draw();
}

2
lib/acorn-min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -29,7 +29,7 @@
exports.version = "0.2.01";
// The main exported interface (under `this.acorn` when in the
// The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and
// returns an abstract syntax tree as specified by [Mozilla parser
// API][api], with the caveat that the SpiderMonkey-specific syntax
@ -407,7 +407,7 @@
var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/;
var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
var nonASCIIidentifierChars = "\u0371-\u0374\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
@ -1716,4 +1716,4 @@
return finishNode(node, "Identifier");
}
});
});

View file

@ -1,36 +1,31 @@
/**
* Straps.js - Inheritance library with support for bean-style accessors and
* AOP patterns.
* straps.js - Class inheritance library with support for bean-style accessors
*
* Copyright (c) 2006 - 2013 Juerg Lehni
* http://lehni.org/
*
* Distributed under the MIT license.
*
* straps.js was created by extracting and simplifying the inheritance code from
* boostrap.js, a JavaScript DOM library, also published by Juerg Lehni:
* straps.js was created by extracting and simplifying the inheritance framework
* from boostrap.js, a JavaScript DOM library, also published by Juerg Lehni:
* https://github.com/lehni/bootstrap.js
* The name was changed due to Twitter's introduction of their CSS framework
* with the same name.
*
* Inspirations:
* http://dean.edwards.name/weblog/2006/03/base/
* http://dev.helma.org/Wiki/JavaScript+Inheritance+Sugar/
*/
var Base = this.Base = new function() { // Straps scope
var Base = new function() {
var hidden = /^(statics|generics|preserve|enumerable|prototype|toString|valueOf)$/,
proto = Object.prototype,
toString = proto.toString,
toString = Object.prototype.toString,
proto = Array.prototype,
isArray = Array.isArray = Array.isArray || function(obj) {
return toString.call(obj) === '[object Array]';
},
slice = proto.slice,
forEach = proto.forEach || function(iter, bind) {
for (var i = 0, l = this.length; i < l; i++)
iter.call(bind, this[i], i, this);
},
forIn = function(iter, bind) {
// Do not use Object.keys for iteration as iterators might modify
// the object we're iterating over, making the hasOwnProperty still
@ -39,52 +34,54 @@ var Base = this.Base = new function() { // Straps scope
if (this.hasOwnProperty(i))
iter.call(bind, this[i], i, this);
},
// A ahort cut to a simplified version of Object.create that only
isArray = Array.isArray = Array.isArray || function(obj) {
return toString.call(obj) === '[object Array]';
},
// A short-cut to a simplified version of Object.create that only
// supports the first parameter (in the emulation):
create = Object.create || function(proto) {
// From all browsers that do not offer Object.create(), we only
// support Firefox 3.5 & 3.5, and this hack works there:
// support Firefox 3.5 & 3.6, and this hack works there:
return { __proto__: proto };
},
_define = Object.defineProperty,
_describe = Object.getOwnPropertyDescriptor;
// Support a mixed environment of some ECMAScript 5 features present,
// along with __defineGetter/Setter__ functions, as found in browsers today.
function define(obj, name, desc) {
// Unfortunately Safari seems to ignore configurable: true and
// does not override existing properties, so we need to delete
// first:
if (_define) {
try {
delete obj[name];
return _define(obj, name, desc);
} catch (e) {}
}
if ((desc.get || desc.set) && obj.__defineGetter__) {
if (desc.get) obj.__defineGetter__(name, desc.get);
if (desc.set) obj.__defineSetter__(name, desc.set);
} else {
obj[name] = desc.value;
}
return obj;
}
describe = Object.getOwnPropertyDescriptor || function(obj, name) {
// Emulate Object.getOwnPropertyDescriptor for outdated browsers
var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
return get
? { get: get, set: obj.__lookupSetter__(name),
enumerable: true, configurable: true }
: obj.hasOwnProperty(name)
? { value: obj[name], enumerable: true,
configurable: true, writable: true }
: null;
},
function describe(obj, name) {
if (_describe) {
try {
return _describe(obj, name);
} catch (e) {}
}
var get = obj.__lookupGetter__ && obj.__lookupGetter__(name);
return get
? { get: get, set: obj.__lookupSetter__(name), enumerable: true,
configurable: true }
: obj.hasOwnProperty(name)
? { value: obj[name], enumerable: true, configurable: true,
writable: true }
: null;
}
_define = Object.defineProperty || function(obj, name, desc) {
// Emulate Object.defineProperty for outdated browsers
if ((desc.get || desc.set) && obj.__defineGetter__) {
if (desc.get)
obj.__defineGetter__(name, desc.get);
if (desc.set)
obj.__defineSetter__(name, desc.set);
} else {
obj[name] = desc.value;
}
return obj;
},
define = function(obj, name, desc) {
// Both Safari and Chrome at one point ignored configurable = true
// and did not allow overriding of existing properties:
// https://code.google.com/p/chromium/issues/detail?id=72736
// https://bugs.webkit.org/show_bug.cgi?id=54289
// The workaround is to delete the property first.
// TODO: Remove this fix in July 2014, and use _define directly.
delete obj[name];
return _define(obj, name, desc);
};
/**
* Private function that injects functions from src into dest, overriding
@ -109,58 +106,34 @@ var Base = this.Base = new function() { // Straps scope
// string values starting with '#'
if (typeof val === 'string' && val[0] === '#')
val = src[val.substring(1)] || val;
var func = typeof val === 'function',
var isFunc = typeof val === 'function',
res = val,
// Only lookup previous value if we preserve or define a
// function that might need it for this.base(). If we're
// defining a getter, don't lookup previous value, but look if
// the property exists (name in dest) and store result in prev
prev = preserve || func
prev = preserve || isFunc
? (val && val.get ? name in dest : dest[name]) : null;
if ((dontCheck || val !== undefined && src.hasOwnProperty(name))
&& (!preserve || !prev)) {
if (func) {
if (prev && /\bthis\.base\b/.test(val)) {
var fromBase = base && base[name] == prev;
res = function() {
// Look up the base function each time if we can,
// to reflect changes to the base class after
// inheritance.
var tmp = describe(this, 'base');
define(this, 'base', { value: fromBase
? base[name] : prev, configurable: true });
try {
return val.apply(this, arguments);
} finally {
tmp ? define(this, 'base', tmp)
: delete this.base;
}
};
// Make wrapping closure pretend to be the original
// function on inspection
res.toString = function() {
return val.toString();
};
res.valueOf = function() {
return val.valueOf();
};
}
// Produce bean properties if getters are specified. This
// does not produce properties for setter-only properties.
// Just collect beans for now, and look them up in dest at
// the end of fields injection. This ensures this.base()
// works in beans too, and inherits setters for redefined
// getters in subclasses. Only add getter beans if they do
// not expect arguments. Functions that should function both
// with optional arguments and as beans should not declare
// the parameters and use the arguments array internally
// instead.
if (beans && val.length === 0
&& (bean = name.match(/^(get|is)(([A-Z])(.*))$/)))
beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]);
}
// Expose the 'super' function (meaning the one this function is
// overriding) through #base:
if (isFunc && prev)
val.base = prev;
// Produce bean properties if getters are specified. This does
// not produce properties for setter-only properties. Just
// collect beans for now, and look them up in dest at the end of
// fields injection. This ensures base works for beans too, and
// inherits setters for redefined getters in subclasses. Only
// add getter beans if they do not expect arguments. Functions
// that should function both with optional arguments and as
// beans should not declare the parameters and use the arguments
// array internally instead.
if (isFunc && beans && val.length === 0
&& (bean = name.match(/^(get|is)(([A-Z])(.*))$/)))
beans.push([ bean[3].toLowerCase() + bean[4], bean[2] ]);
// No need to look up getter if this is a function already.
if (!res || func || !res.get)
if (!res || isFunc || !res.get)
res = { value: res, writable: true };
// Only set/change configurable and enumerable if this field is
// configurable
@ -171,7 +144,7 @@ var Base = this.Base = new function() { // Straps scope
}
define(dest, name, res);
}
if (generics && func && (!preserve || !generics[name])) {
if (generics && isFunc && (!preserve || !generics[name])) {
generics[name] = function(bind) {
// Do not call Array.slice generic here, as on Safari,
// this seems to confuse scopes (calling another
@ -210,10 +183,11 @@ var Base = this.Base = new function() { // Straps scope
function each(obj, iter, bind, asArray) {
try {
if (obj)
(asArray || asArray === undefined && isArray(obj)
(asArray || typeof asArray === 'undefined' && isArray(obj)
? forEach : forIn).call(obj, iter, bind = bind || obj);
} catch (e) {
if (e !== Base.stop) throw e;
if (e !== Base.stop)
throw e;
}
return bind;
}
@ -225,7 +199,8 @@ var Base = this.Base = new function() { // Straps scope
}
// Inject into new ctor object that's passed to inject(), and then returned
return inject(function() {}, {
// as the Base class.
return inject(function Base() {}, {
inject: function(src/*, ... */) {
if (src) {
var proto = this.prototype,
@ -252,16 +227,19 @@ var Base = this.Base = new function() { // Straps scope
},
extend: function(src/* , ... */) {
var ctor = function() {
// Call the constructor function, if defined
if (this.initialize)
return this.initialize.apply(this, arguments);
var base = this,
ctor;
// Look for an initialize function in all injection objects and use
// it directly as the actual constructor.
for (var i = 0, l = arguments.length; i < l; i++)
if (ctor = arguments[i].initialize)
break;
// If no initialize function is provided, create a constructor that
// simply calls the base constructor.
ctor = ctor || function() {
base.apply(this, arguments);
};
ctor.prototype = create(this.prototype);
// Add a toString function that delegates to initialize if possible
ctor.toString = function() {
return (this.prototype.initialize || function() {}).toString();
};
// The new prototype extends the constructor on which extend is
// called. Fix constructor.
define(ctor.prototype, 'constructor',
@ -320,8 +298,8 @@ var Base = this.Base = new function() { // Straps scope
define: define,
describe: describe,
// Base.create does something different from Object.create, it only
// works on constructors and uses their prototype.
// Base.create does something different from Object.create:
// It works on constructors and uses their prototype.
create: function(ctor) {
return create(ctor.prototype);
},
@ -331,10 +309,12 @@ var Base = this.Base = new function() { // Straps scope
* plain Base object, as produced by Base.merge().
*/
isPlainObject: function(obj) {
var proto = obj !== null && typeof obj === 'object'
&& Object.getPrototypeOf(obj);
return proto && (proto === Object.prototype
|| proto === Base.prototype);
var ctor = obj != null && obj.constructor;
// We also need to check for ctor.name === 'Object', in case
// this is an object from another global scope (e.g. an iframe,
// or another vm context in node.js).
return ctor && (ctor === Object || ctor === Base
|| ctor.name === 'Object');
},
check: function(obj) {
@ -342,9 +322,8 @@ var Base = this.Base = new function() { // Straps scope
},
/**
* Returns the first argument that is defined.
* Null is counted as defined too, since !== undefined is used for
* comparisons. In this it differs from Mootools!
* Returns the first argument that is defined. null is counted as
* defined too, as !== undefined is used for comparisons.
*/
pick: function() {
for (var i = 0, l = arguments.length; i < l; i++)
@ -354,13 +333,10 @@ var Base = this.Base = new function() { // Straps scope
},
/**
* A special constant, to be thrown by closures passed to each()
* Base.stop can be thrown by iterators passed to each()
*
* $continue / Base.next is not implemented, as the same
* functionality can achieved by using return in the closure.
* In prototype, the implementation of $continue also leads to a
* huge speed decrease, as the closure is wrapped in another closure
* that does nothing else than handling $continue.
* continue (Base.next) is not implemented, as the same can achieved
* by using return in the iterator.
*/
stop: {}
}

View file

@ -1,6 +1,6 @@
{
"name": "paper",
"version": "0.8.3",
"version": "0.9.0",
"main": "./src/node/index.js",
"engines": { "node": ">= 0.4.0" },
"dependencies": {

View file

@ -15,32 +15,33 @@
*
* @class The Line object represents..
*/
var Line = this.Line = Base.extend(/** @lends Line# */{
var Line = Base.extend(/** @lends Line# */{
// DOCS: document Line class and constructor
/**
* Creates a Line object.
*
* @param {Point} point1
* @param {Point} point2
* @param {Boolean} [infinite=true]
* @param {Boolean} [asVector=false]
*/
initialize: function(point1, point2, infinite) {
// Convention: With 3 parameters, both points are absolute, and infinite
// controls wether the line extends beyond the defining points, meaning
// intersection outside the line segment are allowed.
// With two parameters, the 2nd parameter is a direction, and infinite
// is automatially true, since we're describing an infinite line.
var _point1 = Point.read(arguments),
_point2 = Point.read(arguments),
_infinite = Base.read(arguments);
if (_infinite !== undefined) {
this.point = _point1;
this.vector = _point2.subtract(_point1);
this.infinite = _infinite;
initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
var asVector = false;
if (arguments.length >= 4) {
this._px = arg0;
this._py = arg1;
this._vx = arg2;
this._vy = arg3;
asVector = arg4;
} else {
this.point = _point1;
this.vector = _point2;
this.infinite = true;
this._px = arg0.x;
this._py = arg0.y;
this._vx = arg1.x;
this._vy = arg1.y;
asVector = arg2;
}
if (!asVector) {
this._vx -= this._px;
this._vy -= this._py;
}
},
@ -50,6 +51,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @name Line#point
* @type Point
*/
getPoint: function() {
return new Point(this._px, this._py);
},
/**
* The vector of the line
@ -57,33 +61,21 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @name Line#vector
* @type Point
*/
/**
* Specifies whether the line extends infinitely
*
* @name Line#infinite
* @type Boolean
*/
getVector: function() {
return new Point(this._vx, this._vy);
},
/**
* @param {Line} line
* @param {Boolean} [isInfinite=false]
* @return {Point} the intersection point of the lines, {@code undefined}
* if the two lines are colinear, or {@code null} if they don't intersect.
*/
intersect: function(line) {
var cross = this.vector.cross(line.vector);
// Avoid divisions by 0, and errors when getting too close to 0
if (Numerical.isZero(cross))
return undefined;
var v = line.point.subtract(this.point),
t1 = v.cross(line.vector) / cross,
t2 = v.cross(this.vector) / cross;
// Check the ranges of t parameters if the line is not allowed to
// extend beyond the definition points.
return (this.infinite || 0 <= t1 && t1 <= 1)
&& (line.infinite || 0 <= t2 && t2 <= 1)
? this.point.add(this.vector.multiply(t1))
: null;
intersect: function(line, isInfinite) {
return Line.intersect(
this._px, this._py, this._vx, this._vy,
line._px, line._py, line._vx, line._vy,
true, isInfinite);
},
// DOCS: document Line#getSide(point)
@ -92,18 +84,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @return {Number}
*/
getSide: function(point) {
var v1 = this.vector,
v2 = point.subtract(this.point),
ccw = v2.cross(v1);
if (ccw === 0) {
ccw = v2.dot(v1);
if (ccw > 0) {
ccw = v2.subtract(v1).dot(v1);
if (ccw < 0)
ccw = 0;
}
}
return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
return Line.getSide(
this._px, this._py, this._vx, this._vy,
point.x, point.y, true);
},
// DOCS: document Line#getDistance(point)
@ -112,33 +95,70 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @return {Number}
*/
getDistance: function(point) {
var m = this.vector.y / this.vector.x, // slope
b = this.point.y - (m * this.point.x); // y offset
// Distance to the linear equation
var dist = Math.abs(point.y - (m * point.x) - b) / Math.sqrt(m * m + 1);
return this.infinite ? dist : Math.min(dist,
point.getDistance(this.point),
point.getDistance(this.point.add(this.vector)));
return Math.abs(Line.getSignedDistance(
this._px, this._py, this._vx, this._vy,
point.x, point.y, true));
},
statics: {
intersect: function(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, infinite) {
var adx = ax2 - ax1,
ady = ay2 - ay1,
bdx = bx2 - bx1,
bdy = by2 - by1,
dx = ax1 - bx1,
dy = ay1 - by1,
cross = bdy * adx - bdx * ady;
if (!Numerical.isZero(cross)) {
var ta = (bdx * dy - bdy * dx) / cross,
tb = (adx * dy - ady * dx) / cross;
if ((infinite || 0 <= ta && ta <= 1)
&& (infinite || 0 <= tb && tb <= 1))
return Point.create(
ax1 + ta * adx,
ay1 + ta * ady);
statics: /** @lends Line */{
intersect: function(apx, apy, avx, avy, bpx, bpy, bvx, bvy, asVector,
isInfinite) {
// Convert 2nd points to vectors if they are not specified as such.
if (!asVector) {
avx -= apx;
avy -= apy;
bvx -= bpx;
bvy -= bpy;
}
var cross = bvy * avx - bvx * avy;
// Avoid divisions by 0, and errors when getting too close to 0
if (!Numerical.isZero(cross)) {
var dx = apx - bpx,
dy = apy - bpy,
ta = (bvx * dy - bvy * dx) / cross,
tb = (avx * dy - avy * dx) / cross;
// Check the ranges of t parameters if the line is not allowed
// to extend beyond the definition points.
if ((isInfinite || 0 <= ta && ta <= 1)
&& (isInfinite || 0 <= tb && tb <= 1))
return new Point(
apx + ta * avx,
apy + ta * avy);
}
},
getSide: function(px, py, vx, vy, x, y, asVector) {
if (!asVector) {
vx -= px;
vy -= py;
}
var v2x = x - px,
v2y = y - py,
ccw = v2x * vy - v2y * vx; // ccw = v2.cross(v1);
if (ccw === 0) {
ccw = v2x * vx + v2y * vy; // ccw = v2.dot(v1);
if (ccw > 0) {
// ccw = v2.subtract(v1).dot(v1);
v2x -= vx;
v2y -= vy;
ccw = v2x * vx + v2y * vy;
if (ccw < 0)
ccw = 0;
}
}
return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
},
getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
if (!asVector) {
vx -= px;
vy -= py;
}
// Cache these values since they're used heavily in fatline code
var m = vy / vx, // slope
b = py - m * px; // y offset
// Distance to the linear equation
return (y - (m * x) - b) / Math.sqrt(m * m + 1);
}
}
});

View file

@ -37,9 +37,7 @@
* knowledge of the underlying matrix (as opposed to say simply performing
* matrix multiplication).
*/
var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
_class: 'Matrix',
var Matrix = Base.extend(/** @lends Matrix# */{
/**
* Creates a 2D affine transform.
*
@ -50,7 +48,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
* @param {Number} tx The translateX coordinate of the transform
* @param {Number} ty The translateY coordinate of the transform
*/
initialize: function(arg) {
initialize: function Matrix(arg) {
var count = arguments.length,
ok = true;
if (count == 6) {
@ -101,7 +99,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
* @return {Matrix} A copy of this transform.
*/
clone: function() {
return Matrix.create(this._a, this._c, this._b, this._d,
return new Matrix(this._a, this._c, this._b, this._d,
this._tx, this._ty);
},
@ -518,7 +516,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
return {
translation: this.getTranslation(),
scaling: Point.create(scaleX, scaleY),
scaling: new Point(scaleX, scaleY),
rotation: -Math.atan2(b, a) * 180 / Math.PI,
shearing: shear
};
@ -585,7 +583,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
*/
getTranslation: function() {
// No decomposition is required to extract translation, so treat this
return Point.create(this._tx, this._ty);
return new Point(this._tx, this._ty);
},
/**
@ -620,7 +618,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
*/
inverted: function() {
var det = this._getDeterminant();
return det && Matrix.create(
return det && new Matrix(
this._d / det,
-this._c / det,
-this._b / det,
@ -630,7 +628,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
},
shiftless: function() {
return Matrix.create(this._a, this._c, this._b, this._d, 0, 0);
return new Matrix(this._a, this._c, this._b, this._d, 0, 0);
},
/**
@ -640,13 +638,6 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{
*/
applyToContext: function(ctx) {
ctx.transform(this._a, this._c, this._b, this._d, this._tx, this._ty);
},
statics: /** @lends Matrix */{
// See Point.create()
create: function(a, c, b, d, tx, ty) {
return Base.create(Matrix).set(a, c, b, d, tx, ty);
}
}
}, new function() {
return Base.each({

View file

@ -23,8 +23,7 @@
* console.log(point.x); // 10
* console.log(point.y); // 5
*/
var Point = this.Point = Base.extend(/** @lends Point# */{
_class: 'Point',
var Point = Base.extend(/** @lends Point# */{
// Tell Base.read that the Point constructor supports reading with index
_readIndex: true,
@ -129,7 +128,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
* @param {Point} point
* @name Point#initialize
*/
initialize: function(arg0, arg1) {
initialize: function Point(arg0, arg1) {
var type = typeof arg0;
if (type === 'number') {
var hasY = typeof arg1 === 'number';
@ -217,7 +216,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
* @returns {Point} the cloned point
*/
clone: function() {
return Point.create(this.x, this.y);
return new Point(this.x, this.y);
},
/**
@ -269,7 +268,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
*/
add: function(point) {
point = Point.read(arguments);
return Point.create(this.x + point.x, this.y + point.y);
return new Point(this.x + point.x, this.y + point.y);
},
/**
@ -305,7 +304,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
*/
subtract: function(point) {
point = Point.read(arguments);
return Point.create(this.x - point.x, this.y - point.y);
return new Point(this.x - point.x, this.y - point.y);
},
/**
@ -341,7 +340,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
*/
multiply: function(point) {
point = Point.read(arguments);
return Point.create(this.x * point.x, this.y * point.y);
return new Point(this.x * point.x, this.y * point.y);
},
/**
@ -377,7 +376,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
*/
divide: function(point) {
point = Point.read(arguments);
return Point.create(this.x / point.x, this.y / point.y);
return new Point(this.x / point.x, this.y / point.y);
},
/**
@ -410,11 +409,11 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
*/
modulo: function(point) {
point = Point.read(arguments);
return Point.create(this.x % point.x, this.y % point.y);
return new Point(this.x % point.x, this.y % point.y);
},
negate: function() {
return Point.create(-this.x, -this.y);
return new Point(-this.x, -this.y);
},
/**
@ -501,7 +500,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
length = 1;
var current = this.getLength(),
scale = current != 0 ? length / current : 0,
point = Point.create(this.x * scale, this.y * scale);
point = new Point(this.x * scale, this.y * scale);
// Preserve angle.
point._angle = this._angle;
return point;
@ -650,7 +649,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
var point = center ? this.subtract(center) : this,
s = Math.sin(angle),
c = Math.cos(angle);
point = Point.create(
point = new Point(
point.x * c - point.y * s,
point.y * c + point.x * s
);
@ -754,10 +753,10 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
project: function(point) {
point = Point.read(arguments);
if (point.isZero()) {
return Point.create(0, 0);
return new Point(0, 0);
} else {
var scale = this.dot(point) / point.dot(point);
return Point.create(
return new Point(
point.x * scale,
point.y * scale
);
@ -775,23 +774,6 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
*/
statics: /** @lends Point */{
/**
* Provide a faster creator for Points out of two coordinates that
* does not rely on Point#initialize at all. This speeds up all math
* operations a lot.
*
* @ignore
*/
create: function(x, y) {
// Don't use the shorter form as we want absolute maximum
// performance here:
// return Base.create(Point).set(x, y);
var point = Base.create(Point);
point.x = x;
point.y = y;
return point;
},
/**
* Returns a new point object with the smallest {@link #x} and
* {@link #y} of the supplied points.
@ -810,7 +792,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
min: function(point1, point2) {
var _point1 = Point.read(arguments);
_point2 = Point.read(arguments);
return Point.create(
return new Point(
Math.min(_point1.x, _point2.x),
Math.min(_point1.y, _point2.y)
);
@ -834,7 +816,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
max: function(point1, point2) {
var _point1 = Point.read(arguments);
_point2 = Point.read(arguments);
return Point.create(
return new Point(
Math.max(_point1.x, _point2.x),
Math.max(_point1.y, _point2.y)
);
@ -855,7 +837,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
* var point = maxPoint * randomPoint;
*/
random: function() {
return Point.create(Math.random(), Math.random());
return new Point(Math.random(), Math.random());
}
}
}, new function() { // Scope for injecting round, ceil, floor, abs:
@ -922,7 +904,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
var op = Math[name];
this[name] = function() {
return Point.create(op(this.x), op(this.y));
return new Point(op(this.x), op(this.y));
};
}, {});
});
@ -970,7 +952,7 @@ var LinkedPoint = Point.extend({
// through an optional parameter that can be passed to the getters.
// See e.g. Rectangle#getPoint(true).
if (dontLink)
return Point.create(x, y);
return new Point(x, y);
var point = Base.create(LinkedPoint);
point._x = x;
point._y = y;

View file

@ -17,8 +17,7 @@
* point (x, y), its width, and its height. It should not be confused with a
* rectangular path, it is not an item.
*/
var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
_class: 'Rectangle',
var Rectangle = Base.extend(/** @lends Rectangle# */{
// Tell Base.read that the Rectangle constructor supports reading with index
_readIndex: true,
@ -72,7 +71,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
* @name Rectangle#initialize
* @param {Rectangle} rt
*/
initialize: function(arg0, arg1, arg2, arg3) {
initialize: function Rectangle(arg0, arg1, arg2, arg3) {
var type = typeof arg0,
read = 0;
if (type === 'number') {
@ -191,7 +190,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
* Returns a copy of the rectangle.
*/
clone: function() {
return Rectangle.create(this.x, this.y, this.width, this.height);
return new Rectangle(this.x, this.y, this.width, this.height);
},
/**
@ -652,7 +651,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
y1 = Math.max(this.y, rect.y),
x2 = Math.min(this.x + this.width, rect.x + rect.width),
y2 = Math.min(this.y + this.height, rect.y + rect.height);
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
},
/**
@ -669,7 +668,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
y1 = Math.min(this.y, rect.y),
x2 = Math.max(this.x + this.width, rect.x + rect.width),
y2 = Math.max(this.y + this.height, rect.y + rect.height);
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
},
/**
@ -692,7 +691,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
y1 = Math.min(this.y, point.y),
x2 = Math.max(this.x + this.width, point.x),
y2 = Math.max(this.y + this.height, point.y);
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
},
/**
@ -716,7 +715,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
expand: function(hor, ver) {
if (ver === undefined)
ver = hor;
return Rectangle.create(this.x - hor / 2, this.y - ver / 2,
return new Rectangle(this.x - hor / 2, this.y - ver / 2,
this.width + hor, this.height + ver);
},
@ -740,13 +739,6 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
scale: function(hor, ver) {
return this.expand(this.width * hor - this.width,
this.height * (ver === undefined ? hor : ver) - this.height);
},
statics: {
// See Point.create()
create: function(x, y, width, height) {
return Base.create(Rectangle).set(x, y, width, height);
}
}
}, new function() {
return Base.each([

View file

@ -22,8 +22,7 @@
* console.log(size.width); // 10
* console.log(size.height); // 5
*/
var Size = this.Size = Base.extend(/** @lends Size# */{
_class: 'Size',
var Size = Base.extend(/** @lends Size# */{
// Tell Base.read that the Point constructor supports reading with index
_readIndex: true,
@ -90,7 +89,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
* console.log(size.width); // 50
* console.log(size.height); // 50
*/
initialize: function(arg0, arg1) {
initialize: function Size(arg0, arg1) {
var type = typeof arg0;
if (type === 'number') {
var hasHeight = typeof arg1 === 'number';
@ -164,7 +163,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
* Returns a copy of the size.
*/
clone: function() {
return Size.create(this.width, this.height);
return new Size(this.width, this.height);
},
/**
@ -214,7 +213,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
*/
add: function(size) {
size = Size.read(arguments);
return Size.create(this.width + size.width, this.height + size.height);
return new Size(this.width + size.width, this.height + size.height);
},
/**
@ -249,7 +248,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
*/
subtract: function(size) {
size = Size.read(arguments);
return Size.create(this.width - size.width, this.height - size.height);
return new Size(this.width - size.width, this.height - size.height);
},
/**
@ -283,7 +282,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
*/
multiply: function(size) {
size = Size.read(arguments);
return Size.create(this.width * size.width, this.height * size.height);
return new Size(this.width * size.width, this.height * size.height);
},
/**
@ -317,7 +316,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
*/
divide: function(size) {
size = Size.read(arguments);
return Size.create(this.width / size.width, this.height / size.height);
return new Size(this.width / size.width, this.height / size.height);
},
/**
@ -350,11 +349,11 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
*/
modulo: function(size) {
size = Size.read(arguments);
return Size.create(this.width % size.width, this.height % size.height);
return new Size(this.width % size.width, this.height % size.height);
},
negate: function() {
return Size.create(-this.width, -this.height);
return new Size(-this.width, -this.height);
},
/**
@ -377,11 +376,6 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
},
statics: /** @lends Size */{
// See Point.create()
create: function(width, height) {
return Base.create(Size).set(width, height);
},
/**
* Returns a new size object with the smallest {@link #width} and
* {@link #height} of the supplied sizes.
@ -398,7 +392,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
* console.log(minSize); // {width: 10, height: 5}
*/
min: function(size1, size2) {
return Size.create(
return new Size(
Math.min(size1.width, size2.width),
Math.min(size1.height, size2.height));
},
@ -419,7 +413,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
* console.log(maxSize); // {width: 200, height: 100}
*/
max: function(size1, size2) {
return Size.create(
return new Size(
Math.max(size1.width, size2.width),
Math.max(size1.height, size2.height));
},
@ -437,7 +431,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
* var size = maxSize * randomSize;
*/
random: function() {
return Size.create(Math.random(), Math.random());
return new Size(Math.random(), Math.random());
}
}
}, new function() { // Scope for injecting round, ceil, floor, abs:
@ -505,7 +499,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{
return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
var op = Math[name];
this[name] = function() {
return Size.create(op(this.width), op(this.height));
return new Size(op(this.width), op(this.height));
};
}, {});
});
@ -551,7 +545,7 @@ var LinkedSize = Size.extend({
create: function(owner, setter, width, height, dontLink) {
// See LinkedPoint.create() for an explanation about dontLink.
if (dontLink)
return Size.create(width, height);
return new Size(width, height);
var size = Base.create(LinkedSize);
size._width = width;
size._height = height;

View file

@ -16,7 +16,7 @@ var CanvasProvider = {
canvases: [],
getCanvas: function(width, height) {
var size = height === undefined ? width : Size.create(width, height);
var size = height === undefined ? width : new Size(width, height);
if (this.canvases.length) {
var canvas = this.canvases.pop();
// If they are not the same size, we don't need to clear them

View file

@ -17,7 +17,7 @@
*/
// Extend Base with utility functions used across the library. Also set
// this.Base on the injection scope, since straps.js ommits that.
this.Base = Base.inject(/** @lends Base# */{
Base.inject(/** @lends Base# */{
// Have generics versions of #clone() and #toString():
generics: true,
@ -36,7 +36,7 @@ this.Base = Base.inject(/** @lends Base# */{
*/
toString: function() {
return this._id != null
? (this._class || 'Object') + (this._name
? (this.constructor.name || 'Object') + (this._name
? " '" + this._name + "'"
: ' @' + this._id)
: '{ ' + Base.each(this, function(value, key) {
@ -80,15 +80,17 @@ this.Base = Base.inject(/** @lends Base# */{
statics: /** @lends Base */{
_classes: {},
// Keep track of all named classes for serialization and exporting.
// Also register the Base class itself.
exports: new Base({ Base: Base }),
extend: function(src) {
// Override Base.extend() with a version that registers classes that
// define #_class inside the Base._classes lookup, for
// deserialization.
var res = this.base.apply(this, arguments);
if (src._class)
Base._classes[src._class] = res;
extend: function extend(src) {
// Override Base.extend() to register named classes in Base.exports,
// for deserialization and injection into PaperScope.
var res = extend.base.apply(this, arguments),
name = res.name;
if (name)
Base.exports[name] = res;
return res;
},
@ -289,11 +291,12 @@ this.Base = Base.inject(/** @lends Base# */{
ref = this.references[id];
if (!ref) {
this.length++;
var res = create.call(item);
var res = create.call(item),
name = item.constructor.name;
// Also automatically insert class for dictionary
// entries.
if (item._class && res[0] !== item._class)
res.unshift(item._class);
if (name && res[0] !== name)
res.unshift(name);
this.definitions[id] = res;
ref = this.references[id] = [id];
}
@ -306,13 +309,18 @@ this.Base = Base.inject(/** @lends Base# */{
// If we don't serialize to compact form (meaning no type
// identifier), see if _serialize didn't already add the class,
// e.g. for classes that do not support compact form.
if (obj._class && !compact && res[0] !== obj._class)
res.unshift(obj._class);
var name = obj.constructor.name;
if (name && !compact && !res._compact && res[0] !== name)
res.unshift(name);
} else if (Array.isArray(obj)) {
res = [];
for (var i = 0, l = obj.length; i < l; i++)
res[i] = Base.serialize(obj[i], options, compact,
dictionary);
// Mark array as compact, so obj._serialize handling above
// doesn't add the constructor name again.
if (compact)
res._compact = true;
} else if (Base.isPlainObject(obj)) {
res = {};
for (var i in obj)
@ -332,7 +340,7 @@ this.Base = Base.inject(/** @lends Base# */{
/**
* Deserializes from parsed JSON data. A simple convention is followed:
* Array values with a string at the first position are links to
* deserializable types through Base._classes, and the values following
* deserializable types through Base.exports, and the values following
* in the array are the arguments to their initialize function.
* Any other value is passed on unmodified.
* The passed data is recoursively traversed and converted, leaves first
@ -356,7 +364,7 @@ this.Base = Base.inject(/** @lends Base# */{
// if so return its definition instead.
if (data.dictionary && obj.length == 1 && /^#/.test(type))
return data.dictionary[type];
type = Base._classes[type];
type = Base.exports[type];
}
res = [];
// Skip first type entry for arguments

View file

@ -98,7 +98,7 @@ var Callback = {
statics: {
// Override inject() so that sub-classes automatically add the accessors
// for the event handler functions (e.g. #onMouseDown) for each property
inject: function(/* src, ... */) {
inject: function inject(/* src, ... */) {
for (var i = 0, l = arguments.length; i < l; i++) {
var src = arguments[i],
events = src._events;
@ -132,7 +132,7 @@ var Callback = {
});
src._eventTypes = types;
}
this.base(src);
inject.base.call(this, src);
}
return this;
}

View file

@ -32,7 +32,7 @@
* The global {@link paper} object is simply a reference to the currently active
* {@code PaperScope}.
*/
var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
var PaperScope = Base.extend(/** @lends PaperScope# */{
/**
* Creates a PaperScope object.
@ -40,7 +40,7 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
* @name PaperScope#initialize
* @function
*/
initialize: function(script) {
initialize: function PaperScope(script) {
// script is only used internally, when creating scopes for PaperScript.
// Whenever a PaperScope is created, it automatically becomes the active
// one.
@ -71,11 +71,11 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
},
/**
* The version of Paper.js, as a float number.
* The version of Paper.js, as a string.
*
* @type Number
* @type String
*/
version: /*#=*/ options.version,
version: '/*#=*/ options.version',
/**
* The currently active project.
@ -139,7 +139,6 @@ var PaperScope = this.PaperScope = Base.extend(/** @lends PaperScope# */{
Base.each(['project', 'view', 'tool'], function(key) {
Base.define(scope, key, {
configurable: true,
writable: true,
get: function() {
return that[key];
}

View file

@ -20,8 +20,8 @@
/*#*/ } else if (options.parser == 'esprima') {
/*#*/ include('../../lib/esprima-min.js');
/*#*/ }
var PaperScript = this.PaperScript = new function() {
var PaperScript = new function() {
// Operators to overload
var binaryOperators = {

View file

@ -1,24 +0,0 @@
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
* http://lehni.org/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
/*#*/ if (options.version == 'dev') {
// When in dev mode, also export all classes through PaperScope, to mimick
// scoping behavior of the built library.
Base.each(this, function(val, key) {
if (val && val.prototype instanceof Base || val === Base)
PaperScope.prototype[key] = val;
});
// 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
var paper = new PaperScope();
/*#*/ } // options.version == 'dev'

View file

@ -158,7 +158,7 @@ var DomElement = new function() {
var doc = el.ownerDocument,
view = doc.defaultView,
html = doc.documentElement;
return Rectangle.create(0, 0,
return new Rectangle(0, 0,
view.innerWidth || html.clientWidth,
view.innerHeight || html.clientHeight
);

View file

@ -49,7 +49,7 @@ var DomEvent = {
? event.targetTouches[0]
: event.changedTouches[0]
: event;
return Point.create(
return new Point(
pos.pageX || pos.clientX + document.documentElement.scrollLeft,
pos.pageY || pos.clientY + document.documentElement.scrollTop
);

18
src/export.js Normal file
View file

@ -0,0 +1,18 @@
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
* http://lehni.org/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
// Add PaperScript and Numerical to exports, inject all exports into PaperScope,
// and create the initial paper object, all in one condensed statement:
var paper = new (PaperScope.inject(Base.exports.inject({
PaperScript: PaperScript,
Numerical: Numerical
})))();

View file

@ -20,7 +20,10 @@
*
* @extends Group
*/
var Clip = this.Clip = Group.extend(/** @lends Clip# */{
_class: 'Clip',
_applyMatrix: false
var Clip = Group.extend(/** @lends Clip# */{
_applyMatrix: false,
initialize: function Clip() {
Group.apply(this, arguments);
}
});

View file

@ -19,8 +19,7 @@
*
* @extends Item
*/
var Group = this.Group = Item.extend(/** @lends Group# */{
_class: 'Group',
var Group = Item.extend(/** @lends Group# */{
_serializeFields: {
children: []
},
@ -88,8 +87,8 @@ var Group = this.Group = Item.extend(/** @lends Group# */{
* position: view.center
* });
*/
initialize: function(arg) {
this.base();
initialize: function Group(arg) {
Item.call(this);
// Allow Group to have children and named children
this._children = [];
this._namedChildren = {};
@ -97,9 +96,12 @@ var Group = this.Group = Item.extend(/** @lends Group# */{
this.addChildren(Array.isArray(arg) ? arg : arguments);
},
_changed: function(flags) {
// Don't use this.base() for reasons of performance.
Item.prototype._changed.call(this, flags);
_changed: function _changed(flags) {
_changed.base.call(this, flags);
if (flags & /*#=*/ ChangeFlag.HIERARCHY && !this._matrix.isIdentity()) {
// Apply matrix now that we have content.
this.applyMatrix();
}
if (flags & (/*#=*/ ChangeFlag.HIERARCHY | /*#=*/ ChangeFlag.CLIPPING)) {
// Clear cached clip item whenever hierarchy changes
delete this._clipItem;

View file

@ -17,8 +17,8 @@
* test. It is returned by {@link Item#hitTest(point)} and
* {@link Project#hitTest(point)}.
*/
var HitResult = this.HitResult = Base.extend(/** @lends HitResult# */{
initialize: function(type, item, values) {
var HitResult = Base.extend(/** @lends HitResult# */{
initialize: function HitResult(type, item, values) {
this.type = type;
this.item = item;
// Inject passed values, so we can be flexible about the HitResult

View file

@ -20,23 +20,27 @@
* is unique to their type, but share the underlying properties and functions
* that they inherit from Item.
*/
var Item = this.Item = Base.extend(Callback, {
var Item = Base.extend(Callback, /** @lends Item# */{
statics: {
/**
* Override Item.extend() to merge the subclass' _serializeFields with
* the parent class' _serializeFields.
*
* @private
*/
extend: function(src) {
extend: function extend(src) {
if (src._serializeFields)
src._serializeFields = Base.merge(
this.prototype._serializeFields, src._serializeFields);
// Derive the _type string from _class
if (src._class)
src._type = Base.hyphenate(src._class);
return this.base.apply(this, arguments);
var res = extend.base.apply(this, arguments),
name = res.name;
// Derive the _type string from constructor name
if (name)
res.prototype._type = Base.hyphenate(name);
return res;
}
}
}, /** @lends Item# */{
},
// All items apply their matrix by default.
// Exceptions are Raster, PlacedSymbol, Clip and Shape.
_applyMatrix: true,
@ -55,7 +59,7 @@ var Item = this.Item = Base.extend(Callback, {
data: {}
},
initialize: function(point) {
initialize: function Item(point) {
// Define this Item's unique id.
this._id = Item._id = (Item._id || 0) + 1;
// If _project is already set, the item was already moved into the DOM
@ -168,7 +172,7 @@ var Item = this.Item = Base.extend(Callback, {
serialize(this._style._defaults);
// There is no compact form for Item serialization, we always keep the
// type.
return [ this._class, props ];
return [ this.constructor.name, props ];
},
/**
@ -198,7 +202,7 @@ var Item = this.Item = Base.extend(Callback, {
this._clearBoundsCache();
}
if (flags & /*#=*/ ChangeFlag.APPEARANCE) {
this._project._needsRedraw();
this._project._needsRedraw = true;
}
// If this item is a symbol's definition, notify it of the change too
if (this._parentSymbol)
@ -878,7 +882,7 @@ var Item = this.Item = Base.extend(Callback, {
}
}
return isFinite(x1)
? Rectangle.create(x1, y1, x2 - x1, y2 - y1)
? new Rectangle(x1, y1, x2 - x1, y2 - y1)
: new Rectangle();
},
@ -1428,7 +1432,6 @@ var Item = this.Item = Base.extend(Callback, {
* @param {Item} item The item to be added as a child
*/
addChild: function(item, _preserve) {
// Pass on internal _preserve boolean, for CompoundPath#insertChild
return this.insertChild(undefined, item, _preserve);
},
@ -1441,21 +1444,8 @@ var Item = this.Item = Base.extend(Callback, {
* @param {Item} item The item to be appended as a child
*/
insertChild: function(index, item, _preserve) {
// _preserve parameter is not used here, but CompoundPath#insertChild()
// needs it.
if (this._children) {
item._remove(true);
Base.splice(this._children, [item], index, 0);
item._parent = this;
item._setProject(this._project);
// Setting the name again makes sure all name lookup structures are
// kept in sync.
if (item._name)
item.setName(item._name);
this._changed(/*#=*/ Change.HIERARCHY);
return item;
}
return null;
var res = this.insertChildren(index, [item], _preserve);
return res && res[0];
},
/**
@ -1477,25 +1467,42 @@ var Item = this.Item = Base.extend(Callback, {
* @param {Number} index
* @param {Item[]} items The items to be appended as children
*/
insertChildren: function(index, items, _preserve) {
// We need to clone items because it might be
// an Item#children array. Use Array.prototype.slice because
// in certain cases items is an arguments object
items = items && Array.prototype.slice.apply(items);
var children = this._children,
length = children.length,
i = index;
for (var j = 0, l = items && items.length; j < l; j++) {
if (this.insertChild(i, items[j], _preserve)) {
// We need to keep track of how much the list actually grows,
// bcause we might be removing and inserting into the same list,
// in which case the size would not chage.
var newLength = children.length;
i += newLength - length;
length = newLength;
insertChildren: function(index, items, _preserve, _type) {
// CompoundPath#insertChildren() requires _preserve and _type:
// _preserve avoids changing of the children's path orientation
// _type enforces the inserted type.
var children = this._children;
if (children && items && items.length > 0) {
// We need to clone items because it might be
// an Item#children array. Also, we're removing elements if they
// don't match _type. Use Array.prototype.slice becaus items can be
// an arguments object.
items = Array.prototype.slice.apply(items);
// Remove the items from their parents first, since they might be
// inserted into their own parents, affecting indices.
// Use the loop also to filter out wrong _type.
for (var i = items.length - 1; i >= 0; i--) {
var item = items[i];
if (_type && item._type !== _type)
items.splice(i, 1);
else
item._remove(true);
}
Base.splice(children, items, index, 0);
for (var i = 0, l = items.length; i < l; i++) {
var item = items[i];
item._parent = this;
item._setProject(this._project);
// Setting the name again makes sure all name lookup structures
// are kept in sync.
if (item._name)
item.setName(item._name);
}
this._changed(/*#=*/ Change.HIERARCHY);
} else {
items = null;
}
return i != index;
return items;
},
/**
@ -2220,9 +2227,10 @@ var Item = this.Item = Base.extend(Callback, {
},
_transformContent: function(matrix, applyMatrix) {
if (this._children) {
for (var i = 0, l = this._children.length; i < l; i++)
this._children[i].transform(matrix, applyMatrix);
var children = this._children;
if (children && children.length > 0) {
for (var i = 0, l = children.length; i < l; i++)
children[i].transform(matrix, applyMatrix);
return true;
}
},
@ -2332,7 +2340,7 @@ var Item = this.Item = Base.extend(Callback, {
? rectangle.width / bounds.width
: rectangle.height / bounds.height,
newBounds = new Rectangle(new Point(),
Size.create(bounds.width * scale, bounds.height * scale));
new Size(bounds.width * scale, bounds.height * scale));
newBounds.setCenter(rectangle.getCenter());
this.setBounds(newBounds);
},
@ -2877,7 +2885,7 @@ var Item = this.Item = Base.extend(Callback, {
// so we draw onto it, instead of the parentCtx
parentCtx = ctx;
ctx = CanvasProvider.getContext(
bounds.getSize().ceil().add(Size.create(1, 1)));
bounds.getSize().ceil().add(new Size(1, 1)));
}
ctx.save();
// Translate the context so the topLeft of the item is at (0, 0)

View file

@ -22,8 +22,7 @@
*
* @extends Group
*/
var Layer = this.Layer = Group.extend(/** @lends Layer# */{
_class: 'Layer',
var Layer = Group.extend(/** @lends Layer# */{
// DOCS: improve constructor code example.
/**
* Creates a new Layer item and places it at the end of the
@ -57,11 +56,11 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
* position: view.center
* });
*/
initialize: function(items) {
initialize: function Layer(items) {
this._project = paper.project;
// Push it onto project.layers and set index:
this._index = this._project.layers.push(this) - 1;
this.base.apply(this, arguments);
Group.apply(this, arguments);
this.activate();
},
@ -69,9 +68,9 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
* Removes the layer from its project's layers list
* or its parent's children list.
*/
_remove: function(notify) {
_remove: function _remove(notify) {
if (this._parent)
return this.base(notify);
return _remove.base.call(this, notify);
if (this._index != null) {
if (this._project.activeLayer === this)
this._project.activeLayer = this.getNextSibling()
@ -79,24 +78,24 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
Base.splice(this._project.layers, null, this._index, 1);
// Tell project we need a redraw. This is similar to _changed()
// mechanism.
this._project._needsRedraw();
this._project._needsRedraw = true;
return true;
}
return false;
},
getNextSibling: function() {
return this._parent ? this.base()
getNextSibling: function getNextSibling() {
return this._parent ? getNextSibling.base.call(this)
: this._project.layers[this._index + 1] || null;
},
getPreviousSibling: function() {
return this._parent ? this.base()
getPreviousSibling: function getPreviousSibling() {
return this._parent ? getPreviousSibling.base.call(this)
: this._project.layers[this._index - 1] || null;
},
isInserted: function() {
return this._parent ? this.base() : this._index != null;
isInserted: function isInserted() {
return this._parent ? isInserted.base.call(this) : this._index != null;
},
/**
@ -114,7 +113,7 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
}
}, new function () {
function insert(above) {
return function(item) {
return function insert(item) {
// If the item is a layer and contained within Project#layers, use
// our own version of move().
if (item instanceof Layer && !item._parent
@ -124,7 +123,7 @@ var Layer = this.Layer = Group.extend(/** @lends Layer# */{
this._setProject(item._project);
return true;
}
return this.base(item);
return insert.base.call(this, item);
};
}

View file

@ -18,8 +18,7 @@
*
* @extends Item
*/
var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
_class: 'PlacedSymbol',
var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
_applyMatrix: false,
// PlacedSymbol uses strokeBounds for bounds
_boundsGetter: { getBounds: 'getStrokeBounds' },
@ -68,11 +67,11 @@ var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
* instance.scale(0.25 + Math.random() * 0.75);
* }
*/
initialize: function(arg0, arg1) {
initialize: function PlacedSymbol(arg0, arg1) {
// Support two forms of item initialization: Passing one object literal
// describing all the different properties to be set, or a symbol (arg0)
// and a point where it should be placed (arg1).
this.base(arg1 !== undefined && Point.read(arguments, 1));
Item.call(this, arg1 !== undefined && Point.read(arguments, 1));
// If we can handle setting properties through object literal, we're all
// set. Otherwise we need to set symbol.
if (arg0 && !this._set(arg0))

View file

@ -17,8 +17,7 @@
*
* @extends Item
*/
var Raster = this.Raster = Item.extend(/** @lends Raster# */{
_class: 'Raster',
var Raster = Item.extend(/** @lends Raster# */{
_applyMatrix: false,
// Raster doesn't make the distinction between the different bounds,
// so use the same name for all of them
@ -72,11 +71,11 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
* raster.scale(0.5);
* raster.rotate(10);
*/
initialize: function(object, position) {
initialize: function Raster(object, position) {
// Support two forms of item initialization: Passing one object literal
// describing all the different properties to be set, or an image
// (object) and a point where it should be placed (point).
this.base(position !== undefined && Point.read(arguments, 1));
Item.call(this, position !== undefined && Point.read(arguments, 1));
// If we can handle setting properties through object literal, we're all
// set. Otherwise we need to check the type of object:
if (object && !this._set(object)) {
@ -164,7 +163,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
orig = new Point(0, 0).transform(matrix),
u = new Point(1, 0).transform(matrix).subtract(orig),
v = new Point(0, 1).transform(matrix).subtract(orig);
return Size.create(
return new Size(
72 / u.getLength(),
72 / v.getLength()
);
@ -218,7 +217,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
if (this._canvas)
CanvasProvider.release(this._canvas);
this._canvas = canvas;
this._size = Size.create(canvas.width, canvas.height);
this._size = new Size(canvas.width, canvas.height);
this._image = null;
this._context = null;
this._changed(/*#=*/ Change.GEOMETRY | /*#=*/ Change.PIXELS);
@ -239,10 +238,10 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
CanvasProvider.release(this._canvas);
this._image = image;
/*#*/ if (options.browser) {
this._size = Size.create(image.naturalWidth, image.naturalHeight);
/*#*/ } else if (options.server) {
this._size = Size.create(image.width, image.height);
/*#*/ } // options.server
this._size = new Size(image.naturalWidth, image.naturalHeight);
/*#*/ } else if (options.node) {
this._size = new Size(image.width, image.height);
/*#*/ } // options.node
this._canvas = null;
this._context = null;
this._changed(/*#=*/ Change.GEOMETRY);
@ -296,14 +295,22 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
} else if (!image.src) {
image.src = src;
}
/*#*/ } else if (options.server) {
// If we're running on the server and it's a string,
// load it from disk:
// TODO: load images async, calling setImage once loaded as above
var image = new Image();
image.src = fs.readFileSync(src);
/*#*/ } // options.server
this.setImage(image);
/*#*/ } else if (options.node) {
var image = new Image();
// If we're running on the server and it's a string,
// check if it is a data URL
if (/^data:/.test(src)) {
// Preserve the data in this._data since canvas-node eats it.
// TODO: Fix canvas-node instead
image.src = this._data = src;
} else {
// Load it from disk:
// TODO: load images async, calling setImage once loaded as above.
image.src = fs.readFileSync(src);
}
this.setImage(image);
/*#*/ } // options.node
},
// DOCS: document Raster#getElement
@ -334,9 +341,14 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
toDataURL: function() {
// See if the linked image is base64 encoded already, if so reuse it,
// otherwise try using canvas.toDataURL()
/*#*/ if (options.node) {
if (this._data)
return this._data;
/*#*/ } else {
var src = this._image && this._image.src;
if (/^data:/.test(src))
return src;
/*#*/ }
var canvas = this.getCanvas();
return canvas ? canvas.toDataURL() : null;
},
@ -375,7 +387,7 @@ var Raster = this.Raster = Item.extend(/** @lends Raster# */{
bounds = new Rectangle(object);
} else if (object.x) {
// Create a rectangle of 1px size around the specified coordinates
bounds = Rectangle.create(object.x - 0.5, object.y - 0.5, 1, 1);
bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);
}
// Use a sample size of max 32 x 32 pixels, into which the path is
// scaled as a clipping path, and then the actual image is drawn in and

View file

@ -17,12 +17,11 @@
*
* @extends Item
*/
var Shape = this.Shape = Item.extend(/** @lends Shape# */{
_class: 'Shape',
var Shape = Item.extend(/** @lends Shape# */{
_applyMatrix: false,
initialize: function(type, point, size) {
this.base(point);
initialize: function Shape(type, point, size) {
Item.call(this, point);
this._type = type;
this._size = size;
},
@ -67,10 +66,10 @@ var Shape = this.Shape = Item.extend(/** @lends Shape# */{
}
},
_contains: function(point) {
_contains: function _contains(point) {
switch (this._type) {
case 'rect':
return this.base(point);
return _contains.base.call(this, point);
case 'circle':
case 'ellipse':
return point.divide(this._size).getLength() <= 0.5;

View file

@ -14,17 +14,7 @@
// 'preprocess' it on the fly in the browser, avoiding the step of having to
// manually preprocess it after each change.
// Define options for compile-time preprocessing.
var options = {
parser: 'acorn',
version: 'dev',
browser: true,
stats: true,
svg: true,
fatline: true,
debug: false
};
// This folder is specified relatively to the lib folder from which prepro.js is
// loaded, and which is referenced as the root.
include('../src/options.js');
include('../src/paper.js');

View file

@ -16,24 +16,23 @@ var fs = require('fs'),
// Node Canvas library: https://github.com/learnboost/node-canvas
Canvas = require('canvas'),
jsdom = require('jsdom'),
domToHtml = require('jsdom/lib/jsdom/browser/domtohtml').domToHtml,
json = require('../../package.json');
domToHtml = require('jsdom/lib/jsdom/browser/domtohtml').domToHtml;
var options = {
parser: 'acorn',
// Use 'dev' for on-the fly compilation of separate files ,but update after.
version: 'dev',
server: true,
svg: true,
fatline: false
};
// Load the options from load.js, but evaluate into local scope:
eval(fs.readFileSync(path.resolve(__dirname, '../options.js'), 'utf8'));
// Change node.js specific settings. Use 'dev' version for on-the fly
// compilation of separate files, and set to correct value after.
options.version = 'dev';
options.browser = false;
options.node = true;
options.stats = false;
// Create a document and a window using jsdom, e.g. for exportSVG()
var doc = jsdom.jsdom("<html><body></body></html>"),
win = doc.createWindow();
// Define XMLSerializer.
// TODO: Put this into a simple node module, with dependency on jsdom
// Define XMLSerializer and DOMParser shims, to emulate browser behavior.
// TODO: Put this into a simple node module, with dependency on jsdom?
function XMLSerializer() {
}
@ -41,7 +40,7 @@ XMLSerializer.prototype.serializeToString = function(node) {
var text = domToHtml(node);
// Fix a jsdom issue where linearGradient gets converted to lineargradient:
// https://github.com/tmpvar/jsdom/issues/620
return text.replace(/(linear|radial)(gradient)/g, function(all, type) {
return text.replace(/(linear|radial)gradient/g, function(all, type) {
return type + 'Gradient';
});
};
@ -89,26 +88,13 @@ var context = vm.createContext({
// Load Paper.js library files:
context.include('paper.js');
// Since the context used for Paper.js compilation, and the context in which
// Node.js scripts are executed do not share the definition of Object, we need
// to redefine Base.isPlainObject() here.
// So instead of checking for Object.prototype, we're checking
// proto.constructor.name for 'Object'
var Base = context.Base;
Base.isPlainObject = function(obj) {
var proto = obj !== null && typeof obj === 'object'
&& Object.getPrototypeOf(obj);
return proto && (proto.constructor.name === 'Object'
|| proto === Base.prototype);
};
context.PaperScope.inject({
// Expose the Canvas, XMLSerializer & DOMParser to PaperScope:
Canvas: Canvas,
XMLSerializer: XMLSerializer,
DOMParser: DOMParser,
// Also fix version. Remove 2nd dot, so we can make a float out of it:
version: parseFloat(json.version.replace(/(.)(\d)$/, '$2'))
// Also set the correct version from package.json
version: require('../../package.json').version
});
require.extensions['.pjs'] = function(module, uri) {

24
src/options.js Normal file
View file

@ -0,0 +1,24 @@
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
* http://lehni.org/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
// Define default options for compile-time preprocessing. These are also used
// for building, but some values are overridden (e.g. version, stats).
var options = {
parser: 'acorn',
version: 'dev',
browser: true,
stats: true,
svg: true,
fatline: false,
debug: false
};

View file

@ -35,14 +35,14 @@ var paper = new function() {
// Inline Bootstrap core (the Base class) inside the paper scope first:
/*#*/ include('../lib/straps.js');
/*#*/ if (options.version == 'dev') {
/*#*/ include('constants.js');
/*#*/ } // options.version == 'dev'
/*#*/ if (options.stats) {
/*#*/ include('../lib/stats.js');
/*#*/ } // options.stats
/*#*/ if (options.version == 'dev') {
/*#*/ include('constants.js');
/*#*/ } // options.version == 'dev'
/*#*/ include('core/Base.js');
/*#*/ include('core/Callback.js');
/*#*/ include('core/PaperScope.js');
@ -53,7 +53,7 @@ var paper = new function() {
// Include Paper classes, which are later injected into PaperScope by setting
// them on the 'this' object, e.g.:
// var Point = this.Point = Base.extend(...);
// var Point = Base.extend(...);
/*#*/ include('basic/Point.js');
/*#*/ include('basic/Size.js');
@ -126,18 +126,7 @@ var paper = new function() {
/*#*/ } // options.svg
/*#*/ include('core/PaperScript.js');
/*#*/ include('core/initialize.js');
/*#*/ if (options.server) {
/*#*/ include('export.js');
return paper;
/*#*/ } else if (options.version != 'dev') {
// Finally inject the classes set on 'this' into the PaperScope class and create
// 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'
};

View file

@ -20,8 +20,7 @@
*
* @extends PathItem
*/
var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
_class: 'CompoundPath',
var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
_serializeFields: {
pathData: ''
},
@ -49,8 +48,8 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath#
* // Move the inner circle 5pt to the right:
* compoundPath.children[1].position.x += 5;
*/
initialize: function(arg) {
this.base();
initialize: function CompoundPath(arg) {
PathItem.call(this);
// CompoundPath has children and supports named children.
this._children = [];
this._namedChildren = {};
@ -58,18 +57,20 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath#
this.addChildren(Array.isArray(arg) ? arg : arguments);
},
insertChild: function(index, item, _preserve) {
// Only allow the insertion of paths
if (item._type !== 'path')
return null;
item = this.base(index, item);
insertChildren: function insertChildren(index, items, _preserve) {
// Pass on 'path' for _type, to make sure that only paths are added as
// children.
items = insertChildren.base.call(this, index, items, _preserve, 'path');
// All children except for the bottom one (first one in list) are set
// to anti-clockwise orientation, so that they appear as holes, but
// only if their orientation was not already specified before
// (= _clockwise is defined).
if (!_preserve && item && item._clockwise === undefined)
item.setClockwise(item._index == 0);
return item;
for (var i = 0, l = !_preserve && items && items.length; i < l; i++) {
var item = items[i];
if (item._clockwise === undefined)
item.setClockwise(item._index === 0);
}
return items;
},
/**
@ -223,8 +224,9 @@ var CompoundPath = this.CompoundPath = PathItem.extend(/** @lends CompoundPath#
return (children.length & 1) == 1 && children;
},
_hitTest: function(point, options) {
var res = this.base(point, Base.merge(options, { fill: false }));
_hitTest: function _hitTest(point, options) {
var res = _hitTest.base.call(this, point,
Base.merge(options, { fill: false }));
if (!res && options.fill && this._style.getFillColor()) {
res = this._contains(point);
res = res ? new HitResult('fill', res[0]) : null;

View file

@ -24,7 +24,7 @@
* convenient ways to work with parts of the path, finding lengths, positions or
* tangents at given offsets.
*/
var Curve = this.Curve = Base.extend(/** @lends Curve# */{
var Curve = Base.extend(/** @lends Curve# */{
/**
* Creates a new curve object.
*
@ -55,7 +55,7 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{
* @param {Number} x2
* @param {Number} y2
*/
initialize: function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
var count = arguments.length;
if (count === 0) {
this._segment1 = new Segment();
@ -243,7 +243,7 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{
var coords = this.getValues(),
points = [];
for (var i = 0; i < 8; i += 2)
points.push(Point.create(coords[i], coords[i + 1]));
points.push(new Point(coords[i], coords[i + 1]));
return points;
},
@ -408,9 +408,9 @@ var Curve = this.Curve = Base.extend(/** @lends Curve# */{
// Create the new segment, convert absolute -> relative:
var x = left[6], y = left[7],
segment = new Segment(Point.create(x, y),
!isLinear && Point.create(left[4] - x, left[5] - y),
!isLinear && Point.create(right[2] - x, right[3] - y));
segment = new Segment(new Point(x, y),
!isLinear && new Point(left[4] - x, left[5] - y),
!isLinear && new Point(right[2] - x, right[3] - y));
// Insert it in the segments list, if needed:
if (this._path) {
@ -662,7 +662,7 @@ statics: {
for (var i = 0; i < 2; i++)
Curve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],
i, 0, min, max, roots);
return Rectangle.create(min[0], min[1], max[0] - min[0], max[1] - min[1]);
return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
},
/**
@ -697,8 +697,8 @@ statics: {
// Only add strokeWidth to bounds for points which lie within 0 < t < 1
// The corner cases for cap and join are handled in getStrokeBounds()
add(v3, 0);
for (var j = 0; j < count; j++) {
var t = roots[j],
for (var i = 0; i < count; i++) {
var t = roots[i],
u = 1 - t;
// Test for good roots and only add to bounds if good.
if (tMin < t && t < tMax)
@ -1023,7 +1023,7 @@ new function() { // Scope for methods that require numerical integration
a, b, 16, /*#=*/ Numerical.TOLERANCE);
}
};
}, new function() { // Scope for Curve intersection
}, new function() { // Scope for intersection using bezier fat-line clipping
function addLocation(locations, curve1, parameter, point, curve2) {
// Avoid duplicates when hitting segments (closed paths too)
var first = locations[0],
@ -1033,7 +1033,7 @@ new function() { // Scope for methods that require numerical integration
locations.push(new CurveLocation(curve1, parameter, point, curve2));
}
function getCurveIntersections(v1, v2, curve1, curve2, locations,
function addCurveIntersections(v1, v2, curve1, curve2, locations,
range1, range2, recursion) {
/*#*/ if (options.fatline) {
// NOTE: range1 and range1 are only used for recusion
@ -1097,17 +1097,17 @@ new function() { // Scope for methods that require numerical integration
if (range1[1] - range1[0] > range2[1] - range2[0]) {
// subdivide v1 and recurse
var t = (range1[0] + range1[1]) / 2;
getCurveIntersections(v1, v2, curve1, curve2, locations,
addCurveIntersections(v1, v2, curve1, curve2, locations,
[ range1[0], t ], range2, recursion);
getCurveIntersections(v1, v2, curve1, curve2, locations,
addCurveIntersections(v1, v2, curve1, curve2, locations,
[ t, range1[1] ], range2, recursion);
break;
} else {
// subdivide v2 and recurse
var t = (range2[0] + range2[1]) / 2;
getCurveIntersections(v1, v2, curve1, curve2, locations,
addCurveIntersections(v1, v2, curve1, curve2, locations,
range1, [ range2[0], t ], recursion);
getCurveIntersections(v1, v2, curve1, curve2, locations,
addCurveIntersections(v1, v2, curve1, curve2, locations,
range1, [ t, range2[1] ], recursion);
break;
}
@ -1123,12 +1123,16 @@ new function() { // Scope for methods that require numerical integration
// Check if one of the parameter range has converged completely to a
// point. Now things could get only worse if we iterate more for the
// other curve to converge if it hasn't yet happened so.
var converged1 = Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE,
converged2 = Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE;
if (converged1 || converged2) {
addLocation(locations, curve1, null, converged1
? curve1.getPointAt(range1[0], true)
: curve2.getPointAt(range2[0], true), curve2);
if (Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE) {
var t = (range1[0] + range1[1]) / 2;
addLocation(locations, curve1, t,
Curve.evaluate(v1, t, true, 0), curve2);
break;
}
if (Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE) {
var t = (range2[0] + range2[1]) / 2;
addLocation(locations, curve2, t,
Curve.evaluate(v2, t, true, 0), curve1);
break;
}
// see if either or both of the curves are flat enough to be treated
@ -1137,10 +1141,10 @@ new function() { // Scope for methods that require numerical integration
flat2 = Curve.isFlatEnough(part2, /*#=*/ Numerical.TOLERANCE);
if (flat1 || flat2) {
(flat1 && flat2
? getLineLineIntersection
? addLineIntersection
// Use curve line intersection method while specifying
// which curve to be treated as line
: getCurveLineIntersections)(part1, part2,
: addCurveLineIntersections)(part1, part2,
curve1, curve2, locations, flat1);
break;
}
@ -1158,15 +1162,7 @@ new function() { // Scope for methods that require numerical integration
&& (Curve.isLinear(v2)
|| Curve.isFlatEnough(v2, /*#=*/ Numerical.TOLERANCE))) {
// See if the parametric equations of the lines interesct.
// var point = new Line(v1[0], v1[1], v1[6], v1[7], false)
// .intersect(new Line(v2[0], v2[1], v2[6], v2[7], false));
// Use static version without creation of Line objects, but it
// doesn't seem to yield measurable speed improvements!
var point = Line.intersect(
v1[0], v1[1], v1[6], v1[7],
v2[0], v2[1], v2[6], v2[7], false);
if (point)
addLocation(locations, curve1, null, point, curve2);
addLineIntersection(v1, v2, curve1, curve2, locations);
} else {
// Subdivide both curves, and see if they intersect.
// If one of the curves is flat already, no further subdivion
@ -1200,6 +1196,7 @@ new function() { // Scope for methods that require numerical integration
p2x = v1[4], p2y = v1[5], p3x = v1[6], p3y = v1[7],
q0x = v2[0], q0y = v2[1], q1x = v2[2], q1y = v2[3],
q2x = v2[4], q2y = v2[5], q3x = v2[6], q3y = v2[7],
getSignedDistance = Line.getSignedDistance,
// Calculate the fat-line L for P is the baseline l and two
// offsets which completely encloses the curve P.
d1 = getSignedDistance(p0x, p0y, p3x, p3y, p1x, p1y) || 0,
@ -1213,20 +1210,19 @@ new function() { // Scope for methods that require numerical integration
dq0 = getSignedDistance(p0x, p0y, p3x, p3y, q0x, q0y),
dq1 = getSignedDistance(p0x, p0y, p3x, p3y, q1x, q1y),
dq2 = getSignedDistance(p0x, p0y, p3x, p3y, q2x, q2y),
dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y),
// Find the minimum and maximum distances from l, this is useful for
// checking whether the curves intersect with each other or not.
mindist = Math.min(dq0, dq1, dq2, dq3),
maxdist = Math.max(dq0, dq1, dq2, dq3);
dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y);
// Find the minimum and maximum distances from l, this is useful for
// checking whether the curves intersect with each other or not.
// If the fatlines don't overlap, we have no intersections!
if (dmin > maxdist || dmax < mindist)
if (dmin > Math.max(dq0, dq1, dq2, dq3)
|| dmax < Math.min(dq0, dq1, dq2, dq3))
return 0;
var Dt = getConvexHull(dq0, dq1, dq2, dq3),
tmp;
var hull = getConvexHull(dq0, dq1, dq2, dq3),
swap;
if (dq3 < dq0) {
tmp = dmin;
swap = dmin;
dmin = dmax;
dmax = tmp;
dmax = swap;
}
// Calculate the convex hull for non-parametric bezier curve D(ti, di(t))
// Now we clip the convex hulls for D(ti, di(t)) with dmin and dmax
@ -1235,31 +1231,29 @@ new function() { // Scope for methods that require numerical integration
var tmaxdmin = -Infinity,
tmin = Infinity,
tmax = -Infinity;
for (var i = 0, l = Dt.length; i < l; i++) {
var Dtl = Dt[i],
dtlx1 = Dtl[0],
dtly1 = Dtl[1],
dtlx2 = Dtl[2],
dtly2 = Dtl[3];
if (dtly2 < dtly1) {
tmp = dtly2;
dtly2 = dtly1;
dtly1 = tmp;
tmp = dtlx2;
dtlx2 = dtlx1;
dtlx1 = tmp;
for (var i = 0, l = hull.length; i < l; i++) {
var p1 = hull[i],
p2 = hull[(i + 1) % l];
if (p2[1] < p1[1]) {
swap = p2;
p2 = p1;
p1 = swap;
}
// We know that (dtlx2 - dtlx1) is never 0
var inv = (dtly2 - dtly1) / (dtlx2 - dtlx1);
if (dmin >= dtly1 && dmin <= dtly2) {
var ixdx = dtlx1 + (dmin - dtly1) / inv;
var x1 = p1[0],
y1 = p1[1],
x2 = p2[0],
y2 = p2[1];
// We know that (x2 - x1) is never 0
var inv = (y2 - y1) / (x2 - x1);
if (dmin >= y1 && dmin <= y2) {
var ixdx = x1 + (dmin - y1) / inv;
if (ixdx < tmin)
tmin = ixdx;
if (ixdx > tmaxdmin)
tmaxdmin = ixdx;
}
if (dmax >= dtly1 && dmax <= dtly2) {
var ixdx = dtlx1 + (dmax - dtly1) / inv;
if (dmax >= y1 && dmax <= y2) {
var ixdx = x1 + (dmax - y1) / inv;
if (ixdx > tmax)
tmax = ixdx;
if (ixdx < tmin)
@ -1269,11 +1263,11 @@ new function() { // Scope for methods that require numerical integration
// Return the parameter values for v2 for which we can be sure that the
// intersection with v1 lies within.
if (tmin !== Infinity && tmax !== -Infinity) {
var mindmin = Math.min(dmin, dmax),
mindmax = Math.max(dmin, dmax);
if (dq3 > mindmin && dq3 < mindmax)
var min = Math.min(dmin, dmax),
max = Math.max(dmin, dmax);
if (dq3 > min && dq3 < max)
tmax = 1;
if (dq0 > mindmin && dq0 < mindmax)
if (dq0 > min && dq0 < max)
tmin = 0;
if (tmaxdmin > tmax)
tmax = 1;
@ -1304,79 +1298,48 @@ new function() { // Scope for methods that require numerical integration
* Calculating convex-hull is much easier than a set of arbitrary points.
*/
function getConvexHull(dq0, dq1, dq2, dq3) {
var distq1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1),
distq2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2);
// Check if [1/3, dq1] and [2/3, dq2] are on the same side of line
// [0,dq0, 1,dq3]
if (distq1 * distq2 < 0) {
// dq1 and dq2 lie on different sides on [0, q0, 1, q3]. The hull is
// a quadrilateral and line [0, q0, 1, q3] is NOT part of the hull
// so we are pretty much done here.
return [
[ 0, dq0, 1 / 3, dq1 ],
[ 1 / 3, dq1, 1, dq3 ],
[ 2 / 3, dq2, 0, dq0 ],
[ 1, dq3, 2 / 3, dq2 ]
];
var p0 = [ 0, dq0 ],
p1 = [ 1 / 3, dq1 ],
p2 = [ 2 / 3, dq2 ],
p3 = [ 1, dq3 ],
// Find signed distance of p1 and p2 from line [ p0, p3 ]
getSignedDistance = Line.getSignedDistance,
dist1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1),
dist2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2);
// Check if p1 and p2 are on the same side of the line [ p0, p3 ]
if (dist1 * dist2 < 0) {
// p1 and p2 lie on different sides of [ p0, p3 ]. The hull is a
// quadrilateral and line [ p0, p3 ] is NOT part of the hull so we
// are pretty much done here.
return [ p0, p1, p3, p2 ];
}
// dq1 and dq2 lie on the same sides on [0, q0, 1, q3]. The hull can be
// a triangle or a quadrilateral and line [0, q0, 1, q3] is part of the
// p1 and p2 lie on the same sides of [ p0, p3 ]. The hull can be
// a triangle or a quadrilateral and line [ p0, p3 ] is part of the
// hull. Check if the hull is a triangle or a quadrilateral.
var dqMaxX, dqMaxY, vqa1a2X, vqa1a2Y, vqa1MaxX, vqa1MaxY, vqa1MinX, vqa1MinY;
if (Math.abs(distq1) > Math.abs(distq2)) {
dqMaxX = 1 / 3;
dqMaxY = dq1;
var pmax, cross;
if (Math.abs(dist1) > Math.abs(dist2)) {
pmax = p1;
// apex is dq3 and the other apex point is dq0 vector
// dqapex->dqapex2 or base vector which is already part of the hull.
vqa1a2X = 1;
vqa1a2Y = dq3 - dq0;
// vector dqapex->dqMax
vqa1MaxX = 2 / 3;
vqa1MaxY = dq3 - dq1;
// vector dqapex->dqmin
vqa1MinX = 1 / 3;
vqa1MinY = dq3 - dq2;
// cross = (vqa1a2X * vqa1MinY - vqa1a2Y * vqa1MinX)
// * (vqa1MaxX * vqa1MinY - vqa1MaxY * vqa1MinX)
cross = (dq3 - dq2 - (dq3 - dq0) / 3)
* (2 * (dq3 - dq2) - dq3 + dq1) / 3;
} else {
dqMaxX = 2 / 3;
dqMaxY = dq2;
pmax = p2;
// apex is dq0 in this case, and the other apex point is dq3 vector
// dqapex->dqapex2 or base vector which is already part of the hull.
vqa1a2X = -1;
vqa1a2Y = dq0 - dq3;
// vector dqapex->dqMax
vqa1MaxX = -2 / 3;
vqa1MaxY = dq0 - dq2;
// vector dqapex->dqmin
vqa1MinX = -1 / 3;
vqa1MinY = dq0 - dq1;
cross = (dq1 - dq0 + (dq0 - dq3) / 3)
* (-2 * (dq0 - dq1) + dq0 - dq2) / 3;
}
// Compare cross products of these vectors to determine, if
// point is in triangles [ dq3, dqMax, dq0 ] or [ dq0, dqMax, dq3 ]
var a1a2_a1Min = vqa1a2X * vqa1MinY - vqa1a2Y * vqa1MinX,
a1Max_a1Min = vqa1MaxX * vqa1MinY - vqa1MaxY * vqa1MinX;
return a1a2_a1Min * a1Max_a1Min < 0
// Point [2/3, dq2] is inside the triangle, hull is a triangle.
? [
[ 0, dq0, dqMaxX, dqMaxY ],
[ dqMaxX, dqMaxY, 1, dq3 ],
[ 1, dq3, 0, dq0 ]
]
// Compare cross products of these vectors to determine if the point is
// in the triangle [ p3, pmax, p0 ], or if it is a quadrilateral.
return cross < 0
// p2 is inside the triangle, hull is a triangle.
? [ p0, pmax, p3 ]
// Convexhull is a quadrilateral and we need all lines in the
// correct order where line [0, q0, 1, q3] is part of the hull.
: [
[ 0, dq0, 1 / 3, dq1 ],
[ 1 / 3, dq1, 2 / 3, dq2 ],
[ 2 / 3, dq2, 1, dq3 ],
[ 1, dq3, 0, dq0 ]
];
}
// This is basically an "unrolled" version of #Line.getDistance() with sign
// May be a static method could be better!
function getSignedDistance(a1x, a1y, a2x, a2y, bx, by) {
var m = (a2y - a1y) / (a2x - a1x),
b = a1y - (m * a1x);
return (by - (m * bx) - b) / Math.sqrt(m * m + 1);
// correct order where line [ p1, p3 ] is part of the hull.
: [ p0, p1, p2, p3 ];
}
/*#*/ } // options.fatline
@ -1386,7 +1349,7 @@ new function() { // Scope for methods that require numerical integration
* line is on the X axis, and solve the implicit equations for the X axis
* and the curve.
*/
function getCurveLineIntersections(v1, v2, curve1, curve2, locations, flip) {
function addCurveLineIntersections(v1, v2, curve1, curve2, locations, flip) {
if (flip === undefined)
flip = Curve.isLinear(v1);
var vc = flip ? v2 : v1,
@ -1432,17 +1395,17 @@ new function() { // Scope for methods that require numerical integration
}
}
function getLineLineIntersection(v1, v2, curve1, curve2, locations) {
function addLineIntersection(v1, v2, curve1, curve2, locations) {
var point = Line.intersect(
v1[0], v1[1], v1[6], v1[7],
v2[0], v2[1], v2[6], v2[7], false);
v2[0], v2[1], v2[6], v2[7]);
// Passing null for parameter leads to lazy determination of parameter
// values in CurveLocation#getParameter() only once they are requested.
if (point)
addLocation(locations, curve1, null, point, curve2);
}
return { statics: {
return { statics: /** @lends Curve */{
// We need to provide the original left curve reference to the
// #getIntersections() calls as it is required to create the resulting
// CurveLocation objects.
@ -1452,10 +1415,10 @@ new function() { // Scope for methods that require numerical integration
// Determine the correct intersection method based on values of
// linear1 & 2:
(linear1 && linear2
? getLineLineIntersection
? addLineIntersection
: linear1 || linear2
? getCurveLineIntersections
: getCurveIntersections)(v1, v2, curve1, curve2, locations);
? addCurveLineIntersections
: addCurveIntersections)(v1, v2, curve1, curve2, locations);
return locations;
}
}};

View file

@ -26,7 +26,7 @@
* {@link PathItem#getIntersections(path)},
* etc.
*/
var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# */{
var CurveLocation = Base.extend(/** @lends CurveLocation# */{
// DOCS: CurveLocation class description: add these back when the mentioned
// functioned have been added: {@link Path#split(location)}
/**
@ -36,7 +36,8 @@ var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# *
* @param {Number} parameter
* @param {Point} point
*/
initialize: function(curve, parameter, point, _otherCurve, _distance) {
initialize: function CurveLocation(curve, parameter, point, _otherCurve,
_distance) {
// Define this CurveLocation's unique id.
this._id = CurveLocation._id = (CurveLocation._id || 0) + 1;
this._curve = curve;

View file

@ -274,7 +274,7 @@ Path.inject({ statics: new function() {
var center = Point.readNamed(arguments, 'center'),
radius = Base.readNamed(arguments, 'radius');
return createEllipse(new Rectangle(center.subtract(radius),
Size.create(radius * 2, radius * 2)))
new Size(radius * 2, radius * 2)))
.set(Base.getNamed(arguments));
},

View file

@ -18,8 +18,7 @@
* @extends PathItem
*/
// DOCS: Explain that path matrix is always applied with each transformation.
var Path = this.Path = PathItem.extend(/** @lends Path# */{
_class: 'Path',
var Path = PathItem.extend(/** @lends Path# */{
_serializeFields: {
segments: [],
closed: false
@ -67,10 +66,10 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
* selected: true
* });
*/
initialize: function(arg) {
initialize: function Path(arg) {
this._closed = false;
this._segments = [];
this.base();
Item.call(this);
// arg can either be an object literal describing properties to be set
// on the path, a list of segments to be set, or the first of multiple
// arguments describing separate segments.
@ -788,12 +787,12 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
this.setSelected(selected);
},
setSelected: function(selected) {
setSelected: function setSelected(selected) {
// Deselect all segments when path is marked as not selected
if (!selected)
this._selectSegments(false);
// No need to pass true for noChildren since Path has none anyway.
this.base(selected);
setSelected.base.call(this, selected);
},
_selectSegments: function(selected) {
@ -1982,13 +1981,13 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
segment.setHandleIn(handleIn.subtract(segment._point));
if (i < n) {
segment.setHandleOut(
Point.create(x[i], y[i]).subtract(segment._point));
new Point(x[i], y[i]).subtract(segment._point));
if (i < n - 1)
handleIn = Point.create(
handleIn = new Point(
2 * knots[i + 1]._x - x[i + 1],
2 * knots[i + 1]._y - y[i + 1]);
else
handleIn = Point.create(
handleIn = new Point(
(knots[n]._x + x[n - 1]) / 2,
(knots[n]._y + y[n - 1]) / 2);
}
@ -2104,11 +2103,11 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
// Construct the two perpendicular middle lines to (from, through)
// and (through, to), and intersect them to get the center
var l1 = new Line(from.add(through).divide(2),
through.subtract(from).rotate(90)),
through.subtract(from).rotate(90), true),
l2 = new Line(through.add(to).divide(2),
to.subtract(through).rotate(90)),
center = l1.intersect(l2),
line = new Line(from, to, true),
to.subtract(through).rotate(90), true),
center = l1.intersect(l2, true),
line = new Line(from, to),
throughSide = line.getSide(through);
if (!center) {
// If the two lines are colinear, there cannot be an arc as the
@ -2179,7 +2178,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
throughVector = Point.read(throughVector);
toVector = Point.read(toVector);
var current = getCurrentSegment(this)._point;
this.arcBy(current.add(throughVector), current.add(toVector));
this.arcTo(current.add(throughVector), current.add(toVector));
},
closePath: function() {
@ -2283,7 +2282,7 @@ statics: {
processSegment(segments[i]);
if (closed)
processSegment(first);
return Rectangle.create(min[0], min[1], max[0] - min[0], max[1] - min[1]);
return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);
},
/**
@ -2305,8 +2304,8 @@ statics: {
// Get rotated hor and ver vectors, and determine rotation angle
// and elipse values from them:
var mx = matrix.shiftless(),
hor = mx.transform(Point.create(radius, 0)),
ver = mx.transform(Point.create(0, radius)),
hor = mx.transform(new Point(radius, 0)),
ver = mx.transform(new Point(0, radius)),
phi = hor.getAngleInRadians(),
a = hor.getLength(),
b = ver.getLength();
@ -2389,10 +2388,10 @@ statics: {
normal2 = curve2.getNormalAt(0, true).normalize(miterRadius),
// Intersect the two lines
line1 = new Line(point.add(normal1),
Point.create(-normal1.y, normal1.x)),
new Point(-normal1.y, normal1.x), true),
line2 = new Line(point.add(normal2),
Point.create(-normal2.y, normal2.x)),
corner = line1.intersect(line2);
new Point(-normal2.y, normal2.x), true),
corner = line1.intersect(line2, true);
// Now measure the distance from the segment to the
// intersection, which his half of the miter distance
if (!corner || point.getDistance(corner) > miterLimit) {
@ -2466,7 +2465,7 @@ statics: {
if (yx > y2) y2 = yx;
}
}
return Rectangle.create(x1, y1, x2 - x1, y2 - y1);
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
},
/**

View file

@ -158,7 +158,7 @@ PathItem.inject(new function() {
if (segment.getPrevious()._invalid)
segment.setHandleIn(intersection
? intersection._handleIn
: Point.create(0, 0));
: new Point(0, 0));
do {
segment._visited = true;
if (segment._invalid && segment._intersection) {

View file

@ -19,7 +19,11 @@
*
* @extends Item
*/
var PathItem = this.PathItem = Item.extend(/** @lends PathItem# */{
var PathItem = Item.extend(/** @lends PathItem# */{
initialize: function PathItem() {
Item.apply(this, arguments);
},
/**
* Returns all intersections between two {@link PathItem} items as an array
* of {@link CurveLocation} objects. {@link CompoundPath} items are also

View file

@ -22,9 +22,7 @@
* {@link Segment#handleOut}), describing the tangents of the two {@link Curve}
* objects that are connected by this segment.
*/
var Segment = this.Segment = Base.extend(/** @lends Segment# */{
_class: 'Segment',
var Segment = Base.extend(/** @lends Segment# */{
/**
* Creates a new Segment object.
*
@ -110,7 +108,7 @@ var Segment = this.Segment = Base.extend(/** @lends Segment# */{
* path.strokeColor = 'black';
* @ignore
*/
initialize: function(arg0, arg1, arg2, arg3, arg4, arg5) {
initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {
var count = arguments.length,
createPoint = SegmentPoint.create,
point, handleIn, handleOut;

View file

@ -30,7 +30,7 @@
* An array of all open projects is accessible through the
* {@link PaperScope#projects} variable.
*/
var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
var Project = PaperScopeItem.extend(/** @lends Project# */{
_list: 'projects',
_reference: 'project',
@ -44,10 +44,10 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
* @param {View|HTMLCanvasElement} view Either a view object or an HTML
* Canvas element that should be wrapped in a newly created view.
*/
initialize: function(view) {
initialize: function Project(view) {
// Activate straight away by passing true to base(), so paper.project is
// set, as required by Layer and DoumentView constructors.
this.base(true);
PaperScopeItem.call(this, true);
this.layers = [];
this.symbols = [];
this._currentStyle = new Style();
@ -69,12 +69,8 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
// into the active project automatically. We might want to add proper
// project serialization later, but deserialization of a layers array
// will always work.
return Base.serialize(this.layers, options, false, dictionary);
},
_needsRedraw: function() {
if (this.view)
this.view._redrawNeeded = true;
// Pass true for compact, so 'Project' does not get added as the class
return Base.serialize(this.layers, options, true, dictionary);
},
/**
@ -97,8 +93,8 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
* Removes this project from the {@link PaperScope#projects} list, and also
* removes its view, if one was defined.
*/
remove: function() {
if (!this.base())
remove: function remove() {
if (!remove.base.call(this))
return false;
if (this.view)
this.view.remove();
@ -271,6 +267,7 @@ var Project = this.Project = PaperScopeItem.extend(/** @lends Project# */{
// DOCS: Figure out a way to group these together with importSVG / exportSVG
importJSON: function(json) {
this.activate();
return Base.importJSON(json);
},

View file

@ -19,9 +19,7 @@
* internal properties such as segment lists and gradient positions don't need
* to be updated with every transformation.
*/
var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
_class: 'Symbol',
var Symbol = Base.extend(/** @lends Symbol# */{
/**
* Creates a Symbol item.
*
@ -59,7 +57,7 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
* instance.scale(0.25 + Math.random() * 0.75);
* }
*/
initialize: function(item, dontCenter) {
initialize: function Symbol(item, dontCenter) {
// Define this Symbols's unique id.
this._id = Symbol._id = (Symbol._id || 0) + 1;
this.project = paper.project;
@ -72,7 +70,7 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
_serialize: function(options, dictionary) {
return dictionary.add(this, function() {
return Base.serialize([this._class, this._definition],
return Base.serialize([this.constructor.name, this._definition],
options, false, dictionary);
});
},

View file

@ -40,7 +40,7 @@
* // converted to a Color.
* circle.fillColor = '#ff0000';
*/
var Color = this.Color = Base.extend(new function() {
var Color = Base.extend(new function() {
var types = {
gray: ['gray'],
@ -275,7 +275,6 @@ var Color = this.Color = Base.extend(new function() {
};
}, this);
}, /** @lends Color# */{
_class: 'Color',
// Tell Base.read that the Point constructor supports reading with index
_readIndex: true,
@ -436,7 +435,7 @@ var Color = this.Color = Base.extend(new function() {
* // 100% and a lightness of 50%:
* circle.fillColor = { hue: 90, saturation: 1, lightness: 0.5 };
*/
initialize: function(arg) {
initialize: function Color(arg) {
// We are storing color internally as an array of components
var slice = Array.prototype.slice,
args = arguments,
@ -503,7 +502,7 @@ var Color = this.Color = Base.extend(new function() {
: nameToRGB(arg);
type = 'rgb';
} else if (argType === 'object') {
if (arg._class === 'Color') {
if (arg.constructor === Color) {
type = arg._type;
components = arg._components.slice();
alpha = arg._alpha;
@ -516,7 +515,7 @@ var Color = this.Color = Base.extend(new function() {
components[i] = point.clone();
}
}
} else if (arg._class === 'Gradient') {
} else if (arg.constructor === Gradient) {
type = 'gradient';
values = args;
} else {

View file

@ -59,11 +59,9 @@
* destination: path.bounds.rightCenter
* };
*/
var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{
_class: 'Gradient',
var Gradient = Base.extend(/** @lends Gradient# */{
// DOCS: Document #initialize()
initialize: function(stops, radial) {
initialize: function Gradient(stops, radial) {
// Define this Gradient's unique id.
this._id = Gradient._id = (Gradient._id || 0) + 1;
if (stops && this._set(stops))

View file

@ -16,7 +16,7 @@
*
* @class The GradientStop object.
*/
var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
var GradientStop = Base.extend(/** @lends GradientStop# */{
/**
* Creates a GradientStop object.
*
@ -24,7 +24,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
* @param {Number} [rampPoint=0] the position of the stop on the gradient
* ramp as a value between 0 and 1.
*/
initialize: function(arg0, arg1) {
initialize: function GradientStop(arg0, arg1) {
if (arg0) {
var color, rampPoint;
if (arg1 === undefined && Array.isArray(arg0)) {

View file

@ -65,7 +65,7 @@
* };
*
*/
var Style = this.Style = Base.extend(new function() {
var Style = Base.extend(new function() {
// windingRule / resolution / fillOverprint / strokeOverprint are currently
// not supported.
var defaults = {
@ -201,7 +201,7 @@ var Style = this.Style = Base.extend(new function() {
Item.inject(item);
return fields;
}, /** @lends Style# */{
initialize: function(style) {
initialize: function Style(style) {
// We keep values in a separate object that we can iterate over.
this._values = {};
if (this._item instanceof TextItem)
@ -223,9 +223,9 @@ var Style = this.Style = Base.extend(new function() {
}
},
getLeading: function() {
getLeading: function getLeading() {
// Override leading to return fontSize * 1.2 by default.
var leading = this.base();
var leading = getLeading.base.call(this);
return leading != null ? leading : this.getFontSize() * 1.2;
},

View file

@ -122,10 +122,10 @@ new function() {
if (handle1.isOrthogonal(handle2)) {
var from = segment._point,
to = next._point,
// Find hte corner point by intersecting the lines described
// Find the corner point by intersecting the lines described
// by both handles:
corner = new Line(from, handle1).intersect(
new Line(to, handle2));
corner = new Line(from, handle1, true).intersect(
new Line(to, handle2, true), true);
return corner && Numerical.isZero(handle1.getLength() /
corner.subtract(from).getLength() - kappa)
&& Numerical.isZero(handle2.getLength() /

View file

@ -44,14 +44,14 @@ new function() {
x = getValue(node, x, false, allowNull);
y = getValue(node, y, false, allowNull);
return allowNull && x == null && y == null ? null
: Point.create(x || 0, y || 0);
: new Point(x || 0, y || 0);
}
function getSize(node, w, h, allowNull) {
w = getValue(node, w, false, allowNull);
h = getValue(node, h, false, allowNull);
return allowNull && w == null && h == null ? null
: Size.create(w || 0, h || 0);
: new Size(w || 0, h || 0);
}
// Converts a string attribute value to the specified type
@ -383,7 +383,8 @@ new function() {
'stop-color': function(item, value) {
// http://www.w3.org/TR/SVG/pservers.html#StopColorProperty
item.setColor(value);
if (item.setColor)
item.setColor(value);
},
'stop-opacity': function(item, value) {

View file

@ -19,9 +19,7 @@
*
* @extends TextItem
*/
var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{
_class: 'PointText',
var PointText = TextItem.extend(/** @lends PointText# */{
/**
* Creates a point text item
*
@ -43,6 +41,9 @@ var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{
* fontSize: 25
* });
*/
initialize: function PointText() {
TextItem.apply(this, arguments);
},
clone: function() {
return this._clone(new PointText());
@ -109,7 +110,7 @@ var PointText = this.PointText = TextItem.extend(/** @lends PointText# */{
x -= width / (justification === 'center' ? 2: 1);
// Until we don't have baseline measuring, assume leading / 4 as a
// rough guess:
var bounds = Rectangle.create(x,
var bounds = new Rectangle(x,
count ? leading / 4 + (count - 1) * leading : 0,
width, -count * leading);
return matrix ? matrix._transformBounds(bounds, bounds) : bounds;

View file

@ -21,7 +21,7 @@
*
* @extends Item
*/
var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
var TextItem = Item.extend(/** @lends TextItem# */{
_boundsSelected: true,
_serializeFields: {
content: null
@ -30,7 +30,7 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
// so use the same name for all of them
_boundsGetter: 'getBounds',
initialize: function(arg) {
initialize: function TextItem(arg) {
// Support two forms of item initialization: Passing one object literal
// describing all the different properties to be set, or a point where
// it should be placed (arg).
@ -38,7 +38,7 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
// might be a properties object literal for #setPropeties() at the end.
var hasProperties = arg && Base.isPlainObject(arg)
&& arg.x === undefined && arg.y === undefined;
this.base(hasProperties ? null : Point.read(arguments));
Item.call(this, hasProperties ? null : Point.read(arguments));
this._content = '';
this._lines = [];
if (hasProperties)
@ -77,9 +77,9 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
* }
*/
_clone: function(copy) {
_clone: function _clone(copy) {
copy.setContent(this._content);
return this.base(copy);
return _clone.base.call(this, copy);
},
getContent: function() {

View file

@ -42,7 +42,7 @@
* path.add(event.point);
* }
*/
var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{
var Tool = PaperScopeItem.extend(/** @lends Tool# */{
_list: 'tools',
_reference: '_tool', // PaperScope has accessor for #tool
_events: [ 'onActivate', 'onDeactivate', 'onEditOptions',
@ -50,8 +50,8 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{
'onKeyDown', 'onKeyUp' ],
// DOCS: rewrite Tool constructor explanation
initialize: function(props) {
this.base();
initialize: function Tool(props) {
PaperScopeItem.call(this);
this._firstMove = true;
this._count = 0;
this._downCount = 0;
@ -322,7 +322,7 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{
return true;
},
fire: function(type, event) {
fire: function fire(type, event) {
// Override Callback#fire() so we can handle items marked in removeOn*()
// calls first,.
var sets = Tool._removeSets;
@ -346,7 +346,7 @@ var Tool = this.Tool = PaperScopeItem.extend(/** @lends Tool# */{
sets[type] = null;
}
}
return this.base(type, event);
return fire.base.call(this, type, event);
},
_onHandleEvent: function(type, point, event) {

View file

@ -21,11 +21,11 @@
*
* @extends Event
*/
var ToolEvent = this.ToolEvent = Event.extend(/** @lends ToolEvent# */{
var ToolEvent = Event.extend(/** @lends ToolEvent# */{
// Have ToolEvent#item fall back to returning null, not undefined.
_item: null,
initialize: function(tool, type, event) {
initialize: function ToolEvent(tool, type, event) {
this.tool = tool;
this.type = type;
this.event = event;

View file

@ -22,19 +22,19 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
* @param {HTMLCanvasElement} canvas The canvas object that this view should
* wrap
*/
initialize: function(canvas) {
initialize: function CanvasView(canvas) {
// Handle canvas argument
if (!(canvas instanceof HTMLCanvasElement)) {
// 2nd argument onwards could be view size, otherwise use default:
var size = Size.read(arguments, 1);
if (size.isZero())
size = Size.create(1024, 768);
size = new Size(1024, 768);
canvas = CanvasProvider.getCanvas(size);
}
this._context = canvas.getContext('2d');
// Have Item count installed mouse events.
this._eventCounters = {};
this.base(canvas);
View.call(this, canvas);
},
/**
@ -44,7 +44,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
* @function
*/
draw: function(checkRedraw) {
if (checkRedraw && !this._redrawNeeded)
if (checkRedraw && !this._project._needsRedraw)
return false;
// Initial tests conclude that clearing the canvas using clearRect
// is always faster than setting canvas.width = canvas.width
@ -53,7 +53,7 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
size = this._viewSize;
ctx.clearRect(0, 0, size._width + 1, size._height + 1);
this._project.draw(ctx, this._matrix);
this._redrawNeeded = false;
this._project._needsRedraw = false;
return true;
}
}, new function() { // Item based mouse handling:
@ -169,8 +169,8 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
};
});
/*#*/ if (options.server) {
// Node.js server based image exporting code.
/*#*/ if (options.node) {
// Node.js based image exporting code.
CanvasView.inject(new function() {
// Utility function that converts a number to a string with
// x amount of padded 0 digits:
@ -252,4 +252,4 @@ CanvasView.inject(new function() {
}
};
});
/*#*/ } // options.server
/*#*/ } // options.node

View file

@ -14,7 +14,7 @@
* @name Component
* @class
*/
var Component = this.Component = Base.extend(Callback, /** @lends Component# */{
var Component = Base.extend(Callback, /** @lends Component# */{
_events: [ 'onChange', 'onClick' ],
_types: {
@ -58,7 +58,7 @@ var Component = this.Component = Base.extend(Callback, /** @lends Component# */{
}
},
initialize: function(obj) {
initialize: function Component(obj) {
this._type = obj.type in this._types
? obj.type
: 'options' in obj

View file

@ -14,8 +14,8 @@
* @name Event
* @class
*/
var Event = this.Event = Base.extend(/** @lends Event# */{
initialize: function(event) {
var Event = Base.extend(/** @lends Event# */{
initialize: function Event(event) {
this.event = event;
},

View file

@ -14,7 +14,7 @@
* @name Key
* @namespace
*/
var Key = this.Key = new function() {
var Key = new function() {
// TODO: Make sure the keys are called the same as in Scriptographer
// Missing: tab, cancel, clear, page-down, page-up, comma, minus, period,
// slash, etc etc etc.

View file

@ -20,9 +20,9 @@
*
* @extends Event
*/
var KeyEvent = this.KeyEvent = Event.extend(/** @lends KeyEvent# */{
initialize: function(down, key, character, event) {
this.base(event);
var KeyEvent = Event.extend(/** @lends KeyEvent# */{
initialize: function KeyEvent(down, key, character, event) {
Event.call(this, event);
this.type = down ? 'keydown' : 'keyup';
this.key = key;
this.character = character;

View file

@ -22,9 +22,9 @@
*
* @extends Event
*/
var MouseEvent = this.MouseEvent = Event.extend(/** @lends MouseEvent# */{
initialize: function(type, event, point, target, delta) {
this.base(event);
var MouseEvent = Event.extend(/** @lends MouseEvent# */{
initialize: function MouseEvent(type, event, point, target, delta) {
Event.call(this, event);
this.type = type;
this.point = point;
this.target = target;

View file

@ -14,10 +14,10 @@
* @name Palette
* @class
*/
var Palette = this.Palette = Base.extend(Callback, /** @lends Palette# */{
var Palette = Base.extend(Callback, /** @lends Palette# */{
_events: [ 'onChange' ],
initialize: function(title, components, values) {
initialize: function Palette(title, components, values) {
var parent = DomElement.find('.palettejs-panel')
|| DomElement.find('body').appendChild(
DomElement.create('div', { 'class': 'palettejs-panel' }));
@ -49,7 +49,6 @@ var Palette = this.Palette = Base.extend(Callback, /** @lends Palette# */{
Base.define(values, name, {
enumerable: true,
configurable: true,
writable: true,
get: function() {
return component._value;
},

View file

@ -19,8 +19,8 @@
* center, both useful for constructing artwork that should appear centered on
* screen.
*/
var View = this.View = Base.extend(Callback, /** @lends View# */{
initialize: function(element) {
var View = Base.extend(Callback, /** @lends View# */{
initialize: function View(element) {
// Store reference to the currently active global paper scope, and the
// active project, which will be represented by this view
this._scope = paper;
@ -60,7 +60,7 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{
// If the element is invisible, we cannot directly access
// element.width / height, because they would appear 0.
// Reading the attributes still works.
size = Size.create(parseInt(element.getAttribute('width'), 10),
size = new Size(parseInt(element.getAttribute('width'), 10),
parseInt(element.getAttribute('height'), 10));
// If no size was specified on the canvas, read it from CSS
if (size.isNaN())
@ -83,11 +83,11 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{
style.top = offset.y + 'px';
document.body.appendChild(stats);
}
/*#*/ } else if (options.server) {
/*#*/ } else if (options.node) {
// Generate an id for this view
this._id = 'view-' + View._id++;
size = Size.create(element.width, element.height);
/*#*/ } // options.server
size = new Size(element.width, element.height);
/*#*/ } // options.node
// Keep track of views internally
View._views.push(this);
// Link this id to our view
@ -235,7 +235,7 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{
},
_redraw: function() {
this._redrawNeeded = true;
this._project._needsRedraw = true;
if (this._handlingFrame)
return;
if (this._animate) {

View file

@ -30,6 +30,8 @@ var Formatter = Base.extend({
* @param {Number} num the number to be converted to a string
*/
number: function(val) {
// It would be nice to use Number#toFixed() instead, but it pads with 0,
// unecessarily consuming space.
return Math.round(val * this.multiplier) / this.multiplier;
},

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
var Numerical = this.Numerical = new function() {
var Numerical = new function() {
// Lookup tables for abscissas and weights with values for n = 2 .. 16.
// As values are symetric, only store half of them and addapt algorithm