diff --git a/.env b/.env index 753f02789..831c3d5f9 100644 --- a/.env +++ b/.env @@ -1,2 +1,3 @@ NODE_PATH='src/' GENERATE_SOURCEMAP=false +VITE_PUBLIC_URL=/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8f96682fd..8e05f7b23 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,9 @@ /public/corelibs/wick-engine/ /engine/dist/ +# package-lock +package-lock.json + # misc .DS_Store .env.local diff --git a/README.md b/README.md index 0495097fa..27c211bf5 100644 --- a/README.md +++ b/README.md @@ -81,21 +81,21 @@ Then create a production build of the project: ``` npm run build ``` -^ This command is not always needed while testing, you'll need it most prior to deploying your code +^ This command is not always needed while testing, you'll need it most prior to deploying your code because it's basically just an optimisation command you don't need to use much And lastly, to run your project in development: ``` npm start ``` +While working on the engine it's easier to test by running npm run engine-quickrun If it worked, you should see something like this in the terminal. ``` -Compiled successfully! +VITE v8.1.5 ready in 450 ms -You can now view Candlestick in the browser. - - Local: http://localhost:3000/ - On Your Network: http://###.###.#.###:3000/ + ➜ Local: http://localhost:3000/ + ➜ Network: use --host to expose + ➜ press h + enter to show help ``` If you go to your browser and open up [http://localhost:3000/](http://localhost:3000/) you should find the project there. You can also test on your mobile devices by going to the network `http://###.###.#.###:3000/` link on another device *connected to the same network* (it should work, but if it doesn't, it could be due to certain network restrictions). @@ -118,10 +118,10 @@ Wick Editor was created by Luca Damasco and Zach Rispoli. See more credits on th Candlestick was created and is maintained by [Hamzah Alani](https://forum.wickeditor.com/u/hamzah_alani/summary), [Baron](https://forum.wickeditor.com/u/baronawc/summary), and [Jovanny Rodriguez](https://forum.wickeditor.com/u/jovanny/summary). Active contributors: -- [StickmanRed](https://forum.wickeditor.com/u/stickmanred/summary) +- [StickmanRed](https://forum.wickeditor.com/u/stickmanred/summary) also found at (https://github.com/StickmanRed) Additional, indirect contributors: -- [pumpkinhead](https://forum.wickeditor.com/u/pumpkinhead/summary) +- [pumpkinhead](https://forum.wickeditor.com/u/pumpkinhead/summary) also found at [pkhead](https://github.com/pkhead) - [SomeoneElse](https://forum.wickeditor.com/u/someoneelse/summary) ___ diff --git a/engine/gulpfile.js b/engine/gulpfile.js deleted file mode 100644 index b90e28d10..000000000 --- a/engine/gulpfile.js +++ /dev/null @@ -1,189 +0,0 @@ -var fs = require('fs'); -var gulp = require('gulp'); -var babel = require("gulp-babel"); -var concat = require('gulp-concat'); -var rename = require('gulp-rename'); -var uglify = require('gulp-uglify'); -var header = require('gulp-header'); -var mergeStream = require('merge-stream'); - -gulp.task("default", function() { - /* Generate build number */ - /* Year.Month.Day[micro] */ - var date = new Date(); - var year = date.getFullYear(); - var month = date.getMonth() + 1; - var day = date.getDate(); - var hour = date.getHours(); - var minute = date.getMinutes(); - var second = date.getSeconds(); - var buildString = year + '.' + month + '.' + day + '.' + hour + '.' + minute + '.' + second; - - /* Libraries */ - var libs = gulp - .src([ - 'lib/paper.js', - 'lib/base64-arraybuffer.js', - 'lib/convert-range.js', - 'lib/croquis.js', - 'lib/currentTransform.js', - 'lib/esprima.js', - 'lib/floodfill.min.js', - 'lib/howler.js', - 'lib/hull.js', - 'lib/invert.min.js', - 'lib/is-var-name.js', - 'lib/jquery-3.3.1.min.js', - 'lib/jquery.pressure.js', - 'lib/jquery.mousewheel.js', - 'lib/jszip.js', - 'lib/lerp.js', - 'lib/localforage.min.js', - 'lib/platform.js', - 'lib/potrace.js', - 'lib/reserved-words.js', - 'lib/roundRect.js', - 'lib/timestamp.js', - 'lib/soundcloud-waveform.js', - 'lib/Tween.js', - 'lib/uuid.js' - ]) - .pipe(concat('libs.js')); - - /* Engine */ - var src = gulp - .src([ - 'src/Wick.js', - 'src/Clipboard.js', - 'src/Quadtree.js', - 'src/Color.js', - 'src/FileCache.js', - 'src/History.js', - 'src/ObjectCache.js', - 'src/Transformation.js', - 'src/ToolSettings.js', - 'src/ObjectCache.js', - 'src/Transformation.js', - 'src/GlobalAPI.js', - 'src/builtinassets/BuiltinAssets.js', - 'src/export/ExportUtils.js', - 'src/export/audio/AudioTrack.js', - 'src/export/autosave/AutoSave.js', - 'src/export/wick/WickFile.js', - 'src/export/wick/WickFile.Alpha.js', - 'src/export/wickobj/WickObjectFile.js', - 'src/export/html/HTMLExport.js', - 'src/export/html/HTMLPreview.js', - 'src/export/svg/SvgFile.js', - 'src/export/image/imageSequence.js', - 'src/export/zip/ZIPExport.js', - 'src/base/Base.js', - 'src/base/Layer.js', - 'src/base/Project.js', - 'src/base/Selection.js', - 'src/base/Timeline.js', - 'src/base/Tween.js', - 'src/base/Path.js', - 'src/base/asset/Asset.js', - 'src/base/asset/FileAsset.js', - 'src/base/asset/FontAsset.js', - 'src/base/asset/ImageAsset.js', - 'src/base/asset/ClipAsset.js', - 'src/base/asset/GIFAsset.js', - 'src/base/asset/SoundAsset.js', - 'src/base/asset/SVGAsset.js', - 'src/base/WickSound.js', - 'src/base/Tickable.js', - 'src/base/Frame.js', - 'src/base/Clip.js', - 'src/base/Button.js', - 'src/tools/Tool.js', - 'src/tools/Brush.js', - 'src/tools/Cursor.js', - 'src/tools/Ellipse.js', - 'src/tools/Eraser.js', - 'src/tools/Eyedropper.js', - 'src/tools/FillBucket.js', - 'src/tools/Interact.js', - 'src/tools/Line.js', - 'src/tools/None.js', - 'src/tools/Pan.js', - 'src/tools/PathCursor.js', - 'src/tools/Pencil.js', - 'src/tools/Rectangle.js', - 'src/tools/Text.js', - 'src/tools/Zoom.js', - 'src/view/paper-ext/Layer.erase.js', - //'src/view/paper-ext/Offsets/PaperJsExtensions.js', - 'src/view/paper-ext/Paper.hole.js', - 'src/view/paper-ext/Paper.OrderingUtils.js', - 'src/view/paper-ext/Paper.SelectionWidget.js', - 'src/view/paper-ext/Paper.SelectionBox.js', - 'src/view/paper-ext/Path.potrace.js', - 'src/view/paper-ext/TextItem.edit.js', - 'src/view/paper-ext/View.pressure.js', - 'src/view/paper-ext/View.gestures.js', - 'src/view/paper-ext/View.scrollToZoom.js', - 'src/view/View.js', - 'src/view/View.Project.js', - 'src/view/View.Selection.js', - 'src/view/View.Clip.js', - 'src/view/View.Button.js', - 'src/view/View.Timeline.js', - 'src/view/View.Layer.js', - 'src/view/View.Frame.js', - 'src/view/View.Path.js', - 'src/gui/GUIElement.js', - 'src/gui/Button.js', - 'src/gui/Ghost.js', - 'src/gui/Icons.js', - 'src/gui/ActionButton.js', - 'src/gui/ActionButtonsContainer.js', - 'src/gui/Breadcrumbs.js', - 'src/gui/BreadcrumbsButton.js', - 'src/gui/Frame.js', - 'src/gui/FrameEdgeGhost.js', - 'src/gui/FrameGhost.js', - 'src/gui/FramesContainer.js', - 'src/gui/Layer.js', - 'src/gui/LayerButton.js', - 'src/gui/LayerCreateLabel.js', - 'src/gui/LayersContainer.js', - 'src/gui/NumberLine.js', - 'src/gui/OnionSkinRange.js', - 'src/gui/Playhead.js', - 'src/gui/PopupMenu.js', - 'src/gui/Project.js', - 'src/gui/Scrollbar.js', - 'src/gui/ScrollbarGrabber.js', - 'src/gui/SelectionBox.js', - 'src/gui/Timeline.js', - 'src/gui/Tooltip.js', - 'src/gui/Tween.js', - 'src/gui/TweenGhost.js', - ]) - .pipe(babel()) - .pipe(concat('src.js')); - - /* Write wickengine.js */ - return mergeStream(src, libs) - .pipe(concat('wickengine.js')) - .pipe(header('/*Wick Engine https://github.com/Wicklets/wick-engine*/\nvar WICK_ENGINE_BUILD_VERSION = "' + buildString + '";\n')) - .pipe(gulp.dest('dist')) - .on('end', () => { - /* Generate empty HTML file ready for wick projects to be injected into */ - var blankHTML = fs.readFileSync('src/export/html/project.html', 'utf8'); - var engineSRC = fs.readFileSync('dist/wickengine.js', 'utf8'); - var engineSRCSafe = engineSRC.replace(/\$/g, "$$$"); // http://forums.mozillazine.org/viewtopic.php?f=19&t=2182187 - blankHTML = blankHTML.replace('', engineSRCSafe); - fs.writeFileSync('dist/emptyproject.html', blankHTML); - - /* Copy ZIP export resources to dist folder */ - var zipindex = fs.readFileSync('src/export/zip/index.html', 'utf8'); - var preloadjs = fs.readFileSync('src/export/zip/preloadjs.min.js', 'utf8'); - var projecthtml = fs.readFileSync('src/export/html/project.html', 'utf8'); - fs.writeFileSync('dist/index.html', zipindex); - fs.writeFileSync('dist/preloadjs.min.js', preloadjs); - fs.writeFileSync('dist/project.html', projecthtml); - }); -}); diff --git a/engine/lib/Tween.js b/engine/lib/Tween.js deleted file mode 100644 index dcf10e241..000000000 --- a/engine/lib/Tween.js +++ /dev/null @@ -1,882 +0,0 @@ -/** - * Tween.js - Licensed under the MIT license - * https://github.com/tweenjs/tween.js - * ---------------------------------------------- - * - * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors. - * Thank you all, you're awesome! - */ - -var TWEEN = TWEEN || (function () { - - var _tweens = []; - - return { - - getAll: function () { - - return _tweens; - - }, - - removeAll: function () { - - _tweens = []; - - }, - - add: function (tween) { - - _tweens.push(tween); - - }, - - remove: function (tween) { - - var i = _tweens.indexOf(tween); - - if (i !== -1) { - _tweens.splice(i, 1); - } - - }, - - update: function (time, preserve) { - - if (_tweens.length === 0) { - return false; - } - - var i = 0; - - time = time !== undefined ? time : TWEEN.now(); - - while (i < _tweens.length) { - - if (_tweens[i].update(time) || preserve) { - i++; - } else { - _tweens.splice(i, 1); - } - - } - - return true; - - } - }; - -})(); - - -// Include a performance.now polyfill. -// In node.js, use process.hrtime. -if (typeof (window) === 'undefined' && typeof (process) !== 'undefined') { - TWEEN.now = function () { - var time = process.hrtime(); - - // Convert [seconds, nanoseconds] to milliseconds. - return time[0] * 1000 + time[1] / 1000000; - }; -} -// In a browser, use window.performance.now if it is available. -else if (typeof (window) !== 'undefined' && - window.performance !== undefined && - window.performance.now !== undefined) { - // This must be bound, because directly assigning this function - // leads to an invocation exception in Chrome. - TWEEN.now = window.performance.now.bind(window.performance); -} -// Use Date.now if it is available. -else if (Date.now !== undefined) { - TWEEN.now = Date.now; -} -// Otherwise, use 'new Date().getTime()'. -else { - TWEEN.now = function () { - return new Date().getTime(); - }; -} - - -TWEEN.Tween = function (object) { - - var _object = object; - var _valuesStart = {}; - var _valuesEnd = {}; - var _valuesStartRepeat = {}; - var _duration = 1000; - var _repeat = 0; - var _repeatDelayTime; - var _yoyo = false; - var _isPlaying = false; - var _reversed = false; - var _delayTime = 0; - var _startTime = null; - var _easingFunction = TWEEN.Easing.Linear.None; - var _interpolationFunction = TWEEN.Interpolation.Linear; - var _chainedTweens = []; - var _onStartCallback = null; - var _onStartCallbackFired = false; - var _onUpdateCallback = null; - var _onCompleteCallback = null; - var _onStopCallback = null; - - this.to = function (properties, duration) { - - _valuesEnd = properties; - - if (duration !== undefined) { - _duration = duration; - } - - return this; - - }; - - this.start = function (time) { - - TWEEN.add(this); - - _isPlaying = true; - - _onStartCallbackFired = false; - - _startTime = time !== undefined ? time : TWEEN.now(); - _startTime += _delayTime; - - for (var property in _valuesEnd) { - - // Check if an Array was provided as property value - if (_valuesEnd[property] instanceof Array) { - - if (_valuesEnd[property].length === 0) { - continue; - } - - // Create a local copy of the Array with the start value at the front - _valuesEnd[property] = [_object[property]].concat(_valuesEnd[property]); - - } - - // If `to()` specifies a property that doesn't exist in the source object, - // we should not set that property in the object - if (_object[property] === undefined) { - continue; - } - - // Save the starting value. - _valuesStart[property] = _object[property]; - - if ((_valuesStart[property] instanceof Array) === false) { - _valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings - } - - _valuesStartRepeat[property] = _valuesStart[property] || 0; - - } - - return this; - - }; - - this.stop = function () { - - if (!_isPlaying) { - return this; - } - - TWEEN.remove(this); - _isPlaying = false; - - if (_onStopCallback !== null) { - _onStopCallback.call(_object, _object); - } - - this.stopChainedTweens(); - return this; - - }; - - this.end = function () { - - this.update(_startTime + _duration); - return this; - - }; - - this.stopChainedTweens = function () { - - for (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) { - _chainedTweens[i].stop(); - } - - }; - - this.delay = function (amount) { - - _delayTime = amount; - return this; - - }; - - this.repeat = function (times) { - - _repeat = times; - return this; - - }; - - this.repeatDelay = function (amount) { - - _repeatDelayTime = amount; - return this; - - }; - - this.yoyo = function (yoyo) { - - _yoyo = yoyo; - return this; - - }; - - - this.easing = function (easing) { - - _easingFunction = easing; - return this; - - }; - - this.interpolation = function (interpolation) { - - _interpolationFunction = interpolation; - return this; - - }; - - this.chain = function () { - - _chainedTweens = arguments; - return this; - - }; - - this.onStart = function (callback) { - - _onStartCallback = callback; - return this; - - }; - - this.onUpdate = function (callback) { - - _onUpdateCallback = callback; - return this; - - }; - - this.onComplete = function (callback) { - - _onCompleteCallback = callback; - return this; - - }; - - this.onStop = function (callback) { - - _onStopCallback = callback; - return this; - - }; - - this.update = function (time) { - - var property; - var elapsed; - var value; - - if (time < _startTime) { - return true; - } - - if (_onStartCallbackFired === false) { - - if (_onStartCallback !== null) { - _onStartCallback.call(_object, _object); - } - - _onStartCallbackFired = true; - } - - elapsed = (time - _startTime) / _duration; - elapsed = elapsed > 1 ? 1 : elapsed; - - value = _easingFunction(elapsed); - - for (property in _valuesEnd) { - - // Don't update properties that do not exist in the source object - if (_valuesStart[property] === undefined) { - continue; - } - - var start = _valuesStart[property] || 0; - var end = _valuesEnd[property]; - - if (end instanceof Array) { - - _object[property] = _interpolationFunction(end, value); - - } else { - - // Parses relative end values with start as base (e.g.: +10, -3) - if (typeof (end) === 'string') { - - if (end.charAt(0) === '+' || end.charAt(0) === '-') { - end = start + parseFloat(end); - } else { - end = parseFloat(end); - } - } - - // Protect against non numeric properties. - if (typeof (end) === 'number') { - _object[property] = start + (end - start) * value; - } - - } - - } - - if (_onUpdateCallback !== null) { - _onUpdateCallback.call(_object, value); - } - - if (elapsed === 1) { - - if (_repeat > 0) { - - if (isFinite(_repeat)) { - _repeat--; - } - - // Reassign starting values, restart by making startTime = now - for (property in _valuesStartRepeat) { - - if (typeof (_valuesEnd[property]) === 'string') { - _valuesStartRepeat[property] = _valuesStartRepeat[property] + parseFloat(_valuesEnd[property]); - } - - if (_yoyo) { - var tmp = _valuesStartRepeat[property]; - - _valuesStartRepeat[property] = _valuesEnd[property]; - _valuesEnd[property] = tmp; - } - - _valuesStart[property] = _valuesStartRepeat[property]; - - } - - if (_yoyo) { - _reversed = !_reversed; - } - - if (_repeatDelayTime !== undefined) { - _startTime = time + _repeatDelayTime; - } else { - _startTime = time + _delayTime; - } - - return true; - - } else { - - if (_onCompleteCallback !== null) { - - _onCompleteCallback.call(_object, _object); - } - - for (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) { - // Make the chained tweens start exactly at the time they should, - // even if the `update()` method was called way past the duration of the tween - _chainedTweens[i].start(_startTime + _duration); - } - - return false; - - } - - } - - return true; - - }; - -}; - - -TWEEN.Easing = { - - Linear: { - - None: function (k) { - - return k; - - } - - }, - - Quadratic: { - - In: function (k) { - - return k * k; - - }, - - Out: function (k) { - - return k * (2 - k); - - }, - - InOut: function (k) { - - if ((k *= 2) < 1) { - return 0.5 * k * k; - } - - return - 0.5 * (--k * (k - 2) - 1); - - } - - }, - - Cubic: { - - In: function (k) { - - return k * k * k; - - }, - - Out: function (k) { - - return --k * k * k + 1; - - }, - - InOut: function (k) { - - if ((k *= 2) < 1) { - return 0.5 * k * k * k; - } - - return 0.5 * ((k -= 2) * k * k + 2); - - } - - }, - - Quartic: { - - In: function (k) { - - return k * k * k * k; - - }, - - Out: function (k) { - - return 1 - (--k * k * k * k); - - }, - - InOut: function (k) { - - if ((k *= 2) < 1) { - return 0.5 * k * k * k * k; - } - - return - 0.5 * ((k -= 2) * k * k * k - 2); - - } - - }, - - Quintic: { - - In: function (k) { - - return k * k * k * k * k; - - }, - - Out: function (k) { - - return --k * k * k * k * k + 1; - - }, - - InOut: function (k) { - - if ((k *= 2) < 1) { - return 0.5 * k * k * k * k * k; - } - - return 0.5 * ((k -= 2) * k * k * k * k + 2); - - } - - }, - - Sinusoidal: { - - In: function (k) { - - return 1 - Math.cos(k * Math.PI / 2); - - }, - - Out: function (k) { - - return Math.sin(k * Math.PI / 2); - - }, - - InOut: function (k) { - - return 0.5 * (1 - Math.cos(Math.PI * k)); - - } - - }, - - Exponential: { - - In: function (k) { - - return k === 0 ? 0 : Math.pow(1024, k - 1); - - }, - - Out: function (k) { - - return k === 1 ? 1 : 1 - Math.pow(2, - 10 * k); - - }, - - InOut: function (k) { - - if (k === 0) { - return 0; - } - - if (k === 1) { - return 1; - } - - if ((k *= 2) < 1) { - return 0.5 * Math.pow(1024, k - 1); - } - - return 0.5 * (- Math.pow(2, - 10 * (k - 1)) + 2); - - } - - }, - - Circular: { - - In: function (k) { - - return 1 - Math.sqrt(1 - k * k); - - }, - - Out: function (k) { - - return Math.sqrt(1 - (--k * k)); - - }, - - InOut: function (k) { - - if ((k *= 2) < 1) { - return - 0.5 * (Math.sqrt(1 - k * k) - 1); - } - - return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); - - } - - }, - - Elastic: { - - In: function (k) { - - if (k === 0) { - return 0; - } - - if (k === 1) { - return 1; - } - - return -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI); - - }, - - Out: function (k) { - - if (k === 0) { - return 0; - } - - if (k === 1) { - return 1; - } - - return Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1; - - }, - - InOut: function (k) { - - if (k === 0) { - return 0; - } - - if (k === 1) { - return 1; - } - - k *= 2; - - if (k < 1) { - return -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI); - } - - return 0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1; - - } - - }, - - Back: { - - In: function (k) { - - var s = 1.70158; - - return k * k * ((s + 1) * k - s); - - }, - - Out: function (k) { - - var s = 1.70158; - - return --k * k * ((s + 1) * k + s) + 1; - - }, - - InOut: function (k) { - - var s = 1.70158 * 1.525; - - if ((k *= 2) < 1) { - return 0.5 * (k * k * ((s + 1) * k - s)); - } - - return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); - - } - - }, - - Bounce: { - - In: function (k) { - - return 1 - TWEEN.Easing.Bounce.Out(1 - k); - - }, - - Out: function (k) { - - if (k < (1 / 2.75)) { - return 7.5625 * k * k; - } else if (k < (2 / 2.75)) { - return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; - } else if (k < (2.5 / 2.75)) { - return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; - } else { - return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; - } - - }, - - InOut: function (k) { - - if (k < 0.5) { - return TWEEN.Easing.Bounce.In(k * 2) * 0.5; - } - - return TWEEN.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5; - - } - - } - -}; - -TWEEN.Interpolation = { - - Linear: function (v, k) { - - var m = v.length - 1; - var f = m * k; - var i = Math.floor(f); - var fn = TWEEN.Interpolation.Utils.Linear; - - if (k < 0) { - return fn(v[0], v[1], f); - } - - if (k > 1) { - return fn(v[m], v[m - 1], m - f); - } - - return fn(v[i], v[i + 1 > m ? m : i + 1], f - i); - - }, - - Bezier: function (v, k) { - - var b = 0; - var n = v.length - 1; - var pw = Math.pow; - var bn = TWEEN.Interpolation.Utils.Bernstein; - - for (var i = 0; i <= n; i++) { - b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i); - } - - return b; - - }, - - CatmullRom: function (v, k) { - - var m = v.length - 1; - var f = m * k; - var i = Math.floor(f); - var fn = TWEEN.Interpolation.Utils.CatmullRom; - - if (v[0] === v[m]) { - - if (k < 0) { - i = Math.floor(f = m * (1 + k)); - } - - return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i); - - } else { - - if (k < 0) { - return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]); - } - - if (k > 1) { - return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]); - } - - return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i); - - } - - }, - - Utils: { - - Linear: function (p0, p1, t) { - - return (p1 - p0) * t + p0; - - }, - - Bernstein: function (n, i) { - - var fc = TWEEN.Interpolation.Utils.Factorial; - - return fc(n) / fc(i) / fc(n - i); - - }, - - Factorial: (function () { - - var a = [1]; - - return function (n) { - - var s = 1; - - if (a[n]) { - return a[n]; - } - - for (var i = n; i > 1; i--) { - s *= i; - } - - a[n] = s; - return s; - - }; - - })(), - - CatmullRom: function (p0, p1, p2, p3, t) { - - var v0 = (p2 - p0) * 0.5; - var v1 = (p3 - p1) * 0.5; - var t2 = t * t; - var t3 = t * t2; - - return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (- 3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; - - } - - } - -}; - -// UMD (Universal Module Definition) -(function (root) { - - if (typeof define === 'function' && define.amd) { - - // AMD - define([], function () { - return TWEEN; - }); - - } else if (typeof module !== 'undefined' && typeof exports === 'object') { - - // Node.js - module.exports = TWEEN; - - } else if (root !== undefined) { - - // Global variable - root.TWEEN = TWEEN; - - } - -})(this); diff --git a/engine/lib/base64-arraybuffer.js b/engine/lib/base64-arraybuffer.js deleted file mode 100644 index b1f9b7194..000000000 --- a/engine/lib/base64-arraybuffer.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * @license base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ -var Base64ArrayBuffer = (function () { - "use strict"; - - var base64ArrayBuffer = { }; - - var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - // Use a lookup table to find the index. - var lookup = new Uint8Array(256); - for (var i = 0; i < chars.length; i++) { - lookup[chars.charCodeAt(i)] = i; - } - - base64ArrayBuffer.encode = function(arraybuffer) { - var bytes = new Uint8Array(arraybuffer), - i, len = bytes.length, base64 = ""; - - for (i = 0; i < len; i+=3) { - base64 += chars[bytes[i] >> 2]; - base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64 += chars[bytes[i + 2] & 63]; - } - - if ((len % 3) === 2) { - base64 = base64.substring(0, base64.length - 1) + "="; - } else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + "=="; - } - - return base64; - }; - - base64ArrayBuffer.decode = function(base64) { - var bufferLength = base64.length * 0.75, - len = base64.length, i, p = 0, - encoded1, encoded2, encoded3, encoded4; - - if (base64[base64.length - 1] === "=") { - bufferLength--; - if (base64[base64.length - 2] === "=") { - bufferLength--; - } - } - - var arraybuffer = new ArrayBuffer(bufferLength), - bytes = new Uint8Array(arraybuffer); - - for (i = 0; i < len; i+=4) { - encoded1 = lookup[base64.charCodeAt(i)]; - encoded2 = lookup[base64.charCodeAt(i+1)]; - encoded3 = lookup[base64.charCodeAt(i+2)]; - encoded4 = lookup[base64.charCodeAt(i+3)]; - - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - - return arraybuffer; - }; - - return base64ArrayBuffer; - -})(); diff --git a/engine/lib/convert-range.js b/engine/lib/convert-range.js index 6a030ba49..b67ef67f5 100644 --- a/engine/lib/convert-range.js +++ b/engine/lib/convert-range.js @@ -1,4 +1,6 @@ // @license https://stackoverflow.com/questions/14224535/scaling-between-two-number-ranges function convertRange( value, r1, r2 ) { return ( value - r1[ 0 ] ) * ( r2[ 1 ] - r2[ 0 ] ) / ( r1[ 1 ] - r1[ 0 ] ) + r2[ 0 ]; -} \ No newline at end of file +} + +module.exports = convertRange; \ No newline at end of file diff --git a/engine/lib/croquis.js b/engine/lib/croquis.js index 5a1fc86be..7fbfb38cb 100644 --- a/engine/lib/croquis.js +++ b/engine/lib/croquis.js @@ -1548,3 +1548,5 @@ Croquis.Brush = function () { return dirtyRect; }; }; + +module.exports = Croquis; \ No newline at end of file diff --git a/engine/lib/esprima.js b/engine/lib/esprima.js deleted file mode 100644 index 41f02e219..000000000 --- a/engine/lib/esprima.js +++ /dev/null @@ -1,6734 +0,0 @@ -/** - * @license esprima.js - * Copyright JS Foundation and other contributors, https://js.foundation/ - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -(function webpackUniversalModuleDefinition(root, factory) { -/* istanbul ignore next */ - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); -/* istanbul ignore next */ - else if(typeof exports === 'object') - exports["esprima"] = factory(); - else - root["esprima"] = factory(); -})(this, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/* istanbul ignore if */ -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - /* - Copyright JS Foundation and other contributors, https://js.foundation/ - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - Object.defineProperty(exports, "__esModule", { value: true }); - var comment_handler_1 = __webpack_require__(1); - var jsx_parser_1 = __webpack_require__(3); - var parser_1 = __webpack_require__(8); - var tokenizer_1 = __webpack_require__(15); - function parse(code, options, delegate) { - var commentHandler = null; - var proxyDelegate = function (node, metadata) { - if (delegate) { - delegate(node, metadata); - } - if (commentHandler) { - commentHandler.visit(node, metadata); - } - }; - var parserDelegate = (typeof delegate === 'function') ? proxyDelegate : null; - var collectComment = false; - if (options) { - collectComment = (typeof options.comment === 'boolean' && options.comment); - var attachComment = (typeof options.attachComment === 'boolean' && options.attachComment); - if (collectComment || attachComment) { - commentHandler = new comment_handler_1.CommentHandler(); - commentHandler.attach = attachComment; - options.comment = true; - parserDelegate = proxyDelegate; - } - } - var isModule = false; - if (options && typeof options.sourceType === 'string') { - isModule = (options.sourceType === 'module'); - } - var parser; - if (options && typeof options.jsx === 'boolean' && options.jsx) { - parser = new jsx_parser_1.JSXParser(code, options, parserDelegate); - } - else { - parser = new parser_1.Parser(code, options, parserDelegate); - } - var program = isModule ? parser.parseModule() : parser.parseScript(); - var ast = program; - if (collectComment && commentHandler) { - ast.comments = commentHandler.comments; - } - if (parser.config.tokens) { - ast.tokens = parser.tokens; - } - if (parser.config.tolerant) { - ast.errors = parser.errorHandler.errors; - } - return ast; - } - exports.parse = parse; - function parseModule(code, options, delegate) { - var parsingOptions = options || {}; - parsingOptions.sourceType = 'module'; - return parse(code, parsingOptions, delegate); - } - exports.parseModule = parseModule; - function parseScript(code, options, delegate) { - var parsingOptions = options || {}; - parsingOptions.sourceType = 'script'; - return parse(code, parsingOptions, delegate); - } - exports.parseScript = parseScript; - function tokenize(code, options, delegate) { - var tokenizer = new tokenizer_1.Tokenizer(code, options); - var tokens; - tokens = []; - try { - while (true) { - var token = tokenizer.getNextToken(); - if (!token) { - break; - } - if (delegate) { - token = delegate(token); - } - tokens.push(token); - } - } - catch (e) { - tokenizer.errorHandler.tolerate(e); - } - if (tokenizer.errorHandler.tolerant) { - tokens.errors = tokenizer.errors(); - } - return tokens; - } - exports.tokenize = tokenize; - var syntax_1 = __webpack_require__(2); - exports.Syntax = syntax_1.Syntax; - // Sync with *.json manifests. - exports.version = '4.0.1'; - - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var syntax_1 = __webpack_require__(2); - var CommentHandler = (function () { - function CommentHandler() { - this.attach = false; - this.comments = []; - this.stack = []; - this.leading = []; - this.trailing = []; - } - CommentHandler.prototype.insertInnerComments = function (node, metadata) { - // innnerComments for properties empty block - // `function a() {/** comments **\/}` - if (node.type === syntax_1.Syntax.BlockStatement && node.body.length === 0) { - var innerComments = []; - for (var i = this.leading.length - 1; i >= 0; --i) { - var entry = this.leading[i]; - if (metadata.end.offset >= entry.start) { - innerComments.unshift(entry.comment); - this.leading.splice(i, 1); - this.trailing.splice(i, 1); - } - } - if (innerComments.length) { - node.innerComments = innerComments; - } - } - }; - CommentHandler.prototype.findTrailingComments = function (metadata) { - var trailingComments = []; - if (this.trailing.length > 0) { - for (var i = this.trailing.length - 1; i >= 0; --i) { - var entry_1 = this.trailing[i]; - if (entry_1.start >= metadata.end.offset) { - trailingComments.unshift(entry_1.comment); - } - } - this.trailing.length = 0; - return trailingComments; - } - var entry = this.stack[this.stack.length - 1]; - if (entry && entry.node.trailingComments) { - var firstComment = entry.node.trailingComments[0]; - if (firstComment && firstComment.range[0] >= metadata.end.offset) { - trailingComments = entry.node.trailingComments; - delete entry.node.trailingComments; - } - } - return trailingComments; - }; - CommentHandler.prototype.findLeadingComments = function (metadata) { - var leadingComments = []; - var target; - while (this.stack.length > 0) { - var entry = this.stack[this.stack.length - 1]; - if (entry && entry.start >= metadata.start.offset) { - target = entry.node; - this.stack.pop(); - } - else { - break; - } - } - if (target) { - var count = target.leadingComments ? target.leadingComments.length : 0; - for (var i = count - 1; i >= 0; --i) { - var comment = target.leadingComments[i]; - if (comment.range[1] <= metadata.start.offset) { - leadingComments.unshift(comment); - target.leadingComments.splice(i, 1); - } - } - if (target.leadingComments && target.leadingComments.length === 0) { - delete target.leadingComments; - } - return leadingComments; - } - for (var i = this.leading.length - 1; i >= 0; --i) { - var entry = this.leading[i]; - if (entry.start <= metadata.start.offset) { - leadingComments.unshift(entry.comment); - this.leading.splice(i, 1); - } - } - return leadingComments; - }; - CommentHandler.prototype.visitNode = function (node, metadata) { - if (node.type === syntax_1.Syntax.Program && node.body.length > 0) { - return; - } - this.insertInnerComments(node, metadata); - var trailingComments = this.findTrailingComments(metadata); - var leadingComments = this.findLeadingComments(metadata); - if (leadingComments.length > 0) { - node.leadingComments = leadingComments; - } - if (trailingComments.length > 0) { - node.trailingComments = trailingComments; - } - this.stack.push({ - node: node, - start: metadata.start.offset - }); - }; - CommentHandler.prototype.visitComment = function (node, metadata) { - var type = (node.type[0] === 'L') ? 'Line' : 'Block'; - var comment = { - type: type, - value: node.value - }; - if (node.range) { - comment.range = node.range; - } - if (node.loc) { - comment.loc = node.loc; - } - this.comments.push(comment); - if (this.attach) { - var entry = { - comment: { - type: type, - value: node.value, - range: [metadata.start.offset, metadata.end.offset] - }, - start: metadata.start.offset - }; - if (node.loc) { - entry.comment.loc = node.loc; - } - node.type = type; - this.leading.push(entry); - this.trailing.push(entry); - } - }; - CommentHandler.prototype.visit = function (node, metadata) { - if (node.type === 'LineComment') { - this.visitComment(node, metadata); - } - else if (node.type === 'BlockComment') { - this.visitComment(node, metadata); - } - else if (this.attach) { - this.visitNode(node, metadata); - } - }; - return CommentHandler; - }()); - exports.CommentHandler = CommentHandler; - - -/***/ }, -/* 2 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Syntax = { - AssignmentExpression: 'AssignmentExpression', - AssignmentPattern: 'AssignmentPattern', - ArrayExpression: 'ArrayExpression', - ArrayPattern: 'ArrayPattern', - ArrowFunctionExpression: 'ArrowFunctionExpression', - AwaitExpression: 'AwaitExpression', - BlockStatement: 'BlockStatement', - BinaryExpression: 'BinaryExpression', - BreakStatement: 'BreakStatement', - CallExpression: 'CallExpression', - CatchClause: 'CatchClause', - ClassBody: 'ClassBody', - ClassDeclaration: 'ClassDeclaration', - ClassExpression: 'ClassExpression', - ConditionalExpression: 'ConditionalExpression', - ContinueStatement: 'ContinueStatement', - DoWhileStatement: 'DoWhileStatement', - DebuggerStatement: 'DebuggerStatement', - EmptyStatement: 'EmptyStatement', - ExportAllDeclaration: 'ExportAllDeclaration', - ExportDefaultDeclaration: 'ExportDefaultDeclaration', - ExportNamedDeclaration: 'ExportNamedDeclaration', - ExportSpecifier: 'ExportSpecifier', - ExpressionStatement: 'ExpressionStatement', - ForStatement: 'ForStatement', - ForOfStatement: 'ForOfStatement', - ForInStatement: 'ForInStatement', - FunctionDeclaration: 'FunctionDeclaration', - FunctionExpression: 'FunctionExpression', - Identifier: 'Identifier', - IfStatement: 'IfStatement', - ImportDeclaration: 'ImportDeclaration', - ImportDefaultSpecifier: 'ImportDefaultSpecifier', - ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', - ImportSpecifier: 'ImportSpecifier', - Literal: 'Literal', - LabeledStatement: 'LabeledStatement', - LogicalExpression: 'LogicalExpression', - MemberExpression: 'MemberExpression', - MetaProperty: 'MetaProperty', - MethodDefinition: 'MethodDefinition', - NewExpression: 'NewExpression', - ObjectExpression: 'ObjectExpression', - ObjectPattern: 'ObjectPattern', - Program: 'Program', - Property: 'Property', - RestElement: 'RestElement', - ReturnStatement: 'ReturnStatement', - SequenceExpression: 'SequenceExpression', - SpreadElement: 'SpreadElement', - Super: 'Super', - SwitchCase: 'SwitchCase', - SwitchStatement: 'SwitchStatement', - TaggedTemplateExpression: 'TaggedTemplateExpression', - TemplateElement: 'TemplateElement', - TemplateLiteral: 'TemplateLiteral', - ThisExpression: 'ThisExpression', - ThrowStatement: 'ThrowStatement', - TryStatement: 'TryStatement', - UnaryExpression: 'UnaryExpression', - UpdateExpression: 'UpdateExpression', - VariableDeclaration: 'VariableDeclaration', - VariableDeclarator: 'VariableDeclarator', - WhileStatement: 'WhileStatement', - WithStatement: 'WithStatement', - YieldExpression: 'YieldExpression' - }; - - -/***/ }, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; -/* istanbul ignore next */ - var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; - })(); - Object.defineProperty(exports, "__esModule", { value: true }); - var character_1 = __webpack_require__(4); - var JSXNode = __webpack_require__(5); - var jsx_syntax_1 = __webpack_require__(6); - var Node = __webpack_require__(7); - var parser_1 = __webpack_require__(8); - var token_1 = __webpack_require__(13); - var xhtml_entities_1 = __webpack_require__(14); - token_1.TokenName[100 /* Identifier */] = 'JSXIdentifier'; - token_1.TokenName[101 /* Text */] = 'JSXText'; - // Fully qualified element name, e.g. returns "svg:path" - function getQualifiedElementName(elementName) { - var qualifiedName; - switch (elementName.type) { - case jsx_syntax_1.JSXSyntax.JSXIdentifier: - var id = elementName; - qualifiedName = id.name; - break; - case jsx_syntax_1.JSXSyntax.JSXNamespacedName: - var ns = elementName; - qualifiedName = getQualifiedElementName(ns.namespace) + ':' + - getQualifiedElementName(ns.name); - break; - case jsx_syntax_1.JSXSyntax.JSXMemberExpression: - var expr = elementName; - qualifiedName = getQualifiedElementName(expr.object) + '.' + - getQualifiedElementName(expr.property); - break; - /* istanbul ignore next */ - default: - break; - } - return qualifiedName; - } - var JSXParser = (function (_super) { - __extends(JSXParser, _super); - function JSXParser(code, options, delegate) { - return _super.call(this, code, options, delegate) || this; - } - JSXParser.prototype.parsePrimaryExpression = function () { - return this.match('<') ? this.parseJSXRoot() : _super.prototype.parsePrimaryExpression.call(this); - }; - JSXParser.prototype.startJSX = function () { - // Unwind the scanner before the lookahead token. - this.scanner.index = this.startMarker.index; - this.scanner.lineNumber = this.startMarker.line; - this.scanner.lineStart = this.startMarker.index - this.startMarker.column; - }; - JSXParser.prototype.finishJSX = function () { - // Prime the next lookahead. - this.nextToken(); - }; - JSXParser.prototype.reenterJSX = function () { - this.startJSX(); - this.expectJSX('}'); - // Pop the closing '}' added from the lookahead. - if (this.config.tokens) { - this.tokens.pop(); - } - }; - JSXParser.prototype.createJSXNode = function () { - this.collectComments(); - return { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - }; - JSXParser.prototype.createJSXChildNode = function () { - return { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - }; - JSXParser.prototype.scanXHTMLEntity = function (quote) { - var result = '&'; - var valid = true; - var terminated = false; - var numeric = false; - var hex = false; - while (!this.scanner.eof() && valid && !terminated) { - var ch = this.scanner.source[this.scanner.index]; - if (ch === quote) { - break; - } - terminated = (ch === ';'); - result += ch; - ++this.scanner.index; - if (!terminated) { - switch (result.length) { - case 2: - // e.g. '{' - numeric = (ch === '#'); - break; - case 3: - if (numeric) { - // e.g. 'A' - hex = (ch === 'x'); - valid = hex || character_1.Character.isDecimalDigit(ch.charCodeAt(0)); - numeric = numeric && !hex; - } - break; - default: - valid = valid && !(numeric && !character_1.Character.isDecimalDigit(ch.charCodeAt(0))); - valid = valid && !(hex && !character_1.Character.isHexDigit(ch.charCodeAt(0))); - break; - } - } - } - if (valid && terminated && result.length > 2) { - // e.g. 'A' becomes just '#x41' - var str = result.substr(1, result.length - 2); - if (numeric && str.length > 1) { - result = String.fromCharCode(parseInt(str.substr(1), 10)); - } - else if (hex && str.length > 2) { - result = String.fromCharCode(parseInt('0' + str.substr(1), 16)); - } - else if (!numeric && !hex && xhtml_entities_1.XHTMLEntities[str]) { - result = xhtml_entities_1.XHTMLEntities[str]; - } - } - return result; - }; - // Scan the next JSX token. This replaces Scanner#lex when in JSX mode. - JSXParser.prototype.lexJSX = function () { - var cp = this.scanner.source.charCodeAt(this.scanner.index); - // < > / : = { } - if (cp === 60 || cp === 62 || cp === 47 || cp === 58 || cp === 61 || cp === 123 || cp === 125) { - var value = this.scanner.source[this.scanner.index++]; - return { - type: 7 /* Punctuator */, - value: value, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: this.scanner.index - 1, - end: this.scanner.index - }; - } - // " ' - if (cp === 34 || cp === 39) { - var start = this.scanner.index; - var quote = this.scanner.source[this.scanner.index++]; - var str = ''; - while (!this.scanner.eof()) { - var ch = this.scanner.source[this.scanner.index++]; - if (ch === quote) { - break; - } - else if (ch === '&') { - str += this.scanXHTMLEntity(quote); - } - else { - str += ch; - } - } - return { - type: 8 /* StringLiteral */, - value: str, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - // ... or . - if (cp === 46) { - var n1 = this.scanner.source.charCodeAt(this.scanner.index + 1); - var n2 = this.scanner.source.charCodeAt(this.scanner.index + 2); - var value = (n1 === 46 && n2 === 46) ? '...' : '.'; - var start = this.scanner.index; - this.scanner.index += value.length; - return { - type: 7 /* Punctuator */, - value: value, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - // ` - if (cp === 96) { - // Only placeholder, since it will be rescanned as a real assignment expression. - return { - type: 10 /* Template */, - value: '', - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: this.scanner.index, - end: this.scanner.index - }; - } - // Identifer can not contain backslash (char code 92). - if (character_1.Character.isIdentifierStart(cp) && (cp !== 92)) { - var start = this.scanner.index; - ++this.scanner.index; - while (!this.scanner.eof()) { - var ch = this.scanner.source.charCodeAt(this.scanner.index); - if (character_1.Character.isIdentifierPart(ch) && (ch !== 92)) { - ++this.scanner.index; - } - else if (ch === 45) { - // Hyphen (char code 45) can be part of an identifier. - ++this.scanner.index; - } - else { - break; - } - } - var id = this.scanner.source.slice(start, this.scanner.index); - return { - type: 100 /* Identifier */, - value: id, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - return this.scanner.lex(); - }; - JSXParser.prototype.nextJSXToken = function () { - this.collectComments(); - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - var token = this.lexJSX(); - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - if (this.config.tokens) { - this.tokens.push(this.convertToken(token)); - } - return token; - }; - JSXParser.prototype.nextJSXText = function () { - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - var start = this.scanner.index; - var text = ''; - while (!this.scanner.eof()) { - var ch = this.scanner.source[this.scanner.index]; - if (ch === '{' || ch === '<') { - break; - } - ++this.scanner.index; - text += ch; - if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { - ++this.scanner.lineNumber; - if (ch === '\r' && this.scanner.source[this.scanner.index] === '\n') { - ++this.scanner.index; - } - this.scanner.lineStart = this.scanner.index; - } - } - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - var token = { - type: 101 /* Text */, - value: text, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - if ((text.length > 0) && this.config.tokens) { - this.tokens.push(this.convertToken(token)); - } - return token; - }; - JSXParser.prototype.peekJSXToken = function () { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.lexJSX(); - this.scanner.restoreState(state); - return next; - }; - // Expect the next JSX token to match the specified punctuator. - // If not, an exception will be thrown. - JSXParser.prototype.expectJSX = function (value) { - var token = this.nextJSXToken(); - if (token.type !== 7 /* Punctuator */ || token.value !== value) { - this.throwUnexpectedToken(token); - } - }; - // Return true if the next JSX token matches the specified punctuator. - JSXParser.prototype.matchJSX = function (value) { - var next = this.peekJSXToken(); - return next.type === 7 /* Punctuator */ && next.value === value; - }; - JSXParser.prototype.parseJSXIdentifier = function () { - var node = this.createJSXNode(); - var token = this.nextJSXToken(); - if (token.type !== 100 /* Identifier */) { - this.throwUnexpectedToken(token); - } - return this.finalize(node, new JSXNode.JSXIdentifier(token.value)); - }; - JSXParser.prototype.parseJSXElementName = function () { - var node = this.createJSXNode(); - var elementName = this.parseJSXIdentifier(); - if (this.matchJSX(':')) { - var namespace = elementName; - this.expectJSX(':'); - var name_1 = this.parseJSXIdentifier(); - elementName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_1)); - } - else if (this.matchJSX('.')) { - while (this.matchJSX('.')) { - var object = elementName; - this.expectJSX('.'); - var property = this.parseJSXIdentifier(); - elementName = this.finalize(node, new JSXNode.JSXMemberExpression(object, property)); - } - } - return elementName; - }; - JSXParser.prototype.parseJSXAttributeName = function () { - var node = this.createJSXNode(); - var attributeName; - var identifier = this.parseJSXIdentifier(); - if (this.matchJSX(':')) { - var namespace = identifier; - this.expectJSX(':'); - var name_2 = this.parseJSXIdentifier(); - attributeName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_2)); - } - else { - attributeName = identifier; - } - return attributeName; - }; - JSXParser.prototype.parseJSXStringLiteralAttribute = function () { - var node = this.createJSXNode(); - var token = this.nextJSXToken(); - if (token.type !== 8 /* StringLiteral */) { - this.throwUnexpectedToken(token); - } - var raw = this.getTokenRaw(token); - return this.finalize(node, new Node.Literal(token.value, raw)); - }; - JSXParser.prototype.parseJSXExpressionAttribute = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - this.finishJSX(); - if (this.match('}')) { - this.tolerateError('JSX attributes must only be assigned a non-empty expression'); - } - var expression = this.parseAssignmentExpression(); - this.reenterJSX(); - return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); - }; - JSXParser.prototype.parseJSXAttributeValue = function () { - return this.matchJSX('{') ? this.parseJSXExpressionAttribute() : - this.matchJSX('<') ? this.parseJSXElement() : this.parseJSXStringLiteralAttribute(); - }; - JSXParser.prototype.parseJSXNameValueAttribute = function () { - var node = this.createJSXNode(); - var name = this.parseJSXAttributeName(); - var value = null; - if (this.matchJSX('=')) { - this.expectJSX('='); - value = this.parseJSXAttributeValue(); - } - return this.finalize(node, new JSXNode.JSXAttribute(name, value)); - }; - JSXParser.prototype.parseJSXSpreadAttribute = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - this.expectJSX('...'); - this.finishJSX(); - var argument = this.parseAssignmentExpression(); - this.reenterJSX(); - return this.finalize(node, new JSXNode.JSXSpreadAttribute(argument)); - }; - JSXParser.prototype.parseJSXAttributes = function () { - var attributes = []; - while (!this.matchJSX('/') && !this.matchJSX('>')) { - var attribute = this.matchJSX('{') ? this.parseJSXSpreadAttribute() : - this.parseJSXNameValueAttribute(); - attributes.push(attribute); - } - return attributes; - }; - JSXParser.prototype.parseJSXOpeningElement = function () { - var node = this.createJSXNode(); - this.expectJSX('<'); - var name = this.parseJSXElementName(); - var attributes = this.parseJSXAttributes(); - var selfClosing = this.matchJSX('/'); - if (selfClosing) { - this.expectJSX('/'); - } - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); - }; - JSXParser.prototype.parseJSXBoundaryElement = function () { - var node = this.createJSXNode(); - this.expectJSX('<'); - if (this.matchJSX('/')) { - this.expectJSX('/'); - var name_3 = this.parseJSXElementName(); - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXClosingElement(name_3)); - } - var name = this.parseJSXElementName(); - var attributes = this.parseJSXAttributes(); - var selfClosing = this.matchJSX('/'); - if (selfClosing) { - this.expectJSX('/'); - } - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); - }; - JSXParser.prototype.parseJSXEmptyExpression = function () { - var node = this.createJSXChildNode(); - this.collectComments(); - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - return this.finalize(node, new JSXNode.JSXEmptyExpression()); - }; - JSXParser.prototype.parseJSXExpressionContainer = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - var expression; - if (this.matchJSX('}')) { - expression = this.parseJSXEmptyExpression(); - this.expectJSX('}'); - } - else { - this.finishJSX(); - expression = this.parseAssignmentExpression(); - this.reenterJSX(); - } - return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); - }; - JSXParser.prototype.parseJSXChildren = function () { - var children = []; - while (!this.scanner.eof()) { - var node = this.createJSXChildNode(); - var token = this.nextJSXText(); - if (token.start < token.end) { - var raw = this.getTokenRaw(token); - var child = this.finalize(node, new JSXNode.JSXText(token.value, raw)); - children.push(child); - } - if (this.scanner.source[this.scanner.index] === '{') { - var container = this.parseJSXExpressionContainer(); - children.push(container); - } - else { - break; - } - } - return children; - }; - JSXParser.prototype.parseComplexJSXElement = function (el) { - var stack = []; - while (!this.scanner.eof()) { - el.children = el.children.concat(this.parseJSXChildren()); - var node = this.createJSXChildNode(); - var element = this.parseJSXBoundaryElement(); - if (element.type === jsx_syntax_1.JSXSyntax.JSXOpeningElement) { - var opening = element; - if (opening.selfClosing) { - var child = this.finalize(node, new JSXNode.JSXElement(opening, [], null)); - el.children.push(child); - } - else { - stack.push(el); - el = { node: node, opening: opening, closing: null, children: [] }; - } - } - if (element.type === jsx_syntax_1.JSXSyntax.JSXClosingElement) { - el.closing = element; - var open_1 = getQualifiedElementName(el.opening.name); - var close_1 = getQualifiedElementName(el.closing.name); - if (open_1 !== close_1) { - this.tolerateError('Expected corresponding JSX closing tag for %0', open_1); - } - if (stack.length > 0) { - var child = this.finalize(el.node, new JSXNode.JSXElement(el.opening, el.children, el.closing)); - el = stack[stack.length - 1]; - el.children.push(child); - stack.pop(); - } - else { - break; - } - } - } - return el; - }; - JSXParser.prototype.parseJSXElement = function () { - var node = this.createJSXNode(); - var opening = this.parseJSXOpeningElement(); - var children = []; - var closing = null; - if (!opening.selfClosing) { - var el = this.parseComplexJSXElement({ node: node, opening: opening, closing: closing, children: children }); - children = el.children; - closing = el.closing; - } - return this.finalize(node, new JSXNode.JSXElement(opening, children, closing)); - }; - JSXParser.prototype.parseJSXRoot = function () { - // Pop the opening '<' added from the lookahead. - if (this.config.tokens) { - this.tokens.pop(); - } - this.startJSX(); - var element = this.parseJSXElement(); - this.finishJSX(); - return element; - }; - JSXParser.prototype.isStartOfExpression = function () { - return _super.prototype.isStartOfExpression.call(this) || this.match('<'); - }; - return JSXParser; - }(parser_1.Parser)); - exports.JSXParser = JSXParser; - - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - // See also tools/generate-unicode-regex.js. - var Regex = { - // Unicode v8.0.0 NonAsciiIdentifierStart: - NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\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-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\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\u0AF9\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-\u0C39\u0C3D\u0C58-\u0C5A\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\u0D5F-\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-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\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\u2118-\u211D\u2124\u2126\u2128\u212A-\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\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\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]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/, - // Unicode v8.0.0 NonAsciiIdentifierPart: - NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\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\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\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\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ - }; - exports.Character = { - /* tslint:disable:no-bitwise */ - fromCodePoint: function (cp) { - return (cp < 0x10000) ? String.fromCharCode(cp) : - String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) + - String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023)); - }, - // https://tc39.github.io/ecma262/#sec-white-space - isWhiteSpace: function (cp) { - return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) || - (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0); - }, - // https://tc39.github.io/ecma262/#sec-line-terminators - isLineTerminator: function (cp) { - return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029); - }, - // https://tc39.github.io/ecma262/#sec-names-and-keywords - isIdentifierStart: function (cp) { - return (cp === 0x24) || (cp === 0x5F) || - (cp >= 0x41 && cp <= 0x5A) || - (cp >= 0x61 && cp <= 0x7A) || - (cp === 0x5C) || - ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(exports.Character.fromCodePoint(cp))); - }, - isIdentifierPart: function (cp) { - return (cp === 0x24) || (cp === 0x5F) || - (cp >= 0x41 && cp <= 0x5A) || - (cp >= 0x61 && cp <= 0x7A) || - (cp >= 0x30 && cp <= 0x39) || - (cp === 0x5C) || - ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(exports.Character.fromCodePoint(cp))); - }, - // https://tc39.github.io/ecma262/#sec-literals-numeric-literals - isDecimalDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x39); // 0..9 - }, - isHexDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x39) || - (cp >= 0x41 && cp <= 0x46) || - (cp >= 0x61 && cp <= 0x66); // a..f - }, - isOctalDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x37); // 0..7 - } - }; - - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var jsx_syntax_1 = __webpack_require__(6); - /* tslint:disable:max-classes-per-file */ - var JSXClosingElement = (function () { - function JSXClosingElement(name) { - this.type = jsx_syntax_1.JSXSyntax.JSXClosingElement; - this.name = name; - } - return JSXClosingElement; - }()); - exports.JSXClosingElement = JSXClosingElement; - var JSXElement = (function () { - function JSXElement(openingElement, children, closingElement) { - this.type = jsx_syntax_1.JSXSyntax.JSXElement; - this.openingElement = openingElement; - this.children = children; - this.closingElement = closingElement; - } - return JSXElement; - }()); - exports.JSXElement = JSXElement; - var JSXEmptyExpression = (function () { - function JSXEmptyExpression() { - this.type = jsx_syntax_1.JSXSyntax.JSXEmptyExpression; - } - return JSXEmptyExpression; - }()); - exports.JSXEmptyExpression = JSXEmptyExpression; - var JSXExpressionContainer = (function () { - function JSXExpressionContainer(expression) { - this.type = jsx_syntax_1.JSXSyntax.JSXExpressionContainer; - this.expression = expression; - } - return JSXExpressionContainer; - }()); - exports.JSXExpressionContainer = JSXExpressionContainer; - var JSXIdentifier = (function () { - function JSXIdentifier(name) { - this.type = jsx_syntax_1.JSXSyntax.JSXIdentifier; - this.name = name; - } - return JSXIdentifier; - }()); - exports.JSXIdentifier = JSXIdentifier; - var JSXMemberExpression = (function () { - function JSXMemberExpression(object, property) { - this.type = jsx_syntax_1.JSXSyntax.JSXMemberExpression; - this.object = object; - this.property = property; - } - return JSXMemberExpression; - }()); - exports.JSXMemberExpression = JSXMemberExpression; - var JSXAttribute = (function () { - function JSXAttribute(name, value) { - this.type = jsx_syntax_1.JSXSyntax.JSXAttribute; - this.name = name; - this.value = value; - } - return JSXAttribute; - }()); - exports.JSXAttribute = JSXAttribute; - var JSXNamespacedName = (function () { - function JSXNamespacedName(namespace, name) { - this.type = jsx_syntax_1.JSXSyntax.JSXNamespacedName; - this.namespace = namespace; - this.name = name; - } - return JSXNamespacedName; - }()); - exports.JSXNamespacedName = JSXNamespacedName; - var JSXOpeningElement = (function () { - function JSXOpeningElement(name, selfClosing, attributes) { - this.type = jsx_syntax_1.JSXSyntax.JSXOpeningElement; - this.name = name; - this.selfClosing = selfClosing; - this.attributes = attributes; - } - return JSXOpeningElement; - }()); - exports.JSXOpeningElement = JSXOpeningElement; - var JSXSpreadAttribute = (function () { - function JSXSpreadAttribute(argument) { - this.type = jsx_syntax_1.JSXSyntax.JSXSpreadAttribute; - this.argument = argument; - } - return JSXSpreadAttribute; - }()); - exports.JSXSpreadAttribute = JSXSpreadAttribute; - var JSXText = (function () { - function JSXText(value, raw) { - this.type = jsx_syntax_1.JSXSyntax.JSXText; - this.value = value; - this.raw = raw; - } - return JSXText; - }()); - exports.JSXText = JSXText; - - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.JSXSyntax = { - JSXAttribute: 'JSXAttribute', - JSXClosingElement: 'JSXClosingElement', - JSXElement: 'JSXElement', - JSXEmptyExpression: 'JSXEmptyExpression', - JSXExpressionContainer: 'JSXExpressionContainer', - JSXIdentifier: 'JSXIdentifier', - JSXMemberExpression: 'JSXMemberExpression', - JSXNamespacedName: 'JSXNamespacedName', - JSXOpeningElement: 'JSXOpeningElement', - JSXSpreadAttribute: 'JSXSpreadAttribute', - JSXText: 'JSXText' - }; - - -/***/ }, -/* 7 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var syntax_1 = __webpack_require__(2); - /* tslint:disable:max-classes-per-file */ - var ArrayExpression = (function () { - function ArrayExpression(elements) { - this.type = syntax_1.Syntax.ArrayExpression; - this.elements = elements; - } - return ArrayExpression; - }()); - exports.ArrayExpression = ArrayExpression; - var ArrayPattern = (function () { - function ArrayPattern(elements) { - this.type = syntax_1.Syntax.ArrayPattern; - this.elements = elements; - } - return ArrayPattern; - }()); - exports.ArrayPattern = ArrayPattern; - var ArrowFunctionExpression = (function () { - function ArrowFunctionExpression(params, body, expression) { - this.type = syntax_1.Syntax.ArrowFunctionExpression; - this.id = null; - this.params = params; - this.body = body; - this.generator = false; - this.expression = expression; - this.async = false; - } - return ArrowFunctionExpression; - }()); - exports.ArrowFunctionExpression = ArrowFunctionExpression; - var AssignmentExpression = (function () { - function AssignmentExpression(operator, left, right) { - this.type = syntax_1.Syntax.AssignmentExpression; - this.operator = operator; - this.left = left; - this.right = right; - } - return AssignmentExpression; - }()); - exports.AssignmentExpression = AssignmentExpression; - var AssignmentPattern = (function () { - function AssignmentPattern(left, right) { - this.type = syntax_1.Syntax.AssignmentPattern; - this.left = left; - this.right = right; - } - return AssignmentPattern; - }()); - exports.AssignmentPattern = AssignmentPattern; - var AsyncArrowFunctionExpression = (function () { - function AsyncArrowFunctionExpression(params, body, expression) { - this.type = syntax_1.Syntax.ArrowFunctionExpression; - this.id = null; - this.params = params; - this.body = body; - this.generator = false; - this.expression = expression; - this.async = true; - } - return AsyncArrowFunctionExpression; - }()); - exports.AsyncArrowFunctionExpression = AsyncArrowFunctionExpression; - var AsyncFunctionDeclaration = (function () { - function AsyncFunctionDeclaration(id, params, body) { - this.type = syntax_1.Syntax.FunctionDeclaration; - this.id = id; - this.params = params; - this.body = body; - this.generator = false; - this.expression = false; - this.async = true; - } - return AsyncFunctionDeclaration; - }()); - exports.AsyncFunctionDeclaration = AsyncFunctionDeclaration; - var AsyncFunctionExpression = (function () { - function AsyncFunctionExpression(id, params, body) { - this.type = syntax_1.Syntax.FunctionExpression; - this.id = id; - this.params = params; - this.body = body; - this.generator = false; - this.expression = false; - this.async = true; - } - return AsyncFunctionExpression; - }()); - exports.AsyncFunctionExpression = AsyncFunctionExpression; - var AwaitExpression = (function () { - function AwaitExpression(argument) { - this.type = syntax_1.Syntax.AwaitExpression; - this.argument = argument; - } - return AwaitExpression; - }()); - exports.AwaitExpression = AwaitExpression; - var BinaryExpression = (function () { - function BinaryExpression(operator, left, right) { - var logical = (operator === '||' || operator === '&&'); - this.type = logical ? syntax_1.Syntax.LogicalExpression : syntax_1.Syntax.BinaryExpression; - this.operator = operator; - this.left = left; - this.right = right; - } - return BinaryExpression; - }()); - exports.BinaryExpression = BinaryExpression; - var BlockStatement = (function () { - function BlockStatement(body) { - this.type = syntax_1.Syntax.BlockStatement; - this.body = body; - } - return BlockStatement; - }()); - exports.BlockStatement = BlockStatement; - var BreakStatement = (function () { - function BreakStatement(label) { - this.type = syntax_1.Syntax.BreakStatement; - this.label = label; - } - return BreakStatement; - }()); - exports.BreakStatement = BreakStatement; - var CallExpression = (function () { - function CallExpression(callee, args) { - this.type = syntax_1.Syntax.CallExpression; - this.callee = callee; - this.arguments = args; - } - return CallExpression; - }()); - exports.CallExpression = CallExpression; - var CatchClause = (function () { - function CatchClause(param, body) { - this.type = syntax_1.Syntax.CatchClause; - this.param = param; - this.body = body; - } - return CatchClause; - }()); - exports.CatchClause = CatchClause; - var ClassBody = (function () { - function ClassBody(body) { - this.type = syntax_1.Syntax.ClassBody; - this.body = body; - } - return ClassBody; - }()); - exports.ClassBody = ClassBody; - var ClassDeclaration = (function () { - function ClassDeclaration(id, superClass, body) { - this.type = syntax_1.Syntax.ClassDeclaration; - this.id = id; - this.superClass = superClass; - this.body = body; - } - return ClassDeclaration; - }()); - exports.ClassDeclaration = ClassDeclaration; - var ClassExpression = (function () { - function ClassExpression(id, superClass, body) { - this.type = syntax_1.Syntax.ClassExpression; - this.id = id; - this.superClass = superClass; - this.body = body; - } - return ClassExpression; - }()); - exports.ClassExpression = ClassExpression; - var ComputedMemberExpression = (function () { - function ComputedMemberExpression(object, property) { - this.type = syntax_1.Syntax.MemberExpression; - this.computed = true; - this.object = object; - this.property = property; - } - return ComputedMemberExpression; - }()); - exports.ComputedMemberExpression = ComputedMemberExpression; - var ConditionalExpression = (function () { - function ConditionalExpression(test, consequent, alternate) { - this.type = syntax_1.Syntax.ConditionalExpression; - this.test = test; - this.consequent = consequent; - this.alternate = alternate; - } - return ConditionalExpression; - }()); - exports.ConditionalExpression = ConditionalExpression; - var ContinueStatement = (function () { - function ContinueStatement(label) { - this.type = syntax_1.Syntax.ContinueStatement; - this.label = label; - } - return ContinueStatement; - }()); - exports.ContinueStatement = ContinueStatement; - var DebuggerStatement = (function () { - function DebuggerStatement() { - this.type = syntax_1.Syntax.DebuggerStatement; - } - return DebuggerStatement; - }()); - exports.DebuggerStatement = DebuggerStatement; - var Directive = (function () { - function Directive(expression, directive) { - this.type = syntax_1.Syntax.ExpressionStatement; - this.expression = expression; - this.directive = directive; - } - return Directive; - }()); - exports.Directive = Directive; - var DoWhileStatement = (function () { - function DoWhileStatement(body, test) { - this.type = syntax_1.Syntax.DoWhileStatement; - this.body = body; - this.test = test; - } - return DoWhileStatement; - }()); - exports.DoWhileStatement = DoWhileStatement; - var EmptyStatement = (function () { - function EmptyStatement() { - this.type = syntax_1.Syntax.EmptyStatement; - } - return EmptyStatement; - }()); - exports.EmptyStatement = EmptyStatement; - var ExportAllDeclaration = (function () { - function ExportAllDeclaration(source) { - this.type = syntax_1.Syntax.ExportAllDeclaration; - this.source = source; - } - return ExportAllDeclaration; - }()); - exports.ExportAllDeclaration = ExportAllDeclaration; - var ExportDefaultDeclaration = (function () { - function ExportDefaultDeclaration(declaration) { - this.type = syntax_1.Syntax.ExportDefaultDeclaration; - this.declaration = declaration; - } - return ExportDefaultDeclaration; - }()); - exports.ExportDefaultDeclaration = ExportDefaultDeclaration; - var ExportNamedDeclaration = (function () { - function ExportNamedDeclaration(declaration, specifiers, source) { - this.type = syntax_1.Syntax.ExportNamedDeclaration; - this.declaration = declaration; - this.specifiers = specifiers; - this.source = source; - } - return ExportNamedDeclaration; - }()); - exports.ExportNamedDeclaration = ExportNamedDeclaration; - var ExportSpecifier = (function () { - function ExportSpecifier(local, exported) { - this.type = syntax_1.Syntax.ExportSpecifier; - this.exported = exported; - this.local = local; - } - return ExportSpecifier; - }()); - exports.ExportSpecifier = ExportSpecifier; - var ExpressionStatement = (function () { - function ExpressionStatement(expression) { - this.type = syntax_1.Syntax.ExpressionStatement; - this.expression = expression; - } - return ExpressionStatement; - }()); - exports.ExpressionStatement = ExpressionStatement; - var ForInStatement = (function () { - function ForInStatement(left, right, body) { - this.type = syntax_1.Syntax.ForInStatement; - this.left = left; - this.right = right; - this.body = body; - this.each = false; - } - return ForInStatement; - }()); - exports.ForInStatement = ForInStatement; - var ForOfStatement = (function () { - function ForOfStatement(left, right, body) { - this.type = syntax_1.Syntax.ForOfStatement; - this.left = left; - this.right = right; - this.body = body; - } - return ForOfStatement; - }()); - exports.ForOfStatement = ForOfStatement; - var ForStatement = (function () { - function ForStatement(init, test, update, body) { - this.type = syntax_1.Syntax.ForStatement; - this.init = init; - this.test = test; - this.update = update; - this.body = body; - } - return ForStatement; - }()); - exports.ForStatement = ForStatement; - var FunctionDeclaration = (function () { - function FunctionDeclaration(id, params, body, generator) { - this.type = syntax_1.Syntax.FunctionDeclaration; - this.id = id; - this.params = params; - this.body = body; - this.generator = generator; - this.expression = false; - this.async = false; - } - return FunctionDeclaration; - }()); - exports.FunctionDeclaration = FunctionDeclaration; - var FunctionExpression = (function () { - function FunctionExpression(id, params, body, generator) { - this.type = syntax_1.Syntax.FunctionExpression; - this.id = id; - this.params = params; - this.body = body; - this.generator = generator; - this.expression = false; - this.async = false; - } - return FunctionExpression; - }()); - exports.FunctionExpression = FunctionExpression; - var Identifier = (function () { - function Identifier(name) { - this.type = syntax_1.Syntax.Identifier; - this.name = name; - } - return Identifier; - }()); - exports.Identifier = Identifier; - var IfStatement = (function () { - function IfStatement(test, consequent, alternate) { - this.type = syntax_1.Syntax.IfStatement; - this.test = test; - this.consequent = consequent; - this.alternate = alternate; - } - return IfStatement; - }()); - exports.IfStatement = IfStatement; - var ImportDeclaration = (function () { - function ImportDeclaration(specifiers, source) { - this.type = syntax_1.Syntax.ImportDeclaration; - this.specifiers = specifiers; - this.source = source; - } - return ImportDeclaration; - }()); - exports.ImportDeclaration = ImportDeclaration; - var ImportDefaultSpecifier = (function () { - function ImportDefaultSpecifier(local) { - this.type = syntax_1.Syntax.ImportDefaultSpecifier; - this.local = local; - } - return ImportDefaultSpecifier; - }()); - exports.ImportDefaultSpecifier = ImportDefaultSpecifier; - var ImportNamespaceSpecifier = (function () { - function ImportNamespaceSpecifier(local) { - this.type = syntax_1.Syntax.ImportNamespaceSpecifier; - this.local = local; - } - return ImportNamespaceSpecifier; - }()); - exports.ImportNamespaceSpecifier = ImportNamespaceSpecifier; - var ImportSpecifier = (function () { - function ImportSpecifier(local, imported) { - this.type = syntax_1.Syntax.ImportSpecifier; - this.local = local; - this.imported = imported; - } - return ImportSpecifier; - }()); - exports.ImportSpecifier = ImportSpecifier; - var LabeledStatement = (function () { - function LabeledStatement(label, body) { - this.type = syntax_1.Syntax.LabeledStatement; - this.label = label; - this.body = body; - } - return LabeledStatement; - }()); - exports.LabeledStatement = LabeledStatement; - var Literal = (function () { - function Literal(value, raw) { - this.type = syntax_1.Syntax.Literal; - this.value = value; - this.raw = raw; - } - return Literal; - }()); - exports.Literal = Literal; - var MetaProperty = (function () { - function MetaProperty(meta, property) { - this.type = syntax_1.Syntax.MetaProperty; - this.meta = meta; - this.property = property; - } - return MetaProperty; - }()); - exports.MetaProperty = MetaProperty; - var MethodDefinition = (function () { - function MethodDefinition(key, computed, value, kind, isStatic) { - this.type = syntax_1.Syntax.MethodDefinition; - this.key = key; - this.computed = computed; - this.value = value; - this.kind = kind; - this.static = isStatic; - } - return MethodDefinition; - }()); - exports.MethodDefinition = MethodDefinition; - var Module = (function () { - function Module(body) { - this.type = syntax_1.Syntax.Program; - this.body = body; - this.sourceType = 'module'; - } - return Module; - }()); - exports.Module = Module; - var NewExpression = (function () { - function NewExpression(callee, args) { - this.type = syntax_1.Syntax.NewExpression; - this.callee = callee; - this.arguments = args; - } - return NewExpression; - }()); - exports.NewExpression = NewExpression; - var ObjectExpression = (function () { - function ObjectExpression(properties) { - this.type = syntax_1.Syntax.ObjectExpression; - this.properties = properties; - } - return ObjectExpression; - }()); - exports.ObjectExpression = ObjectExpression; - var ObjectPattern = (function () { - function ObjectPattern(properties) { - this.type = syntax_1.Syntax.ObjectPattern; - this.properties = properties; - } - return ObjectPattern; - }()); - exports.ObjectPattern = ObjectPattern; - var Property = (function () { - function Property(kind, key, computed, value, method, shorthand) { - this.type = syntax_1.Syntax.Property; - this.key = key; - this.computed = computed; - this.value = value; - this.kind = kind; - this.method = method; - this.shorthand = shorthand; - } - return Property; - }()); - exports.Property = Property; - var RegexLiteral = (function () { - function RegexLiteral(value, raw, pattern, flags) { - this.type = syntax_1.Syntax.Literal; - this.value = value; - this.raw = raw; - this.regex = { pattern: pattern, flags: flags }; - } - return RegexLiteral; - }()); - exports.RegexLiteral = RegexLiteral; - var RestElement = (function () { - function RestElement(argument) { - this.type = syntax_1.Syntax.RestElement; - this.argument = argument; - } - return RestElement; - }()); - exports.RestElement = RestElement; - var ReturnStatement = (function () { - function ReturnStatement(argument) { - this.type = syntax_1.Syntax.ReturnStatement; - this.argument = argument; - } - return ReturnStatement; - }()); - exports.ReturnStatement = ReturnStatement; - var Script = (function () { - function Script(body) { - this.type = syntax_1.Syntax.Program; - this.body = body; - this.sourceType = 'script'; - } - return Script; - }()); - exports.Script = Script; - var SequenceExpression = (function () { - function SequenceExpression(expressions) { - this.type = syntax_1.Syntax.SequenceExpression; - this.expressions = expressions; - } - return SequenceExpression; - }()); - exports.SequenceExpression = SequenceExpression; - var SpreadElement = (function () { - function SpreadElement(argument) { - this.type = syntax_1.Syntax.SpreadElement; - this.argument = argument; - } - return SpreadElement; - }()); - exports.SpreadElement = SpreadElement; - var StaticMemberExpression = (function () { - function StaticMemberExpression(object, property) { - this.type = syntax_1.Syntax.MemberExpression; - this.computed = false; - this.object = object; - this.property = property; - } - return StaticMemberExpression; - }()); - exports.StaticMemberExpression = StaticMemberExpression; - var Super = (function () { - function Super() { - this.type = syntax_1.Syntax.Super; - } - return Super; - }()); - exports.Super = Super; - var SwitchCase = (function () { - function SwitchCase(test, consequent) { - this.type = syntax_1.Syntax.SwitchCase; - this.test = test; - this.consequent = consequent; - } - return SwitchCase; - }()); - exports.SwitchCase = SwitchCase; - var SwitchStatement = (function () { - function SwitchStatement(discriminant, cases) { - this.type = syntax_1.Syntax.SwitchStatement; - this.discriminant = discriminant; - this.cases = cases; - } - return SwitchStatement; - }()); - exports.SwitchStatement = SwitchStatement; - var TaggedTemplateExpression = (function () { - function TaggedTemplateExpression(tag, quasi) { - this.type = syntax_1.Syntax.TaggedTemplateExpression; - this.tag = tag; - this.quasi = quasi; - } - return TaggedTemplateExpression; - }()); - exports.TaggedTemplateExpression = TaggedTemplateExpression; - var TemplateElement = (function () { - function TemplateElement(value, tail) { - this.type = syntax_1.Syntax.TemplateElement; - this.value = value; - this.tail = tail; - } - return TemplateElement; - }()); - exports.TemplateElement = TemplateElement; - var TemplateLiteral = (function () { - function TemplateLiteral(quasis, expressions) { - this.type = syntax_1.Syntax.TemplateLiteral; - this.quasis = quasis; - this.expressions = expressions; - } - return TemplateLiteral; - }()); - exports.TemplateLiteral = TemplateLiteral; - var ThisExpression = (function () { - function ThisExpression() { - this.type = syntax_1.Syntax.ThisExpression; - } - return ThisExpression; - }()); - exports.ThisExpression = ThisExpression; - var ThrowStatement = (function () { - function ThrowStatement(argument) { - this.type = syntax_1.Syntax.ThrowStatement; - this.argument = argument; - } - return ThrowStatement; - }()); - exports.ThrowStatement = ThrowStatement; - var TryStatement = (function () { - function TryStatement(block, handler, finalizer) { - this.type = syntax_1.Syntax.TryStatement; - this.block = block; - this.handler = handler; - this.finalizer = finalizer; - } - return TryStatement; - }()); - exports.TryStatement = TryStatement; - var UnaryExpression = (function () { - function UnaryExpression(operator, argument) { - this.type = syntax_1.Syntax.UnaryExpression; - this.operator = operator; - this.argument = argument; - this.prefix = true; - } - return UnaryExpression; - }()); - exports.UnaryExpression = UnaryExpression; - var UpdateExpression = (function () { - function UpdateExpression(operator, argument, prefix) { - this.type = syntax_1.Syntax.UpdateExpression; - this.operator = operator; - this.argument = argument; - this.prefix = prefix; - } - return UpdateExpression; - }()); - exports.UpdateExpression = UpdateExpression; - var VariableDeclaration = (function () { - function VariableDeclaration(declarations, kind) { - this.type = syntax_1.Syntax.VariableDeclaration; - this.declarations = declarations; - this.kind = kind; - } - return VariableDeclaration; - }()); - exports.VariableDeclaration = VariableDeclaration; - var VariableDeclarator = (function () { - function VariableDeclarator(id, init) { - this.type = syntax_1.Syntax.VariableDeclarator; - this.id = id; - this.init = init; - } - return VariableDeclarator; - }()); - exports.VariableDeclarator = VariableDeclarator; - var WhileStatement = (function () { - function WhileStatement(test, body) { - this.type = syntax_1.Syntax.WhileStatement; - this.test = test; - this.body = body; - } - return WhileStatement; - }()); - exports.WhileStatement = WhileStatement; - var WithStatement = (function () { - function WithStatement(object, body) { - this.type = syntax_1.Syntax.WithStatement; - this.object = object; - this.body = body; - } - return WithStatement; - }()); - exports.WithStatement = WithStatement; - var YieldExpression = (function () { - function YieldExpression(argument, delegate) { - this.type = syntax_1.Syntax.YieldExpression; - this.argument = argument; - this.delegate = delegate; - } - return YieldExpression; - }()); - exports.YieldExpression = YieldExpression; - - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var assert_1 = __webpack_require__(9); - var error_handler_1 = __webpack_require__(10); - var messages_1 = __webpack_require__(11); - var Node = __webpack_require__(7); - var scanner_1 = __webpack_require__(12); - var syntax_1 = __webpack_require__(2); - var token_1 = __webpack_require__(13); - var ArrowParameterPlaceHolder = 'ArrowParameterPlaceHolder'; - var Parser = (function () { - function Parser(code, options, delegate) { - if (options === void 0) { options = {}; } - this.config = { - range: (typeof options.range === 'boolean') && options.range, - loc: (typeof options.loc === 'boolean') && options.loc, - source: null, - tokens: (typeof options.tokens === 'boolean') && options.tokens, - comment: (typeof options.comment === 'boolean') && options.comment, - tolerant: (typeof options.tolerant === 'boolean') && options.tolerant - }; - if (this.config.loc && options.source && options.source !== null) { - this.config.source = String(options.source); - } - this.delegate = delegate; - this.errorHandler = new error_handler_1.ErrorHandler(); - this.errorHandler.tolerant = this.config.tolerant; - this.scanner = new scanner_1.Scanner(code, this.errorHandler); - this.scanner.trackComment = this.config.comment; - this.operatorPrecedence = { - ')': 0, - ';': 0, - ',': 0, - '=': 0, - ']': 0, - '||': 1, - '&&': 2, - '|': 3, - '^': 4, - '&': 5, - '==': 6, - '!=': 6, - '===': 6, - '!==': 6, - '<': 7, - '>': 7, - '<=': 7, - '>=': 7, - '<<': 8, - '>>': 8, - '>>>': 8, - '+': 9, - '-': 9, - '*': 11, - '/': 11, - '%': 11 - }; - this.lookahead = { - type: 2 /* EOF */, - value: '', - lineNumber: this.scanner.lineNumber, - lineStart: 0, - start: 0, - end: 0 - }; - this.hasLineTerminator = false; - this.context = { - isModule: false, - await: false, - allowIn: true, - allowStrictDirective: true, - allowYield: true, - firstCoverInitializedNameError: null, - isAssignmentTarget: false, - isBindingElement: false, - inFunctionBody: false, - inIteration: false, - inSwitch: false, - labelSet: {}, - strict: false - }; - this.tokens = []; - this.startMarker = { - index: 0, - line: this.scanner.lineNumber, - column: 0 - }; - this.lastMarker = { - index: 0, - line: this.scanner.lineNumber, - column: 0 - }; - this.nextToken(); - this.lastMarker = { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - } - Parser.prototype.throwError = function (messageFormat) { - var values = []; - for (var _i = 1; _i < arguments.length; _i++) { - values[_i - 1] = arguments[_i]; - } - var args = Array.prototype.slice.call(arguments, 1); - var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { - assert_1.assert(idx < args.length, 'Message reference must be in range'); - return args[idx]; - }); - var index = this.lastMarker.index; - var line = this.lastMarker.line; - var column = this.lastMarker.column + 1; - throw this.errorHandler.createError(index, line, column, msg); - }; - Parser.prototype.tolerateError = function (messageFormat) { - var values = []; - for (var _i = 1; _i < arguments.length; _i++) { - values[_i - 1] = arguments[_i]; - } - var args = Array.prototype.slice.call(arguments, 1); - var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { - assert_1.assert(idx < args.length, 'Message reference must be in range'); - return args[idx]; - }); - var index = this.lastMarker.index; - var line = this.scanner.lineNumber; - var column = this.lastMarker.column + 1; - this.errorHandler.tolerateError(index, line, column, msg); - }; - // Throw an exception because of the token. - Parser.prototype.unexpectedTokenError = function (token, message) { - var msg = message || messages_1.Messages.UnexpectedToken; - var value; - if (token) { - if (!message) { - msg = (token.type === 2 /* EOF */) ? messages_1.Messages.UnexpectedEOS : - (token.type === 3 /* Identifier */) ? messages_1.Messages.UnexpectedIdentifier : - (token.type === 6 /* NumericLiteral */) ? messages_1.Messages.UnexpectedNumber : - (token.type === 8 /* StringLiteral */) ? messages_1.Messages.UnexpectedString : - (token.type === 10 /* Template */) ? messages_1.Messages.UnexpectedTemplate : - messages_1.Messages.UnexpectedToken; - if (token.type === 4 /* Keyword */) { - if (this.scanner.isFutureReservedWord(token.value)) { - msg = messages_1.Messages.UnexpectedReserved; - } - else if (this.context.strict && this.scanner.isStrictModeReservedWord(token.value)) { - msg = messages_1.Messages.StrictReservedWord; - } - } - } - value = token.value; - } - else { - value = 'ILLEGAL'; - } - msg = msg.replace('%0', value); - if (token && typeof token.lineNumber === 'number') { - var index = token.start; - var line = token.lineNumber; - var lastMarkerLineStart = this.lastMarker.index - this.lastMarker.column; - var column = token.start - lastMarkerLineStart + 1; - return this.errorHandler.createError(index, line, column, msg); - } - else { - var index = this.lastMarker.index; - var line = this.lastMarker.line; - var column = this.lastMarker.column + 1; - return this.errorHandler.createError(index, line, column, msg); - } - }; - Parser.prototype.throwUnexpectedToken = function (token, message) { - throw this.unexpectedTokenError(token, message); - }; - Parser.prototype.tolerateUnexpectedToken = function (token, message) { - this.errorHandler.tolerate(this.unexpectedTokenError(token, message)); - }; - Parser.prototype.collectComments = function () { - if (!this.config.comment) { - this.scanner.scanComments(); - } - else { - var comments = this.scanner.scanComments(); - if (comments.length > 0 && this.delegate) { - for (var i = 0; i < comments.length; ++i) { - var e = comments[i]; - var node = void 0; - node = { - type: e.multiLine ? 'BlockComment' : 'LineComment', - value: this.scanner.source.slice(e.slice[0], e.slice[1]) - }; - if (this.config.range) { - node.range = e.range; - } - if (this.config.loc) { - node.loc = e.loc; - } - var metadata = { - start: { - line: e.loc.start.line, - column: e.loc.start.column, - offset: e.range[0] - }, - end: { - line: e.loc.end.line, - column: e.loc.end.column, - offset: e.range[1] - } - }; - this.delegate(node, metadata); - } - } - } - }; - // From internal representation to an external structure - Parser.prototype.getTokenRaw = function (token) { - return this.scanner.source.slice(token.start, token.end); - }; - Parser.prototype.convertToken = function (token) { - var t = { - type: token_1.TokenName[token.type], - value: this.getTokenRaw(token) - }; - if (this.config.range) { - t.range = [token.start, token.end]; - } - if (this.config.loc) { - t.loc = { - start: { - line: this.startMarker.line, - column: this.startMarker.column - }, - end: { - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - } - }; - } - if (token.type === 9 /* RegularExpression */) { - var pattern = token.pattern; - var flags = token.flags; - t.regex = { pattern: pattern, flags: flags }; - } - return t; - }; - Parser.prototype.nextToken = function () { - var token = this.lookahead; - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - this.collectComments(); - if (this.scanner.index !== this.startMarker.index) { - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - } - var next = this.scanner.lex(); - this.hasLineTerminator = (token.lineNumber !== next.lineNumber); - if (next && this.context.strict && next.type === 3 /* Identifier */) { - if (this.scanner.isStrictModeReservedWord(next.value)) { - next.type = 4 /* Keyword */; - } - } - this.lookahead = next; - if (this.config.tokens && next.type !== 2 /* EOF */) { - this.tokens.push(this.convertToken(next)); - } - return token; - }; - Parser.prototype.nextRegexToken = function () { - this.collectComments(); - var token = this.scanner.scanRegExp(); - if (this.config.tokens) { - // Pop the previous token, '/' or '/=' - // This is added from the lookahead token. - this.tokens.pop(); - this.tokens.push(this.convertToken(token)); - } - // Prime the next lookahead. - this.lookahead = token; - this.nextToken(); - return token; - }; - Parser.prototype.createNode = function () { - return { - index: this.startMarker.index, - line: this.startMarker.line, - column: this.startMarker.column - }; - }; - Parser.prototype.startNode = function (token, lastLineStart) { - if (lastLineStart === void 0) { lastLineStart = 0; } - var column = token.start - token.lineStart; - var line = token.lineNumber; - if (column < 0) { - column += lastLineStart; - line--; - } - return { - index: token.start, - line: line, - column: column - }; - }; - Parser.prototype.finalize = function (marker, node) { - if (this.config.range) { - node.range = [marker.index, this.lastMarker.index]; - } - if (this.config.loc) { - node.loc = { - start: { - line: marker.line, - column: marker.column, - }, - end: { - line: this.lastMarker.line, - column: this.lastMarker.column - } - }; - if (this.config.source) { - node.loc.source = this.config.source; - } - } - if (this.delegate) { - var metadata = { - start: { - line: marker.line, - column: marker.column, - offset: marker.index - }, - end: { - line: this.lastMarker.line, - column: this.lastMarker.column, - offset: this.lastMarker.index - } - }; - this.delegate(node, metadata); - } - return node; - }; - // Expect the next token to match the specified punctuator. - // If not, an exception will be thrown. - Parser.prototype.expect = function (value) { - var token = this.nextToken(); - if (token.type !== 7 /* Punctuator */ || token.value !== value) { - this.throwUnexpectedToken(token); - } - }; - // Quietly expect a comma when in tolerant mode, otherwise delegates to expect(). - Parser.prototype.expectCommaSeparator = function () { - if (this.config.tolerant) { - var token = this.lookahead; - if (token.type === 7 /* Punctuator */ && token.value === ',') { - this.nextToken(); - } - else if (token.type === 7 /* Punctuator */ && token.value === ';') { - this.nextToken(); - this.tolerateUnexpectedToken(token); - } - else { - this.tolerateUnexpectedToken(token, messages_1.Messages.UnexpectedToken); - } - } - else { - this.expect(','); - } - }; - // Expect the next token to match the specified keyword. - // If not, an exception will be thrown. - Parser.prototype.expectKeyword = function (keyword) { - var token = this.nextToken(); - if (token.type !== 4 /* Keyword */ || token.value !== keyword) { - this.throwUnexpectedToken(token); - } - }; - // Return true if the next token matches the specified punctuator. - Parser.prototype.match = function (value) { - return this.lookahead.type === 7 /* Punctuator */ && this.lookahead.value === value; - }; - // Return true if the next token matches the specified keyword - Parser.prototype.matchKeyword = function (keyword) { - return this.lookahead.type === 4 /* Keyword */ && this.lookahead.value === keyword; - }; - // Return true if the next token matches the specified contextual keyword - // (where an identifier is sometimes a keyword depending on the context) - Parser.prototype.matchContextualKeyword = function (keyword) { - return this.lookahead.type === 3 /* Identifier */ && this.lookahead.value === keyword; - }; - // Return true if the next token is an assignment operator - Parser.prototype.matchAssign = function () { - if (this.lookahead.type !== 7 /* Punctuator */) { - return false; - } - var op = this.lookahead.value; - return op === '=' || - op === '*=' || - op === '**=' || - op === '/=' || - op === '%=' || - op === '+=' || - op === '-=' || - op === '<<=' || - op === '>>=' || - op === '>>>=' || - op === '&=' || - op === '^=' || - op === '|='; - }; - // Cover grammar support. - // - // When an assignment expression position starts with an left parenthesis, the determination of the type - // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) - // or the first comma. This situation also defers the determination of all the expressions nested in the pair. - // - // There are three productions that can be parsed in a parentheses pair that needs to be determined - // after the outermost pair is closed. They are: - // - // 1. AssignmentExpression - // 2. BindingElements - // 3. AssignmentTargets - // - // In order to avoid exponential backtracking, we use two flags to denote if the production can be - // binding element or assignment target. - // - // The three productions have the relationship: - // - // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression - // - // with a single exception that CoverInitializedName when used directly in an Expression, generates - // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the - // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. - // - // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not - // effect the current flags. This means the production the parser parses is only used as an expression. Therefore - // the CoverInitializedName check is conducted. - // - // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates - // the flags outside of the parser. This means the production the parser parses is used as a part of a potential - // pattern. The CoverInitializedName check is deferred. - Parser.prototype.isolateCoverGrammar = function (parseFunction) { - var previousIsBindingElement = this.context.isBindingElement; - var previousIsAssignmentTarget = this.context.isAssignmentTarget; - var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; - this.context.isBindingElement = true; - this.context.isAssignmentTarget = true; - this.context.firstCoverInitializedNameError = null; - var result = parseFunction.call(this); - if (this.context.firstCoverInitializedNameError !== null) { - this.throwUnexpectedToken(this.context.firstCoverInitializedNameError); - } - this.context.isBindingElement = previousIsBindingElement; - this.context.isAssignmentTarget = previousIsAssignmentTarget; - this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError; - return result; - }; - Parser.prototype.inheritCoverGrammar = function (parseFunction) { - var previousIsBindingElement = this.context.isBindingElement; - var previousIsAssignmentTarget = this.context.isAssignmentTarget; - var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; - this.context.isBindingElement = true; - this.context.isAssignmentTarget = true; - this.context.firstCoverInitializedNameError = null; - var result = parseFunction.call(this); - this.context.isBindingElement = this.context.isBindingElement && previousIsBindingElement; - this.context.isAssignmentTarget = this.context.isAssignmentTarget && previousIsAssignmentTarget; - this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.context.firstCoverInitializedNameError; - return result; - }; - Parser.prototype.consumeSemicolon = function () { - if (this.match(';')) { - this.nextToken(); - } - else if (!this.hasLineTerminator) { - if (this.lookahead.type !== 2 /* EOF */ && !this.match('}')) { - this.throwUnexpectedToken(this.lookahead); - } - this.lastMarker.index = this.startMarker.index; - this.lastMarker.line = this.startMarker.line; - this.lastMarker.column = this.startMarker.column; - } - }; - // https://tc39.github.io/ecma262/#sec-primary-expression - Parser.prototype.parsePrimaryExpression = function () { - var node = this.createNode(); - var expr; - var token, raw; - switch (this.lookahead.type) { - case 3 /* Identifier */: - if ((this.context.isModule || this.context.await) && this.lookahead.value === 'await') { - this.tolerateUnexpectedToken(this.lookahead); - } - expr = this.matchAsyncFunction() ? this.parseFunctionExpression() : this.finalize(node, new Node.Identifier(this.nextToken().value)); - break; - case 6 /* NumericLiteral */: - case 8 /* StringLiteral */: - if (this.context.strict && this.lookahead.octal) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.StrictOctalLiteral); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(token.value, raw)); - break; - case 1 /* BooleanLiteral */: - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(token.value === 'true', raw)); - break; - case 5 /* NullLiteral */: - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(null, raw)); - break; - case 10 /* Template */: - expr = this.parseTemplateLiteral(); - break; - case 7 /* Punctuator */: - switch (this.lookahead.value) { - case '(': - this.context.isBindingElement = false; - expr = this.inheritCoverGrammar(this.parseGroupExpression); - break; - case '[': - expr = this.inheritCoverGrammar(this.parseArrayInitializer); - break; - case '{': - expr = this.inheritCoverGrammar(this.parseObjectInitializer); - break; - case '/': - case '/=': - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - this.scanner.index = this.startMarker.index; - token = this.nextRegexToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.RegexLiteral(token.regex, raw, token.pattern, token.flags)); - break; - default: - expr = this.throwUnexpectedToken(this.nextToken()); - } - break; - case 4 /* Keyword */: - if (!this.context.strict && this.context.allowYield && this.matchKeyword('yield')) { - expr = this.parseIdentifierName(); - } - else if (!this.context.strict && this.matchKeyword('let')) { - expr = this.finalize(node, new Node.Identifier(this.nextToken().value)); - } - else { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - if (this.matchKeyword('function')) { - expr = this.parseFunctionExpression(); - } - else if (this.matchKeyword('this')) { - this.nextToken(); - expr = this.finalize(node, new Node.ThisExpression()); - } - else if (this.matchKeyword('class')) { - expr = this.parseClassExpression(); - } - else { - expr = this.throwUnexpectedToken(this.nextToken()); - } - } - break; - default: - expr = this.throwUnexpectedToken(this.nextToken()); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-array-initializer - Parser.prototype.parseSpreadElement = function () { - var node = this.createNode(); - this.expect('...'); - var arg = this.inheritCoverGrammar(this.parseAssignmentExpression); - return this.finalize(node, new Node.SpreadElement(arg)); - }; - Parser.prototype.parseArrayInitializer = function () { - var node = this.createNode(); - var elements = []; - this.expect('['); - while (!this.match(']')) { - if (this.match(',')) { - this.nextToken(); - elements.push(null); - } - else if (this.match('...')) { - var element = this.parseSpreadElement(); - if (!this.match(']')) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - this.expect(','); - } - elements.push(element); - } - else { - elements.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); - if (!this.match(']')) { - this.expect(','); - } - } - } - this.expect(']'); - return this.finalize(node, new Node.ArrayExpression(elements)); - }; - // https://tc39.github.io/ecma262/#sec-object-initializer - Parser.prototype.parsePropertyMethod = function (params) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = params.simple; - var body = this.isolateCoverGrammar(this.parseFunctionSourceElements); - if (this.context.strict && params.firstRestricted) { - this.tolerateUnexpectedToken(params.firstRestricted, params.message); - } - if (this.context.strict && params.stricted) { - this.tolerateUnexpectedToken(params.stricted, params.message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - return body; - }; - Parser.prototype.parsePropertyMethodFunction = function () { - var isGenerator = false; - var node = this.createNode(); - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var params = this.parseFormalParameters(); - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); - }; - Parser.prototype.parsePropertyMethodAsyncFunction = function () { - var node = this.createNode(); - var previousAllowYield = this.context.allowYield; - var previousAwait = this.context.await; - this.context.allowYield = false; - this.context.await = true; - var params = this.parseFormalParameters(); - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - this.context.await = previousAwait; - return this.finalize(node, new Node.AsyncFunctionExpression(null, params.params, method)); - }; - Parser.prototype.parseObjectPropertyKey = function () { - var node = this.createNode(); - var token = this.nextToken(); - var key; - switch (token.type) { - case 8 /* StringLiteral */: - case 6 /* NumericLiteral */: - if (this.context.strict && token.octal) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictOctalLiteral); - } - var raw = this.getTokenRaw(token); - key = this.finalize(node, new Node.Literal(token.value, raw)); - break; - case 3 /* Identifier */: - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 4 /* Keyword */: - key = this.finalize(node, new Node.Identifier(token.value)); - break; - case 7 /* Punctuator */: - if (token.value === '[') { - key = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.expect(']'); - } - else { - key = this.throwUnexpectedToken(token); - } - break; - default: - key = this.throwUnexpectedToken(token); - } - return key; - }; - Parser.prototype.isPropertyKey = function (key, value) { - return (key.type === syntax_1.Syntax.Identifier && key.name === value) || - (key.type === syntax_1.Syntax.Literal && key.value === value); - }; - Parser.prototype.parseObjectProperty = function (hasProto) { - var node = this.createNode(); - var token = this.lookahead; - var kind; - var key = null; - var value = null; - var computed = false; - var method = false; - var shorthand = false; - var isAsync = false; - if (token.type === 3 /* Identifier */) { - var id = token.value; - this.nextToken(); - computed = this.match('['); - isAsync = !this.hasLineTerminator && (id === 'async') && - !this.match(':') && !this.match('(') && !this.match('*') && !this.match(','); - key = isAsync ? this.parseObjectPropertyKey() : this.finalize(node, new Node.Identifier(id)); - } - else if (this.match('*')) { - this.nextToken(); - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - } - var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); - if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'get' && lookaheadPropertyKey) { - kind = 'get'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.context.allowYield = false; - value = this.parseGetterMethod(); - } - else if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'set' && lookaheadPropertyKey) { - kind = 'set'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseSetterMethod(); - } - else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { - kind = 'init'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseGeneratorMethod(); - method = true; - } - else { - if (!key) { - this.throwUnexpectedToken(this.lookahead); - } - kind = 'init'; - if (this.match(':') && !isAsync) { - if (!computed && this.isPropertyKey(key, '__proto__')) { - if (hasProto.value) { - this.tolerateError(messages_1.Messages.DuplicateProtoProperty); - } - hasProto.value = true; - } - this.nextToken(); - value = this.inheritCoverGrammar(this.parseAssignmentExpression); - } - else if (this.match('(')) { - value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); - method = true; - } - else if (token.type === 3 /* Identifier */) { - var id = this.finalize(node, new Node.Identifier(token.value)); - if (this.match('=')) { - this.context.firstCoverInitializedNameError = this.lookahead; - this.nextToken(); - shorthand = true; - var init = this.isolateCoverGrammar(this.parseAssignmentExpression); - value = this.finalize(node, new Node.AssignmentPattern(id, init)); - } - else { - shorthand = true; - value = id; - } - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - } - return this.finalize(node, new Node.Property(kind, key, computed, value, method, shorthand)); - }; - Parser.prototype.parseObjectInitializer = function () { - var node = this.createNode(); - this.expect('{'); - var properties = []; - var hasProto = { value: false }; - while (!this.match('}')) { - properties.push(this.parseObjectProperty(hasProto)); - if (!this.match('}')) { - this.expectCommaSeparator(); - } - } - this.expect('}'); - return this.finalize(node, new Node.ObjectExpression(properties)); - }; - // https://tc39.github.io/ecma262/#sec-template-literals - Parser.prototype.parseTemplateHead = function () { - assert_1.assert(this.lookahead.head, 'Template literal must start with a template head'); - var node = this.createNode(); - var token = this.nextToken(); - var raw = token.value; - var cooked = token.cooked; - return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); - }; - Parser.prototype.parseTemplateElement = function () { - if (this.lookahead.type !== 10 /* Template */) { - this.throwUnexpectedToken(); - } - var node = this.createNode(); - var token = this.nextToken(); - var raw = token.value; - var cooked = token.cooked; - return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); - }; - Parser.prototype.parseTemplateLiteral = function () { - var node = this.createNode(); - var expressions = []; - var quasis = []; - var quasi = this.parseTemplateHead(); - quasis.push(quasi); - while (!quasi.tail) { - expressions.push(this.parseExpression()); - quasi = this.parseTemplateElement(); - quasis.push(quasi); - } - return this.finalize(node, new Node.TemplateLiteral(quasis, expressions)); - }; - // https://tc39.github.io/ecma262/#sec-grouping-operator - Parser.prototype.reinterpretExpressionAsPattern = function (expr) { - switch (expr.type) { - case syntax_1.Syntax.Identifier: - case syntax_1.Syntax.MemberExpression: - case syntax_1.Syntax.RestElement: - case syntax_1.Syntax.AssignmentPattern: - break; - case syntax_1.Syntax.SpreadElement: - expr.type = syntax_1.Syntax.RestElement; - this.reinterpretExpressionAsPattern(expr.argument); - break; - case syntax_1.Syntax.ArrayExpression: - expr.type = syntax_1.Syntax.ArrayPattern; - for (var i = 0; i < expr.elements.length; i++) { - if (expr.elements[i] !== null) { - this.reinterpretExpressionAsPattern(expr.elements[i]); - } - } - break; - case syntax_1.Syntax.ObjectExpression: - expr.type = syntax_1.Syntax.ObjectPattern; - for (var i = 0; i < expr.properties.length; i++) { - this.reinterpretExpressionAsPattern(expr.properties[i].value); - } - break; - case syntax_1.Syntax.AssignmentExpression: - expr.type = syntax_1.Syntax.AssignmentPattern; - delete expr.operator; - this.reinterpretExpressionAsPattern(expr.left); - break; - default: - // Allow other node type for tolerant parsing. - break; - } - }; - Parser.prototype.parseGroupExpression = function () { - var expr; - this.expect('('); - if (this.match(')')) { - this.nextToken(); - if (!this.match('=>')) { - this.expect('=>'); - } - expr = { - type: ArrowParameterPlaceHolder, - params: [], - async: false - }; - } - else { - var startToken = this.lookahead; - var params = []; - if (this.match('...')) { - expr = this.parseRestElement(params); - this.expect(')'); - if (!this.match('=>')) { - this.expect('=>'); - } - expr = { - type: ArrowParameterPlaceHolder, - params: [expr], - async: false - }; - } - else { - var arrow = false; - this.context.isBindingElement = true; - expr = this.inheritCoverGrammar(this.parseAssignmentExpression); - if (this.match(',')) { - var expressions = []; - this.context.isAssignmentTarget = false; - expressions.push(expr); - while (this.lookahead.type !== 2 /* EOF */) { - if (!this.match(',')) { - break; - } - this.nextToken(); - if (this.match(')')) { - this.nextToken(); - for (var i = 0; i < expressions.length; i++) { - this.reinterpretExpressionAsPattern(expressions[i]); - } - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: expressions, - async: false - }; - } - else if (this.match('...')) { - if (!this.context.isBindingElement) { - this.throwUnexpectedToken(this.lookahead); - } - expressions.push(this.parseRestElement(params)); - this.expect(')'); - if (!this.match('=>')) { - this.expect('=>'); - } - this.context.isBindingElement = false; - for (var i = 0; i < expressions.length; i++) { - this.reinterpretExpressionAsPattern(expressions[i]); - } - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: expressions, - async: false - }; - } - else { - expressions.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); - } - if (arrow) { - break; - } - } - if (!arrow) { - expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); - } - } - if (!arrow) { - this.expect(')'); - if (this.match('=>')) { - if (expr.type === syntax_1.Syntax.Identifier && expr.name === 'yield') { - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: [expr], - async: false - }; - } - if (!arrow) { - if (!this.context.isBindingElement) { - this.throwUnexpectedToken(this.lookahead); - } - if (expr.type === syntax_1.Syntax.SequenceExpression) { - for (var i = 0; i < expr.expressions.length; i++) { - this.reinterpretExpressionAsPattern(expr.expressions[i]); - } - } - else { - this.reinterpretExpressionAsPattern(expr); - } - var parameters = (expr.type === syntax_1.Syntax.SequenceExpression ? expr.expressions : [expr]); - expr = { - type: ArrowParameterPlaceHolder, - params: parameters, - async: false - }; - } - } - this.context.isBindingElement = false; - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions - Parser.prototype.parseArguments = function () { - this.expect('('); - var args = []; - if (!this.match(')')) { - while (true) { - var expr = this.match('...') ? this.parseSpreadElement() : - this.isolateCoverGrammar(this.parseAssignmentExpression); - args.push(expr); - if (this.match(')')) { - break; - } - this.expectCommaSeparator(); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return args; - }; - Parser.prototype.isIdentifierName = function (token) { - return token.type === 3 /* Identifier */ || - token.type === 4 /* Keyword */ || - token.type === 1 /* BooleanLiteral */ || - token.type === 5 /* NullLiteral */; - }; - Parser.prototype.parseIdentifierName = function () { - var node = this.createNode(); - var token = this.nextToken(); - if (!this.isIdentifierName(token)) { - this.throwUnexpectedToken(token); - } - return this.finalize(node, new Node.Identifier(token.value)); - }; - Parser.prototype.parseNewExpression = function () { - var node = this.createNode(); - var id = this.parseIdentifierName(); - assert_1.assert(id.name === 'new', 'New expression must start with `new`'); - var expr; - if (this.match('.')) { - this.nextToken(); - if (this.lookahead.type === 3 /* Identifier */ && this.context.inFunctionBody && this.lookahead.value === 'target') { - var property = this.parseIdentifierName(); - expr = new Node.MetaProperty(id, property); - } - else { - this.throwUnexpectedToken(this.lookahead); - } - } - else { - var callee = this.isolateCoverGrammar(this.parseLeftHandSideExpression); - var args = this.match('(') ? this.parseArguments() : []; - expr = new Node.NewExpression(callee, args); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - return this.finalize(node, expr); - }; - Parser.prototype.parseAsyncArgument = function () { - var arg = this.parseAssignmentExpression(); - this.context.firstCoverInitializedNameError = null; - return arg; - }; - Parser.prototype.parseAsyncArguments = function () { - this.expect('('); - var args = []; - if (!this.match(')')) { - while (true) { - var expr = this.match('...') ? this.parseSpreadElement() : - this.isolateCoverGrammar(this.parseAsyncArgument); - args.push(expr); - if (this.match(')')) { - break; - } - this.expectCommaSeparator(); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return args; - }; - Parser.prototype.parseLeftHandSideExpressionAllowCall = function () { - var startToken = this.lookahead; - var maybeAsync = this.matchContextualKeyword('async'); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - var expr; - if (this.matchKeyword('super') && this.context.inFunctionBody) { - expr = this.createNode(); - this.nextToken(); - expr = this.finalize(expr, new Node.Super()); - if (!this.match('(') && !this.match('.') && !this.match('[')) { - this.throwUnexpectedToken(this.lookahead); - } - } - else { - expr = this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); - } - while (true) { - if (this.match('.')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('.'); - var property = this.parseIdentifierName(); - expr = this.finalize(this.startNode(startToken), new Node.StaticMemberExpression(expr, property)); - } - else if (this.match('(')) { - var asyncArrow = maybeAsync && (startToken.lineNumber === this.lookahead.lineNumber); - this.context.isBindingElement = false; - this.context.isAssignmentTarget = false; - var args = asyncArrow ? this.parseAsyncArguments() : this.parseArguments(); - expr = this.finalize(this.startNode(startToken), new Node.CallExpression(expr, args)); - if (asyncArrow && this.match('=>')) { - for (var i = 0; i < args.length; ++i) { - this.reinterpretExpressionAsPattern(args[i]); - } - expr = { - type: ArrowParameterPlaceHolder, - params: args, - async: true - }; - } - } - else if (this.match('[')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('['); - var property = this.isolateCoverGrammar(this.parseExpression); - this.expect(']'); - expr = this.finalize(this.startNode(startToken), new Node.ComputedMemberExpression(expr, property)); - } - else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { - var quasi = this.parseTemplateLiteral(); - expr = this.finalize(this.startNode(startToken), new Node.TaggedTemplateExpression(expr, quasi)); - } - else { - break; - } - } - this.context.allowIn = previousAllowIn; - return expr; - }; - Parser.prototype.parseSuper = function () { - var node = this.createNode(); - this.expectKeyword('super'); - if (!this.match('[') && !this.match('.')) { - this.throwUnexpectedToken(this.lookahead); - } - return this.finalize(node, new Node.Super()); - }; - Parser.prototype.parseLeftHandSideExpression = function () { - assert_1.assert(this.context.allowIn, 'callee of new expression always allow in keyword.'); - var node = this.startNode(this.lookahead); - var expr = (this.matchKeyword('super') && this.context.inFunctionBody) ? this.parseSuper() : - this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); - while (true) { - if (this.match('[')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('['); - var property = this.isolateCoverGrammar(this.parseExpression); - this.expect(']'); - expr = this.finalize(node, new Node.ComputedMemberExpression(expr, property)); - } - else if (this.match('.')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('.'); - var property = this.parseIdentifierName(); - expr = this.finalize(node, new Node.StaticMemberExpression(expr, property)); - } - else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { - var quasi = this.parseTemplateLiteral(); - expr = this.finalize(node, new Node.TaggedTemplateExpression(expr, quasi)); - } - else { - break; - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-update-expressions - Parser.prototype.parseUpdateExpression = function () { - var expr; - var startToken = this.lookahead; - if (this.match('++') || this.match('--')) { - var node = this.startNode(startToken); - var token = this.nextToken(); - expr = this.inheritCoverGrammar(this.parseUnaryExpression); - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { - this.tolerateError(messages_1.Messages.StrictLHSPrefix); - } - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - var prefix = true; - expr = this.finalize(node, new Node.UpdateExpression(token.value, expr, prefix)); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else { - expr = this.inheritCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - if (!this.hasLineTerminator && this.lookahead.type === 7 /* Punctuator */) { - if (this.match('++') || this.match('--')) { - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { - this.tolerateError(messages_1.Messages.StrictLHSPostfix); - } - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var operator = this.nextToken().value; - var prefix = false; - expr = this.finalize(this.startNode(startToken), new Node.UpdateExpression(operator, expr, prefix)); - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-unary-operators - Parser.prototype.parseAwaitExpression = function () { - var node = this.createNode(); - this.nextToken(); - var argument = this.parseUnaryExpression(); - return this.finalize(node, new Node.AwaitExpression(argument)); - }; - Parser.prototype.parseUnaryExpression = function () { - var expr; - if (this.match('+') || this.match('-') || this.match('~') || this.match('!') || - this.matchKeyword('delete') || this.matchKeyword('void') || this.matchKeyword('typeof')) { - var node = this.startNode(this.lookahead); - var token = this.nextToken(); - expr = this.inheritCoverGrammar(this.parseUnaryExpression); - expr = this.finalize(node, new Node.UnaryExpression(token.value, expr)); - if (this.context.strict && expr.operator === 'delete' && expr.argument.type === syntax_1.Syntax.Identifier) { - this.tolerateError(messages_1.Messages.StrictDelete); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else if (this.context.await && this.matchContextualKeyword('await')) { - expr = this.parseAwaitExpression(); - } - else { - expr = this.parseUpdateExpression(); - } - return expr; - }; - Parser.prototype.parseExponentiationExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseUnaryExpression); - if (expr.type !== syntax_1.Syntax.UnaryExpression && this.match('**')) { - this.nextToken(); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var left = expr; - var right = this.isolateCoverGrammar(this.parseExponentiationExpression); - expr = this.finalize(this.startNode(startToken), new Node.BinaryExpression('**', left, right)); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-exp-operator - // https://tc39.github.io/ecma262/#sec-multiplicative-operators - // https://tc39.github.io/ecma262/#sec-additive-operators - // https://tc39.github.io/ecma262/#sec-bitwise-shift-operators - // https://tc39.github.io/ecma262/#sec-relational-operators - // https://tc39.github.io/ecma262/#sec-equality-operators - // https://tc39.github.io/ecma262/#sec-binary-bitwise-operators - // https://tc39.github.io/ecma262/#sec-binary-logical-operators - Parser.prototype.binaryPrecedence = function (token) { - var op = token.value; - var precedence; - if (token.type === 7 /* Punctuator */) { - precedence = this.operatorPrecedence[op] || 0; - } - else if (token.type === 4 /* Keyword */) { - precedence = (op === 'instanceof' || (this.context.allowIn && op === 'in')) ? 7 : 0; - } - else { - precedence = 0; - } - return precedence; - }; - Parser.prototype.parseBinaryExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseExponentiationExpression); - var token = this.lookahead; - var prec = this.binaryPrecedence(token); - if (prec > 0) { - this.nextToken(); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var markers = [startToken, this.lookahead]; - var left = expr; - var right = this.isolateCoverGrammar(this.parseExponentiationExpression); - var stack = [left, token.value, right]; - var precedences = [prec]; - while (true) { - prec = this.binaryPrecedence(this.lookahead); - if (prec <= 0) { - break; - } - // Reduce: make a binary expression from the three topmost entries. - while ((stack.length > 2) && (prec <= precedences[precedences.length - 1])) { - right = stack.pop(); - var operator = stack.pop(); - precedences.pop(); - left = stack.pop(); - markers.pop(); - var node = this.startNode(markers[markers.length - 1]); - stack.push(this.finalize(node, new Node.BinaryExpression(operator, left, right))); - } - // Shift. - stack.push(this.nextToken().value); - precedences.push(prec); - markers.push(this.lookahead); - stack.push(this.isolateCoverGrammar(this.parseExponentiationExpression)); - } - // Final reduce to clean-up the stack. - var i = stack.length - 1; - expr = stack[i]; - var lastMarker = markers.pop(); - while (i > 1) { - var marker = markers.pop(); - var lastLineStart = lastMarker && lastMarker.lineStart; - var node = this.startNode(marker, lastLineStart); - var operator = stack[i - 1]; - expr = this.finalize(node, new Node.BinaryExpression(operator, stack[i - 2], expr)); - i -= 2; - lastMarker = marker; - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-conditional-operator - Parser.prototype.parseConditionalExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseBinaryExpression); - if (this.match('?')) { - this.nextToken(); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - var consequent = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.context.allowIn = previousAllowIn; - this.expect(':'); - var alternate = this.isolateCoverGrammar(this.parseAssignmentExpression); - expr = this.finalize(this.startNode(startToken), new Node.ConditionalExpression(expr, consequent, alternate)); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-assignment-operators - Parser.prototype.checkPatternParam = function (options, param) { - switch (param.type) { - case syntax_1.Syntax.Identifier: - this.validateParam(options, param, param.name); - break; - case syntax_1.Syntax.RestElement: - this.checkPatternParam(options, param.argument); - break; - case syntax_1.Syntax.AssignmentPattern: - this.checkPatternParam(options, param.left); - break; - case syntax_1.Syntax.ArrayPattern: - for (var i = 0; i < param.elements.length; i++) { - if (param.elements[i] !== null) { - this.checkPatternParam(options, param.elements[i]); - } - } - break; - case syntax_1.Syntax.ObjectPattern: - for (var i = 0; i < param.properties.length; i++) { - this.checkPatternParam(options, param.properties[i].value); - } - break; - default: - break; - } - options.simple = options.simple && (param instanceof Node.Identifier); - }; - Parser.prototype.reinterpretAsCoverFormalsList = function (expr) { - var params = [expr]; - var options; - var asyncArrow = false; - switch (expr.type) { - case syntax_1.Syntax.Identifier: - break; - case ArrowParameterPlaceHolder: - params = expr.params; - asyncArrow = expr.async; - break; - default: - return null; - } - options = { - simple: true, - paramSet: {} - }; - for (var i = 0; i < params.length; ++i) { - var param = params[i]; - if (param.type === syntax_1.Syntax.AssignmentPattern) { - if (param.right.type === syntax_1.Syntax.YieldExpression) { - if (param.right.argument) { - this.throwUnexpectedToken(this.lookahead); - } - param.right.type = syntax_1.Syntax.Identifier; - param.right.name = 'yield'; - delete param.right.argument; - delete param.right.delegate; - } - } - else if (asyncArrow && param.type === syntax_1.Syntax.Identifier && param.name === 'await') { - this.throwUnexpectedToken(this.lookahead); - } - this.checkPatternParam(options, param); - params[i] = param; - } - if (this.context.strict || !this.context.allowYield) { - for (var i = 0; i < params.length; ++i) { - var param = params[i]; - if (param.type === syntax_1.Syntax.YieldExpression) { - this.throwUnexpectedToken(this.lookahead); - } - } - } - if (options.message === messages_1.Messages.StrictParamDupe) { - var token = this.context.strict ? options.stricted : options.firstRestricted; - this.throwUnexpectedToken(token, options.message); - } - return { - simple: options.simple, - params: params, - stricted: options.stricted, - firstRestricted: options.firstRestricted, - message: options.message - }; - }; - Parser.prototype.parseAssignmentExpression = function () { - var expr; - if (!this.context.allowYield && this.matchKeyword('yield')) { - expr = this.parseYieldExpression(); - } - else { - var startToken = this.lookahead; - var token = startToken; - expr = this.parseConditionalExpression(); - if (token.type === 3 /* Identifier */ && (token.lineNumber === this.lookahead.lineNumber) && token.value === 'async') { - if (this.lookahead.type === 3 /* Identifier */ || this.matchKeyword('yield')) { - var arg = this.parsePrimaryExpression(); - this.reinterpretExpressionAsPattern(arg); - expr = { - type: ArrowParameterPlaceHolder, - params: [arg], - async: true - }; - } - } - if (expr.type === ArrowParameterPlaceHolder || this.match('=>')) { - // https://tc39.github.io/ecma262/#sec-arrow-function-definitions - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var isAsync = expr.async; - var list = this.reinterpretAsCoverFormalsList(expr); - if (list) { - if (this.hasLineTerminator) { - this.tolerateUnexpectedToken(this.lookahead); - } - this.context.firstCoverInitializedNameError = null; - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = list.simple; - var previousAllowYield = this.context.allowYield; - var previousAwait = this.context.await; - this.context.allowYield = true; - this.context.await = isAsync; - var node = this.startNode(startToken); - this.expect('=>'); - var body = void 0; - if (this.match('{')) { - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - body = this.parseFunctionSourceElements(); - this.context.allowIn = previousAllowIn; - } - else { - body = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - var expression = body.type !== syntax_1.Syntax.BlockStatement; - if (this.context.strict && list.firstRestricted) { - this.throwUnexpectedToken(list.firstRestricted, list.message); - } - if (this.context.strict && list.stricted) { - this.tolerateUnexpectedToken(list.stricted, list.message); - } - expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression)) : - this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression)); - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.allowYield = previousAllowYield; - this.context.await = previousAwait; - } - } - else { - if (this.matchAssign()) { - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier) { - var id = expr; - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictLHSAssignment); - } - if (this.scanner.isStrictModeReservedWord(id.name)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - } - if (!this.match('=')) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else { - this.reinterpretExpressionAsPattern(expr); - } - token = this.nextToken(); - var operator = token.value; - var right = this.isolateCoverGrammar(this.parseAssignmentExpression); - expr = this.finalize(this.startNode(startToken), new Node.AssignmentExpression(operator, expr, right)); - this.context.firstCoverInitializedNameError = null; - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-comma-operator - Parser.prototype.parseExpression = function () { - var startToken = this.lookahead; - var expr = this.isolateCoverGrammar(this.parseAssignmentExpression); - if (this.match(',')) { - var expressions = []; - expressions.push(expr); - while (this.lookahead.type !== 2 /* EOF */) { - if (!this.match(',')) { - break; - } - this.nextToken(); - expressions.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); - } - expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-block - Parser.prototype.parseStatementListItem = function () { - var statement; - this.context.isAssignmentTarget = true; - this.context.isBindingElement = true; - if (this.lookahead.type === 4 /* Keyword */) { - switch (this.lookahead.value) { - case 'export': - if (!this.context.isModule) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalExportDeclaration); - } - statement = this.parseExportDeclaration(); - break; - case 'import': - if (!this.context.isModule) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalImportDeclaration); - } - statement = this.parseImportDeclaration(); - break; - case 'const': - statement = this.parseLexicalDeclaration({ inFor: false }); - break; - case 'function': - statement = this.parseFunctionDeclaration(); - break; - case 'class': - statement = this.parseClassDeclaration(); - break; - case 'let': - statement = this.isLexicalDeclaration() ? this.parseLexicalDeclaration({ inFor: false }) : this.parseStatement(); - break; - default: - statement = this.parseStatement(); - break; - } - } - else { - statement = this.parseStatement(); - } - return statement; - }; - Parser.prototype.parseBlock = function () { - var node = this.createNode(); - this.expect('{'); - var block = []; - while (true) { - if (this.match('}')) { - break; - } - block.push(this.parseStatementListItem()); - } - this.expect('}'); - return this.finalize(node, new Node.BlockStatement(block)); - }; - // https://tc39.github.io/ecma262/#sec-let-and-const-declarations - Parser.prototype.parseLexicalBinding = function (kind, options) { - var node = this.createNode(); - var params = []; - var id = this.parsePattern(params, kind); - if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateError(messages_1.Messages.StrictVarName); - } - } - var init = null; - if (kind === 'const') { - if (!this.matchKeyword('in') && !this.matchContextualKeyword('of')) { - if (this.match('=')) { - this.nextToken(); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - else { - this.throwError(messages_1.Messages.DeclarationMissingInitializer, 'const'); - } - } - } - else if ((!options.inFor && id.type !== syntax_1.Syntax.Identifier) || this.match('=')) { - this.expect('='); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - return this.finalize(node, new Node.VariableDeclarator(id, init)); - }; - Parser.prototype.parseBindingList = function (kind, options) { - var list = [this.parseLexicalBinding(kind, options)]; - while (this.match(',')) { - this.nextToken(); - list.push(this.parseLexicalBinding(kind, options)); - } - return list; - }; - Parser.prototype.isLexicalDeclaration = function () { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.scanner.lex(); - this.scanner.restoreState(state); - return (next.type === 3 /* Identifier */) || - (next.type === 7 /* Punctuator */ && next.value === '[') || - (next.type === 7 /* Punctuator */ && next.value === '{') || - (next.type === 4 /* Keyword */ && next.value === 'let') || - (next.type === 4 /* Keyword */ && next.value === 'yield'); - }; - Parser.prototype.parseLexicalDeclaration = function (options) { - var node = this.createNode(); - var kind = this.nextToken().value; - assert_1.assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const'); - var declarations = this.parseBindingList(kind, options); - this.consumeSemicolon(); - return this.finalize(node, new Node.VariableDeclaration(declarations, kind)); - }; - // https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns - Parser.prototype.parseBindingRestElement = function (params, kind) { - var node = this.createNode(); - this.expect('...'); - var arg = this.parsePattern(params, kind); - return this.finalize(node, new Node.RestElement(arg)); - }; - Parser.prototype.parseArrayPattern = function (params, kind) { - var node = this.createNode(); - this.expect('['); - var elements = []; - while (!this.match(']')) { - if (this.match(',')) { - this.nextToken(); - elements.push(null); - } - else { - if (this.match('...')) { - elements.push(this.parseBindingRestElement(params, kind)); - break; - } - else { - elements.push(this.parsePatternWithDefault(params, kind)); - } - if (!this.match(']')) { - this.expect(','); - } - } - } - this.expect(']'); - return this.finalize(node, new Node.ArrayPattern(elements)); - }; - Parser.prototype.parsePropertyPattern = function (params, kind) { - var node = this.createNode(); - var computed = false; - var shorthand = false; - var method = false; - var key; - var value; - if (this.lookahead.type === 3 /* Identifier */) { - var keyToken = this.lookahead; - key = this.parseVariableIdentifier(); - var init = this.finalize(node, new Node.Identifier(keyToken.value)); - if (this.match('=')) { - params.push(keyToken); - shorthand = true; - this.nextToken(); - var expr = this.parseAssignmentExpression(); - value = this.finalize(this.startNode(keyToken), new Node.AssignmentPattern(init, expr)); - } - else if (!this.match(':')) { - params.push(keyToken); - shorthand = true; - value = init; - } - else { - this.expect(':'); - value = this.parsePatternWithDefault(params, kind); - } - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.expect(':'); - value = this.parsePatternWithDefault(params, kind); - } - return this.finalize(node, new Node.Property('init', key, computed, value, method, shorthand)); - }; - Parser.prototype.parseObjectPattern = function (params, kind) { - var node = this.createNode(); - var properties = []; - this.expect('{'); - while (!this.match('}')) { - properties.push(this.parsePropertyPattern(params, kind)); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - return this.finalize(node, new Node.ObjectPattern(properties)); - }; - Parser.prototype.parsePattern = function (params, kind) { - var pattern; - if (this.match('[')) { - pattern = this.parseArrayPattern(params, kind); - } - else if (this.match('{')) { - pattern = this.parseObjectPattern(params, kind); - } - else { - if (this.matchKeyword('let') && (kind === 'const' || kind === 'let')) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.LetInLexicalBinding); - } - params.push(this.lookahead); - pattern = this.parseVariableIdentifier(kind); - } - return pattern; - }; - Parser.prototype.parsePatternWithDefault = function (params, kind) { - var startToken = this.lookahead; - var pattern = this.parsePattern(params, kind); - if (this.match('=')) { - this.nextToken(); - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var right = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.context.allowYield = previousAllowYield; - pattern = this.finalize(this.startNode(startToken), new Node.AssignmentPattern(pattern, right)); - } - return pattern; - }; - // https://tc39.github.io/ecma262/#sec-variable-statement - Parser.prototype.parseVariableIdentifier = function (kind) { - var node = this.createNode(); - var token = this.nextToken(); - if (token.type === 4 /* Keyword */ && token.value === 'yield') { - if (this.context.strict) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - else if (!this.context.allowYield) { - this.throwUnexpectedToken(token); - } - } - else if (token.type !== 3 /* Identifier */) { - if (this.context.strict && token.type === 4 /* Keyword */ && this.scanner.isStrictModeReservedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - else { - if (this.context.strict || token.value !== 'let' || kind !== 'var') { - this.throwUnexpectedToken(token); - } - } - } - else if ((this.context.isModule || this.context.await) && token.type === 3 /* Identifier */ && token.value === 'await') { - this.tolerateUnexpectedToken(token); - } - return this.finalize(node, new Node.Identifier(token.value)); - }; - Parser.prototype.parseVariableDeclaration = function (options) { - var node = this.createNode(); - var params = []; - var id = this.parsePattern(params, 'var'); - if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateError(messages_1.Messages.StrictVarName); - } - } - var init = null; - if (this.match('=')) { - this.nextToken(); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - else if (id.type !== syntax_1.Syntax.Identifier && !options.inFor) { - this.expect('='); - } - return this.finalize(node, new Node.VariableDeclarator(id, init)); - }; - Parser.prototype.parseVariableDeclarationList = function (options) { - var opt = { inFor: options.inFor }; - var list = []; - list.push(this.parseVariableDeclaration(opt)); - while (this.match(',')) { - this.nextToken(); - list.push(this.parseVariableDeclaration(opt)); - } - return list; - }; - Parser.prototype.parseVariableStatement = function () { - var node = this.createNode(); - this.expectKeyword('var'); - var declarations = this.parseVariableDeclarationList({ inFor: false }); - this.consumeSemicolon(); - return this.finalize(node, new Node.VariableDeclaration(declarations, 'var')); - }; - // https://tc39.github.io/ecma262/#sec-empty-statement - Parser.prototype.parseEmptyStatement = function () { - var node = this.createNode(); - this.expect(';'); - return this.finalize(node, new Node.EmptyStatement()); - }; - // https://tc39.github.io/ecma262/#sec-expression-statement - Parser.prototype.parseExpressionStatement = function () { - var node = this.createNode(); - var expr = this.parseExpression(); - this.consumeSemicolon(); - return this.finalize(node, new Node.ExpressionStatement(expr)); - }; - // https://tc39.github.io/ecma262/#sec-if-statement - Parser.prototype.parseIfClause = function () { - if (this.context.strict && this.matchKeyword('function')) { - this.tolerateError(messages_1.Messages.StrictFunction); - } - return this.parseStatement(); - }; - Parser.prototype.parseIfStatement = function () { - var node = this.createNode(); - var consequent; - var alternate = null; - this.expectKeyword('if'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - consequent = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - consequent = this.parseIfClause(); - if (this.matchKeyword('else')) { - this.nextToken(); - alternate = this.parseIfClause(); - } - } - return this.finalize(node, new Node.IfStatement(test, consequent, alternate)); - }; - // https://tc39.github.io/ecma262/#sec-do-while-statement - Parser.prototype.parseDoWhileStatement = function () { - var node = this.createNode(); - this.expectKeyword('do'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - var body = this.parseStatement(); - this.context.inIteration = previousInIteration; - this.expectKeyword('while'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - } - else { - this.expect(')'); - if (this.match(';')) { - this.nextToken(); - } - } - return this.finalize(node, new Node.DoWhileStatement(body, test)); - }; - // https://tc39.github.io/ecma262/#sec-while-statement - Parser.prototype.parseWhileStatement = function () { - var node = this.createNode(); - var body; - this.expectKeyword('while'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - body = this.parseStatement(); - this.context.inIteration = previousInIteration; - } - return this.finalize(node, new Node.WhileStatement(test, body)); - }; - // https://tc39.github.io/ecma262/#sec-for-statement - // https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements - Parser.prototype.parseForStatement = function () { - var init = null; - var test = null; - var update = null; - var forIn = true; - var left, right; - var node = this.createNode(); - this.expectKeyword('for'); - this.expect('('); - if (this.match(';')) { - this.nextToken(); - } - else { - if (this.matchKeyword('var')) { - init = this.createNode(); - this.nextToken(); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - var declarations = this.parseVariableDeclarationList({ inFor: true }); - this.context.allowIn = previousAllowIn; - if (declarations.length === 1 && this.matchKeyword('in')) { - var decl = declarations[0]; - if (decl.init && (decl.id.type === syntax_1.Syntax.ArrayPattern || decl.id.type === syntax_1.Syntax.ObjectPattern || this.context.strict)) { - this.tolerateError(messages_1.Messages.ForInOfLoopInitializer, 'for-in'); - } - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.nextToken(); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.expect(';'); - } - } - else if (this.matchKeyword('const') || this.matchKeyword('let')) { - init = this.createNode(); - var kind = this.nextToken().value; - if (!this.context.strict && this.lookahead.value === 'in') { - init = this.finalize(init, new Node.Identifier(kind)); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else { - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - var declarations = this.parseBindingList(kind, { inFor: true }); - this.context.allowIn = previousAllowIn; - if (declarations.length === 1 && declarations[0].init === null && this.matchKeyword('in')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - this.nextToken(); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - this.consumeSemicolon(); - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - } - } - } - else { - var initStartToken = this.lookahead; - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - init = this.inheritCoverGrammar(this.parseAssignmentExpression); - this.context.allowIn = previousAllowIn; - if (this.matchKeyword('in')) { - if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { - this.tolerateError(messages_1.Messages.InvalidLHSInForIn); - } - this.nextToken(); - this.reinterpretExpressionAsPattern(init); - left = init; - right = this.parseExpression(); - init = null; - } - else if (this.matchContextualKeyword('of')) { - if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { - this.tolerateError(messages_1.Messages.InvalidLHSInForLoop); - } - this.nextToken(); - this.reinterpretExpressionAsPattern(init); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - if (this.match(',')) { - var initSeq = [init]; - while (this.match(',')) { - this.nextToken(); - initSeq.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); - } - init = this.finalize(this.startNode(initStartToken), new Node.SequenceExpression(initSeq)); - } - this.expect(';'); - } - } - } - if (typeof left === 'undefined') { - if (!this.match(';')) { - test = this.parseExpression(); - } - this.expect(';'); - if (!this.match(')')) { - update = this.parseExpression(); - } - } - var body; - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - body = this.isolateCoverGrammar(this.parseStatement); - this.context.inIteration = previousInIteration; - } - return (typeof left === 'undefined') ? - this.finalize(node, new Node.ForStatement(init, test, update, body)) : - forIn ? this.finalize(node, new Node.ForInStatement(left, right, body)) : - this.finalize(node, new Node.ForOfStatement(left, right, body)); - }; - // https://tc39.github.io/ecma262/#sec-continue-statement - Parser.prototype.parseContinueStatement = function () { - var node = this.createNode(); - this.expectKeyword('continue'); - var label = null; - if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { - var id = this.parseVariableIdentifier(); - label = id; - var key = '$' + id.name; - if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.UnknownLabel, id.name); - } - } - this.consumeSemicolon(); - if (label === null && !this.context.inIteration) { - this.throwError(messages_1.Messages.IllegalContinue); - } - return this.finalize(node, new Node.ContinueStatement(label)); - }; - // https://tc39.github.io/ecma262/#sec-break-statement - Parser.prototype.parseBreakStatement = function () { - var node = this.createNode(); - this.expectKeyword('break'); - var label = null; - if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { - var id = this.parseVariableIdentifier(); - var key = '$' + id.name; - if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.UnknownLabel, id.name); - } - label = id; - } - this.consumeSemicolon(); - if (label === null && !this.context.inIteration && !this.context.inSwitch) { - this.throwError(messages_1.Messages.IllegalBreak); - } - return this.finalize(node, new Node.BreakStatement(label)); - }; - // https://tc39.github.io/ecma262/#sec-return-statement - Parser.prototype.parseReturnStatement = function () { - if (!this.context.inFunctionBody) { - this.tolerateError(messages_1.Messages.IllegalReturn); - } - var node = this.createNode(); - this.expectKeyword('return'); - var hasArgument = (!this.match(';') && !this.match('}') && - !this.hasLineTerminator && this.lookahead.type !== 2 /* EOF */) || - this.lookahead.type === 8 /* StringLiteral */ || - this.lookahead.type === 10 /* Template */; - var argument = hasArgument ? this.parseExpression() : null; - this.consumeSemicolon(); - return this.finalize(node, new Node.ReturnStatement(argument)); - }; - // https://tc39.github.io/ecma262/#sec-with-statement - Parser.prototype.parseWithStatement = function () { - if (this.context.strict) { - this.tolerateError(messages_1.Messages.StrictModeWith); - } - var node = this.createNode(); - var body; - this.expectKeyword('with'); - this.expect('('); - var object = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - body = this.parseStatement(); - } - return this.finalize(node, new Node.WithStatement(object, body)); - }; - // https://tc39.github.io/ecma262/#sec-switch-statement - Parser.prototype.parseSwitchCase = function () { - var node = this.createNode(); - var test; - if (this.matchKeyword('default')) { - this.nextToken(); - test = null; - } - else { - this.expectKeyword('case'); - test = this.parseExpression(); - } - this.expect(':'); - var consequent = []; - while (true) { - if (this.match('}') || this.matchKeyword('default') || this.matchKeyword('case')) { - break; - } - consequent.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.SwitchCase(test, consequent)); - }; - Parser.prototype.parseSwitchStatement = function () { - var node = this.createNode(); - this.expectKeyword('switch'); - this.expect('('); - var discriminant = this.parseExpression(); - this.expect(')'); - var previousInSwitch = this.context.inSwitch; - this.context.inSwitch = true; - var cases = []; - var defaultFound = false; - this.expect('{'); - while (true) { - if (this.match('}')) { - break; - } - var clause = this.parseSwitchCase(); - if (clause.test === null) { - if (defaultFound) { - this.throwError(messages_1.Messages.MultipleDefaultsInSwitch); - } - defaultFound = true; - } - cases.push(clause); - } - this.expect('}'); - this.context.inSwitch = previousInSwitch; - return this.finalize(node, new Node.SwitchStatement(discriminant, cases)); - }; - // https://tc39.github.io/ecma262/#sec-labelled-statements - Parser.prototype.parseLabelledStatement = function () { - var node = this.createNode(); - var expr = this.parseExpression(); - var statement; - if ((expr.type === syntax_1.Syntax.Identifier) && this.match(':')) { - this.nextToken(); - var id = expr; - var key = '$' + id.name; - if (Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.Redeclaration, 'Label', id.name); - } - this.context.labelSet[key] = true; - var body = void 0; - if (this.matchKeyword('class')) { - this.tolerateUnexpectedToken(this.lookahead); - body = this.parseClassDeclaration(); - } - else if (this.matchKeyword('function')) { - var token = this.lookahead; - var declaration = this.parseFunctionDeclaration(); - if (this.context.strict) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunction); - } - else if (declaration.generator) { - this.tolerateUnexpectedToken(token, messages_1.Messages.GeneratorInLegacyContext); - } - body = declaration; - } - else { - body = this.parseStatement(); - } - delete this.context.labelSet[key]; - statement = new Node.LabeledStatement(id, body); - } - else { - this.consumeSemicolon(); - statement = new Node.ExpressionStatement(expr); - } - return this.finalize(node, statement); - }; - // https://tc39.github.io/ecma262/#sec-throw-statement - Parser.prototype.parseThrowStatement = function () { - var node = this.createNode(); - this.expectKeyword('throw'); - if (this.hasLineTerminator) { - this.throwError(messages_1.Messages.NewlineAfterThrow); - } - var argument = this.parseExpression(); - this.consumeSemicolon(); - return this.finalize(node, new Node.ThrowStatement(argument)); - }; - // https://tc39.github.io/ecma262/#sec-try-statement - Parser.prototype.parseCatchClause = function () { - var node = this.createNode(); - this.expectKeyword('catch'); - this.expect('('); - if (this.match(')')) { - this.throwUnexpectedToken(this.lookahead); - } - var params = []; - var param = this.parsePattern(params); - var paramMap = {}; - for (var i = 0; i < params.length; i++) { - var key = '$' + params[i].value; - if (Object.prototype.hasOwnProperty.call(paramMap, key)) { - this.tolerateError(messages_1.Messages.DuplicateBinding, params[i].value); - } - paramMap[key] = true; - } - if (this.context.strict && param.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(param.name)) { - this.tolerateError(messages_1.Messages.StrictCatchVariable); - } - } - this.expect(')'); - var body = this.parseBlock(); - return this.finalize(node, new Node.CatchClause(param, body)); - }; - Parser.prototype.parseFinallyClause = function () { - this.expectKeyword('finally'); - return this.parseBlock(); - }; - Parser.prototype.parseTryStatement = function () { - var node = this.createNode(); - this.expectKeyword('try'); - var block = this.parseBlock(); - var handler = this.matchKeyword('catch') ? this.parseCatchClause() : null; - var finalizer = this.matchKeyword('finally') ? this.parseFinallyClause() : null; - if (!handler && !finalizer) { - this.throwError(messages_1.Messages.NoCatchOrFinally); - } - return this.finalize(node, new Node.TryStatement(block, handler, finalizer)); - }; - // https://tc39.github.io/ecma262/#sec-debugger-statement - Parser.prototype.parseDebuggerStatement = function () { - var node = this.createNode(); - this.expectKeyword('debugger'); - this.consumeSemicolon(); - return this.finalize(node, new Node.DebuggerStatement()); - }; - // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations - Parser.prototype.parseStatement = function () { - var statement; - switch (this.lookahead.type) { - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 6 /* NumericLiteral */: - case 8 /* StringLiteral */: - case 10 /* Template */: - case 9 /* RegularExpression */: - statement = this.parseExpressionStatement(); - break; - case 7 /* Punctuator */: - var value = this.lookahead.value; - if (value === '{') { - statement = this.parseBlock(); - } - else if (value === '(') { - statement = this.parseExpressionStatement(); - } - else if (value === ';') { - statement = this.parseEmptyStatement(); - } - else { - statement = this.parseExpressionStatement(); - } - break; - case 3 /* Identifier */: - statement = this.matchAsyncFunction() ? this.parseFunctionDeclaration() : this.parseLabelledStatement(); - break; - case 4 /* Keyword */: - switch (this.lookahead.value) { - case 'break': - statement = this.parseBreakStatement(); - break; - case 'continue': - statement = this.parseContinueStatement(); - break; - case 'debugger': - statement = this.parseDebuggerStatement(); - break; - case 'do': - statement = this.parseDoWhileStatement(); - break; - case 'for': - statement = this.parseForStatement(); - break; - case 'function': - statement = this.parseFunctionDeclaration(); - break; - case 'if': - statement = this.parseIfStatement(); - break; - case 'return': - statement = this.parseReturnStatement(); - break; - case 'switch': - statement = this.parseSwitchStatement(); - break; - case 'throw': - statement = this.parseThrowStatement(); - break; - case 'try': - statement = this.parseTryStatement(); - break; - case 'var': - statement = this.parseVariableStatement(); - break; - case 'while': - statement = this.parseWhileStatement(); - break; - case 'with': - statement = this.parseWithStatement(); - break; - default: - statement = this.parseExpressionStatement(); - break; - } - break; - default: - statement = this.throwUnexpectedToken(this.lookahead); - } - return statement; - }; - // https://tc39.github.io/ecma262/#sec-function-definitions - Parser.prototype.parseFunctionSourceElements = function () { - var node = this.createNode(); - this.expect('{'); - var body = this.parseDirectivePrologues(); - var previousLabelSet = this.context.labelSet; - var previousInIteration = this.context.inIteration; - var previousInSwitch = this.context.inSwitch; - var previousInFunctionBody = this.context.inFunctionBody; - this.context.labelSet = {}; - this.context.inIteration = false; - this.context.inSwitch = false; - this.context.inFunctionBody = true; - while (this.lookahead.type !== 2 /* EOF */) { - if (this.match('}')) { - break; - } - body.push(this.parseStatementListItem()); - } - this.expect('}'); - this.context.labelSet = previousLabelSet; - this.context.inIteration = previousInIteration; - this.context.inSwitch = previousInSwitch; - this.context.inFunctionBody = previousInFunctionBody; - return this.finalize(node, new Node.BlockStatement(body)); - }; - Parser.prototype.validateParam = function (options, param, name) { - var key = '$' + name; - if (this.context.strict) { - if (this.scanner.isRestrictedWord(name)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamName; - } - if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamDupe; - } - } - else if (!options.firstRestricted) { - if (this.scanner.isRestrictedWord(name)) { - options.firstRestricted = param; - options.message = messages_1.Messages.StrictParamName; - } - else if (this.scanner.isStrictModeReservedWord(name)) { - options.firstRestricted = param; - options.message = messages_1.Messages.StrictReservedWord; - } - else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamDupe; - } - } - /* istanbul ignore next */ - if (typeof Object.defineProperty === 'function') { - Object.defineProperty(options.paramSet, key, { value: true, enumerable: true, writable: true, configurable: true }); - } - else { - options.paramSet[key] = true; - } - }; - Parser.prototype.parseRestElement = function (params) { - var node = this.createNode(); - this.expect('...'); - var arg = this.parsePattern(params); - if (this.match('=')) { - this.throwError(messages_1.Messages.DefaultRestParameter); - } - if (!this.match(')')) { - this.throwError(messages_1.Messages.ParameterAfterRestParameter); - } - return this.finalize(node, new Node.RestElement(arg)); - }; - Parser.prototype.parseFormalParameter = function (options) { - var params = []; - var param = this.match('...') ? this.parseRestElement(params) : this.parsePatternWithDefault(params); - for (var i = 0; i < params.length; i++) { - this.validateParam(options, params[i], params[i].value); - } - options.simple = options.simple && (param instanceof Node.Identifier); - options.params.push(param); - }; - Parser.prototype.parseFormalParameters = function (firstRestricted) { - var options; - options = { - simple: true, - params: [], - firstRestricted: firstRestricted - }; - this.expect('('); - if (!this.match(')')) { - options.paramSet = {}; - while (this.lookahead.type !== 2 /* EOF */) { - this.parseFormalParameter(options); - if (this.match(')')) { - break; - } - this.expect(','); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return { - simple: options.simple, - params: options.params, - stricted: options.stricted, - firstRestricted: options.firstRestricted, - message: options.message - }; - }; - Parser.prototype.matchAsyncFunction = function () { - var match = this.matchContextualKeyword('async'); - if (match) { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.scanner.lex(); - this.scanner.restoreState(state); - match = (state.lineNumber === next.lineNumber) && (next.type === 4 /* Keyword */) && (next.value === 'function'); - } - return match; - }; - Parser.prototype.parseFunctionDeclaration = function (identifierIsOptional) { - var node = this.createNode(); - var isAsync = this.matchContextualKeyword('async'); - if (isAsync) { - this.nextToken(); - } - this.expectKeyword('function'); - var isGenerator = isAsync ? false : this.match('*'); - if (isGenerator) { - this.nextToken(); - } - var message; - var id = null; - var firstRestricted = null; - if (!identifierIsOptional || !this.match('(')) { - var token = this.lookahead; - id = this.parseVariableIdentifier(); - if (this.context.strict) { - if (this.scanner.isRestrictedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); - } - } - else { - if (this.scanner.isRestrictedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictFunctionName; - } - else if (this.scanner.isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictReservedWord; - } - } - } - var previousAllowAwait = this.context.await; - var previousAllowYield = this.context.allowYield; - this.context.await = isAsync; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(firstRestricted); - var params = formalParameters.params; - var stricted = formalParameters.stricted; - firstRestricted = formalParameters.firstRestricted; - if (formalParameters.message) { - message = formalParameters.message; - } - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = formalParameters.simple; - var body = this.parseFunctionSourceElements(); - if (this.context.strict && firstRestricted) { - this.throwUnexpectedToken(firstRestricted, message); - } - if (this.context.strict && stricted) { - this.tolerateUnexpectedToken(stricted, message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.await = previousAllowAwait; - this.context.allowYield = previousAllowYield; - return isAsync ? this.finalize(node, new Node.AsyncFunctionDeclaration(id, params, body)) : - this.finalize(node, new Node.FunctionDeclaration(id, params, body, isGenerator)); - }; - Parser.prototype.parseFunctionExpression = function () { - var node = this.createNode(); - var isAsync = this.matchContextualKeyword('async'); - if (isAsync) { - this.nextToken(); - } - this.expectKeyword('function'); - var isGenerator = isAsync ? false : this.match('*'); - if (isGenerator) { - this.nextToken(); - } - var message; - var id = null; - var firstRestricted; - var previousAllowAwait = this.context.await; - var previousAllowYield = this.context.allowYield; - this.context.await = isAsync; - this.context.allowYield = !isGenerator; - if (!this.match('(')) { - var token = this.lookahead; - id = (!this.context.strict && !isGenerator && this.matchKeyword('yield')) ? this.parseIdentifierName() : this.parseVariableIdentifier(); - if (this.context.strict) { - if (this.scanner.isRestrictedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); - } - } - else { - if (this.scanner.isRestrictedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictFunctionName; - } - else if (this.scanner.isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictReservedWord; - } - } - } - var formalParameters = this.parseFormalParameters(firstRestricted); - var params = formalParameters.params; - var stricted = formalParameters.stricted; - firstRestricted = formalParameters.firstRestricted; - if (formalParameters.message) { - message = formalParameters.message; - } - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = formalParameters.simple; - var body = this.parseFunctionSourceElements(); - if (this.context.strict && firstRestricted) { - this.throwUnexpectedToken(firstRestricted, message); - } - if (this.context.strict && stricted) { - this.tolerateUnexpectedToken(stricted, message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.await = previousAllowAwait; - this.context.allowYield = previousAllowYield; - return isAsync ? this.finalize(node, new Node.AsyncFunctionExpression(id, params, body)) : - this.finalize(node, new Node.FunctionExpression(id, params, body, isGenerator)); - }; - // https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive - Parser.prototype.parseDirective = function () { - var token = this.lookahead; - var node = this.createNode(); - var expr = this.parseExpression(); - var directive = (expr.type === syntax_1.Syntax.Literal) ? this.getTokenRaw(token).slice(1, -1) : null; - this.consumeSemicolon(); - return this.finalize(node, directive ? new Node.Directive(expr, directive) : new Node.ExpressionStatement(expr)); - }; - Parser.prototype.parseDirectivePrologues = function () { - var firstRestricted = null; - var body = []; - while (true) { - var token = this.lookahead; - if (token.type !== 8 /* StringLiteral */) { - break; - } - var statement = this.parseDirective(); - body.push(statement); - var directive = statement.directive; - if (typeof directive !== 'string') { - break; - } - if (directive === 'use strict') { - this.context.strict = true; - if (firstRestricted) { - this.tolerateUnexpectedToken(firstRestricted, messages_1.Messages.StrictOctalLiteral); - } - if (!this.context.allowStrictDirective) { - this.tolerateUnexpectedToken(token, messages_1.Messages.IllegalLanguageModeDirective); - } - } - else { - if (!firstRestricted && token.octal) { - firstRestricted = token; - } - } - } - return body; - }; - // https://tc39.github.io/ecma262/#sec-method-definitions - Parser.prototype.qualifiedPropertyName = function (token) { - switch (token.type) { - case 3 /* Identifier */: - case 8 /* StringLiteral */: - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 6 /* NumericLiteral */: - case 4 /* Keyword */: - return true; - case 7 /* Punctuator */: - return token.value === '['; - default: - break; - } - return false; - }; - Parser.prototype.parseGetterMethod = function () { - var node = this.createNode(); - var isGenerator = false; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(); - if (formalParameters.params.length > 0) { - this.tolerateError(messages_1.Messages.BadGetterArity); - } - var method = this.parsePropertyMethod(formalParameters); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); - }; - Parser.prototype.parseSetterMethod = function () { - var node = this.createNode(); - var isGenerator = false; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(); - if (formalParameters.params.length !== 1) { - this.tolerateError(messages_1.Messages.BadSetterArity); - } - else if (formalParameters.params[0] instanceof Node.RestElement) { - this.tolerateError(messages_1.Messages.BadSetterRestParameter); - } - var method = this.parsePropertyMethod(formalParameters); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); - }; - Parser.prototype.parseGeneratorMethod = function () { - var node = this.createNode(); - var isGenerator = true; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var params = this.parseFormalParameters(); - this.context.allowYield = false; - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); - }; - // https://tc39.github.io/ecma262/#sec-generator-function-definitions - Parser.prototype.isStartOfExpression = function () { - var start = true; - var value = this.lookahead.value; - switch (this.lookahead.type) { - case 7 /* Punctuator */: - start = (value === '[') || (value === '(') || (value === '{') || - (value === '+') || (value === '-') || - (value === '!') || (value === '~') || - (value === '++') || (value === '--') || - (value === '/') || (value === '/='); // regular expression literal - break; - case 4 /* Keyword */: - start = (value === 'class') || (value === 'delete') || - (value === 'function') || (value === 'let') || (value === 'new') || - (value === 'super') || (value === 'this') || (value === 'typeof') || - (value === 'void') || (value === 'yield'); - break; - default: - break; - } - return start; - }; - Parser.prototype.parseYieldExpression = function () { - var node = this.createNode(); - this.expectKeyword('yield'); - var argument = null; - var delegate = false; - if (!this.hasLineTerminator) { - var previousAllowYield = this.context.allowYield; - this.context.allowYield = false; - delegate = this.match('*'); - if (delegate) { - this.nextToken(); - argument = this.parseAssignmentExpression(); - } - else if (this.isStartOfExpression()) { - argument = this.parseAssignmentExpression(); - } - this.context.allowYield = previousAllowYield; - } - return this.finalize(node, new Node.YieldExpression(argument, delegate)); - }; - // https://tc39.github.io/ecma262/#sec-class-definitions - Parser.prototype.parseClassElement = function (hasConstructor) { - var token = this.lookahead; - var node = this.createNode(); - var kind = ''; - var key = null; - var value = null; - var computed = false; - var method = false; - var isStatic = false; - var isAsync = false; - if (this.match('*')) { - this.nextToken(); - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - var id = key; - if (id.name === 'static' && (this.qualifiedPropertyName(this.lookahead) || this.match('*'))) { - token = this.lookahead; - isStatic = true; - computed = this.match('['); - if (this.match('*')) { - this.nextToken(); - } - else { - key = this.parseObjectPropertyKey(); - } - } - if ((token.type === 3 /* Identifier */) && !this.hasLineTerminator && (token.value === 'async')) { - var punctuator = this.lookahead.value; - if (punctuator !== ':' && punctuator !== '(' && punctuator !== '*') { - isAsync = true; - token = this.lookahead; - key = this.parseObjectPropertyKey(); - if (token.type === 3 /* Identifier */ && token.value === 'constructor') { - this.tolerateUnexpectedToken(token, messages_1.Messages.ConstructorIsAsync); - } - } - } - } - var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); - if (token.type === 3 /* Identifier */) { - if (token.value === 'get' && lookaheadPropertyKey) { - kind = 'get'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.context.allowYield = false; - value = this.parseGetterMethod(); - } - else if (token.value === 'set' && lookaheadPropertyKey) { - kind = 'set'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseSetterMethod(); - } - } - else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { - kind = 'init'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseGeneratorMethod(); - method = true; - } - if (!kind && key && this.match('(')) { - kind = 'init'; - value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); - method = true; - } - if (!kind) { - this.throwUnexpectedToken(this.lookahead); - } - if (kind === 'init') { - kind = 'method'; - } - if (!computed) { - if (isStatic && this.isPropertyKey(key, 'prototype')) { - this.throwUnexpectedToken(token, messages_1.Messages.StaticPrototype); - } - if (!isStatic && this.isPropertyKey(key, 'constructor')) { - if (kind !== 'method' || !method || (value && value.generator)) { - this.throwUnexpectedToken(token, messages_1.Messages.ConstructorSpecialMethod); - } - if (hasConstructor.value) { - this.throwUnexpectedToken(token, messages_1.Messages.DuplicateConstructor); - } - else { - hasConstructor.value = true; - } - kind = 'constructor'; - } - } - return this.finalize(node, new Node.MethodDefinition(key, computed, value, kind, isStatic)); - }; - Parser.prototype.parseClassElementList = function () { - var body = []; - var hasConstructor = { value: false }; - this.expect('{'); - while (!this.match('}')) { - if (this.match(';')) { - this.nextToken(); - } - else { - body.push(this.parseClassElement(hasConstructor)); - } - } - this.expect('}'); - return body; - }; - Parser.prototype.parseClassBody = function () { - var node = this.createNode(); - var elementList = this.parseClassElementList(); - return this.finalize(node, new Node.ClassBody(elementList)); - }; - Parser.prototype.parseClassDeclaration = function (identifierIsOptional) { - var node = this.createNode(); - var previousStrict = this.context.strict; - this.context.strict = true; - this.expectKeyword('class'); - var id = (identifierIsOptional && (this.lookahead.type !== 3 /* Identifier */)) ? null : this.parseVariableIdentifier(); - var superClass = null; - if (this.matchKeyword('extends')) { - this.nextToken(); - superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - } - var classBody = this.parseClassBody(); - this.context.strict = previousStrict; - return this.finalize(node, new Node.ClassDeclaration(id, superClass, classBody)); - }; - Parser.prototype.parseClassExpression = function () { - var node = this.createNode(); - var previousStrict = this.context.strict; - this.context.strict = true; - this.expectKeyword('class'); - var id = (this.lookahead.type === 3 /* Identifier */) ? this.parseVariableIdentifier() : null; - var superClass = null; - if (this.matchKeyword('extends')) { - this.nextToken(); - superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - } - var classBody = this.parseClassBody(); - this.context.strict = previousStrict; - return this.finalize(node, new Node.ClassExpression(id, superClass, classBody)); - }; - // https://tc39.github.io/ecma262/#sec-scripts - // https://tc39.github.io/ecma262/#sec-modules - Parser.prototype.parseModule = function () { - this.context.strict = true; - this.context.isModule = true; - this.scanner.isModule = true; - var node = this.createNode(); - var body = this.parseDirectivePrologues(); - while (this.lookahead.type !== 2 /* EOF */) { - body.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.Module(body)); - }; - Parser.prototype.parseScript = function () { - var node = this.createNode(); - var body = this.parseDirectivePrologues(); - while (this.lookahead.type !== 2 /* EOF */) { - body.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.Script(body)); - }; - // https://tc39.github.io/ecma262/#sec-imports - Parser.prototype.parseModuleSpecifier = function () { - var node = this.createNode(); - if (this.lookahead.type !== 8 /* StringLiteral */) { - this.throwError(messages_1.Messages.InvalidModuleSpecifier); - } - var token = this.nextToken(); - var raw = this.getTokenRaw(token); - return this.finalize(node, new Node.Literal(token.value, raw)); - }; - // import {} ...; - Parser.prototype.parseImportSpecifier = function () { - var node = this.createNode(); - var imported; - var local; - if (this.lookahead.type === 3 /* Identifier */) { - imported = this.parseVariableIdentifier(); - local = imported; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - local = this.parseVariableIdentifier(); - } - } - else { - imported = this.parseIdentifierName(); - local = imported; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - local = this.parseVariableIdentifier(); - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - } - return this.finalize(node, new Node.ImportSpecifier(local, imported)); - }; - // {foo, bar as bas} - Parser.prototype.parseNamedImports = function () { - this.expect('{'); - var specifiers = []; - while (!this.match('}')) { - specifiers.push(this.parseImportSpecifier()); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - return specifiers; - }; - // import ...; - Parser.prototype.parseImportDefaultSpecifier = function () { - var node = this.createNode(); - var local = this.parseIdentifierName(); - return this.finalize(node, new Node.ImportDefaultSpecifier(local)); - }; - // import <* as foo> ...; - Parser.prototype.parseImportNamespaceSpecifier = function () { - var node = this.createNode(); - this.expect('*'); - if (!this.matchContextualKeyword('as')) { - this.throwError(messages_1.Messages.NoAsAfterImportNamespace); - } - this.nextToken(); - var local = this.parseIdentifierName(); - return this.finalize(node, new Node.ImportNamespaceSpecifier(local)); - }; - Parser.prototype.parseImportDeclaration = function () { - if (this.context.inFunctionBody) { - this.throwError(messages_1.Messages.IllegalImportDeclaration); - } - var node = this.createNode(); - this.expectKeyword('import'); - var src; - var specifiers = []; - if (this.lookahead.type === 8 /* StringLiteral */) { - // import 'foo'; - src = this.parseModuleSpecifier(); - } - else { - if (this.match('{')) { - // import {bar} - specifiers = specifiers.concat(this.parseNamedImports()); - } - else if (this.match('*')) { - // import * as foo - specifiers.push(this.parseImportNamespaceSpecifier()); - } - else if (this.isIdentifierName(this.lookahead) && !this.matchKeyword('default')) { - // import foo - specifiers.push(this.parseImportDefaultSpecifier()); - if (this.match(',')) { - this.nextToken(); - if (this.match('*')) { - // import foo, * as foo - specifiers.push(this.parseImportNamespaceSpecifier()); - } - else if (this.match('{')) { - // import foo, {bar} - specifiers = specifiers.concat(this.parseNamedImports()); - } - else { - this.throwUnexpectedToken(this.lookahead); - } - } - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - if (!this.matchContextualKeyword('from')) { - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - this.nextToken(); - src = this.parseModuleSpecifier(); - } - this.consumeSemicolon(); - return this.finalize(node, new Node.ImportDeclaration(specifiers, src)); - }; - // https://tc39.github.io/ecma262/#sec-exports - Parser.prototype.parseExportSpecifier = function () { - var node = this.createNode(); - var local = this.parseIdentifierName(); - var exported = local; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - exported = this.parseIdentifierName(); - } - return this.finalize(node, new Node.ExportSpecifier(local, exported)); - }; - Parser.prototype.parseExportDeclaration = function () { - if (this.context.inFunctionBody) { - this.throwError(messages_1.Messages.IllegalExportDeclaration); - } - var node = this.createNode(); - this.expectKeyword('export'); - var exportDeclaration; - if (this.matchKeyword('default')) { - // export default ... - this.nextToken(); - if (this.matchKeyword('function')) { - // export default function foo () {} - // export default function () {} - var declaration = this.parseFunctionDeclaration(true); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else if (this.matchKeyword('class')) { - // export default class foo {} - var declaration = this.parseClassDeclaration(true); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else if (this.matchContextualKeyword('async')) { - // export default async function f () {} - // export default async function () {} - // export default async x => x - var declaration = this.matchAsyncFunction() ? this.parseFunctionDeclaration(true) : this.parseAssignmentExpression(); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else { - if (this.matchContextualKeyword('from')) { - this.throwError(messages_1.Messages.UnexpectedToken, this.lookahead.value); - } - // export default {}; - // export default []; - // export default (1 + 2); - var declaration = this.match('{') ? this.parseObjectInitializer() : - this.match('[') ? this.parseArrayInitializer() : this.parseAssignmentExpression(); - this.consumeSemicolon(); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - } - else if (this.match('*')) { - // export * from 'foo'; - this.nextToken(); - if (!this.matchContextualKeyword('from')) { - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - this.nextToken(); - var src = this.parseModuleSpecifier(); - this.consumeSemicolon(); - exportDeclaration = this.finalize(node, new Node.ExportAllDeclaration(src)); - } - else if (this.lookahead.type === 4 /* Keyword */) { - // export var f = 1; - var declaration = void 0; - switch (this.lookahead.value) { - case 'let': - case 'const': - declaration = this.parseLexicalDeclaration({ inFor: false }); - break; - case 'var': - case 'class': - case 'function': - declaration = this.parseStatementListItem(); - break; - default: - this.throwUnexpectedToken(this.lookahead); - } - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); - } - else if (this.matchAsyncFunction()) { - var declaration = this.parseFunctionDeclaration(); - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); - } - else { - var specifiers = []; - var source = null; - var isExportFromIdentifier = false; - this.expect('{'); - while (!this.match('}')) { - isExportFromIdentifier = isExportFromIdentifier || this.matchKeyword('default'); - specifiers.push(this.parseExportSpecifier()); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - if (this.matchContextualKeyword('from')) { - // export {default} from 'foo'; - // export {foo} from 'foo'; - this.nextToken(); - source = this.parseModuleSpecifier(); - this.consumeSemicolon(); - } - else if (isExportFromIdentifier) { - // export {default}; // missing fromClause - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - else { - // export {foo}; - this.consumeSemicolon(); - } - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(null, specifiers, source)); - } - return exportDeclaration; - }; - return Parser; - }()); - exports.Parser = Parser; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - "use strict"; - // Ensure the condition is true, otherwise throw an error. - // This is only to have a better contract semantic, i.e. another safety net - // to catch a logic error. The condition shall be fulfilled in normal case. - // Do NOT use this to enforce a certain condition on any user input. - Object.defineProperty(exports, "__esModule", { value: true }); - function assert(condition, message) { - /* istanbul ignore if */ - if (!condition) { - throw new Error('ASSERT: ' + message); - } - } - exports.assert = assert; - - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - "use strict"; - /* tslint:disable:max-classes-per-file */ - Object.defineProperty(exports, "__esModule", { value: true }); - var ErrorHandler = (function () { - function ErrorHandler() { - this.errors = []; - this.tolerant = false; - } - ErrorHandler.prototype.recordError = function (error) { - this.errors.push(error); - }; - ErrorHandler.prototype.tolerate = function (error) { - if (this.tolerant) { - this.recordError(error); - } - else { - throw error; - } - }; - ErrorHandler.prototype.constructError = function (msg, column) { - var error = new Error(msg); - try { - throw error; - } - catch (base) { - /* istanbul ignore else */ - if (Object.create && Object.defineProperty) { - error = Object.create(base); - Object.defineProperty(error, 'column', { value: column }); - } - } - /* istanbul ignore next */ - return error; - }; - ErrorHandler.prototype.createError = function (index, line, col, description) { - var msg = 'Line ' + line + ': ' + description; - var error = this.constructError(msg, col); - error.index = index; - error.lineNumber = line; - error.description = description; - return error; - }; - ErrorHandler.prototype.throwError = function (index, line, col, description) { - throw this.createError(index, line, col, description); - }; - ErrorHandler.prototype.tolerateError = function (index, line, col, description) { - var error = this.createError(index, line, col, description); - if (this.tolerant) { - this.recordError(error); - } - else { - throw error; - } - }; - return ErrorHandler; - }()); - exports.ErrorHandler = ErrorHandler; - - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - // Error messages should be identical to V8. - exports.Messages = { - BadGetterArity: 'Getter must not have any formal parameters', - BadSetterArity: 'Setter must have exactly one formal parameter', - BadSetterRestParameter: 'Setter function argument must not be a rest parameter', - ConstructorIsAsync: 'Class constructor may not be an async method', - ConstructorSpecialMethod: 'Class constructor may not be an accessor', - DeclarationMissingInitializer: 'Missing initializer in %0 declaration', - DefaultRestParameter: 'Unexpected token =', - DuplicateBinding: 'Duplicate binding %0', - DuplicateConstructor: 'A class may only have one constructor', - DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals', - ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer', - GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts', - IllegalBreak: 'Illegal break statement', - IllegalContinue: 'Illegal continue statement', - IllegalExportDeclaration: 'Unexpected token', - IllegalImportDeclaration: 'Unexpected token', - IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list', - IllegalReturn: 'Illegal return statement', - InvalidEscapedReservedWord: 'Keyword must not contain escaped characters', - InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence', - InvalidLHSInAssignment: 'Invalid left-hand side in assignment', - InvalidLHSInForIn: 'Invalid left-hand side in for-in', - InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', - InvalidModuleSpecifier: 'Unexpected token', - InvalidRegExp: 'Invalid regular expression', - LetInLexicalBinding: 'let is disallowed as a lexically bound name', - MissingFromClause: 'Unexpected token', - MultipleDefaultsInSwitch: 'More than one default clause in switch statement', - NewlineAfterThrow: 'Illegal newline after throw', - NoAsAfterImportNamespace: 'Unexpected token', - NoCatchOrFinally: 'Missing catch or finally after try', - ParameterAfterRestParameter: 'Rest parameter must be last formal parameter', - Redeclaration: '%0 \'%1\' has already been declared', - StaticPrototype: 'Classes may not have static property named prototype', - StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', - StrictDelete: 'Delete of an unqualified identifier in strict mode.', - StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block', - StrictFunctionName: 'Function name may not be eval or arguments in strict mode', - StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', - StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', - StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', - StrictModeWith: 'Strict mode code may not include a with statement', - StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', - StrictParamDupe: 'Strict mode function may not have duplicate parameter names', - StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', - StrictReservedWord: 'Use of future reserved word in strict mode', - StrictVarName: 'Variable name may not be eval or arguments in strict mode', - TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', - UnexpectedEOS: 'Unexpected end of input', - UnexpectedIdentifier: 'Unexpected identifier', - UnexpectedNumber: 'Unexpected number', - UnexpectedReserved: 'Unexpected reserved word', - UnexpectedString: 'Unexpected string', - UnexpectedTemplate: 'Unexpected quasi %0', - UnexpectedToken: 'Unexpected token %0', - UnexpectedTokenIllegal: 'Unexpected token ILLEGAL', - UnknownLabel: 'Undefined label \'%0\'', - UnterminatedRegExp: 'Invalid regular expression: missing /' - }; - - -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var assert_1 = __webpack_require__(9); - var character_1 = __webpack_require__(4); - var messages_1 = __webpack_require__(11); - function hexValue(ch) { - return '0123456789abcdef'.indexOf(ch.toLowerCase()); - } - function octalValue(ch) { - return '01234567'.indexOf(ch); - } - var Scanner = (function () { - function Scanner(code, handler) { - this.source = code; - this.errorHandler = handler; - this.trackComment = false; - this.isModule = false; - this.length = code.length; - this.index = 0; - this.lineNumber = (code.length > 0) ? 1 : 0; - this.lineStart = 0; - this.curlyStack = []; - } - Scanner.prototype.saveState = function () { - return { - index: this.index, - lineNumber: this.lineNumber, - lineStart: this.lineStart - }; - }; - Scanner.prototype.restoreState = function (state) { - this.index = state.index; - this.lineNumber = state.lineNumber; - this.lineStart = state.lineStart; - }; - Scanner.prototype.eof = function () { - return this.index >= this.length; - }; - Scanner.prototype.throwUnexpectedToken = function (message) { - if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } - return this.errorHandler.throwError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); - }; - Scanner.prototype.tolerateUnexpectedToken = function (message) { - if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } - this.errorHandler.tolerateError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); - }; - // https://tc39.github.io/ecma262/#sec-comments - Scanner.prototype.skipSingleLineComment = function (offset) { - var comments = []; - var start, loc; - if (this.trackComment) { - comments = []; - start = this.index - offset; - loc = { - start: { - line: this.lineNumber, - column: this.index - this.lineStart - offset - }, - end: {} - }; - } - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - ++this.index; - if (character_1.Character.isLineTerminator(ch)) { - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - 1 - }; - var entry = { - multiLine: false, - slice: [start + offset, this.index - 1], - range: [start, this.index - 1], - loc: loc - }; - comments.push(entry); - } - if (ch === 13 && this.source.charCodeAt(this.index) === 10) { - ++this.index; - } - ++this.lineNumber; - this.lineStart = this.index; - return comments; - } - } - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: false, - slice: [start + offset, this.index], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - return comments; - }; - Scanner.prototype.skipMultiLineComment = function () { - var comments = []; - var start, loc; - if (this.trackComment) { - comments = []; - start = this.index - 2; - loc = { - start: { - line: this.lineNumber, - column: this.index - this.lineStart - 2 - }, - end: {} - }; - } - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - if (character_1.Character.isLineTerminator(ch)) { - if (ch === 0x0D && this.source.charCodeAt(this.index + 1) === 0x0A) { - ++this.index; - } - ++this.lineNumber; - ++this.index; - this.lineStart = this.index; - } - else if (ch === 0x2A) { - // Block comment ends with '*/'. - if (this.source.charCodeAt(this.index + 1) === 0x2F) { - this.index += 2; - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: true, - slice: [start + 2, this.index - 2], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - return comments; - } - ++this.index; - } - else { - ++this.index; - } - } - // Ran off the end of the file - the whole thing is a comment - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: true, - slice: [start + 2, this.index], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - this.tolerateUnexpectedToken(); - return comments; - }; - Scanner.prototype.scanComments = function () { - var comments; - if (this.trackComment) { - comments = []; - } - var start = (this.index === 0); - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - if (character_1.Character.isWhiteSpace(ch)) { - ++this.index; - } - else if (character_1.Character.isLineTerminator(ch)) { - ++this.index; - if (ch === 0x0D && this.source.charCodeAt(this.index) === 0x0A) { - ++this.index; - } - ++this.lineNumber; - this.lineStart = this.index; - start = true; - } - else if (ch === 0x2F) { - ch = this.source.charCodeAt(this.index + 1); - if (ch === 0x2F) { - this.index += 2; - var comment = this.skipSingleLineComment(2); - if (this.trackComment) { - comments = comments.concat(comment); - } - start = true; - } - else if (ch === 0x2A) { - this.index += 2; - var comment = this.skipMultiLineComment(); - if (this.trackComment) { - comments = comments.concat(comment); - } - } - else { - break; - } - } - else if (start && ch === 0x2D) { - // U+003E is '>' - if ((this.source.charCodeAt(this.index + 1) === 0x2D) && (this.source.charCodeAt(this.index + 2) === 0x3E)) { - // '-->' is a single-line comment - this.index += 3; - var comment = this.skipSingleLineComment(3); - if (this.trackComment) { - comments = comments.concat(comment); - } - } - else { - break; - } - } - else if (ch === 0x3C && !this.isModule) { - if (this.source.slice(this.index + 1, this.index + 4) === '!--') { - this.index += 4; // `', engineSRCSafe); +fs.writeFileSync(path.join(distDir, 'emptyproject.html'), blankHTML); +fs.writeFileSync(path.join(distDir, 'index.html'), fs.readFileSync('src/export/zip/index.html', 'utf8')); +fs.writeFileSync(path.join(distDir, 'preloadjs.min.js'), fs.readFileSync('src/export/zip/preloadjs.min.js', 'utf8')); +fs.writeFileSync(path.join(distDir, 'project.html'), fs.readFileSync('src/export/html/project.html', 'utf8')); + +console.log('Engine built!') \ No newline at end of file diff --git a/engine/rolldown.config.mjs b/engine/rolldown.config.mjs new file mode 100644 index 000000000..af0a93a14 --- /dev/null +++ b/engine/rolldown.config.mjs @@ -0,0 +1,76 @@ +import { defineConfig } from 'rolldown'; +import path from 'path'; + +const root = process.cwd(); + +export default defineConfig({ + input: 'src/Wick.js', + external: ['paper', '$', 'jquery'], + resolve: { + alias: {}, + aliasFields: [['browser']], + mainFields: ['browser', 'module', 'main'], + extensions: ['.js', '.json'], + modules: ['node_modules'] + }, + output: { + dir: path.resolve(root, 'dist'), + format: 'iife', + name: 'WickModule', + intro: `globalThis.Wick = { + version: window.CandlestickVersion || "dev", + resourcepath: '../dist/', + _originals: {}, + gesture: { active: false, type: null }}; + /** + * This object creates a Wick namespace for wick-engine functionality and utilities. + */ + let _resolveLoaded; + globalThis.Wick.loaded = new Promise(resolve => { _resolveLoaded = resolve; }); + // expose resolver so we can resolve later when bootstrap completes + globalThis.Wick._resolveLoaded = _resolveLoaded; + + // Ensure that the Wick namespace is accessible in environments where globals are finicky (react, vite, etc) + const Wick = globalThis.Wick; + window.Wick = Wick;`, + outro: `if (Wick.Wick && typeof Wick.Wick === 'object') { + Object.assign(Wick, Wick.Wick); + }; + /* One instance of each Wick.Base class is created so we can access + * a list of all possible properties of each class. This is used + * to clean up custom variables after projects are stopped. + * + * Instantiating these classes creates paper.js views, which need a + * real document.body to compute canvas bounds against. This script + * runs synchronously while the document is still being parsed (often + * before exists), so this step is deferred until the DOM is + * actually ready instead of running immediately. + */ + function _collectWickOriginals() { + for (const [name, value] of Object.entries(Wick)) { + if (typeof value === 'function' && Wick.Base) { + const proto = value.prototype; + if (proto && proto instanceof Wick.Base) { + Wick._originals[name] = new value(); + } + } + } + + if (globalThis.Wick && globalThis.Wick._resolveLoaded) { + try { globalThis.Wick._resolveLoaded(globalThis.Wick); } catch (e) {} + delete globalThis.Wick._resolveLoaded; + } else globalThis.Wick.loaded = Promise.resolve(globalThis.Wick); + } + + if (document.body) { + _collectWickOriginals(); + } else { + document.addEventListener('DOMContentLoaded', _collectWickOriginals, { once: true }); + }`, + entryFileNames: 'wickengine.js', + sourcemap: true, + exports: 'auto', + esModule: false, + codeSplitting: false, + } +}); \ No newline at end of file diff --git a/engine/src/FileCache.js b/engine/src/FileCache.js index 1604db9f1..d59bc52c4 100644 --- a/engine/src/FileCache.js +++ b/engine/src/FileCache.js @@ -17,6 +17,7 @@ * along with Wick Engine. If not, see . */ +const localforage = require('localforage'); /** * Global utility class for storing and retrieving large file data. */ diff --git a/engine/src/Quadtree.js b/engine/src/Quadtree.js index f48879d53..4e2bd9936 100644 --- a/engine/src/Quadtree.js +++ b/engine/src/Quadtree.js @@ -7,6 +7,8 @@ // this.elements: // - dictionary of elements {uuid1: element1, uuid2: element2} // - these are the exact objects that go into this.quadtree by reference +const Quadtree = require('quadtree-lib'); + Wick.Quadtree = class { constructor(width, height) { this._quadtree = new Quadtree({ diff --git a/engine/src/ToolSettings.js b/engine/src/ToolSettings.js index ef4e9d969..8720209e4 100644 --- a/engine/src/ToolSettings.js +++ b/engine/src/ToolSettings.js @@ -17,6 +17,8 @@ * along with Wick Engine. If not, see . */ +const localforage = require('localforage'); + Wick.ToolSettings = class { static get DEFAULT_SETTINGS () { return [{ diff --git a/engine/src/Wick.js b/engine/src/Wick.js index 9deaa56a2..a643fb276 100644 --- a/engine/src/Wick.js +++ b/engine/src/Wick.js @@ -17,21 +17,153 @@ * along with Wick Engine. If not, see . */ -/** - * This object creates a Wick namespace for wick-engine functionality and utilities. - */ -Wick = { - version: window.WICK_ENGINE_BUILD_VERSION || "dev", - resourcepath: '../dist/', - _originals: {}, // Eventually store a single instance of each type of Wick.Base object (see Wick.Base constructor). - // adding global variable to track finger gestures -H.A. - gesture: { - active: false, - type: null - } -} - -console.log('Wick Engine version "' + Wick.version + '" is available.'); - -// Ensure that the Wick namespace is accessible in environments where globals are finicky (react, webpack, etc) -window.Wick = Wick; \ No newline at end of file +/* Import modules */ + +// Packages +import Quadtree from 'quadtree-lib'; +import { Howl, Howler } from 'howler'; +import JSZip from 'jszip'; +import lerp from 'lerp'; +import TWEEN from '@tweenjs/tween.js' +import hull from 'hull'; +import localforage from 'localforage'; +import platform from 'platform'; +import 'floodfill'; +import * as Base64ArrayBuffer from 'base64-arraybuffer'; +import 'esprima'; +import 'invert-color'; + +// Non-npm libraries +import Timestamp from '../lib/timestamp.js'; +import convertRange from '../lib/convert-range.js'; +import Croquis from '../lib/croquis.js'; +import '../lib/soundcloud-waveform.js'; +import '../lib/roundRect.js'; +import '../lib/currentTransform.js'; +import '../lib/potrace.js'; + +// Engine + +// src +import './Clipboard.js'; +import './Color.js'; +import './Transformation.js'; +import './ToolSettings.js'; +import './Quadtree.js'; +import './ObjectCache.js'; +import './History.js'; +import './GlobalAPI.js'; +import './FileCache.js'; + +// Base +import './base/Base.js'; +import './base/Tickable.js'; +import './base/Clip.js'; +import './base/Project.js'; +import './base/Layer.js'; +import './base/Selection.js'; +import './base/Timeline.js'; +import './base/Tween.js'; +import './base/Path.js'; +import './base/Frame.js'; +import './base/Button.js'; +import './base/WickSound.js'; + +// Base/asset +import './base/asset/Asset.js'; +import './base/asset/FileAsset.js'; +import './base/asset/ClipAsset.js'; +import './base/asset/FontAsset.js'; +import './base/asset/ImageAsset.js'; +import './base/asset/SoundAsset.js'; +import './base/asset/SVGAsset.js'; +import './base/asset/GIFAsset.js'; + +// Builtin assets +import './builtinassets/BuiltinAssets.js'; + +// View +import './view/View.js'; +import './view/View.Clip.js'; +import './view/View.Button.js'; +import './view/View.Project.js'; +import './view/View.Selection.js'; +import './view/View.Timeline.js'; +import './view/View.Layer.js'; +import './view/View.Frame.js'; +import './view/View.Path.js'; + +// paper-ext +import './view/paper-ext/Layer.erase.js'; +import './view/paper-ext/Paper.hole.js'; +import './view/paper-ext/Paper.OrderingUtils.js'; +import './view/paper-ext/Paper.SelectionWidget.js'; +import './view/paper-ext/Paper.SelectionBox.js'; +import './view/paper-ext/Path.potrace.js'; +import './view/paper-ext/OffsetUtils.js'; +import './view/paper-ext/Path.flatten.js'; +import './view/paper-ext/TextItem.edit.js'; +import './view/paper-ext/View.pressure.js'; +import './view/paper-ext/View.gestures.js'; +import './view/paper-ext/View.scrollToZoom.js'; + +// GUI +import './gui/GUIElement.js'; +import './gui/Ghost.js'; +import './gui/Button.js'; +import './gui/Icons.js'; +import './gui/FramesContainer.js'; +import './gui/Layer.js'; +import './gui/LayerCreateLabel.js'; +import './gui/LayersContainer.js'; +import './gui/NumberLine.js'; +import './gui/OnionSkinRange.js'; +import './gui/Playhead.js'; +import './gui/PopupMenu.js'; +import './gui/Project.js'; +import './gui/Scrollbar.js'; +import './gui/ScrollbarGrabber.js'; +import './gui/Timeline.js'; +import './gui/Tooltip.js'; +import './gui/Tween.js'; +import './gui/ActionButtonsContainer.js'; +import './gui/Breadcrumbs.js'; +import './gui/Frame.js'; +import './gui/ActionButton.js'; +import './gui/BreadcrumbsButton.js'; +import './gui/LayerButton.js'; +import './gui/FrameEdgeGhost.js'; +import './gui/FrameGhost.js'; +import './gui/SelectionBox.js'; +import './gui/TweenGhost.js'; + +// The 'export' folder +import './export/ExportUtils.js'; +import './export/audio/AudioTrack.js'; +import './export/autosave/AutoSave.js'; +import './export/html/HTMLExport.js'; +import './export/html/HTMLPreview.js'; +import './export/image/imageSequence.js'; +import './export/svg/SvgFile.js'; +import './export/wickobj/WickObjectFile.js'; +import './export/zip/ZIPExport.js'; +import './export/wick/WickFile.js'; +import './export/wick/WickFile.Alpha.js'; + +// Tools +import './tools/Tool.js'; +import './tools/Zoom.js'; +import './tools/Brush.js'; +import './tools/Cursor.js'; +import './tools/Eraser.js'; +import './tools/Eyedropper.js'; +import './tools/Ellipse.js'; +import './tools/Rectangle.js'; +import './tools/FillBucket.js'; +import './tools/Interact.js'; +import './tools/Line.js'; +import './tools/None.js'; +import './tools/Pan.js'; +import './tools/PathCursor.js'; +import './tools/Pencil.js'; +import './tools/Text.js'; \ No newline at end of file diff --git a/engine/src/base/Base.js b/engine/src/base/Base.js index 124ae6d0d..86061e497 100644 --- a/engine/src/base/Base.js +++ b/engine/src/base/Base.js @@ -17,24 +17,22 @@ * along with Wick Engine. If not, see . */ +// uuid +const { v4: uuidv4 } = require('uuid'); +// is-var-name +const isVarName = require('is-var-name').default; +const reserved = require('../../lib/reserved-words.js'); + /** * The base class for all objects within the Wick Engine. */ Wick.Base = class { /** * Creates a Base object. - * @parm {string} identifier - (Optional) The identifier of the object. Defaults to null. - * @parm {string} name - (Optional) The name of the object. Defaults to null. + * @param {string} identifier - (Optional) The identifier of the object. Defaults to null. + * @param {string} name - (Optional) The name of the object. Defaults to null. */ constructor(args) { - /* One instance of each Wick.Base class is created so we can access - * a list of all possible properties of each class. This is used - * to clean up custom variables after projects are stopped. */ - if (!Wick._originals[this.classname]) { - Wick._originals[this.classname] = {}; - Wick._originals[this.classname] = new Wick[this.classname]; - } - if (!args) args = {}; this._uuid = args.uuid || uuidv4(); diff --git a/engine/src/base/Clip.js b/engine/src/base/Clip.js index 0df88a5cf..fcae7d252 100644 --- a/engine/src/base/Clip.js +++ b/engine/src/base/Clip.js @@ -17,7 +17,7 @@ * along with Wick Engine. If not, see . */ - +const hull = require('hull'); /** * A class representing a Wick Clip. */ diff --git a/engine/src/base/Tickable.js b/engine/src/base/Tickable.js index cdc27adb2..8496e7feb 100644 --- a/engine/src/base/Tickable.js +++ b/engine/src/base/Tickable.js @@ -17,6 +17,7 @@ * along with Wick Engine. If not, see . */ +const esprima = require('esprima'); /** * A class that is extended by any wick object that ticks. */ diff --git a/engine/src/base/Tween.js b/engine/src/base/Tween.js index 9c0fa994d..dc33ff6e4 100644 --- a/engine/src/base/Tween.js +++ b/engine/src/base/Tween.js @@ -16,7 +16,8 @@ * You should have received a copy of the GNU General Public License * along with Wick Engine. If not, see . */ - +const lerp = require('lerp'); +const TWEEN = require('@tweenjs/tween.js'); /** * Class representing a tween. */ diff --git a/engine/src/base/asset/FontAsset.js b/engine/src/base/asset/FontAsset.js index 70518eb99..72cfebce9 100644 --- a/engine/src/base/asset/FontAsset.js +++ b/engine/src/base/asset/FontAsset.js @@ -17,6 +17,7 @@ * along with Wick Engine. If not, see . */ +const Base64ArrayBuffer = require('base64-arraybuffer'); Wick.FontAsset = class extends Wick.FileAsset { /** * Valid MIME types for font assets. diff --git a/engine/src/base/asset/SoundAsset.js b/engine/src/base/asset/SoundAsset.js index 940057c52..d29bd1048 100644 --- a/engine/src/base/asset/SoundAsset.js +++ b/engine/src/base/asset/SoundAsset.js @@ -17,6 +17,7 @@ * along with Wick Engine. If not, see . */ +const SCWF = require('../../../lib/soundcloud-waveform.js'); Wick.SoundAsset = class extends Wick.FileAsset { /** * Returns valid MIME types for a Sound Asset. diff --git a/engine/src/export/audio/AudioTrack.js b/engine/src/export/audio/AudioTrack.js index e9cd52267..8b358f030 100644 --- a/engine/src/export/audio/AudioTrack.js +++ b/engine/src/export/audio/AudioTrack.js @@ -17,6 +17,7 @@ * along with Wick Engine. If not, see . */ +const Base64ArrayBuffer = require('base64-arraybuffer'); Wick.AudioTrack = class { /** * @type {Wick.Project} diff --git a/engine/src/export/autosave/AutoSave.js b/engine/src/export/autosave/AutoSave.js index 4a1fa04cf..9e352449d 100644 --- a/engine/src/export/autosave/AutoSave.js +++ b/engine/src/export/autosave/AutoSave.js @@ -17,6 +17,7 @@ * along with Wick Engine. If not, see . */ +const localforage = require('localforage') /** * Utility class for autosaving projects. */ diff --git a/engine/src/export/image/imageSequence.js b/engine/src/export/image/imageSequence.js index 8b21146da..489be379a 100644 --- a/engine/src/export/image/imageSequence.js +++ b/engine/src/export/image/imageSequence.js @@ -17,6 +17,7 @@ * along with Wick Engine. If not, see . */ +const JSZip = require('jszip'); /** * Utility class for generating image sequences. */ diff --git a/engine/src/export/wick/WickFile.js b/engine/src/export/wick/WickFile.js index 4ee272e9e..8888c4065 100644 --- a/engine/src/export/wick/WickFile.js +++ b/engine/src/export/wick/WickFile.js @@ -17,7 +17,8 @@ * along with Wick Engine. If not, see . */ - +const platform = require('platform'); +const JSZip = require('jszip'); /** * Utility class for creating and parsing wick files. */ diff --git a/engine/src/export/zip/ZIPExport.js b/engine/src/export/zip/ZIPExport.js index 2d8e507be..609387daf 100644 --- a/engine/src/export/zip/ZIPExport.js +++ b/engine/src/export/zip/ZIPExport.js @@ -16,6 +16,7 @@ * You should have received a copy of the GNU General Public License * along with Wick Engine. If not, see . */ +const JSZip = require('jszip'); /** * Utility class for bundling Wick projects inside ZIP files. diff --git a/engine/src/export/zip/wickengine.js b/engine/src/export/zip/wickengine.js deleted file mode 100644 index a12409c00..000000000 --- a/engine/src/export/zip/wickengine.js +++ /dev/null @@ -1,61753 +0,0 @@ -/*Wick Engine https://github.com/Wicklets/wick-engine*/ -var WICK_ENGINE_BUILD_VERSION = "2019.11.6"; -/*! - * Paper.js v0.11.8 - The Swiss Army Knife of Vector Graphics Scripting. - * http://paperjs.org/ - * - * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey - * http://scratchdisk.com/ & http://jonathanpuckey.com/ - * - * Distributed under the MIT license. See LICENSE file for details. - * - * All rights reserved. - * - * Date: Wed Oct 17 17:00:54 2018 +0200 - * - *** - * - * Straps.js - Class inheritance library with support for bean-style accessors - * - * Copyright (c) 2006 - 2016 Juerg Lehni - * http://scratchdisk.com/ - * - * Distributed under the MIT license. - * - *** - * - * Acorn.js - * http://marijnhaverbeke.nl/acorn/ - * - * Acorn is a tiny, fast JavaScript parser written in JavaScript, - * created by Marijn Haverbeke and released under an MIT license. - * - */ - -var paper = function(self, undefined) { - -self = self || require('./node/self.js'); -var window = self.window, - document = self.document; - -var Base = new function() { - var hidden = /^(statics|enumerable|beans|preserve)$/, - array = [], - slice = array.slice, - create = Object.create, - describe = Object.getOwnPropertyDescriptor, - define = Object.defineProperty, - - forEach = array.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) { - for (var i in this) { - if (this.hasOwnProperty(i)) - iter.call(bind, this[i], i, this); - } - }, - - set = Object.assign || function(dst) { - for (var i = 1, l = arguments.length; i < l; i++) { - var src = arguments[i]; - for (var key in src) { - if (src.hasOwnProperty(key)) - dst[key] = src[key]; - } - } - return dst; - }, - - each = function(obj, iter, bind) { - if (obj) { - var desc = describe(obj, 'length'); - (desc && typeof desc.value === 'number' ? forEach : forIn) - .call(obj, iter, bind = bind || obj); - } - return bind; - }; - - function inject(dest, src, enumerable, beans, preserve) { - var beansNames = {}; - - function field(name, val) { - val = val || (val = describe(src, name)) - && (val.get ? val : val.value); - if (typeof val === 'string' && val[0] === '#') - val = dest[val.substring(1)] || val; - var isFunc = typeof val === 'function', - res = val, - prev = preserve || isFunc && !val.base - ? (val && val.get ? name in dest : dest[name]) - : null, - bean; - if (!preserve || !prev) { - if (isFunc && prev) - val.base = prev; - if (isFunc && beans !== false - && (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/))) - beansNames[bean[3].toLowerCase() + bean[4]] = bean[2]; - if (!res || isFunc || !res.get || typeof res.get !== 'function' - || !Base.isPlainObject(res)) { - res = { value: res, writable: true }; - } - if ((describe(dest, name) - || { configurable: true }).configurable) { - res.configurable = true; - res.enumerable = enumerable != null ? enumerable : !bean; - } - define(dest, name, res); - } - } - if (src) { - for (var name in src) { - if (src.hasOwnProperty(name) && !hidden.test(name)) - field(name); - } - for (var name in beansNames) { - var part = beansNames[name], - set = dest['set' + part], - get = dest['get' + part] || set && dest['is' + part]; - if (get && (beans === true || get.length === 0)) - field(name, { get: get, set: set }); - } - } - return dest; - } - - function Base() { - for (var i = 0, l = arguments.length; i < l; i++) { - var src = arguments[i]; - if (src) - set(this, src); - } - return this; - } - - return inject(Base, { - inject: function(src) { - if (src) { - var statics = src.statics === true ? src : src.statics, - beans = src.beans, - preserve = src.preserve; - if (statics !== src) - inject(this.prototype, src, src.enumerable, beans, preserve); - inject(this, statics, null, beans, preserve); - } - for (var i = 1, l = arguments.length; i < l; i++) - this.inject(arguments[i]); - return this; - }, - - extend: function() { - var base = this, - ctor, - proto; - for (var i = 0, obj, l = arguments.length; - i < l && !(ctor && proto); i++) { - obj = arguments[i]; - ctor = ctor || obj.initialize; - proto = proto || obj.prototype; - } - ctor = ctor || function() { - base.apply(this, arguments); - }; - proto = ctor.prototype = proto || create(this.prototype); - define(proto, 'constructor', - { value: ctor, writable: true, configurable: true }); - inject(ctor, this); - if (arguments.length) - this.inject.apply(ctor, arguments); - ctor.base = base; - return ctor; - } - }).inject({ - enumerable: false, - - initialize: Base, - - set: Base, - - inject: function() { - for (var i = 0, l = arguments.length; i < l; i++) { - var src = arguments[i]; - if (src) { - inject(this, src, src.enumerable, src.beans, src.preserve); - } - } - return this; - }, - - extend: function() { - var res = create(this); - return res.inject.apply(res, arguments); - }, - - each: function(iter, bind) { - return each(this, iter, bind); - }, - - clone: function() { - return new this.constructor(this); - }, - - statics: { - set: set, - each: each, - create: create, - define: define, - describe: describe, - - clone: function(obj) { - return set(new obj.constructor(), obj); - }, - - isPlainObject: function(obj) { - var ctor = obj != null && obj.constructor; - return ctor && (ctor === Object || ctor === Base - || ctor.name === 'Object'); - }, - - pick: function(a, b) { - return a !== undefined ? a : b; - }, - - slice: function(list, begin, end) { - return slice.call(list, begin, end); - } - } - }); -}; - -if (typeof module !== 'undefined') - module.exports = Base; - -Base.inject({ - enumerable: false, - - toString: function() { - return this._id != null - ? (this._class || 'Object') + (this._name - ? " '" + this._name + "'" - : ' @' + this._id) - : '{ ' + Base.each(this, function(value, key) { - if (!/^_/.test(key)) { - var type = typeof value; - this.push(key + ': ' + (type === 'number' - ? Formatter.instance.number(value) - : type === 'string' ? "'" + value + "'" : value)); - } - }, []).join(', ') + ' }'; - }, - - getClassName: function() { - return this._class || ''; - }, - - importJSON: function(json) { - return Base.importJSON(json, this); - }, - - exportJSON: function(options) { - return Base.exportJSON(this, options); - }, - - toJSON: function() { - return Base.serialize(this); - }, - - set: function(props, exclude) { - if (props) - Base.filter(this, props, exclude, this._prioritize); - return this; - } -}, { - -beans: false, -statics: { - exports: {}, - - extend: function extend() { - var res = extend.base.apply(this, arguments), - name = res.prototype._class; - if (name && !Base.exports[name]) - Base.exports[name] = res; - return res; - }, - - equals: function(obj1, obj2) { - if (obj1 === obj2) - return true; - if (obj1 && obj1.equals) - return obj1.equals(obj2); - if (obj2 && obj2.equals) - return obj2.equals(obj1); - if (obj1 && obj2 - && typeof obj1 === 'object' && typeof obj2 === 'object') { - if (Array.isArray(obj1) && Array.isArray(obj2)) { - var length = obj1.length; - if (length !== obj2.length) - return false; - while (length--) { - if (!Base.equals(obj1[length], obj2[length])) - return false; - } - } else { - var keys = Object.keys(obj1), - length = keys.length; - if (length !== Object.keys(obj2).length) - return false; - while (length--) { - var key = keys[length]; - if (!(obj2.hasOwnProperty(key) - && Base.equals(obj1[key], obj2[key]))) - return false; - } - } - return true; - } - return false; - }, - - read: function(list, start, options, amount) { - if (this === Base) { - var value = this.peek(list, start); - list.__index++; - return value; - } - var proto = this.prototype, - readIndex = proto._readIndex, - begin = start || readIndex && list.__index || 0, - length = list.length, - obj = list[begin]; - amount = amount || length - begin; - if (obj instanceof this - || options && options.readNull && obj == null && amount <= 1) { - if (readIndex) - list.__index = begin + 1; - return obj && options && options.clone ? obj.clone() : obj; - } - obj = Base.create(proto); - if (readIndex) - obj.__read = true; - obj = obj.initialize.apply(obj, begin > 0 || begin + amount < length - ? Base.slice(list, begin, begin + amount) - : list) || obj; - if (readIndex) { - list.__index = begin + obj.__read; - var filtered = obj.__filtered; - if (filtered) { - list.__filtered = filtered; - obj.__filtered = undefined; - } - obj.__read = undefined; - } - return obj; - }, - - peek: function(list, start) { - return list[list.__index = start || list.__index || 0]; - }, - - remain: function(list) { - return list.length - (list.__index || 0); - }, - - readList: function(list, start, options, amount) { - var res = [], - entry, - begin = start || 0, - end = amount ? begin + amount : list.length; - for (var i = begin; i < end; i++) { - res.push(Array.isArray(entry = list[i]) - ? this.read(entry, 0, options) - : this.read(list, i, options, 1)); - } - return res; - }, - - readNamed: function(list, name, start, options, amount) { - var value = this.getNamed(list, name), - hasObject = value !== undefined; - if (hasObject) { - var filtered = list.__filtered; - if (!filtered) { - filtered = list.__filtered = Base.create(list[0]); - filtered.__unfiltered = list[0]; - } - filtered[name] = undefined; - } - var l = hasObject ? [value] : list, - res = this.read(l, start, options, amount); - return res; - }, - - getNamed: function(list, name) { - var arg = list[0]; - if (list._hasObject === undefined) - list._hasObject = list.length === 1 && Base.isPlainObject(arg); - if (list._hasObject) - return name ? arg[name] : list.__filtered || arg; - }, - - hasNamed: function(list, name) { - return !!this.getNamed(list, name); - }, - - filter: function(dest, source, exclude, prioritize) { - var processed; - - function handleKey(key) { - if (!(exclude && key in exclude) && - !(processed && key in processed)) { - var value = source[key]; - if (value !== undefined) - dest[key] = value; - } - } - - if (prioritize) { - var keys = {}; - for (var i = 0, key, l = prioritize.length; i < l; i++) { - if ((key = prioritize[i]) in source) { - handleKey(key); - keys[key] = true; - } - } - processed = keys; - } - - Object.keys(source.__unfiltered || source).forEach(handleKey); - return dest; - }, - - isPlainValue: function(obj, asString) { - return Base.isPlainObject(obj) || Array.isArray(obj) - || asString && typeof obj === 'string'; - }, - - serialize: function(obj, options, compact, dictionary) { - options = options || {}; - - var isRoot = !dictionary, - res; - if (isRoot) { - options.formatter = new Formatter(options.precision); - dictionary = { - length: 0, - definitions: {}, - references: {}, - add: function(item, create) { - var id = '#' + item._id, - ref = this.references[id]; - if (!ref) { - this.length++; - var res = create.call(item), - name = item._class; - if (name && res[0] !== name) - res.unshift(name); - this.definitions[id] = res; - ref = this.references[id] = [id]; - } - return ref; - } - }; - } - if (obj && obj._serialize) { - res = obj._serialize(options, dictionary); - var name = obj._class; - if (name && !obj._compactSerialize && (isRoot || !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); - } else if (Base.isPlainObject(obj)) { - res = {}; - var keys = Object.keys(obj); - for (var i = 0, l = keys.length; i < l; i++) { - var key = keys[i]; - res[key] = Base.serialize(obj[key], options, compact, - dictionary); - } - } else if (typeof obj === 'number') { - res = options.formatter.number(obj, options.precision); - } else { - res = obj; - } - return isRoot && dictionary.length > 0 - ? [['dictionary', dictionary.definitions], res] - : res; - }, - - deserialize: function(json, create, _data, _setDictionary, _isRoot) { - var res = json, - isFirst = !_data, - hasDictionary = isFirst && json && json.length - && json[0][0] === 'dictionary'; - _data = _data || {}; - if (Array.isArray(json)) { - var type = json[0], - isDictionary = type === 'dictionary'; - if (json.length == 1 && /^#/.test(type)) { - return _data.dictionary[type]; - } - type = Base.exports[type]; - res = []; - for (var i = type ? 1 : 0, l = json.length; i < l; i++) { - res.push(Base.deserialize(json[i], create, _data, - isDictionary, hasDictionary)); - } - if (type) { - var args = res; - if (create) { - res = create(type, args, isFirst || _isRoot); - } else { - res = new type(args); - } - } - } else if (Base.isPlainObject(json)) { - res = {}; - if (_setDictionary) - _data.dictionary = res; - for (var key in json) - res[key] = Base.deserialize(json[key], create, _data); - } - return hasDictionary ? res[1] : res; - }, - - exportJSON: function(obj, options) { - var json = Base.serialize(obj, options); - return options && options.asString == false - ? json - : JSON.stringify(json); - }, - - importJSON: function(json, target) { - return Base.deserialize( - typeof json === 'string' ? JSON.parse(json) : json, - function(ctor, args, isRoot) { - var useTarget = isRoot && target - && target.constructor === ctor, - obj = useTarget ? target - : Base.create(ctor.prototype); - if (args.length === 1 && obj instanceof Item - && (useTarget || !(obj instanceof Layer))) { - var arg = args[0]; - if (Base.isPlainObject(arg)) - arg.insert = false; - } - (useTarget ? obj.set : ctor).apply(obj, args); - if (useTarget) - target = null; - return obj; - }); - }, - - push: function(list, items) { - var itemsLength = items.length; - if (itemsLength < 4096) { - list.push.apply(list, items); - } else { - var startLength = list.length; - list.length += itemsLength; - for (var i = 0; i < itemsLength; i++) { - list[startLength + i] = items[i]; - } - } - return list; - }, - - splice: function(list, items, index, remove) { - var amount = items && items.length, - append = index === undefined; - index = append ? list.length : index; - if (index > list.length) - index = list.length; - for (var i = 0; i < amount; i++) - items[i]._index = index + i; - if (append) { - Base.push(list, items); - return []; - } else { - var args = [index, remove]; - if (items) - Base.push(args, items); - var removed = list.splice.apply(list, args); - for (var i = 0, l = removed.length; i < l; i++) - removed[i]._index = undefined; - for (var i = index + amount, l = list.length; i < l; i++) - list[i]._index = i; - return removed; - } - }, - - capitalize: function(str) { - return str.replace(/\b[a-z]/g, function(match) { - return match.toUpperCase(); - }); - }, - - camelize: function(str) { - return str.replace(/-(.)/g, function(match, chr) { - return chr.toUpperCase(); - }); - }, - - hyphenate: function(str) { - return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); - } -}}); - -var Emitter = { - on: function(type, func) { - if (typeof type !== 'string') { - Base.each(type, function(value, key) { - this.on(key, value); - }, this); - } else { - var types = this._eventTypes, - entry = types && types[type], - handlers = this._callbacks = this._callbacks || {}; - handlers = handlers[type] = handlers[type] || []; - if (handlers.indexOf(func) === -1) { - handlers.push(func); - if (entry && entry.install && handlers.length === 1) - entry.install.call(this, type); - } - } - return this; - }, - - off: function(type, func) { - if (typeof type !== 'string') { - Base.each(type, function(value, key) { - this.off(key, value); - }, this); - return; - } - var types = this._eventTypes, - entry = types && types[type], - handlers = this._callbacks && this._callbacks[type], - index; - if (handlers) { - if (!func || (index = handlers.indexOf(func)) !== -1 - && handlers.length === 1) { - if (entry && entry.uninstall) - entry.uninstall.call(this, type); - delete this._callbacks[type]; - } else if (index !== -1) { - handlers.splice(index, 1); - } - } - return this; - }, - - once: function(type, func) { - return this.on(type, function() { - func.apply(this, arguments); - this.off(type, func); - }); - }, - - emit: function(type, event) { - var handlers = this._callbacks && this._callbacks[type]; - if (!handlers) - return false; - var args = Base.slice(arguments, 1), - setTarget = event && event.target && !event.currentTarget; - handlers = handlers.slice(); - if (setTarget) - event.currentTarget = this; - for (var i = 0, l = handlers.length; i < l; i++) { - if (handlers[i].apply(this, args) == false) { - if (event && event.stop) - event.stop(); - break; - } - } - if (setTarget) - delete event.currentTarget; - return true; - }, - - responds: function(type) { - return !!(this._callbacks && this._callbacks[type]); - }, - - attach: '#on', - detach: '#off', - fire: '#emit', - - _installEvents: function(install) { - var types = this._eventTypes, - handlers = this._callbacks, - key = install ? 'install' : 'uninstall'; - if (types) { - for (var type in handlers) { - if (handlers[type].length > 0) { - var entry = types[type], - func = entry && entry[key]; - if (func) - func.call(this, type); - } - } - } - }, - - statics: { - inject: function inject(src) { - var events = src._events; - if (events) { - var types = {}; - Base.each(events, function(entry, key) { - var isString = typeof entry === 'string', - name = isString ? entry : key, - part = Base.capitalize(name), - type = name.substring(2).toLowerCase(); - types[type] = isString ? {} : entry; - name = '_' + name; - src['get' + part] = function() { - return this[name]; - }; - src['set' + part] = function(func) { - var prev = this[name]; - if (prev) - this.off(type, prev); - if (func) - this.on(type, func); - this[name] = func; - }; - }); - src._eventTypes = types; - } - return inject.base.apply(this, arguments); - } - } -}; - -var PaperScope = Base.extend({ - _class: 'PaperScope', - - initialize: function PaperScope() { - paper = this; - this.settings = new Base({ - applyMatrix: true, - insertItems: true, - handleSize: 4, - hitTolerance: 0 - }); - this.project = null; - this.projects = []; - this.tools = []; - this._id = PaperScope._id++; - PaperScope._scopes[this._id] = this; - var proto = PaperScope.prototype; - if (!this.support) { - var ctx = CanvasProvider.getContext(1, 1) || {}; - proto.support = { - nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx, - nativeBlendModes: BlendMode.nativeModes - }; - CanvasProvider.release(ctx); - } - if (!this.agent) { - var user = self.navigator.userAgent.toLowerCase(), - os = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0], - platform = os === 'darwin' ? 'mac' : os, - agent = proto.agent = proto.browser = { platform: platform }; - if (platform) - agent[platform] = true; - user.replace( - /(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\/?\s*([.\d]+)(?:.*version\/([.\d]+))?(?:.*rv\:v?([.\d]+))?/g, - function(match, n, v1, v2, rv) { - if (!agent.chrome) { - var v = n === 'opera' ? v2 : - /^(node|trident)$/.test(n) ? rv : v1; - agent.version = v; - agent.versionNumber = parseFloat(v); - n = n === 'trident' ? 'msie' : n; - agent.name = n; - agent[n] = true; - } - } - ); - if (agent.chrome) - delete agent.webkit; - if (agent.atom) - delete agent.chrome; - } - }, - - version: "0.11.8", - - getView: function() { - var project = this.project; - return project && project._view; - }, - - getPaper: function() { - return this; - }, - - execute: function(code, options) { - var exports = paper.PaperScript.execute(code, this, options); - View.updateFocus(); - return exports; - }, - - install: function(scope) { - var that = this; - Base.each(['project', 'view', 'tool'], function(key) { - Base.define(scope, key, { - configurable: true, - get: function() { - return that[key]; - } - }); - }); - for (var key in this) - if (!/^_/.test(key) && this[key]) - scope[key] = this[key]; - }, - - setup: function(element) { - paper = this; - this.project = new Project(element); - return this; - }, - - createCanvas: function(width, height) { - return CanvasProvider.getCanvas(width, height); - }, - - activate: function() { - paper = this; - }, - - clear: function() { - var projects = this.projects, - tools = this.tools; - for (var i = projects.length - 1; i >= 0; i--) - projects[i].remove(); - for (var i = tools.length - 1; i >= 0; i--) - tools[i].remove(); - }, - - remove: function() { - this.clear(); - delete PaperScope._scopes[this._id]; - }, - - statics: new function() { - function handleAttribute(name) { - name += 'Attribute'; - return function(el, attr) { - return el[name](attr) || el[name]('data-paper-' + attr); - }; - } - - return { - _scopes: {}, - _id: 0, - - get: function(id) { - return this._scopes[id] || null; - }, - - getAttribute: handleAttribute('get'), - hasAttribute: handleAttribute('has') - }; - } -}); - -var PaperScopeItem = Base.extend(Emitter, { - - initialize: function(activate) { - this._scope = paper; - this._index = this._scope[this._list].push(this) - 1; - if (activate || !this._scope[this._reference]) - this.activate(); - }, - - activate: function() { - if (!this._scope) - return false; - var prev = this._scope[this._reference]; - if (prev && prev !== this) - prev.emit('deactivate'); - this._scope[this._reference] = this; - this.emit('activate', prev); - return true; - }, - - isActive: function() { - return this._scope[this._reference] === this; - }, - - remove: function() { - if (this._index == null) - return false; - Base.splice(this._scope[this._list], null, this._index, 1); - if (this._scope[this._reference] == this) - this._scope[this._reference] = null; - this._scope = null; - return true; - }, - - getView: function() { - return this._scope.getView(); - } -}); - -var Formatter = Base.extend({ - initialize: function(precision) { - this.precision = Base.pick(precision, 5); - this.multiplier = Math.pow(10, this.precision); - }, - - number: function(val) { - return this.precision < 16 - ? Math.round(val * this.multiplier) / this.multiplier : val; - }, - - pair: function(val1, val2, separator) { - return this.number(val1) + (separator || ',') + this.number(val2); - }, - - point: function(val, separator) { - return this.number(val.x) + (separator || ',') + this.number(val.y); - }, - - size: function(val, separator) { - return this.number(val.width) + (separator || ',') - + this.number(val.height); - }, - - rectangle: function(val, separator) { - return this.point(val, separator) + (separator || ',') - + this.size(val, separator); - } -}); - -Formatter.instance = new Formatter(); - -var Numerical = new function() { - - var abscissas = [ - [ 0.5773502691896257645091488], - [0,0.7745966692414833770358531], - [ 0.3399810435848562648026658,0.8611363115940525752239465], - [0,0.5384693101056830910363144,0.9061798459386639927976269], - [ 0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016], - [0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897], - [ 0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609], - [0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762], - [ 0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640], - [0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380], - [ 0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491], - [0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294], - [ 0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973], - [0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657], - [ 0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542] - ]; - - var weights = [ - [1], - [0.8888888888888888888888889,0.5555555555555555555555556], - [0.6521451548625461426269361,0.3478548451374538573730639], - [0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640], - [0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961], - [0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114], - [0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314], - [0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922], - [0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688], - [0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537], - [0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160], - [0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216], - [0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329], - [0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284], - [0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806] - ]; - - var abs = Math.abs, - sqrt = Math.sqrt, - pow = Math.pow, - log2 = Math.log2 || function(x) { - return Math.log(x) * Math.LOG2E; - }, - EPSILON = 1e-12, - MACHINE_EPSILON = 1.12e-16; - - function clamp(value, min, max) { - return value < min ? min : value > max ? max : value; - } - - function getDiscriminant(a, b, c) { - function split(v) { - var x = v * 134217729, - y = v - x, - hi = y + x, - lo = v - hi; - return [hi, lo]; - } - - var D = b * b - a * c, - E = b * b + a * c; - if (abs(D) * 3 < E) { - var ad = split(a), - bd = split(b), - cd = split(c), - p = b * b, - dp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1], - q = a * c, - dq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0]) - + ad[1] * cd[1]; - D = (p - q) + (dp - dq); - } - return D; - } - - function getNormalizationFactor() { - var norm = Math.max.apply(Math, arguments); - return norm && (norm < 1e-8 || norm > 1e8) - ? pow(2, -Math.round(log2(norm))) - : 0; - } - - return { - EPSILON: EPSILON, - MACHINE_EPSILON: MACHINE_EPSILON, - CURVETIME_EPSILON: 1e-8, - GEOMETRIC_EPSILON: 1e-7, - TRIGONOMETRIC_EPSILON: 1e-8, - KAPPA: 4 * (sqrt(2) - 1) / 3, - - isZero: function(val) { - return val >= -EPSILON && val <= EPSILON; - }, - - clamp: clamp, - - integrate: function(f, a, b, n) { - var x = abscissas[n - 2], - w = weights[n - 2], - A = (b - a) * 0.5, - B = A + a, - i = 0, - m = (n + 1) >> 1, - sum = n & 1 ? w[i++] * f(B) : 0; - while (i < m) { - var Ax = A * x[i]; - sum += w[i++] * (f(B + Ax) + f(B - Ax)); - } - return A * sum; - }, - - findRoot: function(f, df, x, a, b, n, tolerance) { - for (var i = 0; i < n; i++) { - var fx = f(x), - dx = fx / df(x), - nx = x - dx; - if (abs(dx) < tolerance) { - x = nx; - break; - } - if (fx > 0) { - b = x; - x = nx <= a ? (a + b) * 0.5 : nx; - } else { - a = x; - x = nx >= b ? (a + b) * 0.5 : nx; - } - } - return clamp(x, a, b); - }, - - solveQuadratic: function(a, b, c, roots, min, max) { - var x1, x2 = Infinity; - if (abs(a) < EPSILON) { - if (abs(b) < EPSILON) - return abs(c) < EPSILON ? -1 : 0; - x1 = -c / b; - } else { - b *= -0.5; - var D = getDiscriminant(a, b, c); - if (D && abs(D) < MACHINE_EPSILON) { - var f = getNormalizationFactor(abs(a), abs(b), abs(c)); - if (f) { - a *= f; - b *= f; - c *= f; - D = getDiscriminant(a, b, c); - } - } - if (D >= -MACHINE_EPSILON) { - var Q = D < 0 ? 0 : sqrt(D), - R = b + (b < 0 ? -Q : Q); - if (R === 0) { - x1 = c / a; - x2 = -x1; - } else { - x1 = R / a; - x2 = c / R; - } - } - } - var count = 0, - boundless = min == null, - minB = min - EPSILON, - maxB = max + EPSILON; - if (isFinite(x1) && (boundless || x1 > minB && x1 < maxB)) - roots[count++] = boundless ? x1 : clamp(x1, min, max); - if (x2 !== x1 - && isFinite(x2) && (boundless || x2 > minB && x2 < maxB)) - roots[count++] = boundless ? x2 : clamp(x2, min, max); - return count; - }, - - solveCubic: function(a, b, c, d, roots, min, max) { - var f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)), - x, b1, c2, qd, q; - if (f) { - a *= f; - b *= f; - c *= f; - d *= f; - } - - function evaluate(x0) { - x = x0; - var tmp = a * x; - b1 = tmp + b; - c2 = b1 * x + c; - qd = (tmp + b1) * x + c2; - q = c2 * x + d; - } - - if (abs(a) < EPSILON) { - a = b; - b1 = c; - c2 = d; - x = Infinity; - } else if (abs(d) < EPSILON) { - b1 = b; - c2 = c; - x = 0; - } else { - evaluate(-(b / a) / 3); - var t = q / a, - r = pow(abs(t), 1/3), - s = t < 0 ? -1 : 1, - td = -qd / a, - rd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r, - x0 = x - s * rd; - if (x0 !== x) { - do { - evaluate(x0); - x0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON); - } while (s * x0 > s * x); - if (abs(a) * x * x > abs(d / x)) { - c2 = -d / x; - b1 = (c2 - c) / x; - } - } - } - var count = Numerical.solveQuadratic(a, b1, c2, roots, min, max), - boundless = min == null; - if (isFinite(x) && (count === 0 - || count > 0 && x !== roots[0] && x !== roots[1]) - && (boundless || x > min - EPSILON && x < max + EPSILON)) - roots[count++] = boundless ? x : clamp(x, min, max); - return count; - } - }; -}; - -var UID = { - _id: 1, - _pools: {}, - - get: function(name) { - if (name) { - var pool = this._pools[name]; - if (!pool) - pool = this._pools[name] = { _id: 1 }; - return pool._id++; - } else { - return this._id++; - } - } -}; - -var Point = Base.extend({ - _class: 'Point', - _readIndex: true, - - initialize: function Point(arg0, arg1) { - var type = typeof arg0, - reading = this.__read, - read = 0; - if (type === 'number') { - var hasY = typeof arg1 === 'number'; - this._set(arg0, hasY ? arg1 : arg0); - if (reading) - read = hasY ? 2 : 1; - } else if (type === 'undefined' || arg0 === null) { - this._set(0, 0); - if (reading) - read = arg0 === null ? 1 : 0; - } else { - var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0; - read = 1; - if (Array.isArray(obj)) { - this._set(+obj[0], +(obj.length > 1 ? obj[1] : obj[0])); - } else if ('x' in obj) { - this._set(obj.x || 0, obj.y || 0); - } else if ('width' in obj) { - this._set(obj.width || 0, obj.height || 0); - } else if ('angle' in obj) { - this._set(obj.length || 0, 0); - this.setAngle(obj.angle || 0); - } else { - this._set(0, 0); - read = 0; - } - } - if (reading) - this.__read = read; - return this; - }, - - set: '#initialize', - - _set: function(x, y) { - this.x = x; - this.y = y; - return this; - }, - - equals: function(point) { - return this === point || point - && (this.x === point.x && this.y === point.y - || Array.isArray(point) - && this.x === point[0] && this.y === point[1]) - || false; - }, - - clone: function() { - return new Point(this.x, this.y); - }, - - toString: function() { - var f = Formatter.instance; - return '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }'; - }, - - _serialize: function(options) { - var f = options.formatter; - return [f.number(this.x), f.number(this.y)]; - }, - - getLength: function() { - return Math.sqrt(this.x * this.x + this.y * this.y); - }, - - setLength: function(length) { - if (this.isZero()) { - var angle = this._angle || 0; - this._set( - Math.cos(angle) * length, - Math.sin(angle) * length - ); - } else { - var scale = length / this.getLength(); - if (Numerical.isZero(scale)) - this.getAngle(); - this._set( - this.x * scale, - this.y * scale - ); - } - }, - getAngle: function() { - return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI; - }, - - setAngle: function(angle) { - this.setAngleInRadians.call(this, angle * Math.PI / 180); - }, - - getAngleInDegrees: '#getAngle', - setAngleInDegrees: '#setAngle', - - getAngleInRadians: function() { - if (!arguments.length) { - return this.isZero() - ? this._angle || 0 - : this._angle = Math.atan2(this.y, this.x); - } else { - var point = Point.read(arguments), - div = this.getLength() * point.getLength(); - if (Numerical.isZero(div)) { - return NaN; - } else { - var a = this.dot(point) / div; - return Math.acos(a < -1 ? -1 : a > 1 ? 1 : a); - } - } - }, - - setAngleInRadians: function(angle) { - this._angle = angle; - if (!this.isZero()) { - var length = this.getLength(); - this._set( - Math.cos(angle) * length, - Math.sin(angle) * length - ); - } - }, - - getQuadrant: function() { - return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3; - } -}, { - beans: false, - - getDirectedAngle: function() { - var point = Point.read(arguments); - return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI; - }, - - getDistance: function() { - var point = Point.read(arguments), - x = point.x - this.x, - y = point.y - this.y, - d = x * x + y * y, - squared = Base.read(arguments); - return squared ? d : Math.sqrt(d); - }, - - normalize: function(length) { - if (length === undefined) - length = 1; - var current = this.getLength(), - scale = current !== 0 ? length / current : 0, - point = new Point(this.x * scale, this.y * scale); - if (scale >= 0) - point._angle = this._angle; - return point; - }, - - rotate: function(angle, center) { - if (angle === 0) - return this.clone(); - angle = angle * Math.PI / 180; - var point = center ? this.subtract(center) : this, - sin = Math.sin(angle), - cos = Math.cos(angle); - point = new Point( - point.x * cos - point.y * sin, - point.x * sin + point.y * cos - ); - return center ? point.add(center) : point; - }, - - transform: function(matrix) { - return matrix ? matrix._transformPoint(this) : this; - }, - - add: function() { - var point = Point.read(arguments); - return new Point(this.x + point.x, this.y + point.y); - }, - - subtract: function() { - var point = Point.read(arguments); - return new Point(this.x - point.x, this.y - point.y); - }, - - multiply: function() { - var point = Point.read(arguments); - return new Point(this.x * point.x, this.y * point.y); - }, - - divide: function() { - var point = Point.read(arguments); - return new Point(this.x / point.x, this.y / point.y); - }, - - modulo: function() { - var point = Point.read(arguments); - return new Point(this.x % point.x, this.y % point.y); - }, - - negate: function() { - return new Point(-this.x, -this.y); - }, - - isInside: function() { - return Rectangle.read(arguments).contains(this); - }, - - isClose: function() { - var point = Point.read(arguments), - tolerance = Base.read(arguments); - return this.getDistance(point) <= tolerance; - }, - - isCollinear: function() { - var point = Point.read(arguments); - return Point.isCollinear(this.x, this.y, point.x, point.y); - }, - - isColinear: '#isCollinear', - - isOrthogonal: function() { - var point = Point.read(arguments); - return Point.isOrthogonal(this.x, this.y, point.x, point.y); - }, - - isZero: function() { - var isZero = Numerical.isZero; - return isZero(this.x) && isZero(this.y); - }, - - isNaN: function() { - return isNaN(this.x) || isNaN(this.y); - }, - - isInQuadrant: function(q) { - return this.x * (q > 1 && q < 4 ? -1 : 1) >= 0 - && this.y * (q > 2 ? -1 : 1) >= 0; - }, - - dot: function() { - var point = Point.read(arguments); - return this.x * point.x + this.y * point.y; - }, - - cross: function() { - var point = Point.read(arguments); - return this.x * point.y - this.y * point.x; - }, - - project: function() { - var point = Point.read(arguments), - scale = point.isZero() ? 0 : this.dot(point) / point.dot(point); - return new Point( - point.x * scale, - point.y * scale - ); - }, - - statics: { - min: function() { - var point1 = Point.read(arguments), - point2 = Point.read(arguments); - return new Point( - Math.min(point1.x, point2.x), - Math.min(point1.y, point2.y) - ); - }, - - max: function() { - var point1 = Point.read(arguments), - point2 = Point.read(arguments); - return new Point( - Math.max(point1.x, point2.x), - Math.max(point1.y, point2.y) - ); - }, - - random: function() { - return new Point(Math.random(), Math.random()); - }, - - isCollinear: function(x1, y1, x2, y2) { - return Math.abs(x1 * y2 - y1 * x2) - <= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2)) - * 1e-8; - }, - - isOrthogonal: function(x1, y1, x2, y2) { - return Math.abs(x1 * x2 + y1 * y2) - <= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2)) - * 1e-8; - } - } -}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) { - var op = Math[key]; - this[key] = function() { - return new Point(op(this.x), op(this.y)); - }; -}, {})); - -var LinkedPoint = Point.extend({ - initialize: function Point(x, y, owner, setter) { - this._x = x; - this._y = y; - this._owner = owner; - this._setter = setter; - }, - - _set: function(x, y, _dontNotify) { - this._x = x; - this._y = y; - if (!_dontNotify) - this._owner[this._setter](this); - return this; - }, - - getX: function() { - return this._x; - }, - - setX: function(x) { - this._x = x; - this._owner[this._setter](this); - }, - - getY: function() { - return this._y; - }, - - setY: function(y) { - this._y = y; - this._owner[this._setter](this); - }, - - isSelected: function() { - return !!(this._owner._selection & this._getSelection()); - }, - - setSelected: function(selected) { - this._owner._changeSelection(this._getSelection(), selected); - }, - - _getSelection: function() { - return this._setter === 'setPosition' ? 4 : 0; - } -}); - -var Size = Base.extend({ - _class: 'Size', - _readIndex: true, - - initialize: function Size(arg0, arg1) { - var type = typeof arg0, - reading = this.__read, - read = 0; - if (type === 'number') { - var hasHeight = typeof arg1 === 'number'; - this._set(arg0, hasHeight ? arg1 : arg0); - if (reading) - read = hasHeight ? 2 : 1; - } else if (type === 'undefined' || arg0 === null) { - this._set(0, 0); - if (reading) - read = arg0 === null ? 1 : 0; - } else { - var obj = type === 'string' ? arg0.split(/[\s,]+/) || [] : arg0; - read = 1; - if (Array.isArray(obj)) { - this._set(+obj[0], +(obj.length > 1 ? obj[1] : obj[0])); - } else if ('width' in obj) { - this._set(obj.width || 0, obj.height || 0); - } else if ('x' in obj) { - this._set(obj.x || 0, obj.y || 0); - } else { - this._set(0, 0); - read = 0; - } - } - if (reading) - this.__read = read; - return this; - }, - - set: '#initialize', - - _set: function(width, height) { - this.width = width; - this.height = height; - return this; - }, - - equals: function(size) { - return size === this || size && (this.width === size.width - && this.height === size.height - || Array.isArray(size) && this.width === size[0] - && this.height === size[1]) || false; - }, - - clone: function() { - return new Size(this.width, this.height); - }, - - toString: function() { - var f = Formatter.instance; - return '{ width: ' + f.number(this.width) - + ', height: ' + f.number(this.height) + ' }'; - }, - - _serialize: function(options) { - var f = options.formatter; - return [f.number(this.width), - f.number(this.height)]; - }, - - add: function() { - var size = Size.read(arguments); - return new Size(this.width + size.width, this.height + size.height); - }, - - subtract: function() { - var size = Size.read(arguments); - return new Size(this.width - size.width, this.height - size.height); - }, - - multiply: function() { - var size = Size.read(arguments); - return new Size(this.width * size.width, this.height * size.height); - }, - - divide: function() { - var size = Size.read(arguments); - return new Size(this.width / size.width, this.height / size.height); - }, - - modulo: function() { - var size = Size.read(arguments); - return new Size(this.width % size.width, this.height % size.height); - }, - - negate: function() { - return new Size(-this.width, -this.height); - }, - - isZero: function() { - var isZero = Numerical.isZero; - return isZero(this.width) && isZero(this.height); - }, - - isNaN: function() { - return isNaN(this.width) || isNaN(this.height); - }, - - statics: { - min: function(size1, size2) { - return new Size( - Math.min(size1.width, size2.width), - Math.min(size1.height, size2.height)); - }, - - max: function(size1, size2) { - return new Size( - Math.max(size1.width, size2.width), - Math.max(size1.height, size2.height)); - }, - - random: function() { - return new Size(Math.random(), Math.random()); - } - } -}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) { - var op = Math[key]; - this[key] = function() { - return new Size(op(this.width), op(this.height)); - }; -}, {})); - -var LinkedSize = Size.extend({ - initialize: function Size(width, height, owner, setter) { - this._width = width; - this._height = height; - this._owner = owner; - this._setter = setter; - }, - - _set: function(width, height, _dontNotify) { - this._width = width; - this._height = height; - if (!_dontNotify) - this._owner[this._setter](this); - return this; - }, - - getWidth: function() { - return this._width; - }, - - setWidth: function(width) { - this._width = width; - this._owner[this._setter](this); - }, - - getHeight: function() { - return this._height; - }, - - setHeight: function(height) { - this._height = height; - this._owner[this._setter](this); - } -}); - -var Rectangle = Base.extend({ - _class: 'Rectangle', - _readIndex: true, - beans: true, - - initialize: function Rectangle(arg0, arg1, arg2, arg3) { - var type = typeof arg0, - read; - if (type === 'number') { - this._set(arg0, arg1, arg2, arg3); - read = 4; - } else if (type === 'undefined' || arg0 === null) { - this._set(0, 0, 0, 0); - read = arg0 === null ? 1 : 0; - } else if (arguments.length === 1) { - if (Array.isArray(arg0)) { - this._set.apply(this, arg0); - read = 1; - } else if (arg0.x !== undefined || arg0.width !== undefined) { - this._set(arg0.x || 0, arg0.y || 0, - arg0.width || 0, arg0.height || 0); - read = 1; - } else if (arg0.from === undefined && arg0.to === undefined) { - this._set(0, 0, 0, 0); - Base.filter(this, arg0); - read = 1; - } - } - if (read === undefined) { - var frm = Point.readNamed(arguments, 'from'), - next = Base.peek(arguments), - x = frm.x, - y = frm.y, - width, - height; - if (next && next.x !== undefined - || Base.hasNamed(arguments, 'to')) { - var to = Point.readNamed(arguments, 'to'); - width = to.x - x; - height = to.y - y; - if (width < 0) { - x = to.x; - width = -width; - } - if (height < 0) { - y = to.y; - height = -height; - } - } else { - var size = Size.read(arguments); - width = size.width; - height = size.height; - } - this._set(x, y, width, height); - read = arguments.__index; - var filtered = arguments.__filtered; - if (filtered) - this.__filtered = filtered; - } - if (this.__read) - this.__read = read; - return this; - }, - - set: '#initialize', - - _set: function(x, y, width, height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - return this; - }, - - clone: function() { - return new Rectangle(this.x, this.y, this.width, this.height); - }, - - equals: function(rect) { - var rt = Base.isPlainValue(rect) - ? Rectangle.read(arguments) - : rect; - return rt === this - || rt && this.x === rt.x && this.y === rt.y - && this.width === rt.width && this.height === rt.height - || false; - }, - - toString: function() { - var f = Formatter.instance; - return '{ x: ' + f.number(this.x) - + ', y: ' + f.number(this.y) - + ', width: ' + f.number(this.width) - + ', height: ' + f.number(this.height) - + ' }'; - }, - - _serialize: function(options) { - var f = options.formatter; - return [f.number(this.x), - f.number(this.y), - f.number(this.width), - f.number(this.height)]; - }, - - getPoint: function(_dontLink) { - var ctor = _dontLink ? Point : LinkedPoint; - return new ctor(this.x, this.y, this, 'setPoint'); - }, - - setPoint: function() { - var point = Point.read(arguments); - this.x = point.x; - this.y = point.y; - }, - - getSize: function(_dontLink) { - var ctor = _dontLink ? Size : LinkedSize; - return new ctor(this.width, this.height, this, 'setSize'); - }, - - _fw: 1, - _fh: 1, - - setSize: function() { - var size = Size.read(arguments), - sx = this._sx, - sy = this._sy, - w = size.width, - h = size.height; - if (sx) { - this.x += (this.width - w) * sx; - } - if (sy) { - this.y += (this.height - h) * sy; - } - this.width = w; - this.height = h; - this._fw = this._fh = 1; - }, - - getLeft: function() { - return this.x; - }, - - setLeft: function(left) { - if (!this._fw) { - var amount = left - this.x; - this.width -= this._sx === 0.5 ? amount * 2 : amount; - } - this.x = left; - this._sx = this._fw = 0; - }, - - getTop: function() { - return this.y; - }, - - setTop: function(top) { - if (!this._fh) { - var amount = top - this.y; - this.height -= this._sy === 0.5 ? amount * 2 : amount; - } - this.y = top; - this._sy = this._fh = 0; - }, - - getRight: function() { - return this.x + this.width; - }, - - setRight: function(right) { - if (!this._fw) { - var amount = right - this.x; - this.width = this._sx === 0.5 ? amount * 2 : amount; - } - this.x = right - this.width; - this._sx = 1; - this._fw = 0; - }, - - getBottom: function() { - return this.y + this.height; - }, - - setBottom: function(bottom) { - if (!this._fh) { - var amount = bottom - this.y; - this.height = this._sy === 0.5 ? amount * 2 : amount; - } - this.y = bottom - this.height; - this._sy = 1; - this._fh = 0; - }, - - getCenterX: function() { - return this.x + this.width / 2; - }, - - setCenterX: function(x) { - if (this._fw || this._sx === 0.5) { - this.x = x - this.width / 2; - } else { - if (this._sx) { - this.x += (x - this.x) * 2 * this._sx; - } - this.width = (x - this.x) * 2; - } - this._sx = 0.5; - this._fw = 0; - }, - - getCenterY: function() { - return this.y + this.height / 2; - }, - - setCenterY: function(y) { - if (this._fh || this._sy === 0.5) { - this.y = y - this.height / 2; - } else { - if (this._sy) { - this.y += (y - this.y) * 2 * this._sy; - } - this.height = (y - this.y) * 2; - } - this._sy = 0.5; - this._fh = 0; - }, - - getCenter: function(_dontLink) { - var ctor = _dontLink ? Point : LinkedPoint; - return new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter'); - }, - - setCenter: function() { - var point = Point.read(arguments); - this.setCenterX(point.x); - this.setCenterY(point.y); - return this; - }, - - getArea: function() { - return this.width * this.height; - }, - - isEmpty: function() { - return this.width === 0 || this.height === 0; - }, - - contains: function(arg) { - return arg && arg.width !== undefined - || (Array.isArray(arg) ? arg : arguments).length === 4 - ? this._containsRectangle(Rectangle.read(arguments)) - : this._containsPoint(Point.read(arguments)); - }, - - _containsPoint: function(point) { - var x = point.x, - y = point.y; - return x >= this.x && y >= this.y - && x <= this.x + this.width - && y <= this.y + this.height; - }, - - _containsRectangle: function(rect) { - var x = rect.x, - y = rect.y; - return x >= this.x && y >= this.y - && x + rect.width <= this.x + this.width - && y + rect.height <= this.y + this.height; - }, - - intersects: function() { - var rect = Rectangle.read(arguments), - epsilon = Base.read(arguments) || 0; - return rect.x + rect.width > this.x - epsilon - && rect.y + rect.height > this.y - epsilon - && rect.x < this.x + this.width + epsilon - && rect.y < this.y + this.height + epsilon; - }, - - intersect: function() { - var rect = Rectangle.read(arguments), - x1 = Math.max(this.x, rect.x), - 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 new Rectangle(x1, y1, x2 - x1, y2 - y1); - }, - - unite: function() { - var rect = Rectangle.read(arguments), - x1 = Math.min(this.x, rect.x), - 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 new Rectangle(x1, y1, x2 - x1, y2 - y1); - }, - - include: function() { - var point = Point.read(arguments); - var x1 = Math.min(this.x, point.x), - 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 new Rectangle(x1, y1, x2 - x1, y2 - y1); - }, - - expand: function() { - var amount = Size.read(arguments), - hor = amount.width, - ver = amount.height; - return new Rectangle(this.x - hor / 2, this.y - ver / 2, - this.width + hor, this.height + ver); - }, - - scale: function(hor, ver) { - return this.expand(this.width * hor - this.width, - this.height * (ver === undefined ? hor : ver) - this.height); - } -}, Base.each([ - ['Top', 'Left'], ['Top', 'Right'], - ['Bottom', 'Left'], ['Bottom', 'Right'], - ['Left', 'Center'], ['Top', 'Center'], - ['Right', 'Center'], ['Bottom', 'Center'] - ], - function(parts, index) { - var part = parts.join(''), - xFirst = /^[RL]/.test(part); - if (index >= 4) - parts[1] += xFirst ? 'Y' : 'X'; - var x = parts[xFirst ? 0 : 1], - y = parts[xFirst ? 1 : 0], - getX = 'get' + x, - getY = 'get' + y, - setX = 'set' + x, - setY = 'set' + y, - get = 'get' + part, - set = 'set' + part; - this[get] = function(_dontLink) { - var ctor = _dontLink ? Point : LinkedPoint; - return new ctor(this[getX](), this[getY](), this, set); - }; - this[set] = function() { - var point = Point.read(arguments); - this[setX](point.x); - this[setY](point.y); - }; - }, { - beans: true - } -)); - -var LinkedRectangle = Rectangle.extend({ - initialize: function Rectangle(x, y, width, height, owner, setter) { - this._set(x, y, width, height, true); - this._owner = owner; - this._setter = setter; - }, - - _set: function(x, y, width, height, _dontNotify) { - this._x = x; - this._y = y; - this._width = width; - this._height = height; - if (!_dontNotify) - this._owner[this._setter](this); - return this; - } -}, -new function() { - var proto = Rectangle.prototype; - - return Base.each(['x', 'y', 'width', 'height'], function(key) { - var part = Base.capitalize(key), - internal = '_' + key; - this['get' + part] = function() { - return this[internal]; - }; - - this['set' + part] = function(value) { - this[internal] = value; - if (!this._dontNotify) - this._owner[this._setter](this); - }; - }, Base.each(['Point', 'Size', 'Center', - 'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY', - 'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight', - 'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'], - function(key) { - var name = 'set' + key; - this[name] = function() { - this._dontNotify = true; - proto[name].apply(this, arguments); - this._dontNotify = false; - this._owner[this._setter](this); - }; - }, { - isSelected: function() { - return !!(this._owner._selection & 2); - }, - - setSelected: function(selected) { - var owner = this._owner; - if (owner._changeSelection) { - owner._changeSelection(2, selected); - } - } - }) - ); -}); - -var Matrix = Base.extend({ - _class: 'Matrix', - - initialize: function Matrix(arg, _dontNotify) { - var count = arguments.length, - ok = true; - if (count >= 6) { - this._set.apply(this, arguments); - } else if (count === 1 || count === 2) { - if (arg instanceof Matrix) { - this._set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty, - _dontNotify); - } else if (Array.isArray(arg)) { - this._set.apply(this, - _dontNotify ? arg.concat([_dontNotify]) : arg); - } else { - ok = false; - } - } else if (!count) { - this.reset(); - } else { - ok = false; - } - if (!ok) { - throw new Error('Unsupported matrix parameters'); - } - return this; - }, - - set: '#initialize', - - _set: function(a, b, c, d, tx, ty, _dontNotify) { - this._a = a; - this._b = b; - this._c = c; - this._d = d; - this._tx = tx; - this._ty = ty; - if (!_dontNotify) - this._changed(); - return this; - }, - - _serialize: function(options, dictionary) { - return Base.serialize(this.getValues(), options, true, dictionary); - }, - - _changed: function() { - var owner = this._owner; - if (owner) { - if (owner._applyMatrix) { - owner.transform(null, true); - } else { - owner._changed(25); - } - } - }, - - clone: function() { - return new Matrix(this._a, this._b, this._c, this._d, - this._tx, this._ty); - }, - - equals: function(mx) { - return mx === this || mx && this._a === mx._a && this._b === mx._b - && this._c === mx._c && this._d === mx._d - && this._tx === mx._tx && this._ty === mx._ty; - }, - - toString: function() { - var f = Formatter.instance; - return '[[' + [f.number(this._a), f.number(this._c), - f.number(this._tx)].join(', ') + '], [' - + [f.number(this._b), f.number(this._d), - f.number(this._ty)].join(', ') + ']]'; - }, - - reset: function(_dontNotify) { - this._a = this._d = 1; - this._b = this._c = this._tx = this._ty = 0; - if (!_dontNotify) - this._changed(); - return this; - }, - - apply: function(recursively, _setApplyMatrix) { - var owner = this._owner; - if (owner) { - owner.transform(null, true, Base.pick(recursively, true), - _setApplyMatrix); - return this.isIdentity(); - } - return false; - }, - - translate: function() { - var point = Point.read(arguments), - x = point.x, - y = point.y; - this._tx += x * this._a + y * this._c; - this._ty += x * this._b + y * this._d; - this._changed(); - return this; - }, - - scale: function() { - var scale = Point.read(arguments), - center = Point.read(arguments, 0, { readNull: true }); - if (center) - this.translate(center); - this._a *= scale.x; - this._b *= scale.x; - this._c *= scale.y; - this._d *= scale.y; - if (center) - this.translate(center.negate()); - this._changed(); - return this; - }, - - rotate: function(angle ) { - angle *= Math.PI / 180; - var center = Point.read(arguments, 1), - x = center.x, - y = center.y, - cos = Math.cos(angle), - sin = Math.sin(angle), - tx = x - x * cos + y * sin, - ty = y - x * sin - y * cos, - a = this._a, - b = this._b, - c = this._c, - d = this._d; - this._a = cos * a + sin * c; - this._b = cos * b + sin * d; - this._c = -sin * a + cos * c; - this._d = -sin * b + cos * d; - this._tx += tx * a + ty * c; - this._ty += tx * b + ty * d; - this._changed(); - return this; - }, - - shear: function() { - var shear = Point.read(arguments), - center = Point.read(arguments, 0, { readNull: true }); - if (center) - this.translate(center); - var a = this._a, - b = this._b; - this._a += shear.y * this._c; - this._b += shear.y * this._d; - this._c += shear.x * a; - this._d += shear.x * b; - if (center) - this.translate(center.negate()); - this._changed(); - return this; - }, - - skew: function() { - var skew = Point.read(arguments), - center = Point.read(arguments, 0, { readNull: true }), - toRadians = Math.PI / 180, - shear = new Point(Math.tan(skew.x * toRadians), - Math.tan(skew.y * toRadians)); - return this.shear(shear, center); - }, - - append: function(mx, _dontNotify) { - if (mx) { - var a1 = this._a, - b1 = this._b, - c1 = this._c, - d1 = this._d, - a2 = mx._a, - b2 = mx._c, - c2 = mx._b, - d2 = mx._d, - tx2 = mx._tx, - ty2 = mx._ty; - this._a = a2 * a1 + c2 * c1; - this._c = b2 * a1 + d2 * c1; - this._b = a2 * b1 + c2 * d1; - this._d = b2 * b1 + d2 * d1; - this._tx += tx2 * a1 + ty2 * c1; - this._ty += tx2 * b1 + ty2 * d1; - if (!_dontNotify) - this._changed(); - } - return this; - }, - - prepend: function(mx, _dontNotify) { - if (mx) { - var a1 = this._a, - b1 = this._b, - c1 = this._c, - d1 = this._d, - tx1 = this._tx, - ty1 = this._ty, - a2 = mx._a, - b2 = mx._c, - c2 = mx._b, - d2 = mx._d, - tx2 = mx._tx, - ty2 = mx._ty; - this._a = a2 * a1 + b2 * b1; - this._c = a2 * c1 + b2 * d1; - this._b = c2 * a1 + d2 * b1; - this._d = c2 * c1 + d2 * d1; - this._tx = a2 * tx1 + b2 * ty1 + tx2; - this._ty = c2 * tx1 + d2 * ty1 + ty2; - if (!_dontNotify) - this._changed(); - } - return this; - }, - - appended: function(mx) { - return this.clone().append(mx); - }, - - prepended: function(mx) { - return this.clone().prepend(mx); - }, - - invert: function() { - var a = this._a, - b = this._b, - c = this._c, - d = this._d, - tx = this._tx, - ty = this._ty, - det = a * d - b * c, - res = null; - if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) { - this._a = d / det; - this._b = -b / det; - this._c = -c / det; - this._d = a / det; - this._tx = (c * ty - d * tx) / det; - this._ty = (b * tx - a * ty) / det; - res = this; - } - return res; - }, - - inverted: function() { - return this.clone().invert(); - }, - - concatenate: '#append', - preConcatenate: '#prepend', - chain: '#appended', - - _shiftless: function() { - return new Matrix(this._a, this._b, this._c, this._d, 0, 0); - }, - - _orNullIfIdentity: function() { - return this.isIdentity() ? null : this; - }, - - isIdentity: function() { - return this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1 - && this._tx === 0 && this._ty === 0; - }, - - isInvertible: function() { - var det = this._a * this._d - this._c * this._b; - return det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty); - }, - - isSingular: function() { - return !this.isInvertible(); - }, - - transform: function( src, dst, count) { - return arguments.length < 3 - ? this._transformPoint(Point.read(arguments)) - : this._transformCoordinates(src, dst, count); - }, - - _transformPoint: function(point, dest, _dontNotify) { - var x = point.x, - y = point.y; - if (!dest) - dest = new Point(); - return dest._set( - x * this._a + y * this._c + this._tx, - x * this._b + y * this._d + this._ty, - _dontNotify); - }, - - _transformCoordinates: function(src, dst, count) { - for (var i = 0, max = 2 * count; i < max; i += 2) { - var x = src[i], - y = src[i + 1]; - dst[i] = x * this._a + y * this._c + this._tx; - dst[i + 1] = x * this._b + y * this._d + this._ty; - } - return dst; - }, - - _transformCorners: function(rect) { - var x1 = rect.x, - y1 = rect.y, - x2 = x1 + rect.width, - y2 = y1 + rect.height, - coords = [ x1, y1, x2, y1, x2, y2, x1, y2 ]; - return this._transformCoordinates(coords, coords, 4); - }, - - _transformBounds: function(bounds, dest, _dontNotify) { - var coords = this._transformCorners(bounds), - min = coords.slice(0, 2), - max = min.slice(); - for (var i = 2; i < 8; i++) { - var val = coords[i], - j = i & 1; - if (val < min[j]) { - min[j] = val; - } else if (val > max[j]) { - max[j] = val; - } - } - if (!dest) - dest = new Rectangle(); - return dest._set(min[0], min[1], max[0] - min[0], max[1] - min[1], - _dontNotify); - }, - - inverseTransform: function() { - return this._inverseTransform(Point.read(arguments)); - }, - - _inverseTransform: function(point, dest, _dontNotify) { - var a = this._a, - b = this._b, - c = this._c, - d = this._d, - tx = this._tx, - ty = this._ty, - det = a * d - b * c, - res = null; - if (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) { - var x = point.x - this._tx, - y = point.y - this._ty; - if (!dest) - dest = new Point(); - res = dest._set( - (x * d - y * c) / det, - (y * a - x * b) / det, - _dontNotify); - } - return res; - }, - - decompose: function() { - var a = this._a, - b = this._b, - c = this._c, - d = this._d, - det = a * d - b * c, - sqrt = Math.sqrt, - atan2 = Math.atan2, - degrees = 180 / Math.PI, - rotate, - scale, - skew; - if (a !== 0 || b !== 0) { - var r = sqrt(a * a + b * b); - rotate = Math.acos(a / r) * (b > 0 ? 1 : -1); - scale = [r, det / r]; - skew = [atan2(a * c + b * d, r * r), 0]; - } else if (c !== 0 || d !== 0) { - var s = sqrt(c * c + d * d); - rotate = Math.asin(c / s) * (d > 0 ? 1 : -1); - scale = [det / s, s]; - skew = [0, atan2(a * c + b * d, s * s)]; - } else { - rotate = 0; - skew = scale = [0, 0]; - } - return { - translation: this.getTranslation(), - rotation: rotate * degrees, - scaling: new Point(scale), - skewing: new Point(skew[0] * degrees, skew[1] * degrees) - }; - }, - - getValues: function() { - return [ this._a, this._b, this._c, this._d, this._tx, this._ty ]; - }, - - getTranslation: function() { - return new Point(this._tx, this._ty); - }, - - getScaling: function() { - return (this.decompose() || {}).scaling; - }, - - getRotation: function() { - return (this.decompose() || {}).rotation; - }, - - applyToContext: function(ctx) { - if (!this.isIdentity()) { - ctx.transform(this._a, this._b, this._c, this._d, - this._tx, this._ty); - } - } -}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) { - var part = Base.capitalize(key), - prop = '_' + key; - this['get' + part] = function() { - return this[prop]; - }; - this['set' + part] = function(value) { - this[prop] = value; - this._changed(); - }; -}, {})); - -var Line = Base.extend({ - _class: 'Line', - - 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._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; - } - }, - - getPoint: function() { - return new Point(this._px, this._py); - }, - - getVector: function() { - return new Point(this._vx, this._vy); - }, - - getLength: function() { - return this.getVector().getLength(); - }, - - 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); - }, - - getSide: function(point, isInfinite) { - return Line.getSide( - this._px, this._py, this._vx, this._vy, - point.x, point.y, true, isInfinite); - }, - - getDistance: function(point) { - return Math.abs(this.getSignedDistance(point)); - }, - - getSignedDistance: function(point) { - return Line.getSignedDistance(this._px, this._py, this._vx, this._vy, - point.x, point.y, true); - }, - - isCollinear: function(line) { - return Point.isCollinear(this._vx, this._vy, line._vx, line._vy); - }, - - isOrthogonal: function(line) { - return Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy); - }, - - statics: { - intersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector, - isInfinite) { - if (!asVector) { - v1x -= p1x; - v1y -= p1y; - v2x -= p2x; - v2y -= p2y; - } - var cross = v1x * v2y - v1y * v2x; - if (!Numerical.isZero(cross)) { - var dx = p1x - p2x, - dy = p1y - p2y, - u1 = (v2x * dy - v2y * dx) / cross, - u2 = (v1x * dy - v1y * dx) / cross, - epsilon = 1e-12, - uMin = -epsilon, - uMax = 1 + epsilon; - if (isInfinite - || uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) { - if (!isInfinite) { - u1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1; - } - return new Point( - p1x + u1 * v1x, - p1y + u1 * v1y); - } - } - }, - - getSide: function(px, py, vx, vy, x, y, asVector, isInfinite) { - if (!asVector) { - vx -= px; - vy -= py; - } - var v2x = x - px, - v2y = y - py, - ccw = v2x * vy - v2y * vx; - if (!isInfinite && Numerical.isZero(ccw)) { - ccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy); - if (ccw >= 0 && ccw <= 1) - 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; - } - return vx === 0 ? vy > 0 ? x - px : px - x - : vy === 0 ? vx < 0 ? y - py : py - y - : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy); - }, - - getDistance: function(px, py, vx, vy, x, y, asVector) { - return Math.abs( - Line.getSignedDistance(px, py, vx, vy, x, y, asVector)); - } - } -}); - -var Project = PaperScopeItem.extend({ - _class: 'Project', - _list: 'projects', - _reference: 'project', - _compactSerialize: true, - - initialize: function Project(element) { - PaperScopeItem.call(this, true); - this._children = []; - this._namedChildren = {}; - this._activeLayer = null; - this._currentStyle = new Style(null, null, this); - this._view = View.create(this, - element || CanvasProvider.getCanvas(1, 1)); - this._selectionItems = {}; - this._selectionCount = 0; - this._updateVersion = 0; - }, - - _serialize: function(options, dictionary) { - return Base.serialize(this._children, options, true, dictionary); - }, - - _changed: function(flags, item) { - if (flags & 1) { - var view = this._view; - if (view) { - view._needsUpdate = true; - if (!view._requested && view._autoUpdate) - view.requestUpdate(); - } - } - var changes = this._changes; - if (changes && item) { - var changesById = this._changesById, - id = item._id, - entry = changesById[id]; - if (entry) { - entry.flags |= flags; - } else { - changes.push(changesById[id] = { item: item, flags: flags }); - } - } - }, - - clear: function() { - var children = this._children; - for (var i = children.length - 1; i >= 0; i--) - children[i].remove(); - }, - - isEmpty: function() { - return !this._children.length; - }, - - remove: function remove() { - if (!remove.base.call(this)) - return false; - if (this._view) - this._view.remove(); - return true; - }, - - getView: function() { - return this._view; - }, - - getCurrentStyle: function() { - return this._currentStyle; - }, - - setCurrentStyle: function(style) { - this._currentStyle.set(style); - }, - - getIndex: function() { - return this._index; - }, - - getOptions: function() { - return this._scope.settings; - }, - - getLayers: function() { - return this._children; - }, - - getActiveLayer: function() { - return this._activeLayer || new Layer({ project: this, insert: true }); - }, - - getSymbolDefinitions: function() { - var definitions = [], - ids = {}; - this.getItems({ - class: SymbolItem, - match: function(item) { - var definition = item._definition, - id = definition._id; - if (!ids[id]) { - ids[id] = true; - definitions.push(definition); - } - return false; - } - }); - return definitions; - }, - - getSymbols: 'getSymbolDefinitions', - - getSelectedItems: function() { - var selectionItems = this._selectionItems, - items = []; - for (var id in selectionItems) { - var item = selectionItems[id], - selection = item._selection; - if ((selection & 1) && item.isInserted()) { - items.push(item); - } else if (!selection) { - this._updateSelection(item); - } - } - return items; - }, - - _updateSelection: function(item) { - var id = item._id, - selectionItems = this._selectionItems; - if (item._selection) { - if (selectionItems[id] !== item) { - this._selectionCount++; - selectionItems[id] = item; - } - } else if (selectionItems[id] === item) { - this._selectionCount--; - delete selectionItems[id]; - } - }, - - selectAll: function() { - var children = this._children; - for (var i = 0, l = children.length; i < l; i++) - children[i].setFullySelected(true); - }, - - deselectAll: function() { - var selectionItems = this._selectionItems; - for (var i in selectionItems) - selectionItems[i].setFullySelected(false); - }, - - addLayer: function(layer) { - return this.insertLayer(undefined, layer); - }, - - insertLayer: function(index, layer) { - if (layer instanceof Layer) { - layer._remove(false, true); - Base.splice(this._children, [layer], index, 0); - layer._setProject(this, true); - var name = layer._name; - if (name) - layer.setName(name); - if (this._changes) - layer._changed(5); - if (!this._activeLayer) - this._activeLayer = layer; - } else { - layer = null; - } - return layer; - }, - - _insertItem: function(index, item, _created) { - item = this.insertLayer(index, item) - || (this._activeLayer || this._insertItem(undefined, - new Layer(Item.NO_INSERT), true)) - .insertChild(index, item); - if (_created && item.activate) - item.activate(); - return item; - }, - - getItems: function(options) { - return Item._getItems(this, options); - }, - - getItem: function(options) { - return Item._getItems(this, options, null, null, true)[0] || null; - }, - - importJSON: function(json) { - this.activate(); - var layer = this._activeLayer; - return Base.importJSON(json, layer && layer.isEmpty() && layer); - }, - - removeOn: function(type) { - var sets = this._removeSets; - if (sets) { - if (type === 'mouseup') - sets.mousedrag = null; - var set = sets[type]; - if (set) { - for (var id in set) { - var item = set[id]; - for (var key in sets) { - var other = sets[key]; - if (other && other != set) - delete other[item._id]; - } - item.remove(); - } - sets[type] = null; - } - } - }, - - draw: function(ctx, matrix, pixelRatio) { - this._updateVersion++; - ctx.save(); - matrix.applyToContext(ctx); - var children = this._children, - param = new Base({ - offset: new Point(0, 0), - pixelRatio: pixelRatio, - viewMatrix: matrix.isIdentity() ? null : matrix, - matrices: [new Matrix()], - updateMatrix: true - }); - for (var i = 0, l = children.length; i < l; i++) { - children[i].draw(ctx, param); - } - ctx.restore(); - - if (this._selectionCount > 0) { - ctx.save(); - ctx.strokeWidth = 1; - var items = this._selectionItems, - size = this._scope.settings.handleSize, - version = this._updateVersion; - for (var id in items) { - items[id]._drawSelection(ctx, matrix, size, items, version); - } - ctx.restore(); - } - } -}); - -var Item = Base.extend(Emitter, { - statics: { - extend: function extend(src) { - if (src._serializeFields) - src._serializeFields = Base.set({}, - this.prototype._serializeFields, src._serializeFields); - return extend.base.apply(this, arguments); - }, - - NO_INSERT: { insert: false } - }, - - _class: 'Item', - _name: null, - _applyMatrix: true, - _canApplyMatrix: true, - _canScaleStroke: false, - _pivot: null, - _visible: true, - _blendMode: 'normal', - _opacity: 1, - _locked: false, - _guide: false, - _clipMask: false, - _selection: 0, - _selectBounds: true, - _selectChildren: false, - _serializeFields: { - name: null, - applyMatrix: null, - matrix: new Matrix(), - pivot: null, - visible: true, - blendMode: 'normal', - opacity: 1, - locked: false, - guide: false, - clipMask: false, - selected: false, - data: {} - }, - _prioritize: ['applyMatrix'] -}, -new function() { - var handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick', - 'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave']; - return Base.each(handlers, - function(name) { - this._events[name] = { - install: function(type) { - this.getView()._countItemEvent(type, 1); - }, - - uninstall: function(type) { - this.getView()._countItemEvent(type, -1); - } - }; - }, { - _events: { - onFrame: { - install: function() { - this.getView()._animateItem(this, true); - }, - - uninstall: function() { - this.getView()._animateItem(this, false); - } - }, - - onLoad: {}, - onError: {} - }, - statics: { - _itemHandlers: handlers - } - } - ); -}, { - initialize: function Item() { - }, - - _initialize: function(props, point) { - var hasProps = props && Base.isPlainObject(props), - internal = hasProps && props.internal === true, - matrix = this._matrix = new Matrix(), - project = hasProps && props.project || paper.project, - settings = paper.settings; - this._id = internal ? null : UID.get(); - this._parent = this._index = null; - this._applyMatrix = this._canApplyMatrix && settings.applyMatrix; - if (point) - matrix.translate(point); - matrix._owner = this; - this._style = new Style(project._currentStyle, this, project); - if (internal || hasProps && props.insert == false - || !settings.insertItems && !(hasProps && props.insert === true)) { - this._setProject(project); - } else { - (hasProps && props.parent || project) - ._insertItem(undefined, this, true); - } - if (hasProps && props !== Item.NO_INSERT) { - this.set(props, { - internal: true, insert: true, project: true, parent: true - }); - } - return hasProps; - }, - - _serialize: function(options, dictionary) { - var props = {}, - that = this; - - function serialize(fields) { - for (var key in fields) { - var value = that[key]; - if (!Base.equals(value, key === 'leading' - ? fields.fontSize * 1.2 : fields[key])) { - props[key] = Base.serialize(value, options, - key !== 'data', dictionary); - } - } - } - - serialize(this._serializeFields); - if (!(this instanceof Group)) - serialize(this._style._defaults); - return [ this._class, props ]; - }, - - _changed: function(flags) { - var symbol = this._symbol, - cacheParent = this._parent || symbol, - project = this._project; - if (flags & 8) { - this._bounds = this._position = this._decomposed = undefined; - } - if (flags & 16) { - this._globalMatrix = undefined; - } - if (cacheParent - && (flags & 72)) { - Item._clearBoundsCache(cacheParent); - } - if (flags & 2) { - Item._clearBoundsCache(this); - } - if (project) - project._changed(flags, this); - if (symbol) - symbol._changed(flags); - }, - - getId: function() { - return this._id; - }, - - getName: function() { - return this._name; - }, - - setName: function(name) { - - if (this._name) - this._removeNamed(); - if (name === (+name) + '') - throw new Error( - 'Names consisting only of numbers are not supported.'); - var owner = this._getOwner(); - if (name && owner) { - var children = owner._children, - namedChildren = owner._namedChildren; - (namedChildren[name] = namedChildren[name] || []).push(this); - if (!(name in children)) - children[name] = this; - } - this._name = name || undefined; - this._changed(256); - }, - - getStyle: function() { - return this._style; - }, - - setStyle: function(style) { - this.getStyle().set(style); - } -}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'], - function(name) { - var part = Base.capitalize(name), - key = '_' + name, - flags = { - locked: 256, - visible: 265 - }; - this['get' + part] = function() { - return this[key]; - }; - this['set' + part] = function(value) { - if (value != this[key]) { - this[key] = value; - this._changed(flags[name] || 257); - } - }; - }, -{}), { - beans: true, - - getSelection: function() { - return this._selection; - }, - - setSelection: function(selection) { - if (selection !== this._selection) { - this._selection = selection; - var project = this._project; - if (project) { - project._updateSelection(this); - this._changed(257); - } - } - }, - - _changeSelection: function(flag, selected) { - var selection = this._selection; - this.setSelection(selected ? selection | flag : selection & ~flag); - }, - - isSelected: function() { - if (this._selectChildren) { - var children = this._children; - for (var i = 0, l = children.length; i < l; i++) - if (children[i].isSelected()) - return true; - } - return !!(this._selection & 1); - }, - - setSelected: function(selected) { - if (this._selectChildren) { - var children = this._children; - for (var i = 0, l = children.length; i < l; i++) - children[i].setSelected(selected); - } - this._changeSelection(1, selected); - }, - - isFullySelected: function() { - var children = this._children, - selected = !!(this._selection & 1); - if (children && selected) { - for (var i = 0, l = children.length; i < l; i++) - if (!children[i].isFullySelected()) - return false; - return true; - } - return selected; - }, - - setFullySelected: function(selected) { - var children = this._children; - if (children) { - for (var i = 0, l = children.length; i < l; i++) - children[i].setFullySelected(selected); - } - this._changeSelection(1, selected); - }, - - isClipMask: function() { - return this._clipMask; - }, - - setClipMask: function(clipMask) { - if (this._clipMask != (clipMask = !!clipMask)) { - this._clipMask = clipMask; - if (clipMask) { - this.setFillColor(null); - this.setStrokeColor(null); - } - this._changed(257); - if (this._parent) - this._parent._changed(2048); - } - }, - - getData: function() { - if (!this._data) - this._data = {}; - return this._data; - }, - - setData: function(data) { - this._data = data; - }, - - getPosition: function(_dontLink) { - var ctor = _dontLink ? Point : LinkedPoint; - var position = this._position || - (this._position = this._getPositionFromBounds()); - return new ctor(position.x, position.y, this, 'setPosition'); - }, - - setPosition: function() { - this.translate(Point.read(arguments).subtract(this.getPosition(true))); - }, - - _getPositionFromBounds: function(bounds) { - return this._pivot - ? this._matrix._transformPoint(this._pivot) - : (bounds || this.getBounds()).getCenter(true); - }, - - getPivot: function() { - var pivot = this._pivot; - return pivot - ? new LinkedPoint(pivot.x, pivot.y, this, 'setPivot') - : null; - }, - - setPivot: function() { - this._pivot = Point.read(arguments, 0, { clone: true, readNull: true }); - this._position = undefined; - } -}, Base.each({ - getStrokeBounds: { stroke: true }, - getHandleBounds: { handle: true }, - getInternalBounds: { internal: true } - }, - function(options, key) { - this[key] = function(matrix) { - return this.getBounds(matrix, options); - }; - }, -{ - beans: true, - - getBounds: function(matrix, options) { - var hasMatrix = options || matrix instanceof Matrix, - opts = Base.set({}, hasMatrix ? options : matrix, - this._boundsOptions); - if (!opts.stroke || this.getStrokeScaling()) - opts.cacheItem = this; - var rect = this._getCachedBounds(hasMatrix && matrix, opts).rect; - return !arguments.length - ? new LinkedRectangle(rect.x, rect.y, rect.width, rect.height, - this, 'setBounds') - : rect; - }, - - setBounds: function() { - var rect = Rectangle.read(arguments), - bounds = this.getBounds(), - _matrix = this._matrix, - matrix = new Matrix(), - center = rect.getCenter(); - matrix.translate(center); - if (rect.width != bounds.width || rect.height != bounds.height) { - if (!_matrix.isInvertible()) { - _matrix.set(_matrix._backup - || new Matrix().translate(_matrix.getTranslation())); - bounds = this.getBounds(); - } - matrix.scale( - bounds.width !== 0 ? rect.width / bounds.width : 0, - bounds.height !== 0 ? rect.height / bounds.height : 0); - } - center = bounds.getCenter(); - matrix.translate(-center.x, -center.y); - this.transform(matrix); - }, - - _getBounds: function(matrix, options) { - var children = this._children; - if (!children || !children.length) - return new Rectangle(); - Item._updateBoundsCache(this, options.cacheItem); - return Item._getBounds(children, matrix, options); - }, - - _getBoundsCacheKey: function(options, internal) { - return [ - options.stroke ? 1 : 0, - options.handle ? 1 : 0, - internal ? 1 : 0 - ].join(''); - }, - - _getCachedBounds: function(matrix, options, noInternal) { - matrix = matrix && matrix._orNullIfIdentity(); - var internal = options.internal && !noInternal, - cacheItem = options.cacheItem, - _matrix = internal ? null : this._matrix._orNullIfIdentity(), - cacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) - && this._getBoundsCacheKey(options, internal), - bounds = this._bounds; - Item._updateBoundsCache(this._parent || this._symbol, cacheItem); - if (cacheKey && bounds && cacheKey in bounds) { - var cached = bounds[cacheKey]; - return { - rect: cached.rect.clone(), - nonscaling: cached.nonscaling - }; - } - var res = this._getBounds(matrix || _matrix, options), - rect = res.rect || res, - style = this._style, - nonscaling = res.nonscaling || style.hasStroke() - && !style.getStrokeScaling(); - if (cacheKey) { - if (!bounds) { - this._bounds = bounds = {}; - } - var cached = bounds[cacheKey] = { - rect: rect.clone(), - nonscaling: nonscaling, - internal: internal - }; - } - return { - rect: rect, - nonscaling: nonscaling - }; - }, - - _getStrokeMatrix: function(matrix, options) { - var parent = this.getStrokeScaling() ? null - : options && options.internal ? this - : this._parent || this._symbol && this._symbol._item, - mx = parent ? parent.getViewMatrix().invert() : matrix; - return mx && mx._shiftless(); - }, - - statics: { - _updateBoundsCache: function(parent, item) { - if (parent && item) { - var id = item._id, - ref = parent._boundsCache = parent._boundsCache || { - ids: {}, - list: [] - }; - if (!ref.ids[id]) { - ref.list.push(item); - ref.ids[id] = item; - } - } - }, - - _clearBoundsCache: function(item) { - var cache = item._boundsCache; - if (cache) { - item._bounds = item._position = item._boundsCache = undefined; - for (var i = 0, list = cache.list, l = list.length; i < l; i++){ - var other = list[i]; - if (other !== item) { - other._bounds = other._position = undefined; - if (other._boundsCache) - Item._clearBoundsCache(other); - } - } - } - }, - - _getBounds: function(items, matrix, options) { - var x1 = Infinity, - x2 = -x1, - y1 = x1, - y2 = x2, - nonscaling = false; - options = options || {}; - for (var i = 0, l = items.length; i < l; i++) { - var item = items[i]; - if (item._visible && !item.isEmpty()) { - var bounds = item._getCachedBounds( - matrix && matrix.appended(item._matrix), options, true), - rect = bounds.rect; - x1 = Math.min(rect.x, x1); - y1 = Math.min(rect.y, y1); - x2 = Math.max(rect.x + rect.width, x2); - y2 = Math.max(rect.y + rect.height, y2); - if (bounds.nonscaling) - nonscaling = true; - } - } - return { - rect: isFinite(x1) - ? new Rectangle(x1, y1, x2 - x1, y2 - y1) - : new Rectangle(), - nonscaling: nonscaling - }; - } - } - -}), { - beans: true, - - _decompose: function() { - return this._applyMatrix - ? null - : this._decomposed || (this._decomposed = this._matrix.decompose()); - }, - - getRotation: function() { - var decomposed = this._decompose(); - return decomposed ? decomposed.rotation : 0; - }, - - setRotation: function(rotation) { - var current = this.getRotation(); - if (current != null && rotation != null) { - var decomposed = this._decomposed; - this.rotate(rotation - current); - if (decomposed) { - decomposed.rotation = rotation; - this._decomposed = decomposed; - } - } - }, - - getScaling: function() { - var decomposed = this._decompose(), - s = decomposed && decomposed.scaling; - return new LinkedPoint(s ? s.x : 1, s ? s.y : 1, this, 'setScaling'); - }, - - setScaling: function() { - var current = this.getScaling(), - scaling = Point.read(arguments, 0, { clone: true, readNull: true }); - if (current && scaling && !current.equals(scaling)) { - var rotation = this.getRotation(), - decomposed = this._decomposed, - matrix = new Matrix(), - center = this.getPosition(true); - matrix.translate(center); - if (rotation) - matrix.rotate(rotation); - matrix.scale(scaling.x / current.x, scaling.y / current.y); - if (rotation) - matrix.rotate(-rotation); - matrix.translate(center.negate()); - this.transform(matrix); - if (decomposed) { - decomposed.scaling = scaling; - this._decomposed = decomposed; - } - } - }, - - getMatrix: function() { - return this._matrix; - }, - - setMatrix: function() { - var matrix = this._matrix; - matrix.initialize.apply(matrix, arguments); - }, - - getGlobalMatrix: function(_dontClone) { - var matrix = this._globalMatrix; - if (matrix) { - var parent = this._parent; - var parents = []; - while (parent) { - if (!parent._globalMatrix) { - matrix = null; - for (var i = 0, l = parents.length; i < l; i++) { - parents[i]._globalMatrix = null; - } - break; - } - parents.push(parent); - parent = parent._parent; - } - } - if (!matrix) { - matrix = this._globalMatrix = this._matrix.clone(); - var parent = this._parent; - if (parent) - matrix.prepend(parent.getGlobalMatrix(true)); - } - return _dontClone ? matrix : matrix.clone(); - }, - - getViewMatrix: function() { - return this.getGlobalMatrix().prepend(this.getView()._matrix); - }, - - getApplyMatrix: function() { - return this._applyMatrix; - }, - - setApplyMatrix: function(apply) { - if (this._applyMatrix = this._canApplyMatrix && !!apply) - this.transform(null, true); - }, - - getTransformContent: '#getApplyMatrix', - setTransformContent: '#setApplyMatrix', -}, { - getProject: function() { - return this._project; - }, - - _setProject: function(project, installEvents) { - if (this._project !== project) { - if (this._project) - this._installEvents(false); - this._project = project; - var children = this._children; - for (var i = 0, l = children && children.length; i < l; i++) - children[i]._setProject(project); - installEvents = true; - } - if (installEvents) - this._installEvents(true); - }, - - getView: function() { - return this._project._view; - }, - - _installEvents: function _installEvents(install) { - _installEvents.base.call(this, install); - var children = this._children; - for (var i = 0, l = children && children.length; i < l; i++) - children[i]._installEvents(install); - }, - - getLayer: function() { - var parent = this; - while (parent = parent._parent) { - if (parent instanceof Layer) - return parent; - } - return null; - }, - - getParent: function() { - return this._parent; - }, - - setParent: function(item) { - return item.addChild(this); - }, - - _getOwner: '#getParent', - - getChildren: function() { - return this._children; - }, - - setChildren: function(items) { - this.removeChildren(); - this.addChildren(items); - }, - - getFirstChild: function() { - return this._children && this._children[0] || null; - }, - - getLastChild: function() { - return this._children && this._children[this._children.length - 1] - || null; - }, - - getNextSibling: function() { - var owner = this._getOwner(); - return owner && owner._children[this._index + 1] || null; - }, - - getPreviousSibling: function() { - var owner = this._getOwner(); - return owner && owner._children[this._index - 1] || null; - }, - - getIndex: function() { - return this._index; - }, - - equals: function(item) { - return item === this || item && this._class === item._class - && this._style.equals(item._style) - && this._matrix.equals(item._matrix) - && this._locked === item._locked - && this._visible === item._visible - && this._blendMode === item._blendMode - && this._opacity === item._opacity - && this._clipMask === item._clipMask - && this._guide === item._guide - && this._equals(item) - || false; - }, - - _equals: function(item) { - return Base.equals(this._children, item._children); - }, - - clone: function(options) { - var copy = new this.constructor(Item.NO_INSERT), - children = this._children, - insert = Base.pick(options ? options.insert : undefined, - options === undefined || options === true), - deep = Base.pick(options ? options.deep : undefined, true); - if (children) - copy.copyAttributes(this); - if (!children || deep) - copy.copyContent(this); - if (!children) - copy.copyAttributes(this); - if (insert) - copy.insertAbove(this); - var name = this._name, - parent = this._parent; - if (name && parent) { - var children = parent._children, - orig = name, - i = 1; - while (children[name]) - name = orig + ' ' + (i++); - if (name !== orig) - copy.setName(name); - } - return copy; - }, - - copyContent: function(source) { - var children = source._children; - for (var i = 0, l = children && children.length; i < l; i++) { - this.addChild(children[i].clone(false), true); - } - }, - - copyAttributes: function(source, excludeMatrix) { - this.setStyle(source._style); - var keys = ['_locked', '_visible', '_blendMode', '_opacity', - '_clipMask', '_guide']; - for (var i = 0, l = keys.length; i < l; i++) { - var key = keys[i]; - if (source.hasOwnProperty(key)) - this[key] = source[key]; - } - if (!excludeMatrix) - this._matrix.set(source._matrix, true); - this.setApplyMatrix(source._applyMatrix); - this.setPivot(source._pivot); - this.setSelection(source._selection); - var data = source._data, - name = source._name; - this._data = data ? Base.clone(data) : null; - if (name) - this.setName(name); - }, - - rasterize: function(resolution, insert) { - var bounds = this.getStrokeBounds(), - scale = (resolution || this.getView().getResolution()) / 72, - topLeft = bounds.getTopLeft().floor(), - bottomRight = bounds.getBottomRight().ceil(), - size = new Size(bottomRight.subtract(topLeft)), - raster = new Raster(Item.NO_INSERT); - if (!size.isZero()) { - var canvas = CanvasProvider.getCanvas(size.multiply(scale)), - ctx = canvas.getContext('2d'), - matrix = new Matrix().scale(scale).translate(topLeft.negate()); - ctx.save(); - matrix.applyToContext(ctx); - this.draw(ctx, new Base({ matrices: [matrix] })); - ctx.restore(); - raster.setCanvas(canvas); - } - raster.transform(new Matrix().translate(topLeft.add(size.divide(2))) - .scale(1 / scale)); - if (insert === undefined || insert) - raster.insertAbove(this); - return raster; - }, - - contains: function() { - return !!this._contains( - this._matrix._inverseTransform(Point.read(arguments))); - }, - - _contains: function(point) { - var children = this._children; - if (children) { - for (var i = children.length - 1; i >= 0; i--) { - if (children[i].contains(point)) - return true; - } - return false; - } - return point.isInside(this.getInternalBounds()); - }, - - isInside: function() { - return Rectangle.read(arguments).contains(this.getBounds()); - }, - - _asPathItem: function() { - return new Path.Rectangle({ - rectangle: this.getInternalBounds(), - matrix: this._matrix, - insert: false, - }); - }, - - intersects: function(item, _matrix) { - if (!(item instanceof Item)) - return false; - return this._asPathItem().getIntersections(item._asPathItem(), null, - _matrix, true).length > 0; - } -}, -new function() { - function hitTest() { - return this._hitTest( - Point.read(arguments), - HitResult.getOptions(arguments)); - } - - function hitTestAll() { - var point = Point.read(arguments), - options = HitResult.getOptions(arguments), - all = []; - this._hitTest(point, Base.set({ all: all }, options)); - return all; - } - - function hitTestChildren(point, options, viewMatrix, _exclude) { - var children = this._children; - if (children) { - for (var i = children.length - 1; i >= 0; i--) { - var child = children[i]; - var res = child !== _exclude && child._hitTest(point, options, - viewMatrix); - if (res && !options.all) - return res; - } - } - return null; - } - - Project.inject({ - hitTest: hitTest, - hitTestAll: hitTestAll, - _hitTest: hitTestChildren - }); - - return { - hitTest: hitTest, - hitTestAll: hitTestAll, - _hitTestChildren: hitTestChildren, - }; -}, { - - _hitTest: function(point, options, parentViewMatrix) { - if (this._locked || !this._visible || this._guide && !options.guides - || this.isEmpty()) { - return null; - } - - var matrix = this._matrix, - viewMatrix = parentViewMatrix - ? parentViewMatrix.appended(matrix) - : this.getGlobalMatrix().prepend(this.getView()._matrix), - tolerance = Math.max(options.tolerance, 1e-12), - tolerancePadding = options._tolerancePadding = new Size( - Path._getStrokePadding(tolerance, - matrix._shiftless().invert())); - point = matrix._inverseTransform(point); - if (!point || !this._children && - !this.getBounds({ internal: true, stroke: true, handle: true }) - .expand(tolerancePadding.multiply(2))._containsPoint(point)) { - return null; - } - - var checkSelf = !(options.guides && !this._guide - || options.selected && !this.isSelected() - || options.type && options.type !== Base.hyphenate(this._class) - || options.class && !(this instanceof options.class)), - match = options.match, - that = this, - bounds, - res; - - function filter(hit) { - if (hit && match && !match(hit)) - hit = null; - if (hit && options.all) - options.all.push(hit); - return hit; - } - - function checkPoint(type, part) { - var pt = part ? bounds['get' + part]() : that.getPosition(); - if (point.subtract(pt).divide(tolerancePadding).length <= 1) { - return new HitResult(type, that, { - name: part ? Base.hyphenate(part) : type, - point: pt - }); - } - } - - var checkPosition = options.position, - checkCenter = options.center, - checkBounds = options.bounds; - if (checkSelf && this._parent - && (checkPosition || checkCenter || checkBounds)) { - if (checkCenter || checkBounds) { - bounds = this.getInternalBounds(); - } - res = checkPosition && checkPoint('position') || - checkCenter && checkPoint('center', 'Center'); - if (!res && checkBounds) { - var points = [ - 'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight', - 'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter' - ]; - for (var i = 0; i < 8 && !res; i++) { - res = checkPoint('bounds', points[i]); - } - } - res = filter(res); - } - - if (!res) { - res = this._hitTestChildren(point, options, viewMatrix) - || checkSelf - && filter(this._hitTestSelf(point, options, viewMatrix, - this.getStrokeScaling() ? null - : viewMatrix._shiftless().invert())) - || null; - } - if (res && res.point) { - res.point = matrix.transform(res.point); - } - return res; - }, - - _hitTestSelf: function(point, options) { - if (options.fill && this.hasFill() && this._contains(point)) - return new HitResult('fill', this); - }, - - matches: function(name, compare) { - function matchObject(obj1, obj2) { - for (var i in obj1) { - if (obj1.hasOwnProperty(i)) { - var val1 = obj1[i], - val2 = obj2[i]; - if (Base.isPlainObject(val1) && Base.isPlainObject(val2)) { - if (!matchObject(val1, val2)) - return false; - } else if (!Base.equals(val1, val2)) { - return false; - } - } - } - return true; - } - var type = typeof name; - if (type === 'object') { - for (var key in name) { - if (name.hasOwnProperty(key) && !this.matches(key, name[key])) - return false; - } - return true; - } else if (type === 'function') { - return name(this); - } else if (name === 'match') { - return compare(this); - } else { - var value = /^(empty|editable)$/.test(name) - ? this['is' + Base.capitalize(name)]() - : name === 'type' - ? Base.hyphenate(this._class) - : this[name]; - if (name === 'class') { - if (typeof compare === 'function') - return this instanceof compare; - value = this._class; - } - if (typeof compare === 'function') { - return !!compare(value); - } else if (compare) { - if (compare.test) { - return compare.test(value); - } else if (Base.isPlainObject(compare)) { - return matchObject(compare, value); - } - } - return Base.equals(value, compare); - } - }, - - getItems: function(options) { - return Item._getItems(this, options, this._matrix); - }, - - getItem: function(options) { - return Item._getItems(this, options, this._matrix, null, true)[0] - || null; - }, - - statics: { - _getItems: function _getItems(item, options, matrix, param, firstOnly) { - if (!param) { - var obj = typeof options === 'object' && options, - overlapping = obj && obj.overlapping, - inside = obj && obj.inside, - bounds = overlapping || inside, - rect = bounds && Rectangle.read([bounds]); - param = { - items: [], - recursive: obj && obj.recursive !== false, - inside: !!inside, - overlapping: !!overlapping, - rect: rect, - path: overlapping && new Path.Rectangle({ - rectangle: rect, - insert: false - }) - }; - if (obj) { - options = Base.filter({}, options, { - recursive: true, inside: true, overlapping: true - }); - } - } - var children = item._children, - items = param.items, - rect = param.rect; - matrix = rect && (matrix || new Matrix()); - for (var i = 0, l = children && children.length; i < l; i++) { - var child = children[i], - childMatrix = matrix && matrix.appended(child._matrix), - add = true; - if (rect) { - var bounds = child.getBounds(childMatrix); - if (!rect.intersects(bounds)) - continue; - if (!(rect.contains(bounds) - || param.overlapping && (bounds.contains(rect) - || param.path.intersects(child, childMatrix)))) - add = false; - } - if (add && child.matches(options)) { - items.push(child); - if (firstOnly) - break; - } - if (param.recursive !== false) { - _getItems(child, options, childMatrix, param, firstOnly); - } - if (firstOnly && items.length > 0) - break; - } - return items; - } - } -}, { - - importJSON: function(json) { - var res = Base.importJSON(json, this); - return res !== this ? this.addChild(res) : res; - }, - - addChild: function(item) { - return this.insertChild(undefined, item); - }, - - insertChild: function(index, item) { - var res = item ? this.insertChildren(index, [item]) : null; - return res && res[0]; - }, - - addChildren: function(items) { - return this.insertChildren(this._children.length, items); - }, - - insertChildren: function(index, items) { - var children = this._children; - if (children && items && items.length > 0) { - items = Base.slice(items); - var inserted = {}; - for (var i = items.length - 1; i >= 0; i--) { - var item = items[i], - id = item && item._id; - if (!item || inserted[id]) { - items.splice(i, 1); - } else { - item._remove(false, true); - inserted[id] = true; - } - } - Base.splice(children, items, index, 0); - var project = this._project, - notifySelf = project._changes; - for (var i = 0, l = items.length; i < l; i++) { - var item = items[i], - name = item._name; - item._parent = this; - item._setProject(project, true); - if (name) - item.setName(name); - if (notifySelf) - item._changed(5); - } - this._changed(11); - } else { - items = null; - } - return items; - }, - - _insertItem: '#insertChild', - - _insertAt: function(item, offset) { - var owner = item && item._getOwner(), - res = item !== this && owner ? this : null; - if (res) { - res._remove(false, true); - owner._insertItem(item._index + offset, res); - } - return res; - }, - - insertAbove: function(item) { - return this._insertAt(item, 1); - }, - - insertBelow: function(item) { - return this._insertAt(item, 0); - }, - - sendToBack: function() { - var owner = this._getOwner(); - return owner ? owner._insertItem(0, this) : null; - }, - - bringToFront: function() { - var owner = this._getOwner(); - return owner ? owner._insertItem(undefined, this) : null; - }, - - appendTop: '#addChild', - - appendBottom: function(item) { - return this.insertChild(0, item); - }, - - moveAbove: '#insertAbove', - - moveBelow: '#insertBelow', - - addTo: function(owner) { - return owner._insertItem(undefined, this); - }, - - copyTo: function(owner) { - return this.clone(false).addTo(owner); - }, - - reduce: function(options) { - var children = this._children; - if (children && children.length === 1) { - var child = children[0].reduce(options); - if (this._parent) { - child.insertAbove(this); - this.remove(); - } else { - child.remove(); - } - return child; - } - return this; - }, - - _removeNamed: function() { - var owner = this._getOwner(); - if (owner) { - var children = owner._children, - namedChildren = owner._namedChildren, - name = this._name, - namedArray = namedChildren[name], - index = namedArray ? namedArray.indexOf(this) : -1; - if (index !== -1) { - if (children[name] == this) - delete children[name]; - namedArray.splice(index, 1); - if (namedArray.length) { - children[name] = namedArray[0]; - } else { - delete namedChildren[name]; - } - } - } - }, - - _remove: function(notifySelf, notifyParent) { - var owner = this._getOwner(), - project = this._project, - index = this._index; - if (this._style) - this._style._dispose(); - if (owner) { - if (this._name) - this._removeNamed(); - if (index != null) { - if (project._activeLayer === this) - project._activeLayer = this.getNextSibling() - || this.getPreviousSibling(); - Base.splice(owner._children, null, index, 1); - } - this._installEvents(false); - if (notifySelf && project._changes) - this._changed(5); - if (notifyParent) - owner._changed(11, this); - this._parent = null; - return true; - } - return false; - }, - - remove: function() { - return this._remove(true, true); - }, - - replaceWith: function(item) { - var ok = item && item.insertBelow(this); - if (ok) - this.remove(); - return ok; - }, - - removeChildren: function(start, end) { - if (!this._children) - return null; - start = start || 0; - end = Base.pick(end, this._children.length); - var removed = Base.splice(this._children, null, start, end - start); - for (var i = removed.length - 1; i >= 0; i--) { - removed[i]._remove(true, false); - } - if (removed.length > 0) - this._changed(11); - return removed; - }, - - clear: '#removeChildren', - - reverseChildren: function() { - if (this._children) { - this._children.reverse(); - for (var i = 0, l = this._children.length; i < l; i++) - this._children[i]._index = i; - this._changed(11); - } - }, - - isEmpty: function() { - var children = this._children; - return !children || !children.length; - }, - - isEditable: function() { - var item = this; - while (item) { - if (!item._visible || item._locked) - return false; - item = item._parent; - } - return true; - }, - - hasFill: function() { - return this.getStyle().hasFill(); - }, - - hasStroke: function() { - return this.getStyle().hasStroke(); - }, - - hasShadow: function() { - return this.getStyle().hasShadow(); - }, - - _getOrder: function(item) { - function getList(item) { - var list = []; - do { - list.unshift(item); - } while (item = item._parent); - return list; - } - var list1 = getList(this), - list2 = getList(item); - for (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) { - if (list1[i] != list2[i]) { - return list1[i]._index < list2[i]._index ? 1 : -1; - } - } - return 0; - }, - - hasChildren: function() { - return this._children && this._children.length > 0; - }, - - isInserted: function() { - return this._parent ? this._parent.isInserted() : false; - }, - - isAbove: function(item) { - return this._getOrder(item) === -1; - }, - - isBelow: function(item) { - return this._getOrder(item) === 1; - }, - - isParent: function(item) { - return this._parent === item; - }, - - isChild: function(item) { - return item && item._parent === this; - }, - - isDescendant: function(item) { - var parent = this; - while (parent = parent._parent) { - if (parent === item) - return true; - } - return false; - }, - - isAncestor: function(item) { - return item ? item.isDescendant(this) : false; - }, - - isSibling: function(item) { - return this._parent === item._parent; - }, - - isGroupedWith: function(item) { - var parent = this._parent; - while (parent) { - if (parent._parent - && /^(Group|Layer|CompoundPath)$/.test(parent._class) - && item.isDescendant(parent)) - return true; - parent = parent._parent; - } - return false; - }, - -}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) { - var rotate = key === 'rotate'; - this[key] = function() { - var value = (rotate ? Base : Point).read(arguments), - center = Point.read(arguments, 0, { readNull: true }); - return this.transform(new Matrix()[key](value, - center || this.getPosition(true))); - }; -}, { - translate: function() { - var mx = new Matrix(); - return this.transform(mx.translate.apply(mx, arguments)); - }, - - transform: function(matrix, _applyMatrix, _applyRecursively, - _setApplyMatrix) { - var _matrix = this._matrix, - transformMatrix = matrix && !matrix.isIdentity(), - applyMatrix = (_applyMatrix || this._applyMatrix) - && ((!_matrix.isIdentity() || transformMatrix) - || _applyMatrix && _applyRecursively && this._children); - if (!transformMatrix && !applyMatrix) - return this; - if (transformMatrix) { - if (!matrix.isInvertible() && _matrix.isInvertible()) - _matrix._backup = _matrix.getValues(); - _matrix.prepend(matrix, true); - var style = this._style, - fillColor = style.getFillColor(true), - strokeColor = style.getStrokeColor(true); - if (fillColor) - fillColor.transform(matrix); - if (strokeColor) - strokeColor.transform(matrix); - } - if (applyMatrix && (applyMatrix = this._transformContent(_matrix, - _applyRecursively, _setApplyMatrix))) { - var pivot = this._pivot; - if (pivot) - _matrix._transformPoint(pivot, pivot, true); - _matrix.reset(true); - if (_setApplyMatrix && this._canApplyMatrix) - this._applyMatrix = true; - } - var bounds = this._bounds, - position = this._position; - if (transformMatrix || applyMatrix) { - this._changed(25); - } - var decomp = transformMatrix && bounds && matrix.decompose(); - if (decomp && decomp.skewing.isZero() && decomp.rotation % 90 === 0) { - for (var key in bounds) { - var cache = bounds[key]; - if (cache.nonscaling) { - delete bounds[key]; - } else if (applyMatrix || !cache.internal) { - var rect = cache.rect; - matrix._transformBounds(rect, rect); - } - } - this._bounds = bounds; - var cached = bounds[this._getBoundsCacheKey( - this._boundsOptions || {})]; - if (cached) { - this._position = this._getPositionFromBounds(cached.rect); - } - } else if (transformMatrix && position && this._pivot) { - this._position = matrix._transformPoint(position, position); - } - return this; - }, - - _transformContent: function(matrix, applyRecursively, setApplyMatrix) { - var children = this._children; - if (children) { - for (var i = 0, l = children.length; i < l; i++) - children[i].transform(matrix, true, applyRecursively, - setApplyMatrix); - return true; - } - }, - - globalToLocal: function() { - return this.getGlobalMatrix(true)._inverseTransform( - Point.read(arguments)); - }, - - localToGlobal: function() { - return this.getGlobalMatrix(true)._transformPoint( - Point.read(arguments)); - }, - - parentToLocal: function() { - return this._matrix._inverseTransform(Point.read(arguments)); - }, - - localToParent: function() { - return this._matrix._transformPoint(Point.read(arguments)); - }, - - fitBounds: function(rectangle, fill) { - rectangle = Rectangle.read(arguments); - var bounds = this.getBounds(), - itemRatio = bounds.height / bounds.width, - rectRatio = rectangle.height / rectangle.width, - scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio) - ? rectangle.width / bounds.width - : rectangle.height / bounds.height, - newBounds = new Rectangle(new Point(), - new Size(bounds.width * scale, bounds.height * scale)); - newBounds.setCenter(rectangle.getCenter()); - this.setBounds(newBounds); - } -}), { - - _setStyles: function(ctx, param, viewMatrix) { - var style = this._style, - matrix = this._matrix; - if (style.hasFill()) { - ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx, matrix); - } - if (style.hasStroke()) { - ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx, matrix); - ctx.lineWidth = style.getStrokeWidth(); - var strokeJoin = style.getStrokeJoin(), - strokeCap = style.getStrokeCap(), - miterLimit = style.getMiterLimit(); - if (strokeJoin) - ctx.lineJoin = strokeJoin; - if (strokeCap) - ctx.lineCap = strokeCap; - if (miterLimit) - ctx.miterLimit = miterLimit; - if (paper.support.nativeDash) { - var dashArray = style.getDashArray(), - dashOffset = style.getDashOffset(); - if (dashArray && dashArray.length) { - if ('setLineDash' in ctx) { - ctx.setLineDash(dashArray); - ctx.lineDashOffset = dashOffset; - } else { - ctx.mozDash = dashArray; - ctx.mozDashOffset = dashOffset; - } - } - } - } - if (style.hasShadow()) { - var pixelRatio = param.pixelRatio || 1, - mx = viewMatrix._shiftless().prepend( - new Matrix().scale(pixelRatio, pixelRatio)), - blur = mx.transform(new Point(style.getShadowBlur(), 0)), - offset = mx.transform(this.getShadowOffset()); - ctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx); - ctx.shadowBlur = blur.getLength(); - ctx.shadowOffsetX = offset.x; - ctx.shadowOffsetY = offset.y; - } - }, - - draw: function(ctx, param, parentStrokeMatrix) { - var updateVersion = this._updateVersion = this._project._updateVersion; - if (!this._visible || this._opacity === 0) - return; - var matrices = param.matrices, - viewMatrix = param.viewMatrix, - matrix = this._matrix, - globalMatrix = matrices[matrices.length - 1].appended(matrix); - if (!globalMatrix.isInvertible()) - return; - - viewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix) - : globalMatrix; - - matrices.push(globalMatrix); - if (param.updateMatrix) { - this._globalMatrix = globalMatrix; - } - - var blendMode = this._blendMode, - opacity = this._opacity, - normalBlend = blendMode === 'normal', - nativeBlend = BlendMode.nativeModes[blendMode], - direct = normalBlend && opacity === 1 - || param.dontStart - || param.clip - || (nativeBlend || normalBlend && opacity < 1) - && this._canComposite(), - pixelRatio = param.pixelRatio || 1, - mainCtx, itemOffset, prevOffset; - if (!direct) { - var bounds = this.getStrokeBounds(viewMatrix); - if (!bounds.width || !bounds.height) { - matrices.pop(); - return; - } - prevOffset = param.offset; - itemOffset = param.offset = bounds.getTopLeft().floor(); - mainCtx = ctx; - ctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1) - .multiply(pixelRatio)); - if (pixelRatio !== 1) - ctx.scale(pixelRatio, pixelRatio); - } - ctx.save(); - var strokeMatrix = parentStrokeMatrix - ? parentStrokeMatrix.appended(matrix) - : this._canScaleStroke && !this.getStrokeScaling(true) - && viewMatrix, - clip = !direct && param.clipItem, - transform = !strokeMatrix || clip; - if (direct) { - ctx.globalAlpha = opacity; - if (nativeBlend) - ctx.globalCompositeOperation = blendMode; - } else if (transform) { - ctx.translate(-itemOffset.x, -itemOffset.y); - } - if (transform) { - (direct ? matrix : viewMatrix).applyToContext(ctx); - } - if (clip) { - param.clipItem.draw(ctx, param.extend({ clip: true })); - } - if (strokeMatrix) { - ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); - var offset = param.offset; - if (offset) - ctx.translate(-offset.x, -offset.y); - } - this._draw(ctx, param, viewMatrix, strokeMatrix); - ctx.restore(); - matrices.pop(); - if (param.clip && !param.dontFinish) - ctx.clip(); - if (!direct) { - BlendMode.process(blendMode, ctx, mainCtx, opacity, - itemOffset.subtract(prevOffset).multiply(pixelRatio)); - CanvasProvider.release(ctx); - param.offset = prevOffset; - } - }, - - _isUpdated: function(updateVersion) { - var parent = this._parent; - if (parent instanceof CompoundPath) - return parent._isUpdated(updateVersion); - var updated = this._updateVersion === updateVersion; - if (!updated && parent && parent._visible - && parent._isUpdated(updateVersion)) { - this._updateVersion = updateVersion; - updated = true; - } - return updated; - }, - - _drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) { - var selection = this._selection, - itemSelected = selection & 1, - boundsSelected = selection & 2 - || itemSelected && this._selectBounds, - positionSelected = selection & 4; - if (!this._drawSelected) - itemSelected = false; - if ((itemSelected || boundsSelected || positionSelected) - && this._isUpdated(updateVersion)) { - var layer, - color = this.getSelectedColor(true) || (layer = this.getLayer()) - && layer.getSelectedColor(true), - mx = matrix.appended(this.getGlobalMatrix(true)), - half = size / 2; - ctx.strokeStyle = ctx.fillStyle = color - ? color.toCanvasStyle(ctx) : '#009dec'; - if (itemSelected) - this._drawSelected(ctx, mx, selectionItems); - if (positionSelected) { - var pos = this.getPosition(true), - parent = this._parent, - point = parent ? parent.localToGlobal(pos) : pos, - x = point.x, - y = point.y; - ctx.beginPath(); - ctx.arc(x, y, half, 0, Math.PI * 2, true); - ctx.stroke(); - var deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]], - start = half, - end = size + 1; - for (var i = 0; i < 4; i++) { - var delta = deltas[i], - dx = delta[0], - dy = delta[1]; - ctx.moveTo(x + dx * start, y + dy * start); - ctx.lineTo(x + dx * end, y + dy * end); - ctx.stroke(); - } - } - if (boundsSelected) { - var coords = mx._transformCorners(this.getInternalBounds()); - ctx.beginPath(); - for (var i = 0; i < 8; i++) { - ctx[!i ? 'moveTo' : 'lineTo'](coords[i], coords[++i]); - } - ctx.closePath(); - ctx.stroke(); - for (var i = 0; i < 8; i++) { - ctx.fillRect(coords[i] - half, coords[++i] - half, - size, size); - } - } - } - }, - - _canComposite: function() { - return false; - } -}, Base.each(['down', 'drag', 'up', 'move'], function(key) { - this['removeOn' + Base.capitalize(key)] = function() { - var hash = {}; - hash[key] = true; - return this.removeOn(hash); - }; -}, { - - removeOn: function(obj) { - for (var name in obj) { - if (obj[name]) { - var key = 'mouse' + name, - project = this._project, - sets = project._removeSets = project._removeSets || {}; - sets[key] = sets[key] || {}; - sets[key][this._id] = this; - } - } - return this; - } -})); - -var Group = Item.extend({ - _class: 'Group', - _selectBounds: false, - _selectChildren: true, - _serializeFields: { - children: [] - }, - - initialize: function Group(arg) { - this._children = []; - this._namedChildren = {}; - if (!this._initialize(arg)) - this.addChildren(Array.isArray(arg) ? arg : arguments); - }, - - _changed: function _changed(flags) { - _changed.base.call(this, flags); - if (flags & 2050) { - this._clipItem = undefined; - } - }, - - _getClipItem: function() { - var clipItem = this._clipItem; - if (clipItem === undefined) { - clipItem = null; - var children = this._children; - for (var i = 0, l = children.length; i < l; i++) { - if (children[i]._clipMask) { - clipItem = children[i]; - break; - } - } - this._clipItem = clipItem; - } - return clipItem; - }, - - isClipped: function() { - return !!this._getClipItem(); - }, - - setClipped: function(clipped) { - var child = this.getFirstChild(); - if (child) - child.setClipMask(clipped); - }, - - _getBounds: function _getBounds(matrix, options) { - var clipItem = this._getClipItem(); - return clipItem - ? clipItem._getCachedBounds( - matrix && matrix.appended(clipItem._matrix), - Base.set({}, options, { stroke: false })) - : _getBounds.base.call(this, matrix, options); - }, - - _hitTestChildren: function _hitTestChildren(point, options, viewMatrix) { - var clipItem = this._getClipItem(); - return (!clipItem || clipItem.contains(point)) - && _hitTestChildren.base.call(this, point, options, viewMatrix, - clipItem); - }, - - _draw: function(ctx, param) { - var clip = param.clip, - clipItem = !clip && this._getClipItem(); - param = param.extend({ clipItem: clipItem, clip: false }); - if (clip) { - ctx.beginPath(); - param.dontStart = param.dontFinish = true; - } else if (clipItem) { - clipItem.draw(ctx, param.extend({ clip: true })); - } - var children = this._children; - for (var i = 0, l = children.length; i < l; i++) { - var item = children[i]; - if (item !== clipItem) - item.draw(ctx, param); - } - } -}); - -var Layer = Group.extend({ - _class: 'Layer', - - initialize: function Layer() { - Group.apply(this, arguments); - }, - - _getOwner: function() { - return this._parent || this._index != null && this._project; - }, - - isInserted: function isInserted() { - return this._parent ? isInserted.base.call(this) : this._index != null; - }, - - activate: function() { - this._project._activeLayer = this; - }, - - _hitTestSelf: function() { - } -}); - -var Shape = Item.extend({ - _class: 'Shape', - _applyMatrix: false, - _canApplyMatrix: false, - _canScaleStroke: true, - _serializeFields: { - type: null, - size: null, - radius: null - }, - - initialize: function Shape(props, point) { - this._initialize(props, point); - }, - - _equals: function(item) { - return this._type === item._type - && this._size.equals(item._size) - && Base.equals(this._radius, item._radius); - }, - - copyContent: function(source) { - this.setType(source._type); - this.setSize(source._size); - this.setRadius(source._radius); - }, - - getType: function() { - return this._type; - }, - - setType: function(type) { - this._type = type; - }, - - getShape: '#getType', - setShape: '#setType', - - getSize: function() { - var size = this._size; - return new LinkedSize(size.width, size.height, this, 'setSize'); - }, - - setSize: function() { - var size = Size.read(arguments); - if (!this._size) { - this._size = size.clone(); - } else if (!this._size.equals(size)) { - var type = this._type, - width = size.width, - height = size.height; - if (type === 'rectangle') { - this._radius.set(Size.min(this._radius, size.divide(2))); - } else if (type === 'circle') { - width = height = (width + height) / 2; - this._radius = width / 2; - } else if (type === 'ellipse') { - this._radius._set(width / 2, height / 2); - } - this._size._set(width, height); - this._changed(9); - } - }, - - getRadius: function() { - var rad = this._radius; - return this._type === 'circle' - ? rad - : new LinkedSize(rad.width, rad.height, this, 'setRadius'); - }, - - setRadius: function(radius) { - var type = this._type; - if (type === 'circle') { - if (radius === this._radius) - return; - var size = radius * 2; - this._radius = radius; - this._size._set(size, size); - } else { - radius = Size.read(arguments); - if (!this._radius) { - this._radius = radius.clone(); - } else { - if (this._radius.equals(radius)) - return; - this._radius.set(radius); - if (type === 'rectangle') { - var size = Size.max(this._size, radius.multiply(2)); - this._size.set(size); - } else if (type === 'ellipse') { - this._size._set(radius.width * 2, radius.height * 2); - } - } - } - this._changed(9); - }, - - isEmpty: function() { - return false; - }, - - toPath: function(insert) { - var path = new Path[Base.capitalize(this._type)]({ - center: new Point(), - size: this._size, - radius: this._radius, - insert: false - }); - path.copyAttributes(this); - if (paper.settings.applyMatrix) - path.setApplyMatrix(true); - if (insert === undefined || insert) - path.insertAbove(this); - return path; - }, - - toShape: '#clone', - - _asPathItem: function() { - return this.toPath(false); - }, - - _draw: function(ctx, param, viewMatrix, strokeMatrix) { - var style = this._style, - hasFill = style.hasFill(), - hasStroke = style.hasStroke(), - dontPaint = param.dontFinish || param.clip, - untransformed = !strokeMatrix; - if (hasFill || hasStroke || dontPaint) { - var type = this._type, - radius = this._radius, - isCircle = type === 'circle'; - if (!param.dontStart) - ctx.beginPath(); - if (untransformed && isCircle) { - ctx.arc(0, 0, radius, 0, Math.PI * 2, true); - } else { - var rx = isCircle ? radius : radius.width, - ry = isCircle ? radius : radius.height, - size = this._size, - width = size.width, - height = size.height; - if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) { - ctx.rect(-width / 2, -height / 2, width, height); - } else { - var x = width / 2, - y = height / 2, - kappa = 1 - 0.5522847498307936, - cx = rx * kappa, - cy = ry * kappa, - c = [ - -x, -y + ry, - -x, -y + cy, - -x + cx, -y, - -x + rx, -y, - x - rx, -y, - x - cx, -y, - x, -y + cy, - x, -y + ry, - x, y - ry, - x, y - cy, - x - cx, y, - x - rx, y, - -x + rx, y, - -x + cx, y, - -x, y - cy, - -x, y - ry - ]; - if (strokeMatrix) - strokeMatrix.transform(c, c, 32); - ctx.moveTo(c[0], c[1]); - ctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]); - if (x !== rx) - ctx.lineTo(c[8], c[9]); - ctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]); - if (y !== ry) - ctx.lineTo(c[16], c[17]); - ctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]); - if (x !== rx) - ctx.lineTo(c[24], c[25]); - ctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]); - } - } - ctx.closePath(); - } - if (!dontPaint && (hasFill || hasStroke)) { - this._setStyles(ctx, param, viewMatrix); - if (hasFill) { - ctx.fill(style.getFillRule()); - ctx.shadowColor = 'rgba(0,0,0,0)'; - } - if (hasStroke) - ctx.stroke(); - } - }, - - _canComposite: function() { - return !(this.hasFill() && this.hasStroke()); - }, - - _getBounds: function(matrix, options) { - var rect = new Rectangle(this._size).setCenter(0, 0), - style = this._style, - strokeWidth = options.stroke && style.hasStroke() - && style.getStrokeWidth(); - if (matrix) - rect = matrix._transformBounds(rect); - return strokeWidth - ? rect.expand(Path._getStrokePadding(strokeWidth, - this._getStrokeMatrix(matrix, options))) - : rect; - } -}, -new function() { - function getCornerCenter(that, point, expand) { - var radius = that._radius; - if (!radius.isZero()) { - var halfSize = that._size.divide(2); - for (var q = 1; q <= 4; q++) { - var dir = new Point(q > 1 && q < 4 ? -1 : 1, q > 2 ? -1 : 1), - corner = dir.multiply(halfSize), - center = corner.subtract(dir.multiply(radius)), - rect = new Rectangle( - expand ? corner.add(dir.multiply(expand)) : corner, - center); - if (rect.contains(point)) - return { point: center, quadrant: q }; - } - } - } - - function isOnEllipseStroke(point, radius, padding, quadrant) { - var vector = point.divide(radius); - return (!quadrant || vector.isInQuadrant(quadrant)) && - vector.subtract(vector.normalize()).multiply(radius) - .divide(padding).length <= 1; - } - - return { - _contains: function _contains(point) { - if (this._type === 'rectangle') { - var center = getCornerCenter(this, point); - return center - ? point.subtract(center.point).divide(this._radius) - .getLength() <= 1 - : _contains.base.call(this, point); - } else { - return point.divide(this.size).getLength() <= 0.5; - } - }, - - _hitTestSelf: function _hitTestSelf(point, options, viewMatrix, - strokeMatrix) { - var hit = false, - style = this._style, - hitStroke = options.stroke && style.hasStroke(), - hitFill = options.fill && style.hasFill(); - if (hitStroke || hitFill) { - var type = this._type, - radius = this._radius, - strokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0, - strokePadding = options._tolerancePadding.add( - Path._getStrokePadding(strokeRadius, - !style.getStrokeScaling() && strokeMatrix)); - if (type === 'rectangle') { - var padding = strokePadding.multiply(2), - center = getCornerCenter(this, point, padding); - if (center) { - hit = isOnEllipseStroke(point.subtract(center.point), - radius, strokePadding, center.quadrant); - } else { - var rect = new Rectangle(this._size).setCenter(0, 0), - outer = rect.expand(padding), - inner = rect.expand(padding.negate()); - hit = outer._containsPoint(point) - && !inner._containsPoint(point); - } - } else { - hit = isOnEllipseStroke(point, radius, strokePadding); - } - } - return hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this) - : _hitTestSelf.base.apply(this, arguments); - } - }; -}, { - -statics: new function() { - function createShape(type, point, size, radius, args) { - var item = new Shape(Base.getNamed(args), point); - item._type = type; - item._size = size; - item._radius = radius; - return item; - } - - return { - Circle: function() { - var center = Point.readNamed(arguments, 'center'), - radius = Base.readNamed(arguments, 'radius'); - return createShape('circle', center, new Size(radius * 2), radius, - arguments); - }, - - Rectangle: function() { - var rect = Rectangle.readNamed(arguments, 'rectangle'), - radius = Size.min(Size.readNamed(arguments, 'radius'), - rect.getSize(true).divide(2)); - return createShape('rectangle', rect.getCenter(true), - rect.getSize(true), radius, arguments); - }, - - Ellipse: function() { - var ellipse = Shape._readEllipse(arguments), - radius = ellipse.radius; - return createShape('ellipse', ellipse.center, radius.multiply(2), - radius, arguments); - }, - - _readEllipse: function(args) { - var center, - radius; - if (Base.hasNamed(args, 'radius')) { - center = Point.readNamed(args, 'center'); - radius = Size.readNamed(args, 'radius'); - } else { - var rect = Rectangle.readNamed(args, 'rectangle'); - center = rect.getCenter(true); - radius = rect.getSize(true).divide(2); - } - return { center: center, radius: radius }; - } - }; -}}); - -var Raster = Item.extend({ - _class: 'Raster', - _applyMatrix: false, - _canApplyMatrix: false, - _boundsOptions: { stroke: false, handle: false }, - _serializeFields: { - crossOrigin: null, - source: null - }, - _prioritize: ['crossOrigin'], - _smoothing: true, - - initialize: function Raster(object, position) { - if (!this._initialize(object, - position !== undefined && Point.read(arguments, 1))) { - var image = typeof object === 'string' - ? document.getElementById(object) : object; - if (image) { - this.setImage(image); - } else { - this.setSource(object); - } - } - if (!this._size) { - this._size = new Size(); - this._loaded = false; - } - }, - - _equals: function(item) { - return this.getSource() === item.getSource(); - }, - - copyContent: function(source) { - var image = source._image, - canvas = source._canvas; - if (image) { - this._setImage(image); - } else if (canvas) { - var copyCanvas = CanvasProvider.getCanvas(source._size); - copyCanvas.getContext('2d').drawImage(canvas, 0, 0); - this._setImage(copyCanvas); - } - this._crossOrigin = source._crossOrigin; - }, - - getSize: function() { - var size = this._size; - return new LinkedSize(size ? size.width : 0, size ? size.height : 0, - this, 'setSize'); - }, - - setSize: function() { - var size = Size.read(arguments); - if (!size.equals(this._size)) { - if (size.width > 0 && size.height > 0) { - var element = this.getElement(); - this._setImage(CanvasProvider.getCanvas(size)); - if (element) - this.getContext(true).drawImage(element, 0, 0, - size.width, size.height); - } else { - if (this._canvas) - CanvasProvider.release(this._canvas); - this._size = size.clone(); - } - } - }, - - getWidth: function() { - return this._size ? this._size.width : 0; - }, - - setWidth: function(width) { - this.setSize(width, this.getHeight()); - }, - - getHeight: function() { - return this._size ? this._size.height : 0; - }, - - setHeight: function(height) { - this.setSize(this.getWidth(), height); - }, - - getLoaded: function() { - return this._loaded; - }, - - isEmpty: function() { - var size = this._size; - return !size || size.width === 0 && size.height === 0; - }, - - getResolution: function() { - var matrix = this._matrix, - 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 new Size( - 72 / u.getLength(), - 72 / v.getLength() - ); - }, - - getPpi: '#getResolution', - - getImage: function() { - return this._image; - }, - - setImage: function(image) { - var that = this; - - function emit(event) { - var view = that.getView(), - type = event && event.type || 'load'; - if (view && that.responds(type)) { - paper = view._scope; - that.emit(type, new Event(event)); - } - } - - this._setImage(image); - if (this._loaded) { - setTimeout(emit, 0); - } else if (image) { - DomEvent.add(image, { - load: function(event) { - that._setImage(image); - emit(event); - }, - error: emit - }); - } - }, - - _setImage: function(image) { - if (this._canvas) - CanvasProvider.release(this._canvas); - if (image && image.getContext) { - this._image = null; - this._canvas = image; - this._loaded = true; - } else { - this._image = image; - this._canvas = null; - this._loaded = !!(image && image.src && image.complete); - } - this._size = new Size( - image ? image.naturalWidth || image.width : 0, - image ? image.naturalHeight || image.height : 0); - this._context = null; - this._changed(1033); - }, - - getCanvas: function() { - if (!this._canvas) { - var ctx = CanvasProvider.getContext(this._size); - try { - if (this._image) - ctx.drawImage(this._image, 0, 0); - this._canvas = ctx.canvas; - } catch (e) { - CanvasProvider.release(ctx); - } - } - return this._canvas; - }, - - setCanvas: '#setImage', - - getContext: function(modify) { - if (!this._context) - this._context = this.getCanvas().getContext('2d'); - if (modify) { - this._image = null; - this._changed(1025); - } - return this._context; - }, - - setContext: function(context) { - this._context = context; - }, - - getSource: function() { - var image = this._image; - return image && image.src || this.toDataURL(); - }, - - setSource: function(src) { - var image = new self.Image(), - crossOrigin = this._crossOrigin; - if (crossOrigin) - image.crossOrigin = crossOrigin; - image.src = src; - this.setImage(image); - }, - - getCrossOrigin: function() { - var image = this._image; - return image && image.crossOrigin || this._crossOrigin || ''; - }, - - setCrossOrigin: function(crossOrigin) { - this._crossOrigin = crossOrigin; - var image = this._image; - if (image) - image.crossOrigin = crossOrigin; - }, - - getSmoothing: function() { - return this._smoothing; - }, - - setSmoothing: function(smoothing) { - this._smoothing = smoothing; - this._changed(257); - }, - - getElement: function() { - return this._canvas || this._loaded && this._image; - } -}, { - beans: false, - - getSubCanvas: function() { - var rect = Rectangle.read(arguments), - ctx = CanvasProvider.getContext(rect.getSize()); - ctx.drawImage(this.getCanvas(), rect.x, rect.y, - rect.width, rect.height, 0, 0, rect.width, rect.height); - return ctx.canvas; - }, - - getSubRaster: function() { - var rect = Rectangle.read(arguments), - raster = new Raster(Item.NO_INSERT); - raster._setImage(this.getSubCanvas(rect)); - raster.translate(rect.getCenter().subtract(this.getSize().divide(2))); - raster._matrix.prepend(this._matrix); - raster.insertAbove(this); - return raster; - }, - - toDataURL: function() { - var image = this._image, - src = image && image.src; - if (/^data:/.test(src)) - return src; - var canvas = this.getCanvas(); - return canvas ? canvas.toDataURL.apply(canvas, arguments) : null; - }, - - drawImage: function(image ) { - var point = Point.read(arguments, 1); - this.getContext(true).drawImage(image, point.x, point.y); - }, - - getAverageColor: function(object) { - var bounds, path; - if (!object) { - bounds = this.getBounds(); - } else if (object instanceof PathItem) { - path = object; - bounds = object.getBounds(); - } else if (typeof object === 'object') { - if ('width' in object) { - bounds = new Rectangle(object); - } else if ('x' in object) { - bounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1); - } - } - if (!bounds) - return null; - var sampleSize = 32, - width = Math.min(bounds.width, sampleSize), - height = Math.min(bounds.height, sampleSize); - var ctx = Raster._sampleContext; - if (!ctx) { - ctx = Raster._sampleContext = CanvasProvider.getContext( - new Size(sampleSize)); - } else { - ctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1); - } - ctx.save(); - var matrix = new Matrix() - .scale(width / bounds.width, height / bounds.height) - .translate(-bounds.x, -bounds.y); - matrix.applyToContext(ctx); - if (path) - path.draw(ctx, new Base({ clip: true, matrices: [matrix] })); - this._matrix.applyToContext(ctx); - var element = this.getElement(), - size = this._size; - if (element) - ctx.drawImage(element, -size.width / 2, -size.height / 2); - ctx.restore(); - var pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width), - Math.ceil(height)).data, - channels = [0, 0, 0], - total = 0; - for (var i = 0, l = pixels.length; i < l; i += 4) { - var alpha = pixels[i + 3]; - total += alpha; - alpha /= 255; - channels[0] += pixels[i] * alpha; - channels[1] += pixels[i + 1] * alpha; - channels[2] += pixels[i + 2] * alpha; - } - for (var i = 0; i < 3; i++) - channels[i] /= total; - return total ? Color.read(channels) : null; - }, - - getPixel: function() { - var point = Point.read(arguments); - var data = this.getContext().getImageData(point.x, point.y, 1, 1).data; - return new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255], - data[3] / 255); - }, - - setPixel: function() { - var point = Point.read(arguments), - color = Color.read(arguments), - components = color._convert('rgb'), - alpha = color._alpha, - ctx = this.getContext(true), - imageData = ctx.createImageData(1, 1), - data = imageData.data; - data[0] = components[0] * 255; - data[1] = components[1] * 255; - data[2] = components[2] * 255; - data[3] = alpha != null ? alpha * 255 : 255; - ctx.putImageData(imageData, point.x, point.y); - }, - - createImageData: function() { - var size = Size.read(arguments); - return this.getContext().createImageData(size.width, size.height); - }, - - getImageData: function() { - var rect = Rectangle.read(arguments); - if (rect.isEmpty()) - rect = new Rectangle(this._size); - return this.getContext().getImageData(rect.x, rect.y, - rect.width, rect.height); - }, - - setImageData: function(data ) { - var point = Point.read(arguments, 1); - this.getContext(true).putImageData(data, point.x, point.y); - }, - - _getBounds: function(matrix, options) { - var rect = new Rectangle(this._size).setCenter(0, 0); - return matrix ? matrix._transformBounds(rect) : rect; - }, - - _hitTestSelf: function(point) { - if (this._contains(point)) { - var that = this; - return new HitResult('pixel', that, { - offset: point.add(that._size.divide(2)).round(), - color: { - get: function() { - return that.getPixel(this.offset); - } - } - }); - } - }, - - _draw: function(ctx, param, viewMatrix) { - var element = this.getElement(); - if (element) { - ctx.globalAlpha = this._opacity; - - this._setStyles(ctx, param, viewMatrix); - - DomElement.setPrefixed( - ctx, 'imageSmoothingEnabled', this._smoothing - ); - - ctx.drawImage(element, - -this._size.width / 2, -this._size.height / 2); - } - }, - - _canComposite: function() { - return true; - } -}); - -var SymbolItem = Item.extend({ - _class: 'SymbolItem', - _applyMatrix: false, - _canApplyMatrix: false, - _boundsOptions: { stroke: true }, - _serializeFields: { - symbol: null - }, - - initialize: function SymbolItem(arg0, arg1) { - if (!this._initialize(arg0, - arg1 !== undefined && Point.read(arguments, 1))) - this.setDefinition(arg0 instanceof SymbolDefinition ? - arg0 : new SymbolDefinition(arg0)); - }, - - _equals: function(item) { - return this._definition === item._definition; - }, - - copyContent: function(source) { - this.setDefinition(source._definition); - }, - - getDefinition: function() { - return this._definition; - }, - - setDefinition: function(definition) { - this._definition = definition; - this._changed(9); - }, - - getSymbol: '#getDefinition', - setSymbol: '#setDefinition', - - isEmpty: function() { - return this._definition._item.isEmpty(); - }, - - _getBounds: function(matrix, options) { - var item = this._definition._item; - return item._getCachedBounds(item._matrix.prepended(matrix), options); - }, - - _hitTestSelf: function(point, options, viewMatrix) { - var res = this._definition._item._hitTest(point, options, viewMatrix); - if (res) - res.item = this; - return res; - }, - - _draw: function(ctx, param) { - this._definition._item.draw(ctx, param); - } - -}); - -var SymbolDefinition = Base.extend({ - _class: 'SymbolDefinition', - - initialize: function SymbolDefinition(item, dontCenter) { - this._id = UID.get(); - this.project = paper.project; - if (item) - this.setItem(item, dontCenter); - }, - - _serialize: function(options, dictionary) { - return dictionary.add(this, function() { - return Base.serialize([this._class, this._item], - options, false, dictionary); - }); - }, - - _changed: function(flags) { - if (flags & 8) - Item._clearBoundsCache(this); - if (flags & 1) - this.project._changed(flags); - }, - - getItem: function() { - return this._item; - }, - - setItem: function(item, _dontCenter) { - if (item._symbol) - item = item.clone(); - if (this._item) - this._item._symbol = null; - this._item = item; - item.remove(); - item.setSelected(false); - if (!_dontCenter) - item.setPosition(new Point()); - item._symbol = this; - this._changed(9); - }, - - getDefinition: '#getItem', - setDefinition: '#setItem', - - place: function(position) { - return new SymbolItem(this, position); - }, - - clone: function() { - return new SymbolDefinition(this._item.clone(false)); - }, - - equals: function(symbol) { - return symbol === this - || symbol && this._item.equals(symbol._item) - || false; - } -}); - -var HitResult = Base.extend({ - _class: 'HitResult', - - initialize: function HitResult(type, item, values) { - this.type = type; - this.item = item; - if (values) - this.inject(values); - }, - - statics: { - getOptions: function(args) { - var options = args && Base.read(args); - return Base.set({ - type: null, - tolerance: paper.settings.hitTolerance, - fill: !options, - stroke: !options, - segments: !options, - handles: false, - ends: false, - position: false, - center: false, - bounds: false, - guides: false, - selected: false - }, options); - } - } -}); - -var Segment = Base.extend({ - _class: 'Segment', - beans: true, - _selection: 0, - - initialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) { - var count = arguments.length, - point, handleIn, handleOut, selection; - if (count > 0) { - if (arg0 == null || typeof arg0 === 'object') { - if (count === 1 && arg0 && 'point' in arg0) { - point = arg0.point; - handleIn = arg0.handleIn; - handleOut = arg0.handleOut; - selection = arg0.selection; - } else { - point = arg0; - handleIn = arg1; - handleOut = arg2; - selection = arg3; - } - } else { - point = [ arg0, arg1 ]; - handleIn = arg2 !== undefined ? [ arg2, arg3 ] : null; - handleOut = arg4 !== undefined ? [ arg4, arg5 ] : null; - } - } - new SegmentPoint(point, this, '_point'); - new SegmentPoint(handleIn, this, '_handleIn'); - new SegmentPoint(handleOut, this, '_handleOut'); - if (selection) - this.setSelection(selection); - }, - - _serialize: function(options, dictionary) { - var point = this._point, - selection = this._selection, - obj = selection || this.hasHandles() - ? [point, this._handleIn, this._handleOut] - : point; - if (selection) - obj.push(selection); - return Base.serialize(obj, options, true, dictionary); - }, - - _changed: function(point) { - var path = this._path; - if (!path) - return; - var curves = path._curves, - index = this._index, - curve; - if (curves) { - if ((!point || point === this._point || point === this._handleIn) - && (curve = index > 0 ? curves[index - 1] : path._closed - ? curves[curves.length - 1] : null)) - curve._changed(); - if ((!point || point === this._point || point === this._handleOut) - && (curve = curves[index])) - curve._changed(); - } - path._changed(41); - }, - - getPoint: function() { - return this._point; - }, - - setPoint: function() { - this._point.set(Point.read(arguments)); - }, - - getHandleIn: function() { - return this._handleIn; - }, - - setHandleIn: function() { - this._handleIn.set(Point.read(arguments)); - }, - - getHandleOut: function() { - return this._handleOut; - }, - - setHandleOut: function() { - this._handleOut.set(Point.read(arguments)); - }, - - hasHandles: function() { - return !this._handleIn.isZero() || !this._handleOut.isZero(); - }, - - isSmooth: function() { - var handleIn = this._handleIn, - handleOut = this._handleOut; - return !handleIn.isZero() && !handleOut.isZero() - && handleIn.isCollinear(handleOut); - }, - - clearHandles: function() { - this._handleIn._set(0, 0); - this._handleOut._set(0, 0); - }, - - getSelection: function() { - return this._selection; - }, - - setSelection: function(selection) { - var oldSelection = this._selection, - path = this._path; - this._selection = selection = selection || 0; - if (path && selection !== oldSelection) { - path._updateSelection(this, oldSelection, selection); - path._changed(257); - } - }, - - _changeSelection: function(flag, selected) { - var selection = this._selection; - this.setSelection(selected ? selection | flag : selection & ~flag); - }, - - isSelected: function() { - return !!(this._selection & 7); - }, - - setSelected: function(selected) { - this._changeSelection(7, selected); - }, - - getIndex: function() { - return this._index !== undefined ? this._index : null; - }, - - getPath: function() { - return this._path || null; - }, - - getCurve: function() { - var path = this._path, - index = this._index; - if (path) { - if (index > 0 && !path._closed - && index === path._segments.length - 1) - index--; - return path.getCurves()[index] || null; - } - return null; - }, - - getLocation: function() { - var curve = this.getCurve(); - return curve - ? new CurveLocation(curve, this === curve._segment1 ? 0 : 1) - : null; - }, - - getNext: function() { - var segments = this._path && this._path._segments; - return segments && (segments[this._index + 1] - || this._path._closed && segments[0]) || null; - }, - - smooth: function(options, _first, _last) { - var opts = options || {}, - type = opts.type, - factor = opts.factor, - prev = this.getPrevious(), - next = this.getNext(), - p0 = (prev || this)._point, - p1 = this._point, - p2 = (next || this)._point, - d1 = p0.getDistance(p1), - d2 = p1.getDistance(p2); - if (!type || type === 'catmull-rom') { - var a = factor === undefined ? 0.5 : factor, - d1_a = Math.pow(d1, a), - d1_2a = d1_a * d1_a, - d2_a = Math.pow(d2, a), - d2_2a = d2_a * d2_a; - if (!_first && prev) { - var A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a, - N = 3 * d2_a * (d2_a + d1_a); - this.setHandleIn(N !== 0 - ? new Point( - (d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x, - (d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y) - : new Point()); - } - if (!_last && next) { - var A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a, - N = 3 * d1_a * (d1_a + d2_a); - this.setHandleOut(N !== 0 - ? new Point( - (d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x, - (d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y) - : new Point()); - } - } else if (type === 'geometric') { - if (prev && next) { - var vector = p0.subtract(p2), - t = factor === undefined ? 0.4 : factor, - k = t * d1 / (d1 + d2); - if (!_first) - this.setHandleIn(vector.multiply(k)); - if (!_last) - this.setHandleOut(vector.multiply(k - t)); - } - } else { - throw new Error('Smoothing method \'' + type + '\' not supported.'); - } - }, - - getPrevious: function() { - var segments = this._path && this._path._segments; - return segments && (segments[this._index - 1] - || this._path._closed && segments[segments.length - 1]) || null; - }, - - isFirst: function() { - return !this._index; - }, - - isLast: function() { - var path = this._path; - return path && this._index === path._segments.length - 1 || false; - }, - - reverse: function() { - var handleIn = this._handleIn, - handleOut = this._handleOut, - tmp = handleIn.clone(); - handleIn.set(handleOut); - handleOut.set(tmp); - }, - - reversed: function() { - return new Segment(this._point, this._handleOut, this._handleIn); - }, - - remove: function() { - return this._path ? !!this._path.removeSegment(this._index) : false; - }, - - clone: function() { - return new Segment(this._point, this._handleIn, this._handleOut); - }, - - equals: function(segment) { - return segment === this || segment && this._class === segment._class - && this._point.equals(segment._point) - && this._handleIn.equals(segment._handleIn) - && this._handleOut.equals(segment._handleOut) - || false; - }, - - toString: function() { - var parts = [ 'point: ' + this._point ]; - if (!this._handleIn.isZero()) - parts.push('handleIn: ' + this._handleIn); - if (!this._handleOut.isZero()) - parts.push('handleOut: ' + this._handleOut); - return '{ ' + parts.join(', ') + ' }'; - }, - - transform: function(matrix) { - this._transformCoordinates(matrix, new Array(6), true); - this._changed(); - }, - - interpolate: function(from, to, factor) { - var u = 1 - factor, - v = factor, - point1 = from._point, - point2 = to._point, - handleIn1 = from._handleIn, - handleIn2 = to._handleIn, - handleOut2 = to._handleOut, - handleOut1 = from._handleOut; - this._point._set( - u * point1._x + v * point2._x, - u * point1._y + v * point2._y, true); - this._handleIn._set( - u * handleIn1._x + v * handleIn2._x, - u * handleIn1._y + v * handleIn2._y, true); - this._handleOut._set( - u * handleOut1._x + v * handleOut2._x, - u * handleOut1._y + v * handleOut2._y, true); - this._changed(); - }, - - _transformCoordinates: function(matrix, coords, change) { - var point = this._point, - handleIn = !change || !this._handleIn.isZero() - ? this._handleIn : null, - handleOut = !change || !this._handleOut.isZero() - ? this._handleOut : null, - x = point._x, - y = point._y, - i = 2; - coords[0] = x; - coords[1] = y; - if (handleIn) { - coords[i++] = handleIn._x + x; - coords[i++] = handleIn._y + y; - } - if (handleOut) { - coords[i++] = handleOut._x + x; - coords[i++] = handleOut._y + y; - } - if (matrix) { - matrix._transformCoordinates(coords, coords, i / 2); - x = coords[0]; - y = coords[1]; - if (change) { - point._x = x; - point._y = y; - i = 2; - if (handleIn) { - handleIn._x = coords[i++] - x; - handleIn._y = coords[i++] - y; - } - if (handleOut) { - handleOut._x = coords[i++] - x; - handleOut._y = coords[i++] - y; - } - } else { - if (!handleIn) { - coords[i++] = x; - coords[i++] = y; - } - if (!handleOut) { - coords[i++] = x; - coords[i++] = y; - } - } - } - return coords; - } -}); - -var SegmentPoint = Point.extend({ - initialize: function SegmentPoint(point, owner, key) { - var x, y, - selected; - if (!point) { - x = y = 0; - } else if ((x = point[0]) !== undefined) { - y = point[1]; - } else { - var pt = point; - if ((x = pt.x) === undefined) { - pt = Point.read(arguments); - x = pt.x; - } - y = pt.y; - selected = pt.selected; - } - this._x = x; - this._y = y; - this._owner = owner; - owner[key] = this; - if (selected) - this.setSelected(true); - }, - - _set: function(x, y) { - this._x = x; - this._y = y; - this._owner._changed(this); - return this; - }, - - getX: function() { - return this._x; - }, - - setX: function(x) { - this._x = x; - this._owner._changed(this); - }, - - getY: function() { - return this._y; - }, - - setY: function(y) { - this._y = y; - this._owner._changed(this); - }, - - isZero: function() { - var isZero = Numerical.isZero; - return isZero(this._x) && isZero(this._y); - }, - - isSelected: function() { - return !!(this._owner._selection & this._getSelection()); - }, - - setSelected: function(selected) { - this._owner._changeSelection(this._getSelection(), selected); - }, - - _getSelection: function() { - var owner = this._owner; - return this === owner._point ? 1 - : this === owner._handleIn ? 2 - : this === owner._handleOut ? 4 - : 0; - } -}); - -var Curve = Base.extend({ - _class: 'Curve', - beans: true, - - initialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { - var count = arguments.length, - seg1, seg2, - point1, point2, - handle1, handle2; - if (count === 3) { - this._path = arg0; - seg1 = arg1; - seg2 = arg2; - } else if (!count) { - seg1 = new Segment(); - seg2 = new Segment(); - } else if (count === 1) { - if ('segment1' in arg0) { - seg1 = new Segment(arg0.segment1); - seg2 = new Segment(arg0.segment2); - } else if ('point1' in arg0) { - point1 = arg0.point1; - handle1 = arg0.handle1; - handle2 = arg0.handle2; - point2 = arg0.point2; - } else if (Array.isArray(arg0)) { - point1 = [arg0[0], arg0[1]]; - point2 = [arg0[6], arg0[7]]; - handle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]]; - handle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]]; - } - } else if (count === 2) { - seg1 = new Segment(arg0); - seg2 = new Segment(arg1); - } else if (count === 4) { - point1 = arg0; - handle1 = arg1; - handle2 = arg2; - point2 = arg3; - } else if (count === 8) { - point1 = [arg0, arg1]; - point2 = [arg6, arg7]; - handle1 = [arg2 - arg0, arg3 - arg1]; - handle2 = [arg4 - arg6, arg5 - arg7]; - } - this._segment1 = seg1 || new Segment(point1, null, handle1); - this._segment2 = seg2 || new Segment(point2, handle2, null); - }, - - _serialize: function(options, dictionary) { - return Base.serialize(this.hasHandles() - ? [this.getPoint1(), this.getHandle1(), this.getHandle2(), - this.getPoint2()] - : [this.getPoint1(), this.getPoint2()], - options, true, dictionary); - }, - - _changed: function() { - this._length = this._bounds = undefined; - }, - - clone: function() { - return new Curve(this._segment1, this._segment2); - }, - - toString: function() { - var parts = [ 'point1: ' + this._segment1._point ]; - if (!this._segment1._handleOut.isZero()) - parts.push('handle1: ' + this._segment1._handleOut); - if (!this._segment2._handleIn.isZero()) - parts.push('handle2: ' + this._segment2._handleIn); - parts.push('point2: ' + this._segment2._point); - return '{ ' + parts.join(', ') + ' }'; - }, - - classify: function() { - return Curve.classify(this.getValues()); - }, - - remove: function() { - var removed = false; - if (this._path) { - var segment2 = this._segment2, - handleOut = segment2._handleOut; - removed = segment2.remove(); - if (removed) - this._segment1._handleOut.set(handleOut); - } - return removed; - }, - - getPoint1: function() { - return this._segment1._point; - }, - - setPoint1: function() { - this._segment1._point.set(Point.read(arguments)); - }, - - getPoint2: function() { - return this._segment2._point; - }, - - setPoint2: function() { - this._segment2._point.set(Point.read(arguments)); - }, - - getHandle1: function() { - return this._segment1._handleOut; - }, - - setHandle1: function() { - this._segment1._handleOut.set(Point.read(arguments)); - }, - - getHandle2: function() { - return this._segment2._handleIn; - }, - - setHandle2: function() { - this._segment2._handleIn.set(Point.read(arguments)); - }, - - getSegment1: function() { - return this._segment1; - }, - - getSegment2: function() { - return this._segment2; - }, - - getPath: function() { - return this._path; - }, - - getIndex: function() { - return this._segment1._index; - }, - - getNext: function() { - var curves = this._path && this._path._curves; - return curves && (curves[this._segment1._index + 1] - || this._path._closed && curves[0]) || null; - }, - - getPrevious: function() { - var curves = this._path && this._path._curves; - return curves && (curves[this._segment1._index - 1] - || this._path._closed && curves[curves.length - 1]) || null; - }, - - isFirst: function() { - return !this._segment1._index; - }, - - isLast: function() { - var path = this._path; - return path && this._segment1._index === path._curves.length - 1 - || false; - }, - - isSelected: function() { - return this.getPoint1().isSelected() - && this.getHandle1().isSelected() - && this.getHandle2().isSelected() - && this.getPoint2().isSelected(); - }, - - setSelected: function(selected) { - this.getPoint1().setSelected(selected); - this.getHandle1().setSelected(selected); - this.getHandle2().setSelected(selected); - this.getPoint2().setSelected(selected); - }, - - getValues: function(matrix) { - return Curve.getValues(this._segment1, this._segment2, matrix); - }, - - getPoints: function() { - var coords = this.getValues(), - points = []; - for (var i = 0; i < 8; i += 2) - points.push(new Point(coords[i], coords[i + 1])); - return points; - } -}, { - getLength: function() { - if (this._length == null) - this._length = Curve.getLength(this.getValues(), 0, 1); - return this._length; - }, - - getArea: function() { - return Curve.getArea(this.getValues()); - }, - - getLine: function() { - return new Line(this._segment1._point, this._segment2._point); - }, - - getPart: function(from, to) { - return new Curve(Curve.getPart(this.getValues(), from, to)); - }, - - getPartLength: function(from, to) { - return Curve.getLength(this.getValues(), from, to); - }, - - divideAt: function(location) { - return this.divideAtTime(location && location.curve === this - ? location.time : this.getTimeAt(location)); - }, - - divideAtTime: function(time, _setHandles) { - var tMin = 1e-8, - tMax = 1 - tMin, - res = null; - if (time >= tMin && time <= tMax) { - var parts = Curve.subdivide(this.getValues(), time), - left = parts[0], - right = parts[1], - setHandles = _setHandles || this.hasHandles(), - seg1 = this._segment1, - seg2 = this._segment2, - path = this._path; - if (setHandles) { - seg1._handleOut._set(left[2] - left[0], left[3] - left[1]); - seg2._handleIn._set(right[4] - right[6],right[5] - right[7]); - } - var x = left[6], y = left[7], - segment = new Segment(new Point(x, y), - setHandles && new Point(left[4] - x, left[5] - y), - setHandles && new Point(right[2] - x, right[3] - y)); - if (path) { - path.insert(seg1._index + 1, segment); - res = this.getNext(); - } else { - this._segment2 = segment; - this._changed(); - res = new Curve(segment, seg2); - } - } - return res; - }, - - splitAt: function(location) { - var path = this._path; - return path ? path.splitAt(location) : null; - }, - - splitAtTime: function(time) { - return this.splitAt(this.getLocationAtTime(time)); - }, - - divide: function(offset, isTime) { - return this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset - : this.getTimeAt(offset)); - }, - - split: function(offset, isTime) { - return this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset - : this.getTimeAt(offset)); - }, - - reversed: function() { - return new Curve(this._segment2.reversed(), this._segment1.reversed()); - }, - - clearHandles: function() { - this._segment1._handleOut._set(0, 0); - this._segment2._handleIn._set(0, 0); - }, - -statics: { - getValues: function(segment1, segment2, matrix, straight) { - var p1 = segment1._point, - h1 = segment1._handleOut, - h2 = segment2._handleIn, - p2 = segment2._point, - x1 = p1.x, y1 = p1.y, - x2 = p2.x, y2 = p2.y, - values = straight - ? [ x1, y1, x1, y1, x2, y2, x2, y2 ] - : [ - x1, y1, - x1 + h1._x, y1 + h1._y, - x2 + h2._x, y2 + h2._y, - x2, y2 - ]; - if (matrix) - matrix._transformCoordinates(values, values, 4); - return values; - }, - - subdivide: function(v, t) { - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7]; - if (t === undefined) - t = 0.5; - var u = 1 - t, - x4 = u * x0 + t * x1, y4 = u * y0 + t * y1, - x5 = u * x1 + t * x2, y5 = u * y1 + t * y2, - x6 = u * x2 + t * x3, y6 = u * y2 + t * y3, - x7 = u * x4 + t * x5, y7 = u * y4 + t * y5, - x8 = u * x5 + t * x6, y8 = u * y5 + t * y6, - x9 = u * x7 + t * x8, y9 = u * y7 + t * y8; - return [ - [x0, y0, x4, y4, x7, y7, x9, y9], - [x9, y9, x8, y8, x6, y6, x3, y3] - ]; - }, - - getMonoCurves: function(v, dir) { - var curves = [], - io = dir ? 0 : 1, - o0 = v[io + 0], - o1 = v[io + 2], - o2 = v[io + 4], - o3 = v[io + 6]; - if ((o0 >= o1) === (o1 >= o2) && (o1 >= o2) === (o2 >= o3) - || Curve.isStraight(v)) { - curves.push(v); - } else { - var a = 3 * (o1 - o2) - o0 + o3, - b = 2 * (o0 + o2) - 4 * o1, - c = o1 - o0, - tMin = 1e-8, - tMax = 1 - tMin, - roots = [], - n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax); - if (!n) { - curves.push(v); - } else { - roots.sort(); - var t = roots[0], - parts = Curve.subdivide(v, t); - curves.push(parts[0]); - if (n > 1) { - t = (roots[1] - t) / (1 - t); - parts = Curve.subdivide(parts[1], t); - curves.push(parts[0]); - } - curves.push(parts[1]); - } - } - return curves; - }, - - solveCubic: function (v, coord, val, roots, min, max) { - var v0 = v[coord], - v1 = v[coord + 2], - v2 = v[coord + 4], - v3 = v[coord + 6], - res = 0; - if ( !(v0 < val && v3 < val && v1 < val && v2 < val || - v0 > val && v3 > val && v1 > val && v2 > val)) { - var c = 3 * (v1 - v0), - b = 3 * (v2 - v1) - c, - a = v3 - v0 - c - b; - res = Numerical.solveCubic(a, b, c, v0 - val, roots, min, max); - } - return res; - }, - - getTimeOf: function(v, point) { - var p0 = new Point(v[0], v[1]), - p3 = new Point(v[6], v[7]), - epsilon = 1e-12, - geomEpsilon = 1e-7, - t = point.isClose(p0, epsilon) ? 0 - : point.isClose(p3, epsilon) ? 1 - : null; - if (t === null) { - var coords = [point.x, point.y], - roots = []; - for (var c = 0; c < 2; c++) { - var count = Curve.solveCubic(v, c, coords[c], roots, 0, 1); - for (var i = 0; i < count; i++) { - var u = roots[i]; - if (point.isClose(Curve.getPoint(v, u), geomEpsilon)) - return u; - } - } - } - return point.isClose(p0, geomEpsilon) ? 0 - : point.isClose(p3, geomEpsilon) ? 1 - : null; - }, - - getNearestTime: function(v, point) { - if (Curve.isStraight(v)) { - var x0 = v[0], y0 = v[1], - x3 = v[6], y3 = v[7], - vx = x3 - x0, vy = y3 - y0, - det = vx * vx + vy * vy; - if (det === 0) - return 0; - var u = ((point.x - x0) * vx + (point.y - y0) * vy) / det; - return u < 1e-12 ? 0 - : u > 0.999999999999 ? 1 - : Curve.getTimeOf(v, - new Point(x0 + u * vx, y0 + u * vy)); - } - - var count = 100, - minDist = Infinity, - minT = 0; - - function refine(t) { - if (t >= 0 && t <= 1) { - var dist = point.getDistance(Curve.getPoint(v, t), true); - if (dist < minDist) { - minDist = dist; - minT = t; - return true; - } - } - } - - for (var i = 0; i <= count; i++) - refine(i / count); - - var step = 1 / (count * 2); - while (step > 1e-8) { - if (!refine(minT - step) && !refine(minT + step)) - step /= 2; - } - return minT; - }, - - getPart: function(v, from, to) { - var flip = from > to; - if (flip) { - var tmp = from; - from = to; - to = tmp; - } - if (from > 0) - v = Curve.subdivide(v, from)[1]; - if (to < 1) - v = Curve.subdivide(v, (to - from) / (1 - from))[0]; - return flip - ? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]] - : v; - }, - - isFlatEnough: function(v, flatness) { - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7], - ux = 3 * x1 - 2 * x0 - x3, - uy = 3 * y1 - 2 * y0 - y3, - vx = 3 * x2 - 2 * x3 - x0, - vy = 3 * y2 - 2 * y3 - y0; - return Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy) - <= 16 * flatness * flatness; - }, - - getArea: function(v) { - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7]; - return 3 * ((y3 - y0) * (x1 + x2) - (x3 - x0) * (y1 + y2) - + y1 * (x0 - x2) - x1 * (y0 - y2) - + y3 * (x2 + x0 / 3) - x3 * (y2 + y0 / 3)) / 20; - }, - - getBounds: function(v) { - var min = v.slice(0, 2), - max = min.slice(), - roots = [0, 0]; - 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 new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]); - }, - - _addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) { - function add(value, padding) { - var left = value - padding, - right = value + padding; - if (left < min[coord]) - min[coord] = left; - if (right > max[coord]) - max[coord] = right; - } - - padding /= 2; - var minPad = min[coord] - padding, - maxPad = max[coord] + padding; - if ( v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad || - v0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) { - if (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) { - add(v0, padding); - add(v3, padding); - } else { - var a = 3 * (v1 - v2) - v0 + v3, - b = 2 * (v0 + v2) - 4 * v1, - c = v1 - v0, - count = Numerical.solveQuadratic(a, b, c, roots), - tMin = 1e-8, - tMax = 1 - tMin; - add(v3, 0); - for (var i = 0; i < count; i++) { - var t = roots[i], - u = 1 - t; - if (tMin <= t && t <= tMax) - add(u * u * u * v0 - + 3 * u * u * t * v1 - + 3 * u * t * t * v2 - + t * t * t * v3, - padding); - } - } - } - } -}}, Base.each( - ['getBounds', 'getStrokeBounds', 'getHandleBounds'], - function(name) { - this[name] = function() { - if (!this._bounds) - this._bounds = {}; - var bounds = this._bounds[name]; - if (!bounds) { - bounds = this._bounds[name] = Path[name]( - [this._segment1, this._segment2], false, this._path); - } - return bounds.clone(); - }; - }, -{ - -}), Base.each({ - isStraight: function(p1, h1, h2, p2) { - if (h1.isZero() && h2.isZero()) { - return true; - } else { - var v = p2.subtract(p1); - if (v.isZero()) { - return false; - } else if (v.isCollinear(h1) && v.isCollinear(h2)) { - var l = new Line(p1, p2), - epsilon = 1e-7; - if (l.getDistance(p1.add(h1)) < epsilon && - l.getDistance(p2.add(h2)) < epsilon) { - var div = v.dot(v), - s1 = v.dot(h1) / div, - s2 = v.dot(h2) / div; - return s1 >= 0 && s1 <= 1 && s2 <= 0 && s2 >= -1; - } - } - } - return false; - }, - - isLinear: function(p1, h1, h2, p2) { - var third = p2.subtract(p1).divide(3); - return h1.equals(third) && h2.negate().equals(third); - } -}, function(test, name) { - this[name] = function(epsilon) { - var seg1 = this._segment1, - seg2 = this._segment2; - return test(seg1._point, seg1._handleOut, seg2._handleIn, seg2._point, - epsilon); - }; - - this.statics[name] = function(v, epsilon) { - var x0 = v[0], y0 = v[1], - x3 = v[6], y3 = v[7]; - return test( - new Point(x0, y0), - new Point(v[2] - x0, v[3] - y0), - new Point(v[4] - x3, v[5] - y3), - new Point(x3, y3), epsilon); - }; -}, { - statics: {}, - - hasHandles: function() { - return !this._segment1._handleOut.isZero() - || !this._segment2._handleIn.isZero(); - }, - - hasLength: function(epsilon) { - return (!this.getPoint1().equals(this.getPoint2()) || this.hasHandles()) - && this.getLength() > (epsilon || 0); - }, - - isCollinear: function(curve) { - return curve && this.isStraight() && curve.isStraight() - && this.getLine().isCollinear(curve.getLine()); - }, - - isHorizontal: function() { - return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y) - < 1e-8; - }, - - isVertical: function() { - return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x) - < 1e-8; - } -}), { - beans: false, - - getLocationAt: function(offset, _isTime) { - return this.getLocationAtTime( - _isTime ? offset : this.getTimeAt(offset)); - }, - - getLocationAtTime: function(t) { - return t != null && t >= 0 && t <= 1 - ? new CurveLocation(this, t) - : null; - }, - - getTimeAt: function(offset, start) { - return Curve.getTimeAt(this.getValues(), offset, start); - }, - - getParameterAt: '#getTimeAt', - - getTimesWithTangent: function () { - var tangent = Point.read(arguments); - return tangent.isZero() - ? [] - : Curve.getTimesWithTangent(this.getValues(), tangent); - }, - - getOffsetAtTime: function(t) { - return this.getPartLength(0, t); - }, - - getLocationOf: function() { - return this.getLocationAtTime(this.getTimeOf(Point.read(arguments))); - }, - - getOffsetOf: function() { - var loc = this.getLocationOf.apply(this, arguments); - return loc ? loc.getOffset() : null; - }, - - getTimeOf: function() { - return Curve.getTimeOf(this.getValues(), Point.read(arguments)); - }, - - getParameterOf: '#getTimeOf', - - getNearestLocation: function() { - var point = Point.read(arguments), - values = this.getValues(), - t = Curve.getNearestTime(values, point), - pt = Curve.getPoint(values, t); - return new CurveLocation(this, t, pt, null, point.getDistance(pt)); - }, - - getNearestPoint: function() { - var loc = this.getNearestLocation.apply(this, arguments); - return loc ? loc.getPoint() : loc; - } - -}, -new function() { - var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent', - 'getWeightedNormal', 'getCurvature']; - return Base.each(methods, - function(name) { - this[name + 'At'] = function(location, _isTime) { - var values = this.getValues(); - return Curve[name](values, _isTime ? location - : Curve.getTimeAt(values, location)); - }; - - this[name + 'AtTime'] = function(time) { - return Curve[name](this.getValues(), time); - }; - }, { - statics: { - _evaluateMethods: methods - } - } - ); -}, -new function() { - - function getLengthIntegrand(v) { - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7], - - ax = 9 * (x1 - x2) + 3 * (x3 - x0), - bx = 6 * (x0 + x2) - 12 * x1, - cx = 3 * (x1 - x0), - - ay = 9 * (y1 - y2) + 3 * (y3 - y0), - by = 6 * (y0 + y2) - 12 * y1, - cy = 3 * (y1 - y0); - - return function(t) { - var dx = (ax * t + bx) * t + cx, - dy = (ay * t + by) * t + cy; - return Math.sqrt(dx * dx + dy * dy); - }; - } - - function getIterations(a, b) { - return Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32))); - } - - function evaluate(v, t, type, normalized) { - if (t == null || t < 0 || t > 1) - return null; - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7], - isZero = Numerical.isZero; - if (isZero(x1 - x0) && isZero(y1 - y0)) { - x1 = x0; - y1 = y0; - } - if (isZero(x2 - x3) && isZero(y2 - y3)) { - x2 = x3; - y2 = y3; - } - var cx = 3 * (x1 - x0), - bx = 3 * (x2 - x1) - cx, - ax = x3 - x0 - cx - bx, - cy = 3 * (y1 - y0), - by = 3 * (y2 - y1) - cy, - ay = y3 - y0 - cy - by, - x, y; - if (type === 0) { - x = t === 0 ? x0 : t === 1 ? x3 - : ((ax * t + bx) * t + cx) * t + x0; - y = t === 0 ? y0 : t === 1 ? y3 - : ((ay * t + by) * t + cy) * t + y0; - } else { - var tMin = 1e-8, - tMax = 1 - tMin; - if (t < tMin) { - x = cx; - y = cy; - } else if (t > tMax) { - x = 3 * (x3 - x2); - y = 3 * (y3 - y2); - } else { - x = (3 * ax * t + 2 * bx) * t + cx; - y = (3 * ay * t + 2 * by) * t + cy; - } - if (normalized) { - if (x === 0 && y === 0 && (t < tMin || t > tMax)) { - x = x2 - x1; - y = y2 - y1; - } - var len = Math.sqrt(x * x + y * y); - if (len) { - x /= len; - y /= len; - } - } - if (type === 3) { - var x2 = 6 * ax * t + 2 * bx, - y2 = 6 * ay * t + 2 * by, - d = Math.pow(x * x + y * y, 3 / 2); - x = d !== 0 ? (x * y2 - y * x2) / d : 0; - y = 0; - } - } - return type === 2 ? new Point(y, -x) : new Point(x, y); - } - - return { statics: { - - classify: function(v) { - - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7], - a1 = x0 * (y3 - y2) + y0 * (x2 - x3) + x3 * y2 - y3 * x2, - a2 = x1 * (y0 - y3) + y1 * (x3 - x0) + x0 * y3 - y0 * x3, - a3 = x2 * (y1 - y0) + y2 * (x0 - x1) + x1 * y0 - y1 * x0, - d3 = 3 * a3, - d2 = d3 - a2, - d1 = d2 - a2 + a1, - l = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3), - s = l !== 0 ? 1 / l : 0, - isZero = Numerical.isZero, - serpentine = 'serpentine'; - d1 *= s; - d2 *= s; - d3 *= s; - - function type(type, t1, t2) { - var hasRoots = t1 !== undefined, - t1Ok = hasRoots && t1 > 0 && t1 < 1, - t2Ok = hasRoots && t2 > 0 && t2 < 1; - if (hasRoots && (!(t1Ok || t2Ok) - || type === 'loop' && !(t1Ok && t2Ok))) { - type = 'arch'; - t1Ok = t2Ok = false; - } - return { - type: type, - roots: t1Ok || t2Ok - ? t1Ok && t2Ok - ? t1 < t2 ? [t1, t2] : [t2, t1] - : [t1Ok ? t1 : t2] - : null - }; - } - - if (isZero(d1)) { - return isZero(d2) - ? type(isZero(d3) ? 'line' : 'quadratic') - : type(serpentine, d3 / (3 * d2)); - } - var d = 3 * d2 * d2 - 4 * d1 * d3; - if (isZero(d)) { - return type('cusp', d2 / (2 * d1)); - } - var f1 = d > 0 ? Math.sqrt(d / 3) : Math.sqrt(-d), - f2 = 2 * d1; - return type(d > 0 ? serpentine : 'loop', - (d2 + f1) / f2, - (d2 - f1) / f2); - }, - - getLength: function(v, a, b, ds) { - if (a === undefined) - a = 0; - if (b === undefined) - b = 1; - if (Curve.isStraight(v)) { - var c = v; - if (b < 1) { - c = Curve.subdivide(c, b)[0]; - a /= b; - } - if (a > 0) { - c = Curve.subdivide(c, a)[1]; - } - var dx = c[6] - c[0], - dy = c[7] - c[1]; - return Math.sqrt(dx * dx + dy * dy); - } - return Numerical.integrate(ds || getLengthIntegrand(v), a, b, - getIterations(a, b)); - }, - - getTimeAt: function(v, offset, start) { - if (start === undefined) - start = offset < 0 ? 1 : 0; - if (offset === 0) - return start; - var abs = Math.abs, - epsilon = 1e-12, - forward = offset > 0, - a = forward ? start : 0, - b = forward ? 1 : start, - ds = getLengthIntegrand(v), - rangeLength = Curve.getLength(v, a, b, ds), - diff = abs(offset) - rangeLength; - if (abs(diff) < epsilon) { - return forward ? b : a; - } else if (diff > epsilon) { - return null; - } - var guess = offset / rangeLength, - length = 0; - function f(t) { - length += Numerical.integrate(ds, start, t, - getIterations(start, t)); - start = t; - return length - offset; - } - return Numerical.findRoot(f, ds, start + guess, a, b, 32, - 1e-12); - }, - - getPoint: function(v, t) { - return evaluate(v, t, 0, false); - }, - - getTangent: function(v, t) { - return evaluate(v, t, 1, true); - }, - - getWeightedTangent: function(v, t) { - return evaluate(v, t, 1, false); - }, - - getNormal: function(v, t) { - return evaluate(v, t, 2, true); - }, - - getWeightedNormal: function(v, t) { - return evaluate(v, t, 2, false); - }, - - getCurvature: function(v, t) { - return evaluate(v, t, 3, false).x; - }, - - getPeaks: function(v) { - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7], - ax = -x0 + 3 * x1 - 3 * x2 + x3, - bx = 3 * x0 - 6 * x1 + 3 * x2, - cx = -3 * x0 + 3 * x1, - ay = -y0 + 3 * y1 - 3 * y2 + y3, - by = 3 * y0 - 6 * y1 + 3 * y2, - cy = -3 * y0 + 3 * y1, - tMin = 1e-8, - tMax = 1 - tMin, - roots = []; - Numerical.solveCubic( - 9 * (ax * ax + ay * ay), - 9 * (ax * bx + by * ay), - 2 * (bx * bx + by * by) + 3 * (cx * ax + cy * ay), - (cx * bx + by * cy), - roots, tMin, tMax); - return roots.sort(); - } - }}; -}, -new function() { - - function addLocation(locations, include, c1, t1, c2, t2, overlap) { - var excludeStart = !overlap && c1.getPrevious() === c2, - excludeEnd = !overlap && c1 !== c2 && c1.getNext() === c2, - tMin = 1e-8, - tMax = 1 - tMin; - if (t1 !== null && t1 >= (excludeStart ? tMin : 0) && - t1 <= (excludeEnd ? tMax : 1)) { - if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) && - t2 <= (excludeStart ? tMax : 1)) { - var loc1 = new CurveLocation(c1, t1, null, overlap), - loc2 = new CurveLocation(c2, t2, null, overlap); - loc1._intersection = loc2; - loc2._intersection = loc1; - if (!include || include(loc1)) { - CurveLocation.insert(locations, loc1, true); - } - } - } - } - - function addCurveIntersections(v1, v2, c1, c2, locations, include, flip, - recursion, calls, tMin, tMax, uMin, uMax) { - if (++calls >= 4096 || ++recursion >= 40) - return calls; - var fatLineEpsilon = 1e-9, - q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7], - getSignedDistance = Line.getSignedDistance, - d1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]), - d2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]), - factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9, - dMin = factor * Math.min(0, d1, d2), - dMax = factor * Math.max(0, d1, d2), - dp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]), - dp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]), - dp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]), - dp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]), - hull = getConvexHull(dp0, dp1, dp2, dp3), - top = hull[0], - bottom = hull[1], - tMinClip, - tMaxClip; - if (d1 === 0 && d2 === 0 - && dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0 - || (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null - || (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(), - dMin, dMax)) == null) - return calls; - var tMinNew = tMin + (tMax - tMin) * tMinClip, - tMaxNew = tMin + (tMax - tMin) * tMaxClip; - if (Math.max(uMax - uMin, tMaxNew - tMinNew) < fatLineEpsilon) { - var t = (tMinNew + tMaxNew) / 2, - u = (uMin + uMax) / 2; - addLocation(locations, include, - flip ? c2 : c1, flip ? u : t, - flip ? c1 : c2, flip ? t : u); - } else { - v1 = Curve.getPart(v1, tMinClip, tMaxClip); - if (tMaxClip - tMinClip > 0.8) { - if (tMaxNew - tMinNew > uMax - uMin) { - var parts = Curve.subdivide(v1, 0.5), - t = (tMinNew + tMaxNew) / 2; - calls = addCurveIntersections( - v2, parts[0], c2, c1, locations, include, !flip, - recursion, calls, uMin, uMax, tMinNew, t); - calls = addCurveIntersections( - v2, parts[1], c2, c1, locations, include, !flip, - recursion, calls, uMin, uMax, t, tMaxNew); - } else { - var parts = Curve.subdivide(v2, 0.5), - u = (uMin + uMax) / 2; - calls = addCurveIntersections( - parts[0], v1, c2, c1, locations, include, !flip, - recursion, calls, uMin, u, tMinNew, tMaxNew); - calls = addCurveIntersections( - parts[1], v1, c2, c1, locations, include, !flip, - recursion, calls, u, uMax, tMinNew, tMaxNew); - } - } else { - if (uMax - uMin >= fatLineEpsilon) { - calls = addCurveIntersections( - v2, v1, c2, c1, locations, include, !flip, - recursion, calls, uMin, uMax, tMinNew, tMaxNew); - } else { - calls = addCurveIntersections( - v1, v2, c1, c2, locations, include, flip, - recursion, calls, tMinNew, tMaxNew, uMin, uMax); - } - } - } - return calls; - } - - function getConvexHull(dq0, dq1, dq2, dq3) { - var p0 = [ 0, dq0 ], - p1 = [ 1 / 3, dq1 ], - p2 = [ 2 / 3, dq2 ], - p3 = [ 1, dq3 ], - dist1 = dq1 - (2 * dq0 + dq3) / 3, - dist2 = dq2 - (dq0 + 2 * dq3) / 3, - hull; - if (dist1 * dist2 < 0) { - hull = [[p0, p1, p3], [p0, p2, p3]]; - } else { - var distRatio = dist1 / dist2; - hull = [ - distRatio >= 2 ? [p0, p1, p3] - : distRatio <= 0.5 ? [p0, p2, p3] - : [p0, p1, p2, p3], - [p0, p3] - ]; - } - return (dist1 || dist2) < 0 ? hull.reverse() : hull; - } - - function clipConvexHull(hullTop, hullBottom, dMin, dMax) { - if (hullTop[0][1] < dMin) { - return clipConvexHullPart(hullTop, true, dMin); - } else if (hullBottom[0][1] > dMax) { - return clipConvexHullPart(hullBottom, false, dMax); - } else { - return hullTop[0][0]; - } - } - - function clipConvexHullPart(part, top, threshold) { - var px = part[0][0], - py = part[0][1]; - for (var i = 1, l = part.length; i < l; i++) { - var qx = part[i][0], - qy = part[i][1]; - if (top ? qy >= threshold : qy <= threshold) { - return qy === threshold ? qx - : px + (threshold - py) * (qx - px) / (qy - py); - } - px = qx; - py = qy; - } - return null; - } - - function getCurveLineIntersections(v, px, py, vx, vy) { - var isZero = Numerical.isZero; - if (isZero(vx) && isZero(vy)) { - var t = Curve.getTimeOf(v, new Point(px, py)); - return t === null ? [] : [t]; - } - var angle = Math.atan2(-vy, vx), - sin = Math.sin(angle), - cos = Math.cos(angle), - rv = [], - roots = []; - for (var i = 0; i < 8; i += 2) { - var x = v[i] - px, - y = v[i + 1] - py; - rv.push( - x * cos - y * sin, - x * sin + y * cos); - } - Curve.solveCubic(rv, 1, 0, roots, 0, 1); - return roots; - } - - function addCurveLineIntersections(v1, v2, c1, c2, locations, include, - flip) { - var x1 = v2[0], y1 = v2[1], - x2 = v2[6], y2 = v2[7], - roots = getCurveLineIntersections(v1, x1, y1, x2 - x1, y2 - y1); - for (var i = 0, l = roots.length; i < l; i++) { - var t1 = roots[i], - p1 = Curve.getPoint(v1, t1), - t2 = Curve.getTimeOf(v2, p1); - if (t2 !== null) { - addLocation(locations, include, - flip ? c2 : c1, flip ? t2 : t1, - flip ? c1 : c2, flip ? t1 : t2); - } - } - } - - function addLineIntersection(v1, v2, c1, c2, locations, include) { - var pt = Line.intersect( - v1[0], v1[1], v1[6], v1[7], - v2[0], v2[1], v2[6], v2[7]); - if (pt) { - addLocation(locations, include, - c1, Curve.getTimeOf(v1, pt), - c2, Curve.getTimeOf(v2, pt)); - } - } - - function getCurveIntersections(v1, v2, c1, c2, locations, include) { - var epsilon = 1e-12, - min = Math.min, - max = Math.max; - - if (max(v1[0], v1[2], v1[4], v1[6]) + epsilon > - min(v2[0], v2[2], v2[4], v2[6]) && - min(v1[0], v1[2], v1[4], v1[6]) - epsilon < - max(v2[0], v2[2], v2[4], v2[6]) && - max(v1[1], v1[3], v1[5], v1[7]) + epsilon > - min(v2[1], v2[3], v2[5], v2[7]) && - min(v1[1], v1[3], v1[5], v1[7]) - epsilon < - max(v2[1], v2[3], v2[5], v2[7])) { - var overlaps = getOverlaps(v1, v2); - if (overlaps) { - for (var i = 0; i < 2; i++) { - var overlap = overlaps[i]; - addLocation(locations, include, - c1, overlap[0], - c2, overlap[1], true); - } - } else { - var straight1 = Curve.isStraight(v1), - straight2 = Curve.isStraight(v2), - straight = straight1 && straight2, - flip = straight1 && !straight2, - before = locations.length; - (straight - ? addLineIntersection - : straight1 || straight2 - ? addCurveLineIntersections - : addCurveIntersections)( - flip ? v2 : v1, flip ? v1 : v2, - flip ? c2 : c1, flip ? c1 : c2, - locations, include, flip, - 0, 0, 0, 1, 0, 1); - if (!straight || locations.length === before) { - for (var i = 0; i < 4; i++) { - var t1 = i >> 1, - t2 = i & 1, - i1 = t1 * 6, - i2 = t2 * 6, - p1 = new Point(v1[i1], v1[i1 + 1]), - p2 = new Point(v2[i2], v2[i2 + 1]); - if (p1.isClose(p2, epsilon)) { - addLocation(locations, include, - c1, t1, - c2, t2); - } - } - } - } - } - return locations; - } - - function getLoopIntersection(v1, c1, locations, include) { - var info = Curve.classify(v1); - if (info.type === 'loop') { - var roots = info.roots; - addLocation(locations, include, - c1, roots[0], - c1, roots[1]); - } - return locations; - } - - function getIntersections(curves1, curves2, include, matrix1, matrix2, - _returnFirst) { - var self = !curves2; - if (self) - curves2 = curves1; - var length1 = curves1.length, - length2 = curves2.length, - values2 = [], - arrays = [], - locations, - current; - for (var i = 0; i < length2; i++) - values2[i] = curves2[i].getValues(matrix2); - for (var i = 0; i < length1; i++) { - var curve1 = curves1[i], - values1 = self ? values2[i] : curve1.getValues(matrix1), - path1 = curve1.getPath(); - if (path1 !== current) { - current = path1; - locations = []; - arrays.push(locations); - } - if (self) { - getLoopIntersection(values1, curve1, locations, include); - } - for (var j = self ? i + 1 : 0; j < length2; j++) { - if (_returnFirst && locations.length) - return locations; - getCurveIntersections(values1, values2[j], curve1, curves2[j], - locations, include); - } - } - locations = []; - for (var i = 0, l = arrays.length; i < l; i++) { - Base.push(locations, arrays[i]); - } - return locations; - } - - function getOverlaps(v1, v2) { - - function getSquaredLineLength(v) { - var x = v[6] - v[0], - y = v[7] - v[1]; - return x * x + y * y; - } - - var abs = Math.abs, - getDistance = Line.getDistance, - timeEpsilon = 1e-8, - geomEpsilon = 1e-7, - straight1 = Curve.isStraight(v1), - straight2 = Curve.isStraight(v2), - straightBoth = straight1 && straight2, - flip = getSquaredLineLength(v1) < getSquaredLineLength(v2), - l1 = flip ? v2 : v1, - l2 = flip ? v1 : v2, - px = l1[0], py = l1[1], - vx = l1[6] - px, vy = l1[7] - py; - if (getDistance(px, py, vx, vy, l2[0], l2[1], true) < geomEpsilon && - getDistance(px, py, vx, vy, l2[6], l2[7], true) < geomEpsilon) { - if (!straightBoth && - getDistance(px, py, vx, vy, l1[2], l1[3], true) < geomEpsilon && - getDistance(px, py, vx, vy, l1[4], l1[5], true) < geomEpsilon && - getDistance(px, py, vx, vy, l2[2], l2[3], true) < geomEpsilon && - getDistance(px, py, vx, vy, l2[4], l2[5], true) < geomEpsilon) { - straight1 = straight2 = straightBoth = true; - } - } else if (straightBoth) { - return null; - } - if (straight1 ^ straight2) { - return null; - } - - var v = [v1, v2], - pairs = []; - for (var i = 0; i < 4 && pairs.length < 2; i++) { - var i1 = i & 1, - i2 = i1 ^ 1, - t1 = i >> 1, - t2 = Curve.getTimeOf(v[i1], new Point( - v[i2][t1 ? 6 : 0], - v[i2][t1 ? 7 : 1])); - if (t2 != null) { - var pair = i1 ? [t1, t2] : [t2, t1]; - if (!pairs.length || - abs(pair[0] - pairs[0][0]) > timeEpsilon && - abs(pair[1] - pairs[0][1]) > timeEpsilon) { - pairs.push(pair); - } - } - if (i > 2 && !pairs.length) - break; - } - if (pairs.length !== 2) { - pairs = null; - } else if (!straightBoth) { - var o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]), - o2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]); - if (abs(o2[2] - o1[2]) > geomEpsilon || - abs(o2[3] - o1[3]) > geomEpsilon || - abs(o2[4] - o1[4]) > geomEpsilon || - abs(o2[5] - o1[5]) > geomEpsilon) - pairs = null; - } - return pairs; - } - - function getTimesWithTangent(v, tangent) { - var x0 = v[0], y0 = v[1], - x1 = v[2], y1 = v[3], - x2 = v[4], y2 = v[5], - x3 = v[6], y3 = v[7], - normalized = tangent.normalize(), - tx = normalized.x, - ty = normalized.y, - ax = 3 * x3 - 9 * x2 + 9 * x1 - 3 * x0, - ay = 3 * y3 - 9 * y2 + 9 * y1 - 3 * y0, - bx = 6 * x2 - 12 * x1 + 6 * x0, - by = 6 * y2 - 12 * y1 + 6 * y0, - cx = 3 * x1 - 3 * x0, - cy = 3 * y1 - 3 * y0, - den = 2 * ax * ty - 2 * ay * tx, - times = []; - if (Math.abs(den) < Numerical.CURVETIME_EPSILON) { - var num = ax * cy - ay * cx, - den = ax * by - ay * bx; - if (den != 0) { - var t = -num / den; - if (t >= 0 && t <= 1) times.push(t); - } - } else { - var delta = (bx * bx - 4 * ax * cx) * ty * ty + - (-2 * bx * by + 4 * ay * cx + 4 * ax * cy) * tx * ty + - (by * by - 4 * ay * cy) * tx * tx, - k = bx * ty - by * tx; - if (delta >= 0 && den != 0) { - var d = Math.sqrt(delta), - t0 = -(k + d) / den, - t1 = (-k + d) / den; - if (t0 >= 0 && t0 <= 1) times.push(t0); - if (t1 >= 0 && t1 <= 1) times.push(t1); - } - } - return times; - } - - return { - getIntersections: function(curve) { - var v1 = this.getValues(), - v2 = curve && curve !== this && curve.getValues(); - return v2 ? getCurveIntersections(v1, v2, this, curve, []) - : getLoopIntersection(v1, this, []); - }, - - statics: { - getOverlaps: getOverlaps, - getIntersections: getIntersections, - getCurveLineIntersections: getCurveLineIntersections, - getTimesWithTangent: getTimesWithTangent - } - }; -}); - -var CurveLocation = Base.extend({ - _class: 'CurveLocation', - - initialize: function CurveLocation(curve, time, point, _overlap, _distance) { - if (time >= 0.99999999) { - var next = curve.getNext(); - if (next) { - time = 0; - curve = next; - } - } - this._setCurve(curve); - this._time = time; - this._point = point || curve.getPointAtTime(time); - this._overlap = _overlap; - this._distance = _distance; - this._intersection = this._next = this._previous = null; - }, - - _setCurve: function(curve) { - var path = curve._path; - this._path = path; - this._version = path ? path._version : 0; - this._curve = curve; - this._segment = null; - this._segment1 = curve._segment1; - this._segment2 = curve._segment2; - }, - - _setSegment: function(segment) { - this._setCurve(segment.getCurve()); - this._segment = segment; - this._time = segment === this._segment1 ? 0 : 1; - this._point = segment._point.clone(); - }, - - getSegment: function() { - var segment = this._segment; - if (!segment) { - var curve = this.getCurve(), - time = this.getTime(); - if (time === 0) { - segment = curve._segment1; - } else if (time === 1) { - segment = curve._segment2; - } else if (time != null) { - segment = curve.getPartLength(0, time) - < curve.getPartLength(time, 1) - ? curve._segment1 - : curve._segment2; - } - this._segment = segment; - } - return segment; - }, - - getCurve: function() { - var path = this._path, - that = this; - if (path && path._version !== this._version) { - this._time = this._offset = this._curveOffset = this._curve = null; - } - - function trySegment(segment) { - var curve = segment && segment.getCurve(); - if (curve && (that._time = curve.getTimeOf(that._point)) != null) { - that._setCurve(curve); - return curve; - } - } - - return this._curve - || trySegment(this._segment) - || trySegment(this._segment1) - || trySegment(this._segment2.getPrevious()); - }, - - getPath: function() { - var curve = this.getCurve(); - return curve && curve._path; - }, - - getIndex: function() { - var curve = this.getCurve(); - return curve && curve.getIndex(); - }, - - getTime: function() { - var curve = this.getCurve(), - time = this._time; - return curve && time == null - ? this._time = curve.getTimeOf(this._point) - : time; - }, - - getParameter: '#getTime', - - getPoint: function() { - return this._point; - }, - - getOffset: function() { - var offset = this._offset; - if (offset == null) { - offset = 0; - var path = this.getPath(), - index = this.getIndex(); - if (path && index != null) { - var curves = path.getCurves(); - for (var i = 0; i < index; i++) - offset += curves[i].getLength(); - } - this._offset = offset += this.getCurveOffset(); - } - return offset; - }, - - getCurveOffset: function() { - var offset = this._curveOffset; - if (offset == null) { - var curve = this.getCurve(), - time = this.getTime(); - this._curveOffset = offset = time != null && curve - && curve.getPartLength(0, time); - } - return offset; - }, - - getIntersection: function() { - return this._intersection; - }, - - getDistance: function() { - return this._distance; - }, - - divide: function() { - var curve = this.getCurve(), - res = curve && curve.divideAtTime(this.getTime()); - if (res) { - this._setSegment(res._segment1); - } - return res; - }, - - split: function() { - var curve = this.getCurve(), - path = curve._path, - res = curve && curve.splitAtTime(this.getTime()); - if (res) { - this._setSegment(path.getLastSegment()); - } - return res; - }, - - equals: function(loc, _ignoreOther) { - var res = this === loc; - if (!res && loc instanceof CurveLocation) { - var c1 = this.getCurve(), - c2 = loc.getCurve(), - p1 = c1._path, - p2 = c2._path; - if (p1 === p2) { - var abs = Math.abs, - epsilon = 1e-7, - diff = abs(this.getOffset() - loc.getOffset()), - i1 = !_ignoreOther && this._intersection, - i2 = !_ignoreOther && loc._intersection; - res = (diff < epsilon - || p1 && abs(p1.getLength() - diff) < epsilon) - && (!i1 && !i2 || i1 && i2 && i1.equals(i2, true)); - } - } - return res; - }, - - toString: function() { - var parts = [], - point = this.getPoint(), - f = Formatter.instance; - if (point) - parts.push('point: ' + point); - var index = this.getIndex(); - if (index != null) - parts.push('index: ' + index); - var time = this.getTime(); - if (time != null) - parts.push('time: ' + f.number(time)); - if (this._distance != null) - parts.push('distance: ' + f.number(this._distance)); - return '{ ' + parts.join(', ') + ' }'; - }, - - isTouching: function() { - var inter = this._intersection; - if (inter && this.getTangent().isCollinear(inter.getTangent())) { - var curve1 = this.getCurve(), - curve2 = inter.getCurve(); - return !(curve1.isStraight() && curve2.isStraight() - && curve1.getLine().intersect(curve2.getLine())); - } - return false; - }, - - isCrossing: function() { - var inter = this._intersection; - if (!inter) - return false; - var t1 = this.getTime(), - t2 = inter.getTime(), - tMin = 1e-8, - tMax = 1 - tMin, - t1Inside = t1 >= tMin && t1 <= tMax, - t2Inside = t2 >= tMin && t2 <= tMax; - if (t1Inside && t2Inside) - return !this.isTouching(); - var c2 = this.getCurve(), - c1 = t1 < tMin ? c2.getPrevious() : c2, - c4 = inter.getCurve(), - c3 = t2 < tMin ? c4.getPrevious() : c4; - if (t1 > tMax) - c2 = c2.getNext(); - if (t2 > tMax) - c4 = c4.getNext(); - if (!c1 || !c2 || !c3 || !c4) - return false; - - var offsets = []; - - function addOffsets(curve, end) { - var v = curve.getValues(), - roots = Curve.classify(v).roots || Curve.getPeaks(v), - count = roots.length, - t = end && count > 1 ? roots[count - 1] - : count > 0 ? roots[0] - : 0.5; - offsets.push(Curve.getLength(v, end ? t : 0, end ? 1 : t) / 2); - } - - function isInRange(angle, min, max) { - return min < max - ? angle > min && angle < max - : angle > min || angle < max; - } - - if (!t1Inside) { - addOffsets(c1, true); - addOffsets(c2, false); - } - if (!t2Inside) { - addOffsets(c3, true); - addOffsets(c4, false); - } - var pt = this.getPoint(), - offset = Math.min.apply(Math, offsets), - v2 = t1Inside ? c2.getTangentAtTime(t1) - : c2.getPointAt(offset).subtract(pt), - v1 = t1Inside ? v2.negate() - : c1.getPointAt(-offset).subtract(pt), - v4 = t2Inside ? c4.getTangentAtTime(t2) - : c4.getPointAt(offset).subtract(pt), - v3 = t2Inside ? v4.negate() - : c3.getPointAt(-offset).subtract(pt), - a1 = v1.getAngle(), - a2 = v2.getAngle(), - a3 = v3.getAngle(), - a4 = v4.getAngle(); - return !!(t1Inside - ? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) && - (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3)) - : (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) && - (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1))); - }, - - hasOverlap: function() { - return !!this._overlap; - } -}, Base.each(Curve._evaluateMethods, function(name) { - var get = name + 'At'; - this[name] = function() { - var curve = this.getCurve(), - time = this.getTime(); - return time != null && curve && curve[get](time, true); - }; -}, { - preserve: true -}), -new function() { - - function insert(locations, loc, merge) { - var length = locations.length, - l = 0, - r = length - 1; - - function search(index, dir) { - for (var i = index + dir; i >= -1 && i <= length; i += dir) { - var loc2 = locations[((i % length) + length) % length]; - if (!loc.getPoint().isClose(loc2.getPoint(), - 1e-7)) - break; - if (loc.equals(loc2)) - return loc2; - } - return null; - } - - while (l <= r) { - var m = (l + r) >>> 1, - loc2 = locations[m], - found; - if (merge && (found = loc.equals(loc2) ? loc2 - : (search(m, -1) || search(m, 1)))) { - if (loc._overlap) { - found._overlap = found._intersection._overlap = true; - } - return found; - } - var path1 = loc.getPath(), - path2 = loc2.getPath(), - diff = path1 !== path2 - ? path1._id - path2._id - : (loc.getIndex() + loc.getTime()) - - (loc2.getIndex() + loc2.getTime()); - if (diff < 0) { - r = m - 1; - } else { - l = m + 1; - } - } - locations.splice(l, 0, loc); - return loc; - } - - return { statics: { - insert: insert, - - expand: function(locations) { - var expanded = locations.slice(); - for (var i = locations.length - 1; i >= 0; i--) { - insert(expanded, locations[i]._intersection, false); - } - return expanded; - } - }}; -}); - -var PathItem = Item.extend({ - _class: 'PathItem', - _selectBounds: false, - _canScaleStroke: true, - beans: true, - - initialize: function PathItem() { - }, - - statics: { - create: function(arg) { - var data, - segments, - compound; - if (Base.isPlainObject(arg)) { - segments = arg.segments; - data = arg.pathData; - } else if (Array.isArray(arg)) { - segments = arg; - } else if (typeof arg === 'string') { - data = arg; - } - if (segments) { - var first = segments[0]; - compound = first && Array.isArray(first[0]); - } else if (data) { - compound = (data.match(/m/gi) || []).length > 1 - || /z\s*\S+/i.test(data); - } - var ctor = compound ? CompoundPath : Path; - return new ctor(arg); - } - }, - - _asPathItem: function() { - return this; - }, - - isClockwise: function() { - return this.getArea() >= 0; - }, - - setClockwise: function(clockwise) { - if (this.isClockwise() != (clockwise = !!clockwise)) - this.reverse(); - }, - - setPathData: function(data) { - - var parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig), - coords, - relative = false, - previous, - control, - current = new Point(), - start = new Point(); - - function getCoord(index, coord) { - var val = +coords[index]; - if (relative) - val += current[coord]; - return val; - } - - function getPoint(index) { - return new Point( - getCoord(index, 'x'), - getCoord(index + 1, 'y') - ); - } - - this.clear(); - - for (var i = 0, l = parts && parts.length; i < l; i++) { - var part = parts[i], - command = part[0], - lower = command.toLowerCase(); - coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g); - var length = coords && coords.length; - relative = command === lower; - if (previous === 'z' && !/[mz]/.test(lower)) - this.moveTo(current); - switch (lower) { - case 'm': - case 'l': - var move = lower === 'm'; - for (var j = 0; j < length; j += 2) { - this[move ? 'moveTo' : 'lineTo'](current = getPoint(j)); - if (move) { - start = current; - move = false; - } - } - control = current; - break; - case 'h': - case 'v': - var coord = lower === 'h' ? 'x' : 'y'; - current = current.clone(); - for (var j = 0; j < length; j++) { - current[coord] = getCoord(j, coord); - this.lineTo(current); - } - control = current; - break; - case 'c': - for (var j = 0; j < length; j += 6) { - this.cubicCurveTo( - getPoint(j), - control = getPoint(j + 2), - current = getPoint(j + 4)); - } - break; - case 's': - for (var j = 0; j < length; j += 4) { - this.cubicCurveTo( - /[cs]/.test(previous) - ? current.multiply(2).subtract(control) - : current, - control = getPoint(j), - current = getPoint(j + 2)); - previous = lower; - } - break; - case 'q': - for (var j = 0; j < length; j += 4) { - this.quadraticCurveTo( - control = getPoint(j), - current = getPoint(j + 2)); - } - break; - case 't': - for (var j = 0; j < length; j += 2) { - this.quadraticCurveTo( - control = (/[qt]/.test(previous) - ? current.multiply(2).subtract(control) - : current), - current = getPoint(j)); - previous = lower; - } - break; - case 'a': - for (var j = 0; j < length; j += 7) { - this.arcTo(current = getPoint(j + 5), - new Size(+coords[j], +coords[j + 1]), - +coords[j + 2], +coords[j + 4], +coords[j + 3]); - } - break; - case 'z': - this.closePath(1e-12); - current = start; - break; - } - previous = lower; - } - }, - - _canComposite: function() { - return !(this.hasFill() && this.hasStroke()); - }, - - _contains: function(point) { - var winding = point.isInside( - this.getBounds({ internal: true, handle: true })) - ? this._getWinding(point) - : {}; - return winding.onPath || !!(this.getFillRule() === 'evenodd' - ? winding.windingL & 1 || winding.windingR & 1 - : winding.winding); - }, - - getIntersections: function(path, include, _matrix, _returnFirst) { - var self = this === path || !path, - matrix1 = this._matrix._orNullIfIdentity(), - matrix2 = self ? matrix1 - : (_matrix || path._matrix)._orNullIfIdentity(); - return self || this.getBounds(matrix1).intersects( - path.getBounds(matrix2), 1e-12) - ? Curve.getIntersections( - this.getCurves(), !self && path.getCurves(), include, - matrix1, matrix2, _returnFirst) - : []; - }, - - getCrossings: function(path) { - return this.getIntersections(path, function(inter) { - return inter.hasOverlap() || inter.isCrossing(); - }); - }, - - getNearestLocation: function() { - var point = Point.read(arguments), - curves = this.getCurves(), - minDist = Infinity, - minLoc = null; - for (var i = 0, l = curves.length; i < l; i++) { - var loc = curves[i].getNearestLocation(point); - if (loc._distance < minDist) { - minDist = loc._distance; - minLoc = loc; - } - } - return minLoc; - }, - - getNearestPoint: function() { - var loc = this.getNearestLocation.apply(this, arguments); - return loc ? loc.getPoint() : loc; - }, - - interpolate: function(from, to, factor) { - var isPath = !this._children, - name = isPath ? '_segments' : '_children', - itemsFrom = from[name], - itemsTo = to[name], - items = this[name]; - if (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) { - throw new Error('Invalid operands in interpolate() call: ' + - from + ', ' + to); - } - var current = items.length, - length = itemsTo.length; - if (current < length) { - var ctor = isPath ? Segment : Path; - for (var i = current; i < length; i++) { - this.add(new ctor()); - } - } else if (current > length) { - this[isPath ? 'removeSegments' : 'removeChildren'](length, current); - } - for (var i = 0; i < length; i++) { - items[i].interpolate(itemsFrom[i], itemsTo[i], factor); - } - if (isPath) { - this.setClosed(from._closed); - this._changed(9); - } - }, - - compare: function(path) { - var ok = false; - if (path) { - var paths1 = this._children || [this], - paths2 = path._children ? path._children.slice() : [path], - length1 = paths1.length, - length2 = paths2.length, - matched = [], - count = 0; - ok = true; - for (var i1 = length1 - 1; i1 >= 0 && ok; i1--) { - var path1 = paths1[i1]; - ok = false; - for (var i2 = length2 - 1; i2 >= 0 && !ok; i2--) { - if (path1.compare(paths2[i2])) { - if (!matched[i2]) { - matched[i2] = true; - count++; - } - ok = true; - } - } - } - ok = ok && count === length2; - } - return ok; - }, - -}); - -var Path = PathItem.extend({ - _class: 'Path', - _serializeFields: { - segments: [], - closed: false - }, - - initialize: function Path(arg) { - this._closed = false; - this._segments = []; - this._version = 0; - var segments = Array.isArray(arg) - ? typeof arg[0] === 'object' - ? arg - : arguments - : arg && (arg.size === undefined && (arg.x !== undefined - || arg.point !== undefined)) - ? arguments - : null; - if (segments && segments.length > 0) { - this.setSegments(segments); - } else { - this._curves = undefined; - this._segmentSelection = 0; - if (!segments && typeof arg === 'string') { - this.setPathData(arg); - arg = null; - } - } - this._initialize(!segments && arg); - }, - - _equals: function(item) { - return this._closed === item._closed - && Base.equals(this._segments, item._segments); - }, - - copyContent: function(source) { - this.setSegments(source._segments); - this._closed = source._closed; - }, - - _changed: function _changed(flags) { - _changed.base.call(this, flags); - if (flags & 8) { - this._length = this._area = undefined; - if (flags & 32) { - this._version++; - } else if (this._curves) { - for (var i = 0, l = this._curves.length; i < l; i++) - this._curves[i]._changed(); - } - } else if (flags & 64) { - this._bounds = undefined; - } - }, - - getStyle: function() { - var parent = this._parent; - return (parent instanceof CompoundPath ? parent : this)._style; - }, - - getSegments: function() { - return this._segments; - }, - - setSegments: function(segments) { - var fullySelected = this.isFullySelected(), - length = segments && segments.length; - this._segments.length = 0; - this._segmentSelection = 0; - this._curves = undefined; - if (length) { - var last = segments[length - 1]; - if (typeof last === 'boolean') { - this.setClosed(last); - length--; - } - this._add(Segment.readList(segments, 0, {}, length)); - } - if (fullySelected) - this.setFullySelected(true); - }, - - getFirstSegment: function() { - return this._segments[0]; - }, - - getLastSegment: function() { - return this._segments[this._segments.length - 1]; - }, - - getCurves: function() { - var curves = this._curves, - segments = this._segments; - if (!curves) { - var length = this._countCurves(); - curves = this._curves = new Array(length); - for (var i = 0; i < length; i++) - curves[i] = new Curve(this, segments[i], - segments[i + 1] || segments[0]); - } - return curves; - }, - - getFirstCurve: function() { - return this.getCurves()[0]; - }, - - getLastCurve: function() { - var curves = this.getCurves(); - return curves[curves.length - 1]; - }, - - isClosed: function() { - return this._closed; - }, - - setClosed: function(closed) { - if (this._closed != (closed = !!closed)) { - this._closed = closed; - if (this._curves) { - var length = this._curves.length = this._countCurves(); - if (closed) - this._curves[length - 1] = new Curve(this, - this._segments[length - 1], this._segments[0]); - } - this._changed(41); - } - } -}, { - beans: true, - - getPathData: function(_matrix, _precision) { - var segments = this._segments, - length = segments.length, - f = new Formatter(_precision), - coords = new Array(6), - first = true, - curX, curY, - prevX, prevY, - inX, inY, - outX, outY, - parts = []; - - function addSegment(segment, skipLine) { - segment._transformCoordinates(_matrix, coords); - curX = coords[0]; - curY = coords[1]; - if (first) { - parts.push('M' + f.pair(curX, curY)); - first = false; - } else { - inX = coords[2]; - inY = coords[3]; - if (inX === curX && inY === curY - && outX === prevX && outY === prevY) { - if (!skipLine) { - var dx = curX - prevX, - dy = curY - prevY; - parts.push( - dx === 0 ? 'v' + f.number(dy) - : dy === 0 ? 'h' + f.number(dx) - : 'l' + f.pair(dx, dy)); - } - } else { - parts.push('c' + f.pair(outX - prevX, outY - prevY) - + ' ' + f.pair( inX - prevX, inY - prevY) - + ' ' + f.pair(curX - prevX, curY - prevY)); - } - } - prevX = curX; - prevY = curY; - outX = coords[4]; - outY = coords[5]; - } - - if (!length) - return ''; - - for (var i = 0; i < length; i++) - addSegment(segments[i]); - if (this._closed && length > 0) { - addSegment(segments[0], true); - parts.push('z'); - } - return parts.join(''); - }, - - isEmpty: function() { - return !this._segments.length; - }, - - _transformContent: function(matrix) { - var segments = this._segments, - coords = new Array(6); - for (var i = 0, l = segments.length; i < l; i++) - segments[i]._transformCoordinates(matrix, coords, true); - return true; - }, - - _add: function(segs, index) { - var segments = this._segments, - curves = this._curves, - amount = segs.length, - append = index == null, - index = append ? segments.length : index; - for (var i = 0; i < amount; i++) { - var segment = segs[i]; - if (segment._path) - segment = segs[i] = segment.clone(); - segment._path = this; - segment._index = index + i; - if (segment._selection) - this._updateSelection(segment, 0, segment._selection); - } - if (append) { - Base.push(segments, segs); - } else { - segments.splice.apply(segments, [index, 0].concat(segs)); - for (var i = index + amount, l = segments.length; i < l; i++) - segments[i]._index = i; - } - if (curves) { - var total = this._countCurves(), - start = index > 0 && index + amount - 1 === total ? index - 1 - : index, - insert = start, - end = Math.min(start + amount, total); - if (segs._curves) { - curves.splice.apply(curves, [start, 0].concat(segs._curves)); - insert += segs._curves.length; - } - for (var i = insert; i < end; i++) - curves.splice(i, 0, new Curve(this, null, null)); - this._adjustCurves(start, end); - } - this._changed(41); - return segs; - }, - - _adjustCurves: function(start, end) { - var segments = this._segments, - curves = this._curves, - curve; - for (var i = start; i < end; i++) { - curve = curves[i]; - curve._path = this; - curve._segment1 = segments[i]; - curve._segment2 = segments[i + 1] || segments[0]; - curve._changed(); - } - if (curve = curves[this._closed && !start ? segments.length - 1 - : start - 1]) { - curve._segment2 = segments[start] || segments[0]; - curve._changed(); - } - if (curve = curves[end]) { - curve._segment1 = segments[end]; - curve._changed(); - } - }, - - _countCurves: function() { - var length = this._segments.length; - return !this._closed && length > 0 ? length - 1 : length; - }, - - add: function(segment1 ) { - return arguments.length > 1 && typeof segment1 !== 'number' - ? this._add(Segment.readList(arguments)) - : this._add([ Segment.read(arguments) ])[0]; - }, - - insert: function(index, segment1 ) { - return arguments.length > 2 && typeof segment1 !== 'number' - ? this._add(Segment.readList(arguments, 1), index) - : this._add([ Segment.read(arguments, 1) ], index)[0]; - }, - - addSegment: function() { - return this._add([ Segment.read(arguments) ])[0]; - }, - - insertSegment: function(index ) { - return this._add([ Segment.read(arguments, 1) ], index)[0]; - }, - - addSegments: function(segments) { - return this._add(Segment.readList(segments)); - }, - - insertSegments: function(index, segments) { - return this._add(Segment.readList(segments), index); - }, - - removeSegment: function(index) { - return this.removeSegments(index, index + 1)[0] || null; - }, - - removeSegments: function(start, end, _includeCurves) { - start = start || 0; - end = Base.pick(end, this._segments.length); - var segments = this._segments, - curves = this._curves, - count = segments.length, - removed = segments.splice(start, end - start), - amount = removed.length; - if (!amount) - return removed; - for (var i = 0; i < amount; i++) { - var segment = removed[i]; - if (segment._selection) - this._updateSelection(segment, segment._selection, 0); - segment._index = segment._path = null; - } - for (var i = start, l = segments.length; i < l; i++) - segments[i]._index = i; - if (curves) { - var index = start > 0 && end === count + (this._closed ? 1 : 0) - ? start - 1 - : start, - curves = curves.splice(index, amount); - for (var i = curves.length - 1; i >= 0; i--) - curves[i]._path = null; - if (_includeCurves) - removed._curves = curves.slice(1); - this._adjustCurves(index, index); - } - this._changed(41); - return removed; - }, - - clear: '#removeSegments', - - hasHandles: function() { - var segments = this._segments; - for (var i = 0, l = segments.length; i < l; i++) { - if (segments[i].hasHandles()) - return true; - } - return false; - }, - - clearHandles: function() { - var segments = this._segments; - for (var i = 0, l = segments.length; i < l; i++) - segments[i].clearHandles(); - }, - - getLength: function() { - if (this._length == null) { - var curves = this.getCurves(), - length = 0; - for (var i = 0, l = curves.length; i < l; i++) - length += curves[i].getLength(); - this._length = length; - } - return this._length; - }, - - getArea: function() { - var area = this._area; - if (area == null) { - var segments = this._segments, - closed = this._closed; - area = 0; - for (var i = 0, l = segments.length; i < l; i++) { - var last = i + 1 === l; - area += Curve.getArea(Curve.getValues( - segments[i], segments[last ? 0 : i + 1], - null, last && !closed)); - } - this._area = area; - } - return area; - }, - - isFullySelected: function() { - var length = this._segments.length; - return this.isSelected() && length > 0 && this._segmentSelection - === length * 7; - }, - - setFullySelected: function(selected) { - if (selected) - this._selectSegments(true); - this.setSelected(selected); - }, - - setSelection: function setSelection(selection) { - if (!(selection & 1)) - this._selectSegments(false); - setSelection.base.call(this, selection); - }, - - _selectSegments: function(selected) { - var segments = this._segments, - length = segments.length, - selection = selected ? 7 : 0; - this._segmentSelection = selection * length; - for (var i = 0; i < length; i++) - segments[i]._selection = selection; - }, - - _updateSelection: function(segment, oldSelection, newSelection) { - segment._selection = newSelection; - var selection = this._segmentSelection += newSelection - oldSelection; - if (selection > 0) - this.setSelected(true); - }, - - divideAt: function(location) { - var loc = this.getLocationAt(location), - curve; - return loc && (curve = loc.getCurve().divideAt(loc.getCurveOffset())) - ? curve._segment1 - : null; - }, - - splitAt: function(location) { - var loc = this.getLocationAt(location), - index = loc && loc.index, - time = loc && loc.time, - tMin = 1e-8, - tMax = 1 - tMin; - if (time > tMax) { - index++; - time = 0; - } - var curves = this.getCurves(); - if (index >= 0 && index < curves.length) { - if (time >= tMin) { - curves[index++].divideAtTime(time); - } - var segs = this.removeSegments(index, this._segments.length, true), - path; - if (this._closed) { - this.setClosed(false); - path = this; - } else { - path = new Path(Item.NO_INSERT); - path.insertAbove(this); - path.copyAttributes(this); - } - path._add(segs, 0); - this.addSegment(segs[0]); - return path; - } - return null; - }, - - split: function(index, time) { - var curve, - location = time === undefined ? index - : (curve = this.getCurves()[index]) - && curve.getLocationAtTime(time); - return location != null ? this.splitAt(location) : null; - }, - - join: function(path, tolerance) { - var epsilon = tolerance || 0; - if (path && path !== this) { - var segments = path._segments, - last1 = this.getLastSegment(), - last2 = path.getLastSegment(); - if (!last2) - return this; - if (last1 && last1._point.isClose(last2._point, epsilon)) - path.reverse(); - var first2 = path.getFirstSegment(); - if (last1 && last1._point.isClose(first2._point, epsilon)) { - last1.setHandleOut(first2._handleOut); - this._add(segments.slice(1)); - } else { - var first1 = this.getFirstSegment(); - if (first1 && first1._point.isClose(first2._point, epsilon)) - path.reverse(); - last2 = path.getLastSegment(); - if (first1 && first1._point.isClose(last2._point, epsilon)) { - first1.setHandleIn(last2._handleIn); - this._add(segments.slice(0, segments.length - 1), 0); - } else { - this._add(segments.slice()); - } - } - if (path._closed) - this._add([segments[0]]); - path.remove(); - } - var first = this.getFirstSegment(), - last = this.getLastSegment(); - if (first !== last && first._point.isClose(last._point, epsilon)) { - first.setHandleIn(last._handleIn); - last.remove(); - this.setClosed(true); - } - return this; - }, - - reduce: function(options) { - var curves = this.getCurves(), - simplify = options && options.simplify, - tolerance = simplify ? 1e-7 : 0; - for (var i = curves.length - 1; i >= 0; i--) { - var curve = curves[i]; - if (!curve.hasHandles() && (!curve.hasLength(tolerance) - || simplify && curve.isCollinear(curve.getNext()))) - curve.remove(); - } - return this; - }, - - reverse: function() { - this._segments.reverse(); - for (var i = 0, l = this._segments.length; i < l; i++) { - var segment = this._segments[i]; - var handleIn = segment._handleIn; - segment._handleIn = segment._handleOut; - segment._handleOut = handleIn; - segment._index = i; - } - this._curves = null; - this._changed(9); - }, - - flatten: function(flatness) { - var flattener = new PathFlattener(this, flatness || 0.25, 256, true), - parts = flattener.parts, - length = parts.length, - segments = []; - for (var i = 0; i < length; i++) { - segments.push(new Segment(parts[i].curve.slice(0, 2))); - } - if (!this._closed && length > 0) { - segments.push(new Segment(parts[length - 1].curve.slice(6))); - } - this.setSegments(segments); - }, - - simplify: function(tolerance) { - var segments = new PathFitter(this).fit(tolerance || 2.5); - if (segments) - this.setSegments(segments); - return !!segments; - }, - - smooth: function(options) { - var that = this, - opts = options || {}, - type = opts.type || 'asymmetric', - segments = this._segments, - length = segments.length, - closed = this._closed; - - function getIndex(value, _default) { - var index = value && value.index; - if (index != null) { - var path = value.path; - if (path && path !== that) - throw new Error(value._class + ' ' + index + ' of ' + path - + ' is not part of ' + that); - if (_default && value instanceof Curve) - index++; - } else { - index = typeof value === 'number' ? value : _default; - } - return Math.min(index < 0 && closed - ? index % length - : index < 0 ? index + length : index, length - 1); - } - - var loop = closed && opts.from === undefined && opts.to === undefined, - from = getIndex(opts.from, 0), - to = getIndex(opts.to, length - 1); - - if (from > to) { - if (closed) { - from -= length; - } else { - var tmp = from; - from = to; - to = tmp; - } - } - if (/^(?:asymmetric|continuous)$/.test(type)) { - var asymmetric = type === 'asymmetric', - min = Math.min, - amount = to - from + 1, - n = amount - 1, - padding = loop ? min(amount, 4) : 1, - paddingLeft = padding, - paddingRight = padding, - knots = []; - if (!closed) { - paddingLeft = min(1, from); - paddingRight = min(1, length - to - 1); - } - n += paddingLeft + paddingRight; - if (n <= 1) - return; - for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) { - knots[i] = segments[(j < 0 ? j + length : j) % length]._point; - } - - var x = knots[0]._x + 2 * knots[1]._x, - y = knots[0]._y + 2 * knots[1]._y, - f = 2, - n_1 = n - 1, - rx = [x], - ry = [y], - rf = [f], - px = [], - py = []; - for (var i = 1; i < n; i++) { - var internal = i < n_1, - a = internal ? 1 : asymmetric ? 1 : 2, - b = internal ? 4 : asymmetric ? 2 : 7, - u = internal ? 4 : asymmetric ? 3 : 8, - v = internal ? 2 : asymmetric ? 0 : 1, - m = a / f; - f = rf[i] = b - m; - x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x; - y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y; - } - - px[n_1] = rx[n_1] / rf[n_1]; - py[n_1] = ry[n_1] / rf[n_1]; - for (var i = n - 2; i >= 0; i--) { - px[i] = (rx[i] - px[i + 1]) / rf[i]; - py[i] = (ry[i] - py[i + 1]) / rf[i]; - } - px[n] = (3 * knots[n]._x - px[n_1]) / 2; - py[n] = (3 * knots[n]._y - py[n_1]) / 2; - - for (var i = paddingLeft, max = n - paddingRight, j = from; - i <= max; i++, j++) { - var segment = segments[j < 0 ? j + length : j], - pt = segment._point, - hx = px[i] - pt._x, - hy = py[i] - pt._y; - if (loop || i < max) - segment.setHandleOut(hx, hy); - if (loop || i > paddingLeft) - segment.setHandleIn(-hx, -hy); - } - } else { - for (var i = from; i <= to; i++) { - segments[i < 0 ? i + length : i].smooth(opts, - !loop && i === from, !loop && i === to); - } - } - }, - - toShape: function(insert) { - if (!this._closed) - return null; - - var segments = this._segments, - type, - size, - radius, - topCenter; - - function isCollinear(i, j) { - var seg1 = segments[i], - seg2 = seg1.getNext(), - seg3 = segments[j], - seg4 = seg3.getNext(); - return seg1._handleOut.isZero() && seg2._handleIn.isZero() - && seg3._handleOut.isZero() && seg4._handleIn.isZero() - && seg2._point.subtract(seg1._point).isCollinear( - seg4._point.subtract(seg3._point)); - } - - function isOrthogonal(i) { - var seg2 = segments[i], - seg1 = seg2.getPrevious(), - seg3 = seg2.getNext(); - return seg1._handleOut.isZero() && seg2._handleIn.isZero() - && seg2._handleOut.isZero() && seg3._handleIn.isZero() - && seg2._point.subtract(seg1._point).isOrthogonal( - seg3._point.subtract(seg2._point)); - } - - function isArc(i) { - var seg1 = segments[i], - seg2 = seg1.getNext(), - handle1 = seg1._handleOut, - handle2 = seg2._handleIn, - kappa = 0.5522847498307936; - if (handle1.isOrthogonal(handle2)) { - var pt1 = seg1._point, - pt2 = seg2._point, - corner = new Line(pt1, handle1, true).intersect( - new Line(pt2, handle2, true), true); - return corner && Numerical.isZero(handle1.getLength() / - corner.subtract(pt1).getLength() - kappa) - && Numerical.isZero(handle2.getLength() / - corner.subtract(pt2).getLength() - kappa); - } - return false; - } - - function getDistance(i, j) { - return segments[i]._point.getDistance(segments[j]._point); - } - - if (!this.hasHandles() && segments.length === 4 - && isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) { - type = Shape.Rectangle; - size = new Size(getDistance(0, 3), getDistance(0, 1)); - topCenter = segments[1]._point.add(segments[2]._point).divide(2); - } else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4) - && isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) { - type = Shape.Rectangle; - size = new Size(getDistance(1, 6), getDistance(0, 3)); - radius = size.subtract(new Size(getDistance(0, 7), - getDistance(1, 2))).divide(2); - topCenter = segments[3]._point.add(segments[4]._point).divide(2); - } else if (segments.length === 4 - && isArc(0) && isArc(1) && isArc(2) && isArc(3)) { - if (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) { - type = Shape.Circle; - radius = getDistance(0, 2) / 2; - } else { - type = Shape.Ellipse; - radius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2); - } - topCenter = segments[1]._point; - } - - if (type) { - var center = this.getPosition(true), - shape = new type({ - center: center, - size: size, - radius: radius, - insert: false - }); - shape.copyAttributes(this, true); - shape._matrix.prepend(this._matrix); - shape.rotate(topCenter.subtract(center).getAngle() + 90); - if (insert === undefined || insert) - shape.insertAbove(this); - return shape; - } - return null; - }, - - toPath: '#clone', - - compare: function compare(path) { - if (!path || path instanceof CompoundPath) - return compare.base.call(this, path); - var curves1 = this.getCurves(), - curves2 = path.getCurves(), - length1 = curves1.length, - length2 = curves2.length; - if (!length1 || !length2) { - return length1 == length2; - } - var v1 = curves1[0].getValues(), - values2 = [], - pos1 = 0, pos2, - end1 = 0, end2; - for (var i = 0; i < length2; i++) { - var v2 = curves2[i].getValues(); - values2.push(v2); - var overlaps = Curve.getOverlaps(v1, v2); - if (overlaps) { - pos2 = !i && overlaps[0][0] > 0 ? length2 - 1 : i; - end2 = overlaps[0][1]; - break; - } - } - var abs = Math.abs, - epsilon = 1e-8, - v2 = values2[pos2], - start2; - while (v1 && v2) { - var overlaps = Curve.getOverlaps(v1, v2); - if (overlaps) { - var t1 = overlaps[0][0]; - if (abs(t1 - end1) < epsilon) { - end1 = overlaps[1][0]; - if (end1 === 1) { - v1 = ++pos1 < length1 ? curves1[pos1].getValues() : null; - end1 = 0; - } - var t2 = overlaps[0][1]; - if (abs(t2 - end2) < epsilon) { - if (!start2) - start2 = [pos2, t2]; - end2 = overlaps[1][1]; - if (end2 === 1) { - if (++pos2 >= length2) - pos2 = 0; - v2 = values2[pos2] || curves2[pos2].getValues(); - end2 = 0; - } - if (!v1) { - return start2[0] === pos2 && start2[1] === end2; - } - continue; - } - } - } - break; - } - return false; - }, - - _hitTestSelf: function(point, options, viewMatrix, strokeMatrix) { - var that = this, - style = this.getStyle(), - segments = this._segments, - numSegments = segments.length, - closed = this._closed, - tolerancePadding = options._tolerancePadding, - strokePadding = tolerancePadding, - join, cap, miterLimit, - area, loc, res, - hitStroke = options.stroke && style.hasStroke(), - hitFill = options.fill && style.hasFill(), - hitCurves = options.curves, - strokeRadius = hitStroke - ? style.getStrokeWidth() / 2 - : hitFill && options.tolerance > 0 || hitCurves - ? 0 : null; - if (strokeRadius !== null) { - if (strokeRadius > 0) { - join = style.getStrokeJoin(); - cap = style.getStrokeCap(); - miterLimit = style.getMiterLimit(); - strokePadding = strokePadding.add( - Path._getStrokePadding(strokeRadius, strokeMatrix)); - } else { - join = cap = 'round'; - } - } - - function isCloseEnough(pt, padding) { - return point.subtract(pt).divide(padding).length <= 1; - } - - function checkSegmentPoint(seg, pt, name) { - if (!options.selected || pt.isSelected()) { - var anchor = seg._point; - if (pt !== anchor) - pt = pt.add(anchor); - if (isCloseEnough(pt, strokePadding)) { - return new HitResult(name, that, { - segment: seg, - point: pt - }); - } - } - } - - function checkSegmentPoints(seg, ends) { - return (ends || options.segments) - && checkSegmentPoint(seg, seg._point, 'segment') - || (!ends && options.handles) && ( - checkSegmentPoint(seg, seg._handleIn, 'handle-in') || - checkSegmentPoint(seg, seg._handleOut, 'handle-out')); - } - - function addToArea(point) { - area.add(point); - } - - function checkSegmentStroke(segment) { - var isJoin = closed || segment._index > 0 - && segment._index < numSegments - 1; - if ((isJoin ? join : cap) === 'round') { - return isCloseEnough(segment._point, strokePadding); - } else { - area = new Path({ internal: true, closed: true }); - if (isJoin) { - if (!segment.isSmooth()) { - Path._addBevelJoin(segment, join, strokeRadius, - miterLimit, null, strokeMatrix, addToArea, true); - } - } else if (cap === 'square') { - Path._addSquareCap(segment, cap, strokeRadius, null, - strokeMatrix, addToArea, true); - } - if (!area.isEmpty()) { - var loc; - return area.contains(point) - || (loc = area.getNearestLocation(point)) - && isCloseEnough(loc.getPoint(), tolerancePadding); - } - } - } - - if (options.ends && !options.segments && !closed) { - if (res = checkSegmentPoints(segments[0], true) - || checkSegmentPoints(segments[numSegments - 1], true)) - return res; - } else if (options.segments || options.handles) { - for (var i = 0; i < numSegments; i++) - if (res = checkSegmentPoints(segments[i])) - return res; - } - if (strokeRadius !== null) { - loc = this.getNearestLocation(point); - if (loc) { - var time = loc.getTime(); - if (time === 0 || time === 1 && numSegments > 1) { - if (!checkSegmentStroke(loc.getSegment())) - loc = null; - } else if (!isCloseEnough(loc.getPoint(), strokePadding)) { - loc = null; - } - } - if (!loc && join === 'miter' && numSegments > 1) { - for (var i = 0; i < numSegments; i++) { - var segment = segments[i]; - if (point.getDistance(segment._point) - <= miterLimit * strokeRadius - && checkSegmentStroke(segment)) { - loc = segment.getLocation(); - break; - } - } - } - } - return !loc && hitFill && this._contains(point) - || loc && !hitStroke && !hitCurves - ? new HitResult('fill', this) - : loc - ? new HitResult(hitStroke ? 'stroke' : 'curve', this, { - location: loc, - point: loc.getPoint() - }) - : null; - } - -}, Base.each(Curve._evaluateMethods, - function(name) { - this[name + 'At'] = function(offset) { - var loc = this.getLocationAt(offset); - return loc && loc[name](); - }; - }, -{ - beans: false, - - getLocationOf: function() { - var point = Point.read(arguments), - curves = this.getCurves(); - for (var i = 0, l = curves.length; i < l; i++) { - var loc = curves[i].getLocationOf(point); - if (loc) - return loc; - } - return null; - }, - - getOffsetOf: function() { - var loc = this.getLocationOf.apply(this, arguments); - return loc ? loc.getOffset() : null; - }, - - getLocationAt: function(offset) { - if (typeof offset === 'number') { - var curves = this.getCurves(), - length = 0; - for (var i = 0, l = curves.length; i < l; i++) { - var start = length, - curve = curves[i]; - length += curve.getLength(); - if (length > offset) { - return curve.getLocationAt(offset - start); - } - } - if (curves.length > 0 && offset <= this.getLength()) { - return new CurveLocation(curves[curves.length - 1], 1); - } - } else if (offset && offset.getPath && offset.getPath() === this) { - return offset; - } - return null; - }, - - getOffsetsWithTangent: function() { - var tangent = Point.read(arguments); - if (tangent.isZero()) { - return []; - } - - var offsets = []; - var curveStart = 0; - var curves = this.getCurves(); - for (var i = 0, l = curves.length; i < l; i++) { - var curve = curves[i]; - var curveTimes = curve.getTimesWithTangent(tangent); - for (var j = 0, m = curveTimes.length; j < m; j++) { - var offset = curveStart + curve.getOffsetAtTime(curveTimes[j]); - if (offsets.indexOf(offset) < 0) { - offsets.push(offset); - } - } - curveStart += curve.length; - } - return offsets; - } -}), -new function() { - - function drawHandles(ctx, segments, matrix, size) { - var half = size / 2, - coords = new Array(6), - pX, pY; - - function drawHandle(index) { - var hX = coords[index], - hY = coords[index + 1]; - if (pX != hX || pY != hY) { - ctx.beginPath(); - ctx.moveTo(pX, pY); - ctx.lineTo(hX, hY); - ctx.stroke(); - ctx.beginPath(); - ctx.arc(hX, hY, half, 0, Math.PI * 2, true); - ctx.fill(); - } - } - - for (var i = 0, l = segments.length; i < l; i++) { - var segment = segments[i], - selection = segment._selection; - segment._transformCoordinates(matrix, coords); - pX = coords[0]; - pY = coords[1]; - if (selection & 2) - drawHandle(2); - if (selection & 4) - drawHandle(4); - ctx.fillRect(pX - half, pY - half, size, size); - if (!(selection & 1)) { - var fillStyle = ctx.fillStyle; - ctx.fillStyle = '#ffffff'; - ctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2); - ctx.fillStyle = fillStyle; - } - } - } - - function drawSegments(ctx, path, matrix) { - var segments = path._segments, - length = segments.length, - coords = new Array(6), - first = true, - curX, curY, - prevX, prevY, - inX, inY, - outX, outY; - - function drawSegment(segment) { - if (matrix) { - segment._transformCoordinates(matrix, coords); - curX = coords[0]; - curY = coords[1]; - } else { - var point = segment._point; - curX = point._x; - curY = point._y; - } - if (first) { - ctx.moveTo(curX, curY); - first = false; - } else { - if (matrix) { - inX = coords[2]; - inY = coords[3]; - } else { - var handle = segment._handleIn; - inX = curX + handle._x; - inY = curY + handle._y; - } - if (inX === curX && inY === curY - && outX === prevX && outY === prevY) { - ctx.lineTo(curX, curY); - } else { - ctx.bezierCurveTo(outX, outY, inX, inY, curX, curY); - } - } - prevX = curX; - prevY = curY; - if (matrix) { - outX = coords[4]; - outY = coords[5]; - } else { - var handle = segment._handleOut; - outX = prevX + handle._x; - outY = prevY + handle._y; - } - } - - for (var i = 0; i < length; i++) - drawSegment(segments[i]); - if (path._closed && length > 0) - drawSegment(segments[0]); - } - - return { - _draw: function(ctx, param, viewMatrix, strokeMatrix) { - var dontStart = param.dontStart, - dontPaint = param.dontFinish || param.clip, - style = this.getStyle(), - hasFill = style.hasFill(), - hasStroke = style.hasStroke(), - dashArray = style.getDashArray(), - dashLength = !paper.support.nativeDash && hasStroke - && dashArray && dashArray.length; - - if (!dontStart) - ctx.beginPath(); - - if (hasFill || hasStroke && !dashLength || dontPaint) { - drawSegments(ctx, this, strokeMatrix); - if (this._closed) - ctx.closePath(); - } - - function getOffset(i) { - return dashArray[((i % dashLength) + dashLength) % dashLength]; - } - - if (!dontPaint && (hasFill || hasStroke)) { - this._setStyles(ctx, param, viewMatrix); - if (hasFill) { - ctx.fill(style.getFillRule()); - ctx.shadowColor = 'rgba(0,0,0,0)'; - } - if (hasStroke) { - if (dashLength) { - if (!dontStart) - ctx.beginPath(); - var flattener = new PathFlattener(this, 0.25, 32, false, - strokeMatrix), - length = flattener.length, - from = -style.getDashOffset(), to, - i = 0; - from = from % length; - while (from > 0) { - from -= getOffset(i--) + getOffset(i--); - } - while (from < length) { - to = from + getOffset(i++); - if (from > 0 || to > 0) - flattener.drawPart(ctx, - Math.max(from, 0), Math.max(to, 0)); - from = to + getOffset(i++); - } - } - ctx.stroke(); - } - } - }, - - _drawSelected: function(ctx, matrix) { - ctx.beginPath(); - drawSegments(ctx, this, matrix); - ctx.stroke(); - drawHandles(ctx, this._segments, matrix, paper.settings.handleSize); - } - }; -}, -new function() { - function getCurrentSegment(that) { - var segments = that._segments; - if (!segments.length) - throw new Error('Use a moveTo() command first'); - return segments[segments.length - 1]; - } - - return { - moveTo: function() { - var segments = this._segments; - if (segments.length === 1) - this.removeSegment(0); - if (!segments.length) - this._add([ new Segment(Point.read(arguments)) ]); - }, - - moveBy: function() { - throw new Error('moveBy() is unsupported on Path items.'); - }, - - lineTo: function() { - this._add([ new Segment(Point.read(arguments)) ]); - }, - - cubicCurveTo: function() { - var handle1 = Point.read(arguments), - handle2 = Point.read(arguments), - to = Point.read(arguments), - current = getCurrentSegment(this); - current.setHandleOut(handle1.subtract(current._point)); - this._add([ new Segment(to, handle2.subtract(to)) ]); - }, - - quadraticCurveTo: function() { - var handle = Point.read(arguments), - to = Point.read(arguments), - current = getCurrentSegment(this)._point; - this.cubicCurveTo( - handle.add(current.subtract(handle).multiply(1 / 3)), - handle.add(to.subtract(handle).multiply(1 / 3)), - to - ); - }, - - curveTo: function() { - var through = Point.read(arguments), - to = Point.read(arguments), - t = Base.pick(Base.read(arguments), 0.5), - t1 = 1 - t, - current = getCurrentSegment(this)._point, - handle = through.subtract(current.multiply(t1 * t1)) - .subtract(to.multiply(t * t)).divide(2 * t * t1); - if (handle.isNaN()) - throw new Error( - 'Cannot put a curve through points with parameter = ' + t); - this.quadraticCurveTo(handle, to); - }, - - arcTo: function() { - var abs = Math.abs, - sqrt = Math.sqrt, - current = getCurrentSegment(this), - from = current._point, - to = Point.read(arguments), - through, - peek = Base.peek(arguments), - clockwise = Base.pick(peek, true), - center, extent, vector, matrix; - if (typeof clockwise === 'boolean') { - var middle = from.add(to).divide(2), - through = middle.add(middle.subtract(from).rotate( - clockwise ? -90 : 90)); - } else if (Base.remain(arguments) <= 2) { - through = to; - to = Point.read(arguments); - } else { - var radius = Size.read(arguments), - isZero = Numerical.isZero; - if (isZero(radius.width) || isZero(radius.height)) - return this.lineTo(to); - var rotation = Base.read(arguments), - clockwise = !!Base.read(arguments), - large = !!Base.read(arguments), - middle = from.add(to).divide(2), - pt = from.subtract(middle).rotate(-rotation), - x = pt.x, - y = pt.y, - rx = abs(radius.width), - ry = abs(radius.height), - rxSq = rx * rx, - rySq = ry * ry, - xSq = x * x, - ySq = y * y; - var factor = sqrt(xSq / rxSq + ySq / rySq); - if (factor > 1) { - rx *= factor; - ry *= factor; - rxSq = rx * rx; - rySq = ry * ry; - } - factor = (rxSq * rySq - rxSq * ySq - rySq * xSq) / - (rxSq * ySq + rySq * xSq); - if (abs(factor) < 1e-12) - factor = 0; - if (factor < 0) - throw new Error( - 'Cannot create an arc with the given arguments'); - center = new Point(rx * y / ry, -ry * x / rx) - .multiply((large === clockwise ? -1 : 1) * sqrt(factor)) - .rotate(rotation).add(middle); - matrix = new Matrix().translate(center).rotate(rotation) - .scale(rx, ry); - vector = matrix._inverseTransform(from); - extent = vector.getDirectedAngle(matrix._inverseTransform(to)); - if (!clockwise && extent > 0) - extent -= 360; - else if (clockwise && extent < 0) - extent += 360; - } - if (through) { - var l1 = new Line(from.add(through).divide(2), - through.subtract(from).rotate(90), true), - l2 = new Line(through.add(to).divide(2), - to.subtract(through).rotate(90), true), - line = new Line(from, to), - throughSide = line.getSide(through); - center = l1.intersect(l2, true); - if (!center) { - if (!throughSide) - return this.lineTo(to); - throw new Error( - 'Cannot create an arc with the given arguments'); - } - vector = from.subtract(center); - extent = vector.getDirectedAngle(to.subtract(center)); - var centerSide = line.getSide(center, true); - if (centerSide === 0) { - extent = throughSide * abs(extent); - } else if (throughSide === centerSide) { - extent += extent < 0 ? 360 : -360; - } - } - var epsilon = 1e-7, - ext = abs(extent), - count = ext >= 360 ? 4 : Math.ceil((ext - epsilon) / 90), - inc = extent / count, - half = inc * Math.PI / 360, - z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)), - segments = []; - for (var i = 0; i <= count; i++) { - var pt = to, - out = null; - if (i < count) { - out = vector.rotate(90).multiply(z); - if (matrix) { - pt = matrix._transformPoint(vector); - out = matrix._transformPoint(vector.add(out)) - .subtract(pt); - } else { - pt = center.add(vector); - } - } - if (!i) { - current.setHandleOut(out); - } else { - var _in = vector.rotate(-90).multiply(z); - if (matrix) { - _in = matrix._transformPoint(vector.add(_in)) - .subtract(pt); - } - segments.push(new Segment(pt, _in, out)); - } - vector = vector.rotate(inc); - } - this._add(segments); - }, - - lineBy: function() { - var to = Point.read(arguments), - current = getCurrentSegment(this)._point; - this.lineTo(current.add(to)); - }, - - curveBy: function() { - var through = Point.read(arguments), - to = Point.read(arguments), - parameter = Base.read(arguments), - current = getCurrentSegment(this)._point; - this.curveTo(current.add(through), current.add(to), parameter); - }, - - cubicCurveBy: function() { - var handle1 = Point.read(arguments), - handle2 = Point.read(arguments), - to = Point.read(arguments), - current = getCurrentSegment(this)._point; - this.cubicCurveTo(current.add(handle1), current.add(handle2), - current.add(to)); - }, - - quadraticCurveBy: function() { - var handle = Point.read(arguments), - to = Point.read(arguments), - current = getCurrentSegment(this)._point; - this.quadraticCurveTo(current.add(handle), current.add(to)); - }, - - arcBy: function() { - var current = getCurrentSegment(this)._point, - point = current.add(Point.read(arguments)), - clockwise = Base.pick(Base.peek(arguments), true); - if (typeof clockwise === 'boolean') { - this.arcTo(point, clockwise); - } else { - this.arcTo(point, current.add(Point.read(arguments))); - } - }, - - closePath: function(tolerance) { - this.setClosed(true); - this.join(this, tolerance); - } - }; -}, { - - _getBounds: function(matrix, options) { - var method = options.handle - ? 'getHandleBounds' - : options.stroke - ? 'getStrokeBounds' - : 'getBounds'; - return Path[method](this._segments, this._closed, this, matrix, options); - }, - -statics: { - getBounds: function(segments, closed, path, matrix, options, strokePadding) { - var first = segments[0]; - if (!first) - return new Rectangle(); - var coords = new Array(6), - prevCoords = first._transformCoordinates(matrix, new Array(6)), - min = prevCoords.slice(0, 2), - max = min.slice(), - roots = new Array(2); - - function processSegment(segment) { - segment._transformCoordinates(matrix, coords); - for (var i = 0; i < 2; i++) { - Curve._addBounds( - prevCoords[i], - prevCoords[i + 4], - coords[i + 2], - coords[i], - i, strokePadding ? strokePadding[i] : 0, min, max, roots); - } - var tmp = prevCoords; - prevCoords = coords; - coords = tmp; - } - - for (var i = 1, l = segments.length; i < l; i++) - processSegment(segments[i]); - if (closed) - processSegment(first); - return new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]); - }, - - getStrokeBounds: function(segments, closed, path, matrix, options) { - var style = path.getStyle(), - stroke = style.hasStroke(), - strokeWidth = style.getStrokeWidth(), - strokeMatrix = stroke && path._getStrokeMatrix(matrix, options), - strokePadding = stroke && Path._getStrokePadding(strokeWidth, - strokeMatrix), - bounds = Path.getBounds(segments, closed, path, matrix, options, - strokePadding); - if (!stroke) - return bounds; - var strokeRadius = strokeWidth / 2, - join = style.getStrokeJoin(), - cap = style.getStrokeCap(), - miterLimit = style.getMiterLimit(), - joinBounds = new Rectangle(new Size(strokePadding)); - - function addPoint(point) { - bounds = bounds.include(point); - } - - function addRound(segment) { - bounds = bounds.unite( - joinBounds.setCenter(segment._point.transform(matrix))); - } - - function addJoin(segment, join) { - if (join === 'round' || segment.isSmooth()) { - addRound(segment); - } else { - Path._addBevelJoin(segment, join, strokeRadius, miterLimit, - matrix, strokeMatrix, addPoint); - } - } - - function addCap(segment, cap) { - if (cap === 'round') { - addRound(segment); - } else { - Path._addSquareCap(segment, cap, strokeRadius, matrix, - strokeMatrix, addPoint); - } - } - - var length = segments.length - (closed ? 0 : 1); - for (var i = 1; i < length; i++) - addJoin(segments[i], join); - if (closed) { - addJoin(segments[0], join); - } else if (length > 0) { - addCap(segments[0], cap); - addCap(segments[segments.length - 1], cap); - } - return bounds; - }, - - _getStrokePadding: function(radius, matrix) { - if (!matrix) - return [radius, radius]; - var hor = new Point(radius, 0).transform(matrix), - ver = new Point(0, radius).transform(matrix), - phi = hor.getAngleInRadians(), - a = hor.getLength(), - b = ver.getLength(); - var sin = Math.sin(phi), - cos = Math.cos(phi), - tan = Math.tan(phi), - tx = Math.atan2(b * tan, a), - ty = Math.atan2(b, tan * a); - return [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin), - Math.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)]; - }, - - _addBevelJoin: function(segment, join, radius, miterLimit, matrix, - strokeMatrix, addPoint, isArea) { - var curve2 = segment.getCurve(), - curve1 = curve2.getPrevious(), - point = curve2.getPoint1().transform(matrix), - normal1 = curve1.getNormalAtTime(1).multiply(radius) - .transform(strokeMatrix), - normal2 = curve2.getNormalAtTime(0).multiply(radius) - .transform(strokeMatrix); - if (normal1.getDirectedAngle(normal2) < 0) { - normal1 = normal1.negate(); - normal2 = normal2.negate(); - } - if (isArea) - addPoint(point); - addPoint(point.add(normal1)); - if (join === 'miter') { - var corner = new Line(point.add(normal1), - new Point(-normal1.y, normal1.x), true - ).intersect(new Line(point.add(normal2), - new Point(-normal2.y, normal2.x), true - ), true); - if (corner && point.getDistance(corner) <= miterLimit * radius) { - addPoint(corner); - } - } - addPoint(point.add(normal2)); - }, - - _addSquareCap: function(segment, cap, radius, matrix, strokeMatrix, - addPoint, isArea) { - var point = segment._point.transform(matrix), - loc = segment.getLocation(), - normal = loc.getNormal() - .multiply(loc.getTime() === 0 ? radius : -radius) - .transform(strokeMatrix); - if (cap === 'square') { - if (isArea) { - addPoint(point.subtract(normal)); - addPoint(point.add(normal)); - } - point = point.add(normal.rotate(-90)); - } - addPoint(point.add(normal)); - addPoint(point.subtract(normal)); - }, - - getHandleBounds: function(segments, closed, path, matrix, options) { - var style = path.getStyle(), - stroke = options.stroke && style.hasStroke(), - strokePadding, - joinPadding; - if (stroke) { - var strokeMatrix = path._getStrokeMatrix(matrix, options), - strokeRadius = style.getStrokeWidth() / 2, - joinRadius = strokeRadius; - if (style.getStrokeJoin() === 'miter') - joinRadius = strokeRadius * style.getMiterLimit(); - if (style.getStrokeCap() === 'square') - joinRadius = Math.max(joinRadius, strokeRadius * Math.SQRT2); - strokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix); - joinPadding = Path._getStrokePadding(joinRadius, strokeMatrix); - } - var coords = new Array(6), - x1 = Infinity, - x2 = -x1, - y1 = x1, - y2 = x2; - for (var i = 0, l = segments.length; i < l; i++) { - var segment = segments[i]; - segment._transformCoordinates(matrix, coords); - for (var j = 0; j < 6; j += 2) { - var padding = !j ? joinPadding : strokePadding, - paddingX = padding ? padding[0] : 0, - paddingY = padding ? padding[1] : 0, - x = coords[j], - y = coords[j + 1], - xn = x - paddingX, - xx = x + paddingX, - yn = y - paddingY, - yx = y + paddingY; - if (xn < x1) x1 = xn; - if (xx > x2) x2 = xx; - if (yn < y1) y1 = yn; - if (yx > y2) y2 = yx; - } - } - return new Rectangle(x1, y1, x2 - x1, y2 - y1); - } -}}); - -Path.inject({ statics: new function() { - - var kappa = 0.5522847498307936, - ellipseSegments = [ - new Segment([-1, 0], [0, kappa ], [0, -kappa]), - new Segment([0, -1], [-kappa, 0], [kappa, 0 ]), - new Segment([1, 0], [0, -kappa], [0, kappa ]), - new Segment([0, 1], [kappa, 0 ], [-kappa, 0]) - ]; - - function createPath(segments, closed, args) { - var props = Base.getNamed(args), - path = new Path(props && props.insert == false && Item.NO_INSERT); - path._add(segments); - path._closed = closed; - return path.set(props, { insert: true }); - } - - function createEllipse(center, radius, args) { - var segments = new Array(4); - for (var i = 0; i < 4; i++) { - var segment = ellipseSegments[i]; - segments[i] = new Segment( - segment._point.multiply(radius).add(center), - segment._handleIn.multiply(radius), - segment._handleOut.multiply(radius) - ); - } - return createPath(segments, true, args); - } - - return { - Line: function() { - return createPath([ - new Segment(Point.readNamed(arguments, 'from')), - new Segment(Point.readNamed(arguments, 'to')) - ], false, arguments); - }, - - Circle: function() { - var center = Point.readNamed(arguments, 'center'), - radius = Base.readNamed(arguments, 'radius'); - return createEllipse(center, new Size(radius), arguments); - }, - - Rectangle: function() { - var rect = Rectangle.readNamed(arguments, 'rectangle'), - radius = Size.readNamed(arguments, 'radius', 0, - { readNull: true }), - bl = rect.getBottomLeft(true), - tl = rect.getTopLeft(true), - tr = rect.getTopRight(true), - br = rect.getBottomRight(true), - segments; - if (!radius || radius.isZero()) { - segments = [ - new Segment(bl), - new Segment(tl), - new Segment(tr), - new Segment(br) - ]; - } else { - radius = Size.min(radius, rect.getSize(true).divide(2)); - var rx = radius.width, - ry = radius.height, - hx = rx * kappa, - hy = ry * kappa; - segments = [ - new Segment(bl.add(rx, 0), null, [-hx, 0]), - new Segment(bl.subtract(0, ry), [0, hy]), - new Segment(tl.add(0, ry), null, [0, -hy]), - new Segment(tl.add(rx, 0), [-hx, 0], null), - new Segment(tr.subtract(rx, 0), null, [hx, 0]), - new Segment(tr.add(0, ry), [0, -hy], null), - new Segment(br.subtract(0, ry), null, [0, hy]), - new Segment(br.subtract(rx, 0), [hx, 0]) - ]; - } - return createPath(segments, true, arguments); - }, - - RoundRectangle: '#Rectangle', - - Ellipse: function() { - var ellipse = Shape._readEllipse(arguments); - return createEllipse(ellipse.center, ellipse.radius, arguments); - }, - - Oval: '#Ellipse', - - Arc: function() { - var from = Point.readNamed(arguments, 'from'), - through = Point.readNamed(arguments, 'through'), - to = Point.readNamed(arguments, 'to'), - props = Base.getNamed(arguments), - path = new Path(props && props.insert == false - && Item.NO_INSERT); - path.moveTo(from); - path.arcTo(through, to); - return path.set(props); - }, - - RegularPolygon: function() { - var center = Point.readNamed(arguments, 'center'), - sides = Base.readNamed(arguments, 'sides'), - radius = Base.readNamed(arguments, 'radius'), - step = 360 / sides, - three = sides % 3 === 0, - vector = new Point(0, three ? -radius : radius), - offset = three ? -1 : 0.5, - segments = new Array(sides); - for (var i = 0; i < sides; i++) - segments[i] = new Segment(center.add( - vector.rotate((i + offset) * step))); - return createPath(segments, true, arguments); - }, - - Star: function() { - var center = Point.readNamed(arguments, 'center'), - points = Base.readNamed(arguments, 'points') * 2, - radius1 = Base.readNamed(arguments, 'radius1'), - radius2 = Base.readNamed(arguments, 'radius2'), - step = 360 / points, - vector = new Point(0, -1), - segments = new Array(points); - for (var i = 0; i < points; i++) - segments[i] = new Segment(center.add(vector.rotate(step * i) - .multiply(i % 2 ? radius2 : radius1))); - return createPath(segments, true, arguments); - } - }; -}}); - -var CompoundPath = PathItem.extend({ - _class: 'CompoundPath', - _serializeFields: { - children: [] - }, - beans: true, - - initialize: function CompoundPath(arg) { - this._children = []; - this._namedChildren = {}; - if (!this._initialize(arg)) { - if (typeof arg === 'string') { - this.setPathData(arg); - } else { - this.addChildren(Array.isArray(arg) ? arg : arguments); - } - } - }, - - insertChildren: function insertChildren(index, items) { - var list = items, - first = list[0]; - if (first && typeof first[0] === 'number') - list = [list]; - for (var i = items.length - 1; i >= 0; i--) { - var item = list[i]; - if (list === items && !(item instanceof Path)) - list = Base.slice(list); - if (Array.isArray(item)) { - list[i] = new Path({ segments: item, insert: false }); - } else if (item instanceof CompoundPath) { - list.splice.apply(list, [i, 1].concat(item.removeChildren())); - item.remove(); - } - } - return insertChildren.base.call(this, index, list); - }, - - reduce: function reduce(options) { - var children = this._children; - for (var i = children.length - 1; i >= 0; i--) { - var path = children[i].reduce(options); - if (path.isEmpty()) - path.remove(); - } - if (!children.length) { - var path = new Path(Item.NO_INSERT); - path.copyAttributes(this); - path.insertAbove(this); - this.remove(); - return path; - } - return reduce.base.call(this); - }, - - isClosed: function() { - var children = this._children; - for (var i = 0, l = children.length; i < l; i++) { - if (!children[i]._closed) - return false; - } - return true; - }, - - setClosed: function(closed) { - var children = this._children; - for (var i = 0, l = children.length; i < l; i++) { - children[i].setClosed(closed); - } - }, - - getFirstSegment: function() { - var first = this.getFirstChild(); - return first && first.getFirstSegment(); - }, - - getLastSegment: function() { - var last = this.getLastChild(); - return last && last.getLastSegment(); - }, - - getCurves: function() { - var children = this._children, - curves = []; - for (var i = 0, l = children.length; i < l; i++) { - Base.push(curves, children[i].getCurves()); - } - return curves; - }, - - getFirstCurve: function() { - var first = this.getFirstChild(); - return first && first.getFirstCurve(); - }, - - getLastCurve: function() { - var last = this.getLastChild(); - return last && last.getLastCurve(); - }, - - getArea: function() { - var children = this._children, - area = 0; - for (var i = 0, l = children.length; i < l; i++) - area += children[i].getArea(); - return area; - }, - - getLength: function() { - var children = this._children, - length = 0; - for (var i = 0, l = children.length; i < l; i++) - length += children[i].getLength(); - return length; - }, - - getPathData: function(_matrix, _precision) { - var children = this._children, - paths = []; - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i], - mx = child._matrix; - paths.push(child.getPathData(_matrix && !mx.isIdentity() - ? _matrix.appended(mx) : _matrix, _precision)); - } - return paths.join(''); - }, - - _hitTestChildren: function _hitTestChildren(point, options, viewMatrix) { - return _hitTestChildren.base.call(this, point, - options.class === Path || options.type === 'path' ? options - : Base.set({}, options, { fill: false }), - viewMatrix); - }, - - _draw: function(ctx, param, viewMatrix, strokeMatrix) { - var children = this._children; - if (!children.length) - return; - - param = param.extend({ dontStart: true, dontFinish: true }); - ctx.beginPath(); - for (var i = 0, l = children.length; i < l; i++) - children[i].draw(ctx, param, strokeMatrix); - - if (!param.clip) { - this._setStyles(ctx, param, viewMatrix); - var style = this._style; - if (style.hasFill()) { - ctx.fill(style.getFillRule()); - ctx.shadowColor = 'rgba(0,0,0,0)'; - } - if (style.hasStroke()) - ctx.stroke(); - } - }, - - _drawSelected: function(ctx, matrix, selectionItems) { - var children = this._children; - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i], - mx = child._matrix; - if (!selectionItems[child._id]) { - child._drawSelected(ctx, mx.isIdentity() ? matrix - : matrix.appended(mx)); - } - } - } -}, -new function() { - function getCurrentPath(that, check) { - var children = that._children; - if (check && !children.length) - throw new Error('Use a moveTo() command first'); - return children[children.length - 1]; - } - - return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo', - 'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy', - 'arcBy'], - function(key) { - this[key] = function() { - var path = getCurrentPath(this, true); - path[key].apply(path, arguments); - }; - }, { - moveTo: function() { - var current = getCurrentPath(this), - path = current && current.isEmpty() ? current - : new Path(Item.NO_INSERT); - if (path !== current) - this.addChild(path); - path.moveTo.apply(path, arguments); - }, - - moveBy: function() { - var current = getCurrentPath(this, true), - last = current && current.getLastSegment(), - point = Point.read(arguments); - this.moveTo(last ? point.add(last._point) : point); - }, - - closePath: function(tolerance) { - getCurrentPath(this, true).closePath(tolerance); - } - } - ); -}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) { - this[key] = function(param) { - var children = this._children, - res; - for (var i = 0, l = children.length; i < l; i++) { - res = children[i][key](param) || res; - } - return res; - }; -}, {})); - -PathItem.inject(new function() { - var min = Math.min, - max = Math.max, - abs = Math.abs, - operators = { - unite: { '1': true, '2': true }, - intersect: { '2': true }, - subtract: { '1': true }, - exclude: { '1': true, '-1': true } - }; - - function preparePath(path, resolve) { - var res = path.clone(false).reduce({ simplify: true }) - .transform(null, true, true); - return resolve - ? res.resolveCrossings().reorient( - res.getFillRule() === 'nonzero', true) - : res; - } - - function createResult(paths, simplify, path1, path2, options) { - var result = new CompoundPath(Item.NO_INSERT); - result.addChildren(paths, true); - result = result.reduce({ simplify: simplify }); - if (!(options && options.insert == false)) { - result.insertAbove(path2 && path1.isSibling(path2) - && path1.getIndex() < path2.getIndex() ? path2 : path1); - } - result.copyAttributes(path1, true); - return result; - } - - function traceBoolean(path1, path2, operation, options) { - if (options && (options.trace == false || options.stroke) && - /^(subtract|intersect)$/.test(operation)) - return splitBoolean(path1, path2, operation); - var _path1 = preparePath(path1, true), - _path2 = path2 && path1 !== path2 && preparePath(path2, true), - operator = operators[operation]; - operator[operation] = true; - if (_path2 && (operator.subtract || operator.exclude) - ^ (_path2.isClockwise() ^ _path1.isClockwise())) - _path2.reverse(); - var crossings = divideLocations( - CurveLocation.expand(_path1.getCrossings(_path2))), - paths1 = _path1._children || [_path1], - paths2 = _path2 && (_path2._children || [_path2]), - segments = [], - curves = [], - paths; - - function collect(paths) { - for (var i = 0, l = paths.length; i < l; i++) { - var path = paths[i]; - Base.push(segments, path._segments); - Base.push(curves, path.getCurves()); - path._overlapsOnly = true; - } - } - - if (crossings.length) { - collect(paths1); - if (paths2) - collect(paths2); - for (var i = 0, l = crossings.length; i < l; i++) { - propagateWinding(crossings[i]._segment, _path1, _path2, curves, - operator); - } - for (var i = 0, l = segments.length; i < l; i++) { - var segment = segments[i], - inter = segment._intersection; - if (!segment._winding) { - propagateWinding(segment, _path1, _path2, curves, operator); - } - if (!(inter && inter._overlap)) - segment._path._overlapsOnly = false; - } - paths = tracePaths(segments, operator); - } else { - paths = reorientPaths( - paths2 ? paths1.concat(paths2) : paths1.slice(), - function(w) { - return !!operator[w]; - }); - } - - return createResult(paths, true, path1, path2, options); - } - - function splitBoolean(path1, path2, operation) { - var _path1 = preparePath(path1), - _path2 = preparePath(path2), - crossings = _path1.getCrossings(_path2), - subtract = operation === 'subtract', - divide = operation === 'divide', - added = {}, - paths = []; - - function addPath(path) { - if (!added[path._id] && (divide || - _path2.contains(path.getPointAt(path.getLength() / 2)) - ^ subtract)) { - paths.unshift(path); - return added[path._id] = true; - } - } - - for (var i = crossings.length - 1; i >= 0; i--) { - var path = crossings[i].split(); - if (path) { - if (addPath(path)) - path.getFirstSegment().setHandleIn(0, 0); - _path1.getLastSegment().setHandleOut(0, 0); - } - } - addPath(_path1); - return createResult(paths, false, path1, path2); - } - - function linkIntersections(from, to) { - var prev = from; - while (prev) { - if (prev === to) - return; - prev = prev._previous; - } - while (from._next && from._next !== to) - from = from._next; - if (!from._next) { - while (to._previous) - to = to._previous; - from._next = to; - to._previous = from; - } - } - - function clearCurveHandles(curves) { - for (var i = curves.length - 1; i >= 0; i--) - curves[i].clearHandles(); - } - - function reorientPaths(paths, isInside, clockwise) { - var length = paths && paths.length; - if (length) { - var lookup = Base.each(paths, function (path, i) { - this[path._id] = { - container: null, - winding: path.isClockwise() ? 1 : -1, - index: i - }; - }, {}), - sorted = paths.slice().sort(function (a, b) { - return abs(b.getArea()) - abs(a.getArea()); - }), - first = sorted[0]; - if (clockwise == null) - clockwise = first.isClockwise(); - for (var i = 0; i < length; i++) { - var path1 = sorted[i], - entry1 = lookup[path1._id], - point = path1.getInteriorPoint(), - containerWinding = 0; - for (var j = i - 1; j >= 0; j--) { - var path2 = sorted[j]; - if (path2.contains(point)) { - var entry2 = lookup[path2._id]; - containerWinding = entry2.winding; - entry1.winding += containerWinding; - entry1.container = entry2.exclude ? entry2.container - : path2; - break; - } - } - if (isInside(entry1.winding) === isInside(containerWinding)) { - entry1.exclude = true; - paths[entry1.index] = null; - } else { - var container = entry1.container; - path1.setClockwise(container ? !container.isClockwise() - : clockwise); - } - } - } - return paths; - } - - function divideLocations(locations, include, clearLater) { - var results = include && [], - tMin = 1e-8, - tMax = 1 - tMin, - clearHandles = false, - clearCurves = clearLater || [], - clearLookup = clearLater && {}, - renormalizeLocs, - prevCurve, - prevTime; - - function getId(curve) { - return curve._path._id + '.' + curve._segment1._index; - } - - for (var i = (clearLater && clearLater.length) - 1; i >= 0; i--) { - var curve = clearLater[i]; - if (curve._path) - clearLookup[getId(curve)] = true; - } - - for (var i = locations.length - 1; i >= 0; i--) { - var loc = locations[i], - time = loc._time, - origTime = time, - exclude = include && !include(loc), - curve = loc._curve, - segment; - if (curve) { - if (curve !== prevCurve) { - clearHandles = !curve.hasHandles() - || clearLookup && clearLookup[getId(curve)]; - renormalizeLocs = []; - prevTime = null; - prevCurve = curve; - } else if (prevTime >= tMin) { - time /= prevTime; - } - } - if (exclude) { - if (renormalizeLocs) - renormalizeLocs.push(loc); - continue; - } else if (include) { - results.unshift(loc); - } - prevTime = origTime; - if (time < tMin) { - segment = curve._segment1; - } else if (time > tMax) { - segment = curve._segment2; - } else { - var newCurve = curve.divideAtTime(time, true); - if (clearHandles) - clearCurves.push(curve, newCurve); - segment = newCurve._segment1; - for (var j = renormalizeLocs.length - 1; j >= 0; j--) { - var l = renormalizeLocs[j]; - l._time = (l._time - time) / (1 - time); - } - } - loc._setSegment(segment); - var inter = segment._intersection, - dest = loc._intersection; - if (inter) { - linkIntersections(inter, dest); - var other = inter; - while (other) { - linkIntersections(other._intersection, inter); - other = other._next; - } - } else { - segment._intersection = dest; - } - } - if (!clearLater) - clearCurveHandles(clearCurves); - return results || locations; - } - - function getWinding(point, curves, dir, closed, dontFlip) { - var ia = dir ? 1 : 0, - io = ia ^ 1, - pv = [point.x, point.y], - pa = pv[ia], - po = pv[io], - windingEpsilon = 1e-9, - qualityEpsilon = 1e-6, - paL = pa - windingEpsilon, - paR = pa + windingEpsilon, - windingL = 0, - windingR = 0, - pathWindingL = 0, - pathWindingR = 0, - onPath = false, - onAnyPath = false, - quality = 1, - roots = [], - vPrev, - vClose; - - function addWinding(v) { - var o0 = v[io + 0], - o3 = v[io + 6]; - if (po < min(o0, o3) || po > max(o0, o3)) { - return; - } - var a0 = v[ia + 0], - a1 = v[ia + 2], - a2 = v[ia + 4], - a3 = v[ia + 6]; - if (o0 === o3) { - if (a0 < paR && a3 > paL || a3 < paR && a0 > paL) { - onPath = true; - } - return; - } - var t = po === o0 ? 0 - : po === o3 ? 1 - : paL > max(a0, a1, a2, a3) || paR < min(a0, a1, a2, a3) - ? 1 - : Curve.solveCubic(v, io, po, roots, 0, 1) > 0 - ? roots[0] - : 1, - a = t === 0 ? a0 - : t === 1 ? a3 - : Curve.getPoint(v, t)[dir ? 'y' : 'x'], - winding = o0 > o3 ? 1 : -1, - windingPrev = vPrev[io] > vPrev[io + 6] ? 1 : -1, - a3Prev = vPrev[ia + 6]; - if (po !== o0) { - if (a < paL) { - pathWindingL += winding; - } else if (a > paR) { - pathWindingR += winding; - } else { - onPath = true; - } - if (a > pa - qualityEpsilon && a < pa + qualityEpsilon) - quality /= 2; - } else { - if (winding !== windingPrev) { - if (a0 < paL) { - pathWindingL += winding; - } else if (a0 > paR) { - pathWindingR += winding; - } - } else if (a0 != a3Prev) { - if (a3Prev < paR && a > paR) { - pathWindingR += winding; - onPath = true; - } else if (a3Prev > paL && a < paL) { - pathWindingL += winding; - onPath = true; - } - } - quality = 0; - } - vPrev = v; - return !dontFlip && a > paL && a < paR - && Curve.getTangent(v, t)[dir ? 'x' : 'y'] === 0 - && getWinding(point, curves, !dir, closed, true); - } - - function handleCurve(v) { - var o0 = v[io + 0], - o1 = v[io + 2], - o2 = v[io + 4], - o3 = v[io + 6]; - if (po <= max(o0, o1, o2, o3) && po >= min(o0, o1, o2, o3)) { - var a0 = v[ia + 0], - a1 = v[ia + 2], - a2 = v[ia + 4], - a3 = v[ia + 6], - monoCurves = paL > max(a0, a1, a2, a3) || - paR < min(a0, a1, a2, a3) - ? [v] : Curve.getMonoCurves(v, dir), - res; - for (var i = 0, l = monoCurves.length; i < l; i++) { - if (res = addWinding(monoCurves[i])) - return res; - } - } - } - - for (var i = 0, l = curves.length; i < l; i++) { - var curve = curves[i], - path = curve._path, - v = curve.getValues(), - res; - if (!i || curves[i - 1]._path !== path) { - vPrev = null; - if (!path._closed) { - vClose = Curve.getValues( - path.getLastCurve().getSegment2(), - curve.getSegment1(), - null, !closed); - if (vClose[io] !== vClose[io + 6]) { - vPrev = vClose; - } - } - - if (!vPrev) { - vPrev = v; - var prev = path.getLastCurve(); - while (prev && prev !== curve) { - var v2 = prev.getValues(); - if (v2[io] !== v2[io + 6]) { - vPrev = v2; - break; - } - prev = prev.getPrevious(); - } - } - } - - if (res = handleCurve(v)) - return res; - - if (i + 1 === l || curves[i + 1]._path !== path) { - if (vClose && (res = handleCurve(vClose))) - return res; - if (onPath && !pathWindingL && !pathWindingR) { - pathWindingL = pathWindingR = path.isClockwise(closed) ^ dir - ? 1 : -1; - } - windingL += pathWindingL; - windingR += pathWindingR; - pathWindingL = pathWindingR = 0; - if (onPath) { - onAnyPath = true; - onPath = false; - } - vClose = null; - } - } - windingL = abs(windingL); - windingR = abs(windingR); - return { - winding: max(windingL, windingR), - windingL: windingL, - windingR: windingR, - quality: quality, - onPath: onAnyPath - }; - } - - function propagateWinding(segment, path1, path2, curves, operator) { - var chain = [], - start = segment, - totalLength = 0, - winding; - do { - var curve = segment.getCurve(), - length = curve.getLength(); - chain.push({ segment: segment, curve: curve, length: length }); - totalLength += length; - segment = segment.getNext(); - } while (segment && !segment._intersection && segment !== start); - var offsets = [0.5, 0.25, 0.75], - winding = { winding: 0, quality: -1 }, - tMin = 1e-8, - tMax = 1 - tMin; - for (var i = 0; i < offsets.length && winding.quality < 0.5; i++) { - var length = totalLength * offsets[i]; - for (var j = 0, l = chain.length; j < l; j++) { - var entry = chain[j], - curveLength = entry.length; - if (length <= curveLength) { - var curve = entry.curve, - path = curve._path, - parent = path._parent, - operand = parent instanceof CompoundPath ? parent : path, - t = Numerical.clamp(curve.getTimeAt(length), tMin, tMax), - pt = curve.getPointAtTime(t), - dir = abs(curve.getTangentAtTime(t).y) < Math.SQRT1_2; - var wind = null; - if (operator.subtract && path2) { - var pathWinding = operand === path1 - ? path2._getWinding(pt, dir, true) - : path1._getWinding(pt, dir, true); - if (operand === path1 && pathWinding.winding || - operand === path2 && !pathWinding.winding) { - if (pathWinding.quality < 1) { - continue; - } else { - wind = { winding: 0, quality: 1 }; - } - } - } - wind = wind || getWinding(pt, curves, dir, true); - if (wind.quality > winding.quality) - winding = wind; - break; - } - length -= curveLength; - } - } - for (var j = chain.length - 1; j >= 0; j--) { - chain[j].segment._winding = winding; - } - } - - function tracePaths(segments, operator) { - var paths = [], - starts; - - function isValid(seg) { - var winding; - return !!(seg && !seg._visited && (!operator - || operator[(winding = seg._winding || {}).winding] - && !(operator.unite && winding.winding === 2 - && winding.windingL && winding.windingR))); - } - - function isStart(seg) { - if (seg) { - for (var i = 0, l = starts.length; i < l; i++) { - if (seg === starts[i]) - return true; - } - } - return false; - } - - function visitPath(path) { - var segments = path._segments; - for (var i = 0, l = segments.length; i < l; i++) { - segments[i]._visited = true; - } - } - - function getCrossingSegments(segment, collectStarts) { - var inter = segment._intersection, - start = inter, - crossings = []; - if (collectStarts) - starts = [segment]; - - function collect(inter, end) { - while (inter && inter !== end) { - var other = inter._segment, - path = other && other._path; - if (path) { - var next = other.getNext() || path.getFirstSegment(), - nextInter = next._intersection; - if (other !== segment && (isStart(other) - || isStart(next) - || next && (isValid(other) && (isValid(next) - || nextInter && isValid(nextInter._segment)))) - ) { - crossings.push(other); - } - if (collectStarts) - starts.push(other); - } - inter = inter._next; - } - } - - if (inter) { - collect(inter); - while (inter && inter._prev) - inter = inter._prev; - collect(inter, start); - } - return crossings; - } - - segments.sort(function(seg1, seg2) { - var inter1 = seg1._intersection, - inter2 = seg2._intersection, - over1 = !!(inter1 && inter1._overlap), - over2 = !!(inter2 && inter2._overlap), - path1 = seg1._path, - path2 = seg2._path; - return over1 ^ over2 - ? over1 ? 1 : -1 - : !inter1 ^ !inter2 - ? inter1 ? 1 : -1 - : path1 !== path2 - ? path1._id - path2._id - : seg1._index - seg2._index; - }); - - for (var i = 0, l = segments.length; i < l; i++) { - var seg = segments[i], - valid = isValid(seg), - path = null, - finished = false, - closed = true, - branches = [], - branch, - visited, - handleIn; - if (valid && seg._path._overlapsOnly) { - var path1 = seg._path, - path2 = seg._intersection._segment._path; - if (path1.compare(path2)) { - if (path1.getArea()) - paths.push(path1.clone(false)); - visitPath(path1); - visitPath(path2); - valid = false; - } - } - while (valid) { - var first = !path, - crossings = getCrossingSegments(seg, first), - other = crossings.shift(), - finished = !first && (isStart(seg) || isStart(other)), - cross = !finished && other; - if (first) { - path = new Path(Item.NO_INSERT); - branch = null; - } - if (finished) { - if (seg.isFirst() || seg.isLast()) - closed = seg._path._closed; - seg._visited = true; - break; - } - if (cross && branch) { - branches.push(branch); - branch = null; - } - if (!branch) { - if (cross) - crossings.push(seg); - branch = { - start: path._segments.length, - crossings: crossings, - visited: visited = [], - handleIn: handleIn - }; - } - if (cross) - seg = other; - if (!isValid(seg)) { - path.removeSegments(branch.start); - for (var j = 0, k = visited.length; j < k; j++) { - visited[j]._visited = false; - } - visited.length = 0; - do { - seg = branch && branch.crossings.shift(); - if (!seg || !seg._path) { - seg = null; - branch = branches.pop(); - if (branch) { - visited = branch.visited; - handleIn = branch.handleIn; - } - } - } while (branch && !isValid(seg)); - if (!seg) - break; - } - var next = seg.getNext(); - path.add(new Segment(seg._point, handleIn, - next && seg._handleOut)); - seg._visited = true; - visited.push(seg); - seg = next || seg._path.getFirstSegment(); - handleIn = next && next._handleIn; - } - if (finished) { - if (closed) { - path.getFirstSegment().setHandleIn(handleIn); - path.setClosed(closed); - } - if (path.getArea() !== 0) { - paths.push(path); - } - } - } - return paths; - } - - return { - _getWinding: function(point, dir, closed) { - return getWinding(point, this.getCurves(), dir, closed); - }, - - unite: function(path, options) { - return traceBoolean(this, path, 'unite', options); - }, - - intersect: function(path, options) { - return traceBoolean(this, path, 'intersect', options); - }, - - subtract: function(path, options) { - return traceBoolean(this, path, 'subtract', options); - }, - - exclude: function(path, options) { - return traceBoolean(this, path, 'exclude', options); - }, - - divide: function(path, options) { - return options && (options.trace == false || options.stroke) - ? splitBoolean(this, path, 'divide') - : createResult([ - this.subtract(path, options), - this.intersect(path, options) - ], true, this, path, options); - }, - - resolveCrossings: function() { - var children = this._children, - paths = children || [this]; - - function hasOverlap(seg, path) { - var inter = seg && seg._intersection; - return inter && inter._overlap && inter._path === path; - } - - var hasOverlaps = false, - hasCrossings = false, - intersections = this.getIntersections(null, function(inter) { - return inter.hasOverlap() && (hasOverlaps = true) || - inter.isCrossing() && (hasCrossings = true); - }), - clearCurves = hasOverlaps && hasCrossings && []; - intersections = CurveLocation.expand(intersections); - if (hasOverlaps) { - var overlaps = divideLocations(intersections, function(inter) { - return inter.hasOverlap(); - }, clearCurves); - for (var i = overlaps.length - 1; i >= 0; i--) { - var overlap = overlaps[i], - path = overlap._path, - seg = overlap._segment, - prev = seg.getPrevious(), - next = seg.getNext(); - if (hasOverlap(prev, path) && hasOverlap(next, path)) { - seg.remove(); - prev._handleOut._set(0, 0); - next._handleIn._set(0, 0); - if (prev !== seg && !prev.getCurve().hasLength()) { - next._handleIn.set(prev._handleIn); - prev.remove(); - } - } - } - } - if (hasCrossings) { - divideLocations(intersections, hasOverlaps && function(inter) { - var curve1 = inter.getCurve(), - seg1 = inter.getSegment(), - other = inter._intersection, - curve2 = other._curve, - seg2 = other._segment; - if (curve1 && curve2 && curve1._path && curve2._path) - return true; - if (seg1) - seg1._intersection = null; - if (seg2) - seg2._intersection = null; - }, clearCurves); - if (clearCurves) - clearCurveHandles(clearCurves); - paths = tracePaths(Base.each(paths, function(path) { - Base.push(this, path._segments); - }, [])); - } - var length = paths.length, - item; - if (length > 1 && children) { - if (paths !== children) - this.setChildren(paths); - item = this; - } else if (length === 1 && !children) { - if (paths[0] !== this) - this.setSegments(paths[0].removeSegments()); - item = this; - } - if (!item) { - item = new CompoundPath(Item.NO_INSERT); - item.addChildren(paths); - item = item.reduce(); - item.copyAttributes(this); - this.replaceWith(item); - } - return item; - }, - - reorient: function(nonZero, clockwise) { - var children = this._children; - if (children && children.length) { - this.setChildren(reorientPaths(this.removeChildren(), - function(w) { - return !!(nonZero ? w : w & 1); - }, - clockwise)); - } else if (clockwise !== undefined) { - this.setClockwise(clockwise); - } - return this; - }, - - getInteriorPoint: function() { - var bounds = this.getBounds(), - point = bounds.getCenter(true); - if (!this.contains(point)) { - var curves = this.getCurves(), - y = point.y, - intercepts = [], - roots = []; - for (var i = 0, l = curves.length; i < l; i++) { - var v = curves[i].getValues(), - o0 = v[1], - o1 = v[3], - o2 = v[5], - o3 = v[7]; - if (y >= min(o0, o1, o2, o3) && y <= max(o0, o1, o2, o3)) { - var monoCurves = Curve.getMonoCurves(v); - for (var j = 0, m = monoCurves.length; j < m; j++) { - var mv = monoCurves[j], - mo0 = mv[1], - mo3 = mv[7]; - if ((mo0 !== mo3) && - (y >= mo0 && y <= mo3 || y >= mo3 && y <= mo0)){ - var x = y === mo0 ? mv[0] - : y === mo3 ? mv[6] - : Curve.solveCubic(mv, 1, y, roots, 0, 1) - === 1 - ? Curve.getPoint(mv, roots[0]).x - : (mv[0] + mv[6]) / 2; - intercepts.push(x); - } - } - } - } - if (intercepts.length > 1) { - intercepts.sort(function(a, b) { return a - b; }); - point.x = (intercepts[0] + intercepts[1]) / 2; - } - } - return point; - } - }; -}); - -var PathFlattener = Base.extend({ - _class: 'PathFlattener', - - initialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) { - var curves = [], - parts = [], - length = 0, - minSpan = 1 / (maxRecursion || 32), - segments = path._segments, - segment1 = segments[0], - segment2; - - function addCurve(segment1, segment2) { - var curve = Curve.getValues(segment1, segment2, matrix); - curves.push(curve); - computeParts(curve, segment1._index, 0, 1); - } - - function computeParts(curve, index, t1, t2) { - if ((t2 - t1) > minSpan - && !(ignoreStraight && Curve.isStraight(curve)) - && !Curve.isFlatEnough(curve, flatness || 0.25)) { - var halves = Curve.subdivide(curve, 0.5), - tMid = (t1 + t2) / 2; - computeParts(halves[0], index, t1, tMid); - computeParts(halves[1], index, tMid, t2); - } else { - var dx = curve[6] - curve[0], - dy = curve[7] - curve[1], - dist = Math.sqrt(dx * dx + dy * dy); - if (dist > 0) { - length += dist; - parts.push({ - offset: length, - curve: curve, - index: index, - time: t2, - }); - } - } - } - - for (var i = 1, l = segments.length; i < l; i++) { - segment2 = segments[i]; - addCurve(segment1, segment2); - segment1 = segment2; - } - if (path._closed) - addCurve(segment2 || segment1, segments[0]); - this.curves = curves; - this.parts = parts; - this.length = length; - this.index = 0; - }, - - _get: function(offset) { - var parts = this.parts, - length = parts.length, - start, - i, j = this.index; - for (;;) { - i = j; - if (!j || parts[--j].offset < offset) - break; - } - for (; i < length; i++) { - var part = parts[i]; - if (part.offset >= offset) { - this.index = i; - var prev = parts[i - 1], - prevTime = prev && prev.index === part.index ? prev.time : 0, - prevOffset = prev ? prev.offset : 0; - return { - index: part.index, - time: prevTime + (part.time - prevTime) - * (offset - prevOffset) / (part.offset - prevOffset) - }; - } - } - return { - index: parts[length - 1].index, - time: 1 - }; - }, - - drawPart: function(ctx, from, to) { - var start = this._get(from), - end = this._get(to); - for (var i = start.index, l = end.index; i <= l; i++) { - var curve = Curve.getPart(this.curves[i], - i === start.index ? start.time : 0, - i === end.index ? end.time : 1); - if (i === start.index) - ctx.moveTo(curve[0], curve[1]); - ctx.bezierCurveTo.apply(ctx, curve.slice(2)); - } - } -}, Base.each(Curve._evaluateMethods, - function(name) { - this[name + 'At'] = function(offset) { - var param = this._get(offset); - return Curve[name](this.curves[param.index], param.time); - }; - }, {}) -); - -var PathFitter = Base.extend({ - initialize: function(path) { - var points = this.points = [], - segments = path._segments, - closed = path._closed; - for (var i = 0, prev, l = segments.length; i < l; i++) { - var point = segments[i].point; - if (!prev || !prev.equals(point)) { - points.push(prev = point.clone()); - } - } - if (closed) { - points.unshift(points[points.length - 1]); - points.push(points[1]); - } - this.closed = closed; - }, - - fit: function(error) { - var points = this.points, - length = points.length, - segments = null; - if (length > 0) { - segments = [new Segment(points[0])]; - if (length > 1) { - this.fitCubic(segments, error, 0, length - 1, - points[1].subtract(points[0]), - points[length - 2].subtract(points[length - 1])); - if (this.closed) { - segments.shift(); - segments.pop(); - } - } - } - return segments; - }, - - fitCubic: function(segments, error, first, last, tan1, tan2) { - var points = this.points; - if (last - first === 1) { - var pt1 = points[first], - pt2 = points[last], - dist = pt1.getDistance(pt2) / 3; - this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)), - pt2.add(tan2.normalize(dist)), pt2]); - return; - } - var uPrime = this.chordLengthParameterize(first, last), - maxError = Math.max(error, error * error), - split, - parametersInOrder = true; - for (var i = 0; i <= 4; i++) { - var curve = this.generateBezier(first, last, uPrime, tan1, tan2); - var max = this.findMaxError(first, last, curve, uPrime); - if (max.error < error && parametersInOrder) { - this.addCurve(segments, curve); - return; - } - split = max.index; - if (max.error >= maxError) - break; - parametersInOrder = this.reparameterize(first, last, uPrime, curve); - maxError = max.error; - } - var tanCenter = points[split - 1].subtract(points[split + 1]); - this.fitCubic(segments, error, first, split, tan1, tanCenter); - this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2); - }, - - addCurve: function(segments, curve) { - var prev = segments[segments.length - 1]; - prev.setHandleOut(curve[1].subtract(curve[0])); - segments.push(new Segment(curve[3], curve[2].subtract(curve[3]))); - }, - - generateBezier: function(first, last, uPrime, tan1, tan2) { - var epsilon = 1e-12, - abs = Math.abs, - points = this.points, - pt1 = points[first], - pt2 = points[last], - C = [[0, 0], [0, 0]], - X = [0, 0]; - - for (var i = 0, l = last - first + 1; i < l; i++) { - var u = uPrime[i], - t = 1 - u, - b = 3 * u * t, - b0 = t * t * t, - b1 = b * t, - b2 = b * u, - b3 = u * u * u, - a1 = tan1.normalize(b1), - a2 = tan2.normalize(b2), - tmp = points[first + i] - .subtract(pt1.multiply(b0 + b1)) - .subtract(pt2.multiply(b2 + b3)); - C[0][0] += a1.dot(a1); - C[0][1] += a1.dot(a2); - C[1][0] = C[0][1]; - C[1][1] += a2.dot(a2); - X[0] += a1.dot(tmp); - X[1] += a2.dot(tmp); - } - - var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1], - alpha1, - alpha2; - if (abs(detC0C1) > epsilon) { - var detC0X = C[0][0] * X[1] - C[1][0] * X[0], - detXC1 = X[0] * C[1][1] - X[1] * C[0][1]; - alpha1 = detXC1 / detC0C1; - alpha2 = detC0X / detC0C1; - } else { - var c0 = C[0][0] + C[0][1], - c1 = C[1][0] + C[1][1]; - alpha1 = alpha2 = abs(c0) > epsilon ? X[0] / c0 - : abs(c1) > epsilon ? X[1] / c1 - : 0; - } - - var segLength = pt2.getDistance(pt1), - eps = epsilon * segLength, - handle1, - handle2; - if (alpha1 < eps || alpha2 < eps) { - alpha1 = alpha2 = segLength / 3; - } else { - var line = pt2.subtract(pt1); - handle1 = tan1.normalize(alpha1); - handle2 = tan2.normalize(alpha2); - if (handle1.dot(line) - handle2.dot(line) > segLength * segLength) { - alpha1 = alpha2 = segLength / 3; - handle1 = handle2 = null; - } - } - - return [pt1, - pt1.add(handle1 || tan1.normalize(alpha1)), - pt2.add(handle2 || tan2.normalize(alpha2)), - pt2]; - }, - - reparameterize: function(first, last, u, curve) { - for (var i = first; i <= last; i++) { - u[i - first] = this.findRoot(curve, this.points[i], u[i - first]); - } - for (var i = 1, l = u.length; i < l; i++) { - if (u[i] <= u[i - 1]) - return false; - } - return true; - }, - - findRoot: function(curve, point, u) { - var curve1 = [], - curve2 = []; - for (var i = 0; i <= 2; i++) { - curve1[i] = curve[i + 1].subtract(curve[i]).multiply(3); - } - for (var i = 0; i <= 1; i++) { - curve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2); - } - var pt = this.evaluate(3, curve, u), - pt1 = this.evaluate(2, curve1, u), - pt2 = this.evaluate(1, curve2, u), - diff = pt.subtract(point), - df = pt1.dot(pt1) + diff.dot(pt2); - return Numerical.isZero(df) ? u : u - diff.dot(pt1) / df; - }, - - evaluate: function(degree, curve, t) { - var tmp = curve.slice(); - for (var i = 1; i <= degree; i++) { - for (var j = 0; j <= degree - i; j++) { - tmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t)); - } - } - return tmp[0]; - }, - - chordLengthParameterize: function(first, last) { - var u = [0]; - for (var i = first + 1; i <= last; i++) { - u[i - first] = u[i - first - 1] - + this.points[i].getDistance(this.points[i - 1]); - } - for (var i = 1, m = last - first; i <= m; i++) { - u[i] /= u[m]; - } - return u; - }, - - findMaxError: function(first, last, curve, u) { - var index = Math.floor((last - first + 1) / 2), - maxDist = 0; - for (var i = first + 1; i < last; i++) { - var P = this.evaluate(3, curve, u[i - first]); - var v = P.subtract(this.points[i]); - var dist = v.x * v.x + v.y * v.y; - if (dist >= maxDist) { - maxDist = dist; - index = i; - } - } - return { - error: maxDist, - index: index - }; - } -}); - -var TextItem = Item.extend({ - _class: 'TextItem', - _applyMatrix: false, - _canApplyMatrix: false, - _serializeFields: { - content: null - }, - _boundsOptions: { stroke: false, handle: false }, - - initialize: function TextItem(arg) { - this._content = ''; - this._lines = []; - var hasProps = arg && Base.isPlainObject(arg) - && arg.x === undefined && arg.y === undefined; - this._initialize(hasProps && arg, !hasProps && Point.read(arguments)); - }, - - _equals: function(item) { - return this._content === item._content; - }, - - copyContent: function(source) { - this.setContent(source._content); - }, - - getContent: function() { - return this._content; - }, - - setContent: function(content) { - this._content = '' + content; - this._lines = this._content.split(/\r\n|\n|\r/mg); - this._changed(521); - }, - - isEmpty: function() { - return !this._content; - }, - - getCharacterStyle: '#getStyle', - setCharacterStyle: '#setStyle', - - getParagraphStyle: '#getStyle', - setParagraphStyle: '#setStyle' -}); - -var PointText = TextItem.extend({ - _class: 'PointText', - - initialize: function PointText() { - TextItem.apply(this, arguments); - }, - - getPoint: function() { - var point = this._matrix.getTranslation(); - return new LinkedPoint(point.x, point.y, this, 'setPoint'); - }, - - setPoint: function() { - var point = Point.read(arguments); - this.translate(point.subtract(this._matrix.getTranslation())); - }, - - _draw: function(ctx, param, viewMatrix) { - if (!this._content) - return; - this._setStyles(ctx, param, viewMatrix); - var lines = this._lines, - style = this._style, - hasFill = style.hasFill(), - hasStroke = style.hasStroke(), - leading = style.getLeading(), - shadowColor = ctx.shadowColor; - ctx.font = style.getFontStyle(); - ctx.textAlign = style.getJustification(); - for (var i = 0, l = lines.length; i < l; i++) { - ctx.shadowColor = shadowColor; - var line = lines[i]; - if (hasFill) { - ctx.fillText(line, 0, 0); - ctx.shadowColor = 'rgba(0,0,0,0)'; - } - if (hasStroke) - ctx.strokeText(line, 0, 0); - ctx.translate(0, leading); - } - }, - - _getBounds: function(matrix, options) { - var style = this._style, - lines = this._lines, - numLines = lines.length, - justification = style.getJustification(), - leading = style.getLeading(), - width = this.getView().getTextWidth(style.getFontStyle(), lines), - x = 0; - if (justification !== 'left') - x -= width / (justification === 'center' ? 2: 1); - var rect = new Rectangle(x, - numLines ? - 0.75 * leading : 0, - width, numLines * leading); - return matrix ? matrix._transformBounds(rect, rect) : rect; - } -}); - -var Color = Base.extend(new function() { - var types = { - gray: ['gray'], - rgb: ['red', 'green', 'blue'], - hsb: ['hue', 'saturation', 'brightness'], - hsl: ['hue', 'saturation', 'lightness'], - gradient: ['gradient', 'origin', 'destination', 'highlight'] - }; - - var componentParsers = {}, - namedColors = { - transparent: [0, 0, 0, 0] - }, - colorCtx; - - function fromCSS(string) { - var match = string.match( - /^#([\da-f]{2})([\da-f]{2})([\da-f]{2})([\da-f]{2})?$/i - ) || string.match( - /^#([\da-f])([\da-f])([\da-f])([\da-f])?$/i - ), - type = 'rgb', - components; - if (match) { - var amount = match[4] ? 4 : 3; - components = new Array(amount); - for (var i = 0; i < amount; i++) { - var value = match[i + 1]; - components[i] = parseInt(value.length == 1 - ? value + value : value, 16) / 255; - } - } else if (match = string.match(/^(rgb|hsl)a?\((.*)\)$/)) { - type = match[1]; - components = match[2].split(/[,\s]+/g); - var isHSL = type === 'hsl'; - for (var i = 0, l = Math.min(components.length, 4); i < l; i++) { - var component = components[i]; - var value = parseFloat(component); - if (isHSL) { - if (i === 0) { - var unit = component.match(/([a-z]*)$/)[1]; - value *= ({ - turn: 360, - rad: 180 / Math.PI, - grad: 0.9 - }[unit] || 1); - } else if (i < 3) { - value /= 100; - } - } else if (i < 3) { - value /= 255; - } - components[i] = value; - } - } else { - var color = namedColors[string]; - if (!color) { - if (window) { - if (!colorCtx) { - colorCtx = CanvasProvider.getContext(1, 1); - colorCtx.globalCompositeOperation = 'copy'; - } - colorCtx.fillStyle = 'rgba(0,0,0,0)'; - colorCtx.fillStyle = string; - colorCtx.fillRect(0, 0, 1, 1); - var data = colorCtx.getImageData(0, 0, 1, 1).data; - color = namedColors[string] = [ - data[0] / 255, - data[1] / 255, - data[2] / 255 - ]; - } else { - color = [0, 0, 0]; - } - } - components = color.slice(); - } - return [type, components]; - } - - var hsbIndices = [ - [0, 3, 1], - [2, 0, 1], - [1, 0, 3], - [1, 2, 0], - [3, 1, 0], - [0, 1, 2] - ]; - - var converters = { - 'rgb-hsb': function(r, g, b) { - var max = Math.max(r, g, b), - min = Math.min(r, g, b), - delta = max - min, - h = delta === 0 ? 0 - : ( max == r ? (g - b) / delta + (g < b ? 6 : 0) - : max == g ? (b - r) / delta + 2 - : (r - g) / delta + 4) * 60; - return [h, max === 0 ? 0 : delta / max, max]; - }, - - 'hsb-rgb': function(h, s, b) { - h = (((h / 60) % 6) + 6) % 6; - var i = Math.floor(h), - f = h - i, - i = hsbIndices[i], - v = [ - b, - b * (1 - s), - b * (1 - s * f), - b * (1 - s * (1 - f)) - ]; - return [v[i[0]], v[i[1]], v[i[2]]]; - }, - - 'rgb-hsl': function(r, g, b) { - var max = Math.max(r, g, b), - min = Math.min(r, g, b), - delta = max - min, - achromatic = delta === 0, - h = achromatic ? 0 - : ( max == r ? (g - b) / delta + (g < b ? 6 : 0) - : max == g ? (b - r) / delta + 2 - : (r - g) / delta + 4) * 60, - l = (max + min) / 2, - s = achromatic ? 0 : l < 0.5 - ? delta / (max + min) - : delta / (2 - max - min); - return [h, s, l]; - }, - - 'hsl-rgb': function(h, s, l) { - h = (((h / 360) % 1) + 1) % 1; - if (s === 0) - return [l, l, l]; - var t3s = [ h + 1 / 3, h, h - 1 / 3 ], - t2 = l < 0.5 ? l * (1 + s) : l + s - l * s, - t1 = 2 * l - t2, - c = []; - for (var i = 0; i < 3; i++) { - var t3 = t3s[i]; - if (t3 < 0) t3 += 1; - if (t3 > 1) t3 -= 1; - c[i] = 6 * t3 < 1 - ? t1 + (t2 - t1) * 6 * t3 - : 2 * t3 < 1 - ? t2 - : 3 * t3 < 2 - ? t1 + (t2 - t1) * ((2 / 3) - t3) * 6 - : t1; - } - return c; - }, - - 'rgb-gray': function(r, g, b) { - return [r * 0.2989 + g * 0.587 + b * 0.114]; - }, - - 'gray-rgb': function(g) { - return [g, g, g]; - }, - - 'gray-hsb': function(g) { - return [0, 0, g]; - }, - - 'gray-hsl': function(g) { - return [0, 0, g]; - }, - - 'gradient-rgb': function() { - return []; - }, - - 'rgb-gradient': function() { - return []; - } - - }; - - return Base.each(types, function(properties, type) { - componentParsers[type] = []; - Base.each(properties, function(name, index) { - var part = Base.capitalize(name), - hasOverlap = /^(hue|saturation)$/.test(name), - parser = componentParsers[type][index] = type === 'gradient' - ? name === 'gradient' - ? function(value) { - var current = this._components[0]; - value = Gradient.read( - Array.isArray(value) - ? value - : arguments, 0, { readNull: true } - ); - if (current !== value) { - if (current) - current._removeOwner(this); - if (value) - value._addOwner(this); - } - return value; - } - : function() { - return Point.read(arguments, 0, { - readNull: name === 'highlight', - clone: true - }); - } - : function(value) { - return value == null || isNaN(value) ? 0 : +value; - }; - this['get' + part] = function() { - return this._type === type - || hasOverlap && /^hs[bl]$/.test(this._type) - ? this._components[index] - : this._convert(type)[index]; - }; - - this['set' + part] = function(value) { - if (this._type !== type - && !(hasOverlap && /^hs[bl]$/.test(this._type))) { - this._components = this._convert(type); - this._properties = types[type]; - this._type = type; - } - this._components[index] = parser.call(this, value); - this._changed(); - }; - }, this); - }, { - _class: 'Color', - _readIndex: true, - - initialize: function Color(arg) { - var args = arguments, - reading = this.__read, - read = 0, - type, - components, - alpha, - values; - if (Array.isArray(arg)) { - args = arg; - arg = args[0]; - } - var argType = arg != null && typeof arg; - if (argType === 'string' && arg in types) { - type = arg; - arg = args[1]; - if (Array.isArray(arg)) { - components = arg; - alpha = args[2]; - } else { - if (reading) - read = 1; - args = Base.slice(args, 1); - argType = typeof arg; - } - } - if (!components) { - values = argType === 'number' - ? args - : argType === 'object' && arg.length != null - ? arg - : null; - if (values) { - if (!type) - type = values.length >= 3 - ? 'rgb' - : 'gray'; - var length = types[type].length; - alpha = values[length]; - if (reading) { - read += values === arguments - ? length + (alpha != null ? 1 : 0) - : 1; - } - if (values.length > length) - values = Base.slice(values, 0, length); - } else if (argType === 'string') { - var converted = fromCSS(arg); - type = converted[0]; - components = converted[1]; - if (components.length === 4) { - alpha = components[3]; - components.length--; - } - } else if (argType === 'object') { - if (arg.constructor === Color) { - type = arg._type; - components = arg._components.slice(); - alpha = arg._alpha; - if (type === 'gradient') { - for (var i = 1, l = components.length; i < l; i++) { - var point = components[i]; - if (point) - components[i] = point.clone(); - } - } - } else if (arg.constructor === Gradient) { - type = 'gradient'; - values = args; - } else { - type = 'hue' in arg - ? 'lightness' in arg - ? 'hsl' - : 'hsb' - : 'gradient' in arg || 'stops' in arg - || 'radial' in arg - ? 'gradient' - : 'gray' in arg - ? 'gray' - : 'rgb'; - var properties = types[type], - parsers = componentParsers[type]; - this._components = components = []; - for (var i = 0, l = properties.length; i < l; i++) { - var value = arg[properties[i]]; - if (value == null && !i && type === 'gradient' - && 'stops' in arg) { - value = { - stops: arg.stops, - radial: arg.radial - }; - } - value = parsers[i].call(this, value); - if (value != null) - components[i] = value; - } - alpha = arg.alpha; - } - } - if (reading && type) - read = 1; - } - this._type = type || 'rgb'; - if (!components) { - this._components = components = []; - var parsers = componentParsers[this._type]; - for (var i = 0, l = parsers.length; i < l; i++) { - var value = parsers[i].call(this, values && values[i]); - if (value != null) - components[i] = value; - } - } - this._components = components; - this._properties = types[this._type]; - this._alpha = alpha; - if (reading) - this.__read = read; - return this; - }, - - set: '#initialize', - - _serialize: function(options, dictionary) { - var components = this.getComponents(); - return Base.serialize( - /^(gray|rgb)$/.test(this._type) - ? components - : [this._type].concat(components), - options, true, dictionary); - }, - - _changed: function() { - this._canvasStyle = null; - if (this._owner) - this._owner._changed(129); - }, - - _convert: function(type) { - var converter; - return this._type === type - ? this._components.slice() - : (converter = converters[this._type + '-' + type]) - ? converter.apply(this, this._components) - : converters['rgb-' + type].apply(this, - converters[this._type + '-rgb'].apply(this, - this._components)); - }, - - convert: function(type) { - return new Color(type, this._convert(type), this._alpha); - }, - - getType: function() { - return this._type; - }, - - setType: function(type) { - this._components = this._convert(type); - this._properties = types[type]; - this._type = type; - }, - - getComponents: function() { - var components = this._components.slice(); - if (this._alpha != null) - components.push(this._alpha); - return components; - }, - - getAlpha: function() { - return this._alpha != null ? this._alpha : 1; - }, - - setAlpha: function(alpha) { - this._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1); - this._changed(); - }, - - hasAlpha: function() { - return this._alpha != null; - }, - - equals: function(color) { - var col = Base.isPlainValue(color, true) - ? Color.read(arguments) - : color; - return col === this || col && this._class === col._class - && this._type === col._type - && this.getAlpha() === col.getAlpha() - && Base.equals(this._components, col._components) - || false; - }, - - toString: function() { - var properties = this._properties, - parts = [], - isGradient = this._type === 'gradient', - f = Formatter.instance; - for (var i = 0, l = properties.length; i < l; i++) { - var value = this._components[i]; - if (value != null) - parts.push(properties[i] + ': ' - + (isGradient ? value : f.number(value))); - } - if (this._alpha != null) - parts.push('alpha: ' + f.number(this._alpha)); - return '{ ' + parts.join(', ') + ' }'; - }, - - toCSS: function(hex) { - var components = this._convert('rgb'), - alpha = hex || this._alpha == null ? 1 : this._alpha; - function convert(val) { - return Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255); - } - components = [ - convert(components[0]), - convert(components[1]), - convert(components[2]) - ]; - if (alpha < 1) - components.push(alpha < 0 ? 0 : alpha); - return hex - ? '#' + ((1 << 24) + (components[0] << 16) - + (components[1] << 8) - + components[2]).toString(16).slice(1) - : (components.length == 4 ? 'rgba(' : 'rgb(') - + components.join(',') + ')'; - }, - - toCanvasStyle: function(ctx, matrix) { - if (this._canvasStyle) - return this._canvasStyle; - if (this._type !== 'gradient') - return this._canvasStyle = this.toCSS(); - var components = this._components, - gradient = components[0], - stops = gradient._stops, - origin = components[1], - destination = components[2], - highlight = components[3], - inverse = matrix && matrix.inverted(), - canvasGradient; - if (inverse) { - origin = inverse._transformPoint(origin); - destination = inverse._transformPoint(destination); - if (highlight) - highlight = inverse._transformPoint(highlight); - } - if (gradient._radial) { - var radius = destination.getDistance(origin); - if (highlight) { - var vector = highlight.subtract(origin); - if (vector.getLength() > radius) - highlight = origin.add(vector.normalize(radius - 0.1)); - } - var start = highlight || origin; - canvasGradient = ctx.createRadialGradient(start.x, start.y, - 0, origin.x, origin.y, radius); - } else { - canvasGradient = ctx.createLinearGradient(origin.x, origin.y, - destination.x, destination.y); - } - for (var i = 0, l = stops.length; i < l; i++) { - var stop = stops[i], - offset = stop._offset; - canvasGradient.addColorStop( - offset == null ? i / (l - 1) : offset, - stop._color.toCanvasStyle()); - } - return this._canvasStyle = canvasGradient; - }, - - transform: function(matrix) { - if (this._type === 'gradient') { - var components = this._components; - for (var i = 1, l = components.length; i < l; i++) { - var point = components[i]; - matrix._transformPoint(point, point, true); - } - this._changed(); - } - }, - - statics: { - _types: types, - - random: function() { - var random = Math.random; - return new Color(random(), random(), random()); - } - } - }); -}, -new function() { - var operators = { - add: function(a, b) { - return a + b; - }, - - subtract: function(a, b) { - return a - b; - }, - - multiply: function(a, b) { - return a * b; - }, - - divide: function(a, b) { - return a / b; - } - }; - - return Base.each(operators, function(operator, name) { - this[name] = function(color) { - color = Color.read(arguments); - var type = this._type, - components1 = this._components, - components2 = color._convert(type); - for (var i = 0, l = components1.length; i < l; i++) - components2[i] = operator(components1[i], components2[i]); - return new Color(type, components2, - this._alpha != null - ? operator(this._alpha, color.getAlpha()) - : null); - }; - }, { - }); -}); - -var Gradient = Base.extend({ - _class: 'Gradient', - - initialize: function Gradient(stops, radial) { - this._id = UID.get(); - if (stops && Base.isPlainObject(stops)) { - this.set(stops); - stops = radial = null; - } - if (this._stops == null) { - this.setStops(stops || ['white', 'black']); - } - if (this._radial == null) { - this.setRadial(typeof radial === 'string' && radial === 'radial' - || radial || false); - } - }, - - _serialize: function(options, dictionary) { - return dictionary.add(this, function() { - return Base.serialize([this._stops, this._radial], - options, true, dictionary); - }); - }, - - _changed: function() { - for (var i = 0, l = this._owners && this._owners.length; i < l; i++) { - this._owners[i]._changed(); - } - }, - - _addOwner: function(color) { - if (!this._owners) - this._owners = []; - this._owners.push(color); - }, - - _removeOwner: function(color) { - var index = this._owners ? this._owners.indexOf(color) : -1; - if (index != -1) { - this._owners.splice(index, 1); - if (!this._owners.length) - this._owners = undefined; - } - }, - - clone: function() { - var stops = []; - for (var i = 0, l = this._stops.length; i < l; i++) { - stops[i] = this._stops[i].clone(); - } - return new Gradient(stops, this._radial); - }, - - getStops: function() { - return this._stops; - }, - - setStops: function(stops) { - if (stops.length < 2) { - throw new Error( - 'Gradient stop list needs to contain at least two stops.'); - } - var _stops = this._stops; - if (_stops) { - for (var i = 0, l = _stops.length; i < l; i++) - _stops[i]._owner = undefined; - } - _stops = this._stops = GradientStop.readList(stops, 0, { clone: true }); - for (var i = 0, l = _stops.length; i < l; i++) - _stops[i]._owner = this; - this._changed(); - }, - - getRadial: function() { - return this._radial; - }, - - setRadial: function(radial) { - this._radial = radial; - this._changed(); - }, - - equals: function(gradient) { - if (gradient === this) - return true; - if (gradient && this._class === gradient._class) { - var stops1 = this._stops, - stops2 = gradient._stops, - length = stops1.length; - if (length === stops2.length) { - for (var i = 0; i < length; i++) { - if (!stops1[i].equals(stops2[i])) - return false; - } - return true; - } - } - return false; - } -}); - -var GradientStop = Base.extend({ - _class: 'GradientStop', - - initialize: function GradientStop(arg0, arg1) { - var color = arg0, - offset = arg1; - if (typeof arg0 === 'object' && arg1 === undefined) { - if (Array.isArray(arg0) && typeof arg0[0] !== 'number') { - color = arg0[0]; - offset = arg0[1]; - } else if ('color' in arg0 || 'offset' in arg0 - || 'rampPoint' in arg0) { - color = arg0.color; - offset = arg0.offset || arg0.rampPoint || 0; - } - } - this.setColor(color); - this.setOffset(offset); - }, - - clone: function() { - return new GradientStop(this._color.clone(), this._offset); - }, - - _serialize: function(options, dictionary) { - var color = this._color, - offset = this._offset; - return Base.serialize(offset == null ? [color] : [color, offset], - options, true, dictionary); - }, - - _changed: function() { - if (this._owner) - this._owner._changed(129); - }, - - getOffset: function() { - return this._offset; - }, - - setOffset: function(offset) { - this._offset = offset; - this._changed(); - }, - - getRampPoint: '#getOffset', - setRampPoint: '#setOffset', - - getColor: function() { - return this._color; - }, - - setColor: function() { - var color = Color.read(arguments, 0, { clone: true }); - if (color) - color._owner = this; - this._color = color; - this._changed(); - }, - - equals: function(stop) { - return stop === this || stop && this._class === stop._class - && this._color.equals(stop._color) - && this._offset == stop._offset - || false; - } -}); - -var Style = Base.extend(new function() { - var itemDefaults = { - fillColor: null, - fillRule: 'nonzero', - strokeColor: null, - strokeWidth: 1, - strokeCap: 'butt', - strokeJoin: 'miter', - strokeScaling: true, - miterLimit: 10, - dashOffset: 0, - dashArray: [], - shadowColor: null, - shadowBlur: 0, - shadowOffset: new Point(), - selectedColor: null - }, - groupDefaults = Base.set({}, itemDefaults, { - fontFamily: 'sans-serif', - fontWeight: 'normal', - fontSize: 12, - leading: null, - justification: 'left' - }), - textDefaults = Base.set({}, groupDefaults, { - fillColor: new Color() - }), - flags = { - strokeWidth: 193, - strokeCap: 193, - strokeJoin: 193, - strokeScaling: 201, - miterLimit: 193, - fontFamily: 9, - fontWeight: 9, - fontSize: 9, - font: 9, - leading: 9, - justification: 9 - }, - item = { - beans: true - }, - fields = { - _class: 'Style', - beans: true, - - initialize: function Style(style, _owner, _project) { - this._values = {}; - this._owner = _owner; - this._project = _owner && _owner._project || _project - || paper.project; - this._defaults = !_owner || _owner instanceof Group ? groupDefaults - : _owner instanceof TextItem ? textDefaults - : itemDefaults; - if (style) - this.set(style); - } - }; - - Base.each(groupDefaults, function(value, key) { - var isColor = /Color$/.test(key), - isPoint = key === 'shadowOffset', - part = Base.capitalize(key), - flag = flags[key], - set = 'set' + part, - get = 'get' + part; - - fields[set] = function(value) { - var owner = this._owner, - children = owner && owner._children; - if (children && children.length > 0 - && !(owner instanceof CompoundPath)) { - for (var i = 0, l = children.length; i < l; i++) - children[i]._style[set](value); - } else if (key in this._defaults) { - var old = this._values[key]; - if (old !== value) { - if (isColor) { - if (old && old._owner !== undefined) { - old._owner = undefined; - old._canvasStyle = null; - } - if (value && value.constructor === Color) { - if (value._owner) - value = value.clone(); - value._owner = owner; - } - } - this._values[key] = value; - if (owner) - owner._changed(flag || 129); - } - } - }; - - fields[get] = function(_dontMerge) { - var owner = this._owner, - children = owner && owner._children, - value; - if (key in this._defaults && (!children || !children.length - || _dontMerge || owner instanceof CompoundPath)) { - var value = this._values[key]; - if (value === undefined) { - value = this._defaults[key]; - if (value && value.clone) - value = value.clone(); - } else { - var ctor = isColor ? Color : isPoint ? Point : null; - if (ctor && !(value && value.constructor === ctor)) { - this._values[key] = value = ctor.read([value], 0, - { readNull: true, clone: true }); - if (value && isColor) - value._owner = owner; - } - } - } else if (children) { - for (var i = 0, l = children.length; i < l; i++) { - var childValue = children[i]._style[get](); - if (!i) { - value = childValue; - } else if (!Base.equals(value, childValue)) { - return undefined; - } - } - } - return value; - }; - - item[get] = function(_dontMerge) { - return this._style[get](_dontMerge); - }; - - item[set] = function(value) { - this._style[set](value); - }; - }); - - Base.each({ - Font: 'FontFamily', - WindingRule: 'FillRule' - }, function(value, key) { - var get = 'get' + key, - set = 'set' + key; - fields[get] = item[get] = '#get' + value; - fields[set] = item[set] = '#set' + value; - }); - - Item.inject(item); - return fields; -}, { - set: function(style) { - var isStyle = style instanceof Style, - values = isStyle ? style._values : style; - if (values) { - for (var key in values) { - if (key in this._defaults) { - var value = values[key]; - this[key] = value && isStyle && value.clone - ? value.clone() : value; - } - } - } - }, - - equals: function(style) { - function compare(style1, style2, secondary) { - var values1 = style1._values, - values2 = style2._values, - defaults2 = style2._defaults; - for (var key in values1) { - var value1 = values1[key], - value2 = values2[key]; - if (!(secondary && key in values2) && !Base.equals(value1, - value2 === undefined ? defaults2[key] : value2)) - return false; - } - return true; - } - - return style === this || style && this._class === style._class - && compare(this, style) - && compare(style, this, true) - || false; - }, - - _dispose: function() { - var color; - color = this.getFillColor(); - if (color) color._canvasStyle = null; - color = this.getStrokeColor(); - if (color) color._canvasStyle = null; - color = this.getShadowColor(); - if (color) color._canvasStyle = null; - }, - - hasFill: function() { - var color = this.getFillColor(); - return !!color && color.alpha > 0; - }, - - hasStroke: function() { - var color = this.getStrokeColor(); - return !!color && color.alpha > 0 && this.getStrokeWidth() > 0; - }, - - hasShadow: function() { - var color = this.getShadowColor(); - return !!color && color.alpha > 0 && (this.getShadowBlur() > 0 - || !this.getShadowOffset().isZero()); - }, - - getView: function() { - return this._project._view; - }, - - getFontStyle: function() { - var fontSize = this.getFontSize(); - return this.getFontWeight() - + ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ') - + this.getFontFamily(); - }, - - getFont: '#getFontFamily', - setFont: '#setFontFamily', - - getLeading: function getLeading() { - var leading = getLeading.base.call(this), - fontSize = this.getFontSize(); - if (/pt|em|%|px/.test(fontSize)) - fontSize = this.getView().getPixelSize(fontSize); - return leading != null ? leading : fontSize * 1.2; - } - -}); - -var DomElement = new function() { - function handlePrefix(el, name, set, value) { - var prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'], - suffix = name[0].toUpperCase() + name.substring(1); - for (var i = 0; i < 6; i++) { - var prefix = prefixes[i], - key = prefix ? prefix + suffix : name; - if (key in el) { - if (set) { - el[key] = value; - } else { - return el[key]; - } - break; - } - } - } - - return { - getStyles: function(el) { - var doc = el && el.nodeType !== 9 ? el.ownerDocument : el, - view = doc && doc.defaultView; - return view && view.getComputedStyle(el, ''); - }, - - getBounds: function(el, viewport) { - var doc = el.ownerDocument, - body = doc.body, - html = doc.documentElement, - rect; - try { - rect = el.getBoundingClientRect(); - } catch (e) { - rect = { left: 0, top: 0, width: 0, height: 0 }; - } - var x = rect.left - (html.clientLeft || body.clientLeft || 0), - y = rect.top - (html.clientTop || body.clientTop || 0); - if (!viewport) { - var view = doc.defaultView; - x += view.pageXOffset || html.scrollLeft || body.scrollLeft; - y += view.pageYOffset || html.scrollTop || body.scrollTop; - } - return new Rectangle(x, y, rect.width, rect.height); - }, - - getViewportBounds: function(el) { - var doc = el.ownerDocument, - view = doc.defaultView, - html = doc.documentElement; - return new Rectangle(0, 0, - view.innerWidth || html.clientWidth, - view.innerHeight || html.clientHeight - ); - }, - - getOffset: function(el, viewport) { - return DomElement.getBounds(el, viewport).getPoint(); - }, - - getSize: function(el) { - return DomElement.getBounds(el, true).getSize(); - }, - - isInvisible: function(el) { - return DomElement.getSize(el).equals(new Size(0, 0)); - }, - - isInView: function(el) { - return !DomElement.isInvisible(el) - && DomElement.getViewportBounds(el).intersects( - DomElement.getBounds(el, true)); - }, - - isInserted: function(el) { - return document.body.contains(el); - }, - - getPrefixed: function(el, name) { - return el && handlePrefix(el, name); - }, - - setPrefixed: function(el, name, value) { - if (typeof name === 'object') { - for (var key in name) - handlePrefix(el, key, true, name[key]); - } else { - handlePrefix(el, name, true, value); - } - } - }; -}; - -var DomEvent = { - add: function(el, events) { - if (el) { - for (var type in events) { - var func = events[type], - parts = type.split(/[\s,]+/g); - for (var i = 0, l = parts.length; i < l; i++) { - var name = parts[i]; - var options = ( - el === document - && (name === 'touchstart' || name === 'touchmove') - ) ? { passive: false } : false; - el.addEventListener(name, func, options); - } - } - } - }, - - remove: function(el, events) { - if (el) { - for (var type in events) { - var func = events[type], - parts = type.split(/[\s,]+/g); - for (var i = 0, l = parts.length; i < l; i++) - el.removeEventListener(parts[i], func, false); - } - } - }, - - getPoint: function(event) { - var pos = event.targetTouches - ? event.targetTouches.length - ? event.targetTouches[0] - : event.changedTouches[0] - : event; - return new Point( - pos.pageX || pos.clientX + document.documentElement.scrollLeft, - pos.pageY || pos.clientY + document.documentElement.scrollTop - ); - }, - - getTarget: function(event) { - return event.target || event.srcElement; - }, - - getRelatedTarget: function(event) { - return event.relatedTarget || event.toElement; - }, - - getOffset: function(event, target) { - return DomEvent.getPoint(event).subtract(DomElement.getOffset( - target || DomEvent.getTarget(event))); - } -}; - -DomEvent.requestAnimationFrame = new function() { - var nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'), - requested = false, - callbacks = [], - timer; - - function handleCallbacks() { - var functions = callbacks; - callbacks = []; - for (var i = 0, l = functions.length; i < l; i++) - functions[i](); - requested = nativeRequest && callbacks.length; - if (requested) - nativeRequest(handleCallbacks); - } - - return function(callback) { - callbacks.push(callback); - if (nativeRequest) { - if (!requested) { - nativeRequest(handleCallbacks); - requested = true; - } - } else if (!timer) { - timer = setInterval(handleCallbacks, 1000 / 60); - } - }; -}; - -var View = Base.extend(Emitter, { - _class: 'View', - - initialize: function View(project, element) { - - function getSize(name) { - return element[name] || parseInt(element.getAttribute(name), 10); - } - - function getCanvasSize() { - var size = DomElement.getSize(element); - return size.isNaN() || size.isZero() - ? new Size(getSize('width'), getSize('height')) - : size; - } - - var size; - if (window && element) { - this._id = element.getAttribute('id'); - if (this._id == null) - element.setAttribute('id', this._id = 'view-' + View._id++); - DomEvent.add(element, this._viewEvents); - var none = 'none'; - DomElement.setPrefixed(element.style, { - userDrag: none, - userSelect: none, - touchCallout: none, - contentZooming: none, - tapHighlightColor: 'rgba(0,0,0,0)' - }); - - if (PaperScope.hasAttribute(element, 'resize')) { - var that = this; - DomEvent.add(window, this._windowEvents = { - resize: function() { - that.setViewSize(getCanvasSize()); - } - }); - } - - size = getCanvasSize(); - - if (PaperScope.hasAttribute(element, 'stats') - && typeof Stats !== 'undefined') { - this._stats = new Stats(); - var stats = this._stats.domElement, - style = stats.style, - offset = DomElement.getOffset(element); - style.position = 'absolute'; - style.left = offset.x + 'px'; - style.top = offset.y + 'px'; - document.body.appendChild(stats); - } - } else { - size = new Size(element); - element = null; - } - this._project = project; - this._scope = project._scope; - this._element = element; - if (!this._pixelRatio) - this._pixelRatio = window && window.devicePixelRatio || 1; - this._setElementSize(size.width, size.height); - this._viewSize = size; - View._views.push(this); - View._viewsById[this._id] = this; - (this._matrix = new Matrix())._owner = this; - if (!View._focused) - View._focused = this; - this._frameItems = {}; - this._frameItemCount = 0; - this._itemEvents = { native: {}, virtual: {} }; - this._autoUpdate = !paper.agent.node; - this._needsUpdate = false; - }, - - remove: function() { - if (!this._project) - return false; - if (View._focused === this) - View._focused = null; - View._views.splice(View._views.indexOf(this), 1); - delete View._viewsById[this._id]; - var project = this._project; - if (project._view === this) - project._view = null; - DomEvent.remove(this._element, this._viewEvents); - DomEvent.remove(window, this._windowEvents); - this._element = this._project = null; - this.off('frame'); - this._animate = false; - this._frameItems = {}; - return true; - }, - - _events: Base.each( - Item._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']), - function(name) { - this[name] = {}; - }, { - onFrame: { - install: function() { - this.play(); - }, - - uninstall: function() { - this.pause(); - } - } - } - ), - - _animate: false, - _time: 0, - _count: 0, - - getAutoUpdate: function() { - return this._autoUpdate; - }, - - setAutoUpdate: function(autoUpdate) { - this._autoUpdate = autoUpdate; - if (autoUpdate) - this.requestUpdate(); - }, - - update: function() { - }, - - draw: function() { - this.update(); - }, - - requestUpdate: function() { - if (!this._requested) { - var that = this; - DomEvent.requestAnimationFrame(function() { - that._requested = false; - if (that._animate) { - that.requestUpdate(); - var element = that._element; - if ((!DomElement.getPrefixed(document, 'hidden') - || PaperScope.getAttribute(element, 'keepalive') - === 'true') && DomElement.isInView(element)) { - that._handleFrame(); - } - } - if (that._autoUpdate) - that.update(); - }); - this._requested = true; - } - }, - - play: function() { - this._animate = true; - this.requestUpdate(); - }, - - pause: function() { - this._animate = false; - }, - - _handleFrame: function() { - paper = this._scope; - var now = Date.now() / 1000, - delta = this._last ? now - this._last : 0; - this._last = now; - this.emit('frame', new Base({ - delta: delta, - time: this._time += delta, - count: this._count++ - })); - if (this._stats) - this._stats.update(); - }, - - _animateItem: function(item, animate) { - var items = this._frameItems; - if (animate) { - items[item._id] = { - item: item, - time: 0, - count: 0 - }; - if (++this._frameItemCount === 1) - this.on('frame', this._handleFrameItems); - } else { - delete items[item._id]; - if (--this._frameItemCount === 0) { - this.off('frame', this._handleFrameItems); - } - } - }, - - _handleFrameItems: function(event) { - for (var i in this._frameItems) { - var entry = this._frameItems[i]; - entry.item.emit('frame', new Base(event, { - time: entry.time += event.delta, - count: entry.count++ - })); - } - }, - - _changed: function() { - this._project._changed(4097); - this._bounds = this._decomposed = undefined; - }, - - getElement: function() { - return this._element; - }, - - getPixelRatio: function() { - return this._pixelRatio; - }, - - getResolution: function() { - return this._pixelRatio * 72; - }, - - getViewSize: function() { - var size = this._viewSize; - return new LinkedSize(size.width, size.height, this, 'setViewSize'); - }, - - setViewSize: function() { - var size = Size.read(arguments), - delta = size.subtract(this._viewSize); - if (delta.isZero()) - return; - this._setElementSize(size.width, size.height); - this._viewSize.set(size); - this._changed(); - this.emit('resize', { size: size, delta: delta }); - if (this._autoUpdate) { - this.update(); - } - }, - - _setElementSize: function(width, height) { - var element = this._element; - if (element) { - if (element.width !== width) - element.width = width; - if (element.height !== height) - element.height = height; - } - }, - - getBounds: function() { - if (!this._bounds) - this._bounds = this._matrix.inverted()._transformBounds( - new Rectangle(new Point(), this._viewSize)); - return this._bounds; - }, - - getSize: function() { - return this.getBounds().getSize(); - }, - - isVisible: function() { - return DomElement.isInView(this._element); - }, - - isInserted: function() { - return DomElement.isInserted(this._element); - }, - - getPixelSize: function(size) { - var element = this._element, - pixels; - if (element) { - var parent = element.parentNode, - temp = document.createElement('div'); - temp.style.fontSize = size; - parent.appendChild(temp); - pixels = parseFloat(DomElement.getStyles(temp).fontSize); - parent.removeChild(temp); - } else { - pixels = parseFloat(pixels); - } - return pixels; - }, - - getTextWidth: function(font, lines) { - return 0; - } -}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) { - var rotate = key === 'rotate'; - this[key] = function() { - var value = (rotate ? Base : Point).read(arguments), - center = Point.read(arguments, 0, { readNull: true }); - return this.transform(new Matrix()[key](value, - center || this.getCenter(true))); - }; -}, { - _decompose: function() { - return this._decomposed || (this._decomposed = this._matrix.decompose()); - }, - - translate: function() { - var mx = new Matrix(); - return this.transform(mx.translate.apply(mx, arguments)); - }, - - getCenter: function() { - return this.getBounds().getCenter(); - }, - - setCenter: function() { - var center = Point.read(arguments); - this.translate(this.getCenter().subtract(center)); - }, - - getZoom: function() { - var decomposed = this._decompose(), - scaling = decomposed && decomposed.scaling; - return scaling ? (scaling.x + scaling.y) / 2 : 0; - }, - - setZoom: function(zoom) { - this.transform(new Matrix().scale(zoom / this.getZoom(), - this.getCenter())); - }, - - getRotation: function() { - var decomposed = this._decompose(); - return decomposed && decomposed.rotation; - }, - - setRotation: function(rotation) { - var current = this.getRotation(); - if (current != null && rotation != null) { - this.rotate(rotation - current); - } - }, - - getScaling: function() { - var decomposed = this._decompose(), - scaling = decomposed && decomposed.scaling; - return scaling - ? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling') - : undefined; - }, - - setScaling: function() { - var current = this.getScaling(), - scaling = Point.read(arguments, 0, { clone: true, readNull: true }); - if (current && scaling) { - this.scale(scaling.x / current.x, scaling.y / current.y); - } - }, - - getMatrix: function() { - return this._matrix; - }, - - setMatrix: function() { - var matrix = this._matrix; - matrix.initialize.apply(matrix, arguments); - }, - - transform: function(matrix) { - this._matrix.append(matrix); - }, - - scrollBy: function() { - this.translate(Point.read(arguments).negate()); - } -}), { - - projectToView: function() { - return this._matrix._transformPoint(Point.read(arguments)); - }, - - viewToProject: function() { - return this._matrix._inverseTransform(Point.read(arguments)); - }, - - getEventPoint: function(event) { - return this.viewToProject(DomEvent.getOffset(event, this._element)); - }, - -}, { - statics: { - _views: [], - _viewsById: {}, - _id: 0, - - create: function(project, element) { - if (document && typeof element === 'string') - element = document.getElementById(element); - var ctor = window ? CanvasView : View; - return new ctor(project, element); - } - } -}, -new function() { - if (!window) - return; - var prevFocus, - tempFocus, - dragging = false, - mouseDown = false; - - function getView(event) { - var target = DomEvent.getTarget(event); - return target.getAttribute && View._viewsById[ - target.getAttribute('id')]; - } - - function updateFocus() { - var view = View._focused; - if (!view || !view.isVisible()) { - for (var i = 0, l = View._views.length; i < l; i++) { - if ((view = View._views[i]).isVisible()) { - View._focused = tempFocus = view; - break; - } - } - } - } - - function handleMouseMove(view, event, point) { - view._handleMouseEvent('mousemove', event, point); - } - - var navigator = window.navigator, - mousedown, mousemove, mouseup; - if (navigator.pointerEnabled || navigator.msPointerEnabled) { - mousedown = 'pointerdown MSPointerDown'; - mousemove = 'pointermove MSPointerMove'; - mouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel'; - } else { - mousedown = 'touchstart'; - mousemove = 'touchmove'; - mouseup = 'touchend touchcancel'; - if (!('ontouchstart' in window && navigator.userAgent.match( - /mobile|tablet|ip(ad|hone|od)|android|silk/i))) { - mousedown += ' mousedown'; - mousemove += ' mousemove'; - mouseup += ' mouseup'; - } - } - - var viewEvents = {}, - docEvents = { - mouseout: function(event) { - var view = View._focused, - target = DomEvent.getRelatedTarget(event); - if (view && (!target || target.nodeName === 'HTML')) { - var offset = DomEvent.getOffset(event, view._element), - x = offset.x, - abs = Math.abs, - ax = abs(x), - max = 1 << 25, - diff = ax - max; - offset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x; - handleMouseMove(view, event, view.viewToProject(offset)); - } - }, - - scroll: updateFocus - }; - - viewEvents[mousedown] = function(event) { - var view = View._focused = getView(event); - if (!dragging) { - dragging = true; - view._handleMouseEvent('mousedown', event); - } - }; - - docEvents[mousemove] = function(event) { - var view = View._focused; - if (!mouseDown) { - var target = getView(event); - if (target) { - if (view !== target) { - if (view) - handleMouseMove(view, event); - if (!prevFocus) - prevFocus = view; - view = View._focused = tempFocus = target; - } - } else if (tempFocus && tempFocus === view) { - if (prevFocus && !prevFocus.isInserted()) - prevFocus = null; - view = View._focused = prevFocus; - prevFocus = null; - updateFocus(); - } - } - if (view) - handleMouseMove(view, event); - }; - - docEvents[mousedown] = function() { - mouseDown = true; - }; - - docEvents[mouseup] = function(event) { - var view = View._focused; - if (view && dragging) - view._handleMouseEvent('mouseup', event); - mouseDown = dragging = false; - }; - - DomEvent.add(document, docEvents); - - DomEvent.add(window, { - load: updateFocus - }); - - var called = false, - prevented = false, - fallbacks = { - doubleclick: 'click', - mousedrag: 'mousemove' - }, - wasInView = false, - overView, - downPoint, - lastPoint, - downItem, - overItem, - dragItem, - clickItem, - clickTime, - dblClick; - - function emitMouseEvent(obj, target, type, event, point, prevPoint, - stopItem) { - var stopped = false, - mouseEvent; - - function emit(obj, type) { - if (obj.responds(type)) { - if (!mouseEvent) { - mouseEvent = new MouseEvent(type, event, point, - target || obj, - prevPoint ? point.subtract(prevPoint) : null); - } - if (obj.emit(type, mouseEvent)) { - called = true; - if (mouseEvent.prevented) - prevented = true; - if (mouseEvent.stopped) - return stopped = true; - } - } else { - var fallback = fallbacks[type]; - if (fallback) - return emit(obj, fallback); - } - } - - while (obj && obj !== stopItem) { - if (emit(obj, type)) - break; - obj = obj._parent; - } - return stopped; - } - - function emitMouseEvents(view, hitItem, type, event, point, prevPoint) { - view._project.removeOn(type); - prevented = called = false; - return (dragItem && emitMouseEvent(dragItem, null, type, event, - point, prevPoint) - || hitItem && hitItem !== dragItem - && !hitItem.isDescendant(dragItem) - && emitMouseEvent(hitItem, null, type, event, point, prevPoint, - dragItem) - || emitMouseEvent(view, dragItem || hitItem || view, type, event, - point, prevPoint)); - } - - var itemEventsMap = { - mousedown: { - mousedown: 1, - mousedrag: 1, - click: 1, - doubleclick: 1 - }, - mouseup: { - mouseup: 1, - mousedrag: 1, - click: 1, - doubleclick: 1 - }, - mousemove: { - mousedrag: 1, - mousemove: 1, - mouseenter: 1, - mouseleave: 1 - } - }; - - return { - _viewEvents: viewEvents, - - _handleMouseEvent: function(type, event, point) { - var itemEvents = this._itemEvents, - hitItems = itemEvents.native[type], - nativeMove = type === 'mousemove', - tool = this._scope.tool, - view = this; - - function responds(type) { - return itemEvents.virtual[type] || view.responds(type) - || tool && tool.responds(type); - } - - if (nativeMove && dragging && responds('mousedrag')) - type = 'mousedrag'; - if (!point) - point = this.getEventPoint(event); - - var inView = this.getBounds().contains(point), - hit = hitItems && inView && view._project.hitTest(point, { - tolerance: 0, - fill: true, - stroke: true - }), - hitItem = hit && hit.item || null, - handle = false, - mouse = {}; - mouse[type.substr(5)] = true; - - if (hitItems && hitItem !== overItem) { - if (overItem) { - emitMouseEvent(overItem, null, 'mouseleave', event, point); - } - if (hitItem) { - emitMouseEvent(hitItem, null, 'mouseenter', event, point); - } - overItem = hitItem; - } - if (wasInView ^ inView) { - emitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave', - event, point); - overView = inView ? this : null; - handle = true; - } - if ((inView || mouse.drag) && !point.equals(lastPoint)) { - emitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove', - event, point, lastPoint); - handle = true; - } - wasInView = inView; - if (mouse.down && inView || mouse.up && downPoint) { - emitMouseEvents(this, hitItem, type, event, point, downPoint); - if (mouse.down) { - dblClick = hitItem === clickItem - && (Date.now() - clickTime < 300); - downItem = clickItem = hitItem; - if (!prevented && hitItem) { - var item = hitItem; - while (item && !item.responds('mousedrag')) - item = item._parent; - if (item) - dragItem = hitItem; - } - downPoint = point; - } else if (mouse.up) { - if (!prevented && hitItem === downItem) { - clickTime = Date.now(); - emitMouseEvents(this, hitItem, dblClick ? 'doubleclick' - : 'click', event, point, downPoint); - dblClick = false; - } - downItem = dragItem = null; - } - wasInView = false; - handle = true; - } - lastPoint = point; - if (handle && tool) { - called = tool._handleMouseEvent(type, event, point, mouse) - || called; - } - - if ( - event.cancelable !== false - && (called && !mouse.move || mouse.down && responds('mouseup')) - ) { - event.preventDefault(); - } - }, - - _handleKeyEvent: function(type, event, key, character) { - var scope = this._scope, - tool = scope.tool, - keyEvent; - - function emit(obj) { - if (obj.responds(type)) { - paper = scope; - obj.emit(type, keyEvent = keyEvent - || new KeyEvent(type, event, key, character)); - } - } - - if (this.isVisible()) { - emit(this); - if (tool && tool.responds(type)) - emit(tool); - } - }, - - _countItemEvent: function(type, sign) { - var itemEvents = this._itemEvents, - native = itemEvents.native, - virtual = itemEvents.virtual; - for (var key in itemEventsMap) { - native[key] = (native[key] || 0) - + (itemEventsMap[key][type] || 0) * sign; - } - virtual[type] = (virtual[type] || 0) + sign; - }, - - statics: { - updateFocus: updateFocus, - - _resetState: function() { - dragging = mouseDown = called = wasInView = false; - prevFocus = tempFocus = overView = downPoint = lastPoint = - downItem = overItem = dragItem = clickItem = clickTime = - dblClick = null; - } - } - }; -}); - -var CanvasView = View.extend({ - _class: 'CanvasView', - - initialize: function CanvasView(project, canvas) { - if (!(canvas instanceof window.HTMLCanvasElement)) { - var size = Size.read(arguments, 1); - if (size.isZero()) - throw new Error( - 'Cannot create CanvasView with the provided argument: ' - + Base.slice(arguments, 1)); - canvas = CanvasProvider.getCanvas(size); - } - var ctx = this._context = canvas.getContext('2d'); - ctx.save(); - this._pixelRatio = 1; - if (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) { - var deviceRatio = window.devicePixelRatio || 1, - backingStoreRatio = DomElement.getPrefixed(ctx, - 'backingStorePixelRatio') || 1; - this._pixelRatio = deviceRatio / backingStoreRatio; - } - View.call(this, project, canvas); - this._needsUpdate = true; - }, - - remove: function remove() { - this._context.restore(); - return remove.base.call(this); - }, - - _setElementSize: function _setElementSize(width, height) { - var pixelRatio = this._pixelRatio; - _setElementSize.base.call(this, width * pixelRatio, height * pixelRatio); - if (pixelRatio !== 1) { - var element = this._element, - ctx = this._context; - if (!PaperScope.hasAttribute(element, 'resize')) { - var style = element.style; - style.width = width + 'px'; - style.height = height + 'px'; - } - ctx.restore(); - ctx.save(); - ctx.scale(pixelRatio, pixelRatio); - } - }, - - getPixelSize: function getPixelSize(size) { - var agent = paper.agent, - pixels; - if (agent && agent.firefox) { - pixels = getPixelSize.base.call(this, size); - } else { - var ctx = this._context, - prevFont = ctx.font; - ctx.font = size + ' serif'; - pixels = parseFloat(ctx.font); - ctx.font = prevFont; - } - return pixels; - }, - - getTextWidth: function(font, lines) { - var ctx = this._context, - prevFont = ctx.font, - width = 0; - ctx.font = font; - for (var i = 0, l = lines.length; i < l; i++) - width = Math.max(width, ctx.measureText(lines[i]).width); - ctx.font = prevFont; - return width; - }, - - update: function() { - if (!this._needsUpdate) - return false; - var project = this._project, - ctx = this._context, - size = this._viewSize; - ctx.clearRect(0, 0, size.width + 1, size.height + 1); - if (project) - project.draw(ctx, this._matrix, this._pixelRatio); - this._needsUpdate = false; - return true; - } -}); - -var Event = Base.extend({ - _class: 'Event', - - initialize: function Event(event) { - this.event = event; - this.type = event && event.type; - }, - - prevented: false, - stopped: false, - - preventDefault: function() { - this.prevented = true; - this.event.preventDefault(); - }, - - stopPropagation: function() { - this.stopped = true; - this.event.stopPropagation(); - }, - - stop: function() { - this.stopPropagation(); - this.preventDefault(); - }, - - getTimeStamp: function() { - return this.event.timeStamp; - }, - - getModifiers: function() { - return Key.modifiers; - } -}); - -var KeyEvent = Event.extend({ - _class: 'KeyEvent', - - initialize: function KeyEvent(type, event, key, character) { - this.type = type; - this.event = event; - this.key = key; - this.character = character; - }, - - toString: function() { - return "{ type: '" + this.type - + "', key: '" + this.key - + "', character: '" + this.character - + "', modifiers: " + this.getModifiers() - + " }"; - } -}); - -var Key = new function() { - var keyLookup = { - '\t': 'tab', - ' ': 'space', - '\b': 'backspace', - '\x7f': 'delete', - 'Spacebar': 'space', - 'Del': 'delete', - 'Win': 'meta', - 'Esc': 'escape' - }, - - charLookup = { - 'tab': '\t', - 'space': ' ', - 'enter': '\r' - }, - - keyMap = {}, - charMap = {}, - metaFixMap, - downKey, - - modifiers = new Base({ - shift: false, - control: false, - alt: false, - meta: false, - capsLock: false, - space: false - }).inject({ - option: { - get: function() { - return this.alt; - } - }, - - command: { - get: function() { - var agent = paper && paper.agent; - return agent && agent.mac ? this.meta : this.control; - } - } - }); - - function getKey(event) { - var key = event.key || event.keyIdentifier; - key = /^U\+/.test(key) - ? String.fromCharCode(parseInt(key.substr(2), 16)) - : /^Arrow[A-Z]/.test(key) ? key.substr(5) - : key === 'Unidentified' || key === undefined - ? String.fromCharCode(event.keyCode) - : key; - return keyLookup[key] || - (key.length > 1 ? Base.hyphenate(key) : key.toLowerCase()); - } - - function handleKey(down, key, character, event) { - var type = down ? 'keydown' : 'keyup', - view = View._focused, - name; - keyMap[key] = down; - if (down) { - charMap[key] = character; - } else { - delete charMap[key]; - } - if (key.length > 1 && (name = Base.camelize(key)) in modifiers) { - modifiers[name] = down; - var agent = paper && paper.agent; - if (name === 'meta' && agent && agent.mac) { - if (down) { - metaFixMap = {}; - } else { - for (var k in metaFixMap) { - if (k in charMap) - handleKey(false, k, metaFixMap[k], event); - } - metaFixMap = null; - } - } - } else if (down && metaFixMap) { - metaFixMap[key] = character; - } - if (view) { - view._handleKeyEvent(down ? 'keydown' : 'keyup', event, key, - character); - } - } - - DomEvent.add(document, { - keydown: function(event) { - var key = getKey(event), - agent = paper && paper.agent; - if (key.length > 1 || agent && (agent.chrome && (event.altKey - || agent.mac && event.metaKey - || !agent.mac && event.ctrlKey))) { - handleKey(true, key, - charLookup[key] || (key.length > 1 ? '' : key), event); - } else { - downKey = key; - } - }, - - keypress: function(event) { - if (downKey) { - var key = getKey(event), - code = event.charCode, - character = code >= 32 ? String.fromCharCode(code) - : key.length > 1 ? '' : key; - if (key !== downKey) { - key = character.toLowerCase(); - } - handleKey(true, key, character, event); - downKey = null; - } - }, - - keyup: function(event) { - var key = getKey(event); - if (key in charMap) - handleKey(false, key, charMap[key], event); - } - }); - - DomEvent.add(window, { - blur: function(event) { - for (var key in charMap) - handleKey(false, key, charMap[key], event); - } - }); - - return { - modifiers: modifiers, - - isDown: function(key) { - return !!keyMap[key]; - } - }; -}; - -var MouseEvent = Event.extend({ - _class: 'MouseEvent', - - initialize: function MouseEvent(type, event, point, target, delta) { - this.type = type; - this.event = event; - this.point = point; - this.target = target; - this.delta = delta; - }, - - toString: function() { - return "{ type: '" + this.type - + "', point: " + this.point - + ', target: ' + this.target - + (this.delta ? ', delta: ' + this.delta : '') - + ', modifiers: ' + this.getModifiers() - + ' }'; - } -}); - -var ToolEvent = Event.extend({ - _class: 'ToolEvent', - _item: null, - - initialize: function ToolEvent(tool, type, event) { - this.tool = tool; - this.type = type; - this.event = event; - }, - - _choosePoint: function(point, toolPoint) { - return point ? point : toolPoint ? toolPoint.clone() : null; - }, - - getPoint: function() { - return this._choosePoint(this._point, this.tool._point); - }, - - setPoint: function(point) { - this._point = point; - }, - - getLastPoint: function() { - return this._choosePoint(this._lastPoint, this.tool._lastPoint); - }, - - setLastPoint: function(lastPoint) { - this._lastPoint = lastPoint; - }, - - getDownPoint: function() { - return this._choosePoint(this._downPoint, this.tool._downPoint); - }, - - setDownPoint: function(downPoint) { - this._downPoint = downPoint; - }, - - getMiddlePoint: function() { - if (!this._middlePoint && this.tool._lastPoint) { - return this.tool._point.add(this.tool._lastPoint).divide(2); - } - return this._middlePoint; - }, - - setMiddlePoint: function(middlePoint) { - this._middlePoint = middlePoint; - }, - - getDelta: function() { - return !this._delta && this.tool._lastPoint - ? this.tool._point.subtract(this.tool._lastPoint) - : this._delta; - }, - - setDelta: function(delta) { - this._delta = delta; - }, - - getCount: function() { - return this.tool[/^mouse(down|up)$/.test(this.type) - ? '_downCount' : '_moveCount']; - }, - - setCount: function(count) { - this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count'] - = count; - }, - - getItem: function() { - if (!this._item) { - var result = this.tool._scope.project.hitTest(this.getPoint()); - if (result) { - var item = result.item, - parent = item._parent; - while (/^(Group|CompoundPath)$/.test(parent._class)) { - item = parent; - parent = parent._parent; - } - this._item = item; - } - } - return this._item; - }, - - setItem: function(item) { - this._item = item; - }, - - toString: function() { - return '{ type: ' + this.type - + ', point: ' + this.getPoint() - + ', count: ' + this.getCount() - + ', modifiers: ' + this.getModifiers() - + ' }'; - } -}); - -var Tool = PaperScopeItem.extend({ - _class: 'Tool', - _list: 'tools', - _reference: 'tool', - _events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove', - 'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown', - 'onKeyUp'], - - initialize: function Tool(props) { - PaperScopeItem.call(this); - this._moveCount = -1; - this._downCount = -1; - this.set(props); - }, - - getMinDistance: function() { - return this._minDistance; - }, - - setMinDistance: function(minDistance) { - this._minDistance = minDistance; - if (minDistance != null && this._maxDistance != null - && minDistance > this._maxDistance) { - this._maxDistance = minDistance; - } - }, - - getMaxDistance: function() { - return this._maxDistance; - }, - - setMaxDistance: function(maxDistance) { - this._maxDistance = maxDistance; - if (this._minDistance != null && maxDistance != null - && maxDistance < this._minDistance) { - this._minDistance = maxDistance; - } - }, - - getFixedDistance: function() { - return this._minDistance == this._maxDistance - ? this._minDistance : null; - }, - - setFixedDistance: function(distance) { - this._minDistance = this._maxDistance = distance; - }, - - _handleMouseEvent: function(type, event, point, mouse) { - paper = this._scope; - if (mouse.drag && !this.responds(type)) - type = 'mousemove'; - var move = mouse.move || mouse.drag, - responds = this.responds(type), - minDistance = this.minDistance, - maxDistance = this.maxDistance, - called = false, - tool = this; - function update(minDistance, maxDistance) { - var pt = point, - toolPoint = move ? tool._point : (tool._downPoint || pt); - if (move) { - if (tool._moveCount >= 0 && pt.equals(toolPoint)) { - return false; - } - if (toolPoint && (minDistance != null || maxDistance != null)) { - var vector = pt.subtract(toolPoint), - distance = vector.getLength(); - if (distance < (minDistance || 0)) - return false; - if (maxDistance) { - pt = toolPoint.add(vector.normalize( - Math.min(distance, maxDistance))); - } - } - tool._moveCount++; - } - tool._point = pt; - tool._lastPoint = toolPoint || pt; - if (mouse.down) { - tool._moveCount = -1; - tool._downPoint = pt; - tool._downCount++; - } - return true; - } - - function emit() { - if (responds) { - called = tool.emit(type, new ToolEvent(tool, type, event)) - || called; - } - } - - if (mouse.down) { - update(); - emit(); - } else if (mouse.up) { - update(null, maxDistance); - emit(); - } else if (responds) { - while (update(minDistance, maxDistance)) - emit(); - } - return called; - } - -}); - -var Http = { - request: function(options) { - var xhr = new self.XMLHttpRequest(); - xhr.open((options.method || 'get').toUpperCase(), options.url, - Base.pick(options.async, true)); - if (options.mimeType) - xhr.overrideMimeType(options.mimeType); - xhr.onload = function() { - var status = xhr.status; - if (status === 0 || status === 200) { - if (options.onLoad) { - options.onLoad.call(xhr, xhr.responseText); - } - } else { - xhr.onerror(); - } - }; - xhr.onerror = function() { - var status = xhr.status, - message = 'Could not load "' + options.url + '" (Status: ' - + status + ')'; - if (options.onError) { - options.onError(message, status); - } else { - throw new Error(message); - } - }; - return xhr.send(null); - } -}; - -var CanvasProvider = { - canvases: [], - - getCanvas: function(width, height) { - if (!window) - return null; - var canvas, - clear = true; - if (typeof width === 'object') { - height = width.height; - width = width.width; - } - if (this.canvases.length) { - canvas = this.canvases.pop(); - } else { - canvas = document.createElement('canvas'); - clear = false; - } - var ctx = canvas.getContext('2d'); - if (!ctx) { - throw new Error('Canvas ' + canvas + - ' is unable to provide a 2D context.'); - } - if (canvas.width === width && canvas.height === height) { - if (clear) - ctx.clearRect(0, 0, width + 1, height + 1); - } else { - canvas.width = width; - canvas.height = height; - } - ctx.save(); - return canvas; - }, - - getContext: function(width, height) { - var canvas = this.getCanvas(width, height); - return canvas ? canvas.getContext('2d') : null; - }, - - release: function(obj) { - var canvas = obj && obj.canvas ? obj.canvas : obj; - if (canvas && canvas.getContext) { - canvas.getContext('2d').restore(); - this.canvases.push(canvas); - } - } -}; - -var BlendMode = new function() { - var min = Math.min, - max = Math.max, - abs = Math.abs, - sr, sg, sb, sa, - br, bg, bb, ba, - dr, dg, db; - - function getLum(r, g, b) { - return 0.2989 * r + 0.587 * g + 0.114 * b; - } - - function setLum(r, g, b, l) { - var d = l - getLum(r, g, b); - dr = r + d; - dg = g + d; - db = b + d; - var l = getLum(dr, dg, db), - mn = min(dr, dg, db), - mx = max(dr, dg, db); - if (mn < 0) { - var lmn = l - mn; - dr = l + (dr - l) * l / lmn; - dg = l + (dg - l) * l / lmn; - db = l + (db - l) * l / lmn; - } - if (mx > 255) { - var ln = 255 - l, - mxl = mx - l; - dr = l + (dr - l) * ln / mxl; - dg = l + (dg - l) * ln / mxl; - db = l + (db - l) * ln / mxl; - } - } - - function getSat(r, g, b) { - return max(r, g, b) - min(r, g, b); - } - - function setSat(r, g, b, s) { - var col = [r, g, b], - mx = max(r, g, b), - mn = min(r, g, b), - md; - mn = mn === r ? 0 : mn === g ? 1 : 2; - mx = mx === r ? 0 : mx === g ? 1 : 2; - md = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0; - if (col[mx] > col[mn]) { - col[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]); - col[mx] = s; - } else { - col[md] = col[mx] = 0; - } - col[mn] = 0; - dr = col[0]; - dg = col[1]; - db = col[2]; - } - - var modes = { - multiply: function() { - dr = br * sr / 255; - dg = bg * sg / 255; - db = bb * sb / 255; - }, - - screen: function() { - dr = br + sr - (br * sr / 255); - dg = bg + sg - (bg * sg / 255); - db = bb + sb - (bb * sb / 255); - }, - - overlay: function() { - dr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255; - dg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255; - db = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255; - }, - - 'soft-light': function() { - var t = sr * br / 255; - dr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255; - t = sg * bg / 255; - dg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255; - t = sb * bb / 255; - db = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255; - }, - - 'hard-light': function() { - dr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255; - dg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255; - db = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255; - }, - - 'color-dodge': function() { - dr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr)); - dg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg)); - db = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb)); - }, - - 'color-burn': function() { - dr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr); - dg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg); - db = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb); - }, - - darken: function() { - dr = br < sr ? br : sr; - dg = bg < sg ? bg : sg; - db = bb < sb ? bb : sb; - }, - - lighten: function() { - dr = br > sr ? br : sr; - dg = bg > sg ? bg : sg; - db = bb > sb ? bb : sb; - }, - - difference: function() { - dr = br - sr; - if (dr < 0) - dr = -dr; - dg = bg - sg; - if (dg < 0) - dg = -dg; - db = bb - sb; - if (db < 0) - db = -db; - }, - - exclusion: function() { - dr = br + sr * (255 - br - br) / 255; - dg = bg + sg * (255 - bg - bg) / 255; - db = bb + sb * (255 - bb - bb) / 255; - }, - - hue: function() { - setSat(sr, sg, sb, getSat(br, bg, bb)); - setLum(dr, dg, db, getLum(br, bg, bb)); - }, - - saturation: function() { - setSat(br, bg, bb, getSat(sr, sg, sb)); - setLum(dr, dg, db, getLum(br, bg, bb)); - }, - - luminosity: function() { - setLum(br, bg, bb, getLum(sr, sg, sb)); - }, - - color: function() { - setLum(sr, sg, sb, getLum(br, bg, bb)); - }, - - add: function() { - dr = min(br + sr, 255); - dg = min(bg + sg, 255); - db = min(bb + sb, 255); - }, - - subtract: function() { - dr = max(br - sr, 0); - dg = max(bg - sg, 0); - db = max(bb - sb, 0); - }, - - average: function() { - dr = (br + sr) / 2; - dg = (bg + sg) / 2; - db = (bb + sb) / 2; - }, - - negation: function() { - dr = 255 - abs(255 - sr - br); - dg = 255 - abs(255 - sg - bg); - db = 255 - abs(255 - sb - bb); - } - }; - - var nativeModes = this.nativeModes = Base.each([ - 'source-over', 'source-in', 'source-out', 'source-atop', - 'destination-over', 'destination-in', 'destination-out', - 'destination-atop', 'lighter', 'darker', 'copy', 'xor' - ], function(mode) { - this[mode] = true; - }, {}); - - var ctx = CanvasProvider.getContext(1, 1); - if (ctx) { - Base.each(modes, function(func, mode) { - var darken = mode === 'darken', - ok = false; - ctx.save(); - try { - ctx.fillStyle = darken ? '#300' : '#a00'; - ctx.fillRect(0, 0, 1, 1); - ctx.globalCompositeOperation = mode; - if (ctx.globalCompositeOperation === mode) { - ctx.fillStyle = darken ? '#a00' : '#300'; - ctx.fillRect(0, 0, 1, 1); - ok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken - ? 170 : 51; - } - } catch (e) {} - ctx.restore(); - nativeModes[mode] = ok; - }); - CanvasProvider.release(ctx); - } - - this.process = function(mode, srcContext, dstContext, alpha, offset) { - var srcCanvas = srcContext.canvas, - normal = mode === 'normal'; - if (normal || nativeModes[mode]) { - dstContext.save(); - dstContext.setTransform(1, 0, 0, 1, 0, 0); - dstContext.globalAlpha = alpha; - if (!normal) - dstContext.globalCompositeOperation = mode; - dstContext.drawImage(srcCanvas, offset.x, offset.y); - dstContext.restore(); - } else { - var process = modes[mode]; - if (!process) - return; - var dstData = dstContext.getImageData(offset.x, offset.y, - srcCanvas.width, srcCanvas.height), - dst = dstData.data, - src = srcContext.getImageData(0, 0, - srcCanvas.width, srcCanvas.height).data; - for (var i = 0, l = dst.length; i < l; i += 4) { - sr = src[i]; - br = dst[i]; - sg = src[i + 1]; - bg = dst[i + 1]; - sb = src[i + 2]; - bb = dst[i + 2]; - sa = src[i + 3]; - ba = dst[i + 3]; - process(); - var a1 = sa * alpha / 255, - a2 = 1 - a1; - dst[i] = a1 * dr + a2 * br; - dst[i + 1] = a1 * dg + a2 * bg; - dst[i + 2] = a1 * db + a2 * bb; - dst[i + 3] = sa * alpha + a2 * ba; - } - dstContext.putImageData(dstData, offset.x, offset.y); - } - }; -}; - -var SvgElement = new function() { - var svg = 'http://www.w3.org/2000/svg', - xmlns = 'http://www.w3.org/2000/xmlns', - xlink = 'http://www.w3.org/1999/xlink', - attributeNamespace = { - href: xlink, - xlink: xmlns, - xmlns: xmlns + '/', - 'xmlns:xlink': xmlns + '/' - }; - - function create(tag, attributes, formatter) { - return set(document.createElementNS(svg, tag), attributes, formatter); - } - - function get(node, name) { - var namespace = attributeNamespace[name], - value = namespace - ? node.getAttributeNS(namespace, name) - : node.getAttribute(name); - return value === 'null' ? null : value; - } - - function set(node, attributes, formatter) { - for (var name in attributes) { - var value = attributes[name], - namespace = attributeNamespace[name]; - if (typeof value === 'number' && formatter) - value = formatter.number(value); - if (namespace) { - node.setAttributeNS(namespace, name, value); - } else { - node.setAttribute(name, value); - } - } - return node; - } - - return { - svg: svg, - xmlns: xmlns, - xlink: xlink, - - create: create, - get: get, - set: set - }; -}; - -var SvgStyles = Base.each({ - fillColor: ['fill', 'color'], - fillRule: ['fill-rule', 'string'], - strokeColor: ['stroke', 'color'], - strokeWidth: ['stroke-width', 'number'], - strokeCap: ['stroke-linecap', 'string'], - strokeJoin: ['stroke-linejoin', 'string'], - strokeScaling: ['vector-effect', 'lookup', { - true: 'none', - false: 'non-scaling-stroke' - }, function(item, value) { - return !value - && (item instanceof PathItem - || item instanceof Shape - || item instanceof TextItem); - }], - miterLimit: ['stroke-miterlimit', 'number'], - dashArray: ['stroke-dasharray', 'array'], - dashOffset: ['stroke-dashoffset', 'number'], - fontFamily: ['font-family', 'string'], - fontWeight: ['font-weight', 'string'], - fontSize: ['font-size', 'number'], - justification: ['text-anchor', 'lookup', { - left: 'start', - center: 'middle', - right: 'end' - }], - opacity: ['opacity', 'number'], - blendMode: ['mix-blend-mode', 'style'] -}, function(entry, key) { - var part = Base.capitalize(key), - lookup = entry[2]; - this[key] = { - type: entry[1], - property: key, - attribute: entry[0], - toSVG: lookup, - fromSVG: lookup && Base.each(lookup, function(value, name) { - this[value] = name; - }, {}), - exportFilter: entry[3], - get: 'get' + part, - set: 'set' + part - }; -}, {}); - -new function() { - var formatter; - - function getTransform(matrix, coordinates, center) { - var attrs = new Base(), - trans = matrix.getTranslation(); - if (coordinates) { - matrix = matrix._shiftless(); - var point = matrix._inverseTransform(trans); - attrs[center ? 'cx' : 'x'] = point.x; - attrs[center ? 'cy' : 'y'] = point.y; - trans = null; - } - if (!matrix.isIdentity()) { - var decomposed = matrix.decompose(); - if (decomposed) { - var parts = [], - angle = decomposed.rotation, - scale = decomposed.scaling, - skew = decomposed.skewing; - if (trans && !trans.isZero()) - parts.push('translate(' + formatter.point(trans) + ')'); - if (angle) - parts.push('rotate(' + formatter.number(angle) + ')'); - if (!Numerical.isZero(scale.x - 1) - || !Numerical.isZero(scale.y - 1)) - parts.push('scale(' + formatter.point(scale) +')'); - if (skew.x) - parts.push('skewX(' + formatter.number(skew.x) + ')'); - if (skew.y) - parts.push('skewY(' + formatter.number(skew.y) + ')'); - attrs.transform = parts.join(' '); - } else { - attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')'; - } - } - return attrs; - } - - function exportGroup(item, options) { - var attrs = getTransform(item._matrix), - children = item._children; - var node = SvgElement.create('g', attrs, formatter); - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i]; - var childNode = exportSVG(child, options); - if (childNode) { - if (child.isClipMask()) { - var clip = SvgElement.create('clipPath'); - clip.appendChild(childNode); - setDefinition(child, clip, 'clip'); - SvgElement.set(node, { - 'clip-path': 'url(#' + clip.id + ')' - }); - } else { - node.appendChild(childNode); - } - } - } - return node; - } - - function exportRaster(item, options) { - var attrs = getTransform(item._matrix, true), - size = item.getSize(), - image = item.getImage(); - attrs.x -= size.width / 2; - attrs.y -= size.height / 2; - attrs.width = size.width; - attrs.height = size.height; - attrs.href = options.embedImages == false && image && image.src - || item.toDataURL(); - return SvgElement.create('image', attrs, formatter); - } - - function exportPath(item, options) { - var matchShapes = options.matchShapes; - if (matchShapes) { - var shape = item.toShape(false); - if (shape) - return exportShape(shape, options); - } - var segments = item._segments, - length = segments.length, - type, - attrs = getTransform(item._matrix); - if (matchShapes && length >= 2 && !item.hasHandles()) { - if (length > 2) { - type = item._closed ? 'polygon' : 'polyline'; - var parts = []; - for (var i = 0; i < length; i++) { - parts.push(formatter.point(segments[i]._point)); - } - attrs.points = parts.join(' '); - } else { - type = 'line'; - var start = segments[0]._point, - end = segments[1]._point; - attrs.set({ - x1: start.x, - y1: start.y, - x2: end.x, - y2: end.y - }); - } - } else { - type = 'path'; - attrs.d = item.getPathData(null, options.precision); - } - return SvgElement.create(type, attrs, formatter); - } - - function exportShape(item) { - var type = item._type, - radius = item._radius, - attrs = getTransform(item._matrix, true, type !== 'rectangle'); - if (type === 'rectangle') { - type = 'rect'; - var size = item._size, - width = size.width, - height = size.height; - attrs.x -= width / 2; - attrs.y -= height / 2; - attrs.width = width; - attrs.height = height; - if (radius.isZero()) - radius = null; - } - if (radius) { - if (type === 'circle') { - attrs.r = radius; - } else { - attrs.rx = radius.width; - attrs.ry = radius.height; - } - } - return SvgElement.create(type, attrs, formatter); - } - - function exportCompoundPath(item, options) { - var attrs = getTransform(item._matrix); - var data = item.getPathData(null, options.precision); - if (data) - attrs.d = data; - return SvgElement.create('path', attrs, formatter); - } - - function exportSymbolItem(item, options) { - var attrs = getTransform(item._matrix, true), - definition = item._definition, - node = getDefinition(definition, 'symbol'), - definitionItem = definition._item, - bounds = definitionItem.getBounds(); - if (!node) { - node = SvgElement.create('symbol', { - viewBox: formatter.rectangle(bounds) - }); - node.appendChild(exportSVG(definitionItem, options)); - setDefinition(definition, node, 'symbol'); - } - attrs.href = '#' + node.id; - attrs.x += bounds.x; - attrs.y += bounds.y; - attrs.width = bounds.width; - attrs.height = bounds.height; - attrs.overflow = 'visible'; - return SvgElement.create('use', attrs, formatter); - } - - function exportGradient(color) { - var gradientNode = getDefinition(color, 'color'); - if (!gradientNode) { - var gradient = color.getGradient(), - radial = gradient._radial, - origin = color.getOrigin(), - destination = color.getDestination(), - attrs; - if (radial) { - attrs = { - cx: origin.x, - cy: origin.y, - r: origin.getDistance(destination) - }; - var highlight = color.getHighlight(); - if (highlight) { - attrs.fx = highlight.x; - attrs.fy = highlight.y; - } - } else { - attrs = { - x1: origin.x, - y1: origin.y, - x2: destination.x, - y2: destination.y - }; - } - attrs.gradientUnits = 'userSpaceOnUse'; - gradientNode = SvgElement.create((radial ? 'radial' : 'linear') - + 'Gradient', attrs, formatter); - var stops = gradient._stops; - for (var i = 0, l = stops.length; i < l; i++) { - var stop = stops[i], - stopColor = stop._color, - alpha = stopColor.getAlpha(), - offset = stop._offset; - attrs = { - offset: offset == null ? i / (l - 1) : offset - }; - if (stopColor) - attrs['stop-color'] = stopColor.toCSS(true); - if (alpha < 1) - attrs['stop-opacity'] = alpha; - gradientNode.appendChild( - SvgElement.create('stop', attrs, formatter)); - } - setDefinition(color, gradientNode, 'color'); - } - return 'url(#' + gradientNode.id + ')'; - } - - function exportText(item) { - var node = SvgElement.create('text', getTransform(item._matrix, true), - formatter); - node.textContent = item._content; - return node; - } - - var exporters = { - Group: exportGroup, - Layer: exportGroup, - Raster: exportRaster, - Path: exportPath, - Shape: exportShape, - CompoundPath: exportCompoundPath, - SymbolItem: exportSymbolItem, - PointText: exportText - }; - - function applyStyle(item, node, isRoot) { - var attrs = {}, - parent = !isRoot && item.getParent(), - style = []; - - if (item._name != null) - attrs.id = item._name; - - Base.each(SvgStyles, function(entry) { - var get = entry.get, - type = entry.type, - value = item[get](); - if (entry.exportFilter - ? entry.exportFilter(item, value) - : !parent || !Base.equals(parent[get](), value)) { - if (type === 'color' && value != null) { - var alpha = value.getAlpha(); - if (alpha < 1) - attrs[entry.attribute + '-opacity'] = alpha; - } - if (type === 'style') { - style.push(entry.attribute + ': ' + value); - } else { - attrs[entry.attribute] = value == null ? 'none' - : type === 'color' ? value.gradient - ? exportGradient(value, item) - : value.toCSS(true) - : type === 'array' ? value.join(',') - : type === 'lookup' ? entry.toSVG[value] - : value; - } - } - }); - - if (style.length) - attrs.style = style.join(';'); - - if (attrs.opacity === 1) - delete attrs.opacity; - - if (!item._visible) - attrs.visibility = 'hidden'; - - return SvgElement.set(node, attrs, formatter); - } - - var definitions; - function getDefinition(item, type) { - if (!definitions) - definitions = { ids: {}, svgs: {} }; - return item && definitions.svgs[type + '-' - + (item._id || item.__id || (item.__id = UID.get('svg')))]; - } - - function setDefinition(item, node, type) { - if (!definitions) - getDefinition(); - var typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1; - node.id = type + '-' + typeId; - definitions.svgs[type + '-' + (item._id || item.__id)] = node; - } - - function exportDefinitions(node, options) { - var svg = node, - defs = null; - if (definitions) { - svg = node.nodeName.toLowerCase() === 'svg' && node; - for (var i in definitions.svgs) { - if (!defs) { - if (!svg) { - svg = SvgElement.create('svg'); - svg.appendChild(node); - } - defs = svg.insertBefore(SvgElement.create('defs'), - svg.firstChild); - } - defs.appendChild(definitions.svgs[i]); - } - definitions = null; - } - return options.asString - ? new self.XMLSerializer().serializeToString(svg) - : svg; - } - - function exportSVG(item, options, isRoot) { - var exporter = exporters[item._class], - node = exporter && exporter(item, options); - if (node) { - var onExport = options.onExport; - if (onExport) - node = onExport(item, node, options) || node; - var data = JSON.stringify(item._data); - if (data && data !== '{}' && data !== 'null') - node.setAttribute('data-paper-data', data); - } - return node && applyStyle(item, node, isRoot); - } - - function setOptions(options) { - if (!options) - options = {}; - formatter = new Formatter(options.precision); - return options; - } - - Item.inject({ - exportSVG: function(options) { - options = setOptions(options); - return exportDefinitions(exportSVG(this, options, true), options); - } - }); - - Project.inject({ - exportSVG: function(options) { - options = setOptions(options); - var children = this._children, - view = this.getView(), - bounds = Base.pick(options.bounds, 'view'), - mx = options.matrix || bounds === 'view' && view._matrix, - matrix = mx && Matrix.read([mx]), - rect = bounds === 'view' - ? new Rectangle([0, 0], view.getViewSize()) - : bounds === 'content' - ? Item._getBounds(children, matrix, { stroke: true }) - .rect - : Rectangle.read([bounds], 0, { readNull: true }), - attrs = { - version: '1.1', - xmlns: SvgElement.svg, - 'xmlns:xlink': SvgElement.xlink, - }; - if (rect) { - attrs.width = rect.width; - attrs.height = rect.height; - if (rect.x || rect.y) - attrs.viewBox = formatter.rectangle(rect); - } - var node = SvgElement.create('svg', attrs, formatter), - parent = node; - if (matrix && !matrix.isIdentity()) { - parent = node.appendChild(SvgElement.create('g', - getTransform(matrix), formatter)); - } - for (var i = 0, l = children.length; i < l; i++) { - parent.appendChild(exportSVG(children[i], options, true)); - } - return exportDefinitions(node, options); - } - }); -}; - -new function() { - - var definitions = {}, - rootSize; - - function getValue(node, name, isString, allowNull, allowPercent) { - var value = SvgElement.get(node, name), - res = value == null - ? allowNull - ? null - : isString ? '' : 0 - : isString - ? value - : parseFloat(value); - return /%\s*$/.test(value) - ? (res / 100) * (allowPercent ? 1 - : rootSize[/x|^width/.test(name) ? 'width' : 'height']) - : res; - } - - function getPoint(node, x, y, allowNull, allowPercent) { - x = getValue(node, x || 'x', false, allowNull, allowPercent); - y = getValue(node, y || 'y', false, allowNull, allowPercent); - return allowNull && (x == null || y == null) ? null - : new Point(x, y); - } - - function getSize(node, w, h, allowNull, allowPercent) { - w = getValue(node, w || 'width', false, allowNull, allowPercent); - h = getValue(node, h || 'height', false, allowNull, allowPercent); - return allowNull && (w == null || h == null) ? null - : new Size(w, h); - } - - function convertValue(value, type, lookup) { - return value === 'none' ? null - : type === 'number' ? parseFloat(value) - : type === 'array' ? - value ? value.split(/[\s,]+/g).map(parseFloat) : [] - : type === 'color' ? getDefinition(value) || value - : type === 'lookup' ? lookup[value] - : value; - } - - function importGroup(node, type, options, isRoot) { - var nodes = node.childNodes, - isClip = type === 'clippath', - isDefs = type === 'defs', - item = new Group(), - project = item._project, - currentStyle = project._currentStyle, - children = []; - if (!isClip && !isDefs) { - item = applyAttributes(item, node, isRoot); - project._currentStyle = item._style.clone(); - } - if (isRoot) { - var defs = node.querySelectorAll('defs'); - for (var i = 0, l = defs.length; i < l; i++) { - importNode(defs[i], options, false); - } - } - for (var i = 0, l = nodes.length; i < l; i++) { - var childNode = nodes[i], - child; - if (childNode.nodeType === 1 - && !/^defs$/i.test(childNode.nodeName) - && (child = importNode(childNode, options, false)) - && !(child instanceof SymbolDefinition)) - children.push(child); - } - item.addChildren(children); - if (isClip) - item = applyAttributes(item.reduce(), node, isRoot); - project._currentStyle = currentStyle; - if (isClip || isDefs) { - item.remove(); - item = null; - } - return item; - } - - function importPoly(node, type) { - var coords = node.getAttribute('points').match( - /[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g), - points = []; - for (var i = 0, l = coords.length; i < l; i += 2) - points.push(new Point( - parseFloat(coords[i]), - parseFloat(coords[i + 1]))); - var path = new Path(points); - if (type === 'polygon') - path.closePath(); - return path; - } - - function importPath(node) { - return PathItem.create(node.getAttribute('d')); - } - - function importGradient(node, type) { - var id = (getValue(node, 'href', true) || '').substring(1), - radial = type === 'radialgradient', - gradient; - if (id) { - gradient = definitions[id].getGradient(); - if (gradient._radial ^ radial) { - gradient = gradient.clone(); - gradient._radial = radial; - } - } else { - var nodes = node.childNodes, - stops = []; - for (var i = 0, l = nodes.length; i < l; i++) { - var child = nodes[i]; - if (child.nodeType === 1) - stops.push(applyAttributes(new GradientStop(), child)); - } - gradient = new Gradient(stops, radial); - } - var origin, destination, highlight, - scaleToBounds = getValue(node, 'gradientUnits', true) !== - 'userSpaceOnUse'; - if (radial) { - origin = getPoint(node, 'cx', 'cy', false, scaleToBounds); - destination = origin.add( - getValue(node, 'r', false, false, scaleToBounds), 0); - highlight = getPoint(node, 'fx', 'fy', true, scaleToBounds); - } else { - origin = getPoint(node, 'x1', 'y1', false, scaleToBounds); - destination = getPoint(node, 'x2', 'y2', false, scaleToBounds); - } - var color = applyAttributes( - new Color(gradient, origin, destination, highlight), node); - color._scaleToBounds = scaleToBounds; - return null; - } - - var importers = { - '#document': function (node, type, options, isRoot) { - var nodes = node.childNodes; - for (var i = 0, l = nodes.length; i < l; i++) { - var child = nodes[i]; - if (child.nodeType === 1) - return importNode(child, options, isRoot); - } - }, - g: importGroup, - svg: importGroup, - clippath: importGroup, - polygon: importPoly, - polyline: importPoly, - path: importPath, - lineargradient: importGradient, - radialgradient: importGradient, - - image: function (node) { - var raster = new Raster(getValue(node, 'href', true)); - raster.on('load', function() { - var size = getSize(node); - this.setSize(size); - var center = getPoint(node).add(size.divide(2)); - this._matrix.append(new Matrix().translate(center)); - }); - return raster; - }, - - symbol: function(node, type, options, isRoot) { - return new SymbolDefinition( - importGroup(node, type, options, isRoot), true); - }, - - defs: importGroup, - - use: function(node) { - var id = (getValue(node, 'href', true) || '').substring(1), - definition = definitions[id], - point = getPoint(node); - return definition - ? definition instanceof SymbolDefinition - ? definition.place(point) - : definition.clone().translate(point) - : null; - }, - - circle: function(node) { - return new Shape.Circle( - getPoint(node, 'cx', 'cy'), - getValue(node, 'r')); - }, - - ellipse: function(node) { - return new Shape.Ellipse({ - center: getPoint(node, 'cx', 'cy'), - radius: getSize(node, 'rx', 'ry') - }); - }, - - rect: function(node) { - return new Shape.Rectangle(new Rectangle( - getPoint(node), - getSize(node) - ), getSize(node, 'rx', 'ry')); - }, - - line: function(node) { - return new Path.Line( - getPoint(node, 'x1', 'y1'), - getPoint(node, 'x2', 'y2')); - }, - - text: function(node) { - var text = new PointText(getPoint(node).add( - getPoint(node, 'dx', 'dy'))); - text.setContent(node.textContent.trim() || ''); - return text; - } - }; - - function applyTransform(item, value, name, node) { - if (item.transform) { - var transforms = (node.getAttribute(name) || '').split(/\)\s*/g), - matrix = new Matrix(); - for (var i = 0, l = transforms.length; i < l; i++) { - var transform = transforms[i]; - if (!transform) - break; - var parts = transform.split(/\(\s*/), - command = parts[0], - v = parts[1].split(/[\s,]+/g); - for (var j = 0, m = v.length; j < m; j++) - v[j] = parseFloat(v[j]); - switch (command) { - case 'matrix': - matrix.append( - new Matrix(v[0], v[1], v[2], v[3], v[4], v[5])); - break; - case 'rotate': - matrix.rotate(v[0], v[1] || 0, v[2] || 0); - break; - case 'translate': - matrix.translate(v[0], v[1] || 0); - break; - case 'scale': - matrix.scale(v); - break; - case 'skewX': - matrix.skew(v[0], 0); - break; - case 'skewY': - matrix.skew(0, v[0]); - break; - } - } - item.transform(matrix); - } - } - - function applyOpacity(item, value, name) { - var key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor', - color = item[key] && item[key](); - if (color) - color.setAlpha(parseFloat(value)); - } - - var attributes = Base.set(Base.each(SvgStyles, function(entry) { - this[entry.attribute] = function(item, value) { - if (item[entry.set]) { - item[entry.set](convertValue(value, entry.type, entry.fromSVG)); - if (entry.type === 'color') { - var color = item[entry.get](); - if (color) { - if (color._scaleToBounds) { - var bounds = item.getBounds(); - color.transform(new Matrix() - .translate(bounds.getPoint()) - .scale(bounds.getSize())); - } - } - } - } - }; - }, {}), { - id: function(item, value) { - definitions[value] = item; - if (item.setName) - item.setName(value); - }, - - 'clip-path': function(item, value) { - var clip = getDefinition(value); - if (clip) { - clip = clip.clone(); - clip.setClipMask(true); - if (item instanceof Group) { - item.insertChild(0, clip); - } else { - return new Group(clip, item); - } - } - }, - - gradientTransform: applyTransform, - transform: applyTransform, - - 'fill-opacity': applyOpacity, - 'stroke-opacity': applyOpacity, - - visibility: function(item, value) { - if (item.setVisible) - item.setVisible(value === 'visible'); - }, - - display: function(item, value) { - if (item.setVisible) - item.setVisible(value !== null); - }, - - 'stop-color': function(item, value) { - if (item.setColor) - item.setColor(value); - }, - - 'stop-opacity': function(item, value) { - if (item._color) - item._color.setAlpha(parseFloat(value)); - }, - - offset: function(item, value) { - if (item.setOffset) { - var percent = value.match(/(.*)%$/); - item.setOffset(percent ? percent[1] / 100 : parseFloat(value)); - } - }, - - viewBox: function(item, value, name, node, styles) { - var rect = new Rectangle(convertValue(value, 'array')), - size = getSize(node, null, null, true), - group, - matrix; - if (item instanceof Group) { - var scale = size ? size.divide(rect.getSize()) : 1, - matrix = new Matrix().scale(scale) - .translate(rect.getPoint().negate()); - group = item; - } else if (item instanceof SymbolDefinition) { - if (size) - rect.setSize(size); - group = item._item; - } - if (group) { - if (getAttribute(node, 'overflow', styles) !== 'visible') { - var clip = new Shape.Rectangle(rect); - clip.setClipMask(true); - group.addChild(clip); - } - if (matrix) - group.transform(matrix); - } - } - }); - - function getAttribute(node, name, styles) { - var attr = node.attributes[name], - value = attr && attr.value; - if (!value && node.style) { - var style = Base.camelize(name); - value = node.style[style]; - if (!value && styles.node[style] !== styles.parent[style]) - value = styles.node[style]; - } - return !value ? undefined - : value === 'none' ? null - : value; - } - - function applyAttributes(item, node, isRoot) { - var parent = node.parentNode, - styles = { - node: DomElement.getStyles(node) || {}, - parent: !isRoot && !/^defs$/i.test(parent.tagName) - && DomElement.getStyles(parent) || {} - }; - Base.each(attributes, function(apply, name) { - var value = getAttribute(node, name, styles); - item = value !== undefined - && apply(item, value, name, node, styles) || item; - }); - return item; - } - - function getDefinition(value) { - var match = value && value.match(/\((?:["'#]*)([^"')]+)/), - name = match && match[1], - res = name && definitions[window - ? name.replace(window.location.href.split('#')[0] + '#', '') - : name]; - if (res && res._scaleToBounds) { - res = res.clone(); - res._scaleToBounds = true; - } - return res; - } - - function importNode(node, options, isRoot) { - var type = node.nodeName.toLowerCase(), - isElement = type !== '#document', - body = document.body, - container, - parent, - next; - if (isRoot && isElement) { - rootSize = paper.getView().getSize(); - rootSize = getSize(node, null, null, true) || rootSize; - container = SvgElement.create('svg', { - style: 'stroke-width: 1px; stroke-miterlimit: 10' - }); - parent = node.parentNode; - next = node.nextSibling; - container.appendChild(node); - body.appendChild(container); - } - var settings = paper.settings, - applyMatrix = settings.applyMatrix, - insertItems = settings.insertItems; - settings.applyMatrix = false; - settings.insertItems = false; - var importer = importers[type], - item = importer && importer(node, type, options, isRoot) || null; - settings.insertItems = insertItems; - settings.applyMatrix = applyMatrix; - if (item) { - if (isElement && !(item instanceof Group)) - item = applyAttributes(item, node, isRoot); - var onImport = options.onImport, - data = isElement && node.getAttribute('data-paper-data'); - if (onImport) - item = onImport(node, item, options) || item; - if (options.expandShapes && item instanceof Shape) { - item.remove(); - item = item.toPath(); - } - if (data) - item._data = JSON.parse(data); - } - if (container) { - body.removeChild(container); - if (parent) { - if (next) { - parent.insertBefore(node, next); - } else { - parent.appendChild(node); - } - } - } - if (isRoot) { - definitions = {}; - if (item && Base.pick(options.applyMatrix, applyMatrix)) - item.matrix.apply(true, true); - } - return item; - } - - function importSVG(source, options, owner) { - if (!source) - return null; - options = typeof options === 'function' ? { onLoad: options } - : options || {}; - var scope = paper, - item = null; - - function onLoad(svg) { - try { - var node = typeof svg === 'object' ? svg : new self.DOMParser() - .parseFromString(svg, 'image/svg+xml'); - if (!node.nodeName) { - node = null; - throw new Error('Unsupported SVG source: ' + source); - } - paper = scope; - item = importNode(node, options, true); - if (!options || options.insert !== false) { - owner._insertItem(undefined, item); - } - var onLoad = options.onLoad; - if (onLoad) - onLoad(item, svg); - } catch (e) { - onError(e); - } - } - - function onError(message, status) { - var onError = options.onError; - if (onError) { - onError(message, status); - } else { - throw new Error(message); - } - } - - if (typeof source === 'string' && !/^.* 3) { - cats.sort(function(a, b) {return b.length - a.length;}); - f += "switch(str.length){"; - for (var i = 0; i < cats.length; ++i) { - var cat = cats[i]; - f += "case " + cat[0].length + ":"; - compareTo(cat); - } - f += "}"; - - } else { - compareTo(words); - } - return new Function("str", f); - } - - var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"); - - var isReservedWord5 = makePredicate("class enum extends super const export import"); - - var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield"); - - var isStrictBadIdWord = makePredicate("eval arguments"); - - var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"); - - var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\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 = "\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 + "]"); - - var newline = /[\n\r\u2028\u2029]/; - - var lineBreak = /\r\n|[\n\r\u2028\u2029]/g; - - var isIdentifierStart = exports.isIdentifierStart = function(code) { - if (code < 65) return code === 36; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123)return true; - return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); - }; - - var isIdentifierChar = exports.isIdentifierChar = function(code) { - if (code < 48) return code === 36; - if (code < 58) return true; - if (code < 65) return false; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123)return true; - return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); - }; - - function line_loc_t() { - this.line = tokCurLine; - this.column = tokPos - tokLineStart; - } - - function initTokenState() { - tokCurLine = 1; - tokPos = tokLineStart = 0; - tokRegexpAllowed = true; - skipSpace(); - } - - function finishToken(type, val) { - tokEnd = tokPos; - if (options.locations) tokEndLoc = new line_loc_t; - tokType = type; - skipSpace(); - tokVal = val; - tokRegexpAllowed = type.beforeExpr; - } - - function skipBlockComment() { - var startLoc = options.onComment && options.locations && new line_loc_t; - var start = tokPos, end = input.indexOf("*/", tokPos += 2); - if (end === -1) raise(tokPos - 2, "Unterminated comment"); - tokPos = end + 2; - if (options.locations) { - lineBreak.lastIndex = start; - var match; - while ((match = lineBreak.exec(input)) && match.index < tokPos) { - ++tokCurLine; - tokLineStart = match.index + match[0].length; - } - } - if (options.onComment) - options.onComment(true, input.slice(start + 2, end), start, tokPos, - startLoc, options.locations && new line_loc_t); - } - - function skipLineComment() { - var start = tokPos; - var startLoc = options.onComment && options.locations && new line_loc_t; - var ch = input.charCodeAt(tokPos+=2); - while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { - ++tokPos; - ch = input.charCodeAt(tokPos); - } - if (options.onComment) - options.onComment(false, input.slice(start + 2, tokPos), start, tokPos, - startLoc, options.locations && new line_loc_t); - } - - function skipSpace() { - while (tokPos < inputLen) { - var ch = input.charCodeAt(tokPos); - if (ch === 32) { - ++tokPos; - } else if (ch === 13) { - ++tokPos; - var next = input.charCodeAt(tokPos); - if (next === 10) { - ++tokPos; - } - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - } else if (ch === 10 || ch === 8232 || ch === 8233) { - ++tokPos; - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - } else if (ch > 8 && ch < 14) { - ++tokPos; - } else if (ch === 47) { - var next = input.charCodeAt(tokPos + 1); - if (next === 42) { - skipBlockComment(); - } else if (next === 47) { - skipLineComment(); - } else break; - } else if (ch === 160) { - ++tokPos; - } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++tokPos; - } else { - break; - } - } - } - - function readToken_dot() { - var next = input.charCodeAt(tokPos + 1); - if (next >= 48 && next <= 57) return readNumber(true); - ++tokPos; - return finishToken(_dot); - } - - function readToken_slash() { - var next = input.charCodeAt(tokPos + 1); - if (tokRegexpAllowed) {++tokPos; return readRegexp();} - if (next === 61) return finishOp(_assign, 2); - return finishOp(_slash, 1); - } - - function readToken_mult_modulo() { - var next = input.charCodeAt(tokPos + 1); - if (next === 61) return finishOp(_assign, 2); - return finishOp(_multiplyModulo, 1); - } - - function readToken_pipe_amp(code) { - var next = input.charCodeAt(tokPos + 1); - if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2); - if (next === 61) return finishOp(_assign, 2); - return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1); - } - - function readToken_caret() { - var next = input.charCodeAt(tokPos + 1); - if (next === 61) return finishOp(_assign, 2); - return finishOp(_bitwiseXOR, 1); - } - - function readToken_plus_min(code) { - var next = input.charCodeAt(tokPos + 1); - if (next === code) { - if (next == 45 && input.charCodeAt(tokPos + 2) == 62 && - newline.test(input.slice(lastEnd, tokPos))) { - tokPos += 3; - skipLineComment(); - skipSpace(); - return readToken(); - } - return finishOp(_incDec, 2); - } - if (next === 61) return finishOp(_assign, 2); - return finishOp(_plusMin, 1); - } - - function readToken_lt_gt(code) { - var next = input.charCodeAt(tokPos + 1); - var size = 1; - if (next === code) { - size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2; - if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1); - return finishOp(_bitShift, size); - } - if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 && - input.charCodeAt(tokPos + 3) == 45) { - tokPos += 4; - skipLineComment(); - skipSpace(); - return readToken(); - } - if (next === 61) - size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2; - return finishOp(_relational, size); - } - - function readToken_eq_excl(code) { - var next = input.charCodeAt(tokPos + 1); - if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2); - return finishOp(code === 61 ? _eq : _prefix, 1); - } - - function getTokenFromCode(code) { - switch(code) { - case 46: - return readToken_dot(); - - case 40: ++tokPos; return finishToken(_parenL); - case 41: ++tokPos; return finishToken(_parenR); - case 59: ++tokPos; return finishToken(_semi); - case 44: ++tokPos; return finishToken(_comma); - case 91: ++tokPos; return finishToken(_bracketL); - case 93: ++tokPos; return finishToken(_bracketR); - case 123: ++tokPos; return finishToken(_braceL); - case 125: ++tokPos; return finishToken(_braceR); - case 58: ++tokPos; return finishToken(_colon); - case 63: ++tokPos; return finishToken(_question); - - case 48: - var next = input.charCodeAt(tokPos + 1); - if (next === 120 || next === 88) return readHexNumber(); - case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: - return readNumber(false); - - case 34: case 39: - return readString(code); - - case 47: - return readToken_slash(code); - - case 37: case 42: - return readToken_mult_modulo(); - - case 124: case 38: - return readToken_pipe_amp(code); - - case 94: - return readToken_caret(); - - case 43: case 45: - return readToken_plus_min(code); - - case 60: case 62: - return readToken_lt_gt(code); - - case 61: case 33: - return readToken_eq_excl(code); - - case 126: - return finishOp(_prefix, 1); - } - - return false; - } - - function readToken(forceRegexp) { - if (!forceRegexp) tokStart = tokPos; - else tokPos = tokStart + 1; - if (options.locations) tokStartLoc = new line_loc_t; - if (forceRegexp) return readRegexp(); - if (tokPos >= inputLen) return finishToken(_eof); - - var code = input.charCodeAt(tokPos); - if (isIdentifierStart(code) || code === 92 ) return readWord(); - - var tok = getTokenFromCode(code); - - if (tok === false) { - var ch = String.fromCharCode(code); - if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return readWord(); - raise(tokPos, "Unexpected character '" + ch + "'"); - } - return tok; - } - - function finishOp(type, size) { - var str = input.slice(tokPos, tokPos + size); - tokPos += size; - finishToken(type, str); - } - - function readRegexp() { - var content = "", escaped, inClass, start = tokPos; - for (;;) { - if (tokPos >= inputLen) raise(start, "Unterminated regular expression"); - var ch = input.charAt(tokPos); - if (newline.test(ch)) raise(start, "Unterminated regular expression"); - if (!escaped) { - if (ch === "[") inClass = true; - else if (ch === "]" && inClass) inClass = false; - else if (ch === "/" && !inClass) break; - escaped = ch === "\\"; - } else escaped = false; - ++tokPos; - } - var content = input.slice(start, tokPos); - ++tokPos; - var mods = readWord1(); - if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regexp flag"); - try { - var value = new RegExp(content, mods); - } catch (e) { - if (e instanceof SyntaxError) raise(start, e.message); - raise(e); - } - return finishToken(_regexp, value); - } - - function readInt(radix, len) { - var start = tokPos, total = 0; - for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { - var code = input.charCodeAt(tokPos), val; - if (code >= 97) val = code - 97 + 10; - else if (code >= 65) val = code - 65 + 10; - else if (code >= 48 && code <= 57) val = code - 48; - else val = Infinity; - if (val >= radix) break; - ++tokPos; - total = total * radix + val; - } - if (tokPos === start || len != null && tokPos - start !== len) return null; - - return total; - } - - function readHexNumber() { - tokPos += 2; - var val = readInt(16); - if (val == null) raise(tokStart + 2, "Expected hexadecimal number"); - if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number"); - return finishToken(_num, val); - } - - function readNumber(startsWithDot) { - var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48; - if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number"); - if (input.charCodeAt(tokPos) === 46) { - ++tokPos; - readInt(10); - isFloat = true; - } - var next = input.charCodeAt(tokPos); - if (next === 69 || next === 101) { - next = input.charCodeAt(++tokPos); - if (next === 43 || next === 45) ++tokPos; - if (readInt(10) === null) raise(start, "Invalid number"); - isFloat = true; - } - if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number"); - - var str = input.slice(start, tokPos), val; - if (isFloat) val = parseFloat(str); - else if (!octal || str.length === 1) val = parseInt(str, 10); - else if (/[89]/.test(str) || strict) raise(start, "Invalid number"); - else val = parseInt(str, 8); - return finishToken(_num, val); - } - - function readString(quote) { - tokPos++; - var out = ""; - for (;;) { - if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant"); - var ch = input.charCodeAt(tokPos); - if (ch === quote) { - ++tokPos; - return finishToken(_string, out); - } - if (ch === 92) { - ch = input.charCodeAt(++tokPos); - var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3)); - if (octal) octal = octal[0]; - while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1); - if (octal === "0") octal = null; - ++tokPos; - if (octal) { - if (strict) raise(tokPos - 2, "Octal literal in strict mode"); - out += String.fromCharCode(parseInt(octal, 8)); - tokPos += octal.length - 1; - } else { - switch (ch) { - case 110: out += "\n"; break; - case 114: out += "\r"; break; - case 120: out += String.fromCharCode(readHexChar(2)); break; - case 117: out += String.fromCharCode(readHexChar(4)); break; - case 85: out += String.fromCharCode(readHexChar(8)); break; - case 116: out += "\t"; break; - case 98: out += "\b"; break; - case 118: out += "\u000b"; break; - case 102: out += "\f"; break; - case 48: out += "\0"; break; - case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; - case 10: - if (options.locations) { tokLineStart = tokPos; ++tokCurLine; } - break; - default: out += String.fromCharCode(ch); break; - } - } - } else { - if (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) raise(tokStart, "Unterminated string constant"); - out += String.fromCharCode(ch); - ++tokPos; - } - } - } - - function readHexChar(len) { - var n = readInt(16, len); - if (n === null) raise(tokStart, "Bad character escape sequence"); - return n; - } - - var containsEsc; - - function readWord1() { - containsEsc = false; - var word, first = true, start = tokPos; - for (;;) { - var ch = input.charCodeAt(tokPos); - if (isIdentifierChar(ch)) { - if (containsEsc) word += input.charAt(tokPos); - ++tokPos; - } else if (ch === 92) { - if (!containsEsc) word = input.slice(start, tokPos); - containsEsc = true; - if (input.charCodeAt(++tokPos) != 117) - raise(tokPos, "Expecting Unicode escape sequence \\uXXXX"); - ++tokPos; - var esc = readHexChar(4); - var escStr = String.fromCharCode(esc); - if (!escStr) raise(tokPos - 1, "Invalid Unicode escape"); - if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc))) - raise(tokPos - 4, "Invalid Unicode escape"); - word += escStr; - } else { - break; - } - first = false; - } - return containsEsc ? word : input.slice(start, tokPos); - } - - function readWord() { - var word = readWord1(); - var type = _name; - if (!containsEsc && isKeyword(word)) - type = keywordTypes[word]; - return finishToken(type, word); - } - - function next() { - lastStart = tokStart; - lastEnd = tokEnd; - lastEndLoc = tokEndLoc; - readToken(); - } - - function setStrict(strct) { - strict = strct; - tokPos = tokStart; - if (options.locations) { - while (tokPos < tokLineStart) { - tokLineStart = input.lastIndexOf("\n", tokLineStart - 2) + 1; - --tokCurLine; - } - } - skipSpace(); - readToken(); - } - - function node_t() { - this.type = null; - this.start = tokStart; - this.end = null; - } - - function node_loc_t() { - this.start = tokStartLoc; - this.end = null; - if (sourceFile !== null) this.source = sourceFile; - } - - function startNode() { - var node = new node_t(); - if (options.locations) - node.loc = new node_loc_t(); - if (options.directSourceFile) - node.sourceFile = options.directSourceFile; - if (options.ranges) - node.range = [tokStart, 0]; - return node; - } - - function startNodeFrom(other) { - var node = new node_t(); - node.start = other.start; - if (options.locations) { - node.loc = new node_loc_t(); - node.loc.start = other.loc.start; - } - if (options.ranges) - node.range = [other.range[0], 0]; - - return node; - } - - function finishNode(node, type) { - node.type = type; - node.end = lastEnd; - if (options.locations) - node.loc.end = lastEndLoc; - if (options.ranges) - node.range[1] = lastEnd; - return node; - } - - function isUseStrict(stmt) { - return options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && - stmt.expression.type === "Literal" && stmt.expression.value === "use strict"; - } - - function eat(type) { - if (tokType === type) { - next(); - return true; - } - } - - function canInsertSemicolon() { - return !options.strictSemicolons && - (tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart))); - } - - function semicolon() { - if (!eat(_semi) && !canInsertSemicolon()) unexpected(); - } - - function expect(type) { - if (tokType === type) next(); - else unexpected(); - } - - function unexpected() { - raise(tokStart, "Unexpected token"); - } - - function checkLVal(expr) { - if (expr.type !== "Identifier" && expr.type !== "MemberExpression") - raise(expr.start, "Assigning to rvalue"); - if (strict && expr.type === "Identifier" && isStrictBadIdWord(expr.name)) - raise(expr.start, "Assigning to " + expr.name + " in strict mode"); - } - - function parseTopLevel(program) { - lastStart = lastEnd = tokPos; - if (options.locations) lastEndLoc = new line_loc_t; - inFunction = strict = null; - labels = []; - readToken(); - - var node = program || startNode(), first = true; - if (!program) node.body = []; - while (tokType !== _eof) { - var stmt = parseStatement(); - node.body.push(stmt); - if (first && isUseStrict(stmt)) setStrict(true); - first = false; - } - return finishNode(node, "Program"); - } - - var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; - - function parseStatement() { - if (tokType === _slash || tokType === _assign && tokVal == "/=") - readToken(true); - - var starttype = tokType, node = startNode(); - - switch (starttype) { - case _break: case _continue: - next(); - var isBreak = starttype === _break; - if (eat(_semi) || canInsertSemicolon()) node.label = null; - else if (tokType !== _name) unexpected(); - else { - node.label = parseIdent(); - semicolon(); - } - - for (var i = 0; i < labels.length; ++i) { - var lab = labels[i]; - if (node.label == null || lab.name === node.label.name) { - if (lab.kind != null && (isBreak || lab.kind === "loop")) break; - if (node.label && isBreak) break; - } - } - if (i === labels.length) raise(node.start, "Unsyntactic " + starttype.keyword); - return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); - - case _debugger: - next(); - semicolon(); - return finishNode(node, "DebuggerStatement"); - - case _do: - next(); - labels.push(loopLabel); - node.body = parseStatement(); - labels.pop(); - expect(_while); - node.test = parseParenExpression(); - semicolon(); - return finishNode(node, "DoWhileStatement"); - - case _for: - next(); - labels.push(loopLabel); - expect(_parenL); - if (tokType === _semi) return parseFor(node, null); - if (tokType === _var) { - var init = startNode(); - next(); - parseVar(init, true); - finishNode(init, "VariableDeclaration"); - if (init.declarations.length === 1 && eat(_in)) - return parseForIn(node, init); - return parseFor(node, init); - } - var init = parseExpression(false, true); - if (eat(_in)) {checkLVal(init); return parseForIn(node, init);} - return parseFor(node, init); - - case _function: - next(); - return parseFunction(node, true); - - case _if: - next(); - node.test = parseParenExpression(); - node.consequent = parseStatement(); - node.alternate = eat(_else) ? parseStatement() : null; - return finishNode(node, "IfStatement"); - - case _return: - if (!inFunction && !options.allowReturnOutsideFunction) - raise(tokStart, "'return' outside of function"); - next(); - - if (eat(_semi) || canInsertSemicolon()) node.argument = null; - else { node.argument = parseExpression(); semicolon(); } - return finishNode(node, "ReturnStatement"); - - case _switch: - next(); - node.discriminant = parseParenExpression(); - node.cases = []; - expect(_braceL); - labels.push(switchLabel); - - for (var cur, sawDefault; tokType != _braceR;) { - if (tokType === _case || tokType === _default) { - var isCase = tokType === _case; - if (cur) finishNode(cur, "SwitchCase"); - node.cases.push(cur = startNode()); - cur.consequent = []; - next(); - if (isCase) cur.test = parseExpression(); - else { - if (sawDefault) raise(lastStart, "Multiple default clauses"); sawDefault = true; - cur.test = null; - } - expect(_colon); - } else { - if (!cur) unexpected(); - cur.consequent.push(parseStatement()); - } - } - if (cur) finishNode(cur, "SwitchCase"); - next(); - labels.pop(); - return finishNode(node, "SwitchStatement"); - - case _throw: - next(); - if (newline.test(input.slice(lastEnd, tokStart))) - raise(lastEnd, "Illegal newline after throw"); - node.argument = parseExpression(); - semicolon(); - return finishNode(node, "ThrowStatement"); - - case _try: - next(); - node.block = parseBlock(); - node.handler = null; - if (tokType === _catch) { - var clause = startNode(); - next(); - expect(_parenL); - clause.param = parseIdent(); - if (strict && isStrictBadIdWord(clause.param.name)) - raise(clause.param.start, "Binding " + clause.param.name + " in strict mode"); - expect(_parenR); - clause.guard = null; - clause.body = parseBlock(); - node.handler = finishNode(clause, "CatchClause"); - } - node.guardedHandlers = empty; - node.finalizer = eat(_finally) ? parseBlock() : null; - if (!node.handler && !node.finalizer) - raise(node.start, "Missing catch or finally clause"); - return finishNode(node, "TryStatement"); - - case _var: - next(); - parseVar(node); - semicolon(); - return finishNode(node, "VariableDeclaration"); - - case _while: - next(); - node.test = parseParenExpression(); - labels.push(loopLabel); - node.body = parseStatement(); - labels.pop(); - return finishNode(node, "WhileStatement"); - - case _with: - if (strict) raise(tokStart, "'with' in strict mode"); - next(); - node.object = parseParenExpression(); - node.body = parseStatement(); - return finishNode(node, "WithStatement"); - - case _braceL: - return parseBlock(); - - case _semi: - next(); - return finishNode(node, "EmptyStatement"); - - default: - var maybeName = tokVal, expr = parseExpression(); - if (starttype === _name && expr.type === "Identifier" && eat(_colon)) { - for (var i = 0; i < labels.length; ++i) - if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared"); - var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null; - labels.push({name: maybeName, kind: kind}); - node.body = parseStatement(); - labels.pop(); - node.label = expr; - return finishNode(node, "LabeledStatement"); - } else { - node.expression = expr; - semicolon(); - return finishNode(node, "ExpressionStatement"); - } - } - } - - function parseParenExpression() { - expect(_parenL); - var val = parseExpression(); - expect(_parenR); - return val; - } - - function parseBlock(allowStrict) { - var node = startNode(), first = true, strict = false, oldStrict; - node.body = []; - expect(_braceL); - while (!eat(_braceR)) { - var stmt = parseStatement(); - node.body.push(stmt); - if (first && allowStrict && isUseStrict(stmt)) { - oldStrict = strict; - setStrict(strict = true); - } - first = false; - } - if (strict && !oldStrict) setStrict(false); - return finishNode(node, "BlockStatement"); - } - - function parseFor(node, init) { - node.init = init; - expect(_semi); - node.test = tokType === _semi ? null : parseExpression(); - expect(_semi); - node.update = tokType === _parenR ? null : parseExpression(); - expect(_parenR); - node.body = parseStatement(); - labels.pop(); - return finishNode(node, "ForStatement"); - } - - function parseForIn(node, init) { - node.left = init; - node.right = parseExpression(); - expect(_parenR); - node.body = parseStatement(); - labels.pop(); - return finishNode(node, "ForInStatement"); - } - - function parseVar(node, noIn) { - node.declarations = []; - node.kind = "var"; - for (;;) { - var decl = startNode(); - decl.id = parseIdent(); - if (strict && isStrictBadIdWord(decl.id.name)) - raise(decl.id.start, "Binding " + decl.id.name + " in strict mode"); - decl.init = eat(_eq) ? parseExpression(true, noIn) : null; - node.declarations.push(finishNode(decl, "VariableDeclarator")); - if (!eat(_comma)) break; - } - return node; - } - - function parseExpression(noComma, noIn) { - var expr = parseMaybeAssign(noIn); - if (!noComma && tokType === _comma) { - var node = startNodeFrom(expr); - node.expressions = [expr]; - while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn)); - return finishNode(node, "SequenceExpression"); - } - return expr; - } - - function parseMaybeAssign(noIn) { - var left = parseMaybeConditional(noIn); - if (tokType.isAssign) { - var node = startNodeFrom(left); - node.operator = tokVal; - node.left = left; - next(); - node.right = parseMaybeAssign(noIn); - checkLVal(left); - return finishNode(node, "AssignmentExpression"); - } - return left; - } - - function parseMaybeConditional(noIn) { - var expr = parseExprOps(noIn); - if (eat(_question)) { - var node = startNodeFrom(expr); - node.test = expr; - node.consequent = parseExpression(true); - expect(_colon); - node.alternate = parseExpression(true, noIn); - return finishNode(node, "ConditionalExpression"); - } - return expr; - } - - function parseExprOps(noIn) { - return parseExprOp(parseMaybeUnary(), -1, noIn); - } - - function parseExprOp(left, minPrec, noIn) { - var prec = tokType.binop; - if (prec != null && (!noIn || tokType !== _in)) { - if (prec > minPrec) { - var node = startNodeFrom(left); - node.left = left; - node.operator = tokVal; - var op = tokType; - next(); - node.right = parseExprOp(parseMaybeUnary(), prec, noIn); - var exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? "LogicalExpression" : "BinaryExpression"); - return parseExprOp(exprNode, minPrec, noIn); - } - } - return left; - } - - function parseMaybeUnary() { - if (tokType.prefix) { - var node = startNode(), update = tokType.isUpdate; - node.operator = tokVal; - node.prefix = true; - tokRegexpAllowed = true; - next(); - node.argument = parseMaybeUnary(); - if (update) checkLVal(node.argument); - else if (strict && node.operator === "delete" && - node.argument.type === "Identifier") - raise(node.start, "Deleting local variable in strict mode"); - return finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); - } - var expr = parseExprSubscripts(); - while (tokType.postfix && !canInsertSemicolon()) { - var node = startNodeFrom(expr); - node.operator = tokVal; - node.prefix = false; - node.argument = expr; - checkLVal(expr); - next(); - expr = finishNode(node, "UpdateExpression"); - } - return expr; - } - - function parseExprSubscripts() { - return parseSubscripts(parseExprAtom()); - } - - function parseSubscripts(base, noCalls) { - if (eat(_dot)) { - var node = startNodeFrom(base); - node.object = base; - node.property = parseIdent(true); - node.computed = false; - return parseSubscripts(finishNode(node, "MemberExpression"), noCalls); - } else if (eat(_bracketL)) { - var node = startNodeFrom(base); - node.object = base; - node.property = parseExpression(); - node.computed = true; - expect(_bracketR); - return parseSubscripts(finishNode(node, "MemberExpression"), noCalls); - } else if (!noCalls && eat(_parenL)) { - var node = startNodeFrom(base); - node.callee = base; - node.arguments = parseExprList(_parenR, false); - return parseSubscripts(finishNode(node, "CallExpression"), noCalls); - } else return base; - } - - function parseExprAtom() { - switch (tokType) { - case _this: - var node = startNode(); - next(); - return finishNode(node, "ThisExpression"); - case _name: - return parseIdent(); - case _num: case _string: case _regexp: - var node = startNode(); - node.value = tokVal; - node.raw = input.slice(tokStart, tokEnd); - next(); - return finishNode(node, "Literal"); - - case _null: case _true: case _false: - var node = startNode(); - node.value = tokType.atomValue; - node.raw = tokType.keyword; - next(); - return finishNode(node, "Literal"); - - case _parenL: - var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart; - next(); - var val = parseExpression(); - val.start = tokStart1; - val.end = tokEnd; - if (options.locations) { - val.loc.start = tokStartLoc1; - val.loc.end = tokEndLoc; - } - if (options.ranges) - val.range = [tokStart1, tokEnd]; - expect(_parenR); - return val; - - case _bracketL: - var node = startNode(); - next(); - node.elements = parseExprList(_bracketR, true, true); - return finishNode(node, "ArrayExpression"); - - case _braceL: - return parseObj(); - - case _function: - var node = startNode(); - next(); - return parseFunction(node, false); - - case _new: - return parseNew(); - - default: - unexpected(); - } - } - - function parseNew() { - var node = startNode(); - next(); - node.callee = parseSubscripts(parseExprAtom(), true); - if (eat(_parenL)) node.arguments = parseExprList(_parenR, false); - else node.arguments = empty; - return finishNode(node, "NewExpression"); - } - - function parseObj() { - var node = startNode(), first = true, sawGetSet = false; - node.properties = []; - next(); - while (!eat(_braceR)) { - if (!first) { - expect(_comma); - if (options.allowTrailingCommas && eat(_braceR)) break; - } else first = false; - - var prop = {key: parsePropertyName()}, isGetSet = false, kind; - if (eat(_colon)) { - prop.value = parseExpression(true); - kind = prop.kind = "init"; - } else if (options.ecmaVersion >= 5 && prop.key.type === "Identifier" && - (prop.key.name === "get" || prop.key.name === "set")) { - isGetSet = sawGetSet = true; - kind = prop.kind = prop.key.name; - prop.key = parsePropertyName(); - if (tokType !== _parenL) unexpected(); - prop.value = parseFunction(startNode(), false); - } else unexpected(); - - if (prop.key.type === "Identifier" && (strict || sawGetSet)) { - for (var i = 0; i < node.properties.length; ++i) { - var other = node.properties[i]; - if (other.key.name === prop.key.name) { - var conflict = kind == other.kind || isGetSet && other.kind === "init" || - kind === "init" && (other.kind === "get" || other.kind === "set"); - if (conflict && !strict && kind === "init" && other.kind === "init") conflict = false; - if (conflict) raise(prop.key.start, "Redefinition of property"); - } - } - } - node.properties.push(prop); - } - return finishNode(node, "ObjectExpression"); - } - - function parsePropertyName() { - if (tokType === _num || tokType === _string) return parseExprAtom(); - return parseIdent(true); - } - - function parseFunction(node, isStatement) { - if (tokType === _name) node.id = parseIdent(); - else if (isStatement) unexpected(); - else node.id = null; - node.params = []; - var first = true; - expect(_parenL); - while (!eat(_parenR)) { - if (!first) expect(_comma); else first = false; - node.params.push(parseIdent()); - } - - var oldInFunc = inFunction, oldLabels = labels; - inFunction = true; labels = []; - node.body = parseBlock(true); - inFunction = oldInFunc; labels = oldLabels; - - if (strict || node.body.body.length && isUseStrict(node.body.body[0])) { - for (var i = node.id ? -1 : 0; i < node.params.length; ++i) { - var id = i < 0 ? node.id : node.params[i]; - if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name)) - raise(id.start, "Defining '" + id.name + "' in strict mode"); - if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name) - raise(id.start, "Argument name clash in strict mode"); - } - } - - return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); - } - - function parseExprList(close, allowTrailingComma, allowEmpty) { - var elts = [], first = true; - while (!eat(close)) { - if (!first) { - expect(_comma); - if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break; - } else first = false; - - if (allowEmpty && tokType === _comma) elts.push(null); - else elts.push(parseExpression(true)); - } - return elts; - } - - function parseIdent(liberal) { - var node = startNode(); - if (liberal && options.forbidReserved == "everywhere") liberal = false; - if (tokType === _name) { - if (!liberal && - (options.forbidReserved && - (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(tokVal) || - strict && isStrictReservedWord(tokVal)) && - input.slice(tokStart, tokEnd).indexOf("\\") == -1) - raise(tokStart, "The keyword '" + tokVal + "' is reserved"); - node.name = tokVal; - } else if (liberal && tokType.keyword) { - node.name = tokType.keyword; - } else { - unexpected(); - } - tokRegexpAllowed = false; - next(); - return finishNode(node, "Identifier"); - } - -}); - - if (!acorn.version) - acorn = null; - } - - function parse(code, options) { - return (global.acorn || acorn).parse(code, options); - } - - var binaryOperators = { - '+': '__add', - '-': '__subtract', - '*': '__multiply', - '/': '__divide', - '%': '__modulo', - '==': '__equals', - '!=': '__equals' - }; - - var unaryOperators = { - '-': '__negate', - '+': '__self' - }; - - var fields = Base.each( - ['add', 'subtract', 'multiply', 'divide', 'modulo', 'equals', 'negate'], - function(name) { - this['__' + name] = '#' + name; - }, - { - __self: function() { - return this; - } - } - ); - Point.inject(fields); - Size.inject(fields); - Color.inject(fields); - - function __$__(left, operator, right) { - var handler = binaryOperators[operator]; - if (left && left[handler]) { - var res = left[handler](right); - return operator === '!=' ? !res : res; - } - switch (operator) { - case '+': return left + right; - case '-': return left - right; - case '*': return left * right; - case '/': return left / right; - case '%': return left % right; - case '==': return left == right; - case '!=': return left != right; - } - } - - function $__(operator, value) { - var handler = unaryOperators[operator]; - if (value && value[handler]) - return value[handler](); - switch (operator) { - case '+': return +value; - case '-': return -value; - } - } - - function compile(code, options) { - if (!code) - return ''; - options = options || {}; - - var insertions = []; - - function getOffset(offset) { - for (var i = 0, l = insertions.length; i < l; i++) { - var insertion = insertions[i]; - if (insertion[0] >= offset) - break; - offset += insertion[1]; - } - return offset; - } - - function getCode(node) { - return code.substring(getOffset(node.range[0]), - getOffset(node.range[1])); - } - - function getBetween(left, right) { - return code.substring(getOffset(left.range[1]), - getOffset(right.range[0])); - } - - function replaceCode(node, str) { - var start = getOffset(node.range[0]), - end = getOffset(node.range[1]), - insert = 0; - for (var i = insertions.length - 1; i >= 0; i--) { - if (start > insertions[i][0]) { - insert = i + 1; - break; - } - } - insertions.splice(insert, 0, [start, str.length - end + start]); - code = code.substring(0, start) + str + code.substring(end); - } - - function walkAST(node, parent) { - if (!node) - return; - for (var key in node) { - if (key === 'range' || key === 'loc') - continue; - var value = node[key]; - if (Array.isArray(value)) { - for (var i = 0, l = value.length; i < l; i++) - walkAST(value[i], node); - } else if (value && typeof value === 'object') { - walkAST(value, node); - } - } - switch (node.type) { - case 'UnaryExpression': - if (node.operator in unaryOperators - && node.argument.type !== 'Literal') { - var arg = getCode(node.argument); - replaceCode(node, '$__("' + node.operator + '", ' - + arg + ')'); - } - break; - case 'BinaryExpression': - if (node.operator in binaryOperators - && node.left.type !== 'Literal') { - var left = getCode(node.left), - right = getCode(node.right), - between = getBetween(node.left, node.right), - operator = node.operator; - replaceCode(node, '__$__(' + left + ',' - + between.replace(new RegExp('\\' + operator), - '"' + operator + '"') - + ', ' + right + ')'); - } - break; - case 'UpdateExpression': - case 'AssignmentExpression': - var parentType = parent && parent.type; - if (!( - parentType === 'ForStatement' - || parentType === 'BinaryExpression' - && /^[=!<>]/.test(parent.operator) - || parentType === 'MemberExpression' && parent.computed - )) { - if (node.type === 'UpdateExpression') { - var arg = getCode(node.argument), - exp = '__$__(' + arg + ', "' + node.operator[0] - + '", 1)', - str = arg + ' = ' + exp; - if (!node.prefix - && (parentType === 'AssignmentExpression' - || parentType === 'VariableDeclarator')) { - if (getCode(parent.left || parent.id) === arg) - str = exp; - str = arg + '; ' + str; - } - replaceCode(node, str); - } else { - if (/^.=$/.test(node.operator) - && node.left.type !== 'Literal') { - var left = getCode(node.left), - right = getCode(node.right), - exp = left + ' = __$__(' + left + ', "' - + node.operator[0] + '", ' + right + ')'; - replaceCode(node, /^\(.*\)$/.test(getCode(node)) - ? '(' + exp + ')' : exp); - } - } - } - break; - case 'ExportDefaultDeclaration': - replaceCode({ - range: [node.start, node.declaration.start] - }, 'module.exports = '); - break; - case 'ExportNamedDeclaration': - var declaration = node.declaration; - var specifiers = node.specifiers; - if (declaration) { - var declarations = declaration.declarations; - if (declarations) { - declarations.forEach(function(dec) { - replaceCode(dec, 'module.exports.' + getCode(dec)); - }); - replaceCode({ - range: [ - node.start, - declaration.start + declaration.kind.length - ] - }, ''); - } - } else if (specifiers) { - var exports = specifiers.map(function(specifier) { - var name = getCode(specifier); - return 'module.exports.' + name + ' = ' + name + '; '; - }).join(''); - if (exports) { - replaceCode(node, exports); - } - } - break; - } - } - - function encodeVLQ(value) { - var res = '', - base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - value = (Math.abs(value) << 1) + (value < 0 ? 1 : 0); - while (value || !res) { - var next = value & (32 - 1); - value >>= 5; - if (value) - next |= 32; - res += base64[next]; - } - return res; - } - - var url = options.url || '', - agent = paper.agent, - version = agent.versionNumber, - offsetCode = false, - sourceMaps = options.sourceMaps, - source = options.source || code, - lineBreaks = /\r\n|\n|\r/mg, - offset = options.offset || 0, - map; - if (sourceMaps && (agent.chrome && version >= 30 - || agent.webkit && version >= 537.76 - || agent.firefox && version >= 23 - || agent.node)) { - if (agent.node) { - offset -= 2; - } else if (window && url && !window.location.href.indexOf(url)) { - var html = document.getElementsByTagName('html')[0].innerHTML; - offset = html.substr(0, html.indexOf(code) + 1).match( - lineBreaks).length + 1; - } - offsetCode = offset > 0 && !( - agent.chrome && version >= 36 || - agent.safari && version >= 600 || - agent.firefox && version >= 40 || - agent.node); - var mappings = ['AA' + encodeVLQ(offsetCode ? 0 : offset) + 'A']; - mappings.length = (code.match(lineBreaks) || []).length + 1 - + (offsetCode ? offset : 0); - map = { - version: 3, - file: url, - names:[], - mappings: mappings.join(';AACA'), - sourceRoot: '', - sources: [url], - sourcesContent: [source] - }; - } - walkAST(parse(code, { - ranges: true, - preserveParens: true, - sourceType: 'module' - })); - if (map) { - if (offsetCode) { - code = new Array(offset + 1).join('\n') + code; - } - if (/^(inline|both)$/.test(sourceMaps)) { - code += "\n//# sourceMappingURL=data:application/json;base64," - + self.btoa(unescape(encodeURIComponent( - JSON.stringify(map)))); - } - code += "\n//# sourceURL=" + (url || 'paperscript'); - } - return { - url: url, - source: source, - code: code, - map: map - }; - } - - function execute(code, scope, options) { - paper = scope; - var view = scope.getView(), - tool = /\btool\.\w+|\s+on(?:Key|Mouse)(?:Up|Down|Move|Drag)\b/ - .test(code) && !/\bnew\s+Tool\b/.test(code) - ? new Tool() : null, - toolHandlers = tool ? tool._events : [], - handlers = ['onFrame', 'onResize'].concat(toolHandlers), - params = [], - args = [], - func, - compiled = typeof code === 'object' ? code : compile(code, options); - code = compiled.code; - function expose(scope, hidden) { - for (var key in scope) { - if ((hidden || !/^_/.test(key)) && new RegExp('([\\b\\s\\W]|^)' - + key.replace(/\$/g, '\\$') + '\\b').test(code)) { - params.push(key); - args.push(scope[key]); - } - } - } - expose({ __$__: __$__, $__: $__, paper: scope, view: view, tool: tool }, - true); - expose(scope); - code = 'var module = { exports: {} }; ' + code; - var exports = Base.each(handlers, function(key) { - if (new RegExp('\\s+' + key + '\\b').test(code)) { - params.push(key); - this.push('module.exports.' + key + ' = ' + key + ';'); - } - }, []).join('\n'); - if (exports) { - code += '\n' + exports; - } - code += '\nreturn module.exports;'; - var agent = paper.agent; - if (document && (agent.chrome - || agent.firefox && agent.versionNumber < 40)) { - var script = document.createElement('script'), - head = document.head || document.getElementsByTagName('head')[0]; - if (agent.firefox) - code = '\n' + code; - script.appendChild(document.createTextNode( - 'document.__paperscript__ = function(' + params + ') {' + - code + - '\n}' - )); - head.appendChild(script); - func = document.__paperscript__; - delete document.__paperscript__; - head.removeChild(script); - } else { - func = Function(params, code); - } - var exports = func && func.apply(scope, args); - var obj = exports || {}; - Base.each(toolHandlers, function(key) { - var value = obj[key]; - if (value) - tool[key] = value; - }); - if (view) { - if (obj.onResize) - view.setOnResize(obj.onResize); - view.emit('resize', { - size: view.size, - delta: new Point() - }); - if (obj.onFrame) - view.setOnFrame(obj.onFrame); - view.requestUpdate(); - } - return exports; - } - - function loadScript(script) { - if (/^text\/(?:x-|)paperscript$/.test(script.type) - && PaperScope.getAttribute(script, 'ignore') !== 'true') { - var canvasId = PaperScope.getAttribute(script, 'canvas'), - canvas = document.getElementById(canvasId), - src = script.src || script.getAttribute('data-src'), - async = PaperScope.hasAttribute(script, 'async'), - scopeAttribute = 'data-paper-scope'; - if (!canvas) - throw new Error('Unable to find canvas with id "' - + canvasId + '"'); - var scope = PaperScope.get(canvas.getAttribute(scopeAttribute)) - || new PaperScope().setup(canvas); - canvas.setAttribute(scopeAttribute, scope._id); - if (src) { - Http.request({ - url: src, - async: async, - mimeType: 'text/plain', - onLoad: function(code) { - execute(code, scope, src); - } - }); - } else { - execute(script.innerHTML, scope, script.baseURI); - } - script.setAttribute('data-paper-ignore', 'true'); - return scope; - } - } - - function loadAll() { - Base.each(document && document.getElementsByTagName('script'), - loadScript); - } - - function load(script) { - return script ? loadScript(script) : loadAll(); - } - - if (window) { - if (document.readyState === 'complete') { - setTimeout(loadAll); - } else { - DomEvent.add(window, { load: loadAll }); - } - } - - return { - compile: compile, - execute: execute, - load: load, - parse: parse - }; - -}.call(this); - -var paper = new (PaperScope.inject(Base.exports, { - Base: Base, - Numerical: Numerical, - Key: Key, - DomEvent: DomEvent, - DomElement: DomElement, - document: document, - window: window, - Symbol: SymbolDefinition, - PlacedSymbol: SymbolItem -}))(); - -if (paper.agent.node) { - require('./node/extend.js')(paper); -} - -if (typeof define === 'function' && define.amd) { - define('paper', paper); -} else if (typeof module === 'object' && module) { - module.exports = paper; -} - -return paper; -}.call(this, typeof self === 'object' ? self : null); - -/* - * base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ -var Base64ArrayBuffer = (function () { - "use strict"; - - var base64ArrayBuffer = { }; - - var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - // Use a lookup table to find the index. - var lookup = new Uint8Array(256); - for (var i = 0; i < chars.length; i++) { - lookup[chars.charCodeAt(i)] = i; - } - - base64ArrayBuffer.encode = function(arraybuffer) { - var bytes = new Uint8Array(arraybuffer), - i, len = bytes.length, base64 = ""; - - for (i = 0; i < len; i+=3) { - base64 += chars[bytes[i] >> 2]; - base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64 += chars[bytes[i + 2] & 63]; - } - - if ((len % 3) === 2) { - base64 = base64.substring(0, base64.length - 1) + "="; - } else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + "=="; - } - - return base64; - }; - - base64ArrayBuffer.decode = function(base64) { - var bufferLength = base64.length * 0.75, - len = base64.length, i, p = 0, - encoded1, encoded2, encoded3, encoded4; - - if (base64[base64.length - 1] === "=") { - bufferLength--; - if (base64[base64.length - 2] === "=") { - bufferLength--; - } - } - - var arraybuffer = new ArrayBuffer(bufferLength), - bytes = new Uint8Array(arraybuffer); - - for (i = 0; i < len; i+=4) { - encoded1 = lookup[base64.charCodeAt(i)]; - encoded2 = lookup[base64.charCodeAt(i+1)]; - encoded3 = lookup[base64.charCodeAt(i+2)]; - encoded4 = lookup[base64.charCodeAt(i+3)]; - - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - - return arraybuffer; - }; - - return base64ArrayBuffer; - -})(); - -// https://stackoverflow.com/questions/14224535/scaling-between-two-number-ranges -function convertRange( value, r1, r2 ) { - return ( value - r1[ 0 ] ) * ( r2[ 1 ] - r2[ 0 ] ) / ( r1[ 1 ] - r1[ 0 ] ) + r2[ 0 ]; -} -/* croquis.js */ -/* https://github.com/disjukr/croquis.js/tree/master */ - -function Croquis(imageDataList, properties) { - var self = this; - if (properties != null) - for (var property in properties) - self[property] = properties[property]; - var domElement = document.createElement('div'); - domElement.style.clear = 'both'; - domElement.style.setProperty('user-select', 'none'); - domElement.style.setProperty('-webkit-user-select', 'none'); - domElement.style.setProperty('-ms-user-select', 'none'); - domElement.style.setProperty('-moz-user-select', 'none'); - self.getDOMElement = function () { - return domElement; - }; - self.getRelativePosition = function (absoluteX, absoluteY) { - var rect = domElement.getBoundingClientRect(); - return {x: absoluteX - rect.left,y: absoluteY - rect.top}; - }; - var eventListeners = { - 'ondown': [], - 'onmove': [], - 'onup': [], - 'ontick': [], - 'onchange': [], - 'onundo': [], - 'onredo': [], - 'ontool': [], - 'oncanvassize': [], - 'onlayeradd': [], - 'onlayerremove': [], - 'onlayerswap': [], - 'onlayerselect': [] - }; - function dispatchEvent(event, e) { - event = event.toLowerCase(); - e = e || {}; - if (eventListeners.hasOwnProperty(event)) { - eventListeners[event].forEach(function (listener) { - listener.call(self, e); - }); - } - else throw 'don\'t support ' + event; - } - self.addEventListener = function (event, listener) { - event = event.toLowerCase(); - if (eventListeners.hasOwnProperty(event)) { - if (typeof listener !== 'function') - throw listener + ' is not a function'; - eventListeners[event].push(listener); - } - else throw 'don\'t support ' + event; - }; - self.removeEventListener = function (event, listener) { - event = event.toLowerCase(); - if (eventListeners.hasOwnProperty(event)) { - if (listener == null) { // remove all - eventListeners[event] = []; - return; - } - var listeners = eventListeners[event]; - var index = listeners.indexOf(listener); - if (index >= 0) listeners.splice(index, 1); - } - else throw 'don\'t support ' + event; - }; - self.hasEventListener = function (event, listener) { - event = event.toLowerCase(); - if (eventListeners.hasOwnProperty(event)) { - if (listener == null) - return eventListeners[event].length > 0; - return eventListeners[event].indexOf(listener) >= 0; - } - else return false; - }; - var undoStack = []; - var redoStack = []; - var undoLimit = 10; - var preventPushUndo = false; - var pushToTransaction = false; - self.getUndoLimit = function () { - return undoLimit; - }; - self.setUndoLimit = function (limit) { - undoLimit = limit; - }; - self.lockHistory = function () { - preventPushUndo = true; - }; - self.unlockHistory = function () { - preventPushUndo = false; - }; - self.beginHistoryTransaction = function () { - undoStack.push([]); - pushToTransaction = true; - }; - self.endHistoryTransaction = function () { - pushToTransaction = false; - }; - self.clearHistory = function () { - if (preventPushUndo) - throw 'history is locked'; - undoStack = []; - redoStack = []; - }; - function pushUndo(undoFunction) { - dispatchEvent('onchange'); - if (self.onChanged) - self.onChanged(); - if (preventPushUndo) - return; - redoStack = []; - if (pushToTransaction) - undoStack[undoStack.length - 1].push(undoFunction); - else - undoStack.push([undoFunction]); - while (undoStack.length > undoLimit) - undoStack.shift(); - } - self.undo = function () { - if (pushToTransaction) - throw 'transaction is not ended'; - if (preventPushUndo) - throw 'history is locked'; - if (isDrawing || isStabilizing) - throw 'still drawing'; - if (undoStack.length == 0) - throw 'no more undo data'; - var undoTransaction = undoStack.pop(); - var redoTransaction = []; - while (undoTransaction.length) - redoTransaction.push(undoTransaction.pop()()); - redoStack.push(redoTransaction); - dispatchEvent('onundo'); - }; - self.redo = function () { - if (pushToTransaction) - throw 'transaction is not ended'; - if (preventPushUndo) - throw 'history is locked'; - if (isDrawing || isStabilizing) - throw 'still drawing'; - if (redoStack.length == 0) - throw 'no more redo data'; - var redoTransaction = redoStack.pop(); - var undoTransaction = []; - while (redoTransaction.length) - undoTransaction.push(redoTransaction.pop()()); - undoStack.push(undoTransaction); - dispatchEvent('onredo'); - }; - function pushLayerMetadataUndo(index) { - index = index || layerIndex; - var snapshotMetadata = self.getLayerMetadata(index); - var swap = function () { - self.lockHistory(); - var temp = self.getLayerMetadata(index); - self.setLayerMetadata(snapshotMetadata, index); - snapshotMetadata = temp; - self.unlockHistory(); - return swap; - }; - pushUndo(swap); - } - function pushLayerOpacityUndo(index) { - index = index || layerIndex; - var snapshotOpacity = self.getLayerOpacity(index); - var swap = function () { - self.lockHistory(); - var temp = self.getLayerOpacity(index); - self.setLayerOpacity(snapshotOpacity, index); - snapshotOpacity = temp; - self.unlockHistory(); - return swap; - }; - pushUndo(swap); - } - function pushLayerVisibleUndo(index) { - index = index || layerIndex; - var snapshotVisible = self.getLayerVisible(index); - var swap = function () { - self.lockHistory(); - var temp = self.getLayerVisible(index); - self.setLayerVisible(snapshotVisible, index); - snapshotVisible = temp; - self.unlockHistory(); - return swap; - }; - pushUndo(swap); - } - function pushSwapLayerUndo(layerA, layerB) { - var swap = function () { - self.lockHistory(); - self.swapLayer(layerA, layerB); - self.unlockHistory(); - return swap; - }; - pushUndo(swap); - } - function pushAddLayerUndo(index) { - var add = function () { - self.lockHistory(); - self.addLayer(index); - self.unlockHistory(); - cacheLayer(index); - return remove; - }; - var remove = function () { - self.lockHistory(); - self.removeLayer(index); - self.unlockHistory(); - return add; - }; - pushUndo(remove); - } - function pushRemoveLayerUndo(index) { - var layerContext = getLayerContext(index); - var w = size.width; - var h = size.height; - var snapshotData = layerContext.getImageData(0, 0, w, h); - var snapshotMetadata = self.getLayerMetadata(index); - var snapshotOpacity = self.getLayerOpacity(index); - var snapshotVisible = self.getLayerVisible(index); - var add = function () { - self.lockHistory(); - self.addLayer(index); - self.setLayerMetadata(snapshotMetadata, index); - self.setLayerOpacity(snapshotOpacity, index); - self.setLayerVisible(snapshotVisible, index); - var layerContext = getLayerContext(index); - layerContext.putImageData(snapshotData, 0, 0); - self.unlockHistory(); - cacheLayer(index); - return remove; - }; - var remove = function () { - self.lockHistory(); - self.removeLayer(index); - self.unlockHistory(); - return add; - }; - pushUndo(add); - } - function pushDirtyRectUndo(x, y, width, height, index) { - index = index || layerIndex; - var w = size.width; - var h = size.height; - var right = x + width; - var bottom = y + height; - x = Math.min(w, Math.max(0, x)); - y = Math.min(h, Math.max(0, y)); - width = Math.min(w, Math.max(x, right)) - x; - height = Math.min(h, Math.max(y, bottom)) - y; - if ((x % 1) > 0) - ++width; - if ((y % 1) > 0) - ++height; - x = x | 0; - y = y | 0; - width = Math.min(w - x, Math.ceil(width)); - height = Math.min(h - y, Math.ceil(height)); - if ((width === 0) || (height === 0)) { - var doNothing = function () { - return doNothing; - }; - pushUndo(doNothing); - } - else { - var layerContext = getLayerContext(index); - var snapshotData = layerContext.getImageData(x, y, width, height); - var swap = function () { - var layerContext = getLayerContext(index); - var tempData = layerContext.getImageData(x, y, width, height); - layerContext.putImageData(snapshotData, x, y); - snapshotData = tempData; - cacheLayer(index); - return swap; - }; - pushUndo(swap); - } - if (renderDirtyRect) - drawDirtyRect(x, y, width, height); - } - function pushContextUndo(index) { - index = index || layerIndex; - pushDirtyRectUndo(0, 0, size.width, size.height, index); - } - function pushAllContextUndo() { - var snapshotDatas = []; - var i; - var w = size.width; - var h = size.height; - for (i = 0; i < layers.length; ++i) { - var layerContext = getLayerContext(i); - snapshotDatas.push(layerContext.getImageData(0, 0, w, h)); - } - var swap = function (index) { - var layerContext = getLayerContext(index); - var tempData = layerContext.getImageData(0, 0, w, h); - layerContext.putImageData(snapshotDatas[index], 0, 0); - snapshotDatas[index] = tempData; - cacheLayer(index); - }; - var swapAll = function () { - for (var i = 0; i < layers.length; ++i) - swap(i); - return swapAll; - }; - pushUndo(swapAll); - } - function pushCanvasSizeUndo(width, height, offsetX, offsetY) { - var snapshotSize = self.getCanvasSize(); - var snapshotDatas = []; - var w = snapshotSize.width; - var h = snapshotSize.height; - for (var i = 0; i < layers.length; ++i) { - var layerContext = getLayerContext(i); - snapshotDatas[i] = layerContext.getImageData(0, 0, w, h); - } - function setSize(width, height, offsetX, offsetY) { - self.lockHistory(); - self.setCanvasSize(width, height, offsetX, offsetY); - self.unlockHistory(); - } - var rollback = function () { - setSize(w, h); - for (var i = 0; i < layers.length; ++i) { - var layerContext = getLayerContext(i); - layerContext.putImageData(snapshotDatas[i], 0, 0); - } - return redo; - }; - var redo = function () { - rollback(); - setSize(width, height, offsetX, offsetY); - return rollback; - }; - pushUndo(rollback); - } - var size = {width: 640, height: 480}; - self.getCanvasSize = function () { - return {width: size.width, height: size.height}; //clone size - }; - self.setCanvasSize = function (width, height, offsetX, offsetY) { - offsetX = offsetX || 0; - offsetY = offsetY || 0; - size.width = width = Math.floor(width); - size.height = height = Math.floor(height); - pushCanvasSizeUndo(width, height, offsetX, offsetY); - dispatchEvent('oncanvassize', { - width: width, height: height, - offsetX: offsetX, offsetY: offsetY - }); - paintingCanvas.width = width; - paintingCanvas.height = height; - dirtyRectDisplay.width = width; - dirtyRectDisplay.height = height; - domElement.style.width = width + 'px'; - domElement.style.height = height + 'px'; - for (var i=0; i 2) && (h > 2)) { - context.globalCompositeOperation = 'destination-out'; - context.fillRect(x + 1, y + 1, w - 2, h - 2); - } - } - self.getRenderDirtyRect = function () { - return renderDirtyRect; - }; - self.setRenderDirtyRect = function (render) { - renderDirtyRect = render; - if (render == false) - dirtyRectDisplayContext.clearRect(0, 0, size.width, size.height); - }; - self.createLayerThumbnail = function (index, width, height) { - index = index || layerIndex; - width = width || size.width; - height = height || size.height; - var canvas = getLayerCanvas(index); - var thumbnail = document.createElement('canvas'); - var thumbnailContext = thumbnail.getContext('2d'); - thumbnail.width = width; - thumbnail.height = height; - thumbnailContext.drawImage(canvas, 0, 0, width, height); - return thumbnail; - }; - self.createFlattenThumbnail = function (width, height) { - width = width || size.width; - height = height || size.height; - var thumbnail = document.createElement('canvas'); - var thumbnailContext = thumbnail.getContext('2d'); - thumbnail.width = width; - thumbnail.height = height; - for (var i = 0; i < layers.length; ++i) { - if (!self.getLayerVisible(i)) - continue; - var canvas = getLayerCanvas(i); - thumbnailContext.globalAlpha = self.getLayerOpacity(i); - thumbnailContext.drawImage(canvas, 0, 0, width, height); - } - return thumbnail; - }; - self.getLayers = function () { - return layers.concat(); //clone layers - }; - self.getLayerCount = function () { - return layers.length; - }; - self.addLayer = function (index) { - index = index || layers.length; - pushAddLayerUndo(index); - var layer = document.createElement('div'); - layer.className = 'croquis-layer'; - layer.style.visibility = 'visible'; - layer.style.opacity = 1; - layer['croquis-metadata'] = {}; - var canvas = document.createElement('canvas'); - canvas.className = 'croquis-layer-canvas'; - canvas.width = size.width; - canvas.height = size.height; - canvas.style.position = 'absolute'; - layer.appendChild(canvas); - domElement.appendChild(layer); - layers.splice(index, 0, layer); - sortLayers(); - self.selectLayer(layerIndex); - dispatchEvent('onlayeradd', {index: index}); - if (self.onLayerAdded) - self.onLayerAdded(index); - return layer; - }; - self.removeLayer = function (index) { - index = index || layerIndex; - pushRemoveLayerUndo(index); - domElement.removeChild(layers[index]); - layers.splice(index, 1); - if (layerIndex == layers.length) - self.selectLayer(layerIndex - 1); - sortLayers(); - dispatchEvent('onlayerremove', {index: index}); - if (self.onLayerRemoved) - self.onLayerRemoved(index); - }; - self.removeAllLayer = function () { - while (layers.length) - self.removeLayer(0); - }; - self.swapLayer = function (layerA, layerB) { - pushSwapLayerUndo(layerA, layerB); - var layer = layers[layerA]; - layers[layerA] = layers[layerB]; - layers[layerB] = layer; - sortLayers(); - dispatchEvent('onlayerswap', {a: layerA, b: layerB}); - if (self.onLayerSwapped) - self.onLayerSwapped(layerA, layerB); - }; - self.getCurrentLayerIndex = function () { - return layerIndex; - }; - self.selectLayer = function (index) { - var lastestLayerIndex = layers.length - 1; - if (index > lastestLayerIndex) - index = lastestLayerIndex; - layerIndex = index; - if (paintingCanvas.parentElement != null) - paintingCanvas.parentElement.removeChild(paintingCanvas); - layers[index].appendChild(paintingCanvas); - dispatchEvent('onlayerselect', {index: index}); - if (self.onLayerSelected) - self.onLayerSelected(index); - }; - self.clearLayer = function (index) { - index = index || layerIndex; - pushContextUndo(index); - var context = getLayerContext(index); - context.clearRect(0, 0, size.width, size.height); - cacheLayer(index); - }; - self.fillLayer = function (fillColor, index) { - index = index || layerIndex; - pushContextUndo(index); - var context = getLayerContext(index); - context.fillStyle = fillColor; - context.fillRect(0, 0, size.width, size.height); - cacheLayer(index); - }; - self.fillLayerRect = function (fillColor, x, y, width, height, index) { - index = index || layerIndex; - pushDirtyRectUndo(x, y, width, height, index); - var context = getLayerContext(index); - context.fillStyle = fillColor; - context.fillRect(x, y, width, height); - cacheLayer(index); - }; - self.floodFill = function (x, y, r, g, b, a, index) { - index = index || layerIndex; - pushContextUndo(index); - var context = getLayerContext(index); - var w = size.width; - var h = size.height; - if ((x < 0) || (x >= w) || (y < 0) || (y >= h)) - return; - var imageData = context.getImageData(0, 0, w, h); - var d = imageData.data; - var targetColor = getColor(x, y); - var replacementColor = (r << 24) | (g << 16) | (b << 8) | a; - if (targetColor === replacementColor) - return; - function getColor(x, y) { - var index = ((y * w) + x) * 4; - return ((d[index] << 24) | (d[index + 1] << 16) | - (d[index + 2] << 8) | d[index + 3]); - } - function setColor(x, y) { - var index = ((y * w) + x) * 4; - d[index] = r; - d[index + 1] = g; - d[index + 2] = b; - d[index + 3] = a; - } - var queue = []; - queue.push(x, y); - while (queue.length) { - var nx = queue.shift(); - var ny = queue.shift(); - if ((nx < 0) || (nx >= w) || (ny < 0) || (ny >= h) || - (getColor(nx, ny) !== targetColor)) - continue; - var west, east; - west = east = nx; - do { - var wc = getColor(--west, ny); - } while ((west >= 0) && (wc === targetColor)); - do { - var ec = getColor(++east, ny); - } while ((east < w) && (ec === targetColor)); - for (var i = west + 1; i < east; ++i) { - setColor(i, ny); - var north = ny - 1; - var south = ny + 1; - if (getColor(i, north) === targetColor) - queue.push(i, north); - if (getColor(i, south) === targetColor) - queue.push(i, south); - } - } - context.putImageData(imageData, 0, 0); - cacheLayer(index); - }; - self.getLayerMetadata = function (index) { - index = index || layerIndex; - var metadata = layers[index]['croquis-metadata']; - var clone = {}; - Object.keys(metadata).forEach(function (key) { - clone[key] = metadata[key]; - }); - return clone; - }; - self.setLayerMetadata = function (metadata, index) { - index = index || layerIndex; - pushLayerMetadataUndo(index); - layers[index]['croquis-metadata'] = metadata; - }; - self.getLayerOpacity = function (index) { - index = index || layerIndex; - var opacity = parseFloat( - layers[index].style.getPropertyValue('opacity')); - return window.isNaN(opacity) ? 1 : opacity; - }; - self.setLayerOpacity = function (opacity, index) { - index = index || layerIndex; - pushLayerOpacityUndo(index); - layers[index].style.opacity = opacity; - }; - self.getLayerVisible = function (index) { - index = index || layerIndex; - var visible = layers[index].style.getPropertyValue('visibility'); - return visible != 'hidden'; - }; - self.setLayerVisible = function (visible, index) { - index = index || layerIndex; - pushLayerVisibleUndo(index); - layers[index].style.visibility = visible ? 'visible' : 'hidden'; - }; - function cacheLayer(index) { - index = index || layerIndex; - var w = size.width; - var h = size.height; - layers[index].cache = getLayerContext(index).getImageData(0, 0, w, h); - } - self.getLayerImageDataCache = function (index) { - index = index || layerIndex; - if (layers[index].cache == null) - cacheLayer(index); - return layers[index].cache; - }; - function makeColorData(imageData1x1) { - var data = imageData1x1.data; - var r = data[0]; - var g = data[1]; - var b = data[2]; - var a = data[3]; - return { - r: r, g: g, b: b, a: a, - htmlColor: 'rgba(' + [r, g, b, a / 0xff].join(',') + ')' - }; - } - self.pickColor = function (x, y, index) { - x = x | 0; // cast to int - y = y | 0; - if ((x < 0) || (x >= size.width) || (y < 0) || (y >= size.height)) - return null; - index = index || layerIndex; - var cache = self.getLayerImageDataCache(index); - var position = (y * size.width + x) * 4; - var data = []; - data[0] = cache.data[position]; - data[1] = cache.data[++position]; - data[2] = cache.data[++position]; - data[3] = cache.data[++position]; - return makeColorData({data: data}); - }; - self.eyeDrop = function (x, y, baseColor) { - if (self.pickColor(x, y) == null) - return null; - baseColor = baseColor || '#fff'; - var plane = document.createElement('canvas'); - plane.width = 1; - plane.height = 1; - var planeContext = plane.getContext('2d'); - planeContext.fillStyle = baseColor; - planeContext.fillRect(0, 0, 1, 1); - for (var i = 0; i < layers.length; ++i) { - if (!self.getLayerVisible(i)) - continue; - planeContext.globalAlpha = self.getLayerOpacity(i); - planeContext.fillStyle = self.pickColor(x, y, i).htmlColor; - planeContext.fillRect(0, 0, 1, 1); - } - return makeColorData(planeContext.getImageData(0, 0, 1, 1)); - }; - var tool; - var toolStabilizeLevel = 0; - var toolStabilizeWeight = 0.8; - var stabilizer = null; - var stabilizerInterval = 5; - var tick; - var tickInterval = 20; - var paintingOpacity = 1; - var paintingKnockout = false; - self.getTool = function () { - return tool; - }; - self.setTool = function (value) { - tool = value; - dispatchEvent('ontool', {tool: value}); - paintingContext = paintingCanvas.getContext('2d'); - if (tool && tool.setContext) - tool.setContext(paintingContext); - }; - self.setTool(new Croquis.Brush()); - self.getPaintingOpacity = function () { - return paintingOpacity; - }; - self.setPaintingOpacity = function (opacity) { - paintingOpacity = opacity; - paintingCanvas.style.opacity = opacity; - }; - self.getPaintingKnockout = function () { - return paintingKnockout; - }; - self.setPaintingKnockout = function (knockout) { - if (isDrawing || isStabilizing) - throw 'still drawing'; - paintingKnockout = knockout; - paintingCanvas.style.visibility = knockout ? 'hidden' : 'visible'; - }; - self.getTickInterval = function () { - return tickInterval; - }; - self.setTickInterval = function (interval) { - tickInterval = interval; - }; - /* - stabilize level is the number of coordinate tracker. - higher stabilize level makes lines smoother. - */ - self.getToolStabilizeLevel = function () { - return toolStabilizeLevel; - }; - self.setToolStabilizeLevel = function (level) { - toolStabilizeLevel = (level < 0) ? 0 : level; - }; - /* - higher stabilize weight makes trackers follow slower. - */ - self.getToolStabilizeWeight = function () { - return toolStabilizeWeight; - }; - self.setToolStabilizeWeight = function (weight) { - toolStabilizeWeight = weight; - }; - self.getToolStabilizeInterval = function () { - return stabilizerInterval; - }; - self.setToolStabilizeInterval = function (interval) { - stabilizerInterval = interval; - }; - var isDrawing = false; - var isStabilizing = false; - var beforeKnockout = document.createElement('canvas'); - var knockoutTick; - var knockoutTickInterval = 20; - function gotoBeforeKnockout() { - var context = getLayerContext(layerIndex); - var w = size.width; - var h = size.height; - context.clearRect(0, 0, w, h); - context.drawImage(beforeKnockout, 0, 0, w, h); - } - function drawPaintingCanvas() { //draw painting canvas on current layer - var context = getLayerContext(layerIndex); - var w = size.width; - var h = size.height; - context.save(); - context.globalAlpha = paintingOpacity; - context.globalCompositeOperation = paintingKnockout ? - 'destination-out' : 'source-over'; - context.drawImage(paintingCanvas, 0, 0, w, h); - context.restore(); - } - function _move(x, y, pressure) { - if (tool.move) - tool.move(x, y, pressure); - dispatchEvent('onmove', {x: x, y: y, pressure: pressure}); - if (self.onMoved) - self.onMoved(x, y, pressure); - } - function _up(x, y, pressure) { - isDrawing = false; - isStabilizing = false; - var dirtyRect; - if (tool.up) - dirtyRect = tool.up(x, y, pressure); - if (paintingKnockout) - gotoBeforeKnockout(); - if (dirtyRect) - pushDirtyRectUndo(dirtyRect.x, dirtyRect.y, - dirtyRect.width, dirtyRect.height); - else - pushContextUndo(); - drawPaintingCanvas(); - paintingContext.clearRect(0, 0, size.width, size.height); - dirtyRect = dirtyRect || - {x: 0, y: 0, width: size.width, height: size.height}; - dispatchEvent('onup', - {x: x, y: y, pressure: pressure, dirtyRect: dirtyRect}); - if (self.onUpped) - self.onUpped(x, y, pressure, dirtyRect); - window.clearInterval(knockoutTick); - window.clearInterval(tick); - cacheLayer(self.getCurrentLayerIndex()); - } - self.down = function (x, y, pressure) { - if (isDrawing || isStabilizing) - throw 'still drawing'; - isDrawing = true; - if (tool == null) - return; - if (paintingKnockout) { - var w = size.width; - var h = size.height; - var canvas = getLayerCanvas(layerIndex); - var beforeKnockoutContext = beforeKnockout.getContext('2d'); - beforeKnockout.width = w; - beforeKnockout.height = h; - beforeKnockoutContext.clearRect(0, 0, w, h); - beforeKnockoutContext.drawImage(canvas, 0, 0, w, h); - } - pressure = pressure || Croquis.Tablet.pressure(); - var down = tool.down; - if (toolStabilizeLevel > 0) { - stabilizer = new Croquis.Stabilizer(down, _move, _up, - toolStabilizeLevel, toolStabilizeWeight, - x, y, pressure, stabilizerInterval); - isStabilizing = true; - } - else if (down != null) - down(x, y, pressure); - dispatchEvent('ondown', {x: x, y: y, pressure: pressure}); - if (self.onDowned) - self.onDowned(x, y, pressure); - knockoutTick = window.setInterval(function () { - if (paintingKnockout) { - gotoBeforeKnockout(); - drawPaintingCanvas(); - } - }, knockoutTickInterval); - tick = window.setInterval(function () { - if (tool.tick) - tool.tick(); - dispatchEvent('ontick'); - if (self.onTicked) - self.onTicked(); - }, tickInterval); - }; - self.move = function (x, y, pressure) { - if (!isDrawing) - throw 'you need to call \'down\' first'; - if (tool == null) - return; - pressure = pressure || Croquis.Tablet.pressure(); - if (stabilizer != null) - stabilizer.move(x, y, pressure); - else if (!isStabilizing) - _move(x, y, pressure); - }; - self.up = function (x, y, pressure) { - if (!isDrawing) - throw 'you need to call \'down\' first'; - if (tool == null) { - isDrawing = false; - return; - } - pressure = pressure || Croquis.Tablet.pressure(); - if (stabilizer != null) - stabilizer.up(x, y, pressure); - else - _up(x, y, pressure); - stabilizer = null; - }; - // apply image data - ;(function (croquis, imageDataList) { - if (imageDataList != null) { - if (imageDataList.length === 0) - return; - croquis.lockHistory(); - var first = imageDataList[0]; - croquis.setCanvasSize(first.width, first.height); - for (var i = 0; i < imageDataList.length; ++i) { - var current = imageDataList[i]; - if ((current.width != first.width) || - (current.height != first.height)) - throw 'all image data must have same size'; - croquis.addLayer(); - var context = croquis.getLayerCanvas(i).getContext('2d'); - context.putImageData(current, 0, 0); - } - croquis.selectLayer(0); - croquis.unlockHistory(); - } - }).call(null, self, imageDataList); -} -Croquis.createChecker = function (cellSize, colorA, colorB) { - cellSize = cellSize || 10; - colorA = colorA || '#fff'; - colorB = colorB || '#ccc'; - var size = cellSize + cellSize; - var checker = document.createElement('canvas'); - checker.width = checker.height = size; - var context = checker.getContext('2d'); - context.fillStyle = colorB; - context.fillRect(0, 0, size, size); - context.fillStyle = colorA; - context.fillRect(0, 0, cellSize, cellSize); - context.fillRect(cellSize, cellSize, size, size); - return checker; -}; -Croquis.createBrushPointer = function (brushImage, brushSize, brushAngle, - threshold, antialias, color, - shadow, shadowOffsetX, shadowOffsetY) { - brushSize = brushSize | 0; - var pointer = document.createElement('canvas'); - var pointerContext = pointer.getContext('2d'); - var boundWidth; - var boundHeight; - if (brushSize === 0) { - pointer.width = boundWidth = 1; - pointer.height = boundHeight = 1; - } - if (brushImage == null) { - var halfSize = (brushSize * 0.5) | 0; - pointer.width = boundWidth = brushSize; - pointer.height = boundHeight = brushSize; - pointerContext.fillStyle = '#000'; - pointerContext.beginPath(); - pointerContext.arc(halfSize, halfSize, halfSize, 0, Math.PI * 2); - pointerContext.closePath(); - pointerContext.fill(); - } - else { - var width = brushSize; - var height = brushSize * (brushImage.height / brushImage.width); - var toRad = Math.PI / 180; - var ra = brushAngle * toRad; - var abs = Math.abs; - var sin = Math.sin; - var cos = Math.cos; - boundWidth = abs(height * sin(ra)) + abs(width * cos(ra)); - boundHeight = abs(width * sin(ra)) + abs(height * cos(ra)); - pointer.width = boundWidth; - pointer.height = boundHeight; - pointerContext.save(); - pointerContext.translate(boundWidth * 0.5, boundHeight * 0.5); - pointerContext.rotate(ra); - pointerContext.translate(width * -0.5, height * -0.5); - pointerContext.drawImage(brushImage, 0, 0, width, height); - pointerContext.restore(); - } - var result; - var alphaThresholdBorder = Croquis.createAlphaThresholdBorder( - pointer, threshold, antialias, color); - if (shadow) { - shadowOffsetX = shadowOffsetX || 1; - shadowOffsetY = shadowOffsetY || 1; - result = document.createElement('canvas'); - result.width = boundWidth + shadowOffsetX; - result.height = boundHeight + shadowOffsetY; - var resultContext = result.getContext('2d'); - resultContext.shadowOffsetX = shadowOffsetX; - resultContext.shadowOffsetY = shadowOffsetY; - resultContext.shadowColor = shadow; - resultContext.drawImage( - alphaThresholdBorder, 0, 0, boundWidth, boundHeight); - } - else { - result = alphaThresholdBorder; - } - return result; -}; -Croquis.createAlphaThresholdBorder = function (image, threshold, - antialias, color) { - threshold = threshold || 0x80; - color = color || '#000'; - var width = image.width; - var height = image.height; - var canvas = document.createElement('canvas'); - var context = canvas.getContext('2d'); - canvas.width = width; - canvas.height = height; - try { - context.drawImage(image, 0, 0, width, height); - } - catch (e) { - return canvas; - } - var imageData = context.getImageData(0, 0, width, height); - var d = imageData.data; - function getAlphaIndex(index) { - return d[index * 4 + 3]; - } - function setRedIndex(index, red) { - d[index * 4] = red; - } - function getRedXY(x, y) { - var red = d[((y * width) + x) * 4]; - return red || 0; - } - function getGreenXY(x, y) { - var green = d[((y * width) + x) * 4 + 1]; - return green; - } - function setColorXY(x, y, red, green, alpha) { - var i = ((y * width) + x) * 4; - d[i] = red; - d[i + 1] = green; - d[i + 2] = 0; - d[i + 3] = alpha; - } - //threshold - var pixelCount = (d.length * 0.25) | 0; - for (var i = 0; i < pixelCount; ++i) - setRedIndex(i, (getAlphaIndex(i) < threshold) ? 0 : 1); - //outline - var x; - var y; - for (x = 0; x < width; ++x) { - for (y = 0; y < height; ++y) { - if (!getRedXY(x, y)) { - setColorXY(x, y, 0, 0, 0); - } - else { - var redCount = 0; - var left = x - 1; - var right = x + 1; - var up = y - 1; - var down = y + 1; - redCount += getRedXY(left, up); - redCount += getRedXY(left, y); - redCount += getRedXY(left, down); - redCount += getRedXY(right, up); - redCount += getRedXY(right, y); - redCount += getRedXY(right, down); - redCount += getRedXY(x, up); - redCount += getRedXY(x, down); - if (redCount != 8) - setColorXY(x, y, 1, 1, 255); - else - setColorXY(x, y, 1, 0, 0); - } - } - } - //antialias - if (antialias) { - for (x = 0; x < width; ++x) { - for (y = 0; y < height; ++y) { - if (getGreenXY(x, y)) { - var alpha = 0; - if (getGreenXY(x - 1, y) != getGreenXY(x + 1, y)) - setColorXY(x, y, 1, 1, alpha += 0x40); - if (getGreenXY(x, y - 1) != getGreenXY(x, y + 1)) - setColorXY(x, y, 1, 1, alpha + 0x50); - } - } - } - } - context.putImageData(imageData, 0, 0); - context.globalCompositeOperation = 'source-in'; - context.fillStyle = color; - context.fillRect(0, 0, width, height); - return canvas; -}; -Croquis.createFloodFill = function (canvas, x, y, r, g, b, a) { - var result = document.createElement('canvas'); - var w = result.width = canvas.width; - var h = result.height = canvas.height; - if ((x < 0) || (x >= w) || (y < 0) || (y >= h) || !(r || g || b || a)) - return result; - var originalContext = canvas.getContext('2d'); - var originalData = originalContext.getImageData(0, 0, w, h); - var od = originalData.data; - var resultContext = result.getContext('2d'); - var resultData = resultContext.getImageData(0, 0, w, h); - var rd = resultData.data; - var targetColor = getColor(x, y); - var replacementColor = (r << 24) | (g << 16) | (b << 8) | a; - function getColor(x, y) { - var index = ((y * w) + x) * 4; - return (rd[index] ? replacementColor : - ((od[index] << 24) | (od[index + 1] << 16) | - (od[index + 2] << 8) | od[index + 3])); - } - var queue = []; - queue.push(x, y); - while (queue.length) { - var nx = queue.shift(); - var ny = queue.shift(); - if ((nx < 0) || (nx >= w) || (ny < 0) || (ny >= h) || - (getColor(nx, ny) !== targetColor)) - continue; - var west, east; - west = east = nx; - do { - var wc = getColor(--west, ny); - } while ((west >= 0) && (wc === targetColor)); - do { - var ec = getColor(++east, ny); - } while ((east < w) && (ec === targetColor)); - for (var i = west + 1; i < east; ++i) { - rd[((ny * w) + i) * 4] = 1; - var north = ny - 1; - var south = ny + 1; - if (getColor(i, north) === targetColor) - queue.push(i, north); - if (getColor(i, south) === targetColor) - queue.push(i, south); - } - } - for (var i = 0; i < w; ++i) { - for (var j = 0; j < h; ++j) { - var index = ((j * w) + i) * 4; - if (rd[index] === 0) - continue; - rd[index] = r; - rd[index + 1] = g; - rd[index + 2] = b; - rd[index + 3] = a; - } - } - resultContext.putImageData(resultData, 0, 0); - return result; -}; - -Croquis.Tablet = {}; -Croquis.Tablet.plugin = function () { - var plugin = document.querySelector( - 'object[type=\'application/x-wacomtabletplugin\']'); - if (!plugin) { - plugin = document.createElement('object'); - plugin.type = 'application/x-wacomtabletplugin'; - plugin.style.position = 'absolute'; - plugin.style.top = '-1000px'; - document.body.appendChild(plugin); - } - return plugin; -}; -Croquis.Tablet.pen = function () { - var plugin = Croquis.Tablet.plugin(); - return plugin.penAPI; -}; -Croquis.Tablet.pressure = function () { - var pen = Croquis.Tablet.pen(); - return (pen && pen.pointerType) ? pen.pressure : 1; -}; -Croquis.Tablet.isEraser = function () { - var pen = Croquis.Tablet.pen(); - return pen ? pen.isEraser : false; -}; - -Croquis.Stabilizer = function (down, move, up, level, weight, - x, y, pressure, interval) { - interval = interval || 5; - var follow = 1 - Math.min(0.95, Math.max(0, weight)); - var paramTable = []; - var current = { x: x, y: y, pressure: pressure }; - for (var i = 0; i < level; ++i) - paramTable.push({ x: x, y: y, pressure: pressure }); - var first = paramTable[0]; - var last = paramTable[paramTable.length - 1]; - var upCalled = false; - if (down != null) - down(x, y, pressure); - window.setTimeout(_move, interval); - this.getParamTable = function () { //for test - return paramTable; - }; - this.move = function (x, y, pressure) { - current.x = x; - current.y = y; - current.pressure = pressure; - }; - this.up = function (x, y, pressure) { - current.x = x; - current.y = y; - current.pressure = pressure; - upCalled = true; - }; - function dlerp(a, d, t) { - return a + d * t; - } - function _move(justCalc) { - var curr; - var prev; - var dx; - var dy; - var dp; - var delta = 0; - first.x = current.x; - first.y = current.y; - first.pressure = current.pressure; - for (var i = 1; i < paramTable.length; ++i) { - curr = paramTable[i]; - prev = paramTable[i - 1]; - dx = prev.x - curr.x; - dy = prev.y - curr.y; - dp = prev.pressure - curr.pressure; - delta += Math.abs(dx); - delta += Math.abs(dy); - curr.x = dlerp(curr.x, dx, follow); - curr.y = dlerp(curr.y, dy, follow); - curr.pressure = dlerp(curr.pressure, dp, follow); - } - if (justCalc) - return delta; - if (upCalled) { - while(delta > 1) { - move(last.x, last.y, last.pressure); - delta = _move(true); - } - up(last.x, last.y, last.pressure); - } - else { - move(last.x, last.y, last.pressure); - window.setTimeout(_move, interval); - } - } -}; - -Croquis.Random = {}; -Croquis.Random.LFSR113 = function (seed) { - var IA = 16807; - var IM = 2147483647; - var IQ = 127773; - var IR = 2836; - var a, b, c, d, e; - this.get = function () { - var f = ((a << 6) ^ a) >> 13; - a = ((a & 4294967294) << 18) ^ f; - f = ((b << 2) ^ b) >> 27; - b = ((b & 4294967288) << 2) ^ f; - f = ((c << 13) ^ c) >> 21; - c = ((c & 4294967280) << 7) ^ f; - f = ((d << 3) ^ d) >> 12; - d = ((d & 4294967168) << 13) ^ f; - return (a ^ b ^ c ^ d) * 2.3283064365386963e-10 + 0.5; - }; - seed |= 0; - if (seed <= 0) seed = 1; - e = (seed / IQ) | 0; - seed = (((IA * (seed - ((e * IQ) | 0))) | 0) - ((IR * e) | 0)) | 0; - if (seed < 0) seed = (seed + IM) | 0; - if (seed < 2) a = (seed + 2) | 0 ; else a = seed; - e = (seed / IQ) | 0; - seed = (((IA * (seed - ((e * IQ) | 0))) | 0) - ((IR * e) | 0)) | 0; - if (seed < 0) seed = (seed + IM) | 0; - if (seed < 8) b = (seed + 8) | 0; else b = seed; - e = (seed / IQ) | 0; - seed = (((IA * (seed - ((e * IQ) | 0))) | 0) - ((IR * e) | 0)) | 0; - if (seed < 0) seed = (seed + IM) | 0; - if (seed < 16) c = (seed + 16) | 0; else c = seed; - e = (seed / IQ) | 0; - seed = (((IA * (seed - ((e * IQ) | 0))) | 0) - ((IR * e) | 0)) | 0; - if (seed < 0) seed = (seed + IM) | 0; - if (seed < 128) d = (seed + 128) | 0; else d = seed; - this.get(); -}; - -Croquis.Brush = function () { - // math shortcut - var min = Math.min; - var max = Math.max; - var abs = Math.abs; - var sin = Math.sin; - var cos = Math.cos; - var sqrt = Math.sqrt; - var atan2 = Math.atan2; - var PI = Math.PI; - var ONE = PI + PI; - var QUARTER = PI * 0.5; - var random = Math.random; - this.setRandomFunction = function (value) { - random = value; - }; - this.clone = function () { - var clone = new Brush(context); - clone.setColor(this.getColor()); - clone.setFlow(this.getFlow()); - clone.setSize(this.getSize()); - clone.setSpacing(this.getSpacing()); - clone.setAngle(this.getAngle()); - clone.setRotateToDirection(this.getRotateToDirection()); - clone.setNormalSpread(this.getNormalSpread()); - clone.setTangentSpread(this.getTangentSpread()); - clone.setImage(this.getImage()); - }; - var context = null; - this.getContext = function () { - return context; - }; - this.setContext = function (value) { - context = value; - }; - var color = '#000'; - this.getColor = function () { - return color; - }; - this.setColor = function (value) { - color = value; - transformedImageIsDirty = true; - }; - var flow = 1; - this.getFlow = function() { - return flow; - }; - this.setFlow = function(value) { - flow = value; - transformedImageIsDirty = true; - }; - var size = 10; - this.getSize = function () { - return size; - }; - this.setSize = function (value) { - size = (value < 1) ? 1 : value; - transformedImageIsDirty = true; - }; - var spacing = 0.2; - this.getSpacing = function () { - return spacing; - }; - this.setSpacing = function (value) { - spacing = (value < 0.01) ? 0.01 : value; - }; - var toRad = PI / 180; - var toDeg = 1 / toRad; - var angle = 0; // radian unit - this.getAngle = function () { // returns degree unit - return angle * toDeg; - }; - this.setAngle = function (value) { - angle = value * toRad; - }; - var rotateToDirection = false; - this.getRotateToDirection = function () { - return rotateToDirection; - }; - this.setRotateToDirection = function (value) { - rotateToDirection = value; - }; - var normalSpread = 0; - this.getNormalSpread = function () { - return normalSpread; - }; - this.setNormalSpread = function (value) { - normalSpread = value; - }; - var tangentSpread = 0; - this.getTangentSpread = function () { - return tangentSpread; - }; - this.setTangentSpread = function (value) { - tangentSpread = value; - }; - var image = null; - var transformedImage = null; - var transformedImageIsDirty = true; - var imageRatio = 1; - this.getImage = function () { - return image; - }; - this.setImage = function (value) { - if (value == null) { - transformedImage = image = null; - imageRatio = 1; - drawFunction = drawCircle; - } - else if (value != image) { - image = value; - imageRatio = image.height / image.width; - transformedImage = document.createElement('canvas'); - drawFunction = drawImage; - transformedImageIsDirty = true; - } - }; - var delta = 0; - var prevX = 0; - var prevY = 0; - var lastX = 0; - var lastY = 0; - var dir = 0; - var prevScale = 0; - var drawFunction = drawCircle; - var reserved = null; - var dirtyRect; - function spreadRandom() { - return random() - 0.5; - } - function drawReserved() { - if (reserved != null) { - drawTo(reserved.x, reserved.y, reserved.scale); - reserved = null; - } - } - function appendDirtyRect(x, y, width, height) { - if (!(width && height)) - return; - var dxw = dirtyRect.x + dirtyRect.width; - var dyh = dirtyRect.y + dirtyRect.height; - var xw = x + width; - var yh = y + height; - var minX = dirtyRect.width ? min(dirtyRect.x, x) : x; - var minY = dirtyRect.height ? min(dirtyRect.y, y) : y; - dirtyRect.x = minX; - dirtyRect.y = minY; - dirtyRect.width = max(dxw, xw) - minX; - dirtyRect.height = max(dyh, yh) - minY; - } - function transformImage() { - transformedImage.width = size; - transformedImage.height = size * imageRatio; - var brushContext = transformedImage.getContext('2d'); - brushContext.clearRect(0, 0, - transformedImage.width, transformedImage.height); - brushContext.drawImage(image, 0, 0, - transformedImage.width, transformedImage.height); - brushContext.globalCompositeOperation = 'source-in'; - brushContext.fillStyle = color; - brushContext.globalAlpha = flow; - brushContext.fillRect(0, 0, - transformedImage.width, transformedImage.height); - } - function drawCircle(size) { - var halfSize = size * 0.5; - context.fillStyle = color; - context.globalAlpha = flow; - context.beginPath(); - context.arc(halfSize, halfSize, halfSize, 0, ONE); - context.closePath(); - context.fill(); - } - function drawImage(size) { - if (transformedImageIsDirty) - transformImage(); - try { - context.drawImage(transformedImage, 0, 0, size, size * imageRatio); - } - catch (e) { - drawCircle(size); - } - } - function drawTo(x, y, scale) { - var scaledSize = size * scale; - var nrm = dir + QUARTER; - var nr = normalSpread * scaledSize * spreadRandom(); - var tr = tangentSpread * scaledSize * spreadRandom(); - var ra = rotateToDirection ? angle + dir : angle; - var width = scaledSize; - var height = width * imageRatio; - var boundWidth = abs(height * sin(ra)) + abs(width * cos(ra)); - var boundHeight = abs(width * sin(ra)) + abs(height * cos(ra)); - x += Math.cos(nrm) * nr + Math.cos(dir) * tr; - y += Math.sin(nrm) * nr + Math.sin(dir) * tr; - context.save(); - context.translate(x, y); - context.rotate(ra); - context.translate(-(width * 0.5), -(height * 0.5)); - drawFunction(width); - context.restore(); - appendDirtyRect(x - (boundWidth * 0.5), - y - (boundHeight * 0.5), - boundWidth, boundHeight); - } - this.down = function(x, y, scale) { - if (context == null) - throw 'brush needs the context'; - dir = 0; - dirtyRect = {x: 0, y: 0, width: 0, height: 0}; - if (scale > 0) { - if (rotateToDirection || normalSpread !== 0 || tangentSpread !== 0) - reserved = {x: x, y: y, scale: scale}; - else - drawTo(x, y, scale); - } - delta = 0; - lastX = prevX = x; - lastY = prevY = y; - prevScale = scale; - }; - this.move = function(x, y, scale) { - if (context == null) - throw 'brush needs the context'; - if (scale <= 0) { - delta = 0; - prevX = x; - prevY = y; - prevScale = scale; - return; - } - var dx = x - prevX; - var dy = y - prevY; - var ds = scale - prevScale; - var d = sqrt(dx * dx + dy * dy); - prevX = x; - prevY = y; - delta += d; - var midScale = (prevScale + scale) * 0.5; - var drawSpacing = size * spacing * midScale; - var ldx = x - lastX; - var ldy = y - lastY; - var ld = sqrt(ldx * ldx + ldy * ldy); - dir = atan2(ldy, ldx); - if (ldx || ldy) - drawReserved(); - if (drawSpacing < 0.5) - drawSpacing = 0.5; - if (delta < drawSpacing) { - prevScale = scale; - return; - } - var scaleSpacing = ds * (drawSpacing / delta); - if (ld < drawSpacing) { - lastX = x; - lastY = y; - drawTo(lastX, lastY, scale); - delta -= drawSpacing; - } else { - while(delta >= drawSpacing) { - ldx = x - lastX; - ldy = y - lastY; - var tx = cos(dir); - var ty = sin(dir); - lastX += tx * drawSpacing; - lastY += ty * drawSpacing; - prevScale += scaleSpacing; - drawTo(lastX, lastY, prevScale); - delta -= drawSpacing; - } - } - prevScale = scale; - }; - this.up = function (x, y, scale) { - dir = atan2(y - lastY, x - lastX); - drawReserved(); - return dirtyRect; - }; -}; - -/** - * @fileoverview Implement 'currentTransform' of CanvasRenderingContext2D prototype (polyfill) - * @author Stefan Goessner (c) 2015 - */ - -/** - * extend CanvasRenderingContext2D.prototype by current transformation matrix access. - */ -if (!("currentTransform" in CanvasRenderingContext2D.prototype)) { -/** - * define property 'currentTransform' - */ - if ("mozCurrentTransform" in CanvasRenderingContext2D.prototype) { - Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", { - get : function() { var m = this.mozCurrentTransform; return {a:m[0],b:m[1],c:m[2],d:m[3],e:m[4],f:m[5]}; }, - set : function(x) { this.mozCurrentTransform = [x.a,x.b,x.c,x.d,x.e,x.f]; }, - enumerable : true, - configurable : false - }); - } - else if ("webkitCurrentTransform" in CanvasRenderingContext2D.prototype) { - Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", { - get : function() { return this.webkitCurrentTransform; }, - set : function(x) { this.webkitCurrentTransform = x; }, - enumerable : true, - configurable : false - }); - } - else { // fully implement it ... hmm ... 'currentTransform', 'save()', 'restore()', 'transform()', 'setTransform()', 'resetTransform()' - Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", { - get : function() {return this._t2stack && this._t2stack[this._t2stack.length-1] || {a:1,b:0,c:0,d:1,e:0,f:0};}, - set : function(x) { - if (!this._t2stack) - this._t2stack = [{}]; - this._t2stack[this._t2stack.length-1] = {a:x.a,b:x.b,c:x.c,d:x.d,e:x.e,f:x.f}; - }, - enumerable : true, - configurable : false - }); - CanvasRenderingContext2D.prototype.save = function() { - var save = CanvasRenderingContext2D.prototype.save; - return function() { - if (!this._t2stack) - this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}]; - var t = this._t2stack[this._t2stack.length-1]; - this._t2stack.push(t && {a:t.a,b:t.b,c:t.c,d:t.d,e:t.e,f:t.f}); - save.call(this); - } - }(); - CanvasRenderingContext2D.prototype.restore = function() { - var restore = CanvasRenderingContext2D.prototype.restore; - return function() { - if (this._t2stack) this._t2stack.pop(); - restore.call(this); - } - }(); - CanvasRenderingContext2D.prototype.transform = function() { - var transform = CanvasRenderingContext2D.prototype.transform; - return function(a,b,c,d,e,f) { - if (!this._t2stack) - this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}]; - var t = this._t2stack[this._t2stack.length-1], q; - - var na = t.a*a + t.c * b; - var nb = t.b*a + t.d * b; - - var nc = t.a*c + t.c * d; - var nd = t.b*c + t.d * d; - - var ne = t.e + t.a*e + t.c*f; - var nf = t.f + t.b*e + t.d*f; - - t.a = na; - t.b = nb; - t.c = nc; - t.d = nd; - t.e = ne; - t.f = nf; - transform.call(this,a,b,c,d,e,f); - } - }(); - CanvasRenderingContext2D.prototype.setTransform = function() { - var setTransform = CanvasRenderingContext2D.prototype.setTransform; - return function(a,b,c,d,e,f) { - if (!this._t2stack) - this._t2stack = [{}]; - this._t2stack[this._t2stack.length-1] = {a:a,b:b,c:c,d:d,e:e,f:f}; - setTransform.call(this,a,b,c,d,e,f); - } - }(); - CanvasRenderingContext2D.prototype.resetTransform = function() { - var resetTransform = CanvasRenderingContext2D.prototype.resetTransform; - return function() { - if (!this._t2stack) - this._t2stack = [{}]; - this._t2stack[this._t2stack.length-1] = {a:1,b:0,c:0,d:1,e:0,f:0}; - resetTransform && resetTransform.call(this); - } - }(); - CanvasRenderingContext2D.prototype.scale = function() { - var scale = CanvasRenderingContext2D.prototype.scale; - return function(sx,sy) { - if (!this._t2stack) - this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}]; - var t = this._t2stack[this._t2stack.length-1]; - sx = sx || 1; - sy = sy || sx; - t.a *= sx; t.c *= sy; - t.b *= sx; t.d *= sy; - scale.call(this,sx,sy); - } - }(); - CanvasRenderingContext2D.prototype.rotate = function() { - var rotate = CanvasRenderingContext2D.prototype.rotate; - return function(w) { - if (!this._t2stack) - this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}]; - var t = this._t2stack[this._t2stack.length-1]; - - var cw = Math.cos(-w); - var sw = Math.sin(-w); - - var a = t.a*cw - t.c*sw; - var b = t.b*cw - t.d*sw; - var c = t.c*cw + t.a*sw; - var d = t.d*cw + t.b*sw; - - t.a = a; - t.b = b; - t.c = c; - t.d = d; - - return rotate.call(this,w); - } - }(); - CanvasRenderingContext2D.prototype.translate = function() { - var translate = CanvasRenderingContext2D.prototype.translate; - return function(x,y) { - if (!this._t2stack) - this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}]; - var t = this._t2stack[this._t2stack.length-1]; - t.e += x*t.a + y*t.c; - t.f += x*t.b + y*t.d; - return translate.call(this,x,y); - } - }(); - } -} - -(function webpackUniversalModuleDefinition(root, factory) { -/* istanbul ignore next */ - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); -/* istanbul ignore next */ - else if(typeof exports === 'object') - exports["esprima"] = factory(); - else - root["esprima"] = factory(); -})(this, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/* istanbul ignore if */ -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - /* - Copyright JS Foundation and other contributors, https://js.foundation/ - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - Object.defineProperty(exports, "__esModule", { value: true }); - var comment_handler_1 = __webpack_require__(1); - var jsx_parser_1 = __webpack_require__(3); - var parser_1 = __webpack_require__(8); - var tokenizer_1 = __webpack_require__(15); - function parse(code, options, delegate) { - var commentHandler = null; - var proxyDelegate = function (node, metadata) { - if (delegate) { - delegate(node, metadata); - } - if (commentHandler) { - commentHandler.visit(node, metadata); - } - }; - var parserDelegate = (typeof delegate === 'function') ? proxyDelegate : null; - var collectComment = false; - if (options) { - collectComment = (typeof options.comment === 'boolean' && options.comment); - var attachComment = (typeof options.attachComment === 'boolean' && options.attachComment); - if (collectComment || attachComment) { - commentHandler = new comment_handler_1.CommentHandler(); - commentHandler.attach = attachComment; - options.comment = true; - parserDelegate = proxyDelegate; - } - } - var isModule = false; - if (options && typeof options.sourceType === 'string') { - isModule = (options.sourceType === 'module'); - } - var parser; - if (options && typeof options.jsx === 'boolean' && options.jsx) { - parser = new jsx_parser_1.JSXParser(code, options, parserDelegate); - } - else { - parser = new parser_1.Parser(code, options, parserDelegate); - } - var program = isModule ? parser.parseModule() : parser.parseScript(); - var ast = program; - if (collectComment && commentHandler) { - ast.comments = commentHandler.comments; - } - if (parser.config.tokens) { - ast.tokens = parser.tokens; - } - if (parser.config.tolerant) { - ast.errors = parser.errorHandler.errors; - } - return ast; - } - exports.parse = parse; - function parseModule(code, options, delegate) { - var parsingOptions = options || {}; - parsingOptions.sourceType = 'module'; - return parse(code, parsingOptions, delegate); - } - exports.parseModule = parseModule; - function parseScript(code, options, delegate) { - var parsingOptions = options || {}; - parsingOptions.sourceType = 'script'; - return parse(code, parsingOptions, delegate); - } - exports.parseScript = parseScript; - function tokenize(code, options, delegate) { - var tokenizer = new tokenizer_1.Tokenizer(code, options); - var tokens; - tokens = []; - try { - while (true) { - var token = tokenizer.getNextToken(); - if (!token) { - break; - } - if (delegate) { - token = delegate(token); - } - tokens.push(token); - } - } - catch (e) { - tokenizer.errorHandler.tolerate(e); - } - if (tokenizer.errorHandler.tolerant) { - tokens.errors = tokenizer.errors(); - } - return tokens; - } - exports.tokenize = tokenize; - var syntax_1 = __webpack_require__(2); - exports.Syntax = syntax_1.Syntax; - // Sync with *.json manifests. - exports.version = '4.0.1'; - - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var syntax_1 = __webpack_require__(2); - var CommentHandler = (function () { - function CommentHandler() { - this.attach = false; - this.comments = []; - this.stack = []; - this.leading = []; - this.trailing = []; - } - CommentHandler.prototype.insertInnerComments = function (node, metadata) { - // innnerComments for properties empty block - // `function a() {/** comments **\/}` - if (node.type === syntax_1.Syntax.BlockStatement && node.body.length === 0) { - var innerComments = []; - for (var i = this.leading.length - 1; i >= 0; --i) { - var entry = this.leading[i]; - if (metadata.end.offset >= entry.start) { - innerComments.unshift(entry.comment); - this.leading.splice(i, 1); - this.trailing.splice(i, 1); - } - } - if (innerComments.length) { - node.innerComments = innerComments; - } - } - }; - CommentHandler.prototype.findTrailingComments = function (metadata) { - var trailingComments = []; - if (this.trailing.length > 0) { - for (var i = this.trailing.length - 1; i >= 0; --i) { - var entry_1 = this.trailing[i]; - if (entry_1.start >= metadata.end.offset) { - trailingComments.unshift(entry_1.comment); - } - } - this.trailing.length = 0; - return trailingComments; - } - var entry = this.stack[this.stack.length - 1]; - if (entry && entry.node.trailingComments) { - var firstComment = entry.node.trailingComments[0]; - if (firstComment && firstComment.range[0] >= metadata.end.offset) { - trailingComments = entry.node.trailingComments; - delete entry.node.trailingComments; - } - } - return trailingComments; - }; - CommentHandler.prototype.findLeadingComments = function (metadata) { - var leadingComments = []; - var target; - while (this.stack.length > 0) { - var entry = this.stack[this.stack.length - 1]; - if (entry && entry.start >= metadata.start.offset) { - target = entry.node; - this.stack.pop(); - } - else { - break; - } - } - if (target) { - var count = target.leadingComments ? target.leadingComments.length : 0; - for (var i = count - 1; i >= 0; --i) { - var comment = target.leadingComments[i]; - if (comment.range[1] <= metadata.start.offset) { - leadingComments.unshift(comment); - target.leadingComments.splice(i, 1); - } - } - if (target.leadingComments && target.leadingComments.length === 0) { - delete target.leadingComments; - } - return leadingComments; - } - for (var i = this.leading.length - 1; i >= 0; --i) { - var entry = this.leading[i]; - if (entry.start <= metadata.start.offset) { - leadingComments.unshift(entry.comment); - this.leading.splice(i, 1); - } - } - return leadingComments; - }; - CommentHandler.prototype.visitNode = function (node, metadata) { - if (node.type === syntax_1.Syntax.Program && node.body.length > 0) { - return; - } - this.insertInnerComments(node, metadata); - var trailingComments = this.findTrailingComments(metadata); - var leadingComments = this.findLeadingComments(metadata); - if (leadingComments.length > 0) { - node.leadingComments = leadingComments; - } - if (trailingComments.length > 0) { - node.trailingComments = trailingComments; - } - this.stack.push({ - node: node, - start: metadata.start.offset - }); - }; - CommentHandler.prototype.visitComment = function (node, metadata) { - var type = (node.type[0] === 'L') ? 'Line' : 'Block'; - var comment = { - type: type, - value: node.value - }; - if (node.range) { - comment.range = node.range; - } - if (node.loc) { - comment.loc = node.loc; - } - this.comments.push(comment); - if (this.attach) { - var entry = { - comment: { - type: type, - value: node.value, - range: [metadata.start.offset, metadata.end.offset] - }, - start: metadata.start.offset - }; - if (node.loc) { - entry.comment.loc = node.loc; - } - node.type = type; - this.leading.push(entry); - this.trailing.push(entry); - } - }; - CommentHandler.prototype.visit = function (node, metadata) { - if (node.type === 'LineComment') { - this.visitComment(node, metadata); - } - else if (node.type === 'BlockComment') { - this.visitComment(node, metadata); - } - else if (this.attach) { - this.visitNode(node, metadata); - } - }; - return CommentHandler; - }()); - exports.CommentHandler = CommentHandler; - - -/***/ }, -/* 2 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Syntax = { - AssignmentExpression: 'AssignmentExpression', - AssignmentPattern: 'AssignmentPattern', - ArrayExpression: 'ArrayExpression', - ArrayPattern: 'ArrayPattern', - ArrowFunctionExpression: 'ArrowFunctionExpression', - AwaitExpression: 'AwaitExpression', - BlockStatement: 'BlockStatement', - BinaryExpression: 'BinaryExpression', - BreakStatement: 'BreakStatement', - CallExpression: 'CallExpression', - CatchClause: 'CatchClause', - ClassBody: 'ClassBody', - ClassDeclaration: 'ClassDeclaration', - ClassExpression: 'ClassExpression', - ConditionalExpression: 'ConditionalExpression', - ContinueStatement: 'ContinueStatement', - DoWhileStatement: 'DoWhileStatement', - DebuggerStatement: 'DebuggerStatement', - EmptyStatement: 'EmptyStatement', - ExportAllDeclaration: 'ExportAllDeclaration', - ExportDefaultDeclaration: 'ExportDefaultDeclaration', - ExportNamedDeclaration: 'ExportNamedDeclaration', - ExportSpecifier: 'ExportSpecifier', - ExpressionStatement: 'ExpressionStatement', - ForStatement: 'ForStatement', - ForOfStatement: 'ForOfStatement', - ForInStatement: 'ForInStatement', - FunctionDeclaration: 'FunctionDeclaration', - FunctionExpression: 'FunctionExpression', - Identifier: 'Identifier', - IfStatement: 'IfStatement', - ImportDeclaration: 'ImportDeclaration', - ImportDefaultSpecifier: 'ImportDefaultSpecifier', - ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', - ImportSpecifier: 'ImportSpecifier', - Literal: 'Literal', - LabeledStatement: 'LabeledStatement', - LogicalExpression: 'LogicalExpression', - MemberExpression: 'MemberExpression', - MetaProperty: 'MetaProperty', - MethodDefinition: 'MethodDefinition', - NewExpression: 'NewExpression', - ObjectExpression: 'ObjectExpression', - ObjectPattern: 'ObjectPattern', - Program: 'Program', - Property: 'Property', - RestElement: 'RestElement', - ReturnStatement: 'ReturnStatement', - SequenceExpression: 'SequenceExpression', - SpreadElement: 'SpreadElement', - Super: 'Super', - SwitchCase: 'SwitchCase', - SwitchStatement: 'SwitchStatement', - TaggedTemplateExpression: 'TaggedTemplateExpression', - TemplateElement: 'TemplateElement', - TemplateLiteral: 'TemplateLiteral', - ThisExpression: 'ThisExpression', - ThrowStatement: 'ThrowStatement', - TryStatement: 'TryStatement', - UnaryExpression: 'UnaryExpression', - UpdateExpression: 'UpdateExpression', - VariableDeclaration: 'VariableDeclaration', - VariableDeclarator: 'VariableDeclarator', - WhileStatement: 'WhileStatement', - WithStatement: 'WithStatement', - YieldExpression: 'YieldExpression' - }; - - -/***/ }, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; -/* istanbul ignore next */ - var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; - })(); - Object.defineProperty(exports, "__esModule", { value: true }); - var character_1 = __webpack_require__(4); - var JSXNode = __webpack_require__(5); - var jsx_syntax_1 = __webpack_require__(6); - var Node = __webpack_require__(7); - var parser_1 = __webpack_require__(8); - var token_1 = __webpack_require__(13); - var xhtml_entities_1 = __webpack_require__(14); - token_1.TokenName[100 /* Identifier */] = 'JSXIdentifier'; - token_1.TokenName[101 /* Text */] = 'JSXText'; - // Fully qualified element name, e.g. returns "svg:path" - function getQualifiedElementName(elementName) { - var qualifiedName; - switch (elementName.type) { - case jsx_syntax_1.JSXSyntax.JSXIdentifier: - var id = elementName; - qualifiedName = id.name; - break; - case jsx_syntax_1.JSXSyntax.JSXNamespacedName: - var ns = elementName; - qualifiedName = getQualifiedElementName(ns.namespace) + ':' + - getQualifiedElementName(ns.name); - break; - case jsx_syntax_1.JSXSyntax.JSXMemberExpression: - var expr = elementName; - qualifiedName = getQualifiedElementName(expr.object) + '.' + - getQualifiedElementName(expr.property); - break; - /* istanbul ignore next */ - default: - break; - } - return qualifiedName; - } - var JSXParser = (function (_super) { - __extends(JSXParser, _super); - function JSXParser(code, options, delegate) { - return _super.call(this, code, options, delegate) || this; - } - JSXParser.prototype.parsePrimaryExpression = function () { - return this.match('<') ? this.parseJSXRoot() : _super.prototype.parsePrimaryExpression.call(this); - }; - JSXParser.prototype.startJSX = function () { - // Unwind the scanner before the lookahead token. - this.scanner.index = this.startMarker.index; - this.scanner.lineNumber = this.startMarker.line; - this.scanner.lineStart = this.startMarker.index - this.startMarker.column; - }; - JSXParser.prototype.finishJSX = function () { - // Prime the next lookahead. - this.nextToken(); - }; - JSXParser.prototype.reenterJSX = function () { - this.startJSX(); - this.expectJSX('}'); - // Pop the closing '}' added from the lookahead. - if (this.config.tokens) { - this.tokens.pop(); - } - }; - JSXParser.prototype.createJSXNode = function () { - this.collectComments(); - return { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - }; - JSXParser.prototype.createJSXChildNode = function () { - return { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - }; - JSXParser.prototype.scanXHTMLEntity = function (quote) { - var result = '&'; - var valid = true; - var terminated = false; - var numeric = false; - var hex = false; - while (!this.scanner.eof() && valid && !terminated) { - var ch = this.scanner.source[this.scanner.index]; - if (ch === quote) { - break; - } - terminated = (ch === ';'); - result += ch; - ++this.scanner.index; - if (!terminated) { - switch (result.length) { - case 2: - // e.g. '{' - numeric = (ch === '#'); - break; - case 3: - if (numeric) { - // e.g. 'A' - hex = (ch === 'x'); - valid = hex || character_1.Character.isDecimalDigit(ch.charCodeAt(0)); - numeric = numeric && !hex; - } - break; - default: - valid = valid && !(numeric && !character_1.Character.isDecimalDigit(ch.charCodeAt(0))); - valid = valid && !(hex && !character_1.Character.isHexDigit(ch.charCodeAt(0))); - break; - } - } - } - if (valid && terminated && result.length > 2) { - // e.g. 'A' becomes just '#x41' - var str = result.substr(1, result.length - 2); - if (numeric && str.length > 1) { - result = String.fromCharCode(parseInt(str.substr(1), 10)); - } - else if (hex && str.length > 2) { - result = String.fromCharCode(parseInt('0' + str.substr(1), 16)); - } - else if (!numeric && !hex && xhtml_entities_1.XHTMLEntities[str]) { - result = xhtml_entities_1.XHTMLEntities[str]; - } - } - return result; - }; - // Scan the next JSX token. This replaces Scanner#lex when in JSX mode. - JSXParser.prototype.lexJSX = function () { - var cp = this.scanner.source.charCodeAt(this.scanner.index); - // < > / : = { } - if (cp === 60 || cp === 62 || cp === 47 || cp === 58 || cp === 61 || cp === 123 || cp === 125) { - var value = this.scanner.source[this.scanner.index++]; - return { - type: 7 /* Punctuator */, - value: value, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: this.scanner.index - 1, - end: this.scanner.index - }; - } - // " ' - if (cp === 34 || cp === 39) { - var start = this.scanner.index; - var quote = this.scanner.source[this.scanner.index++]; - var str = ''; - while (!this.scanner.eof()) { - var ch = this.scanner.source[this.scanner.index++]; - if (ch === quote) { - break; - } - else if (ch === '&') { - str += this.scanXHTMLEntity(quote); - } - else { - str += ch; - } - } - return { - type: 8 /* StringLiteral */, - value: str, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - // ... or . - if (cp === 46) { - var n1 = this.scanner.source.charCodeAt(this.scanner.index + 1); - var n2 = this.scanner.source.charCodeAt(this.scanner.index + 2); - var value = (n1 === 46 && n2 === 46) ? '...' : '.'; - var start = this.scanner.index; - this.scanner.index += value.length; - return { - type: 7 /* Punctuator */, - value: value, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - // ` - if (cp === 96) { - // Only placeholder, since it will be rescanned as a real assignment expression. - return { - type: 10 /* Template */, - value: '', - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: this.scanner.index, - end: this.scanner.index - }; - } - // Identifer can not contain backslash (char code 92). - if (character_1.Character.isIdentifierStart(cp) && (cp !== 92)) { - var start = this.scanner.index; - ++this.scanner.index; - while (!this.scanner.eof()) { - var ch = this.scanner.source.charCodeAt(this.scanner.index); - if (character_1.Character.isIdentifierPart(ch) && (ch !== 92)) { - ++this.scanner.index; - } - else if (ch === 45) { - // Hyphen (char code 45) can be part of an identifier. - ++this.scanner.index; - } - else { - break; - } - } - var id = this.scanner.source.slice(start, this.scanner.index); - return { - type: 100 /* Identifier */, - value: id, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - return this.scanner.lex(); - }; - JSXParser.prototype.nextJSXToken = function () { - this.collectComments(); - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - var token = this.lexJSX(); - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - if (this.config.tokens) { - this.tokens.push(this.convertToken(token)); - } - return token; - }; - JSXParser.prototype.nextJSXText = function () { - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - var start = this.scanner.index; - var text = ''; - while (!this.scanner.eof()) { - var ch = this.scanner.source[this.scanner.index]; - if (ch === '{' || ch === '<') { - break; - } - ++this.scanner.index; - text += ch; - if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { - ++this.scanner.lineNumber; - if (ch === '\r' && this.scanner.source[this.scanner.index] === '\n') { - ++this.scanner.index; - } - this.scanner.lineStart = this.scanner.index; - } - } - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - var token = { - type: 101 /* Text */, - value: text, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - if ((text.length > 0) && this.config.tokens) { - this.tokens.push(this.convertToken(token)); - } - return token; - }; - JSXParser.prototype.peekJSXToken = function () { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.lexJSX(); - this.scanner.restoreState(state); - return next; - }; - // Expect the next JSX token to match the specified punctuator. - // If not, an exception will be thrown. - JSXParser.prototype.expectJSX = function (value) { - var token = this.nextJSXToken(); - if (token.type !== 7 /* Punctuator */ || token.value !== value) { - this.throwUnexpectedToken(token); - } - }; - // Return true if the next JSX token matches the specified punctuator. - JSXParser.prototype.matchJSX = function (value) { - var next = this.peekJSXToken(); - return next.type === 7 /* Punctuator */ && next.value === value; - }; - JSXParser.prototype.parseJSXIdentifier = function () { - var node = this.createJSXNode(); - var token = this.nextJSXToken(); - if (token.type !== 100 /* Identifier */) { - this.throwUnexpectedToken(token); - } - return this.finalize(node, new JSXNode.JSXIdentifier(token.value)); - }; - JSXParser.prototype.parseJSXElementName = function () { - var node = this.createJSXNode(); - var elementName = this.parseJSXIdentifier(); - if (this.matchJSX(':')) { - var namespace = elementName; - this.expectJSX(':'); - var name_1 = this.parseJSXIdentifier(); - elementName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_1)); - } - else if (this.matchJSX('.')) { - while (this.matchJSX('.')) { - var object = elementName; - this.expectJSX('.'); - var property = this.parseJSXIdentifier(); - elementName = this.finalize(node, new JSXNode.JSXMemberExpression(object, property)); - } - } - return elementName; - }; - JSXParser.prototype.parseJSXAttributeName = function () { - var node = this.createJSXNode(); - var attributeName; - var identifier = this.parseJSXIdentifier(); - if (this.matchJSX(':')) { - var namespace = identifier; - this.expectJSX(':'); - var name_2 = this.parseJSXIdentifier(); - attributeName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_2)); - } - else { - attributeName = identifier; - } - return attributeName; - }; - JSXParser.prototype.parseJSXStringLiteralAttribute = function () { - var node = this.createJSXNode(); - var token = this.nextJSXToken(); - if (token.type !== 8 /* StringLiteral */) { - this.throwUnexpectedToken(token); - } - var raw = this.getTokenRaw(token); - return this.finalize(node, new Node.Literal(token.value, raw)); - }; - JSXParser.prototype.parseJSXExpressionAttribute = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - this.finishJSX(); - if (this.match('}')) { - this.tolerateError('JSX attributes must only be assigned a non-empty expression'); - } - var expression = this.parseAssignmentExpression(); - this.reenterJSX(); - return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); - }; - JSXParser.prototype.parseJSXAttributeValue = function () { - return this.matchJSX('{') ? this.parseJSXExpressionAttribute() : - this.matchJSX('<') ? this.parseJSXElement() : this.parseJSXStringLiteralAttribute(); - }; - JSXParser.prototype.parseJSXNameValueAttribute = function () { - var node = this.createJSXNode(); - var name = this.parseJSXAttributeName(); - var value = null; - if (this.matchJSX('=')) { - this.expectJSX('='); - value = this.parseJSXAttributeValue(); - } - return this.finalize(node, new JSXNode.JSXAttribute(name, value)); - }; - JSXParser.prototype.parseJSXSpreadAttribute = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - this.expectJSX('...'); - this.finishJSX(); - var argument = this.parseAssignmentExpression(); - this.reenterJSX(); - return this.finalize(node, new JSXNode.JSXSpreadAttribute(argument)); - }; - JSXParser.prototype.parseJSXAttributes = function () { - var attributes = []; - while (!this.matchJSX('/') && !this.matchJSX('>')) { - var attribute = this.matchJSX('{') ? this.parseJSXSpreadAttribute() : - this.parseJSXNameValueAttribute(); - attributes.push(attribute); - } - return attributes; - }; - JSXParser.prototype.parseJSXOpeningElement = function () { - var node = this.createJSXNode(); - this.expectJSX('<'); - var name = this.parseJSXElementName(); - var attributes = this.parseJSXAttributes(); - var selfClosing = this.matchJSX('/'); - if (selfClosing) { - this.expectJSX('/'); - } - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); - }; - JSXParser.prototype.parseJSXBoundaryElement = function () { - var node = this.createJSXNode(); - this.expectJSX('<'); - if (this.matchJSX('/')) { - this.expectJSX('/'); - var name_3 = this.parseJSXElementName(); - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXClosingElement(name_3)); - } - var name = this.parseJSXElementName(); - var attributes = this.parseJSXAttributes(); - var selfClosing = this.matchJSX('/'); - if (selfClosing) { - this.expectJSX('/'); - } - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); - }; - JSXParser.prototype.parseJSXEmptyExpression = function () { - var node = this.createJSXChildNode(); - this.collectComments(); - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - return this.finalize(node, new JSXNode.JSXEmptyExpression()); - }; - JSXParser.prototype.parseJSXExpressionContainer = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - var expression; - if (this.matchJSX('}')) { - expression = this.parseJSXEmptyExpression(); - this.expectJSX('}'); - } - else { - this.finishJSX(); - expression = this.parseAssignmentExpression(); - this.reenterJSX(); - } - return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); - }; - JSXParser.prototype.parseJSXChildren = function () { - var children = []; - while (!this.scanner.eof()) { - var node = this.createJSXChildNode(); - var token = this.nextJSXText(); - if (token.start < token.end) { - var raw = this.getTokenRaw(token); - var child = this.finalize(node, new JSXNode.JSXText(token.value, raw)); - children.push(child); - } - if (this.scanner.source[this.scanner.index] === '{') { - var container = this.parseJSXExpressionContainer(); - children.push(container); - } - else { - break; - } - } - return children; - }; - JSXParser.prototype.parseComplexJSXElement = function (el) { - var stack = []; - while (!this.scanner.eof()) { - el.children = el.children.concat(this.parseJSXChildren()); - var node = this.createJSXChildNode(); - var element = this.parseJSXBoundaryElement(); - if (element.type === jsx_syntax_1.JSXSyntax.JSXOpeningElement) { - var opening = element; - if (opening.selfClosing) { - var child = this.finalize(node, new JSXNode.JSXElement(opening, [], null)); - el.children.push(child); - } - else { - stack.push(el); - el = { node: node, opening: opening, closing: null, children: [] }; - } - } - if (element.type === jsx_syntax_1.JSXSyntax.JSXClosingElement) { - el.closing = element; - var open_1 = getQualifiedElementName(el.opening.name); - var close_1 = getQualifiedElementName(el.closing.name); - if (open_1 !== close_1) { - this.tolerateError('Expected corresponding JSX closing tag for %0', open_1); - } - if (stack.length > 0) { - var child = this.finalize(el.node, new JSXNode.JSXElement(el.opening, el.children, el.closing)); - el = stack[stack.length - 1]; - el.children.push(child); - stack.pop(); - } - else { - break; - } - } - } - return el; - }; - JSXParser.prototype.parseJSXElement = function () { - var node = this.createJSXNode(); - var opening = this.parseJSXOpeningElement(); - var children = []; - var closing = null; - if (!opening.selfClosing) { - var el = this.parseComplexJSXElement({ node: node, opening: opening, closing: closing, children: children }); - children = el.children; - closing = el.closing; - } - return this.finalize(node, new JSXNode.JSXElement(opening, children, closing)); - }; - JSXParser.prototype.parseJSXRoot = function () { - // Pop the opening '<' added from the lookahead. - if (this.config.tokens) { - this.tokens.pop(); - } - this.startJSX(); - var element = this.parseJSXElement(); - this.finishJSX(); - return element; - }; - JSXParser.prototype.isStartOfExpression = function () { - return _super.prototype.isStartOfExpression.call(this) || this.match('<'); - }; - return JSXParser; - }(parser_1.Parser)); - exports.JSXParser = JSXParser; - - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - // See also tools/generate-unicode-regex.js. - var Regex = { - // Unicode v8.0.0 NonAsciiIdentifierStart: - NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\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-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\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\u0AF9\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-\u0C39\u0C3D\u0C58-\u0C5A\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\u0D5F-\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-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\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\u2118-\u211D\u2124\u2126\u2128\u212A-\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\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\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]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/, - // Unicode v8.0.0 NonAsciiIdentifierPart: - NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\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\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\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\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ - }; - exports.Character = { - /* tslint:disable:no-bitwise */ - fromCodePoint: function (cp) { - return (cp < 0x10000) ? String.fromCharCode(cp) : - String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) + - String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023)); - }, - // https://tc39.github.io/ecma262/#sec-white-space - isWhiteSpace: function (cp) { - return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) || - (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0); - }, - // https://tc39.github.io/ecma262/#sec-line-terminators - isLineTerminator: function (cp) { - return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029); - }, - // https://tc39.github.io/ecma262/#sec-names-and-keywords - isIdentifierStart: function (cp) { - return (cp === 0x24) || (cp === 0x5F) || - (cp >= 0x41 && cp <= 0x5A) || - (cp >= 0x61 && cp <= 0x7A) || - (cp === 0x5C) || - ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(exports.Character.fromCodePoint(cp))); - }, - isIdentifierPart: function (cp) { - return (cp === 0x24) || (cp === 0x5F) || - (cp >= 0x41 && cp <= 0x5A) || - (cp >= 0x61 && cp <= 0x7A) || - (cp >= 0x30 && cp <= 0x39) || - (cp === 0x5C) || - ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(exports.Character.fromCodePoint(cp))); - }, - // https://tc39.github.io/ecma262/#sec-literals-numeric-literals - isDecimalDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x39); // 0..9 - }, - isHexDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x39) || - (cp >= 0x41 && cp <= 0x46) || - (cp >= 0x61 && cp <= 0x66); // a..f - }, - isOctalDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x37); // 0..7 - } - }; - - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var jsx_syntax_1 = __webpack_require__(6); - /* tslint:disable:max-classes-per-file */ - var JSXClosingElement = (function () { - function JSXClosingElement(name) { - this.type = jsx_syntax_1.JSXSyntax.JSXClosingElement; - this.name = name; - } - return JSXClosingElement; - }()); - exports.JSXClosingElement = JSXClosingElement; - var JSXElement = (function () { - function JSXElement(openingElement, children, closingElement) { - this.type = jsx_syntax_1.JSXSyntax.JSXElement; - this.openingElement = openingElement; - this.children = children; - this.closingElement = closingElement; - } - return JSXElement; - }()); - exports.JSXElement = JSXElement; - var JSXEmptyExpression = (function () { - function JSXEmptyExpression() { - this.type = jsx_syntax_1.JSXSyntax.JSXEmptyExpression; - } - return JSXEmptyExpression; - }()); - exports.JSXEmptyExpression = JSXEmptyExpression; - var JSXExpressionContainer = (function () { - function JSXExpressionContainer(expression) { - this.type = jsx_syntax_1.JSXSyntax.JSXExpressionContainer; - this.expression = expression; - } - return JSXExpressionContainer; - }()); - exports.JSXExpressionContainer = JSXExpressionContainer; - var JSXIdentifier = (function () { - function JSXIdentifier(name) { - this.type = jsx_syntax_1.JSXSyntax.JSXIdentifier; - this.name = name; - } - return JSXIdentifier; - }()); - exports.JSXIdentifier = JSXIdentifier; - var JSXMemberExpression = (function () { - function JSXMemberExpression(object, property) { - this.type = jsx_syntax_1.JSXSyntax.JSXMemberExpression; - this.object = object; - this.property = property; - } - return JSXMemberExpression; - }()); - exports.JSXMemberExpression = JSXMemberExpression; - var JSXAttribute = (function () { - function JSXAttribute(name, value) { - this.type = jsx_syntax_1.JSXSyntax.JSXAttribute; - this.name = name; - this.value = value; - } - return JSXAttribute; - }()); - exports.JSXAttribute = JSXAttribute; - var JSXNamespacedName = (function () { - function JSXNamespacedName(namespace, name) { - this.type = jsx_syntax_1.JSXSyntax.JSXNamespacedName; - this.namespace = namespace; - this.name = name; - } - return JSXNamespacedName; - }()); - exports.JSXNamespacedName = JSXNamespacedName; - var JSXOpeningElement = (function () { - function JSXOpeningElement(name, selfClosing, attributes) { - this.type = jsx_syntax_1.JSXSyntax.JSXOpeningElement; - this.name = name; - this.selfClosing = selfClosing; - this.attributes = attributes; - } - return JSXOpeningElement; - }()); - exports.JSXOpeningElement = JSXOpeningElement; - var JSXSpreadAttribute = (function () { - function JSXSpreadAttribute(argument) { - this.type = jsx_syntax_1.JSXSyntax.JSXSpreadAttribute; - this.argument = argument; - } - return JSXSpreadAttribute; - }()); - exports.JSXSpreadAttribute = JSXSpreadAttribute; - var JSXText = (function () { - function JSXText(value, raw) { - this.type = jsx_syntax_1.JSXSyntax.JSXText; - this.value = value; - this.raw = raw; - } - return JSXText; - }()); - exports.JSXText = JSXText; - - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.JSXSyntax = { - JSXAttribute: 'JSXAttribute', - JSXClosingElement: 'JSXClosingElement', - JSXElement: 'JSXElement', - JSXEmptyExpression: 'JSXEmptyExpression', - JSXExpressionContainer: 'JSXExpressionContainer', - JSXIdentifier: 'JSXIdentifier', - JSXMemberExpression: 'JSXMemberExpression', - JSXNamespacedName: 'JSXNamespacedName', - JSXOpeningElement: 'JSXOpeningElement', - JSXSpreadAttribute: 'JSXSpreadAttribute', - JSXText: 'JSXText' - }; - - -/***/ }, -/* 7 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var syntax_1 = __webpack_require__(2); - /* tslint:disable:max-classes-per-file */ - var ArrayExpression = (function () { - function ArrayExpression(elements) { - this.type = syntax_1.Syntax.ArrayExpression; - this.elements = elements; - } - return ArrayExpression; - }()); - exports.ArrayExpression = ArrayExpression; - var ArrayPattern = (function () { - function ArrayPattern(elements) { - this.type = syntax_1.Syntax.ArrayPattern; - this.elements = elements; - } - return ArrayPattern; - }()); - exports.ArrayPattern = ArrayPattern; - var ArrowFunctionExpression = (function () { - function ArrowFunctionExpression(params, body, expression) { - this.type = syntax_1.Syntax.ArrowFunctionExpression; - this.id = null; - this.params = params; - this.body = body; - this.generator = false; - this.expression = expression; - this.async = false; - } - return ArrowFunctionExpression; - }()); - exports.ArrowFunctionExpression = ArrowFunctionExpression; - var AssignmentExpression = (function () { - function AssignmentExpression(operator, left, right) { - this.type = syntax_1.Syntax.AssignmentExpression; - this.operator = operator; - this.left = left; - this.right = right; - } - return AssignmentExpression; - }()); - exports.AssignmentExpression = AssignmentExpression; - var AssignmentPattern = (function () { - function AssignmentPattern(left, right) { - this.type = syntax_1.Syntax.AssignmentPattern; - this.left = left; - this.right = right; - } - return AssignmentPattern; - }()); - exports.AssignmentPattern = AssignmentPattern; - var AsyncArrowFunctionExpression = (function () { - function AsyncArrowFunctionExpression(params, body, expression) { - this.type = syntax_1.Syntax.ArrowFunctionExpression; - this.id = null; - this.params = params; - this.body = body; - this.generator = false; - this.expression = expression; - this.async = true; - } - return AsyncArrowFunctionExpression; - }()); - exports.AsyncArrowFunctionExpression = AsyncArrowFunctionExpression; - var AsyncFunctionDeclaration = (function () { - function AsyncFunctionDeclaration(id, params, body) { - this.type = syntax_1.Syntax.FunctionDeclaration; - this.id = id; - this.params = params; - this.body = body; - this.generator = false; - this.expression = false; - this.async = true; - } - return AsyncFunctionDeclaration; - }()); - exports.AsyncFunctionDeclaration = AsyncFunctionDeclaration; - var AsyncFunctionExpression = (function () { - function AsyncFunctionExpression(id, params, body) { - this.type = syntax_1.Syntax.FunctionExpression; - this.id = id; - this.params = params; - this.body = body; - this.generator = false; - this.expression = false; - this.async = true; - } - return AsyncFunctionExpression; - }()); - exports.AsyncFunctionExpression = AsyncFunctionExpression; - var AwaitExpression = (function () { - function AwaitExpression(argument) { - this.type = syntax_1.Syntax.AwaitExpression; - this.argument = argument; - } - return AwaitExpression; - }()); - exports.AwaitExpression = AwaitExpression; - var BinaryExpression = (function () { - function BinaryExpression(operator, left, right) { - var logical = (operator === '||' || operator === '&&'); - this.type = logical ? syntax_1.Syntax.LogicalExpression : syntax_1.Syntax.BinaryExpression; - this.operator = operator; - this.left = left; - this.right = right; - } - return BinaryExpression; - }()); - exports.BinaryExpression = BinaryExpression; - var BlockStatement = (function () { - function BlockStatement(body) { - this.type = syntax_1.Syntax.BlockStatement; - this.body = body; - } - return BlockStatement; - }()); - exports.BlockStatement = BlockStatement; - var BreakStatement = (function () { - function BreakStatement(label) { - this.type = syntax_1.Syntax.BreakStatement; - this.label = label; - } - return BreakStatement; - }()); - exports.BreakStatement = BreakStatement; - var CallExpression = (function () { - function CallExpression(callee, args) { - this.type = syntax_1.Syntax.CallExpression; - this.callee = callee; - this.arguments = args; - } - return CallExpression; - }()); - exports.CallExpression = CallExpression; - var CatchClause = (function () { - function CatchClause(param, body) { - this.type = syntax_1.Syntax.CatchClause; - this.param = param; - this.body = body; - } - return CatchClause; - }()); - exports.CatchClause = CatchClause; - var ClassBody = (function () { - function ClassBody(body) { - this.type = syntax_1.Syntax.ClassBody; - this.body = body; - } - return ClassBody; - }()); - exports.ClassBody = ClassBody; - var ClassDeclaration = (function () { - function ClassDeclaration(id, superClass, body) { - this.type = syntax_1.Syntax.ClassDeclaration; - this.id = id; - this.superClass = superClass; - this.body = body; - } - return ClassDeclaration; - }()); - exports.ClassDeclaration = ClassDeclaration; - var ClassExpression = (function () { - function ClassExpression(id, superClass, body) { - this.type = syntax_1.Syntax.ClassExpression; - this.id = id; - this.superClass = superClass; - this.body = body; - } - return ClassExpression; - }()); - exports.ClassExpression = ClassExpression; - var ComputedMemberExpression = (function () { - function ComputedMemberExpression(object, property) { - this.type = syntax_1.Syntax.MemberExpression; - this.computed = true; - this.object = object; - this.property = property; - } - return ComputedMemberExpression; - }()); - exports.ComputedMemberExpression = ComputedMemberExpression; - var ConditionalExpression = (function () { - function ConditionalExpression(test, consequent, alternate) { - this.type = syntax_1.Syntax.ConditionalExpression; - this.test = test; - this.consequent = consequent; - this.alternate = alternate; - } - return ConditionalExpression; - }()); - exports.ConditionalExpression = ConditionalExpression; - var ContinueStatement = (function () { - function ContinueStatement(label) { - this.type = syntax_1.Syntax.ContinueStatement; - this.label = label; - } - return ContinueStatement; - }()); - exports.ContinueStatement = ContinueStatement; - var DebuggerStatement = (function () { - function DebuggerStatement() { - this.type = syntax_1.Syntax.DebuggerStatement; - } - return DebuggerStatement; - }()); - exports.DebuggerStatement = DebuggerStatement; - var Directive = (function () { - function Directive(expression, directive) { - this.type = syntax_1.Syntax.ExpressionStatement; - this.expression = expression; - this.directive = directive; - } - return Directive; - }()); - exports.Directive = Directive; - var DoWhileStatement = (function () { - function DoWhileStatement(body, test) { - this.type = syntax_1.Syntax.DoWhileStatement; - this.body = body; - this.test = test; - } - return DoWhileStatement; - }()); - exports.DoWhileStatement = DoWhileStatement; - var EmptyStatement = (function () { - function EmptyStatement() { - this.type = syntax_1.Syntax.EmptyStatement; - } - return EmptyStatement; - }()); - exports.EmptyStatement = EmptyStatement; - var ExportAllDeclaration = (function () { - function ExportAllDeclaration(source) { - this.type = syntax_1.Syntax.ExportAllDeclaration; - this.source = source; - } - return ExportAllDeclaration; - }()); - exports.ExportAllDeclaration = ExportAllDeclaration; - var ExportDefaultDeclaration = (function () { - function ExportDefaultDeclaration(declaration) { - this.type = syntax_1.Syntax.ExportDefaultDeclaration; - this.declaration = declaration; - } - return ExportDefaultDeclaration; - }()); - exports.ExportDefaultDeclaration = ExportDefaultDeclaration; - var ExportNamedDeclaration = (function () { - function ExportNamedDeclaration(declaration, specifiers, source) { - this.type = syntax_1.Syntax.ExportNamedDeclaration; - this.declaration = declaration; - this.specifiers = specifiers; - this.source = source; - } - return ExportNamedDeclaration; - }()); - exports.ExportNamedDeclaration = ExportNamedDeclaration; - var ExportSpecifier = (function () { - function ExportSpecifier(local, exported) { - this.type = syntax_1.Syntax.ExportSpecifier; - this.exported = exported; - this.local = local; - } - return ExportSpecifier; - }()); - exports.ExportSpecifier = ExportSpecifier; - var ExpressionStatement = (function () { - function ExpressionStatement(expression) { - this.type = syntax_1.Syntax.ExpressionStatement; - this.expression = expression; - } - return ExpressionStatement; - }()); - exports.ExpressionStatement = ExpressionStatement; - var ForInStatement = (function () { - function ForInStatement(left, right, body) { - this.type = syntax_1.Syntax.ForInStatement; - this.left = left; - this.right = right; - this.body = body; - this.each = false; - } - return ForInStatement; - }()); - exports.ForInStatement = ForInStatement; - var ForOfStatement = (function () { - function ForOfStatement(left, right, body) { - this.type = syntax_1.Syntax.ForOfStatement; - this.left = left; - this.right = right; - this.body = body; - } - return ForOfStatement; - }()); - exports.ForOfStatement = ForOfStatement; - var ForStatement = (function () { - function ForStatement(init, test, update, body) { - this.type = syntax_1.Syntax.ForStatement; - this.init = init; - this.test = test; - this.update = update; - this.body = body; - } - return ForStatement; - }()); - exports.ForStatement = ForStatement; - var FunctionDeclaration = (function () { - function FunctionDeclaration(id, params, body, generator) { - this.type = syntax_1.Syntax.FunctionDeclaration; - this.id = id; - this.params = params; - this.body = body; - this.generator = generator; - this.expression = false; - this.async = false; - } - return FunctionDeclaration; - }()); - exports.FunctionDeclaration = FunctionDeclaration; - var FunctionExpression = (function () { - function FunctionExpression(id, params, body, generator) { - this.type = syntax_1.Syntax.FunctionExpression; - this.id = id; - this.params = params; - this.body = body; - this.generator = generator; - this.expression = false; - this.async = false; - } - return FunctionExpression; - }()); - exports.FunctionExpression = FunctionExpression; - var Identifier = (function () { - function Identifier(name) { - this.type = syntax_1.Syntax.Identifier; - this.name = name; - } - return Identifier; - }()); - exports.Identifier = Identifier; - var IfStatement = (function () { - function IfStatement(test, consequent, alternate) { - this.type = syntax_1.Syntax.IfStatement; - this.test = test; - this.consequent = consequent; - this.alternate = alternate; - } - return IfStatement; - }()); - exports.IfStatement = IfStatement; - var ImportDeclaration = (function () { - function ImportDeclaration(specifiers, source) { - this.type = syntax_1.Syntax.ImportDeclaration; - this.specifiers = specifiers; - this.source = source; - } - return ImportDeclaration; - }()); - exports.ImportDeclaration = ImportDeclaration; - var ImportDefaultSpecifier = (function () { - function ImportDefaultSpecifier(local) { - this.type = syntax_1.Syntax.ImportDefaultSpecifier; - this.local = local; - } - return ImportDefaultSpecifier; - }()); - exports.ImportDefaultSpecifier = ImportDefaultSpecifier; - var ImportNamespaceSpecifier = (function () { - function ImportNamespaceSpecifier(local) { - this.type = syntax_1.Syntax.ImportNamespaceSpecifier; - this.local = local; - } - return ImportNamespaceSpecifier; - }()); - exports.ImportNamespaceSpecifier = ImportNamespaceSpecifier; - var ImportSpecifier = (function () { - function ImportSpecifier(local, imported) { - this.type = syntax_1.Syntax.ImportSpecifier; - this.local = local; - this.imported = imported; - } - return ImportSpecifier; - }()); - exports.ImportSpecifier = ImportSpecifier; - var LabeledStatement = (function () { - function LabeledStatement(label, body) { - this.type = syntax_1.Syntax.LabeledStatement; - this.label = label; - this.body = body; - } - return LabeledStatement; - }()); - exports.LabeledStatement = LabeledStatement; - var Literal = (function () { - function Literal(value, raw) { - this.type = syntax_1.Syntax.Literal; - this.value = value; - this.raw = raw; - } - return Literal; - }()); - exports.Literal = Literal; - var MetaProperty = (function () { - function MetaProperty(meta, property) { - this.type = syntax_1.Syntax.MetaProperty; - this.meta = meta; - this.property = property; - } - return MetaProperty; - }()); - exports.MetaProperty = MetaProperty; - var MethodDefinition = (function () { - function MethodDefinition(key, computed, value, kind, isStatic) { - this.type = syntax_1.Syntax.MethodDefinition; - this.key = key; - this.computed = computed; - this.value = value; - this.kind = kind; - this.static = isStatic; - } - return MethodDefinition; - }()); - exports.MethodDefinition = MethodDefinition; - var Module = (function () { - function Module(body) { - this.type = syntax_1.Syntax.Program; - this.body = body; - this.sourceType = 'module'; - } - return Module; - }()); - exports.Module = Module; - var NewExpression = (function () { - function NewExpression(callee, args) { - this.type = syntax_1.Syntax.NewExpression; - this.callee = callee; - this.arguments = args; - } - return NewExpression; - }()); - exports.NewExpression = NewExpression; - var ObjectExpression = (function () { - function ObjectExpression(properties) { - this.type = syntax_1.Syntax.ObjectExpression; - this.properties = properties; - } - return ObjectExpression; - }()); - exports.ObjectExpression = ObjectExpression; - var ObjectPattern = (function () { - function ObjectPattern(properties) { - this.type = syntax_1.Syntax.ObjectPattern; - this.properties = properties; - } - return ObjectPattern; - }()); - exports.ObjectPattern = ObjectPattern; - var Property = (function () { - function Property(kind, key, computed, value, method, shorthand) { - this.type = syntax_1.Syntax.Property; - this.key = key; - this.computed = computed; - this.value = value; - this.kind = kind; - this.method = method; - this.shorthand = shorthand; - } - return Property; - }()); - exports.Property = Property; - var RegexLiteral = (function () { - function RegexLiteral(value, raw, pattern, flags) { - this.type = syntax_1.Syntax.Literal; - this.value = value; - this.raw = raw; - this.regex = { pattern: pattern, flags: flags }; - } - return RegexLiteral; - }()); - exports.RegexLiteral = RegexLiteral; - var RestElement = (function () { - function RestElement(argument) { - this.type = syntax_1.Syntax.RestElement; - this.argument = argument; - } - return RestElement; - }()); - exports.RestElement = RestElement; - var ReturnStatement = (function () { - function ReturnStatement(argument) { - this.type = syntax_1.Syntax.ReturnStatement; - this.argument = argument; - } - return ReturnStatement; - }()); - exports.ReturnStatement = ReturnStatement; - var Script = (function () { - function Script(body) { - this.type = syntax_1.Syntax.Program; - this.body = body; - this.sourceType = 'script'; - } - return Script; - }()); - exports.Script = Script; - var SequenceExpression = (function () { - function SequenceExpression(expressions) { - this.type = syntax_1.Syntax.SequenceExpression; - this.expressions = expressions; - } - return SequenceExpression; - }()); - exports.SequenceExpression = SequenceExpression; - var SpreadElement = (function () { - function SpreadElement(argument) { - this.type = syntax_1.Syntax.SpreadElement; - this.argument = argument; - } - return SpreadElement; - }()); - exports.SpreadElement = SpreadElement; - var StaticMemberExpression = (function () { - function StaticMemberExpression(object, property) { - this.type = syntax_1.Syntax.MemberExpression; - this.computed = false; - this.object = object; - this.property = property; - } - return StaticMemberExpression; - }()); - exports.StaticMemberExpression = StaticMemberExpression; - var Super = (function () { - function Super() { - this.type = syntax_1.Syntax.Super; - } - return Super; - }()); - exports.Super = Super; - var SwitchCase = (function () { - function SwitchCase(test, consequent) { - this.type = syntax_1.Syntax.SwitchCase; - this.test = test; - this.consequent = consequent; - } - return SwitchCase; - }()); - exports.SwitchCase = SwitchCase; - var SwitchStatement = (function () { - function SwitchStatement(discriminant, cases) { - this.type = syntax_1.Syntax.SwitchStatement; - this.discriminant = discriminant; - this.cases = cases; - } - return SwitchStatement; - }()); - exports.SwitchStatement = SwitchStatement; - var TaggedTemplateExpression = (function () { - function TaggedTemplateExpression(tag, quasi) { - this.type = syntax_1.Syntax.TaggedTemplateExpression; - this.tag = tag; - this.quasi = quasi; - } - return TaggedTemplateExpression; - }()); - exports.TaggedTemplateExpression = TaggedTemplateExpression; - var TemplateElement = (function () { - function TemplateElement(value, tail) { - this.type = syntax_1.Syntax.TemplateElement; - this.value = value; - this.tail = tail; - } - return TemplateElement; - }()); - exports.TemplateElement = TemplateElement; - var TemplateLiteral = (function () { - function TemplateLiteral(quasis, expressions) { - this.type = syntax_1.Syntax.TemplateLiteral; - this.quasis = quasis; - this.expressions = expressions; - } - return TemplateLiteral; - }()); - exports.TemplateLiteral = TemplateLiteral; - var ThisExpression = (function () { - function ThisExpression() { - this.type = syntax_1.Syntax.ThisExpression; - } - return ThisExpression; - }()); - exports.ThisExpression = ThisExpression; - var ThrowStatement = (function () { - function ThrowStatement(argument) { - this.type = syntax_1.Syntax.ThrowStatement; - this.argument = argument; - } - return ThrowStatement; - }()); - exports.ThrowStatement = ThrowStatement; - var TryStatement = (function () { - function TryStatement(block, handler, finalizer) { - this.type = syntax_1.Syntax.TryStatement; - this.block = block; - this.handler = handler; - this.finalizer = finalizer; - } - return TryStatement; - }()); - exports.TryStatement = TryStatement; - var UnaryExpression = (function () { - function UnaryExpression(operator, argument) { - this.type = syntax_1.Syntax.UnaryExpression; - this.operator = operator; - this.argument = argument; - this.prefix = true; - } - return UnaryExpression; - }()); - exports.UnaryExpression = UnaryExpression; - var UpdateExpression = (function () { - function UpdateExpression(operator, argument, prefix) { - this.type = syntax_1.Syntax.UpdateExpression; - this.operator = operator; - this.argument = argument; - this.prefix = prefix; - } - return UpdateExpression; - }()); - exports.UpdateExpression = UpdateExpression; - var VariableDeclaration = (function () { - function VariableDeclaration(declarations, kind) { - this.type = syntax_1.Syntax.VariableDeclaration; - this.declarations = declarations; - this.kind = kind; - } - return VariableDeclaration; - }()); - exports.VariableDeclaration = VariableDeclaration; - var VariableDeclarator = (function () { - function VariableDeclarator(id, init) { - this.type = syntax_1.Syntax.VariableDeclarator; - this.id = id; - this.init = init; - } - return VariableDeclarator; - }()); - exports.VariableDeclarator = VariableDeclarator; - var WhileStatement = (function () { - function WhileStatement(test, body) { - this.type = syntax_1.Syntax.WhileStatement; - this.test = test; - this.body = body; - } - return WhileStatement; - }()); - exports.WhileStatement = WhileStatement; - var WithStatement = (function () { - function WithStatement(object, body) { - this.type = syntax_1.Syntax.WithStatement; - this.object = object; - this.body = body; - } - return WithStatement; - }()); - exports.WithStatement = WithStatement; - var YieldExpression = (function () { - function YieldExpression(argument, delegate) { - this.type = syntax_1.Syntax.YieldExpression; - this.argument = argument; - this.delegate = delegate; - } - return YieldExpression; - }()); - exports.YieldExpression = YieldExpression; - - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var assert_1 = __webpack_require__(9); - var error_handler_1 = __webpack_require__(10); - var messages_1 = __webpack_require__(11); - var Node = __webpack_require__(7); - var scanner_1 = __webpack_require__(12); - var syntax_1 = __webpack_require__(2); - var token_1 = __webpack_require__(13); - var ArrowParameterPlaceHolder = 'ArrowParameterPlaceHolder'; - var Parser = (function () { - function Parser(code, options, delegate) { - if (options === void 0) { options = {}; } - this.config = { - range: (typeof options.range === 'boolean') && options.range, - loc: (typeof options.loc === 'boolean') && options.loc, - source: null, - tokens: (typeof options.tokens === 'boolean') && options.tokens, - comment: (typeof options.comment === 'boolean') && options.comment, - tolerant: (typeof options.tolerant === 'boolean') && options.tolerant - }; - if (this.config.loc && options.source && options.source !== null) { - this.config.source = String(options.source); - } - this.delegate = delegate; - this.errorHandler = new error_handler_1.ErrorHandler(); - this.errorHandler.tolerant = this.config.tolerant; - this.scanner = new scanner_1.Scanner(code, this.errorHandler); - this.scanner.trackComment = this.config.comment; - this.operatorPrecedence = { - ')': 0, - ';': 0, - ',': 0, - '=': 0, - ']': 0, - '||': 1, - '&&': 2, - '|': 3, - '^': 4, - '&': 5, - '==': 6, - '!=': 6, - '===': 6, - '!==': 6, - '<': 7, - '>': 7, - '<=': 7, - '>=': 7, - '<<': 8, - '>>': 8, - '>>>': 8, - '+': 9, - '-': 9, - '*': 11, - '/': 11, - '%': 11 - }; - this.lookahead = { - type: 2 /* EOF */, - value: '', - lineNumber: this.scanner.lineNumber, - lineStart: 0, - start: 0, - end: 0 - }; - this.hasLineTerminator = false; - this.context = { - isModule: false, - await: false, - allowIn: true, - allowStrictDirective: true, - allowYield: true, - firstCoverInitializedNameError: null, - isAssignmentTarget: false, - isBindingElement: false, - inFunctionBody: false, - inIteration: false, - inSwitch: false, - labelSet: {}, - strict: false - }; - this.tokens = []; - this.startMarker = { - index: 0, - line: this.scanner.lineNumber, - column: 0 - }; - this.lastMarker = { - index: 0, - line: this.scanner.lineNumber, - column: 0 - }; - this.nextToken(); - this.lastMarker = { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - } - Parser.prototype.throwError = function (messageFormat) { - var values = []; - for (var _i = 1; _i < arguments.length; _i++) { - values[_i - 1] = arguments[_i]; - } - var args = Array.prototype.slice.call(arguments, 1); - var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { - assert_1.assert(idx < args.length, 'Message reference must be in range'); - return args[idx]; - }); - var index = this.lastMarker.index; - var line = this.lastMarker.line; - var column = this.lastMarker.column + 1; - throw this.errorHandler.createError(index, line, column, msg); - }; - Parser.prototype.tolerateError = function (messageFormat) { - var values = []; - for (var _i = 1; _i < arguments.length; _i++) { - values[_i - 1] = arguments[_i]; - } - var args = Array.prototype.slice.call(arguments, 1); - var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { - assert_1.assert(idx < args.length, 'Message reference must be in range'); - return args[idx]; - }); - var index = this.lastMarker.index; - var line = this.scanner.lineNumber; - var column = this.lastMarker.column + 1; - this.errorHandler.tolerateError(index, line, column, msg); - }; - // Throw an exception because of the token. - Parser.prototype.unexpectedTokenError = function (token, message) { - var msg = message || messages_1.Messages.UnexpectedToken; - var value; - if (token) { - if (!message) { - msg = (token.type === 2 /* EOF */) ? messages_1.Messages.UnexpectedEOS : - (token.type === 3 /* Identifier */) ? messages_1.Messages.UnexpectedIdentifier : - (token.type === 6 /* NumericLiteral */) ? messages_1.Messages.UnexpectedNumber : - (token.type === 8 /* StringLiteral */) ? messages_1.Messages.UnexpectedString : - (token.type === 10 /* Template */) ? messages_1.Messages.UnexpectedTemplate : - messages_1.Messages.UnexpectedToken; - if (token.type === 4 /* Keyword */) { - if (this.scanner.isFutureReservedWord(token.value)) { - msg = messages_1.Messages.UnexpectedReserved; - } - else if (this.context.strict && this.scanner.isStrictModeReservedWord(token.value)) { - msg = messages_1.Messages.StrictReservedWord; - } - } - } - value = token.value; - } - else { - value = 'ILLEGAL'; - } - msg = msg.replace('%0', value); - if (token && typeof token.lineNumber === 'number') { - var index = token.start; - var line = token.lineNumber; - var lastMarkerLineStart = this.lastMarker.index - this.lastMarker.column; - var column = token.start - lastMarkerLineStart + 1; - return this.errorHandler.createError(index, line, column, msg); - } - else { - var index = this.lastMarker.index; - var line = this.lastMarker.line; - var column = this.lastMarker.column + 1; - return this.errorHandler.createError(index, line, column, msg); - } - }; - Parser.prototype.throwUnexpectedToken = function (token, message) { - throw this.unexpectedTokenError(token, message); - }; - Parser.prototype.tolerateUnexpectedToken = function (token, message) { - this.errorHandler.tolerate(this.unexpectedTokenError(token, message)); - }; - Parser.prototype.collectComments = function () { - if (!this.config.comment) { - this.scanner.scanComments(); - } - else { - var comments = this.scanner.scanComments(); - if (comments.length > 0 && this.delegate) { - for (var i = 0; i < comments.length; ++i) { - var e = comments[i]; - var node = void 0; - node = { - type: e.multiLine ? 'BlockComment' : 'LineComment', - value: this.scanner.source.slice(e.slice[0], e.slice[1]) - }; - if (this.config.range) { - node.range = e.range; - } - if (this.config.loc) { - node.loc = e.loc; - } - var metadata = { - start: { - line: e.loc.start.line, - column: e.loc.start.column, - offset: e.range[0] - }, - end: { - line: e.loc.end.line, - column: e.loc.end.column, - offset: e.range[1] - } - }; - this.delegate(node, metadata); - } - } - } - }; - // From internal representation to an external structure - Parser.prototype.getTokenRaw = function (token) { - return this.scanner.source.slice(token.start, token.end); - }; - Parser.prototype.convertToken = function (token) { - var t = { - type: token_1.TokenName[token.type], - value: this.getTokenRaw(token) - }; - if (this.config.range) { - t.range = [token.start, token.end]; - } - if (this.config.loc) { - t.loc = { - start: { - line: this.startMarker.line, - column: this.startMarker.column - }, - end: { - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - } - }; - } - if (token.type === 9 /* RegularExpression */) { - var pattern = token.pattern; - var flags = token.flags; - t.regex = { pattern: pattern, flags: flags }; - } - return t; - }; - Parser.prototype.nextToken = function () { - var token = this.lookahead; - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - this.collectComments(); - if (this.scanner.index !== this.startMarker.index) { - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - } - var next = this.scanner.lex(); - this.hasLineTerminator = (token.lineNumber !== next.lineNumber); - if (next && this.context.strict && next.type === 3 /* Identifier */) { - if (this.scanner.isStrictModeReservedWord(next.value)) { - next.type = 4 /* Keyword */; - } - } - this.lookahead = next; - if (this.config.tokens && next.type !== 2 /* EOF */) { - this.tokens.push(this.convertToken(next)); - } - return token; - }; - Parser.prototype.nextRegexToken = function () { - this.collectComments(); - var token = this.scanner.scanRegExp(); - if (this.config.tokens) { - // Pop the previous token, '/' or '/=' - // This is added from the lookahead token. - this.tokens.pop(); - this.tokens.push(this.convertToken(token)); - } - // Prime the next lookahead. - this.lookahead = token; - this.nextToken(); - return token; - }; - Parser.prototype.createNode = function () { - return { - index: this.startMarker.index, - line: this.startMarker.line, - column: this.startMarker.column - }; - }; - Parser.prototype.startNode = function (token, lastLineStart) { - if (lastLineStart === void 0) { lastLineStart = 0; } - var column = token.start - token.lineStart; - var line = token.lineNumber; - if (column < 0) { - column += lastLineStart; - line--; - } - return { - index: token.start, - line: line, - column: column - }; - }; - Parser.prototype.finalize = function (marker, node) { - if (this.config.range) { - node.range = [marker.index, this.lastMarker.index]; - } - if (this.config.loc) { - node.loc = { - start: { - line: marker.line, - column: marker.column, - }, - end: { - line: this.lastMarker.line, - column: this.lastMarker.column - } - }; - if (this.config.source) { - node.loc.source = this.config.source; - } - } - if (this.delegate) { - var metadata = { - start: { - line: marker.line, - column: marker.column, - offset: marker.index - }, - end: { - line: this.lastMarker.line, - column: this.lastMarker.column, - offset: this.lastMarker.index - } - }; - this.delegate(node, metadata); - } - return node; - }; - // Expect the next token to match the specified punctuator. - // If not, an exception will be thrown. - Parser.prototype.expect = function (value) { - var token = this.nextToken(); - if (token.type !== 7 /* Punctuator */ || token.value !== value) { - this.throwUnexpectedToken(token); - } - }; - // Quietly expect a comma when in tolerant mode, otherwise delegates to expect(). - Parser.prototype.expectCommaSeparator = function () { - if (this.config.tolerant) { - var token = this.lookahead; - if (token.type === 7 /* Punctuator */ && token.value === ',') { - this.nextToken(); - } - else if (token.type === 7 /* Punctuator */ && token.value === ';') { - this.nextToken(); - this.tolerateUnexpectedToken(token); - } - else { - this.tolerateUnexpectedToken(token, messages_1.Messages.UnexpectedToken); - } - } - else { - this.expect(','); - } - }; - // Expect the next token to match the specified keyword. - // If not, an exception will be thrown. - Parser.prototype.expectKeyword = function (keyword) { - var token = this.nextToken(); - if (token.type !== 4 /* Keyword */ || token.value !== keyword) { - this.throwUnexpectedToken(token); - } - }; - // Return true if the next token matches the specified punctuator. - Parser.prototype.match = function (value) { - return this.lookahead.type === 7 /* Punctuator */ && this.lookahead.value === value; - }; - // Return true if the next token matches the specified keyword - Parser.prototype.matchKeyword = function (keyword) { - return this.lookahead.type === 4 /* Keyword */ && this.lookahead.value === keyword; - }; - // Return true if the next token matches the specified contextual keyword - // (where an identifier is sometimes a keyword depending on the context) - Parser.prototype.matchContextualKeyword = function (keyword) { - return this.lookahead.type === 3 /* Identifier */ && this.lookahead.value === keyword; - }; - // Return true if the next token is an assignment operator - Parser.prototype.matchAssign = function () { - if (this.lookahead.type !== 7 /* Punctuator */) { - return false; - } - var op = this.lookahead.value; - return op === '=' || - op === '*=' || - op === '**=' || - op === '/=' || - op === '%=' || - op === '+=' || - op === '-=' || - op === '<<=' || - op === '>>=' || - op === '>>>=' || - op === '&=' || - op === '^=' || - op === '|='; - }; - // Cover grammar support. - // - // When an assignment expression position starts with an left parenthesis, the determination of the type - // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) - // or the first comma. This situation also defers the determination of all the expressions nested in the pair. - // - // There are three productions that can be parsed in a parentheses pair that needs to be determined - // after the outermost pair is closed. They are: - // - // 1. AssignmentExpression - // 2. BindingElements - // 3. AssignmentTargets - // - // In order to avoid exponential backtracking, we use two flags to denote if the production can be - // binding element or assignment target. - // - // The three productions have the relationship: - // - // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression - // - // with a single exception that CoverInitializedName when used directly in an Expression, generates - // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the - // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. - // - // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not - // effect the current flags. This means the production the parser parses is only used as an expression. Therefore - // the CoverInitializedName check is conducted. - // - // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates - // the flags outside of the parser. This means the production the parser parses is used as a part of a potential - // pattern. The CoverInitializedName check is deferred. - Parser.prototype.isolateCoverGrammar = function (parseFunction) { - var previousIsBindingElement = this.context.isBindingElement; - var previousIsAssignmentTarget = this.context.isAssignmentTarget; - var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; - this.context.isBindingElement = true; - this.context.isAssignmentTarget = true; - this.context.firstCoverInitializedNameError = null; - var result = parseFunction.call(this); - if (this.context.firstCoverInitializedNameError !== null) { - this.throwUnexpectedToken(this.context.firstCoverInitializedNameError); - } - this.context.isBindingElement = previousIsBindingElement; - this.context.isAssignmentTarget = previousIsAssignmentTarget; - this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError; - return result; - }; - Parser.prototype.inheritCoverGrammar = function (parseFunction) { - var previousIsBindingElement = this.context.isBindingElement; - var previousIsAssignmentTarget = this.context.isAssignmentTarget; - var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; - this.context.isBindingElement = true; - this.context.isAssignmentTarget = true; - this.context.firstCoverInitializedNameError = null; - var result = parseFunction.call(this); - this.context.isBindingElement = this.context.isBindingElement && previousIsBindingElement; - this.context.isAssignmentTarget = this.context.isAssignmentTarget && previousIsAssignmentTarget; - this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.context.firstCoverInitializedNameError; - return result; - }; - Parser.prototype.consumeSemicolon = function () { - if (this.match(';')) { - this.nextToken(); - } - else if (!this.hasLineTerminator) { - if (this.lookahead.type !== 2 /* EOF */ && !this.match('}')) { - this.throwUnexpectedToken(this.lookahead); - } - this.lastMarker.index = this.startMarker.index; - this.lastMarker.line = this.startMarker.line; - this.lastMarker.column = this.startMarker.column; - } - }; - // https://tc39.github.io/ecma262/#sec-primary-expression - Parser.prototype.parsePrimaryExpression = function () { - var node = this.createNode(); - var expr; - var token, raw; - switch (this.lookahead.type) { - case 3 /* Identifier */: - if ((this.context.isModule || this.context.await) && this.lookahead.value === 'await') { - this.tolerateUnexpectedToken(this.lookahead); - } - expr = this.matchAsyncFunction() ? this.parseFunctionExpression() : this.finalize(node, new Node.Identifier(this.nextToken().value)); - break; - case 6 /* NumericLiteral */: - case 8 /* StringLiteral */: - if (this.context.strict && this.lookahead.octal) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.StrictOctalLiteral); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(token.value, raw)); - break; - case 1 /* BooleanLiteral */: - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(token.value === 'true', raw)); - break; - case 5 /* NullLiteral */: - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(null, raw)); - break; - case 10 /* Template */: - expr = this.parseTemplateLiteral(); - break; - case 7 /* Punctuator */: - switch (this.lookahead.value) { - case '(': - this.context.isBindingElement = false; - expr = this.inheritCoverGrammar(this.parseGroupExpression); - break; - case '[': - expr = this.inheritCoverGrammar(this.parseArrayInitializer); - break; - case '{': - expr = this.inheritCoverGrammar(this.parseObjectInitializer); - break; - case '/': - case '/=': - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - this.scanner.index = this.startMarker.index; - token = this.nextRegexToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.RegexLiteral(token.regex, raw, token.pattern, token.flags)); - break; - default: - expr = this.throwUnexpectedToken(this.nextToken()); - } - break; - case 4 /* Keyword */: - if (!this.context.strict && this.context.allowYield && this.matchKeyword('yield')) { - expr = this.parseIdentifierName(); - } - else if (!this.context.strict && this.matchKeyword('let')) { - expr = this.finalize(node, new Node.Identifier(this.nextToken().value)); - } - else { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - if (this.matchKeyword('function')) { - expr = this.parseFunctionExpression(); - } - else if (this.matchKeyword('this')) { - this.nextToken(); - expr = this.finalize(node, new Node.ThisExpression()); - } - else if (this.matchKeyword('class')) { - expr = this.parseClassExpression(); - } - else { - expr = this.throwUnexpectedToken(this.nextToken()); - } - } - break; - default: - expr = this.throwUnexpectedToken(this.nextToken()); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-array-initializer - Parser.prototype.parseSpreadElement = function () { - var node = this.createNode(); - this.expect('...'); - var arg = this.inheritCoverGrammar(this.parseAssignmentExpression); - return this.finalize(node, new Node.SpreadElement(arg)); - }; - Parser.prototype.parseArrayInitializer = function () { - var node = this.createNode(); - var elements = []; - this.expect('['); - while (!this.match(']')) { - if (this.match(',')) { - this.nextToken(); - elements.push(null); - } - else if (this.match('...')) { - var element = this.parseSpreadElement(); - if (!this.match(']')) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - this.expect(','); - } - elements.push(element); - } - else { - elements.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); - if (!this.match(']')) { - this.expect(','); - } - } - } - this.expect(']'); - return this.finalize(node, new Node.ArrayExpression(elements)); - }; - // https://tc39.github.io/ecma262/#sec-object-initializer - Parser.prototype.parsePropertyMethod = function (params) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = params.simple; - var body = this.isolateCoverGrammar(this.parseFunctionSourceElements); - if (this.context.strict && params.firstRestricted) { - this.tolerateUnexpectedToken(params.firstRestricted, params.message); - } - if (this.context.strict && params.stricted) { - this.tolerateUnexpectedToken(params.stricted, params.message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - return body; - }; - Parser.prototype.parsePropertyMethodFunction = function () { - var isGenerator = false; - var node = this.createNode(); - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var params = this.parseFormalParameters(); - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); - }; - Parser.prototype.parsePropertyMethodAsyncFunction = function () { - var node = this.createNode(); - var previousAllowYield = this.context.allowYield; - var previousAwait = this.context.await; - this.context.allowYield = false; - this.context.await = true; - var params = this.parseFormalParameters(); - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - this.context.await = previousAwait; - return this.finalize(node, new Node.AsyncFunctionExpression(null, params.params, method)); - }; - Parser.prototype.parseObjectPropertyKey = function () { - var node = this.createNode(); - var token = this.nextToken(); - var key; - switch (token.type) { - case 8 /* StringLiteral */: - case 6 /* NumericLiteral */: - if (this.context.strict && token.octal) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictOctalLiteral); - } - var raw = this.getTokenRaw(token); - key = this.finalize(node, new Node.Literal(token.value, raw)); - break; - case 3 /* Identifier */: - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 4 /* Keyword */: - key = this.finalize(node, new Node.Identifier(token.value)); - break; - case 7 /* Punctuator */: - if (token.value === '[') { - key = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.expect(']'); - } - else { - key = this.throwUnexpectedToken(token); - } - break; - default: - key = this.throwUnexpectedToken(token); - } - return key; - }; - Parser.prototype.isPropertyKey = function (key, value) { - return (key.type === syntax_1.Syntax.Identifier && key.name === value) || - (key.type === syntax_1.Syntax.Literal && key.value === value); - }; - Parser.prototype.parseObjectProperty = function (hasProto) { - var node = this.createNode(); - var token = this.lookahead; - var kind; - var key = null; - var value = null; - var computed = false; - var method = false; - var shorthand = false; - var isAsync = false; - if (token.type === 3 /* Identifier */) { - var id = token.value; - this.nextToken(); - computed = this.match('['); - isAsync = !this.hasLineTerminator && (id === 'async') && - !this.match(':') && !this.match('(') && !this.match('*') && !this.match(','); - key = isAsync ? this.parseObjectPropertyKey() : this.finalize(node, new Node.Identifier(id)); - } - else if (this.match('*')) { - this.nextToken(); - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - } - var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); - if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'get' && lookaheadPropertyKey) { - kind = 'get'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.context.allowYield = false; - value = this.parseGetterMethod(); - } - else if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'set' && lookaheadPropertyKey) { - kind = 'set'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseSetterMethod(); - } - else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { - kind = 'init'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseGeneratorMethod(); - method = true; - } - else { - if (!key) { - this.throwUnexpectedToken(this.lookahead); - } - kind = 'init'; - if (this.match(':') && !isAsync) { - if (!computed && this.isPropertyKey(key, '__proto__')) { - if (hasProto.value) { - this.tolerateError(messages_1.Messages.DuplicateProtoProperty); - } - hasProto.value = true; - } - this.nextToken(); - value = this.inheritCoverGrammar(this.parseAssignmentExpression); - } - else if (this.match('(')) { - value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); - method = true; - } - else if (token.type === 3 /* Identifier */) { - var id = this.finalize(node, new Node.Identifier(token.value)); - if (this.match('=')) { - this.context.firstCoverInitializedNameError = this.lookahead; - this.nextToken(); - shorthand = true; - var init = this.isolateCoverGrammar(this.parseAssignmentExpression); - value = this.finalize(node, new Node.AssignmentPattern(id, init)); - } - else { - shorthand = true; - value = id; - } - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - } - return this.finalize(node, new Node.Property(kind, key, computed, value, method, shorthand)); - }; - Parser.prototype.parseObjectInitializer = function () { - var node = this.createNode(); - this.expect('{'); - var properties = []; - var hasProto = { value: false }; - while (!this.match('}')) { - properties.push(this.parseObjectProperty(hasProto)); - if (!this.match('}')) { - this.expectCommaSeparator(); - } - } - this.expect('}'); - return this.finalize(node, new Node.ObjectExpression(properties)); - }; - // https://tc39.github.io/ecma262/#sec-template-literals - Parser.prototype.parseTemplateHead = function () { - assert_1.assert(this.lookahead.head, 'Template literal must start with a template head'); - var node = this.createNode(); - var token = this.nextToken(); - var raw = token.value; - var cooked = token.cooked; - return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); - }; - Parser.prototype.parseTemplateElement = function () { - if (this.lookahead.type !== 10 /* Template */) { - this.throwUnexpectedToken(); - } - var node = this.createNode(); - var token = this.nextToken(); - var raw = token.value; - var cooked = token.cooked; - return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); - }; - Parser.prototype.parseTemplateLiteral = function () { - var node = this.createNode(); - var expressions = []; - var quasis = []; - var quasi = this.parseTemplateHead(); - quasis.push(quasi); - while (!quasi.tail) { - expressions.push(this.parseExpression()); - quasi = this.parseTemplateElement(); - quasis.push(quasi); - } - return this.finalize(node, new Node.TemplateLiteral(quasis, expressions)); - }; - // https://tc39.github.io/ecma262/#sec-grouping-operator - Parser.prototype.reinterpretExpressionAsPattern = function (expr) { - switch (expr.type) { - case syntax_1.Syntax.Identifier: - case syntax_1.Syntax.MemberExpression: - case syntax_1.Syntax.RestElement: - case syntax_1.Syntax.AssignmentPattern: - break; - case syntax_1.Syntax.SpreadElement: - expr.type = syntax_1.Syntax.RestElement; - this.reinterpretExpressionAsPattern(expr.argument); - break; - case syntax_1.Syntax.ArrayExpression: - expr.type = syntax_1.Syntax.ArrayPattern; - for (var i = 0; i < expr.elements.length; i++) { - if (expr.elements[i] !== null) { - this.reinterpretExpressionAsPattern(expr.elements[i]); - } - } - break; - case syntax_1.Syntax.ObjectExpression: - expr.type = syntax_1.Syntax.ObjectPattern; - for (var i = 0; i < expr.properties.length; i++) { - this.reinterpretExpressionAsPattern(expr.properties[i].value); - } - break; - case syntax_1.Syntax.AssignmentExpression: - expr.type = syntax_1.Syntax.AssignmentPattern; - delete expr.operator; - this.reinterpretExpressionAsPattern(expr.left); - break; - default: - // Allow other node type for tolerant parsing. - break; - } - }; - Parser.prototype.parseGroupExpression = function () { - var expr; - this.expect('('); - if (this.match(')')) { - this.nextToken(); - if (!this.match('=>')) { - this.expect('=>'); - } - expr = { - type: ArrowParameterPlaceHolder, - params: [], - async: false - }; - } - else { - var startToken = this.lookahead; - var params = []; - if (this.match('...')) { - expr = this.parseRestElement(params); - this.expect(')'); - if (!this.match('=>')) { - this.expect('=>'); - } - expr = { - type: ArrowParameterPlaceHolder, - params: [expr], - async: false - }; - } - else { - var arrow = false; - this.context.isBindingElement = true; - expr = this.inheritCoverGrammar(this.parseAssignmentExpression); - if (this.match(',')) { - var expressions = []; - this.context.isAssignmentTarget = false; - expressions.push(expr); - while (this.lookahead.type !== 2 /* EOF */) { - if (!this.match(',')) { - break; - } - this.nextToken(); - if (this.match(')')) { - this.nextToken(); - for (var i = 0; i < expressions.length; i++) { - this.reinterpretExpressionAsPattern(expressions[i]); - } - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: expressions, - async: false - }; - } - else if (this.match('...')) { - if (!this.context.isBindingElement) { - this.throwUnexpectedToken(this.lookahead); - } - expressions.push(this.parseRestElement(params)); - this.expect(')'); - if (!this.match('=>')) { - this.expect('=>'); - } - this.context.isBindingElement = false; - for (var i = 0; i < expressions.length; i++) { - this.reinterpretExpressionAsPattern(expressions[i]); - } - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: expressions, - async: false - }; - } - else { - expressions.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); - } - if (arrow) { - break; - } - } - if (!arrow) { - expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); - } - } - if (!arrow) { - this.expect(')'); - if (this.match('=>')) { - if (expr.type === syntax_1.Syntax.Identifier && expr.name === 'yield') { - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: [expr], - async: false - }; - } - if (!arrow) { - if (!this.context.isBindingElement) { - this.throwUnexpectedToken(this.lookahead); - } - if (expr.type === syntax_1.Syntax.SequenceExpression) { - for (var i = 0; i < expr.expressions.length; i++) { - this.reinterpretExpressionAsPattern(expr.expressions[i]); - } - } - else { - this.reinterpretExpressionAsPattern(expr); - } - var parameters = (expr.type === syntax_1.Syntax.SequenceExpression ? expr.expressions : [expr]); - expr = { - type: ArrowParameterPlaceHolder, - params: parameters, - async: false - }; - } - } - this.context.isBindingElement = false; - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions - Parser.prototype.parseArguments = function () { - this.expect('('); - var args = []; - if (!this.match(')')) { - while (true) { - var expr = this.match('...') ? this.parseSpreadElement() : - this.isolateCoverGrammar(this.parseAssignmentExpression); - args.push(expr); - if (this.match(')')) { - break; - } - this.expectCommaSeparator(); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return args; - }; - Parser.prototype.isIdentifierName = function (token) { - return token.type === 3 /* Identifier */ || - token.type === 4 /* Keyword */ || - token.type === 1 /* BooleanLiteral */ || - token.type === 5 /* NullLiteral */; - }; - Parser.prototype.parseIdentifierName = function () { - var node = this.createNode(); - var token = this.nextToken(); - if (!this.isIdentifierName(token)) { - this.throwUnexpectedToken(token); - } - return this.finalize(node, new Node.Identifier(token.value)); - }; - Parser.prototype.parseNewExpression = function () { - var node = this.createNode(); - var id = this.parseIdentifierName(); - assert_1.assert(id.name === 'new', 'New expression must start with `new`'); - var expr; - if (this.match('.')) { - this.nextToken(); - if (this.lookahead.type === 3 /* Identifier */ && this.context.inFunctionBody && this.lookahead.value === 'target') { - var property = this.parseIdentifierName(); - expr = new Node.MetaProperty(id, property); - } - else { - this.throwUnexpectedToken(this.lookahead); - } - } - else { - var callee = this.isolateCoverGrammar(this.parseLeftHandSideExpression); - var args = this.match('(') ? this.parseArguments() : []; - expr = new Node.NewExpression(callee, args); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - return this.finalize(node, expr); - }; - Parser.prototype.parseAsyncArgument = function () { - var arg = this.parseAssignmentExpression(); - this.context.firstCoverInitializedNameError = null; - return arg; - }; - Parser.prototype.parseAsyncArguments = function () { - this.expect('('); - var args = []; - if (!this.match(')')) { - while (true) { - var expr = this.match('...') ? this.parseSpreadElement() : - this.isolateCoverGrammar(this.parseAsyncArgument); - args.push(expr); - if (this.match(')')) { - break; - } - this.expectCommaSeparator(); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return args; - }; - Parser.prototype.parseLeftHandSideExpressionAllowCall = function () { - var startToken = this.lookahead; - var maybeAsync = this.matchContextualKeyword('async'); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - var expr; - if (this.matchKeyword('super') && this.context.inFunctionBody) { - expr = this.createNode(); - this.nextToken(); - expr = this.finalize(expr, new Node.Super()); - if (!this.match('(') && !this.match('.') && !this.match('[')) { - this.throwUnexpectedToken(this.lookahead); - } - } - else { - expr = this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); - } - while (true) { - if (this.match('.')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('.'); - var property = this.parseIdentifierName(); - expr = this.finalize(this.startNode(startToken), new Node.StaticMemberExpression(expr, property)); - } - else if (this.match('(')) { - var asyncArrow = maybeAsync && (startToken.lineNumber === this.lookahead.lineNumber); - this.context.isBindingElement = false; - this.context.isAssignmentTarget = false; - var args = asyncArrow ? this.parseAsyncArguments() : this.parseArguments(); - expr = this.finalize(this.startNode(startToken), new Node.CallExpression(expr, args)); - if (asyncArrow && this.match('=>')) { - for (var i = 0; i < args.length; ++i) { - this.reinterpretExpressionAsPattern(args[i]); - } - expr = { - type: ArrowParameterPlaceHolder, - params: args, - async: true - }; - } - } - else if (this.match('[')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('['); - var property = this.isolateCoverGrammar(this.parseExpression); - this.expect(']'); - expr = this.finalize(this.startNode(startToken), new Node.ComputedMemberExpression(expr, property)); - } - else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { - var quasi = this.parseTemplateLiteral(); - expr = this.finalize(this.startNode(startToken), new Node.TaggedTemplateExpression(expr, quasi)); - } - else { - break; - } - } - this.context.allowIn = previousAllowIn; - return expr; - }; - Parser.prototype.parseSuper = function () { - var node = this.createNode(); - this.expectKeyword('super'); - if (!this.match('[') && !this.match('.')) { - this.throwUnexpectedToken(this.lookahead); - } - return this.finalize(node, new Node.Super()); - }; - Parser.prototype.parseLeftHandSideExpression = function () { - assert_1.assert(this.context.allowIn, 'callee of new expression always allow in keyword.'); - var node = this.startNode(this.lookahead); - var expr = (this.matchKeyword('super') && this.context.inFunctionBody) ? this.parseSuper() : - this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); - while (true) { - if (this.match('[')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('['); - var property = this.isolateCoverGrammar(this.parseExpression); - this.expect(']'); - expr = this.finalize(node, new Node.ComputedMemberExpression(expr, property)); - } - else if (this.match('.')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('.'); - var property = this.parseIdentifierName(); - expr = this.finalize(node, new Node.StaticMemberExpression(expr, property)); - } - else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { - var quasi = this.parseTemplateLiteral(); - expr = this.finalize(node, new Node.TaggedTemplateExpression(expr, quasi)); - } - else { - break; - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-update-expressions - Parser.prototype.parseUpdateExpression = function () { - var expr; - var startToken = this.lookahead; - if (this.match('++') || this.match('--')) { - var node = this.startNode(startToken); - var token = this.nextToken(); - expr = this.inheritCoverGrammar(this.parseUnaryExpression); - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { - this.tolerateError(messages_1.Messages.StrictLHSPrefix); - } - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - var prefix = true; - expr = this.finalize(node, new Node.UpdateExpression(token.value, expr, prefix)); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else { - expr = this.inheritCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - if (!this.hasLineTerminator && this.lookahead.type === 7 /* Punctuator */) { - if (this.match('++') || this.match('--')) { - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { - this.tolerateError(messages_1.Messages.StrictLHSPostfix); - } - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var operator = this.nextToken().value; - var prefix = false; - expr = this.finalize(this.startNode(startToken), new Node.UpdateExpression(operator, expr, prefix)); - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-unary-operators - Parser.prototype.parseAwaitExpression = function () { - var node = this.createNode(); - this.nextToken(); - var argument = this.parseUnaryExpression(); - return this.finalize(node, new Node.AwaitExpression(argument)); - }; - Parser.prototype.parseUnaryExpression = function () { - var expr; - if (this.match('+') || this.match('-') || this.match('~') || this.match('!') || - this.matchKeyword('delete') || this.matchKeyword('void') || this.matchKeyword('typeof')) { - var node = this.startNode(this.lookahead); - var token = this.nextToken(); - expr = this.inheritCoverGrammar(this.parseUnaryExpression); - expr = this.finalize(node, new Node.UnaryExpression(token.value, expr)); - if (this.context.strict && expr.operator === 'delete' && expr.argument.type === syntax_1.Syntax.Identifier) { - this.tolerateError(messages_1.Messages.StrictDelete); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else if (this.context.await && this.matchContextualKeyword('await')) { - expr = this.parseAwaitExpression(); - } - else { - expr = this.parseUpdateExpression(); - } - return expr; - }; - Parser.prototype.parseExponentiationExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseUnaryExpression); - if (expr.type !== syntax_1.Syntax.UnaryExpression && this.match('**')) { - this.nextToken(); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var left = expr; - var right = this.isolateCoverGrammar(this.parseExponentiationExpression); - expr = this.finalize(this.startNode(startToken), new Node.BinaryExpression('**', left, right)); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-exp-operator - // https://tc39.github.io/ecma262/#sec-multiplicative-operators - // https://tc39.github.io/ecma262/#sec-additive-operators - // https://tc39.github.io/ecma262/#sec-bitwise-shift-operators - // https://tc39.github.io/ecma262/#sec-relational-operators - // https://tc39.github.io/ecma262/#sec-equality-operators - // https://tc39.github.io/ecma262/#sec-binary-bitwise-operators - // https://tc39.github.io/ecma262/#sec-binary-logical-operators - Parser.prototype.binaryPrecedence = function (token) { - var op = token.value; - var precedence; - if (token.type === 7 /* Punctuator */) { - precedence = this.operatorPrecedence[op] || 0; - } - else if (token.type === 4 /* Keyword */) { - precedence = (op === 'instanceof' || (this.context.allowIn && op === 'in')) ? 7 : 0; - } - else { - precedence = 0; - } - return precedence; - }; - Parser.prototype.parseBinaryExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseExponentiationExpression); - var token = this.lookahead; - var prec = this.binaryPrecedence(token); - if (prec > 0) { - this.nextToken(); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var markers = [startToken, this.lookahead]; - var left = expr; - var right = this.isolateCoverGrammar(this.parseExponentiationExpression); - var stack = [left, token.value, right]; - var precedences = [prec]; - while (true) { - prec = this.binaryPrecedence(this.lookahead); - if (prec <= 0) { - break; - } - // Reduce: make a binary expression from the three topmost entries. - while ((stack.length > 2) && (prec <= precedences[precedences.length - 1])) { - right = stack.pop(); - var operator = stack.pop(); - precedences.pop(); - left = stack.pop(); - markers.pop(); - var node = this.startNode(markers[markers.length - 1]); - stack.push(this.finalize(node, new Node.BinaryExpression(operator, left, right))); - } - // Shift. - stack.push(this.nextToken().value); - precedences.push(prec); - markers.push(this.lookahead); - stack.push(this.isolateCoverGrammar(this.parseExponentiationExpression)); - } - // Final reduce to clean-up the stack. - var i = stack.length - 1; - expr = stack[i]; - var lastMarker = markers.pop(); - while (i > 1) { - var marker = markers.pop(); - var lastLineStart = lastMarker && lastMarker.lineStart; - var node = this.startNode(marker, lastLineStart); - var operator = stack[i - 1]; - expr = this.finalize(node, new Node.BinaryExpression(operator, stack[i - 2], expr)); - i -= 2; - lastMarker = marker; - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-conditional-operator - Parser.prototype.parseConditionalExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseBinaryExpression); - if (this.match('?')) { - this.nextToken(); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - var consequent = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.context.allowIn = previousAllowIn; - this.expect(':'); - var alternate = this.isolateCoverGrammar(this.parseAssignmentExpression); - expr = this.finalize(this.startNode(startToken), new Node.ConditionalExpression(expr, consequent, alternate)); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-assignment-operators - Parser.prototype.checkPatternParam = function (options, param) { - switch (param.type) { - case syntax_1.Syntax.Identifier: - this.validateParam(options, param, param.name); - break; - case syntax_1.Syntax.RestElement: - this.checkPatternParam(options, param.argument); - break; - case syntax_1.Syntax.AssignmentPattern: - this.checkPatternParam(options, param.left); - break; - case syntax_1.Syntax.ArrayPattern: - for (var i = 0; i < param.elements.length; i++) { - if (param.elements[i] !== null) { - this.checkPatternParam(options, param.elements[i]); - } - } - break; - case syntax_1.Syntax.ObjectPattern: - for (var i = 0; i < param.properties.length; i++) { - this.checkPatternParam(options, param.properties[i].value); - } - break; - default: - break; - } - options.simple = options.simple && (param instanceof Node.Identifier); - }; - Parser.prototype.reinterpretAsCoverFormalsList = function (expr) { - var params = [expr]; - var options; - var asyncArrow = false; - switch (expr.type) { - case syntax_1.Syntax.Identifier: - break; - case ArrowParameterPlaceHolder: - params = expr.params; - asyncArrow = expr.async; - break; - default: - return null; - } - options = { - simple: true, - paramSet: {} - }; - for (var i = 0; i < params.length; ++i) { - var param = params[i]; - if (param.type === syntax_1.Syntax.AssignmentPattern) { - if (param.right.type === syntax_1.Syntax.YieldExpression) { - if (param.right.argument) { - this.throwUnexpectedToken(this.lookahead); - } - param.right.type = syntax_1.Syntax.Identifier; - param.right.name = 'yield'; - delete param.right.argument; - delete param.right.delegate; - } - } - else if (asyncArrow && param.type === syntax_1.Syntax.Identifier && param.name === 'await') { - this.throwUnexpectedToken(this.lookahead); - } - this.checkPatternParam(options, param); - params[i] = param; - } - if (this.context.strict || !this.context.allowYield) { - for (var i = 0; i < params.length; ++i) { - var param = params[i]; - if (param.type === syntax_1.Syntax.YieldExpression) { - this.throwUnexpectedToken(this.lookahead); - } - } - } - if (options.message === messages_1.Messages.StrictParamDupe) { - var token = this.context.strict ? options.stricted : options.firstRestricted; - this.throwUnexpectedToken(token, options.message); - } - return { - simple: options.simple, - params: params, - stricted: options.stricted, - firstRestricted: options.firstRestricted, - message: options.message - }; - }; - Parser.prototype.parseAssignmentExpression = function () { - var expr; - if (!this.context.allowYield && this.matchKeyword('yield')) { - expr = this.parseYieldExpression(); - } - else { - var startToken = this.lookahead; - var token = startToken; - expr = this.parseConditionalExpression(); - if (token.type === 3 /* Identifier */ && (token.lineNumber === this.lookahead.lineNumber) && token.value === 'async') { - if (this.lookahead.type === 3 /* Identifier */ || this.matchKeyword('yield')) { - var arg = this.parsePrimaryExpression(); - this.reinterpretExpressionAsPattern(arg); - expr = { - type: ArrowParameterPlaceHolder, - params: [arg], - async: true - }; - } - } - if (expr.type === ArrowParameterPlaceHolder || this.match('=>')) { - // https://tc39.github.io/ecma262/#sec-arrow-function-definitions - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var isAsync = expr.async; - var list = this.reinterpretAsCoverFormalsList(expr); - if (list) { - if (this.hasLineTerminator) { - this.tolerateUnexpectedToken(this.lookahead); - } - this.context.firstCoverInitializedNameError = null; - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = list.simple; - var previousAllowYield = this.context.allowYield; - var previousAwait = this.context.await; - this.context.allowYield = true; - this.context.await = isAsync; - var node = this.startNode(startToken); - this.expect('=>'); - var body = void 0; - if (this.match('{')) { - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - body = this.parseFunctionSourceElements(); - this.context.allowIn = previousAllowIn; - } - else { - body = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - var expression = body.type !== syntax_1.Syntax.BlockStatement; - if (this.context.strict && list.firstRestricted) { - this.throwUnexpectedToken(list.firstRestricted, list.message); - } - if (this.context.strict && list.stricted) { - this.tolerateUnexpectedToken(list.stricted, list.message); - } - expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression)) : - this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression)); - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.allowYield = previousAllowYield; - this.context.await = previousAwait; - } - } - else { - if (this.matchAssign()) { - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier) { - var id = expr; - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictLHSAssignment); - } - if (this.scanner.isStrictModeReservedWord(id.name)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - } - if (!this.match('=')) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else { - this.reinterpretExpressionAsPattern(expr); - } - token = this.nextToken(); - var operator = token.value; - var right = this.isolateCoverGrammar(this.parseAssignmentExpression); - expr = this.finalize(this.startNode(startToken), new Node.AssignmentExpression(operator, expr, right)); - this.context.firstCoverInitializedNameError = null; - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-comma-operator - Parser.prototype.parseExpression = function () { - var startToken = this.lookahead; - var expr = this.isolateCoverGrammar(this.parseAssignmentExpression); - if (this.match(',')) { - var expressions = []; - expressions.push(expr); - while (this.lookahead.type !== 2 /* EOF */) { - if (!this.match(',')) { - break; - } - this.nextToken(); - expressions.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); - } - expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-block - Parser.prototype.parseStatementListItem = function () { - var statement; - this.context.isAssignmentTarget = true; - this.context.isBindingElement = true; - if (this.lookahead.type === 4 /* Keyword */) { - switch (this.lookahead.value) { - case 'export': - if (!this.context.isModule) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalExportDeclaration); - } - statement = this.parseExportDeclaration(); - break; - case 'import': - if (!this.context.isModule) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalImportDeclaration); - } - statement = this.parseImportDeclaration(); - break; - case 'const': - statement = this.parseLexicalDeclaration({ inFor: false }); - break; - case 'function': - statement = this.parseFunctionDeclaration(); - break; - case 'class': - statement = this.parseClassDeclaration(); - break; - case 'let': - statement = this.isLexicalDeclaration() ? this.parseLexicalDeclaration({ inFor: false }) : this.parseStatement(); - break; - default: - statement = this.parseStatement(); - break; - } - } - else { - statement = this.parseStatement(); - } - return statement; - }; - Parser.prototype.parseBlock = function () { - var node = this.createNode(); - this.expect('{'); - var block = []; - while (true) { - if (this.match('}')) { - break; - } - block.push(this.parseStatementListItem()); - } - this.expect('}'); - return this.finalize(node, new Node.BlockStatement(block)); - }; - // https://tc39.github.io/ecma262/#sec-let-and-const-declarations - Parser.prototype.parseLexicalBinding = function (kind, options) { - var node = this.createNode(); - var params = []; - var id = this.parsePattern(params, kind); - if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateError(messages_1.Messages.StrictVarName); - } - } - var init = null; - if (kind === 'const') { - if (!this.matchKeyword('in') && !this.matchContextualKeyword('of')) { - if (this.match('=')) { - this.nextToken(); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - else { - this.throwError(messages_1.Messages.DeclarationMissingInitializer, 'const'); - } - } - } - else if ((!options.inFor && id.type !== syntax_1.Syntax.Identifier) || this.match('=')) { - this.expect('='); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - return this.finalize(node, new Node.VariableDeclarator(id, init)); - }; - Parser.prototype.parseBindingList = function (kind, options) { - var list = [this.parseLexicalBinding(kind, options)]; - while (this.match(',')) { - this.nextToken(); - list.push(this.parseLexicalBinding(kind, options)); - } - return list; - }; - Parser.prototype.isLexicalDeclaration = function () { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.scanner.lex(); - this.scanner.restoreState(state); - return (next.type === 3 /* Identifier */) || - (next.type === 7 /* Punctuator */ && next.value === '[') || - (next.type === 7 /* Punctuator */ && next.value === '{') || - (next.type === 4 /* Keyword */ && next.value === 'let') || - (next.type === 4 /* Keyword */ && next.value === 'yield'); - }; - Parser.prototype.parseLexicalDeclaration = function (options) { - var node = this.createNode(); - var kind = this.nextToken().value; - assert_1.assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const'); - var declarations = this.parseBindingList(kind, options); - this.consumeSemicolon(); - return this.finalize(node, new Node.VariableDeclaration(declarations, kind)); - }; - // https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns - Parser.prototype.parseBindingRestElement = function (params, kind) { - var node = this.createNode(); - this.expect('...'); - var arg = this.parsePattern(params, kind); - return this.finalize(node, new Node.RestElement(arg)); - }; - Parser.prototype.parseArrayPattern = function (params, kind) { - var node = this.createNode(); - this.expect('['); - var elements = []; - while (!this.match(']')) { - if (this.match(',')) { - this.nextToken(); - elements.push(null); - } - else { - if (this.match('...')) { - elements.push(this.parseBindingRestElement(params, kind)); - break; - } - else { - elements.push(this.parsePatternWithDefault(params, kind)); - } - if (!this.match(']')) { - this.expect(','); - } - } - } - this.expect(']'); - return this.finalize(node, new Node.ArrayPattern(elements)); - }; - Parser.prototype.parsePropertyPattern = function (params, kind) { - var node = this.createNode(); - var computed = false; - var shorthand = false; - var method = false; - var key; - var value; - if (this.lookahead.type === 3 /* Identifier */) { - var keyToken = this.lookahead; - key = this.parseVariableIdentifier(); - var init = this.finalize(node, new Node.Identifier(keyToken.value)); - if (this.match('=')) { - params.push(keyToken); - shorthand = true; - this.nextToken(); - var expr = this.parseAssignmentExpression(); - value = this.finalize(this.startNode(keyToken), new Node.AssignmentPattern(init, expr)); - } - else if (!this.match(':')) { - params.push(keyToken); - shorthand = true; - value = init; - } - else { - this.expect(':'); - value = this.parsePatternWithDefault(params, kind); - } - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.expect(':'); - value = this.parsePatternWithDefault(params, kind); - } - return this.finalize(node, new Node.Property('init', key, computed, value, method, shorthand)); - }; - Parser.prototype.parseObjectPattern = function (params, kind) { - var node = this.createNode(); - var properties = []; - this.expect('{'); - while (!this.match('}')) { - properties.push(this.parsePropertyPattern(params, kind)); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - return this.finalize(node, new Node.ObjectPattern(properties)); - }; - Parser.prototype.parsePattern = function (params, kind) { - var pattern; - if (this.match('[')) { - pattern = this.parseArrayPattern(params, kind); - } - else if (this.match('{')) { - pattern = this.parseObjectPattern(params, kind); - } - else { - if (this.matchKeyword('let') && (kind === 'const' || kind === 'let')) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.LetInLexicalBinding); - } - params.push(this.lookahead); - pattern = this.parseVariableIdentifier(kind); - } - return pattern; - }; - Parser.prototype.parsePatternWithDefault = function (params, kind) { - var startToken = this.lookahead; - var pattern = this.parsePattern(params, kind); - if (this.match('=')) { - this.nextToken(); - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var right = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.context.allowYield = previousAllowYield; - pattern = this.finalize(this.startNode(startToken), new Node.AssignmentPattern(pattern, right)); - } - return pattern; - }; - // https://tc39.github.io/ecma262/#sec-variable-statement - Parser.prototype.parseVariableIdentifier = function (kind) { - var node = this.createNode(); - var token = this.nextToken(); - if (token.type === 4 /* Keyword */ && token.value === 'yield') { - if (this.context.strict) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - else if (!this.context.allowYield) { - this.throwUnexpectedToken(token); - } - } - else if (token.type !== 3 /* Identifier */) { - if (this.context.strict && token.type === 4 /* Keyword */ && this.scanner.isStrictModeReservedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - else { - if (this.context.strict || token.value !== 'let' || kind !== 'var') { - this.throwUnexpectedToken(token); - } - } - } - else if ((this.context.isModule || this.context.await) && token.type === 3 /* Identifier */ && token.value === 'await') { - this.tolerateUnexpectedToken(token); - } - return this.finalize(node, new Node.Identifier(token.value)); - }; - Parser.prototype.parseVariableDeclaration = function (options) { - var node = this.createNode(); - var params = []; - var id = this.parsePattern(params, 'var'); - if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateError(messages_1.Messages.StrictVarName); - } - } - var init = null; - if (this.match('=')) { - this.nextToken(); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - else if (id.type !== syntax_1.Syntax.Identifier && !options.inFor) { - this.expect('='); - } - return this.finalize(node, new Node.VariableDeclarator(id, init)); - }; - Parser.prototype.parseVariableDeclarationList = function (options) { - var opt = { inFor: options.inFor }; - var list = []; - list.push(this.parseVariableDeclaration(opt)); - while (this.match(',')) { - this.nextToken(); - list.push(this.parseVariableDeclaration(opt)); - } - return list; - }; - Parser.prototype.parseVariableStatement = function () { - var node = this.createNode(); - this.expectKeyword('var'); - var declarations = this.parseVariableDeclarationList({ inFor: false }); - this.consumeSemicolon(); - return this.finalize(node, new Node.VariableDeclaration(declarations, 'var')); - }; - // https://tc39.github.io/ecma262/#sec-empty-statement - Parser.prototype.parseEmptyStatement = function () { - var node = this.createNode(); - this.expect(';'); - return this.finalize(node, new Node.EmptyStatement()); - }; - // https://tc39.github.io/ecma262/#sec-expression-statement - Parser.prototype.parseExpressionStatement = function () { - var node = this.createNode(); - var expr = this.parseExpression(); - this.consumeSemicolon(); - return this.finalize(node, new Node.ExpressionStatement(expr)); - }; - // https://tc39.github.io/ecma262/#sec-if-statement - Parser.prototype.parseIfClause = function () { - if (this.context.strict && this.matchKeyword('function')) { - this.tolerateError(messages_1.Messages.StrictFunction); - } - return this.parseStatement(); - }; - Parser.prototype.parseIfStatement = function () { - var node = this.createNode(); - var consequent; - var alternate = null; - this.expectKeyword('if'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - consequent = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - consequent = this.parseIfClause(); - if (this.matchKeyword('else')) { - this.nextToken(); - alternate = this.parseIfClause(); - } - } - return this.finalize(node, new Node.IfStatement(test, consequent, alternate)); - }; - // https://tc39.github.io/ecma262/#sec-do-while-statement - Parser.prototype.parseDoWhileStatement = function () { - var node = this.createNode(); - this.expectKeyword('do'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - var body = this.parseStatement(); - this.context.inIteration = previousInIteration; - this.expectKeyword('while'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - } - else { - this.expect(')'); - if (this.match(';')) { - this.nextToken(); - } - } - return this.finalize(node, new Node.DoWhileStatement(body, test)); - }; - // https://tc39.github.io/ecma262/#sec-while-statement - Parser.prototype.parseWhileStatement = function () { - var node = this.createNode(); - var body; - this.expectKeyword('while'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - body = this.parseStatement(); - this.context.inIteration = previousInIteration; - } - return this.finalize(node, new Node.WhileStatement(test, body)); - }; - // https://tc39.github.io/ecma262/#sec-for-statement - // https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements - Parser.prototype.parseForStatement = function () { - var init = null; - var test = null; - var update = null; - var forIn = true; - var left, right; - var node = this.createNode(); - this.expectKeyword('for'); - this.expect('('); - if (this.match(';')) { - this.nextToken(); - } - else { - if (this.matchKeyword('var')) { - init = this.createNode(); - this.nextToken(); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - var declarations = this.parseVariableDeclarationList({ inFor: true }); - this.context.allowIn = previousAllowIn; - if (declarations.length === 1 && this.matchKeyword('in')) { - var decl = declarations[0]; - if (decl.init && (decl.id.type === syntax_1.Syntax.ArrayPattern || decl.id.type === syntax_1.Syntax.ObjectPattern || this.context.strict)) { - this.tolerateError(messages_1.Messages.ForInOfLoopInitializer, 'for-in'); - } - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.nextToken(); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.expect(';'); - } - } - else if (this.matchKeyword('const') || this.matchKeyword('let')) { - init = this.createNode(); - var kind = this.nextToken().value; - if (!this.context.strict && this.lookahead.value === 'in') { - init = this.finalize(init, new Node.Identifier(kind)); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else { - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - var declarations = this.parseBindingList(kind, { inFor: true }); - this.context.allowIn = previousAllowIn; - if (declarations.length === 1 && declarations[0].init === null && this.matchKeyword('in')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - this.nextToken(); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - this.consumeSemicolon(); - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - } - } - } - else { - var initStartToken = this.lookahead; - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - init = this.inheritCoverGrammar(this.parseAssignmentExpression); - this.context.allowIn = previousAllowIn; - if (this.matchKeyword('in')) { - if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { - this.tolerateError(messages_1.Messages.InvalidLHSInForIn); - } - this.nextToken(); - this.reinterpretExpressionAsPattern(init); - left = init; - right = this.parseExpression(); - init = null; - } - else if (this.matchContextualKeyword('of')) { - if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { - this.tolerateError(messages_1.Messages.InvalidLHSInForLoop); - } - this.nextToken(); - this.reinterpretExpressionAsPattern(init); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - if (this.match(',')) { - var initSeq = [init]; - while (this.match(',')) { - this.nextToken(); - initSeq.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); - } - init = this.finalize(this.startNode(initStartToken), new Node.SequenceExpression(initSeq)); - } - this.expect(';'); - } - } - } - if (typeof left === 'undefined') { - if (!this.match(';')) { - test = this.parseExpression(); - } - this.expect(';'); - if (!this.match(')')) { - update = this.parseExpression(); - } - } - var body; - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - body = this.isolateCoverGrammar(this.parseStatement); - this.context.inIteration = previousInIteration; - } - return (typeof left === 'undefined') ? - this.finalize(node, new Node.ForStatement(init, test, update, body)) : - forIn ? this.finalize(node, new Node.ForInStatement(left, right, body)) : - this.finalize(node, new Node.ForOfStatement(left, right, body)); - }; - // https://tc39.github.io/ecma262/#sec-continue-statement - Parser.prototype.parseContinueStatement = function () { - var node = this.createNode(); - this.expectKeyword('continue'); - var label = null; - if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { - var id = this.parseVariableIdentifier(); - label = id; - var key = '$' + id.name; - if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.UnknownLabel, id.name); - } - } - this.consumeSemicolon(); - if (label === null && !this.context.inIteration) { - this.throwError(messages_1.Messages.IllegalContinue); - } - return this.finalize(node, new Node.ContinueStatement(label)); - }; - // https://tc39.github.io/ecma262/#sec-break-statement - Parser.prototype.parseBreakStatement = function () { - var node = this.createNode(); - this.expectKeyword('break'); - var label = null; - if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { - var id = this.parseVariableIdentifier(); - var key = '$' + id.name; - if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.UnknownLabel, id.name); - } - label = id; - } - this.consumeSemicolon(); - if (label === null && !this.context.inIteration && !this.context.inSwitch) { - this.throwError(messages_1.Messages.IllegalBreak); - } - return this.finalize(node, new Node.BreakStatement(label)); - }; - // https://tc39.github.io/ecma262/#sec-return-statement - Parser.prototype.parseReturnStatement = function () { - if (!this.context.inFunctionBody) { - this.tolerateError(messages_1.Messages.IllegalReturn); - } - var node = this.createNode(); - this.expectKeyword('return'); - var hasArgument = (!this.match(';') && !this.match('}') && - !this.hasLineTerminator && this.lookahead.type !== 2 /* EOF */) || - this.lookahead.type === 8 /* StringLiteral */ || - this.lookahead.type === 10 /* Template */; - var argument = hasArgument ? this.parseExpression() : null; - this.consumeSemicolon(); - return this.finalize(node, new Node.ReturnStatement(argument)); - }; - // https://tc39.github.io/ecma262/#sec-with-statement - Parser.prototype.parseWithStatement = function () { - if (this.context.strict) { - this.tolerateError(messages_1.Messages.StrictModeWith); - } - var node = this.createNode(); - var body; - this.expectKeyword('with'); - this.expect('('); - var object = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - body = this.parseStatement(); - } - return this.finalize(node, new Node.WithStatement(object, body)); - }; - // https://tc39.github.io/ecma262/#sec-switch-statement - Parser.prototype.parseSwitchCase = function () { - var node = this.createNode(); - var test; - if (this.matchKeyword('default')) { - this.nextToken(); - test = null; - } - else { - this.expectKeyword('case'); - test = this.parseExpression(); - } - this.expect(':'); - var consequent = []; - while (true) { - if (this.match('}') || this.matchKeyword('default') || this.matchKeyword('case')) { - break; - } - consequent.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.SwitchCase(test, consequent)); - }; - Parser.prototype.parseSwitchStatement = function () { - var node = this.createNode(); - this.expectKeyword('switch'); - this.expect('('); - var discriminant = this.parseExpression(); - this.expect(')'); - var previousInSwitch = this.context.inSwitch; - this.context.inSwitch = true; - var cases = []; - var defaultFound = false; - this.expect('{'); - while (true) { - if (this.match('}')) { - break; - } - var clause = this.parseSwitchCase(); - if (clause.test === null) { - if (defaultFound) { - this.throwError(messages_1.Messages.MultipleDefaultsInSwitch); - } - defaultFound = true; - } - cases.push(clause); - } - this.expect('}'); - this.context.inSwitch = previousInSwitch; - return this.finalize(node, new Node.SwitchStatement(discriminant, cases)); - }; - // https://tc39.github.io/ecma262/#sec-labelled-statements - Parser.prototype.parseLabelledStatement = function () { - var node = this.createNode(); - var expr = this.parseExpression(); - var statement; - if ((expr.type === syntax_1.Syntax.Identifier) && this.match(':')) { - this.nextToken(); - var id = expr; - var key = '$' + id.name; - if (Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.Redeclaration, 'Label', id.name); - } - this.context.labelSet[key] = true; - var body = void 0; - if (this.matchKeyword('class')) { - this.tolerateUnexpectedToken(this.lookahead); - body = this.parseClassDeclaration(); - } - else if (this.matchKeyword('function')) { - var token = this.lookahead; - var declaration = this.parseFunctionDeclaration(); - if (this.context.strict) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunction); - } - else if (declaration.generator) { - this.tolerateUnexpectedToken(token, messages_1.Messages.GeneratorInLegacyContext); - } - body = declaration; - } - else { - body = this.parseStatement(); - } - delete this.context.labelSet[key]; - statement = new Node.LabeledStatement(id, body); - } - else { - this.consumeSemicolon(); - statement = new Node.ExpressionStatement(expr); - } - return this.finalize(node, statement); - }; - // https://tc39.github.io/ecma262/#sec-throw-statement - Parser.prototype.parseThrowStatement = function () { - var node = this.createNode(); - this.expectKeyword('throw'); - if (this.hasLineTerminator) { - this.throwError(messages_1.Messages.NewlineAfterThrow); - } - var argument = this.parseExpression(); - this.consumeSemicolon(); - return this.finalize(node, new Node.ThrowStatement(argument)); - }; - // https://tc39.github.io/ecma262/#sec-try-statement - Parser.prototype.parseCatchClause = function () { - var node = this.createNode(); - this.expectKeyword('catch'); - this.expect('('); - if (this.match(')')) { - this.throwUnexpectedToken(this.lookahead); - } - var params = []; - var param = this.parsePattern(params); - var paramMap = {}; - for (var i = 0; i < params.length; i++) { - var key = '$' + params[i].value; - if (Object.prototype.hasOwnProperty.call(paramMap, key)) { - this.tolerateError(messages_1.Messages.DuplicateBinding, params[i].value); - } - paramMap[key] = true; - } - if (this.context.strict && param.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(param.name)) { - this.tolerateError(messages_1.Messages.StrictCatchVariable); - } - } - this.expect(')'); - var body = this.parseBlock(); - return this.finalize(node, new Node.CatchClause(param, body)); - }; - Parser.prototype.parseFinallyClause = function () { - this.expectKeyword('finally'); - return this.parseBlock(); - }; - Parser.prototype.parseTryStatement = function () { - var node = this.createNode(); - this.expectKeyword('try'); - var block = this.parseBlock(); - var handler = this.matchKeyword('catch') ? this.parseCatchClause() : null; - var finalizer = this.matchKeyword('finally') ? this.parseFinallyClause() : null; - if (!handler && !finalizer) { - this.throwError(messages_1.Messages.NoCatchOrFinally); - } - return this.finalize(node, new Node.TryStatement(block, handler, finalizer)); - }; - // https://tc39.github.io/ecma262/#sec-debugger-statement - Parser.prototype.parseDebuggerStatement = function () { - var node = this.createNode(); - this.expectKeyword('debugger'); - this.consumeSemicolon(); - return this.finalize(node, new Node.DebuggerStatement()); - }; - // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations - Parser.prototype.parseStatement = function () { - var statement; - switch (this.lookahead.type) { - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 6 /* NumericLiteral */: - case 8 /* StringLiteral */: - case 10 /* Template */: - case 9 /* RegularExpression */: - statement = this.parseExpressionStatement(); - break; - case 7 /* Punctuator */: - var value = this.lookahead.value; - if (value === '{') { - statement = this.parseBlock(); - } - else if (value === '(') { - statement = this.parseExpressionStatement(); - } - else if (value === ';') { - statement = this.parseEmptyStatement(); - } - else { - statement = this.parseExpressionStatement(); - } - break; - case 3 /* Identifier */: - statement = this.matchAsyncFunction() ? this.parseFunctionDeclaration() : this.parseLabelledStatement(); - break; - case 4 /* Keyword */: - switch (this.lookahead.value) { - case 'break': - statement = this.parseBreakStatement(); - break; - case 'continue': - statement = this.parseContinueStatement(); - break; - case 'debugger': - statement = this.parseDebuggerStatement(); - break; - case 'do': - statement = this.parseDoWhileStatement(); - break; - case 'for': - statement = this.parseForStatement(); - break; - case 'function': - statement = this.parseFunctionDeclaration(); - break; - case 'if': - statement = this.parseIfStatement(); - break; - case 'return': - statement = this.parseReturnStatement(); - break; - case 'switch': - statement = this.parseSwitchStatement(); - break; - case 'throw': - statement = this.parseThrowStatement(); - break; - case 'try': - statement = this.parseTryStatement(); - break; - case 'var': - statement = this.parseVariableStatement(); - break; - case 'while': - statement = this.parseWhileStatement(); - break; - case 'with': - statement = this.parseWithStatement(); - break; - default: - statement = this.parseExpressionStatement(); - break; - } - break; - default: - statement = this.throwUnexpectedToken(this.lookahead); - } - return statement; - }; - // https://tc39.github.io/ecma262/#sec-function-definitions - Parser.prototype.parseFunctionSourceElements = function () { - var node = this.createNode(); - this.expect('{'); - var body = this.parseDirectivePrologues(); - var previousLabelSet = this.context.labelSet; - var previousInIteration = this.context.inIteration; - var previousInSwitch = this.context.inSwitch; - var previousInFunctionBody = this.context.inFunctionBody; - this.context.labelSet = {}; - this.context.inIteration = false; - this.context.inSwitch = false; - this.context.inFunctionBody = true; - while (this.lookahead.type !== 2 /* EOF */) { - if (this.match('}')) { - break; - } - body.push(this.parseStatementListItem()); - } - this.expect('}'); - this.context.labelSet = previousLabelSet; - this.context.inIteration = previousInIteration; - this.context.inSwitch = previousInSwitch; - this.context.inFunctionBody = previousInFunctionBody; - return this.finalize(node, new Node.BlockStatement(body)); - }; - Parser.prototype.validateParam = function (options, param, name) { - var key = '$' + name; - if (this.context.strict) { - if (this.scanner.isRestrictedWord(name)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamName; - } - if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamDupe; - } - } - else if (!options.firstRestricted) { - if (this.scanner.isRestrictedWord(name)) { - options.firstRestricted = param; - options.message = messages_1.Messages.StrictParamName; - } - else if (this.scanner.isStrictModeReservedWord(name)) { - options.firstRestricted = param; - options.message = messages_1.Messages.StrictReservedWord; - } - else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamDupe; - } - } - /* istanbul ignore next */ - if (typeof Object.defineProperty === 'function') { - Object.defineProperty(options.paramSet, key, { value: true, enumerable: true, writable: true, configurable: true }); - } - else { - options.paramSet[key] = true; - } - }; - Parser.prototype.parseRestElement = function (params) { - var node = this.createNode(); - this.expect('...'); - var arg = this.parsePattern(params); - if (this.match('=')) { - this.throwError(messages_1.Messages.DefaultRestParameter); - } - if (!this.match(')')) { - this.throwError(messages_1.Messages.ParameterAfterRestParameter); - } - return this.finalize(node, new Node.RestElement(arg)); - }; - Parser.prototype.parseFormalParameter = function (options) { - var params = []; - var param = this.match('...') ? this.parseRestElement(params) : this.parsePatternWithDefault(params); - for (var i = 0; i < params.length; i++) { - this.validateParam(options, params[i], params[i].value); - } - options.simple = options.simple && (param instanceof Node.Identifier); - options.params.push(param); - }; - Parser.prototype.parseFormalParameters = function (firstRestricted) { - var options; - options = { - simple: true, - params: [], - firstRestricted: firstRestricted - }; - this.expect('('); - if (!this.match(')')) { - options.paramSet = {}; - while (this.lookahead.type !== 2 /* EOF */) { - this.parseFormalParameter(options); - if (this.match(')')) { - break; - } - this.expect(','); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return { - simple: options.simple, - params: options.params, - stricted: options.stricted, - firstRestricted: options.firstRestricted, - message: options.message - }; - }; - Parser.prototype.matchAsyncFunction = function () { - var match = this.matchContextualKeyword('async'); - if (match) { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.scanner.lex(); - this.scanner.restoreState(state); - match = (state.lineNumber === next.lineNumber) && (next.type === 4 /* Keyword */) && (next.value === 'function'); - } - return match; - }; - Parser.prototype.parseFunctionDeclaration = function (identifierIsOptional) { - var node = this.createNode(); - var isAsync = this.matchContextualKeyword('async'); - if (isAsync) { - this.nextToken(); - } - this.expectKeyword('function'); - var isGenerator = isAsync ? false : this.match('*'); - if (isGenerator) { - this.nextToken(); - } - var message; - var id = null; - var firstRestricted = null; - if (!identifierIsOptional || !this.match('(')) { - var token = this.lookahead; - id = this.parseVariableIdentifier(); - if (this.context.strict) { - if (this.scanner.isRestrictedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); - } - } - else { - if (this.scanner.isRestrictedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictFunctionName; - } - else if (this.scanner.isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictReservedWord; - } - } - } - var previousAllowAwait = this.context.await; - var previousAllowYield = this.context.allowYield; - this.context.await = isAsync; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(firstRestricted); - var params = formalParameters.params; - var stricted = formalParameters.stricted; - firstRestricted = formalParameters.firstRestricted; - if (formalParameters.message) { - message = formalParameters.message; - } - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = formalParameters.simple; - var body = this.parseFunctionSourceElements(); - if (this.context.strict && firstRestricted) { - this.throwUnexpectedToken(firstRestricted, message); - } - if (this.context.strict && stricted) { - this.tolerateUnexpectedToken(stricted, message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.await = previousAllowAwait; - this.context.allowYield = previousAllowYield; - return isAsync ? this.finalize(node, new Node.AsyncFunctionDeclaration(id, params, body)) : - this.finalize(node, new Node.FunctionDeclaration(id, params, body, isGenerator)); - }; - Parser.prototype.parseFunctionExpression = function () { - var node = this.createNode(); - var isAsync = this.matchContextualKeyword('async'); - if (isAsync) { - this.nextToken(); - } - this.expectKeyword('function'); - var isGenerator = isAsync ? false : this.match('*'); - if (isGenerator) { - this.nextToken(); - } - var message; - var id = null; - var firstRestricted; - var previousAllowAwait = this.context.await; - var previousAllowYield = this.context.allowYield; - this.context.await = isAsync; - this.context.allowYield = !isGenerator; - if (!this.match('(')) { - var token = this.lookahead; - id = (!this.context.strict && !isGenerator && this.matchKeyword('yield')) ? this.parseIdentifierName() : this.parseVariableIdentifier(); - if (this.context.strict) { - if (this.scanner.isRestrictedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); - } - } - else { - if (this.scanner.isRestrictedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictFunctionName; - } - else if (this.scanner.isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictReservedWord; - } - } - } - var formalParameters = this.parseFormalParameters(firstRestricted); - var params = formalParameters.params; - var stricted = formalParameters.stricted; - firstRestricted = formalParameters.firstRestricted; - if (formalParameters.message) { - message = formalParameters.message; - } - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = formalParameters.simple; - var body = this.parseFunctionSourceElements(); - if (this.context.strict && firstRestricted) { - this.throwUnexpectedToken(firstRestricted, message); - } - if (this.context.strict && stricted) { - this.tolerateUnexpectedToken(stricted, message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.await = previousAllowAwait; - this.context.allowYield = previousAllowYield; - return isAsync ? this.finalize(node, new Node.AsyncFunctionExpression(id, params, body)) : - this.finalize(node, new Node.FunctionExpression(id, params, body, isGenerator)); - }; - // https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive - Parser.prototype.parseDirective = function () { - var token = this.lookahead; - var node = this.createNode(); - var expr = this.parseExpression(); - var directive = (expr.type === syntax_1.Syntax.Literal) ? this.getTokenRaw(token).slice(1, -1) : null; - this.consumeSemicolon(); - return this.finalize(node, directive ? new Node.Directive(expr, directive) : new Node.ExpressionStatement(expr)); - }; - Parser.prototype.parseDirectivePrologues = function () { - var firstRestricted = null; - var body = []; - while (true) { - var token = this.lookahead; - if (token.type !== 8 /* StringLiteral */) { - break; - } - var statement = this.parseDirective(); - body.push(statement); - var directive = statement.directive; - if (typeof directive !== 'string') { - break; - } - if (directive === 'use strict') { - this.context.strict = true; - if (firstRestricted) { - this.tolerateUnexpectedToken(firstRestricted, messages_1.Messages.StrictOctalLiteral); - } - if (!this.context.allowStrictDirective) { - this.tolerateUnexpectedToken(token, messages_1.Messages.IllegalLanguageModeDirective); - } - } - else { - if (!firstRestricted && token.octal) { - firstRestricted = token; - } - } - } - return body; - }; - // https://tc39.github.io/ecma262/#sec-method-definitions - Parser.prototype.qualifiedPropertyName = function (token) { - switch (token.type) { - case 3 /* Identifier */: - case 8 /* StringLiteral */: - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 6 /* NumericLiteral */: - case 4 /* Keyword */: - return true; - case 7 /* Punctuator */: - return token.value === '['; - default: - break; - } - return false; - }; - Parser.prototype.parseGetterMethod = function () { - var node = this.createNode(); - var isGenerator = false; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(); - if (formalParameters.params.length > 0) { - this.tolerateError(messages_1.Messages.BadGetterArity); - } - var method = this.parsePropertyMethod(formalParameters); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); - }; - Parser.prototype.parseSetterMethod = function () { - var node = this.createNode(); - var isGenerator = false; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(); - if (formalParameters.params.length !== 1) { - this.tolerateError(messages_1.Messages.BadSetterArity); - } - else if (formalParameters.params[0] instanceof Node.RestElement) { - this.tolerateError(messages_1.Messages.BadSetterRestParameter); - } - var method = this.parsePropertyMethod(formalParameters); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); - }; - Parser.prototype.parseGeneratorMethod = function () { - var node = this.createNode(); - var isGenerator = true; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var params = this.parseFormalParameters(); - this.context.allowYield = false; - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); - }; - // https://tc39.github.io/ecma262/#sec-generator-function-definitions - Parser.prototype.isStartOfExpression = function () { - var start = true; - var value = this.lookahead.value; - switch (this.lookahead.type) { - case 7 /* Punctuator */: - start = (value === '[') || (value === '(') || (value === '{') || - (value === '+') || (value === '-') || - (value === '!') || (value === '~') || - (value === '++') || (value === '--') || - (value === '/') || (value === '/='); // regular expression literal - break; - case 4 /* Keyword */: - start = (value === 'class') || (value === 'delete') || - (value === 'function') || (value === 'let') || (value === 'new') || - (value === 'super') || (value === 'this') || (value === 'typeof') || - (value === 'void') || (value === 'yield'); - break; - default: - break; - } - return start; - }; - Parser.prototype.parseYieldExpression = function () { - var node = this.createNode(); - this.expectKeyword('yield'); - var argument = null; - var delegate = false; - if (!this.hasLineTerminator) { - var previousAllowYield = this.context.allowYield; - this.context.allowYield = false; - delegate = this.match('*'); - if (delegate) { - this.nextToken(); - argument = this.parseAssignmentExpression(); - } - else if (this.isStartOfExpression()) { - argument = this.parseAssignmentExpression(); - } - this.context.allowYield = previousAllowYield; - } - return this.finalize(node, new Node.YieldExpression(argument, delegate)); - }; - // https://tc39.github.io/ecma262/#sec-class-definitions - Parser.prototype.parseClassElement = function (hasConstructor) { - var token = this.lookahead; - var node = this.createNode(); - var kind = ''; - var key = null; - var value = null; - var computed = false; - var method = false; - var isStatic = false; - var isAsync = false; - if (this.match('*')) { - this.nextToken(); - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - var id = key; - if (id.name === 'static' && (this.qualifiedPropertyName(this.lookahead) || this.match('*'))) { - token = this.lookahead; - isStatic = true; - computed = this.match('['); - if (this.match('*')) { - this.nextToken(); - } - else { - key = this.parseObjectPropertyKey(); - } - } - if ((token.type === 3 /* Identifier */) && !this.hasLineTerminator && (token.value === 'async')) { - var punctuator = this.lookahead.value; - if (punctuator !== ':' && punctuator !== '(' && punctuator !== '*') { - isAsync = true; - token = this.lookahead; - key = this.parseObjectPropertyKey(); - if (token.type === 3 /* Identifier */ && token.value === 'constructor') { - this.tolerateUnexpectedToken(token, messages_1.Messages.ConstructorIsAsync); - } - } - } - } - var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); - if (token.type === 3 /* Identifier */) { - if (token.value === 'get' && lookaheadPropertyKey) { - kind = 'get'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.context.allowYield = false; - value = this.parseGetterMethod(); - } - else if (token.value === 'set' && lookaheadPropertyKey) { - kind = 'set'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseSetterMethod(); - } - } - else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { - kind = 'init'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseGeneratorMethod(); - method = true; - } - if (!kind && key && this.match('(')) { - kind = 'init'; - value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); - method = true; - } - if (!kind) { - this.throwUnexpectedToken(this.lookahead); - } - if (kind === 'init') { - kind = 'method'; - } - if (!computed) { - if (isStatic && this.isPropertyKey(key, 'prototype')) { - this.throwUnexpectedToken(token, messages_1.Messages.StaticPrototype); - } - if (!isStatic && this.isPropertyKey(key, 'constructor')) { - if (kind !== 'method' || !method || (value && value.generator)) { - this.throwUnexpectedToken(token, messages_1.Messages.ConstructorSpecialMethod); - } - if (hasConstructor.value) { - this.throwUnexpectedToken(token, messages_1.Messages.DuplicateConstructor); - } - else { - hasConstructor.value = true; - } - kind = 'constructor'; - } - } - return this.finalize(node, new Node.MethodDefinition(key, computed, value, kind, isStatic)); - }; - Parser.prototype.parseClassElementList = function () { - var body = []; - var hasConstructor = { value: false }; - this.expect('{'); - while (!this.match('}')) { - if (this.match(';')) { - this.nextToken(); - } - else { - body.push(this.parseClassElement(hasConstructor)); - } - } - this.expect('}'); - return body; - }; - Parser.prototype.parseClassBody = function () { - var node = this.createNode(); - var elementList = this.parseClassElementList(); - return this.finalize(node, new Node.ClassBody(elementList)); - }; - Parser.prototype.parseClassDeclaration = function (identifierIsOptional) { - var node = this.createNode(); - var previousStrict = this.context.strict; - this.context.strict = true; - this.expectKeyword('class'); - var id = (identifierIsOptional && (this.lookahead.type !== 3 /* Identifier */)) ? null : this.parseVariableIdentifier(); - var superClass = null; - if (this.matchKeyword('extends')) { - this.nextToken(); - superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - } - var classBody = this.parseClassBody(); - this.context.strict = previousStrict; - return this.finalize(node, new Node.ClassDeclaration(id, superClass, classBody)); - }; - Parser.prototype.parseClassExpression = function () { - var node = this.createNode(); - var previousStrict = this.context.strict; - this.context.strict = true; - this.expectKeyword('class'); - var id = (this.lookahead.type === 3 /* Identifier */) ? this.parseVariableIdentifier() : null; - var superClass = null; - if (this.matchKeyword('extends')) { - this.nextToken(); - superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - } - var classBody = this.parseClassBody(); - this.context.strict = previousStrict; - return this.finalize(node, new Node.ClassExpression(id, superClass, classBody)); - }; - // https://tc39.github.io/ecma262/#sec-scripts - // https://tc39.github.io/ecma262/#sec-modules - Parser.prototype.parseModule = function () { - this.context.strict = true; - this.context.isModule = true; - this.scanner.isModule = true; - var node = this.createNode(); - var body = this.parseDirectivePrologues(); - while (this.lookahead.type !== 2 /* EOF */) { - body.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.Module(body)); - }; - Parser.prototype.parseScript = function () { - var node = this.createNode(); - var body = this.parseDirectivePrologues(); - while (this.lookahead.type !== 2 /* EOF */) { - body.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.Script(body)); - }; - // https://tc39.github.io/ecma262/#sec-imports - Parser.prototype.parseModuleSpecifier = function () { - var node = this.createNode(); - if (this.lookahead.type !== 8 /* StringLiteral */) { - this.throwError(messages_1.Messages.InvalidModuleSpecifier); - } - var token = this.nextToken(); - var raw = this.getTokenRaw(token); - return this.finalize(node, new Node.Literal(token.value, raw)); - }; - // import {} ...; - Parser.prototype.parseImportSpecifier = function () { - var node = this.createNode(); - var imported; - var local; - if (this.lookahead.type === 3 /* Identifier */) { - imported = this.parseVariableIdentifier(); - local = imported; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - local = this.parseVariableIdentifier(); - } - } - else { - imported = this.parseIdentifierName(); - local = imported; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - local = this.parseVariableIdentifier(); - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - } - return this.finalize(node, new Node.ImportSpecifier(local, imported)); - }; - // {foo, bar as bas} - Parser.prototype.parseNamedImports = function () { - this.expect('{'); - var specifiers = []; - while (!this.match('}')) { - specifiers.push(this.parseImportSpecifier()); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - return specifiers; - }; - // import ...; - Parser.prototype.parseImportDefaultSpecifier = function () { - var node = this.createNode(); - var local = this.parseIdentifierName(); - return this.finalize(node, new Node.ImportDefaultSpecifier(local)); - }; - // import <* as foo> ...; - Parser.prototype.parseImportNamespaceSpecifier = function () { - var node = this.createNode(); - this.expect('*'); - if (!this.matchContextualKeyword('as')) { - this.throwError(messages_1.Messages.NoAsAfterImportNamespace); - } - this.nextToken(); - var local = this.parseIdentifierName(); - return this.finalize(node, new Node.ImportNamespaceSpecifier(local)); - }; - Parser.prototype.parseImportDeclaration = function () { - if (this.context.inFunctionBody) { - this.throwError(messages_1.Messages.IllegalImportDeclaration); - } - var node = this.createNode(); - this.expectKeyword('import'); - var src; - var specifiers = []; - if (this.lookahead.type === 8 /* StringLiteral */) { - // import 'foo'; - src = this.parseModuleSpecifier(); - } - else { - if (this.match('{')) { - // import {bar} - specifiers = specifiers.concat(this.parseNamedImports()); - } - else if (this.match('*')) { - // import * as foo - specifiers.push(this.parseImportNamespaceSpecifier()); - } - else if (this.isIdentifierName(this.lookahead) && !this.matchKeyword('default')) { - // import foo - specifiers.push(this.parseImportDefaultSpecifier()); - if (this.match(',')) { - this.nextToken(); - if (this.match('*')) { - // import foo, * as foo - specifiers.push(this.parseImportNamespaceSpecifier()); - } - else if (this.match('{')) { - // import foo, {bar} - specifiers = specifiers.concat(this.parseNamedImports()); - } - else { - this.throwUnexpectedToken(this.lookahead); - } - } - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - if (!this.matchContextualKeyword('from')) { - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - this.nextToken(); - src = this.parseModuleSpecifier(); - } - this.consumeSemicolon(); - return this.finalize(node, new Node.ImportDeclaration(specifiers, src)); - }; - // https://tc39.github.io/ecma262/#sec-exports - Parser.prototype.parseExportSpecifier = function () { - var node = this.createNode(); - var local = this.parseIdentifierName(); - var exported = local; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - exported = this.parseIdentifierName(); - } - return this.finalize(node, new Node.ExportSpecifier(local, exported)); - }; - Parser.prototype.parseExportDeclaration = function () { - if (this.context.inFunctionBody) { - this.throwError(messages_1.Messages.IllegalExportDeclaration); - } - var node = this.createNode(); - this.expectKeyword('export'); - var exportDeclaration; - if (this.matchKeyword('default')) { - // export default ... - this.nextToken(); - if (this.matchKeyword('function')) { - // export default function foo () {} - // export default function () {} - var declaration = this.parseFunctionDeclaration(true); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else if (this.matchKeyword('class')) { - // export default class foo {} - var declaration = this.parseClassDeclaration(true); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else if (this.matchContextualKeyword('async')) { - // export default async function f () {} - // export default async function () {} - // export default async x => x - var declaration = this.matchAsyncFunction() ? this.parseFunctionDeclaration(true) : this.parseAssignmentExpression(); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else { - if (this.matchContextualKeyword('from')) { - this.throwError(messages_1.Messages.UnexpectedToken, this.lookahead.value); - } - // export default {}; - // export default []; - // export default (1 + 2); - var declaration = this.match('{') ? this.parseObjectInitializer() : - this.match('[') ? this.parseArrayInitializer() : this.parseAssignmentExpression(); - this.consumeSemicolon(); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - } - else if (this.match('*')) { - // export * from 'foo'; - this.nextToken(); - if (!this.matchContextualKeyword('from')) { - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - this.nextToken(); - var src = this.parseModuleSpecifier(); - this.consumeSemicolon(); - exportDeclaration = this.finalize(node, new Node.ExportAllDeclaration(src)); - } - else if (this.lookahead.type === 4 /* Keyword */) { - // export var f = 1; - var declaration = void 0; - switch (this.lookahead.value) { - case 'let': - case 'const': - declaration = this.parseLexicalDeclaration({ inFor: false }); - break; - case 'var': - case 'class': - case 'function': - declaration = this.parseStatementListItem(); - break; - default: - this.throwUnexpectedToken(this.lookahead); - } - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); - } - else if (this.matchAsyncFunction()) { - var declaration = this.parseFunctionDeclaration(); - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); - } - else { - var specifiers = []; - var source = null; - var isExportFromIdentifier = false; - this.expect('{'); - while (!this.match('}')) { - isExportFromIdentifier = isExportFromIdentifier || this.matchKeyword('default'); - specifiers.push(this.parseExportSpecifier()); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - if (this.matchContextualKeyword('from')) { - // export {default} from 'foo'; - // export {foo} from 'foo'; - this.nextToken(); - source = this.parseModuleSpecifier(); - this.consumeSemicolon(); - } - else if (isExportFromIdentifier) { - // export {default}; // missing fromClause - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - else { - // export {foo}; - this.consumeSemicolon(); - } - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(null, specifiers, source)); - } - return exportDeclaration; - }; - return Parser; - }()); - exports.Parser = Parser; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - "use strict"; - // Ensure the condition is true, otherwise throw an error. - // This is only to have a better contract semantic, i.e. another safety net - // to catch a logic error. The condition shall be fulfilled in normal case. - // Do NOT use this to enforce a certain condition on any user input. - Object.defineProperty(exports, "__esModule", { value: true }); - function assert(condition, message) { - /* istanbul ignore if */ - if (!condition) { - throw new Error('ASSERT: ' + message); - } - } - exports.assert = assert; - - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - "use strict"; - /* tslint:disable:max-classes-per-file */ - Object.defineProperty(exports, "__esModule", { value: true }); - var ErrorHandler = (function () { - function ErrorHandler() { - this.errors = []; - this.tolerant = false; - } - ErrorHandler.prototype.recordError = function (error) { - this.errors.push(error); - }; - ErrorHandler.prototype.tolerate = function (error) { - if (this.tolerant) { - this.recordError(error); - } - else { - throw error; - } - }; - ErrorHandler.prototype.constructError = function (msg, column) { - var error = new Error(msg); - try { - throw error; - } - catch (base) { - /* istanbul ignore else */ - if (Object.create && Object.defineProperty) { - error = Object.create(base); - Object.defineProperty(error, 'column', { value: column }); - } - } - /* istanbul ignore next */ - return error; - }; - ErrorHandler.prototype.createError = function (index, line, col, description) { - var msg = 'Line ' + line + ': ' + description; - var error = this.constructError(msg, col); - error.index = index; - error.lineNumber = line; - error.description = description; - return error; - }; - ErrorHandler.prototype.throwError = function (index, line, col, description) { - throw this.createError(index, line, col, description); - }; - ErrorHandler.prototype.tolerateError = function (index, line, col, description) { - var error = this.createError(index, line, col, description); - if (this.tolerant) { - this.recordError(error); - } - else { - throw error; - } - }; - return ErrorHandler; - }()); - exports.ErrorHandler = ErrorHandler; - - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - // Error messages should be identical to V8. - exports.Messages = { - BadGetterArity: 'Getter must not have any formal parameters', - BadSetterArity: 'Setter must have exactly one formal parameter', - BadSetterRestParameter: 'Setter function argument must not be a rest parameter', - ConstructorIsAsync: 'Class constructor may not be an async method', - ConstructorSpecialMethod: 'Class constructor may not be an accessor', - DeclarationMissingInitializer: 'Missing initializer in %0 declaration', - DefaultRestParameter: 'Unexpected token =', - DuplicateBinding: 'Duplicate binding %0', - DuplicateConstructor: 'A class may only have one constructor', - DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals', - ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer', - GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts', - IllegalBreak: 'Illegal break statement', - IllegalContinue: 'Illegal continue statement', - IllegalExportDeclaration: 'Unexpected token', - IllegalImportDeclaration: 'Unexpected token', - IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list', - IllegalReturn: 'Illegal return statement', - InvalidEscapedReservedWord: 'Keyword must not contain escaped characters', - InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence', - InvalidLHSInAssignment: 'Invalid left-hand side in assignment', - InvalidLHSInForIn: 'Invalid left-hand side in for-in', - InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', - InvalidModuleSpecifier: 'Unexpected token', - InvalidRegExp: 'Invalid regular expression', - LetInLexicalBinding: 'let is disallowed as a lexically bound name', - MissingFromClause: 'Unexpected token', - MultipleDefaultsInSwitch: 'More than one default clause in switch statement', - NewlineAfterThrow: 'Illegal newline after throw', - NoAsAfterImportNamespace: 'Unexpected token', - NoCatchOrFinally: 'Missing catch or finally after try', - ParameterAfterRestParameter: 'Rest parameter must be last formal parameter', - Redeclaration: '%0 \'%1\' has already been declared', - StaticPrototype: 'Classes may not have static property named prototype', - StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', - StrictDelete: 'Delete of an unqualified identifier in strict mode.', - StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block', - StrictFunctionName: 'Function name may not be eval or arguments in strict mode', - StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', - StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', - StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', - StrictModeWith: 'Strict mode code may not include a with statement', - StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', - StrictParamDupe: 'Strict mode function may not have duplicate parameter names', - StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', - StrictReservedWord: 'Use of future reserved word in strict mode', - StrictVarName: 'Variable name may not be eval or arguments in strict mode', - TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', - UnexpectedEOS: 'Unexpected end of input', - UnexpectedIdentifier: 'Unexpected identifier', - UnexpectedNumber: 'Unexpected number', - UnexpectedReserved: 'Unexpected reserved word', - UnexpectedString: 'Unexpected string', - UnexpectedTemplate: 'Unexpected quasi %0', - UnexpectedToken: 'Unexpected token %0', - UnexpectedTokenIllegal: 'Unexpected token ILLEGAL', - UnknownLabel: 'Undefined label \'%0\'', - UnterminatedRegExp: 'Invalid regular expression: missing /' - }; - - -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var assert_1 = __webpack_require__(9); - var character_1 = __webpack_require__(4); - var messages_1 = __webpack_require__(11); - function hexValue(ch) { - return '0123456789abcdef'.indexOf(ch.toLowerCase()); - } - function octalValue(ch) { - return '01234567'.indexOf(ch); - } - var Scanner = (function () { - function Scanner(code, handler) { - this.source = code; - this.errorHandler = handler; - this.trackComment = false; - this.isModule = false; - this.length = code.length; - this.index = 0; - this.lineNumber = (code.length > 0) ? 1 : 0; - this.lineStart = 0; - this.curlyStack = []; - } - Scanner.prototype.saveState = function () { - return { - index: this.index, - lineNumber: this.lineNumber, - lineStart: this.lineStart - }; - }; - Scanner.prototype.restoreState = function (state) { - this.index = state.index; - this.lineNumber = state.lineNumber; - this.lineStart = state.lineStart; - }; - Scanner.prototype.eof = function () { - return this.index >= this.length; - }; - Scanner.prototype.throwUnexpectedToken = function (message) { - if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } - return this.errorHandler.throwError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); - }; - Scanner.prototype.tolerateUnexpectedToken = function (message) { - if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } - this.errorHandler.tolerateError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); - }; - // https://tc39.github.io/ecma262/#sec-comments - Scanner.prototype.skipSingleLineComment = function (offset) { - var comments = []; - var start, loc; - if (this.trackComment) { - comments = []; - start = this.index - offset; - loc = { - start: { - line: this.lineNumber, - column: this.index - this.lineStart - offset - }, - end: {} - }; - } - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - ++this.index; - if (character_1.Character.isLineTerminator(ch)) { - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - 1 - }; - var entry = { - multiLine: false, - slice: [start + offset, this.index - 1], - range: [start, this.index - 1], - loc: loc - }; - comments.push(entry); - } - if (ch === 13 && this.source.charCodeAt(this.index) === 10) { - ++this.index; - } - ++this.lineNumber; - this.lineStart = this.index; - return comments; - } - } - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: false, - slice: [start + offset, this.index], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - return comments; - }; - Scanner.prototype.skipMultiLineComment = function () { - var comments = []; - var start, loc; - if (this.trackComment) { - comments = []; - start = this.index - 2; - loc = { - start: { - line: this.lineNumber, - column: this.index - this.lineStart - 2 - }, - end: {} - }; - } - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - if (character_1.Character.isLineTerminator(ch)) { - if (ch === 0x0D && this.source.charCodeAt(this.index + 1) === 0x0A) { - ++this.index; - } - ++this.lineNumber; - ++this.index; - this.lineStart = this.index; - } - else if (ch === 0x2A) { - // Block comment ends with '*/'. - if (this.source.charCodeAt(this.index + 1) === 0x2F) { - this.index += 2; - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: true, - slice: [start + 2, this.index - 2], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - return comments; - } - ++this.index; - } - else { - ++this.index; - } - } - // Ran off the end of the file - the whole thing is a comment - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: true, - slice: [start + 2, this.index], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - this.tolerateUnexpectedToken(); - return comments; - }; - Scanner.prototype.scanComments = function () { - var comments; - if (this.trackComment) { - comments = []; - } - var start = (this.index === 0); - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - if (character_1.Character.isWhiteSpace(ch)) { - ++this.index; - } - else if (character_1.Character.isLineTerminator(ch)) { - ++this.index; - if (ch === 0x0D && this.source.charCodeAt(this.index) === 0x0A) { - ++this.index; - } - ++this.lineNumber; - this.lineStart = this.index; - start = true; - } - else if (ch === 0x2F) { - ch = this.source.charCodeAt(this.index + 1); - if (ch === 0x2F) { - this.index += 2; - var comment = this.skipSingleLineComment(2); - if (this.trackComment) { - comments = comments.concat(comment); - } - start = true; - } - else if (ch === 0x2A) { - this.index += 2; - var comment = this.skipMultiLineComment(); - if (this.trackComment) { - comments = comments.concat(comment); - } - } - else { - break; - } - } - else if (start && ch === 0x2D) { - // U+003E is '>' - if ((this.source.charCodeAt(this.index + 1) === 0x2D) && (this.source.charCodeAt(this.index + 2) === 0x3E)) { - // '-->' is a single-line comment - this.index += 3; - var comment = this.skipSingleLineComment(3); - if (this.trackComment) { - comments = comments.concat(comment); - } - } - else { - break; - } - } - else if (ch === 0x3C && !this.isModule) { - if (this.source.slice(this.index + 1, this.index + 4) === '!--') { - this.index += 4; // `', wickFileBase64); - callback(text); - }).catch(e => { - console.error('Wick.HTMLExport: Could not download HTML file template.'); - console.error(e); - }); - }, 'base64'); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * Utility class for bundling Wick projects inside ZIP files. - */ -Wick.ZIPExport = class { - static bundleProject(project, done) { - this._downloadDependenciesFiles(items => { - window.Wick.WickFile.toWickFile(project, wickFile => { - this._bundleFilesIntoZip(wickFile, items, done); - }); - }); - } - - static _downloadDependenciesFiles(done) { - var list = []; - var urls = ["index.html", "preloadjs.min.js", "wickengine.js"]; - var results = []; - urls.forEach(function (url, i) { - list.push(fetch(Wick.resourcepath + url).then(function (res) { - results[i] = { - data: res.blob(), - name: url - }; - })); - }); - Promise.all(list).then(function () { - done(results); - }); - } - - static _bundleFilesIntoZip(wickFile, dependenciesFiles, done) { - var zip = new JSZip(); - dependenciesFiles.forEach(file => { - zip.file(file.name, file.data); - }); - zip.file('project.wick', wickFile); - zip.generateAsync({ - type: "blob", - compression: "DEFLATE", - compressionOptions: { - level: 9 - } - }).then(done); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * The base class for all objects within the Wick Engine. - */ -Wick.Base = class { - /** - * Creates a Base object. - * @parm {string} identifier - (Optional) The identifier of the object. Defaults to null. - * @parm {string} name - (Optional) The name of the object. Defaults to null. - */ - constructor(args) { - if (!args) args = {}; - this._uuid = uuidv4(); - this._identifier = args.identifier || null; - this._name = args.naeme || null; - this._view = null; - this.view = this._generateView(); - this._guiElement = null; - this.guiElement = this._generateGUIElement(); - this._classname = this.classname; - this._children = {}; - this._childrenData = null; - this._parent = null; - this._project = this.classname === 'Project' ? this : null; - Wick.ObjectCache.addObject(this); - } - /** - * @param {object} data - Serialized data to use to create a new object. - */ - - - static fromData(data) { - if (!data.classname) { - console.warn('Wick.Base.fromData(): data was missing, did you mean to deserialize something else?'); - } - - if (!Wick[data.classname]) { - console.warn('Tried to deserialize an object with no Wick class: ' + data.classname); - } - - var object = new Wick[data.classname](); - object.deserialize(data); - return object; - } - /** - * Parses serialized data representing Base Objects which have been serialized using the serialize function of their class. - * @param {object} data Serialized data that was returned by a Base Object's serialize function. - */ - - - deserialize(data) { - this._uuid = data.uuid; - this._identifier = data.identifier; - this._name = data.name; - this._children = {}; - this._childrenData = data.children; - Wick.ObjectCache.addObject(this); - } - /** - * Converts this Wick Base object into a plain javascript object contianing raw data (no references). - * @return {object} Plain JavaScript object representing this Wick Base object. - */ - - - serialize() { - var data = {}; - data.classname = this.classname; - data.identifier = this._identifier; - data.name = this._name; - data.uuid = this._uuid; - data.children = this.getChildren().map(child => { - return child.uuid; - }); - return data; - } - /** - * Returns a copy of a Wick Base object. - * @return {Wick.Base} The object resulting from the copy - */ - - - copy() { - var data = this.serialize(); - data.uuid = uuidv4(); - var copy = Wick.Base.fromData(data); - copy._childrenData = null; // Copy children - - this.getChildren().forEach(child => { - copy.addChild(child.copy()); - }); - return copy; - } - /** - * Returns an object containing serialied data of this object, as well as all of its children. - * Use this to copy entire Wick.Base objects between projects, and to export individual Clips as files. - * @returns {object} The exported data. - */ - - - export() { - var copy = this.copy(); - copy._project = this.project; // the main object - - var object = copy.serialize(); // children - - var children = copy.getChildrenRecursive().map(child => { - return child.serialize(); - }); // assets - - var assets = []; - copy.getChildrenRecursive().concat(copy).forEach(child => { - child._project = copy._project; - child.getLinkedAssets().forEach(asset => { - assets.push(asset.serialize({ - includeOriginalSource: true - })); - }); - }); - return { - object: object, - children: children, - assets: assets - }; - } - /** - * Import data created using Wick.Base.export(). - * @param {object} exportData - an object created from Wick.Base.export(). - */ - - - static import(exportData, project) { - if (!exportData) console.error('Wick.Base.import(): exportData is required'); - if (!exportData.object) console.error('Wick.Base.import(): exportData is missing data'); - if (!exportData.children) console.error('Wick.Base.import(): exportData is missing data'); - var object = Wick.Base.fromData(exportData.object); // Import children as well - - exportData.children.forEach(childData => { - // Only need to call deserialize here, we just want the object to get added to ObjectCache - var child = Wick.Base.fromData(childData); - }); // Also import linked assets - - exportData.assets.forEach(assetData => { - // Don't import assets if they exist in the project already - // (Assets only get reimported when objects are pasted between projects) - if (project.getAssetByUUID(assetData.uuid)) { - return; - } - - var asset = Wick.Base.fromData(assetData); - project.addAsset(asset); - }); - return object; - } - /** - * Returns the classname of a Wick Base object. - * @type {string} - */ - - - get classname() { - return 'Base'; - } - /** - * The uuid of a Wick Base object. - * @type {string} - */ - - - get uuid() { - return this._uuid; - } - - set uuid(uuid) { - // Please try to avoid using this unless you absolutely have to ;_; - this._uuid = uuid; - Wick.ObjectCache.addObject(this); - } - /** - * The name of the object that is used to access the object through scripts. Must be a valid JS variable name. - * @type {string} - */ - - - get identifier() { - return this._identifier; - } - - set identifier(identifier) { - if (identifier === '' || identifier === null) { - this._identifier = null; - return; - } - - if (!isVarName(identifier)) return; - if (reserved.check(identifier)) return; - this._identifier = this._getUniqueIdentifier(identifier); - } - /** - * The name of the object. - * @type {string} - */ - - - get name() { - return this._name; - } - - set name(name) { - if (typeof name !== 'string') return; - if (name === '') this._name = null; - this._name = name; - } - /** - * The Wick.View object that is used for rendering this object on the canvas. - */ - - - get view() { - return this._view; - } - - set view(view) { - if (view) view.model = this; - this._view = view; - } - /** - * The object that is used for rendering this object in the timeline GUI. - */ - - - get guiElement() { - return this._guiElement; - } - - set guiElement(guiElement) { - if (guiElement) guiElement.model = this; - this._guiElement = guiElement; - } - /** - * - */ - - - getChild(classname) { - return this.getChildren(classname)[0]; - } - /** - * Gets all children with a given classname(s). - * @param {Array|string} classname - (optional) A string, or list of strings, of classnames. - */ - - - getChildren(classname) { - // Lazily generate children list from serialized data - if (this._childrenData) { - this._childrenData.forEach(uuid => { - this.addChild(Wick.ObjectCache.getObjectByUUID(uuid)); - }); - - this._childrenData = null; - } - - if (classname instanceof Array) { - var children = []; - classname.forEach(classnameSeek => { - children = children.concat(this.getChildren(classnameSeek)); - }); - return children; - } else if (classname === undefined) { - // Retrieve all children if no classname was given - var allChildren = []; - - for (var classnameSeek in this._children) { - allChildren = allChildren.concat(this._children[classnameSeek]); - } - - return allChildren; - } else { - // Retrieve children by classname - return this._children[classname] || []; - } - } - /** - * Get an array of all children of this object, and the children of those children, recursively. - * @type {Wick.Base[]} - */ - - - getChildrenRecursive() { - var children = this.getChildren(); - this.getChildren().forEach(child => { - children = children.concat(child.getChildrenRecursive()); - }); - return children; - } - /** - * The parent of this object. - * @type {Wick.Base} - */ - - - get parent() { - return this._parent; - } - /** - * The parent Clip of this object. - * @type {Wick.Clip} - */ - - - get parentClip() { - return this._getParentByClassName('Clip'); - } - /** - * The parent Layer of this object. - * @type {Wick.Layer} - */ - - - get parentLayer() { - return this._getParentByClassName('Layer'); - } - /** - * The parent Frame of this object. - * @type {Wick.Frame} - */ - - - get parentFrame() { - return this._getParentByClassName('Frame'); - } - /** - * The parent Timeline of this object. - * @type {Wick.Timeline} - */ - - - get parentTimeline() { - return this._getParentByClassName('Timeline'); - } - /** - * The project that this object belongs to. Can be null if the object is not in a project. - * @type {Wick.Project} - */ - - - get project() { - return this._project; - } - /** - * Check if an object is selected or not. - * @type {boolean} - */ - - - get isSelected() { - if (!this.project) return false; - return this.project.selection.isObjectSelected(this); - } - /** - * Add a child to this object. - * @param {Wick.Base} child - the child to add. - */ - - - addChild(child) { - var classname = child.classname; - - if (!this._children[classname]) { - this._children[classname] = []; - } - - child._parent = this; - - child._setProject(this.project); - - this._children[classname].push(child); - } - /** - * Remove a child from this object. - * @param {Wick.Base} child - the child to remove. - */ - - - removeChild(child) { - var classname = child.classname; - - if (!this._children[classname]) { - return; - } - - child._parent = null; - child._project = null; - this._children[classname] = this._children[classname].filter(seekChild => { - return seekChild !== child; - }); - } - - getLinkedAssets() { - // Implemented by Wick.Frame and Wick.Clip - return []; - } - - _generateView() { - var viewClass = Wick.View[this.classname]; - - if (viewClass) { - return new viewClass(this); - } else { - return null; - } - } - - _generateGUIElement() { - var guiElementClass = Wick.GUIElement[this.classname]; - - if (guiElementClass && guiElementClass !== Wick.Button) { - return new guiElementClass(this); - } else { - return null; - } - } - - _getParentByClassName(classname) { - if (!this.parent) return null; - - if (this.parent instanceof Wick[classname]) { - return this.parent; - } else { - if (!this.parent._getParentByClassName) return null; - return this.parent._getParentByClassName(classname); - } - } - - _setProject(project) { - this._project = project; - this.getChildren().forEach(child => { - child._setProject(project); - }); - } - - _getUniqueIdentifier(identifier) { - if (!this.parent) return identifier; - var otherIdentifiers = this.parent.getChildren(['Clip', 'Frame', 'Button']).filter(child => { - return child !== this && child.identifier; - }).map(child => { - return child.identifier; - }); - - if (otherIdentifiers.indexOf(identifier) === -1) { - return identifier; - } else { - return this._getUniqueIdentifier(identifier + '_copy'); - } - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * Represents a Wick Layer. - */ -Wick.Layer = class extends Wick.Base { - /** - * Called when creating a Wick Layer. - * @param {boolean} locked - Is the layer locked? - * @param {boolean} hideen - Is the layer hidden? - */ - constructor(args) { - if (!args) args = {}; - super(args); - this.locked = args.locked === undefined ? false : args.locked; - this.hidden = args.hidden === undefined ? false : args.hidden; - this.name = args.name || null; - } - - serialize(args) { - var data = super.serialize(args); - data.locked = this.locked; - data.hidden = this.hidden; - return data; - } - - deserialize(data) { - super.deserialize(data); - this.locked = data.locked; - this.hidden = data.hidden; - } - - get classname() { - return 'Layer'; - } - /** - * The frames belonging to this layer. - * @type {Wick.Frame[]} - */ - - - get frames() { - return this.getChildren('Frame'); - } - /** - * The order of the Layer in the timeline. - * @type {number} - */ - - - get index() { - return this.parent && this.parent.layers.indexOf(this); - } - /** - * Set this layer to be the active layer in its timeline. - */ - - - activate() { - this.parent.activeLayerIndex = this.index; - } - /** - * True if this layer is the active layer in its timeline. - * @type {boolean} - */ - - - get isActive() { - return this.parent && this === this.parent.activeLayer; - } - /** - * The length of the layer in frames. - * @type {number} - */ - - - get length() { - var end = 0; - this.frames.forEach(function (frame) { - if (frame.end > end) { - end = frame.end; - } - }); - return end; - } - /** - * The active frame on the layer. - * @type {Wick.Frame} - */ - - - get activeFrame() { - if (!this.parent) return null; - return this.getFrameAtPlayheadPosition(this.parent.playheadPosition); - } - /** - * Moves this layer to a different position, inserting it before/after other layers if needed. - * @param {number} index - the new position to move the layer to. - */ - - - move(index) { - this.parentTimeline.moveLayer(this, index); - } - /** - * Remove this layer from its timeline. - */ - - - remove() { - this.parentTimeline.removeLayer(this); - } - /** - * Adds a frame to the layer. - * @param {Wick.Frame} frame - The frame to add to the Layer. - */ - - - addFrame(frame) { - this.addChild(frame); - this.resolveOverlap([frame]); - this.resolveGaps([frame]); - } - /** - * Removes a frame from the Layer. - * @param {Wick.Frame} frame Frame to remove. - */ - - - removeFrame(frame) { - this.removeChild(frame); - this.resolveGaps(); - } - /** - * Gets the frame at a specific playhead position. - * @param {number} playheadPosition - Playhead position to search for frame at. - * @return {Wick.Frame} The frame at the given playheadPosition. - */ - - - getFrameAtPlayheadPosition(playheadPosition) { - return this.frames.find(frame => { - return frame.inPosition(playheadPosition); - }) || null; - } - /** - * Gets all frames in the layer that are between the two given playhead positions. - * @param {number} playheadPositionStart - The start of the range to search - * @param {number} playheadPositionEnd - The end of the range to search - * @return {Wick.Frame[]} The frames in the given range. - */ - - - getFramesInRange(playheadPositionStart, playheadPositionEnd) { - return this.frames.filter(frame => { - return frame.inRange(playheadPositionStart, playheadPositionEnd); - }); - } - /** - * Gets all frames in the layer that are contained within the two given playhead positions. - * @param {number} playheadPositionStart - The start of the range to search - * @param {number} playheadPositionEnd - The end of the range to search - * @return {Wick.Frame[]} The frames contained in the given range. - */ - - - getFramesContainedWithin(playheadPositionStart, playheadPositionEnd) { - return this.frames.filter(frame => { - return frame.containedWithin(playheadPositionStart, playheadPositionEnd); - }); - } - /** - * Prevents frames from overlapping each other by removing pieces of frames that are touching. - * @param {Wick.Frame[]} newOrModifiedFrames - the frames that should take precedence when determining which frames should get "eaten". - */ - - - resolveOverlap(newOrModifiedFrames) { - newOrModifiedFrames = newOrModifiedFrames || []; // Ensure that frames never go beyond the beginning of the timeline - - newOrModifiedFrames.forEach(frame => { - if (frame.start <= 1) { - frame.start = 1; - } - }); - - var isEdible = existingFrame => { - return newOrModifiedFrames.indexOf(existingFrame) === -1; - }; - - newOrModifiedFrames.forEach(frame => { - // "Full eat" - // The frame completely eats the other frame. - var containedFrames = this.getFramesContainedWithin(frame.start, frame.end); - containedFrames.filter(isEdible).forEach(existingFrame => { - existingFrame.remove(); - }); // "Right eat" - // The frame takes a chunk out of the right side of another frame. - - this.frames.filter(isEdible).forEach(existingFrame => { - if (existingFrame.inPosition(frame.start) && existingFrame.start !== frame.start) { - existingFrame.end = frame.start - 1; - } - }); // "Left eat" - // The frame takes a chunk out of the left side of another frame. - - this.frames.filter(isEdible).forEach(existingFrame => { - if (existingFrame.inPosition(frame.end) && existingFrame.end !== frame.end) { - existingFrame.start = frame.end + 1; - } - }); - }); - } - /** - * Prevents gaps between frames by extending frames to fill empty space between themselves. - */ - - - resolveGaps(newOrModifiedFrames) { - if (this.parentTimeline && this.parentTimeline.waitToFillFrameGaps) return; - newOrModifiedFrames = newOrModifiedFrames || []; - var fillGapsMethod = this.parentTimeline && this.parentTimeline.fillGapsMethod; - if (!fillGapsMethod) fillGapsMethod = 'blank_frames'; - this.findGaps().forEach(gap => { - // Method 1: Use the frame on the left (if there is one) to fill the gap - if (fillGapsMethod === 'auto_extend') { - var frameOnLeft = this.getFrameAtPlayheadPosition(gap.start - 1); - - if (!frameOnLeft || newOrModifiedFrames.indexOf(frameOnLeft) !== -1 || gap.start === 1) { - // If there is no frame on the left, create a blank one - var empty = new Wick.Frame({ - start: gap.start, - end: gap.end - }); - this.addFrame(empty); - } else { - // Otherwise, extend the frame to the left to fill the gap - frameOnLeft.end = gap.end; - } - } // Method 2: Always create empty frames to fill gaps - - - if (fillGapsMethod === 'blank_frames') { - var empty = new Wick.Frame({ - start: gap.start, - end: gap.end - }); - this.addFrame(empty); - } - }); - } - /** - * Generate a list of positions where there is empty space between frames. - * @returns {Object[]} An array of objects with start/end positions describing gaps. - */ - - - findGaps() { - var gaps = []; - var currentGap = null; - - for (var i = 1; i <= this.length; i++) { - var frame = this.getFrameAtPlayheadPosition(i); // Found the start of a gap - - if (!frame && !currentGap) { - currentGap = {}; - currentGap.start = i; - } // Found the end of a gap - - - if (frame && currentGap) { - currentGap.end = i - 1; - gaps.push(currentGap); - currentGap = null; - } - } - - return gaps; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * Class representing a Wick Project. - */ -Wick.Project = class extends Wick.Base { - /** - * Create a project. - * @param {string} name - Project name. Default "My Project". - * @param {number} width - Project width in pixels. Default 720. - * @param {number} height - Project height in pixels. Default 405. - * @param {number} framerate - Project framerate in frames-per-second. Default 12. - * @param {string} backgroundColor - Project background color in hex. Default #ffffff. - */ - constructor(args) { - if (!args) args = {}; - super(args); - this._name = args.name || 'My Project'; - this._width = args.width || 720; - this._height = args.height || 405; - this._framerate = args.framerate || 12; - this._backgroundColor = args.backgroundColor || '#ffffff'; - this.pan = { - x: 0, - y: 0 - }; - this.zoom = 1.0; - this.onionSkinEnabled = false; - this.onionSkinSeekBackwards = 1; - this.onionSkinSeekForwards = 1; - this.selection = new Wick.Selection(); - this.history = new Wick.History(); - this.clipboard = new Wick.Clipboard(); - this.root = new Wick.Clip(); - this.root._identifier = 'Project'; - this.focus = this.root; - this._mousePosition = { - x: 0, - y: 0 - }; - this._lastMousePosition = { - x: 0, - y: 0 - }; - this._isMouseDown = false; - this._mouseTargets = []; - this._keysDown = []; - this._keysLastDown = []; - this._currentKey = null; - this._tickIntervalID = null; - this._hideCursor = false; - this._muted = false; - this._publishedMode = false; - this._tools = { - brush: new Wick.Tools.Brush(), - cursor: new Wick.Tools.Cursor(), - ellipse: new Wick.Tools.Ellipse(), - eraser: new Wick.Tools.Eraser(), - eyedropper: new Wick.Tools.Eyedropper(), - fillbucket: new Wick.Tools.FillBucket(), - interact: new Wick.Tools.Interact(), - line: new Wick.Tools.Line(), - none: new Wick.Tools.None(), - pan: new Wick.Tools.Pan(), - pathcursor: new Wick.Tools.PathCursor(), - pencil: new Wick.Tools.Pencil(), - rectangle: new Wick.Tools.Rectangle(), - text: new Wick.Tools.Text(), - zoom: new Wick.Tools.Zoom() - }; - - for (var toolName in this._tools) { - this._tools[toolName].project = this; - } - - this.activeTool = 'cursor'; - this._toolSettings = new Wick.ToolSettings(); - - this._toolSettings.onSettingsChanged((name, value) => { - if (name === 'fillColor') { - this.selection.fillColor = value; - } else if (name === 'strokeColor') { - this.selection.strokeColor = value; - } - }); - - this._playing = false; - this.history.project = this; - this.history.pushState(Wick.History.StateType.ONLY_VISIBLE_OBJECTS); - } - - deserialize(data) { - super.deserialize(data); - this.name = data.name; - this.width = data.width; - this.height = data.height; - this.framerate = data.framerate; - this.backgroundColor = data.backgroundColor; - this._focus = data.focus; - this._hideCursor = false; - this._muted = false; - } - - serialize(args) { - var data = super.serialize(args); - data.name = this.name; - data.width = this.width; - data.height = this.height; - data.backgroundColor = this.backgroundColor; - data.framerate = this.framerate; - data.onionSkinEnabled = this.onionSkinEnabled; - data.onionSkinSeekForwards = this.onionSkinSeekForwards; - data.onionSkinSeekBackwards = this.onionSkinSeekBackwards; - data.focus = this.focus.uuid; // Save some metadata which will eventually end up in the wick file - - data.metadata = Wick.WickFile.generateMetaData(); - return data; - } - - get classname() { - return 'Project'; - } - /** - * The width of the project. - * @type {number} - */ - - - get width() { - return this._width; - } - - set width(width) { - if (typeof width !== 'number') return; - if (width < 1) width = 1; - if (width > 200000) width = 200000; - this._width = width; - } - /** - * The height of the project. - * @type {number} - */ - - - get height() { - return this._height; - } - - set height(height) { - if (typeof height !== 'number') return; - if (height < 1) height = 1; - if (height > 200000) height = 200000; - this._height = height; - } - /** - * The framerate of the project. - * @type {number} - */ - - - get framerate() { - return this._framerate; - } - - set framerate(framerate) { - if (typeof framerate !== 'number') return; - if (framerate < 1) framerate = 1; - if (framerate > 9999) framerate = 9999; - this._framerate = framerate; - } - /** - * The background color of the project. - * @type {string} - */ - - - get backgroundColor() { - return this._backgroundColor; - } - - set backgroundColor(backgroundColor) { - if (typeof backgroundColor !== 'string') return; - this._backgroundColor = backgroundColor; - } - /** - * The timeline of the active clip. - * @type {Wick.Timeline} - */ - - - get activeTimeline() { - return this.focus.timeline; - } - /** - * The active layer of the active timeline. - * @type {Wick.Layer} - */ - - - get activeLayer() { - return this.activeTimeline.activeLayer; - } - /** - * The active frame of the active layer. - * @type {Wick.Frame} - */ - - - get activeFrame() { - return this.activeLayer.activeFrame; - } - /** - * The active frames of the active timeline. - * @type {Wick.Frame[]} - */ - - - get activeFrames() { - return this.focus.timeline.activeFrames; - } - /** - * All frames in this project. - * @type {Wick.Frame[]} - */ - - - getAllFrames() { - return this.root.timeline.getAllFrames(true); - } - /** - * The project selection. - * @type {Wick.Selection} - */ - - - get selection() { - return this.getChild('Selection'); - } - - set selection(selection) { - if (this.selection) { - this.removeChild(this.selection); - } - - this.addChild(selection); - } - /** - * An instance of the Wick.History utility class for undo/redo functionality. - * @type {Wick.History} - */ - - - get history() { - return this._history; - } - - set history(history) { - this._history = history; - } - /** - * Undo the last action. - * @returns {boolean} true if there was something to undo, false otherwise. - */ - - - undo() { - // Undo discards in-progress brush strokes. - if (this._tools.brush.isInProgress()) { - this._tools.brush.discard(); - - return true; - } - - this.selection.clear(); - var success = this.project.history.popState(); - return success; - } - /** - * Redo the last action that was undone. - * @returns {boolean} true if there was something to redo, false otherwise. - */ - - - redo() { - this.selection.clear(); - var success = this.project.history.recoverState(); - return success; - } - /** - * The assets belonging to the project. - * @type {Wick.Asset[]} - */ - - - get assets() { - return this.getChildren(['ImageAsset', 'SoundAsset', 'ClipAsset', 'FontAsset']); - } - /** - * Adds an asset to the project. - * @param {Wick.Asset} asset - The asset to add to the project. - */ - - - addAsset(asset) { - if (this.assets.indexOf(asset) === -1) { - this.addChild(asset); - } - } - /** - * Removes an asset from the project. Also removes all instances of that asset from the project. - * @param {Wick.Asset} asset - The asset to remove from the project. - */ - - - removeAsset(asset) { - asset.removeAllInstances(); - this.removeChild(asset); - } - /** - * Retrieve an asset from the project by its UUID. - * @param {string} uuid - The UUID of the asset to get. - * @return {Wick.Asset} The asset - */ - - - getAssetByUUID(uuid) { - var asset = this.getAssets().find(asset => { - return asset.uuid === uuid; - }); - - if (asset) { - return asset; - } else { - console.warn('Wick.Project.getAssetByUUID: No asset found with uuid ' + uuid); - } - } - /** - * Retrieve an asset from the project by its name. - * @param {string} name - The name of the asset to get. - * @return {Wick.Asset} The asset - */ - - - getAssetByName(name) { - return this.getAssets().find(asset => { - return asset.name === name; - }); - } - /** - * The assets belonging to the project. - * @param {string} type - Optional, filter assets by type ("Sound"/"Image"/"Clip"/"Button") - * @returns {Wick.Asset[]} The assets in the project - */ - - - getAssets(type) { - if (!type) { - return this.assets; - } else { - return this.assets.filter(asset => { - return asset instanceof Wick[type + 'Asset']; - }); - } - } - /** - * A list of all "fontFamily" in the asset library. - * @returns {[string]} - */ - - - getFonts() { - return this.getAssets('Font').map(asset => { - return asset.fontFamily; - }); - } - /** - * Check if a FontAsset with a given fontFamily exists in the project. - * @param {string} fontFamily - The font to check for - * @returns {boolean} - */ - - - hasFont(fontFamily) { - return this.getFonts().find(seekFontFamily => { - return seekFontFamily === fontFamily; - }) !== undefined; - } - /** - * The root clip. - * @type {Wick.Clip} - */ - - - get root() { - return this.getChild('Clip'); - } - - set root(root) { - if (this.root) { - this.removeChild(this.root); - } - - this.addChild(root); - } - /** - * The currently focused clip. - * @type {Wick.Clip} - */ - - - get focus() { - return this._focus && Wick.ObjectCache.getObjectByUUID(this._focus); - } - - set focus(focus) { - var focusChanged = this.focus !== null && this.focus !== focus; - this._focus = focus.uuid; - - if (focusChanged) { - this.selection.clear(); // Reset timelines of subclips of the newly focused clip - - focus.timeline.clips.forEach(subclip => { - subclip.timeline.playheadPosition = 1; - }); // Reset pan and zoom and clear selection on focus change - - this.recenter(); - } - } - /** - * The position of the mouse - * @type {object} - */ - - - get mousePosition() { - return this._mousePosition; - } - - set mousePosition(mousePosition) { - this._lastMousePosition = { - x: this.mousePosition.x, - y: this.mousePosition.y - }; - this._mousePosition = mousePosition; - } - /** - * The amount the mouse has moved in the last tick - * @type {object} - */ - - - get mouseMove() { - let moveX = this.mousePosition.x - this._lastMousePosition.x; - let moveY = this.mousePosition.y - this._lastMousePosition.y; - return { - x: moveX, - y: moveY - }; - } - /** - * Determine if the mouse is down. - * @type {boolean} - */ - - - get isMouseDown() { - return this._isMouseDown; - } - - set isMouseDown(isMouseDown) { - this._isMouseDown = isMouseDown; - } - /** - * The keys that are currenty held down. - * @type {string[]} - */ - - - get keysDown() { - return this._keysDown; - } - - set keysDown(keysDown) { - this._keysDown = keysDown; - } - /** - * The keys were just pressed (i.e., are currently held down, but were not last tick). - * @type {string[]} - */ - - - get keysJustPressed() { - // keys that are in _keysDown, but not in _keysLastDown - return this._keysDown.filter(key => { - return this._keysLastDown.indexOf(key) === -1; - }); - } - /** - * The keys that were just released (i.e. were down last tick back are no longer down.) - * @return {string[]} - */ - - - get keysJustReleased() { - return this._keysLastDown.filter(key => { - return this._keysDown.indexOf(key) === -1; - }); - } - /** - * Check if a key is being pressed. - * @param {string} key - The name of the key to check - */ - - - isKeyDown(key) { - return this.keysDown.indexOf(key) !== -1; - } - /** - * Check if a key was just pressed. - * @param {string} key - The name of the key to check - */ - - - isKeyJustPressed(key) { - return this.keysJustPressed.indexOf(key) !== -1; - } - /** - * The key to be used in the global 'key' variable in the scripting API. Update currentKey before you run any key script. - * @type {string[]} - */ - - - get currentKey() { - return this._currentKey; - } - - set currentKey(currentKey) { - this._currentKey = currentKey; - } - /** - * Creates an asset from a File object and adds that asset to the project. - * @param {File} file - File object to be read and converted into an asset. - * @param {function} callback Function with the created Wick Asset. Can be passed undefined on improper file input. - */ - - - importFile(file, callback) { - let imageTypes = Wick.ImageAsset.getValidMIMETypes(); - let soundTypes = Wick.SoundAsset.getValidMIMETypes(); - let fontTypes = Wick.FontAsset.getValidMIMETypes(); - let asset = undefined; - - if (imageTypes.indexOf(file.type) !== -1) { - asset = new Wick.ImageAsset(); - } else if (soundTypes.indexOf(file.type) !== -1) { - asset = new Wick.SoundAsset(); - } else if (fontTypes.indexOf(file.type) !== -1) { - asset = new Wick.FontAsset(); - } - - if (asset === undefined) { - console.warn('importFile(): Could not import file ' + file.name + ', filetype: "' + file.type + '" is not supported.'); - console.warn('supported image file types:'); - console.log(imageTypes); - console.warn('supported sound file types:'); - console.log(soundTypes); - console.warn('supported font file types:'); - console.log(fontTypes); - callback(null); - return; - } - - let reader = new FileReader(); - - reader.onload = () => { - let dataURL = reader.result; - asset.src = dataURL; - asset.filename = file.name; - asset.name = file.name; - this.addAsset(asset); - asset.load(() => { - callback(asset); - }); - }; - - reader.readAsDataURL(file); - } - /** - * Deletes all objects in the selection. - */ - - - deleteSelectedObjects() { - var objects = this.selection.getSelectedObjects(); - this.selection.clear(); - this.activeTimeline.deferFrameGapResolve(); - objects.forEach(object => { - object.remove && object.remove(); - }); - this.activeTimeline.resolveFrameGaps([]); - } - /** - * Perform a boolean operation on all selected paths. - * @param {string} booleanOpName - The name of the boolean op function to use. See Wick.Path.booleanOp. - */ - - - doBooleanOperationOnSelection(booleanOpName) { - var paths = this.selection.getSelectedObjects('Path'); - this.selection.clear(); - var booleanOpResult = Wick.Path.booleanOp(paths, booleanOpName); - paths.forEach(path => { - path.remove(); - }); - this.activeFrame.addPath(booleanOpResult); - this.selection.select(booleanOpResult); - } - /** - * Copy the contents of the selection to the clipboard. - * @returns {boolean} True if there was something to copy, false otherwise - */ - - - copySelectionToClipboard() { - var objects = this.selection.getSelectedObjects(); - - if (objects.length === 0) { - return false; - } else { - this.clipboard.copyObjectsToClipboard(this, objects); - return true; - } - } - /** - * Copy the contents of the selection to the clipboard, and delete what was copied. - * @returns {boolean} True if there was something to cut, false otherwise - */ - - - cutSelectionToClipboard() { - if (this.copySelectionToClipboard()) { - this.deleteSelectedObjects(); - return true; - } else { - return false; - } - } - /** - * Paste the contents of the clipboard into the project. - * @returns {boolean} True if there was something to paste in the clipboard, false otherwise. - */ - - - pasteClipboardContents() { - return this.clipboard.pasteObjectsFromClipboard(this); - } - /** - * Copy and paste the current selection. - * @returns {boolean} True if there was something to duplicate, false otherwise - */ - - - duplicateSelection() { - if (!this.copySelectionToClipboard()) { - return false; - } else { - return this.pasteClipboardContents(); - } - } - /** - * Cut the currently selected frames. - */ - - - cutSelectedFrames() { - this.selection.getSelectedObjects('Frame').forEach(frame => { - frame.cut(); - }); - } - /** - * Insert a blank frame at the current playhead position, and selects the newly added frames. - */ - - - insertBlankFrame() { - var addedFrames = []; - - if (this.selection.numObjects > 0) { - // Are there frames selected? insert blank frames inside of them - this.selection.getSelectedObjects('Frame').forEach(frame => { - addedFrames.push(frame.insertBlankFrame()); - }); - } else if (this.activeFrame) { - // Otherwise, just add a frame at the playhead position + active layer - addedFrames.push(this.activeFrame.insertBlankFrame()); - } else { - // Or, if there was no active frame, create a new frame - var newFrame = new Wick.Frame({ - start: this.activeTimeline.playheadPosition - }); - this.activeLayer.addFrame(newFrame); - addedFrames.push(newFrame); - } // Select the newly added frames - - - this.selection.clear(); - - this.selection.selectMultipleObjects(addedFrames); - } - /** - * A tween can be created if frames are selected or if there is a frame under the playhead on the active layer. - */ - - - get canCreateTween() { - // Frames are selected, a tween can be created - var selectedFrames = this.selection.getSelectedObjects('Frame'); - - if (selectedFrames.length > 0) { - // Make sure you can only create tweens on contentful frames - if (selectedFrames.find(frame => { - return !frame.contentful; - })) { - return false; - } else { - return true; - } - } // There is a frame under the playhead on the active layer, a tween can be created - - - var activeFrame = this.activeLayer.activeFrame; - - if (activeFrame) { - // ...but only if that frame is contentful - return activeFrame.contentful; - } - - return false; - } - /** - * Create a new tween on all selected frames OR on the active frame of the active layer. - */ - - - createTween() { - var selectedFrames = this.selection.getSelectedObjects('Frame'); - - if (selectedFrames.length > 0) { - // Create a tween on all selected frames - this.selection.getSelectedObjects('Frame').forEach(frame => { - frame.createTween(); - }); - } else { - // Create a tween on the active frame - this.activeLayer.activeFrame.createTween(); - } - } - /** - * Tries to create a tween if there is an empty space between tweens. - */ - - - tryToAutoCreateTween() { - var frame = this.activeFrame; - - if (frame.tweens.length > 0 && !frame.getTweenAtPosition(frame.getRelativePlayheadPosition())) { - frame.createTween(); - } - } - /** - * Move the right edge of all selected frames right one frame. - */ - - - extendSelectedFrames() { - var frames = this.selection.getSelectedObjects('Frame'); - frames.forEach(frame => { - frame.end++; - }); - this.activeTimeline.resolveFrameOverlap(frames); - this.activeTimeline.resolveFrameGaps(frames); - } - /** - * Move the right edge of all selected frames right one frame, and push other frames away. - */ - - - extendSelectedFramesAndPushOtherFrames() { - var frames = this.selection.getSelectedObjects('Frame'); - frames.forEach(frame => { - frame.extendAndPushOtherFrames(); - }); - } - /** - * Move the right edge of all selected frames left one frame. - */ - - - shrinkSelectedFrames() { - var frames = this.selection.getSelectedObjects('Frame'); - frames.forEach(frame => { - if (frame.length === 1) return; - frame.end--; - }); - this.activeTimeline.resolveFrameOverlap(frames); - this.activeTimeline.resolveFrameGaps(frames); - } - /** - * Move the right edge of all selected frames left one frame, and pull other frames along. - */ - - - shrinkSelectedFramesAndPullOtherFrames() { - var frames = this.selection.getSelectedObjects('Frame'); - frames.forEach(frame => { - frame.shrinkAndPullOtherFrames(); - }); - } - /** - * Shift all selected frames over one frame to the right - */ - - - moveSelectedFramesRight() { - var frames = this.selection.getSelectedObjects('Frame'); - frames.forEach(frame => { - frame.end++; - frame.start++; - }); - this.activeTimeline.resolveFrameOverlap(frames); - this.activeTimeline.resolveFrameGaps(); - } - /** - * Shift all selected frames over one frame to the left - */ - - - moveSelectedFramesLeft() { - var frames = this.selection.getSelectedObjects('Frame'); - frames.forEach(frame => { - frame.start--; - frame.end--; - }); - this.activeTimeline.resolveFrameOverlap(frames); - this.activeTimeline.resolveFrameGaps(); - } - /** - * Selects all objects that are visible on the canvas (excluding locked layers and onion skinned objects) - */ - - - selectAll() { - this.selection.clear(); - this.activeFrames.filter(frame => { - return !frame.parentLayer.locked && !frame.parentLayer.hidden; - }).forEach(frame => { - frame.paths.forEach(path => { - this.selection.select(path); - }); - frame.clips.forEach(clip => { - this.selection.select(clip); - }); - }); - } - /** - * Adds an image path to the active frame using a given asset as its image src. - * @param {Wick.Asset} asset - the asset to use for the image src - * @param {number} x - the x position to create the image path at - * @param {number} y - the y position to create the image path at - * @param {function} callback - the function to call after the path is created. - */ - - - createImagePathFromAsset(asset, x, y, callback) { - asset.createInstance(path => { - this.activeFrame.addPath(path); - path.x = x; - path.y = y; - callback(path); - }); - } - /** - * Creates a symbol from the objects currently selected. - * @param {string} identifier - the identifier to give the new symbol - * @param {string} type - "Clip" or "Button" - */ - - - createClipFromSelection(args) { - if (!args) { - args = {}; - } - - ; - - if (args.type !== 'Clip' && args.type !== 'Button') { - console.error('createClipFromSelection: invalid type: ' + args.type); - return; - } - - var clip = new Wick[args.type]({ - identifier: args.identifier, - objects: this.selection.getSelectedObjects('Canvas'), - transformation: new Wick.Transformation({ - x: this.selection.x + this.selection.width / 2, - y: this.selection.y + this.selection.height / 2 - }) - }); - this.activeFrame.addClip(clip); // TODO add to asset library - - this.selection.clear(); - this.selection.select(clip); - } - /** - * Breaks selected clips into their children clips and paths. - */ - - - breakApartSelection() { - var leftovers = []; - var clips = this.selection.getSelectedObjects('Clip'); - this.selection.clear(); - clips.forEach(clip => { - leftovers = leftovers.concat(clip.breakApart()); - }); - leftovers.forEach(object => { - this.selection.select(object); - }); - } - /** - * Sets the project focus to the timeline of the selected clip. - */ - - - focusTimelineOfSelectedClip() { - if (this.selection.getSelectedObject() instanceof Wick.Clip) { - this.focus = this.selection.getSelectedObject(); - } - } - /** - * Sets the project focus to the parent timeline of the currently focused clip. - */ - - - focusTimelineOfParentClip() { - if (!this.focus.isRoot) { - this.focus = this.focus.parentClip; - } - } - /** - * Plays the sound in the asset library with the given name. - * @param {string} assetName - Name of the sound asset to play - * @param {Object} options - options for the sound. See Wick.SoundAsset.play - */ - - - playSound(assetName, options) { - var asset = this.getAssetByName(assetName); - - if (!asset) { - console.warn('playSound(): No asset with name: "' + assetName + '"'); - } else if (!(asset instanceof Wick.SoundAsset)) { - console.warn('playSound(): Asset is not a sound: "' + assetName + '"'); - } else { - asset.play(options); - } - } - /** - * Stops all sounds playing from frames and sounds played using playSound(). - */ - - - stopAllSounds() { - // Stop all sounds started with Wick.Project.playSound(); - this.getAssets('Sound').forEach(soundAsset => { - soundAsset.stop(); - }); // Stop all sounds on frames - - this.getAllFrames().forEach(frame => { - frame.stopSound(); - }); - } - /** - * Disable all sounds from playing - */ - - - mute() { - this._muted = true; - } - /** - * Enable all sounds to play - */ - - - unmute() { - this._muted = false; - } - /** - * Is the project currently muted? - */ - - - get muted() { - return this._muted; - } - /** - * In "Published Mode", all layers will be rendered even if they are set to be hidden. - * This is enabled during GIF/Video export, and enabled when the project is run standalone. - * @type {boolean} - */ - - - get publishedMode() { - return this._publishedMode; - } - - set publishedMode(publishedMode) { - this._publishedMode = publishedMode; - } - /** - * Ticks the project. - * @returns {object} An object containing information about an error, if one occured while running scripts. Null otherwise. - */ - - - tick() { - this.root._identifier = 'Project'; // Process input - - this._mousePosition = this.tools.interact.mousePosition; - this._isMouseDown = this.tools.interact.mouseIsDown; - this._keysDown = this.tools.interact.keysDown; - this._currentKey = this.tools.interact.lastKeyDown; - this._mouseTargets = this.tools.interact.mouseTargets; // Tick the focus - - this.focus._attachChildClipReferences(); - - var error = this.focus.tick(); // Save the current keysDown - - this._lastMousePosition = { - x: this._mousePosition.x, - y: this._mousePosition.y - }; - this._keysLastDown = [].concat(this._keysDown); - this.view.render(); - return error; - } - /** - * Checks if the project is currently playing. - * @type {boolean} - */ - - - get playing() { - return this._playing; - } - /** - * Start playing the project. - * Arguments: onError: Called when a script error occurs during a tick. - * onBeforeTick: Called before every tick - * onAfterTick: Called after every tick - * @param {object} args - Optional arguments - */ - - - play(args) { - if (!args) args = {}; - if (!args.onError) args.onError = () => {}; - if (!args.onBeforeTick) args.onBeforeTick = () => {}; - if (!args.onAfterTick) args.onAfterTick = () => {}; - this._playing = true; - this.view.paper.view.autoUpdate = false; - - if (this._tickIntervalID) { - this.stop(); - } - - this.history.saveSnapshot('state-before-play'); - this.selection.clear(); // Start tick loop - - this._tickIntervalID = setInterval(() => { - args.onBeforeTick(); - var error = this.tick(); - this.view.paper.view.update(); - - if (error) { - args.onError(error); - this.stop(); - return; - } - - args.onAfterTick(); - }, 1000 / this.framerate); - } - /** - * Stop playing the project. - */ - - - stop() { - this._playing = false; - this.view.paper.view.autoUpdate = true; // Run unload scripts on all objects - - this.getAllFrames().forEach(frame => { - frame.clips.forEach(clip => { - clip.runScript('unload'); - }); - }); - this.stopAllSounds(); - clearInterval(this._tickIntervalID); - this._tickIntervalID = null; // Loading the snapshot to restore project state also moves the playhead back to where it was originally. - // We actually don't want this, preview play should actually move the playhead after it's stopped. - - var currentPlayhead = this.focus.timeline.playheadPosition; - this.history.loadSnapshot('state-before-play'); - this.focus.timeline.playheadPosition = currentPlayhead; - } - /** - * Resets zoom and pan. - */ - - - recenter() { - this.pan = { - x: 0, - y: 0 - }; - this.zoom = 1; - } - /** - * Zooms the canvas in. - */ - - - zoomIn() { - this.zoom *= 1.25; - } - /** - * Zooms the canvas out. - */ - - - zoomOut() { - this.zoom *= 0.8; - } - /** - * All tools belonging to the project. - * @type {Array} - */ - - - get tools() { - return this._tools; - } - /** - * The tool settings for the project's tools. - * @type {Wick.ToolSettings} - */ - - - get toolSettings() { - return this._toolSettings; - } - /** - * The currently activated tool. - * @type {Wick.Tool} - */ - - - get activeTool() { - return this._activeTool; - } - - set activeTool(activeTool) { - var newTool; - - if (typeof activeTool === 'string') { - var tool = this.tools[activeTool]; - - if (!tool) { - console.error('set activeTool: invalid tool: ' + activeTool); - } - - newTool = tool; - } else { - newTool = activeTool; - } // Clear selection if we changed between drawing tools - - - if (newTool.name !== 'pan' && newTool.name !== 'eyedropper' && newTool.name !== 'cursor') { - this.selection.clear(); - } - - this._activeTool = newTool; - } - /** - * Adds an object to the project. - * @param {Wick.Base} object - * @return {boolean} returns true if the obejct was added successfully, false otherwise. - */ - - - addObject(object) { - if (object instanceof Wick.Path) { - this.activeFrame.addPath(object); - } else if (object instanceof Wick.Clip) { - this.activeFrame.addClip(object); - } else if (object instanceof Wick.Frame) { - this.activeTimeline.addFrame(object); - } else if (object instanceof Wick.Asset) { - this.addAsset(object); - } else if (object instanceof Wick.Layer) { - this.activeTimeline.addLayer(object); - } else if (object instanceof Wick.Tween) { - this.activeFrame.addTween(object); - } else { - return false; - } - - return true; - } - /** - * Create a sequence of images from every frame in the project. - * @param {object} args - Options for generating the image sequence - * @param {string} imageType - MIMEtype to use for rendered images. Defaults to 'image/png'. - * @param {function} onProgress = Function to call for each image loaded, useful for progress bars - * @param {function} onFinish - Function to call when the images are all loaded. - */ - - - generateImageSequence(args) { - if (!args) args = {}; - if (!args.imageType) args.imageType = 'image/png'; - if (!args.onProgress) args.onProgress = () => {}; - if (!args.onFinish) args.onFinish = () => {}; - var renderCopy = this; - var oldCanvasContainer = this.view.canvasContainer; - this.history.saveSnapshot('before-gif-render'); - this.mute(); - this.publishedMode = true; - this.tick(); // Put the project canvas inside a div that's the same size as the project so the frames render at the correct resolution. - - let container = window.document.createElement('div'); - container.style.width = renderCopy.width / window.devicePixelRatio + 'px'; - container.style.height = renderCopy.height / window.devicePixelRatio + 'px'; - window.document.body.appendChild(container); - renderCopy.view.canvasContainer = container; - renderCopy.view.resize(); // Set the initial state of the project. - - renderCopy.focus = renderCopy.root; - renderCopy.focus.timeline.playheadPosition = 1; - renderCopy.onionSkinEnabled = false; - renderCopy.zoom = 1 / window.devicePixelRatio; - renderCopy.pan = { - x: 0, - y: 0 - }; //renderCopy.tick(); - // We need full control over when paper.js renders, if we leave autoUpdate on, it's possible to lose frames if paper.js doesnt automatically render as fast as we are generating the images. - // (See paper.js docs for info about autoUpdate) - - renderCopy.view.paper.view.autoUpdate = false; - var frameImages = []; - var numMaxFrameImages = renderCopy.focus.timeline.length; - - var renderFrame = () => { - var frameImage = new Image(); - - frameImage.onload = () => { - frameImages.push(frameImage); - var currentPos = renderCopy.focus.timeline.playheadPosition; - args.onProgress(currentPos, numMaxFrameImages); - - if (currentPos >= numMaxFrameImages) { - // reset autoUpdate back to normal - renderCopy.view.paper.view.autoUpdate = true; - this.view.canvasContainer = oldCanvasContainer; - this.view.resize(); - this.history.loadSnapshot('before-gif-render'); - this.publishedMode = false; - this.view.render(); - window.document.body.removeChild(container); - args.onFinish(frameImages); - } else { - renderCopy.tick(); - renderFrame(); - } - }; - - renderCopy.view.render(); - renderCopy.view.paper.view.update(); - frameImage.src = renderCopy.view.canvas.toDataURL(args.imageType); - }; - - renderFrame(); - } - /** - * Create an object containing info on all sounds in the project. - * Format: - * start: The amount of time in milliseconds to cut from the beginning of the sound. - * end: The amount of time that the sound will play before stopping. - * offset: The amount of time to offset the start of the sound. - * src: The source of the sound as a dataURL. - * filetype: The file type of the sound asset. - */ - - - getAudioInfo() { - return this.root.timeline.frames.filter(frame => { - return frame.sound !== null; - }).map(frame => { - return { - start: frame.soundStartMS, - end: frame.soundEndMS, - offset: frame.cropSoundOffsetMS, - src: frame.sound.src, - filetype: frame.sound.fileExtension - }; - }); - } - /** - * Generate an audiobuffer containing all the project's sounds merged together. - * @param {object} args - placeholder for future options, not currently used - * @param {Function} callback - callback used to recieve the final audiobuffer. - */ - - - generateAudioTrack(args, callback) { - var audioTrack = new Wick.AudioTrack(this); - audioTrack.toAudioBuffer(audioBuffer => { - callback(audioBuffer); - }); - } - /** - * Check if an object is a mouse target (if the mouse is currently hovered over the object) - * @param {Wick.Tickable} object - the object to check if it is a mouse target - */ - - - objectIsMouseTarget(object) { - return this._mouseTargets.indexOf(object) !== -1; - } - /** - * Whether or not to hide the cursor while project is playing. - * @type {boolean} - */ - - - get hideCursor() { - return this._hideCursor; - } - - set hideCursor(hideCursor) { - this._hideCursor = hideCursor; - } - /** - * Returns true if there is currently an active frame to draw onto. - * @type {boolean} - */ - - - get canDraw() { - return !this.activeLayer.locked && !this.activeLayer.hidden; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * Class representing a Wick Selection. - */ -Wick.Selection = class extends Wick.Base { - static get SELECTABLE_OBJECT_TYPES() { - return ['Path', 'Clip', 'Frame', 'Tween', 'Layer', 'Asset']; - } - - static get LOCATION_NAMES() { - return ['Canvas', 'Timeline', 'AssetLibrary']; - } - /** - * Create a Wick Selection. - */ - - - constructor(args) { - if (!args) args = {}; - super(args); - this._selectedObjectsUUIDs = args.selectedObjects || []; - this._widgetRotation = args.widgetRotation || 0; - this._pivotPoint = { - x: 0, - y: 0 - }; - } - - serialize(args) { - var data = super.serialize(args); - data.selectedObjects = Array.from(this._selectedObjectsUUIDs); - data.widgetRotation = this._widgetRotation; - data.pivotPoint = { - x: this._pivotPoint.x, - y: this._pivotPoint.y - }; - return data; - } - - deserialize(data) { - super.deserialize(data); - this._selectedObjectsUUIDs = data.selectedObjects || []; - this._widgetRotation = data.widgetRotation; - this._pivotPoint = { - x: data.pivotPoint.x, - y: data.pivotPoint.y - }; - } - - get classname() { - return 'Selection'; - } - /** - * The names of all attributes of the selection that can be changed. - * @type {string[]} - */ - - - get allAttributeNames() { - return ["strokeWidth", "fillColor", "strokeColor", "name", "filename", "fontSize", "fontFamily", "fontWeight", "fontStyle", "src", "frameLength", "x", "y", "width", "height", "rotation", "opacity", "sound", "soundVolume", "soundStart", "identifier", "easingType"]; - } - /** - * Add a wick object to the selection. - * @param {Wick.Base} object - The object to select. - */ - - - select(object) { - // Do not allow selection of objects not defined to be selectable - if (!Wick.Selection.SELECTABLE_OBJECT_TYPES.find(type => { - return object instanceof Wick[type]; - })) { - console.warn("Tried to select a " + object.classname + " object. This type is not selectable"); - return; - } // Don't do anything if the object is already selected - - - if (this.isObjectSelected(object)) { - return; - } // Activate the cursor tool when selection changes - - - if (this._locationOf(object) === 'Canvas') { - this.project.activeTool = this.project.tools.cursor; - object.parentLayer && object.parentLayer.activate(); - } // Only allow selection of objects of in the same location - - - if (this._locationOf(object) !== this.location) { - this.clear(); - } // Add the object to the selection! - - - this._selectedObjectsUUIDs.push(object.uuid); // Select in between frames (for shift+click selecting frames) - - - if (object instanceof Wick.Frame) { - this._selectInBetweenFrames(object); - } - - this._resetPositioningValues(); // Make sure the view gets updated the next time its needed... - - - this.view.dirty = true; - } - /** - * Remove a wick object from the selection. - * @param {Wick.Base} object - The object to deselect. - */ - - - deselect(object) { - this._selectedObjectsUUIDs = this._selectedObjectsUUIDs.filter(uuid => { - return uuid !== object.uuid; - }); - - this._resetPositioningValues(); // Make sure the view gets updated the next time its needed... - - - this.view.dirty = true; - } - /** - * Remove all objects from the selection with an optional filter. - * @param {string} filter - A location or a type (see SELECTABLE_OBJECT_TYPES and LOCATION_NAMES) - */ - - - clear(filter) { - this.project.selection.getSelectedObjects(filter).forEach(object => { - this.deselect(object); - }); - } - /** - * Checks if a given object is selected. - * @param {Wick.Base} object - The object to check selection of. - */ - - - isObjectSelected(object) { - return this._selectedObjectsUUIDs.indexOf(object.uuid) !== -1; - } - /** - * Get the first object in the selection if there is a single object in the selection. - * @return {Wick.Base} The first object in the selection. - */ - - - getSelectedObject() { - if (this.numObjects === 1) { - return this.getSelectedObjects()[0]; - } else { - return null; - } - } - /** - * Get the objects in the selection with an optional filter. - * @param {string} filter - A location or a type (see SELECTABLE_OBJECT_TYPES and LOCATION_NAMES) - * @return {Wick.Base[]} The selected objects. - */ - - - getSelectedObjects(filter) { - var objects = this._selectedObjectsUUIDs.map(uuid => { - return Wick.ObjectCache.getObjectByUUID(uuid); - }); - - if (Wick.Selection.LOCATION_NAMES.indexOf(filter) !== -1) { - var location = filter; - - if (this.location !== location) { - return []; - } else { - return this.getSelectedObjects(); - } - } else if (typeof filter === 'string') { - var classname = filter; - objects = objects.filter(object => { - return object instanceof Wick[classname]; - }); - } - - return objects; - } - /** - * Get the UUIDs of the objects in the selection with an optional filter. - * @param {string} filter - A location or a type (see SELECTABLE_OBJECT_TYPES and LOCATION_NAMES) - * @return {string[]} The UUIDs of the selected objects. - */ - - - getSelectedObjectUUIDs(filter) { - return this.getSelectedObjects(filter).map(object => { - return object.uuid; - }); - } - /** - * The location of the objects in the selection. (see LOCATION_NAMES) - * @type {string} - */ - - - get location() { - if (this.numObjects === 0) return null; - return this._locationOf(this.getSelectedObjects()[0]); - } - /** - * The types of the objects in the selection. (see SELECTABLE_OBJECT_TYPES) - * @type {string[]} - */ - - - get types() { - var types = this.getSelectedObjects().map(object => { - return object.classname; - }); - var uniqueTypes = [...new Set(types)]; - return uniqueTypes; - } - /** - * A single string describing the contents of the selection. - * @type {string} - */ - - - get selectionType() { - let selection = this; - - if (selection.location === 'Canvas') { - if (selection.numObjects === 1) { - var selectedObject = selection.getSelectedObject(); - - if (selectedObject instanceof window.Wick.Path) { - return selectedObject.pathType; - } else if (selectedObject instanceof window.Wick.Button) { - return 'button'; - } else if (selectedObject instanceof window.Wick.Clip) { - return 'clip'; - } - } else if (selection.types.length === 1) { - if (selection.types[0] === 'Path') { - return 'multipath'; - } else { - return 'multiclip'; - } - } else { - return 'multicanvas'; - } - } else if (selection.location === 'Timeline') { - if (selection.numObjects === 1) { - if (selection.getSelectedObject() instanceof window.Wick.Frame) { - return 'frame'; - } else if (selection.getSelectedObject() instanceof window.Wick.Layer) { - return 'layer'; - } else if (selection.getSelectedObject() instanceof window.Wick.Tween) { - return 'tween'; - } - } else if (selection.types.length === 1) { - if (selection.getSelectedObjects()[0] instanceof window.Wick.Frame) { - return 'multiframe'; - } else if (selection.getSelectedObjects()[0] instanceof window.Wick.Layer) { - return 'multilayer'; - } else if (selection.getSelectedObjects()[0] instanceof window.Wick.Tween) { - return 'multitween'; - } - } else { - return 'multitimeline'; - } - } else if (selection.location === 'AssetLibrary') { - if (selection.getSelectedObjects()[0] instanceof window.Wick.ImageAsset) { - return 'imageasset'; - } else if (selection.getSelectedObjects()[0] instanceof window.Wick.SoundAsset) { - return 'soundasset'; - } else { - return 'multiassetmixed'; - } - } else { - return 'unknown'; - } - } - /** - * The number of objects in the selection. - * @type {number} - */ - - - get numObjects() { - return this._selectedObjectsUUIDs.length; - } - /** - * The rotation of the selection (used for canvas selections) - * @type {number} - */ - - - get widgetRotation() { - return this._widgetRotation; - } - - set widgetRotation(widgetRotation) { - this._widgetRotation = widgetRotation; - } - /** - * The point that transformations to the selection will be based around. - * @type {object} - */ - - - get pivotPoint() { - return this._pivotPoint; - } - - set pivotPoint(pivotPoint) { - this._pivotPoint = pivotPoint; - } - /** - * The position of the selection. - * @type {number} - */ - - - get x() { - return this.view.x; - } - - set x(x) { - this.view.x = x; - this.project.tryToAutoCreateTween(); - } - /** - * The position of the selection. - * @type {number} - */ - - - get y() { - return this.view.y; - } - - set y(y) { - this.view.y = y; - this.project.tryToAutoCreateTween(); - } - /** - * The width of the selection. - * @type {number} - */ - - - get width() { - return this.view.width; - } - - set width(width) { - this.project.tryToAutoCreateTween(); - this.view.width = width; - } - /** - * The height of the selection. - * @type {number} - */ - - - get height() { - return this.view.height; - } - - set height(height) { - this.project.tryToAutoCreateTween(); - this.view.height = height; - } - /** - * The rotation of the selection. - * @type {number} - */ - - - get rotation() { - return this.view.rotation; - } - - set rotation(rotation) { - this.project.tryToAutoCreateTween(); - this.view.rotation = rotation; - } - /** - * Flips the selected obejcts horizontally. - */ - - - flipHorizontally() { - this.project.tryToAutoCreateTween(); - this.view.flipHorizontally(); - } - /** - * Flips the selected obejcts vertically. - */ - - - flipVertically() { - this.project.tryToAutoCreateTween(); - this.view.flipVertically(); - } - /** - * Sends the selected objects to the back. - */ - - - sendToBack() { - this.view.sendToBack(); - } - /** - * Brings the selected objects to the front. - */ - - - bringToFront() { - this.view.bringToFront(); - } - /** - * Moves the selected objects forwards. - */ - - - moveForwards() { - this.view.moveForwards(); - } - /** - * Moves the selected objects backwards. - */ - - - moveBackwards() { - this.view.moveBackwards(); - } - /** - * The identifier of the selected object. - * @type {string} - */ - - - get identifier() { - return this._getSingleAttribute('identifier'); - } - - set identifier(identifier) { - this._setSingleAttribute('identifier', identifier); - } - /** - * The name of the selected object. - * @type {string} - */ - - - get name() { - return this._getSingleAttribute('name'); - } - - set name(name) { - this._setSingleAttribute('name', name); - } - /** - * The fill color of the selected object. - * @type {paper.Color} - */ - - - get fillColor() { - return this._getSingleAttribute('fillColor'); - } - - set fillColor(fillColor) { - this._setSingleAttribute('fillColor', fillColor); - } - /** - * The stroke color of the selected object. - * @type {paper.Color} - */ - - - get strokeColor() { - return this._getSingleAttribute('strokeColor'); - } - - set strokeColor(strokeColor) { - this._setSingleAttribute('strokeColor', strokeColor); - } - /** - * The stroke width of the selected object. - * @type {number} - */ - - - get strokeWidth() { - return this._getSingleAttribute('strokeWidth'); - } - - set strokeWidth(strokeWidth) { - this._setSingleAttribute('strokeWidth', strokeWidth); - } - /** - * The font family of the selected object. - * @type {string} - */ - - - get fontFamily() { - return this._getSingleAttribute('fontFamily'); - } - - set fontFamily(fontFamily) { - this._setSingleAttribute('fontFamily', fontFamily); - } - /** - * The font size of the selected object. - * @type {number} - */ - - - get fontSize() { - return this._getSingleAttribute('fontSize'); - } - - set fontSize(fontSize) { - this._setSingleAttribute('fontSize', fontSize); - } - /** - * The font weight of the selected object. - * @type {number} - */ - - - get fontWeight() { - return this._getSingleAttribute('fontWeight'); - } - - set fontWeight(fontWeight) { - this._setSingleAttribute('fontWeight', fontWeight); - } - /** - * The font style of the selected object. ('italic' or 'oblique') - * @type {string} - */ - - - get fontStyle() { - return this._getSingleAttribute('fontStyle'); - } - - set fontStyle(fontStyle) { - this._setSingleAttribute('fontStyle', fontStyle); - } - /** - * The opacity of the selected object. - * @type {number} - */ - - - get opacity() { - return this._getSingleAttribute('opacity'); - } - - set opacity(opacity) { - this.project.tryToAutoCreateTween(); - - this._setSingleAttribute('opacity', opacity); - } - /** - * The sound attached to the selected frame. - * @type {Wick.SoundAsset} - */ - - - get sound() { - return this._getSingleAttribute('sound'); - } - - set sound(sound) { - this._setSingleAttribute('sound', sound); - } - /** - * The length of the selected frame. - * @type {number} - */ - - - get frameLength() { - return this._getSingleAttribute('length'); - } - - set frameLength(frameLength) { - this._setSingleAttribute('length', frameLength); - - var layer = this.project.activeLayer; - layer.resolveOverlap(this.getSelectedObjects()); - layer.resolveGaps(); - } - /** - * The volume of the sound attached to the selected frame. - * @type {number} - */ - - - get soundVolume() { - return this._getSingleAttribute('soundVolume'); - } - - set soundVolume(soundVolume) { - this._setSingleAttribute('soundVolume', soundVolume); - } - /** - * The easing type of a selected tween. See Wick.Tween.VALID_EASING_TYPES. - * @type {string} - */ - - - get easingType() { - return this._getSingleAttribute('easingType'); - } - - set easingType(easingType) { - return this._setSingleAttribute('easingType', easingType); - } - /** - * The filename of the selected asset. - * @type {string} - */ - - - get filename() { - return this._getSingleAttribute('filename'); - } - /** - * True if the selection is scriptable. - * @type {boolean} - */ - - - get isScriptable() { - return this.numObjects === 1 && this.getSelectedObjects()[0].isScriptable; - } - /** - * Get a list of only the farthest right frames on each layer. - * @returns {Wick.Frame[]} - */ - - - getRightmostFrames() { - var selectedFrames = this.getSelectedObjects('Frame'); - var rightmostFrames = {}; - selectedFrames.forEach(frame => { - var layerid = frame.parentLayer.uuid; - - if (!rightmostFrames[layerid] || frame.end > rightmostFrames[layerid].end) { - rightmostFrames[layerid] = frame; - } - }); - var result = []; - - for (var id in rightmostFrames) { - result.push(rightmostFrames[id]); - } - - return result; - } - /** - * Get a list of only the farthest left frames on each layer. - * @returns {Wick.Frame[]} - */ - - - getLeftmostFrames() { - var selectedFrames = this.getSelectedObjects('Frame'); - var leftmostFrames = {}; - selectedFrames.forEach(frame => { - var layerid = frame.parentLayer.uuid; - - if (!leftmostFrames[layerid] || frame.start < leftmostFrames[layerid].end) { - leftmostFrames[layerid] = frame; - } - }); - var result = []; - - for (var id in leftmostFrames) { - result.push(leftmostFrames[id]); - } - - return result; - } - - _locationOf(object) { - if (object instanceof Wick.Frame || object instanceof Wick.Tween || object instanceof Wick.Layer) { - return 'Timeline'; - } else if (object instanceof Wick.Asset) { - return 'AssetLibrary'; - } else if (object instanceof Wick.Path || object instanceof Wick.Clip) { - return 'Canvas'; - } - } - /* Helper function: Calculate the selection x,y */ - - - _resetPositioningValues() { - var selectedObject = this.getSelectedObject(); - - if (selectedObject instanceof Wick.Clip) { - // Single clip selected: Use that Clip's transformation for the pivot point and rotation - this._widgetRotation = selectedObject.transformation.rotation; - this._pivotPoint = { - x: selectedObject.transformation.x, - y: selectedObject.transformation.y - }; - } else { - // Path selected or multiple objects selected: Reset rotation and use center for pivot point - this._widgetRotation = 0; - - var boundsCenter = this.view._getSelectedObjectsBounds().center; - - this._pivotPoint = { - x: boundsCenter.x, - y: boundsCenter.y - }; - } - } - /* helper function for getting a single value from multiple selected objects */ - - - _getSingleAttribute(attributeName) { - if (this.numObjects === 0) return null; - return this.getSelectedObjects()[0][attributeName]; - } - /* helper function for updating the same attribute on all items in the selection */ - - - _setSingleAttribute(attributeName, value) { - this.getSelectedObjects().forEach(selectedObject => { - selectedObject[attributeName] = value; - }); - } - /*helper function for shift+selecting frames*/ - - - _selectInBetweenFrames(selectedFrame) { - var frameBounds = { - playheadStart: null, - playheadEnd: null - }; // Calculate bounding box of all selected frames - - var selectedFrames = this.getSelectedObjects('Frame'); - selectedFrames.filter(frame => { - return frame.parentLayer === selectedFrame.parentLayer; - }).forEach(frame => { - var start = frame.start; - var end = frame.end; - - if (!frameBounds.playheadStart || !frameBounds.playheadEnd) { - frameBounds.playheadStart = start; - frameBounds.playheadEnd = end; - } - - if (start < frameBounds.playheadStart) { - frameBounds.playheadStart = start; - } - - if (end > frameBounds.playheadEnd) { - frameBounds.playheadEnd = end; - } - }); // Select all frames inside bounding box - - this.project.activeTimeline.getAllFrames().filter(frame => { - return !frame.isSelected && frame.parentLayer === selectedFrame.parentLayer && frame.inRange(frameBounds.playheadStart, frameBounds.playheadEnd); - }).forEach(frame => { - this._selectedObjectsUUIDs.push(frame.uuid); - }); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * Class representing a Wick Timeline. - */ -Wick.Timeline = class extends Wick.Base { - /** - * Create a timeline. - */ - constructor(args) { - super(args); - this._playheadPosition = 1; - this._activeLayerIndex = 0; - this._playing = true; - this._forceNextFrame = null; - this._fillGapsMethod = "auto_extend"; - } - - serialize(args) { - var data = super.serialize(args); - data.playheadPosition = this._playheadPosition; - data.activeLayerIndex = this._activeLayerIndex; - return data; - } - - deserialize(data) { - super.deserialize(data); - this._playheadPosition = data.playheadPosition; - this._activeLayerIndex = data.activeLayerIndex; - this._playing = true; - this._forceNextFrame = null; - } - - get classname() { - return 'Timeline'; - } - /** - * The layers that belong to this timeline. - * @type {Wick.Layer} - */ - - - get layers() { - return this.getChildren('Layer'); - } - /** - * The position of the playhead. Determines which frames are visible. - * @type {number} - */ - - - get playheadPosition() { - return this._playheadPosition; - } - - set playheadPosition(playheadPosition) { - // Automatically clear selection when any playhead in the project moves - if (this.project && this._playheadPosition !== playheadPosition) { - this.project.selection.clear('Canvas'); - } - - this._playheadPosition = playheadPosition; - - if (this._playheadPosition < 1) { - this._playheadPosition = 1; - } // Automatically apply tween transforms on child frames when playhead moves - - - this.activeFrames.forEach(frame => { - frame.applyTweenTransforms(); - }); - } - /** - * The index of the active layer. Determines which frame to draw onto. - * @type {number} - */ - - - get activeLayerIndex() { - return this._activeLayerIndex; - } - - set activeLayerIndex(activeLayerIndex) { - this._activeLayerIndex = activeLayerIndex; - } - /** - * The total length of the timeline. - * @type {number} - */ - - - get length() { - var length = 0; - this.layers.forEach(function (layer) { - var layerLength = layer.length; - - if (layerLength > length) { - length = layerLength; - } - }); - return length; - } - /** - * The active layer. - * @type {Wick.Layer} - */ - - - get activeLayer() { - return this.layers[this.activeLayerIndex]; - } - /** - * The active frames, determined by the playhead position. - * @type {Wick.Frame[]} - */ - - - get activeFrames() { - var frames = []; - this.layers.forEach(layer => { - var layerFrame = layer.activeFrame; - - if (layerFrame) { - frames.push(layerFrame); - } - }); - return frames; - } - /** - * The active frame, determined by the playhead position. - * @type {Wick.Frame} - */ - - - get activeFrame() { - return this.activeLayer && this.activeLayer.activeFrame; - } - /** - * All frames inside the timeline. - * @type {Wick.Frame[]} - */ - - - get frames() { - var frames = []; - this.layers.forEach(layer => { - layer.frames.forEach(frame => { - frames.push(frame); - }); - }); - return frames; - } - /** - * All clips inside the timeline. - * @type {Wick.Clip[]} - */ - - - get clips() { - var clips = []; - this.frames.forEach(frame => { - clips = clips.concat(frame.clips); - }); - return clips; - } - /** - * The playhead position of the frame with the given name. - * @type {number|null} - */ - - - getPlayheadPositionOfFrameWithName(name) { - var frame = this.getFrameByName(name); - - if (frame) { - return frame.start; - } else { - return null; - } - } - /** - * Finds the frame with a given name. - * @type {Wick.Frame|null} - */ - - - getFrameByName(name) { - return this.frames.find(frame => { - return frame.name === name; - }) || null; - } - /** - * Add a frame to one of the layers on this timeline. If there is no layer where the frame wants to go, the frame will not be added. - * @param {Wick.Frame} frame - the frame to add - */ - - - addFrame(frame) { - if (frame.originalLayerIndex >= this.layers.length) return; - - if (frame.originalLayerIndex === -1) { - this.activeLayer.addFrame(frame); - } else { - this.layers[frame.originalLayerIndex].addFrame(frame); - } - } - /** - * Adds a layer to the timeline. - * @param {Wick.Layer} layer - The layer to add. - */ - - - addLayer(layer) { - this.addChild(layer); - - if (!layer.name) { - if (this.layers.length > 1) { - layer.name = "Layer " + this.layers.length; - } else { - layer.name = "Layer"; - } - } - } - /** - * Remmoves a layer from the timeline. - * @param {Wick.Layer} layer - The layer to remove. - */ - - - removeLayer(layer) { - // You can't remove the last layer. - if (this.layers.length <= 1) { - return; - } // Activate the layer below the removed layer if we removed the active layer. - - - if (this.activeLayerIndex === this.layers.length - 1) { - this.activeLayerIndex--; - } - - this.removeChild(layer); - } - /** - * Moves a layer to a different position, inserting it before/after other layers if needed. - * @param {Wick.Layer} layer - The layer to add. - * @param {number} index - the new position to move the layer to. - */ - - - moveLayer(layer, index) { - var layers = this.getChildren('Layer'); - layers.splice(layers.indexOf(layer), 1); - layers.splice(index, 0, layer); - } - /** - * Gets the frames at the given playhead position. - * @param {number} playheadPosition - the playhead position to search. - * @returns {Wick.Frame[]} The frames at the playhead position. - */ - - - getFramesAtPlayheadPosition(playheadPosition) { - var frames = []; - this.layers.forEach(layer => { - var frame = layer.getFrameAtPlayheadPosition(playheadPosition); - if (frame) frames.push(frame); - }); - return frames; - } - /** - * Get all frames in this timeline. - * @param {boolean} recursive - If set to true, will also include the children of all child timelines. - */ - - - getAllFrames(recursive) { - var allFrames = []; - this.layers.forEach(layer => { - allFrames = allFrames.concat(layer.frames); - - if (recursive) { - layer.frames.forEach(frame => { - frame.clips.forEach(clip => { - allFrames = allFrames.concat(clip.timeline.getAllFrames(recursive)); - }); - }); - } - }); - return allFrames; - } - /** - * Gets all frames in the layer that are between the two given playhead positions and layer indices. - * @param {number} playheadPositionStart - The start of the horizontal range to search - * @param {number} playheadPositionEnd - The end of the horizontal range to search - * @param {number} layerIndexStart - The start of the vertical range to search - * @param {number} layerIndexEnd - The end of the vertical range to search - * @return {Wick.Frame[]} The frames in the given range. - */ - - - getFramesInRange(playheadPositionStart, playheadPositionEnd, layerIndexStart, layerIndexEnd) { - var framesInRange = []; - this.layers.filter(layer => { - return layer.index >= layerIndexStart && layer.index <= layerIndexEnd; - }).forEach(layer => { - framesInRange = framesInRange.concat(layer.getFramesInRange(playheadPositionStart, playheadPositionEnd)); - }); - return framesInRange; - } - /** - * Advances the timeline one frame forwards. Loops back to beginning if the end is reached. - */ - - - advance() { - if (this._forceNextFrame) { - this.playheadPosition = this._forceNextFrame; - this._forceNextFrame = null; - } else if (this._playing) { - this.playheadPosition++; - - if (this.playheadPosition > this.length) { - this.playheadPosition = 1; - } - } - } - /** - * Makes the timeline advance automatically during ticks. - */ - - - play() { - this._playing = true; - } - /** - * Stops the timeline from advancing during ticks. - */ - - - stop() { - this._playing = false; - } - /** - * Stops the timeline and moves to a given frame number or name. - * @param {string|number} frame - A playhead position or name of a frame to move to. - */ - - - gotoAndStop(frame) { - this.stop(); - this.gotoFrame(frame); - } - /** - * Plays the timeline and moves to a given frame number or name. - * @param {string|number} frame - A playhead position or name of a frame to move to. - */ - - - gotoAndPlay(frame) { - this.play(); - this.gotoFrame(frame); - } - /** - * Moves the timeline forward one frame. Loops back to 1 if gotoNextFrame moves the playhead past the past frame. - */ - - - gotoNextFrame() { - // Loop back to beginning if gotoNextFrame goes past the last frame - var nextFramePlayheadPosition = this.playheadPosition + 1; - - if (nextFramePlayheadPosition > this.length) { - nextFramePlayheadPosition = 1; - } - - this.gotoFrame(nextFramePlayheadPosition); - } - /** - * Moves the timeline backwards one frame. Loops to the last frame if gotoPrevFrame moves the playhead before the first frame. - */ - - - gotoPrevFrame() { - var prevFramePlayheadPosition = this.playheadPosition - 1; - - if (prevFramePlayheadPosition <= 0) { - prevFramePlayheadPosition = this.length; - } - - this.gotoFrame(prevFramePlayheadPosition); - } - /** - * Moves the playhead to a given frame number or name. - * @param {string|number} frame - A playhead position or name of a frame to move to. - */ - - - gotoFrame(frame) { - if (typeof frame === 'string') { - var namedFrame = this.frames.find(seekframe => { - return seekframe.identifier === frame; - }); - if (namedFrame) this._forceNextFrame = namedFrame.start; - } else if (typeof frame === 'number') { - this._forceNextFrame = frame; - } else { - throw new Error('gotoFrame: Invalid argument: ' + frame); - } - } - /** - * The method to use to fill gaps in-beteen frames. Options: "blank_frames" or "auto_extend" (see Wick.Layer.resolveGaps) - * @type {string} - */ - - - get fillGapsMethod() { - return this._fillGapsMethod; - } - - set fillGapsMethod(fillGapsMethod) { - if (fillGapsMethod === 'blank_frames' || fillGapsMethod === 'auto_extend') { - this._fillGapsMethod = fillGapsMethod; - } else { - console.warn('Warning: Invalid fillGapsMethod: ' + fillGapsMethod); - console.warn('Valid fillGapsMethod: "blank_frames", "auto_extend"'); - } - } - /** - * Check if frame gap fixing should be deferred until later. Read only. - * @type {boolean} - */ - - - get waitToFillFrameGaps() { - return this._waitToFillFrameGaps; - } - /** - * Disables frame gap filling until resolveFrameGaps is called again. - */ - - - deferFrameGapResolve() { - this._waitToFillFrameGaps = true; - } - /** - * Fill in all gaps between frames in all layers in this timeline. - * @param {Wick.Frame[]} newOrModifiedFrames - The frames that should not be affected by the gap fill by being extended or shrunk. - */ - - - resolveFrameGaps(newOrModifiedFrames) { - if (!newOrModifiedFrames) newOrModifiedFrames = []; - this._waitToFillFrameGaps = false; - this.layers.forEach(layer => { - layer.resolveGaps(newOrModifiedFrames.filter(frame => { - return frame.parentLayer === layer; - })); - }); - } - /** - * Prevents frames from overlapping each other by removing pieces of frames that are touching. - * @param {Wick.Frame[]} newOrModifiedFrames - the frames that should take precedence when determining which frames should get "eaten". - */ - - - resolveFrameOverlap(frames) { - this.layers.forEach(layer => { - layer.resolveOverlap(frames.filter(frame => { - return frame.parentLayer === layer; - })); - }); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * Class representing a tween. - */ -Wick.Tween = class extends Wick.Base { - static get VALID_EASING_TYPES() { - return ['none', 'in', 'out', 'in-out']; - } - - static _calculateTimeValue(tweenA, tweenB, playheadPosition) { - var tweenAPlayhead = tweenA.playheadPosition; - var tweenBPlayhead = tweenB.playheadPosition; - var dist = tweenBPlayhead - tweenAPlayhead; - var t = (playheadPosition - tweenAPlayhead) / dist; - return t; - } - /** - * Create a tween - * @param {number} playheadPosition - the playhead position relative to the frame that the tween belongs to - * @param {Wick.Transform} transformation - the transformation this tween will apply to child objects - * @param {number} fullRotations - the number of rotations to add to the tween's transformation - */ - - - constructor(args) { - if (!args) args = {}; - super(args); - this._playheadPosition = args.playheadPosition || 1; - this.transformation = args.transformation || new Wick.Transformation(); - this.fullRotations = args.fullRotations === undefined ? 0 : args.fullRotations; - this.easingType = args.easingType || 'none'; - } - /** - * Create a tween by interpolating two existing tweens. - * @param {Wick.Tween} tweenA - The first tween - * @param {Wick.Tween} tweenB - The second tween - * @param {Number} playheadPosition - The point between the two tweens to use to interpolate - */ - - - static interpolate(tweenA, tweenB, playheadPosition) { - var interpTween = new Wick.Tween(); // Calculate value (0.0-1.0) to pass to tweening function - - var t = Wick.Tween._calculateTimeValue(tweenA, tweenB, playheadPosition); // Interpolate every transformation attribute using the t value - - - ["x", "y", "scaleX", "scaleY", "rotation", "opacity"].forEach(propName => { - var tweenFn = tweenA._getTweenFunction(); - - var tt = tweenFn(t); - var valA = tweenA.transformation[propName]; - var valB = tweenB.transformation[propName]; - - if (propName === 'rotation') { - // Constrain rotation values to range of -180 to 180 - while (valA < -180) valA += 360; - - while (valB < -180) valB += 360; - - while (valA > 180) valA -= 360; - - while (valB > 180) valB -= 360; // Convert full rotations to 360 degree amounts - - - valB += tweenA.fullRotations * 360; - } - - interpTween.transformation[propName] = lerp(valA, valB, tt); - }); - interpTween.playheadPosition = playheadPosition; - return interpTween; - } - - get classname() { - return 'Tween'; - } - - serialize(args) { - var data = super.serialize(args); - data.playheadPosition = this.playheadPosition; - data.transformation = this.transformation.values; - data.fullRotations = this.fullRotations; - data.easingType = this.easingType; - return data; - } - - deserialize(data) { - super.deserialize(data); - this.playheadPosition = data.playheadPosition; - this.transformation = new Wick.Transformation(data.transformation); - this.fullRotations = data.fullRotations; - this.easingType = data.easingType; - } - /** - * The playhead position of the tween. - * @type {number} - */ - - - get playheadPosition() { - return this._playheadPosition; - } - - set playheadPosition(playheadPosition) { - this._playheadPosition = playheadPosition; - } - /** - * The type of interpolation to use for easing. - * @type {string} - */ - - - get easingType() { - return this._easingType; - } - - set easingType(easingType) { - if (Wick.Tween.VALID_EASING_TYPES.indexOf(easingType) === -1) { - console.warn('Invalid easingType. Valid easingTypes: '); - console.warn(Wick.Tween.VALID_EASING_TYPES); - return; - } - - this._easingType = easingType; - } - /** - * Remove this tween from its parent frame. - */ - - - remove() { - this.parent.removeTween(this); - } - /** - * Set the transformation of a clip to this tween's transformation. - * @param {Wick.Clip} clip - the clip to apply the tween transforms to. - */ - - - applyTransformsToClip(clip) { - clip.transformation = this.transformation.copy(); - } - /** - * The tween that comes after this tween in the parent frame. - * @returns {Wick.Tween} - */ - - - getNextTween() { - if (!this.parentFrame) return null; - var frontTween = this.parentFrame.seekTweenInFront(this.playheadPosition + 1); - return frontTween; - } - /** - * Prevents tweens from existing outside of the frame's length. Call this after changing the length of the parent frame. - */ - - - restrictToFrameSize() { - var playheadPosition = this.playheadPosition; // Remove tween if playheadPosition is out of bounds - - if (playheadPosition < 1 || playheadPosition > this.parentFrame.length) { - this.remove(); - } - } - /* retrieve Tween.js easing functions by name */ - - - _getTweenFunction() { - return { - 'none': TWEEN.Easing.Linear.None, - 'in': TWEEN.Easing.Quadratic.In, - 'out': TWEEN.Easing.Quadratic.Out, - 'in-out': TWEEN.Easing.Quadratic.InOut - }[this.easingType]; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * Represents a Wick Path. - */ -Wick.Path = class extends Wick.Base { - /** - * Create a Wick Path. - * @param {array} json - Path data exported from paper.js using exportJSON({asString:false}). - */ - constructor(args) { - if (!args) args = {}; - super(args); - this._fontStyle = 'normal'; - this._fontWeight = 400; - - if (args.json) { - this.json = args.json; - } else { - this.json = new paper.Path({ - insert: false - }).exportJSON({ - asString: false - }); - } - } - /** - * Create a path containing an image from an ImageAsset. - * @param {Wick.ImageAsset} asset - The asset from which the image src will be loaded from - * @param {Function} callback - A function that will be called when the image is done loading. - */ - - - static createImagePath(asset, callback) { - var img = new Image(); - img.src = asset.src; - - img.onload = () => { - var raster = new paper.Raster(img); - raster.remove(); - var path = new Wick.Path({ - json: Wick.View.Path.exportJSON(raster) - }); - callback(path); - }; - } - /** - * Create a path (synchronously) containing an image from an ImageAsset. - * @param {Wick.ImageAsset} asset - The asset from which the image src will be loaded from - */ - - - static createImagePathSync(asset) { - var raster = new paper.Raster(asset.src); - raster.remove(); - var path = new Wick.Path({ - json: Wick.View.Path.exportJSON(raster) - }); - return path; - } - - get classname() { - return 'Path'; - } - - serialize(args) { - var data = super.serialize(args); - data.json = this.json; - delete data.json[1].data; // optimization: replace dataurls with asset uuids - - if (data.json[0] === 'Raster' && data.json[1].source.startsWith('data:')) { - if (!this.project) { - console.warn('Could not replace raster image source with asset UUID, path does not belong to a project.'); - } else { - this.project.getAssets('Image').forEach(imageAsset => { - if (imageAsset.src === data.json[1].source) { - data.json[1].source = 'asset:' + imageAsset.uuid; - } - }); - } - } - - data.fontStyle = this._fontStyle; - data.fontWeight = this._fontWeight; - return data; - } - - deserialize(data) { - super.deserialize(data); - this.json = data.json; - this._fontStyle = data.fontStyle || 'normal'; - this._fontWeight = data.fontWeight || 400; - } - /** - * - */ - - - get onScreen() { - return this.parent.onScreen; - } - /** - * The type of path that this path is. Can be 'path', 'text', or 'image' - * @returns {string} - */ - - - get pathType() { - if (this.view.item instanceof paper.TextItem) { - return 'text'; - } else if (this.view.item instanceof paper.Raster) { - return 'image'; - } else { - return 'path'; - } - } - /** - * Path data exported from paper.js using exportJSON({asString:false}). - * @type {object} - */ - - - get json() { - return this._json; - } - - set json(json) { - this._json = json; - this.view.render(); - } - /** - * The bounding box of the path. - * @type {object} - */ - - - get bounds() { - var paperBounds = this.view.item.bounds; - return { - top: paperBounds.top, - bottom: paperBounds.bottom, - left: paperBounds.left, - right: paperBounds.right, - width: paperBounds.width, - height: paperBounds.height - }; - } - /** - * The position of the path. - * @type {number} - */ - - - get x() { - return this.view.item.position.x; - } - - set x(x) { - this.view.item.position.x = x; - this.json = this.view.exportJSON(); - } - /** - * The position of the path. - * @type {number} - */ - - - get y() { - return this.view.item.position.y; - } - - set y(y) { - this.view.item.position.y = y; - this.json = this.view.exportJSON(); - } - /** - * The fill color of the path. - * @type {paper.Color} - */ - - - get fillColor() { - return this.view.item.fillColor || new paper.Color(); - } - - set fillColor(fillColor) { - this.view.item.fillColor = fillColor; - this.json = this.view.exportJSON(); - } - /** - * The stroke color of the path. - * @type {paper.Color} - */ - - - get strokeColor() { - return this.view.item.strokeColor || new paper.Color(); - } - - set strokeColor(strokeColor) { - this.view.item.strokeColor = strokeColor; - this.json = this.view.exportJSON(); - } - /** - * The stroke width of the path. - * @type {number} - */ - - - get strokeWidth() { - return this.view.item.strokeWidth; - } - - set strokeWidth(strokeWidth) { - this.view.item.strokeWidth = strokeWidth; - this.json = this.view.exportJSON(); - } - /** - * The opacity of the path. - * @type {number} - */ - - - get opacity() { - if (this.view.item.opacity === undefined || this.view.item.opacity === null) { - return 1.0; - } - - return this.view.item.opacity; - } - - set opacity(opacity) { - this.view.item.opacity = opacity; - this.json = this.view.exportJSON(); - } - /** - * The font family of the path. - * @type {string} - */ - - - get fontFamily() { - return this.view.item.fontFamily; - } - - set fontFamily(fontFamily) { - this.view.item.fontFamily = fontFamily; - this.fontWeight = 400; - this.fontStyle = 'normal'; - this.json = this.view.exportJSON(); - } - /** - * The font size of the path. - * @type {number} - */ - - - get fontSize() { - return this.view.item.fontSize; - } - - set fontSize(fontSize) { - this.view.item.fontSize = fontSize; - this.view.item.leading = fontSize * 1.2; - this.json = this.view.exportJSON(); - } - /** - * The font weight of the path. - * @type {number} - */ - - - get fontWeight() { - return this._fontWeight; - } - - set fontWeight(fontWeight) { - if (typeof fontWeight === 'string') { - console.error('fontWeight must be a number.'); - return; - } - - this._fontWeight = fontWeight; - } - /** - * The font style of the path ('italic' or 'oblique'). - * @type {string} - */ - - - get fontStyle() { - return this._fontStyle; - } - - set fontStyle(fontStyle) { - this._fontStyle = fontStyle; - } - /** - * The content of the text. - * @type {string} - */ - - - get textContent() { - return this.view.item.content; - } - - set textContent(textContent) { - this.view.item.content = textContent; - } - /** - * API function to change the textContent of dynamic text paths. - */ - - - setText(newTextContent) { - this.textContent = newTextContent; - } - /** - * Check if this path is a dynamic text object. - * @type {boolean} - */ - - - get isDynamicText() { - return this.pathType === 'text' && this.identifier !== null; - } - /** - * The image asset that this path uses, if this path is a Raster path. - * @returns {Wick.Asset[]} - */ - - - getLinkedAssets() { - var linkedAssets = []; - var data = this.serialize(); // just need the asset uuid... - - if (data.json[0] === 'Raster') { - var uuid = data.json[1].source.split(':')[1]; - linkedAssets.push(this.project.getAssetByUUID(uuid)); - } - - return linkedAssets; - } - /** - * Removes this path from its parent frame. - */ - - - remove() { - this.parentFrame.removePath(this); - } - /** - * Creates a new path using boolean unite on multiple paths. The resulting path will use the fillColor, strokeWidth, and strokeColor of the first path in the array. - * @param {Wick.Path[]} paths - an array containing the paths to process. - * @returns {Wick.Path} The path resulting from the boolean unite. - */ - - - static unite(paths) { - return Wick.Path.booleanOp(paths, 'unite'); - } - /** - * Creates a new path using boolean subtration on multiple paths. The resulting path will use the fillColor, strokeWidth, and strokeColor of the first path in the array. - * @param {Wick.Path[]} paths - an array containing the paths to process. - * @returns {Wick.Path} The path resulting from the boolean subtraction. - */ - - - static subtract(paths) { - return Wick.Path.booleanOp(paths, 'subtract'); - } - /** - * Creates a new path using boolean intersection on multiple paths. The resulting path will use the fillColor, strokeWidth, and strokeColor of the first path in the array. - * @param {Wick.Path[]} paths - an array containing the paths to process. - * @returns {Wick.Path} The path resulting from the boolean intersection. - */ - - - static intersect(paths) { - return Wick.Path.booleanOp(paths, 'intersect'); - } - /** - * Perform a paper.js boolean operation on a list of paths. - * @param {Wick.Path[]} paths - a list of paths to perform the boolean operation on. - * @param {string} booleanOpName - the name of the boolean operation to perform. Currently supports "unite", "subtract", and "intersect" - */ - - - static booleanOp(paths, booleanOpName) { - if (!booleanOpName) { - console.error('Wick.Path.booleanOp: booleanOpName is required'); - } - - if (booleanOpName !== 'unite' && booleanOpName !== 'subtract' && booleanOpName !== 'intersect') { - console.error('Wick.Path.booleanOp: unsupported booleanOpName: ' + booleanOpName); - } - - if (!paths || paths.length === 0) { - console.error('Wick.Path.booleanOp: a non-empty list of paths is required'); - } // Single path? Nothing to do. - - - if (paths.length === 1) { - return paths[0]; - } // Get paper.js path objects - - - paths = paths.map(path => { - return path.view.item; - }); - var result = paths[0].clone({ - insert: false - }); - paths.forEach(path => { - if (path === paths[0]) return; - result = result[booleanOpName](path); - result.remove(); - }); - var resultWickPath = new Wick.Path({ - json: result.exportJSON({ - asString: false - }) - }); - return resultWickPath; - } - /** - * Converts a stroke into fill. Only works with paths that have a strokeWidth and strokeColor, and have no fillColor. Does nothing otherwise. - * @returns {Wick.Path} A flattened version of this path. Can be null if the path cannot be flattened. - */ - - - flatten() { - if (this.fillColor || !this.strokeColor || !this.strokeWidth) { - return null; - } - - if (!(this instanceof paper.Path)) { - return null; - } - - var flatPath = new Wick.Path({ - json: this.view.item.flatten().exportJSON({ - asString: false - }) - }); - flatPath.fillColor = this.strokeColor; - return flatPath; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Asset = class extends Wick.Base { - /** - * Creates a new Wick Asset. - * @param {string} name - the name of the asset - */ - constructor(args) { - if (!args) args = {}; - super(args); - this.name = args.name; - } - - serialize(args) { - var data = super.serialize(args); - data.name = this.name; - return data; - } - - deserialize(data) { - super.deserialize(data); - this.name = data.name; - } - /** - * Removes this asset from the project. - */ - - - remove() { - this.project.removeAsset(this); - } - /** - * A list of all objects using this asset. - */ - - - getInstances() {} // Implemented by subclasses - - /** - * Check if there are any objects in the project that use this asset. - * @returns {boolean} - */ - - - hasInstances() {} // Implemented by sublasses - - /** - * Remove all instances of this asset from the project. (Implemented by ClipAsset, ImageAsset, and SoundAsset) - */ - - - removeAllInstances() {// Implemented by sublasses - } - - get classname() { - return 'Asset'; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.FileAsset = class extends Wick.Asset { - /** - * Returns all valid MIME types for files which can be converted to Wick Assets. - * @return {string[]} Array of strings of MIME types in the form MediaType/Subtype. - */ - static getValidMIMETypes() { - let imageTypes = Wick.ImageAsset.getValidMIMETypes(); - let soundTypes = Wick.SoundAsset.getValidMIMETypes(); - return imageTypes.concat(soundTypes); - } - /** - * Returns all valid extensions types for files which can be attempted to be - * converted to Wick Assets. - * @return {string[]} Array of strings representing extensions. - */ - - - static getValidExtensions() { - let imageExtensions = Wick.ImageAsset.getValidExtensions(); - let soundExtensions = Wick.SoundAsset.getValidExtensions(); - return imageExtensions.concat(soundExtensions); - } - /** - * Create a new FileAsset. - * @param {string} filename - the filename of the file being used as this asset's source. - * @param {string} src - a base64 string containing the source for this asset. - */ - - - constructor(args) { - if (!args) args = {}; - args.name = args.filename; - super(args); - this.fileExtension = null; - this.MIMEType = null; - this.filename = args.filename; - this.src = args.src; - } - - serialize(args) { - var data = super.serialize(args); - data.filename = this.filename; - data.MIMEType = this.MIMEType; - data.fileExtension = this.fileExtension; - - if (args && args.includeOriginalSource) { - data.originalSource = this.src; - } - - return data; - } - - deserialize(data) { - super.deserialize(data); - this.filename = data.filename; - this.MIMEType = data.MIMEType; - this.fileExtension = data.fileExtension; - - if (data.originalSource) { - this.src = data.originalSource; - } - } - - get classname() { - return 'FileAsset'; - } - /** - * The source of the data of the asset, in base64. - * @type {string} - */ - - - get src() { - return Wick.FileCache.getFile(this.uuid).src; - } - - set src(src) { - if (src) { - Wick.FileCache.addFile(src, this.uuid); - this.fileExtension = this._fileExtensionOfString(src); - this.MIMEType = this._MIMETypeOfString(src); - } - } - /** - * Loads data about the file into the asset. - */ - - - load(callback) { - callback(); - } - /** - * Copies the FileAsset and also copies the src in FileCache. - * @return {Wick.FileAsset} - */ - - - copy() { - var copy = super.copy(); - copy.src = this.src; - return copy; - } - - _MIMETypeOfString(string) { - return string.split(':')[1].split(',')[0].split(';')[0]; - } - - _fileExtensionOfString(string) { - var MIMEType = this._MIMETypeOfString(string); - - return MIMEType && MIMEType.split('/')[1]; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.ImageAsset = class extends Wick.FileAsset { - /** - * Valid MIME types for image assets. - * @returns {string[]} Array of strings representing MIME types in the form image/filetype. - */ - static getValidMIMETypes() { - let jpgTypes = ['image/jpeg']; - let pngTypes = ['image/png']; - return jpgTypes.concat(pngTypes); - } - /** - * Valid extensions for image assets. - * @returns {string[]} Array of strings representing extensions. - */ - - - static getValidExtensions() { - return ['.jpeg', '.jpg', '.png']; - } - /** - * Create a new ImageAsset. - * @param {object} args - */ - - - constructor(args) { - super(args); - } - - serialize(args) { - var data = super.serialize(args); - return data; - } - - deserialize(data) { - super.deserialize(data); - } - - get classname() { - return 'ImageAsset'; - } - /** - * A list of Wick Paths that use this image as their image source. - * @returns {Wick.Path[]} - */ - - - getInstances() { - return []; // TODO - } - /** - * Check if there are any objects in the project that use this asset. - * @returns {boolean} - */ - - - hasInstances() { - return false; // TODO - } - /** - * Removes all paths using this asset as their image source from the project. - * @returns {boolean} - */ - - - removeAllInstances() {} // TODO - - /** - * Load data in the asset - */ - - - load(callback) { - // Try to get paper.js to cache the image src. - var img = new Image(); - img.src = this.src; - - img.onload = () => { - var raster = new paper.Raster(img); - raster.remove(); - callback(); - }; - } - /** - * Creates a new Wick Path that uses this asset's image data as it's image source. - * @param {function} callback - called when the path is done loading. - */ - - - createInstance(callback) { - Wick.Path.createImagePath(this, path => { - callback(path); - }); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.ClipAsset = class extends Wick.Asset { - /** - * Creates a new Clip Asset. - * @param {Wick.Clip} clip - the clip to link this asset to - */ - constructor(args) { - if (!args) args = {}; - args.identifier = args.clip ? args.clip.identifier : null; - super(args); - this.clipType = null; - this.linkedClips = []; - if (args.clip) this.useClipAsSource(args.clip); - } - - deserialize(data) { - super.deserialize(data); - this._timeline = data.timeline; - } - - serialize(args) { - var data = super.serialize(args); - data.timeline = this._timeline; - return data; - } - - get classname() { - return 'ClipAsset'; - } - /** - * The timeline that this asset is linked to. - */ - - - get timeline() { - return Wick.ObjectCache.getObjectByUUID(this._timeline); - } - /** - * Uses the timeline of the given clip as the data for this asset. - * @param {Wick.Clip} clip - the clip to use as the source - */ - - - useClipAsSource(clip) { - this.identifier = clip.identifier; - this.clipType = clip.classname; - this.timeline = clip.timeline.copy(); - } - /** - * Creates a new Clip using the source of this asset. - */ - - - createInstance() { - var clip = new Wick[this.clipType](); - this.useAsSourceForClip(clip); - return clip; - } - /** - * Sets a given clip to use the source of this asset for its timeline data. - * Note: This will replace the timeline of the clip with the asset's timeline. - * @param {Wick.Clip} clip - the clip to change the timeline data of - */ - - - useAsSourceForClip(clip) { - this.linkedClips.push(clip); - this.updateClipFromAsset(clip); - } - /** - * Unlink a given clip from this asset. The clip's timeline will no longer be synced with this asset. - * @param {Wick.Clip} clip - The clip to unlink from this asset. - */ - - - removeAsSourceForClip(clip) { - this.linkedClips = this.linkedClips.filter(checkClip => { - return checkClip !== clip; - }); - } - /** - * Take the timeline data from a clip and use it to update this asset. - * This will also update the timelines of all instances of this asset. - * @param {Wick.Clip} clip - The clip to use the timeline of to update this asset. - */ - - - updateAssetFromClip(clip) { - this.timeline = clip.timeline.copy(); - var self = this; - this.linkedClips.forEach(linkedClip => { - if (linkedClip === clip) return; // This one should already be synced, of course - - this.updateClipFromAsset(linkedClip); - }); - } - /** - * Replace the timeline of the clip with the asset's timeline. - * @param {Wick.Clip} clip - the clip to change the timeline data of - */ - - - updateClipFromAsset(clip) { - var timeline = this.timeline.copy(); - clip.timeline = timeline; - } - /** - * Removes all instances of this asset from the project. - */ - - - removeAllInstances() { - this.linkedClips.forEach(clip => { - clip.remove(); - }); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.SoundAsset = class extends Wick.FileAsset { - /** - * Returns valid MIME types for a Sound Asset. - * @returns {string[]} Array of strings representing MIME types in the form audio/Subtype. - */ - static getValidMIMETypes() { - let mp3Types = ['audio/mp3', 'audio/mpeg3', 'audio/x-mpeg-3', 'audio/mpeg', 'video/mpeg', 'video/x-mpeg']; - let oggTypes = ['audio/ogg', 'video/ogg', 'application/ogg']; - let wavTypes = ['audio/wave', 'audio/wav', 'audio/x-wav', 'audio/x-pn-wav']; - return mp3Types.concat(oggTypes).concat(wavTypes); - } - /** - * Returns valid extensions for a sound asset. - * @returns {string[]} Array of strings representing valid - */ - - - static getValidExtensions() { - return ['.mp3', '.ogg', '.wav']; - } - /** - * Creates a new SoundAsset. - */ - - - constructor(args) { - super(args); - this._waveform = null; - } - - serialize(args) { - var data = super.serialize(args); - return data; - } - - deserialize(data) { - super.deserialize(data); - } - - get classname() { - return 'SoundAsset'; - } - /** - * Plays this asset's sound. - * @param {number} seekMS - the amount of time in milliseconds to start the sound at. - * @param {number} volume - the volume of the sound, from 0.0 - 1.0 - * @param {boolean} loop - if set to true, the sound will loop - * @return {number} The id of the sound instance that was played. - */ - - - play(options) { - if (!options) options = {}; - if (options.seekMS === undefined) options.seekMS = 0; - if (options.volume === undefined) options.volume = 1.0; - if (options.loop === undefined) options.loop = false; // don't do anything if the project is muted... - - if (this.project.muted) { - return; - } - - var id = this._howl.play(); - - this._howl.seek(options.seekMS / 1000, id); - - this._howl.volume(options.volume, id); - - this._howl.loop(options.loop, id); - - return id; - } - /** - * Stops this asset's sound. - * @param {number} id - (optional) the ID of the instance to stop. If ID is not given, every instance of this sound will stop. - */ - - - stop(id) { - // Howl instance was never created, sound has never played yet, so do nothing - if (!this._howl) { - return; - } - - if (id === undefined) { - this._howl.stop(); - } else { - this._howl.stop(id); - } - } - /** - * The length of the sound in seconds - * @type {number} - */ - - - get duration() { - return this._howl.duration(); - } - /** - * A list of Wick Paths that use this font as their fontFamily. - * @returns {Wick.Path[]} - */ - - - getInstances() { - var frames = []; - this.project.getAllFrames().forEach(frame => { - if (frame._soundAssetUUID === this.uuid) { - frames.push(frame); - } - }); - return frames; - } - /** - * Check if there are any objects in the project that use this asset. - * @returns {boolean} - */ - - - hasInstances() { - return this.getInstances().length > 0; - } - /** - * Remove the sound from any frames in the project that use this asset as their sound. - */ - - - removeAllInstances() { - this.getInstances().forEach(frame => { - frame.removeSound(); - }); - } - /** - * Loads data about the sound into the asset. - */ - - - load(callback) { - this._generateWaveform(() => { - this._waitForHowlLoad(() => { - callback(); - }); - }); - } - /** - * Image of the waveform of this sound. - * @type {Image} - */ - - - get waveform() { - return this._waveform; - } - - get _howl() { - // Lazily create howler instance - if (!this._howlInstance) { - // This fixes OGGs in firefox, as video/ogg is sometimes set as the MIMEType, which Howler doesn't like. - var srcFixed = this.src; - srcFixed = this.src.replace('video/ogg', 'audio/ogg'); - this._howlInstance = new Howl({ - src: [srcFixed] - }); - } - - return this._howlInstance; - } - - _waitForHowlLoad(callback) { - if (this._howl.state() === 'loaded') { - callback(); - } else { - this._howl.on('load', () => { - callback(); - }); - } - } - - _generateWaveform(callback) { - if (this._waveform) { - callback(); - return; - } - - var soundSrc = this.src; - var scwf = new SCWF(); - scwf.generate(soundSrc, { - onComplete: (png, pixels) => { - this._waveform = new Image(); - - this._waveform.onload = () => { - callback(); - }; - - this._waveform.src = png; - } - }); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.FontAsset = class extends Wick.FileAsset { - /** - * Valid MIME types for font assets. - * @returns {string[]} Array of strings representing MIME types in the form font/filetype. - */ - static getValidMIMETypes() { - return ['font/ttf', 'application/x-font-ttf', 'application/x-font-truetype']; - } - /** - * Valid extensions for font assets. - * @returns {string[]} Array of strings representing extensions. - */ - - - static getValidExtensions() { - return ['.ttf']; - } - /** - * The default font to use if a font couldn't load, or if a FontAsset was deleted - */ - - - static get MISSING_FONT_DEFAULT() { - return 'Helvetica, Arial, sans-serif'; - } - /** - * Create a new FontAsset. - */ - - - constructor(args) { - super(args); - } - - serialize(args) { - var data = super.serialize(args); - return data; - } - - deserialize(data) { - super.deserialize(data); - } - - get classname() { - return 'FontAsset'; - } - /** - * Loads the font into the window. - */ - - - load(callback) { - var fontDataArraybuffer = Base64ArrayBuffer.decode(this.src.split(',')[1]); - var fontFamily = this.fontFamily; - - if (!fontFamily) { - console.error('FontAsset: Could not get fontFamily from filename.'); - } else if (fontFamily === "") { - console.error('FontAsset: fontfamily not found. Showing as "".'); - } - - var font = new FontFace(fontFamily, fontDataArraybuffer); - font.load().then(loaded_face => { - document.fonts.add(loaded_face); - callback(); - }).catch(error => { - console.error('FontAsset.load(): An error occured while loading a font:'); - console.log(font); - console.error(error); - callback(); // Make the callback so that the page doesn't freeze. - }); - } - /** - * A list of Wick Paths that use this font as their fontFamily. - * @returns {Wick.Path[]} - */ - - - getInstances() { - var paths = []; - this.project.getAllFrames().forEach(frame => { - frame.paths.forEach(path => { - if (path.fontFamily === this.fontFamily) { - paths.push(path); - } - }); - }); - return paths; - } - /** - * Check if there are any objects in the project that use this asset. - * @returns {boolean} - */ - - - hasInstances() { - return this.getInstances().length > 0; - } - /** - * Finds all PointText paths using this font as their fontFamily and replaces that font with a default font. - */ - - - removeAllInstances() { - this.getInstances().forEach(path => { - path.fontFamily = Wick.FontAsset.MISSING_FONT_DEFAULT; - }); - } - /** - * - * @type {string} - */ - - - get fontFamily() { - return this.filename.split('.')[0]; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * A class that is extended by any wick object that ticks. - */ -Wick.Tickable = class extends Wick.Base { - /** - * Debugging feature. Logs errors as they happen - */ - static get LOG_ERRORS() { - return false; - } - /** - * Returns a list of all possible events for this object. - * @return {string[]} Array of all possible scripts. - */ - - - static get possibleScripts() { - return ['default', 'mouseenter', 'mousedown', 'mousepressed', 'mousereleased', 'mouseleave', 'mousehover', 'mousedrag', 'mouseclick', 'keypressed', 'keyreleased', 'keydown', 'load', 'update', 'unload']; - } - /** - * Create a new tickable object. - */ - - - constructor(args) { - if (!args) args = {}; - super(args); - this._onscreen = false; - this._onscreenLastTick = false; - this._mouseState = 'out'; - this._lastMouseState = 'out'; - this._isClickTarget = false; - this._scripts = []; - this.cursor = 'default'; - this.addScript('default', ''); - this._onEventFns = {}; - this._cachedScripts = {}; - } - - deserialize(data) { - super.deserialize(data); - this._onscreen = false; - this._onscreenLastTick = false; - this._mouseState = 'out'; - this._lastMouseState = 'out'; - this._scripts = JSON.parse(JSON.stringify(data.scripts)); - this.cursor = data.cursor; - this._onEventFns = {}; - this._cachedScripts = {}; - } - - serialize(args) { - var data = super.serialize(args); - data.scripts = JSON.parse(JSON.stringify(this._scripts)); - data.cursor = this.cursor; - return data; - } - - get classname() { - return 'Tickable'; - } - /** - * The scripts on this object. - * @type {object[]} - */ - - - get scripts() { - return this._scripts; - } - /** - * Checks if this object has a non-empty script. - * @type {boolean} - */ - - - get hasContentfulScripts() { - var hasContentfulScripts = false; - - this._scripts.forEach(script => { - if (hasContentfulScripts) return; - - if (script.src !== '') { - hasContentfulScripts = true; - } - }); - - return hasContentfulScripts; - } - /** - * Check if this object is currently visible in the project, based on its parent. - * @type {boolean} - */ - - - get onScreen() { - if (!this.parent) return false; - return this.parent.onScreen; - } - /** - * Add a function to be called when an event happens. - * @param {string} name - The name of the event to attach the function to. - * @param {function} fn - The function to call when the given event happens. - */ - - - onEvent(name, fn) { - if (Wick.Tickable.possibleScripts.indexOf(name) === -1) { - console.warn("onEvent: " + name + " is not a valid event name."); - return; - } - - this.addEventFn(name, fn); - } - /** - * Attach a function to a given event. - * @param {string} name - the name of the event to attach a function to. - * @param {function} fn - the function to attach - */ - - - addEventFn(name, fn) { - this.getEventFns(name).push(fn); - } - /** - * Gets all functions attached to an event with a given name. - * @param {string} - The name of the event - */ - - - getEventFns(name) { - if (!this._onEventFns[name]) { - this._onEventFns[name] = []; - } - - return this._onEventFns[name]; - } - /** - * Check if an object can have scripts attached to it. Helpful when iterating through a lot of different wick objects that may or may not be tickables. Always returns true. - * @type {boolean} - */ - - - get isScriptable() { - return true; - } - /** - * Add a new script to an object. - * @param {string} name - The name of the event that will trigger the script. See Wick.Tickable.possibleScripts - * @param {string} src - The source code of the new script. - */ - - - addScript(name, src) { - if (Wick.Tickable.possibleScripts.indexOf(name) === -1) console.error(name + ' is not a valid script!'); - - if (this.hasScript(name)) { - this.updateScript(name, src); - return; - } - - this._scripts.push({ - name: name, - src: '' - }); // Sort scripts by where they appear in the possibleScripts list - - - var possibleScripts = Wick.Tickable.possibleScripts; - - this._scripts.sort((a, b) => { - return possibleScripts.indexOf(a.name) - possibleScripts.indexOf(b.name); - }); - - if (src) { - this.updateScript(name, src); - } - } - /** - * Get the script of this object that is triggered when the given event name happens. - * @param {string} name - The name of the event. See Wick.Tickable.possibleScripts - * @returns {object} the script with the given name. Can be null if the object doesn't have that script. - */ - - - getScript(name) { - if (Wick.Tickable.possibleScripts.indexOf(name) === -1) console.error(name + ' is not a valid script!'); - return this._scripts.find(script => { - return script.name === name; - }); - } - /** - * Returns a list of script names which are not currently in use for this object. - * @return {string[]} Available script names. - */ - - - getAvailableScripts() { - return Wick.Tickable.possibleScripts.filter(script => !this.hasScript(script)); - } - /** - * Check if the object has a script with the given event name. - * @param {string} name - The name of the event. See Wick.Tickable.possibleScripts - * @returns {boolean} True if the script with the given name exists - */ - - - hasScript(name) { - return this.getScript(name) !== undefined; - } - /** - * Check if the object has a non-empty script with a given name. - * @param {string} name - The name of the event. See Wick.Tickable.possibleScripts - * @returns {boolean} True if the script with the given name has code - */ - - - scriptIsContentful(name) { - if (!this.hasScript(name)) { - return false; - } - - var script = this.getScript(name); - return script.src.trim() !== ''; - } - /** - * Changes the source of the script with the given event name. - * @param {string} name - The name of the event that will trigger the script. See Wick.Tickable.possibleScripts - * @param {string} src - The source code of the script. - */ - - - updateScript(name, src) { - this.getScript(name).src = src; - delete this._cachedScripts[name]; - } - /** - * Remove the script that corresponds to a given event name. - * @param {string} name - The name of the event. See Wick.Tickable.possibleScripts - */ - - - removeScript(name) { - this._scripts = this._scripts.filter(script => { - return script.name !== name; - }); - } - /** - * Run the script with the corresponding event name. - * @param {string} name - The name of the event. See Wick.Tickable.possibleScripts - * @returns {object} object containing error info if an error happened. Returns null if there was no error (script ran successfully) - */ - - - runScript(name) { - if (!Wick.Tickable.possibleScripts.indexOf(name) === -1) { - console.error(name + ' is not a valid script!'); - } // Don't run scripts if this object is the focus - // (this makes it so preview play will always play, even if the parent Clip of the timeline has a stop script) - - - if (this.project && this.project.focus === this) { - return null; - } // Run functions attached using onEvent - - - var eventFnError = null; - this.getEventFns(name).forEach(eventFn => { - if (eventFnError) return; - eventFnError = this._runFunction(eventFn); - }); - if (eventFnError) return eventFnError; // Run function inside tab - - if (this.scriptIsContentful(name)) { - var script = this.getScript(name); - - var fn = this._cachedScripts[name] || this._evalScript(name, script.src); - - if (!(fn instanceof Function)) { - return fn; // error - } - - this._cachedScripts[name] = fn; - - var error = this._runFunction(fn); - - if (error) return error; - } - - return null; - } - /** - * The tick routine to be called when the object ticks. - * @returns {object} - An object with information about the result from ticking. Null if no errors occured, and the script ran successfully. - */ - - - tick() { - // Update named child references - this._attachChildClipReferences(); // Update onScreen flags. - - - this._onscreenLastTick = this._onscreen; - this._onscreen = this.onScreen; // Update mouse states. - - this._lastMouseState = this._mouseState; - - if (this.project && this.project.objectIsMouseTarget(this)) { - if (this.project.isMouseDown) { - this._mouseState = 'down'; - } else { - this._mouseState = 'over'; - } - } else { - this._mouseState = 'out'; - } // Call tick event function that corresponds to state. - - - if (!this._onscreen && !this._onscreenLastTick) { - return this._onInactive(); - } else if (this._onscreen && !this._onscreenLastTick) { - return this._onActivated(); - } else if (this._onscreen && this._onscreenLastTick) { - return this._onActive(); - } else if (!this._onscreen && this._onscreenLastTick) { - return this._onDeactivated(); - } - } - - _onInactive() { - return null; - } - - _onActivated() { - var error = this.runScript('default'); - if (error) return error; - error = this.runScript('load'); - return error; - } - - _onActive() { - var error = this.runScript('update'); - if (error) return error; - var current = this._mouseState; - var last = this._lastMouseState; // Mouse enter - - if (last === 'out' && current !== 'out') { - var error = this.runScript('mouseenter'); - if (error) return error; - } // Mouse down - - - if (current === 'down') { - var error = this.runScript('mousedown'); - if (error) return error; - } // Mouse pressed - - - if (last === 'over' && current === 'down') { - this._isClickTarget = true; - var error = this.runScript('mousepressed'); - if (error) return error; - } // Mouse click - - - if (last === 'down' && current === 'over' && this._isClickTarget) { - var error = this.runScript('mouseclick'); - if (error) return error; - } // Mouse released - - - if (last === 'down' && current === 'over') { - this._isClickTarget = false; - var error = this.runScript('mousereleased'); - if (error) return error; - } // Mouse leave - - - if (last !== 'out' && current === 'out') { - var error = this.runScript('mouseleave'); - if (error) return error; - } // Mouse hover - - - if (current === 'over') { - var error = this.runScript('mousehover'); - if (error) return error; - } // Mouse drag - - - if (last === 'down' && current === 'down') { - var error = this.runScript('mousedrag'); - if (error) return error; - } // Key events require the Tickable object to be inside of a project. Don't run them if there is no project - - - if (!this.project) return null; // Key down - - this.project.keysDown.forEach(key => { - this.project.currentKey = key; - var error = this.runScript('keydown'); - if (error) return error; - }); // Key press - - this.project.keysJustPressed.forEach(key => { - this.project.currentKey = key; - var error = this.runScript('keypressed'); - if (error) return error; - }); // Key released - - this.project.keysJustReleased.forEach(key => { - this.project.currentKey = key; - var error = this.runScript('keyreleased'); - if (error) return error; - }); - } - - _onDeactivated() { - this._isClickTarget = false; - return this.runScript('unload'); - } - - _evalScript(name, src) { - var fn = null; // Check for syntax/parsing errors - - try { - esprima.parseScript(src); - } catch (e) { - return this._generateEsprimaErrorInfo(e, name); - } // Attempt to create valid function... - - - try { - fn = new Function([], src); - } catch (e) { - // This should almost never be thrown unless there is an attempt to use syntax - // that the syntax checker (esprima) does not understand. - return this._generateErrorInfo(e, name); - } - - return fn; - } - - _runFunction(fn) { - var error = null; // Attach API methods - - var globalAPI = new GlobalAPI(this); - var otherObjects = this.parentClip ? this.parentClip.activeNamedChildren : []; - var apiMembers = globalAPI.apiMembers.concat(otherObjects.map(otherObject => { - return { - name: otherObject.identifier, - fn: otherObject - }; - })); - apiMembers.forEach(apiMember => { - window[apiMember.name] = apiMember.fn; - }); // These are currently hacked in here for performance reasons... - - var project = this.project; - var root = project && project.root; - window.project = root; - - if (project) { - window.project.resolution = { - x: project.width, - y: project.height - }; - window.project.framerate = project.framerate; - window.project.backgroundColor = project.backgroundColor; - } - - window.root = root; - window.parent = this.parentClip; - window.parentObject = this.parentObject; // Run the function - - var thisScope = this instanceof Wick.Frame ? this.parentClip : this; - - try { - fn.bind(thisScope)(); - } catch (e) { - // Catch runtime errors - error = this._generateErrorInfo(e, name); - } // These are currently hacked in here for performance reasons... - - - delete window.project; - delete window.root; - delete window.parent; - delete window.parentObject; // Detatch API methods - - apiMembers.forEach(apiMember => { - delete window[apiMember.name]; - }); - return error; - } - - _generateErrorInfo(error, name) { - if (Wick.Tickable.LOG_ERRORS) console.log(error); - return { - name: name !== undefined ? name : '', - lineNumber: this._generateLineNumberFromStackTrace(error.stack), - message: error.message, - uuid: this.uuid - }; - } - - _generateEsprimaErrorInfo(error, name) { - if (Wick.Tickable.LOG_ERRORS) console.log(error); - return { - name: name !== undefined ? name : '', - lineNumber: error.lineNumber, - message: error.description, - uuid: this.uuid - }; - } - - _generateLineNumberFromStackTrace(trace) { - var lineNumber = null; - trace.split('\n').forEach(line => { - if (lineNumber !== null) return; - var split = line.split(':'); - var lineString = split[split.length - 2]; - var lineInt = parseInt(lineString); - - if (!isNaN(lineInt)) { - lineNumber = lineInt - 2; - lineNumber = lineInt; - - if (platform.name === 'Firefox') { - lineNumber = lineNumber - 2; - } - } - }); - return lineNumber; - } - - _attachChildClipReferences() {// Implemented by Wick.Clip and Wick.Frame. - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * A class representing a frame. - */ -Wick.Frame = class extends Wick.Tickable { - /** - * Create a new frame. - * @param {number} start - The start of the frame. Optional, defaults to 1. - * @param {number} end - The end of the frame. Optional, defaults to be the same as start. - */ - constructor(args) { - if (!args) args = {}; - super(args); - this.start = args.start || 1; - this.end = args.end || this.start; - this._soundAssetUUID = null; - this._soundID = null; - this._soundVolume = 1.0; - this._soundLoop = false; - this._cropSoundOffsetMS = 0; // milliseconds. - - this._originalLayerIndex = -1; - } - - serialize(args) { - var data = super.serialize(args); - data.start = this.start; - data.end = this.end; - data.sound = this._soundAssetUUID; - data.soundVolume = this._soundVolume; - data.soundLoop = this._soundLoop; - data.originalLayerIndex = this.layerIndex !== -1 ? this.layerIndex : this._originalLayerIndex; - return data; - } - - deserialize(data) { - super.deserialize(data); - this.start = data.start; - this.end = data.end; - this._soundAssetUUID = data.sound; - this._soundVolume = data.soundVolume === undefined ? 1.0 : data.soundVolume; - this._soundLoop = data.soundLoop === undefined ? false : data.soundLoop; - this._originalLayerIndex = data.originalLayerIndex; - } - - get classname() { - return 'Frame'; - } - /** - * The length of the frame. - * @type {number} - */ - - - get length() { - return this.end - this.start + 1; - } - - set length(length) { - length = Math.max(1, length); - var diff = length - this.length; - this.end += diff; - } - /** - * The midpoint of the frame. - * @type {number} - */ - - - get midpoint() { - return this.start + (this.end - this.start) / 2; - } - /** - * Is true if the frame is currently visible. - * @type {boolean} - */ - - - get onScreen() { - if (!this.parent) return true; - return this.inPosition(this.parentTimeline.playheadPosition); - } - /** - * The sound attached to the frame. - * @type {Wick.SoundAsset} - */ - - - get sound() { - var uuid = this._soundAssetUUID; - return uuid ? this.project.getAssetByUUID(uuid) : null; - } - - set sound(soundAsset) { - this._soundAssetUUID = soundAsset.uuid; - } - /** - * The volume of the sound attached to the frame. - * @type {number} - */ - - - get soundVolume() { - return this._soundVolume; - } - - set soundVolume(soundVolume) { - this._soundVolume = soundVolume; - } - /** - * Whether or not the sound loops. - * @type {boolean} - */ - - - get soundLoop() { - return this._soundLoop; - } - - set soundLoop(soundLoop) { - this._soundLoop = soundLoop; - } - /** - * Removes the sound attached to this frame. - */ - - - removeSound() { - this._soundAssetUUID = null; - } - /** - * Plays the sound attached to this frame. - */ - - - playSound() { - if (!this.sound) { - return; - } - - var options = { - seekMS: this.playheadSoundOffsetMS + this.cropSoundOffsetMS, - volume: this.soundVolume, - loop: this.soundLoop - }; - this._soundID = this.sound.play(options); - } - /** - * Stops the sound attached to this frame. - */ - - - stopSound() { - if (this.sound) { - this.sound.stop(this._soundID); - this._soundID = null; - } - } - /** - * Check if the sound on this frame is playing. - * @returns {boolean} true if the sound is playing - */ - - - isSoundPlaying() { - return this._soundID !== null; - } - /** - * The amount of time, in milliseconds, that the frame's sound should play before stopping. - * @type {number} - */ - - - get playheadSoundOffsetMS() { - var offsetFrames = this.parentTimeline.playheadPosition - this.start; - var offsetMS = 1000 / this.project.framerate * offsetFrames; - return offsetMS; - } - /** - * The amount of time the sound playing should be offset, in milliseconds. If this is 0, - * the sound plays normally. A negative value means the sound should start at a later point - * in the track. THIS DOES NOT DETERMINE WHEN A SOUND PLAYS. - * @type {number} - */ - - - get cropSoundOffsetMS() { - return this._cropSoundOffsetMS; - } - - set cropSoundOffsetMS(val) { - this._cropSoundOffsetMS = val; - } - /** - * When should the sound start, in milliseconds. - * @type {number} - */ - - - get soundStartMS() { - return 1000 / this.project.framerate * (this.start - 1); - } - /** - * When should the sound end, in milliseconds. - * @type {number} - */ - - - get soundEndMS() { - return 1000 / this.project.framerate * (this.end - 1); - } - /** - * The paths on the frame. - * @type {Wick.Path[]} - */ - - - get paths() { - return this.getChildren('Path'); - } - /** - * The paths that are text and have identifiers, for dynamic text. - * @type {Wick.Path[]} - */ - - - get dynamicTextPaths() { - return this.paths.filter(path => { - return path.isDynamicText; - }); - } - /** - * The clips on the frame. - * @type {Wick.Clip[]} - */ - - - get clips() { - return this.getChildren(['Clip', 'Button']); - } - /** - * The tweens on this frame. - * @type {Wick.Tween[]} - */ - - - get tweens() { - // Ensure no tweens are outside of this frame's length. - var tweens = this.getChildren('Tween'); - tweens.forEach(tween => { - tween.restrictToFrameSize(); - }); - return this.getChildren('Tween'); - } - /** - * True if there are clips or paths on the frame. - * @type {boolean} - */ - - - get contentful() { - return this.paths.length > 0 || this.clips.length > 0; - } - /** - * The index of the parent layer. - * @type {number} - */ - - - get layerIndex() { - return this.parentLayer ? this.parentLayer.index : -1; - } - /** - * The index of the layer that this frame last belonged to. Useful when copying and pasting frames! - * @type {number} - */ - - - get originalLayerIndex() { - return this._originalLayerIndex; - } - /** - * Removes this frame from its parent layer. - */ - - - remove() { - this.parent.removeFrame(this); - } - /** - * True if the playhead is on this frame. - * @param {number} playheadPosition - the position of the playhead. - * @return {boolean} - */ - - - inPosition(playheadPosition) { - return this.start <= playheadPosition && this.end >= playheadPosition; - } - /** - * True if the frame exists within the given range. - * @param {number} start - the start of the range to check. - * @param {number} end - the end of the range to check. - * @return {boolean} - */ - - - inRange(start, end) { - return this.inPosition(start) || this.inPosition(end) || this.start >= start && this.start <= end || this.end >= start && this.end <= end; - } - /** - * True if the frame is contained fully within a given range. - * @param {number} start - the start of the range to check. - * @param {number} end - the end of the range to check. - * @return {boolean} - */ - - - containedWithin(start, end) { - return this.start >= start && this.end <= end; - } - /** - * The number of frames that this frame is from a given playhead position. - * @param {number} playheadPosition - */ - - - distanceFrom(playheadPosition) { - // playhead position is inside frame, distance is zero. - if (this.start <= playheadPosition && this.end >= playheadPosition) { - return 0; - } // otherwise, find the distance from the nearest end - - - if (this.start >= playheadPosition) { - return this.start - playheadPosition; - } else if (this.end <= playheadPosition) { - return playheadPosition - this.end; - } - } - /** - * Add a clip to the frame. - * @param {Wick.Clip} clip - the clip to add. - */ - - - addClip(clip) { - if (clip.parent) { - clip.remove(); - } - - this.addChild(clip); - } - /** - * Remove a clip from the frame. - * @param {Wick.Clip} clip - the clip to remove. - */ - - - removeClip(clip) { - this.removeChild(clip); - } - /** - * Add a path to the frame. - * @param {Wick.Path} path - the path to add. - */ - - - addPath(path) { - if (path.parent) { - path.remove(); - } - - this.addChild(path); - } - /** - * Remove a path from the frame. - * @param {Wick.Path} path - the path to remove. - */ - - - removePath(path) { - this.removeChild(path); - } - /** - * Add a tween to the frame. - * @param {Wick.Tween} tween - the tween to add. - */ - - - addTween(tween) { - // New tweens eat existing tweens. - var otherTween = this.getTweenAtPosition(tween.playheadPosition); - - if (otherTween) { - otherTween.remove(); - } - - this.addChild(tween); - tween.restrictToFrameSize(); - } - /** - * Automatically creates a tween at the current playhead position. Converts all objects into one clip if needed. - */ - - - createTween() { - // Don't make a tween if one already exits - var playheadPosition = this.getRelativePlayheadPosition(); - - if (this.getTweenAtPosition(playheadPosition)) { - return; - } // If more than one object exists on the frame, or if there is only one path, create a clip from those objects - - - var numClips = this.clips.length; - var numPaths = this.paths.length; - - if (numClips === 0 && numPaths === 1 || numClips + numPaths > 1) { - var allObjects = this.paths.concat(this.clips); - - var center = this.project.selection.view._getObjectsBounds(allObjects).center; - - var clip = new Wick.Clip({ - objects: this.paths.concat(this.clips), - transformation: new Wick.Transformation({ - x: center.x, - y: center.y - }) - }); - this.addClip(clip); - } // Create the tween (if there's not already a tween at the current playhead position) - - - var clip = this.clips[0]; - this.addTween(new Wick.Tween({ - playheadPosition: playheadPosition, - transformation: clip ? clip.transformation.copy() : new Wick.Transformation() - })); - } - /** - * Remove a tween from the frame. - * @param {Wick.Tween} tween - the tween to remove. - */ - - - removeTween(tween) { - this.removeChild(tween); - } - /** - * Remove all tweens from this frame. - */ - - - removeAllTweens(tween) { - this.tweens.forEach(tween => { - tween.remove(); - }); - } - /** - * Get the tween at the given playhead position. Returns null if there is no tween. - * @param {number} playheadPosition - the playhead position to look for tweens at. - * @returns {Wick.Tween} the tween at the given playhead position. - */ - - - getTweenAtPosition(playheadPosition) { - return this.tweens.find(tween => { - return tween.playheadPosition === playheadPosition; - }) || null; - } - /** - * The tween being used to transform the objects on the frame. - * @returns {Wick.Tween} tween - the active tween. Null if there is no active tween. - */ - - - getActiveTween() { - if (!this.parentTimeline) return null; - var playheadPosition = this.getRelativePlayheadPosition(); - var tween = this.getTweenAtPosition(playheadPosition); - - if (tween) { - return tween; - } - - var seekBackwardsTween = this.seekTweenBehind(playheadPosition); - var seekForwardsTween = this.seekTweenInFront(playheadPosition); - - if (seekBackwardsTween && seekForwardsTween) { - return Wick.Tween.interpolate(seekBackwardsTween, seekForwardsTween, playheadPosition); - } else if (seekForwardsTween) { - return seekForwardsTween; - } else if (seekBackwardsTween) { - return seekBackwardsTween; - } else { - return null; - } - } - /** - * Applies the transformation of current tween to the objects on the frame. - */ - - - applyTweenTransforms() { - var tween = this.getActiveTween(); - - if (tween) { - this.clips.forEach(clip => { - tween.applyTransformsToClip(clip); - }); - } - } - /** - * The asset of the sound attached to this frame, if one exists - * @returns {Wick.Asset[]} - */ - - - getLinkedAssets() { - var linkedAssets = []; - - if (this.sound) { - linkedAssets.push(this.sound); - } - - return linkedAssets; - } - /** - * Cut this frame in half using the parent timeline's playhead position. - */ - - - cut() { - // Can't cut a frame that doesn't beolong to a timeline + layer - if (!this.parentTimeline) return; // Can't cut a frame with length 1 - - if (this.length === 1) return; // Can't cut a frame that isn't under the playhead - - var playheadPosition = this.parentTimeline.playheadPosition; - if (!this.inPosition(playheadPosition)) return; // Create right half (leftover) frame - - var rightHalf = this.copy(); - rightHalf.identifier = null; - rightHalf.removeSound(); - rightHalf.removeAllTweens(); - rightHalf.start = playheadPosition = playheadPosition; // Cut this frame shorter - - this.end = playheadPosition - 1; // Add right frame - - this.parentLayer.addFrame(rightHalf); - } - /** - * Insert a blank frame into this frame using the parent timeline's playhead position. - * @returns {Wick.Frame} the newly added blank frame. - */ - - - insertBlankFrame() { - var playheadPosition = this.parentTimeline.playheadPosition; // Cut this frame - - this.cut(); // Add a blank frame where this frame was cut - - var blankFrame = new Wick.Frame({ - start: playheadPosition - }); - this.parentLayer.addFrame(blankFrame); - return blankFrame; - } - /** - * Extend this frame by one and push all frames right of this frame to the right. - */ - - - extendAndPushOtherFrames() { - this.parentLayer.getFramesInRange(this.end + 1, Infinity).forEach(frame => { - frame.start += 1; - frame.end += 1; - }); - this.end += 1; - } - /** - * Shrink this frame by one and pull all frames left of this frame to the left. - */ - - - shrinkAndPullOtherFrames() { - if (this.length === 1) return; - this.parentLayer.getFramesInRange(this.end + 1, Infinity).forEach(frame => { - frame.start -= 1; - frame.end -= 1; - }); - this.end -= 1; - } - /** - * Import SVG data into this frame. SVGs containing mulitple paths will be split into multiple Wick Paths. - * @param {string} svg - the SVG data to parse and import. - */ - - - importSVG(svg) { - this.view.importSVG(svg); - } - /** - * Get the position of this frame in relation to the parent timeline's playhead position. - * @returns {number} - */ - - - getRelativePlayheadPosition() { - return this.parentTimeline.playheadPosition - this.start + 1; - } - /** - * Find the first tween on this frame that exists behind the given playhead position. - * @returns {Wick.Tween} - */ - - - seekTweenBehind(playheadPosition) { - var seekBackwardsPosition = playheadPosition; - var seekBackwardsTween = null; - - while (seekBackwardsPosition > 0) { - seekBackwardsTween = this.getTweenAtPosition(seekBackwardsPosition); - seekBackwardsPosition--; - if (seekBackwardsTween) break; - } - - return seekBackwardsTween; - } - /** - * Find the first tween on this frame that exists past the given playhead position. - * @returns {Wick.Tween} - */ - - - seekTweenInFront(playheadPosition) { - var seekForwardsPosition = playheadPosition; - var seekForwardsTween = null; - - while (seekForwardsPosition <= this.end) { - seekForwardsTween = this.getTweenAtPosition(seekForwardsPosition); - seekForwardsPosition++; - if (seekForwardsTween) break; - } - - return seekForwardsTween; - } - - _onInactive() { - return super._onInactive(); - } - - _onActivated() { - var error = super._onActivated(); - - if (error) return error; - this.playSound(); - return this._tickChildren(); - } - - _onActive() { - var error = super._onActive(); - - if (error) return error; - return this._tickChildren(); - } - - _onDeactivated() { - var error = super._onDeactivated(); - - if (error) return error; - this.stopSound(); - return this._tickChildren(); - } - - _tickChildren() { - var childError = null; - this.clips.forEach(clip => { - if (childError) return; - childError = clip.tick(); - }); - return childError; - } - - _attachChildClipReferences() { - this.clips.forEach(clip => { - if (clip.identifier) { - this[clip.identifier] = clip; - - clip._attachChildClipReferences(); - } - }); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * A class representing a Wick Clip. - */ -Wick.Clip = class extends Wick.Tickable { - /** - * Create a new clip. - * @param {string} identifier - The identifier of the new clip. - * @param {Wick.Path|Wick.Clip[]} objects - Optional. A list of objects to add to the clip. - * @param {Wick.Transformation} transformation - Optional. The initial transformation of the clip. - */ - constructor(args) { - if (!args) args = {}; - super(args); - this.timeline = new Wick.Timeline(); - this.timeline.addLayer(new Wick.Layer()); - this.timeline.activeLayer.addFrame(new Wick.Frame()); - this._transformation = args.transformation || new Wick.Transformation(); - this.cursor = 'default'; - /* If objects are passed in, add them to the clip and reposition them */ - - if (args.objects) { - this.addObjects(args.objects); - } - - this._clones = []; - } - - serialize(args) { - var data = super.serialize(args); - data.transformation = this.transformation.values; - data.timeline = this._timeline; - return data; - } - - deserialize(data) { - super.deserialize(data); - this.transformation = new Wick.Transformation(data.transformation); - this._timeline = data.timeline; - this._clones = []; - } - - get classname() { - return 'Clip'; - } - /** - * Determines whether or not the clip is visible in the project. - * @type {boolean} - */ - - - get onScreen() { - if (this.isRoot) { - return true; - } else if (this.parent) { - return this.parent.onScreen; - } else { - return true; - } - } - /** - * Determines whether or not the clip is the root clip in the project. - * @type {boolean} - */ - - - get isRoot() { - return this.project && this === this.project.root; - } - /** - * Determines whether or not the clip is the currently focused clip in the project. - */ - - - get isFocus() { - return this.project && this === this.project.focus; - } - /** - * The timeline of the clip. - * @type {Wick.Timeline} - */ - - - get timeline() { - return this.getChild('Timeline'); - } - - set timeline(timeline) { - if (this.timeline) { - this.removeChild(this.timeline); - } - - this.addChild(timeline); - } - /** - * The active layer of the clip's timeline. - * @type {Wick.Layer} - */ - - - get activeLayer() { - return this.timeline.activeLayer; - } - /** - * The active frame of the clip's timeline. - * @type {Wick.Frame} - */ - - - get activeFrame() { - return this.activeLayer.activeFrame; - } - /** - * An array containing every clip and frame that is a child of this clip and has an identifier. - * @type {Wick.Base[]} - */ - - - get namedChildren() { - var namedChildren = []; - this.timeline.frames.forEach(frame => { - // Objects that can be accessed by their identifiers: - // Frames - if (frame.identifier) { - namedChildren.push(frame); - } // Clips - - - frame.clips.forEach(clip => { - if (clip.identifier) { - namedChildren.push(clip); - } - }); // Dynamic text paths - - frame.dynamicTextPaths.forEach(path => { - namedChildren.push(path); - }); - }); - return namedChildren; - } - /** - * An array containing every clip and frame that is a child of this clip and has an identifier, and also is visible on screen. - * @type {Wick.Base[]} - */ - - - get activeNamedChildren() { - return this.namedChildren.filter(child => { - return child.onScreen; - }); - } - /** - * Remove this clip from its parent frame. - */ - - - remove() { - // Don't attempt to remove if the object has already been removed. - // (This is caused by calling remove() multiple times on one object inside a script.) - if (!this.parent) return; - this.parent.removeClip(this); - } - /** - * Remove this clip and add all of its paths and clips to its parent frame. - * @returns {Wick.Base[]} the objects that were inside the clip. - */ - - - breakApart() { - var leftovers = []; - this.timeline.activeFrames.forEach(frame => { - frame.clips.forEach(clip => { - clip.transformation.x += this.transformation.x; - clip.transformation.y += this.transformation.y; - this.parentTimeline.activeFrame.addClip(clip); - leftovers.push(clip); - }); - frame.paths.forEach(path => { - path.x += this.transformation.x; - path.y += this.transformation.y; - this.parentTimeline.activeFrame.addPath(path); - leftovers.push(path); - }); - }); - this.remove(); - return leftovers; - } - /** - * Add paths and clips to this clip. - * @param {Wick.Base[]} objects - the paths and clips to add to the clip - */ - - - addObjects(objects) { - // Reposition objects such that their origin point is equal to this Clip's position - objects.forEach(object => { - object.x -= this.transformation.x; - object.y -= this.transformation.y; - }); // Add clips - - objects.filter(object => { - return object instanceof Wick.Clip; - }).forEach(clip => { - this.activeFrame.addClip(clip); - }); // Add paths - - objects.filter(object => { - return object instanceof Wick.Path; - }).forEach(path => { - this.activeFrame.addPath(path); - }); - } - /** - * Stops a clip's timeline on that clip's current playhead position. - */ - - - stop() { - this.timeline.stop(); - } - /** - * Plays a clip's timeline from that clip's current playhead position. - */ - - - play() { - this.timeline.play(); - } - /** - * Moves a clip's playhead to a specific position and stops that clip's timeline on that position. - * @param {number|string} frame - number or string representing the frame to move the playhead to. - */ - - - gotoAndStop(frame) { - this.timeline.gotoAndStop(frame); - } - /** - * Moves a clip's playhead to a specific position and plays that clip's timeline from that position. - * @param {number|string} frame - number or string representing the frame to move the playhead to. - */ - - - gotoAndPlay(frame) { - this.timeline.gotoAndPlay(frame); - } - /** - * Move the playhead of the clips timeline forward one frame. Does nothing if the clip is on its last frame. - */ - - - gotoNextFrame() { - this.timeline.gotoNextFrame(); - } - /** - * Move the playhead of the clips timeline backwards one frame. Does nothing if the clip is on its first frame. - */ - - - gotoPrevFrame() { - this.timeline.gotoPrevFrame(); - } - /** - * Returns the name of the frame which is currently active. If multiple frames are active, returns the - * name of the first active frame. - * @returns {string} Active Frame name. If the active frame does not have an identifier, returns empty string. - */ - - - get currentFrameName() { - let frames = this.timeline.activeFrames; - let name = ''; - frames.forEach(frame => { - if (name) return; - - if (frame.identifier) { - name = frame.identifier; - } - }); - return name; - } - /** - * @deprecated - * Returns the current playhead position. This is a legacy function, you should use clip.playheadPosition instead. - * @returns {number} Playhead Position. - */ - - - get currentFrameNumber() { - return this.timeline.playheadPosition; - } - /** - * The current transformation of the clip. - * @type {Wick.Transformation} - */ - - - get transformation() { - return this._transformation; - } - - set transformation(transformation) { - this._transformation = transformation; // When the transformation changes, update the current tween, if one exists - - if (this.parentFrame) { - var tween = this.parentFrame.getActiveTween(); - - if (tween) { - tween.transformation = this._transformation.copy(); - } - } - } - /** - * Returns true if this clip collides with another clip. - * @param {Wick.Clip} other - The other clip to check collision with. - * @returns {boolean} True if this clip collides the other clip. - */ - - - hitTest(other) { - return this.bounds.intersects(other.bounds); - } - /** - * The bounding box of the clip. - * @type {object} - */ - - - get bounds() { - return this.view.group.bounds; - } - /** - * The X position of the clip. - * @type {number} - */ - - - get x() { - return this.transformation.x; - } - - set x(x) { - this.transformation.x = x; - } - /** - * The Y position of the clip. - * @type {number} - */ - - - get y() { - return this.transformation.y; - } - - set y(y) { - this.transformation.y = y; - } - /** - * The X scale of the clip. - * @type {number} - */ - - - get scaleX() { - return this.transformation.scaleX; - } - - set scaleX(scaleX) { - this.transformation.scaleX = scaleX; - } - /** - * The Y scale of the clip. - * @type {number} - */ - - - get scaleY() { - return this.transformation.scaleY; - } - - set scaleY(scaleY) { - this.transformation.scaleY = scaleY; - } - /** - * The width of the clip. - * @type {number} - */ - - - get width() { - return this.isRoot ? this.project.width : this.bounds.width * this.scaleX; - } - - set width(width) { - this.scaleX = width / this.width * this.scaleX; - } - /** - * The height of the clip. - * @type {number} - */ - - - get height() { - return this.isRoot ? this.project.height : this.bounds.height * this.scaleY; - } - - set height(height) { - this.scaleY = height / this.height * this.scaleY; - } - /** - * The rotation of the clip. - * @type {number} - */ - - - get rotation() { - return this.transformation.rotation; - } - - set rotation(rotation) { - this.transformation.rotation = rotation; - } - /** - * The opacity of the clip. - * @type {number} - */ - - - get opacity() { - return this.transformation.opacity; - } - - set opacity(opacity) { - opacity = Math.min(1, opacity); - opacity = Math.max(0, opacity); - this.transformation.opacity = opacity; - } - /** - * Copy this clip, and add the copy to the same frame as the original clip. - * @returns {Wick.Clip} the result of the clone. - */ - - - clone() { - var clone = this.copy(); - clone.identifier = null; - this.parentFrame.addClip(clone); - - this._clones.push(clone); - - return clone; - } - /** - * An array containing all objects that were created by calling clone() on this Clip. - * @type {Wick.Clip[]} - */ - - - get clones() { - return this._clones; - } - /** - * This is a stopgap to prevent users from using setText with a Clip. - */ - - - setText(newTextContent) { - throw new Error('setText() can only be used with text objects.'); - } - /** - * The list of parents, grandparents, grand-grandparents...etc of the clip. - * @returns {Wick.Clip[]} Array of all parents - */ - - - get lineage() { - if (this.isRoot) { - return [this]; - } else { - return [this].concat(this.parentClip.lineage); - } - } - - _onInactive() { - return super._onInactive(); - } - - _onActivated() { - var error = super._onActivated(); - - if (error) return error; - return this._tickChildren(); - } - - _onActive() { - var error = super._onActive(); - - if (error) return error; - this.timeline.advance(); - return this._tickChildren(); - } - - _onDeactivated() { - var error = super._onDeactivated(); - - if (error) return error; - return this._tickChildren(); - } - - _tickChildren() { - var childError = null; - this.timeline.frames.forEach(frame => { - if (childError) return; - childError = frame.tick(); - }); - return childError; - } - - _attachChildClipReferences() { - this.timeline.activeFrames.forEach(frame => { - frame.clips.forEach(clip => { - if (clip.identifier) { - this[clip.identifier] = clip; - - clip._attachChildClipReferences(); - } - }); // Dynamic text paths can be accessed by their identifiers. - - frame.dynamicTextPaths.forEach(path => { - this[path.identifier] = path; - }); - }); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ - -/** - * A class representing a Wick Button. - * Buttons are just clips with special timelines controlled by mouse interactions. - */ -Wick.Button = class extends Wick.Clip { - /** - * Create a new button. - * @param {object} args - */ - constructor(args) { - super(args); - this.cursor = 'pointer'; - var frame1 = this.timeline.activeFrame; - var frame2 = frame1.copy(); - var frame3 = frame1.copy(); - frame2.start = 2; - frame2.end = 2; - frame3.start = 3; - frame3.end = 3; - frame1.identifier = 'up'; - frame2.identifier = 'over'; - frame3.identifier = 'down'; - this.timeline.activeLayer.addFrame(frame2); - this.timeline.activeLayer.addFrame(frame3); - this.removeScript('default'); - this.addScript('mouseclick', ''); - } - - serialize(args) { - var data = super.serialize(args); - return data; - } - - deserialize(data) { - super.deserialize(data); - } - - get classname() { - return 'Button'; - } - - _onInactive() { - return super._onInactive(); - } - - _onActivated() { - var error = super._onActivated(); - - this.timeline.stop(); - this.timeline.playheadPosition = 1; - return error; - } - - _onActive() { - this.timeline._forceNextFrame = 1; - var frame2Exists = this.timeline.getFramesAtPlayheadPosition(2).length > 0; - var frame3Exists = this.timeline.getFramesAtPlayheadPosition(3).length > 0; - - if (this._mouseState === 'over') { - if (frame2Exists) { - this.timeline.gotoFrame(2); - } - } else if (this._mouseState === 'down') { - if (frame3Exists) { - this.timeline.gotoFrame(3); - } else if (frame2Exists) { - this.timeline.gotoFrame(2); - } - } - - var error = super._onActive(); - - if (error) return error; - return null; - } - - _onDeactivated() { - super._onDeactivated(); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tool = class { - static get DOUBLE_CLICK_TIME() { - return 300; - } - /** - * Creates a new Wick Tool. - */ - - - constructor() { - this.paperTool = new this.paper.Tool(); // Attach onActivate event - - this.paperTool.onActivate = e => { - this.onActivate(e); - }; // Attach onDeactivate event - - - this.paperTool.onDeactivate = e => { - this.onDeactivate(e); - }; // Attach mouse move event - - - this.paperTool.onMouseMove = e => { - this.onMouseMove(e); - }; // Attach mouse down + double click event - - - this.paperTool.onMouseDown = e => { - if (this.doubleClickEnabled && this._lastMousedownTimestamp !== null && e.timeStamp - this._lastMousedownTimestamp < Wick.Tool.DOUBLE_CLICK_TIME) { - this.onDoubleClick(e); - } else { - this.onMouseDown(e); - } - - this._lastMousedownTimestamp = e.timeStamp; - }; // Attach key events - - - this.paperTool.onKeyDown = e => { - this.onKeyDown(e); - }; - - this.paperTool.onKeyUp = e => { - this.onKeyUp(e); - }; // Attach mouse move event - - - this.paperTool.onMouseDrag = e => { - this.onMouseDrag(e); - }; // Attach mouse up event - - - this.paperTool.onMouseUp = e => { - this.onMouseUp(e); - }; - - this._eventCallbacks = {}; - this._lastMousedownTimestamp = null; - } - /** - * The paper.js scope to use. - */ - - - get paper() { - return Wick.View.paperScope; - } - /** - * The CSS cursor to display for this tool. - */ - - - get cursor() { - console.warn("Warning: Tool is missing a cursor!"); - } - /** - * Called when the tool is activated - */ - - - onActivate(e) {} - /** - * Called when the tool is deactivated (another tool is activated) - */ - - - onDeactivate(e) {} - /** - * Called when the mouse moves and the tool is active. - */ - - - onMouseMove(e) { - this.setCursor(this.cursor); - } - /** - * Called when the mouse clicks the paper.js canvas and this is the active tool. - */ - - - onMouseDown(e) {} - /** - * Called when the mouse is dragged on the paper.js canvas and this is the active tool. - */ - - - onMouseDrag(e) {} - /** - * Called when the mouse is clicked on the paper.js canvas and this is the active tool. - */ - - - onMouseUp(e) {} - /** - * Called when the mouse double clicks on the paper.js canvas and this is the active tool. - */ - - - onDoubleClick(e) {} - /** - * Called when a key is pressed and this is the active tool. - */ - - - onKeyDown(e) {} - /** - * Called when a key is released and this is the active tool. - */ - - - onKeyUp(e) {} - /** - * Activates this tool in paper.js. - */ - - - activate() { - this.paperTool.activate(); - } - /** - * Sets the cursor of the paper.js canvas that the tool belongs to. - * @param {string} cursor - a CSS cursor style - */ - - - setCursor(cursor) { - this.paper.view._element.style.cursor = cursor; - } - /** - * Attach a function to get called when an event happens. - * @param {string} eventName - the name of the event - * @param {function} fn - the function to call when the event is fired - */ - - - on(eventName, fn) { - this._eventCallbacks[eventName] = fn; - } - /** - * Call the functions attached to a given event. - * @param {string} eventName - the name of the event to fire - * @param {object} e - (optional) an object to attach some data to, if needed - */ - - - fireEvent(eventName, e) { - if (!e) e = {}; - - if (!e.layers) { - e.layers = [this.paper.project.activeLayer]; - } - - var fn = this._eventCallbacks[eventName]; - fn && fn(e); - } - /** - * - * @param {paper.Color} color - the color of the cursor - * @param {number} size - the width of the cursor image to generate - * @param {boolean} transparent - if set to true, color is ignored - */ - - - createDynamicCursor(color, size, transparent) { - var radius = size / 2; - var canvas = document.createElement("canvas"); - canvas.width = radius * 2 + 2; - canvas.height = radius * 2 + 2; - var context = canvas.getContext('2d'); - var centerX = canvas.width / 2; - var centerY = canvas.height / 2; - context.beginPath(); - context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); - context.strokeStyle = transparent ? 'black' : invert(color); - context.stroke(); - - if (transparent) { - context.beginPath(); - context.arc(centerX, centerY, radius - 1, 0, 2 * Math.PI, false); - context.strokeStyle = 'white'; - context.stroke(); - } else { - context.beginPath(); - context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); - context.fillStyle = color; - context.fill(); - } - - return 'url(' + canvas.toDataURL() + ') ' + (radius + 1) + ' ' + (radius + 1) + ',default'; - } - /** - * Get a tool setting from the project. See Wick.ToolSettings for all options - * @param {string} name - the name of the setting to get - */ - - - getSetting(name) { - return this.project.toolSettings.getSetting(name); - } - /** - * Does this tool have a double click action? (override this in classes that extend Wick.Tool) - * @type {boolean} - */ - - - get doubleClickEnabled() { - return true; - } - /** - * Adds a paper.Path to the active frame's paper.Layer. - * @param {paper.Path} path - the path to add - */ - - - addPathToProject(path) { - // Automatically add a frame is there isn't one - if (!this.project.activeFrame) { - var playheadPosition = this.project.activeTimeline.playheadPosition; - var newFrame = new Wick.Frame({ - start: playheadPosition - }); - this.project.activeLayer.addFrame(newFrame); - this.project.view.render(); - } - - if (path) this.paper.project.activeLayer.addChild(path); - } - -}; -Wick.Tools = {}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Brush = class extends Wick.Tool { - static get CROQUIS_WAIT_AMT_MS() { - return 100; - } - - get doubleClickEnabled() { - return false; - } - /** - * Creates the brush tool. - */ - - - constructor() { - super(); - this.name = 'brush'; - this.BRUSH_POINT_SPACING = 0.2; - this.BRUSH_STABILIZER_LEVEL = 3; - this.POTRACE_RESOLUTION = 1.0; - this.MIN_PRESSURE = 0.14; - this.croquis; - this.croquisDOMElement; - this.croquisBrush; - this.cachedCursor; - this.lastPressure; - this.errorOccured = false; - this.strokeBounds = new paper.Rectangle(); - this._croquisStartTimeout = null; - } - - get cursor() {// the brush cursor is done in a custom way using _regenCursor(). - } - - get isDrawingTool() { - return true; - } - - onActivate(e) { - if (!this.croquis) { - this.croquis = new Croquis(); - this.croquis.setCanvasSize(500, 500); - this.croquis.addLayer(); - this.croquis.fillLayer('rgba(0,0,0,0)'); - this.croquis.addLayer(); - this.croquis.selectLayer(1); - this.croquis.lockHistory(); - this.croquisBrush = new Croquis.Brush(); - this.croquis.setTool(this.croquisBrush); - this.croquisDOMElement = this.croquis.getDOMElement(); - this.croquisDOMElement.style.position = 'absolute'; - this.croquisDOMElement.style.left = '0px'; - this.croquisDOMElement.style.top = '0px'; - this.croquisDOMElement.style.width = '100%'; - this.croquisDOMElement.style.height = '100%'; - this.croquisDOMElement.style.display = 'block'; - this.croquisDOMElement.style.pointerEvents = 'none'; - } - } - - onDeactivate(e) {} - - onMouseMove(e) { - super.onMouseMove(e); - - this._updateCanvasAttributes(); - - this._regenCursor(); - } - - onMouseDown(e) { - clearTimeout(this._croquisStartTimeout); - this._isInProgress = true; - - this._updateCanvasAttributes(); // Update croquis params - - - this.croquisBrush.setSize(this._getRealBrushSize()); - this.croquisBrush.setColor(this.getSetting('fillColor').toCSS(true)); - this.croquisBrush.setSpacing(this.BRUSH_POINT_SPACING); - this.croquis.setToolStabilizeLevel(this.BRUSH_STABILIZER_LEVEL); - this.croquis.setToolStabilizeWeight(this.getSetting('brushStabilizerWeight') / 100.0 + 0.3); - this.croquis.setToolStabilizeInterval(1); // Forward mouse event to croquis canvas - - var point = this._croquisToPaperPoint(e.point); - - this._updateStrokeBounds(point); - - try { - this.croquis.down(point.x, point.y, this.pressure); - } catch (e) { - this.handleBrushError(e); - return; - } - } - - onMouseDrag(e) { - if (!this._isInProgress) return; // Forward mouse event to croquis canvas - - var point = this._croquisToPaperPoint(e.point); - - this._updateStrokeBounds(point); - - try { - this.croquis.move(point.x, point.y, this.pressure); - } catch (e) { - this.handleBrushError(e); - return; - } - - this.lastPressure = this.pressure; - } - - onMouseUp(e) { - if (!this._isInProgress) return; - this._isInProgress = false; // Forward mouse event to croquis canvas - - var point = this._croquisToPaperPoint(e.point); - - this._updateStrokeBounds(point); // This prevents cropping out edges of the brush stroke - - - this.strokeBounds = this.strokeBounds.expand(this._getRealBrushSize()); - - try { - this.croquis.up(point.x, point.y, this.lastPressure); - } catch (e) { - this.handleBrushError(e); - return; - } // Give croquis just a little bit to get the canvas ready... - - - this.errorOccured = false; - var strokeBounds = this.strokeBounds.clone(); - this._croquisStartTimeout = setTimeout(() => { - // Retrieve Croquis canvas - var canvas = this.paper.view._element.parentElement.getElementsByClassName('croquis-layer-canvas')[1]; - - if (!canvas) { - console.warn("Croquis canvas was not found in the canvas container. Something very bad has happened."); - this.handleBrushError('misingCroquisCanvas'); - return; - } // Rip image data out of Croquis.js canvas - // (and crop out empty space using strokeBounds - this massively speeds up potrace) - - - var croppedCanvas = document.createElement("canvas"); - var croppedCanvasCtx = croppedCanvas.getContext("2d"); - croppedCanvas.width = strokeBounds.width; - croppedCanvas.height = strokeBounds.height; - if (strokeBounds.x < 0) strokeBounds.x = 0; - if (strokeBounds.y < 0) strokeBounds.y = 0; - croppedCanvasCtx.drawImage(canvas, strokeBounds.x, strokeBounds.y, strokeBounds.width, strokeBounds.height, 0, 0, croppedCanvas.width, croppedCanvas.height); // Run potrace and add the resulting path to the project - - var svg = potrace.fromImage(croppedCanvas).toSVG(1 / this.POTRACE_RESOLUTION / this.paper.view.zoom); - var potracePath = this.paper.project.importSVG(svg); - potracePath.fillColor = this.getSetting('fillColor'); - potracePath.position.x += this.paper.view.bounds.x; - potracePath.position.y += this.paper.view.bounds.y; - potracePath.position.x += strokeBounds.x / this.paper.view.zoom; - potracePath.position.y += strokeBounds.y / this.paper.view.zoom; - potracePath.remove(); - potracePath.closed = true; - potracePath.children[0].closed = true; - potracePath.children[0].applyMatrix = true; - this.addPathToProject(potracePath.children[0]); // We're done potracing using the current croquis canvas, reset the stroke bounds - - this._resetStrokeBounds(point); // Clear croquis canvas - - - this.croquis.clearLayer(); - this.fireEvent('canvasModified'); - }, Wick.Tools.Brush.CROQUIS_WAIT_AMT_MS); - } - /** - * The current amount of pressure applied to the paper js canvas this tool belongs to. - */ - - - get pressure() { - if (this.getSetting('pressureEnabled')) { - var pressure = this.paper.view.pressure; - return convertRange(pressure, [0, 1], [this.MIN_PRESSURE, 1]); - } else { - return 1; - } - } - /** - * Croquis throws a lot of errrors. This is a helpful function to handle those errors gracefully. - */ - - - handleBrushError(e) { - this._isInProgress = false; - this.croquis.clearLayer(); - - if (!this.errorOccured) { - console.error("Brush error"); - console.error(e); - } - - this.errorOccured = true; - } - /** - * Is the brush currently making a stroke? - * @type {boolean} - */ - - - isInProgress() { - return this._isInProgress; - } - /** - * Discard the current brush stroke. - */ - - - discard() { - if (!this.isInProgress) return; - setTimeout(() => { - this.croquis.up(0, 0, 0); - this.croquis.clearLayer(); - this.croquisDOMElement.style.opacity = 0; - }, Wick.Tools.Brush.CROQUIS_WAIT_AMT_MS); - } - /* Generate a new circle cursor based on the brush size. */ - - - _regenCursor() { - var size = this._getRealBrushSize(); - - var color = this.getSetting('fillColor').toCSS(true); - this.cachedCursor = this.createDynamicCursor(color, size, this.getSetting('pressureEnabled')); - this.setCursor(this.cachedCursor); - } - /* Get the actual pixel size of the brush to send to Croquis. */ - - - _getRealBrushSize() { - var size = this.getSetting('brushSize') + 1; - - if (!this.getSetting('relativeBrushSize')) { - size *= this.paper.view.zoom; - } - - return size; - } - /* Update Croquis and the div containing croquis to reflect all current options. */ - - - _updateCanvasAttributes() { - // Update croquis element and pressure options - if (!this.paper.view._element.parentElement.contains(this.croquisDOMElement)) { - this.paper.view.enablePressure(); - - this.paper.view._element.parentElement.appendChild(this.croquisDOMElement); - } // Update croquis element canvas size - - - if (this.croquis.getCanvasWidth() !== this.paper.view._element.width || this.croquis.getCanvasHeight() !== this.paper.view._element.height) { - this.croquis.setCanvasSize(this.paper.view._element.width, this.paper.view._element.height); - } // Fake brush opacity in croquis by changing the opacity of the croquis canvas - - - this.croquisDOMElement.style.opacity = this.getSetting('fillColor').alpha; - } - /* Convert a point in Croquis' canvas space to paper.js's canvas space. */ - - - _croquisToPaperPoint(croquisPoint) { - var paperPoint = this.paper.view.projectToView(croquisPoint.x, croquisPoint.y); - return paperPoint; - } - /* Used for calculating the crop amount for potrace. */ - - - _resetStrokeBounds(point) { - this.strokeBounds = new paper.Rectangle(point.x, point.y, 1, 1); - } - /* Used for calculating the crop amount for potrace. */ - - - _updateStrokeBounds(point) { - this.strokeBounds = this.strokeBounds.include(point); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Cursor = class extends Wick.Tool { - /** - * Creates a cursor tool. - */ - constructor() { - super(); - this.name = 'cursor'; - this.SELECTION_TOLERANCE = 3; - this.CURSOR_DEFAULT = 'cursors/default.png'; - this.CURSOR_SCALE_TOP_RIGHT_BOTTOM_LEFT = 'cursors/scale-top-right-bottom-left.png'; - this.CURSOR_SCALE_TOP_LEFT_BOTTOM_RIGHT = 'cursors/scale-top-left-bottom-right.png'; - this.CURSOR_SCALE_VERTICAL = 'cursors/scale-vertical.png'; - this.CURSOR_SCALE_HORIZONTAL = 'cursors/scale-horizontal.png'; - this.CURSOR_ROTATE_TOP = 'cursors/rotate-top-right.png'; - this.CURSOR_ROTATE_RIGHT = 'cursors/rotate-bottom-right.png'; - this.CURSOR_ROTATE_BOTTOM = 'cursors/rotate-bottom-left.png'; - this.CURSOR_ROTATE_LEFT = 'cursors/rotate-top-left.png'; - this.CURSOR_ROTATE_TOP_RIGHT = 'cursors/rotate-top-right.png'; - this.CURSOR_ROTATE_TOP_LEFT = 'cursors/rotate-top-left.png'; - this.CURSOR_ROTATE_BOTTOM_RIGHT = 'cursors/rotate-bottom-right.png'; - this.CURSOR_ROTATE_BOTTOM_LEFT = 'cursors/rotate-bottom-left.png'; - this.CURSOR_MOVE = 'cursors/move.png'; - this.hitResult = new this.paper.HitResult(); - this.selectionBox = new this.paper.SelectionBox(paper); - this.selectedItems = []; - this.currentCursorIcon = ''; - } - /** - * Generate the current cursor. - * @type {string} - */ - - - get cursor() { - return 'url("' + this.currentCursorIcon + '") 32 32, auto'; - } - - onActivate(e) { - this.selectedItems = []; - } - - onDeactivate(e) {} - - onMouseMove(e) { - super.onMouseMove(e); // Find the thing that is currently under the cursor. - - this.hitResult = this._updateHitResult(e); // Update the image being used for the cursor - - this._setCursor(this._getCursor()); - } - - onMouseDown(e) { - super.onMouseDown(e); - if (!e.modifiers) e.modifiers = {}; - this.hitResult = this._updateHitResult(e); - - if (this.hitResult.item && this.hitResult.item.data.isSelectionBoxGUI) {// Clicked the selection box GUI, do nothing - } else if (this.hitResult.item && this._isItemSelected(this.hitResult.item)) { - // We clicked something that was already selected. - // Shift click: Deselect that item - if (e.modifiers.shift) { - this._deselectItem(this.hitResult.item); - - this._checkIfSelectionChanged(); - } - } else if (this.hitResult.item && this.hitResult.type === 'fill') { - if (!e.modifiers.shift) { - // Shift click? Keep everything else selected. - this._clearSelection(); - } // Clicked an item: select that item - - - this._selectItem(this.hitResult.item); - - this._checkIfSelectionChanged(); - } else { - // Nothing was clicked, so clear the selection and start a new selection box - // (don't clear the selection if shift is held, though) - if (this._selection.numObjects > 0 && !e.modifiers.shift) { - this._clearSelection(); - - this._checkIfSelectionChanged(); - } - - this.selectionBox.start(e.point); - } - } - - onDoubleClick(e) { - var selectedObject = this._selection.getSelectedObject(); - - if (selectedObject && selectedObject instanceof Wick.Clip) { - // Double clicked a Clip, set the focus to that Clip. - this.project.focusTimelineOfSelectedClip(); - this.fireEvent('canvasModified'); - } else if (selectedObject && selectedObject instanceof Wick.Path && selectedObject.view.item instanceof paper.PointText) {// Double clicked text, switch to text tool and edit the text item. - // TODO - } else { - // Double clicked the canvas, leave the current focus. - this.project.focusTimelineOfParentClip(); - this.fireEvent('canvasModified'); - } - } - - onMouseDrag(e) { - if (!e.modifiers) e.modifiers = {}; - this.__isDragging = true; - - if (this.hitResult.item && this.hitResult.item.data.isSelectionBoxGUI) { - // Update selection drag - if (!this._widget.currentTransformation) { - this._widget.startTransformation(this.hitResult.item); - } - - this._widget.updateTransformation(this.hitResult.item, e); - } else if (this.selectionBox.active) { - // Selection box is being used, update it with a new point - this.selectionBox.drag(e.point); - } else if (this.hitResult.item && this.hitResult.type === 'fill') { - // We're dragging the selection itself, so move the whole item. - if (!this._widget.currentTransformation) { - this._widget.startTransformation(this.hitResult.item); - } - - this._widget.updateTransformation(this.hitResult.item, e); - } else { - this.__isDragging = false; - } - } - - onMouseUp(e) { - if (!e.modifiers) e.modifiers = {}; - - if (this.selectionBox.active) { - // Finish selection box and select objects touching box (or inside box, if alt is held) - this.selectionBox.mode = e.modifiers.alt ? 'contains' : 'intersects'; - this.selectionBox.end(e.point); - - if (!e.modifiers.shift) { - this._selection.clear(); - } - - this.selectionBox.items.filter(item => { - return item.data.wickUUID; - }).forEach(item => { - this._selectItem(item); - }); - - this._checkIfSelectionChanged(); - } else if (this._selection.numObjects > 0) { - if (this.__isDragging) { - this.__isDragging = false; - this.project.tryToAutoCreateTween(); - - this._widget.finishTransformation(); - - this.fireEvent('canvasModified'); - } - } - } - - _updateHitResult(e) { - var newHitResult = this.paper.project.hitTest(e.point, { - fill: true, - stroke: true, - curves: true, - segments: true, - tolerance: this.SELECTION_TOLERANCE, - match: result => { - return result.item !== this.hoverPreview && !result.item.data.isBorder; - } - }); - if (!newHitResult) newHitResult = new this.paper.HitResult(); - - if (newHitResult.item && !newHitResult.item.data.isSelectionBoxGUI) { - // You can't select children of compound paths, you can only select the whole thing. - if (newHitResult.item.parent.className === 'CompoundPath') { - newHitResult.item = newHitResult.item.parent; - } // You can't select individual children in a group, you can only select the whole thing. - - - if (newHitResult.item.parent.parent) { - newHitResult.type = 'fill'; - - while (newHitResult.item.parent.parent) { - newHitResult.item = newHitResult.item.parent; - } - } // this.paper.js has two names for strokes+curves, we don't need that extra info - - - if (newHitResult.type === 'stroke') { - newHitResult.type = 'curve'; - } // Mousing over rasters acts the same as mousing over fills. - - - if (newHitResult.type === 'pixel') { - newHitResult.type = 'fill'; - } - - ; // Disable curve and segment selection. (this was moved to the PathCursor) - - if (newHitResult.type === 'segment' || newHitResult.type === 'curve') { - newHitResult.type = 'fill'; - } - - ; - } - - return newHitResult; - } - - _getCursor() { - if (!this.hitResult.item) { - return this.CURSOR_DEFAULT; - } else if (this.hitResult.item.data.isSelectionBoxGUI) { - // Don't show any custom cursor if the mouse is over the border, the border does nothing - if (this.hitResult.item.name === 'border') { - return this.CURSOR_DEFAULT; - } // Calculate the angle in which the scale handle scales the selection. - // Use that angle to determine the cursor graphic to use. - // Here is a handy diagram showing the cursors that correspond to the angles: - // 315 0 45 - // o-----o-----o - // | | - // | | - // 270 o o 90 - // | | - // | | - // o-----o-----o - // 225 180 135 - - - var baseAngle = { - topCenter: 0, - topRight: 45, - rightCenter: 90, - bottomRight: 135, - bottomCenter: 180, - bottomLeft: 225, - leftCenter: 270, - topLeft: 315 - }[this.hitResult.item.data.handleEdge]; - var angle = baseAngle + this._widget.rotation; // It makes angle math easier if we dont allow angles >360 or <0 degrees: - - if (angle < 0) angle += 360; - if (angle > 360) angle -= 360; // Round the angle to the nearest 45 degree interval. - - var angleRoundedToNearest45 = Math.round(angle / 45) * 45; - angleRoundedToNearest45 = Math.round(angleRoundedToNearest45); // just incase of float weirdness - - angleRoundedToNearest45 = '' + angleRoundedToNearest45; // convert to string - // Now we know which of eight directions the handle is pointing, so we choose the correct cursor - - if (this.hitResult.item.data.handleType === 'scale') { - var cursorGraphicFromAngle = { - '0': this.CURSOR_SCALE_VERTICAL, - '45': this.CURSOR_SCALE_TOP_RIGHT_BOTTOM_LEFT, - '90': this.CURSOR_SCALE_HORIZONTAL, - '135': this.CURSOR_SCALE_TOP_LEFT_BOTTOM_RIGHT, - '180': this.CURSOR_SCALE_VERTICAL, - '225': this.CURSOR_SCALE_TOP_RIGHT_BOTTOM_LEFT, - '270': this.CURSOR_SCALE_HORIZONTAL, - '315': this.CURSOR_SCALE_TOP_LEFT_BOTTOM_RIGHT, - '360': this.CURSOR_SCALE_VERTICAL - }[angleRoundedToNearest45]; - return cursorGraphicFromAngle; - } else if (this.hitResult.item.data.handleType === 'rotation') { - var cursorGraphicFromAngle = { - '0': this.CURSOR_ROTATE_TOP, - '45': this.CURSOR_ROTATE_TOP_RIGHT, - '90': this.CURSOR_ROTATE_RIGHT, - '135': this.CURSOR_ROTATE_BOTTOM_RIGHT, - '180': this.CURSOR_ROTATE_BOTTOM, - '225': this.CURSOR_ROTATE_BOTTOM_LEFT, - '270': this.CURSOR_ROTATE_LEFT, - '315': this.CURSOR_ROTATE_TOP_LEFT, - '360': this.CURSOR_ROTATE_TOP - }[angleRoundedToNearest45]; - return cursorGraphicFromAngle; - } - } else { - if (this.hitResult.type === 'fill') { - return this.CURSOR_MOVE; - } - } - } - - _setCursor(cursor) { - this.currentCursorIcon = cursor; - } - - get _selection() { - return this.project.selection; - } - - get _widget() { - return this._selection.view.widget; - } - - _clearSelection() { - this._selection.clear(); - } - - _selectItem(item) { - var object = this._wickObjectFromPaperItem(item); - - this._selection.select(object); - } - - _deselectItem(item) { - var object = this._wickObjectFromPaperItem(item); - - this._selection.deselect(object); - } - - _isItemSelected(item) { - var object = this._wickObjectFromPaperItem(item); - - return object.isSelected; - } - - _wickObjectFromPaperItem(item) { - var uuid = item.data.wickUUID; - - if (!uuid) { - console.error('WARNING: _wickObjectFromPaperItem: item had no wick UUID. did you try to select something that wasnt created by a wick view? is the view up-to-date?'); - console.log(item); - } - - return Wick.ObjectCache.getObjectByUUID(uuid); - } - - _checkIfSelectionChanged() { - var newSelectionData = this._createSelectionData(); - - if (newSelectionData !== this._lastSelection) { - this.fireEvent('canvasModified'); - } - - this._lastSelection = newSelectionData; - } - - _createSelectionData() { - return this._selection.getSelectedObjectUUIDs().join(''); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Ellipse = class extends Wick.Tool { - /** - * Creates an instance of the ellipse tool. - */ - constructor() { - super(); - this.name = 'ellipse'; - this.path = null; - this.topLeft = null; - this.bottomRight = null; - } - - get doubleClickEnabled() { - return false; - } - /** - * A crosshair cursor. - * @type {string} - */ - - - get cursor() { - return 'crosshair'; - } - - get isDrawingTool() { - return true; - } - - onActivate(e) {} - - onDeactivate(e) { - if (this.path) { - this.path.remove(); - this.path = null; - } - } - - onMouseDown(e) { - this.topLeft = e.point; - this.bottomRight = e.point; - } - - onMouseDrag(e) { - if (this.path) this.path.remove(); - this.bottomRight = e.point; // Lock width and height if shift is held down - - if (e.modifiers.shift) { - var d = this.bottomRight.subtract(this.topLeft); - var max = Math.max(Math.abs(d.x), Math.abs(d.y)); - this.bottomRight.x = this.topLeft.x + max * (d.x < 0 ? -1 : 1); - this.bottomRight.y = this.topLeft.y + max * (d.y < 0 ? -1 : 1); - } - - var bounds = new this.paper.Rectangle(new this.paper.Point(this.topLeft.x, this.topLeft.y), new this.paper.Point(this.bottomRight.x, this.bottomRight.y)); - this.path = new this.paper.Path.Ellipse(bounds); - this.paper.project.activeLayer.addChild(this.path); - this.path.fillColor = this.getSetting('fillColor'); - this.path.strokeColor = this.getSetting('strokeColor'); - this.path.strokeWidth = this.getSetting('strokeWidth'); - this.path.strokeCap = 'round'; - } - - onMouseUp(e) { - if (!this.path) return; - this.path.remove(); - this.addPathToProject(this.path); - this.path = null; - this.fireEvent('canvasModified'); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Eraser = class extends Wick.Tool { - /** - * - */ - constructor() { - super(); - this.name = 'eraser'; - this.path = null; - this.cursorSize = null; - this.cachedCursor = null; - } - - get doubleClickEnabled() { - return false; - } - /** - * - * @type {string} - */ - - - get cursor() { - return this.cachedCursor || 'crosshair'; - } - - get isDrawingTool() { - return true; - } - - onActivate(e) { - this.cursorSize = null; - } - - onDeactivate(e) { - if (this.path) { - this.path.remove(); - this.path = null; - } - } - - onMouseMove(e) { - // Don't render cursor after every mouse move, cache and only render when size changes - var cursorNeedsRegen = this.getSetting('eraserSize') !== this.cursorSize; - - if (cursorNeedsRegen) { - this.cachedCursor = this.createDynamicCursor('#ffffff', this.getSetting('eraserSize') + 1); - this.cursorSize = this.getSetting('eraserSize'); - this.setCursor(this.cachedCursor); - } - } - - onMouseDown(e) { - if (!this.path) { - this.path = new this.paper.Path({ - strokeColor: 'white', - strokeCap: 'round', - strokeWidth: (this.getSetting('eraserSize') + 1) / this.paper.view.zoom - }); - } // Add two points so we always at least have a dot. - - - this.path.add(e.point); - this.path.add(e.point); - } - - onMouseDrag(e) { - this.path.add(e.point); - this.path.smooth(); - } - - onMouseUp(e) { - if (!this.path) return; - var potraceResolution = 0.7; - this.path.potrace({ - done: tracedPath => { - this.path.remove(); - this.paper.project.activeLayer.erase(tracedPath, {}); - this.path = null; - this.fireEvent('canvasModified'); - }, - resolution: potraceResolution * this.paper.view.zoom - }); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Eyedropper = class extends Wick.Tool { - /** - * - */ - constructor() { - super(); - this.name = 'eyedropper'; - this.canvasCtx = null; - this.hoverColor = '#ffffff'; - this.colorPreview = null; - } - - get doubleClickEnabled() { - return false; - } - /** - * - * @type {string} - */ - - - get cursor() { - return 'url(cursors/eyedropper.png) 32 32, auto'; - } - - onActivate(e) {} - - onDeactivate(e) { - this._destroyColorPreview(); - } - - onMouseMove(e) { - super.onMouseMove(e); - var canvas = this.paper.view._element; - var ctx = canvas.getContext('2d'); - var pointPx = this.paper.view.projectToView(e.point); - pointPx.x = Math.round(pointPx.x) * window.devicePixelRatio; - pointPx.y = Math.round(pointPx.y) * window.devicePixelRatio; - var colorData = ctx.getImageData(pointPx.x, pointPx.y, 1, 1).data; - var colorCSS = 'rgb(' + colorData[0] + ',' + colorData[1] + ',' + colorData[2] + ')'; - this.hoverColor = colorCSS; - - this._createColorPreview(e.point); - } - - onMouseDown(e) { - this._destroyColorPreview(); - - if (!e.modifiers.shift) { - this.project.toolSettings.setSetting('fillColor', this.hoverColor); - } else { - this.project.toolSettings.setSetting('strokeColor', this.hoverColor); - } - - this.fireEvent('canvasModified'); - } - - onMouseDrag(e) {} - - onMouseUp(e) { - this._createColorPreview(e.point); - } - - _createColorPreview(point) { - this._destroyColorPreview(); - - var offset = 10 / this.paper.view.zoom; - var center = point.add(new paper.Point(offset + 0.5, offset + 0.5)); - var radius = 10 / paper.view.zoom; - var size = new paper.Size(radius, radius); - this.colorPreview = new this.paper.Group(); - this.colorPreview.addChild(new this.paper.Path.Rectangle({ - center: center, - size: size, - strokeColor: '#000000', - fillColor: this.hoverColor, - strokeWidth: 1.0 / this.paper.view.zoom - })); - } - - _destroyColorPreview() { - if (this.colorPreview) { - this.colorPreview.remove(); - this.colorPreview = null; - } - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.FillBucket = class extends Wick.Tool { - /** - * - */ - constructor() { - super(); - this.name = 'fillbucket'; - } - - get doubleClickEnabled() { - return false; - } - /** - * - * @type {string} - */ - - - get cursor() { - return 'url(cursors/fillbucket.png) 32 32, auto'; - } - - get isDrawingTool() { - return true; - } - - onActivate(e) {} - - onDeactivate(e) {} - - onMouseDown(e) { - setTimeout(() => { - this.setCursor('wait'); - }, 0); - setTimeout(() => { - this.paper.hole({ - point: e.point, - bgColor: new paper.Color(this.project.backgroundColor), - layers: this.project.activeFrames.map(frame => { - return frame.view.pathsLayer; - }), - onFinish: path => { - this.setCursor('default'); - - if (path) { - path.fillColor = this.getSetting('fillColor'); - path.name = null; - this.addPathToProject(); - - if (e.item) { - path.insertAbove(e.item); - } else { - this.paper.project.activeLayer.addChild(path); - this.paper.OrderingUtils.sendToBack([path]); - } - - this.fireEvent('canvasModified'); - } - }, - onError: message => { - this.setCursor('default'); - this.fireEvent('error', { - message: message - }); - } - }); - }, 50); - } - - onMouseDrag(e) {} - - onMouseUp(e) {} - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Interact = class extends Wick.Tool { - /** - * Creates an Interact tool. - */ - constructor() { - super(); - this.name = 'interact'; - this._keysDown = []; - this._lastKeyDown = null; - this._mouseIsDown = false; - this._mousePosition = new paper.Point(0, 0); - } - - onActivate(e) {} - - onDeactivate(e) {} - - onMouseMove(e) { - this._mousePosition = e.point; - } - - onMouseDrag(e) { - this._mousePosition = e.point; - } - - onMouseDown(e) { - this._mouseIsDown = true; - } - - onMouseUp(e) { - this._mouseIsDown = false; - } - - onKeyDown(e) { - this._lastKeyDown = e.key; - - if (this._keysDown.indexOf(e.key) === -1) { - this._keysDown.push(e.key); - } - } - - onKeyUp(e) { - this._keysDown = this._keysDown.filter(key => { - return key !== e.key; - }); - } - - get mousePosition() { - return this._mousePosition; - } - - get mouseIsDown() { - return this._mouseIsDown; - } - - get keysDown() { - return this._keysDown; - } - - get lastKeyDown() { - return this._lastKeyDown; - } - - get mouseTargets() { - var targets = []; - var hitResult = this.paper.project.hitTest(this.mousePosition, { - fill: true, - stroke: true, - curves: true, - segments: true - }); // Check for clips under the mouse. - - if (hitResult) { - var uuid = hitResult.item.data.wickUUID; - - if (uuid) { - var path = Wick.ObjectCache.getObjectByUUID(uuid); - - if (!path.parentClip.isRoot) { - var clip = path.parentClip; - var lineageWithoutRoot = clip.lineage; - lineageWithoutRoot.pop(); - targets = lineageWithoutRoot; - } - } - } else if (this.project.activeFrame) { - // No clips are under the mouse, so the frame is under the mouse. - targets = [this.project.activeFrame]; - } else { - targets = []; - } // Update cursor - - - if (this.project.hideCursor) { - this.setCursor('none'); - } else { - var clip = targets.find(target => { - return target instanceof Wick.Button; - }); - - if (clip) { - this.setCursor(clip.cursor); - } else { - this.setCursor('default'); - } - } - - return targets; - } - - get doubleClickEnabled() { - return false; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Line = class extends Wick.Tool { - /** - * - */ - constructor() { - super(); - this.name = 'line'; - this.path = new this.paper.Path({ - insert: false - }); - this.startPoint; - this.endPoint; - } - - get doubleClickEnabled() { - return false; - } - /** - * - * @type {string} - */ - - - get cursor() { - return 'crosshair'; - } - - get isDrawingTool() { - return true; - } - - onActivate(e) { - this.path.remove(); - } - - onDeactivate(e) { - this.path.remove(); - } - - onMouseDown(e) { - this.startPoint = e.point; - } - - onMouseDrag(e) { - this.path.remove(); - this.endPoint = e.point; - this.path = new paper.Path.Line(this.startPoint, this.endPoint); - this.path.strokeCap = 'round'; - this.path.strokeColor = this.getSetting('strokeColor'); - this.path.strokeWidth = this.getSetting('strokeWidth'); - } - - onMouseUp(e) { - this.path.remove(); - this.addPathToProject(this.path); - this.fireEvent('canvasModified'); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.None = class extends Wick.Tool { - /** - * Creates a none tool. - */ - constructor() { - super(); - this.name = 'none'; - } - /** - * The "no-sign" cursor. - * @type {string} - */ - - - get cursor() { - return 'not-allowed'; - } - - onActivate(e) {} - - onDeactivate(e) {} - - onMouseDown(e) { - var message = ''; - - if (!this.project.activeFrame) { - message = 'CLICK_NOT_ALLOWED_NO_FRAME'; - } else if (this.project.activeLayer.locked) { - message = 'CLICK_NOT_ALLOWED_LAYER_LOCKED'; - } else if (this.project.activeLayer.hidden) { - message = 'CLICK_NOT_ALLOWED_LAYER_HIDDEN'; - } else { - return; - } - - this.fireEvent('error', { - message: message - }); - } - - onMouseDrag(e) {} - - onMouseUp(e) {} - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Pan = class extends Wick.Tool { - /** - * - */ - constructor() { - super(); - this.name = 'pan'; - } - - get doubleClickEnabled() { - return false; - } - /** - * - * @type {string} - */ - - - get cursor() { - return 'move'; - } - - onActivate(e) {} - - onDeactivate(e) {} - - onMouseDown(e) {} - - onMouseDrag(e) { - var d = e.downPoint.subtract(e.point); - this.paper.view.center = this.paper.view.center.add(d); - } - - onMouseUp(e) { - this.fireEvent('canvasViewTransformed'); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.PathCursor = class extends Wick.Tool { - constructor() { - super(); - this.name = 'pathcursor'; - this.SELECTION_TOLERANCE = 3; - this.CURSOR_DEFAULT = 'cursors/default.png'; - this.CURSOR_SEGMENT = 'cursors/segment.png'; - this.CURSOR_CURVE = 'cursors/curve.png'; - this.HOVER_PREVIEW_SEGMENT_STROKE_COLOR = 'rgba(100,150,255,1.0)'; - this.HOVER_PREVIEW_SEGMENT_STROKE_WIDTH = 1.5; - this.HOVER_PREVIEW_SEGMENT_FILL_COLOR = '#ffffff'; - this.HOVER_PREVIEW_SEGMENT_RADIUS = 5; - this.HOVER_PREVIEW_CURVE_STROKE_WIDTH = 2; - this.HOVER_PREVIEW_CURVE_STROKE_COLOR = this.HOVER_PREVIEW_SEGMENT_STROKE_COLOR; - this.hitResult = new this.paper.HitResult(); - this.draggingCurve = new this.paper.Curve(); - this.draggingSegment = new this.paper.Segment(); - this.hoverPreview = new this.paper.Item({ - insert: false - }); - this.currentCursorIcon = ''; - } - - get doubleClickEnabled() { - return false; - } - - get cursor() { - return 'url("' + this.currentCursorIcon + '") 32 32, auto'; - } - - onActivate(e) {} - - onDeactivate(e) {} - - onMouseMove(e) { - super.onMouseMove(e); // Remove the hover preview, a new one will be generated if needed - - this.hoverPreview.remove(); // Find the thing that is currently under the cursor. - - this.hitResult = this._updateHitResult(e); // Update the image being used for the cursor - - this._setCursor(this._getCursor()); // Regen hover preview - - - if (this.hitResult.type === 'segment' && !this.hitResult.item.data.isSelectionBoxGUI) { - // Hovering over a segment, draw a circle where the segment is - this.hoverPreview = new this.paper.Path.Circle(this.hitResult.segment.point, this.HOVER_PREVIEW_SEGMENT_RADIUS / this.paper.view.zoom); - this.hoverPreview.strokeColor = this.HOVER_PREVIEW_SEGMENT_STROKE_COLOR; - this.hoverPreview.strokeWidth = this.HOVER_PREVIEW_SEGMENT_STROKE_WIDTH; - this.hoverPreview.fillColor = this.HOVER_PREVIEW_SEGMENT_FILL_COLOR; - } else if (this.hitResult.type === 'curve' && !this.hitResult.item.data.isSelectionBoxGUI) { - // Hovering over a curve, render a copy of the curve that can be bent - this.hoverPreview = new this.paper.Path(); - this.hoverPreview.strokeWidth = this.HOVER_PREVIEW_CURVE_STROKE_WIDTH; - this.hoverPreview.strokeColor = this.HOVER_PREVIEW_CURVE_STROKE_COLOR; - this.hoverPreview.add(new this.paper.Point(this.hitResult.location.curve.point1)); - this.hoverPreview.add(new this.paper.Point(this.hitResult.location.curve.point2)); - this.hoverPreview.segments[0].handleOut = this.hitResult.location.curve.handle1; - this.hoverPreview.segments[1].handleIn = this.hitResult.location.curve.handle2; - } - - this.hoverPreview.data.wickType = 'gui'; - } - - onMouseDown(e) { - super.onMouseDown(e); - if (!e.modifiers) e.modifiers = {}; - this.hitResult = this._updateHitResult(e); - - if (this.hitResult.item && this.hitResult.type === 'curve') { - // Clicked a curve, start dragging it - this.draggingCurve = this.hitResult.location.curve; - } else if (this.hitResult.item && this.hitResult.type === 'segment') {} - } - - onDoubleClick(e) {} - - onMouseDrag(e) { - if (!e.modifiers) e.modifiers = {}; - - if (this.hitResult.item && this.hitResult.type === 'segment') { - // We're dragging an individual point, so move the point. - this.hitResult.segment.point = this.hitResult.segment.point.add(e.delta); - this.hoverPreview.position = this.hitResult.segment.point; - } else if (this.hitResult.item && this.hitResult.type === 'curve') { - // We're dragging a curve, so bend the curve. - var segment1 = this.draggingCurve.segment1; - var segment2 = this.draggingCurve.segment2; - var handleIn = segment1.handleOut; - var handleOut = segment2.handleIn; - - if (handleIn.x === 0 && handleIn.y === 0) { - handleIn.x = (segment2.point.x - segment1.point.x) / 4; - handleIn.y = (segment2.point.y - segment1.point.y) / 4; - } - - if (handleOut.x === 0 && handleOut.y === 0) { - handleOut.x = (segment1.point.x - segment2.point.x) / 4; - handleOut.y = (segment1.point.y - segment2.point.y) / 4; - } - - handleIn.x += e.delta.x; - handleIn.y += e.delta.y; - handleOut.x += e.delta.x; - handleOut.y += e.delta.y; // Update the hover preview to match the curve we just changed - - this.hoverPreview.segments[0].handleOut = this.draggingCurve.handle1; - this.hoverPreview.segments[1].handleIn = this.draggingCurve.handle2; - } - } - - onMouseUp(e) { - if (this.hitResult.type === 'segment' || this.hitResult.type === 'curve') { - this.fireEvent('canvasModified'); - } - } - - _updateHitResult(e) { - var newHitResult = this.paper.project.hitTest(e.point, { - fill: true, - stroke: true, - curves: true, - segments: true, - tolerance: this.SELECTION_TOLERANCE, - match: result => { - return result.item !== this.hoverPreview && !result.item.data.isBorder; - } - }); - if (!newHitResult) newHitResult = new this.paper.HitResult(); - - if (newHitResult.item && !newHitResult.item.data.isSelectionBoxGUI) { - // You can't select children of compound paths, you can only select the whole thing. - if (newHitResult.item.parent.className === 'CompoundPath') { - newHitResult.item = newHitResult.item.parent; - } // You can't select individual children in a group, you can only select the whole thing. - - - if (newHitResult.item.parent.parent) { - newHitResult.type = 'fill'; - - while (newHitResult.item.parent.parent) { - newHitResult.item = newHitResult.item.parent; - } - } // this.paper.js has two names for strokes+curves, we don't need that extra info - - - if (newHitResult.type === 'stroke') { - newHitResult.type = 'curve'; - } // Mousing over rasters acts the same as mousing over fills. - - - if (newHitResult.type === 'pixel') { - newHitResult.type = 'fill'; - } - } - - return newHitResult; - } - - _getCursor() { - if (!this.hitResult.item) { - return this.CURSOR_DEFAULT; - } else if (this.hitResult.type === 'curve') { - return this.CURSOR_CURVE; - } else if (this.hitResult.type === 'segment') { - return this.CURSOR_SEGMENT; - } - } - - _setCursor(cursor) { - this.currentCursorIcon = cursor; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Pencil = class extends Wick.Tool { - static get MIN_ADD_POINT_MOVEMENT() { - return 2; - } - /** - * Creates a pencil tool. - */ - - - constructor() { - super(); - this.name = 'pencil'; - this.path = null; - this._movement = new paper.Point(); - } - - get doubleClickEnabled() { - return false; - } - /** - * The pencil cursor. - * @type {string} - */ - - - get cursor() { - return 'url(cursors/pencil.png) 32 32, auto'; - } - - get isDrawingTool() { - return true; - } - - onActivate(e) {} - - onDeactivate(e) {} - - onMouseDown(e) { - this._movement = new paper.Point(); - - if (!this.path) { - this.path = new this.paper.Path({ - strokeColor: this.getSetting('strokeColor'), - strokeWidth: this.getSetting('strokeWidth'), - strokeCap: 'round' - }); - } - - this.path.add(e.point); - } - - onMouseDrag(e) { - if (!this.path) return; - this._movement = this._movement.add(e.delta); - - if (this._movement.length > Wick.Tools.Pencil.MIN_ADD_POINT_MOVEMENT / this.paper.view.zoom) { - this._movement = new paper.Point(); - this.path.add(e.point); - this.path.smooth(); - } - } - - onMouseUp(e) { - if (!this.path) return; - this.path.add(e.point); - this.path.simplify(); - this.path.remove(); - this.addPathToProject(this.path); - this.path = null; - this.fireEvent('canvasModified'); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Rectangle = class extends Wick.Tool { - /** - * - */ - constructor() { - super(); - this.name = 'rectangle'; - this.path = null; - this.topLeft = null; - this.bottomRight = null; - } - - get doubleClickEnabled() { - return false; - } - /** - * - * @type {string} - */ - - - get cursor() { - return 'crosshair'; - } - - get isDrawingTool() { - return true; - } - - onActivate(e) {} - - onDeactivate(e) { - if (this.path) { - this.path.remove(); - this.path = null; - } - } - - onMouseDown(e) { - this.topLeft = e.point; - this.bottomRight = e.point; - } - - onMouseDrag(e) { - if (this.path) this.path.remove(); - this.bottomRight = e.point; // Lock width and height if shift is held down - - if (e.modifiers.shift) { - var d = this.bottomRight.subtract(this.topLeft); - var max = Math.max(Math.abs(d.x), Math.abs(d.y)); - this.bottomRight.x = this.topLeft.x + max * (d.x < 0 ? -1 : 1); - this.bottomRight.y = this.topLeft.y + max * (d.y < 0 ? -1 : 1); - } - - var bounds = new this.paper.Rectangle(new paper.Point(this.topLeft.x, this.topLeft.y), new paper.Point(this.bottomRight.x, this.bottomRight.y)); - - if (this.getSetting('cornerRadius') !== 0) { - this.path = new this.paper.Path.Rectangle(bounds, this.getSetting('cornerRadius')); - } else { - this.path = new this.paper.Path.Rectangle(bounds); - } - - this.path.fillColor = this.getSetting('fillColor'); - this.path.strokeColor = this.getSetting('strokeColor'); - this.path.strokeWidth = this.getSetting('strokeWidth'); - this.path.strokeCap = 'round'; - } - - onMouseUp(e) { - if (!this.path) return; - this.path.remove(); - this.addPathToProject(this.path); - this.path = null; - this.fireEvent('canvasModified'); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Text = class extends Wick.Tool { - /** - * - */ - constructor() { - super(); - this.name = 'text'; - this.hoveredOverText = null; - this.editingText = null; - } - - get doubleClickEnabled() { - return false; - } - /** - * - * @type {string} - */ - - - get cursor() { - return 'text'; - } - - get isDrawingTool() { - return true; - } - - onActivate(e) {} - - onDeactivate(e) { - if (this.editingText) { - this.finishEditingText(); - } - - this.hoveredOverText = null; - } - - onMouseMove(e) { - super.onMouseMove(e); - - if (e.item && e.item.className === 'PointText' && !e.item.parent.parent) { - this.hoveredOverText = e.item; - this.setCursor('text'); - } else { - this.hoveredOverText = null; - this.setCursor('url(cursors/text.png) 32 32, auto'); - } - } - - onMouseDown(e) { - if (this.editingText) { - this.finishEditingText(); - } else if (this.hoveredOverText) { - this.editingText = this.hoveredOverText; - e.item.edit(this.project.view.paper); - } else { - var text = new this.paper.PointText(e.point); - text.justification = 'left'; - text.fillColor = 'black'; - text.content = 'Text'; - text.fontSize = 24; - var wickText = new Wick.Path({ - json: text.exportJSON({ - asString: false - }) - }); - this.project.activeFrame.addPath(wickText); - this.project.view.render(); - this.editingText = wickText.view.item; - this.editingText.edit(this.project.view.paper); //this.fireEvent('canvasModified'); - } - } - - onMouseDrag(e) {} - - onMouseUp(e) {} - /** - * Stop editing the current text and apply changes. - */ - - - finishEditingText() { - if (!this.editingText) return; - this.editingText.finishEditing(); - - if (this.editingText.content === '') { - this.editingText.remove(); - } - - this.editingText = null; - this.fireEvent('canvasModified'); - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -Wick.Tools.Zoom = class extends Wick.Tool { - /** - * - */ - constructor() { - super(); - this.name = 'zoom'; - this.ZOOM_IN_AMOUNT = 1.25; - this.ZOOM_OUT_AMOUNT = 0.8; - this.zoomBox = null; - } - - get doubleClickEnabled() { - return false; - } - /** - * - * @type {string} - */ - - - get cursor() { - return 'zoom-in'; - } - - onActivate(e) {} - - onDeactivate(e) { - this.deleteZoomBox(); - } - - onMouseDown(e) {} - - onMouseDrag(e) { - this.deleteZoomBox(); - this.createZoomBox(e); - } - - onMouseUp(e) { - if (this.zoomBox && this.zoomBoxIsValidSize()) { - var bounds = this.zoomBox.bounds; - this.paper.view.center = bounds.center; - this.paper.view.zoom = this.paper.view.bounds.height / bounds.height; - } else { - var zoomAmount = e.modifiers.alt ? this.ZOOM_OUT_AMOUNT : this.ZOOM_IN_AMOUNT; - this.paper.view.scale(zoomAmount, e.point); - } - - this.deleteZoomBox(); - this.fireEvent('canvasViewTransformed'); - } - - createZoomBox(e) { - var bounds = new this.paper.Rectangle(e.downPoint, e.point); - bounds.x += 0.5; - bounds.y += 0.5; - this.zoomBox = new this.paper.Path.Rectangle(bounds); - this.zoomBox.strokeColor = 'black'; - this.zoomBox.strokeWidth = 1.0 / this.paper.view.zoom; - } - - deleteZoomBox() { - if (this.zoomBox) { - this.zoomBox.remove(); - this.zoomBox = null; - } - } - - zoomBoxIsValidSize() { - return this.zoomBox.bounds.width > 5 && this.zoomBox.bounds.height > 5; - } - -}; -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Paper.js-drawing-tools. - * - * Paper.js-drawing-tools is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Paper.js-drawing-tools is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Paper.js-drawing-tools. If not, see . - */ - -/* - paper-erase.js - Adds erase() to the paper Layer class which erases paths in that layer using - the shape of a given path. Use this to make a vector eraser! - - by zrispo (github.com/zrispo) (zach@wickeditor.com) - */ -(function () { - // Splits a CompoundPath with multiple CW children into individual pieces - function splitCompoundPath(compoundPath) { - // Create lists of 'holes' (CCW children) and 'parts' (CW children) - var holes = []; - var parts = []; - compoundPath.children.forEach(function (child) { - if (!child.clockwise) { - holes.push(child); - } else { - var part = child.clone({ - insert: false - }); - part.fillColor = compoundPath.fillColor; - part.insertAbove(compoundPath); - parts.push(part); - } - }); // Find hole ownership for each 'part' - - parts.forEach(function (part) { - var cmp; - holes.forEach(function (hole) { - if (part.bounds.contains(hole.bounds)) { - if (!cmp) { - cmp = new paper.CompoundPath({ - insert: false - }); - cmp.insertAbove(part); - cmp.addChild(part.clone({ - insert: false - })); - } - - cmp.addChild(hole); - } - - if (cmp) { - cmp.fillColor = compoundPath.fillColor; - cmp.insertAbove(part); - part.remove(); - } - }); - }); - compoundPath.remove(); - } - - function eraseFill(path, eraserPath) { - if (path.closePath) path.closePath(); - var res = path.subtract(eraserPath, { - insert: false, - trace: true - }); - res.fillColor = path.fillColor; - - if (res.children) { - res.insertAbove(path); - res.data = {}; - path.remove(); - splitCompoundPath(res); - } else { - if (res.segments.length > 0) { - res.data = {}; - res.insertAbove(path); - } - - path.remove(); - } - - path.remove(); - } - - function eraseStroke(path, eraserPath) { - var res = path.subtract(eraserPath, { - insert: false, - trace: false - }); - - if (res.children) { - // Since the path is only strokes, it's trivial to split it into individual paths - var children = []; - res.children.forEach(function (child) { - child.data = {}; - children.push(child); - child.name = null; - }); - children.forEach(function (child) { - child.insertAbove(path); - }); - res.remove(); - } else { - res.remove(); - if (res.segments.length > 0) res.insertAbove(path); - } - - path.remove(); - } - - function splitPath(path) { - var fill = path.clone({ - insert: false - }); - fill.name = null; - fill.strokeColor = null; - fill.strokeWidth = 1; - var stroke = path.clone({ - insert: false - }); - stroke.name = null; - stroke.fillColor = null; - fill.insertAbove(path); - stroke.insertAbove(fill); - path.remove(); - return { - fill: fill, - stroke: stroke - }; - } - - function eraseWithPath(eraserPath) { - var touchingPaths = []; - this.children.forEach(function (child) { - if (eraserPath.bounds.intersects(child.bounds)) { - touchingPaths.push(child); - } - }); - touchingPaths.filter(path => { - return path instanceof paper.Path || path instanceof paper.CompoundPath; - }).forEach(path => { - if (path.strokeColor && path.fillColor) { - var res = splitPath(path); - eraseFill(res.fill, eraserPath); - eraseStroke(res.stroke, eraserPath); - } else if (path.fillColor) { - eraseFill(path, eraserPath); - } else if (path.strokeColor) { - eraseStroke(path, eraserPath); - } - }); - } - - paper.Layer.inject({ - erase: eraseWithPath - }); -})(); -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Paper.js-drawing-tools. - * - * Paper.js-drawing-tools is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Paper.js-drawing-tools is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Paper.js-drawing-tools. If not, see . - */ - -/* - paper-hole.js - Adds hole() to the paper Layer class which finds the shape of the hole - at a certain point. Use this to make a vector fill bucket! - - This version uses a flood fill + potrace method of filling holes. - - Adapted from the FillBucket tool from old Wick - - by zrispo (github.com/zrispo) (zach@wickeditor.com) - */ -(function () { - var VERBOSE = false; - var PREVIEW_IMAGE = false; - var N_RASTER_CLONE = 1; - var RASTER_BASE_RESOLUTION = 3; - var FILL_TOLERANCE = 0; - var EXPAND_AMT = 0.85; - var GAP_FILL_MARGIN = 1; - var onError; - var onFinish; - var layers; - var floodFillX; - var floodFillY; - var bgColor; - - function previewImage(image) { - var win = window.open('', 'Title', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=' + image.width + ', height=' + image.height + ', top=100, left=100'); - win.document.body.innerHTML = '
'; - } - - function rasterizePaths(callback) { - var layerGroup = new paper.Group({ - insert: false - }); - layers.reverse().forEach(layer => { - layer.children.forEach(function (child) { - if (child._class !== 'Path' && child._class !== 'CompoundPath') return; - - for (var i = 0; i < N_RASTER_CLONE; i++) { - var clone = child.clone({ - insert: false - }); //experiment: bump out all strokes a bit by expanding their stroke widths - - if (!clone.strokeColor && clone.fillColor) { - clone.strokeColor = clone.fillColor; - clone.strokeWidth = GAP_FILL_MARGIN / RASTER_BASE_RESOLUTION; - } else if (clone.strokeWidth) { - clone.strokeWidth += GAP_FILL_MARGIN / RASTER_BASE_RESOLUTION; - } - - layerGroup.addChild(clone); - } - }); - }); - - if (layerGroup.children.length === 0) { - onError('NO_PATHS'); - return; - } - - var rasterResolution = paper.view.resolution * RASTER_BASE_RESOLUTION / window.devicePixelRatio; - var layerPathsRaster = layerGroup.rasterize(rasterResolution, { - insert: false - }); - var rasterCanvas = layerPathsRaster.canvas; - var rasterCtx = rasterCanvas.getContext('2d'); - var layerPathsImageData = rasterCtx.getImageData(0, 0, layerPathsRaster.width, layerPathsRaster.height); - var layerPathsImageDataRaw = layerPathsImageData.data; - - for (var i = 0; i < layerPathsImageDataRaw.length; i += 4) { - if (layerPathsImageDataRaw[i + 3] === 0) { - layerPathsImageDataRaw[i] = bgColor.red; - layerPathsImageDataRaw[i + 1] = bgColor.green; - layerPathsImageDataRaw[i + 2] = bgColor.blue; - layerPathsImageDataRaw[i + 3] = 255; - } - } - - rasterCtx.putImageData(layerPathsImageData, 0, 0); - layerPathsImageData = rasterCtx.getImageData(0, 0, layerPathsRaster.width, layerPathsRaster.height); - var rasterPosition = layerPathsRaster.bounds.topLeft; - var x = (floodFillX - rasterPosition.x) * RASTER_BASE_RESOLUTION; - var y = (floodFillY - rasterPosition.y) * RASTER_BASE_RESOLUTION; - x = Math.round(x); - y = Math.round(y); - var floodFillCanvas = document.createElement('canvas'); - floodFillCanvas.width = layerPathsRaster.canvas.width; - floodFillCanvas.height = layerPathsRaster.canvas.height; - - if (x < 0 || y < 0 || x >= floodFillCanvas.width || y >= floodFillCanvas.height) { - onError('OUT_OF_BOUNDS'); - return; - } - - var floodFillCtx = floodFillCanvas.getContext('2d'); - floodFillCtx.putImageData(layerPathsImageData, 0, 0); - floodFillCtx.fillStyle = "rgba(123,124,125,255)"; - floodFillCtx.fillFlood(x, y, FILL_TOLERANCE); - var floodFillImageData = floodFillCtx.getImageData(0, 0, floodFillCanvas.width, floodFillCanvas.height); - var imageDataRaw = floodFillImageData.data; - - for (var i = 0; i < imageDataRaw.length; i += 4) { - if (imageDataRaw[i] === 123 && imageDataRaw[i + 1] === 124 && imageDataRaw[i + 2] === 125) { - imageDataRaw[i] = 0; - imageDataRaw[i + 1] = 0; - imageDataRaw[i + 2] = 0; - imageDataRaw[i + 3] = 255; - } else { - imageDataRaw[i] = 255; - imageDataRaw[i + 1] = 255; - imageDataRaw[i + 2] = 255; - imageDataRaw[i + 3] = 0; - } - } - - floodFillCtx.putImageData(floodFillImageData, 0, 0); - var floodFillProcessedImage = new Image(); - - floodFillProcessedImage.onload = function () { - if (PREVIEW_IMAGE) previewImage(floodFillProcessedImage); - var svgString = potrace.fromImage(floodFillProcessedImage).toSVG(1); - var xmlString = svgString, - parser = new DOMParser(), - doc = parser.parseFromString(xmlString, "text/xml"); - var resultHolePath = paper.project.importSVG(doc, { - insert: true - }); - resultHolePath.remove(); - resultHolePath = resultHolePath.children[0]; - resultHolePath.scale(1 / RASTER_BASE_RESOLUTION, new paper.Point(0, 0)); - var rasterPosition = layerPathsRaster.bounds.topLeft; - resultHolePath.position.x += rasterPosition.x; - resultHolePath.position.y += rasterPosition.y; - resultHolePath.applyMatrix = true; - var holeIsLeaky = false; - var w = floodFillProcessedImage.width; - var h = floodFillProcessedImage.height; - - for (var x = 0; x < floodFillProcessedImage.width; x++) { - if (getPixelAt(x, 0, w, h, floodFillImageData.data).r === 0 && getPixelAt(x, 0, w, h, floodFillImageData.data).a === 255) { - holeIsLeaky = true; - onError('LEAKY_HOLE'); - return; - } - } - - expandHole(resultHolePath); - callback(resultHolePath); - }; - - floodFillProcessedImage.src = floodFillCanvas.toDataURL(); - } - - function expandHole(path) { - if (path instanceof paper.Group) { - path = path.children[0]; - } - - var children; - - if (path instanceof paper.Path) { - children = [path]; - } else if (path instanceof paper.CompoundPath) { - children = path.children; - } - - children.forEach(function (hole) { - var normals = []; - hole.closePath(); - hole.segments.forEach(function (segment) { - var a = segment.previous.point; - var b = segment.point; - var c = segment.next.point; - var ab = { - x: b.x - a.x, - y: b.y - a.y - }; - var cb = { - x: b.x - c.x, - y: b.y - c.y - }; - var d = { - x: ab.x - cb.x, - y: ab.y - cb.y - }; - d.h = Math.sqrt(d.x * d.x + d.y * d.y); - d.x /= d.h; - d.y /= d.h; - d = rotate_point(d.x, d.y, 0, 0, 90); - normals.push({ - x: d.x, - y: d.y - }); - }); - - for (var i = 0; i < hole.segments.length; i++) { - var segment = hole.segments[i]; - var normal = normals[i]; - segment.point.x += normal.x * EXPAND_AMT; - segment.point.y += normal.y * EXPAND_AMT; - } - }); - } // http://www.felixeve.co.uk/how-to-rotate-a-point-around-an-origin-with-javascript/ - - - function rotate_point(pointX, pointY, originX, originY, angle) { - angle = angle * Math.PI / 180.0; - return { - x: Math.cos(angle) * (pointX - originX) - Math.sin(angle) * (pointY - originY) + originX, - y: Math.sin(angle) * (pointX - originX) + Math.cos(angle) * (pointY - originY) + originY - }; - } - - function getPixelAt(x, y, width, height, imageData) { - if (x < 0 || y < 0 || x >= width || y >= height) return null; - var offset = (y * width + x) * 4; - return { - r: imageData[offset], - g: imageData[offset + 1], - b: imageData[offset + 2], - a: imageData[offset + 3] - }; - } - /* Add hole() method to paper */ - - - paper.PaperScope.inject({ - hole: function (args) { - if (!args) console.error('paper.hole: args is required'); - if (!args.point) console.error('paper.hole: args.point is required'); - if (!args.onFinish) console.error('paper.hole: args.onFinish is required'); - if (!args.onError) console.error('paper.hole: args.onError is required'); - if (!args.bgColor) console.error('paper.hole: args.bgColor is required'); - if (!args.layers) console.error('paper.hole: args.layers is required'); - onFinish = args.onFinish; - onError = args.onError; - layers = args.layers; - floodFillX = args.point.x; - floodFillY = args.point.y; - bgColor = args.bgColor; - rasterizePaths(onFinish); - } - }); -})(); -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -class PaperJSOrderingUtils { - /** - * Moves the selected items forwards. - */ - static moveForwards(items) { - PaperJSOrderingUtils._sortItemsByLayer(items).forEach(layerItems => { - PaperJSOrderingUtils._sortItemsByZIndex(layerItems).reverse().forEach(item => { - if (item.nextSibling && items.indexOf(item.nextSibling) === -1) { - item.insertAbove(item.nextSibling); - } - }); - }); - } - /** - * Moves the selected items backwards. - */ - - - static moveBackwards(items) { - PaperJSOrderingUtils._sortItemsByLayer(items).forEach(layerItems => { - PaperJSOrderingUtils._sortItemsByZIndex(layerItems).forEach(item => { - if (item.previousSibling && items.indexOf(item.previousSibling) === -1) { - item.insertBelow(item.previousSibling); - } - }); - }); - } - /** - * Brings the selected objects to the front. - */ - - - static bringToFront(items) { - PaperJSOrderingUtils._sortItemsByLayer(items).forEach(layerItems => { - PaperJSOrderingUtils._sortItemsByZIndex(layerItems).forEach(item => { - item.bringToFront(); - }); - }); - } - /** - * Sends the selected objects to the back. - */ - - - static sendToBack(items) { - PaperJSOrderingUtils._sortItemsByLayer(items).forEach(layerItems => { - PaperJSOrderingUtils._sortItemsByZIndex(layerItems).reverse().forEach(item => { - item.sendToBack(); - }); - }); - } - - static _sortItemsByLayer(items) { - var layerLists = {}; - items.forEach(item => { - // Create new list for the item's layer if it doesn't exist - var layerID = item.layer.id; - - if (!layerLists[layerID]) { - layerLists[layerID] = []; - } // Add this item to its corresponding layer list - - - layerLists[layerID].push(item); - }); // Convert id->array object to array of arrays - - var layerItemsArrays = []; - - for (var layerID in layerLists) { - layerItemsArrays.push(layerLists[layerID]); - } - - return layerItemsArrays; - } - - static _sortItemsByZIndex(items) { - return items.sort(function (a, b) { - return a.index - b.index; - }); - } - -} - -; -paper.PaperScope.inject({ - OrderingUtils: PaperJSOrderingUtils -}); -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Wick Engine. - * - * Wick Engine is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Wick Engine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Wick Engine. If not, see . - */ -class SelectionWidget { - /** - * Creates a SelectionWidget - */ - constructor(args) { - if (!args) args = {}; - if (!args.layer) args.layer = paper.project.activeLayer; - this._layer = args.layer; - this._item = new paper.Group({ - insert: false - }); - } - /** - * The item containing the widget GUI - */ - - - get item() { - return this._item; - } - /** - * The layer to add the widget GUI item to. - */ - - - get layer() { - return this._layer; - } - - set layer(layer) { - this._layer = layer; - } - /** - * The rotation of the selection box GUI. - */ - - - get boxRotation() { - return this._boxRotation; - } - - set boxRotation(boxRotation) { - this._boxRotation = boxRotation; - } - /** - * The items currently inside the selection widget - */ - - - get itemsInSelection() { - return this._itemsInSelection; - } - /** - * The point to rotate/scale the widget around. - */ - - - get pivot() { - return this._pivot; - } - - set pivot(pivot) { - this._pivot = pivot; - } - /** - * The position of the top left corner of the selection box. - */ - - - get position() { - return this._boundingBox.topLeft.rotate(this.rotation, this.pivot); - } - - set position(position) { - var d = position.subtract(this.position); - this.translateSelection(d); - } - /** - * The width of the selection. - */ - - - get width() { - return this._boundingBox.width; - } - - set width(width) { - var d = width / this.width; - this.scaleSelection(new paper.Point(d, 1.0)); - } - /** - * The height of the selection. - */ - - - get height() { - return this._boundingBox.height; - } - - set height(height) { - var d = height / this.height; - this.scaleSelection(new paper.Point(1.0, d)); - } - /** - * The rotation of the selection. - */ - - - get rotation() { - return this._boxRotation; - } - - set rotation(rotation) { - var d = rotation - this.rotation; - this.rotateSelection(d); - } - /** - * Flip the selected items horizontally. - */ - - - flipHorizontally() { - this.scaleSelection(new paper.Point(-1.0, 1.0)); - } - /** - * Flip the selected items vertically. - */ - - - flipVertically() { - this.scaleSelection(new paper.Point(1.0, -1.0)); - } - /** - * The bounding box of the widget. - */ - - - get boundingBox() { - return this._boundingBox; - } - /** - * The current transformation being done to the selection widget. - * @type {string} - */ - - - get currentTransformation() { - return this._currentTransformation; - } - - set currentTransformation(currentTransformation) { - if (['translate', 'scale', 'rotate'].indexOf(currentTransformation) === -1) { - console.error('Paper.SelectionWidget: Invalid transformation type: ' + currentTransformation); - currentTransformation = null; - } else { - this._currentTransformation = currentTransformation; - } - } - /** - * Build a new SelectionWidget GUI around some items. - * @param {number} boxRotation - the rotation of the selection GUI. Optional, defaults to 0 - * @param {paper.Item[]} items - the items to build the GUI around - * @param {paper.Point} pivot - the pivot point that the selection rotates around. Defaults to (0,0) - */ - - - build(args) { - if (!args) args = {}; - if (!args.boxRotation) args.boxRotation = 0; - if (!args.items) args.items = []; - if (!args.pivot) args.pivot = new paper.Point(); - this._itemsInSelection = args.items; - this._boxRotation = args.boxRotation; - this._pivot = args.pivot; - this._boundingBox = this._calculateBoundingBox(); - this.item.remove(); - this.item.removeChildren(); - - if (this._ghost) { - this._ghost.remove(); - } - - if (this._pivotPointHandle) { - this._pivotPointHandle.remove(); - } - - if (this._itemsInSelection.length > 0) { - this._center = this._calculateBoundingBoxOfItems(this._itemsInSelection).center; - - this._buildGUI(); - - this.layer.addChild(this.item); - } - } - /** - * - */ - - - startTransformation(item) { - this._ghost = this._buildGhost(); - - this._layer.addChild(this._ghost); - - if (item.data.handleType === 'rotation') { - this.currentTransformation = 'rotate'; - } else if (item.data.handleType === 'scale') { - this.currentTransformation = 'scale'; - } else { - this.currentTransformation = 'translate'; - } - - this._ghost.data.initialPosition = this._ghost.position; - this._ghost.data.scale = new paper.Point(1, 1); - } - /** - * - */ - - - updateTransformation(item, e) { - if (this.currentTransformation === 'translate') { - this._ghost.position = this._ghost.position.add(e.delta); - } else if (this.currentTransformation === 'scale') { - var lastPoint = e.point.subtract(e.delta); - var currentPoint = e.point; - lastPoint = lastPoint.rotate(-this.boxRotation, this.pivot); - currentPoint = currentPoint.rotate(-this.boxRotation, this.pivot); - var pivotToLastPointVector = lastPoint.subtract(this.pivot); - var pivotToCurrentPointVector = currentPoint.subtract(this.pivot); - var scaleAmt = pivotToCurrentPointVector.divide(pivotToLastPointVector); // Lock scaling in a direction if the side handles are being dragged. - - if (item.data.handleEdge === 'topCenter' || item.data.handleEdge === 'bottomCenter') { - scaleAmt.x = 1.0; - } - - if (item.data.handleEdge === 'leftCenter' || item.data.handleEdge === 'rightCenter') { - scaleAmt.y = 1.0; - } // Holding shift locks aspect ratio - - - if (e.modifiers.shift) { - scaleAmt.y = scaleAmt.x; - } - - this._ghost.data.scale = this._ghost.data.scale.multiply(scaleAmt); - this._ghost.matrix = new paper.Matrix(); - - this._ghost.rotate(-this.boxRotation); - - this._ghost.scale(this._ghost.data.scale.x, this._ghost.data.scale.y, this.pivot); - - this._ghost.rotate(this.boxRotation); - } else if (this.currentTransformation === 'rotate') { - var lastPoint = e.point.subtract(e.delta); - var currentPoint = e.point; - var pivotToLastPointVector = lastPoint.subtract(this.pivot); - var pivotToCurrentPointVector = currentPoint.subtract(this.pivot); - var pivotToLastPointAngle = pivotToLastPointVector.angle; - var pivotToCurrentPointAngle = pivotToCurrentPointVector.angle; - var rotation = pivotToCurrentPointAngle - pivotToLastPointAngle; - - this._ghost.rotate(rotation, this.pivot); - - this.boxRotation += rotation; - } - } - /** - * - */ - - - finishTransformation(item) { - if (!this._currentTransformation) return; - - this._ghost.remove(); - - if (this.currentTransformation === 'translate') { - var d = this._ghost.position.subtract(this._ghost.data.initialPosition); - - this.translateSelection(d); - } else if (this.currentTransformation === 'scale') { - this.scaleSelection(this._ghost.data.scale); - } else if (this.currentTransformation === 'rotate') { - this.rotateSelection(this._ghost.rotation); - } - - this._currentTransformation = null; - } - /** - * - */ - - - translateSelection(delta) { - this._itemsInSelection.forEach(item => { - item.position = item.position.add(delta); - }); - - this.pivot = this.pivot.add(delta); - } - /** - * - */ - - - scaleSelection(scale) { - this._itemsInSelection.forEach(item => { - item.rotate(-this.boxRotation, this.pivot); - item.scale(scale, this.pivot); - item.rotate(this.boxRotation, this.pivot); - }); - } - /** - * - */ - - - rotateSelection(angle) { - this._itemsInSelection.forEach(item => { - item.rotate(angle, this.pivot); - }); - } - - _buildGUI() { - this.item.addChild(this._buildBorder()); - - if (this._itemsInSelection.length > 1) { - this.item.addChildren(this._buildItemOutlines()); - } - - this.item.addChild(this._buildRotationHotspot('topLeft')); - this.item.addChild(this._buildRotationHotspot('topRight')); - this.item.addChild(this._buildRotationHotspot('bottomLeft')); - this.item.addChild(this._buildRotationHotspot('bottomRight')); - this.item.addChild(this._buildScalingHandle('topLeft')); - this.item.addChild(this._buildScalingHandle('topRight')); - this.item.addChild(this._buildScalingHandle('bottomLeft')); - this.item.addChild(this._buildScalingHandle('bottomRight')); - this.item.addChild(this._buildScalingHandle('topCenter')); - this.item.addChild(this._buildScalingHandle('bottomCenter')); - this.item.addChild(this._buildScalingHandle('leftCenter')); - this.item.addChild(this._buildScalingHandle('rightCenter')); - this._pivotPointHandle = this._buildPivotPointHandle(); - this.layer.addChild(this._pivotPointHandle); - this.item.rotate(this.boxRotation, this._center); - this.item.children.forEach(child => { - child.data.isSelectionBoxGUI = true; - }); - } - - _buildBorder() { - var border = new paper.Path.Rectangle({ - name: 'border', - from: this.boundingBox.topLeft, - to: this.boundingBox.bottomRight, - strokeWidth: SelectionWidget.BOX_STROKE_WIDTH, - strokeColor: SelectionWidget.BOX_STROKE_COLOR, - insert: false - }); - border.data.isBorder = true; - return border; - } - - _buildItemOutlines() { - return this._itemsInSelection.map(item => { - var clone = item.clone({ - insert: false - }); - clone.rotate(-this.boxRotation, this._center); - var bounds = clone.bounds; - var border = new paper.Path.Rectangle({ - from: bounds.topLeft, - to: bounds.bottomRight, - strokeWidth: SelectionWidget.BOX_STROKE_WIDTH, - strokeColor: SelectionWidget.BOX_STROKE_COLOR - }); //border.rotate(-this.boxRotation, this._center); - - border.remove(); - return border; - }); - } - - _buildScalingHandle(edge) { - var handle = this._buildHandle({ - name: edge, - type: 'scale', - center: this.boundingBox[edge], - fillColor: SelectionWidget.HANDLE_FILL_COLOR, - strokeColor: SelectionWidget.HANDLE_STROKE_COLOR - }); - - return handle; - } - - _buildPivotPointHandle() { - var handle = this._buildHandle({ - name: 'pivot', - type: 'pivot', - center: this.pivot, - fillColor: SelectionWidget.PIVOT_FILL_COLOR, - strokeColor: SelectionWidget.PIVOT_STROKE_COLOR - }); - - handle.locked = true; - return handle; - } - - _buildHandle(args) { - if (!args) console.error('_createHandle: args is required'); - if (!args.name) console.error('_createHandle: args.name is required'); - if (!args.type) console.error('_createHandle: args.type is required'); - if (!args.center) console.error('_createHandle: args.center is required'); - if (!args.fillColor) console.error('_createHandle: args.fillColor is required'); - if (!args.strokeColor) console.error('_createHandle: args.strokeColor is required'); - var circle = new paper.Path.Circle({ - center: args.center, - radius: SelectionWidget.HANDLE_RADIUS / paper.view.zoom, - strokeWidth: SelectionWidget.HANDLE_STROKE_WIDTH / paper.view.zoom, - strokeColor: args.strokeColor, - fillColor: args.fillColor, - insert: false - }); - circle.applyMatrix = false; - circle.data.isSelectionBoxGUI = true; - circle.data.handleType = args.type; - circle.data.handleEdge = args.name; - return circle; - } - - _buildRotationHotspot(cornerName) { - // Build the not-yet-rotated hotspot, which starts out like this: - // | - // +---+ - // | | - // ---+--+ |--- - // | | - // +------+ - // | - var r = SelectionWidget.ROTATION_HOTSPOT_RADIUS / paper.view.zoom; - var hotspot = new paper.Path([new paper.Point(0, 0), new paper.Point(0, r), new paper.Point(r, r), new paper.Point(r, -r), new paper.Point(-r, -r), new paper.Point(-r, 0)]); - hotspot.fillColor = SelectionWidget.ROTATION_HOTSPOT_FILLCOLOR; - hotspot.position.x = this.boundingBox[cornerName].x; - hotspot.position.y = this.boundingBox[cornerName].y; // Orient the rotation handles in the correct direction, even if the selection is flipped - - hotspot.rotate({ - 'topRight': 0, - 'bottomRight': 90, - 'bottomLeft': 180, - 'topLeft': 270 - }[cornerName]); // Some metadata. - - hotspot.data.handleType = 'rotation'; - hotspot.data.handleEdge = cornerName; - return hotspot; - } - - _buildGhost() { - var ghost = new paper.Group({ - insert: false, - applyMatrix: false - }); - - this._itemsInSelection.forEach(item => { - var outline = item.clone(); - outline.remove(); - outline.fillColor = 'rgba(0,0,0,0)'; - outline.strokeColor = SelectionWidget.GHOST_STROKE_COLOR; - outline.strokeWidth = SelectionWidget.GHOST_STROKE_WIDTH * 2; - ghost.addChild(outline); - var outline2 = outline.clone(); - outline2.remove(); - outline2.fillColor = 'rgba(0,0,0,0)'; - outline2.strokeColor = '#ffffff'; - outline2.strokeWidth = SelectionWidget.GHOST_STROKE_WIDTH; - ghost.addChild(outline2); - }); - - var boundsOutline = new paper.Path.Rectangle({ - from: this.boundingBox.topLeft, - to: this.boundingBox.bottomRight, - fillColor: 'rgba(0,0,0,0)', - strokeColor: SelectionWidget.GHOST_STROKE_COLOR, - strokeWidth: SelectionWidget.GHOST_STROKE_WIDTH, - applyMatrix: false - }); - boundsOutline.rotate(this.boxRotation, this._center); - ghost.addChild(boundsOutline); - ghost.opacity = 0.5; - return ghost; - } - - _calculateBoundingBox() { - if (this._itemsInSelection.length === 0) { - return new paper.Rectangle(); - } - - var center = this._calculateBoundingBoxOfItems(this._itemsInSelection).center; - - var itemsForBoundsCalc = this._itemsInSelection.map(item => { - var clone = item.clone(); - clone.rotate(-this.boxRotation, center); - clone.remove(); - return clone; - }); - - return this._calculateBoundingBoxOfItems(itemsForBoundsCalc); - } - - _calculateBoundingBoxOfItems(items) { - var bounds = null; - items.forEach(item => { - bounds = bounds ? bounds.unite(item.bounds) : item.bounds; - }); - return bounds || new paper.Rectangle(); - } - -} - -; -SelectionWidget.BOX_STROKE_WIDTH = 1; -SelectionWidget.BOX_STROKE_COLOR = 'rgba(100,150,255,1.0)'; -SelectionWidget.HANDLE_RADIUS = 5; -SelectionWidget.HANDLE_STROKE_WIDTH = SelectionWidget.BOX_STROKE_WIDTH; -SelectionWidget.HANDLE_STROKE_COLOR = SelectionWidget.BOX_STROKE_COLOR; -SelectionWidget.HANDLE_FILL_COLOR = 'rgba(255,255,255,0.3)'; -SelectionWidget.PIVOT_STROKE_WIDTH = SelectionWidget.BOX_STROKE_WIDTH; -SelectionWidget.PIVOT_FILL_COLOR = 'rgba(255,255,255,0.5)'; -SelectionWidget.PIVOT_STROKE_COLOR = 'rgba(0,0,0,1)'; -SelectionWidget.PIVOT_RADIUS = SelectionWidget.HANDLE_RADIUS; -SelectionWidget.ROTATION_HOTSPOT_RADIUS = 20; -SelectionWidget.ROTATION_HOTSPOT_FILLCOLOR = 'rgba(100,150,255,0.5)'; -SelectionWidget.GHOST_STROKE_COLOR = 'rgba(0, 0, 0, 1.0)'; -SelectionWidget.GHOST_STROKE_WIDTH = 1; -paper.PaperScope.inject({ - SelectionWidget: SelectionWidget -}); -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Paper.js-drawing-tools. - * - * Paper.js-drawing-tools is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Paper.js-drawing-tools is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Paper.js-drawing-tools. If not, see . - */ -paper.SelectionBox = class { - /* - * - */ - constructor(paperContext) { - this.paper = paperContext; - this._start = new this.paper.Point(); - this._end = new this.paper.Point(); - this._items = []; - this._active = false; - this._box = new this.paper.Path.Rectangle({ - insert: false - }); - this._mode = 'intersects'; - } - /* - * - */ - - - start(point) { - this._active = true; - this._start = point; - this._end = point; - - this._rebuildBox(); - } - /* - * - */ - - - drag(point) { - this._end = point; - - this._rebuildBox(); - } - /* - * - */ - - - end(point) { - this._end = point; - this._active = false; - - this._rebuildBox(); - - this._box.remove(); - - this._items = this._itemsInBox(this._box); - } - /* - * - */ - - - get items() { - return this._items; - } - /* - * - */ - - - get active() { - return this._active; - } - /* - * - */ - - - get mode() { - return this._mode; - } - - set mode(mode) { - if (mode !== 'contains' && mode !== 'intersects') { - throw new Error("SelectionBox.mode: invalid mode"); - } - - this._mode = mode; - } - - _rebuildBox() { - this._box.remove(); - - this._box = new this.paper.Path.Rectangle({ - from: this._start, - to: this._end, - strokeWidth: 1, - strokeColor: 'black' - }); - } - - _itemsInBox(box) { - var checkItems = []; - - this._getSelectableLayers().forEach(layer => { - layer.children.forEach(child => { - checkItems.push(child); - }); - }); - - var items = []; - checkItems.forEach(item => { - if (this.mode === 'contains') { - if (this._box.bounds.contains(item.bounds)) { - items.push(item); - } - } else if (this.mode === 'intersects') { - if (this._shapesIntersect(item, this._box)) { - items.push(item); - } - } - }); - return items; - } - - _shapesIntersect(itemA, itemB) { - if (itemA instanceof this.paper.Group) { - var intersects = false; - var itemBClone = itemB.clone(); - itemBClone.transform(itemA.matrix.inverted()); - itemA.children.forEach(child => { - if (!intersects && this._shapesIntersect(child, itemBClone)) { - intersects = true; - } - }); - return intersects; - } else { - var shapesDoIntersect = itemB.intersects(itemA); - var boundsContain = itemB.bounds.contains(itemA.bounds); - - if (shapesDoIntersect || boundsContain) { - return true; - } - } - } - - _getSelectableLayers() { - var self = this; - return this.paper.project.layers.filter(layer => { - return !layer.locked; - }); - } - -}; -paper.PaperScope.inject({ - SelectionBox: paper.SelectionBox -}); -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Paper.js-drawing-tools. - * - * Paper.js-drawing-tools is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Paper.js-drawing-tools is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Paper.js-drawing-tools. If not, see . - */ - -/* - paper-potrace.js - Adds a potrace() method to paper Items that runs potrace on a rasterized - version of that Item. - - by zrispo (github.com/zrispo) (zach@wickeditor.com) - */ -paper.Path.inject({ - potrace: function (args) { - var self = this; - if (!args) throw new Error('Path.potrace: args is required.'); - if (!args.resolution) throw new Error('Path.potrace: args.resolution is required.'); - if (!args.done) throw new Error('Path.potrace: args.done is required.'); - var finalRasterResolution = paper.view.resolution * args.resolution / window.devicePixelRatio; - var raster = this.rasterize(finalRasterResolution); - raster.remove(); - var rasterDataURL = raster.toDataURL(); - - if (rasterDataURL === 'data:,') { - args.done(null); - } // https://oov.github.io/potrace/ - - - var img = new Image(); - - img.onload = function () { - var svg = potrace.fromImage(img).toSVG(1 / args.resolution); - var potracePath = paper.project.importSVG(svg); - potracePath.position.x = self.position.x; - potracePath.position.y = self.position.y; - potracePath.remove(); - potracePath.closed = true; - potracePath.children[0].closed = true; - args.done(potracePath.children[0]); - }; - - img.src = rasterDataURL; - } -}); -/* - * Copyright 2020 WICKLETS LLC - * - * This file is part of Paper.js-drawing-tools. - * - * Paper.js-drawing-tools is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Paper.js-drawing-tools is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Paper.js-drawing-tools. If not, see . - */ -(function () { - var editElem = $('