From 06c8c79cb44d8ad8cc4f9672eb69a0145110fa3e Mon Sep 17 00:00:00 2001 From: Martin Bolot Date: Thu, 28 Jul 2016 10:35:28 +0200 Subject: [PATCH 1/2] LRB's modifications on Glyph and Outline - related to local merging --- src/Glyph.js | 6 +----- src/Outline.js | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Glyph.js b/src/Glyph.js index 0a37061..d983706 100644 --- a/src/Glyph.js +++ b/src/Glyph.js @@ -204,7 +204,7 @@ Glyph.prototype.combineOTCommands = function( path ) { path = this.ot.path; } - var combined = this.combineTo( new Outline() ); + var combined = this.combineTo(); if ( combined ) { // prototypo.js will make all contours clockwise without this @@ -216,10 +216,6 @@ Glyph.prototype.combineOTCommands = function( path ) { }; Glyph.prototype.combineTo = function( outline ) { - if ( !outline ) { - outline = new Outline(); - } - outline = this.children[0].combineTo( outline ); return this.children[1].children.reduce(function( outline, component ) { diff --git a/src/Outline.js b/src/Outline.js index bb6c75e..4b0306a 100644 --- a/src/Outline.js +++ b/src/Outline.js @@ -82,7 +82,7 @@ Outline.prototype.combineTo = function( outline ) { return reducing; } - var tmp = ( reducing == undefined ? + var tmp = ( reducing == undefined || reducing.isEmpty() ? // when the initial value doesn't exist, use the first path // (clone it otherwise it's removed from this.children) path.clone( false ) : From 28f54705a7c161d61f774e82a80cf7434af4a305 Mon Sep 17 00:00:00 2001 From: Martin Bolot Date: Thu, 28 Jul 2016 10:42:01 +0200 Subject: [PATCH 2/2] generated dist/plumin.* --- dist/plumin.js | 1159 +++++++++++++++++++++++++++++++++----------- dist/plumin.js.map | 2 +- 2 files changed, 873 insertions(+), 288 deletions(-) diff --git a/dist/plumin.js b/dist/plumin.js index 3dea316..cc6674d 100644 --- a/dist/plumin.js +++ b/dist/plumin.js @@ -62,12 +62,12 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports, __webpack_require__) { var opentype = __webpack_require__(2); - var paper = __webpack_require__(33); - var Font = __webpack_require__(36); - var Glyph = __webpack_require__(37); - var Outline = __webpack_require__(38); - var Path = __webpack_require__(40); - var Node = __webpack_require__(41); + var paper = __webpack_require__(35); + var Font = __webpack_require__(38); + var Glyph = __webpack_require__(39); + var Outline = __webpack_require__(40); + var Path = __webpack_require__(42); + var Node = __webpack_require__(43); paper.PaperScope.prototype.Font = Font; paper.PaperScope.prototype.Glyph = Glyph; @@ -100,20 +100,20 @@ return /******/ (function(modules) { // webpackBootstrap var glyph = __webpack_require__(15); var parse = __webpack_require__(12); var path = __webpack_require__(6); - var util = __webpack_require__(25); + var util = __webpack_require__(28); var cmap = __webpack_require__(11); var cff = __webpack_require__(13); - var fvar = __webpack_require__(27); - var glyf = __webpack_require__(28); - var gpos = __webpack_require__(29); - var gsub = __webpack_require__(30); + var fvar = __webpack_require__(30); + var glyf = __webpack_require__(31); + var gpos = __webpack_require__(32); + var gsub = __webpack_require__(25); var head = __webpack_require__(17); var hhea = __webpack_require__(18); var hmtx = __webpack_require__(19); - var kern = __webpack_require__(31); + var kern = __webpack_require__(33); var ltag = __webpack_require__(20); - var loca = __webpack_require__(32); + var loca = __webpack_require__(34); var maxp = __webpack_require__(21); var _name = __webpack_require__(22); var os2 = __webpack_require__(23); @@ -122,7 +122,7 @@ return /******/ (function(modules) { // webpackBootstrap // File loaders ///////////////////////////////////////////////////////// function loadFromFile(path, callback) { - var fs = __webpack_require__(26); + var fs = __webpack_require__(29); fs.readFile(path, function(err, buffer) { if (err) { return callback(err.message); @@ -397,7 +397,7 @@ return /******/ (function(modules) { // webpackBootstrap // Synchronously load the font from a URL or file. // When done, return the font object or throw an error. function loadSync(url) { - var fs = __webpack_require__(26); + var fs = __webpack_require__(29); var buffer = fs.readFileSync(url); return parseBuffer(util.nodeBufferToArrayBuffer(buffer)); } @@ -1016,7 +1016,7 @@ return /******/ (function(modules) { // webpackBootstrap glyph = font.glyphs.get(i); if (font.cffEncoding) { glyph.name = font.cffEncoding.charset[i]; - } else { + } else if (font.glyphNames.names) { glyph.name = font.glyphNames.glyphIndexToName(i); } } @@ -1045,7 +1045,8 @@ return /******/ (function(modules) { // webpackBootstrap var sfnt = __webpack_require__(7); var encoding = __webpack_require__(4); var glyphset = __webpack_require__(14); - var util = __webpack_require__(25); + var Substitution = __webpack_require__(26); + var util = __webpack_require__(28); // A Font represents a loaded OpenType font file. // It contains a set of glyphs and methods to draw text on a drawing context, @@ -1093,6 +1094,7 @@ return /******/ (function(modules) { // webpackBootstrap this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported. this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []); this.encoding = new encoding.DefaultEncoding(this); + this.substitution = new Substitution(this); this.tables = this.tables || {}; } @@ -1367,7 +1369,7 @@ return /******/ (function(modules) { // webpackBootstrap throw err; }); } else { - var fs = __webpack_require__(26); + var fs = __webpack_require__(29); var buffer = util.arrayBufferToNodeBuffer(arrayBuffer); fs.writeFileSync(fileName, buffer); } @@ -1612,6 +1614,7 @@ return /******/ (function(modules) { // webpackBootstrap var _name = __webpack_require__(22); var os2 = __webpack_require__(23); var post = __webpack_require__(24); + var gsub = __webpack_require__(25); function log2(v) { return Math.log(v) / Math.log(2) | 0; @@ -1896,6 +1899,10 @@ return /******/ (function(modules) { // webpackBootstrap if (ltagTable) { tables.push(ltagTable); } + // Optional tables + if (font.tables.gsub) { + tables.push(gsub.make(font.tables.gsub)); + } var sfntTable = makeSfntTable(tables); @@ -1953,6 +1960,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; + var check = __webpack_require__(8); var encode = __webpack_require__(10).encode; var sizeOf = __webpack_require__(10).sizeOf; @@ -1985,7 +1993,91 @@ return /******/ (function(modules) { // webpackBootstrap return sizeOf.TABLE(this); }; + function ushortList(itemName, list, count) { + if (count === undefined) { + count = list.length; + } + var fields = new Array(list.length + 1); + fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count}; + for (var i = 0; i < list.length; i++) { + fields[i + 1] = {name: itemName + i, type: 'USHORT', value: list[i]}; + } + return fields; + } + + function tableList(itemName, records, itemCallback) { + var count = records.length; + var fields = new Array(count + 1); + fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count}; + for (var i = 0; i < count; i++) { + fields[i + 1] = {name: itemName + i, type: 'TABLE', value: itemCallback(records[i], i)}; + } + return fields; + } + + function recordList(itemName, records, itemCallback) { + var count = records.length; + var fields = []; + fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count}; + for (var i = 0; i < count; i++) { + fields = fields.concat(itemCallback(records[i], i)); + } + return fields; + } + + // Common Layout Tables + function Coverage(coverageTable) { + if (coverageTable.format === 1) { + Table.call(this, 'coverageTable', + [{name: 'coverageFormat', type: 'USHORT', value: 1}] + .concat(ushortList('glyph', coverageTable.glyphs)) + ); + } else { + check.assert(false, 'Can\'t create coverage table format 2 yet.'); + } + } + Coverage.prototype = Object.create(Table.prototype); + Coverage.prototype.constructor = Coverage; + + // Missing: script list. See gsub.js + + function FeatureList(featureListTable) { + Table.call(this, 'featureListTable', + recordList('featureRecord', featureListTable, function(featureRecord, i) { + var feature = featureRecord.feature; + return [ + {name: 'featureTag' + i, type: 'TAG', value: featureRecord.tag}, + {name: 'feature' + i, type: 'TABLE', value: new Table('featureTable', [ + {name: 'featureParams', type: 'USHORT', value: feature.featureParams}, + ].concat(ushortList('lookupListIndex', feature.lookupListIndexes)))} + ]; + }) + ); + } + FeatureList.prototype = Object.create(Table.prototype); + FeatureList.prototype.constructor = FeatureList; + + function LookupList(lookupListTable, subtableMakers) { + Table.call(this, 'lookupListTable', tableList('lookup', lookupListTable, function(lookupTable) { + return new Table('lookupTable', [ + {name: 'lookupType', type: 'USHORT', value: lookupTable.lookupType}, + {name: 'lookupFlag', type: 'USHORT', value: lookupTable.lookupFlag} + ].concat(tableList('subtable', lookupTable.subtables, subtableMakers[lookupTable.lookupType]))); + })); + } + LookupList.prototype = Object.create(Table.prototype); + LookupList.prototype.constructor = LookupList; + + // Record = same as Table, but inlined (a Table has an offset and its data is further in the stream) + // Don't use offsets inside Records (probable bug), only in Tables. exports.Record = exports.Table = Table; + exports.Coverage = Coverage; + exports.FeatureList = FeatureList; + exports.LookupList = LookupList; + + exports.ushortList = ushortList; + exports.tableList = tableList; + exports.recordList = recordList; /***/ }, @@ -4411,6 +4503,22 @@ return /******/ (function(modules) { // webpackBootstrap var _glyph = __webpack_require__(15); + // Define a property on the glyph that depends on the path being loaded. + function defineDependentProperty(glyph, externalName, internalName) { + Object.defineProperty(glyph, externalName, { + get: function() { + // Request the path property to make sure the path is loaded. + glyph.path; // jshint ignore:line + return glyph[internalName]; + }, + set: function(newValue) { + glyph[internalName] = newValue; + }, + enumerable: true, + configurable: true + }); + } + // A GlyphSet represents all glyphs available in the font, but modelled using // a deferred glyph loader, for retrieving glyphs only once they are absolutely // necessary, to keep the memory footprint down. @@ -4460,6 +4568,11 @@ return /******/ (function(modules) { // webpackBootstrap return path; }; + defineDependentProperty(glyph, 'xMin', '_xMin'); + defineDependentProperty(glyph, 'xMax', '_xMax'); + defineDependentProperty(glyph, 'yMin', '_yMin'); + defineDependentProperty(glyph, 'yMax', '_yMax'); + return glyph; }; } @@ -6277,6 +6390,665 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 25 */ +/***/ function(module, exports, __webpack_require__) { + + // The `GSUB` table contains ligatures, among other things. + // https://www.microsoft.com/typography/OTSPEC/gsub.htm + + 'use strict'; + + var check = __webpack_require__(8); + var Parser = __webpack_require__(12).Parser; + var subtableParsers = new Array(9); // subtableParsers[0] is unused + var table = __webpack_require__(9); + + // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS + subtableParsers[1] = function parseLookup1() { + var start = this.offset + this.relativeOffset; + var substFormat = this.parseUShort(); + if (substFormat === 1) { + return { + substFormat: 1, + coverage: this.parsePointer(Parser.coverage), + deltaGlyphId: this.parseUShort() + }; + } else if (substFormat === 2) { + return { + substFormat: 2, + coverage: this.parsePointer(Parser.coverage), + substitute: this.parseOffset16List() + }; + } + check.assert(false, '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.'); + }; + + // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS + subtableParsers[2] = function parseLookup2() { + var substFormat = this.parseUShort(); + check.argument(substFormat === 1, 'GSUB Multiple Substitution Subtable identifier-format must be 1'); + return { + substFormat: substFormat, + coverage: this.parsePointer(Parser.coverage), + sequences: this.parseListOfLists() + }; + }; + + // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS + subtableParsers[3] = function parseLookup3() { + var substFormat = this.parseUShort(); + check.argument(substFormat === 1, 'GSUB Alternate Substitution Subtable identifier-format must be 1'); + return { + substFormat: substFormat, + coverage: this.parsePointer(Parser.coverage), + alternateSets: this.parseListOfLists() + }; + }; + + // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS + subtableParsers[4] = function parseLookup4() { + var substFormat = this.parseUShort(); + check.argument(substFormat === 1, 'GSUB ligature table identifier-format must be 1'); + return { + substFormat: substFormat, + coverage: this.parsePointer(Parser.coverage), + ligatureSets: this.parseListOfLists(function() { + return { + ligGlyph: this.parseUShort(), + components: this.parseUShortList(this.parseUShort() - 1) + }; + }) + }; + }; + + var lookupRecordDesc = { + sequenceIndex: Parser.uShort, + lookupListIndex: Parser.uShort + }; + + // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF + subtableParsers[5] = function parseLookup5() { + var start = this.offset + this.relativeOffset; + var substFormat = this.parseUShort(); + + if (substFormat === 1) { + return { + substFormat: substFormat, + coverage: this.parsePointer(Parser.coverage), + ruleSets: this.parseListOfLists(function() { + var glyphCount = this.parseUShort(); + var substCount = this.parseUShort(); + return { + input: this.parseUShortList(glyphCount - 1), + lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) + }; + }) + }; + } else if (substFormat === 2) { + return { + substFormat: substFormat, + coverage: this.parsePointer(Parser.coverage), + classDef: this.parsePointer(Parser.classDef), + classSets: this.parseListOfLists(function() { + var glyphCount = this.parseUShort(); + var substCount = this.parseUShort(); + return { + classes: this.parseUShortList(glyphCount - 1), + lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) + }; + }) + }; + } else if (substFormat === 3) { + var glyphCount = this.parseUShort(); + var substCount = this.parseUShort(); + return { + substFormat: substFormat, + coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)), + lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) + }; + } + check.assert(false, '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.'); + }; + + // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC + subtableParsers[6] = function parseLookup6() { + // TODO add automated tests for lookup 6 : no examples in the MS doc. + var start = this.offset + this.relativeOffset; + var substFormat = this.parseUShort(); + if (substFormat === 1) { + return { + substFormat: 1, + coverage: this.parsePointer(Parser.coverage), + chainRuleSets: this.parseListOfLists(function() { + return { + backtrack: this.parseUShortList(), + input: this.parseUShortList(this.parseShort() - 1), + lookahead: this.parseUShortList(), + lookupRecords: this.parseRecordList(lookupRecordDesc) + }; + }) + }; + } else if (substFormat === 2) { + return { + substFormat: 2, + coverage: this.parsePointer(Parser.coverage), + backtrackClassDef: this.parsePointer(Parser.classDef), + inputClassDef: this.parsePointer(Parser.classDef), + lookaheadClassDef: this.parsePointer(Parser.classDef), + chainClassSet: this.parseListOfLists(function() { + return { + backtrack: this.parseUShortList(), + input: this.parseUShortList(this.parseShort() - 1), + lookahead: this.parseUShortList(), + lookupRecords: this.parseRecordList(lookupRecordDesc) + }; + }) + }; + } else if (substFormat === 3) { + return { + substFormat: 3, + backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)), + inputCoverage: this.parseList(Parser.pointer(Parser.coverage)), + lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)), + lookupRecords: this.parseRecordList(lookupRecordDesc) + }; + } + check.assert(false, '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.'); + }; + + // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES + subtableParsers[7] = function parseLookup7() { + // Extension Substitution subtable + var substFormat = this.parseUShort(); + check.argument(substFormat === 1, 'GSUB Extension Substitution subtable identifier-format must be 1'); + var extensionLookupType = this.parseUShort(); + var extensionParser = new Parser(this.data, this.offset + this.parseULong()); + return { + substFormat: 1, + lookupType: extensionLookupType, + extension: subtableParsers[extensionLookupType].call(extensionParser) + }; + }; + + // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS + subtableParsers[8] = function parseLookup8() { + var substFormat = this.parseUShort(); + check.argument(substFormat === 1, 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1'); + return { + substFormat: substFormat, + coverage: this.parsePointer(Parser.coverage), + backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)), + lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)), + substitutes: this.parseUShortList() + }; + }; + + // https://www.microsoft.com/typography/OTSPEC/gsub.htm + function parseGsubTable(data, start) { + start = start || 0; + var p = new Parser(data, start); + var tableVersion = p.parseVersion(); + check.argument(tableVersion === 1, 'Unsupported GSUB table version.'); + return { + version: tableVersion, + scripts: p.parseScriptList(), + features: p.parseFeatureList(), + lookups: p.parseLookupList(subtableParsers) + }; + } + + // GSUB Writing ////////////////////////////////////////////// + var subtableMakers = new Array(9); + + subtableMakers[1] = function makeLookup1(subtable) { + if (subtable.substFormat === 1) { + return new table.Table('substitutionTable', [ + {name: 'substFormat', type: 'USHORT', value: 1}, + {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)}, + {name: 'deltaGlyphID', type: 'USHORT', value: subtable.deltaGlyphId} + ]); + } else { + check.assert(false, 'Can\'t write lookup type 1 subtable format 2.'); + } + check.assert(false, 'Lookup type 1 substFormat must be 1 or 2.'); + }; + + subtableMakers[4] = function makeLookup4(subtable) { + check.assert(subtable.substFormat === 1, 'Lookup type 4 substFormat must be 1.'); + return new table.Table('substitutionTable', [ + {name: 'substFormat', type: 'USHORT', value: 1}, + {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)} + ].concat(table.tableList('ligSet', subtable.ligatureSets, function(ligatureSet) { + return new table.Table('ligatureSetTable', table.tableList('ligature', ligatureSet, function(ligature) { + return new table.Table('ligatureTable', + [{name: 'ligGlyph', type: 'USHORT', value: ligature.ligGlyph}] + .concat(table.ushortList('component', ligature.components, ligature.components.length + 1)) + ); + })); + }))); + }; + + function makeGsubTable(gsub) { + // Feature limitation - we can only write the table in the most simple cases. + var onlyDfltScript = (gsub.scripts.length === 1 && gsub.scripts[0].tag === 'DFLT'); + check.assert(onlyDfltScript, 'Unable to write: GSUB table must contain only the DFLT script.'); + var dfltScript = gsub.scripts[0].script; + var onlyDfltLang = (dfltScript.defaultLangSys && dfltScript.langSysRecords.length === 0); + check.assert(onlyDfltLang, 'Unable to write: GSUB table must contain only the default language system.'); + + for (var i = 0; i < gsub.lookups.length; i++) { + var lookup = gsub.lookups[i]; + var canWriteLookup = (lookup.lookupType === 4); + check.assert(canWriteLookup, 'Unable to write: GSUB table must contain only type 4 lookup tables'); + } + + var scriptList = new table.Table('scriptList', [ + {name: 'scriptCount', type: 'USHORT', value: 1}, + {name: 'scriptTag_0', type: 'TAG', value: 'DFLT'}, + {name: 'script_0', type: 'TABLE', value: new table.Table('scriptTable', [ + {name: 'defaultLangSys', type: 'TABLE', value: new table.Table('langSysTable', [ + {name: 'lookupOrder', type: 'USHORT', value: 0}, + {name: 'reqFeatureIndex', type: 'USHORT', value: 0xffff}, + {name: 'featureCount', type: 'USHORT', value: gsub.features.length}, + {name: 'featureIndex_0', type: 'USHORT', value: 0} + ])}, + {name: 'langSysCount', type: 'USHORT', value: 0} + ])}, + ]); + + var featureList = new table.FeatureList(gsub.features); + var lookupList = new table.LookupList(gsub.lookups, subtableMakers); + + var gsubTable = new table.Table('GSUB', [ + {name: 'version', type: 'ULONG', value: 0x10000}, + {name: 'scripts', type: 'TABLE', value: scriptList}, + {name: 'features', type: 'TABLE', value: featureList}, + {name: 'lookups', type: 'TABLE', value: lookupList} + ]); + + return gsubTable; + } + + exports.parse = parseGsubTable; + exports.make = makeGsubTable; + + +/***/ }, +/* 26 */ +/***/ function(module, exports, __webpack_require__) { + + // The Substitution object provides utility methods to manipulate + // the GSUB substitution table. + + 'use strict'; + + var check = __webpack_require__(8); + var Layout = __webpack_require__(27); + + var Substitution = function(font) { + this.font = font; + }; + + // Check if 2 arrays of primitives are equal. + function arraysEqual(ar1, ar2) { + var n = ar1.length; + if (n !== ar2.length) { return false; } + for (var i = 0; i < n; i++) { + if (ar1[i] !== ar2[i]) { return false; } + } + return true; + } + + Substitution.prototype = Layout; + + // Get or create the GSUB table. + Substitution.prototype.getGsubTable = function(create) { + var gsub = this.font.tables.gsub; + if (!gsub && create) { + // Generate a default empty GSUB table with just a DFLT script and dflt lang sys. + this.font.tables.gsub = gsub = { + version: 1, + scripts: [{ + tag: 'DFLT', + script: { + defaultLangSys: { reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: [] }, + langSysRecords: [] + } + }], + features: [], + lookups: [] + }; + } + return gsub; + }; + + /** + * List all ligatures (lookup type 4) for a given script, language, and feature. + * The result is an array of ligature objects like { sub: [ids], by: id } + * @param {string} script + * @param {string} language + * @param {string} feature - 4-letter feature name (liga, rlig, dlig...) + */ + Substitution.prototype.getLigatures = function(script, language, feature) { + var lookupTable = this.getLookupTable(script, language, feature, 4); + if (!lookupTable) { return []; } + var subtable = lookupTable.subtables[0]; + if (!subtable) { return []; } + var glyphs = this.expandCoverage(subtable.coverage); + var ligatureSets = subtable.ligatureSets; + var ligatures = []; + for (var i = 0; i < glyphs.length; i++) { + var startGlyph = glyphs[i]; + var ligSet = ligatureSets[i]; + for (var j = 0; j < ligSet.length; j++) { + var lig = ligSet[j]; + ligatures.push({ + sub: [startGlyph].concat(lig.components), + by: lig.ligGlyph + }); + } + } + return ligatures; + }; + + /** + * Add a ligature (lookup type 4) + * Ligatures with more components must be stored ahead of those with fewer components in order to be found + * @param {string} [script='DFLT'] + * @param {string} [language='DFLT'] + * @param {object} ligature - { sub: [ids], by: id } + */ + Substitution.prototype.addLigature = function(script, language, feature, ligature) { + var lookupTable = this.getLookupTable(script, language, feature, 4, true); + var subtable = lookupTable.subtables[0]; + if (!subtable) { + subtable = { // lookup type 4 subtable, format 1, coverage format 1 + substFormat: 1, + coverage: { format: 1, glyphs: [] }, + ligatureSets: [] + }; + lookupTable.subtables[0] = subtable; + } + check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format); + var coverageGlyph = ligature.sub[0]; + var ligComponents = ligature.sub.slice(1); + var ligatureTable = { + ligGlyph: ligature.by, + components: ligComponents + }; + var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph); + if (pos >= 0) { + // ligatureSet already exists + var ligatureSet = subtable.ligatureSets[pos]; + for (var i = 0; i < ligatureSet.length; i++) { + // If ligature already exists, return. + if (arraysEqual(ligatureSet[i].components, ligComponents)) { + return; + } + } + // ligature does not exist: add it. + ligatureSet.push(ligatureTable); + } else { + // Create a new ligatureSet and add coverage for the first glyph. + pos = -1 - pos; + subtable.coverage.glyphs.splice(pos, 0, coverageGlyph); + subtable.ligatureSets.splice(pos, 0, [ligatureTable]); + } + }; + + /** + * List all feature data for a given script and language. + * @param {string} [script='DFLT'] + * @param {string} [language='DFLT'] + * @param {string} feature - 4-letter feature name + */ + Substitution.prototype.getFeature = function(script, language, feature) { + if (arguments.length === 1) { + feature = arguments[0]; + script = language = 'DFLT'; + } + switch (feature) { + case 'dlig': + case 'liga': + case 'rlig': return this.getLigatures(script, language, feature); + } + }; + + /** + * Add a substitution to a feature for a given script and language. + * The result is an array of ligature objects like { sub: [ids], by: id } + * @param {string} [script='DFLT'] + * @param {string} [language='DFLT'] + * @param {string} feature - 4-letter feature name + * @param {object} sub - the substitution to add + */ + Substitution.prototype.add = function(script, language, feature, sub) { + if (arguments.length === 2) { + feature = arguments[0]; + sub = arguments[1]; + script = language = 'DFLT'; + } + switch (feature) { + case 'dlig': + case 'liga': + case 'rlig': return this.addLigature(script, language, feature, sub); + } + }; + + module.exports = Substitution; + + +/***/ }, +/* 27 */ +/***/ function(module, exports) { + + // The Layout object is the prototype of Substition objects, and provides utility methods to manipulate + // common layout tables (GPOS, GSUB, GDEF...) + + 'use strict'; + + function searchTag(arr, tag) { + /* jshint bitwise: false */ + var imin = 0; + var imax = arr.length - 1; + while (imin <= imax) { + var imid = (imin + imax) >>> 1; + var val = arr[imid].tag; + if (val === tag) { + return imid; + } else if (val < tag) { + imin = imid + 1; + } else { imax = imid - 1; } + } + // Not found: return -1-insertion point + return -imin - 1; + } + + function binSearch(arr, value) { + /* jshint bitwise: false */ + var imin = 0; + var imax = arr.length - 1; + while (imin <= imax) { + var imid = (imin + imax) >>> 1; + var val = arr[imid]; + if (val === value) { + return imid; + } else if (val < value) { + imin = imid + 1; + } else { imax = imid - 1; } + } + // Not found: return -1-insertion point + return -imin - 1; + } + + var Layout = { + // Binary search an object by "tag" property + searchTag: searchTag, + + // Binary search in a list of numbers + binSearch: binSearch, + + // Returns all scripts in the substitution table. + getScriptNames: function() { + var gsub = this.getGsubTable(); + if (!gsub) { return []; } + return gsub.scripts.map(function(script) { + return script.tag; + }); + }, + + /** + * Returns all LangSysRecords in the given script. + * @param {string} script - Use 'DFLT' for default script + * @param {boolean} create - forces the creation of this script table if it doesn't exist. + */ + getScriptTable: function(script, create) { + var gsub = this.getGsubTable(create); + if (gsub) { + var scripts = gsub.scripts; + var pos = searchTag(gsub.scripts, script); + if (pos >= 0) { + return scripts[pos].script; + } else { + var scr = { + tag: script, + script: { + defaultLangSys: { reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: [] }, + langSysRecords: [] + } + }; + scripts.splice(-1 - pos, 0, scr.script); + return scr; + } + } + }, + + /** + * Returns a language system table + * @param {string} script - Use 'DFLT' for default script + * @param {string} language - Use 'DFLT' for default language + * @param {boolean} create - forces the creation of this langSysTable if it doesn't exist. + */ + getLangSysTable: function(script, language, create) { + var scriptTable = this.getScriptTable(script, create); + if (scriptTable) { + if (language === 'DFLT') { + return scriptTable.defaultLangSys; + } + var pos = searchTag(scriptTable.langSysRecords, language); + if (pos >= 0) { + return scriptTable.langSysRecords[pos].langSys; + } else if (create) { + var langSysRecord = { + tag: language, + langSys: { reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: [] } + }; + scriptTable.langSysRecords.splice(-1 - pos, 0, langSysRecord); + return langSysRecord.langSys; + } + } + }, + + /** + * Get a specific feature table. + * + * @param {string} script - Use 'DFLT' for default script + * @param {string} language - Use 'DFLT' for default language + * @param {string} feature - One of the codes listed at https://www.microsoft.com/typography/OTSPEC/featurelist.htm + * @param {boolean} create - forces the creation of the feature table if it doesn't exist. + */ + getFeatureTable: function(script, language, feature, create) { + var langSysTable = this.getLangSysTable(script, language, create); + if (langSysTable) { + var featureRecord; + var featIndexes = langSysTable.featureIndexes; + var allFeatures = this.font.tables.gsub.features; + // The FeatureIndex array of indices is in arbitrary order, + // even if allFeatures is sorted alphabetically by feature tag. + for (var i = 0; i < featIndexes.length; i++) { + featureRecord = allFeatures[featIndexes[i]]; + if (featureRecord.tag === feature) { + return featureRecord.feature; + } + } + if (create) { + featureRecord = { + tag: feature, + feature: { params: 0, lookupListIndexes: [] } + }; + var index = allFeatures.length; + allFeatures.push(featureRecord); + featIndexes.push(index); + return featureRecord.feature; + } + } + }, + + /** + * Get the first lookup table of a given type for a script/language/feature. + * @param {string} script - Use 'DFLT' for default script + * @param {string} language - Use 'DFLT' for default language + * @param {string} feature - 4-letter feature code + * @param {number} lookupType - 1 to 8 + * @param {boolean} create - forces the creation of the lookup table if it doesn't exist, with no subtables. + */ + getLookupTable: function(script, language, feature, lookupType, create) { + var featureTable = this.getFeatureTable(script, language, feature, create); + if (featureTable) { + var lookupTable; + var lookupListIndexes = featureTable.lookupListIndexes; + var allLookups = this.font.tables.gsub.lookups; + // lookupListIndexes are in no particular order, so use naïve search. + for (var i = 0; i < lookupListIndexes.length; i++) { + lookupTable = allLookups[lookupListIndexes[i]]; + if (lookupTable.lookupType === lookupType) { + return lookupTable; + } + } + if (create) { + lookupTable = { + lookupType: lookupType, + lookupFlag: 0, + subtables: [], + markFilteringSet: undefined + }; + var index = allLookups.length; + allLookups.push(lookupTable); + lookupListIndexes.push(index); + return lookupTable; + } + } + }, + + /** + * Returns the list of glyph indexes of a coverage table. + * Format 1: the list is stored raw + * Format 2: compact list as range records. + */ + expandCoverage: function(coverageTable) { + if (coverageTable.format === 1) { + return coverageTable.glyphs; + } else { + var glyphs = []; + var ranges = coverageTable.ranges; + for (var i = 0; i < ranges; i++) { + var range = ranges[i]; + var start = range.start; + var end = range.end; + for (var j = start; j <= end; j++) { + glyphs.push(j); + } + } + return glyphs; + } + } + + }; + + module.exports = Layout; + + +/***/ }, +/* 28 */ /***/ function(module, exports) { 'use strict'; @@ -6317,13 +7089,13 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 26 */ +/* 29 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, -/* 27 */ +/* 30 */ /***/ function(module, exports, __webpack_require__) { // The `fvar` table stores font variation axes and instances. @@ -6468,7 +7240,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 28 */ +/* 31 */ /***/ function(module, exports, __webpack_require__) { // The `glyf` table describes the glyphs in TrueType outline format. @@ -6511,10 +7283,10 @@ return /******/ (function(modules) { // webpackBootstrap function parseGlyph(glyph, data, start) { var p = new parse.Parser(data, start); glyph.numberOfContours = p.parseShort(); - glyph.xMin = p.parseShort(); - glyph.yMin = p.parseShort(); - glyph.xMax = p.parseShort(); - glyph.yMax = p.parseShort(); + glyph._xMin = p.parseShort(); + glyph._yMin = p.parseShort(); + glyph._xMax = p.parseShort(); + glyph._yMax = p.parseShort(); var flags; var flag; if (glyph.numberOfContours > 0) { @@ -6775,7 +7547,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 29 */ +/* 32 */ /***/ function(module, exports, __webpack_require__) { // The `GPOS` table contains kerning pairs, among other things. @@ -7017,217 +7789,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 30 */ -/***/ function(module, exports, __webpack_require__) { - - // The `GSUB` table contains ligatures, among other things. - // https://www.microsoft.com/typography/OTSPEC/gsub.htm - - 'use strict'; - - var check = __webpack_require__(8); - var Parser = __webpack_require__(12).Parser; - var subtableParsers = new Array(9); // subtableParsers[0] is unused - - // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS - subtableParsers[1] = function parseLookup1() { - var start = this.offset + this.relativeOffset; - var substFormat = this.parseUShort(); - if (substFormat === 1) { - return { - substFormat: 1, - coverage: this.parsePointer(Parser.coverage), - deltaGlyphId: this.parseUShort() - }; - } else if (substFormat === 2) { - return { - substFormat: 2, - coverage: this.parsePointer(Parser.coverage), - substitute: this.parseOffset16List() - }; - } - check.assert(false, '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.'); - }; - - // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS - subtableParsers[2] = function parseLookup2() { - var substFormat = this.parseUShort(); - check.argument(substFormat === 1, 'GSUB Multiple Substitution Subtable identifier-format must be 1'); - return { - substFormat: substFormat, - coverage: this.parsePointer(Parser.coverage), - sequences: this.parseListOfLists() - }; - }; - - // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS - subtableParsers[3] = function parseLookup3() { - var substFormat = this.parseUShort(); - check.argument(substFormat === 1, 'GSUB Alternate Substitution Subtable identifier-format must be 1'); - return { - substFormat: substFormat, - coverage: this.parsePointer(Parser.coverage), - alternateSets: this.parseListOfLists() - }; - }; - - // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS - subtableParsers[4] = function parseLookup4() { - var substFormat = this.parseUShort(); - check.argument(substFormat === 1, 'GSUB ligature table identifier-format must be 1'); - return { - substFormat: substFormat, - coverage: this.parsePointer(Parser.coverage), - ligatureSets: this.parseListOfLists(function() { - return { - ligGlyph: this.parseUShort(), - components: this.parseUShortList(this.parseUShort() - 1) - }; - }) - }; - }; - - var lookupRecordDesc = { - sequenceIndex: Parser.uShort, - lookupListIndex: Parser.uShort - }; - - // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF - subtableParsers[5] = function parseLookup5() { - var start = this.offset + this.relativeOffset; - var substFormat = this.parseUShort(); - - if (substFormat === 1) { - return { - substFormat: substFormat, - coverage: this.parsePointer(Parser.coverage), - ruleSets: this.parseListOfLists(function() { - var glyphCount = this.parseUShort(); - var substCount = this.parseUShort(); - return { - input: this.parseUShortList(glyphCount - 1), - lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) - }; - }) - }; - } else if (substFormat === 2) { - return { - substFormat: substFormat, - coverage: this.parsePointer(Parser.coverage), - classDef: this.parsePointer(Parser.classDef), - classSets: this.parseListOfLists(function() { - var glyphCount = this.parseUShort(); - var substCount = this.parseUShort(); - return { - classes: this.parseUShortList(glyphCount - 1), - lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) - }; - }) - }; - } else if (substFormat === 3) { - var glyphCount = this.parseUShort(); - var substCount = this.parseUShort(); - return { - substFormat: substFormat, - coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)), - lookupRecords: this.parseRecordList(substCount, lookupRecordDesc) - }; - } - check.assert(false, '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.'); - }; - - // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC - subtableParsers[6] = function parseLookup6() { - // TODO add automated tests for lookup 6 : no examples in the MS doc. - var start = this.offset + this.relativeOffset; - var substFormat = this.parseUShort(); - if (substFormat === 1) { - return { - substFormat: 1, - coverage: this.parsePointer(Parser.coverage), - chainRuleSets: this.parseListOfLists(function() { - return { - backtrack: this.parseUShortList(), - input: this.parseUShortList(this.parseShort() - 1), - lookahead: this.parseUShortList(), - lookupRecords: this.parseRecordList(lookupRecordDesc) - }; - }) - }; - } else if (substFormat === 2) { - return { - substFormat: 2, - coverage: this.parsePointer(Parser.coverage), - backtrackClassDef: this.parsePointer(Parser.classDef), - inputClassDef: this.parsePointer(Parser.classDef), - lookaheadClassDef: this.parsePointer(Parser.classDef), - chainClassSet: this.parseListOfLists(function() { - return { - backtrack: this.parseUShortList(), - input: this.parseUShortList(this.parseShort() - 1), - lookahead: this.parseUShortList(), - lookupRecords: this.parseRecordList(lookupRecordDesc) - }; - }) - }; - } else if (substFormat === 3) { - return { - substFormat: 3, - backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)), - inputCoverage: this.parseList(Parser.pointer(Parser.coverage)), - lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)), - lookupRecords: this.parseRecordList(lookupRecordDesc) - }; - } - check.assert(false, '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.'); - }; - - // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES - subtableParsers[7] = function parseLookup7() { - // Extension Substitution subtable - var substFormat = this.parseUShort(); - check.argument(substFormat === 1, 'GSUB Extension Substitution subtable identifier-format must be 1'); - var extensionLookupType = this.parseUShort(); - var extensionParser = new Parser(this.data, this.offset + this.parseULong()); - return { - substFormat: 1, - lookupType: extensionLookupType, - extension: subtableParsers[extensionLookupType].call(extensionParser) - }; - }; - - // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS - subtableParsers[8] = function parseLookup8() { - var substFormat = this.parseUShort(); - check.argument(substFormat === 1, 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1'); - return { - substFormat: substFormat, - coverage: this.parsePointer(Parser.coverage), - backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)), - lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)), - substitutes: this.parseUShortList() - }; - }; - - // https://www.microsoft.com/typography/OTSPEC/gsub.htm - function parseGsubTable(data, start) { - start = start || 0; - var p = new Parser(data, start); - var tableVersion = p.parseVersion(); - check.argument(tableVersion === 1, 'Unsupported GSUB table version.'); - return { - version: tableVersion, - scripts: p.parseScriptList(), - features: p.parseFeatureList(), - lookups: p.parseLookupList(subtableParsers) - }; - } - - exports.parse = parseGsubTable; - - -/***/ }, -/* 31 */ +/* 33 */ /***/ function(module, exports, __webpack_require__) { // The `kern` table contains kerning pairs. @@ -7268,7 +7830,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 32 */ +/* 34 */ /***/ function(module, exports, __webpack_require__) { // The `loca` table stores the offsets to the locations of the glyphs in the font. @@ -7307,7 +7869,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 33 */ +/* 35 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -7321,7 +7883,7 @@ return /******/ (function(modules) { // webpackBootstrap * * All rights reserved. * - * Date: Sat Jul 23 18:50:58 2016 +0200 + * Date: Tue Jul 26 10:25:32 2016 +0200 * *** * @@ -7344,7 +7906,7 @@ return /******/ (function(modules) { // webpackBootstrap var paper = function(self, undefined) { - self = self || __webpack_require__(34); + self = self || __webpack_require__(36); var window = self.window, document = self.document; @@ -7574,9 +8136,10 @@ return /******/ (function(modules) { // webpackBootstrap return Base.serialize(this); }, - _set: function(props) { - if (props && Base.isPlainObject(props)) - return Base.filter(this, props); + set: function(props, exclude) { + if (props) + Base.filter(this, props, exclude, this._prioritize); + return this; }, statics: { @@ -7645,7 +8208,7 @@ return /******/ (function(modules) { // webpackBootstrap list.__index = begin + 1; return obj && options && options.clone ? obj.clone() : obj; } - obj = Base.create(this.prototype); + obj = Base.create(proto); if (readIndex) obj.__read = true; obj = obj.initialize.apply(obj, begin > 0 || begin + amount < length @@ -7686,7 +8249,7 @@ return /******/ (function(modules) { // webpackBootstrap var filtered = list._filtered; if (!filtered) { filtered = list._filtered = Base.create(list[0]); - filtered._filtering = list[0]; + filtered._unfiltered = list[0]; } filtered[name] = undefined; } @@ -7705,21 +8268,35 @@ return /******/ (function(modules) { // webpackBootstrap return !!this.getNamed(list, name); }, - filter: function(dest, source, exclude) { - var keys = Object.keys(source._filtering || source); - for (var i = 0, l = keys.length; i < l; i++) { - var key = keys[i]; - if (!(exclude && exclude[key])) { + 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 this.isPlainObject(obj) || Array.isArray(obj) + return Base.isPlainObject(obj) || Array.isArray(obj) || asString && typeof obj === 'string'; }, @@ -10202,7 +10779,8 @@ return /******/ (function(modules) { // webpackBootstrap clipMask: false, selected: false, data: {} - } + }, + _prioritize: ['applyMatrix'] }, new function() { var handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick', @@ -10263,7 +10841,7 @@ return /******/ (function(modules) { // webpackBootstrap ._insertItem(undefined, this, true); } if (hasProps && props !== Item.NO_INSERT) { - Base.filter(this, props, { + this.set(props, { internal: true, insert: true, project: true, parent: true }); } @@ -10312,12 +10890,6 @@ return /******/ (function(modules) { // webpackBootstrap symbol._changed(flags); }, - set: function(props) { - if (props) - this._set(props); - return this; - }, - getId: function() { return this._id; }, @@ -12223,6 +12795,7 @@ return /******/ (function(modules) { // webpackBootstrap crossOrigin: null, source: null }, + _prioritize: ['crossOrigin'], initialize: function Raster(object, position) { if (!this._initialize(object, @@ -18510,7 +19083,7 @@ return /******/ (function(modules) { // webpackBootstrap : color; return col === this || col && this._class === col._class && this._type === col._type - && this._alpha === col._alpha + && this.getAlpha() === col.getAlpha() && Base.equals(this._components, col._components) || false; }, @@ -18648,7 +19221,8 @@ return /******/ (function(modules) { // webpackBootstrap initialize: function Gradient(stops, radial) { this._id = UID.get(); - if (stops && this._set(stops)) { + if (stops && Base.isPlainObject(stops)) { + this.set(stops); stops = radial = null; } if (this._stops == null) { @@ -18977,8 +19551,23 @@ return /******/ (function(modules) { // webpackBootstrap }, 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 - && Base.equals(this._values, style._values) + && compare(this, style) + && compare(style, this, true) || false; }, @@ -20328,7 +20917,7 @@ return /******/ (function(modules) { // webpackBootstrap PaperScopeItem.call(this); this._moveCount = -1; this._downCount = -1; - this._set(props); + this.set(props); }, getMinDistance: function() { @@ -21799,7 +22388,7 @@ return /******/ (function(modules) { // webpackBootstrap }))(); if (paper.agent.node) - __webpack_require__(35)(paper); + __webpack_require__(37)(paper); if (true) { !(__WEBPACK_AMD_DEFINE_FACTORY__ = (paper), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); @@ -21812,25 +22401,25 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 34 */ +/* 36 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, -/* 35 */ +/* 37 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, -/* 36 */ +/* 38 */ /***/ function(module, exports, __webpack_require__) { var opentype = __webpack_require__(2), - paper = __webpack_require__(33), - Glyph = __webpack_require__(37), - assign = __webpack_require__(39).assign; + paper = __webpack_require__(35), + Glyph = __webpack_require__(39), + assign = __webpack_require__(41).assign; function Font( args ) { paper.Group.prototype.constructor.apply( this ); @@ -22209,12 +22798,12 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 37 */ +/* 39 */ /***/ function(module, exports, __webpack_require__) { var opentype = __webpack_require__(2), - paper = __webpack_require__(33), - Outline = __webpack_require__(38); + paper = __webpack_require__(35), + Outline = __webpack_require__(40); function Glyph( args ) { paper.Group.prototype.constructor.apply( this ); @@ -22418,7 +23007,7 @@ return /******/ (function(modules) { // webpackBootstrap path = this.ot.path; } - var combined = this.combineTo( new Outline() ); + var combined = this.combineTo(); if ( combined ) { // prototypo.js will make all contours clockwise without this @@ -22430,10 +23019,6 @@ return /******/ (function(modules) { // webpackBootstrap }; Glyph.prototype.combineTo = function( outline ) { - if ( !outline ) { - outline = new Outline(); - } - outline = this.children[0].combineTo( outline ); return this.children[1].children.reduce(function( outline, component ) { @@ -22493,10 +23078,10 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 38 */ +/* 40 */ /***/ function(module, exports, __webpack_require__) { - var paper = __webpack_require__(33); + var paper = __webpack_require__(35); var Outline = paper.CompoundPath; @@ -22580,7 +23165,7 @@ return /******/ (function(modules) { // webpackBootstrap return reducing; } - var tmp = ( reducing == undefined ? + var tmp = ( reducing == undefined || reducing.isEmpty() ? // when the initial value doesn't exist, use the first path // (clone it otherwise it's removed from this.children) path.clone( false ) : @@ -22601,7 +23186,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 39 */ +/* 41 */ /***/ function(module, exports) { /** @@ -22653,13 +23238,13 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 40 */ +/* 42 */ /***/ function(module, exports, __webpack_require__) { /* Extend the Path prototype to add OpenType conversion * and alias *segments methods and properties to *nodes */ - var paper = __webpack_require__(33); + var paper = __webpack_require__(35); var proto = paper.PaperScope.prototype.Path.prototype; @@ -22788,10 +23373,10 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 41 */ +/* 43 */ /***/ function(module, exports, __webpack_require__) { - var paper = __webpack_require__(33); + var paper = __webpack_require__(35); Object.defineProperty( paper.Segment.prototype, 'x', { get: function() { diff --git a/dist/plumin.js.map b/dist/plumin.js.map index 54309b7..a9847a6 100644 --- a/dist/plumin.js.map +++ b/dist/plumin.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap 67861cee41acdf746a05","webpack:///./src/plumin.js","webpack:///../opentype.js/src/opentype.js","webpack:///../opentype.js/~/tiny-inflate/index.js","webpack:///../opentype.js/src/encoding.js","webpack:///../opentype.js/src/font.js","webpack:///../opentype.js/src/path.js","webpack:///../opentype.js/src/tables/sfnt.js","webpack:///../opentype.js/src/check.js","webpack:///../opentype.js/src/table.js","webpack:///../opentype.js/src/types.js","webpack:///../opentype.js/src/tables/cmap.js","webpack:///../opentype.js/src/parse.js","webpack:///../opentype.js/src/tables/cff.js","webpack:///../opentype.js/src/glyphset.js","webpack:///../opentype.js/src/glyph.js","webpack:///../opentype.js/src/draw.js","webpack:///../opentype.js/src/tables/head.js","webpack:///../opentype.js/src/tables/hhea.js","webpack:///../opentype.js/src/tables/hmtx.js","webpack:///../opentype.js/src/tables/ltag.js","webpack:///../opentype.js/src/tables/maxp.js","webpack:///../opentype.js/src/tables/name.js","webpack:///../opentype.js/src/tables/os2.js","webpack:///../opentype.js/src/tables/post.js","webpack:///../opentype.js/src/util.js","webpack:///fs (ignored)","webpack:///../opentype.js/src/tables/fvar.js","webpack:///../opentype.js/src/tables/glyf.js","webpack:///../opentype.js/src/tables/gpos.js","webpack:///../opentype.js/src/tables/gsub.js","webpack:///../opentype.js/src/tables/kern.js","webpack:///../opentype.js/src/tables/loca.js","webpack:///./~/paper/dist/paper-core.js","webpack:///./node/window.js (ignored)","webpack:///./node/extend.js (ignored)","webpack:///./src/Font.js","webpack:///./src/Glyph.js","webpack:///./src/Outline.js","webpack:///./~/es6-object-assign/src/index.js","webpack:///./src/Path.js","webpack:///./src/Node.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;ACVA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;;;;;;;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;;;;;;AChBA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,oBAAmB,eAAe;AAClC;AACA;AACA;AACA;AACA,4BAA2B,iFAAiF;AAC5G;AACA;;AAEA;AACA;;AAEA;AACA;AACA,gBAAe;AACf,oBAAmB,eAAe;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA,4BAA2B;AAC3B,sEAAqE;AACrE;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,iBAAgB;AAChB,MAAK;AACL,iBAAgB;AAChB;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,gCAA+B,YAAY;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,oBAAmB,eAAe;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;ACpUA;AACA;;AAEA;AACA,oCAAmC;AACnC,qCAAoC;AACpC;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,2BAA0B;AAC1B,2BAA0B;AAC1B;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,cAAa,WAAW;AACxB,cAAa,gBAAgB;;AAE7B;AACA,2BAA0B,QAAQ;AAClC;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,cAAa,OAAO;;AAEpB;AACA;AACA;;AAEA,cAAa,QAAQ;AACrB,cAAa,SAAS;AACtB,cAAa,OAAO;AACpB,cAAa,SAAS;;AAEtB;AACA,cAAa,OAAO;;AAEpB;;AAEA,cAAa,QAAQ;AACrB;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,cAAa,QAAQ;;AAErB;AACA,cAAa,SAAS;;AAEtB;;AAEA;AACA,uBAAsB,QAAQ;AAC9B;AACA;AACA;;AAEA;AACA,cAAa,SAAS;AACtB;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;;AAEH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,cAAa,QAAQ;;AAErB;AACA,cAAa,WAAW;AACxB;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,gBAAe,oBAAoB;AACnC;;AAEA;AACA;AACA;AACA;AACA,+CAA8C,QAAQ;AACtD;AACA;AACA;AACA;AACA;AACA,+CAA8C,QAAQ;AACtD;AACA;AACA;AACA;AACA;AACA,gDAA+C,QAAQ;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,qBAAoB,mBAAmB;AACvC;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA,mBAAkB,GAAG;AACrB;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;ACtXA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,wBAAuB,mBAAmB;AAC1C;AACA,4BAA2B,2BAA2B;AACtD;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,yBAAyB;AAChD;AACA;AACA,kBAAiB;AACjB;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAuB,yBAAyB;AAChD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,oBAAmB,sBAAsB;AACzC;AACA;AACA;AACA;AACA;;AAEA,gBAAe,wBAAwB;AACvC;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AC1OA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,0BAAyB,8BAA8B;AACvD,6BAA4B,6BAA6B;AACzD,wBAAuB,qEAAqE;AAC5F,8BAA6B,qEAAqE;AAClG,wBAAuB,4BAA4B;AACnD,2BAA0B,+BAA+B;AACzD,4BAA2B,gCAAgC;AAC3D,+BAA8B,mCAAmC;AACjE,uBAAsB,2BAA2B;AACjD,0BAAyB,8BAA8B;AACvD,uBAAsB,qCAAqC;AAC3D,2BAA0B,+BAA+B;AACzD,yBAAwB,6BAA6B;AACrD,yBAAwB;AACxB;AACA;AACA;AACA;AACA;AACA,wBAAuB;AACvB;AACA;AACA;AACA,UAAS;AACT;;AAEA,2BAA0B;AAC1B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,oCAAmC;AACnC;AACA;AACA;;AAEA;AACA;AACA,oCAAmC;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,cAAc;AACjC;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,mBAAmB;AACtC;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,oBAAmB,kBAAkB;AACrC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wCAAuC,aAAa;AACpD;AACA;AACA,sDAAqD,sBAAsB;AAC3E;;AAEA;AACA;AACA;AACA,sBAAqB;AACrB,kBAAiB;AACjB,cAAa;AACb,UAAS;AACT;AACA;AACA,UAAS;AACT,MAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACrXA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,0BAA0B;AAC7C;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,sBAAsB;AAC7C;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,oBAAmB,0BAA0B;AAC7C;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;ACvKA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,oBAAmB,kBAAkB;AACrC;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,UAAS,8DAA8D;AACvE,UAAS,8EAA8E;AACvF,UAAS,wEAAwE;AACjF,UAAS;AACT;AACA;;AAEA;AACA;AACA,UAAS,4CAA4C;AACrD,UAAS,4CAA4C;AACrD,UAAS,8CAA8C;AACvD,UAAS,gDAAgD;AACzD,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,2BAA0B,wCAAwC;AAClE;;AAEA,oBAAmB,mBAAmB;AACtC;AACA;AACA;AACA;AACA,4BAA2B,4EAA4E;AACvG,2BAA0B,uDAAuD;AACjF;AACA;AACA;AACA;AACA,+BAA8B,wCAAwC;AACtE;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,oBAAmB,kBAAkB;AACrC;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,oBAAmB,eAAe;AAClC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,oBAAmB,wBAAwB;AAC3C;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,yDAAwD;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAgD,uCAAuC;AACvF;AACA;AACA;AACA,MAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,2BAA0B;AAC1B;;AAEA;AACA,iCAAgC;AAChC;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,gBAAe,wBAAwB;AACvC;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;;;;;AC1UA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;;;;;;ACdA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,gBAAe,mBAAmB;AAClC;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,oBAAmB,uBAAuB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;;;;ACpCA;AACA;;AAEA;;AAEA;;AAEA;;AAEA,qBAAoB;AACpB,0BAAyB;;AAEzB;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,oBAAmB,cAAc;AACjC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,2BAA0B,KAAK,GAAG,KAAK,IAAI,IAAI;AAC/C;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,mCAAkC,QAAQ;AAC1C;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA,qCAAoC,QAAQ;AAC5C;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,cAAc;AACjC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,cAAc;AACjC;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,kDAAiD;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oBAAmB,gBAAgB;AACnC;AACA;AACA,qCAAoC;AACpC;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,0CAAyC,sBAAsB;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,oBAAmB,0BAA0B;AAC7C;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oBAAmB,gBAAgB;AACnC;;AAEA;AACA,qCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB;AACnB;AACA;AACA,gBAAe,cAAc;AAC7B;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,gBAAe,oBAAoB;AACnC;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAuB,iBAAiB;AACxC;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,oBAAmB,YAAY;AAC/B;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,gBAAe,YAAY;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA,gBAAe,sBAAsB;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;;;;;;ACjoBA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,gBAAe,oBAAoB;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,gBAAe,kBAAkB;AACjC;AACA;AACA;AACA;AACA;AACA,iCAAgC,eAAe;AAC/C;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA,UAAS,0CAA0C;AACnD,UAAS,4CAA4C;AACrD,UAAS,6CAA6C;AACtD,UAAS,6CAA6C;AACtD,UAAS,yCAAyC;AAClD,UAAS,yCAAyC;AAClD,UAAS,yCAAyC;AAClD,UAAS,2CAA2C;AACpD,UAAS,6CAA6C;AACtD,UAAS,8CAA8C;AACvD,UAAS,gDAAgD;AACzD,UAAS;AACT;;AAEA;AACA,gBAAe,mBAAmB;AAClC;AACA,wBAAuB,2BAA2B;AAClD;AACA;;AAEA;AACA;AACA,UAAS;AACT;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,gBAAe,cAAc;AAC7B;AACA,uCAAsC,qDAAqD;AAC3F,2CAA0C,yDAAyD;AACnG,qCAAoC,0DAA0D;AAC9F,iDAAgD,kEAAkE;AAClH;AACA,yCAAwC,2DAA2D;AACnG;AACA;;AAEA;AACA,oBAAmB,8CAA8C;AACjE;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;ACzLA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,yBAAwB,gBAAgB;AACxC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,oBAAmB,aAAa;AAChC;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,8BAA6B,eAAe;AAC5C;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,kBAAkB;AACrC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,+BAA8B,4BAA4B;AAC1D;AACA;AACA;AACA,oBAAmB,WAAW;AAC9B;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,WAAW;AAC9B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,mCAAkC;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,WAAW;AAC9B;AACA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,6BAA4B;AAC5B;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,4BAA2B;AAC3B;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,WAAW;AAC9B;AACA,2BAA0B;AAC1B,iCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B,uBAAuB;AAClD;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,wBAAuB,WAAW;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb,UAAS;AACT,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;;;;;;;AChcA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA,wBAAuB,cAAc;AACrC;AACA;AACA;AACA;;AAEA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,eAAe;AAClC;AACA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA;;AAEA,gBAAe,wBAAwB;AACvC;AACA;AACA;AACA;;AAEA;AACA;;AAEA,aAAY;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,oBAAmB,oBAAoB;AACvC;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,oBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAK,oCAAoC;AACzC,MAAK,mCAAmC;AACxC,MAAK,yCAAyC;AAC9C,MAAK,qCAAqC;AAC1C,MAAK,uCAAuC;AAC5C,MAAK,mCAAmC;AACxC,MAAK,yDAAyD;AAC9D,MAAK,wDAAwD;AAC7D,MAAK,iEAAiE;AACtE,MAAK,gEAAgE;AACrE,MAAK,sDAAsD;AAC3D,MAAK,2DAA2D;AAChE,MAAK,wHAAwH;AAC7H,MAAK,yCAAyC;AAC9C,MAAK,6FAA6F;AAClG,MAAK,wDAAwD;AAC7D,MAAK,4CAA4C;AACjD,MAAK,kDAAkD;AACvD,MAAK,mDAAmD;AACxD,MAAK,sDAAsD;AAC3D,MAAK;AACL;;AAEA;AACA,MAAK,gDAAgD;AACrD,MAAK,wDAAwD;AAC7D,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,oBAAmB,aAAa;AAChC;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,wBAAuB,YAAY;AACnC;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,wBAAuB,YAAY;AACnC;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA,MAAK;AACL;AACA;AACA,oBAAmB,aAAa;AAChC;AACA;AACA,gCAA+B,oBAAoB;AACnD;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,qDAAoD;AACpD,qDAAoD;AACpD,2CAA0C;AAC1C;AACA;AACA;AACA;AACA;AACA,uDAAsD;AACtD,qCAAoC;AACpC,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uCAAsC;AACtC,uDAAsD;AACtD,uCAAsC;AACtC,uDAAsD;AACtD,qCAAoC;AACpC,qDAAoD;AACpD;AACA;AACA;AACA;AACA;AACA,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uCAAsC;AACtC,uDAAsD;AACtD,uCAAsC;AACtC,uDAAsD;AACtD,uDAAsD;AACtD,qDAAoD;AACpD;AACA;AACA;AACA;AACA;AACA,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD,uDAAsD;AACtD;AACA;AACA,8BAA6B;AAC7B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,sBAAqB;AACrB;AACA,sBAAqB;AACrB;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,kCAAiC;AACjC;AACA,MAAK,mCAAmC;AACxC;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA,oBAAmB,kBAAkB;AACrC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,UAAS,uCAAuC;AAChD,UAAS,uCAAuC;AAChD,UAAS,yCAAyC;AAClD,UAAS;AACT;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA,oBAAmB,sBAAsB;AACzC,uBAAsB,qDAAqD;AAC3E;;AAEA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;AACA;;AAEA,4BAA2B;AAC3B;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA,oBAAmB,iDAAiD;AACpE;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA,oBAAmB,oBAAoB;AACvC,yBAAwB,uDAAuD;AAC/E;;AAEA;AACA;;AAEA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA,oBAAmB,uBAAuB;AAC1C;AACA;AACA,wBAAuB,iDAAiD;AACxE;;AAEA;AACA;;AAEA;AACA;AACA;AACA,eAAc,yDAAyD;AACvE;AACA;AACA,oBAAmB,0BAA0B;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,uBAAsB,sCAAsC;AAC5D,uBAAsB,sCAAsC;AAC5D,uBAAsB,uCAAuC;AAC7D;AACA;AACA,UAAS;AACT;AACA;AACA,uBAAsB,sCAAsC;AAC5D,uBAAsB,sCAAsC;AAC5D,uBAAsB,sCAAsC;AAC5D;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,uBAAsB,wCAAwC;AAC9D,uBAAsB,wCAAwC;AAC9D,uBAAsB,wCAAwC;AAC9D,uBAAsB,wCAAwC;AAC9D,uBAAsB,sCAAsC;AAC5D,uBAAsB,sCAAsC;AAC5D,uBAAsB,wCAAwC;AAC9D;AACA;AACA;;AAEA;;AAEA;;AAEA,eAAc,uCAAuC;AACrD;AACA;;AAEA;AACA;AACA,UAAS;AACT;;AAEA,oBAAmB,mBAAmB;AACtC;AACA;AACA,6BAA4B,iDAAiD;AAC7E;;AAEA;AACA;;AAEA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS,+BAA+B;AACxC,UAAS,kCAAkC;AAC3C,UAAS,qCAAqC;AAC9C,UAAS,oCAAoC;AAC7C,UAAS,wCAAwC;AACjD,UAAS,iCAAiC;AAC1C,UAAS,yCAAyC;AAClD,UAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,oBAAmB,mBAAmB;AACtC;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,yCAAwC;AACxC;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;ACvlCA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,8BAA6B,yBAAyB;AACtD;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,uCAAsC,yBAAyB;;AAE/D;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uCAAsC,yBAAyB;;AAE/D;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;AC5EA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA,0BAAyB;AACzB;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,UAAS;;AAET;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAiD;AACjD;AACA;AACA;AACA;;AAEA;AACA;AACA,oBAAmB,qBAAqB;AACxC;AACA;AACA;AACA,UAAS;AACT;AACA,UAAS;AACT;AACA;AACA,UAAS;AACT;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oBAAmB,wBAAwB;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,oBAAmB,qBAAqB;AACxC;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wBAAuB,cAAc;AACrC;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,0BAA0B;AAC7C;AACA;AACA,+BAA8B,oBAAoB;AAClD;;AAEA;AACA,8BAA6B,sBAAsB;AACnD;;AAEA;AACA,8BAA6B,sBAAsB;AACnD;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;;;;;;ACzSA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;ACZA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,UAAS,kDAAkD;AAC3D,UAAS,uDAAuD;AAChE,UAAS,oDAAoD;AAC7D,UAAS,sDAAsD;AAC/D,UAAS,wCAAwC;AACjD,UAAS,gDAAgD;AACzD,UAAS,+DAA+D;AACxE,UAAS,yDAAyD;AAClE,UAAS,sCAAsC;AAC/C,UAAS,sCAAsC;AAC/C,UAAS,sCAAsC;AAC/C,UAAS,sCAAsC;AAC/C,UAAS,2CAA2C;AACpD,UAAS,gDAAgD;AACzD,UAAS,mDAAmD;AAC5D,UAAS,kDAAkD;AAC3D,UAAS;AACT;AACA;;AAEA;AACA;;;;;;;ACjEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS,kDAAkD;AAC3D,UAAS,0CAA0C;AACnD,UAAS,2CAA2C;AACpD,UAAS,yCAAyC;AAClD,UAAS,kDAAkD;AAC3D,UAAS,oDAAoD;AAC7D,UAAS,qDAAqD;AAC9D,UAAS,4CAA4C;AACrD,UAAS,gDAAgD;AACzD,UAAS,+CAA+C;AACxD,UAAS,6CAA6C;AACtD,UAAS,2CAA2C;AACpD,UAAS,2CAA2C;AACpD,UAAS,2CAA2C;AACpD,UAAS,2CAA2C;AACpD,UAAS,kDAAkD;AAC3D,UAAS;AACT;AACA;;AAEA;AACA;;;;;;;ACpDA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,eAAe;AAClC;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oBAAmB,mBAAmB;AACtC;AACA;AACA;AACA,wBAAuB,+DAA+D;AACtF,wBAAuB,oEAAoE;AAC3F;;AAEA;AACA;;AAEA;AACA;;;;;;;ACzCA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,UAAS,yCAAyC;AAClD,UAAS,uCAAuC;AAChD,UAAS;AACT;;AAEA;AACA;AACA,oBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;;AAEA,6BAA4B,mEAAmE;AAC/F,6BAA4B,2DAA2D;AACvF;;AAEA,yBAAwB,yDAAyD;AACjF;AACA;;AAEA;AACA;AACA;AACA;AACA,2DAA0D;AAC1D;AACA;;AAEA;AACA,oBAAmB,aAAa;AAChC;AACA;AACA;AACA,6BAA4B,qBAAqB;AACjD;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;AC5DA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,UAAS,kDAAkD;AAC3D,UAAS;AACT;AACA;;AAEA;AACA;;;;;;;AC1CA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,WAAW;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,KAAI,UAAU,IAAI;AAClB,sBAAqB;AACrB;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,UAAS,sDAAsD;AAC/D,UAAS,sDAAsD;AAC/D,UAAS,sDAAsD;AAC/D,UAAS,8CAA8C;AACvD,UAAS,8CAA8C;AACvD,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAqB,aAAa;AAClC,eAAc,aAAa;AAC3B,4BAA2B,kBAAkB;AAC7C;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,wCAAuC,SAAS;AAChD;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,oBAAmB,oBAAoB;AACvC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAiD;AACjD;AACA;AACA;AACA,iCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA,iCAAgC;AAChC;AACA;AACA;AACA;AACA;;AAEA,+BAA8B;AAC9B;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA,UAAS,yCAAyC;AAClD,UAAS,yDAAyD;AAClE,UAAS;AACT;;AAEA,oBAAmB,wBAAwB;AAC3C,wBAAuB,2DAA2D;AAClF;;AAEA,oBAAmB,oDAAoD;AACvE;AACA;;AAEA;AACA;;;;;;;AC7zBA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,6BAA6B;AAClC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,2BAA2B;AAChC,MAAK,6BAA6B;AAClC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,2BAA2B;AAChC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC,MAAK,6BAA6B;AAClC;;AAEA;AACA,oBAAmB,0BAA0B;AAC7C;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,QAAQ;AAC3B;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,UAAS,+CAA+C;AACxD,UAAS,+CAA+C;AACxD,UAAS,gDAAgD;AACzD,UAAS,+CAA+C;AACxD,UAAS,yCAAyC;AAClD,UAAS,mDAAmD;AAC5D,UAAS,mDAAmD;AAC5D,UAAS,mDAAmD;AAC5D,UAAS,qDAAqD;AAC9D,UAAS,qDAAqD;AAC9D,UAAS,qDAAqD;AAC9D,UAAS,qDAAqD;AAC9D,UAAS,uDAAuD;AAChE,UAAS,iDAAiD;AAC1D,UAAS,sDAAsD;AAC/D,UAAS,8CAA8C;AACvD,UAAS,4CAA4C;AACrD,UAAS,4CAA4C;AACrD,UAAS,wCAAwC;AACjD,UAAS,4CAA4C;AACrD,UAAS,0CAA0C;AACnD,UAAS,iDAAiD;AAC1D,UAAS,0CAA0C;AACnD,UAAS,4CAA4C;AACrD,UAAS,yCAAyC;AAClD,UAAS,yCAAyC;AAClD,UAAS,iDAAiD;AAC1D,UAAS,iDAAiD;AAC1D,UAAS,iDAAiD;AAC1D,UAAS,iDAAiD;AAC1D,UAAS,oDAAoD;AAC7D,UAAS,8CAA8C;AACvD,UAAS,mDAAmD;AAC5D,UAAS,kDAAkD;AAC3D,UAAS,+CAA+C;AACxD,UAAS,gDAAgD;AACzD,UAAS,8CAA8C;AACvD,UAAS,8CAA8C;AACvD,UAAS,+CAA+C;AACxD,UAAS,kDAAkD;AAC3D,UAAS,kDAAkD;AAC3D,UAAS,0CAA0C;AACnD,UAAS,4CAA4C;AACrD,UAAS,gDAAgD;AACzD,UAAS,8CAA8C;AACvD,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;;;;;;;AC7PA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,yBAAyB;AAChD;AACA;;AAEA;AACA,wBAAuB,yBAAyB;AAChD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,wBAAuB,yBAAyB;AAChD;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAS,kDAAkD;AAC3D,UAAS,6CAA6C;AACtD,UAAS,mDAAmD;AAC5D,UAAS,oDAAoD;AAC7D,UAAS,8CAA8C;AACvD,UAAS,8CAA8C;AACvD,UAAS,8CAA8C;AACvD,UAAS,6CAA6C;AACtD,UAAS;AACT;AACA;;AAEA;AACA;;;;;;;ACtEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,mBAAmB;AACtC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,mBAAmB;AACtC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;AClCA,gB;;;;;;ACAA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS,+CAA+C;AACxD,UAAS,iEAAiE;AAC1E,UAAS,yEAAyE;AAClF,UAAS,iEAAiE;AAC1E,UAAS,6CAA6C;AACtD,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAwB,wBAAwB;AAChD;AACA;AACA;;AAEA;AACA;AACA;AACA,UAAS,mDAAmD;AAC5D,UAAS;AACT;;AAEA,oBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,yBAAwB,wBAAwB;;AAEhD;AACA,oBAAmB,iBAAiB;AACpC;AACA;;AAEA;AACA;;AAEA;AACA;AACA,UAAS,+CAA+C;AACxD,UAAS,+CAA+C;AACxD,UAAS,iDAAiD;AAC1D,UAAS,2DAA2D;AACpE,UAAS,4CAA4C;AACrD,UAAS,oEAAoE;AAC7E,UAAS;AACT;AACA;;AAEA,oBAAmB,sBAAsB;AACzC;AACA;;AAEA,oBAAmB,2BAA2B;AAC9C;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oBAAmB,eAAe;AAClC;AACA;;AAEA;AACA;AACA,oBAAmB,mBAAmB;AACtC;AACA;;AAEA,aAAY;AACZ;;AAEA;AACA;;;;;;;AC1IA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,4BAA4B;AAC/C;AACA;;AAEA;AACA;AACA,oBAAmB,6BAA6B;AAChD;AACA;;AAEA;AACA;AACA,oBAAmB,yBAAyB;AAC5C;AACA;AACA;AACA;AACA;AACA,gCAA+B,iBAAiB;AAChD;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,4BAA2B,yBAAyB;AACpD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,4BAA2B,yBAAyB;AACpD;AACA;AACA;AACA;AACA;;AAEA;AACA,4BAA2B,yBAAyB;AACpD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,UAAS;AACT;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,mBAAmB;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,oBAAmB,mBAAmB;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oBAAmB,qBAAqB;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,4BAA2B;AAC3B;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA,6CAA4C,oBAAoB;AAChE;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,cAAa;AACb,8BAA6B;AAC7B;AACA;AACA,cAAa;AACb;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,6BAA6B;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,gBAAe,qBAAqB;AACpC;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA;;;;;;;AC5SA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,OAAO;AAC1B,+BAA8B;AAC9B;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,eAAc,SAAS;AACvB;AACA;AACA;AACA,gCAA+B,UAAU;AACzC;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,wBAAuB,gBAAgB;AACvC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB;AACjB;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAgC,2BAA2B;AAC3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAsB,kBAAkB;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,wBAAuB,iBAAiB;AACxC;AACA,4BAA2B,iBAAiB;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oBAAmB,qBAAqB;;AAExC;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,mBAAmB;AAC1C;AACA;AACA;AACA;AACA,2CAA0C,KAAK;AAC/C;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;;AAEA;;;;;;;AC3OA;AACA;;AAEA;;AAEA;AACA;AACA,oCAAmC;;AAEnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AC3MA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;;;;;;AClCA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,mBAAmB;AACtC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;;;;;;AChCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oCAAmC,OAAO;AAC1C;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA,yCAAwC,OAAO;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAY;AACZ;AACA,WAAU,qBAAqB;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,qBAAqB;AACvC;AACA;AACA;AACA;;AAEA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yCAAwC,OAAO;AAC/C;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,gCAA+B;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM,kDAAkD;AACxD;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA;;AAEA;AACA,yCAAwC,OAAO;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,KAAI,sBAAsB;AAC1B,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,uBAAsB,SAAS;AAC/B;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,oCAAmC,OAAO;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAoB;AACpB,oBAAmB;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,oCAAmC,OAAO;AAC1C;AACA;AACA,KAAI;AACJ;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAA+C,OAAO;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,YAAY;AAC9B;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA,kDAAiD,OAAO;AACxD;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,KAAI;AACJ,IAAG;;AAEH;AACA;AACA;AACA,KAAI;AACJ,IAAG;;AAEH;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,IAAG;AACH,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,IAAG;AACH;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,oCAAmC,QAAQ;AAC3C;AACA,iCAAgC,QAAQ;AACxC;AACA,oCAAmC,QAAQ;AAC3C;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,eAAc;AACd;;AAEA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA,EAAC;;AAED;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,EAAC;;AAED;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;;AAEH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA,mBAAkB,OAAO;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,YAAW;;AAEX;AACA;AACA;AACA;AACA,iCAAgC;AAChC;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,YAAW,2DAA2D;AACtE,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA,EAAC,IAAI;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,YAAW;AACX,iDAAgD;AAChD,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA,EAAC,IAAI;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,YAAW;AACX;AACA;AACA;AACA,UAAS;AACT,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,uCAAsC,iBAAiB;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,uCAAsC,iBAAiB;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,uCAAsC,iBAAiB;AACvD;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA,mCAAkC,SAAS;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,kBAAiB,OAAO;AACxB;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA,iCAAgC;AAChC,GAAE;;AAEF;AACA,iCAAgC;AAChC,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC,IAAI;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,qCAAoC,2BAA2B;AAC/D;AACA;AACA,GAAE;;AAEF;AACA;AACA,oCAAmC,QAAQ;AAC3C;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA,0CAAyC,8BAA8B;AACvE,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,uCAAsC,OAAO;AAC7C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA,uCAAsC;AACtC;AACA;AACA,IAAG;;AAEH,eAAc;AACd,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,OAAM;;AAEN;AACA;AACA;AACA,MAAK;;AAEL,eAAc;AACd;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,GAAE;;AAEF;AACA,iBAAgB;AAChB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF,GAAE;AACF;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA,2CAA0C,8BAA8B;AACxE;AACA;AACA,EAAC;AACD,qBAAoB,eAAe;AACnC,qBAAoB,eAAe;AACnC,uBAAsB;AACtB,GAAE;AACF;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA,sBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,cAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,wDAAuD,OAAO;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;AACD;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,wCAAuC,8BAA8B;AACrE;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,EAAC;AACD;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,oDAAmD,OAAO;AAC1D;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,mDAAkD,OAAO;AACzD;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,mDAAkD,OAAO;AACzD;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,mCAAkC,OAAO;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA4B,qBAAqB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,qCAAoC,QAAQ;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,IAAG;AACH,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,wBAAuB;AACvB;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA,qCAAoC,QAAQ;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAoB,6CAA6C;AACjE;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,QAAO,wCAAwC;AAC/C;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,eAAe;AAClC;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA,8BAA6B;AAC7B;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA,oDAAmD,OAAO;AAC1D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,kCAAiC,QAAQ;AACzC;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA,GAAE;;AAEF;;AAEA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,mCAAkC,QAAQ;AAC1C;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA,8CAA6C,OAAO;AACpD;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,4DAA2D,OAAO;AAClE;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF,EAAC;AACD;AACA;AACA;AACA,uCAAsC,iBAAiB;AACvD;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,2CAA0C,aAAa;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,OAAO;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,OAAO;AAC1B;AACA;AACA;AACA;AACA,oBAAmB,OAAO;AAC1B;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,gBAAe,YAAY,gBAAgB;AAC3C;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,yBAAwB,kCAAkC;AAC1D;AACA;AACA;AACA,IAAG;AACH,qCAAoC,aAAa;AACjD;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA,mBAAkB,OAAO;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,YAAW;AACX;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,mBAAkB,+BAA+B;AACjD;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,KAAI;AACJ;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA4B,iCAAiC;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,OAAO;AACxB;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA,mBAAkB,eAAe;AACjC;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;;AAEA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,IAAG;AACH,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA,2BAA0B;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,2BAA2B;AACtC,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,2BAA2B;AACtC,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,kBAAiB,OAAO;AACxB;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,wBAAuB;AACvB,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,OAAO;AACxB;AACA,mBAAkB,WAAW;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,kBAAiB,YAAY;AAC7B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,kBAAiB,OAAO;AACxB;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,WAAW;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA,EAAC;AACD;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD,aAAY;;AAEZ;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;;AAEA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,UAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA,mCAAkC,OAAO;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAgB,OAAO;AACvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,WAAW;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,UAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,OAAO;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAsC,WAAW;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,WAAW;AAC9B;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAW,2BAA2B;AACtC,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA;;AAEA;AACA,6BAA4B,wBAAwB;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA,UAAS;AACT;;AAEA;AACA;AACA,sCAAqC,QAAQ;AAC7C;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;;AAEA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,6CAA4C,OAAO;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,qBAAoB,+BAA+B;AACnD;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,aAAa;AAC9B;AACA,kBAAiB,aAAa;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,kCAAiC,aAAa;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,IAAG;AACH,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAwB,YAAY;AACpC;AACA;AACA,IAAG;AACH;AACA;AACA,kBAAiB,YAAY;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8BAA6B,eAAe;AAC5C;AACA;AACA,+BAA8B,gBAAgB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,+CAA8C,OAAO;AACrD;AACA;AACA,IAAG;AACH;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8CAA6C;AAC7C;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,YAAY;AAC9B;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,kBAAiB,YAAY;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,YAAY;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA,qDAAoD,OAAO;AAC3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAuB,SAAS;AAChC;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,sBAAqB,SAAS;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,YAAY;AAC7B;AACA;AACA;AACA;AACA;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;AACA;AACA,mCAAkC,QAAQ;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,sCAAqC,OAAO;AAC5C;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8CAA6C,OAAO;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,kBAAiB,YAAY;AAC7B;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,kCAAiC,QAAQ;AACzC;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,6CAA4C,OAAO;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,kBAAiB,YAAY;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,wBAAuB;AACvB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2CAA0C,QAAQ;AAClD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,OAAO;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,uBAAsB,QAAQ;AAC9B;AACA;AACA;AACA;AACA;;AAEA;AACA,eAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH,sBAAqB,SAAS;AAC9B;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,aAAa;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,sBAAqB,+BAA+B;AACpD;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH,mBAAkB,iBAAiB;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,oBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAO;AACP;AACA;;AAEA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;AACD;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA,kBAAiB,YAAY;AAC7B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,YAAY;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,mBAAkB,OAAO;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;;AAEA;AACA,kBAAiB,YAAY;AAC7B;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA,mBAAkB,OAAO;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF,cAAa;;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,kBAAiB,OAAO;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,QAAO,iBAAiB;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;;AAEA;AACA;AACA;AACA,IAAG;;AAEH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,WAAW;AAC7B;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,YAAY;AAC9B;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,iCAAgC,QAAQ;AACxC;AACA;AACA;AACA;AACA,yBAAwB,gCAAgC;AACxD,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,oCAAmC,QAAQ;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA,EAAC;AACD;;AAEA;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA,mBAAkB,YAAY,cAAc;AAC5C;AACA,GAAE;;AAEF;AACA;AACA;AACA;;AAEA,yBAAwB,oCAAoC;AAC5D;AACA,uCAAsC,OAAO;AAC7C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA,EAAC,IAAI;;AAEL;AACA;AACA;AACA;AACA;AACA,gBAAe,UAAU;AACzB,gBAAe,UAAU;AACzB,gBAAe,UAAU;AACzB,gBAAe;AACf;;AAEA;AACA,uCAAsC,iBAAiB;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,4BAA2B,iBAAiB;AAC5C;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,yCAAwC,eAAe;AACvD;AACA,0CAAyC,eAAe;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,yCAAwC,OAAO;AAC/C;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,qCAAoC,QAAQ;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,qCAAoC,QAAQ;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,0CAAyC,OAAO;AAChD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;;AAEA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAe,iDAAiD;AAChE;AACA;AACA,IAAG;AACH;AACA,oCAAmC,OAAO;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAU;AACV;AACA;AACA;AACA;AACA,iCAAgC,QAAQ;AACxC;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA,MAAK;AACL,sCAAqC,QAAQ;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA,MAAK;AACL;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM,IAAI;AACV;AACA;AACA,OAAM;AACN;AACA;AACA;AACA,qBAAoB,aAAa;AACjC;AACA;AACA;AACA;AACA;AACA;AACA,2BAA0B,uBAAuB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6CAA4C,OAAO;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAqC,cAAc,EAAE;AACrD;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;;AAEA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;AACA;AACA,SAAQ,YAAY;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,2CAA0C,QAAQ;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA,GAAE,IAAI;AACN;;AAEA;AACA;AACA;AACA;AACA;AACA,6CAA4C,OAAO;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAiB,QAAQ;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,KAAI;AACJ;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA,sBAAqB,WAAW;AAChC;AACA;AACA,gCAA+B,OAAO;AACtC;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,kBAAiB,QAAQ;AACzB;AACA;AACA,kBAAiB,QAAQ;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,kBAAiB,aAAa;AAC9B,mBAAkB,iBAAiB;AACnC;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,0BAAyB,WAAW;AACpC;AACA;AACA;AACA,oCAAmC,QAAQ;AAC3C;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,0BAAyB,UAAU;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF,mBAAkB,+BAA+B;;AAEjD;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oCAAmC,OAAO;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,2BAA0B;AAC1B,kBAAiB;AACjB;;AAEA;AACA,mCAAkC,IAAI,KAAK,IAAI,KAAK,IAAI;AACxD;AACA;AACA;AACA,mBAAkB,OAAO;AACzB;AACA;AACA;AACA;AACA,IAAG;AACH;AACA,0CAAyC,OAAO;AAChD;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,OAAO;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0BAAyB,iBAAiB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAQ;AACR;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA,8CAA6C,OAAO;AACpD;AACA;AACA;AACA;AACA;AACA,OAAM;AACN;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6CAA4C,OAAO;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,0CAAyC,OAAO;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAY,2BAA2B;AACvC,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF,EAAC;AACD;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF,GAAE;AACF,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,IAAG;AACH,GAAE;;AAEF;AACA,2DAA0D,OAAO;AACjE;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,0CAAyC,OAAO;AAChD;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAqC,OAAO;AAC5C;AACA;AACA,2DAA0D,cAAc;AACxE,qCAAoC,OAAO;AAC3C;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAmB,YAAY;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA,yCAAwC,cAAc;AACtD;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF,6BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA,GAAE;AACF,4BAA2B;AAC3B;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,yCAAwC,OAAO;AAC/C;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,UAAS,8BAA8B;AACvC;AACA;AACA;AACA;AACA,KAAI;AACJ,yCAAwC,OAAO;AAC/C;AACA;AACA;AACA,OAAM;AACN;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;AACA;AACA;AACA,kBAAiB,OAAO;AACxB;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,aAAY;AACZ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAqC,OAAO;AAC5C;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,sCAAqC,OAAO;AAC5C;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAsB,WAAW,aAAa;AAC9C;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,MAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA,uCAAsC,iBAAiB;AACvD;AACA;AACA;AACA,EAAC;AACD;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,wCAAuC,8BAA8B;AACrE;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF,EAAC;AACD;AACA;AACA,iBAAgB;AAChB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,qBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,oCAAmC,OAAO;AAC1C;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA,YAAW;AACX;AACA;AACA;AACA,UAAS;AACT;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH,cAAa;AACb,eAAc;AACd;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA,YAAW;AACX;AACA;AACA;AACA;AACA,UAAS;AACT;AACA,EAAC;;AAED;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA,YAAW;AACX;AACA;AACA;AACA,UAAS;AACT;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE,IAAI;;AAEN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAkC,OAAO;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA,EAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG,IAAI;AACP;AACA;AACA;AACA;AACA,EAAC,IAAI;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,uCAAsC,OAAO;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAM;AACN,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAkB,YAAY;AAC9B;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,iBAAgB;AAChB;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA,+BAA8B;;AAE9B;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,mBAAkB,QAAQ,UAAU;AACpC;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA2B;AAC3B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4CAA2C,eAAe;AAC1D,sCAAqC,iBAAiB;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAuC,OAAO;AAC9C;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA;;AAEA,sBAAqB;AACrB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oCAAmC,OAAO;AAC1C;AACA;AACA;AACA,oCAAmC,OAAO;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,qCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA,KAAI;AACJ,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,0CAAyC,OAAO;AAChD;AACA;AACA;AACA;AACA;AACA;AACA,kCAAiC,OAAO;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE,IAAI;AACN;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA,IAAG;;AAEH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,2CAA0C;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA8B;AAC9B,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,8CAA6C;AAC7C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA,EAAC;AACD;AACA;;AAEA;AACA,EAAC;;;;;;;AClqcD,gB;;;;;;ACAA,gB;;;;;;ACAA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,GAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA,EAAC;;AAED;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;;AAEH;AACA,GAAE;AACF;AACA;AACA,IAAG;;AAEH,GAAE;AACF;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;;AAEA;AACA,IAAG,IAAI;AACP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,kBAAiB,0BAA0B;AAC3C;AACA;AACA;AACA;AACA,KAAI;;AAEJ;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA,IAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,QAAO;AACP;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,kBAAiB,qCAAqC;AACtD,4BAA2B,EAAE;AAC7B;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAI;AACJ;;AAEA;AACA;AACA,KAAI;AACJ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAe,oCAAoC;AACnD;AACA,KAAI;AACJ;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA,KAAI;AACJ;;AAEA;AACA;;AAEA;;AAEA;;;;;;;AC1XA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,GAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,EAAC;;AAED;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,GAAE;AACF;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;;;;;;;ACrRA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,2CAA0C,OAAO;AACjD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAE;;AAEF;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,4BAA2B,oBAAoB;AAC/C;AACA;;AAEA,GAAE;AACF;;AAEA;;;;;;;ACrGA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,kBAAiB,sBAAsB;AACvC;AACA;AACA;AACA;;AAEA;AACA,oDAAmD,iBAAiB;AACpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;;;;;;;AC7CA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,sCAAqC,SAAS;AAC9C;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ,IAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAI;AACJ;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,IAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;;;;;;;AChIA;;AAEA;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA,EAAC;;AAED;AACA;AACA;AACA,GAAE;AACF;AACA;AACA;AACA,EAAC;;AAED","file":"plumin.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"plumin\"] = factory();\n\telse\n\t\troot[\"plumin\"] = factory();\n})(this, function() {\nreturn \n\n\n/** WEBPACK FOOTER **\n ** webpack/universalModuleDefinition\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 67861cee41acdf746a05\n **/","var opentype = require('opentype.js');\nvar paper = require('paper');\nvar Font = require('./Font.js');\nvar Glyph = require('./Glyph.js');\nvar Outline = require('./Outline');\nvar Path = require('./Path.js');\nvar Node = require('./Node.js');\n\npaper.PaperScope.prototype.Font = Font;\npaper.PaperScope.prototype.Glyph = Glyph;\npaper.PaperScope.prototype.Outline = Outline;\npaper.PaperScope.prototype.Path = Path;\npaper.PaperScope.prototype.Node = Node;\n\npaper.opentype = opentype;\n\nmodule.exports = paper;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/plumin.js\n ** module id = 1\n ** module chunks = 0\n **/","// opentype.js\n// https://github.com/nodebox/opentype.js\n// (c) 2015 Frederik De Bleser\n// opentype.js may be freely distributed under the MIT license.\n\n/* global DataView, Uint8Array, XMLHttpRequest */\n\n'use strict';\n\nvar inflate = require('tiny-inflate');\n\nvar encoding = require('./encoding');\nvar _font = require('./font');\nvar glyph = require('./glyph');\nvar parse = require('./parse');\nvar path = require('./path');\nvar util = require('./util');\n\nvar cmap = require('./tables/cmap');\nvar cff = require('./tables/cff');\nvar fvar = require('./tables/fvar');\nvar glyf = require('./tables/glyf');\nvar gpos = require('./tables/gpos');\nvar gsub = require('./tables/gsub');\nvar head = require('./tables/head');\nvar hhea = require('./tables/hhea');\nvar hmtx = require('./tables/hmtx');\nvar kern = require('./tables/kern');\nvar ltag = require('./tables/ltag');\nvar loca = require('./tables/loca');\nvar maxp = require('./tables/maxp');\nvar _name = require('./tables/name');\nvar os2 = require('./tables/os2');\nvar post = require('./tables/post');\n\n// File loaders /////////////////////////////////////////////////////////\n\nfunction loadFromFile(path, callback) {\n var fs = require('fs');\n fs.readFile(path, function(err, buffer) {\n if (err) {\n return callback(err.message);\n }\n\n callback(null, util.nodeBufferToArrayBuffer(buffer));\n });\n}\n\nfunction loadFromUrl(url, callback) {\n var request = new XMLHttpRequest();\n request.open('get', url, true);\n request.responseType = 'arraybuffer';\n request.onload = function() {\n if (request.status !== 200) {\n return callback('Font could not be loaded: ' + request.statusText);\n }\n\n return callback(null, request.response);\n };\n\n request.send();\n}\n\n// Table Directory Entries //////////////////////////////////////////////\n\nfunction parseOpenTypeTableEntries(data, numTables) {\n var tableEntries = [];\n var p = 12;\n for (var i = 0; i < numTables; i += 1) {\n var tag = parse.getTag(data, p);\n var checksum = parse.getULong(data, p + 4);\n var offset = parse.getULong(data, p + 8);\n var length = parse.getULong(data, p + 12);\n tableEntries.push({tag: tag, checksum: checksum, offset: offset, length: length, compression: false});\n p += 16;\n }\n\n return tableEntries;\n}\n\nfunction parseWOFFTableEntries(data, numTables) {\n var tableEntries = [];\n var p = 44; // offset to the first table directory entry.\n for (var i = 0; i < numTables; i += 1) {\n var tag = parse.getTag(data, p);\n var offset = parse.getULong(data, p + 4);\n var compLength = parse.getULong(data, p + 8);\n var origLength = parse.getULong(data, p + 12);\n var compression;\n if (compLength < origLength) {\n compression = 'WOFF';\n } else {\n compression = false;\n }\n\n tableEntries.push({tag: tag, offset: offset, compression: compression,\n compressedLength: compLength, originalLength: origLength});\n p += 20;\n }\n\n return tableEntries;\n}\n\nfunction uncompressTable(data, tableEntry) {\n if (tableEntry.compression === 'WOFF') {\n var inBuffer = new Uint8Array(data.buffer, tableEntry.offset + 2, tableEntry.compressedLength - 2);\n var outBuffer = new Uint8Array(tableEntry.originalLength);\n inflate(inBuffer, outBuffer);\n if (outBuffer.byteLength !== tableEntry.originalLength) {\n throw new Error('Decompression error: ' + tableEntry.tag + ' decompressed length doesn\\'t match recorded length');\n }\n\n var view = new DataView(outBuffer.buffer, 0);\n return {data: view, offset: 0};\n } else {\n return {data: data, offset: tableEntry.offset};\n }\n}\n\n// Public API ///////////////////////////////////////////////////////////\n\n// Parse the OpenType file data (as an ArrayBuffer) and return a Font object.\n// Throws an error if the font could not be parsed.\nfunction parseBuffer(buffer) {\n var indexToLocFormat;\n var ltagTable;\n\n // Since the constructor can also be called to create new fonts from scratch, we indicate this\n // should be an empty font that we'll fill with our own data.\n var font = new _font.Font({empty: true});\n\n // OpenType fonts use big endian byte ordering.\n // We can't rely on typed array view types, because they operate with the endianness of the host computer.\n // Instead we use DataViews where we can specify endianness.\n var data = new DataView(buffer, 0);\n var numTables;\n var tableEntries = [];\n var signature = parse.getTag(data, 0);\n if (signature === String.fromCharCode(0, 1, 0, 0)) {\n font.outlinesFormat = 'truetype';\n numTables = parse.getUShort(data, 4);\n tableEntries = parseOpenTypeTableEntries(data, numTables);\n } else if (signature === 'OTTO') {\n font.outlinesFormat = 'cff';\n numTables = parse.getUShort(data, 4);\n tableEntries = parseOpenTypeTableEntries(data, numTables);\n } else if (signature === 'wOFF') {\n var flavor = parse.getTag(data, 4);\n if (flavor === String.fromCharCode(0, 1, 0, 0)) {\n font.outlinesFormat = 'truetype';\n } else if (flavor === 'OTTO') {\n font.outlinesFormat = 'cff';\n } else {\n throw new Error('Unsupported OpenType flavor ' + signature);\n }\n\n numTables = parse.getUShort(data, 12);\n tableEntries = parseWOFFTableEntries(data, numTables);\n } else {\n throw new Error('Unsupported OpenType signature ' + signature);\n }\n\n var cffTableEntry;\n var fvarTableEntry;\n var glyfTableEntry;\n var gposTableEntry;\n var gsubTableEntry;\n var hmtxTableEntry;\n var kernTableEntry;\n var locaTableEntry;\n var nameTableEntry;\n\n for (var i = 0; i < numTables; i += 1) {\n var tableEntry = tableEntries[i];\n var table;\n switch (tableEntry.tag) {\n case 'cmap':\n table = uncompressTable(data, tableEntry);\n font.tables.cmap = cmap.parse(table.data, table.offset);\n font.encoding = new encoding.CmapEncoding(font.tables.cmap);\n break;\n case 'fvar':\n fvarTableEntry = tableEntry;\n break;\n case 'head':\n table = uncompressTable(data, tableEntry);\n font.tables.head = head.parse(table.data, table.offset);\n font.unitsPerEm = font.tables.head.unitsPerEm;\n indexToLocFormat = font.tables.head.indexToLocFormat;\n break;\n case 'hhea':\n table = uncompressTable(data, tableEntry);\n font.tables.hhea = hhea.parse(table.data, table.offset);\n font.ascender = font.tables.hhea.ascender;\n font.descender = font.tables.hhea.descender;\n font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics;\n break;\n case 'hmtx':\n hmtxTableEntry = tableEntry;\n break;\n case 'ltag':\n table = uncompressTable(data, tableEntry);\n ltagTable = ltag.parse(table.data, table.offset);\n break;\n case 'maxp':\n table = uncompressTable(data, tableEntry);\n font.tables.maxp = maxp.parse(table.data, table.offset);\n font.numGlyphs = font.tables.maxp.numGlyphs;\n break;\n case 'name':\n nameTableEntry = tableEntry;\n break;\n case 'OS/2':\n table = uncompressTable(data, tableEntry);\n font.tables.os2 = os2.parse(table.data, table.offset);\n break;\n case 'post':\n table = uncompressTable(data, tableEntry);\n font.tables.post = post.parse(table.data, table.offset);\n font.glyphNames = new encoding.GlyphNames(font.tables.post);\n break;\n case 'glyf':\n glyfTableEntry = tableEntry;\n break;\n case 'loca':\n locaTableEntry = tableEntry;\n break;\n case 'CFF ':\n cffTableEntry = tableEntry;\n break;\n case 'kern':\n kernTableEntry = tableEntry;\n break;\n case 'GPOS':\n gposTableEntry = tableEntry;\n break;\n case 'GSUB':\n gsubTableEntry = tableEntry;\n break;\n }\n }\n\n var nameTable = uncompressTable(data, nameTableEntry);\n font.tables.name = _name.parse(nameTable.data, nameTable.offset, ltagTable);\n font.names = font.tables.name;\n\n if (glyfTableEntry && locaTableEntry) {\n var shortVersion = indexToLocFormat === 0;\n var locaTable = uncompressTable(data, locaTableEntry);\n var locaOffsets = loca.parse(locaTable.data, locaTable.offset, font.numGlyphs, shortVersion);\n var glyfTable = uncompressTable(data, glyfTableEntry);\n font.glyphs = glyf.parse(glyfTable.data, glyfTable.offset, locaOffsets, font);\n } else if (cffTableEntry) {\n var cffTable = uncompressTable(data, cffTableEntry);\n cff.parse(cffTable.data, cffTable.offset, font);\n } else {\n throw new Error('Font doesn\\'t contain TrueType or CFF outlines.');\n }\n\n var hmtxTable = uncompressTable(data, hmtxTableEntry);\n hmtx.parse(hmtxTable.data, hmtxTable.offset, font.numberOfHMetrics, font.numGlyphs, font.glyphs);\n encoding.addGlyphNames(font);\n\n if (kernTableEntry) {\n var kernTable = uncompressTable(data, kernTableEntry);\n font.kerningPairs = kern.parse(kernTable.data, kernTable.offset);\n } else {\n font.kerningPairs = {};\n }\n\n if (gposTableEntry) {\n var gposTable = uncompressTable(data, gposTableEntry);\n gpos.parse(gposTable.data, gposTable.offset, font);\n }\n if (gsubTableEntry) {\n var gsubTable = uncompressTable(data, gsubTableEntry);\n font.tables.gsub = gsub.parse(gsubTable.data, gsubTable.offset);\n }\n\n if (fvarTableEntry) {\n var fvarTable = uncompressTable(data, fvarTableEntry);\n font.tables.fvar = fvar.parse(fvarTable.data, fvarTable.offset, font.names);\n }\n\n return font;\n}\n\n// Asynchronously load the font from a URL or a filesystem. When done, call the callback\n// with two arguments `(err, font)`. The `err` will be null on success,\n// the `font` is a Font object.\n//\n// We use the node.js callback convention so that\n// opentype.js can integrate with frameworks like async.js.\nfunction load(url, callback) {\n var isNode = typeof window === 'undefined';\n var loadFn = isNode ? loadFromFile : loadFromUrl;\n loadFn(url, function(err, arrayBuffer) {\n if (err) {\n return callback(err);\n }\n var font;\n try {\n font = parseBuffer(arrayBuffer);\n } catch (e) {\n return callback(e, null);\n }\n return callback(null, font);\n });\n}\n\n// Synchronously load the font from a URL or file.\n// When done, return the font object or throw an error.\nfunction loadSync(url) {\n var fs = require('fs');\n var buffer = fs.readFileSync(url);\n return parseBuffer(util.nodeBufferToArrayBuffer(buffer));\n}\n\nexports._parse = parse;\nexports.Font = _font.Font;\nexports.Glyph = glyph.Glyph;\nexports.Path = path.Path;\nexports.parse = parseBuffer;\nexports.load = load;\nexports.loadSync = loadSync;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/opentype.js\n ** module id = 2\n ** module chunks = 0\n **/","var TINF_OK = 0;\nvar TINF_DATA_ERROR = -3;\n\nfunction Tree() {\n this.table = new Uint16Array(16); /* table of code length counts */\n this.trans = new Uint16Array(288); /* code -> symbol translation table */\n}\n\nfunction Data(source, dest) {\n this.source = source;\n this.sourceIndex = 0;\n this.tag = 0;\n this.bitcount = 0;\n \n this.dest = dest;\n this.destLen = 0;\n \n this.ltree = new Tree(); /* dynamic length/symbol tree */\n this.dtree = new Tree(); /* dynamic distance tree */\n}\n\n/* --------------------------------------------------- *\n * -- uninitialized global data (static structures) -- *\n * --------------------------------------------------- */\n\nvar sltree = new Tree();\nvar sdtree = new Tree();\n\n/* extra bits and base tables for length codes */\nvar length_bits = new Uint8Array(30);\nvar length_base = new Uint16Array(30);\n\n/* extra bits and base tables for distance codes */\nvar dist_bits = new Uint8Array(30);\nvar dist_base = new Uint16Array(30);\n\n/* special ordering of code length codes */\nvar clcidx = new Uint8Array([\n 16, 17, 18, 0, 8, 7, 9, 6,\n 10, 5, 11, 4, 12, 3, 13, 2,\n 14, 1, 15\n]);\n\n/* used by tinf_decode_trees, avoids allocations every call */\nvar code_tree = new Tree();\nvar lengths = new Uint8Array(288 + 32);\n\n/* ----------------------- *\n * -- utility functions -- *\n * ----------------------- */\n\n/* build extra bits and base tables */\nfunction tinf_build_bits_base(bits, base, delta, first) {\n var i, sum;\n\n /* build bits table */\n for (i = 0; i < delta; ++i) bits[i] = 0;\n for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta | 0;\n\n /* build base table */\n for (sum = first, i = 0; i < 30; ++i) {\n base[i] = sum;\n sum += 1 << bits[i];\n }\n}\n\n/* build the fixed huffman trees */\nfunction tinf_build_fixed_trees(lt, dt) {\n var i;\n\n /* build fixed length tree */\n for (i = 0; i < 7; ++i) lt.table[i] = 0;\n\n lt.table[7] = 24;\n lt.table[8] = 152;\n lt.table[9] = 112;\n\n for (i = 0; i < 24; ++i) lt.trans[i] = 256 + i;\n for (i = 0; i < 144; ++i) lt.trans[24 + i] = i;\n for (i = 0; i < 8; ++i) lt.trans[24 + 144 + i] = 280 + i;\n for (i = 0; i < 112; ++i) lt.trans[24 + 144 + 8 + i] = 144 + i;\n\n /* build fixed distance tree */\n for (i = 0; i < 5; ++i) dt.table[i] = 0;\n\n dt.table[5] = 32;\n\n for (i = 0; i < 32; ++i) dt.trans[i] = i;\n}\n\n/* given an array of code lengths, build a tree */\nvar offs = new Uint16Array(16);\n\nfunction tinf_build_tree(t, lengths, off, num) {\n var i, sum;\n\n /* clear code length count table */\n for (i = 0; i < 16; ++i) t.table[i] = 0;\n\n /* scan symbol lengths, and sum code length counts */\n for (i = 0; i < num; ++i) t.table[lengths[off + i]]++;\n\n t.table[0] = 0;\n\n /* compute offset table for distribution sort */\n for (sum = 0, i = 0; i < 16; ++i) {\n offs[i] = sum;\n sum += t.table[i];\n }\n\n /* create code->symbol translation table (symbols sorted by code) */\n for (i = 0; i < num; ++i) {\n if (lengths[off + i]) t.trans[offs[lengths[off + i]]++] = i;\n }\n}\n\n/* ---------------------- *\n * -- decode functions -- *\n * ---------------------- */\n\n/* get one bit from source stream */\nfunction tinf_getbit(d) {\n /* check if tag is empty */\n if (!d.bitcount--) {\n /* load next tag */\n d.tag = d.source[d.sourceIndex++];\n d.bitcount = 7;\n }\n\n /* shift bit out of tag */\n var bit = d.tag & 1;\n d.tag >>>= 1;\n\n return bit;\n}\n\n/* read a num bit value from a stream and add base */\nfunction tinf_read_bits(d, num, base) {\n if (!num)\n return base;\n\n while (d.bitcount < 24) {\n d.tag |= d.source[d.sourceIndex++] << d.bitcount;\n d.bitcount += 8;\n }\n\n var val = d.tag & (0xffff >>> (16 - num));\n d.tag >>>= num;\n d.bitcount -= num;\n return val + base;\n}\n\n/* given a data stream and a tree, decode a symbol */\nfunction tinf_decode_symbol(d, t) {\n while (d.bitcount < 24) {\n d.tag |= d.source[d.sourceIndex++] << d.bitcount;\n d.bitcount += 8;\n }\n \n var sum = 0, cur = 0, len = 0;\n var tag = d.tag;\n\n /* get more bits while code value is above sum */\n do {\n cur = 2 * cur + (tag & 1);\n tag >>>= 1;\n ++len;\n\n sum += t.table[len];\n cur -= t.table[len];\n } while (cur >= 0);\n \n d.tag = tag;\n d.bitcount -= len;\n\n return t.trans[sum + cur];\n}\n\n/* given a data stream, decode dynamic trees from it */\nfunction tinf_decode_trees(d, lt, dt) {\n var hlit, hdist, hclen;\n var i, num, length;\n\n /* get 5 bits HLIT (257-286) */\n hlit = tinf_read_bits(d, 5, 257);\n\n /* get 5 bits HDIST (1-32) */\n hdist = tinf_read_bits(d, 5, 1);\n\n /* get 4 bits HCLEN (4-19) */\n hclen = tinf_read_bits(d, 4, 4);\n\n for (i = 0; i < 19; ++i) lengths[i] = 0;\n\n /* read code lengths for code length alphabet */\n for (i = 0; i < hclen; ++i) {\n /* get 3 bits code length (0-7) */\n var clen = tinf_read_bits(d, 3, 0);\n lengths[clcidx[i]] = clen;\n }\n\n /* build code length tree */\n tinf_build_tree(code_tree, lengths, 0, 19);\n\n /* decode code lengths for the dynamic trees */\n for (num = 0; num < hlit + hdist;) {\n var sym = tinf_decode_symbol(d, code_tree);\n\n switch (sym) {\n case 16:\n /* copy previous code length 3-6 times (read 2 bits) */\n var prev = lengths[num - 1];\n for (length = tinf_read_bits(d, 2, 3); length; --length) {\n lengths[num++] = prev;\n }\n break;\n case 17:\n /* repeat code length 0 for 3-10 times (read 3 bits) */\n for (length = tinf_read_bits(d, 3, 3); length; --length) {\n lengths[num++] = 0;\n }\n break;\n case 18:\n /* repeat code length 0 for 11-138 times (read 7 bits) */\n for (length = tinf_read_bits(d, 7, 11); length; --length) {\n lengths[num++] = 0;\n }\n break;\n default:\n /* values 0-15 represent the actual code lengths */\n lengths[num++] = sym;\n break;\n }\n }\n\n /* build dynamic trees */\n tinf_build_tree(lt, lengths, 0, hlit);\n tinf_build_tree(dt, lengths, hlit, hdist);\n}\n\n/* ----------------------------- *\n * -- block inflate functions -- *\n * ----------------------------- */\n\n/* given a stream and two trees, inflate a block of data */\nfunction tinf_inflate_block_data(d, lt, dt) {\n while (1) {\n var sym = tinf_decode_symbol(d, lt);\n\n /* check for end of block */\n if (sym === 256) {\n return TINF_OK;\n }\n\n if (sym < 256) {\n d.dest[d.destLen++] = sym;\n } else {\n var length, dist, offs;\n var i;\n\n sym -= 257;\n\n /* possibly get more bits from length code */\n length = tinf_read_bits(d, length_bits[sym], length_base[sym]);\n\n dist = tinf_decode_symbol(d, dt);\n\n /* possibly get more bits from distance code */\n offs = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]);\n\n /* copy match */\n for (i = offs; i < offs + length; ++i) {\n d.dest[d.destLen++] = d.dest[i];\n }\n }\n }\n}\n\n/* inflate an uncompressed block of data */\nfunction tinf_inflate_uncompressed_block(d) {\n var length, invlength;\n var i;\n \n /* unread from bitbuffer */\n while (d.bitcount > 8) {\n d.sourceIndex--;\n d.bitcount -= 8;\n }\n\n /* get length */\n length = d.source[d.sourceIndex + 1];\n length = 256 * length + d.source[d.sourceIndex];\n\n /* get one's complement of length */\n invlength = d.source[d.sourceIndex + 3];\n invlength = 256 * invlength + d.source[d.sourceIndex + 2];\n\n /* check length */\n if (length !== (~invlength & 0x0000ffff))\n return TINF_DATA_ERROR;\n\n d.sourceIndex += 4;\n\n /* copy block */\n for (i = length; i; --i)\n d.dest[d.destLen++] = d.source[d.sourceIndex++];\n\n /* make sure we start next block on a byte boundary */\n d.bitcount = 0;\n\n return TINF_OK;\n}\n\n/* inflate stream from source to dest */\nfunction tinf_uncompress(source, dest) {\n var d = new Data(source, dest);\n var bfinal, btype, res;\n\n do {\n /* read final block flag */\n bfinal = tinf_getbit(d);\n\n /* read block type (2 bits) */\n btype = tinf_read_bits(d, 2, 0);\n\n /* decompress block */\n switch (btype) {\n case 0:\n /* decompress uncompressed block */\n res = tinf_inflate_uncompressed_block(d);\n break;\n case 1:\n /* decompress block with fixed huffman trees */\n res = tinf_inflate_block_data(d, sltree, sdtree);\n break;\n case 2:\n /* decompress block with dynamic huffman trees */\n tinf_decode_trees(d, d.ltree, d.dtree);\n res = tinf_inflate_block_data(d, d.ltree, d.dtree);\n break;\n default:\n res = TINF_DATA_ERROR;\n }\n\n if (res !== TINF_OK)\n throw new Error('Data error');\n\n } while (!bfinal);\n\n if (d.destLen < d.dest.length) {\n if (typeof d.dest.slice === 'function')\n return d.dest.slice(0, d.destLen);\n else\n return d.dest.subarray(0, d.destLen);\n }\n \n return d.dest;\n}\n\n/* -------------------- *\n * -- initialization -- *\n * -------------------- */\n\n/* build fixed huffman trees */\ntinf_build_fixed_trees(sltree, sdtree);\n\n/* build extra bits and base tables */\ntinf_build_bits_base(length_bits, length_base, 4, 3);\ntinf_build_bits_base(dist_bits, dist_base, 2, 1);\n\n/* fix a special case */\nlength_bits[28] = 0;\nlength_base[28] = 258;\n\nmodule.exports = tinf_uncompress;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/~/tiny-inflate/index.js\n ** module id = 3\n ** module chunks = 0\n **/","// Glyph encoding\n\n'use strict';\n\nvar cffStandardStrings = [\n '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',\n 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',\n 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',\n 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',\n 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',\n 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',\n 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling',\n 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft',\n 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph',\n 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand',\n 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring',\n 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE',\n 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',\n 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn',\n 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',\n 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex',\n 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',\n 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute',\n 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute',\n 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute',\n 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave',\n 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior',\n 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff', 'onedotenleader',\n 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',\n 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior',\n 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',\n 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl',\n 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',\n 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',\n 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',\n 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall',\n 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall',\n 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall',\n 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds',\n 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',\n 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',\n 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior',\n 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',\n 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall',\n 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall',\n 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',\n 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000',\n '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'];\n\nvar cffStandardEncoding = [\n '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',\n 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',\n 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',\n 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',\n 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',\n 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',\n 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',\n 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',\n 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger',\n 'daggerdbl', 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright',\n 'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde',\n 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron',\n 'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '',\n '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '',\n 'lslash', 'oslash', 'oe', 'germandbls'];\n\nvar cffExpertEncoding = [\n '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior',\n 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader',\n 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',\n 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',\n 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior',\n 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',\n 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl',\n 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',\n 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',\n 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',\n 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',\n 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',\n 'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior',\n '', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',\n 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '',\n '', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',\n 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',\n 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',\n 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',\n 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',\n 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',\n 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall',\n 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',\n 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];\n\nvar standardNames = [\n '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',\n 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',\n 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',\n 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',\n 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',\n 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',\n 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',\n 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave',\n 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',\n 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis',\n 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section',\n 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal',\n 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation',\n 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown',\n 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright',\n 'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft',\n 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',\n 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase',\n 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',\n 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex',\n 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',\n 'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth',\n 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior',\n 'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla',\n 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];\n\n// This is the encoding used for fonts created from scratch.\n// It loops through all glyphs and finds the appropriate unicode value.\n// Since it's linear time, other encodings will be faster.\nfunction DefaultEncoding(font) {\n this.font = font;\n}\n\nDefaultEncoding.prototype.charToGlyphIndex = function(c) {\n var code = c.charCodeAt(0);\n var glyphs = this.font.glyphs;\n if (glyphs) {\n for (var i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs.get(i);\n for (var j = 0; j < glyph.unicodes.length; j += 1) {\n if (glyph.unicodes[j] === code) {\n return i;\n }\n }\n }\n } else {\n return null;\n }\n};\n\nfunction CmapEncoding(cmap) {\n this.cmap = cmap;\n}\n\nCmapEncoding.prototype.charToGlyphIndex = function(c) {\n return this.cmap.glyphIndexMap[c.charCodeAt(0)] || 0;\n};\n\nfunction CffEncoding(encoding, charset) {\n this.encoding = encoding;\n this.charset = charset;\n}\n\nCffEncoding.prototype.charToGlyphIndex = function(s) {\n var code = s.charCodeAt(0);\n var charName = this.encoding[code];\n return this.charset.indexOf(charName);\n};\n\nfunction GlyphNames(post) {\n var i;\n switch (post.version) {\n case 1:\n this.names = exports.standardNames.slice();\n break;\n case 2:\n this.names = new Array(post.numberOfGlyphs);\n for (i = 0; i < post.numberOfGlyphs; i++) {\n if (post.glyphNameIndex[i] < exports.standardNames.length) {\n this.names[i] = exports.standardNames[post.glyphNameIndex[i]];\n } else {\n this.names[i] = post.names[post.glyphNameIndex[i] - exports.standardNames.length];\n }\n }\n\n break;\n case 2.5:\n this.names = new Array(post.numberOfGlyphs);\n for (i = 0; i < post.numberOfGlyphs; i++) {\n this.names[i] = exports.standardNames[i + post.glyphNameIndex[i]];\n }\n\n break;\n case 3:\n this.names = [];\n break;\n }\n}\n\nGlyphNames.prototype.nameToGlyphIndex = function(name) {\n return this.names.indexOf(name);\n};\n\nGlyphNames.prototype.glyphIndexToName = function(gid) {\n return this.names[gid];\n};\n\nfunction addGlyphNames(font) {\n var glyph;\n var glyphIndexMap = font.tables.cmap.glyphIndexMap;\n var charCodes = Object.keys(glyphIndexMap);\n\n for (var i = 0; i < charCodes.length; i += 1) {\n var c = charCodes[i];\n var glyphIndex = glyphIndexMap[c];\n glyph = font.glyphs.get(glyphIndex);\n glyph.addUnicode(parseInt(c));\n }\n\n for (i = 0; i < font.glyphs.length; i += 1) {\n glyph = font.glyphs.get(i);\n if (font.cffEncoding) {\n glyph.name = font.cffEncoding.charset[i];\n } else {\n glyph.name = font.glyphNames.glyphIndexToName(i);\n }\n }\n}\n\nexports.cffStandardStrings = cffStandardStrings;\nexports.cffStandardEncoding = cffStandardEncoding;\nexports.cffExpertEncoding = cffExpertEncoding;\nexports.standardNames = standardNames;\nexports.DefaultEncoding = DefaultEncoding;\nexports.CmapEncoding = CmapEncoding;\nexports.CffEncoding = CffEncoding;\nexports.GlyphNames = GlyphNames;\nexports.addGlyphNames = addGlyphNames;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/encoding.js\n ** module id = 4\n ** module chunks = 0\n **/","// The Font object\n\n'use strict';\n\nvar path = require('./path');\nvar sfnt = require('./tables/sfnt');\nvar encoding = require('./encoding');\nvar glyphset = require('./glyphset');\nvar util = require('./util');\n\n// A Font represents a loaded OpenType font file.\n// It contains a set of glyphs and methods to draw text on a drawing context,\n// or to get a path representing the text.\nfunction Font(options) {\n options = options || {};\n\n if (!options.empty) {\n // Check that we've provided the minimum set of names.\n util.checkArgument(options.familyName, 'When creating a new Font object, familyName is required.');\n util.checkArgument(options.styleName, 'When creating a new Font object, styleName is required.');\n util.checkArgument(options.unitsPerEm, 'When creating a new Font object, unitsPerEm is required.');\n util.checkArgument(options.ascender, 'When creating a new Font object, ascender is required.');\n util.checkArgument(options.descender, 'When creating a new Font object, descender is required.');\n util.checkArgument(options.descender < 0, 'Descender should be negative (e.g. -512).');\n\n // OS X will complain if the names are empty, so we put a single space everywhere by default.\n this.names = {\n fontFamily: {en: options.familyName || ' '},\n fontSubfamily: {en: options.styleName || ' '},\n fullName: {en: options.fullName || options.familyName + ' ' + options.styleName},\n postScriptName: {en: options.postScriptName || options.familyName + options.styleName},\n designer: {en: options.designer || ' '},\n designerURL: {en: options.designerURL || ' '},\n manufacturer: {en: options.manufacturer || ' '},\n manufacturerURL: {en: options.manufacturerURL || ' '},\n license: {en: options.license || ' '},\n licenseURL: {en: options.licenseURL || ' '},\n version: {en: options.version || 'Version 0.1'},\n description: {en: options.description || ' '},\n copyright: {en: options.copyright || ' '},\n trademark: {en: options.trademark || ' '}\n };\n this.unitsPerEm = options.unitsPerEm || 1000;\n this.ascender = options.ascender;\n this.descender = options.descender;\n this.createdTimestamp = options.createdTimestamp;\n this.tables = { os2: {\n usWeightClass: options.weightClass || this.usWeightClasses.MEDIUM,\n usWidthClass: options.widthClass || this.usWidthClasses.MEDIUM,\n fsSelection: options.fsSelection || this.fsSelectionValues.REGULAR\n } };\n }\n\n this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported.\n this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);\n this.encoding = new encoding.DefaultEncoding(this);\n this.tables = this.tables || {};\n}\n\n// Check if the font has a glyph for the given character.\nFont.prototype.hasChar = function(c) {\n return this.encoding.charToGlyphIndex(c) !== null;\n};\n\n// Convert the given character to a single glyph index.\n// Note that this function assumes that there is a one-to-one mapping between\n// the given character and a glyph; for complex scripts this might not be the case.\nFont.prototype.charToGlyphIndex = function(s) {\n return this.encoding.charToGlyphIndex(s);\n};\n\n// Convert the given character to a single Glyph object.\n// Note that this function assumes that there is a one-to-one mapping between\n// the given character and a glyph; for complex scripts this might not be the case.\nFont.prototype.charToGlyph = function(c) {\n var glyphIndex = this.charToGlyphIndex(c);\n var glyph = this.glyphs.get(glyphIndex);\n if (!glyph) {\n // .notdef\n glyph = this.glyphs.get(0);\n }\n\n return glyph;\n};\n\n// Convert the given text to a list of Glyph objects.\n// Note that there is no strict one-to-one mapping between characters and\n// glyphs, so the list of returned glyphs can be larger or smaller than the\n// length of the given string.\nFont.prototype.stringToGlyphs = function(s) {\n var glyphs = [];\n for (var i = 0; i < s.length; i += 1) {\n var c = s[i];\n glyphs.push(this.charToGlyph(c));\n }\n\n return glyphs;\n};\n\nFont.prototype.nameToGlyphIndex = function(name) {\n return this.glyphNames.nameToGlyphIndex(name);\n};\n\nFont.prototype.nameToGlyph = function(name) {\n var glyphIndex = this.nametoGlyphIndex(name);\n var glyph = this.glyphs.get(glyphIndex);\n if (!glyph) {\n // .notdef\n glyph = this.glyphs.get(0);\n }\n\n return glyph;\n};\n\nFont.prototype.glyphIndexToName = function(gid) {\n if (!this.glyphNames.glyphIndexToName) {\n return '';\n }\n\n return this.glyphNames.glyphIndexToName(gid);\n};\n\n// Retrieve the value of the kerning pair between the left glyph (or its index)\n// and the right glyph (or its index). If no kerning pair is found, return 0.\n// The kerning value gets added to the advance width when calculating the spacing\n// between glyphs.\nFont.prototype.getKerningValue = function(leftGlyph, rightGlyph) {\n leftGlyph = leftGlyph.index || leftGlyph;\n rightGlyph = rightGlyph.index || rightGlyph;\n var gposKerning = this.getGposKerningValue;\n return gposKerning ? gposKerning(leftGlyph, rightGlyph) :\n (this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0);\n};\n\n// Helper function that invokes the given callback for each glyph in the given text.\n// The callback gets `(glyph, x, y, fontSize, options)`.\nFont.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) {\n x = x !== undefined ? x : 0;\n y = y !== undefined ? y : 0;\n fontSize = fontSize !== undefined ? fontSize : 72;\n options = options || {};\n var kerning = options.kerning === undefined ? true : options.kerning;\n var fontScale = 1 / this.unitsPerEm * fontSize;\n var glyphs = this.stringToGlyphs(text);\n for (var i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs[i];\n callback(glyph, x, y, fontSize, options);\n if (glyph.advanceWidth) {\n x += glyph.advanceWidth * fontScale;\n }\n\n if (kerning && i < glyphs.length - 1) {\n var kerningValue = this.getKerningValue(glyph, glyphs[i + 1]);\n x += kerningValue * fontScale;\n }\n }\n};\n\n// Create a Path object that represents the given text.\n//\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\n//\n// Returns a Path object.\nFont.prototype.getPath = function(text, x, y, fontSize, options) {\n var fullPath = new path.Path();\n this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {\n var glyphPath = glyph.getPath(gX, gY, gFontSize);\n fullPath.extend(glyphPath);\n });\n\n return fullPath;\n};\n\n// Create an array of Path objects that represent the glyps of a given text.\n//\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\n//\n// Returns an array of Path objects.\nFont.prototype.getPaths = function(text, x, y, fontSize, options) {\n var glyphPaths = [];\n this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {\n var glyphPath = glyph.getPath(gX, gY, gFontSize);\n glyphPaths.push(glyphPath);\n });\n\n return glyphPaths;\n};\n\n// Draw the text on the given drawing context.\n//\n// ctx - A 2D drawing context, like Canvas.\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\nFont.prototype.draw = function(ctx, text, x, y, fontSize, options) {\n this.getPath(text, x, y, fontSize, options).draw(ctx);\n};\n\n// Draw the points of all glyphs in the text.\n// On-curve points will be drawn in blue, off-curve points will be drawn in red.\n//\n// ctx - A 2D drawing context, like Canvas.\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\nFont.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {\n this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {\n glyph.drawPoints(ctx, gX, gY, gFontSize);\n });\n};\n\n// Draw lines indicating important font measurements for all glyphs in the text.\n// Black lines indicate the origin of the coordinate system (point 0,0).\n// Blue lines indicate the glyph bounding box.\n// Green line indicates the advance width of the glyph.\n//\n// ctx - A 2D drawing context, like Canvas.\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\nFont.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {\n this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {\n glyph.drawMetrics(ctx, gX, gY, gFontSize);\n });\n};\n\nFont.prototype.getEnglishName = function(name) {\n var translations = this.names[name];\n if (translations) {\n return translations.en;\n }\n};\n\n// Validate\nFont.prototype.validate = function() {\n var warnings = [];\n var _this = this;\n\n function assert(predicate, message) {\n if (!predicate) {\n warnings.push(message);\n }\n }\n\n function assertNamePresent(name) {\n var englishName = _this.getEnglishName(name);\n assert(englishName && englishName.trim().length > 0,\n 'No English ' + name + ' specified.');\n }\n\n // Identification information\n assertNamePresent('fontFamily');\n assertNamePresent('weightName');\n assertNamePresent('manufacturer');\n assertNamePresent('copyright');\n assertNamePresent('version');\n\n // Dimension information\n assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');\n};\n\n// Convert the font object to a SFNT data structure.\n// This structure contains all the necessary tables and metadata to create a binary OTF file.\nFont.prototype.toTables = function() {\n return sfnt.fontToTable(this);\n};\n\nFont.prototype.toBuffer = function() {\n console.warn('Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.');\n return this.toArrayBuffer();\n};\n\nFont.prototype.toArrayBuffer = function() {\n var sfntTable = this.toTables();\n var bytes = sfntTable.encode();\n var buffer = new ArrayBuffer(bytes.length);\n var intArray = new Uint8Array(buffer);\n for (var i = 0; i < bytes.length; i++) {\n intArray[i] = bytes[i];\n }\n\n return buffer;\n};\n\n// Initiate a download of the OpenType font.\nFont.prototype.download = function() {\n var familyName = this.getEnglishName('fontFamily');\n var styleName = this.getEnglishName('fontSubfamily');\n var fileName = familyName.replace(/\\s/g, '') + '-' + styleName + '.otf';\n var arrayBuffer = this.toArrayBuffer();\n\n if (util.isBrowser()) {\n window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;\n window.requestFileSystem(window.TEMPORARY, arrayBuffer.byteLength, function(fs) {\n fs.root.getFile(fileName, {create: true}, function(fileEntry) {\n fileEntry.createWriter(function(writer) {\n var dataView = new DataView(arrayBuffer);\n var blob = new Blob([dataView], {type: 'font/opentype'});\n writer.write(blob);\n\n writer.addEventListener('writeend', function() {\n // Navigating to the file will download it.\n location.href = fileEntry.toURL();\n }, false);\n });\n });\n },\n function(err) {\n throw err;\n });\n } else {\n var fs = require('fs');\n var buffer = util.arrayBufferToNodeBuffer(arrayBuffer);\n fs.writeFileSync(fileName, buffer);\n }\n};\n\nFont.prototype.fsSelectionValues = {\n ITALIC: 0x001, //1\n UNDERSCORE: 0x002, //2\n NEGATIVE: 0x004, //4\n OUTLINED: 0x008, //8\n STRIKEOUT: 0x010, //16\n BOLD: 0x020, //32\n REGULAR: 0x040, //64\n USER_TYPO_METRICS: 0x080, //128\n WWS: 0x100, //256\n OBLIQUE: 0x200 //512\n};\n\nFont.prototype.usWidthClasses = {\n ULTRA_CONDENSED: 1,\n EXTRA_CONDENSED: 2,\n CONDENSED: 3,\n SEMI_CONDENSED: 4,\n MEDIUM: 5,\n SEMI_EXPANDED: 6,\n EXPANDED: 7,\n EXTRA_EXPANDED: 8,\n ULTRA_EXPANDED: 9\n};\n\nFont.prototype.usWeightClasses = {\n THIN: 100,\n EXTRA_LIGHT: 200,\n LIGHT: 300,\n NORMAL: 400,\n MEDIUM: 500,\n SEMI_BOLD: 600,\n BOLD: 700,\n EXTRA_BOLD: 800,\n BLACK: 900\n};\n\nexports.Font = Font;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/font.js\n ** module id = 5\n ** module chunks = 0\n **/","// Geometric objects\n\n'use strict';\n\n// A bézier path containing a set of path commands similar to a SVG path.\n// Paths can be drawn on a context using `draw`.\nfunction Path() {\n this.commands = [];\n this.fill = 'black';\n this.stroke = null;\n this.strokeWidth = 1;\n}\n\nPath.prototype.moveTo = function(x, y) {\n this.commands.push({\n type: 'M',\n x: x,\n y: y\n });\n};\n\nPath.prototype.lineTo = function(x, y) {\n this.commands.push({\n type: 'L',\n x: x,\n y: y\n });\n};\n\nPath.prototype.curveTo = Path.prototype.bezierCurveTo = function(x1, y1, x2, y2, x, y) {\n this.commands.push({\n type: 'C',\n x1: x1,\n y1: y1,\n x2: x2,\n y2: y2,\n x: x,\n y: y\n });\n};\n\nPath.prototype.quadTo = Path.prototype.quadraticCurveTo = function(x1, y1, x, y) {\n this.commands.push({\n type: 'Q',\n x1: x1,\n y1: y1,\n x: x,\n y: y\n });\n};\n\nPath.prototype.close = Path.prototype.closePath = function() {\n this.commands.push({\n type: 'Z'\n });\n};\n\n// Add the given path or list of commands to the commands of this path.\nPath.prototype.extend = function(pathOrCommands) {\n if (pathOrCommands.commands) {\n pathOrCommands = pathOrCommands.commands;\n }\n\n Array.prototype.push.apply(this.commands, pathOrCommands);\n};\n\n// Draw the path to a 2D context.\nPath.prototype.draw = function(ctx) {\n ctx.beginPath();\n for (var i = 0; i < this.commands.length; i += 1) {\n var cmd = this.commands[i];\n if (cmd.type === 'M') {\n ctx.moveTo(cmd.x, cmd.y);\n } else if (cmd.type === 'L') {\n ctx.lineTo(cmd.x, cmd.y);\n } else if (cmd.type === 'C') {\n ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);\n } else if (cmd.type === 'Q') {\n ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);\n } else if (cmd.type === 'Z') {\n ctx.closePath();\n }\n }\n\n if (this.fill) {\n ctx.fillStyle = this.fill;\n ctx.fill();\n }\n\n if (this.stroke) {\n ctx.strokeStyle = this.stroke;\n ctx.lineWidth = this.strokeWidth;\n ctx.stroke();\n }\n};\n\n// Convert the Path to a string of path data instructions\n// See http://www.w3.org/TR/SVG/paths.html#PathData\n// Parameters:\n// - decimalPlaces: The amount of decimal places for floating-point values (default: 2)\nPath.prototype.toPathData = function(decimalPlaces) {\n decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;\n\n function floatToString(v) {\n if (Math.round(v) === v) {\n return '' + Math.round(v);\n } else {\n return v.toFixed(decimalPlaces);\n }\n }\n\n function packValues() {\n var s = '';\n for (var i = 0; i < arguments.length; i += 1) {\n var v = arguments[i];\n if (v >= 0 && i > 0) {\n s += ' ';\n }\n\n s += floatToString(v);\n }\n\n return s;\n }\n\n var d = '';\n for (var i = 0; i < this.commands.length; i += 1) {\n var cmd = this.commands[i];\n if (cmd.type === 'M') {\n d += 'M' + packValues(cmd.x, cmd.y);\n } else if (cmd.type === 'L') {\n d += 'L' + packValues(cmd.x, cmd.y);\n } else if (cmd.type === 'C') {\n d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);\n } else if (cmd.type === 'Q') {\n d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y);\n } else if (cmd.type === 'Z') {\n d += 'Z';\n }\n }\n\n return d;\n};\n\n// Convert the path to a SVG element, as a string.\n// Parameters:\n// - decimalPlaces: The amount of decimal places for floating-point values (default: 2)\nPath.prototype.toSVG = function(decimalPlaces) {\n var svg = ' r2.value.tag) {\n return 1;\n } else {\n return -1;\n }\n });\n\n sfnt.fields = sfnt.fields.concat(recordFields);\n sfnt.fields = sfnt.fields.concat(tableFields);\n return sfnt;\n}\n\n// Get the metrics for a character. If the string has more than one character\n// this function returns metrics for the first available character.\n// You can provide optional fallback metrics if no characters are available.\nfunction metricsForChar(font, chars, notFoundMetrics) {\n for (var i = 0; i < chars.length; i += 1) {\n var glyphIndex = font.charToGlyphIndex(chars[i]);\n if (glyphIndex > 0) {\n var glyph = font.glyphs.get(glyphIndex);\n return glyph.getMetrics();\n }\n }\n\n return notFoundMetrics;\n}\n\nfunction average(vs) {\n var sum = 0;\n for (var i = 0; i < vs.length; i += 1) {\n sum += vs[i];\n }\n\n return sum / vs.length;\n}\n\n// Convert the font object to a SFNT data structure.\n// This structure contains all the necessary tables and metadata to create a binary OTF file.\nfunction fontToSfntTable(font) {\n var xMins = [];\n var yMins = [];\n var xMaxs = [];\n var yMaxs = [];\n var advanceWidths = [];\n var leftSideBearings = [];\n var rightSideBearings = [];\n var firstCharIndex;\n var lastCharIndex = 0;\n var ulUnicodeRange1 = 0;\n var ulUnicodeRange2 = 0;\n var ulUnicodeRange3 = 0;\n var ulUnicodeRange4 = 0;\n\n for (var i = 0; i < font.glyphs.length; i += 1) {\n var glyph = font.glyphs.get(i);\n var unicode = glyph.unicode | 0;\n\n if (isNaN(glyph.advanceWidth)) {\n throw new Error('Glyph ' + glyph.name + ' (' + i + '): advanceWidth is not a number.');\n }\n\n if (firstCharIndex > unicode || firstCharIndex === undefined) {\n // ignore .notdef char\n if (unicode > 0) {\n firstCharIndex = unicode;\n }\n }\n\n if (lastCharIndex < unicode) {\n lastCharIndex = unicode;\n }\n\n var position = os2.getUnicodeRange(unicode);\n if (position < 32) {\n ulUnicodeRange1 |= 1 << position;\n } else if (position < 64) {\n ulUnicodeRange2 |= 1 << position - 32;\n } else if (position < 96) {\n ulUnicodeRange3 |= 1 << position - 64;\n } else if (position < 123) {\n ulUnicodeRange4 |= 1 << position - 96;\n } else {\n throw new Error('Unicode ranges bits > 123 are reserved for internal usage');\n }\n // Skip non-important characters.\n if (glyph.name === '.notdef') continue;\n var metrics = glyph.getMetrics();\n xMins.push(metrics.xMin);\n yMins.push(metrics.yMin);\n xMaxs.push(metrics.xMax);\n yMaxs.push(metrics.yMax);\n leftSideBearings.push(metrics.leftSideBearing);\n rightSideBearings.push(metrics.rightSideBearing);\n advanceWidths.push(glyph.advanceWidth);\n }\n\n var globals = {\n xMin: Math.min.apply(null, xMins),\n yMin: Math.min.apply(null, yMins),\n xMax: Math.max.apply(null, xMaxs),\n yMax: Math.max.apply(null, yMaxs),\n advanceWidthMax: Math.max.apply(null, advanceWidths),\n advanceWidthAvg: average(advanceWidths),\n minLeftSideBearing: Math.min.apply(null, leftSideBearings),\n maxLeftSideBearing: Math.max.apply(null, leftSideBearings),\n minRightSideBearing: Math.min.apply(null, rightSideBearings)\n };\n globals.ascender = font.ascender;\n globals.descender = font.descender;\n\n var headTable = head.make({\n flags: 3, // 00000011 (baseline for font at y=0; left sidebearing point at x=0)\n unitsPerEm: font.unitsPerEm,\n xMin: globals.xMin,\n yMin: globals.yMin,\n xMax: globals.xMax,\n yMax: globals.yMax,\n lowestRecPPEM: 3,\n createdTimestamp: font.createdTimestamp\n });\n\n var hheaTable = hhea.make({\n ascender: globals.ascender,\n descender: globals.descender,\n advanceWidthMax: globals.advanceWidthMax,\n minLeftSideBearing: globals.minLeftSideBearing,\n minRightSideBearing: globals.minRightSideBearing,\n xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin),\n numberOfHMetrics: font.glyphs.length\n });\n\n var maxpTable = maxp.make(font.glyphs.length);\n\n var os2Table = os2.make({\n xAvgCharWidth: Math.round(globals.advanceWidthAvg),\n usWeightClass: font.tables.os2.usWeightClass,\n usWidthClass: font.tables.os2.usWidthClass,\n usFirstCharIndex: firstCharIndex,\n usLastCharIndex: lastCharIndex,\n ulUnicodeRange1: ulUnicodeRange1,\n ulUnicodeRange2: ulUnicodeRange2,\n ulUnicodeRange3: ulUnicodeRange3,\n ulUnicodeRange4: ulUnicodeRange4,\n fsSelection: font.tables.os2.fsSelection, // REGULAR\n // See http://typophile.com/node/13081 for more info on vertical metrics.\n // We get metrics for typical characters (such as \"x\" for xHeight).\n // We provide some fallback characters if characters are unavailable: their\n // ordering was chosen experimentally.\n sTypoAscender: globals.ascender,\n sTypoDescender: globals.descender,\n sTypoLineGap: 0,\n usWinAscent: globals.yMax,\n usWinDescent: Math.abs(globals.yMin),\n ulCodePageRange1: 1, // FIXME: hard-code Latin 1 support for now\n sxHeight: metricsForChar(font, 'xyvw', {yMax: Math.round(globals.ascender / 2)}).yMax,\n sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals).yMax,\n usDefaultChar: font.hasChar(' ') ? 32 : 0, // Use space as the default character, if available.\n usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available.\n });\n\n var hmtxTable = hmtx.make(font.glyphs);\n var cmapTable = cmap.make(font.glyphs);\n\n var englishFamilyName = font.getEnglishName('fontFamily');\n var englishStyleName = font.getEnglishName('fontSubfamily');\n var englishFullName = englishFamilyName + ' ' + englishStyleName;\n var postScriptName = font.getEnglishName('postScriptName');\n if (!postScriptName) {\n postScriptName = englishFamilyName.replace(/\\s/g, '') + '-' + englishStyleName;\n }\n\n var names = {};\n for (var n in font.names) {\n names[n] = font.names[n];\n }\n\n if (!names.uniqueID) {\n names.uniqueID = {en: font.getEnglishName('manufacturer') + ':' + englishFullName};\n }\n\n if (!names.postScriptName) {\n names.postScriptName = {en: postScriptName};\n }\n\n if (!names.preferredFamily) {\n names.preferredFamily = font.names.fontFamily;\n }\n\n if (!names.preferredSubfamily) {\n names.preferredSubfamily = font.names.fontSubfamily;\n }\n\n var languageTags = [];\n var nameTable = _name.make(names, languageTags);\n var ltagTable = (languageTags.length > 0 ? ltag.make(languageTags) : undefined);\n\n var postTable = post.make();\n var cffTable = cff.make(font.glyphs, {\n version: font.getEnglishName('version'),\n fullName: englishFullName,\n familyName: englishFamilyName,\n weightName: englishStyleName,\n postScriptName: postScriptName,\n unitsPerEm: font.unitsPerEm,\n fontBBox: [0, globals.yMin, globals.ascender, globals.advanceWidthMax]\n });\n\n // The order does not matter because makeSfntTable() will sort them.\n var tables = [headTable, hheaTable, maxpTable, os2Table, nameTable, cmapTable, postTable, cffTable, hmtxTable];\n if (ltagTable) {\n tables.push(ltagTable);\n }\n\n var sfntTable = makeSfntTable(tables);\n\n // Compute the font's checkSum and store it in head.checkSumAdjustment.\n var bytes = sfntTable.encode();\n var checkSum = computeCheckSum(bytes);\n var tableFields = sfntTable.fields;\n var checkSumAdjusted = false;\n for (i = 0; i < tableFields.length; i += 1) {\n if (tableFields[i].name === 'head table') {\n tableFields[i].value.checkSumAdjustment = 0xB1B0AFBA - checkSum;\n checkSumAdjusted = true;\n break;\n }\n }\n\n if (!checkSumAdjusted) {\n throw new Error('Could not find head table with checkSum to adjust.');\n }\n\n return sfntTable;\n}\n\nexports.computeCheckSum = computeCheckSum;\nexports.make = makeSfntTable;\nexports.fontToTable = fontToSfntTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/sfnt.js\n ** module id = 7\n ** module chunks = 0\n **/","// Run-time checking of preconditions.\n\n'use strict';\n\n// Precondition function that checks if the given predicate is true.\n// If not, it will throw an error.\nexports.argument = function(predicate, message) {\n if (!predicate) {\n throw new Error(message);\n }\n};\n\n// Precondition function that checks if the given assertion is true.\n// If not, it will throw an error.\nexports.assert = exports.argument;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/check.js\n ** module id = 8\n ** module chunks = 0\n **/","// Table metadata\n\n'use strict';\n\nvar encode = require('./types').encode;\nvar sizeOf = require('./types').sizeOf;\n\nfunction Table(tableName, fields, options) {\n var i;\n for (i = 0; i < fields.length; i += 1) {\n var field = fields[i];\n this[field.name] = field.value;\n }\n\n this.tableName = tableName;\n this.fields = fields;\n if (options) {\n var optionKeys = Object.keys(options);\n for (i = 0; i < optionKeys.length; i += 1) {\n var k = optionKeys[i];\n var v = options[k];\n if (this[k] !== undefined) {\n this[k] = v;\n }\n }\n }\n}\n\nTable.prototype.encode = function() {\n return encode.TABLE(this);\n};\n\nTable.prototype.sizeOf = function() {\n return sizeOf.TABLE(this);\n};\n\nexports.Record = exports.Table = Table;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/table.js\n ** module id = 9\n ** module chunks = 0\n **/","// Data types used in the OpenType font file.\n// All OpenType fonts use Motorola-style byte ordering (Big Endian)\n\n/* global WeakMap */\n\n'use strict';\n\nvar check = require('./check');\n\nvar LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15\nvar LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31\n\nvar decode = {};\nvar encode = {};\nvar sizeOf = {};\n\n// Return a function that always returns the same value.\nfunction constant(v) {\n return function() {\n return v;\n };\n}\n\n// OpenType data types //////////////////////////////////////////////////////\n\n// Convert an 8-bit unsigned integer to a list of 1 byte.\nencode.BYTE = function(v) {\n check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');\n return [v];\n};\n\nsizeOf.BYTE = constant(1);\n\n// Convert a 8-bit signed integer to a list of 1 byte.\nencode.CHAR = function(v) {\n return [v.charCodeAt(0)];\n};\n\nsizeOf.CHAR = constant(1);\n\n// Convert an ASCII string to a list of bytes.\nencode.CHARARRAY = function(v) {\n var b = [];\n for (var i = 0; i < v.length; i += 1) {\n b.push(v.charCodeAt(i));\n }\n\n return b;\n};\n\nsizeOf.CHARARRAY = function(v) {\n return v.length;\n};\n\n// Convert a 16-bit unsigned integer to a list of 2 bytes.\nencode.USHORT = function(v) {\n return [(v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.USHORT = constant(2);\n\n// Convert a 16-bit signed integer to a list of 2 bytes.\nencode.SHORT = function(v) {\n // Two's complement\n if (v >= LIMIT16) {\n v = -(2 * LIMIT16 - v);\n }\n\n return [(v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.SHORT = constant(2);\n\n// Convert a 24-bit unsigned integer to a list of 3 bytes.\nencode.UINT24 = function(v) {\n return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.UINT24 = constant(3);\n\n// Convert a 32-bit unsigned integer to a list of 4 bytes.\nencode.ULONG = function(v) {\n return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.ULONG = constant(4);\n\n// Convert a 32-bit unsigned integer to a list of 4 bytes.\nencode.LONG = function(v) {\n // Two's complement\n if (v >= LIMIT32) {\n v = -(2 * LIMIT32 - v);\n }\n\n return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.LONG = constant(4);\n\nencode.FIXED = encode.ULONG;\nsizeOf.FIXED = sizeOf.ULONG;\n\nencode.FWORD = encode.SHORT;\nsizeOf.FWORD = sizeOf.SHORT;\n\nencode.UFWORD = encode.USHORT;\nsizeOf.UFWORD = sizeOf.USHORT;\n\n// FIXME Implement LONGDATETIME\n// Convert a 32-bit Apple Mac timestamp integer to a list of 8 bytes, 64-bit timestamp.\nencode.LONGDATETIME = function(v) {\n return [0, 0, 0, 0, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.LONGDATETIME = constant(8);\n\n// Convert a 4-char tag to a list of 4 bytes.\nencode.TAG = function(v) {\n check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');\n return [v.charCodeAt(0),\n v.charCodeAt(1),\n v.charCodeAt(2),\n v.charCodeAt(3)];\n};\n\nsizeOf.TAG = constant(4);\n\n// CFF data types ///////////////////////////////////////////////////////////\n\nencode.Card8 = encode.BYTE;\nsizeOf.Card8 = sizeOf.BYTE;\n\nencode.Card16 = encode.USHORT;\nsizeOf.Card16 = sizeOf.USHORT;\n\nencode.OffSize = encode.BYTE;\nsizeOf.OffSize = sizeOf.BYTE;\n\nencode.SID = encode.USHORT;\nsizeOf.SID = sizeOf.USHORT;\n\n// Convert a numeric operand or charstring number to a variable-size list of bytes.\nencode.NUMBER = function(v) {\n if (v >= -107 && v <= 107) {\n return [v + 139];\n } else if (v >= 108 && v <= 1131) {\n v = v - 108;\n return [(v >> 8) + 247, v & 0xFF];\n } else if (v >= -1131 && v <= -108) {\n v = -v - 108;\n return [(v >> 8) + 251, v & 0xFF];\n } else if (v >= -32768 && v <= 32767) {\n return encode.NUMBER16(v);\n } else {\n return encode.NUMBER32(v);\n }\n};\n\nsizeOf.NUMBER = function(v) {\n return encode.NUMBER(v).length;\n};\n\n// Convert a signed number between -32768 and +32767 to a three-byte value.\n// This ensures we always use three bytes, but is not the most compact format.\nencode.NUMBER16 = function(v) {\n return [28, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.NUMBER16 = constant(3);\n\n// Convert a signed number between -(2^31) and +(2^31-1) to a five-byte value.\n// This is useful if you want to be sure you always use four bytes,\n// at the expense of wasting a few bytes for smaller numbers.\nencode.NUMBER32 = function(v) {\n return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.NUMBER32 = constant(5);\n\nencode.REAL = function(v) {\n var value = v.toString();\n\n // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)\n // This code converts it back to a number without the epsilon.\n var m = /\\.(\\d*?)(?:9{5,20}|0{5,20})\\d{0,2}(?:e(.+)|$)/.exec(value);\n if (m) {\n var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));\n value = (Math.round(v * epsilon) / epsilon).toString();\n }\n\n var nibbles = '';\n var i;\n var ii;\n for (i = 0, ii = value.length; i < ii; i += 1) {\n var c = value[i];\n if (c === 'e') {\n nibbles += value[++i] === '-' ? 'c' : 'b';\n } else if (c === '.') {\n nibbles += 'a';\n } else if (c === '-') {\n nibbles += 'e';\n } else {\n nibbles += c;\n }\n }\n\n nibbles += (nibbles.length & 1) ? 'f' : 'ff';\n var out = [30];\n for (i = 0, ii = nibbles.length; i < ii; i += 2) {\n out.push(parseInt(nibbles.substr(i, 2), 16));\n }\n\n return out;\n};\n\nsizeOf.REAL = function(v) {\n return encode.REAL(v).length;\n};\n\nencode.NAME = encode.CHARARRAY;\nsizeOf.NAME = sizeOf.CHARARRAY;\n\nencode.STRING = encode.CHARARRAY;\nsizeOf.STRING = sizeOf.CHARARRAY;\n\ndecode.UTF16 = function(data, offset, numBytes) {\n var codePoints = [];\n var numChars = numBytes / 2;\n for (var j = 0; j < numChars; j++, offset += 2) {\n codePoints[j] = data.getUint16(offset);\n }\n\n return String.fromCharCode.apply(null, codePoints);\n};\n\n// Convert a JavaScript string to UTF16-BE.\nencode.UTF16 = function(v) {\n var b = [];\n for (var i = 0; i < v.length; i += 1) {\n var codepoint = v.charCodeAt(i);\n b.push((codepoint >> 8) & 0xFF);\n b.push(codepoint & 0xFF);\n }\n\n return b;\n};\n\nsizeOf.UTF16 = function(v) {\n return v.length * 2;\n};\n\n// Data for converting old eight-bit Macintosh encodings to Unicode.\n// This representation is optimized for decoding; encoding is slower\n// and needs more memory. The assumption is that all opentype.js users\n// want to open fonts, but saving a font will be comperatively rare\n// so it can be more expensive. Keyed by IANA character set name.\n//\n// Python script for generating these strings:\n//\n// s = u''.join([chr(c).decode('mac_greek') for c in range(128, 256)])\n// print(s.encode('utf-8'))\nvar eightBitMacEncodings = {\n 'x-mac-croatian': // Python: 'mac_croatian'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø' +\n '¿¡¬√ƒ≈ƫȅ ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ',\n 'x-mac-cyrillic': // Python: 'mac_cyrillic'\n 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњ' +\n 'јЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю',\n 'x-mac-gaelic':\n // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/GAELIC.TXT\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæø' +\n 'ṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ',\n 'x-mac-greek': // Python: 'mac_greek'\n 'Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩ' +\n 'άΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ\\u00AD',\n 'x-mac-icelandic': // Python: 'mac_iceland'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüݰ¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +\n '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',\n 'x-mac-inuit':\n // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/INUIT.TXT\n 'ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗ' +\n 'ᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł',\n 'x-mac-ce': // Python: 'mac_latin2'\n 'ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅ' +\n 'ņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ',\n macintosh: // Python: 'mac_roman'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +\n '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',\n 'x-mac-romanian': // Python: 'mac_romanian'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș' +\n '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',\n 'x-mac-turkish': // Python: 'mac_turkish'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +\n '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ'\n};\n\n// Decodes an old-style Macintosh string. Returns either a Unicode JavaScript\n// string, or 'undefined' if the encoding is unsupported. For example, we do\n// not support Chinese, Japanese or Korean because these would need large\n// mapping tables.\ndecode.MACSTRING = function(dataView, offset, dataLength, encoding) {\n var table = eightBitMacEncodings[encoding];\n if (table === undefined) {\n return undefined;\n }\n\n var result = '';\n for (var i = 0; i < dataLength; i++) {\n var c = dataView.getUint8(offset + i);\n // In all eight-bit Mac encodings, the characters 0x00..0x7F are\n // mapped to U+0000..U+007F; we only need to look up the others.\n if (c <= 0x7F) {\n result += String.fromCharCode(c);\n } else {\n result += table[c & 0x7F];\n }\n }\n\n return result;\n};\n\n// Helper function for encode.MACSTRING. Returns a dictionary for mapping\n// Unicode character codes to their 8-bit MacOS equivalent. This table\n// is not exactly a super cheap data structure, but we do not care because\n// encoding Macintosh strings is only rarely needed in typical applications.\nvar macEncodingTableCache = typeof WeakMap === 'function' && new WeakMap();\nvar macEncodingCacheKeys;\nvar getMacEncodingTable = function(encoding) {\n // Since we use encoding as a cache key for WeakMap, it has to be\n // a String object and not a literal. And at least on NodeJS 2.10.1,\n // WeakMap requires that the same String instance is passed for cache hits.\n if (!macEncodingCacheKeys) {\n macEncodingCacheKeys = {};\n for (var e in eightBitMacEncodings) {\n /*jshint -W053 */ // Suppress \"Do not use String as a constructor.\"\n macEncodingCacheKeys[e] = new String(e);\n }\n }\n\n var cacheKey = macEncodingCacheKeys[encoding];\n if (cacheKey === undefined) {\n return undefined;\n }\n\n // We can't do \"if (cache.has(key)) {return cache.get(key)}\" here:\n // since garbage collection may run at any time, it could also kick in\n // between the calls to cache.has() and cache.get(). In that case,\n // we would return 'undefined' even though we do support the encoding.\n if (macEncodingTableCache) {\n var cachedTable = macEncodingTableCache.get(cacheKey);\n if (cachedTable !== undefined) {\n return cachedTable;\n }\n }\n\n var decodingTable = eightBitMacEncodings[encoding];\n if (decodingTable === undefined) {\n return undefined;\n }\n\n var encodingTable = {};\n for (var i = 0; i < decodingTable.length; i++) {\n encodingTable[decodingTable.charCodeAt(i)] = i + 0x80;\n }\n\n if (macEncodingTableCache) {\n macEncodingTableCache.set(cacheKey, encodingTable);\n }\n\n return encodingTable;\n};\n\n// Encodes an old-style Macintosh string. Returns a byte array upon success.\n// If the requested encoding is unsupported, or if the input string contains\n// a character that cannot be expressed in the encoding, the function returns\n// 'undefined'.\nencode.MACSTRING = function(str, encoding) {\n var table = getMacEncodingTable(encoding);\n if (table === undefined) {\n return undefined;\n }\n\n var result = [];\n for (var i = 0; i < str.length; i++) {\n var c = str.charCodeAt(i);\n\n // In all eight-bit Mac encodings, the characters 0x00..0x7F are\n // mapped to U+0000..U+007F; we only need to look up the others.\n if (c >= 0x80) {\n c = table[c];\n if (c === undefined) {\n // str contains a Unicode character that cannot be encoded\n // in the requested encoding.\n return undefined;\n }\n }\n\n result.push(c);\n }\n\n return result;\n};\n\nsizeOf.MACSTRING = function(str, encoding) {\n var b = encode.MACSTRING(str, encoding);\n if (b !== undefined) {\n return b.length;\n } else {\n return 0;\n }\n};\n\n// Convert a list of values to a CFF INDEX structure.\n// The values should be objects containing name / type / value.\nencode.INDEX = function(l) {\n var i;\n //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,\n // i, v;\n // Because we have to know which data type to use to encode the offsets,\n // we have to go through the values twice: once to encode the data and\n // calculate the offets, then again to encode the offsets using the fitting data type.\n var offset = 1; // First offset is always 1.\n var offsets = [offset];\n var data = [];\n for (i = 0; i < l.length; i += 1) {\n var v = encode.OBJECT(l[i]);\n Array.prototype.push.apply(data, v);\n offset += v.length;\n offsets.push(offset);\n }\n\n if (data.length === 0) {\n return [0, 0];\n }\n\n var encodedOffsets = [];\n var offSize = (1 + Math.floor(Math.log(offset) / Math.log(2)) / 8) | 0;\n var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];\n for (i = 0; i < offsets.length; i += 1) {\n var encodedOffset = offsetEncoder(offsets[i]);\n Array.prototype.push.apply(encodedOffsets, encodedOffset);\n }\n\n return Array.prototype.concat(encode.Card16(l.length),\n encode.OffSize(offSize),\n encodedOffsets,\n data);\n};\n\nsizeOf.INDEX = function(v) {\n return encode.INDEX(v).length;\n};\n\n// Convert an object to a CFF DICT structure.\n// The keys should be numeric.\n// The values should be objects containing name / type / value.\nencode.DICT = function(m) {\n var d = [];\n var keys = Object.keys(m);\n var length = keys.length;\n\n for (var i = 0; i < length; i += 1) {\n // Object.keys() return string keys, but our keys are always numeric.\n var k = parseInt(keys[i], 0);\n var v = m[k];\n // Value comes before the key.\n d = d.concat(encode.OPERAND(v.value, v.type));\n d = d.concat(encode.OPERATOR(k));\n }\n\n return d;\n};\n\nsizeOf.DICT = function(m) {\n return encode.DICT(m).length;\n};\n\nencode.OPERATOR = function(v) {\n if (v < 1200) {\n return [v];\n } else {\n return [12, v - 1200];\n }\n};\n\nencode.OPERAND = function(v, type) {\n var d = [];\n if (Array.isArray(type)) {\n for (var i = 0; i < type.length; i += 1) {\n check.argument(v.length === type.length, 'Not enough arguments given for type' + type);\n d = d.concat(encode.OPERAND(v[i], type[i]));\n }\n } else {\n if (type === 'SID') {\n d = d.concat(encode.NUMBER(v));\n } else if (type === 'offset') {\n // We make it easy for ourselves and always encode offsets as\n // 4 bytes. This makes offset calculation for the top dict easier.\n d = d.concat(encode.NUMBER32(v));\n } else if (type === 'number') {\n d = d.concat(encode.NUMBER(v));\n } else if (type === 'real') {\n d = d.concat(encode.REAL(v));\n } else {\n throw new Error('Unknown operand type ' + type);\n // FIXME Add support for booleans\n }\n }\n\n return d;\n};\n\nencode.OP = encode.BYTE;\nsizeOf.OP = sizeOf.BYTE;\n\n// memoize charstring encoding using WeakMap if available\nvar wmm = typeof WeakMap === 'function' && new WeakMap();\n// Convert a list of CharString operations to bytes.\nencode.CHARSTRING = function(ops) {\n // See encode.MACSTRING for why we don't do \"if (wmm && wmm.has(ops))\".\n if (wmm) {\n var cachedValue = wmm.get(ops);\n if (cachedValue !== undefined) {\n return cachedValue;\n }\n }\n\n var d = [];\n var length = ops.length;\n\n for (var i = 0; i < length; i += 1) {\n var op = ops[i];\n d = d.concat(encode[op.type](op.value));\n }\n\n if (wmm) {\n wmm.set(ops, d);\n }\n\n return d;\n};\n\nsizeOf.CHARSTRING = function(ops) {\n return encode.CHARSTRING(ops).length;\n};\n\n// Utility functions ////////////////////////////////////////////////////////\n\n// Convert an object containing name / type / value to bytes.\nencode.OBJECT = function(v) {\n var encodingFunction = encode[v.type];\n check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);\n return encodingFunction(v.value);\n};\n\nsizeOf.OBJECT = function(v) {\n var sizeOfFunction = sizeOf[v.type];\n check.argument(sizeOfFunction !== undefined, 'No sizeOf function for type ' + v.type);\n return sizeOfFunction(v.value);\n};\n\n// Convert a table object to bytes.\n// A table contains a list of fields containing the metadata (name, type and default value).\n// The table itself has the field values set as attributes.\nencode.TABLE = function(table) {\n var d = [];\n var length = table.fields.length;\n var subtables = [];\n var subtableOffsets = [];\n var i;\n\n for (i = 0; i < length; i += 1) {\n var field = table.fields[i];\n var encodingFunction = encode[field.type];\n check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type + ' (' + field.name + ')');\n var value = table[field.name];\n if (value === undefined) {\n value = field.value;\n }\n\n var bytes = encodingFunction(value);\n\n if (field.type === 'TABLE') {\n subtableOffsets.push(d.length);\n d = d.concat([0, 0]);\n subtables.push(bytes);\n } else {\n d = d.concat(bytes);\n }\n }\n\n for (i = 0; i < subtables.length; i += 1) {\n var o = subtableOffsets[i];\n var offset = d.length;\n check.argument(offset < 65536, 'Table ' + table.tableName + ' too big.');\n d[o] = offset >> 8;\n d[o + 1] = offset & 0xff;\n d = d.concat(subtables[i]);\n }\n\n return d;\n};\n\nsizeOf.TABLE = function(table) {\n var numBytes = 0;\n var length = table.fields.length;\n\n for (var i = 0; i < length; i += 1) {\n var field = table.fields[i];\n var sizeOfFunction = sizeOf[field.type];\n check.argument(sizeOfFunction !== undefined, 'No sizeOf function for field type ' + field.type + ' (' + field.name + ')');\n var value = table[field.name];\n if (value === undefined) {\n value = field.value;\n }\n\n numBytes += sizeOfFunction(value);\n\n // Subtables take 2 more bytes for offsets.\n if (field.type === 'TABLE') {\n numBytes += 2;\n }\n }\n\n return numBytes;\n};\n\nencode.RECORD = encode.TABLE;\nsizeOf.RECORD = sizeOf.TABLE;\n\n// Merge in a list of bytes.\nencode.LITERAL = function(v) {\n return v;\n};\n\nsizeOf.LITERAL = function(v) {\n return v.length;\n};\n\nexports.decode = decode;\nexports.encode = encode;\nexports.sizeOf = sizeOf;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/types.js\n ** module id = 10\n ** module chunks = 0\n **/","// The `cmap` table stores the mappings from characters to glyphs.\n// https://www.microsoft.com/typography/OTSPEC/cmap.htm\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the `cmap` table. This table stores the mappings from characters to glyphs.\n// There are many available formats, but we only support the Windows format 4.\n// This function returns a `CmapEncoding` object or null if no supported format could be found.\nfunction parseCmapTable(data, start) {\n var i;\n var cmap = {};\n cmap.version = parse.getUShort(data, start);\n check.argument(cmap.version === 0, 'cmap table version should be 0.');\n\n // The cmap table can contain many sub-tables, each with their own format.\n // We're only interested in a \"platform 3\" table. This is a Windows format.\n cmap.numTables = parse.getUShort(data, start + 2);\n var offset = -1;\n for (i = 0; i < cmap.numTables; i += 1) {\n var platformId = parse.getUShort(data, start + 4 + (i * 8));\n var encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2);\n if (platformId === 3 && (encodingId === 1 || encodingId === 0)) {\n offset = parse.getULong(data, start + 4 + (i * 8) + 4);\n break;\n }\n }\n\n if (offset === -1) {\n // There is no cmap table in the font that we support, so return null.\n // This font will be marked as unsupported.\n return null;\n }\n\n var p = new parse.Parser(data, start + offset);\n cmap.format = p.parseUShort();\n check.argument(cmap.format === 4, 'Only format 4 cmap tables are supported.');\n\n // Length in bytes of the sub-tables.\n cmap.length = p.parseUShort();\n cmap.language = p.parseUShort();\n\n // segCount is stored x 2.\n var segCount;\n cmap.segCount = segCount = p.parseUShort() >> 1;\n\n // Skip searchRange, entrySelector, rangeShift.\n p.skip('uShort', 3);\n\n // The \"unrolled\" mapping from character codes to glyph indices.\n cmap.glyphIndexMap = {};\n\n var endCountParser = new parse.Parser(data, start + offset + 14);\n var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);\n var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);\n var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);\n var glyphIndexOffset = start + offset + 16 + segCount * 8;\n for (i = 0; i < segCount - 1; i += 1) {\n var glyphIndex;\n var endCount = endCountParser.parseUShort();\n var startCount = startCountParser.parseUShort();\n var idDelta = idDeltaParser.parseShort();\n var idRangeOffset = idRangeOffsetParser.parseUShort();\n for (var c = startCount; c <= endCount; c += 1) {\n if (idRangeOffset !== 0) {\n // The idRangeOffset is relative to the current position in the idRangeOffset array.\n // Take the current offset in the idRangeOffset array.\n glyphIndexOffset = (idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2);\n\n // Add the value of the idRangeOffset, which will move us into the glyphIndex array.\n glyphIndexOffset += idRangeOffset;\n\n // Then add the character index of the current segment, multiplied by 2 for USHORTs.\n glyphIndexOffset += (c - startCount) * 2;\n glyphIndex = parse.getUShort(data, glyphIndexOffset);\n if (glyphIndex !== 0) {\n glyphIndex = (glyphIndex + idDelta) & 0xFFFF;\n }\n } else {\n glyphIndex = (c + idDelta) & 0xFFFF;\n }\n\n cmap.glyphIndexMap[c] = glyphIndex;\n }\n }\n\n return cmap;\n}\n\nfunction addSegment(t, code, glyphIndex) {\n t.segments.push({\n end: code,\n start: code,\n delta: -(code - glyphIndex),\n offset: 0\n });\n}\n\nfunction addTerminatorSegment(t) {\n t.segments.push({\n end: 0xFFFF,\n start: 0xFFFF,\n delta: 1,\n offset: 0\n });\n}\n\nfunction makeCmapTable(glyphs) {\n var i;\n var t = new table.Table('cmap', [\n {name: 'version', type: 'USHORT', value: 0},\n {name: 'numTables', type: 'USHORT', value: 1},\n {name: 'platformID', type: 'USHORT', value: 3},\n {name: 'encodingID', type: 'USHORT', value: 1},\n {name: 'offset', type: 'ULONG', value: 12},\n {name: 'format', type: 'USHORT', value: 4},\n {name: 'length', type: 'USHORT', value: 0},\n {name: 'language', type: 'USHORT', value: 0},\n {name: 'segCountX2', type: 'USHORT', value: 0},\n {name: 'searchRange', type: 'USHORT', value: 0},\n {name: 'entrySelector', type: 'USHORT', value: 0},\n {name: 'rangeShift', type: 'USHORT', value: 0}\n ]);\n\n t.segments = [];\n for (i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs.get(i);\n for (var j = 0; j < glyph.unicodes.length; j += 1) {\n addSegment(t, glyph.unicodes[j], i);\n }\n\n t.segments = t.segments.sort(function(a, b) {\n return a.start - b.start;\n });\n }\n\n addTerminatorSegment(t);\n\n var segCount;\n segCount = t.segments.length;\n t.segCountX2 = segCount * 2;\n t.searchRange = Math.pow(2, Math.floor(Math.log(segCount) / Math.log(2))) * 2;\n t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2);\n t.rangeShift = t.segCountX2 - t.searchRange;\n\n // Set up parallel segment arrays.\n var endCounts = [];\n var startCounts = [];\n var idDeltas = [];\n var idRangeOffsets = [];\n var glyphIds = [];\n\n for (i = 0; i < segCount; i += 1) {\n var segment = t.segments[i];\n endCounts = endCounts.concat({name: 'end_' + i, type: 'USHORT', value: segment.end});\n startCounts = startCounts.concat({name: 'start_' + i, type: 'USHORT', value: segment.start});\n idDeltas = idDeltas.concat({name: 'idDelta_' + i, type: 'SHORT', value: segment.delta});\n idRangeOffsets = idRangeOffsets.concat({name: 'idRangeOffset_' + i, type: 'USHORT', value: segment.offset});\n if (segment.glyphId !== undefined) {\n glyphIds = glyphIds.concat({name: 'glyph_' + i, type: 'USHORT', value: segment.glyphId});\n }\n }\n\n t.fields = t.fields.concat(endCounts);\n t.fields.push({name: 'reservedPad', type: 'USHORT', value: 0});\n t.fields = t.fields.concat(startCounts);\n t.fields = t.fields.concat(idDeltas);\n t.fields = t.fields.concat(idRangeOffsets);\n t.fields = t.fields.concat(glyphIds);\n\n t.length = 14 + // Subtable header\n endCounts.length * 2 +\n 2 + // reservedPad\n startCounts.length * 2 +\n idDeltas.length * 2 +\n idRangeOffsets.length * 2 +\n glyphIds.length * 2;\n\n return t;\n}\n\nexports.parse = parseCmapTable;\nexports.make = makeCmapTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/cmap.js\n ** module id = 11\n ** module chunks = 0\n **/","// Parsing utility functions\n\n'use strict';\n\nvar check = require('./check');\n\n// Retrieve an unsigned byte from the DataView.\nexports.getByte = function getByte(dataView, offset) {\n return dataView.getUint8(offset);\n};\n\nexports.getCard8 = exports.getByte;\n\n// Retrieve an unsigned 16-bit short from the DataView.\n// The value is stored in big endian.\nfunction getUShort(dataView, offset) {\n return dataView.getUint16(offset, false);\n}\n\nexports.getUShort = exports.getCard16 = getUShort;\n\n// Retrieve a signed 16-bit short from the DataView.\n// The value is stored in big endian.\nexports.getShort = function(dataView, offset) {\n return dataView.getInt16(offset, false);\n};\n\n// Retrieve an unsigned 32-bit long from the DataView.\n// The value is stored in big endian.\nexports.getULong = function(dataView, offset) {\n return dataView.getUint32(offset, false);\n};\n\n// Retrieve a 32-bit signed fixed-point number (16.16) from the DataView.\n// The value is stored in big endian.\nexports.getFixed = function(dataView, offset) {\n var decimal = dataView.getInt16(offset, false);\n var fraction = dataView.getUint16(offset + 2, false);\n return decimal + fraction / 65535;\n};\n\n// Retrieve a 4-character tag from the DataView.\n// Tags are used to identify tables.\nexports.getTag = function(dataView, offset) {\n var tag = '';\n for (var i = offset; i < offset + 4; i += 1) {\n tag += String.fromCharCode(dataView.getInt8(i));\n }\n\n return tag;\n};\n\n// Retrieve an offset from the DataView.\n// Offsets are 1 to 4 bytes in length, depending on the offSize argument.\nexports.getOffset = function(dataView, offset, offSize) {\n var v = 0;\n for (var i = 0; i < offSize; i += 1) {\n v <<= 8;\n v += dataView.getUint8(offset + i);\n }\n\n return v;\n};\n\n// Retrieve a number of bytes from start offset to the end offset from the DataView.\nexports.getBytes = function(dataView, startOffset, endOffset) {\n var bytes = [];\n for (var i = startOffset; i < endOffset; i += 1) {\n bytes.push(dataView.getUint8(i));\n }\n\n return bytes;\n};\n\n// Convert the list of bytes to a string.\nexports.bytesToString = function(bytes) {\n var s = '';\n for (var i = 0; i < bytes.length; i += 1) {\n s += String.fromCharCode(bytes[i]);\n }\n\n return s;\n};\n\nvar typeOffsets = {\n byte: 1,\n uShort: 2,\n short: 2,\n uLong: 4,\n fixed: 4,\n longDateTime: 8,\n tag: 4\n};\n\n// A stateful parser that changes the offset whenever a value is retrieved.\n// The data is a DataView.\nfunction Parser(data, offset) {\n this.data = data;\n this.offset = offset;\n this.relativeOffset = 0;\n}\n\nParser.prototype.parseByte = function() {\n var v = this.data.getUint8(this.offset + this.relativeOffset);\n this.relativeOffset += 1;\n return v;\n};\n\nParser.prototype.parseChar = function() {\n var v = this.data.getInt8(this.offset + this.relativeOffset);\n this.relativeOffset += 1;\n return v;\n};\n\nParser.prototype.parseCard8 = Parser.prototype.parseByte;\n\nParser.prototype.parseUShort = function() {\n var v = this.data.getUint16(this.offset + this.relativeOffset);\n this.relativeOffset += 2;\n return v;\n};\n\nParser.prototype.parseCard16 = Parser.prototype.parseUShort;\nParser.prototype.parseSID = Parser.prototype.parseUShort;\nParser.prototype.parseOffset16 = Parser.prototype.parseUShort;\n\nParser.prototype.parseShort = function() {\n var v = this.data.getInt16(this.offset + this.relativeOffset);\n this.relativeOffset += 2;\n return v;\n};\n\nParser.prototype.parseF2Dot14 = function() {\n var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;\n this.relativeOffset += 2;\n return v;\n};\n\nParser.prototype.parseULong = function() {\n var v = exports.getULong(this.data, this.offset + this.relativeOffset);\n this.relativeOffset += 4;\n return v;\n};\n\nParser.prototype.parseFixed = function() {\n var v = exports.getFixed(this.data, this.offset + this.relativeOffset);\n this.relativeOffset += 4;\n return v;\n};\n\nParser.prototype.parseString = function(length) {\n var dataView = this.data;\n var offset = this.offset + this.relativeOffset;\n var string = '';\n this.relativeOffset += length;\n for (var i = 0; i < length; i++) {\n string += String.fromCharCode(dataView.getUint8(offset + i));\n }\n\n return string;\n};\n\nParser.prototype.parseTag = function() {\n return this.parseString(4);\n};\n\n// LONGDATETIME is a 64-bit integer.\n// JavaScript and unix timestamps traditionally use 32 bits, so we\n// only take the last 32 bits.\n// + Since until 2038 those bits will be filled by zeros we can ignore them.\nParser.prototype.parseLongDateTime = function() {\n var v = exports.getULong(this.data, this.offset + this.relativeOffset + 4);\n // Subtract seconds between 01/01/1904 and 01/01/1970\n // to convert Apple Mac timstamp to Standard Unix timestamp\n v -= 2082844800;\n this.relativeOffset += 8;\n return v;\n};\n\nParser.prototype.parseVersion = function() {\n var major = getUShort(this.data, this.offset + this.relativeOffset);\n\n // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1\n // This returns the correct number if minor = 0xN000 where N is 0-9\n var minor = getUShort(this.data, this.offset + this.relativeOffset + 2);\n this.relativeOffset += 4;\n return major + minor / 0x1000 / 10;\n};\n\nParser.prototype.skip = function(type, amount) {\n if (amount === undefined) {\n amount = 1;\n }\n\n this.relativeOffset += typeOffsets[type] * amount;\n};\n\n///// Parsing lists and records ///////////////////////////////\n\n// Parse a list of 16 bit integers. The length of the list can be read on the stream\n// or provided as an argument.\nParser.prototype.parseOffset16List =\nParser.prototype.parseUShortList = function(count) {\n if (count === undefined) { count = this.parseUShort(); }\n var offsets = new Array(count);\n var dataView = this.data;\n var offset = this.offset + this.relativeOffset;\n for (var i = 0; i < count; i++) {\n offsets[i] = dataView.getUint16(offset);\n offset += 2;\n }\n\n this.relativeOffset += count * 2;\n return offsets;\n};\n\n/**\n * Parse a list of items.\n * Record count is optional, if omitted it is read from the stream.\n * itemCallback is one of the Parser methods.\n */\nParser.prototype.parseList = function(count, itemCallback) {\n if (!itemCallback) {\n itemCallback = count;\n count = this.parseUShort();\n }\n var list = new Array(count);\n for (var i = 0; i < count; i++) {\n list[i] = itemCallback.call(this);\n }\n return list;\n};\n\n/**\n * Parse a list of records.\n * Record count is optional, if omitted it is read from the stream.\n * Example of recordDescription: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }\n */\nParser.prototype.parseRecordList = function(count, recordDescription) {\n // If the count argument is absent, read it in the stream.\n if (!recordDescription) {\n recordDescription = count;\n count = this.parseUShort();\n }\n var records = new Array(count);\n var fields = Object.keys(recordDescription);\n for (var i = 0; i < count; i++) {\n var rec = {};\n for (var j = 0; j < fields.length; j++) {\n var fieldName = fields[j];\n var fieldType = recordDescription[fieldName];\n rec[fieldName] = fieldType.call(this);\n }\n records[i] = rec;\n }\n return records;\n};\n\n// Parse a data structure into an object\n// Example of description: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }\nParser.prototype.parseStruct = function(description) {\n if (typeof description === 'function') {\n return description.call(this);\n } else {\n var fields = Object.keys(description);\n var struct = {};\n for (var j = 0; j < fields.length; j++) {\n var fieldName = fields[j];\n var fieldType = description[fieldName];\n struct[fieldName] = fieldType.call(this);\n }\n return struct;\n }\n};\n\nParser.prototype.parsePointer = function(description) {\n var structOffset = this.parseOffset16();\n if (structOffset > 0) { // NULL offset => return indefined\n return new Parser(this.data, this.offset + structOffset).parseStruct(description);\n }\n};\n\n/**\n * Parse a list of offsets to lists of 16-bit integers,\n * or a list of offsets to lists of offsets to any kind of items.\n * If itemCallback is not provided, a list of list of UShort is assumed.\n * If provided, itemCallback is called on each item and must parse the item.\n * See examples in tables/gsub.js\n */\nParser.prototype.parseListOfLists = function(itemCallback) {\n var offsets = this.parseOffset16List();\n var count = offsets.length;\n var relativeOffset = this.relativeOffset;\n var list = new Array(count);\n for (var i = 0; i < count; i++) {\n var start = offsets[i];\n if (start === 0) { // NULL offset\n list[i] = undefined; // Add i as owned property to list. Convenient with assert.\n continue;\n }\n this.relativeOffset = start;\n if (itemCallback) {\n var subOffsets = this.parseOffset16List();\n var subList = new Array(subOffsets.length);\n for (var j = 0; j < subOffsets.length; j++) {\n this.relativeOffset = start + subOffsets[j];\n subList[j] = itemCallback.call(this);\n }\n list[i] = subList;\n } else {\n list[i] = this.parseUShortList();\n }\n }\n this.relativeOffset = relativeOffset;\n return list;\n};\n\n///// Complex tables parsing //////////////////////////////////\n\n// Parse a coverage table in a GSUB, GPOS or GDEF table.\n// https://www.microsoft.com/typography/OTSPEC/chapter2.htm\n// parser.offset must point to the start of the table containing the coverage.\nParser.prototype.parseCoverage = function() {\n var startOffset = this.offset + this.relativeOffset;\n var format = this.parseUShort();\n var count = this.parseUShort();\n if (format === 1) {\n return {\n format: 1,\n glyphs: this.parseUShortList(count)\n };\n } else if (format === 2) {\n var ranges = new Array(count);\n for (var i = 0; i < count; i++) {\n ranges[i] = {\n start: this.parseUShort(),\n end: this.parseUShort(),\n index: this.parseUShort()\n };\n }\n return {\n format: 2,\n ranges: ranges\n };\n }\n check.assert(false, '0x' + startOffset.toString(16) + ': Coverage format must be 1 or 2.');\n};\n\n// Parse a Class Definition Table in a GSUB, GPOS or GDEF table.\n// https://www.microsoft.com/typography/OTSPEC/chapter2.htm\nParser.prototype.parseClassDef = function() {\n var startOffset = this.offset + this.relativeOffset;\n var format = this.parseUShort();\n if (format === 1) {\n return {\n format: 1,\n startGlyph: this.parseUShort(),\n classes: this.parseUShortList()\n };\n } else if (format === 2) {\n return {\n format: 2,\n ranges: this.parseRecordList({\n start: Parser.uShort,\n end: Parser.uShort,\n classId: Parser.uShort\n })\n };\n }\n check.assert(false, '0x' + startOffset.toString(16) + ': ClassDef format must be 1 or 2.');\n};\n\n///// Static methods ///////////////////////////////////\n// These convenience methods can be used as callbacks and should be called with \"this\" context set to a Parser instance.\n\nParser.list = function(count, itemCallback) {\n return function() {\n return this.parseList(count, itemCallback);\n };\n};\n\nParser.recordList = function(count, recordDescription) {\n return function() {\n return this.parseRecordList(count, recordDescription);\n };\n};\n\nParser.pointer = function(description) {\n return function() {\n return this.parsePointer(description);\n };\n};\n\nParser.tag = Parser.prototype.parseTag;\nParser.byte = Parser.prototype.parseByte;\nParser.uShort = Parser.offset16 = Parser.prototype.parseUShort;\nParser.uShortList = Parser.prototype.parseUShortList;\nParser.struct = Parser.prototype.parseStruct;\nParser.coverage = Parser.prototype.parseCoverage;\nParser.classDef = Parser.prototype.parseClassDef;\n\n///// Script, Feature, Lookup lists ///////////////////////////////////////////////\n// https://www.microsoft.com/typography/OTSPEC/chapter2.htm\n\nvar langSysTable = {\n reserved: Parser.uShort,\n reqFeatureIndex: Parser.uShort,\n featureIndexes: Parser.uShortList\n};\n\nParser.prototype.parseScriptList = function() {\n return this.parsePointer(Parser.recordList({\n tag: Parser.tag,\n script: Parser.pointer({\n defaultLangSys: Parser.pointer(langSysTable),\n langSysRecords: Parser.recordList({\n tag: Parser.tag,\n langSys: Parser.pointer(langSysTable)\n })\n })\n }));\n};\n\nParser.prototype.parseFeatureList = function() {\n return this.parsePointer(Parser.recordList({\n tag: Parser.tag,\n feature: Parser.pointer({\n featureParams: Parser.offset16,\n lookupListIndexes: Parser.uShortList\n })\n }));\n};\n\nParser.prototype.parseLookupList = function(lookupTableParsers) {\n return this.parsePointer(Parser.list(Parser.pointer(function() {\n var lookupType = this.parseUShort();\n check.argument(1 <= lookupType && lookupType <= 8, 'GSUB lookup type ' + lookupType + ' unknown.');\n var lookupFlag = this.parseUShort();\n var useMarkFilteringSet = lookupFlag & 0x10;\n return {\n lookupType: lookupType,\n lookupFlag: lookupFlag,\n subtables: this.parseList(Parser.pointer(lookupTableParsers[lookupType])),\n markFilteringSet: useMarkFilteringSet ? this.parseUShort() : undefined\n };\n })));\n};\n\nexports.Parser = Parser;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/parse.js\n ** module id = 12\n ** module chunks = 0\n **/","// The `CFF` table contains the glyph outlines in PostScript format.\n// https://www.microsoft.com/typography/OTSPEC/cff.htm\n// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/cff.pdf\n// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/type2.pdf\n\n'use strict';\n\nvar encoding = require('../encoding');\nvar glyphset = require('../glyphset');\nvar parse = require('../parse');\nvar path = require('../path');\nvar table = require('../table');\n\n// Custom equals function that can also check lists.\nfunction equals(a, b) {\n if (a === b) {\n return true;\n } else if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false;\n }\n\n for (var i = 0; i < a.length; i += 1) {\n if (!equals(a[i], b[i])) {\n return false;\n }\n }\n\n return true;\n } else {\n return false;\n }\n}\n\n// Parse a `CFF` INDEX array.\n// An index array consists of a list of offsets, then a list of objects at those offsets.\nfunction parseCFFIndex(data, start, conversionFn) {\n //var i, objectOffset, endOffset;\n var offsets = [];\n var objects = [];\n var count = parse.getCard16(data, start);\n var i;\n var objectOffset;\n var endOffset;\n if (count !== 0) {\n var offsetSize = parse.getByte(data, start + 2);\n objectOffset = start + ((count + 1) * offsetSize) + 2;\n var pos = start + 3;\n for (i = 0; i < count + 1; i += 1) {\n offsets.push(parse.getOffset(data, pos, offsetSize));\n pos += offsetSize;\n }\n\n // The total size of the index array is 4 header bytes + the value of the last offset.\n endOffset = objectOffset + offsets[count];\n } else {\n endOffset = start + 2;\n }\n\n for (i = 0; i < offsets.length - 1; i += 1) {\n var value = parse.getBytes(data, objectOffset + offsets[i], objectOffset + offsets[i + 1]);\n if (conversionFn) {\n value = conversionFn(value);\n }\n\n objects.push(value);\n }\n\n return {objects: objects, startOffset: start, endOffset: endOffset};\n}\n\n// Parse a `CFF` DICT real value.\nfunction parseFloatOperand(parser) {\n var s = '';\n var eof = 15;\n var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];\n while (true) {\n var b = parser.parseByte();\n var n1 = b >> 4;\n var n2 = b & 15;\n\n if (n1 === eof) {\n break;\n }\n\n s += lookup[n1];\n\n if (n2 === eof) {\n break;\n }\n\n s += lookup[n2];\n }\n\n return parseFloat(s);\n}\n\n// Parse a `CFF` DICT operand.\nfunction parseOperand(parser, b0) {\n var b1;\n var b2;\n var b3;\n var b4;\n if (b0 === 28) {\n b1 = parser.parseByte();\n b2 = parser.parseByte();\n return b1 << 8 | b2;\n }\n\n if (b0 === 29) {\n b1 = parser.parseByte();\n b2 = parser.parseByte();\n b3 = parser.parseByte();\n b4 = parser.parseByte();\n return b1 << 24 | b2 << 16 | b3 << 8 | b4;\n }\n\n if (b0 === 30) {\n return parseFloatOperand(parser);\n }\n\n if (b0 >= 32 && b0 <= 246) {\n return b0 - 139;\n }\n\n if (b0 >= 247 && b0 <= 250) {\n b1 = parser.parseByte();\n return (b0 - 247) * 256 + b1 + 108;\n }\n\n if (b0 >= 251 && b0 <= 254) {\n b1 = parser.parseByte();\n return -(b0 - 251) * 256 - b1 - 108;\n }\n\n throw new Error('Invalid b0 ' + b0);\n}\n\n// Convert the entries returned by `parseDict` to a proper dictionary.\n// If a value is a list of one, it is unpacked.\nfunction entriesToObject(entries) {\n var o = {};\n for (var i = 0; i < entries.length; i += 1) {\n var key = entries[i][0];\n var values = entries[i][1];\n var value;\n if (values.length === 1) {\n value = values[0];\n } else {\n value = values;\n }\n\n if (o.hasOwnProperty(key)) {\n throw new Error('Object ' + o + ' already has key ' + key);\n }\n\n o[key] = value;\n }\n\n return o;\n}\n\n// Parse a `CFF` DICT object.\n// A dictionary contains key-value pairs in a compact tokenized format.\nfunction parseCFFDict(data, start, size) {\n start = start !== undefined ? start : 0;\n var parser = new parse.Parser(data, start);\n var entries = [];\n var operands = [];\n size = size !== undefined ? size : data.length;\n\n while (parser.relativeOffset < size) {\n var op = parser.parseByte();\n\n // The first byte for each dict item distinguishes between operator (key) and operand (value).\n // Values <= 21 are operators.\n if (op <= 21) {\n // Two-byte operators have an initial escape byte of 12.\n if (op === 12) {\n op = 1200 + parser.parseByte();\n }\n\n entries.push([op, operands]);\n operands = [];\n } else {\n // Since the operands (values) come before the operators (keys), we store all operands in a list\n // until we encounter an operator.\n operands.push(parseOperand(parser, op));\n }\n }\n\n return entriesToObject(entries);\n}\n\n// Given a String Index (SID), return the value of the string.\n// Strings below index 392 are standard CFF strings and are not encoded in the font.\nfunction getCFFString(strings, index) {\n if (index <= 390) {\n index = encoding.cffStandardStrings[index];\n } else {\n index = strings[index - 391];\n }\n\n return index;\n}\n\n// Interpret a dictionary and return a new dictionary with readable keys and values for missing entries.\n// This function takes `meta` which is a list of objects containing `operand`, `name` and `default`.\nfunction interpretDict(dict, meta, strings) {\n var newDict = {};\n\n // Because we also want to include missing values, we start out from the meta list\n // and lookup values in the dict.\n for (var i = 0; i < meta.length; i += 1) {\n var m = meta[i];\n var value = dict[m.op];\n if (value === undefined) {\n value = m.value !== undefined ? m.value : null;\n }\n\n if (m.type === 'SID') {\n value = getCFFString(strings, value);\n }\n\n newDict[m.name] = value;\n }\n\n return newDict;\n}\n\n// Parse the CFF header.\nfunction parseCFFHeader(data, start) {\n var header = {};\n header.formatMajor = parse.getCard8(data, start);\n header.formatMinor = parse.getCard8(data, start + 1);\n header.size = parse.getCard8(data, start + 2);\n header.offsetSize = parse.getCard8(data, start + 3);\n header.startOffset = start;\n header.endOffset = start + 4;\n return header;\n}\n\nvar TOP_DICT_META = [\n {name: 'version', op: 0, type: 'SID'},\n {name: 'notice', op: 1, type: 'SID'},\n {name: 'copyright', op: 1200, type: 'SID'},\n {name: 'fullName', op: 2, type: 'SID'},\n {name: 'familyName', op: 3, type: 'SID'},\n {name: 'weight', op: 4, type: 'SID'},\n {name: 'isFixedPitch', op: 1201, type: 'number', value: 0},\n {name: 'italicAngle', op: 1202, type: 'number', value: 0},\n {name: 'underlinePosition', op: 1203, type: 'number', value: -100},\n {name: 'underlineThickness', op: 1204, type: 'number', value: 50},\n {name: 'paintType', op: 1205, type: 'number', value: 0},\n {name: 'charstringType', op: 1206, type: 'number', value: 2},\n {name: 'fontMatrix', op: 1207, type: ['real', 'real', 'real', 'real', 'real', 'real'], value: [0.001, 0, 0, 0.001, 0, 0]},\n {name: 'uniqueId', op: 13, type: 'number'},\n {name: 'fontBBox', op: 5, type: ['number', 'number', 'number', 'number'], value: [0, 0, 0, 0]},\n {name: 'strokeWidth', op: 1208, type: 'number', value: 0},\n {name: 'xuid', op: 14, type: [], value: null},\n {name: 'charset', op: 15, type: 'offset', value: 0},\n {name: 'encoding', op: 16, type: 'offset', value: 0},\n {name: 'charStrings', op: 17, type: 'offset', value: 0},\n {name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0]}\n];\n\nvar PRIVATE_DICT_META = [\n {name: 'subrs', op: 19, type: 'offset', value: 0},\n {name: 'defaultWidthX', op: 20, type: 'number', value: 0},\n {name: 'nominalWidthX', op: 21, type: 'number', value: 0}\n];\n\n// Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary.\n// The top dictionary contains the essential metadata for the font, together with the private dictionary.\nfunction parseCFFTopDict(data, strings) {\n var dict = parseCFFDict(data, 0, data.byteLength);\n return interpretDict(dict, TOP_DICT_META, strings);\n}\n\n// Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need.\nfunction parseCFFPrivateDict(data, start, size, strings) {\n var dict = parseCFFDict(data, start, size);\n return interpretDict(dict, PRIVATE_DICT_META, strings);\n}\n\n// Parse the CFF charset table, which contains internal names for all the glyphs.\n// This function will return a list of glyph names.\n// See Adobe TN #5176 chapter 13, \"Charsets\".\nfunction parseCFFCharset(data, start, nGlyphs, strings) {\n var i;\n var sid;\n var count;\n var parser = new parse.Parser(data, start);\n\n // The .notdef glyph is not included, so subtract 1.\n nGlyphs -= 1;\n var charset = ['.notdef'];\n\n var format = parser.parseCard8();\n if (format === 0) {\n for (i = 0; i < nGlyphs; i += 1) {\n sid = parser.parseSID();\n charset.push(getCFFString(strings, sid));\n }\n } else if (format === 1) {\n while (charset.length <= nGlyphs) {\n sid = parser.parseSID();\n count = parser.parseCard8();\n for (i = 0; i <= count; i += 1) {\n charset.push(getCFFString(strings, sid));\n sid += 1;\n }\n }\n } else if (format === 2) {\n while (charset.length <= nGlyphs) {\n sid = parser.parseSID();\n count = parser.parseCard16();\n for (i = 0; i <= count; i += 1) {\n charset.push(getCFFString(strings, sid));\n sid += 1;\n }\n }\n } else {\n throw new Error('Unknown charset format ' + format);\n }\n\n return charset;\n}\n\n// Parse the CFF encoding data. Only one encoding can be specified per font.\n// See Adobe TN #5176 chapter 12, \"Encodings\".\nfunction parseCFFEncoding(data, start, charset) {\n var i;\n var code;\n var enc = {};\n var parser = new parse.Parser(data, start);\n var format = parser.parseCard8();\n if (format === 0) {\n var nCodes = parser.parseCard8();\n for (i = 0; i < nCodes; i += 1) {\n code = parser.parseCard8();\n enc[code] = i;\n }\n } else if (format === 1) {\n var nRanges = parser.parseCard8();\n code = 1;\n for (i = 0; i < nRanges; i += 1) {\n var first = parser.parseCard8();\n var nLeft = parser.parseCard8();\n for (var j = first; j <= first + nLeft; j += 1) {\n enc[j] = code;\n code += 1;\n }\n }\n } else {\n throw new Error('Unknown encoding format ' + format);\n }\n\n return new encoding.CffEncoding(enc, charset);\n}\n\n// Take in charstring code and return a Glyph object.\n// The encoding is described in the Type 2 Charstring Format\n// https://www.microsoft.com/typography/OTSPEC/charstr2.htm\nfunction parseCFFCharstring(font, glyph, code) {\n var c1x;\n var c1y;\n var c2x;\n var c2y;\n var p = new path.Path();\n var stack = [];\n var nStems = 0;\n var haveWidth = false;\n var width = font.defaultWidthX;\n var open = false;\n var x = 0;\n var y = 0;\n\n function newContour(x, y) {\n if (open) {\n p.closePath();\n }\n\n p.moveTo(x, y);\n open = true;\n }\n\n function parseStems() {\n var hasWidthArg;\n\n // The number of stem operators on the stack is always even.\n // If the value is uneven, that means a width is specified.\n hasWidthArg = stack.length % 2 !== 0;\n if (hasWidthArg && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n }\n\n nStems += stack.length >> 1;\n stack.length = 0;\n haveWidth = true;\n }\n\n function parse(code) {\n var b1;\n var b2;\n var b3;\n var b4;\n var codeIndex;\n var subrCode;\n var jpx;\n var jpy;\n var c3x;\n var c3y;\n var c4x;\n var c4y;\n\n var i = 0;\n while (i < code.length) {\n var v = code[i];\n i += 1;\n switch (v) {\n case 1: // hstem\n parseStems();\n break;\n case 3: // vstem\n parseStems();\n break;\n case 4: // vmoveto\n if (stack.length > 1 && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n haveWidth = true;\n }\n\n y += stack.pop();\n newContour(x, y);\n break;\n case 5: // rlineto\n while (stack.length > 0) {\n x += stack.shift();\n y += stack.shift();\n p.lineTo(x, y);\n }\n\n break;\n case 6: // hlineto\n while (stack.length > 0) {\n x += stack.shift();\n p.lineTo(x, y);\n if (stack.length === 0) {\n break;\n }\n\n y += stack.shift();\n p.lineTo(x, y);\n }\n\n break;\n case 7: // vlineto\n while (stack.length > 0) {\n y += stack.shift();\n p.lineTo(x, y);\n if (stack.length === 0) {\n break;\n }\n\n x += stack.shift();\n p.lineTo(x, y);\n }\n\n break;\n case 8: // rrcurveto\n while (stack.length > 0) {\n c1x = x + stack.shift();\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + stack.shift();\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n case 10: // callsubr\n codeIndex = stack.pop() + font.subrsBias;\n subrCode = font.subrs[codeIndex];\n if (subrCode) {\n parse(subrCode);\n }\n\n break;\n case 11: // return\n return;\n case 12: // flex operators\n v = code[i];\n i += 1;\n switch (v) {\n case 35: // flex\n // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-\n c1x = x + stack.shift(); // dx1\n c1y = y + stack.shift(); // dy1\n c2x = c1x + stack.shift(); // dx2\n c2y = c1y + stack.shift(); // dy2\n jpx = c2x + stack.shift(); // dx3\n jpy = c2y + stack.shift(); // dy3\n c3x = jpx + stack.shift(); // dx4\n c3y = jpy + stack.shift(); // dy4\n c4x = c3x + stack.shift(); // dx5\n c4y = c3y + stack.shift(); // dy5\n x = c4x + stack.shift(); // dx6\n y = c4y + stack.shift(); // dy6\n stack.shift(); // flex depth\n p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);\n p.curveTo(c3x, c3y, c4x, c4y, x, y);\n break;\n case 34: // hflex\n // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-\n c1x = x + stack.shift(); // dx1\n c1y = y; // dy1\n c2x = c1x + stack.shift(); // dx2\n c2y = c1y + stack.shift(); // dy2\n jpx = c2x + stack.shift(); // dx3\n jpy = c2y; // dy3\n c3x = jpx + stack.shift(); // dx4\n c3y = c2y; // dy4\n c4x = c3x + stack.shift(); // dx5\n c4y = y; // dy5\n x = c4x + stack.shift(); // dx6\n p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);\n p.curveTo(c3x, c3y, c4x, c4y, x, y);\n break;\n case 36: // hflex1\n // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-\n c1x = x + stack.shift(); // dx1\n c1y = y + stack.shift(); // dy1\n c2x = c1x + stack.shift(); // dx2\n c2y = c1y + stack.shift(); // dy2\n jpx = c2x + stack.shift(); // dx3\n jpy = c2y; // dy3\n c3x = jpx + stack.shift(); // dx4\n c3y = c2y; // dy4\n c4x = c3x + stack.shift(); // dx5\n c4y = c3y + stack.shift(); // dy5\n x = c4x + stack.shift(); // dx6\n p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);\n p.curveTo(c3x, c3y, c4x, c4y, x, y);\n break;\n case 37: // flex1\n // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-\n c1x = x + stack.shift(); // dx1\n c1y = y + stack.shift(); // dy1\n c2x = c1x + stack.shift(); // dx2\n c2y = c1y + stack.shift(); // dy2\n jpx = c2x + stack.shift(); // dx3\n jpy = c2y + stack.shift(); // dy3\n c3x = jpx + stack.shift(); // dx4\n c3y = jpy + stack.shift(); // dy4\n c4x = c3x + stack.shift(); // dx5\n c4y = c3y + stack.shift(); // dy5\n if (Math.abs(c4x - x) > Math.abs(c4y - y)) {\n x = c4x + stack.shift();\n } else {\n y = c4y + stack.shift();\n }\n\n p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);\n p.curveTo(c3x, c3y, c4x, c4y, x, y);\n break;\n default:\n console.log('Glyph ' + glyph.index + ': unknown operator ' + 1200 + v);\n stack.length = 0;\n }\n break;\n case 14: // endchar\n if (stack.length > 0 && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n haveWidth = true;\n }\n\n if (open) {\n p.closePath();\n open = false;\n }\n\n break;\n case 18: // hstemhm\n parseStems();\n break;\n case 19: // hintmask\n case 20: // cntrmask\n parseStems();\n i += (nStems + 7) >> 3;\n break;\n case 21: // rmoveto\n if (stack.length > 2 && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n haveWidth = true;\n }\n\n y += stack.pop();\n x += stack.pop();\n newContour(x, y);\n break;\n case 22: // hmoveto\n if (stack.length > 1 && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n haveWidth = true;\n }\n\n x += stack.pop();\n newContour(x, y);\n break;\n case 23: // vstemhm\n parseStems();\n break;\n case 24: // rcurveline\n while (stack.length > 2) {\n c1x = x + stack.shift();\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + stack.shift();\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n x += stack.shift();\n y += stack.shift();\n p.lineTo(x, y);\n break;\n case 25: // rlinecurve\n while (stack.length > 6) {\n x += stack.shift();\n y += stack.shift();\n p.lineTo(x, y);\n }\n\n c1x = x + stack.shift();\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + stack.shift();\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n break;\n case 26: // vvcurveto\n if (stack.length % 2) {\n x += stack.shift();\n }\n\n while (stack.length > 0) {\n c1x = x;\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x;\n y = c2y + stack.shift();\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n case 27: // hhcurveto\n if (stack.length % 2) {\n y += stack.shift();\n }\n\n while (stack.length > 0) {\n c1x = x + stack.shift();\n c1y = y;\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y;\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n case 28: // shortint\n b1 = code[i];\n b2 = code[i + 1];\n stack.push(((b1 << 24) | (b2 << 16)) >> 16);\n i += 2;\n break;\n case 29: // callgsubr\n codeIndex = stack.pop() + font.gsubrsBias;\n subrCode = font.gsubrs[codeIndex];\n if (subrCode) {\n parse(subrCode);\n }\n\n break;\n case 30: // vhcurveto\n while (stack.length > 0) {\n c1x = x;\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + (stack.length === 1 ? stack.shift() : 0);\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n if (stack.length === 0) {\n break;\n }\n\n c1x = x + stack.shift();\n c1y = y;\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n y = c2y + stack.shift();\n x = c2x + (stack.length === 1 ? stack.shift() : 0);\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n case 31: // hvcurveto\n while (stack.length > 0) {\n c1x = x + stack.shift();\n c1y = y;\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n y = c2y + stack.shift();\n x = c2x + (stack.length === 1 ? stack.shift() : 0);\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n if (stack.length === 0) {\n break;\n }\n\n c1x = x;\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + (stack.length === 1 ? stack.shift() : 0);\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n default:\n if (v < 32) {\n console.log('Glyph ' + glyph.index + ': unknown operator ' + v);\n } else if (v < 247) {\n stack.push(v - 139);\n } else if (v < 251) {\n b1 = code[i];\n i += 1;\n stack.push((v - 247) * 256 + b1 + 108);\n } else if (v < 255) {\n b1 = code[i];\n i += 1;\n stack.push(-(v - 251) * 256 - b1 - 108);\n } else {\n b1 = code[i];\n b2 = code[i + 1];\n b3 = code[i + 2];\n b4 = code[i + 3];\n i += 4;\n stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536);\n }\n }\n }\n }\n\n parse(code);\n\n glyph.advanceWidth = width;\n return p;\n}\n\n// Subroutines are encoded using the negative half of the number space.\n// See type 2 chapter 4.7 \"Subroutine operators\".\nfunction calcCFFSubroutineBias(subrs) {\n var bias;\n if (subrs.length < 1240) {\n bias = 107;\n } else if (subrs.length < 33900) {\n bias = 1131;\n } else {\n bias = 32768;\n }\n\n return bias;\n}\n\n// Parse the `CFF` table, which contains the glyph outlines in PostScript format.\nfunction parseCFFTable(data, start, font) {\n font.tables.cff = {};\n var header = parseCFFHeader(data, start);\n var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);\n var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);\n var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);\n var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);\n font.gsubrs = globalSubrIndex.objects;\n font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);\n\n var topDictData = new DataView(new Uint8Array(topDictIndex.objects[0]).buffer);\n var topDict = parseCFFTopDict(topDictData, stringIndex.objects);\n font.tables.cff.topDict = topDict;\n\n var privateDictOffset = start + topDict['private'][1];\n var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict['private'][0], stringIndex.objects);\n font.defaultWidthX = privateDict.defaultWidthX;\n font.nominalWidthX = privateDict.nominalWidthX;\n\n if (privateDict.subrs !== 0) {\n var subrOffset = privateDictOffset + privateDict.subrs;\n var subrIndex = parseCFFIndex(data, subrOffset);\n font.subrs = subrIndex.objects;\n font.subrsBias = calcCFFSubroutineBias(font.subrs);\n } else {\n font.subrs = [];\n font.subrsBias = 0;\n }\n\n // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.\n var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);\n font.nGlyphs = charStringsIndex.objects.length;\n\n var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);\n if (topDict.encoding === 0) { // Standard encoding\n font.cffEncoding = new encoding.CffEncoding(encoding.cffStandardEncoding, charset);\n } else if (topDict.encoding === 1) { // Expert encoding\n font.cffEncoding = new encoding.CffEncoding(encoding.cffExpertEncoding, charset);\n } else {\n font.cffEncoding = parseCFFEncoding(data, start + topDict.encoding, charset);\n }\n\n // Prefer the CMAP encoding to the CFF encoding.\n font.encoding = font.encoding || font.cffEncoding;\n\n font.glyphs = new glyphset.GlyphSet(font);\n for (var i = 0; i < font.nGlyphs; i += 1) {\n var charString = charStringsIndex.objects[i];\n font.glyphs.push(i, glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString));\n }\n}\n\n// Convert a string to a String ID (SID).\n// The list of strings is modified in place.\nfunction encodeString(s, strings) {\n var sid;\n\n // Is the string in the CFF standard strings?\n var i = encoding.cffStandardStrings.indexOf(s);\n if (i >= 0) {\n sid = i;\n }\n\n // Is the string already in the string index?\n i = strings.indexOf(s);\n if (i >= 0) {\n sid = i + encoding.cffStandardStrings.length;\n } else {\n sid = encoding.cffStandardStrings.length + strings.length;\n strings.push(s);\n }\n\n return sid;\n}\n\nfunction makeHeader() {\n return new table.Record('Header', [\n {name: 'major', type: 'Card8', value: 1},\n {name: 'minor', type: 'Card8', value: 0},\n {name: 'hdrSize', type: 'Card8', value: 4},\n {name: 'major', type: 'Card8', value: 1}\n ]);\n}\n\nfunction makeNameIndex(fontNames) {\n var t = new table.Record('Name INDEX', [\n {name: 'names', type: 'INDEX', value: []}\n ]);\n t.names = [];\n for (var i = 0; i < fontNames.length; i += 1) {\n t.names.push({name: 'name_' + i, type: 'NAME', value: fontNames[i]});\n }\n\n return t;\n}\n\n// Given a dictionary's metadata, create a DICT structure.\nfunction makeDict(meta, attrs, strings) {\n var m = {};\n for (var i = 0; i < meta.length; i += 1) {\n var entry = meta[i];\n var value = attrs[entry.name];\n if (value !== undefined && !equals(value, entry.value)) {\n if (entry.type === 'SID') {\n value = encodeString(value, strings);\n }\n\n m[entry.op] = {name: entry.name, type: entry.type, value: value};\n }\n }\n\n return m;\n}\n\n// The Top DICT houses the global font attributes.\nfunction makeTopDict(attrs, strings) {\n var t = new table.Record('Top DICT', [\n {name: 'dict', type: 'DICT', value: {}}\n ]);\n t.dict = makeDict(TOP_DICT_META, attrs, strings);\n return t;\n}\n\nfunction makeTopDictIndex(topDict) {\n var t = new table.Record('Top DICT INDEX', [\n {name: 'topDicts', type: 'INDEX', value: []}\n ]);\n t.topDicts = [{name: 'topDict_0', type: 'TABLE', value: topDict}];\n return t;\n}\n\nfunction makeStringIndex(strings) {\n var t = new table.Record('String INDEX', [\n {name: 'strings', type: 'INDEX', value: []}\n ]);\n t.strings = [];\n for (var i = 0; i < strings.length; i += 1) {\n t.strings.push({name: 'string_' + i, type: 'STRING', value: strings[i]});\n }\n\n return t;\n}\n\nfunction makeGlobalSubrIndex() {\n // Currently we don't use subroutines.\n return new table.Record('Global Subr INDEX', [\n {name: 'subrs', type: 'INDEX', value: []}\n ]);\n}\n\nfunction makeCharsets(glyphNames, strings) {\n var t = new table.Record('Charsets', [\n {name: 'format', type: 'Card8', value: 0}\n ]);\n for (var i = 0; i < glyphNames.length; i += 1) {\n var glyphName = glyphNames[i];\n var glyphSID = encodeString(glyphName, strings);\n t.fields.push({name: 'glyph_' + i, type: 'SID', value: glyphSID});\n }\n\n return t;\n}\n\nfunction glyphToOps(glyph) {\n var ops = [];\n var path = glyph.path;\n ops.push({name: 'width', type: 'NUMBER', value: glyph.advanceWidth});\n var x = 0;\n var y = 0;\n for (var i = 0; i < path.commands.length; i += 1) {\n var dx;\n var dy;\n var cmd = path.commands[i];\n if (cmd.type === 'Q') {\n // CFF only supports bézier curves, so convert the quad to a bézier.\n var _13 = 1 / 3;\n var _23 = 2 / 3;\n\n // We're going to create a new command so we don't change the original path.\n cmd = {\n type: 'C',\n x: cmd.x,\n y: cmd.y,\n x1: _13 * x + _23 * cmd.x1,\n y1: _13 * y + _23 * cmd.y1,\n x2: _13 * cmd.x + _23 * cmd.x1,\n y2: _13 * cmd.y + _23 * cmd.y1\n };\n }\n\n if (cmd.type === 'M') {\n dx = Math.round(cmd.x - x);\n dy = Math.round(cmd.y - y);\n ops.push({name: 'dx', type: 'NUMBER', value: dx});\n ops.push({name: 'dy', type: 'NUMBER', value: dy});\n ops.push({name: 'rmoveto', type: 'OP', value: 21});\n x = Math.round(cmd.x);\n y = Math.round(cmd.y);\n } else if (cmd.type === 'L') {\n dx = Math.round(cmd.x - x);\n dy = Math.round(cmd.y - y);\n ops.push({name: 'dx', type: 'NUMBER', value: dx});\n ops.push({name: 'dy', type: 'NUMBER', value: dy});\n ops.push({name: 'rlineto', type: 'OP', value: 5});\n x = Math.round(cmd.x);\n y = Math.round(cmd.y);\n } else if (cmd.type === 'C') {\n var dx1 = Math.round(cmd.x1 - x);\n var dy1 = Math.round(cmd.y1 - y);\n var dx2 = Math.round(cmd.x2 - cmd.x1);\n var dy2 = Math.round(cmd.y2 - cmd.y1);\n dx = Math.round(cmd.x - cmd.x2);\n dy = Math.round(cmd.y - cmd.y2);\n ops.push({name: 'dx1', type: 'NUMBER', value: dx1});\n ops.push({name: 'dy1', type: 'NUMBER', value: dy1});\n ops.push({name: 'dx2', type: 'NUMBER', value: dx2});\n ops.push({name: 'dy2', type: 'NUMBER', value: dy2});\n ops.push({name: 'dx', type: 'NUMBER', value: dx});\n ops.push({name: 'dy', type: 'NUMBER', value: dy});\n ops.push({name: 'rrcurveto', type: 'OP', value: 8});\n x = Math.round(cmd.x);\n y = Math.round(cmd.y);\n }\n\n // Contours are closed automatically.\n\n }\n\n ops.push({name: 'endchar', type: 'OP', value: 14});\n return ops;\n}\n\nfunction makeCharStringsIndex(glyphs) {\n var t = new table.Record('CharStrings INDEX', [\n {name: 'charStrings', type: 'INDEX', value: []}\n ]);\n\n for (var i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs.get(i);\n var ops = glyphToOps(glyph);\n t.charStrings.push({name: glyph.name, type: 'CHARSTRING', value: ops});\n }\n\n return t;\n}\n\nfunction makePrivateDict(attrs, strings) {\n var t = new table.Record('Private DICT', [\n {name: 'dict', type: 'DICT', value: {}}\n ]);\n t.dict = makeDict(PRIVATE_DICT_META, attrs, strings);\n return t;\n}\n\nfunction makeCFFTable(glyphs, options) {\n var t = new table.Table('CFF ', [\n {name: 'header', type: 'RECORD'},\n {name: 'nameIndex', type: 'RECORD'},\n {name: 'topDictIndex', type: 'RECORD'},\n {name: 'stringIndex', type: 'RECORD'},\n {name: 'globalSubrIndex', type: 'RECORD'},\n {name: 'charsets', type: 'RECORD'},\n {name: 'charStringsIndex', type: 'RECORD'},\n {name: 'privateDict', type: 'RECORD'}\n ]);\n\n var fontScale = 1 / options.unitsPerEm;\n // We use non-zero values for the offsets so that the DICT encodes them.\n // This is important because the size of the Top DICT plays a role in offset calculation,\n // and the size shouldn't change after we've written correct offsets.\n var attrs = {\n version: options.version,\n fullName: options.fullName,\n familyName: options.familyName,\n weight: options.weightName,\n fontBBox: options.fontBBox || [0, 0, 0, 0],\n fontMatrix: [fontScale, 0, 0, fontScale, 0, 0],\n charset: 999,\n encoding: 0,\n charStrings: 999,\n private: [0, 999]\n };\n\n var privateAttrs = {};\n\n var glyphNames = [];\n var glyph;\n\n // Skip first glyph (.notdef)\n for (var i = 1; i < glyphs.length; i += 1) {\n glyph = glyphs.get(i);\n glyphNames.push(glyph.name);\n }\n\n var strings = [];\n\n t.header = makeHeader();\n t.nameIndex = makeNameIndex([options.postScriptName]);\n var topDict = makeTopDict(attrs, strings);\n t.topDictIndex = makeTopDictIndex(topDict);\n t.globalSubrIndex = makeGlobalSubrIndex();\n t.charsets = makeCharsets(glyphNames, strings);\n t.charStringsIndex = makeCharStringsIndex(glyphs);\n t.privateDict = makePrivateDict(privateAttrs, strings);\n\n // Needs to come at the end, to encode all custom strings used in the font.\n t.stringIndex = makeStringIndex(strings);\n\n var startOffset = t.header.sizeOf() +\n t.nameIndex.sizeOf() +\n t.topDictIndex.sizeOf() +\n t.stringIndex.sizeOf() +\n t.globalSubrIndex.sizeOf();\n attrs.charset = startOffset;\n\n // We use the CFF standard encoding; proper encoding will be handled in cmap.\n attrs.encoding = 0;\n attrs.charStrings = attrs.charset + t.charsets.sizeOf();\n attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf();\n\n // Recreate the Top DICT INDEX with the correct offsets.\n topDict = makeTopDict(attrs, strings);\n t.topDictIndex = makeTopDictIndex(topDict);\n\n return t;\n}\n\nexports.parse = parseCFFTable;\nexports.make = makeCFFTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/cff.js\n ** module id = 13\n ** module chunks = 0\n **/","// The GlyphSet object\n\n'use strict';\n\nvar _glyph = require('./glyph');\n\n// A GlyphSet represents all glyphs available in the font, but modelled using\n// a deferred glyph loader, for retrieving glyphs only once they are absolutely\n// necessary, to keep the memory footprint down.\nfunction GlyphSet(font, glyphs) {\n this.font = font;\n this.glyphs = {};\n if (Array.isArray(glyphs)) {\n for (var i = 0; i < glyphs.length; i++) {\n this.glyphs[i] = glyphs[i];\n }\n }\n\n this.length = (glyphs && glyphs.length) || 0;\n}\n\nGlyphSet.prototype.get = function(index) {\n if (typeof this.glyphs[index] === 'function') {\n this.glyphs[index] = this.glyphs[index]();\n }\n\n return this.glyphs[index];\n};\n\nGlyphSet.prototype.push = function(index, loader) {\n this.glyphs[index] = loader;\n this.length++;\n};\n\nfunction glyphLoader(font, index) {\n return new _glyph.Glyph({index: index, font: font});\n}\n\n/**\n * Generate a stub glyph that can be filled with all metadata *except*\n * the \"points\" and \"path\" properties, which must be loaded only once\n * the glyph's path is actually requested for text shaping.\n */\n\nfunction ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {\n return function() {\n var glyph = new _glyph.Glyph({index: index, font: font});\n\n glyph.path = function() {\n parseGlyph(glyph, data, position);\n var path = buildPath(font.glyphs, glyph);\n path.unitsPerEm = font.unitsPerEm;\n return path;\n };\n\n return glyph;\n };\n}\n\nfunction cffGlyphLoader(font, index, parseCFFCharstring, charstring) {\n return function() {\n var glyph = new _glyph.Glyph({index: index, font: font});\n\n glyph.path = function() {\n var path = parseCFFCharstring(font, glyph, charstring);\n path.unitsPerEm = font.unitsPerEm;\n return path;\n };\n\n return glyph;\n };\n}\n\nexports.GlyphSet = GlyphSet;\nexports.glyphLoader = glyphLoader;\nexports.ttfGlyphLoader = ttfGlyphLoader;\nexports.cffGlyphLoader = cffGlyphLoader;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/glyphset.js\n ** module id = 14\n ** module chunks = 0\n **/","// The Glyph object\n\n'use strict';\n\nvar check = require('./check');\nvar draw = require('./draw');\nvar path = require('./path');\n\nfunction getPathDefinition(glyph, path) {\n var _path = path || { commands: [] };\n return {\n configurable: true,\n\n get: function() {\n if (typeof _path === 'function') {\n _path = _path();\n }\n\n return _path;\n },\n\n set: function(p) {\n _path = p;\n }\n };\n}\n\n// A Glyph is an individual mark that often corresponds to a character.\n// Some glyphs, such as ligatures, are a combination of many characters.\n// Glyphs are the basic building blocks of a font.\n//\n// The `Glyph` class contains utility methods for drawing the path and its points.\nfunction Glyph(options) {\n // By putting all the code on a prototype function (which is only declared once)\n // we reduce the memory requirements for larger fonts by some 2%\n this.bindConstructorValues(options);\n}\n\nGlyph.prototype.bindConstructorValues = function(options) {\n this.index = options.index || 0;\n\n // These three values cannnot be deferred for memory optimization:\n this.name = options.name || null;\n this.unicode = options.unicode || undefined;\n this.unicodes = options.unicodes || options.unicode !== undefined ? [options.unicode] : [];\n\n // But by binding these values only when necessary, we reduce can\n // the memory requirements by almost 3% for larger fonts.\n if (options.xMin) {\n this.xMin = options.xMin;\n }\n\n if (options.yMin) {\n this.yMin = options.yMin;\n }\n\n if (options.xMax) {\n this.xMax = options.xMax;\n }\n\n if (options.yMax) {\n this.yMax = options.yMax;\n }\n\n if (options.advanceWidth) {\n this.advanceWidth = options.advanceWidth;\n }\n\n // The path for a glyph is the most memory intensive, and is bound as a value\n // with a getter/setter to ensure we actually do path parsing only once the\n // path is actually needed by anything.\n Object.defineProperty(this, 'path', getPathDefinition(this, options.path));\n};\n\nGlyph.prototype.addUnicode = function(unicode) {\n if (this.unicodes.length === 0) {\n this.unicode = unicode;\n }\n\n this.unicodes.push(unicode);\n};\n\n// Convert the glyph to a Path we can draw on a drawing context.\n//\n// x - Horizontal position of the glyph. (default: 0)\n// y - Vertical position of the *baseline* of the glyph. (default: 0)\n// fontSize - Font size, in pixels (default: 72).\n// options - xScale and yScale to strech the glyph.\nGlyph.prototype.getPath = function(x, y, fontSize, options) {\n x = x !== undefined ? x : 0;\n y = y !== undefined ? y : 0;\n options = options !== undefined ? options : {xScale: 1.0, yScale: 1.0};\n fontSize = fontSize !== undefined ? fontSize : 72;\n var scale = 1 / this.path.unitsPerEm * fontSize;\n var xScale = options.xScale * scale;\n var yScale = options.yScale * scale;\n\n var p = new path.Path();\n var commands = this.path.commands;\n for (var i = 0; i < commands.length; i += 1) {\n var cmd = commands[i];\n if (cmd.type === 'M') {\n p.moveTo(x + (cmd.x * xScale), y + (-cmd.y * yScale));\n } else if (cmd.type === 'L') {\n p.lineTo(x + (cmd.x * xScale), y + (-cmd.y * yScale));\n } else if (cmd.type === 'Q') {\n p.quadraticCurveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale),\n x + (cmd.x * xScale), y + (-cmd.y * yScale));\n } else if (cmd.type === 'C') {\n p.curveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale),\n x + (cmd.x2 * xScale), y + (-cmd.y2 * yScale),\n x + (cmd.x * xScale), y + (-cmd.y * yScale));\n } else if (cmd.type === 'Z') {\n p.closePath();\n }\n }\n\n return p;\n};\n\n// Split the glyph into contours.\n// This function is here for backwards compatibility, and to\n// provide raw access to the TrueType glyph outlines.\nGlyph.prototype.getContours = function() {\n if (this.points === undefined) {\n return [];\n }\n\n var contours = [];\n var currentContour = [];\n for (var i = 0; i < this.points.length; i += 1) {\n var pt = this.points[i];\n currentContour.push(pt);\n if (pt.lastPointOfContour) {\n contours.push(currentContour);\n currentContour = [];\n }\n }\n\n check.argument(currentContour.length === 0, 'There are still points left in the current contour.');\n return contours;\n};\n\n// Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph.\nGlyph.prototype.getMetrics = function() {\n var commands = this.path.commands;\n var xCoords = [];\n var yCoords = [];\n for (var i = 0; i < commands.length; i += 1) {\n var cmd = commands[i];\n if (cmd.type !== 'Z') {\n xCoords.push(cmd.x);\n yCoords.push(cmd.y);\n }\n\n if (cmd.type === 'Q' || cmd.type === 'C') {\n xCoords.push(cmd.x1);\n yCoords.push(cmd.y1);\n }\n\n if (cmd.type === 'C') {\n xCoords.push(cmd.x2);\n yCoords.push(cmd.y2);\n }\n }\n\n var metrics = {\n xMin: Math.min.apply(null, xCoords),\n yMin: Math.min.apply(null, yCoords),\n xMax: Math.max.apply(null, xCoords),\n yMax: Math.max.apply(null, yCoords),\n leftSideBearing: this.leftSideBearing\n };\n\n if (!isFinite(metrics.xMin)) {\n metrics.xMin = 0;\n }\n\n if (!isFinite(metrics.xMax)) {\n metrics.xMax = this.advanceWidth;\n }\n\n if (!isFinite(metrics.yMin)) {\n metrics.yMin = 0;\n }\n\n if (!isFinite(metrics.yMax)) {\n metrics.yMax = 0;\n }\n\n metrics.rightSideBearing = this.advanceWidth - metrics.leftSideBearing - (metrics.xMax - metrics.xMin);\n return metrics;\n};\n\n// Draw the glyph on the given context.\n//\n// ctx - The drawing context.\n// x - Horizontal position of the glyph. (default: 0)\n// y - Vertical position of the *baseline* of the glyph. (default: 0)\n// fontSize - Font size, in pixels (default: 72).\n// options - xScale, yScale to strech the glyph\nGlyph.prototype.draw = function(ctx, x, y, fontSize, options) {\n this.getPath(x, y, fontSize, options).draw(ctx);\n};\n\n// Draw the points of the glyph.\n// On-curve points will be drawn in blue, off-curve points will be drawn in red.\n//\n// ctx - The drawing context.\n// x - Horizontal position of the glyph. (default: 0)\n// y - Vertical position of the *baseline* of the glyph. (default: 0)\n// fontSize - Font size, in pixels (default: 72).\nGlyph.prototype.drawPoints = function(ctx, x, y, fontSize) {\n\n function drawCircles(l, x, y, scale) {\n var PI_SQ = Math.PI * 2;\n ctx.beginPath();\n for (var j = 0; j < l.length; j += 1) {\n ctx.moveTo(x + (l[j].x * scale), y + (l[j].y * scale));\n ctx.arc(x + (l[j].x * scale), y + (l[j].y * scale), 2, 0, PI_SQ, false);\n }\n\n ctx.closePath();\n ctx.fill();\n }\n\n x = x !== undefined ? x : 0;\n y = y !== undefined ? y : 0;\n fontSize = fontSize !== undefined ? fontSize : 24;\n var scale = 1 / this.path.unitsPerEm * fontSize;\n\n var blueCircles = [];\n var redCircles = [];\n var path = this.path;\n for (var i = 0; i < path.commands.length; i += 1) {\n var cmd = path.commands[i];\n if (cmd.x !== undefined) {\n blueCircles.push({x: cmd.x, y: -cmd.y});\n }\n\n if (cmd.x1 !== undefined) {\n redCircles.push({x: cmd.x1, y: -cmd.y1});\n }\n\n if (cmd.x2 !== undefined) {\n redCircles.push({x: cmd.x2, y: -cmd.y2});\n }\n }\n\n ctx.fillStyle = 'blue';\n drawCircles(blueCircles, x, y, scale);\n ctx.fillStyle = 'red';\n drawCircles(redCircles, x, y, scale);\n};\n\n// Draw lines indicating important font measurements.\n// Black lines indicate the origin of the coordinate system (point 0,0).\n// Blue lines indicate the glyph bounding box.\n// Green line indicates the advance width of the glyph.\n//\n// ctx - The drawing context.\n// x - Horizontal position of the glyph. (default: 0)\n// y - Vertical position of the *baseline* of the glyph. (default: 0)\n// fontSize - Font size, in pixels (default: 72).\nGlyph.prototype.drawMetrics = function(ctx, x, y, fontSize) {\n var scale;\n x = x !== undefined ? x : 0;\n y = y !== undefined ? y : 0;\n fontSize = fontSize !== undefined ? fontSize : 24;\n scale = 1 / this.path.unitsPerEm * fontSize;\n ctx.lineWidth = 1;\n\n // Draw the origin\n ctx.strokeStyle = 'black';\n draw.line(ctx, x, -10000, x, 10000);\n draw.line(ctx, -10000, y, 10000, y);\n\n // This code is here due to memory optimization: by not using\n // defaults in the constructor, we save a notable amount of memory.\n var xMin = this.xMin || 0;\n var yMin = this.yMin || 0;\n var xMax = this.xMax || 0;\n var yMax = this.yMax || 0;\n var advanceWidth = this.advanceWidth || 0;\n\n // Draw the glyph box\n ctx.strokeStyle = 'blue';\n draw.line(ctx, x + (xMin * scale), -10000, x + (xMin * scale), 10000);\n draw.line(ctx, x + (xMax * scale), -10000, x + (xMax * scale), 10000);\n draw.line(ctx, -10000, y + (-yMin * scale), 10000, y + (-yMin * scale));\n draw.line(ctx, -10000, y + (-yMax * scale), 10000, y + (-yMax * scale));\n\n // Draw the advance width\n ctx.strokeStyle = 'green';\n draw.line(ctx, x + (advanceWidth * scale), -10000, x + (advanceWidth * scale), 10000);\n};\n\nexports.Glyph = Glyph;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/glyph.js\n ** module id = 15\n ** module chunks = 0\n **/","// Drawing utility functions.\n\n'use strict';\n\n// Draw a line on the given context from point `x1,y1` to point `x2,y2`.\nfunction line(ctx, x1, y1, x2, y2) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n}\n\nexports.line = line;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/draw.js\n ** module id = 16\n ** module chunks = 0\n **/","// The `head` table contains global information about the font.\n// https://www.microsoft.com/typography/OTSPEC/head.htm\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the header `head` table\nfunction parseHeadTable(data, start) {\n var head = {};\n var p = new parse.Parser(data, start);\n head.version = p.parseVersion();\n head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;\n head.checkSumAdjustment = p.parseULong();\n head.magicNumber = p.parseULong();\n check.argument(head.magicNumber === 0x5F0F3CF5, 'Font header has wrong magic number.');\n head.flags = p.parseUShort();\n head.unitsPerEm = p.parseUShort();\n head.created = p.parseLongDateTime();\n head.modified = p.parseLongDateTime();\n head.xMin = p.parseShort();\n head.yMin = p.parseShort();\n head.xMax = p.parseShort();\n head.yMax = p.parseShort();\n head.macStyle = p.parseUShort();\n head.lowestRecPPEM = p.parseUShort();\n head.fontDirectionHint = p.parseShort();\n head.indexToLocFormat = p.parseShort();\n head.glyphDataFormat = p.parseShort();\n return head;\n}\n\nfunction makeHeadTable(options) {\n // Apple Mac timestamp epoch is 01/01/1904 not 01/01/1970\n var timestamp = Math.round(new Date().getTime() / 1000) + 2082844800;\n var createdTimestamp = timestamp;\n\n if (options.createdTimestamp) {\n createdTimestamp = options.createdTimestamp + 2082844800;\n }\n\n return new table.Table('head', [\n {name: 'version', type: 'FIXED', value: 0x00010000},\n {name: 'fontRevision', type: 'FIXED', value: 0x00010000},\n {name: 'checkSumAdjustment', type: 'ULONG', value: 0},\n {name: 'magicNumber', type: 'ULONG', value: 0x5F0F3CF5},\n {name: 'flags', type: 'USHORT', value: 0},\n {name: 'unitsPerEm', type: 'USHORT', value: 1000},\n {name: 'created', type: 'LONGDATETIME', value: createdTimestamp},\n {name: 'modified', type: 'LONGDATETIME', value: timestamp},\n {name: 'xMin', type: 'SHORT', value: 0},\n {name: 'yMin', type: 'SHORT', value: 0},\n {name: 'xMax', type: 'SHORT', value: 0},\n {name: 'yMax', type: 'SHORT', value: 0},\n {name: 'macStyle', type: 'USHORT', value: 0},\n {name: 'lowestRecPPEM', type: 'USHORT', value: 0},\n {name: 'fontDirectionHint', type: 'SHORT', value: 2},\n {name: 'indexToLocFormat', type: 'SHORT', value: 0},\n {name: 'glyphDataFormat', type: 'SHORT', value: 0}\n ], options);\n}\n\nexports.parse = parseHeadTable;\nexports.make = makeHeadTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/head.js\n ** module id = 17\n ** module chunks = 0\n **/","// The `hhea` table contains information for horizontal layout.\n// https://www.microsoft.com/typography/OTSPEC/hhea.htm\n\n'use strict';\n\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the horizontal header `hhea` table\nfunction parseHheaTable(data, start) {\n var hhea = {};\n var p = new parse.Parser(data, start);\n hhea.version = p.parseVersion();\n hhea.ascender = p.parseShort();\n hhea.descender = p.parseShort();\n hhea.lineGap = p.parseShort();\n hhea.advanceWidthMax = p.parseUShort();\n hhea.minLeftSideBearing = p.parseShort();\n hhea.minRightSideBearing = p.parseShort();\n hhea.xMaxExtent = p.parseShort();\n hhea.caretSlopeRise = p.parseShort();\n hhea.caretSlopeRun = p.parseShort();\n hhea.caretOffset = p.parseShort();\n p.relativeOffset += 8;\n hhea.metricDataFormat = p.parseShort();\n hhea.numberOfHMetrics = p.parseUShort();\n return hhea;\n}\n\nfunction makeHheaTable(options) {\n return new table.Table('hhea', [\n {name: 'version', type: 'FIXED', value: 0x00010000},\n {name: 'ascender', type: 'FWORD', value: 0},\n {name: 'descender', type: 'FWORD', value: 0},\n {name: 'lineGap', type: 'FWORD', value: 0},\n {name: 'advanceWidthMax', type: 'UFWORD', value: 0},\n {name: 'minLeftSideBearing', type: 'FWORD', value: 0},\n {name: 'minRightSideBearing', type: 'FWORD', value: 0},\n {name: 'xMaxExtent', type: 'FWORD', value: 0},\n {name: 'caretSlopeRise', type: 'SHORT', value: 1},\n {name: 'caretSlopeRun', type: 'SHORT', value: 0},\n {name: 'caretOffset', type: 'SHORT', value: 0},\n {name: 'reserved1', type: 'SHORT', value: 0},\n {name: 'reserved2', type: 'SHORT', value: 0},\n {name: 'reserved3', type: 'SHORT', value: 0},\n {name: 'reserved4', type: 'SHORT', value: 0},\n {name: 'metricDataFormat', type: 'SHORT', value: 0},\n {name: 'numberOfHMetrics', type: 'USHORT', value: 0}\n ], options);\n}\n\nexports.parse = parseHheaTable;\nexports.make = makeHheaTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/hhea.js\n ** module id = 18\n ** module chunks = 0\n **/","// The `hmtx` table contains the horizontal metrics for all glyphs.\n// https://www.microsoft.com/typography/OTSPEC/hmtx.htm\n\n'use strict';\n\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the `hmtx` table, which contains the horizontal metrics for all glyphs.\n// This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph.\nfunction parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {\n var advanceWidth;\n var leftSideBearing;\n var p = new parse.Parser(data, start);\n for (var i = 0; i < numGlyphs; i += 1) {\n // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.\n if (i < numMetrics) {\n advanceWidth = p.parseUShort();\n leftSideBearing = p.parseShort();\n }\n\n var glyph = glyphs.get(i);\n glyph.advanceWidth = advanceWidth;\n glyph.leftSideBearing = leftSideBearing;\n }\n}\n\nfunction makeHmtxTable(glyphs) {\n var t = new table.Table('hmtx', []);\n for (var i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs.get(i);\n var advanceWidth = glyph.advanceWidth || 0;\n var leftSideBearing = glyph.leftSideBearing || 0;\n t.fields.push({name: 'advanceWidth_' + i, type: 'USHORT', value: advanceWidth});\n t.fields.push({name: 'leftSideBearing_' + i, type: 'SHORT', value: leftSideBearing});\n }\n\n return t;\n}\n\nexports.parse = parseHmtxTable;\nexports.make = makeHmtxTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/hmtx.js\n ** module id = 19\n ** module chunks = 0\n **/","// The `ltag` table stores IETF BCP-47 language tags. It allows supporting\n// languages for which TrueType does not assign a numeric code.\n// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html\n// http://www.w3.org/International/articles/language-tags/\n// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\nvar table = require('../table');\n\nfunction makeLtagTable(tags) {\n var result = new table.Table('ltag', [\n {name: 'version', type: 'ULONG', value: 1},\n {name: 'flags', type: 'ULONG', value: 0},\n {name: 'numTags', type: 'ULONG', value: tags.length}\n ]);\n\n var stringPool = '';\n var stringPoolOffset = 12 + tags.length * 4;\n for (var i = 0; i < tags.length; ++i) {\n var pos = stringPool.indexOf(tags[i]);\n if (pos < 0) {\n pos = stringPool.length;\n stringPool += tags[i];\n }\n\n result.fields.push({name: 'offset ' + i, type: 'USHORT', value: stringPoolOffset + pos});\n result.fields.push({name: 'length ' + i, type: 'USHORT', value: tags[i].length});\n }\n\n result.fields.push({name: 'stringPool', type: 'CHARARRAY', value: stringPool});\n return result;\n}\n\nfunction parseLtagTable(data, start) {\n var p = new parse.Parser(data, start);\n var tableVersion = p.parseULong();\n check.argument(tableVersion === 1, 'Unsupported ltag table version.');\n // The 'ltag' specification does not define any flags; skip the field.\n p.skip('uLong', 1);\n var numTags = p.parseULong();\n\n var tags = [];\n for (var i = 0; i < numTags; i++) {\n var tag = '';\n var offset = start + p.parseUShort();\n var length = p.parseUShort();\n for (var j = offset; j < offset + length; ++j) {\n tag += String.fromCharCode(data.getInt8(j));\n }\n\n tags.push(tag);\n }\n\n return tags;\n}\n\nexports.make = makeLtagTable;\nexports.parse = parseLtagTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/ltag.js\n ** module id = 20\n ** module chunks = 0\n **/","// The `maxp` table establishes the memory requirements for the font.\n// We need it just to get the number of glyphs in the font.\n// https://www.microsoft.com/typography/OTSPEC/maxp.htm\n\n'use strict';\n\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the maximum profile `maxp` table.\nfunction parseMaxpTable(data, start) {\n var maxp = {};\n var p = new parse.Parser(data, start);\n maxp.version = p.parseVersion();\n maxp.numGlyphs = p.parseUShort();\n if (maxp.version === 1.0) {\n maxp.maxPoints = p.parseUShort();\n maxp.maxContours = p.parseUShort();\n maxp.maxCompositePoints = p.parseUShort();\n maxp.maxCompositeContours = p.parseUShort();\n maxp.maxZones = p.parseUShort();\n maxp.maxTwilightPoints = p.parseUShort();\n maxp.maxStorage = p.parseUShort();\n maxp.maxFunctionDefs = p.parseUShort();\n maxp.maxInstructionDefs = p.parseUShort();\n maxp.maxStackElements = p.parseUShort();\n maxp.maxSizeOfInstructions = p.parseUShort();\n maxp.maxComponentElements = p.parseUShort();\n maxp.maxComponentDepth = p.parseUShort();\n }\n\n return maxp;\n}\n\nfunction makeMaxpTable(numGlyphs) {\n return new table.Table('maxp', [\n {name: 'version', type: 'FIXED', value: 0x00005000},\n {name: 'numGlyphs', type: 'USHORT', value: numGlyphs}\n ]);\n}\n\nexports.parse = parseMaxpTable;\nexports.make = makeMaxpTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/maxp.js\n ** module id = 21\n ** module chunks = 0\n **/","// The `name` naming table.\n// https://www.microsoft.com/typography/OTSPEC/name.htm\n\n'use strict';\n\nvar types = require('../types');\nvar decode = types.decode;\nvar encode = types.encode;\nvar parse = require('../parse');\nvar table = require('../table');\n\n// NameIDs for the name table.\nvar nameTableNames = [\n 'copyright', // 0\n 'fontFamily', // 1\n 'fontSubfamily', // 2\n 'uniqueID', // 3\n 'fullName', // 4\n 'version', // 5\n 'postScriptName', // 6\n 'trademark', // 7\n 'manufacturer', // 8\n 'designer', // 9\n 'description', // 10\n 'manufacturerURL', // 11\n 'designerURL', // 12\n 'license', // 13\n 'licenseURL', // 14\n 'reserved', // 15\n 'preferredFamily', // 16\n 'preferredSubfamily', // 17\n 'compatibleFullName', // 18\n 'sampleText', // 19\n 'postScriptFindFontName', // 20\n 'wwsFamily', // 21\n 'wwsSubfamily' // 22\n];\n\nvar macLanguages = {\n 0: 'en',\n 1: 'fr',\n 2: 'de',\n 3: 'it',\n 4: 'nl',\n 5: 'sv',\n 6: 'es',\n 7: 'da',\n 8: 'pt',\n 9: 'no',\n 10: 'he',\n 11: 'ja',\n 12: 'ar',\n 13: 'fi',\n 14: 'el',\n 15: 'is',\n 16: 'mt',\n 17: 'tr',\n 18: 'hr',\n 19: 'zh-Hant',\n 20: 'ur',\n 21: 'hi',\n 22: 'th',\n 23: 'ko',\n 24: 'lt',\n 25: 'pl',\n 26: 'hu',\n 27: 'es',\n 28: 'lv',\n 29: 'se',\n 30: 'fo',\n 31: 'fa',\n 32: 'ru',\n 33: 'zh',\n 34: 'nl-BE',\n 35: 'ga',\n 36: 'sq',\n 37: 'ro',\n 38: 'cz',\n 39: 'sk',\n 40: 'si',\n 41: 'yi',\n 42: 'sr',\n 43: 'mk',\n 44: 'bg',\n 45: 'uk',\n 46: 'be',\n 47: 'uz',\n 48: 'kk',\n 49: 'az-Cyrl',\n 50: 'az-Arab',\n 51: 'hy',\n 52: 'ka',\n 53: 'mo',\n 54: 'ky',\n 55: 'tg',\n 56: 'tk',\n 57: 'mn-CN',\n 58: 'mn',\n 59: 'ps',\n 60: 'ks',\n 61: 'ku',\n 62: 'sd',\n 63: 'bo',\n 64: 'ne',\n 65: 'sa',\n 66: 'mr',\n 67: 'bn',\n 68: 'as',\n 69: 'gu',\n 70: 'pa',\n 71: 'or',\n 72: 'ml',\n 73: 'kn',\n 74: 'ta',\n 75: 'te',\n 76: 'si',\n 77: 'my',\n 78: 'km',\n 79: 'lo',\n 80: 'vi',\n 81: 'id',\n 82: 'tl',\n 83: 'ms',\n 84: 'ms-Arab',\n 85: 'am',\n 86: 'ti',\n 87: 'om',\n 88: 'so',\n 89: 'sw',\n 90: 'rw',\n 91: 'rn',\n 92: 'ny',\n 93: 'mg',\n 94: 'eo',\n 128: 'cy',\n 129: 'eu',\n 130: 'ca',\n 131: 'la',\n 132: 'qu',\n 133: 'gn',\n 134: 'ay',\n 135: 'tt',\n 136: 'ug',\n 137: 'dz',\n 138: 'jv',\n 139: 'su',\n 140: 'gl',\n 141: 'af',\n 142: 'br',\n 143: 'iu',\n 144: 'gd',\n 145: 'gv',\n 146: 'ga',\n 147: 'to',\n 148: 'el-polyton',\n 149: 'kl',\n 150: 'az',\n 151: 'nn'\n};\n\n// MacOS language ID → MacOS script ID\n//\n// Note that the script ID is not sufficient to determine what encoding\n// to use in TrueType files. For some languages, MacOS used a modification\n// of a mainstream script. For example, an Icelandic name would be stored\n// with smRoman in the TrueType naming table, but the actual encoding\n// is a special Icelandic version of the normal Macintosh Roman encoding.\n// As another example, Inuktitut uses an 8-bit encoding for Canadian Aboriginal\n// Syllables but MacOS had run out of available script codes, so this was\n// done as a (pretty radical) \"modification\" of Ethiopic.\n//\n// http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt\nvar macLanguageToScript = {\n 0: 0, // langEnglish → smRoman\n 1: 0, // langFrench → smRoman\n 2: 0, // langGerman → smRoman\n 3: 0, // langItalian → smRoman\n 4: 0, // langDutch → smRoman\n 5: 0, // langSwedish → smRoman\n 6: 0, // langSpanish → smRoman\n 7: 0, // langDanish → smRoman\n 8: 0, // langPortuguese → smRoman\n 9: 0, // langNorwegian → smRoman\n 10: 5, // langHebrew → smHebrew\n 11: 1, // langJapanese → smJapanese\n 12: 4, // langArabic → smArabic\n 13: 0, // langFinnish → smRoman\n 14: 6, // langGreek → smGreek\n 15: 0, // langIcelandic → smRoman (modified)\n 16: 0, // langMaltese → smRoman\n 17: 0, // langTurkish → smRoman (modified)\n 18: 0, // langCroatian → smRoman (modified)\n 19: 2, // langTradChinese → smTradChinese\n 20: 4, // langUrdu → smArabic\n 21: 9, // langHindi → smDevanagari\n 22: 21, // langThai → smThai\n 23: 3, // langKorean → smKorean\n 24: 29, // langLithuanian → smCentralEuroRoman\n 25: 29, // langPolish → smCentralEuroRoman\n 26: 29, // langHungarian → smCentralEuroRoman\n 27: 29, // langEstonian → smCentralEuroRoman\n 28: 29, // langLatvian → smCentralEuroRoman\n 29: 0, // langSami → smRoman\n 30: 0, // langFaroese → smRoman (modified)\n 31: 4, // langFarsi → smArabic (modified)\n 32: 7, // langRussian → smCyrillic\n 33: 25, // langSimpChinese → smSimpChinese\n 34: 0, // langFlemish → smRoman\n 35: 0, // langIrishGaelic → smRoman (modified)\n 36: 0, // langAlbanian → smRoman\n 37: 0, // langRomanian → smRoman (modified)\n 38: 29, // langCzech → smCentralEuroRoman\n 39: 29, // langSlovak → smCentralEuroRoman\n 40: 0, // langSlovenian → smRoman (modified)\n 41: 5, // langYiddish → smHebrew\n 42: 7, // langSerbian → smCyrillic\n 43: 7, // langMacedonian → smCyrillic\n 44: 7, // langBulgarian → smCyrillic\n 45: 7, // langUkrainian → smCyrillic (modified)\n 46: 7, // langByelorussian → smCyrillic\n 47: 7, // langUzbek → smCyrillic\n 48: 7, // langKazakh → smCyrillic\n 49: 7, // langAzerbaijani → smCyrillic\n 50: 4, // langAzerbaijanAr → smArabic\n 51: 24, // langArmenian → smArmenian\n 52: 23, // langGeorgian → smGeorgian\n 53: 7, // langMoldavian → smCyrillic\n 54: 7, // langKirghiz → smCyrillic\n 55: 7, // langTajiki → smCyrillic\n 56: 7, // langTurkmen → smCyrillic\n 57: 27, // langMongolian → smMongolian\n 58: 7, // langMongolianCyr → smCyrillic\n 59: 4, // langPashto → smArabic\n 60: 4, // langKurdish → smArabic\n 61: 4, // langKashmiri → smArabic\n 62: 4, // langSindhi → smArabic\n 63: 26, // langTibetan → smTibetan\n 64: 9, // langNepali → smDevanagari\n 65: 9, // langSanskrit → smDevanagari\n 66: 9, // langMarathi → smDevanagari\n 67: 13, // langBengali → smBengali\n 68: 13, // langAssamese → smBengali\n 69: 11, // langGujarati → smGujarati\n 70: 10, // langPunjabi → smGurmukhi\n 71: 12, // langOriya → smOriya\n 72: 17, // langMalayalam → smMalayalam\n 73: 16, // langKannada → smKannada\n 74: 14, // langTamil → smTamil\n 75: 15, // langTelugu → smTelugu\n 76: 18, // langSinhalese → smSinhalese\n 77: 19, // langBurmese → smBurmese\n 78: 20, // langKhmer → smKhmer\n 79: 22, // langLao → smLao\n 80: 30, // langVietnamese → smVietnamese\n 81: 0, // langIndonesian → smRoman\n 82: 0, // langTagalog → smRoman\n 83: 0, // langMalayRoman → smRoman\n 84: 4, // langMalayArabic → smArabic\n 85: 28, // langAmharic → smEthiopic\n 86: 28, // langTigrinya → smEthiopic\n 87: 28, // langOromo → smEthiopic\n 88: 0, // langSomali → smRoman\n 89: 0, // langSwahili → smRoman\n 90: 0, // langKinyarwanda → smRoman\n 91: 0, // langRundi → smRoman\n 92: 0, // langNyanja → smRoman\n 93: 0, // langMalagasy → smRoman\n 94: 0, // langEsperanto → smRoman\n 128: 0, // langWelsh → smRoman (modified)\n 129: 0, // langBasque → smRoman\n 130: 0, // langCatalan → smRoman\n 131: 0, // langLatin → smRoman\n 132: 0, // langQuechua → smRoman\n 133: 0, // langGuarani → smRoman\n 134: 0, // langAymara → smRoman\n 135: 7, // langTatar → smCyrillic\n 136: 4, // langUighur → smArabic\n 137: 26, // langDzongkha → smTibetan\n 138: 0, // langJavaneseRom → smRoman\n 139: 0, // langSundaneseRom → smRoman\n 140: 0, // langGalician → smRoman\n 141: 0, // langAfrikaans → smRoman\n 142: 0, // langBreton → smRoman (modified)\n 143: 28, // langInuktitut → smEthiopic (modified)\n 144: 0, // langScottishGaelic → smRoman (modified)\n 145: 0, // langManxGaelic → smRoman (modified)\n 146: 0, // langIrishGaelicScript → smRoman (modified)\n 147: 0, // langTongan → smRoman\n 148: 6, // langGreekAncient → smRoman\n 149: 0, // langGreenlandic → smRoman\n 150: 0, // langAzerbaijanRoman → smRoman\n 151: 0 // langNynorsk → smRoman\n};\n\n// While Microsoft indicates a region/country for all its language\n// IDs, we omit the region code if it's equal to the \"most likely\n// region subtag\" according to Unicode CLDR. For scripts, we omit\n// the subtag if it is equal to the Suppress-Script entry in the\n// IANA language subtag registry for IETF BCP 47.\n//\n// For example, Microsoft states that its language code 0x041A is\n// Croatian in Croatia. We transform this to the BCP 47 language code 'hr'\n// and not 'hr-HR' because Croatia is the default country for Croatian,\n// according to Unicode CLDR. As another example, Microsoft states\n// that 0x101A is Croatian (Latin) in Bosnia-Herzegovina. We transform\n// this to 'hr-BA' and not 'hr-Latn-BA' because Latin is the default script\n// for the Croatian language, according to IANA.\n//\n// http://www.unicode.org/cldr/charts/latest/supplemental/likely_subtags.html\n// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry\nvar windowsLanguages = {\n 0x0436: 'af',\n 0x041C: 'sq',\n 0x0484: 'gsw',\n 0x045E: 'am',\n 0x1401: 'ar-DZ',\n 0x3C01: 'ar-BH',\n 0x0C01: 'ar',\n 0x0801: 'ar-IQ',\n 0x2C01: 'ar-JO',\n 0x3401: 'ar-KW',\n 0x3001: 'ar-LB',\n 0x1001: 'ar-LY',\n 0x1801: 'ary',\n 0x2001: 'ar-OM',\n 0x4001: 'ar-QA',\n 0x0401: 'ar-SA',\n 0x2801: 'ar-SY',\n 0x1C01: 'aeb',\n 0x3801: 'ar-AE',\n 0x2401: 'ar-YE',\n 0x042B: 'hy',\n 0x044D: 'as',\n 0x082C: 'az-Cyrl',\n 0x042C: 'az',\n 0x046D: 'ba',\n 0x042D: 'eu',\n 0x0423: 'be',\n 0x0845: 'bn',\n 0x0445: 'bn-IN',\n 0x201A: 'bs-Cyrl',\n 0x141A: 'bs',\n 0x047E: 'br',\n 0x0402: 'bg',\n 0x0403: 'ca',\n 0x0C04: 'zh-HK',\n 0x1404: 'zh-MO',\n 0x0804: 'zh',\n 0x1004: 'zh-SG',\n 0x0404: 'zh-TW',\n 0x0483: 'co',\n 0x041A: 'hr',\n 0x101A: 'hr-BA',\n 0x0405: 'cs',\n 0x0406: 'da',\n 0x048C: 'prs',\n 0x0465: 'dv',\n 0x0813: 'nl-BE',\n 0x0413: 'nl',\n 0x0C09: 'en-AU',\n 0x2809: 'en-BZ',\n 0x1009: 'en-CA',\n 0x2409: 'en-029',\n 0x4009: 'en-IN',\n 0x1809: 'en-IE',\n 0x2009: 'en-JM',\n 0x4409: 'en-MY',\n 0x1409: 'en-NZ',\n 0x3409: 'en-PH',\n 0x4809: 'en-SG',\n 0x1C09: 'en-ZA',\n 0x2C09: 'en-TT',\n 0x0809: 'en-GB',\n 0x0409: 'en',\n 0x3009: 'en-ZW',\n 0x0425: 'et',\n 0x0438: 'fo',\n 0x0464: 'fil',\n 0x040B: 'fi',\n 0x080C: 'fr-BE',\n 0x0C0C: 'fr-CA',\n 0x040C: 'fr',\n 0x140C: 'fr-LU',\n 0x180C: 'fr-MC',\n 0x100C: 'fr-CH',\n 0x0462: 'fy',\n 0x0456: 'gl',\n 0x0437: 'ka',\n 0x0C07: 'de-AT',\n 0x0407: 'de',\n 0x1407: 'de-LI',\n 0x1007: 'de-LU',\n 0x0807: 'de-CH',\n 0x0408: 'el',\n 0x046F: 'kl',\n 0x0447: 'gu',\n 0x0468: 'ha',\n 0x040D: 'he',\n 0x0439: 'hi',\n 0x040E: 'hu',\n 0x040F: 'is',\n 0x0470: 'ig',\n 0x0421: 'id',\n 0x045D: 'iu',\n 0x085D: 'iu-Latn',\n 0x083C: 'ga',\n 0x0434: 'xh',\n 0x0435: 'zu',\n 0x0410: 'it',\n 0x0810: 'it-CH',\n 0x0411: 'ja',\n 0x044B: 'kn',\n 0x043F: 'kk',\n 0x0453: 'km',\n 0x0486: 'quc',\n 0x0487: 'rw',\n 0x0441: 'sw',\n 0x0457: 'kok',\n 0x0412: 'ko',\n 0x0440: 'ky',\n 0x0454: 'lo',\n 0x0426: 'lv',\n 0x0427: 'lt',\n 0x082E: 'dsb',\n 0x046E: 'lb',\n 0x042F: 'mk',\n 0x083E: 'ms-BN',\n 0x043E: 'ms',\n 0x044C: 'ml',\n 0x043A: 'mt',\n 0x0481: 'mi',\n 0x047A: 'arn',\n 0x044E: 'mr',\n 0x047C: 'moh',\n 0x0450: 'mn',\n 0x0850: 'mn-CN',\n 0x0461: 'ne',\n 0x0414: 'nb',\n 0x0814: 'nn',\n 0x0482: 'oc',\n 0x0448: 'or',\n 0x0463: 'ps',\n 0x0415: 'pl',\n 0x0416: 'pt',\n 0x0816: 'pt-PT',\n 0x0446: 'pa',\n 0x046B: 'qu-BO',\n 0x086B: 'qu-EC',\n 0x0C6B: 'qu',\n 0x0418: 'ro',\n 0x0417: 'rm',\n 0x0419: 'ru',\n 0x243B: 'smn',\n 0x103B: 'smj-NO',\n 0x143B: 'smj',\n 0x0C3B: 'se-FI',\n 0x043B: 'se',\n 0x083B: 'se-SE',\n 0x203B: 'sms',\n 0x183B: 'sma-NO',\n 0x1C3B: 'sms',\n 0x044F: 'sa',\n 0x1C1A: 'sr-Cyrl-BA',\n 0x0C1A: 'sr',\n 0x181A: 'sr-Latn-BA',\n 0x081A: 'sr-Latn',\n 0x046C: 'nso',\n 0x0432: 'tn',\n 0x045B: 'si',\n 0x041B: 'sk',\n 0x0424: 'sl',\n 0x2C0A: 'es-AR',\n 0x400A: 'es-BO',\n 0x340A: 'es-CL',\n 0x240A: 'es-CO',\n 0x140A: 'es-CR',\n 0x1C0A: 'es-DO',\n 0x300A: 'es-EC',\n 0x440A: 'es-SV',\n 0x100A: 'es-GT',\n 0x480A: 'es-HN',\n 0x080A: 'es-MX',\n 0x4C0A: 'es-NI',\n 0x180A: 'es-PA',\n 0x3C0A: 'es-PY',\n 0x280A: 'es-PE',\n 0x500A: 'es-PR',\n\n // Microsoft has defined two different language codes for\n // “Spanish with modern sorting” and “Spanish with traditional\n // sorting”. This makes sense for collation APIs, and it would be\n // possible to express this in BCP 47 language tags via Unicode\n // extensions (eg., es-u-co-trad is Spanish with traditional\n // sorting). However, for storing names in fonts, the distinction\n // does not make sense, so we give “es” in both cases.\n 0x0C0A: 'es',\n 0x040A: 'es',\n\n 0x540A: 'es-US',\n 0x380A: 'es-UY',\n 0x200A: 'es-VE',\n 0x081D: 'sv-FI',\n 0x041D: 'sv',\n 0x045A: 'syr',\n 0x0428: 'tg',\n 0x085F: 'tzm',\n 0x0449: 'ta',\n 0x0444: 'tt',\n 0x044A: 'te',\n 0x041E: 'th',\n 0x0451: 'bo',\n 0x041F: 'tr',\n 0x0442: 'tk',\n 0x0480: 'ug',\n 0x0422: 'uk',\n 0x042E: 'hsb',\n 0x0420: 'ur',\n 0x0843: 'uz-Cyrl',\n 0x0443: 'uz',\n 0x042A: 'vi',\n 0x0452: 'cy',\n 0x0488: 'wo',\n 0x0485: 'sah',\n 0x0478: 'ii',\n 0x046A: 'yo'\n};\n\n// Returns a IETF BCP 47 language code, for example 'zh-Hant'\n// for 'Chinese in the traditional script'.\nfunction getLanguageCode(platformID, languageID, ltag) {\n switch (platformID) {\n case 0: // Unicode\n if (languageID === 0xFFFF) {\n return 'und';\n } else if (ltag) {\n return ltag[languageID];\n }\n\n break;\n\n case 1: // Macintosh\n return macLanguages[languageID];\n\n case 3: // Windows\n return windowsLanguages[languageID];\n }\n\n return undefined;\n}\n\nvar utf16 = 'utf-16';\n\n// MacOS script ID → encoding. This table stores the default case,\n// which can be overridden by macLanguageEncodings.\nvar macScriptEncodings = {\n 0: 'macintosh', // smRoman\n 1: 'x-mac-japanese', // smJapanese\n 2: 'x-mac-chinesetrad', // smTradChinese\n 3: 'x-mac-korean', // smKorean\n 6: 'x-mac-greek', // smGreek\n 7: 'x-mac-cyrillic', // smCyrillic\n 9: 'x-mac-devanagai', // smDevanagari\n 10: 'x-mac-gurmukhi', // smGurmukhi\n 11: 'x-mac-gujarati', // smGujarati\n 12: 'x-mac-oriya', // smOriya\n 13: 'x-mac-bengali', // smBengali\n 14: 'x-mac-tamil', // smTamil\n 15: 'x-mac-telugu', // smTelugu\n 16: 'x-mac-kannada', // smKannada\n 17: 'x-mac-malayalam', // smMalayalam\n 18: 'x-mac-sinhalese', // smSinhalese\n 19: 'x-mac-burmese', // smBurmese\n 20: 'x-mac-khmer', // smKhmer\n 21: 'x-mac-thai', // smThai\n 22: 'x-mac-lao', // smLao\n 23: 'x-mac-georgian', // smGeorgian\n 24: 'x-mac-armenian', // smArmenian\n 25: 'x-mac-chinesesimp', // smSimpChinese\n 26: 'x-mac-tibetan', // smTibetan\n 27: 'x-mac-mongolian', // smMongolian\n 28: 'x-mac-ethiopic', // smEthiopic\n 29: 'x-mac-ce', // smCentralEuroRoman\n 30: 'x-mac-vietnamese', // smVietnamese\n 31: 'x-mac-extarabic' // smExtArabic\n};\n\n// MacOS language ID → encoding. This table stores the exceptional\n// cases, which override macScriptEncodings. For writing MacOS naming\n// tables, we need to emit a MacOS script ID. Therefore, we cannot\n// merge macScriptEncodings into macLanguageEncodings.\n//\n// http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt\nvar macLanguageEncodings = {\n 15: 'x-mac-icelandic', // langIcelandic\n 17: 'x-mac-turkish', // langTurkish\n 18: 'x-mac-croatian', // langCroatian\n 24: 'x-mac-ce', // langLithuanian\n 25: 'x-mac-ce', // langPolish\n 26: 'x-mac-ce', // langHungarian\n 27: 'x-mac-ce', // langEstonian\n 28: 'x-mac-ce', // langLatvian\n 30: 'x-mac-icelandic', // langFaroese\n 37: 'x-mac-romanian', // langRomanian\n 38: 'x-mac-ce', // langCzech\n 39: 'x-mac-ce', // langSlovak\n 40: 'x-mac-ce', // langSlovenian\n 143: 'x-mac-inuit', // langInuktitut\n 146: 'x-mac-gaelic' // langIrishGaelicScript\n};\n\nfunction getEncoding(platformID, encodingID, languageID) {\n switch (platformID) {\n case 0: // Unicode\n return utf16;\n\n case 1: // Apple Macintosh\n return macLanguageEncodings[languageID] || macScriptEncodings[encodingID];\n\n case 3: // Microsoft Windows\n if (encodingID === 1 || encodingID === 10) {\n return utf16;\n }\n\n break;\n }\n\n return undefined;\n}\n\n// Parse the naming `name` table.\n// FIXME: Format 1 additional fields are not supported yet.\n// ltag is the content of the `ltag' table, such as ['en', 'zh-Hans', 'de-CH-1904'].\nfunction parseNameTable(data, start, ltag) {\n var name = {};\n var p = new parse.Parser(data, start);\n var format = p.parseUShort();\n var count = p.parseUShort();\n var stringOffset = p.offset + p.parseUShort();\n for (var i = 0; i < count; i++) {\n var platformID = p.parseUShort();\n var encodingID = p.parseUShort();\n var languageID = p.parseUShort();\n var nameID = p.parseUShort();\n var property = nameTableNames[nameID] || nameID;\n var byteLength = p.parseUShort();\n var offset = p.parseUShort();\n var language = getLanguageCode(platformID, languageID, ltag);\n var encoding = getEncoding(platformID, encodingID, languageID);\n if (encoding !== undefined && language !== undefined) {\n var text;\n if (encoding === utf16) {\n text = decode.UTF16(data, stringOffset + offset, byteLength);\n } else {\n text = decode.MACSTRING(data, stringOffset + offset, byteLength, encoding);\n }\n\n if (text) {\n var translations = name[property];\n if (translations === undefined) {\n translations = name[property] = {};\n }\n\n translations[language] = text;\n }\n }\n }\n\n var langTagCount = 0;\n if (format === 1) {\n // FIXME: Also handle Microsoft's 'name' table 1.\n langTagCount = p.parseUShort();\n }\n\n return name;\n}\n\n// {23: 'foo'} → {'foo': 23}\n// ['bar', 'baz'] → {'bar': 0, 'baz': 1}\nfunction reverseDict(dict) {\n var result = {};\n for (var key in dict) {\n result[dict[key]] = parseInt(key);\n }\n\n return result;\n}\n\nfunction makeNameRecord(platformID, encodingID, languageID, nameID, length, offset) {\n return new table.Record('NameRecord', [\n {name: 'platformID', type: 'USHORT', value: platformID},\n {name: 'encodingID', type: 'USHORT', value: encodingID},\n {name: 'languageID', type: 'USHORT', value: languageID},\n {name: 'nameID', type: 'USHORT', value: nameID},\n {name: 'length', type: 'USHORT', value: length},\n {name: 'offset', type: 'USHORT', value: offset}\n ]);\n}\n\n// Finds the position of needle in haystack, or -1 if not there.\n// Like String.indexOf(), but for arrays.\nfunction findSubArray(needle, haystack) {\n var needleLength = needle.length;\n var limit = haystack.length - needleLength + 1;\n\n loop:\n for (var pos = 0; pos < limit; pos++) {\n for (; pos < limit; pos++) {\n for (var k = 0; k < needleLength; k++) {\n if (haystack[pos + k] !== needle[k]) {\n continue loop;\n }\n }\n\n return pos;\n }\n }\n\n return -1;\n}\n\nfunction addStringToPool(s, pool) {\n var offset = findSubArray(s, pool);\n if (offset < 0) {\n offset = pool.length;\n for (var i = 0, len = s.length; i < len; ++i) {\n pool.push(s[i]);\n }\n\n }\n\n return offset;\n}\n\nfunction makeNameTable(names, ltag) {\n var nameID;\n var nameIDs = [];\n\n var namesWithNumericKeys = {};\n var nameTableIds = reverseDict(nameTableNames);\n for (var key in names) {\n var id = nameTableIds[key];\n if (id === undefined) {\n id = key;\n }\n\n nameID = parseInt(id);\n namesWithNumericKeys[nameID] = names[key];\n nameIDs.push(nameID);\n }\n\n var macLanguageIds = reverseDict(macLanguages);\n var windowsLanguageIds = reverseDict(windowsLanguages);\n\n var nameRecords = [];\n var stringPool = [];\n\n for (var i = 0; i < nameIDs.length; i++) {\n nameID = nameIDs[i];\n var translations = namesWithNumericKeys[nameID];\n for (var lang in translations) {\n var text = translations[lang];\n\n // For MacOS, we try to emit the name in the form that was introduced\n // in the initial version of the TrueType spec (in the late 1980s).\n // However, this can fail for various reasons: the requested BCP 47\n // language code might not have an old-style Mac equivalent;\n // we might not have a codec for the needed character encoding;\n // or the name might contain characters that cannot be expressed\n // in the old-style Macintosh encoding. In case of failure, we emit\n // the name in a more modern fashion (Unicode encoding with BCP 47\n // language tags) that is recognized by MacOS 10.5, released in 2009.\n // If fonts were only read by operating systems, we could simply\n // emit all names in the modern form; this would be much easier.\n // However, there are many applications and libraries that read\n // 'name' tables directly, and these will usually only recognize\n // the ancient form (silently skipping the unrecognized names).\n var macPlatform = 1; // Macintosh\n var macLanguage = macLanguageIds[lang];\n var macScript = macLanguageToScript[macLanguage];\n var macEncoding = getEncoding(macPlatform, macScript, macLanguage);\n var macName = encode.MACSTRING(text, macEncoding);\n if (macName === undefined) {\n macPlatform = 0; // Unicode\n macLanguage = ltag.indexOf(lang);\n if (macLanguage < 0) {\n macLanguage = ltag.length;\n ltag.push(lang);\n }\n\n macScript = 4; // Unicode 2.0 and later\n macName = encode.UTF16(text);\n }\n\n var macNameOffset = addStringToPool(macName, stringPool);\n nameRecords.push(makeNameRecord(macPlatform, macScript, macLanguage,\n nameID, macName.length, macNameOffset));\n\n var winLanguage = windowsLanguageIds[lang];\n if (winLanguage !== undefined) {\n var winName = encode.UTF16(text);\n var winNameOffset = addStringToPool(winName, stringPool);\n nameRecords.push(makeNameRecord(3, 1, winLanguage,\n nameID, winName.length, winNameOffset));\n }\n }\n }\n\n nameRecords.sort(function(a, b) {\n return ((a.platformID - b.platformID) ||\n (a.encodingID - b.encodingID) ||\n (a.languageID - b.languageID) ||\n (a.nameID - b.nameID));\n });\n\n var t = new table.Table('name', [\n {name: 'format', type: 'USHORT', value: 0},\n {name: 'count', type: 'USHORT', value: nameRecords.length},\n {name: 'stringOffset', type: 'USHORT', value: 6 + nameRecords.length * 12}\n ]);\n\n for (var r = 0; r < nameRecords.length; r++) {\n t.fields.push({name: 'record_' + r, type: 'RECORD', value: nameRecords[r]});\n }\n\n t.fields.push({name: 'strings', type: 'LITERAL', value: stringPool});\n return t;\n}\n\nexports.parse = parseNameTable;\nexports.make = makeNameTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/name.js\n ** module id = 22\n ** module chunks = 0\n **/","// The `OS/2` table contains metrics required in OpenType fonts.\n// https://www.microsoft.com/typography/OTSPEC/os2.htm\n\n'use strict';\n\nvar parse = require('../parse');\nvar table = require('../table');\n\nvar unicodeRanges = [\n {begin: 0x0000, end: 0x007F}, // Basic Latin\n {begin: 0x0080, end: 0x00FF}, // Latin-1 Supplement\n {begin: 0x0100, end: 0x017F}, // Latin Extended-A\n {begin: 0x0180, end: 0x024F}, // Latin Extended-B\n {begin: 0x0250, end: 0x02AF}, // IPA Extensions\n {begin: 0x02B0, end: 0x02FF}, // Spacing Modifier Letters\n {begin: 0x0300, end: 0x036F}, // Combining Diacritical Marks\n {begin: 0x0370, end: 0x03FF}, // Greek and Coptic\n {begin: 0x2C80, end: 0x2CFF}, // Coptic\n {begin: 0x0400, end: 0x04FF}, // Cyrillic\n {begin: 0x0530, end: 0x058F}, // Armenian\n {begin: 0x0590, end: 0x05FF}, // Hebrew\n {begin: 0xA500, end: 0xA63F}, // Vai\n {begin: 0x0600, end: 0x06FF}, // Arabic\n {begin: 0x07C0, end: 0x07FF}, // NKo\n {begin: 0x0900, end: 0x097F}, // Devanagari\n {begin: 0x0980, end: 0x09FF}, // Bengali\n {begin: 0x0A00, end: 0x0A7F}, // Gurmukhi\n {begin: 0x0A80, end: 0x0AFF}, // Gujarati\n {begin: 0x0B00, end: 0x0B7F}, // Oriya\n {begin: 0x0B80, end: 0x0BFF}, // Tamil\n {begin: 0x0C00, end: 0x0C7F}, // Telugu\n {begin: 0x0C80, end: 0x0CFF}, // Kannada\n {begin: 0x0D00, end: 0x0D7F}, // Malayalam\n {begin: 0x0E00, end: 0x0E7F}, // Thai\n {begin: 0x0E80, end: 0x0EFF}, // Lao\n {begin: 0x10A0, end: 0x10FF}, // Georgian\n {begin: 0x1B00, end: 0x1B7F}, // Balinese\n {begin: 0x1100, end: 0x11FF}, // Hangul Jamo\n {begin: 0x1E00, end: 0x1EFF}, // Latin Extended Additional\n {begin: 0x1F00, end: 0x1FFF}, // Greek Extended\n {begin: 0x2000, end: 0x206F}, // General Punctuation\n {begin: 0x2070, end: 0x209F}, // Superscripts And Subscripts\n {begin: 0x20A0, end: 0x20CF}, // Currency Symbol\n {begin: 0x20D0, end: 0x20FF}, // Combining Diacritical Marks For Symbols\n {begin: 0x2100, end: 0x214F}, // Letterlike Symbols\n {begin: 0x2150, end: 0x218F}, // Number Forms\n {begin: 0x2190, end: 0x21FF}, // Arrows\n {begin: 0x2200, end: 0x22FF}, // Mathematical Operators\n {begin: 0x2300, end: 0x23FF}, // Miscellaneous Technical\n {begin: 0x2400, end: 0x243F}, // Control Pictures\n {begin: 0x2440, end: 0x245F}, // Optical Character Recognition\n {begin: 0x2460, end: 0x24FF}, // Enclosed Alphanumerics\n {begin: 0x2500, end: 0x257F}, // Box Drawing\n {begin: 0x2580, end: 0x259F}, // Block Elements\n {begin: 0x25A0, end: 0x25FF}, // Geometric Shapes\n {begin: 0x2600, end: 0x26FF}, // Miscellaneous Symbols\n {begin: 0x2700, end: 0x27BF}, // Dingbats\n {begin: 0x3000, end: 0x303F}, // CJK Symbols And Punctuation\n {begin: 0x3040, end: 0x309F}, // Hiragana\n {begin: 0x30A0, end: 0x30FF}, // Katakana\n {begin: 0x3100, end: 0x312F}, // Bopomofo\n {begin: 0x3130, end: 0x318F}, // Hangul Compatibility Jamo\n {begin: 0xA840, end: 0xA87F}, // Phags-pa\n {begin: 0x3200, end: 0x32FF}, // Enclosed CJK Letters And Months\n {begin: 0x3300, end: 0x33FF}, // CJK Compatibility\n {begin: 0xAC00, end: 0xD7AF}, // Hangul Syllables\n {begin: 0xD800, end: 0xDFFF}, // Non-Plane 0 *\n {begin: 0x10900, end: 0x1091F}, // Phoenicia\n {begin: 0x4E00, end: 0x9FFF}, // CJK Unified Ideographs\n {begin: 0xE000, end: 0xF8FF}, // Private Use Area (plane 0)\n {begin: 0x31C0, end: 0x31EF}, // CJK Strokes\n {begin: 0xFB00, end: 0xFB4F}, // Alphabetic Presentation Forms\n {begin: 0xFB50, end: 0xFDFF}, // Arabic Presentation Forms-A\n {begin: 0xFE20, end: 0xFE2F}, // Combining Half Marks\n {begin: 0xFE10, end: 0xFE1F}, // Vertical Forms\n {begin: 0xFE50, end: 0xFE6F}, // Small Form Variants\n {begin: 0xFE70, end: 0xFEFF}, // Arabic Presentation Forms-B\n {begin: 0xFF00, end: 0xFFEF}, // Halfwidth And Fullwidth Forms\n {begin: 0xFFF0, end: 0xFFFF}, // Specials\n {begin: 0x0F00, end: 0x0FFF}, // Tibetan\n {begin: 0x0700, end: 0x074F}, // Syriac\n {begin: 0x0780, end: 0x07BF}, // Thaana\n {begin: 0x0D80, end: 0x0DFF}, // Sinhala\n {begin: 0x1000, end: 0x109F}, // Myanmar\n {begin: 0x1200, end: 0x137F}, // Ethiopic\n {begin: 0x13A0, end: 0x13FF}, // Cherokee\n {begin: 0x1400, end: 0x167F}, // Unified Canadian Aboriginal Syllabics\n {begin: 0x1680, end: 0x169F}, // Ogham\n {begin: 0x16A0, end: 0x16FF}, // Runic\n {begin: 0x1780, end: 0x17FF}, // Khmer\n {begin: 0x1800, end: 0x18AF}, // Mongolian\n {begin: 0x2800, end: 0x28FF}, // Braille Patterns\n {begin: 0xA000, end: 0xA48F}, // Yi Syllables\n {begin: 0x1700, end: 0x171F}, // Tagalog\n {begin: 0x10300, end: 0x1032F}, // Old Italic\n {begin: 0x10330, end: 0x1034F}, // Gothic\n {begin: 0x10400, end: 0x1044F}, // Deseret\n {begin: 0x1D000, end: 0x1D0FF}, // Byzantine Musical Symbols\n {begin: 0x1D400, end: 0x1D7FF}, // Mathematical Alphanumeric Symbols\n {begin: 0xFF000, end: 0xFFFFD}, // Private Use (plane 15)\n {begin: 0xFE00, end: 0xFE0F}, // Variation Selectors\n {begin: 0xE0000, end: 0xE007F}, // Tags\n {begin: 0x1900, end: 0x194F}, // Limbu\n {begin: 0x1950, end: 0x197F}, // Tai Le\n {begin: 0x1980, end: 0x19DF}, // New Tai Lue\n {begin: 0x1A00, end: 0x1A1F}, // Buginese\n {begin: 0x2C00, end: 0x2C5F}, // Glagolitic\n {begin: 0x2D30, end: 0x2D7F}, // Tifinagh\n {begin: 0x4DC0, end: 0x4DFF}, // Yijing Hexagram Symbols\n {begin: 0xA800, end: 0xA82F}, // Syloti Nagri\n {begin: 0x10000, end: 0x1007F}, // Linear B Syllabary\n {begin: 0x10140, end: 0x1018F}, // Ancient Greek Numbers\n {begin: 0x10380, end: 0x1039F}, // Ugaritic\n {begin: 0x103A0, end: 0x103DF}, // Old Persian\n {begin: 0x10450, end: 0x1047F}, // Shavian\n {begin: 0x10480, end: 0x104AF}, // Osmanya\n {begin: 0x10800, end: 0x1083F}, // Cypriot Syllabary\n {begin: 0x10A00, end: 0x10A5F}, // Kharoshthi\n {begin: 0x1D300, end: 0x1D35F}, // Tai Xuan Jing Symbols\n {begin: 0x12000, end: 0x123FF}, // Cuneiform\n {begin: 0x1D360, end: 0x1D37F}, // Counting Rod Numerals\n {begin: 0x1B80, end: 0x1BBF}, // Sundanese\n {begin: 0x1C00, end: 0x1C4F}, // Lepcha\n {begin: 0x1C50, end: 0x1C7F}, // Ol Chiki\n {begin: 0xA880, end: 0xA8DF}, // Saurashtra\n {begin: 0xA900, end: 0xA92F}, // Kayah Li\n {begin: 0xA930, end: 0xA95F}, // Rejang\n {begin: 0xAA00, end: 0xAA5F}, // Cham\n {begin: 0x10190, end: 0x101CF}, // Ancient Symbols\n {begin: 0x101D0, end: 0x101FF}, // Phaistos Disc\n {begin: 0x102A0, end: 0x102DF}, // Carian\n {begin: 0x1F030, end: 0x1F09F} // Domino Tiles\n];\n\nfunction getUnicodeRange(unicode) {\n for (var i = 0; i < unicodeRanges.length; i += 1) {\n var range = unicodeRanges[i];\n if (unicode >= range.begin && unicode < range.end) {\n return i;\n }\n }\n\n return -1;\n}\n\n// Parse the OS/2 and Windows metrics `OS/2` table\nfunction parseOS2Table(data, start) {\n var os2 = {};\n var p = new parse.Parser(data, start);\n os2.version = p.parseUShort();\n os2.xAvgCharWidth = p.parseShort();\n os2.usWeightClass = p.parseUShort();\n os2.usWidthClass = p.parseUShort();\n os2.fsType = p.parseUShort();\n os2.ySubscriptXSize = p.parseShort();\n os2.ySubscriptYSize = p.parseShort();\n os2.ySubscriptXOffset = p.parseShort();\n os2.ySubscriptYOffset = p.parseShort();\n os2.ySuperscriptXSize = p.parseShort();\n os2.ySuperscriptYSize = p.parseShort();\n os2.ySuperscriptXOffset = p.parseShort();\n os2.ySuperscriptYOffset = p.parseShort();\n os2.yStrikeoutSize = p.parseShort();\n os2.yStrikeoutPosition = p.parseShort();\n os2.sFamilyClass = p.parseShort();\n os2.panose = [];\n for (var i = 0; i < 10; i++) {\n os2.panose[i] = p.parseByte();\n }\n\n os2.ulUnicodeRange1 = p.parseULong();\n os2.ulUnicodeRange2 = p.parseULong();\n os2.ulUnicodeRange3 = p.parseULong();\n os2.ulUnicodeRange4 = p.parseULong();\n os2.achVendID = String.fromCharCode(p.parseByte(), p.parseByte(), p.parseByte(), p.parseByte());\n os2.fsSelection = p.parseUShort();\n os2.usFirstCharIndex = p.parseUShort();\n os2.usLastCharIndex = p.parseUShort();\n os2.sTypoAscender = p.parseShort();\n os2.sTypoDescender = p.parseShort();\n os2.sTypoLineGap = p.parseShort();\n os2.usWinAscent = p.parseUShort();\n os2.usWinDescent = p.parseUShort();\n if (os2.version >= 1) {\n os2.ulCodePageRange1 = p.parseULong();\n os2.ulCodePageRange2 = p.parseULong();\n }\n\n if (os2.version >= 2) {\n os2.sxHeight = p.parseShort();\n os2.sCapHeight = p.parseShort();\n os2.usDefaultChar = p.parseUShort();\n os2.usBreakChar = p.parseUShort();\n os2.usMaxContent = p.parseUShort();\n }\n\n return os2;\n}\n\nfunction makeOS2Table(options) {\n return new table.Table('OS/2', [\n {name: 'version', type: 'USHORT', value: 0x0003},\n {name: 'xAvgCharWidth', type: 'SHORT', value: 0},\n {name: 'usWeightClass', type: 'USHORT', value: 0},\n {name: 'usWidthClass', type: 'USHORT', value: 0},\n {name: 'fsType', type: 'USHORT', value: 0},\n {name: 'ySubscriptXSize', type: 'SHORT', value: 650},\n {name: 'ySubscriptYSize', type: 'SHORT', value: 699},\n {name: 'ySubscriptXOffset', type: 'SHORT', value: 0},\n {name: 'ySubscriptYOffset', type: 'SHORT', value: 140},\n {name: 'ySuperscriptXSize', type: 'SHORT', value: 650},\n {name: 'ySuperscriptYSize', type: 'SHORT', value: 699},\n {name: 'ySuperscriptXOffset', type: 'SHORT', value: 0},\n {name: 'ySuperscriptYOffset', type: 'SHORT', value: 479},\n {name: 'yStrikeoutSize', type: 'SHORT', value: 49},\n {name: 'yStrikeoutPosition', type: 'SHORT', value: 258},\n {name: 'sFamilyClass', type: 'SHORT', value: 0},\n {name: 'bFamilyType', type: 'BYTE', value: 0},\n {name: 'bSerifStyle', type: 'BYTE', value: 0},\n {name: 'bWeight', type: 'BYTE', value: 0},\n {name: 'bProportion', type: 'BYTE', value: 0},\n {name: 'bContrast', type: 'BYTE', value: 0},\n {name: 'bStrokeVariation', type: 'BYTE', value: 0},\n {name: 'bArmStyle', type: 'BYTE', value: 0},\n {name: 'bLetterform', type: 'BYTE', value: 0},\n {name: 'bMidline', type: 'BYTE', value: 0},\n {name: 'bXHeight', type: 'BYTE', value: 0},\n {name: 'ulUnicodeRange1', type: 'ULONG', value: 0},\n {name: 'ulUnicodeRange2', type: 'ULONG', value: 0},\n {name: 'ulUnicodeRange3', type: 'ULONG', value: 0},\n {name: 'ulUnicodeRange4', type: 'ULONG', value: 0},\n {name: 'achVendID', type: 'CHARARRAY', value: 'XXXX'},\n {name: 'fsSelection', type: 'USHORT', value: 0},\n {name: 'usFirstCharIndex', type: 'USHORT', value: 0},\n {name: 'usLastCharIndex', type: 'USHORT', value: 0},\n {name: 'sTypoAscender', type: 'SHORT', value: 0},\n {name: 'sTypoDescender', type: 'SHORT', value: 0},\n {name: 'sTypoLineGap', type: 'SHORT', value: 0},\n {name: 'usWinAscent', type: 'USHORT', value: 0},\n {name: 'usWinDescent', type: 'USHORT', value: 0},\n {name: 'ulCodePageRange1', type: 'ULONG', value: 0},\n {name: 'ulCodePageRange2', type: 'ULONG', value: 0},\n {name: 'sxHeight', type: 'SHORT', value: 0},\n {name: 'sCapHeight', type: 'SHORT', value: 0},\n {name: 'usDefaultChar', type: 'USHORT', value: 0},\n {name: 'usBreakChar', type: 'USHORT', value: 0},\n {name: 'usMaxContext', type: 'USHORT', value: 0}\n ], options);\n}\n\nexports.unicodeRanges = unicodeRanges;\nexports.getUnicodeRange = getUnicodeRange;\nexports.parse = parseOS2Table;\nexports.make = makeOS2Table;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/os2.js\n ** module id = 23\n ** module chunks = 0\n **/","// The `post` table stores additional PostScript information, such as glyph names.\n// https://www.microsoft.com/typography/OTSPEC/post.htm\n\n'use strict';\n\nvar encoding = require('../encoding');\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the PostScript `post` table\nfunction parsePostTable(data, start) {\n var post = {};\n var p = new parse.Parser(data, start);\n var i;\n post.version = p.parseVersion();\n post.italicAngle = p.parseFixed();\n post.underlinePosition = p.parseShort();\n post.underlineThickness = p.parseShort();\n post.isFixedPitch = p.parseULong();\n post.minMemType42 = p.parseULong();\n post.maxMemType42 = p.parseULong();\n post.minMemType1 = p.parseULong();\n post.maxMemType1 = p.parseULong();\n switch (post.version) {\n case 1:\n post.names = encoding.standardNames.slice();\n break;\n case 2:\n post.numberOfGlyphs = p.parseUShort();\n post.glyphNameIndex = new Array(post.numberOfGlyphs);\n for (i = 0; i < post.numberOfGlyphs; i++) {\n post.glyphNameIndex[i] = p.parseUShort();\n }\n\n post.names = [];\n for (i = 0; i < post.numberOfGlyphs; i++) {\n if (post.glyphNameIndex[i] >= encoding.standardNames.length) {\n var nameLength = p.parseChar();\n post.names.push(p.parseString(nameLength));\n }\n }\n\n break;\n case 2.5:\n post.numberOfGlyphs = p.parseUShort();\n post.offset = new Array(post.numberOfGlyphs);\n for (i = 0; i < post.numberOfGlyphs; i++) {\n post.offset[i] = p.parseChar();\n }\n\n break;\n }\n return post;\n}\n\nfunction makePostTable() {\n return new table.Table('post', [\n {name: 'version', type: 'FIXED', value: 0x00030000},\n {name: 'italicAngle', type: 'FIXED', value: 0},\n {name: 'underlinePosition', type: 'FWORD', value: 0},\n {name: 'underlineThickness', type: 'FWORD', value: 0},\n {name: 'isFixedPitch', type: 'ULONG', value: 0},\n {name: 'minMemType42', type: 'ULONG', value: 0},\n {name: 'maxMemType42', type: 'ULONG', value: 0},\n {name: 'minMemType1', type: 'ULONG', value: 0},\n {name: 'maxMemType1', type: 'ULONG', value: 0}\n ]);\n}\n\nexports.parse = parsePostTable;\nexports.make = makePostTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/post.js\n ** module id = 24\n ** module chunks = 0\n **/","'use strict';\n\nexports.isBrowser = function() {\n return typeof window !== 'undefined';\n};\n\nexports.isNode = function() {\n return typeof window === 'undefined';\n};\n\nexports.nodeBufferToArrayBuffer = function(buffer) {\n var ab = new ArrayBuffer(buffer.length);\n var view = new Uint8Array(ab);\n for (var i = 0; i < buffer.length; ++i) {\n view[i] = buffer[i];\n }\n\n return ab;\n};\n\nexports.arrayBufferToNodeBuffer = function(ab) {\n var buffer = new Buffer(ab.byteLength);\n var view = new Uint8Array(ab);\n for (var i = 0; i < buffer.length; ++i) {\n buffer[i] = view[i];\n }\n\n return buffer;\n};\n\nexports.checkArgument = function(expression, message) {\n if (!expression) {\n throw message;\n }\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/util.js\n ** module id = 25\n ** module chunks = 0\n **/","/* (ignored) */\n\n\n/*****************\n ** WEBPACK FOOTER\n ** fs (ignored)\n ** module id = 26\n ** module chunks = 0\n **/","// The `fvar` table stores font variation axes and instances.\n// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fvar.html\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\nvar table = require('../table');\n\nfunction addName(name, names) {\n var nameString = JSON.stringify(name);\n var nameID = 256;\n for (var nameKey in names) {\n var n = parseInt(nameKey);\n if (!n || n < 256) {\n continue;\n }\n\n if (JSON.stringify(names[nameKey]) === nameString) {\n return n;\n }\n\n if (nameID <= n) {\n nameID = n + 1;\n }\n }\n\n names[nameID] = name;\n return nameID;\n}\n\nfunction makeFvarAxis(n, axis, names) {\n var nameID = addName(axis.name, names);\n return [\n {name: 'tag_' + n, type: 'TAG', value: axis.tag},\n {name: 'minValue_' + n, type: 'FIXED', value: axis.minValue << 16},\n {name: 'defaultValue_' + n, type: 'FIXED', value: axis.defaultValue << 16},\n {name: 'maxValue_' + n, type: 'FIXED', value: axis.maxValue << 16},\n {name: 'flags_' + n, type: 'USHORT', value: 0},\n {name: 'nameID_' + n, type: 'USHORT', value: nameID}\n ];\n}\n\nfunction parseFvarAxis(data, start, names) {\n var axis = {};\n var p = new parse.Parser(data, start);\n axis.tag = p.parseTag();\n axis.minValue = p.parseFixed();\n axis.defaultValue = p.parseFixed();\n axis.maxValue = p.parseFixed();\n p.skip('uShort', 1); // reserved for flags; no values defined\n axis.name = names[p.parseUShort()] || {};\n return axis;\n}\n\nfunction makeFvarInstance(n, inst, axes, names) {\n var nameID = addName(inst.name, names);\n var fields = [\n {name: 'nameID_' + n, type: 'USHORT', value: nameID},\n {name: 'flags_' + n, type: 'USHORT', value: 0}\n ];\n\n for (var i = 0; i < axes.length; ++i) {\n var axisTag = axes[i].tag;\n fields.push({\n name: 'axis_' + n + ' ' + axisTag,\n type: 'FIXED',\n value: inst.coordinates[axisTag] << 16\n });\n }\n\n return fields;\n}\n\nfunction parseFvarInstance(data, start, axes, names) {\n var inst = {};\n var p = new parse.Parser(data, start);\n inst.name = names[p.parseUShort()] || {};\n p.skip('uShort', 1); // reserved for flags; no values defined\n\n inst.coordinates = {};\n for (var i = 0; i < axes.length; ++i) {\n inst.coordinates[axes[i].tag] = p.parseFixed();\n }\n\n return inst;\n}\n\nfunction makeFvarTable(fvar, names) {\n var result = new table.Table('fvar', [\n {name: 'version', type: 'ULONG', value: 0x10000},\n {name: 'offsetToData', type: 'USHORT', value: 0},\n {name: 'countSizePairs', type: 'USHORT', value: 2},\n {name: 'axisCount', type: 'USHORT', value: fvar.axes.length},\n {name: 'axisSize', type: 'USHORT', value: 20},\n {name: 'instanceCount', type: 'USHORT', value: fvar.instances.length},\n {name: 'instanceSize', type: 'USHORT', value: 4 + fvar.axes.length * 4}\n ]);\n result.offsetToData = result.sizeOf();\n\n for (var i = 0; i < fvar.axes.length; i++) {\n result.fields = result.fields.concat(makeFvarAxis(i, fvar.axes[i], names));\n }\n\n for (var j = 0; j < fvar.instances.length; j++) {\n result.fields = result.fields.concat(makeFvarInstance(j, fvar.instances[j], fvar.axes, names));\n }\n\n return result;\n}\n\nfunction parseFvarTable(data, start, names) {\n var p = new parse.Parser(data, start);\n var tableVersion = p.parseULong();\n check.argument(tableVersion === 0x00010000, 'Unsupported fvar table version.');\n var offsetToData = p.parseOffset16();\n // Skip countSizePairs.\n p.skip('uShort', 1);\n var axisCount = p.parseUShort();\n var axisSize = p.parseUShort();\n var instanceCount = p.parseUShort();\n var instanceSize = p.parseUShort();\n\n var axes = [];\n for (var i = 0; i < axisCount; i++) {\n axes.push(parseFvarAxis(data, start + offsetToData + i * axisSize, names));\n }\n\n var instances = [];\n var instanceStart = start + offsetToData + axisCount * axisSize;\n for (var j = 0; j < instanceCount; j++) {\n instances.push(parseFvarInstance(data, instanceStart + j * instanceSize, axes, names));\n }\n\n return {axes: axes, instances: instances};\n}\n\nexports.make = makeFvarTable;\nexports.parse = parseFvarTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/fvar.js\n ** module id = 27\n ** module chunks = 0\n **/","// The `glyf` table describes the glyphs in TrueType outline format.\n// http://www.microsoft.com/typography/otspec/glyf.htm\n\n'use strict';\n\nvar check = require('../check');\nvar glyphset = require('../glyphset');\nvar parse = require('../parse');\nvar path = require('../path');\n\n// Parse the coordinate data for a glyph.\nfunction parseGlyphCoordinate(p, flag, previousValue, shortVectorBitMask, sameBitMask) {\n var v;\n if ((flag & shortVectorBitMask) > 0) {\n // The coordinate is 1 byte long.\n v = p.parseByte();\n // The `same` bit is re-used for short values to signify the sign of the value.\n if ((flag & sameBitMask) === 0) {\n v = -v;\n }\n\n v = previousValue + v;\n } else {\n // The coordinate is 2 bytes long.\n // If the `same` bit is set, the coordinate is the same as the previous coordinate.\n if ((flag & sameBitMask) > 0) {\n v = previousValue;\n } else {\n // Parse the coordinate as a signed 16-bit delta value.\n v = previousValue + p.parseShort();\n }\n }\n\n return v;\n}\n\n// Parse a TrueType glyph.\nfunction parseGlyph(glyph, data, start) {\n var p = new parse.Parser(data, start);\n glyph.numberOfContours = p.parseShort();\n glyph.xMin = p.parseShort();\n glyph.yMin = p.parseShort();\n glyph.xMax = p.parseShort();\n glyph.yMax = p.parseShort();\n var flags;\n var flag;\n if (glyph.numberOfContours > 0) {\n var i;\n // This glyph is not a composite.\n var endPointIndices = glyph.endPointIndices = [];\n for (i = 0; i < glyph.numberOfContours; i += 1) {\n endPointIndices.push(p.parseUShort());\n }\n\n glyph.instructionLength = p.parseUShort();\n glyph.instructions = [];\n for (i = 0; i < glyph.instructionLength; i += 1) {\n glyph.instructions.push(p.parseByte());\n }\n\n var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;\n flags = [];\n for (i = 0; i < numberOfCoordinates; i += 1) {\n flag = p.parseByte();\n flags.push(flag);\n // If bit 3 is set, we repeat this flag n times, where n is the next byte.\n if ((flag & 8) > 0) {\n var repeatCount = p.parseByte();\n for (var j = 0; j < repeatCount; j += 1) {\n flags.push(flag);\n i += 1;\n }\n }\n }\n\n check.argument(flags.length === numberOfCoordinates, 'Bad flags.');\n\n if (endPointIndices.length > 0) {\n var points = [];\n var point;\n // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.\n if (numberOfCoordinates > 0) {\n for (i = 0; i < numberOfCoordinates; i += 1) {\n flag = flags[i];\n point = {};\n point.onCurve = !!(flag & 1);\n point.lastPointOfContour = endPointIndices.indexOf(i) >= 0;\n points.push(point);\n }\n\n var px = 0;\n for (i = 0; i < numberOfCoordinates; i += 1) {\n flag = flags[i];\n point = points[i];\n point.x = parseGlyphCoordinate(p, flag, px, 2, 16);\n px = point.x;\n }\n\n var py = 0;\n for (i = 0; i < numberOfCoordinates; i += 1) {\n flag = flags[i];\n point = points[i];\n point.y = parseGlyphCoordinate(p, flag, py, 4, 32);\n py = point.y;\n }\n }\n\n glyph.points = points;\n } else {\n glyph.points = [];\n }\n } else if (glyph.numberOfContours === 0) {\n glyph.points = [];\n } else {\n glyph.isComposite = true;\n glyph.points = [];\n glyph.components = [];\n var moreComponents = true;\n while (moreComponents) {\n flags = p.parseUShort();\n var component = {\n glyphIndex: p.parseUShort(),\n xScale: 1,\n scale01: 0,\n scale10: 0,\n yScale: 1,\n dx: 0,\n dy: 0\n };\n if ((flags & 1) > 0) {\n // The arguments are words\n component.dx = p.parseShort();\n component.dy = p.parseShort();\n } else {\n // The arguments are bytes\n component.dx = p.parseChar();\n component.dy = p.parseChar();\n }\n\n if ((flags & 8) > 0) {\n // We have a scale\n component.xScale = component.yScale = p.parseF2Dot14();\n } else if ((flags & 64) > 0) {\n // We have an X / Y scale\n component.xScale = p.parseF2Dot14();\n component.yScale = p.parseF2Dot14();\n } else if ((flags & 128) > 0) {\n // We have a 2x2 transformation\n component.xScale = p.parseF2Dot14();\n component.scale01 = p.parseF2Dot14();\n component.scale10 = p.parseF2Dot14();\n component.yScale = p.parseF2Dot14();\n }\n\n glyph.components.push(component);\n moreComponents = !!(flags & 32);\n }\n }\n}\n\n// Transform an array of points and return a new array.\nfunction transformPoints(points, transform) {\n var newPoints = [];\n for (var i = 0; i < points.length; i += 1) {\n var pt = points[i];\n var newPt = {\n x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,\n y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,\n onCurve: pt.onCurve,\n lastPointOfContour: pt.lastPointOfContour\n };\n newPoints.push(newPt);\n }\n\n return newPoints;\n}\n\nfunction getContours(points) {\n var contours = [];\n var currentContour = [];\n for (var i = 0; i < points.length; i += 1) {\n var pt = points[i];\n currentContour.push(pt);\n if (pt.lastPointOfContour) {\n contours.push(currentContour);\n currentContour = [];\n }\n }\n\n check.argument(currentContour.length === 0, 'There are still points left in the current contour.');\n return contours;\n}\n\n// Convert the TrueType glyph outline to a Path.\nfunction getPath(points) {\n var p = new path.Path();\n if (!points) {\n return p;\n }\n\n var contours = getContours(points);\n for (var i = 0; i < contours.length; i += 1) {\n var contour = contours[i];\n var firstPt = contour[0];\n var lastPt = contour[contour.length - 1];\n var curvePt;\n var realFirstPoint;\n if (firstPt.onCurve) {\n curvePt = null;\n // The first point will be consumed by the moveTo command,\n // so skip it in the loop.\n realFirstPoint = true;\n } else {\n if (lastPt.onCurve) {\n // If the first point is off-curve and the last point is on-curve,\n // start at the last point.\n firstPt = lastPt;\n } else {\n // If both first and last points are off-curve, start at their middle.\n firstPt = { x: (firstPt.x + lastPt.x) / 2, y: (firstPt.y + lastPt.y) / 2 };\n }\n\n curvePt = firstPt;\n // The first point is synthesized, so don't skip the real first point.\n realFirstPoint = false;\n }\n\n p.moveTo(firstPt.x, firstPt.y);\n\n for (var j = realFirstPoint ? 1 : 0; j < contour.length; j += 1) {\n var pt = contour[j];\n var prevPt = j === 0 ? firstPt : contour[j - 1];\n if (prevPt.onCurve && pt.onCurve) {\n // This is a straight line.\n p.lineTo(pt.x, pt.y);\n } else if (prevPt.onCurve && !pt.onCurve) {\n curvePt = pt;\n } else if (!prevPt.onCurve && !pt.onCurve) {\n var midPt = { x: (prevPt.x + pt.x) / 2, y: (prevPt.y + pt.y) / 2 };\n p.quadraticCurveTo(prevPt.x, prevPt.y, midPt.x, midPt.y);\n curvePt = pt;\n } else if (!prevPt.onCurve && pt.onCurve) {\n // Previous point off-curve, this point on-curve.\n p.quadraticCurveTo(curvePt.x, curvePt.y, pt.x, pt.y);\n curvePt = null;\n } else {\n throw new Error('Invalid state.');\n }\n }\n\n if (firstPt !== lastPt) {\n // Connect the last and first points\n if (curvePt) {\n p.quadraticCurveTo(curvePt.x, curvePt.y, firstPt.x, firstPt.y);\n } else {\n p.lineTo(firstPt.x, firstPt.y);\n }\n }\n }\n\n p.closePath();\n return p;\n}\n\nfunction buildPath(glyphs, glyph) {\n if (glyph.isComposite) {\n for (var j = 0; j < glyph.components.length; j += 1) {\n var component = glyph.components[j];\n var componentGlyph = glyphs.get(component.glyphIndex);\n // Force the ttfGlyphLoader to parse the glyph.\n componentGlyph.getPath();\n if (componentGlyph.points) {\n var transformedPoints = transformPoints(componentGlyph.points, component);\n glyph.points = glyph.points.concat(transformedPoints);\n }\n }\n }\n\n return getPath(glyph.points);\n}\n\n// Parse all the glyphs according to the offsets from the `loca` table.\nfunction parseGlyfTable(data, start, loca, font) {\n var glyphs = new glyphset.GlyphSet(font);\n var i;\n\n // The last element of the loca table is invalid.\n for (i = 0; i < loca.length - 1; i += 1) {\n var offset = loca[i];\n var nextOffset = loca[i + 1];\n if (offset !== nextOffset) {\n glyphs.push(i, glyphset.ttfGlyphLoader(font, i, parseGlyph, data, start + offset, buildPath));\n } else {\n glyphs.push(i, glyphset.glyphLoader(font, i));\n }\n }\n\n return glyphs;\n}\n\nexports.parse = parseGlyfTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/glyf.js\n ** module id = 28\n ** module chunks = 0\n **/","// The `GPOS` table contains kerning pairs, among other things.\n// https://www.microsoft.com/typography/OTSPEC/gpos.htm\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\n\n// Parse ScriptList and FeatureList tables of GPOS, GSUB, GDEF, BASE, JSTF tables.\n// These lists are unused by now, this function is just the basis for a real parsing.\nfunction parseTaggedListTable(data, start) {\n var p = new parse.Parser(data, start);\n var n = p.parseUShort();\n var list = [];\n for (var i = 0; i < n; i++) {\n list[p.parseTag()] = { offset: p.parseUShort() };\n }\n\n return list;\n}\n\n// Parse a coverage table in a GSUB, GPOS or GDEF table.\n// Format 1 is a simple list of glyph ids,\n// Format 2 is a list of ranges. It is expanded in a list of glyphs, maybe not the best idea.\nfunction parseCoverageTable(data, start) {\n var p = new parse.Parser(data, start);\n var format = p.parseUShort();\n var count = p.parseUShort();\n if (format === 1) {\n return p.parseUShortList(count);\n } else if (format === 2) {\n var coverage = [];\n for (; count--;) {\n var begin = p.parseUShort();\n var end = p.parseUShort();\n var index = p.parseUShort();\n for (var i = begin; i <= end; i++) {\n coverage[index++] = i;\n }\n }\n\n return coverage;\n }\n}\n\n// Parse a Class Definition Table in a GSUB, GPOS or GDEF table.\n// Returns a function that gets a class value from a glyph ID.\nfunction parseClassDefTable(data, start) {\n var p = new parse.Parser(data, start);\n var format = p.parseUShort();\n if (format === 1) {\n // Format 1 specifies a range of consecutive glyph indices, one class per glyph ID.\n var startGlyph = p.parseUShort();\n var glyphCount = p.parseUShort();\n var classes = p.parseUShortList(glyphCount);\n return function(glyphID) {\n return classes[glyphID - startGlyph] || 0;\n };\n } else if (format === 2) {\n // Format 2 defines multiple groups of glyph indices that belong to the same class.\n var rangeCount = p.parseUShort();\n var startGlyphs = [];\n var endGlyphs = [];\n var classValues = [];\n for (var i = 0; i < rangeCount; i++) {\n startGlyphs[i] = p.parseUShort();\n endGlyphs[i] = p.parseUShort();\n classValues[i] = p.parseUShort();\n }\n\n return function(glyphID) {\n var l = 0;\n var r = startGlyphs.length - 1;\n while (l < r) {\n var c = (l + r + 1) >> 1;\n if (glyphID < startGlyphs[c]) {\n r = c - 1;\n } else {\n l = c;\n }\n }\n\n if (startGlyphs[l] <= glyphID && glyphID <= endGlyphs[l]) {\n return classValues[l] || 0;\n }\n\n return 0;\n };\n }\n}\n\n// Parse a pair adjustment positioning subtable, format 1 or format 2\n// The subtable is returned in the form of a lookup function.\nfunction parsePairPosSubTable(data, start) {\n var p = new parse.Parser(data, start);\n // This part is common to format 1 and format 2 subtables\n var format = p.parseUShort();\n var coverageOffset = p.parseUShort();\n var coverage = parseCoverageTable(data, start + coverageOffset);\n // valueFormat 4: XAdvance only, 1: XPlacement only, 0: no ValueRecord for second glyph\n // Only valueFormat1=4 and valueFormat2=0 is supported.\n var valueFormat1 = p.parseUShort();\n var valueFormat2 = p.parseUShort();\n var value1;\n var value2;\n if (valueFormat1 !== 4 || valueFormat2 !== 0) return;\n var sharedPairSets = {};\n if (format === 1) {\n // Pair Positioning Adjustment: Format 1\n var pairSetCount = p.parseUShort();\n var pairSet = [];\n // Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index\n var pairSetOffsets = p.parseOffset16List(pairSetCount);\n for (var firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) {\n var pairSetOffset = pairSetOffsets[firstGlyph];\n var sharedPairSet = sharedPairSets[pairSetOffset];\n if (!sharedPairSet) {\n // Parse a pairset table in a pair adjustment subtable format 1\n sharedPairSet = {};\n p.relativeOffset = pairSetOffset;\n var pairValueCount = p.parseUShort();\n for (; pairValueCount--;) {\n var secondGlyph = p.parseUShort();\n if (valueFormat1) value1 = p.parseShort();\n if (valueFormat2) value2 = p.parseShort();\n // We only support valueFormat1 = 4 and valueFormat2 = 0,\n // so value1 is the XAdvance and value2 is empty.\n sharedPairSet[secondGlyph] = value1;\n }\n }\n\n pairSet[coverage[firstGlyph]] = sharedPairSet;\n }\n\n return function(leftGlyph, rightGlyph) {\n var pairs = pairSet[leftGlyph];\n if (pairs) return pairs[rightGlyph];\n };\n } else if (format === 2) {\n // Pair Positioning Adjustment: Format 2\n var classDef1Offset = p.parseUShort();\n var classDef2Offset = p.parseUShort();\n var class1Count = p.parseUShort();\n var class2Count = p.parseUShort();\n var getClass1 = parseClassDefTable(data, start + classDef1Offset);\n var getClass2 = parseClassDefTable(data, start + classDef2Offset);\n\n // Parse kerning values by class pair.\n var kerningMatrix = [];\n for (var i = 0; i < class1Count; i++) {\n var kerningRow = kerningMatrix[i] = [];\n for (var j = 0; j < class2Count; j++) {\n if (valueFormat1) value1 = p.parseShort();\n if (valueFormat2) value2 = p.parseShort();\n // We only support valueFormat1 = 4 and valueFormat2 = 0,\n // so value1 is the XAdvance and value2 is empty.\n kerningRow[j] = value1;\n }\n }\n\n // Convert coverage list to a hash\n var covered = {};\n for (i = 0; i < coverage.length; i++) covered[coverage[i]] = 1;\n\n // Get the kerning value for a specific glyph pair.\n return function(leftGlyph, rightGlyph) {\n if (!covered[leftGlyph]) return;\n var class1 = getClass1(leftGlyph);\n var class2 = getClass2(rightGlyph);\n var kerningRow = kerningMatrix[class1];\n\n if (kerningRow) {\n return kerningRow[class2];\n }\n };\n }\n}\n\n// Parse a LookupTable (present in of GPOS, GSUB, GDEF, BASE, JSTF tables).\nfunction parseLookupTable(data, start) {\n var p = new parse.Parser(data, start);\n var lookupType = p.parseUShort();\n var lookupFlag = p.parseUShort();\n var useMarkFilteringSet = lookupFlag & 0x10;\n var subTableCount = p.parseUShort();\n var subTableOffsets = p.parseOffset16List(subTableCount);\n var table = {\n lookupType: lookupType,\n lookupFlag: lookupFlag,\n markFilteringSet: useMarkFilteringSet ? p.parseUShort() : -1\n };\n // LookupType 2, Pair adjustment\n if (lookupType === 2) {\n var subtables = [];\n for (var i = 0; i < subTableCount; i++) {\n subtables.push(parsePairPosSubTable(data, start + subTableOffsets[i]));\n }\n // Return a function which finds the kerning values in the subtables.\n table.getKerningValue = function(leftGlyph, rightGlyph) {\n for (var i = subtables.length; i--;) {\n var value = subtables[i](leftGlyph, rightGlyph);\n if (value !== undefined) return value;\n }\n\n return 0;\n };\n }\n\n return table;\n}\n\n// Parse the `GPOS` table which contains, among other things, kerning pairs.\n// https://www.microsoft.com/typography/OTSPEC/gpos.htm\nfunction parseGposTable(data, start, font) {\n var p = new parse.Parser(data, start);\n var tableVersion = p.parseFixed();\n check.argument(tableVersion === 1, 'Unsupported GPOS table version.');\n\n // ScriptList and FeatureList - ignored for now\n parseTaggedListTable(data, start + p.parseUShort());\n // 'kern' is the feature we are looking for.\n parseTaggedListTable(data, start + p.parseUShort());\n\n // LookupList\n var lookupListOffset = p.parseUShort();\n p.relativeOffset = lookupListOffset;\n var lookupCount = p.parseUShort();\n var lookupTableOffsets = p.parseOffset16List(lookupCount);\n var lookupListAbsoluteOffset = start + lookupListOffset;\n for (var i = 0; i < lookupCount; i++) {\n var table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]);\n if (table.lookupType === 2 && !font.getGposKerningValue) font.getGposKerningValue = table.getKerningValue;\n }\n}\n\nexports.parse = parseGposTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/gpos.js\n ** module id = 29\n ** module chunks = 0\n **/","// The `GSUB` table contains ligatures, among other things.\n// https://www.microsoft.com/typography/OTSPEC/gsub.htm\n\n'use strict';\n\nvar check = require('../check');\nvar Parser = require('../parse').Parser;\nvar subtableParsers = new Array(9); // subtableParsers[0] is unused\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS\nsubtableParsers[1] = function parseLookup1() {\n var start = this.offset + this.relativeOffset;\n var substFormat = this.parseUShort();\n if (substFormat === 1) {\n return {\n substFormat: 1,\n coverage: this.parsePointer(Parser.coverage),\n deltaGlyphId: this.parseUShort()\n };\n } else if (substFormat === 2) {\n return {\n substFormat: 2,\n coverage: this.parsePointer(Parser.coverage),\n substitute: this.parseOffset16List()\n };\n }\n check.assert(false, '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.');\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS\nsubtableParsers[2] = function parseLookup2() {\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB Multiple Substitution Subtable identifier-format must be 1');\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n sequences: this.parseListOfLists()\n };\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS\nsubtableParsers[3] = function parseLookup3() {\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB Alternate Substitution Subtable identifier-format must be 1');\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n alternateSets: this.parseListOfLists()\n };\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS\nsubtableParsers[4] = function parseLookup4() {\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB ligature table identifier-format must be 1');\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n ligatureSets: this.parseListOfLists(function() {\n return {\n ligGlyph: this.parseUShort(),\n components: this.parseUShortList(this.parseUShort() - 1)\n };\n })\n };\n};\n\nvar lookupRecordDesc = {\n sequenceIndex: Parser.uShort,\n lookupListIndex: Parser.uShort\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF\nsubtableParsers[5] = function parseLookup5() {\n var start = this.offset + this.relativeOffset;\n var substFormat = this.parseUShort();\n\n if (substFormat === 1) {\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n ruleSets: this.parseListOfLists(function() {\n var glyphCount = this.parseUShort();\n var substCount = this.parseUShort();\n return {\n input: this.parseUShortList(glyphCount - 1),\n lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)\n };\n })\n };\n } else if (substFormat === 2) {\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n classDef: this.parsePointer(Parser.classDef),\n classSets: this.parseListOfLists(function() {\n var glyphCount = this.parseUShort();\n var substCount = this.parseUShort();\n return {\n classes: this.parseUShortList(glyphCount - 1),\n lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)\n };\n })\n };\n } else if (substFormat === 3) {\n var glyphCount = this.parseUShort();\n var substCount = this.parseUShort();\n return {\n substFormat: substFormat,\n coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)),\n lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)\n };\n }\n check.assert(false, '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.');\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC\nsubtableParsers[6] = function parseLookup6() {\n // TODO add automated tests for lookup 6 : no examples in the MS doc.\n var start = this.offset + this.relativeOffset;\n var substFormat = this.parseUShort();\n if (substFormat === 1) {\n return {\n substFormat: 1,\n coverage: this.parsePointer(Parser.coverage),\n chainRuleSets: this.parseListOfLists(function() {\n return {\n backtrack: this.parseUShortList(),\n input: this.parseUShortList(this.parseShort() - 1),\n lookahead: this.parseUShortList(),\n lookupRecords: this.parseRecordList(lookupRecordDesc)\n };\n })\n };\n } else if (substFormat === 2) {\n return {\n substFormat: 2,\n coverage: this.parsePointer(Parser.coverage),\n backtrackClassDef: this.parsePointer(Parser.classDef),\n inputClassDef: this.parsePointer(Parser.classDef),\n lookaheadClassDef: this.parsePointer(Parser.classDef),\n chainClassSet: this.parseListOfLists(function() {\n return {\n backtrack: this.parseUShortList(),\n input: this.parseUShortList(this.parseShort() - 1),\n lookahead: this.parseUShortList(),\n lookupRecords: this.parseRecordList(lookupRecordDesc)\n };\n })\n };\n } else if (substFormat === 3) {\n return {\n substFormat: 3,\n backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n inputCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n lookupRecords: this.parseRecordList(lookupRecordDesc)\n };\n }\n check.assert(false, '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.');\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES\nsubtableParsers[7] = function parseLookup7() {\n // Extension Substitution subtable\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB Extension Substitution subtable identifier-format must be 1');\n var extensionLookupType = this.parseUShort();\n var extensionParser = new Parser(this.data, this.offset + this.parseULong());\n return {\n substFormat: 1,\n lookupType: extensionLookupType,\n extension: subtableParsers[extensionLookupType].call(extensionParser)\n };\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS\nsubtableParsers[8] = function parseLookup8() {\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1');\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n substitutes: this.parseUShortList()\n };\n};\n\n// https://www.microsoft.com/typography/OTSPEC/gsub.htm\nfunction parseGsubTable(data, start) {\n start = start || 0;\n var p = new Parser(data, start);\n var tableVersion = p.parseVersion();\n check.argument(tableVersion === 1, 'Unsupported GSUB table version.');\n return {\n version: tableVersion,\n scripts: p.parseScriptList(),\n features: p.parseFeatureList(),\n lookups: p.parseLookupList(subtableParsers)\n };\n}\n\nexports.parse = parseGsubTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/gsub.js\n ** module id = 30\n ** module chunks = 0\n **/","// The `kern` table contains kerning pairs.\n// Note that some fonts use the GPOS OpenType layout table to specify kerning.\n// https://www.microsoft.com/typography/OTSPEC/kern.htm\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\n\n// Parse the `kern` table which contains kerning pairs.\nfunction parseKernTable(data, start) {\n var pairs = {};\n var p = new parse.Parser(data, start);\n var tableVersion = p.parseUShort();\n check.argument(tableVersion === 0, 'Unsupported kern table version.');\n // Skip nTables.\n p.skip('uShort', 1);\n var subTableVersion = p.parseUShort();\n check.argument(subTableVersion === 0, 'Unsupported kern sub-table version.');\n // Skip subTableLength, subTableCoverage\n p.skip('uShort', 2);\n var nPairs = p.parseUShort();\n // Skip searchRange, entrySelector, rangeShift.\n p.skip('uShort', 3);\n for (var i = 0; i < nPairs; i += 1) {\n var leftIndex = p.parseUShort();\n var rightIndex = p.parseUShort();\n var value = p.parseShort();\n pairs[leftIndex + ',' + rightIndex] = value;\n }\n\n return pairs;\n}\n\nexports.parse = parseKernTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/kern.js\n ** module id = 31\n ** module chunks = 0\n **/","// The `loca` table stores the offsets to the locations of the glyphs in the font.\n// https://www.microsoft.com/typography/OTSPEC/loca.htm\n\n'use strict';\n\nvar parse = require('../parse');\n\n// Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font,\n// relative to the beginning of the glyphData table.\n// The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs)\n// The loca table has two versions: a short version where offsets are stored as uShorts, and a long\n// version where offsets are stored as uLongs. The `head` table specifies which version to use\n// (under indexToLocFormat).\nfunction parseLocaTable(data, start, numGlyphs, shortVersion) {\n var p = new parse.Parser(data, start);\n var parseFn = shortVersion ? p.parseUShort : p.parseULong;\n // There is an extra entry after the last index element to compute the length of the last glyph.\n // That's why we use numGlyphs + 1.\n var glyphOffsets = [];\n for (var i = 0; i < numGlyphs + 1; i += 1) {\n var glyphOffset = parseFn.call(p);\n if (shortVersion) {\n // The short table version stores the actual offset divided by 2.\n glyphOffset *= 2;\n }\n\n glyphOffsets.push(glyphOffset);\n }\n\n return glyphOffsets;\n}\n\nexports.parse = parseLocaTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/loca.js\n ** module id = 32\n ** module chunks = 0\n **/","/*!\n * Paper.js v0.10.2-develop - The Swiss Army Knife of Vector Graphics Scripting.\n * http://paperjs.org/\n *\n * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey\n * http://scratchdisk.com/ & http://jonathanpuckey.com/\n *\n * Distributed under the MIT license. See LICENSE file for details.\n *\n * All rights reserved.\n *\n * Date: Sat Jul 23 18:50:58 2016 +0200\n *\n ***\n *\n * Straps.js - Class inheritance library with support for bean-style accessors\n *\n * Copyright (c) 2006 - 2016 Juerg Lehni\n * http://scratchdisk.com/\n *\n * Distributed under the MIT license.\n *\n ***\n *\n * Acorn.js\n * http://marijnhaverbeke.nl/acorn/\n *\n * Acorn is a tiny, fast JavaScript parser written in JavaScript,\n * created by Marijn Haverbeke and released under an MIT license.\n *\n */\n\nvar paper = function(self, undefined) {\n\nself = self || require('./node/window.js');\n\nvar window = self.window,\n\tdocument = self.document;\n\nvar Base = new function() {\n\tvar hidden = /^(statics|enumerable|beans|preserve)$/,\n\t\tarray = [],\n\t\tslice = array.slice,\n\t\tcreate = Object.create,\n\t\tdescribe = Object.getOwnPropertyDescriptor,\n\t\tdefine = Object.defineProperty,\n\n\t\tforEach = array.forEach || function(iter, bind) {\n\t\t\tfor (var i = 0, l = this.length; i < l; i++) {\n\t\t\t\titer.call(bind, this[i], i, this);\n\t\t\t}\n\t\t},\n\n\t\tforIn = function(iter, bind) {\n\t\t\tfor (var i in this) {\n\t\t\t\tif (this.hasOwnProperty(i))\n\t\t\t\t\titer.call(bind, this[i], i, this);\n\t\t\t}\n\t\t},\n\n\t\tset = Object.assign || function(dst) {\n\t\t\tfor (var i = 1, l = arguments.length; i < l; i++) {\n\t\t\t\tvar src = arguments[i];\n\t\t\t\tfor (var key in src) {\n\t\t\t\t\tif (src.hasOwnProperty(key))\n\t\t\t\t\t\tdst[key] = src[key];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn dst;\n\t\t},\n\n\t\teach = function(obj, iter, bind) {\n\t\t\tif (obj) {\n\t\t\t\tvar desc = describe(obj, 'length');\n\t\t\t\t(desc && typeof desc.value === 'number' ? forEach : forIn)\n\t\t\t\t\t.call(obj, iter, bind = bind || obj);\n\t\t\t}\n\t\t\treturn bind;\n\t\t};\n\n\tfunction inject(dest, src, enumerable, beans, preserve) {\n\t\tvar beansNames = {};\n\n\t\tfunction field(name, val) {\n\t\t\tval = val || (val = describe(src, name))\n\t\t\t\t\t&& (val.get ? val : val.value);\n\t\t\tif (typeof val === 'string' && val[0] === '#')\n\t\t\t\tval = dest[val.substring(1)] || val;\n\t\t\tvar isFunc = typeof val === 'function',\n\t\t\t\tres = val,\n\t\t\t\tprev = preserve || isFunc && !val.base\n\t\t\t\t\t\t? (val && val.get ? name in dest : dest[name])\n\t\t\t\t\t\t: null,\n\t\t\t\tbean;\n\t\t\tif (!preserve || !prev) {\n\t\t\t\tif (isFunc && prev)\n\t\t\t\t\tval.base = prev;\n\t\t\t\tif (isFunc && beans !== false\n\t\t\t\t\t\t&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))\n\t\t\t\t\tbeansNames[bean[3].toLowerCase() + bean[4]] = bean[2];\n\t\t\t\tif (!res || isFunc || !res.get || typeof res.get !== 'function'\n\t\t\t\t\t\t|| !Base.isPlainObject(res))\n\t\t\t\t\tres = { value: res, writable: true };\n\t\t\t\tif ((describe(dest, name)\n\t\t\t\t\t\t|| { configurable: true }).configurable) {\n\t\t\t\t\tres.configurable = true;\n\t\t\t\t\tres.enumerable = enumerable;\n\t\t\t\t}\n\t\t\t\tdefine(dest, name, res);\n\t\t\t}\n\t\t}\n\t\tif (src) {\n\t\t\tfor (var name in src) {\n\t\t\t\tif (src.hasOwnProperty(name) && !hidden.test(name))\n\t\t\t\t\tfield(name);\n\t\t\t}\n\t\t\tfor (var name in beansNames) {\n\t\t\t\tvar part = beansNames[name],\n\t\t\t\t\tset = dest['set' + part],\n\t\t\t\t\tget = dest['get' + part] || set && dest['is' + part];\n\t\t\t\tif (get && (beans === true || get.length === 0))\n\t\t\t\t\tfield(name, { get: get, set: set });\n\t\t\t}\n\t\t}\n\t\treturn dest;\n\t}\n\n\tfunction Base() {\n\t\tfor (var i = 0, l = arguments.length; i < l; i++) {\n\t\t\tvar src = arguments[i];\n\t\t\tif (src)\n\t\t\t\tset(this, src);\n\t\t}\n\t\treturn this;\n\t}\n\n\treturn inject(Base, {\n\t\tinject: function(src) {\n\t\t\tif (src) {\n\t\t\t\tvar statics = src.statics === true ? src : src.statics,\n\t\t\t\t\tbeans = src.beans,\n\t\t\t\t\tpreserve = src.preserve;\n\t\t\t\tif (statics !== src)\n\t\t\t\t\tinject(this.prototype, src, src.enumerable, beans, preserve);\n\t\t\t\tinject(this, statics, true, beans, preserve);\n\t\t\t}\n\t\t\tfor (var i = 1, l = arguments.length; i < l; i++)\n\t\t\t\tthis.inject(arguments[i]);\n\t\t\treturn this;\n\t\t},\n\n\t\textend: function() {\n\t\t\tvar base = this,\n\t\t\t\tctor,\n\t\t\t\tproto;\n\t\t\tfor (var i = 0, obj, l = arguments.length;\n\t\t\t\t\ti < l && !(ctor && proto); i++) {\n\t\t\t\tobj = arguments[i];\n\t\t\t\tctor = ctor || obj.initialize;\n\t\t\t\tproto = proto || obj.prototype;\n\t\t\t}\n\t\t\tctor = ctor || function() {\n\t\t\t\tbase.apply(this, arguments);\n\t\t\t};\n\t\t\tproto = ctor.prototype = proto || create(this.prototype);\n\t\t\tdefine(proto, 'constructor',\n\t\t\t\t\t{ value: ctor, writable: true, configurable: true });\n\t\t\tinject(ctor, this, true);\n\t\t\tif (arguments.length)\n\t\t\t\tthis.inject.apply(ctor, arguments);\n\t\t\tctor.base = base;\n\t\t\treturn ctor;\n\t\t}\n\t}, true).inject({\n\t\tinitialize: Base,\n\n\t\tset: Base,\n\n\t\tinject: function() {\n\t\t\tfor (var i = 0, l = arguments.length; i < l; i++) {\n\t\t\t\tvar src = arguments[i];\n\t\t\t\tif (src) {\n\t\t\t\t\tinject(this, src, src.enumerable, src.beans, src.preserve);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\textend: function() {\n\t\t\tvar res = create(this);\n\t\t\treturn res.inject.apply(res, arguments);\n\t\t},\n\n\t\teach: function(iter, bind) {\n\t\t\treturn each(this, iter, bind);\n\t\t},\n\n\t\tclone: function() {\n\t\t\treturn new this.constructor(this);\n\t\t},\n\n\t\tstatics: {\n\t\t\tset: set,\n\t\t\teach: each,\n\t\t\tcreate: create,\n\t\t\tdefine: define,\n\t\t\tdescribe: describe,\n\n\t\t\tclone: function(obj) {\n\t\t\t\treturn set(new obj.constructor(), obj);\n\t\t\t},\n\n\t\t\tisPlainObject: function(obj) {\n\t\t\t\tvar ctor = obj != null && obj.constructor;\n\t\t\t\treturn ctor && (ctor === Object || ctor === Base\n\t\t\t\t\t\t|| ctor.name === 'Object');\n\t\t\t},\n\n\t\t\tpick: function(a, b) {\n\t\t\t\treturn a !== undefined ? a : b;\n\t\t\t},\n\n\t\t\tslice: function(list, begin, end) {\n\t\t\t\treturn slice.call(list, begin, end);\n\t\t\t}\n\t\t}\n\t});\n};\n\nif (typeof module !== 'undefined')\n\tmodule.exports = Base;\n\nBase.inject({\n\ttoString: function() {\n\t\treturn this._id != null\n\t\t\t? (this._class || 'Object') + (this._name\n\t\t\t\t? \" '\" + this._name + \"'\"\n\t\t\t\t: ' @' + this._id)\n\t\t\t: '{ ' + Base.each(this, function(value, key) {\n\t\t\t\tif (!/^_/.test(key)) {\n\t\t\t\t\tvar type = typeof value;\n\t\t\t\t\tthis.push(key + ': ' + (type === 'number'\n\t\t\t\t\t\t\t? Formatter.instance.number(value)\n\t\t\t\t\t\t\t: type === 'string' ? \"'\" + value + \"'\" : value));\n\t\t\t\t}\n\t\t\t}, []).join(', ') + ' }';\n\t},\n\n\tgetClassName: function() {\n\t\treturn this._class || '';\n\t},\n\n\timportJSON: function(json) {\n\t\treturn Base.importJSON(json, this);\n\t},\n\n\texportJSON: function(options) {\n\t\treturn Base.exportJSON(this, options);\n\t},\n\n\ttoJSON: function() {\n\t\treturn Base.serialize(this);\n\t},\n\n\t_set: function(props) {\n\t\tif (props && Base.isPlainObject(props))\n\t\t\treturn Base.filter(this, props);\n\t},\n\n\tstatics: {\n\n\t\texports: {\n\t\t\tenumerable: true\n\t\t},\n\n\t\textend: function extend() {\n\t\t\tvar res = extend.base.apply(this, arguments),\n\t\t\t\tname = res.prototype._class;\n\t\t\tif (name && !Base.exports[name])\n\t\t\t\tBase.exports[name] = res;\n\t\t\treturn res;\n\t\t},\n\n\t\tequals: function(obj1, obj2) {\n\t\t\tif (obj1 === obj2)\n\t\t\t\treturn true;\n\t\t\tif (obj1 && obj1.equals)\n\t\t\t\treturn obj1.equals(obj2);\n\t\t\tif (obj2 && obj2.equals)\n\t\t\t\treturn obj2.equals(obj1);\n\t\t\tif (obj1 && obj2\n\t\t\t\t\t&& typeof obj1 === 'object' && typeof obj2 === 'object') {\n\t\t\t\tif (Array.isArray(obj1) && Array.isArray(obj2)) {\n\t\t\t\t\tvar length = obj1.length;\n\t\t\t\t\tif (length !== obj2.length)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\twhile (length--) {\n\t\t\t\t\t\tif (!Base.equals(obj1[length], obj2[length]))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvar keys = Object.keys(obj1),\n\t\t\t\t\t\tlength = keys.length;\n\t\t\t\t\tif (length !== Object.keys(obj2).length)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\twhile (length--) {\n\t\t\t\t\t\tvar key = keys[length];\n\t\t\t\t\t\tif (!(obj2.hasOwnProperty(key)\n\t\t\t\t\t\t\t\t&& Base.equals(obj1[key], obj2[key])))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\n\t\tread: function(list, start, options, amount) {\n\t\t\tif (this === Base) {\n\t\t\t\tvar value = this.peek(list, start);\n\t\t\t\tlist.__index++;\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\tvar proto = this.prototype,\n\t\t\t\treadIndex = proto._readIndex,\n\t\t\t\tbegin = start || readIndex && list.__index || 0,\n\t\t\t\tlength = list.length,\n\t\t\t\tobj = list[begin];\n\t\t\tamount = amount || length - begin;\n\t\t\tif (obj instanceof this\n\t\t\t\t|| options && options.readNull && obj == null && amount <= 1) {\n\t\t\t\tif (readIndex)\n\t\t\t\t\tlist.__index = begin + 1;\n\t\t\t\treturn obj && options && options.clone ? obj.clone() : obj;\n\t\t\t}\n\t\t\tobj = Base.create(this.prototype);\n\t\t\tif (readIndex)\n\t\t\t\tobj.__read = true;\n\t\t\tobj = obj.initialize.apply(obj, begin > 0 || begin + amount < length\n\t\t\t\t\t? Base.slice(list, begin, begin + amount)\n\t\t\t\t\t: list) || obj;\n\t\t\tif (readIndex) {\n\t\t\t\tlist.__index = begin + obj.__read;\n\t\t\t\tobj.__read = undefined;\n\t\t\t}\n\t\t\treturn obj;\n\t\t},\n\n\t\tpeek: function(list, start) {\n\t\t\treturn list[list.__index = start || list.__index || 0];\n\t\t},\n\n\t\tremain: function(list) {\n\t\t\treturn list.length - (list.__index || 0);\n\t\t},\n\n\t\treadList: function(list, start, options, amount) {\n\t\t\tvar res = [],\n\t\t\t\tentry,\n\t\t\t\tbegin = start || 0,\n\t\t\t\tend = amount ? begin + amount : list.length;\n\t\t\tfor (var i = begin; i < end; i++) {\n\t\t\t\tres.push(Array.isArray(entry = list[i])\n\t\t\t\t\t\t? this.read(entry, 0, options)\n\t\t\t\t\t\t: this.read(list, i, options, 1));\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\n\t\treadNamed: function(list, name, start, options, amount) {\n\t\t\tvar value = this.getNamed(list, name),\n\t\t\t\thasObject = value !== undefined;\n\t\t\tif (hasObject) {\n\t\t\t\tvar filtered = list._filtered;\n\t\t\t\tif (!filtered) {\n\t\t\t\t\tfiltered = list._filtered = Base.create(list[0]);\n\t\t\t\t\tfiltered._filtering = list[0];\n\t\t\t\t}\n\t\t\t\tfiltered[name] = undefined;\n\t\t\t}\n\t\t\treturn this.read(hasObject ? [value] : list, start, options, amount);\n\t\t},\n\n\t\tgetNamed: function(list, name) {\n\t\t\tvar arg = list[0];\n\t\t\tif (list._hasObject === undefined)\n\t\t\t\tlist._hasObject = list.length === 1 && Base.isPlainObject(arg);\n\t\t\tif (list._hasObject)\n\t\t\t\treturn name ? arg[name] : list._filtered || arg;\n\t\t},\n\n\t\thasNamed: function(list, name) {\n\t\t\treturn !!this.getNamed(list, name);\n\t\t},\n\n\t\tfilter: function(dest, source, exclude) {\n\t\t\tvar keys = Object.keys(source._filtering || source);\n\t\t\tfor (var i = 0, l = keys.length; i < l; i++) {\n\t\t\t\tvar key = keys[i];\n\t\t\t\tif (!(exclude && exclude[key])) {\n\t\t\t\t\tvar value = source[key];\n\t\t\t\t\tif (value !== undefined)\n\t\t\t\t\t\tdest[key] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn dest;\n\t\t},\n\n\t\tisPlainValue: function(obj, asString) {\n\t\t\treturn this.isPlainObject(obj) || Array.isArray(obj)\n\t\t\t\t\t|| asString && typeof obj === 'string';\n\t\t},\n\n\t\tserialize: function(obj, options, compact, dictionary) {\n\t\t\toptions = options || {};\n\n\t\t\tvar isRoot = !dictionary,\n\t\t\t\tres;\n\t\t\tif (isRoot) {\n\t\t\t\toptions.formatter = new Formatter(options.precision);\n\t\t\t\tdictionary = {\n\t\t\t\t\tlength: 0,\n\t\t\t\t\tdefinitions: {},\n\t\t\t\t\treferences: {},\n\t\t\t\t\tadd: function(item, create) {\n\t\t\t\t\t\tvar id = '#' + item._id,\n\t\t\t\t\t\t\tref = this.references[id];\n\t\t\t\t\t\tif (!ref) {\n\t\t\t\t\t\t\tthis.length++;\n\t\t\t\t\t\t\tvar res = create.call(item),\n\t\t\t\t\t\t\t\tname = item._class;\n\t\t\t\t\t\t\tif (name && res[0] !== name)\n\t\t\t\t\t\t\t\tres.unshift(name);\n\t\t\t\t\t\t\tthis.definitions[id] = res;\n\t\t\t\t\t\t\tref = this.references[id] = [id];\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn ref;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (obj && obj._serialize) {\n\t\t\t\tres = obj._serialize(options, dictionary);\n\t\t\t\tvar name = obj._class;\n\t\t\t\tif (name && !obj._compactSerialize && (isRoot || !compact)\n\t\t\t\t\t\t&& res[0] !== name) {\n\t\t\t\t\tres.unshift(name);\n\t\t\t\t}\n\t\t\t} else if (Array.isArray(obj)) {\n\t\t\t\tres = [];\n\t\t\t\tfor (var i = 0, l = obj.length; i < l; i++)\n\t\t\t\t\tres[i] = Base.serialize(obj[i], options, compact,\n\t\t\t\t\t\t\tdictionary);\n\t\t\t} else if (Base.isPlainObject(obj)) {\n\t\t\t\tres = {};\n\t\t\t\tvar keys = Object.keys(obj);\n\t\t\t\tfor (var i = 0, l = keys.length; i < l; i++) {\n\t\t\t\t\tvar key = keys[i];\n\t\t\t\t\tres[key] = Base.serialize(obj[key], options, compact,\n\t\t\t\t\t\t\tdictionary);\n\t\t\t\t}\n\t\t\t} else if (typeof obj === 'number') {\n\t\t\t\tres = options.formatter.number(obj, options.precision);\n\t\t\t} else {\n\t\t\t\tres = obj;\n\t\t\t}\n\t\t\treturn isRoot && dictionary.length > 0\n\t\t\t\t\t? [['dictionary', dictionary.definitions], res]\n\t\t\t\t\t: res;\n\t\t},\n\n\t\tdeserialize: function(json, create, _data, _setDictionary, _isRoot) {\n\t\t\tvar res = json,\n\t\t\t\tisFirst = !_data,\n\t\t\t\thasDictionary = isFirst && json && json.length\n\t\t\t\t\t&& json[0][0] === 'dictionary';\n\t\t\t_data = _data || {};\n\t\t\tif (Array.isArray(json)) {\n\t\t\t\tvar type = json[0],\n\t\t\t\t\tisDictionary = type === 'dictionary';\n\t\t\t\tif (json.length == 1 && /^#/.test(type)) {\n\t\t\t\t\treturn _data.dictionary[type];\n\t\t\t\t}\n\t\t\t\ttype = Base.exports[type];\n\t\t\t\tres = [];\n\t\t\t\tfor (var i = type ? 1 : 0, l = json.length; i < l; i++) {\n\t\t\t\t\tres.push(Base.deserialize(json[i], create, _data,\n\t\t\t\t\t\t\tisDictionary, hasDictionary));\n\t\t\t\t}\n\t\t\t\tif (type) {\n\t\t\t\t\tvar args = res;\n\t\t\t\t\tif (create) {\n\t\t\t\t\t\tres = create(type, args, isFirst || _isRoot);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres = Base.create(type.prototype);\n\t\t\t\t\t\ttype.apply(res, args);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (Base.isPlainObject(json)) {\n\t\t\t\tres = {};\n\t\t\t\tif (_setDictionary)\n\t\t\t\t\t_data.dictionary = res;\n\t\t\t\tfor (var key in json)\n\t\t\t\t\tres[key] = Base.deserialize(json[key], create, _data);\n\t\t\t}\n\t\t\treturn hasDictionary ? res[1] : res;\n\t\t},\n\n\t\texportJSON: function(obj, options) {\n\t\t\tvar json = Base.serialize(obj, options);\n\t\t\treturn options && options.asString === false\n\t\t\t\t\t? json\n\t\t\t\t\t: JSON.stringify(json);\n\t\t},\n\n\t\timportJSON: function(json, target) {\n\t\t\treturn Base.deserialize(\n\t\t\t\t\ttypeof json === 'string' ? JSON.parse(json) : json,\n\t\t\t\t\tfunction(ctor, args, isRoot) {\n\t\t\t\t\t\tvar useTarget = isRoot && target\n\t\t\t\t\t\t\t\t&& target.constructor === ctor,\n\t\t\t\t\t\t\tobj = useTarget ? target\n\t\t\t\t\t\t\t\t: Base.create(ctor.prototype);\n\t\t\t\t\t\tif (args.length === 1 && obj instanceof Item\n\t\t\t\t\t\t\t\t&& (useTarget || !(obj instanceof Layer))) {\n\t\t\t\t\t\t\tvar arg = args[0];\n\t\t\t\t\t\t\tif (Base.isPlainObject(arg))\n\t\t\t\t\t\t\t\targ.insert = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t(useTarget ? obj.set : ctor).apply(obj, args);\n\t\t\t\t\t\tif (useTarget)\n\t\t\t\t\t\t\ttarget = null;\n\t\t\t\t\t\treturn obj;\n\t\t\t\t\t});\n\t\t},\n\n\t\tsplice: function(list, items, index, remove) {\n\t\t\tvar amount = items && items.length,\n\t\t\t\tappend = index === undefined;\n\t\t\tindex = append ? list.length : index;\n\t\t\tif (index > list.length)\n\t\t\t\tindex = list.length;\n\t\t\tfor (var i = 0; i < amount; i++)\n\t\t\t\titems[i]._index = index + i;\n\t\t\tif (append) {\n\t\t\t\tlist.push.apply(list, items);\n\t\t\t\treturn [];\n\t\t\t} else {\n\t\t\t\tvar args = [index, remove];\n\t\t\t\tif (items)\n\t\t\t\t\targs.push.apply(args, items);\n\t\t\t\tvar removed = list.splice.apply(list, args);\n\t\t\t\tfor (var i = 0, l = removed.length; i < l; i++)\n\t\t\t\t\tremoved[i]._index = undefined;\n\t\t\t\tfor (var i = index + amount, l = list.length; i < l; i++)\n\t\t\t\t\tlist[i]._index = i;\n\t\t\t\treturn removed;\n\t\t\t}\n\t\t},\n\n\t\tcapitalize: function(str) {\n\t\t\treturn str.replace(/\\b[a-z]/g, function(match) {\n\t\t\t\treturn match.toUpperCase();\n\t\t\t});\n\t\t},\n\n\t\tcamelize: function(str) {\n\t\t\treturn str.replace(/-(.)/g, function(all, chr) {\n\t\t\t\treturn chr.toUpperCase();\n\t\t\t});\n\t\t},\n\n\t\thyphenate: function(str) {\n\t\t\treturn str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n\t\t}\n\t}\n});\n\nvar Emitter = {\n\ton: function(type, func) {\n\t\tif (typeof type !== 'string') {\n\t\t\tBase.each(type, function(value, key) {\n\t\t\t\tthis.on(key, value);\n\t\t\t}, this);\n\t\t} else {\n\t\t\tvar types = this._eventTypes,\n\t\t\t\tentry = types && types[type],\n\t\t\t\thandlers = this._callbacks = this._callbacks || {};\n\t\t\thandlers = handlers[type] = handlers[type] || [];\n\t\t\tif (handlers.indexOf(func) === -1) {\n\t\t\t\thandlers.push(func);\n\t\t\t\tif (entry && entry.install && handlers.length === 1)\n\t\t\t\t\tentry.install.call(this, type);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\toff: function(type, func) {\n\t\tif (typeof type !== 'string') {\n\t\t\tBase.each(type, function(value, key) {\n\t\t\t\tthis.off(key, value);\n\t\t\t}, this);\n\t\t\treturn;\n\t\t}\n\t\tvar types = this._eventTypes,\n\t\t\tentry = types && types[type],\n\t\t\thandlers = this._callbacks && this._callbacks[type],\n\t\t\tindex;\n\t\tif (handlers) {\n\t\t\tif (!func || (index = handlers.indexOf(func)) !== -1\n\t\t\t\t\t&& handlers.length === 1) {\n\t\t\t\tif (entry && entry.uninstall)\n\t\t\t\t\tentry.uninstall.call(this, type);\n\t\t\t\tdelete this._callbacks[type];\n\t\t\t} else if (index !== -1) {\n\t\t\t\thandlers.splice(index, 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\tonce: function(type, func) {\n\t\treturn this.on(type, function() {\n\t\t\tfunc.apply(this, arguments);\n\t\t\tthis.off(type, func);\n\t\t});\n\t},\n\n\temit: function(type, event) {\n\t\tvar handlers = this._callbacks && this._callbacks[type];\n\t\tif (!handlers)\n\t\t\treturn false;\n\t\tvar args = Base.slice(arguments, 1),\n\t\t\tsetTarget = event && event.target && !event.currentTarget;\n\t\thandlers = handlers.slice();\n\t\tif (setTarget)\n\t\t\tevent.currentTarget = this;\n\t\tfor (var i = 0, l = handlers.length; i < l; i++) {\n\t\t\tif (handlers[i].apply(this, args) === false) {\n\t\t\t\tif (event && event.stop)\n\t\t\t\t\tevent.stop();\n\t\t\t\tbreak;\n\t\t }\n\t\t}\n\t\tif (setTarget)\n\t\t\tdelete event.currentTarget;\n\t\treturn true;\n\t},\n\n\tresponds: function(type) {\n\t\treturn !!(this._callbacks && this._callbacks[type]);\n\t},\n\n\tattach: '#on',\n\tdetach: '#off',\n\tfire: '#emit',\n\n\t_installEvents: function(install) {\n\t\tvar types = this._eventTypes,\n\t\t\thandlers = this._callbacks,\n\t\t\tkey = install ? 'install' : 'uninstall';\n\t\tif (types) {\n\t\t\tfor (var type in handlers) {\n\t\t\t\tif (handlers[type].length > 0) {\n\t\t\t\t\tvar entry = types[type],\n\t\t\t\t\t\tfunc = entry && entry[key];\n\t\t\t\t\tif (func)\n\t\t\t\t\t\tfunc.call(this, type);\n\t\t\t\t}\n\t\t}\n\t\t}\n\t},\n\n\tstatics: {\n\t\tinject: function inject(src) {\n\t\t\tvar events = src._events;\n\t\t\tif (events) {\n\t\t\t\tvar types = {};\n\t\t\t\tBase.each(events, function(entry, key) {\n\t\t\t\t\tvar isString = typeof entry === 'string',\n\t\t\t\t\t\tname = isString ? entry : key,\n\t\t\t\t\t\tpart = Base.capitalize(name),\n\t\t\t\t\t\ttype = name.substring(2).toLowerCase();\n\t\t\t\t\ttypes[type] = isString ? {} : entry;\n\t\t\t\t\tname = '_' + name;\n\t\t\t\t\tsrc['get' + part] = function() {\n\t\t\t\t\t\treturn this[name];\n\t\t\t\t\t};\n\t\t\t\t\tsrc['set' + part] = function(func) {\n\t\t\t\t\t\tvar prev = this[name];\n\t\t\t\t\t\tif (prev)\n\t\t\t\t\t\t\tthis.off(type, prev);\n\t\t\t\t\t\tif (func)\n\t\t\t\t\t\t\tthis.on(type, func);\n\t\t\t\t\t\tthis[name] = func;\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t\tsrc._eventTypes = types;\n\t\t\t}\n\t\t\treturn inject.base.apply(this, arguments);\n\t\t}\n\t}\n};\n\nvar PaperScope = Base.extend({\n\t_class: 'PaperScope',\n\n\tinitialize: function PaperScope() {\n\t\tpaper = this;\n\t\tthis.settings = new Base({\n\t\t\tapplyMatrix: true,\n\t\t\tinsertItems: true,\n\t\t\thandleSize: 4,\n\t\t\thitTolerance: 0\n\t\t});\n\t\tthis.project = null;\n\t\tthis.projects = [];\n\t\tthis.tools = [];\n\t\tthis.palettes = [];\n\t\tthis._id = PaperScope._id++;\n\t\tPaperScope._scopes[this._id] = this;\n\t\tvar proto = PaperScope.prototype;\n\t\tif (!this.support) {\n\t\t\tvar ctx = CanvasProvider.getContext(1, 1) || {};\n\t\t\tproto.support = {\n\t\t\t\tnativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,\n\t\t\t\tnativeBlendModes: BlendMode.nativeModes\n\t\t\t};\n\t\t\tCanvasProvider.release(ctx);\n\t\t}\n\t\tif (!this.agent) {\n\t\t\tvar user = self.navigator.userAgent.toLowerCase(),\n\t\t\t\tos = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],\n\t\t\t\tplatform = os === 'darwin' ? 'mac' : os,\n\t\t\t\tagent = proto.agent = proto.browser = { platform: platform };\n\t\t\tif (platform)\n\t\t\t\tagent[platform] = true;\n\t\t\tuser.replace(\n\t\t\t\t/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\\/?\\s*([.\\d]+)(?:.*version\\/([.\\d]+))?(?:.*rv\\:v?([.\\d]+))?/g,\n\t\t\t\tfunction(all, n, v1, v2, rv) {\n\t\t\t\t\tif (!agent.chrome) {\n\t\t\t\t\t\tvar v = n === 'opera' ? v2 :\n\t\t\t\t\t\t\t\t/^(node|trident)$/.test(n) ? rv : v1;\n\t\t\t\t\t\tagent.version = v;\n\t\t\t\t\t\tagent.versionNumber = parseFloat(v);\n\t\t\t\t\t\tn = n === 'trident' ? 'msie' : n;\n\t\t\t\t\t\tagent.name = n;\n\t\t\t\t\t\tagent[n] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t\tif (agent.chrome)\n\t\t\t\tdelete agent.webkit;\n\t\t\tif (agent.atom)\n\t\t\t\tdelete agent.chrome;\n\t\t}\n\t},\n\n\tversion: \"0.10.2-develop\",\n\n\tgetView: function() {\n\t\tvar project = this.project;\n\t\treturn project && project._view;\n\t},\n\n\tgetPaper: function() {\n\t\treturn this;\n\t},\n\n\texecute: function(code, options) {\n\t\tpaper.PaperScript.execute(code, this, options);\n\t\tView.updateFocus();\n\t},\n\n\tinstall: function(scope) {\n\t\tvar that = this;\n\t\tBase.each(['project', 'view', 'tool'], function(key) {\n\t\t\tBase.define(scope, key, {\n\t\t\t\tconfigurable: true,\n\t\t\t\tget: function() {\n\t\t\t\t\treturn that[key];\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\tfor (var key in this)\n\t\t\tif (!/^_/.test(key) && this[key])\n\t\t\t\tscope[key] = this[key];\n\t},\n\n\tsetup: function(element) {\n\t\tpaper = this;\n\t\tthis.project = new Project(element);\n\t\treturn this;\n\t},\n\n\tcreateCanvas: function(width, height) {\n\t\treturn CanvasProvider.getCanvas(width, height);\n\t},\n\n\tactivate: function() {\n\t\tpaper = this;\n\t},\n\n\tclear: function() {\n\t\tvar projects = this.projects,\n\t\t\ttools = this.tools,\n\t\t\tpalettes = this.palettes;\n\t\tfor (var i = projects.length - 1; i >= 0; i--)\n\t\t\tprojects[i].remove();\n\t\tfor (var i = tools.length - 1; i >= 0; i--)\n\t\t\ttools[i].remove();\n\t\tfor (var i = palettes.length - 1; i >= 0; i--)\n\t\t\tpalettes[i].remove();\n\t},\n\n\tremove: function() {\n\t\tthis.clear();\n\t\tdelete PaperScope._scopes[this._id];\n\t},\n\n\tstatics: new function() {\n\t\tfunction handleAttribute(name) {\n\t\t\tname += 'Attribute';\n\t\t\treturn function(el, attr) {\n\t\t\t\treturn el[name](attr) || el[name]('data-paper-' + attr);\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\t_scopes: {},\n\t\t\t_id: 0,\n\n\t\t\tget: function(id) {\n\t\t\t\treturn this._scopes[id] || null;\n\t\t\t},\n\n\t\t\tgetAttribute: handleAttribute('get'),\n\t\t\thasAttribute: handleAttribute('has')\n\t\t};\n\t}\n});\n\nvar PaperScopeItem = Base.extend(Emitter, {\n\n\tinitialize: function(activate) {\n\t\tthis._scope = paper;\n\t\tthis._index = this._scope[this._list].push(this) - 1;\n\t\tif (activate || !this._scope[this._reference])\n\t\t\tthis.activate();\n\t},\n\n\tactivate: function() {\n\t\tif (!this._scope)\n\t\t\treturn false;\n\t\tvar prev = this._scope[this._reference];\n\t\tif (prev && prev !== this)\n\t\t\tprev.emit('deactivate');\n\t\tthis._scope[this._reference] = this;\n\t\tthis.emit('activate', prev);\n\t\treturn true;\n\t},\n\n\tisActive: function() {\n\t\treturn this._scope[this._reference] === this;\n\t},\n\n\tremove: function() {\n\t\tif (this._index == null)\n\t\t\treturn false;\n\t\tBase.splice(this._scope[this._list], null, this._index, 1);\n\t\tif (this._scope[this._reference] == this)\n\t\t\tthis._scope[this._reference] = null;\n\t\tthis._scope = null;\n\t\treturn true;\n\t},\n\n\tgetView: function() {\n\t\treturn this._scope.getView();\n\t}\n});\n\nvar Formatter = Base.extend({\n\tinitialize: function(precision) {\n\t\tthis.precision = Base.pick(precision, 5);\n\t\tthis.multiplier = Math.pow(10, this.precision);\n\t},\n\n\tnumber: function(val) {\n\t\treturn this.precision < 16\n\t\t\t\t? Math.round(val * this.multiplier) / this.multiplier : val;\n\t},\n\n\tpair: function(val1, val2, separator) {\n\t\treturn this.number(val1) + (separator || ',') + this.number(val2);\n\t},\n\n\tpoint: function(val, separator) {\n\t\treturn this.number(val.x) + (separator || ',') + this.number(val.y);\n\t},\n\n\tsize: function(val, separator) {\n\t\treturn this.number(val.width) + (separator || ',')\n\t\t\t\t+ this.number(val.height);\n\t},\n\n\trectangle: function(val, separator) {\n\t\treturn this.point(val, separator) + (separator || ',')\n\t\t\t\t+ this.size(val, separator);\n\t}\n});\n\nFormatter.instance = new Formatter();\n\nvar Numerical = new function() {\n\n\tvar abscissas = [\n\t\t[ 0.5773502691896257645091488],\n\t\t[0,0.7745966692414833770358531],\n\t\t[ 0.3399810435848562648026658,0.8611363115940525752239465],\n\t\t[0,0.5384693101056830910363144,0.9061798459386639927976269],\n\t\t[ 0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],\n\t\t[0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],\n\t\t[ 0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],\n\t\t[0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],\n\t\t[ 0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],\n\t\t[0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],\n\t\t[ 0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],\n\t\t[0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],\n\t\t[ 0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],\n\t\t[0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],\n\t\t[ 0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]\n\t];\n\n\tvar weights = [\n\t\t[1],\n\t\t[0.8888888888888888888888889,0.5555555555555555555555556],\n\t\t[0.6521451548625461426269361,0.3478548451374538573730639],\n\t\t[0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],\n\t\t[0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],\n\t\t[0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],\n\t\t[0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],\n\t\t[0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],\n\t\t[0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],\n\t\t[0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],\n\t\t[0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],\n\t\t[0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],\n\t\t[0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],\n\t\t[0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],\n\t\t[0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]\n\t];\n\n\tvar abs = Math.abs,\n\t\tsqrt = Math.sqrt,\n\t\tpow = Math.pow,\n\t\tlog2 = Math.log2 || function(x) {\n\t\t\treturn Math.log(x) * Math.LOG2E;\n\t\t},\n\t\tEPSILON = 1e-12,\n\t\tMACHINE_EPSILON = 1.12e-16;\n\n\tfunction clamp(value, min, max) {\n\t\treturn value < min ? min : value > max ? max : value;\n\t}\n\n\tfunction getDiscriminant(a, b, c) {\n\t\tfunction split(v) {\n\t\t\tvar x = v * 134217729,\n\t\t\t\ty = v - x,\n\t\t\t\thi = y + x,\n\t\t\t\tlo = v - hi;\n\t\t\treturn [hi, lo];\n\t\t}\n\n\t\tvar D = b * b - a * c,\n\t\t\tE = b * b + a * c;\n\t\tif (abs(D) * 3 < E) {\n\t\t\tvar ad = split(a),\n\t\t\t\tbd = split(b),\n\t\t\t\tcd = split(c),\n\t\t\t\tp = b * b,\n\t\t\t\tdp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],\n\t\t\t\tq = a * c,\n\t\t\t\tdq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])\n\t\t\t\t\t\t+ ad[1] * cd[1];\n\t\t\tD = (p - q) + (dp - dq);\n\t\t}\n\t\treturn D;\n\t}\n\n\tfunction getNormalizationFactor() {\n\t\tvar norm = Math.max.apply(Math, arguments);\n\t\treturn norm && (norm < 1e-8 || norm > 1e8)\n\t\t\t\t? pow(2, -Math.round(log2(norm)))\n\t\t\t\t: 0;\n\t}\n\n\treturn {\n\t\tTOLERANCE: 1e-6,\n\t\tEPSILON: EPSILON,\n\t\tMACHINE_EPSILON: MACHINE_EPSILON,\n\t\tCURVETIME_EPSILON: 4e-7,\n\t\tGEOMETRIC_EPSILON: 1e-7,\n\t\tWINDING_EPSILON: 1e-8,\n\t\tTRIGONOMETRIC_EPSILON: 1e-8,\n\t\tCLIPPING_EPSILON: 1e-10,\n\t\tKAPPA: 4 * (sqrt(2) - 1) / 3,\n\n\t\tisZero: function(val) {\n\t\t\treturn val >= -EPSILON && val <= EPSILON;\n\t\t},\n\n\t\tclamp: clamp,\n\n\t\tintegrate: function(f, a, b, n) {\n\t\t\tvar x = abscissas[n - 2],\n\t\t\t\tw = weights[n - 2],\n\t\t\t\tA = (b - a) * 0.5,\n\t\t\t\tB = A + a,\n\t\t\t\ti = 0,\n\t\t\t\tm = (n + 1) >> 1,\n\t\t\t\tsum = n & 1 ? w[i++] * f(B) : 0;\n\t\t\twhile (i < m) {\n\t\t\t\tvar Ax = A * x[i];\n\t\t\t\tsum += w[i++] * (f(B + Ax) + f(B - Ax));\n\t\t\t}\n\t\t\treturn A * sum;\n\t\t},\n\n\t\tfindRoot: function(f, df, x, a, b, n, tolerance) {\n\t\t\tfor (var i = 0; i < n; i++) {\n\t\t\t\tvar fx = f(x),\n\t\t\t\t\tdx = fx / df(x),\n\t\t\t\t\tnx = x - dx;\n\t\t\t\tif (abs(dx) < tolerance)\n\t\t\t\t\treturn nx;\n\t\t\t\tif (fx > 0) {\n\t\t\t\t\tb = x;\n\t\t\t\t\tx = nx <= a ? (a + b) * 0.5 : nx;\n\t\t\t\t} else {\n\t\t\t\t\ta = x;\n\t\t\t\t\tx = nx >= b ? (a + b) * 0.5 : nx;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn x;\n\t\t},\n\n\t\tsolveQuadratic: function(a, b, c, roots, min, max) {\n\t\t\tvar x1, x2 = Infinity;\n\t\t\tif (abs(a) < EPSILON) {\n\t\t\t\tif (abs(b) < EPSILON)\n\t\t\t\t\treturn abs(c) < EPSILON ? -1 : 0;\n\t\t\t\tx1 = -c / b;\n\t\t\t} else {\n\t\t\t\tb *= -0.5;\n\t\t\t\tvar D = getDiscriminant(a, b, c);\n\t\t\t\tif (D && abs(D) < MACHINE_EPSILON) {\n\t\t\t\t\tvar f = getNormalizationFactor(abs(a), abs(b), abs(c));\n\t\t\t\t\tif (f) {\n\t\t\t\t\t\ta *= f;\n\t\t\t\t\t\tb *= f;\n\t\t\t\t\t\tc *= f;\n\t\t\t\t\t\tD = getDiscriminant(a, b, c);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (D >= -MACHINE_EPSILON) {\n\t\t\t\t\tvar Q = D < 0 ? 0 : sqrt(D),\n\t\t\t\t\t\tR = b + (b < 0 ? -Q : Q);\n\t\t\t\t\tif (R === 0) {\n\t\t\t\t\t\tx1 = c / a;\n\t\t\t\t\t\tx2 = -x1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tx1 = R / a;\n\t\t\t\t\t\tx2 = c / R;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar count = 0,\n\t\t\t\tboundless = min == null,\n\t\t\t\tminB = min - EPSILON,\n\t\t\t\tmaxB = max + EPSILON;\n\t\t\tif (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))\n\t\t\t\troots[count++] = boundless ? x1 : clamp(x1, min, max);\n\t\t\tif (x2 !== x1\n\t\t\t\t\t&& isFinite(x2) && (boundless || x2 > minB && x2 < maxB))\n\t\t\t\troots[count++] = boundless ? x2 : clamp(x2, min, max);\n\t\t\treturn count;\n\t\t},\n\n\t\tsolveCubic: function(a, b, c, d, roots, min, max) {\n\t\t\tvar f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),\n\t\t\t\tx, b1, c2, qd, q;\n\t\t\tif (f) {\n\t\t\t\ta *= f;\n\t\t\t\tb *= f;\n\t\t\t\tc *= f;\n\t\t\t\td *= f;\n\t\t\t}\n\n\t\t\tfunction evaluate(x0) {\n\t\t\t\tx = x0;\n\t\t\t\tvar tmp = a * x;\n\t\t\t\tb1 = tmp + b;\n\t\t\t\tc2 = b1 * x + c;\n\t\t\t\tqd = (tmp + b1) * x + c2;\n\t\t\t\tq = c2 * x + d;\n\t\t\t}\n\n\t\t\tif (abs(a) < EPSILON) {\n\t\t\t\ta = b;\n\t\t\t\tb1 = c;\n\t\t\t\tc2 = d;\n\t\t\t\tx = Infinity;\n\t\t\t} else if (abs(d) < EPSILON) {\n\t\t\t\tb1 = b;\n\t\t\t\tc2 = c;\n\t\t\t\tx = 0;\n\t\t\t} else {\n\t\t\t\tevaluate(-(b / a) / 3);\n\t\t\t\tvar t = q / a,\n\t\t\t\t\tr = pow(abs(t), 1/3),\n\t\t\t\t\ts = t < 0 ? -1 : 1,\n\t\t\t\t\ttd = -qd / a,\n\t\t\t\t\trd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,\n\t\t\t\t\tx0 = x - s * rd;\n\t\t\t\tif (x0 !== x) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tevaluate(x0);\n\t\t\t\t\t\tx0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);\n\t\t\t\t\t} while (s * x0 > s * x);\n\t\t\t\t\tif (abs(a) * x * x > abs(d / x)) {\n\t\t\t\t\t\tc2 = -d / x;\n\t\t\t\t\t\tb1 = (c2 - c) / x;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),\n\t\t\t\tboundless = min == null;\n\t\t\tif (isFinite(x) && (count === 0\n\t\t\t\t\t|| count > 0 && x !== roots[0] && x !== roots[1])\n\t\t\t\t\t&& (boundless || x > min - EPSILON && x < max + EPSILON))\n\t\t\t\troots[count++] = boundless ? x : clamp(x, min, max);\n\t\t\treturn count;\n\t\t}\n\t};\n};\n\nvar UID = {\n\t_id: 1,\n\t_pools: {},\n\n\tget: function(name) {\n\t\tif (name) {\n\t\t\tvar pool = this._pools[name];\n\t\t\tif (!pool)\n\t\t\t\tpool = this._pools[name] = { _id: 1 };\n\t\t\treturn pool._id++;\n\t\t} else {\n\t\t\treturn this._id++;\n\t\t}\n\t}\n};\n\nvar Point = Base.extend({\n\t_class: 'Point',\n\t_readIndex: true,\n\n\tinitialize: function Point(arg0, arg1) {\n\t\tvar type = typeof arg0,\n\t\t\treading = this.__read,\n\t\t\tread = 0;\n\t\tif (type === 'number') {\n\t\t\tvar hasY = typeof arg1 === 'number';\n\t\t\tthis._set(arg0, hasY ? arg1 : arg0);\n\t\t\tif (reading)\n\t\t\t\tread = hasY ? 2 : 1;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0);\n\t\t\tif (reading)\n\t\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else {\n\t\t\tvar obj = type === 'string' ? arg0.split(/[\\s,]+/) || [] : arg0;\n\t\t\tread = 1;\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\tthis._set(+obj[0], +(obj.length > 1 ? obj[1] : obj[0]));\n\t\t\t} else if ('x' in obj) {\n\t\t\t\tthis._set(obj.x || 0, obj.y || 0);\n\t\t\t} else if ('width' in obj) {\n\t\t\t\tthis._set(obj.width || 0, obj.height || 0);\n\t\t\t} else if ('angle' in obj) {\n\t\t\t\tthis._set(obj.length || 0, 0);\n\t\t\t\tthis.setAngle(obj.angle || 0);\n\t\t\t} else {\n\t\t\t\tthis._set(0, 0);\n\t\t\t\tread = 0;\n\t\t\t}\n\t\t}\n\t\tif (reading)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(x, y) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\treturn this;\n\t},\n\n\tequals: function(point) {\n\t\treturn this === point || point\n\t\t\t\t&& (this.x === point.x && this.y === point.y\n\t\t\t\t\t|| Array.isArray(point)\n\t\t\t\t\t\t&& this.x === point[0] && this.y === point[1])\n\t\t\t\t|| false;\n\t},\n\n\tclone: function() {\n\t\treturn new Point(this.x, this.y);\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.x), f.number(this.y)];\n\t},\n\n\tgetLength: function() {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y);\n\t},\n\n\tsetLength: function(length) {\n\t\tif (this.isZero()) {\n\t\t\tvar angle = this._angle || 0;\n\t\t\tthis._set(\n\t\t\t\tMath.cos(angle) * length,\n\t\t\t\tMath.sin(angle) * length\n\t\t\t);\n\t\t} else {\n\t\t\tvar scale = length / this.getLength();\n\t\t\tif (Numerical.isZero(scale))\n\t\t\t\tthis.getAngle();\n\t\t\tthis._set(\n\t\t\t\tthis.x * scale,\n\t\t\t\tthis.y * scale\n\t\t\t);\n\t\t}\n\t},\n\tgetAngle: function() {\n\t\treturn this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;\n\t},\n\n\tsetAngle: function(angle) {\n\t\tthis.setAngleInRadians.call(this, angle * Math.PI / 180);\n\t},\n\n\tgetAngleInDegrees: '#getAngle',\n\tsetAngleInDegrees: '#setAngle',\n\n\tgetAngleInRadians: function() {\n\t\tif (!arguments.length) {\n\t\t\treturn this.isZero()\n\t\t\t\t\t? this._angle || 0\n\t\t\t\t\t: this._angle = Math.atan2(this.y, this.x);\n\t\t} else {\n\t\t\tvar point = Point.read(arguments),\n\t\t\t\tdiv = this.getLength() * point.getLength();\n\t\t\tif (Numerical.isZero(div)) {\n\t\t\t\treturn NaN;\n\t\t\t} else {\n\t\t\t\tvar a = this.dot(point) / div;\n\t\t\t\treturn Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);\n\t\t\t}\n\t\t}\n\t},\n\n\tsetAngleInRadians: function(angle) {\n\t\tthis._angle = angle;\n\t\tif (!this.isZero()) {\n\t\t\tvar length = this.getLength();\n\t\t\tthis._set(\n\t\t\t\tMath.cos(angle) * length,\n\t\t\t\tMath.sin(angle) * length\n\t\t\t);\n\t\t}\n\t},\n\n\tgetQuadrant: function() {\n\t\treturn this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;\n\t}\n}, {\n\tbeans: false,\n\n\tgetDirectedAngle: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;\n\t},\n\n\tgetDistance: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tx = point.x - this.x,\n\t\t\ty = point.y - this.y,\n\t\t\td = x * x + y * y,\n\t\t\tsquared = Base.read(arguments);\n\t\treturn squared ? d : Math.sqrt(d);\n\t},\n\n\tnormalize: function(length) {\n\t\tif (length === undefined)\n\t\t\tlength = 1;\n\t\tvar current = this.getLength(),\n\t\t\tscale = current !== 0 ? length / current : 0,\n\t\t\tpoint = new Point(this.x * scale, this.y * scale);\n\t\tif (scale >= 0)\n\t\t\tpoint._angle = this._angle;\n\t\treturn point;\n\t},\n\n\trotate: function(angle, center) {\n\t\tif (angle === 0)\n\t\t\treturn this.clone();\n\t\tangle = angle * Math.PI / 180;\n\t\tvar point = center ? this.subtract(center) : this,\n\t\t\tsin = Math.sin(angle),\n\t\t\tcos = Math.cos(angle);\n\t\tpoint = new Point(\n\t\t\tpoint.x * cos - point.y * sin,\n\t\t\tpoint.x * sin + point.y * cos\n\t\t);\n\t\treturn center ? point.add(center) : point;\n\t},\n\n\ttransform: function(matrix) {\n\t\treturn matrix ? matrix._transformPoint(this) : this;\n\t},\n\n\tadd: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x + point.x, this.y + point.y);\n\t},\n\n\tsubtract: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x - point.x, this.y - point.y);\n\t},\n\n\tmultiply: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x * point.x, this.y * point.y);\n\t},\n\n\tdivide: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x / point.x, this.y / point.y);\n\t},\n\n\tmodulo: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x % point.x, this.y % point.y);\n\t},\n\n\tnegate: function() {\n\t\treturn new Point(-this.x, -this.y);\n\t},\n\n\tisInside: function() {\n\t\treturn Rectangle.read(arguments).contains(this);\n\t},\n\n\tisClose: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\ttolerance = Base.read(arguments);\n\t\treturn this.getDistance(point) <= tolerance;\n\t},\n\n\tisCollinear: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Point.isCollinear(this.x, this.y, point.x, point.y);\n\t},\n\n\tisColinear: '#isCollinear',\n\n\tisOrthogonal: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Point.isOrthogonal(this.x, this.y, point.x, point.y);\n\t},\n\n\tisZero: function() {\n\t\treturn Numerical.isZero(this.x) && Numerical.isZero(this.y);\n\t},\n\n\tisNaN: function() {\n\t\treturn isNaN(this.x) || isNaN(this.y);\n\t},\n\n\tdot: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn this.x * point.x + this.y * point.y;\n\t},\n\n\tcross: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn this.x * point.y - this.y * point.x;\n\t},\n\n\tproject: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tscale = point.isZero() ? 0 : this.dot(point) / point.dot(point);\n\t\treturn new Point(\n\t\t\tpoint.x * scale,\n\t\t\tpoint.y * scale\n\t\t);\n\t},\n\n\tstatics: {\n\t\tmin: function() {\n\t\t\tvar point1 = Point.read(arguments),\n\t\t\t\tpoint2 = Point.read(arguments);\n\t\t\treturn new Point(\n\t\t\t\tMath.min(point1.x, point2.x),\n\t\t\t\tMath.min(point1.y, point2.y)\n\t\t\t);\n\t\t},\n\n\t\tmax: function() {\n\t\t\tvar point1 = Point.read(arguments),\n\t\t\t\tpoint2 = Point.read(arguments);\n\t\t\treturn new Point(\n\t\t\t\tMath.max(point1.x, point2.x),\n\t\t\t\tMath.max(point1.y, point2.y)\n\t\t\t);\n\t\t},\n\n\t\trandom: function() {\n\t\t\treturn new Point(Math.random(), Math.random());\n\t\t},\n\n\t\tisCollinear: function(x1, y1, x2, y2) {\n\t\t\treturn Math.abs(x1 * y2 - y1 * x2)\n\t\t\t\t\t<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))\n\t\t\t\t\t\t* 1e-8;\n\t\t},\n\n\t\tisOrthogonal: function(x1, y1, x2, y2) {\n\t\t\treturn Math.abs(x1 * x2 + y1 * y2)\n\t\t\t\t\t<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))\n\t\t\t\t\t\t* 1e-8;\n\t\t}\n\t}\n}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {\n\tvar op = Math[key];\n\tthis[key] = function() {\n\t\treturn new Point(op(this.x), op(this.y));\n\t};\n}, {}));\n\nvar LinkedPoint = Point.extend({\n\tinitialize: function Point(x, y, owner, setter) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(x, y, _dontNotify) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t},\n\n\tgetX: function() {\n\t\treturn this._x;\n\t},\n\n\tsetX: function(x) {\n\t\tthis._x = x;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tgetY: function() {\n\t\treturn this._y;\n\t},\n\n\tsetY: function(y) {\n\t\tthis._y = y;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._owner._selection & this._getSelection());\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis._owner.changeSelection(this._getSelection(), selected);\n\t},\n\n\t_getSelection: function() {\n\t\treturn this._setter === 'setPosition' ? 4 : 0;\n\t}\n});\n\nvar Size = Base.extend({\n\t_class: 'Size',\n\t_readIndex: true,\n\n\tinitialize: function Size(arg0, arg1) {\n\t\tvar type = typeof arg0,\n\t\t\treading = this.__read,\n\t\t\tread = 0;\n\t\tif (type === 'number') {\n\t\t\tvar hasHeight = typeof arg1 === 'number';\n\t\t\tthis._set(arg0, hasHeight ? arg1 : arg0);\n\t\t\tif (reading)\n\t\t\t\tread = hasHeight ? 2 : 1;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0);\n\t\t\tif (reading)\n\t\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else {\n\t\t\tvar obj = type === 'string' ? arg0.split(/[\\s,]+/) || [] : arg0;\n\t\t\tread = 1;\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\tthis._set(+obj[0], +(obj.length > 1 ? obj[1] : obj[0]));\n\t\t\t} else if ('width' in obj) {\n\t\t\t\tthis._set(obj.width || 0, obj.height || 0);\n\t\t\t} else if ('x' in obj) {\n\t\t\t\tthis._set(obj.x || 0, obj.y || 0);\n\t\t\t} else {\n\t\t\t\tthis._set(0, 0);\n\t\t\t\tread = 0;\n\t\t\t}\n\t\t}\n\t\tif (reading)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(width, height) {\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\treturn this;\n\t},\n\n\tequals: function(size) {\n\t\treturn size === this || size && (this.width === size.width\n\t\t\t\t&& this.height === size.height\n\t\t\t\t|| Array.isArray(size) && this.width === size[0]\n\t\t\t\t\t&& this.height === size[1]) || false;\n\t},\n\n\tclone: function() {\n\t\treturn new Size(this.width, this.height);\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ width: ' + f.number(this.width)\n\t\t\t\t+ ', height: ' + f.number(this.height) + ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.width),\n\t\t\t\tf.number(this.height)];\n\t},\n\n\tadd: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width + size.width, this.height + size.height);\n\t},\n\n\tsubtract: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width - size.width, this.height - size.height);\n\t},\n\n\tmultiply: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width * size.width, this.height * size.height);\n\t},\n\n\tdivide: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width / size.width, this.height / size.height);\n\t},\n\n\tmodulo: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width % size.width, this.height % size.height);\n\t},\n\n\tnegate: function() {\n\t\treturn new Size(-this.width, -this.height);\n\t},\n\n\tisZero: function() {\n\t\treturn Numerical.isZero(this.width) && Numerical.isZero(this.height);\n\t},\n\n\tisNaN: function() {\n\t\treturn isNaN(this.width) || isNaN(this.height);\n\t},\n\n\tstatics: {\n\t\tmin: function(size1, size2) {\n\t\t\treturn new Size(\n\t\t\t\tMath.min(size1.width, size2.width),\n\t\t\t\tMath.min(size1.height, size2.height));\n\t\t},\n\n\t\tmax: function(size1, size2) {\n\t\t\treturn new Size(\n\t\t\t\tMath.max(size1.width, size2.width),\n\t\t\t\tMath.max(size1.height, size2.height));\n\t\t},\n\n\t\trandom: function() {\n\t\t\treturn new Size(Math.random(), Math.random());\n\t\t}\n\t}\n}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {\n\tvar op = Math[key];\n\tthis[key] = function() {\n\t\treturn new Size(op(this.width), op(this.height));\n\t};\n}, {}));\n\nvar LinkedSize = Size.extend({\n\tinitialize: function Size(width, height, owner, setter) {\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(width, height, _dontNotify) {\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t},\n\n\tgetWidth: function() {\n\t\treturn this._width;\n\t},\n\n\tsetWidth: function(width) {\n\t\tthis._width = width;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tgetHeight: function() {\n\t\treturn this._height;\n\t},\n\n\tsetHeight: function(height) {\n\t\tthis._height = height;\n\t\tthis._owner[this._setter](this);\n\t}\n});\n\nvar Rectangle = Base.extend({\n\t_class: 'Rectangle',\n\t_readIndex: true,\n\tbeans: true,\n\n\tinitialize: function Rectangle(arg0, arg1, arg2, arg3) {\n\t\tvar type = typeof arg0,\n\t\t\tread;\n\t\tif (type === 'number') {\n\t\t\tthis._set(arg0, arg1, arg2, arg3);\n\t\t\tread = 4;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0, 0, 0);\n\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else if (arguments.length === 1) {\n\t\t\tif (Array.isArray(arg0)) {\n\t\t\t\tthis._set.apply(this, arg0);\n\t\t\t\tread = 1;\n\t\t\t} else if (arg0.x !== undefined || arg0.width !== undefined) {\n\t\t\t\tthis._set(arg0.x || 0, arg0.y || 0,\n\t\t\t\t\t\targ0.width || 0, arg0.height || 0);\n\t\t\t\tread = 1;\n\t\t\t} else if (arg0.from === undefined && arg0.to === undefined) {\n\t\t\t\tthis._set(0, 0, 0, 0);\n\t\t\t\tBase.filter(this, arg0);\n\t\t\t\tread = 1;\n\t\t\t}\n\t\t}\n\t\tif (read === undefined) {\n\t\t\tvar frm = Point.readNamed(arguments, 'from'),\n\t\t\t\tnext = Base.peek(arguments),\n\t\t\t\tx = frm.x,\n\t\t\t\ty = frm.y,\n\t\t\t\twidth,\n\t\t\t\theight;\n\t\t\tif (next && next.x !== undefined\n\t\t\t\t\t|| Base.hasNamed(arguments, 'to')) {\n\t\t\t\tvar to = Point.readNamed(arguments, 'to');\n\t\t\t\twidth = to.x - x;\n\t\t\t\theight = to.y - y;\n\t\t\t\tif (width < 0) {\n\t\t\t\t\tx = to.x;\n\t\t\t\t\twidth = -width;\n\t\t\t\t}\n\t\t\t\tif (height < 0) {\n\t\t\t\t\ty = to.y;\n\t\t\t\t\theight = -height;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar size = Size.read(arguments);\n\t\t\t\twidth = size.width;\n\t\t\t\theight = size.height;\n\t\t\t}\n\t\t\tthis._set(x, y, width, height);\n\t\t\tread = arguments.__index;\n\t\t}\n\t\tif (this.__read)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(x, y, width, height) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\treturn this;\n\t},\n\n\tclone: function() {\n\t\treturn new Rectangle(this.x, this.y, this.width, this.height);\n\t},\n\n\tequals: function(rect) {\n\t\tvar rt = Base.isPlainValue(rect)\n\t\t\t\t? Rectangle.read(arguments)\n\t\t\t\t: rect;\n\t\treturn rt === this\n\t\t\t\t|| rt && this.x === rt.x && this.y === rt.y\n\t\t\t\t\t&& this.width === rt.width && this.height === rt.height\n\t\t\t\t|| false;\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ x: ' + f.number(this.x)\n\t\t\t\t+ ', y: ' + f.number(this.y)\n\t\t\t\t+ ', width: ' + f.number(this.width)\n\t\t\t\t+ ', height: ' + f.number(this.height)\n\t\t\t\t+ ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.x),\n\t\t\t\tf.number(this.y),\n\t\t\t\tf.number(this.width),\n\t\t\t\tf.number(this.height)];\n\t},\n\n\tgetPoint: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\treturn new ctor(this.x, this.y, this, 'setPoint');\n\t},\n\n\tsetPoint: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.x = point.x;\n\t\tthis.y = point.y;\n\t},\n\n\tgetSize: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Size : LinkedSize;\n\t\treturn new ctor(this.width, this.height, this, 'setSize');\n\t},\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments);\n\t\tif (this._fixX)\n\t\t\tthis.x += (this.width - size.width) * this._fixX;\n\t\tif (this._fixY)\n\t\t\tthis.y += (this.height - size.height) * this._fixY;\n\t\tthis.width = size.width;\n\t\tthis.height = size.height;\n\t\tthis._fixW = 1;\n\t\tthis._fixH = 1;\n\t},\n\n\tgetLeft: function() {\n\t\treturn this.x;\n\t},\n\n\tsetLeft: function(left) {\n\t\tif (!this._fixW)\n\t\t\tthis.width -= left - this.x;\n\t\tthis.x = left;\n\t\tthis._fixX = 0;\n\t},\n\n\tgetTop: function() {\n\t\treturn this.y;\n\t},\n\n\tsetTop: function(top) {\n\t\tif (!this._fixH)\n\t\t\tthis.height -= top - this.y;\n\t\tthis.y = top;\n\t\tthis._fixY = 0;\n\t},\n\n\tgetRight: function() {\n\t\treturn this.x + this.width;\n\t},\n\n\tsetRight: function(right) {\n\t\tif (this._fixX !== undefined && this._fixX !== 1)\n\t\t\tthis._fixW = 0;\n\t\tif (this._fixW)\n\t\t\tthis.x = right - this.width;\n\t\telse\n\t\t\tthis.width = right - this.x;\n\t\tthis._fixX = 1;\n\t},\n\n\tgetBottom: function() {\n\t\treturn this.y + this.height;\n\t},\n\n\tsetBottom: function(bottom) {\n\t\tif (this._fixY !== undefined && this._fixY !== 1)\n\t\t\tthis._fixH = 0;\n\t\tif (this._fixH)\n\t\t\tthis.y = bottom - this.height;\n\t\telse\n\t\t\tthis.height = bottom - this.y;\n\t\tthis._fixY = 1;\n\t},\n\n\tgetCenterX: function() {\n\t\treturn this.x + this.width * 0.5;\n\t},\n\n\tsetCenterX: function(x) {\n\t\tthis.x = x - this.width * 0.5;\n\t\tthis._fixX = 0.5;\n\t},\n\n\tgetCenterY: function() {\n\t\treturn this.y + this.height * 0.5;\n\t},\n\n\tsetCenterY: function(y) {\n\t\tthis.y = y - this.height * 0.5;\n\t\tthis._fixY = 0.5;\n\t},\n\n\tgetCenter: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\treturn new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');\n\t},\n\n\tsetCenter: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.setCenterX(point.x);\n\t\tthis.setCenterY(point.y);\n\t\treturn this;\n\t},\n\n\tgetArea: function() {\n\t\treturn this.width * this.height;\n\t},\n\n\tisEmpty: function() {\n\t\treturn this.width === 0 || this.height === 0;\n\t},\n\n\tcontains: function(arg) {\n\t\treturn arg && arg.width !== undefined\n\t\t\t\t|| (Array.isArray(arg) ? arg : arguments).length === 4\n\t\t\t\t? this._containsRectangle(Rectangle.read(arguments))\n\t\t\t\t: this._containsPoint(Point.read(arguments));\n\t},\n\n\t_containsPoint: function(point) {\n\t\tvar x = point.x,\n\t\t\ty = point.y;\n\t\treturn x >= this.x && y >= this.y\n\t\t\t\t&& x <= this.x + this.width\n\t\t\t\t&& y <= this.y + this.height;\n\t},\n\n\t_containsRectangle: function(rect) {\n\t\tvar x = rect.x,\n\t\t\ty = rect.y;\n\t\treturn x >= this.x && y >= this.y\n\t\t\t\t&& x + rect.width <= this.x + this.width\n\t\t\t\t&& y + rect.height <= this.y + this.height;\n\t},\n\n\tintersects: function() {\n\t\tvar rect = Rectangle.read(arguments);\n\t\treturn rect.x + rect.width > this.x\n\t\t\t\t&& rect.y + rect.height > this.y\n\t\t\t\t&& rect.x < this.x + this.width\n\t\t\t\t&& rect.y < this.y + this.height;\n\t},\n\n\ttouches: function() {\n\t\tvar rect = Rectangle.read(arguments);\n\t\treturn rect.x + rect.width >= this.x\n\t\t\t\t&& rect.y + rect.height >= this.y\n\t\t\t\t&& rect.x <= this.x + this.width\n\t\t\t\t&& rect.y <= this.y + this.height;\n\t},\n\n\tintersect: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tx1 = Math.max(this.x, rect.x),\n\t\t\ty1 = Math.max(this.y, rect.y),\n\t\t\tx2 = Math.min(this.x + this.width, rect.x + rect.width),\n\t\t\ty2 = Math.min(this.y + this.height, rect.y + rect.height);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\tunite: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tx1 = Math.min(this.x, rect.x),\n\t\t\ty1 = Math.min(this.y, rect.y),\n\t\t\tx2 = Math.max(this.x + this.width, rect.x + rect.width),\n\t\t\ty2 = Math.max(this.y + this.height, rect.y + rect.height);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\tinclude: function() {\n\t\tvar point = Point.read(arguments);\n\t\tvar x1 = Math.min(this.x, point.x),\n\t\t\ty1 = Math.min(this.y, point.y),\n\t\t\tx2 = Math.max(this.x + this.width, point.x),\n\t\t\ty2 = Math.max(this.y + this.height, point.y);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\texpand: function() {\n\t\tvar amount = Size.read(arguments),\n\t\t\thor = amount.width,\n\t\t\tver = amount.height;\n\t\treturn new Rectangle(this.x - hor / 2, this.y - ver / 2,\n\t\t\t\tthis.width + hor, this.height + ver);\n\t},\n\n\tscale: function(hor, ver) {\n\t\treturn this.expand(this.width * hor - this.width,\n\t\t\t\tthis.height * (ver === undefined ? hor : ver) - this.height);\n\t}\n}, Base.each([\n\t\t['Top', 'Left'], ['Top', 'Right'],\n\t\t['Bottom', 'Left'], ['Bottom', 'Right'],\n\t\t['Left', 'Center'], ['Top', 'Center'],\n\t\t['Right', 'Center'], ['Bottom', 'Center']\n\t],\n\tfunction(parts, index) {\n\t\tvar part = parts.join(''),\n\t\t\txFirst = /^[RL]/.test(part);\n\t\tif (index >= 4)\n\t\t\tparts[1] += xFirst ? 'Y' : 'X';\n\t\tvar x = parts[xFirst ? 0 : 1],\n\t\t\ty = parts[xFirst ? 1 : 0],\n\t\t\tgetX = 'get' + x,\n\t\t\tgetY = 'get' + y,\n\t\t\tsetX = 'set' + x,\n\t\t\tsetY = 'set' + y,\n\t\t\tget = 'get' + part,\n\t\t\tset = 'set' + part;\n\t\tthis[get] = function(_dontLink) {\n\t\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\t\treturn new ctor(this[getX](), this[getY](), this, set);\n\t\t};\n\t\tthis[set] = function() {\n\t\t\tvar point = Point.read(arguments);\n\t\t\tthis[setX](point.x);\n\t\t\tthis[setY](point.y);\n\t\t};\n\t}, {\n\t\tbeans: true\n\t}\n));\n\nvar LinkedRectangle = Rectangle.extend({\n\tinitialize: function Rectangle(x, y, width, height, owner, setter) {\n\t\tthis._set(x, y, width, height, true);\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(x, y, width, height, _dontNotify) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t}\n},\nnew function() {\n\tvar proto = Rectangle.prototype;\n\n\treturn Base.each(['x', 'y', 'width', 'height'], function(key) {\n\t\tvar part = Base.capitalize(key),\n\t\t\tinternal = '_' + key;\n\t\tthis['get' + part] = function() {\n\t\t\treturn this[internal];\n\t\t};\n\n\t\tthis['set' + part] = function(value) {\n\t\t\tthis[internal] = value;\n\t\t\tif (!this._dontNotify)\n\t\t\t\tthis._owner[this._setter](this);\n\t\t};\n\t}, Base.each(['Point', 'Size', 'Center',\n\t\t\t'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',\n\t\t\t'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',\n\t\t\t'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],\n\t\tfunction(key) {\n\t\t\tvar name = 'set' + key;\n\t\t\tthis[name] = function() {\n\t\t\t\tthis._dontNotify = true;\n\t\t\t\tproto[name].apply(this, arguments);\n\t\t\t\tthis._dontNotify = false;\n\t\t\t\tthis._owner[this._setter](this);\n\t\t\t};\n\t\t}, {\n\t\t\tisSelected: function() {\n\t\t\t\treturn !!(this._owner._selection & 2);\n\t\t\t},\n\n\t\t\tsetSelected: function(selected) {\n\t\t\t\tvar owner = this._owner;\n\t\t\t\tif (owner.changeSelection) {\n\t\t\t\t\towner.changeSelection(2, selected);\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t);\n});\n\nvar Matrix = Base.extend({\n\t_class: 'Matrix',\n\n\tinitialize: function Matrix(arg) {\n\t\tvar count = arguments.length,\n\t\t\tok = true;\n\t\tif (count === 6) {\n\t\t\tthis._set.apply(this, arguments);\n\t\t} else if (count === 1) {\n\t\t\tif (arg instanceof Matrix) {\n\t\t\t\tthis._set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty);\n\t\t\t} else if (Array.isArray(arg)) {\n\t\t\t\tthis._set.apply(this, arg);\n\t\t\t} else {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t} else if (!count) {\n\t\t\tthis.reset();\n\t\t} else {\n\t\t\tok = false;\n\t\t}\n\t\tif (!ok) {\n\t\t\tthrow new Error('Unsupported matrix parameters');\n\t\t}\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(a, b, c, d, tx, ty, _dontNotify) {\n\t\tthis._a = a;\n\t\tthis._b = b;\n\t\tthis._c = c;\n\t\tthis._d = d;\n\t\tthis._tx = tx;\n\t\tthis._ty = ty;\n\t\tif (!_dontNotify)\n\t\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this.getValues(), options, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tvar owner = this._owner;\n\t\tif (owner) {\n\t\t\tif (owner._applyMatrix) {\n\t\t\t\towner.transform(null, true);\n\t\t\t} else {\n\t\t\t\towner._changed(9);\n\t\t\t}\n\t\t}\n\t},\n\n\tclone: function() {\n\t\treturn new Matrix(this._a, this._b, this._c, this._d,\n\t\t\t\tthis._tx, this._ty);\n\t},\n\n\tequals: function(mx) {\n\t\treturn mx === this || mx && this._a === mx._a && this._b === mx._b\n\t\t\t\t&& this._c === mx._c && this._d === mx._d\n\t\t\t\t&& this._tx === mx._tx && this._ty === mx._ty;\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '[[' + [f.number(this._a), f.number(this._c),\n\t\t\t\t\tf.number(this._tx)].join(', ') + '], ['\n\t\t\t\t+ [f.number(this._b), f.number(this._d),\n\t\t\t\t\tf.number(this._ty)].join(', ') + ']]';\n\t},\n\n\treset: function(_dontNotify) {\n\t\tthis._a = this._d = 1;\n\t\tthis._b = this._c = this._tx = this._ty = 0;\n\t\tif (!_dontNotify)\n\t\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tapply: function(recursively, _setApplyMatrix) {\n\t\tvar owner = this._owner;\n\t\tif (owner) {\n\t\t\towner.transform(null, true, Base.pick(recursively, true),\n\t\t\t\t\t_setApplyMatrix);\n\t\t\treturn this.isIdentity();\n\t\t}\n\t\treturn false;\n\t},\n\n\ttranslate: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tx = point.x,\n\t\t\ty = point.y;\n\t\tthis._tx += x * this._a + y * this._c;\n\t\tthis._ty += x * this._b + y * this._d;\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tscale: function() {\n\t\tvar scale = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\tif (center)\n\t\t\tthis.translate(center);\n\t\tthis._a *= scale.x;\n\t\tthis._b *= scale.x;\n\t\tthis._c *= scale.y;\n\t\tthis._d *= scale.y;\n\t\tif (center)\n\t\t\tthis.translate(center.negate());\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\trotate: function(angle ) {\n\t\tangle *= Math.PI / 180;\n\t\tvar center = Point.read(arguments, 1),\n\t\t\tx = center.x,\n\t\t\ty = center.y,\n\t\t\tcos = Math.cos(angle),\n\t\t\tsin = Math.sin(angle),\n\t\t\ttx = x - x * cos + y * sin,\n\t\t\tty = y - x * sin - y * cos,\n\t\t\ta = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d;\n\t\tthis._a = cos * a + sin * c;\n\t\tthis._b = cos * b + sin * d;\n\t\tthis._c = -sin * a + cos * c;\n\t\tthis._d = -sin * b + cos * d;\n\t\tthis._tx += tx * a + ty * c;\n\t\tthis._ty += tx * b + ty * d;\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tshear: function() {\n\t\tvar shear = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\tif (center)\n\t\t\tthis.translate(center);\n\t\tvar a = this._a,\n\t\t\tb = this._b;\n\t\tthis._a += shear.y * this._c;\n\t\tthis._b += shear.y * this._d;\n\t\tthis._c += shear.x * a;\n\t\tthis._d += shear.x * b;\n\t\tif (center)\n\t\t\tthis.translate(center.negate());\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tskew: function() {\n\t\tvar skew = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true }),\n\t\t\ttoRadians = Math.PI / 180,\n\t\t\tshear = new Point(Math.tan(skew.x * toRadians),\n\t\t\t\tMath.tan(skew.y * toRadians));\n\t\treturn this.shear(shear, center);\n\t},\n\n\tappend: function(mx) {\n\t\tif (mx) {\n\t\t\tvar a1 = this._a,\n\t\t\t\tb1 = this._b,\n\t\t\t\tc1 = this._c,\n\t\t\t\td1 = this._d,\n\t\t\t\ta2 = mx._a,\n\t\t\t\tb2 = mx._c,\n\t\t\t\tc2 = mx._b,\n\t\t\t\td2 = mx._d,\n\t\t\t\ttx2 = mx._tx,\n\t\t\t\tty2 = mx._ty;\n\t\t\tthis._a = a2 * a1 + c2 * c1;\n\t\t\tthis._c = b2 * a1 + d2 * c1;\n\t\t\tthis._b = a2 * b1 + c2 * d1;\n\t\t\tthis._d = b2 * b1 + d2 * d1;\n\t\t\tthis._tx += tx2 * a1 + ty2 * c1;\n\t\t\tthis._ty += tx2 * b1 + ty2 * d1;\n\t\t\tthis._changed();\n\t\t}\n\t\treturn this;\n\t},\n\n\tprepend: function(mx) {\n\t\tif (mx) {\n\t\t\tvar a1 = this._a,\n\t\t\t\tb1 = this._b,\n\t\t\t\tc1 = this._c,\n\t\t\t\td1 = this._d,\n\t\t\t\ttx1 = this._tx,\n\t\t\t\tty1 = this._ty,\n\t\t\t\ta2 = mx._a,\n\t\t\t\tb2 = mx._c,\n\t\t\t\tc2 = mx._b,\n\t\t\t\td2 = mx._d,\n\t\t\t\ttx2 = mx._tx,\n\t\t\t\tty2 = mx._ty;\n\t\t\tthis._a = a2 * a1 + b2 * b1;\n\t\t\tthis._c = a2 * c1 + b2 * d1;\n\t\t\tthis._b = c2 * a1 + d2 * b1;\n\t\t\tthis._d = c2 * c1 + d2 * d1;\n\t\t\tthis._tx = a2 * tx1 + b2 * ty1 + tx2;\n\t\t\tthis._ty = c2 * tx1 + d2 * ty1 + ty2;\n\t\t\tthis._changed();\n\t\t}\n\t\treturn this;\n\t},\n\n\tappended: function(mx) {\n\t\treturn this.clone().append(mx);\n\t},\n\n\tprepended: function(mx) {\n\t\treturn this.clone().prepend(mx);\n\t},\n\n\tinvert: function() {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\ttx = this._tx,\n\t\t\tty = this._ty,\n\t\t\tdet = a * d - b * c,\n\t\t\tres = null;\n\t\tif (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {\n\t\t\tthis._a = d / det;\n\t\t\tthis._b = -b / det;\n\t\t\tthis._c = -c / det;\n\t\t\tthis._d = a / det;\n\t\t\tthis._tx = (c * ty - d * tx) / det;\n\t\t\tthis._ty = (b * tx - a * ty) / det;\n\t\t\tres = this;\n\t\t}\n\t\treturn res;\n\t},\n\n\tinverted: function() {\n\t\treturn this.clone().invert();\n\t},\n\n\tconcatenate: '#append',\n\tpreConcatenate: '#prepend',\n\tchain: '#appended',\n\n\t_shiftless: function() {\n\t\treturn new Matrix(this._a, this._b, this._c, this._d, 0, 0);\n\t},\n\n\t_orNullIfIdentity: function() {\n\t\treturn this.isIdentity() ? null : this;\n\t},\n\n\tisIdentity: function() {\n\t\treturn this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1\n\t\t\t\t&& this._tx === 0 && this._ty === 0;\n\t},\n\n\tisInvertible: function() {\n\t\tvar det = this._a * this._d - this._c * this._b;\n\t\treturn det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty);\n\t},\n\n\tisSingular: function() {\n\t\treturn !this.isInvertible();\n\t},\n\n\ttransform: function( src, dst, count) {\n\t\treturn arguments.length < 3\n\t\t\t? this._transformPoint(Point.read(arguments))\n\t\t\t: this._transformCoordinates(src, dst, count);\n\t},\n\n\t_transformPoint: function(point, dest, _dontNotify) {\n\t\tvar x = point.x,\n\t\t\ty = point.y;\n\t\tif (!dest)\n\t\t\tdest = new Point();\n\t\treturn dest._set(\n\t\t\t\tx * this._a + y * this._c + this._tx,\n\t\t\t\tx * this._b + y * this._d + this._ty,\n\t\t\t\t_dontNotify);\n\t},\n\n\t_transformCoordinates: function(src, dst, count) {\n\t\tfor (var i = 0, max = 2 * count; i < max; i += 2) {\n\t\t\tvar x = src[i],\n\t\t\t\ty = src[i + 1];\n\t\t\tdst[i] = x * this._a + y * this._c + this._tx;\n\t\t\tdst[i + 1] = x * this._b + y * this._d + this._ty;\n\t\t}\n\t\treturn dst;\n\t},\n\n\t_transformCorners: function(rect) {\n\t\tvar x1 = rect.x,\n\t\t\ty1 = rect.y,\n\t\t\tx2 = x1 + rect.width,\n\t\t\ty2 = y1 + rect.height,\n\t\t\tcoords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];\n\t\treturn this._transformCoordinates(coords, coords, 4);\n\t},\n\n\t_transformBounds: function(bounds, dest, _dontNotify) {\n\t\tvar coords = this._transformCorners(bounds),\n\t\t\tmin = coords.slice(0, 2),\n\t\t\tmax = min.slice();\n\t\tfor (var i = 2; i < 8; i++) {\n\t\t\tvar val = coords[i],\n\t\t\t\tj = i & 1;\n\t\t\tif (val < min[j]) {\n\t\t\t\tmin[j] = val;\n\t\t\t} else if (val > max[j]) {\n\t\t\t\tmax[j] = val;\n\t\t\t}\n\t\t}\n\t\tif (!dest)\n\t\t\tdest = new Rectangle();\n\t\treturn dest._set(min[0], min[1], max[0] - min[0], max[1] - min[1],\n\t\t\t\t_dontNotify);\n\t},\n\n\tinverseTransform: function() {\n\t\treturn this._inverseTransform(Point.read(arguments));\n\t},\n\n\t_inverseTransform: function(point, dest, _dontNotify) {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\ttx = this._tx,\n\t\t\tty = this._ty,\n\t\t\tdet = a * d - b * c,\n\t\t\tres = null;\n\t\tif (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {\n\t\t\tvar x = point.x - this._tx,\n\t\t\t\ty = point.y - this._ty;\n\t\t\tif (!dest)\n\t\t\t\tdest = new Point();\n\t\t\tres = dest._set(\n\t\t\t\t\t(x * d - y * c) / det,\n\t\t\t\t\t(y * a - x * b) / det,\n\t\t\t\t\t_dontNotify);\n\t\t}\n\t\treturn res;\n\t},\n\n\tdecompose: function() {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\tdet = a * d - b * c,\n\t\t\tsqrt = Math.sqrt,\n\t\t\tatan2 = Math.atan2,\n\t\t\tdegrees = 180 / Math.PI,\n\t\t\trotate,\n\t\t\tscale,\n\t\t\tskew;\n\t\tif (a !== 0 || b !== 0) {\n\t\t\tvar r = sqrt(a * a + b * b);\n\t\t\trotate = Math.acos(a / r) * (b > 0 ? 1 : -1);\n\t\t\tscale = [r, det / r];\n\t\t\tskew = [atan2(a * c + b * d, r * r), 0];\n\t\t} else if (c !== 0 || d !== 0) {\n\t\t\tvar s = sqrt(c * c + d * d);\n\t\t\trotate = Math.asin(c / s) * (d > 0 ? 1 : -1);\n\t\t\tscale = [det / s, s];\n\t\t\tskew = [0, atan2(a * c + b * d, s * s)];\n\t\t} else {\n\t\t\trotate = 0;\n\t\t\tskew = scale = [0, 0];\n\t\t}\n\t\treturn {\n\t\t\ttranslation: this.getTranslation(),\n\t\t\trotation: rotate * degrees,\n\t\t\tscaling: new Point(scale),\n\t\t\tskewing: new Point(skew[0] * degrees, skew[1] * degrees)\n\t\t};\n\t},\n\n\tgetValues: function() {\n\t\treturn [ this._a, this._b, this._c, this._d, this._tx, this._ty ];\n\t},\n\n\tgetTranslation: function() {\n\t\treturn new Point(this._tx, this._ty);\n\t},\n\n\tgetScaling: function() {\n\t\treturn (this.decompose() || {}).scaling;\n\t},\n\n\tgetRotation: function() {\n\t\treturn (this.decompose() || {}).rotation;\n\t},\n\n\tapplyToContext: function(ctx) {\n\t\tif (!this.isIdentity()) {\n\t\t\tctx.transform(this._a, this._b, this._c, this._d,\n\t\t\t\t\tthis._tx, this._ty);\n\t\t}\n\t}\n}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) {\n\tvar part = Base.capitalize(key),\n\t\tprop = '_' + key;\n\tthis['get' + part] = function() {\n\t\treturn this[prop];\n\t};\n\tthis['set' + part] = function(value) {\n\t\tthis[prop] = value;\n\t\tthis._changed();\n\t};\n}, {}));\n\nvar Line = Base.extend({\n\t_class: 'Line',\n\n\tinitialize: function Line(arg0, arg1, arg2, arg3, arg4) {\n\t\tvar asVector = false;\n\t\tif (arguments.length >= 4) {\n\t\t\tthis._px = arg0;\n\t\t\tthis._py = arg1;\n\t\t\tthis._vx = arg2;\n\t\t\tthis._vy = arg3;\n\t\t\tasVector = arg4;\n\t\t} else {\n\t\t\tthis._px = arg0.x;\n\t\t\tthis._py = arg0.y;\n\t\t\tthis._vx = arg1.x;\n\t\t\tthis._vy = arg1.y;\n\t\t\tasVector = arg2;\n\t\t}\n\t\tif (!asVector) {\n\t\t\tthis._vx -= this._px;\n\t\t\tthis._vy -= this._py;\n\t\t}\n\t},\n\n\tgetPoint: function() {\n\t\treturn new Point(this._px, this._py);\n\t},\n\n\tgetVector: function() {\n\t\treturn new Point(this._vx, this._vy);\n\t},\n\n\tgetLength: function() {\n\t\treturn this.getVector().getLength();\n\t},\n\n\tintersect: function(line, isInfinite) {\n\t\treturn Line.intersect(\n\t\t\t\tthis._px, this._py, this._vx, this._vy,\n\t\t\t\tline._px, line._py, line._vx, line._vy,\n\t\t\t\ttrue, isInfinite);\n\t},\n\n\tgetSide: function(point, isInfinite) {\n\t\treturn Line.getSide(\n\t\t\t\tthis._px, this._py, this._vx, this._vy,\n\t\t\t\tpoint.x, point.y, true, isInfinite);\n\t},\n\n\tgetDistance: function(point) {\n\t\treturn Math.abs(Line.getSignedDistance(\n\t\t\t\tthis._px, this._py, this._vx, this._vy,\n\t\t\t\tpoint.x, point.y, true));\n\t},\n\n\tisCollinear: function(line) {\n\t\treturn Point.isCollinear(this._vx, this._vy, line._vx, line._vy);\n\t},\n\n\tisOrthogonal: function(line) {\n\t\treturn Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);\n\t},\n\n\tstatics: {\n\t\tintersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,\n\t\t\t\tisInfinite) {\n\t\t\tif (!asVector) {\n\t\t\t\tv1x -= p1x;\n\t\t\t\tv1y -= p1y;\n\t\t\t\tv2x -= p2x;\n\t\t\t\tv2y -= p2y;\n\t\t\t}\n\t\t\tvar cross = v1x * v2y - v1y * v2x;\n\t\t\tif (!Numerical.isZero(cross)) {\n\t\t\t\tvar dx = p1x - p2x,\n\t\t\t\t\tdy = p1y - p2y,\n\t\t\t\t\tu1 = (v2x * dy - v2y * dx) / cross,\n\t\t\t\t\tu2 = (v1x * dy - v1y * dx) / cross,\n\t\t\t\t\tepsilon = 1e-12,\n\t\t\t\t\tuMin = -epsilon,\n\t\t\t\t\tuMax = 1 + epsilon;\n\t\t\t\tif (isInfinite\n\t\t\t\t\t\t|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {\n\t\t\t\t\tif (!isInfinite) {\n\t\t\t\t\t\tu1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;\n\t\t\t\t\t}\n\t\t\t\t\treturn new Point(\n\t\t\t\t\t\t\tp1x + u1 * v1x,\n\t\t\t\t\t\t\tp1y + u1 * v1y);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tgetSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {\n\t\t\tif (!asVector) {\n\t\t\t\tvx -= px;\n\t\t\t\tvy -= py;\n\t\t\t}\n\t\t\tvar v2x = x - px,\n\t\t\t\tv2y = y - py,\n\t\t\t\tccw = v2x * vy - v2y * vx;\n\t\t\tif (ccw === 0 && !isInfinite) {\n\t\t\t\tccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);\n\t\t\t\tif (ccw >= 0 && ccw <= 1)\n\t\t\t\t\tccw = 0;\n\t\t\t}\n\t\t\treturn ccw < 0 ? -1 : ccw > 0 ? 1 : 0;\n\t\t},\n\n\t\tgetSignedDistance: function(px, py, vx, vy, x, y, asVector) {\n\t\t\tif (!asVector) {\n\t\t\t\tvx -= px;\n\t\t\t\tvy -= py;\n\t\t\t}\n\t\t\treturn vx === 0 ? vy > 0 ? x - px : px - x\n\t\t\t\t : vy === 0 ? vx < 0 ? y - py : py - y\n\t\t\t\t : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);\n\t\t}\n\t}\n});\n\nvar Project = PaperScopeItem.extend({\n\t_class: 'Project',\n\t_list: 'projects',\n\t_reference: 'project',\n\t_compactSerialize: true,\n\n\tinitialize: function Project(element) {\n\t\tPaperScopeItem.call(this, true);\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tthis._activeLayer = null;\n\t\tthis._currentStyle = new Style(null, null, this);\n\t\tthis._view = View.create(this,\n\t\t\t\telement || CanvasProvider.getCanvas(1, 1));\n\t\tthis._selectionItems = {};\n\t\tthis._selectionCount = 0;\n\t\tthis._updateVersion = 0;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this._children, options, true, dictionary);\n\t},\n\n\t_changed: function(flags, item) {\n\t\tif (flags & 1) {\n\t\t\tvar view = this._view;\n\t\t\tif (view) {\n\t\t\t\tview._needsUpdate = true;\n\t\t\t\tif (!view._requested && view._autoUpdate)\n\t\t\t\t\tview.requestUpdate();\n\t\t\t}\n\t\t}\n\t\tvar changes = this._changes;\n\t\tif (changes && item) {\n\t\t\tvar changesById = this._changesById,\n\t\t\t\tid = item._id,\n\t\t\t\tentry = changesById[id];\n\t\t\tif (entry) {\n\t\t\t\tentry.flags |= flags;\n\t\t\t} else {\n\t\t\t\tchanges.push(changesById[id] = { item: item, flags: flags });\n\t\t\t}\n\t\t}\n\t},\n\n\tclear: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = children.length - 1; i >= 0; i--)\n\t\t\tchildren[i].remove();\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._children.length;\n\t},\n\n\tremove: function remove() {\n\t\tif (!remove.base.call(this))\n\t\t\treturn false;\n\t\tif (this._view)\n\t\t\tthis._view.remove();\n\t\treturn true;\n\t},\n\n\tgetView: function() {\n\t\treturn this._view;\n\t},\n\n\tgetCurrentStyle: function() {\n\t\treturn this._currentStyle;\n\t},\n\n\tsetCurrentStyle: function(style) {\n\t\tthis._currentStyle.set(style);\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index;\n\t},\n\n\tgetOptions: function() {\n\t\treturn this._scope.settings;\n\t},\n\n\tgetLayers: function() {\n\t\treturn this._children;\n\t},\n\n\tgetActiveLayer: function() {\n\t\treturn this._activeLayer || new Layer({ project: this, insert: true });\n\t},\n\n\tgetSymbolDefinitions: function() {\n\t\tvar definitions = [],\n\t\t\tids = {};\n\t\tthis.getItems({\n\t\t\tclass: SymbolItem,\n\t\t\tmatch: function(item) {\n\t\t\t\tvar definition = item._definition,\n\t\t\t\t\tid = definition._id;\n\t\t\t\tif (!ids[id]) {\n\t\t\t\t\tids[id] = true;\n\t\t\t\t\tdefinitions.push(definition);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\treturn definitions;\n\t},\n\n\tgetSymbols: 'getSymbolDefinitions',\n\n\tgetSelectedItems: function() {\n\t\tvar selectionItems = this._selectionItems,\n\t\t\titems = [];\n\t\tfor (var id in selectionItems) {\n\t\t\tvar item = selectionItems[id],\n\t\t\t\tselection = item._selection;\n\t\t\tif (selection & 1 && item.isInserted()) {\n\t\t\t\titems.push(item);\n\t\t\t} else if (!selection) {\n\t\t\t\tthis._updateSelection(item);\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t},\n\n\t_updateSelection: function(item) {\n\t\tvar id = item._id,\n\t\t\tselectionItems = this._selectionItems;\n\t\tif (item._selection) {\n\t\t\tif (selectionItems[id] !== item) {\n\t\t\t\tthis._selectionCount++;\n\t\t\t\tselectionItems[id] = item;\n\t\t\t}\n\t\t} else if (selectionItems[id] === item) {\n\t\t\tthis._selectionCount--;\n\t\t\tdelete selectionItems[id];\n\t\t}\n\t},\n\n\tselectAll: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tchildren[i].setFullySelected(true);\n\t},\n\n\tdeselectAll: function() {\n\t\tvar selectionItems = this._selectionItems;\n\t\tfor (var i in selectionItems)\n\t\t\tselectionItems[i].setFullySelected(false);\n\t},\n\n\taddLayer: function(layer) {\n\t\treturn this.insertLayer(undefined, layer);\n\t},\n\n\tinsertLayer: function(index, layer) {\n\t\tif (layer instanceof Layer) {\n\t\t\tlayer._remove(false, true);\n\t\t\tBase.splice(this._children, [layer], index, 0);\n\t\t\tlayer._setProject(this, true);\n\t\t\tvar name = layer._name;\n\t\t\tif (name)\n\t\t\t\tlayer.setName(name);\n\t\t\tif (this._changes)\n\t\t\t\tlayer._changed(5);\n\t\t\tif (!this._activeLayer)\n\t\t\t\tthis._activeLayer = layer;\n\t\t} else {\n\t\t\tlayer = null;\n\t\t}\n\t\treturn layer;\n\t},\n\n\t_insertItem: function(index, item, _created) {\n\t\titem = this.insertLayer(index, item)\n\t\t\t\t|| (this._activeLayer || this._insertItem(undefined,\n\t\t\t\t\t\tnew Layer(Item.NO_INSERT), true))\n\t\t\t\t\t\t.insertChild(index, item);\n\t\tif (_created && item.activate)\n\t\t\titem.activate();\n\t\treturn item;\n\t},\n\n\tgetItems: function(options) {\n\t\treturn Item._getItems(this, options);\n\t},\n\n\tgetItem: function(options) {\n\t\treturn Item._getItems(this, options, null, null, true)[0] || null;\n\t},\n\n\timportJSON: function(json) {\n\t\tthis.activate();\n\t\tvar layer = this._activeLayer;\n\t\treturn Base.importJSON(json, layer && layer.isEmpty() && layer);\n\t},\n\n\tremoveOn: function(type) {\n\t\tvar sets = this._removeSets;\n\t\tif (sets) {\n\t\t\tif (type === 'mouseup')\n\t\t\t\tsets.mousedrag = null;\n\t\t\tvar set = sets[type];\n\t\t\tif (set) {\n\t\t\t\tfor (var id in set) {\n\t\t\t\t\tvar item = set[id];\n\t\t\t\t\tfor (var key in sets) {\n\t\t\t\t\t\tvar other = sets[key];\n\t\t\t\t\t\tif (other && other != set)\n\t\t\t\t\t\t\tdelete other[item._id];\n\t\t\t\t\t}\n\t\t\t\t\titem.remove();\n\t\t\t\t}\n\t\t\t\tsets[type] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\tdraw: function(ctx, matrix, pixelRatio) {\n\t\tthis._updateVersion++;\n\t\tctx.save();\n\t\tmatrix.applyToContext(ctx);\n\t\tvar children = this._children,\n\t\t\tparam = new Base({\n\t\t\t\toffset: new Point(0, 0),\n\t\t\t\tpixelRatio: pixelRatio,\n\t\t\t\tviewMatrix: matrix.isIdentity() ? null : matrix,\n\t\t\t\tmatrices: [new Matrix()],\n\t\t\t\tupdateMatrix: true\n\t\t\t});\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tchildren[i].draw(ctx, param);\n\t\t}\n\t\tctx.restore();\n\n\t\tif (this._selectionCount > 0) {\n\t\t\tctx.save();\n\t\t\tctx.strokeWidth = 1;\n\t\t\tvar items = this._selectionItems,\n\t\t\t\tsize = this._scope.settings.handleSize,\n\t\t\t\tversion = this._updateVersion;\n\t\t\tfor (var id in items) {\n\t\t\t\titems[id]._drawSelection(ctx, matrix, size, items, version);\n\t\t\t}\n\t\t\tctx.restore();\n\t\t}\n\t}\n});\n\nvar Item = Base.extend(Emitter, {\n\tstatics: {\n\t\textend: function extend(src) {\n\t\t\tif (src._serializeFields)\n\t\t\t\tsrc._serializeFields = Base.set({},\n\t\t\t\t\tthis.prototype._serializeFields, src._serializeFields);\n\t\t\treturn extend.base.apply(this, arguments);\n\t\t},\n\n\t\tNO_INSERT: { insert: false }\n\t},\n\n\t_class: 'Item',\n\t_name: null,\n\t_applyMatrix: true,\n\t_canApplyMatrix: true,\n\t_canScaleStroke: false,\n\t_pivot: null,\n\t_visible: true,\n\t_blendMode: 'normal',\n\t_opacity: 1,\n\t_locked: false,\n\t_guide: false,\n\t_clipMask: false,\n\t_selection: 0,\n\t_selectBounds: true,\n\t_selectChildren: false,\n\t_serializeFields: {\n\t\tname: null,\n\t\tapplyMatrix: null,\n\t\tmatrix: new Matrix(),\n\t\tpivot: null,\n\t\tvisible: true,\n\t\tblendMode: 'normal',\n\t\topacity: 1,\n\t\tlocked: false,\n\t\tguide: false,\n\t\tclipMask: false,\n\t\tselected: false,\n\t\tdata: {}\n\t}\n},\nnew function() {\n\tvar handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',\n\t\t\t'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'];\n\treturn Base.each(handlers,\n\t\tfunction(name) {\n\t\t\tthis._events[name] = {\n\t\t\t\tinstall: function(type) {\n\t\t\t\t\tthis.getView()._countItemEvent(type, 1);\n\t\t\t\t},\n\n\t\t\t\tuninstall: function(type) {\n\t\t\t\t\tthis.getView()._countItemEvent(type, -1);\n\t\t\t\t}\n\t\t\t};\n\t\t}, {\n\t\t\t_events: {\n\t\t\t\tonFrame: {\n\t\t\t\t\tinstall: function() {\n\t\t\t\t\t\tthis.getView()._animateItem(this, true);\n\t\t\t\t\t},\n\n\t\t\t\t\tuninstall: function() {\n\t\t\t\t\t\tthis.getView()._animateItem(this, false);\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tonLoad: {},\n\t\t\t\tonError: {}\n\t\t\t},\n\t\t\tstatics: {\n\t\t\t\t_itemHandlers: handlers\n\t\t\t}\n\t\t}\n\t);\n}, {\n\tinitialize: function Item() {\n\t},\n\n\t_initialize: function(props, point) {\n\t\tvar hasProps = props && Base.isPlainObject(props),\n\t\t\tinternal = hasProps && props.internal === true,\n\t\t\tmatrix = this._matrix = new Matrix(),\n\t\t\tproject = hasProps && props.project || paper.project,\n\t\t\tsettings = paper.settings;\n\t\tthis._id = internal ? null : UID.get();\n\t\tthis._parent = this._index = null;\n\t\tthis._applyMatrix = this._canApplyMatrix && settings.applyMatrix;\n\t\tif (point)\n\t\t\tmatrix.translate(point);\n\t\tmatrix._owner = this;\n\t\tthis._style = new Style(project._currentStyle, this, project);\n\t\tif (internal || hasProps && props.insert === false\n\t\t\t|| !settings.insertItems && !(hasProps && props.insert === true)) {\n\t\t\tthis._setProject(project);\n\t\t} else {\n\t\t\t(hasProps && props.parent || project)\n\t\t\t\t\t._insertItem(undefined, this, true);\n\t\t}\n\t\tif (hasProps && props !== Item.NO_INSERT) {\n\t\t\tBase.filter(this, props, {\n\t\t\t\tinternal: true, insert: true, project: true, parent: true\n\t\t\t});\n\t\t}\n\t\treturn hasProps;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar props = {},\n\t\t\tthat = this;\n\n\t\tfunction serialize(fields) {\n\t\t\tfor (var key in fields) {\n\t\t\t\tvar value = that[key];\n\t\t\t\tif (!Base.equals(value, key === 'leading'\n\t\t\t\t\t\t? fields.fontSize * 1.2 : fields[key])) {\n\t\t\t\t\tprops[key] = Base.serialize(value, options,\n\t\t\t\t\t\t\tkey !== 'data', dictionary);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tserialize(this._serializeFields);\n\t\tif (!(this instanceof Group))\n\t\t\tserialize(this._style._defaults);\n\t\treturn [ this._class, props ];\n\t},\n\n\t_changed: function(flags) {\n\t\tvar symbol = this._symbol,\n\t\t\tcacheParent = this._parent || symbol,\n\t\t\tproject = this._project;\n\t\tif (flags & 8) {\n\t\t\tthis._bounds = this._position = this._decomposed =\n\t\t\t\t\tthis._globalMatrix = undefined;\n\t\t}\n\t\tif (cacheParent\n\t\t\t\t&& (flags & 40)) {\n\t\t\tItem._clearBoundsCache(cacheParent);\n\t\t}\n\t\tif (flags & 2) {\n\t\t\tItem._clearBoundsCache(this);\n\t\t}\n\t\tif (project)\n\t\t\tproject._changed(flags, this);\n\t\tif (symbol)\n\t\t\tsymbol._changed(flags);\n\t},\n\n\tset: function(props) {\n\t\tif (props)\n\t\t\tthis._set(props);\n\t\treturn this;\n\t},\n\n\tgetId: function() {\n\t\treturn this._id;\n\t},\n\n\tgetName: function() {\n\t\treturn this._name;\n\t},\n\n\tsetName: function(name) {\n\n\t\tif (this._name)\n\t\t\tthis._removeNamed();\n\t\tif (name === (+name) + '')\n\t\t\tthrow new Error(\n\t\t\t\t\t'Names consisting only of numbers are not supported.');\n\t\tvar owner = this._getOwner();\n\t\tif (name && owner) {\n\t\t\tvar children = owner._children,\n\t\t\t\tnamedChildren = owner._namedChildren;\n\t\t\t(namedChildren[name] = namedChildren[name] || []).push(this);\n\t\t\tif (!(name in children))\n\t\t\t\tchildren[name] = this;\n\t\t}\n\t\tthis._name = name || undefined;\n\t\tthis._changed(128);\n\t},\n\n\tgetStyle: function() {\n\t\treturn this._style;\n\t},\n\n\tsetStyle: function(style) {\n\t\tthis.getStyle().set(style);\n\t}\n}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],\n\tfunction(name) {\n\t\tvar part = Base.capitalize(name),\n\t\t\tname = '_' + name;\n\t\tthis['get' + part] = function() {\n\t\t\treturn this[name];\n\t\t};\n\t\tthis['set' + part] = function(value) {\n\t\t\tif (value != this[name]) {\n\t\t\t\tthis[name] = value;\n\t\t\t\tthis._changed(name === '_locked'\n\t\t\t\t\t\t? 128 : 129);\n\t\t\t}\n\t\t};\n\t},\n{}), {\n\tbeans: true,\n\n\tgetSelection: function() {\n\t\treturn this._selection;\n\t},\n\n\tsetSelection: function(selection) {\n\t\tif (selection !== this._selection) {\n\t\t\tthis._selection = selection;\n\t\t\tvar project = this._project;\n\t\t\tif (project) {\n\t\t\t\tproject._updateSelection(this);\n\t\t\t\tthis._changed(129);\n\t\t\t}\n\t\t}\n\t},\n\n\tchangeSelection: function(flag, selected) {\n\t\tvar selection = this._selection;\n\t\tthis.setSelection(selected ? selection | flag : selection & ~flag);\n\t},\n\n\tisSelected: function() {\n\t\tif (this._selectChildren) {\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tif (children[i].isSelected())\n\t\t\t\t\treturn true;\n\t\t}\n\t\treturn !!(this._selection & 1);\n\t},\n\n\tsetSelected: function(selected) {\n\t\tif (this._selectChildren) {\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].setSelected(selected);\n\t\t}\n\t\tthis.changeSelection(1, selected);\n\t},\n\n\tisFullySelected: function() {\n\t\tvar children = this._children,\n\t\t\tselected = !!(this._selection & 1);\n\t\tif (children && selected) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tif (!children[i].isFullySelected())\n\t\t\t\t\treturn false;\n\t\t\treturn true;\n\t\t}\n\t\treturn selected;\n\t},\n\n\tsetFullySelected: function(selected) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].setFullySelected(selected);\n\t\t}\n\t\tthis.changeSelection(1, selected);\n\t},\n\n\tisClipMask: function() {\n\t\treturn this._clipMask;\n\t},\n\n\tsetClipMask: function(clipMask) {\n\t\tif (this._clipMask != (clipMask = !!clipMask)) {\n\t\t\tthis._clipMask = clipMask;\n\t\t\tif (clipMask) {\n\t\t\t\tthis.setFillColor(null);\n\t\t\t\tthis.setStrokeColor(null);\n\t\t\t}\n\t\t\tthis._changed(129);\n\t\t\tif (this._parent)\n\t\t\t\tthis._parent._changed(1024);\n\t\t}\n\t},\n\n\tgetData: function() {\n\t\tif (!this._data)\n\t\t\tthis._data = {};\n\t\treturn this._data;\n\t},\n\n\tsetData: function(data) {\n\t\tthis._data = data;\n\t},\n\n\tgetPosition: function(_dontLink) {\n\t\tvar position = this._position,\n\t\t\tctor = _dontLink ? Point : LinkedPoint;\n\t\tif (!position) {\n\t\t\tvar pivot = this._pivot;\n\t\t\tposition = this._position = pivot\n\t\t\t\t\t? this._matrix._transformPoint(pivot)\n\t\t\t\t\t: this.getBounds().getCenter(true);\n\t\t}\n\t\treturn new ctor(position.x, position.y, this, 'setPosition');\n\t},\n\n\tsetPosition: function() {\n\t\tthis.translate(Point.read(arguments).subtract(this.getPosition(true)));\n\t},\n\n\tgetPivot: function() {\n\t\tvar pivot = this._pivot;\n\t\treturn pivot\n\t\t\t\t? new LinkedPoint(pivot.x, pivot.y, this, 'setPivot')\n\t\t\t\t: null;\n\t},\n\n\tsetPivot: function() {\n\t\tthis._pivot = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tthis._position = undefined;\n\t}\n}, Base.each({\n\t\tgetStrokeBounds: { stroke: true },\n\t\tgetHandleBounds: { handle: true },\n\t\tgetInternalBounds: { internal: true }\n\t},\n\tfunction(options, key) {\n\t\tthis[key] = function(matrix) {\n\t\t\treturn this.getBounds(matrix, options);\n\t\t};\n\t},\n{\n\tbeans: true,\n\n\tgetBounds: function(matrix, options) {\n\t\tvar hasMatrix = options || matrix instanceof Matrix,\n\t\t\topts = Base.set({}, hasMatrix ? options : matrix,\n\t\t\t\t\tthis._boundsOptions);\n\t\tif (!opts.stroke || this.getStrokeScaling())\n\t\t\topts.cacheItem = this;\n\t\tvar bounds = this._getCachedBounds(hasMatrix && matrix, opts);\n\t\treturn !arguments.length\n\t\t\t\t? new LinkedRectangle(bounds.x, bounds.y, bounds.width,\n\t\t\t\t\t\tbounds.height, this, 'setBounds')\n\t\t\t\t: bounds;\n\t},\n\n\tsetBounds: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tbounds = this.getBounds(),\n\t\t\t_matrix = this._matrix,\n\t\t\tmatrix = new Matrix(),\n\t\t\tcenter = rect.getCenter();\n\t\tmatrix.translate(center);\n\t\tif (rect.width != bounds.width || rect.height != bounds.height) {\n\t\t\tif (!_matrix.isInvertible()) {\n\t\t\t\t_matrix.set(_matrix._backup\n\t\t\t\t\t\t|| new Matrix().translate(_matrix.getTranslation()));\n\t\t\t\tbounds = this.getBounds();\n\t\t\t}\n\t\t\tmatrix.scale(\n\t\t\t\t\tbounds.width !== 0 ? rect.width / bounds.width : 0,\n\t\t\t\t\tbounds.height !== 0 ? rect.height / bounds.height : 0);\n\t\t}\n\t\tcenter = bounds.getCenter();\n\t\tmatrix.translate(-center.x, -center.y);\n\t\tthis.transform(matrix);\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar children = this._children;\n\t\tif (!children || !children.length)\n\t\t\treturn new Rectangle();\n\t\tItem._updateBoundsCache(this, options.cacheItem);\n\t\treturn Item._getBounds(children, matrix, options);\n\t},\n\n\t_getCachedBounds: function(matrix, options) {\n\t\tmatrix = matrix && matrix._orNullIfIdentity();\n\t\tvar internal = options.internal,\n\t\t\tcacheItem = options.cacheItem,\n\t\t\t_matrix = internal ? null : this._matrix._orNullIfIdentity(),\n\t\t\tcacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [\n\t\t\t\toptions.stroke ? 1 : 0,\n\t\t\t\toptions.handle ? 1 : 0,\n\t\t\t\tinternal ? 1 : 0\n\t\t\t].join('');\n\t\tItem._updateBoundsCache(this._parent || this._symbol, cacheItem);\n\t\tif (cacheKey && this._bounds && cacheKey in this._bounds)\n\t\t\treturn this._bounds[cacheKey].rect.clone();\n\t\tvar bounds = this._getBounds(matrix || _matrix, options);\n\t\tif (cacheKey) {\n\t\t\tif (!this._bounds)\n\t\t\t\tthis._bounds = {};\n\t\t\tvar cached = this._bounds[cacheKey] = {\n\t\t\t\trect: bounds.clone(),\n\t\t\t\tinternal: options.internal\n\t\t\t};\n\t\t}\n\t\treturn bounds;\n\t},\n\n\t_getStrokeMatrix: function(matrix, options) {\n\t\tvar parent = this.getStrokeScaling() ? null\n\t\t\t\t: options && options.internal ? this\n\t\t\t\t\t: this._parent || this._symbol && this._symbol._item,\n\t\t\tmx = parent ? parent.getViewMatrix().invert() : matrix;\n\t\treturn mx && mx._shiftless();\n\t},\n\n\tstatics: {\n\t\t_updateBoundsCache: function(parent, item) {\n\t\t\tif (parent && item) {\n\t\t\t\tvar id = item._id,\n\t\t\t\t\tref = parent._boundsCache = parent._boundsCache || {\n\t\t\t\t\t\tids: {},\n\t\t\t\t\t\tlist: []\n\t\t\t\t\t};\n\t\t\t\tif (!ref.ids[id]) {\n\t\t\t\t\tref.list.push(item);\n\t\t\t\t\tref.ids[id] = item;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_clearBoundsCache: function(item) {\n\t\t\tvar cache = item._boundsCache;\n\t\t\tif (cache) {\n\t\t\t\titem._bounds = item._position = item._boundsCache = undefined;\n\t\t\t\tfor (var i = 0, list = cache.list, l = list.length; i < l; i++){\n\t\t\t\t\tvar other = list[i];\n\t\t\t\t\tif (other !== item) {\n\t\t\t\t\t\tother._bounds = other._position = undefined;\n\t\t\t\t\t\tif (other._boundsCache)\n\t\t\t\t\t\t\tItem._clearBoundsCache(other);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_getBounds: function(items, matrix, options) {\n\t\t\tvar x1 = Infinity,\n\t\t\t\tx2 = -x1,\n\t\t\t\ty1 = x1,\n\t\t\t\ty2 = x2;\n\t\t\toptions = options || {};\n\t\t\tfor (var i = 0, l = items.length; i < l; i++) {\n\t\t\t\tvar item = items[i];\n\t\t\t\tif (item._visible && !item.isEmpty()) {\n\t\t\t\t\tvar rect = item._getCachedBounds(\n\t\t\t\t\t\tmatrix && matrix.appended(item._matrix), options);\n\t\t\t\t\tx1 = Math.min(rect.x, x1);\n\t\t\t\t\ty1 = Math.min(rect.y, y1);\n\t\t\t\t\tx2 = Math.max(rect.x + rect.width, x2);\n\t\t\t\t\ty2 = Math.max(rect.y + rect.height, y2);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn isFinite(x1)\n\t\t\t\t\t? new Rectangle(x1, y1, x2 - x1, y2 - y1)\n\t\t\t\t\t: new Rectangle();\n\t\t}\n\t}\n\n}), {\n\tbeans: true,\n\n\t_decompose: function() {\n\t\treturn this._decomposed || (this._decomposed = this._matrix.decompose());\n\t},\n\n\tgetRotation: function() {\n\t\tvar decomposed = this._decompose();\n\t\treturn decomposed && decomposed.rotation;\n\t},\n\n\tsetRotation: function(rotation) {\n\t\tvar current = this.getRotation();\n\t\tif (current != null && rotation != null) {\n\t\t\tthis.rotate(rotation - current);\n\t\t}\n\t},\n\n\tgetScaling: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\tscaling = decomposed && decomposed.scaling;\n\t\treturn scaling\n\t\t\t\t? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')\n\t\t\t\t: undefined;\n\t},\n\n\tsetScaling: function() {\n\t\tvar current = this.getScaling(),\n\t\t\tscaling = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tif (current && scaling) {\n\t\t\tthis.scale(scaling.x / current.x, scaling.y / current.y);\n\t\t}\n\t},\n\n\tgetMatrix: function() {\n\t\treturn this._matrix;\n\t},\n\n\tsetMatrix: function() {\n\t\tvar matrix = this._matrix;\n\t\tmatrix.initialize.apply(matrix, arguments);\n\t},\n\n\tgetGlobalMatrix: function(_dontClone) {\n\t\tvar matrix = this._globalMatrix,\n\t\t\tupdateVersion = this._project._updateVersion;\n\t\tif (matrix && matrix._updateVersion !== updateVersion)\n\t\t\tmatrix = null;\n\t\tif (!matrix) {\n\t\t\tmatrix = this._globalMatrix = this._matrix.clone();\n\t\t\tvar parent = this._parent;\n\t\t\tif (parent)\n\t\t\t\tmatrix.prepend(parent.getGlobalMatrix(true));\n\t\t\tmatrix._updateVersion = updateVersion;\n\t\t}\n\t\treturn _dontClone ? matrix : matrix.clone();\n\t},\n\n\tgetViewMatrix: function() {\n\t\treturn this.getGlobalMatrix().prepend(this.getView()._matrix);\n\t},\n\n\tgetApplyMatrix: function() {\n\t\treturn this._applyMatrix;\n\t},\n\n\tsetApplyMatrix: function(apply) {\n\t\tif (this._applyMatrix = this._canApplyMatrix && !!apply)\n\t\t\tthis.transform(null, true);\n\t},\n\n\tgetTransformContent: '#getApplyMatrix',\n\tsetTransformContent: '#setApplyMatrix',\n}, {\n\tgetProject: function() {\n\t\treturn this._project;\n\t},\n\n\t_setProject: function(project, installEvents) {\n\t\tif (this._project !== project) {\n\t\t\tif (this._project)\n\t\t\t\tthis._installEvents(false);\n\t\t\tthis._project = project;\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children && children.length; i < l; i++)\n\t\t\t\tchildren[i]._setProject(project);\n\t\t\tinstallEvents = true;\n\t\t}\n\t\tif (installEvents)\n\t\t\tthis._installEvents(true);\n\t},\n\n\tgetView: function() {\n\t\treturn this._project._view;\n\t},\n\n\t_installEvents: function _installEvents(install) {\n\t\t_installEvents.base.call(this, install);\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children && children.length; i < l; i++)\n\t\t\tchildren[i]._installEvents(install);\n\t},\n\n\tgetLayer: function() {\n\t\tvar parent = this;\n\t\twhile (parent = parent._parent) {\n\t\t\tif (parent instanceof Layer)\n\t\t\t\treturn parent;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetParent: function() {\n\t\treturn this._parent;\n\t},\n\n\tsetParent: function(item) {\n\t\treturn item.addChild(this);\n\t},\n\n\t_getOwner: '#getParent',\n\n\tgetChildren: function() {\n\t\treturn this._children;\n\t},\n\n\tsetChildren: function(items) {\n\t\tthis.removeChildren();\n\t\tthis.addChildren(items);\n\t},\n\n\tgetFirstChild: function() {\n\t\treturn this._children && this._children[0] || null;\n\t},\n\n\tgetLastChild: function() {\n\t\treturn this._children && this._children[this._children.length - 1]\n\t\t\t\t|| null;\n\t},\n\n\tgetNextSibling: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner && owner._children[this._index + 1] || null;\n\t},\n\n\tgetPreviousSibling: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner && owner._children[this._index - 1] || null;\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index;\n\t},\n\n\tequals: function(item) {\n\t\treturn item === this || item && this._class === item._class\n\t\t\t\t&& this._style.equals(item._style)\n\t\t\t\t&& this._matrix.equals(item._matrix)\n\t\t\t\t&& this._locked === item._locked\n\t\t\t\t&& this._visible === item._visible\n\t\t\t\t&& this._blendMode === item._blendMode\n\t\t\t\t&& this._opacity === item._opacity\n\t\t\t\t&& this._clipMask === item._clipMask\n\t\t\t\t&& this._guide === item._guide\n\t\t\t\t&& this._equals(item)\n\t\t\t\t|| false;\n\t},\n\n\t_equals: function(item) {\n\t\treturn Base.equals(this._children, item._children);\n\t},\n\n\tclone: function(options) {\n\t\tvar copy = new this.constructor(Item.NO_INSERT),\n\t\t\tchildren = this._children,\n\t\t\tinsert = Base.pick(options ? options.insert : undefined,\n\t\t\t\t\toptions === undefined || options === true),\n\t\t\tdeep = Base.pick(options ? options.deep : undefined, true);\n\t\tif (children)\n\t\t\tcopy.copyAttributes(this);\n\t\tif (!children || deep)\n\t\t\tcopy.copyContent(this);\n\t\tif (!children)\n\t\t\tcopy.copyAttributes(this);\n\t\tif (insert)\n\t\t\tcopy.insertAbove(this);\n\t\tvar name = this._name,\n\t\t\tparent = this._parent;\n\t\tif (name && parent) {\n\t\t\tvar children = parent._children,\n\t\t\t\torig = name,\n\t\t\t\ti = 1;\n\t\t\twhile (children[name])\n\t\t\t\tname = orig + ' ' + (i++);\n\t\t\tif (name !== orig)\n\t\t\t\tcopy.setName(name);\n\t\t}\n\t\treturn copy;\n\t},\n\n\tcopyContent: function(source) {\n\t\tvar children = source._children;\n\t\tfor (var i = 0, l = children && children.length; i < l; i++) {\n\t\t\tthis.addChild(children[i].clone(false), true);\n\t\t}\n\t},\n\n\tcopyAttributes: function(source, excludeMatrix) {\n\t\tthis.setStyle(source._style);\n\t\tvar keys = ['_locked', '_visible', '_blendMode', '_opacity',\n\t\t\t\t'_clipMask', '_guide'];\n\t\tfor (var i = 0, l = keys.length; i < l; i++) {\n\t\t\tvar key = keys[i];\n\t\t\tif (source.hasOwnProperty(key))\n\t\t\t\tthis[key] = source[key];\n\t\t}\n\t\tif (!excludeMatrix)\n\t\t\tthis._matrix.set(source._matrix);\n\t\tthis.setApplyMatrix(source._applyMatrix);\n\t\tthis.setPivot(source._pivot);\n\t\tthis.setSelection(source._selection);\n\t\tvar data = source._data,\n\t\t\tname = source._name;\n\t\tthis._data = data ? Base.clone(data) : null;\n\t\tif (name)\n\t\t\tthis.setName(name);\n\t},\n\n\trasterize: function(resolution, insert) {\n\t\tvar bounds = this.getStrokeBounds(),\n\t\t\tscale = (resolution || this.getView().getResolution()) / 72,\n\t\t\ttopLeft = bounds.getTopLeft().floor(),\n\t\t\tbottomRight = bounds.getBottomRight().ceil(),\n\t\t\tsize = new Size(bottomRight.subtract(topLeft)),\n\t\t\traster = new Raster(Item.NO_INSERT);\n\t\tif (!size.isZero()) {\n\t\t\tvar canvas = CanvasProvider.getCanvas(size.multiply(scale)),\n\t\t\t\tctx = canvas.getContext('2d'),\n\t\t\t\tmatrix = new Matrix().scale(scale).translate(topLeft.negate());\n\t\t\tctx.save();\n\t\t\tmatrix.applyToContext(ctx);\n\t\t\tthis.draw(ctx, new Base({ matrices: [matrix] }));\n\t\t\tctx.restore();\n\t\t\traster.setCanvas(canvas);\n\t\t}\n\t\traster.transform(new Matrix().translate(topLeft.add(size.divide(2)))\n\t\t\t\t.scale(1 / scale));\n\t\tif (insert === undefined || insert)\n\t\t\traster.insertAbove(this);\n\t\treturn raster;\n\t},\n\n\tcontains: function() {\n\t\treturn !!this._contains(\n\t\t\t\tthis._matrix._inverseTransform(Point.read(arguments)));\n\t},\n\n\t_contains: function(point) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\t\tif (children[i].contains(point))\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn point.isInside(this.getInternalBounds());\n\t},\n\n\tisInside: function() {\n\t\treturn Rectangle.read(arguments).contains(this.getBounds());\n\t},\n\n\t_asPathItem: function() {\n\t\treturn new Path.Rectangle({\n\t\t\trectangle: this.getInternalBounds(),\n\t\t\tmatrix: this._matrix,\n\t\t\tinsert: false,\n\t\t});\n\t},\n\n\tintersects: function(item, _matrix) {\n\t\tif (!(item instanceof Item))\n\t\t\treturn false;\n\t\treturn this._asPathItem().getIntersections(item._asPathItem(), null,\n\t\t\t\t_matrix, true).length > 0;\n\t}\n},\nnew function() {\n\tfunction hitTest() {\n\t\treturn this._hitTest(\n\t\t\t\tPoint.read(arguments),\n\t\t\t\tHitResult.getOptions(arguments));\n\t}\n\n\tfunction hitTestAll() {\n\t\tvar point = Point.read(arguments),\n\t\t\toptions = HitResult.getOptions(arguments),\n\t\t\tcallback = options.match,\n\t\t\tresults = [];\n\t\toptions = Base.set({}, options, {\n\t\t\tmatch: function(hit) {\n\t\t\t\tif (!callback || callback(hit))\n\t\t\t\t\tresults.push(hit);\n\t\t\t}\n\t\t});\n\t\tthis._hitTest(point, options);\n\t\treturn results;\n\t}\n\n\tfunction hitTestChildren(point, options, viewMatrix, _exclude) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\t\tvar child = children[i];\n\t\t\t\tvar res = child !== _exclude && child._hitTest(point, options,\n\t\t\t\t\t\tviewMatrix);\n\t\t\t\tif (res)\n\t\t\t\t\treturn res;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tProject.inject({\n\t\thitTest: hitTest,\n\t\thitTestAll: hitTestAll,\n\t\t_hitTest: hitTestChildren\n\t});\n\n\treturn {\n\t\thitTest: hitTest,\n\t\thitTestAll: hitTestAll,\n\t\t_hitTestChildren: hitTestChildren,\n\t};\n}, {\n\n\t_hitTest: function(point, options, parentViewMatrix) {\n\t\tif (this._locked || !this._visible || this._guide && !options.guides\n\t\t\t\t|| this.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar matrix = this._matrix,\n\t\t\tviewMatrix = parentViewMatrix\n\t\t\t\t\t? parentViewMatrix.appended(matrix)\n\t\t\t\t\t: this.getGlobalMatrix().prepend(this.getView()._matrix),\n\t\t\tstrokeMatrix = this.getStrokeScaling()\n\t\t\t\t\t? null\n\t\t\t\t\t: viewMatrix.inverted()._shiftless(),\n\t\t\ttolerance = Math.max(options.tolerance, 1e-6),\n\t\t\ttolerancePadding = options._tolerancePadding = new Size(\n\t\t\t\t\tPath._getStrokePadding(tolerance, strokeMatrix));\n\t\tpoint = matrix._inverseTransform(point);\n\t\tif (!point || !this._children &&\n\t\t\t!this.getBounds({ internal: true, stroke: true, handle: true })\n\t\t\t\t.expand(tolerancePadding.multiply(2))._containsPoint(point)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar checkSelf = !(options.guides && !this._guide\n\t\t\t\t|| options.selected && !this.isSelected()\n\t\t\t\t|| options.type && options.type !== Base.hyphenate(this._class)\n\t\t\t\t|| options.class && !(this instanceof options.class)),\n\t\t\tcallback = options.match,\n\t\t\tthat = this,\n\t\t\tbounds,\n\t\t\tres;\n\n\t\tfunction match(hit) {\n\t\t\treturn !callback || hit && callback(hit) ? hit : null;\n\t\t}\n\n\t\tfunction checkBounds(type, part) {\n\t\t\tvar pt = bounds['get' + part]();\n\t\t\tif (point.subtract(pt).divide(tolerancePadding).length <= 1) {\n\t\t\t\treturn new HitResult(type, that,\n\t\t\t\t\t\t{ name: Base.hyphenate(part), point: pt });\n\t\t\t}\n\t\t}\n\n\t\tif (checkSelf && (options.center || options.bounds) && this._parent) {\n\t\t\tbounds = this.getInternalBounds();\n\t\t\tif (options.center) {\n\t\t\t\tres = checkBounds('center', 'Center');\n\t\t\t}\n\t\t\tif (!res && options.bounds) {\n\t\t\t\tvar points = [\n\t\t\t\t\t'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',\n\t\t\t\t\t'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'\n\t\t\t\t];\n\t\t\t\tfor (var i = 0; i < 8 && !res; i++) {\n\t\t\t\t\tres = checkBounds('bounds', points[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tres = match(res);\n\t\t}\n\n\t\tif (!res) {\n\t\t\tres = this._hitTestChildren(point, options, viewMatrix)\n\t\t\t\t|| checkSelf\n\t\t\t\t\t&& match(this._hitTestSelf(point, options, viewMatrix,\n\t\t\t\t\t\tstrokeMatrix))\n\t\t\t\t|| null;\n\t\t}\n\t\tif (res && res.point) {\n\t\t\tres.point = matrix.transform(res.point);\n\t\t}\n\t\treturn res;\n\t},\n\n\t_hitTestSelf: function(point, options) {\n\t\tif (options.fill && this.hasFill() && this._contains(point))\n\t\t\treturn new HitResult('fill', this);\n\t},\n\n\tmatches: function(name, compare) {\n\t\tfunction matchObject(obj1, obj2) {\n\t\t\tfor (var i in obj1) {\n\t\t\t\tif (obj1.hasOwnProperty(i)) {\n\t\t\t\t\tvar val1 = obj1[i],\n\t\t\t\t\t\tval2 = obj2[i];\n\t\t\t\t\tif (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {\n\t\t\t\t\t\tif (!matchObject(val1, val2))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t} else if (!Base.equals(val1, val2)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tvar type = typeof name;\n\t\tif (type === 'object') {\n\t\t\tfor (var key in name) {\n\t\t\t\tif (name.hasOwnProperty(key) && !this.matches(key, name[key]))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t} else if (type === 'function') {\n\t\t\treturn name(this);\n\t\t} else if (name === 'match') {\n\t\t\treturn compare(this);\n\t\t} else {\n\t\t\tvar value = /^(empty|editable)$/.test(name)\n\t\t\t\t\t? this['is' + Base.capitalize(name)]()\n\t\t\t\t\t: name === 'type'\n\t\t\t\t\t\t? Base.hyphenate(this._class)\n\t\t\t\t\t\t: this[name];\n\t\t\tif (name === 'class') {\n\t\t\t\tif (typeof compare === 'function')\n\t\t\t\t\treturn this instanceof compare;\n\t\t\t\tvalue = this._class;\n\t\t\t}\n\t\t\tif (typeof compare === 'function') {\n\t\t\t\treturn !!compare(value);\n\t\t\t} else if (compare) {\n\t\t\t\tif (compare.test) {\n\t\t\t\t\treturn compare.test(value);\n\t\t\t\t} else if (Base.isPlainObject(compare)) {\n\t\t\t\t\treturn matchObject(compare, value);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Base.equals(value, compare);\n\t\t}\n\t},\n\n\tgetItems: function(options) {\n\t\treturn Item._getItems(this, options, this._matrix);\n\t},\n\n\tgetItem: function(options) {\n\t\treturn Item._getItems(this, options, this._matrix, null, true)[0]\n\t\t\t\t|| null;\n\t},\n\n\tstatics: {\n\t\t_getItems: function _getItems(item, options, matrix, param, firstOnly) {\n\t\t\tif (!param) {\n\t\t\t\tvar obj = typeof options === 'object' && options,\n\t\t\t\t\toverlapping = obj && obj.overlapping,\n\t\t\t\t\tinside = obj && obj.inside,\n\t\t\t\t\tbounds = overlapping || inside,\n\t\t\t\t\trect = bounds && Rectangle.read([bounds]);\n\t\t\t\tparam = {\n\t\t\t\t\titems: [],\n\t\t\t\t\trecursive: obj && obj.recursive !== false,\n\t\t\t\t\tinside: !!inside,\n\t\t\t\t\toverlapping: !!overlapping,\n\t\t\t\t\trect: rect,\n\t\t\t\t\tpath: overlapping && new Path.Rectangle({\n\t\t\t\t\t\trectangle: rect,\n\t\t\t\t\t\tinsert: false\n\t\t\t\t\t})\n\t\t\t\t};\n\t\t\t\tif (obj) {\n\t\t\t\t\toptions = Base.filter({}, options, {\n\t\t\t\t\t\trecursive: true, inside: true, overlapping: true\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar children = item._children,\n\t\t\t\titems = param.items,\n\t\t\t\trect = param.rect;\n\t\t\tmatrix = rect && (matrix || new Matrix());\n\t\t\tfor (var i = 0, l = children && children.length; i < l; i++) {\n\t\t\t\tvar child = children[i],\n\t\t\t\t\tchildMatrix = matrix && matrix.appended(child._matrix),\n\t\t\t\t\tadd = true;\n\t\t\t\tif (rect) {\n\t\t\t\t\tvar bounds = child.getBounds(childMatrix);\n\t\t\t\t\tif (!rect.intersects(bounds))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif (!(rect.contains(bounds)\n\t\t\t\t\t\t\t|| param.overlapping && (bounds.contains(rect)\n\t\t\t\t\t\t\t\t|| param.path.intersects(child, childMatrix))))\n\t\t\t\t\t\tadd = false;\n\t\t\t\t}\n\t\t\t\tif (add && child.matches(options)) {\n\t\t\t\t\titems.push(child);\n\t\t\t\t\tif (firstOnly)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (param.recursive !== false) {\n\t\t\t\t\t_getItems(child, options, childMatrix, param, firstOnly);\n\t\t\t\t}\n\t\t\t\tif (firstOnly && items.length > 0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn items;\n\t\t}\n\t}\n}, {\n\n\timportJSON: function(json) {\n\t\tvar res = Base.importJSON(json, this);\n\t\treturn res !== this ? this.addChild(res) : res;\n\t},\n\n\taddChild: function(item) {\n\t\treturn this.insertChild(undefined, item);\n\t},\n\n\tinsertChild: function(index, item) {\n\t\tvar res = item ? this.insertChildren(index, [item]) : null;\n\t\treturn res && res[0];\n\t},\n\n\taddChildren: function(items) {\n\t\treturn this.insertChildren(this._children.length, items);\n\t},\n\n\tinsertChildren: function(index, items) {\n\t\tvar children = this._children;\n\t\tif (children && items && items.length > 0) {\n\t\t\titems = Base.slice(items);\n\t\t\tfor (var i = items.length - 1; i >= 0; i--) {\n\t\t\t\tvar item = items[i];\n\t\t\t\tif (!item) {\n\t\t\t\t\titems.splice(i, 1);\n\t\t\t\t} else {\n\t\t\t\t\titem._remove(false, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tBase.splice(children, items, index, 0);\n\t\t\tvar project = this._project,\n\t\t\t\tnotifySelf = project._changes;\n\t\t\tfor (var i = 0, l = items.length; i < l; i++) {\n\t\t\t\tvar item = items[i],\n\t\t\t\t\tname = item._name;\n\t\t\t\titem._parent = this;\n\t\t\t\titem._setProject(project, true);\n\t\t\t\tif (name)\n\t\t\t\t\titem.setName(name);\n\t\t\t\tif (notifySelf)\n\t\t\t\t\tthis._changed(5);\n\t\t\t}\n\t\t\tthis._changed(11);\n\t\t} else {\n\t\t\titems = null;\n\t\t}\n\t\treturn items;\n\t},\n\n\t_insertItem: '#insertChild',\n\n\t_insertAt: function(item, offset) {\n\t\tvar owner = item && item._getOwner(),\n\t\t\tres = item !== this && owner ? this : null;\n\t\tif (res) {\n\t\t\tres._remove(false, true);\n\t\t\towner._insertItem(item._index + offset, res);\n\t\t}\n\t\treturn res;\n\t},\n\n\tinsertAbove: function(item) {\n\t\treturn this._insertAt(item, 1);\n\t},\n\n\tinsertBelow: function(item) {\n\t\treturn this._insertAt(item, 0);\n\t},\n\n\tsendToBack: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner ? owner._insertItem(0, this) : null;\n\t},\n\n\tbringToFront: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner ? owner._insertItem(undefined, this) : null;\n\t},\n\n\tappendTop: '#addChild',\n\n\tappendBottom: function(item) {\n\t\treturn this.insertChild(0, item);\n\t},\n\n\tmoveAbove: '#insertAbove',\n\n\tmoveBelow: '#insertBelow',\n\n\tcopyTo: function(owner) {\n\t\treturn owner._insertItem(undefined, this.clone(false));\n\t},\n\n\treduce: function(options) {\n\t\tvar children = this._children;\n\t\tif (children && children.length === 1) {\n\t\t\tvar child = children[0].reduce(options);\n\t\t\tif (this._parent) {\n\t\t\t\tchild.insertAbove(this);\n\t\t\t\tthis.remove();\n\t\t\t} else {\n\t\t\t\tchild.remove();\n\t\t\t}\n\t\t\treturn child;\n\t\t}\n\t\treturn this;\n\t},\n\n\t_removeNamed: function() {\n\t\tvar owner = this._getOwner();\n\t\tif (owner) {\n\t\t\tvar children = owner._children,\n\t\t\t\tnamedChildren = owner._namedChildren,\n\t\t\t\tname = this._name,\n\t\t\t\tnamedArray = namedChildren[name],\n\t\t\t\tindex = namedArray ? namedArray.indexOf(this) : -1;\n\t\t\tif (index !== -1) {\n\t\t\t\tif (children[name] == this)\n\t\t\t\t\tdelete children[name];\n\t\t\t\tnamedArray.splice(index, 1);\n\t\t\t\tif (namedArray.length) {\n\t\t\t\t\tchildren[name] = namedArray[0];\n\t\t\t\t} else {\n\t\t\t\t\tdelete namedChildren[name];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_remove: function(notifySelf, notifyParent) {\n\t\tvar owner = this._getOwner(),\n\t\t\tproject = this._project,\n\t\t\tindex = this._index;\n\t\tif (owner) {\n\t\t\tif (index != null) {\n\t\t\t\tif (project._activeLayer === this)\n\t\t\t\t\tproject._activeLayer = this.getNextSibling()\n\t\t\t\t\t\t\t|| this.getPreviousSibling();\n\t\t\t\tBase.splice(owner._children, null, index, 1);\n\t\t\t}\n\t\t\tif (this._name)\n\t\t\t\tthis._removeNamed();\n\t\t\tthis._installEvents(false);\n\t\t\tif (notifySelf && project._changes)\n\t\t\t\tthis._changed(5);\n\t\t\tif (notifyParent)\n\t\t\t\towner._changed(11, this);\n\t\t\tthis._parent = null;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tremove: function() {\n\t\treturn this._remove(true, true);\n\t},\n\n\treplaceWith: function(item) {\n\t\tvar ok = item && item.insertBelow(this);\n\t\tif (ok)\n\t\t\tthis.remove();\n\t\treturn ok;\n\t},\n\n\tremoveChildren: function(start, end) {\n\t\tif (!this._children)\n\t\t\treturn null;\n\t\tstart = start || 0;\n\t\tend = Base.pick(end, this._children.length);\n\t\tvar removed = Base.splice(this._children, null, start, end - start);\n\t\tfor (var i = removed.length - 1; i >= 0; i--) {\n\t\t\tremoved[i]._remove(true, false);\n\t\t}\n\t\tif (removed.length > 0)\n\t\t\tthis._changed(11);\n\t\treturn removed;\n\t},\n\n\tclear: '#removeChildren',\n\n\treverseChildren: function() {\n\t\tif (this._children) {\n\t\t\tthis._children.reverse();\n\t\t\tfor (var i = 0, l = this._children.length; i < l; i++)\n\t\t\t\tthis._children[i]._index = i;\n\t\t\tthis._changed(11);\n\t\t}\n\t},\n\n\tisEmpty: function() {\n\t\tvar children = this._children;\n\t\treturn !children || !children.length;\n\t},\n\n\tisEditable: function() {\n\t\tvar item = this;\n\t\twhile (item) {\n\t\t\tif (!item._visible || item._locked)\n\t\t\t\treturn false;\n\t\t\titem = item._parent;\n\t\t}\n\t\treturn true;\n\t},\n\n\thasFill: function() {\n\t\treturn this.getStyle().hasFill();\n\t},\n\n\thasStroke: function() {\n\t\treturn this.getStyle().hasStroke();\n\t},\n\n\thasShadow: function() {\n\t\treturn this.getStyle().hasShadow();\n\t},\n\n\t_getOrder: function(item) {\n\t\tfunction getList(item) {\n\t\t\tvar list = [];\n\t\t\tdo {\n\t\t\t\tlist.unshift(item);\n\t\t\t} while (item = item._parent);\n\t\t\treturn list;\n\t\t}\n\t\tvar list1 = getList(this),\n\t\t\tlist2 = getList(item);\n\t\tfor (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {\n\t\t\tif (list1[i] != list2[i]) {\n\t\t\t\treturn list1[i]._index < list2[i]._index ? 1 : -1;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t},\n\n\thasChildren: function() {\n\t\treturn this._children && this._children.length > 0;\n\t},\n\n\tisInserted: function() {\n\t\treturn this._parent ? this._parent.isInserted() : false;\n\t},\n\n\tisAbove: function(item) {\n\t\treturn this._getOrder(item) === -1;\n\t},\n\n\tisBelow: function(item) {\n\t\treturn this._getOrder(item) === 1;\n\t},\n\n\tisParent: function(item) {\n\t\treturn this._parent === item;\n\t},\n\n\tisChild: function(item) {\n\t\treturn item && item._parent === this;\n\t},\n\n\tisDescendant: function(item) {\n\t\tvar parent = this;\n\t\twhile (parent = parent._parent) {\n\t\t\tif (parent === item)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tisAncestor: function(item) {\n\t\treturn item ? item.isDescendant(this) : false;\n\t},\n\n\tisSibling: function(item) {\n\t\treturn this._parent === item._parent;\n\t},\n\n\tisGroupedWith: function(item) {\n\t\tvar parent = this._parent;\n\t\twhile (parent) {\n\t\t\tif (parent._parent\n\t\t\t\t&& /^(Group|Layer|CompoundPath)$/.test(parent._class)\n\t\t\t\t&& item.isDescendant(parent))\n\t\t\t\t\treturn true;\n\t\t\tparent = parent._parent;\n\t\t}\n\t\treturn false;\n\t},\n\n}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {\n\tvar rotate = key === 'rotate';\n\tthis[key] = function() {\n\t\tvar value = (rotate ? Base : Point).read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\treturn this.transform(new Matrix()[key](value,\n\t\t\t\tcenter || this.getPosition(true)));\n\t};\n}, {\n\ttranslate: function() {\n\t\tvar mx = new Matrix();\n\t\treturn this.transform(mx.translate.apply(mx, arguments));\n\t},\n\n\ttransform: function(matrix, _applyMatrix, _applyRecursively,\n\t\t\t_setApplyMatrix) {\n\t\tif (matrix && matrix.isIdentity())\n\t\t\tmatrix = null;\n\t\tvar _matrix = this._matrix,\n\t\t\tapplyMatrix = (_applyMatrix || this._applyMatrix)\n\t\t\t\t\t&& ((!_matrix.isIdentity() || matrix)\n\t\t\t\t\t\t|| _applyMatrix && _applyRecursively && this._children);\n\t\tif (!matrix && !applyMatrix)\n\t\t\treturn this;\n\t\tif (matrix) {\n\t\t\tif (!matrix.isInvertible() && _matrix.isInvertible())\n\t\t\t\t_matrix._backup = _matrix.getValues();\n\t\t\t_matrix.prepend(matrix);\n\t\t}\n\t\tif (applyMatrix = applyMatrix && this._transformContent(_matrix,\n\t\t\t\t\t_applyRecursively, _setApplyMatrix)) {\n\t\t\tvar pivot = this._pivot,\n\t\t\t\tstyle = this._style,\n\t\t\t\tfillColor = style.getFillColor(true),\n\t\t\t\tstrokeColor = style.getStrokeColor(true);\n\t\t\tif (pivot)\n\t\t\t\t_matrix._transformPoint(pivot, pivot, true);\n\t\t\tif (fillColor)\n\t\t\t\tfillColor.transform(_matrix);\n\t\t\tif (strokeColor)\n\t\t\t\tstrokeColor.transform(_matrix);\n\t\t\t_matrix.reset(true);\n\t\t\tif (_setApplyMatrix && this._canApplyMatrix)\n\t\t\t\tthis._applyMatrix = true;\n\t\t}\n\t\tvar bounds = this._bounds,\n\t\t\tposition = this._position;\n\t\tthis._changed(9);\n\t\tvar decomp = bounds && matrix && matrix.decompose();\n\t\tif (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {\n\t\t\tfor (var key in bounds) {\n\t\t\t\tvar cache = bounds[key];\n\t\t\t\tif (applyMatrix || !cache.internal) {\n\t\t\t\t\tvar rect = cache.rect;\n\t\t\t\t\tmatrix._transformBounds(rect, rect);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar getter = this._boundsGetter,\n\t\t\t\trect = bounds[getter && getter.getBounds || getter || 'getBounds'];\n\t\t\tif (rect)\n\t\t\t\tthis._position = rect.getCenter(true);\n\t\t\tthis._bounds = bounds;\n\t\t} else if (matrix && position) {\n\t\t\tthis._position = matrix._transformPoint(position, position);\n\t\t}\n\t\treturn this;\n\t},\n\n\t_transformContent: function(matrix, applyRecursively, setApplyMatrix) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].transform(matrix, true, applyRecursively,\n\t\t\t\t\t\tsetApplyMatrix);\n\t\t\treturn true;\n\t\t}\n\t},\n\n\tglobalToLocal: function() {\n\t\treturn this.getGlobalMatrix(true)._inverseTransform(\n\t\t\t\tPoint.read(arguments));\n\t},\n\n\tlocalToGlobal: function() {\n\t\treturn this.getGlobalMatrix(true)._transformPoint(\n\t\t\t\tPoint.read(arguments));\n\t},\n\n\tparentToLocal: function() {\n\t\treturn this._matrix._inverseTransform(Point.read(arguments));\n\t},\n\n\tlocalToParent: function() {\n\t\treturn this._matrix._transformPoint(Point.read(arguments));\n\t},\n\n\tfitBounds: function(rectangle, fill) {\n\t\trectangle = Rectangle.read(arguments);\n\t\tvar bounds = this.getBounds(),\n\t\t\titemRatio = bounds.height / bounds.width,\n\t\t\trectRatio = rectangle.height / rectangle.width,\n\t\t\tscale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)\n\t\t\t\t\t? rectangle.width / bounds.width\n\t\t\t\t\t: rectangle.height / bounds.height,\n\t\t\tnewBounds = new Rectangle(new Point(),\n\t\t\t\t\tnew Size(bounds.width * scale, bounds.height * scale));\n\t\tnewBounds.setCenter(rectangle.getCenter());\n\t\tthis.setBounds(newBounds);\n\t}\n}), {\n\n\t_setStyles: function(ctx, param, viewMatrix) {\n\t\tvar style = this._style;\n\t\tif (style.hasFill()) {\n\t\t\tctx.fillStyle = style.getFillColor().toCanvasStyle(ctx);\n\t\t}\n\t\tif (style.hasStroke()) {\n\t\t\tctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx);\n\t\t\tctx.lineWidth = style.getStrokeWidth();\n\t\t\tvar strokeJoin = style.getStrokeJoin(),\n\t\t\t\tstrokeCap = style.getStrokeCap(),\n\t\t\t\tmiterLimit = style.getMiterLimit();\n\t\t\tif (strokeJoin)\n\t\t\t\tctx.lineJoin = strokeJoin;\n\t\t\tif (strokeCap)\n\t\t\t\tctx.lineCap = strokeCap;\n\t\t\tif (miterLimit)\n\t\t\t\tctx.miterLimit = miterLimit;\n\t\t\tif (paper.support.nativeDash) {\n\t\t\t\tvar dashArray = style.getDashArray(),\n\t\t\t\t\tdashOffset = style.getDashOffset();\n\t\t\t\tif (dashArray && dashArray.length) {\n\t\t\t\t\tif ('setLineDash' in ctx) {\n\t\t\t\t\t\tctx.setLineDash(dashArray);\n\t\t\t\t\t\tctx.lineDashOffset = dashOffset;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tctx.mozDash = dashArray;\n\t\t\t\t\t\tctx.mozDashOffset = dashOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (style.hasShadow()) {\n\t\t\tvar pixelRatio = param.pixelRatio || 1,\n\t\t\t\tmx = viewMatrix._shiftless().prepend(\n\t\t\t\t\tnew Matrix().scale(pixelRatio, pixelRatio)),\n\t\t\t\tblur = mx.transform(new Point(style.getShadowBlur(), 0)),\n\t\t\t\toffset = mx.transform(this.getShadowOffset());\n\t\t\tctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx);\n\t\t\tctx.shadowBlur = blur.getLength();\n\t\t\tctx.shadowOffsetX = offset.x;\n\t\t\tctx.shadowOffsetY = offset.y;\n\t\t}\n\t},\n\n\tdraw: function(ctx, param, parentStrokeMatrix) {\n\t\tvar updateVersion = this._updateVersion = this._project._updateVersion;\n\t\tif (!this._visible || this._opacity === 0)\n\t\t\treturn;\n\t\tvar matrices = param.matrices,\n\t\t\tviewMatrix = param.viewMatrix,\n\t\t\tmatrix = this._matrix,\n\t\t\tglobalMatrix = matrices[matrices.length - 1].appended(matrix);\n\t\tif (!globalMatrix.isInvertible())\n\t\t\treturn;\n\n\t\tviewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix)\n\t\t\t\t: globalMatrix;\n\n\t\tmatrices.push(globalMatrix);\n\t\tif (param.updateMatrix) {\n\t\t\tglobalMatrix._updateVersion = updateVersion;\n\t\t\tthis._globalMatrix = globalMatrix;\n\t\t}\n\n\t\tvar blendMode = this._blendMode,\n\t\t\topacity = this._opacity,\n\t\t\tnormalBlend = blendMode === 'normal',\n\t\t\tnativeBlend = BlendMode.nativeModes[blendMode],\n\t\t\tdirect = normalBlend && opacity === 1\n\t\t\t\t\t|| param.dontStart\n\t\t\t\t\t|| param.clip\n\t\t\t\t\t|| (nativeBlend || normalBlend && opacity < 1)\n\t\t\t\t\t\t&& this._canComposite(),\n\t\t\tpixelRatio = param.pixelRatio || 1,\n\t\t\tmainCtx, itemOffset, prevOffset;\n\t\tif (!direct) {\n\t\t\tvar bounds = this.getStrokeBounds(viewMatrix);\n\t\t\tif (!bounds.width || !bounds.height)\n\t\t\t\treturn;\n\t\t\tprevOffset = param.offset;\n\t\t\titemOffset = param.offset = bounds.getTopLeft().floor();\n\t\t\tmainCtx = ctx;\n\t\t\tctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)\n\t\t\t\t\t.multiply(pixelRatio));\n\t\t\tif (pixelRatio !== 1)\n\t\t\t\tctx.scale(pixelRatio, pixelRatio);\n\t\t}\n\t\tctx.save();\n\t\tvar strokeMatrix = parentStrokeMatrix\n\t\t\t\t? parentStrokeMatrix.appended(matrix)\n\t\t\t\t: this._canScaleStroke && !this.getStrokeScaling(true)\n\t\t\t\t\t&& viewMatrix,\n\t\t\tclip = !direct && param.clipItem,\n\t\t\ttransform = !strokeMatrix || clip;\n\t\tif (direct) {\n\t\t\tctx.globalAlpha = opacity;\n\t\t\tif (nativeBlend)\n\t\t\t\tctx.globalCompositeOperation = blendMode;\n\t\t} else if (transform) {\n\t\t\tctx.translate(-itemOffset.x, -itemOffset.y);\n\t\t}\n\t\tif (transform) {\n\t\t\t(direct ? matrix : viewMatrix).applyToContext(ctx);\n\t\t}\n\t\tif (clip) {\n\t\t\tparam.clipItem.draw(ctx, param.extend({ clip: true }));\n\t\t}\n\t\tif (strokeMatrix) {\n\t\t\tctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\n\t\t\tvar offset = param.offset;\n\t\t\tif (offset)\n\t\t\t\tctx.translate(-offset.x, -offset.y);\n\t\t}\n\t\tthis._draw(ctx, param, viewMatrix, strokeMatrix);\n\t\tctx.restore();\n\t\tmatrices.pop();\n\t\tif (param.clip && !param.dontFinish)\n\t\t\tctx.clip();\n\t\tif (!direct) {\n\t\t\tBlendMode.process(blendMode, ctx, mainCtx, opacity,\n\t\t\t\t\titemOffset.subtract(prevOffset).multiply(pixelRatio));\n\t\t\tCanvasProvider.release(ctx);\n\t\t\tparam.offset = prevOffset;\n\t\t}\n\t},\n\n\t_isUpdated: function(updateVersion) {\n\t\tvar parent = this._parent;\n\t\tif (parent instanceof CompoundPath)\n\t\t\treturn parent._isUpdated(updateVersion);\n\t\tvar updated = this._updateVersion === updateVersion;\n\t\tif (!updated && parent && parent._visible\n\t\t\t\t&& parent._isUpdated(updateVersion)) {\n\t\t\tthis._updateVersion = updateVersion;\n\t\t\tupdated = true;\n\t\t}\n\t\treturn updated;\n\t},\n\n\t_drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) {\n\t\tvar selection = this._selection,\n\t\t\titemSelected = selection & 1,\n\t\t\tboundsSelected = selection & 2\n\t\t\t\t\t|| itemSelected && this._selectBounds,\n\t\t\tpositionSelected = selection & 4;\n\t\tif (!this._drawSelected)\n\t\t\titemSelected = false;\n\t\tif ((itemSelected || boundsSelected || positionSelected)\n\t\t\t\t&& this._isUpdated(updateVersion)) {\n\t\t\tvar layer,\n\t\t\t\tcolor = this.getSelectedColor(true) || (layer = this.getLayer())\n\t\t\t\t\t&& layer.getSelectedColor(true),\n\t\t\t\tmx = matrix.appended(this.getGlobalMatrix(true)),\n\t\t\t\thalf = size / 2;\n\t\t\tctx.strokeStyle = ctx.fillStyle = color\n\t\t\t\t\t? color.toCanvasStyle(ctx) : '#009dec';\n\t\t\tif (itemSelected)\n\t\t\t\tthis._drawSelected(ctx, mx, selectionItems);\n\t\t\tif (positionSelected) {\n\t\t\t\tvar point = this.getPosition(true),\n\t\t\t\t\tx = point.x,\n\t\t\t\t\ty = point.y;\n\t\t\t\tctx.beginPath();\n\t\t\t\tctx.arc(x, y, half, 0, Math.PI * 2, true);\n\t\t\t\tctx.stroke();\n\t\t\t\tvar deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]],\n\t\t\t\t\tstart = half,\n\t\t\t\t\tend = size + 1;\n\t\t\t\tfor (var i = 0; i < 4; i++) {\n\t\t\t\t\tvar delta = deltas[i],\n\t\t\t\t\t\tdx = delta[0],\n\t\t\t\t\t\tdy = delta[1];\n\t\t\t\t\tctx.moveTo(x + dx * start, y + dy * start);\n\t\t\t\t\tctx.lineTo(x + dx * end, y + dy * end);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (boundsSelected) {\n\t\t\t\tvar coords = mx._transformCorners(this.getInternalBounds());\n\t\t\t\tctx.beginPath();\n\t\t\t\tfor (var i = 0; i < 8; i++) {\n\t\t\t\t\tctx[!i ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);\n\t\t\t\t}\n\t\t\t\tctx.closePath();\n\t\t\t\tctx.stroke();\n\t\t\t\tfor (var i = 0; i < 8; i++) {\n\t\t\t\t\tctx.fillRect(coords[i] - half, coords[++i] - half,\n\t\t\t\t\t\t\tsize, size);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn false;\n\t}\n}, Base.each(['down', 'drag', 'up', 'move'], function(key) {\n\tthis['removeOn' + Base.capitalize(key)] = function() {\n\t\tvar hash = {};\n\t\thash[key] = true;\n\t\treturn this.removeOn(hash);\n\t};\n}, {\n\n\tremoveOn: function(obj) {\n\t\tfor (var name in obj) {\n\t\t\tif (obj[name]) {\n\t\t\t\tvar key = 'mouse' + name,\n\t\t\t\t\tproject = this._project,\n\t\t\t\t\tsets = project._removeSets = project._removeSets || {};\n\t\t\t\tsets[key] = sets[key] || {};\n\t\t\t\tsets[key][this._id] = this;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n}));\n\nvar Group = Item.extend({\n\t_class: 'Group',\n\t_selectBounds: false,\n\t_selectChildren: true,\n\t_serializeFields: {\n\t\tchildren: []\n\t},\n\n\tinitialize: function Group(arg) {\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tif (!this._initialize(arg))\n\t\t\tthis.addChildren(Array.isArray(arg) ? arg : arguments);\n\t},\n\n\t_changed: function _changed(flags) {\n\t\t_changed.base.call(this, flags);\n\t\tif (flags & 1026) {\n\t\t\tthis._clipItem = undefined;\n\t\t}\n\t},\n\n\t_getClipItem: function() {\n\t\tvar clipItem = this._clipItem;\n\t\tif (clipItem === undefined) {\n\t\t\tclipItem = null;\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\tif (children[i]._clipMask) {\n\t\t\t\t\tclipItem = children[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._clipItem = clipItem;\n\t\t}\n\t\treturn clipItem;\n\t},\n\n\tisClipped: function() {\n\t\treturn !!this._getClipItem();\n\t},\n\n\tsetClipped: function(clipped) {\n\t\tvar child = this.getFirstChild();\n\t\tif (child)\n\t\t\tchild.setClipMask(clipped);\n\t},\n\n\t_getBounds: function _getBounds(matrix, options) {\n\t\tvar clipItem = this._getClipItem();\n\t\treturn clipItem\n\t\t\t? clipItem._getCachedBounds(\n\t\t\t\tmatrix && matrix.appended(clipItem._matrix),\n\t\t\t\tBase.set({}, options, { stroke: false }))\n\t\t\t: _getBounds.base.call(this, matrix, options);\n\t},\n\n\t_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {\n\t\tvar clipItem = this._getClipItem();\n\t\treturn (!clipItem || clipItem.contains(point))\n\t\t\t\t&& _hitTestChildren.base.call(this, point, options, viewMatrix,\n\t\t\t\t\tclipItem);\n\t},\n\n\t_draw: function(ctx, param) {\n\t\tvar clip = param.clip,\n\t\t\tclipItem = !clip && this._getClipItem();\n\t\tparam = param.extend({ clipItem: clipItem, clip: false });\n\t\tif (clip) {\n\t\t\tctx.beginPath();\n\t\t\tparam.dontStart = param.dontFinish = true;\n\t\t} else if (clipItem) {\n\t\t\tclipItem.draw(ctx, param.extend({ clip: true }));\n\t\t}\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar item = children[i];\n\t\t\tif (item !== clipItem)\n\t\t\t\titem.draw(ctx, param);\n\t\t}\n\t}\n});\n\nvar Layer = Group.extend({\n\t_class: 'Layer',\n\n\tinitialize: function Layer() {\n\t\tGroup.apply(this, arguments);\n\t},\n\n\t_getOwner: function() {\n\t\treturn this._parent || this._index != null && this._project;\n\t},\n\n\tisInserted: function isInserted() {\n\t\treturn this._parent ? isInserted.base.call(this) : this._index != null;\n\t},\n\n\tactivate: function() {\n\t\tthis._project._activeLayer = this;\n\t},\n\n\t_hitTestSelf: function() {\n\t}\n});\n\nvar Shape = Item.extend({\n\t_class: 'Shape',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_canScaleStroke: true,\n\t_serializeFields: {\n\t\ttype: null,\n\t\tsize: null,\n\t\tradius: null\n\t},\n\n\tinitialize: function Shape(props) {\n\t\tthis._initialize(props);\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._type === item._type\n\t\t\t&& this._size.equals(item._size)\n\t\t\t&& Base.equals(this._radius, item._radius);\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setType(source._type);\n\t\tthis.setSize(source._size);\n\t\tthis.setRadius(source._radius);\n\t},\n\n\tgetType: function() {\n\t\treturn this._type;\n\t},\n\n\tsetType: function(type) {\n\t\tthis._type = type;\n\t},\n\n\tgetShape: '#getType',\n\tsetShape: '#setType',\n\n\tgetSize: function() {\n\t\tvar size = this._size;\n\t\treturn new LinkedSize(size.width, size.height, this, 'setSize');\n\t},\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments);\n\t\tif (!this._size) {\n\t\t\tthis._size = size.clone();\n\t\t} else if (!this._size.equals(size)) {\n\t\t\tvar type = this._type,\n\t\t\t\twidth = size.width,\n\t\t\t\theight = size.height;\n\t\t\tif (type === 'rectangle') {\n\t\t\t\tthis._radius.set(Size.min(this._radius, size.divide(2)));\n\t\t\t} else if (type === 'circle') {\n\t\t\t\twidth = height = (width + height) / 2;\n\t\t\t\tthis._radius = width / 2;\n\t\t\t} else if (type === 'ellipse') {\n\t\t\t\tthis._radius._set(width / 2, height / 2);\n\t\t\t}\n\t\t\tthis._size._set(width, height);\n\t\t\tthis._changed(9);\n\t\t}\n\t},\n\n\tgetRadius: function() {\n\t\tvar rad = this._radius;\n\t\treturn this._type === 'circle'\n\t\t\t\t? rad\n\t\t\t\t: new LinkedSize(rad.width, rad.height, this, 'setRadius');\n\t},\n\n\tsetRadius: function(radius) {\n\t\tvar type = this._type;\n\t\tif (type === 'circle') {\n\t\t\tif (radius === this._radius)\n\t\t\t\treturn;\n\t\t\tvar size = radius * 2;\n\t\t\tthis._radius = radius;\n\t\t\tthis._size._set(size, size);\n\t\t} else {\n\t\t\tradius = Size.read(arguments);\n\t\t\tif (!this._radius) {\n\t\t\t\tthis._radius = radius.clone();\n\t\t\t} else {\n\t\t\t\tif (this._radius.equals(radius))\n\t\t\t\t\treturn;\n\t\t\t\tthis._radius.set(radius);\n\t\t\t\tif (type === 'rectangle') {\n\t\t\t\t\tvar size = Size.max(this._size, radius.multiply(2));\n\t\t\t\t\tthis._size.set(size);\n\t\t\t\t} else if (type === 'ellipse') {\n\t\t\t\t\tthis._size._set(radius.width * 2, radius.height * 2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._changed(9);\n\t},\n\n\tisEmpty: function() {\n\t\treturn false;\n\t},\n\n\ttoPath: function(insert) {\n\t\tvar path = new Path[Base.capitalize(this._type)]({\n\t\t\tcenter: new Point(),\n\t\t\tsize: this._size,\n\t\t\tradius: this._radius,\n\t\t\tinsert: false\n\t\t});\n\t\tpath.copyAttributes(this);\n\t\tif (paper.settings.applyMatrix)\n\t\t\tpath.setApplyMatrix(true);\n\t\tif (insert === undefined || insert)\n\t\t\tpath.insertAbove(this);\n\t\treturn path;\n\t},\n\n\ttoShape: '#clone',\n\n\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\tvar style = this._style,\n\t\t\thasFill = style.hasFill(),\n\t\t\thasStroke = style.hasStroke(),\n\t\t\tdontPaint = param.dontFinish || param.clip,\n\t\t\tuntransformed = !strokeMatrix;\n\t\tif (hasFill || hasStroke || dontPaint) {\n\t\t\tvar type = this._type,\n\t\t\t\tradius = this._radius,\n\t\t\t\tisCircle = type === 'circle';\n\t\t\tif (!param.dontStart)\n\t\t\t\tctx.beginPath();\n\t\t\tif (untransformed && isCircle) {\n\t\t\t\tctx.arc(0, 0, radius, 0, Math.PI * 2, true);\n\t\t\t} else {\n\t\t\t\tvar rx = isCircle ? radius : radius.width,\n\t\t\t\t\try = isCircle ? radius : radius.height,\n\t\t\t\t\tsize = this._size,\n\t\t\t\t\twidth = size.width,\n\t\t\t\t\theight = size.height;\n\t\t\t\tif (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {\n\t\t\t\t\tctx.rect(-width / 2, -height / 2, width, height);\n\t\t\t\t} else {\n\t\t\t\t\tvar x = width / 2,\n\t\t\t\t\t\ty = height / 2,\n\t\t\t\t\t\tkappa = 1 - 0.5522847498307936,\n\t\t\t\t\t\tcx = rx * kappa,\n\t\t\t\t\t\tcy = ry * kappa,\n\t\t\t\t\t\tc = [\n\t\t\t\t\t\t\t-x, -y + ry,\n\t\t\t\t\t\t\t-x, -y + cy,\n\t\t\t\t\t\t\t-x + cx, -y,\n\t\t\t\t\t\t\t-x + rx, -y,\n\t\t\t\t\t\t\tx - rx, -y,\n\t\t\t\t\t\t\tx - cx, -y,\n\t\t\t\t\t\t\tx, -y + cy,\n\t\t\t\t\t\t\tx, -y + ry,\n\t\t\t\t\t\t\tx, y - ry,\n\t\t\t\t\t\t\tx, y - cy,\n\t\t\t\t\t\t\tx - cx, y,\n\t\t\t\t\t\t\tx - rx, y,\n\t\t\t\t\t\t\t-x + rx, y,\n\t\t\t\t\t\t\t-x + cx, y,\n\t\t\t\t\t\t\t-x, y - cy,\n\t\t\t\t\t\t\t-x, y - ry\n\t\t\t\t\t\t];\n\t\t\t\t\tif (strokeMatrix)\n\t\t\t\t\t\tstrokeMatrix.transform(c, c, 32);\n\t\t\t\t\tctx.moveTo(c[0], c[1]);\n\t\t\t\t\tctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);\n\t\t\t\t\tif (x !== rx)\n\t\t\t\t\t\tctx.lineTo(c[8], c[9]);\n\t\t\t\t\tctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);\n\t\t\t\t\tif (y !== ry)\n\t\t\t\t\t\tctx.lineTo(c[16], c[17]);\n\t\t\t\t\tctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);\n\t\t\t\t\tif (x !== rx)\n\t\t\t\t\t\tctx.lineTo(c[24], c[25]);\n\t\t\t\t\tctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tctx.closePath();\n\t\t}\n\t\tif (!dontPaint && (hasFill || hasStroke)) {\n\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\tif (hasFill) {\n\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (hasStroke)\n\t\t\t\tctx.stroke();\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn !(this.hasFill() && this.hasStroke());\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar rect = new Rectangle(this._size).setCenter(0, 0),\n\t\t\tstyle = this._style,\n\t\t\tstrokeWidth = options.stroke && style.hasStroke()\n\t\t\t\t\t&& style.getStrokeWidth();\n\t\tif (matrix)\n\t\t\trect = matrix._transformBounds(rect);\n\t\treturn strokeWidth\n\t\t\t\t? rect.expand(Path._getStrokePadding(strokeWidth,\n\t\t\t\t\tthis._getStrokeMatrix(matrix, options)))\n\t\t\t\t: rect;\n\t}\n},\nnew function() {\n\tfunction getCornerCenter(that, point, expand) {\n\t\tvar radius = that._radius;\n\t\tif (!radius.isZero()) {\n\t\t\tvar halfSize = that._size.divide(2);\n\t\t\tfor (var i = 0; i < 4; i++) {\n\t\t\t\tvar dir = new Point(i & 1 ? 1 : -1, i > 1 ? 1 : -1),\n\t\t\t\t\tcorner = dir.multiply(halfSize),\n\t\t\t\t\tcenter = corner.subtract(dir.multiply(radius)),\n\t\t\t\t\trect = new Rectangle(corner, center);\n\t\t\t\tif ((expand ? rect.expand(expand) : rect).contains(point))\n\t\t\t\t\treturn center;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction isOnEllipseStroke(point, radius, padding, quadrant) {\n\t\tvar vector = point.divide(radius);\n\t\treturn (!quadrant || vector.quadrant === quadrant) &&\n\t\t\t\tvector.subtract(vector.normalize()).multiply(radius)\n\t\t\t\t\t.divide(padding).length <= 1;\n\t}\n\n\treturn {\n\t\t_contains: function _contains(point) {\n\t\t\tif (this._type === 'rectangle') {\n\t\t\t\tvar center = getCornerCenter(this, point);\n\t\t\t\treturn center\n\t\t\t\t\t\t? point.subtract(center).divide(this._radius)\n\t\t\t\t\t\t\t.getLength() <= 1\n\t\t\t\t\t\t: _contains.base.call(this, point);\n\t\t\t} else {\n\t\t\t\treturn point.divide(this.size).getLength() <= 0.5;\n\t\t\t}\n\t\t},\n\n\t\t_hitTestSelf: function _hitTestSelf(point, options, viewMatrix,\n\t\t\t\tstrokeMatrix) {\n\t\t\tvar hit = false,\n\t\t\t\tstyle = this._style,\n\t\t\t\thitStroke = options.stroke && style.hasStroke(),\n\t\t\t\thitFill = options.fill && style.hasFill();\n\t\t\tif (hitStroke || hitFill) {\n\t\t\t\tvar type = this._type,\n\t\t\t\t\tradius = this._radius,\n\t\t\t\t\tstrokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0,\n\t\t\t\t\tstrokePadding = options._tolerancePadding.add(\n\t\t\t\t\t\tPath._getStrokePadding(strokeRadius,\n\t\t\t\t\t\t\t!style.getStrokeScaling() && strokeMatrix));\n\t\t\t\tif (type === 'rectangle') {\n\t\t\t\t\tvar padding = strokePadding.multiply(2),\n\t\t\t\t\t\tcenter = getCornerCenter(this, point, padding);\n\t\t\t\t\tif (center) {\n\t\t\t\t\t\thit = isOnEllipseStroke(point.subtract(center), radius,\n\t\t\t\t\t\t\t\tstrokePadding, center.getQuadrant());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar rect = new Rectangle(this._size).setCenter(0, 0),\n\t\t\t\t\t\t\touter = rect.expand(padding),\n\t\t\t\t\t\t\tinner = rect.expand(padding.negate());\n\t\t\t\t\t\thit = outer._containsPoint(point)\n\t\t\t\t\t\t\t\t&& !inner._containsPoint(point);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\thit = isOnEllipseStroke(point, radius, strokePadding);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this)\n\t\t\t\t\t: _hitTestSelf.base.apply(this, arguments);\n\t\t}\n\t};\n}, {\n\nstatics: new function() {\n\tfunction createShape(type, point, size, radius, args) {\n\t\tvar item = new Shape(Base.getNamed(args));\n\t\titem._type = type;\n\t\titem._size = size;\n\t\titem._radius = radius;\n\t\treturn item.translate(point);\n\t}\n\n\treturn {\n\t\tCircle: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius');\n\t\t\treturn createShape('circle', center, new Size(radius * 2), radius,\n\t\t\t\t\targuments);\n\t\t},\n\n\t\tRectangle: function() {\n\t\t\tvar rect = Rectangle.readNamed(arguments, 'rectangle'),\n\t\t\t\tradius = Size.min(Size.readNamed(arguments, 'radius'),\n\t\t\t\t\t\trect.getSize(true).divide(2));\n\t\t\treturn createShape('rectangle', rect.getCenter(true),\n\t\t\t\t\trect.getSize(true), radius, arguments);\n\t\t},\n\n\t\tEllipse: function() {\n\t\t\tvar ellipse = Shape._readEllipse(arguments),\n\t\t\t\tradius = ellipse.radius;\n\t\t\treturn createShape('ellipse', ellipse.center, radius.multiply(2),\n\t\t\t\t\tradius, arguments);\n\t\t},\n\n\t\t_readEllipse: function(args) {\n\t\t\tvar center,\n\t\t\t\tradius;\n\t\t\tif (Base.hasNamed(args, 'radius')) {\n\t\t\t\tcenter = Point.readNamed(args, 'center');\n\t\t\t\tradius = Size.readNamed(args, 'radius');\n\t\t\t} else {\n\t\t\t\tvar rect = Rectangle.readNamed(args, 'rectangle');\n\t\t\t\tcenter = rect.getCenter(true);\n\t\t\t\tradius = rect.getSize(true).divide(2);\n\t\t\t}\n\t\t\treturn { center: center, radius: radius };\n\t\t}\n\t};\n}});\n\nvar Raster = Item.extend({\n\t_class: 'Raster',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_boundsOptions: { stroke: false, handle: false },\n\t_serializeFields: {\n\t\tcrossOrigin: null,\n\t\tsource: null\n\t},\n\n\tinitialize: function Raster(object, position) {\n\t\tif (!this._initialize(object,\n\t\t\t\tposition !== undefined && Point.read(arguments, 1))) {\n\t\t\tvar image = typeof object === 'string'\n\t\t\t\t\t? document.getElementById(object) : object;\n\t\t\tif (image) {\n\t\t\t\tthis.setImage(image);\n\t\t\t} else {\n\t\t\t\tthis.setSource(object);\n\t\t\t}\n\t\t}\n\t\tif (!this._size) {\n\t\t\tthis._size = new Size();\n\t\t\tthis._loaded = false;\n\t\t}\n\t},\n\n\t_equals: function(item) {\n\t\treturn this.getSource() === item.getSource();\n\t},\n\n\tcopyContent: function(source) {\n\t\tvar image = source._image,\n\t\t\tcanvas = source._canvas;\n\t\tif (image) {\n\t\t\tthis._setImage(image);\n\t\t} else if (canvas) {\n\t\t\tvar copyCanvas = CanvasProvider.getCanvas(source._size);\n\t\t\tcopyCanvas.getContext('2d').drawImage(canvas, 0, 0);\n\t\t\tthis._setImage(copyCanvas);\n\t\t}\n\t\tthis._crossOrigin = source._crossOrigin;\n\t},\n\n\tgetSize: function() {\n\t\tvar size = this._size;\n\t\treturn new LinkedSize(size ? size.width : 0, size ? size.height : 0,\n\t\t\t\tthis, 'setSize');\n\t},\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments);\n\t\tif (!size.equals(this._size)) {\n\t\t\tif (size.width > 0 && size.height > 0) {\n\t\t\t\tvar element = this.getElement();\n\t\t\t\tthis._setImage(CanvasProvider.getCanvas(size));\n\t\t\t\tif (element)\n\t\t\t\t\tthis.getContext(true).drawImage(element, 0, 0,\n\t\t\t\t\t\t\tsize.width, size.height);\n\t\t\t} else {\n\t\t\t\tif (this._canvas)\n\t\t\t\t\tCanvasProvider.release(this._canvas);\n\t\t\t\tthis._size = size.clone();\n\t\t\t}\n\t\t}\n\t},\n\n\tgetWidth: function() {\n\t\treturn this._size ? this._size.width : 0;\n\t},\n\n\tsetWidth: function(width) {\n\t\tthis.setSize(width, this.getHeight());\n\t},\n\n\tgetHeight: function() {\n\t\treturn this._size ? this._size.height : 0;\n\t},\n\n\tsetHeight: function(height) {\n\t\tthis.setSize(this.getWidth(), height);\n\t},\n\n\tgetLoaded: function() {\n\t\treturn this._loaded;\n\t},\n\n\tisEmpty: function() {\n\t\tvar size = this._size;\n\t\treturn !size || size.width === 0 && size.height === 0;\n\t},\n\n\tgetResolution: function() {\n\t\tvar matrix = this._matrix,\n\t\t\torig = new Point(0, 0).transform(matrix),\n\t\t\tu = new Point(1, 0).transform(matrix).subtract(orig),\n\t\t\tv = new Point(0, 1).transform(matrix).subtract(orig);\n\t\treturn new Size(\n\t\t\t72 / u.getLength(),\n\t\t\t72 / v.getLength()\n\t\t);\n\t},\n\n\tgetPpi: '#getResolution',\n\n\tgetImage: function() {\n\t\treturn this._image;\n\t},\n\n\tsetImage: function(image) {\n\t\tvar that = this;\n\n\t\tfunction emit(event) {\n\t\t\tvar view = that.getView(),\n\t\t\t\ttype = event && event.type || 'load';\n\t\t\tif (view && that.responds(type)) {\n\t\t\t\tpaper = view._scope;\n\t\t\t\tthat.emit(type, new Event(event));\n\t\t\t}\n\t\t}\n\n\t\tthis._setImage(image);\n\t\tif (this._loaded) {\n\t\t\tsetTimeout(emit, 0);\n\t\t} else if (image) {\n\t\t\tDomEvent.add(image, {\n\t\t\t\tload: function(event) {\n\t\t\t\t\tthat._setImage(image);\n\t\t\t\t\temit(event);\n\t\t\t\t},\n\t\t\t\terror: emit\n\t\t\t});\n\t\t}\n\t},\n\n\t_setImage: function(image) {\n\t\tif (this._canvas)\n\t\t\tCanvasProvider.release(this._canvas);\n\t\tif (image && image.getContext) {\n\t\t\tthis._image = null;\n\t\t\tthis._canvas = image;\n\t\t\tthis._loaded = true;\n\t\t} else {\n\t\t\tthis._image = image;\n\t\t\tthis._canvas = null;\n\t\t\tthis._loaded = !!(image && image.src && image.complete);\n\t\t}\n\t\tthis._size = new Size(\n\t\t\t\timage ? image.naturalWidth || image.width : 0,\n\t\t\t\timage ? image.naturalHeight || image.height : 0);\n\t\tthis._context = null;\n\t\tthis._changed(521);\n\t},\n\n\tgetCanvas: function() {\n\t\tif (!this._canvas) {\n\t\t\tvar ctx = CanvasProvider.getContext(this._size);\n\t\t\ttry {\n\t\t\t\tif (this._image)\n\t\t\t\t\tctx.drawImage(this._image, 0, 0);\n\t\t\t\tthis._canvas = ctx.canvas;\n\t\t\t} catch (e) {\n\t\t\t\tCanvasProvider.release(ctx);\n\t\t\t}\n\t\t}\n\t\treturn this._canvas;\n\t},\n\n\tsetCanvas: '#setImage',\n\n\tgetContext: function(modify) {\n\t\tif (!this._context)\n\t\t\tthis._context = this.getCanvas().getContext('2d');\n\t\tif (modify) {\n\t\t\tthis._image = null;\n\t\t\tthis._changed(513);\n\t\t}\n\t\treturn this._context;\n\t},\n\n\tsetContext: function(context) {\n\t\tthis._context = context;\n\t},\n\n\tgetSource: function() {\n\t\tvar image = this._image;\n\t\treturn image && image.src || this.toDataURL();\n\t},\n\n\tsetSource: function(src) {\n\t\tvar image = new self.Image(),\n\t\t\tcrossOrigin = this._crossOrigin;\n\t\tif (crossOrigin)\n\t\t\timage.crossOrigin = crossOrigin;\n\t\timage.src = src;\n\t\tthis.setImage(image);\n\t},\n\n\tgetCrossOrigin: function() {\n\t\tvar image = this._image;\n\t\treturn image && image.crossOrigin || this._crossOrigin || '';\n\t},\n\n\tsetCrossOrigin: function(crossOrigin) {\n\t\tthis._crossOrigin = crossOrigin;\n\t\tvar image = this._image;\n\t\tif (image)\n\t\t\timage.crossOrigin = crossOrigin;\n\t},\n\n\tgetElement: function() {\n\t\treturn this._canvas || this._loaded && this._image;\n\t}\n}, {\n\tbeans: false,\n\n\tgetSubCanvas: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tctx = CanvasProvider.getContext(rect.getSize());\n\t\tctx.drawImage(this.getCanvas(), rect.x, rect.y,\n\t\t\t\trect.width, rect.height, 0, 0, rect.width, rect.height);\n\t\treturn ctx.canvas;\n\t},\n\n\tgetSubRaster: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\traster = new Raster(Item.NO_INSERT);\n\t\traster._setImage(this.getSubCanvas(rect));\n\t\traster.translate(rect.getCenter().subtract(this.getSize().divide(2)));\n\t\traster._matrix.prepend(this._matrix);\n\t\traster.insertAbove(this);\n\t\treturn raster;\n\t},\n\n\ttoDataURL: function() {\n\t\tvar image = this._image,\n\t\t\tsrc = image && image.src;\n\t\tif (/^data:/.test(src))\n\t\t\treturn src;\n\t\tvar canvas = this.getCanvas();\n\t\treturn canvas ? canvas.toDataURL.apply(canvas, arguments) : null;\n\t},\n\n\tdrawImage: function(image ) {\n\t\tvar point = Point.read(arguments, 1);\n\t\tthis.getContext(true).drawImage(image, point.x, point.y);\n\t},\n\n\tgetAverageColor: function(object) {\n\t\tvar bounds, path;\n\t\tif (!object) {\n\t\t\tbounds = this.getBounds();\n\t\t} else if (object instanceof PathItem) {\n\t\t\tpath = object;\n\t\t\tbounds = object.getBounds();\n\t\t} else if (typeof object === 'object') {\n\t\t\tif ('width' in object) {\n\t\t\t\tbounds = new Rectangle(object);\n\t\t\t} else if ('x' in object) {\n\t\t\t\tbounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);\n\t\t\t}\n\t\t}\n\t\tif (!bounds)\n\t\t\treturn null;\n\t\tvar sampleSize = 32,\n\t\t\twidth = Math.min(bounds.width, sampleSize),\n\t\t\theight = Math.min(bounds.height, sampleSize);\n\t\tvar ctx = Raster._sampleContext;\n\t\tif (!ctx) {\n\t\t\tctx = Raster._sampleContext = CanvasProvider.getContext(\n\t\t\t\t\tnew Size(sampleSize));\n\t\t} else {\n\t\t\tctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);\n\t\t}\n\t\tctx.save();\n\t\tvar matrix = new Matrix()\n\t\t\t\t.scale(width / bounds.width, height / bounds.height)\n\t\t\t\t.translate(-bounds.x, -bounds.y);\n\t\tmatrix.applyToContext(ctx);\n\t\tif (path)\n\t\t\tpath.draw(ctx, new Base({ clip: true, matrices: [matrix] }));\n\t\tthis._matrix.applyToContext(ctx);\n\t\tvar element = this.getElement(),\n\t\t\tsize = this._size;\n\t\tif (element)\n\t\t\tctx.drawImage(element, -size.width / 2, -size.height / 2);\n\t\tctx.restore();\n\t\tvar pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),\n\t\t\t\tMath.ceil(height)).data,\n\t\t\tchannels = [0, 0, 0],\n\t\t\ttotal = 0;\n\t\tfor (var i = 0, l = pixels.length; i < l; i += 4) {\n\t\t\tvar alpha = pixels[i + 3];\n\t\t\ttotal += alpha;\n\t\t\talpha /= 255;\n\t\t\tchannels[0] += pixels[i] * alpha;\n\t\t\tchannels[1] += pixels[i + 1] * alpha;\n\t\t\tchannels[2] += pixels[i + 2] * alpha;\n\t\t}\n\t\tfor (var i = 0; i < 3; i++)\n\t\t\tchannels[i] /= total;\n\t\treturn total ? Color.read(channels) : null;\n\t},\n\n\tgetPixel: function() {\n\t\tvar point = Point.read(arguments);\n\t\tvar data = this.getContext().getImageData(point.x, point.y, 1, 1).data;\n\t\treturn new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],\n\t\t\t\tdata[3] / 255);\n\t},\n\n\tsetPixel: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcolor = Color.read(arguments),\n\t\t\tcomponents = color._convert('rgb'),\n\t\t\talpha = color._alpha,\n\t\t\tctx = this.getContext(true),\n\t\t\timageData = ctx.createImageData(1, 1),\n\t\t\tdata = imageData.data;\n\t\tdata[0] = components[0] * 255;\n\t\tdata[1] = components[1] * 255;\n\t\tdata[2] = components[2] * 255;\n\t\tdata[3] = alpha != null ? alpha * 255 : 255;\n\t\tctx.putImageData(imageData, point.x, point.y);\n\t},\n\n\tcreateImageData: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn this.getContext().createImageData(size.width, size.height);\n\t},\n\n\tgetImageData: function() {\n\t\tvar rect = Rectangle.read(arguments);\n\t\tif (rect.isEmpty())\n\t\t\trect = new Rectangle(this._size);\n\t\treturn this.getContext().getImageData(rect.x, rect.y,\n\t\t\t\trect.width, rect.height);\n\t},\n\n\tsetImageData: function(data ) {\n\t\tvar point = Point.read(arguments, 1);\n\t\tthis.getContext(true).putImageData(data, point.x, point.y);\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar rect = new Rectangle(this._size).setCenter(0, 0);\n\t\treturn matrix ? matrix._transformBounds(rect) : rect;\n\t},\n\n\t_hitTestSelf: function(point) {\n\t\tif (this._contains(point)) {\n\t\t\tvar that = this;\n\t\t\treturn new HitResult('pixel', that, {\n\t\t\t\toffset: point.add(that._size.divide(2)).round(),\n\t\t\t\tcolor: {\n\t\t\t\t\tget: function() {\n\t\t\t\t\t\treturn that.getPixel(this.offset);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\t_draw: function(ctx) {\n\t\tvar element = this.getElement();\n\t\tif (element) {\n\t\t\tctx.globalAlpha = this._opacity;\n\t\t\tctx.drawImage(element,\n\t\t\t\t\t-this._size.width / 2, -this._size.height / 2);\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn true;\n\t}\n});\n\nvar SymbolItem = Item.extend({\n\t_class: 'SymbolItem',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_boundsOptions: { stroke: true },\n\t_serializeFields: {\n\t\tsymbol: null\n\t},\n\n\tinitialize: function SymbolItem(arg0, arg1) {\n\t\tif (!this._initialize(arg0,\n\t\t\t\targ1 !== undefined && Point.read(arguments, 1)))\n\t\t\tthis.setDefinition(arg0 instanceof SymbolDefinition ?\n\t\t\t\t\targ0 : new SymbolDefinition(arg0));\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._definition === item._definition;\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setDefinition(source._definition);\n\t},\n\n\tgetDefinition: function() {\n\t\treturn this._definition;\n\t},\n\n\tsetDefinition: function(definition) {\n\t\tthis._definition = definition;\n\t\tthis._changed(9);\n\t},\n\n\tgetSymbol: '#getDefinition',\n\tsetSymbol: '#setDefinition',\n\n\tisEmpty: function() {\n\t\treturn this._definition._item.isEmpty();\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar item = this._definition._item;\n\t\treturn item._getCachedBounds(item._matrix.prepended(matrix), options);\n\t},\n\n\t_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {\n\t\tvar res = this._definition._item._hitTest(point, options, viewMatrix);\n\t\tif (res)\n\t\t\tres.item = this;\n\t\treturn res;\n\t},\n\n\t_draw: function(ctx, param) {\n\t\tthis._definition._item.draw(ctx, param);\n\t}\n\n});\n\nvar SymbolDefinition = Base.extend({\n\t_class: 'SymbolDefinition',\n\n\tinitialize: function SymbolDefinition(item, dontCenter) {\n\t\tthis._id = UID.get();\n\t\tthis.project = paper.project;\n\t\tif (item)\n\t\t\tthis.setItem(item, dontCenter);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn dictionary.add(this, function() {\n\t\t\treturn Base.serialize([this._class, this._item],\n\t\t\t\t\toptions, false, dictionary);\n\t\t});\n\t},\n\n\t_changed: function(flags) {\n\t\tif (flags & 8)\n\t\t\tItem._clearBoundsCache(this);\n\t\tif (flags & 1)\n\t\t\tthis.project._changed(flags);\n\t},\n\n\tgetItem: function() {\n\t\treturn this._item;\n\t},\n\n\tsetItem: function(item, _dontCenter) {\n\t\tif (item._symbol)\n\t\t\titem = item.clone();\n\t\tif (this._item)\n\t\t\tthis._item._symbol = null;\n\t\tthis._item = item;\n\t\titem.remove();\n\t\titem.setSelected(false);\n\t\tif (!_dontCenter)\n\t\t\titem.setPosition(new Point());\n\t\titem._symbol = this;\n\t\tthis._changed(9);\n\t},\n\n\tgetDefinition: '#getItem',\n\tsetDefinition: '#setItem',\n\n\tplace: function(position) {\n\t\treturn new SymbolItem(this, position);\n\t},\n\n\tclone: function() {\n\t\treturn new SymbolDefinition(this._item.clone(false));\n\t},\n\n\tequals: function(symbol) {\n\t\treturn symbol === this\n\t\t\t\t|| symbol && this._item.equals(symbol._item)\n\t\t\t\t|| false;\n\t}\n});\n\nvar HitResult = Base.extend({\n\t_class: 'HitResult',\n\n\tinitialize: function HitResult(type, item, values) {\n\t\tthis.type = type;\n\t\tthis.item = item;\n\t\tif (values) {\n\t\t\tvalues.enumerable = true;\n\t\t\tthis.inject(values);\n\t\t}\n\t},\n\n\tstatics: {\n\t\tgetOptions: function(args) {\n\t\t\tvar options = args && Base.read(args);\n\t\t\treturn Base.set({\n\t\t\t\ttype: null,\n\t\t\t\ttolerance: paper.settings.hitTolerance,\n\t\t\t\tfill: !options,\n\t\t\t\tstroke: !options,\n\t\t\t\tsegments: !options,\n\t\t\t\thandles: false,\n\t\t\t\tends: false,\n\t\t\t\tcenter: false,\n\t\t\t\tbounds: false,\n\t\t\t\tguides: false,\n\t\t\t\tselected: false\n\t\t\t}, options);\n\t\t}\n\t}\n});\n\nvar Segment = Base.extend({\n\t_class: 'Segment',\n\tbeans: true,\n\t_selection: 0,\n\n\tinitialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {\n\t\tvar count = arguments.length,\n\t\t\tpoint, handleIn, handleOut, selection;\n\t\tif (count > 0) {\n\t\t\tif (arg0 == null || typeof arg0 === 'object') {\n\t\t\t\tif (count === 1 && arg0 && 'point' in arg0) {\n\t\t\t\t\tpoint = arg0.point;\n\t\t\t\t\thandleIn = arg0.handleIn;\n\t\t\t\t\thandleOut = arg0.handleOut;\n\t\t\t\t\tselection = arg0.selection;\n\t\t\t\t} else {\n\t\t\t\t\tpoint = arg0;\n\t\t\t\t\thandleIn = arg1;\n\t\t\t\t\thandleOut = arg2;\n\t\t\t\t\tselection = arg3;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tpoint = [ arg0, arg1 ];\n\t\t\t\thandleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;\n\t\t\t\thandleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;\n\t\t\t}\n\t\t}\n\t\tnew SegmentPoint(point, this, '_point');\n\t\tnew SegmentPoint(handleIn, this, '_handleIn');\n\t\tnew SegmentPoint(handleOut, this, '_handleOut');\n\t\tif (selection)\n\t\t\tthis.setSelection(selection);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar point = this._point,\n\t\t\tselection = this._selection,\n\t\t\tobj = selection || this.hasHandles()\n\t\t\t\t\t? [point, this._handleIn, this._handleOut]\n\t\t\t\t\t: point;\n\t\tif (selection)\n\t\t\tobj.push(selection);\n\t\treturn Base.serialize(obj, options, true, dictionary);\n\t},\n\n\t_changed: function(point) {\n\t\tvar path = this._path;\n\t\tif (!path)\n\t\t\treturn;\n\t\tvar curves = path._curves,\n\t\t\tindex = this._index,\n\t\t\tcurve;\n\t\tif (curves) {\n\t\t\tif ((!point || point === this._point || point === this._handleIn)\n\t\t\t\t\t&& (curve = index > 0 ? curves[index - 1] : path._closed\n\t\t\t\t\t\t? curves[curves.length - 1] : null))\n\t\t\t\tcurve._changed();\n\t\t\tif ((!point || point === this._point || point === this._handleOut)\n\t\t\t\t\t&& (curve = curves[index]))\n\t\t\t\tcurve._changed();\n\t\t}\n\t\tpath._changed(25);\n\t},\n\n\tgetPoint: function() {\n\t\treturn this._point;\n\t},\n\n\tsetPoint: function() {\n\t\tthis._point.set(Point.read(arguments));\n\t},\n\n\tgetHandleIn: function() {\n\t\treturn this._handleIn;\n\t},\n\n\tsetHandleIn: function() {\n\t\tthis._handleIn.set(Point.read(arguments));\n\t},\n\n\tgetHandleOut: function() {\n\t\treturn this._handleOut;\n\t},\n\n\tsetHandleOut: function() {\n\t\tthis._handleOut.set(Point.read(arguments));\n\t},\n\n\thasHandles: function() {\n\t\treturn !this._handleIn.isZero() || !this._handleOut.isZero();\n\t},\n\n\tclearHandles: function() {\n\t\tthis._handleIn._set(0, 0);\n\t\tthis._handleOut._set(0, 0);\n\t},\n\n\tgetSelection: function() {\n\t\treturn this._selection;\n\t},\n\n\tsetSelection: function(selection) {\n\t\tvar oldSelection = this._selection,\n\t\t\tpath = this._path;\n\t\tthis._selection = selection = selection || 0;\n\t\tif (path && selection !== oldSelection) {\n\t\t\tpath._updateSelection(this, oldSelection, selection);\n\t\t\tpath._changed(129);\n\t\t}\n\t},\n\n\tchangeSelection: function(flag, selected) {\n\t\tvar selection = this._selection;\n\t\tthis.setSelection(selected ? selection | flag : selection & ~flag);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._selection & 7);\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis.changeSelection(7, selected);\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index !== undefined ? this._index : null;\n\t},\n\n\tgetPath: function() {\n\t\treturn this._path || null;\n\t},\n\n\tgetCurve: function() {\n\t\tvar path = this._path,\n\t\t\tindex = this._index;\n\t\tif (path) {\n\t\t\tif (index > 0 && !path._closed\n\t\t\t\t\t&& index === path._segments.length - 1)\n\t\t\t\tindex--;\n\t\t\treturn path.getCurves()[index] || null;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetLocation: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve\n\t\t\t\t? new CurveLocation(curve, this === curve._segment1 ? 0 : 1)\n\t\t\t\t: null;\n\t},\n\n\tgetNext: function() {\n\t\tvar segments = this._path && this._path._segments;\n\t\treturn segments && (segments[this._index + 1]\n\t\t\t\t|| this._path._closed && segments[0]) || null;\n\t},\n\n\tsmooth: function(options, _first, _last) {\n\t\tvar opts = options || {},\n\t\t\ttype = opts.type,\n\t\t\tfactor = opts.factor,\n\t\t\tprev = this.getPrevious(),\n\t\t\tnext = this.getNext(),\n\t\t\tp0 = (prev || this)._point,\n\t\t\tp1 = this._point,\n\t\t\tp2 = (next || this)._point,\n\t\t\td1 = p0.getDistance(p1),\n\t\t\td2 = p1.getDistance(p2);\n\t\tif (!type || type === 'catmull-rom') {\n\t\t\tvar a = factor === undefined ? 0.5 : factor,\n\t\t\t\td1_a = Math.pow(d1, a),\n\t\t\t\td1_2a = d1_a * d1_a,\n\t\t\t\td2_a = Math.pow(d2, a),\n\t\t\t\td2_2a = d2_a * d2_a;\n\t\t\tif (!_first && prev) {\n\t\t\t\tvar A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a,\n\t\t\t\t\tN = 3 * d2_a * (d2_a + d1_a);\n\t\t\t\tthis.setHandleIn(N !== 0\n\t\t\t\t\t? new Point(\n\t\t\t\t\t\t(d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x,\n\t\t\t\t\t\t(d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y)\n\t\t\t\t\t: new Point());\n\t\t\t}\n\t\t\tif (!_last && next) {\n\t\t\t\tvar A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a,\n\t\t\t\t\tN = 3 * d1_a * (d1_a + d2_a);\n\t\t\t\tthis.setHandleOut(N !== 0\n\t\t\t\t\t? new Point(\n\t\t\t\t\t\t(d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x,\n\t\t\t\t\t\t(d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y)\n\t\t\t\t\t: new Point());\n\t\t\t}\n\t\t} else if (type === 'geometric') {\n\t\t\tif (prev && next) {\n\t\t\t\tvar vector = p0.subtract(p2),\n\t\t\t\t\tt = factor === undefined ? 0.4 : factor,\n\t\t\t\t\tk = t * d1 / (d1 + d2);\n\t\t\t\tif (!_first)\n\t\t\t\t\tthis.setHandleIn(vector.multiply(k));\n\t\t\t\tif (!_last)\n\t\t\t\t\tthis.setHandleOut(vector.multiply(k - t));\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new Error('Smoothing method \\'' + type + '\\' not supported.');\n\t\t}\n\t},\n\n\tgetPrevious: function() {\n\t\tvar segments = this._path && this._path._segments;\n\t\treturn segments && (segments[this._index - 1]\n\t\t\t\t|| this._path._closed && segments[segments.length - 1]) || null;\n\t},\n\n\tisFirst: function() {\n\t\treturn !this._index;\n\t},\n\n\tisLast: function() {\n\t\tvar path = this._path;\n\t\treturn path && this._index === path._segments.length - 1 || false;\n\t},\n\n\treverse: function() {\n\t\tvar handleIn = this._handleIn,\n\t\t\thandleOut = this._handleOut,\n\t\t\ttmp = handleIn.clone();\n\t\thandleIn.set(handleOut);\n\t\thandleOut.set(tmp);\n\t},\n\n\treversed: function() {\n\t\treturn new Segment(this._point, this._handleOut, this._handleIn);\n\t},\n\n\tremove: function() {\n\t\treturn this._path ? !!this._path.removeSegment(this._index) : false;\n\t},\n\n\tclone: function() {\n\t\treturn new Segment(this._point, this._handleIn, this._handleOut);\n\t},\n\n\tequals: function(segment) {\n\t\treturn segment === this || segment && this._class === segment._class\n\t\t\t\t&& this._point.equals(segment._point)\n\t\t\t\t&& this._handleIn.equals(segment._handleIn)\n\t\t\t\t&& this._handleOut.equals(segment._handleOut)\n\t\t\t\t|| false;\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [ 'point: ' + this._point ];\n\t\tif (!this._handleIn.isZero())\n\t\t\tparts.push('handleIn: ' + this._handleIn);\n\t\tif (!this._handleOut.isZero())\n\t\t\tparts.push('handleOut: ' + this._handleOut);\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\ttransform: function(matrix) {\n\t\tthis._transformCoordinates(matrix, new Array(6), true);\n\t\tthis._changed();\n\t},\n\n\tinterpolate: function(from, to, factor) {\n\t\tvar u = 1 - factor,\n\t\t\tv = factor,\n\t\t\tpoint1 = from._point,\n\t\t\tpoint2 = to._point,\n\t\t\thandleIn1 = from._handleIn,\n\t\t\thandleIn2 = to._handleIn,\n\t\t\thandleOut2 = to._handleOut,\n\t\t\thandleOut1 = from._handleOut;\n\t\tthis._point._set(\n\t\t\t\tu * point1._x + v * point2._x,\n\t\t\t\tu * point1._y + v * point2._y, true);\n\t\tthis._handleIn._set(\n\t\t\t\tu * handleIn1._x + v * handleIn2._x,\n\t\t\t\tu * handleIn1._y + v * handleIn2._y, true);\n\t\tthis._handleOut._set(\n\t\t\t\tu * handleOut1._x + v * handleOut2._x,\n\t\t\t\tu * handleOut1._y + v * handleOut2._y, true);\n\t\tthis._changed();\n\t},\n\n\t_transformCoordinates: function(matrix, coords, change) {\n\t\tvar point = this._point,\n\t\t\thandleIn = !change || !this._handleIn.isZero()\n\t\t\t\t\t? this._handleIn : null,\n\t\t\thandleOut = !change || !this._handleOut.isZero()\n\t\t\t\t\t? this._handleOut : null,\n\t\t\tx = point._x,\n\t\t\ty = point._y,\n\t\t\ti = 2;\n\t\tcoords[0] = x;\n\t\tcoords[1] = y;\n\t\tif (handleIn) {\n\t\t\tcoords[i++] = handleIn._x + x;\n\t\t\tcoords[i++] = handleIn._y + y;\n\t\t}\n\t\tif (handleOut) {\n\t\t\tcoords[i++] = handleOut._x + x;\n\t\t\tcoords[i++] = handleOut._y + y;\n\t\t}\n\t\tif (matrix) {\n\t\t\tmatrix._transformCoordinates(coords, coords, i / 2);\n\t\t\tx = coords[0];\n\t\t\ty = coords[1];\n\t\t\tif (change) {\n\t\t\t\tpoint._x = x;\n\t\t\t\tpoint._y = y;\n\t\t\t\ti = 2;\n\t\t\t\tif (handleIn) {\n\t\t\t\t\thandleIn._x = coords[i++] - x;\n\t\t\t\t\thandleIn._y = coords[i++] - y;\n\t\t\t\t}\n\t\t\t\tif (handleOut) {\n\t\t\t\t\thandleOut._x = coords[i++] - x;\n\t\t\t\t\thandleOut._y = coords[i++] - y;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!handleIn) {\n\t\t\t\t\tcoords[i++] = x;\n\t\t\t\t\tcoords[i++] = y;\n\t\t\t\t}\n\t\t\t\tif (!handleOut) {\n\t\t\t\t\tcoords[i++] = x;\n\t\t\t\t\tcoords[i++] = y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn coords;\n\t}\n});\n\nvar SegmentPoint = Point.extend({\n\tinitialize: function SegmentPoint(point, owner, key) {\n\t\tvar x, y,\n\t\t\tselected;\n\t\tif (!point) {\n\t\t\tx = y = 0;\n\t\t} else if ((x = point[0]) !== undefined) {\n\t\t\ty = point[1];\n\t\t} else {\n\t\t\tvar pt = point;\n\t\t\tif ((x = pt.x) === undefined) {\n\t\t\t\tpt = Point.read(arguments);\n\t\t\t\tx = pt.x;\n\t\t\t}\n\t\t\ty = pt.y;\n\t\t\tselected = pt.selected;\n\t\t}\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner = owner;\n\t\towner[key] = this;\n\t\tif (selected)\n\t\t\tthis.setSelected(true);\n\t},\n\n\t_set: function(x, y) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner._changed(this);\n\t\treturn this;\n\t},\n\n\tgetX: function() {\n\t\treturn this._x;\n\t},\n\n\tsetX: function(x) {\n\t\tthis._x = x;\n\t\tthis._owner._changed(this);\n\t},\n\n\tgetY: function() {\n\t\treturn this._y;\n\t},\n\n\tsetY: function(y) {\n\t\tthis._y = y;\n\t\tthis._owner._changed(this);\n\t},\n\n\tisZero: function() {\n\t\treturn Numerical.isZero(this._x) && Numerical.isZero(this._y);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._owner._selection & this._getSelection());\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis._owner.changeSelection(this._getSelection(), selected);\n\t},\n\n\t_getSelection: function() {\n\t\tvar owner = this._owner;\n\t\treturn this === owner._point ? 1\n\t\t\t: this === owner._handleIn ? 2\n\t\t\t: this === owner._handleOut ? 4\n\t\t\t: 0;\n\t}\n});\n\nvar Curve = Base.extend({\n\t_class: 'Curve',\n\n\tinitialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {\n\t\tvar count = arguments.length,\n\t\t\tseg1, seg2,\n\t\t\tpoint1, point2,\n\t\t\thandle1, handle2;\n\t\tif (count === 3) {\n\t\t\tthis._path = arg0;\n\t\t\tseg1 = arg1;\n\t\t\tseg2 = arg2;\n\t\t} else if (!count) {\n\t\t\tseg1 = new Segment();\n\t\t\tseg2 = new Segment();\n\t\t} else if (count === 1) {\n\t\t\tif ('segment1' in arg0) {\n\t\t\t\tseg1 = new Segment(arg0.segment1);\n\t\t\t\tseg2 = new Segment(arg0.segment2);\n\t\t\t} else if ('point1' in arg0) {\n\t\t\t\tpoint1 = arg0.point1;\n\t\t\t\thandle1 = arg0.handle1;\n\t\t\t\thandle2 = arg0.handle2;\n\t\t\t\tpoint2 = arg0.point2;\n\t\t\t} else if (Array.isArray(arg0)) {\n\t\t\t\tpoint1 = [arg0[0], arg0[1]];\n\t\t\t\tpoint2 = [arg0[6], arg0[7]];\n\t\t\t\thandle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];\n\t\t\t\thandle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];\n\t\t\t}\n\t\t} else if (count === 2) {\n\t\t\tseg1 = new Segment(arg0);\n\t\t\tseg2 = new Segment(arg1);\n\t\t} else if (count === 4) {\n\t\t\tpoint1 = arg0;\n\t\t\thandle1 = arg1;\n\t\t\thandle2 = arg2;\n\t\t\tpoint2 = arg3;\n\t\t} else if (count === 8) {\n\t\t\tpoint1 = [arg0, arg1];\n\t\t\tpoint2 = [arg6, arg7];\n\t\t\thandle1 = [arg2 - arg0, arg3 - arg1];\n\t\t\thandle2 = [arg4 - arg6, arg5 - arg7];\n\t\t}\n\t\tthis._segment1 = seg1 || new Segment(point1, null, handle1);\n\t\tthis._segment2 = seg2 || new Segment(point2, handle2, null);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this.hasHandles()\n\t\t\t\t? [this.getPoint1(), this.getHandle1(), this.getHandle2(),\n\t\t\t\t\tthis.getPoint2()]\n\t\t\t\t: [this.getPoint1(), this.getPoint2()],\n\t\t\t\toptions, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tthis._length = this._bounds = undefined;\n\t},\n\n\tclone: function() {\n\t\treturn new Curve(this._segment1, this._segment2);\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [ 'point1: ' + this._segment1._point ];\n\t\tif (!this._segment1._handleOut.isZero())\n\t\t\tparts.push('handle1: ' + this._segment1._handleOut);\n\t\tif (!this._segment2._handleIn.isZero())\n\t\t\tparts.push('handle2: ' + this._segment2._handleIn);\n\t\tparts.push('point2: ' + this._segment2._point);\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\tremove: function() {\n\t\tvar removed = false;\n\t\tif (this._path) {\n\t\t\tvar segment2 = this._segment2,\n\t\t\t\thandleOut = segment2._handleOut;\n\t\t\tremoved = segment2.remove();\n\t\t\tif (removed)\n\t\t\t\tthis._segment1._handleOut.set(handleOut);\n\t\t}\n\t\treturn removed;\n\t},\n\n\tgetPoint1: function() {\n\t\treturn this._segment1._point;\n\t},\n\n\tsetPoint1: function() {\n\t\tthis._segment1._point.set(Point.read(arguments));\n\t},\n\n\tgetPoint2: function() {\n\t\treturn this._segment2._point;\n\t},\n\n\tsetPoint2: function() {\n\t\tthis._segment2._point.set(Point.read(arguments));\n\t},\n\n\tgetHandle1: function() {\n\t\treturn this._segment1._handleOut;\n\t},\n\n\tsetHandle1: function() {\n\t\tthis._segment1._handleOut.set(Point.read(arguments));\n\t},\n\n\tgetHandle2: function() {\n\t\treturn this._segment2._handleIn;\n\t},\n\n\tsetHandle2: function() {\n\t\tthis._segment2._handleIn.set(Point.read(arguments));\n\t},\n\n\tgetSegment1: function() {\n\t\treturn this._segment1;\n\t},\n\n\tgetSegment2: function() {\n\t\treturn this._segment2;\n\t},\n\n\tgetPath: function() {\n\t\treturn this._path;\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._segment1._index;\n\t},\n\n\tgetNext: function() {\n\t\tvar curves = this._path && this._path._curves;\n\t\treturn curves && (curves[this._segment1._index + 1]\n\t\t\t\t|| this._path._closed && curves[0]) || null;\n\t},\n\n\tgetPrevious: function() {\n\t\tvar curves = this._path && this._path._curves;\n\t\treturn curves && (curves[this._segment1._index - 1]\n\t\t\t\t|| this._path._closed && curves[curves.length - 1]) || null;\n\t},\n\n\tisFirst: function() {\n\t\treturn !this._segment1._index;\n\t},\n\n\tisLast: function() {\n\t\tvar path = this._path;\n\t\treturn path && this._segment1._index === path._curves.length - 1\n\t\t\t\t|| false;\n\t},\n\n\tisSelected: function() {\n\t\treturn this.getPoint1().isSelected()\n\t\t\t\t&& this.getHandle2().isSelected()\n\t\t\t\t&& this.getHandle2().isSelected()\n\t\t\t\t&& this.getPoint2().isSelected();\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis.getPoint1().setSelected(selected);\n\t\tthis.getHandle1().setSelected(selected);\n\t\tthis.getHandle2().setSelected(selected);\n\t\tthis.getPoint2().setSelected(selected);\n\t},\n\n\tgetValues: function(matrix) {\n\t\treturn Curve.getValues(this._segment1, this._segment2, matrix);\n\t},\n\n\tgetPoints: function() {\n\t\tvar coords = this.getValues(),\n\t\t\tpoints = [];\n\t\tfor (var i = 0; i < 8; i += 2)\n\t\t\tpoints.push(new Point(coords[i], coords[i + 1]));\n\t\treturn points;\n\t},\n\n\tgetLength: function() {\n\t\tif (this._length == null)\n\t\t\tthis._length = Curve.getLength(this.getValues(), 0, 1);\n\t\treturn this._length;\n\t},\n\n\tgetArea: function() {\n\t\treturn Curve.getArea(this.getValues());\n\t},\n\n\tgetLine: function() {\n\t\treturn new Line(this._segment1._point, this._segment2._point);\n\t},\n\n\tgetPart: function(from, to) {\n\t\treturn new Curve(Curve.getPart(this.getValues(), from, to));\n\t},\n\n\tgetPartLength: function(from, to) {\n\t\treturn Curve.getLength(this.getValues(), from, to);\n\t},\n\n\tgetIntersections: function(curve) {\n\t\treturn Curve._getIntersections(this.getValues(),\n\t\t\t\tcurve && curve !== this ? curve.getValues() : null,\n\t\t\t\tthis, curve, [], {});\n\t},\n\n\tdivideAt: function(location) {\n\t\treturn this.divideAtTime(location && location.curve === this\n\t\t\t\t? location.time : location);\n\t},\n\n\tdivideAtTime: function(time, _setHandles) {\n\t\tvar tMin = 4e-7,\n\t\t\ttMax = 1 - tMin,\n\t\t\tres = null;\n\t\tif (time >= tMin && time <= tMax) {\n\t\t\tvar parts = Curve.subdivide(this.getValues(), time),\n\t\t\t\tleft = parts[0],\n\t\t\t\tright = parts[1],\n\t\t\t\tsetHandles = _setHandles || this.hasHandles(),\n\t\t\t\tsegment1 = this._segment1,\n\t\t\t\tsegment2 = this._segment2,\n\t\t\t\tpath = this._path;\n\t\t\tif (setHandles) {\n\t\t\t\tsegment1._handleOut._set(left[2] - left[0], left[3] - left[1]);\n\t\t\t\tsegment2._handleIn._set(right[4] - right[6],right[5] - right[7]);\n\t\t\t}\n\t\t\tvar x = left[6], y = left[7],\n\t\t\t\tsegment = new Segment(new Point(x, y),\n\t\t\t\t\t\tsetHandles && new Point(left[4] - x, left[5] - y),\n\t\t\t\t\t\tsetHandles && new Point(right[2] - x, right[3] - y));\n\t\t\tif (path) {\n\t\t\t\tpath.insert(segment1._index + 1, segment);\n\t\t\t\tres = this.getNext();\n\t\t\t} else {\n\t\t\t\tthis._segment2 = segment;\n\t\t\t\tthis._changed();\n\t\t\t\tres = new Curve(segment, segment2);\n\t\t\t}\n\t\t}\n\t\treturn res;\n\t},\n\n\tsplitAt: function(location) {\n\t\treturn this._path ? this._path.splitAt(location) : null;\n\t},\n\n\tsplitAtTime: function(t) {\n\t\treturn this.splitAt(this.getLocationAtTime(t));\n\t},\n\n\tdivide: function(offset, isTime) {\n\t\treturn this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset\n\t\t\t\t: this.getTimeAt(offset));\n\t},\n\n\tsplit: function(offset, isTime) {\n\t\treturn this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset\n\t\t\t\t: this.getTimeAt(offset));\n\t},\n\n\treversed: function() {\n\t\treturn new Curve(this._segment2.reversed(), this._segment1.reversed());\n\t},\n\n\tclearHandles: function() {\n\t\tthis._segment1._handleOut._set(0, 0);\n\t\tthis._segment2._handleIn._set(0, 0);\n\t},\n\nstatics: {\n\tgetValues: function(segment1, segment2, matrix) {\n\t\tvar p1 = segment1._point,\n\t\t\th1 = segment1._handleOut,\n\t\t\th2 = segment2._handleIn,\n\t\t\tp2 = segment2._point,\n\t\t\tvalues = [\n\t\t\t\tp1._x, p1._y,\n\t\t\t\tp1._x + h1._x, p1._y + h1._y,\n\t\t\t\tp2._x + h2._x, p2._y + h2._y,\n\t\t\t\tp2._x, p2._y\n\t\t\t];\n\t\tif (matrix)\n\t\t\tmatrix._transformCoordinates(values, values, 4);\n\t\treturn values;\n\t},\n\n\tsubdivide: function(v, t) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7];\n\t\tif (t === undefined)\n\t\t\tt = 0.5;\n\t\tvar u = 1 - t,\n\t\t\tp3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y,\n\t\t\tp4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y,\n\t\t\tp5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y,\n\t\t\tp6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y,\n\t\t\tp7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y,\n\t\t\tp8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y;\n\t\treturn [\n\t\t\t[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y],\n\t\t\t[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y]\n\t\t];\n\t},\n\n\tgetMonoCurves: function(v, dir) {\n\t\tvar curves = [],\n\t\t\tio = dir ? 0 : 1,\n\t\t\to0 = v[io],\n\t\t\to1 = v[io + 2],\n\t\t\to2 = v[io + 4],\n\t\t\to3 = v[io + 6];\n\t\tif ((o0 >= o1) === (o1 >= o2) && (o1 >= o2) === (o2 >= o3)\n\t\t\t\t|| Curve.isStraight(v)) {\n\t\t\tcurves.push(v);\n\t\t} else {\n\t\t\tvar a = 3 * (o1 - o2) - o0 + o3,\n\t\t\t\tb = 2 * (o0 + o2) - 4 * o1,\n\t\t\t\tc = o1 - o0,\n\t\t\t\ttMin = 4e-7,\n\t\t\t\ttMax = 1 - tMin,\n\t\t\t\troots = [],\n\t\t\t\tn = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);\n\t\t\tif (!n) {\n\t\t\t\tcurves.push(v);\n\t\t\t} else {\n\t\t\t\troots.sort();\n\t\t\t\tvar t = roots[0],\n\t\t\t\t\tparts = Curve.subdivide(v, t);\n\t\t\t\tcurves.push(parts[0]);\n\t\t\t\tif (n > 1) {\n\t\t\t\t\tt = (roots[1] - t) / (1 - t);\n\t\t\t\t\tparts = Curve.subdivide(parts[1], t);\n\t\t\t\t\tcurves.push(parts[0]);\n\t\t\t\t}\n\t\t\t\tcurves.push(parts[1]);\n\t\t\t}\n\t\t}\n\t\treturn curves;\n\t},\n\n\tsolveCubic: function (v, coord, val, roots, min, max) {\n\t\tvar p1 = v[coord],\n\t\t\tc1 = v[coord + 2],\n\t\t\tc2 = v[coord + 4],\n\t\t\tp2 = v[coord + 6],\n\t\t\tres = 0;\n\t\tif ( !(p1 < val && p2 < val && c1 < val && c2 < val ||\n\t\t\t\tp1 > val && p2 > val && c1 > val && c2 > val)) {\n\t\t\tvar c = 3 * (c1 - p1),\n\t\t\t\tb = 3 * (c2 - c1) - c,\n\t\t\t\ta = p2 - p1 - c - b;\n\t\t\tres = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);\n\t\t}\n\t\treturn res;\n\t},\n\n\tgetTimeOf: function(v, point) {\n\t\tvar p1 = new Point(v[0], v[1]),\n\t\t\tp2 = new Point(v[6], v[7]),\n\t\t\tepsilon = 1e-12,\n\t\t\tt = point.isClose(p1, epsilon) ? 0\n\t\t\t : point.isClose(p2, epsilon) ? 1\n\t\t\t : null;\n\t\tif (t !== null)\n\t\t\treturn t;\n\t\tvar coords = [point.x, point.y],\n\t\t\troots = [],\n\t\t\tgeomEpsilon = 1e-7;\n\t\tfor (var c = 0; c < 2; c++) {\n\t\t\tvar count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);\n\t\t\tfor (var i = 0; i < count; i++) {\n\t\t\t\tt = roots[i];\n\t\t\t\tif (point.isClose(Curve.getPoint(v, t), geomEpsilon))\n\t\t\t\t\treturn t;\n\t\t\t}\n\t\t}\n\t\treturn point.isClose(p1, geomEpsilon) ? 0\n\t\t\t : point.isClose(p2, geomEpsilon) ? 1\n\t\t\t : null;\n\t},\n\n\tgetNearestTime: function(v, point) {\n\t\tif (Curve.isStraight(v)) {\n\t\t\tvar p1x = v[0], p1y = v[1],\n\t\t\t\tp2x = v[6], p2y = v[7],\n\t\t\t\tvx = p2x - p1x, vy = p2y - p1y,\n\t\t\t\tdet = vx * vx + vy * vy;\n\t\t\tif (det === 0)\n\t\t\t\treturn 0;\n\t\t\tvar u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;\n\t\t\treturn u < 1e-12 ? 0\n\t\t\t\t : u > 0.999999999999 ? 1\n\t\t\t\t : Curve.getTimeOf(v,\n\t\t\t\t\tnew Point(p1x + u * vx, p1y + u * vy));\n\t\t}\n\n\t\tvar count = 100,\n\t\t\tminDist = Infinity,\n\t\t\tminT = 0;\n\n\t\tfunction refine(t) {\n\t\t\tif (t >= 0 && t <= 1) {\n\t\t\t\tvar dist = point.getDistance(Curve.getPoint(v, t), true);\n\t\t\t\tif (dist < minDist) {\n\t\t\t\t\tminDist = dist;\n\t\t\t\t\tminT = t;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0; i <= count; i++)\n\t\t\trefine(i / count);\n\n\t\tvar step = 1 / (count * 2);\n\t\twhile (step > 4e-7) {\n\t\t\tif (!refine(minT - step) && !refine(minT + step))\n\t\t\t\tstep /= 2;\n\t\t}\n\t\treturn minT;\n\t},\n\n\tgetPart: function(v, from, to) {\n\t\tvar flip = from > to;\n\t\tif (flip) {\n\t\t\tvar tmp = from;\n\t\t\tfrom = to;\n\t\t\tto = tmp;\n\t\t}\n\t\tif (from > 0)\n\t\t\tv = Curve.subdivide(v, from)[1];\n\t\tif (to < 1)\n\t\t\tv = Curve.subdivide(v, (to - from) / (1 - from))[0];\n\t\treturn flip\n\t\t\t\t? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]\n\t\t\t\t: v;\n\t},\n\n\tisFlatEnough: function(v, flatness) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7],\n\t\t\tux = 3 * c1x - 2 * p1x - p2x,\n\t\t\tuy = 3 * c1y - 2 * p1y - p2y,\n\t\t\tvx = 3 * c2x - 2 * p2x - p1x,\n\t\t\tvy = 3 * c2y - 2 * p2y - p1y;\n\t\treturn Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)\n\t\t\t\t<= 16 * flatness * flatness;\n\t},\n\n\tgetArea: function(v) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7];\n\t\treturn 3 * ((p2y - p1y) * (c1x + c2x) - (p2x - p1x) * (c1y + c2y)\n\t\t\t\t+ c1y * (p1x - c2x) - c1x * (p1y - c2y)\n\t\t\t\t+ p2y * (c2x + p1x / 3) - p2x * (c2y + p1y / 3)) / 20;\n\t},\n\n\tgetBounds: function(v) {\n\t\tvar min = v.slice(0, 2),\n\t\t\tmax = min.slice(),\n\t\t\troots = [0, 0];\n\t\tfor (var i = 0; i < 2; i++)\n\t\t\tCurve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],\n\t\t\t\t\ti, 0, min, max, roots);\n\t\treturn new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);\n\t},\n\n\t_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {\n\t\tfunction add(value, padding) {\n\t\t\tvar left = value - padding,\n\t\t\t\tright = value + padding;\n\t\t\tif (left < min[coord])\n\t\t\t\tmin[coord] = left;\n\t\t\tif (right > max[coord])\n\t\t\t\tmax[coord] = right;\n\t\t}\n\n\t\tpadding /= 2;\n\t\tvar minPad = min[coord] - padding,\n\t\t\tmaxPad = max[coord] + padding;\n\t\tif ( v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||\n\t\t\t\tv0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {\n\t\t\tif (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {\n\t\t\t\tadd(v0, padding);\n\t\t\t\tadd(v3, padding);\n\t\t\t} else {\n\t\t\t\tvar a = 3 * (v1 - v2) - v0 + v3,\n\t\t\t\t\tb = 2 * (v0 + v2) - 4 * v1,\n\t\t\t\t\tc = v1 - v0,\n\t\t\t\t\tcount = Numerical.solveQuadratic(a, b, c, roots),\n\t\t\t\t\ttMin = 4e-7,\n\t\t\t\t\ttMax = 1 - tMin;\n\t\t\t\tadd(v3, 0);\n\t\t\t\tfor (var i = 0; i < count; i++) {\n\t\t\t\t\tvar t = roots[i],\n\t\t\t\t\t\tu = 1 - t;\n\t\t\t\t\tif (tMin < t && t < tMax)\n\t\t\t\t\t\tadd(u * u * u * v0\n\t\t\t\t\t\t\t+ 3 * u * u * t * v1\n\t\t\t\t\t\t\t+ 3 * u * t * t * v2\n\t\t\t\t\t\t\t+ t * t * t * v3,\n\t\t\t\t\t\t\tpadding);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}}, Base.each(\n\t['getBounds', 'getStrokeBounds', 'getHandleBounds'],\n\tfunction(name) {\n\t\tthis[name] = function() {\n\t\t\tif (!this._bounds)\n\t\t\t\tthis._bounds = {};\n\t\t\tvar bounds = this._bounds[name];\n\t\t\tif (!bounds) {\n\t\t\t\tbounds = this._bounds[name] = Path[name](\n\t\t\t\t\t\t[this._segment1, this._segment2], false, this._path);\n\t\t\t}\n\t\t\treturn bounds.clone();\n\t\t};\n\t},\n{\n\n}), Base.each({\n\tisStraight: function(l, h1, h2) {\n\t\tif (h1.isZero() && h2.isZero()) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\tvar v = l.getVector(),\n\t\t\t\tepsilon = 1e-7;\n\t\t\tif (v.isZero()) {\n\t\t\t\treturn false;\n\t\t\t} else if (l.getDistance(h1) < epsilon\n\t\t\t\t\t&& l.getDistance(h2) < epsilon) {\n\t\t\t\tvar div = v.dot(v),\n\t\t\t\t\tp1 = v.dot(h1) / div,\n\t\t\t\t\tp2 = v.dot(h2) / div;\n\t\t\t\treturn p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t},\n\n\tisLinear: function(l, h1, h2) {\n\t\tvar third = l.getVector().divide(3);\n\t\treturn h1.equals(third) && h2.negate().equals(third);\n\t}\n}, function(test, name) {\n\tthis[name] = function() {\n\t\tvar seg1 = this._segment1,\n\t\t\tseg2 = this._segment2;\n\t\treturn test(new Line(seg1._point, seg2._point),\n\t\t\t\tseg1._handleOut, seg2._handleIn);\n\t};\n\n\tthis.statics[name] = function(v) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tp2x = v[6], p2y = v[7];\n\t\treturn test(new Line(p1x, p1y, p2x, p2y),\n\t\t\t\tnew Point(v[2] - p1x, v[3] - p1y),\n\t\t\t\tnew Point(v[4] - p2x, v[5] - p2y));\n\t};\n}, {\n\tstatics: {},\n\n\thasHandles: function() {\n\t\treturn !this._segment1._handleOut.isZero()\n\t\t\t\t|| !this._segment2._handleIn.isZero();\n\t},\n\n\tisCollinear: function(curve) {\n\t\treturn curve && this.isStraight() && curve.isStraight()\n\t\t\t\t&& this.getLine().isCollinear(curve.getLine());\n\t},\n\n\tisHorizontal: function() {\n\t\treturn this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)\n\t\t\t\t< 1e-8;\n\t},\n\n\tisVertical: function() {\n\t\treturn this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)\n\t\t\t\t< 1e-8;\n\t}\n}), {\n\tbeans: false,\n\n\tgetLocationAt: function(offset, _isTime) {\n\t\treturn this.getLocationAtTime(\n\t\t\t\t_isTime ? offset : this.getTimeAt(offset));\n\t},\n\n\tgetLocationAtTime: function(t) {\n\t\treturn t != null && t >= 0 && t <= 1\n\t\t\t\t? new CurveLocation(this, t)\n\t\t\t\t: null;\n\t},\n\n\tgetTimeAt: function(offset, start) {\n\t\treturn Curve.getTimeAt(this.getValues(), offset, start);\n\t},\n\n\tgetParameterAt: '#getTimeAt',\n\n\tgetOffsetAtTime: function(t) {\n\t\treturn this.getPartLength(0, t);\n\t},\n\n\tgetLocationOf: function() {\n\t\treturn this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));\n\t},\n\n\tgetOffsetOf: function() {\n\t\tvar loc = this.getLocationOf.apply(this, arguments);\n\t\treturn loc ? loc.getOffset() : null;\n\t},\n\n\tgetTimeOf: function() {\n\t\treturn Curve.getTimeOf(this.getValues(), Point.read(arguments));\n\t},\n\n\tgetParameterOf: '#getTimeOf',\n\n\tgetNearestLocation: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tvalues = this.getValues(),\n\t\t\tt = Curve.getNearestTime(values, point),\n\t\t\tpt = Curve.getPoint(values, t);\n\t\treturn new CurveLocation(this, t, pt, null, point.getDistance(pt));\n\t},\n\n\tgetNearestPoint: function() {\n\t\tvar loc = this.getNearestLocation.apply(this, arguments);\n\t\treturn loc ? loc.getPoint() : loc;\n\t}\n\n},\nnew function() {\n\tvar methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',\n\t\t'getWeightedNormal', 'getCurvature'];\n\treturn Base.each(methods,\n\t\tfunction(name) {\n\t\t\tthis[name + 'At'] = function(location, _isTime) {\n\t\t\t\tvar values = this.getValues();\n\t\t\t\treturn Curve[name](values, _isTime ? location\n\t\t\t\t\t\t: Curve.getTimeAt(values, location));\n\t\t\t};\n\n\t\t\tthis[name + 'AtTime'] = function(time) {\n\t\t\t\treturn Curve[name](this.getValues(), time);\n\t\t\t};\n\t\t}, {\n\t\t\tstatics: {\n\t\t\t\t_evaluateMethods: methods\n\t\t\t}\n\t\t}\n\t);\n},\nnew function() {\n\n\tfunction getLengthIntegrand(v) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7],\n\n\t\t\tax = 9 * (c1x - c2x) + 3 * (p2x - p1x),\n\t\t\tbx = 6 * (p1x + c2x) - 12 * c1x,\n\t\t\tcx = 3 * (c1x - p1x),\n\n\t\t\tay = 9 * (c1y - c2y) + 3 * (p2y - p1y),\n\t\t\tby = 6 * (p1y + c2y) - 12 * c1y,\n\t\t\tcy = 3 * (c1y - p1y);\n\n\t\treturn function(t) {\n\t\t\tvar dx = (ax * t + bx) * t + cx,\n\t\t\t\tdy = (ay * t + by) * t + cy;\n\t\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t\t};\n\t}\n\n\tfunction getIterations(a, b) {\n\t\treturn Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));\n\t}\n\n\tfunction evaluate(v, t, type, normalized) {\n\t\tif (t == null || t < 0 || t > 1)\n\t\t\treturn null;\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7],\n\t\t\tisZero = Numerical.isZero;\n\t\tif (isZero(c1x - p1x) && isZero(c1y - p1y)) {\n\t\t\tc1x = p1x;\n\t\t\tc1y = p1y;\n\t\t}\n\t\tif (isZero(c2x - p2x) && isZero(c2y - p2y)) {\n\t\t\tc2x = p2x;\n\t\t\tc2y = p2y;\n\t\t}\n\t\tvar cx = 3 * (c1x - p1x),\n\t\t\tbx = 3 * (c2x - c1x) - cx,\n\t\t\tax = p2x - p1x - cx - bx,\n\t\t\tcy = 3 * (c1y - p1y),\n\t\t\tby = 3 * (c2y - c1y) - cy,\n\t\t\tay = p2y - p1y - cy - by,\n\t\t\tx, y;\n\t\tif (type === 0) {\n\t\t\tx = t === 0 ? p1x : t === 1 ? p2x\n\t\t\t\t\t: ((ax * t + bx) * t + cx) * t + p1x;\n\t\t\ty = t === 0 ? p1y : t === 1 ? p2y\n\t\t\t\t\t: ((ay * t + by) * t + cy) * t + p1y;\n\t\t} else {\n\t\t\tvar tMin = 4e-7,\n\t\t\t\ttMax = 1 - tMin;\n\t\t\tif (t < tMin) {\n\t\t\t\tx = cx;\n\t\t\t\ty = cy;\n\t\t\t} else if (t > tMax) {\n\t\t\t\tx = 3 * (p2x - c2x);\n\t\t\t\ty = 3 * (p2y - c2y);\n\t\t\t} else {\n\t\t\t\tx = (3 * ax * t + 2 * bx) * t + cx;\n\t\t\t\ty = (3 * ay * t + 2 * by) * t + cy;\n\t\t\t}\n\t\t\tif (normalized) {\n\t\t\t\tif (x === 0 && y === 0 && (t < tMin || t > tMax)) {\n\t\t\t\t\tx = c2x - c1x;\n\t\t\t\t\ty = c2y - c1y;\n\t\t\t\t}\n\t\t\t\tvar len = Math.sqrt(x * x + y * y);\n\t\t\t\tif (len) {\n\t\t\t\t\tx /= len;\n\t\t\t\t\ty /= len;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (type === 3) {\n\t\t\t\tvar x2 = 6 * ax * t + 2 * bx,\n\t\t\t\t\ty2 = 6 * ay * t + 2 * by,\n\t\t\t\t\td = Math.pow(x * x + y * y, 3 / 2);\n\t\t\t\tx = d !== 0 ? (x * y2 - y * x2) / d : 0;\n\t\t\t\ty = 0;\n\t\t\t}\n\t\t}\n\t\treturn type === 2 ? new Point(y, -x) : new Point(x, y);\n\t}\n\n\treturn { statics: {\n\n\t\tgetLength: function(v, a, b, ds) {\n\t\t\tif (a === undefined)\n\t\t\t\ta = 0;\n\t\t\tif (b === undefined)\n\t\t\t\tb = 1;\n\t\t\tif (Curve.isStraight(v)) {\n\t\t\t\tvar c = v;\n\t\t\t\tif (b < 1) {\n\t\t\t\t\tc = Curve.subdivide(c, b)[0];\n\t\t\t\t\ta /= b;\n\t\t\t\t}\n\t\t\t\tif (a > 0) {\n\t\t\t\t\tc = Curve.subdivide(c, a)[1];\n\t\t\t\t}\n\t\t\t\tvar dx = c[6] - c[0],\n\t\t\t\t\tdy = c[7] - c[1];\n\t\t\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t\t\t}\n\t\t\treturn Numerical.integrate(ds || getLengthIntegrand(v), a, b,\n\t\t\t\t\tgetIterations(a, b));\n\t\t},\n\n\t\tgetTimeAt: function(v, offset, start) {\n\t\t\tif (start === undefined)\n\t\t\t\tstart = offset < 0 ? 1 : 0;\n\t\t\tif (offset === 0)\n\t\t\t\treturn start;\n\t\t\tvar abs = Math.abs,\n\t\t\t\tepsilon = 1e-12,\n\t\t\t\tforward = offset > 0,\n\t\t\t\ta = forward ? start : 0,\n\t\t\t\tb = forward ? 1 : start,\n\t\t\t\tds = getLengthIntegrand(v),\n\t\t\t\trangeLength = Curve.getLength(v, a, b, ds),\n\t\t\t\tdiff = abs(offset) - rangeLength;\n\t\t\tif (abs(diff) < epsilon) {\n\t\t\t\treturn forward ? b : a;\n\t\t\t} else if (diff > epsilon) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tvar guess = offset / rangeLength,\n\t\t\t\tlength = 0;\n\t\t\tfunction f(t) {\n\t\t\t\tlength += Numerical.integrate(ds, start, t,\n\t\t\t\t\t\tgetIterations(start, t));\n\t\t\t\tstart = t;\n\t\t\t\treturn length - offset;\n\t\t\t}\n\t\t\treturn Numerical.findRoot(f, ds, start + guess, a, b, 32,\n\t\t\t\t\t1e-12);\n\t\t},\n\n\t\tgetPoint: function(v, t) {\n\t\t\treturn evaluate(v, t, 0, false);\n\t\t},\n\n\t\tgetTangent: function(v, t) {\n\t\t\treturn evaluate(v, t, 1, true);\n\t\t},\n\n\t\tgetWeightedTangent: function(v, t) {\n\t\t\treturn evaluate(v, t, 1, false);\n\t\t},\n\n\t\tgetNormal: function(v, t) {\n\t\t\treturn evaluate(v, t, 2, true);\n\t\t},\n\n\t\tgetWeightedNormal: function(v, t) {\n\t\t\treturn evaluate(v, t, 2, false);\n\t\t},\n\n\t\tgetCurvature: function(v, t) {\n\t\t\treturn evaluate(v, t, 3, false).x;\n\t\t}\n\t}};\n},\nnew function() {\n\n\tfunction addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,\n\t\t\toverlap) {\n\t\tvar excludeStart = !overlap && param.excludeStart,\n\t\t\texcludeEnd = !overlap && param.excludeEnd,\n\t\t\ttMin = 4e-7,\n\t\t\ttMax = 1 - tMin;\n\t\tif (t1 == null)\n\t\t\tt1 = Curve.getTimeOf(v1, p1);\n\t\tif (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&\n\t\t\tt1 <= (excludeEnd ? tMax : 1)) {\n\t\t\tif (t2 == null)\n\t\t\t\tt2 = Curve.getTimeOf(v2, p2);\n\t\t\tif (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&\n\t\t\t\tt2 <= (excludeStart ? tMax : 1)) {\n\t\t\t\tvar renormalize = param.renormalize;\n\t\t\t\tif (renormalize) {\n\t\t\t\t\tvar res = renormalize(t1, t2);\n\t\t\t\t\tt1 = res[0];\n\t\t\t\t\tt2 = res[1];\n\t\t\t\t}\n\t\t\t\tvar loc1 = new CurveLocation(c1, t1,\n\t\t\t\t\t\tp1 || Curve.getPoint(v1, t1), overlap),\n\t\t\t\t\tloc2 = new CurveLocation(c2, t2,\n\t\t\t\t\t\tp2 || Curve.getPoint(v2, t2), overlap),\n\t\t\t\t\tflip = loc1.getPath() === loc2.getPath()\n\t\t\t\t\t\t&& loc1.getIndex() > loc2.getIndex(),\n\t\t\t\t\tloc = flip ? loc2 : loc1,\n\t\t\t\t\tinclude = param.include;\n\t\t\t\tloc1._intersection = loc2;\n\t\t\t\tloc2._intersection = loc1;\n\t\t\t\tif (!include || include(loc)) {\n\t\t\t\t\tCurveLocation.insert(locations, loc, true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax,\n\t\t\tuMin, uMax, flip, recursion, calls) {\n\t\tif (++recursion >= 48 || ++calls > 4096)\n\t\t\treturn calls;\n\t\tvar q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],\n\t\t\tgetSignedDistance = Line.getSignedDistance,\n\t\t\td1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),\n\t\t\td2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),\n\t\t\tfactor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,\n\t\t\tdMin = factor * Math.min(0, d1, d2),\n\t\t\tdMax = factor * Math.max(0, d1, d2),\n\t\t\tdp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),\n\t\t\tdp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),\n\t\t\tdp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),\n\t\t\tdp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),\n\t\t\thull = getConvexHull(dp0, dp1, dp2, dp3),\n\t\t\ttop = hull[0],\n\t\t\tbottom = hull[1],\n\t\t\ttMinClip,\n\t\t\ttMaxClip;\n\t\tif (d1 === 0 && d2 === 0\n\t\t\t\t&& dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0\n\t\t\t|| (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null\n\t\t\t|| (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),\n\t\t\t\tdMin, dMax)) == null)\n\t\t\treturn calls;\n\t\tvar tMinNew = tMin + (tMax - tMin) * tMinClip,\n\t\t\ttMaxNew = tMin + (tMax - tMin) * tMaxClip;\n\t\tif (Math.max(uMax - uMin, tMaxNew - tMinNew)\n\t\t\t\t< 1e-10) {\n\t\t\tvar t = (tMinNew + tMaxNew) / 2,\n\t\t\t\tu = (uMin + uMax) / 2;\n\t\t\tv1 = c1.getValues();\n\t\t\tv2 = c2.getValues();\n\t\t\taddLocation(locations, param,\n\t\t\t\t\tflip ? v2 : v1, flip ? c2 : c1, flip ? u : t, null,\n\t\t\t\t\tflip ? v1 : v2, flip ? c1 : c2, flip ? t : u, null);\n\t\t} else {\n\t\t\tv1 = Curve.getPart(v1, tMinClip, tMaxClip);\n\t\t\tif (tMaxClip - tMinClip > 0.8) {\n\t\t\t\tif (tMaxNew - tMinNew > uMax - uMin) {\n\t\t\t\t\tvar parts = Curve.subdivide(v1, 0.5),\n\t\t\t\t\t\tt = (tMinNew + tMaxNew) / 2;\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tv2, parts[0], c2, c1, locations, param,\n\t\t\t\t\t\t\tuMin, uMax, tMinNew, t, !flip, recursion, calls);\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tv2, parts[1], c2, c1, locations, param,\n\t\t\t\t\t\t\tuMin, uMax, t, tMaxNew, !flip, recursion, calls);\n\t\t\t\t} else {\n\t\t\t\t\tvar parts = Curve.subdivide(v2, 0.5),\n\t\t\t\t\t\tu = (uMin + uMax) / 2;\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tparts[0], v1, c2, c1, locations, param,\n\t\t\t\t\t\t\tuMin, u, tMinNew, tMaxNew, !flip, recursion, calls);\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tparts[1], v1, c2, c1, locations, param,\n\t\t\t\t\t\t\tu, uMax, tMinNew, tMaxNew, !flip, recursion, calls);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (uMax - uMin >= 1e-10) {\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\tv2, v1, c2, c1, locations, param,\n\t\t\t\t\t\tuMin, uMax, tMinNew, tMaxNew, !flip, recursion, calls);\n\t\t\t\t} else {\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\tv1, v2, c1, c2, locations, param,\n\t\t\t\t\t\ttMinNew, tMaxNew, uMin, uMax, flip, recursion, calls);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn calls;\n\t}\n\n\tfunction getConvexHull(dq0, dq1, dq2, dq3) {\n\t\tvar p0 = [ 0, dq0 ],\n\t\t\tp1 = [ 1 / 3, dq1 ],\n\t\t\tp2 = [ 2 / 3, dq2 ],\n\t\t\tp3 = [ 1, dq3 ],\n\t\t\tdist1 = dq1 - (2 * dq0 + dq3) / 3,\n\t\t\tdist2 = dq2 - (dq0 + 2 * dq3) / 3,\n\t\t\thull;\n\t\tif (dist1 * dist2 < 0) {\n\t\t\thull = [[p0, p1, p3], [p0, p2, p3]];\n\t\t} else {\n\t\t\tvar distRatio = dist1 / dist2;\n\t\t\thull = [\n\t\t\t\tdistRatio >= 2 ? [p0, p1, p3]\n\t\t\t\t: distRatio <= 0.5 ? [p0, p2, p3]\n\t\t\t\t: [p0, p1, p2, p3],\n\t\t\t\t[p0, p3]\n\t\t\t];\n\t\t}\n\t\treturn (dist1 || dist2) < 0 ? hull.reverse() : hull;\n\t}\n\n\tfunction clipConvexHull(hullTop, hullBottom, dMin, dMax) {\n\t\tif (hullTop[0][1] < dMin) {\n\t\t\treturn clipConvexHullPart(hullTop, true, dMin);\n\t\t} else if (hullBottom[0][1] > dMax) {\n\t\t\treturn clipConvexHullPart(hullBottom, false, dMax);\n\t\t} else {\n\t\t\treturn hullTop[0][0];\n\t\t}\n\t}\n\n\tfunction clipConvexHullPart(part, top, threshold) {\n\t\tvar px = part[0][0],\n\t\t\tpy = part[0][1];\n\t\tfor (var i = 1, l = part.length; i < l; i++) {\n\t\t\tvar qx = part[i][0],\n\t\t\t\tqy = part[i][1];\n\t\t\tif (top ? qy >= threshold : qy <= threshold) {\n\t\t\t\treturn qy === threshold ? qx\n\t\t\t\t\t\t: px + (threshold - py) * (qx - px) / (qy - py);\n\t\t\t}\n\t\t\tpx = qx;\n\t\t\tpy = qy;\n\t\t}\n\t\treturn null;\n\t}\n\n\tfunction addCurveLineIntersections(v1, v2, c1, c2, locations, param) {\n\t\tvar flip = Curve.isStraight(v1),\n\t\t\tvc = flip ? v2 : v1,\n\t\t\tvl = flip ? v1 : v2,\n\t\t\tlx1 = vl[0], ly1 = vl[1],\n\t\t\tlx2 = vl[6], ly2 = vl[7],\n\t\t\tldx = lx2 - lx1,\n\t\t\tldy = ly2 - ly1,\n\t\t\tangle = Math.atan2(-ldy, ldx),\n\t\t\tsin = Math.sin(angle),\n\t\t\tcos = Math.cos(angle),\n\t\t\trvc = [];\n\t\tfor(var i = 0; i < 8; i += 2) {\n\t\t\tvar x = vc[i] - lx1,\n\t\t\t\ty = vc[i + 1] - ly1;\n\t\t\trvc.push(\n\t\t\t\tx * cos - y * sin,\n\t\t\t\tx * sin + y * cos);\n\t\t}\n\t\tvar roots = [],\n\t\t\tcount = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);\n\t\tfor (var i = 0; i < count; i++) {\n\t\t\tvar tc = roots[i],\n\t\t\t\tpc = Curve.getPoint(vc, tc),\n\t\t\t\ttl = Curve.getTimeOf(vl, pc);\n\t\t\tif (tl !== null) {\n\t\t\t\tvar pl = Curve.getPoint(vl, tl),\n\t\t\t\t\tt1 = flip ? tl : tc,\n\t\t\t\t\tt2 = flip ? tc : tl;\n\t\t\t\tif (!param.excludeEnd || t2 > Numerical.CURVETIME_EPSILON) {\n\t\t\t\t\taddLocation(locations, param,\n\t\t\t\t\t\t\tv1, c1, t1, flip ? pl : pc,\n\t\t\t\t\t\t\tv2, c2, t2, flip ? pc : pl);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction addLineIntersection(v1, v2, c1, c2, locations, param) {\n\t\tvar pt = Line.intersect(\n\t\t\t\tv1[0], v1[1], v1[6], v1[7],\n\t\t\t\tv2[0], v2[1], v2[6], v2[7]);\n\t\tif (pt) {\n\t\t\taddLocation(locations, param, v1, c1, null, pt, v2, c2, null, pt);\n\t\t}\n\t}\n\n\treturn { statics: {\n\t\t_getIntersections: function(v1, v2, c1, c2, locations, param) {\n\t\t\tif (!v2) {\n\t\t\t\treturn Curve._getSelfIntersection(v1, c1, locations, param);\n\t\t\t}\n\t\t\tvar epsilon = 1e-7,\n\t\t\t\tc1p1x = v1[0], c1p1y = v1[1],\n\t\t\t\tc1p2x = v1[6], c1p2y = v1[7],\n\t\t\t\tc2p1x = v2[0], c2p1y = v2[1],\n\t\t\t\tc2p2x = v2[6], c2p2y = v2[7],\n\t\t\t\tc1s1x = (3 * v1[2] + c1p1x) / 4,\n\t\t\t\tc1s1y = (3 * v1[3] + c1p1y) / 4,\n\t\t\t\tc1s2x = (3 * v1[4] + c1p2x) / 4,\n\t\t\t\tc1s2y = (3 * v1[5] + c1p2y) / 4,\n\t\t\t\tc2s1x = (3 * v2[2] + c2p1x) / 4,\n\t\t\t\tc2s1y = (3 * v2[3] + c2p1y) / 4,\n\t\t\t\tc2s2x = (3 * v2[4] + c2p2x) / 4,\n\t\t\t\tc2s2y = (3 * v2[5] + c2p2y) / 4,\n\t\t\t\tmin = Math.min,\n\t\t\t\tmax = Math.max;\n\t\t\tif (!( max(c1p1x, c1s1x, c1s2x, c1p2x) + epsilon >\n\t\t\t\t\tmin(c2p1x, c2s1x, c2s2x, c2p2x) &&\n\t\t\t\t\tmin(c1p1x, c1s1x, c1s2x, c1p2x) - epsilon <\n\t\t\t\t\tmax(c2p1x, c2s1x, c2s2x, c2p2x) &&\n\t\t\t\t\tmax(c1p1y, c1s1y, c1s2y, c1p2y) + epsilon >\n\t\t\t\t\tmin(c2p1y, c2s1y, c2s2y, c2p2y) &&\n\t\t\t\t\tmin(c1p1y, c1s1y, c1s2y, c1p2y) - epsilon <\n\t\t\t\t\tmax(c2p1y, c2s1y, c2s2y, c2p2y)))\n\t\t\t\treturn locations;\n\t\t\tvar overlaps = Curve.getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tfor (var i = 0; i < 2; i++) {\n\t\t\t\t\tvar overlap = overlaps[i];\n\t\t\t\t\taddLocation(locations, param,\n\t\t\t\t\t\tv1, c1, overlap[0], null,\n\t\t\t\t\t\tv2, c2, overlap[1], null, true);\n\t\t\t\t}\n\t\t\t\treturn locations;\n\t\t\t}\n\n\t\t\tvar straight1 = Curve.isStraight(v1),\n\t\t\t\tstraight2 = Curve.isStraight(v2),\n\t\t\t\tstraight = straight1 && straight2,\n\t\t\t\tbefore = locations.length;\n\t\t\t(straight\n\t\t\t\t? addLineIntersection\n\t\t\t\t: straight1 || straight2\n\t\t\t\t\t? addCurveLineIntersections\n\t\t\t\t\t: addCurveIntersections)(\n\t\t\t\t\t\tv1, v2, c1, c2, locations, param,\n\t\t\t\t\t\t0, 1, 0, 1, 0, 0, 0);\n\t\t\tif (straight && locations.length > before)\n\t\t\t\treturn locations;\n\t\t\tvar c1p1 = new Point(c1p1x, c1p1y),\n\t\t\t\tc1p2 = new Point(c1p2x, c1p2y),\n\t\t\t\tc2p1 = new Point(c2p1x, c2p1y),\n\t\t\t\tc2p2 = new Point(c2p2x, c2p2y);\n\t\t\tif (c1p1.isClose(c2p1, epsilon))\n\t\t\t\taddLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 0, c2p1);\n\t\t\tif (!param.excludeStart && c1p1.isClose(c2p2, epsilon))\n\t\t\t\taddLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 1, c2p2);\n\t\t\tif (!param.excludeEnd && c1p2.isClose(c2p1, epsilon))\n\t\t\t\taddLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 0, c2p1);\n\t\t\tif (c1p2.isClose(c2p2, epsilon))\n\t\t\t\taddLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 1, c2p2);\n\t\t\treturn locations;\n\t\t},\n\n\t\t_getSelfIntersection: function(v1, c1, locations, param) {\n\t\t\tvar p1x = v1[0], p1y = v1[1],\n\t\t\t\th1x = v1[2], h1y = v1[3],\n\t\t\t\th2x = v1[4], h2y = v1[5],\n\t\t\t\tp2x = v1[6], p2y = v1[7];\n\t\t\tvar line = new Line(p1x, p1y, p2x, p2y, false),\n\t\t\t\tside1 = line.getSide(new Point(h1x, h1y), true),\n\t\t\t\tside2 = line.getSide(new Point(h2x, h2y), true);\n\t\t\tif (side1 === side2) {\n\t\t\t\tvar edgeSum = (p1x - h2x) * (h1y - p2y)\n\t\t\t\t\t\t\t+ (h1x - p2x) * (h2y - p1y);\n\t\t\t\tif (edgeSum * side1 > 0)\n\t\t\t\t\treturn locations;\n\t\t\t}\n\t\t\tvar ax = p2x - 3 * h2x + 3 * h1x - p1x,\n\t\t\t\tbx = h2x - 2 * h1x + p1x,\n\t\t\t\tcx = h1x - p1x,\n\t\t\t\tay = p2y - 3 * h2y + 3 * h1y - p1y,\n\t\t\t\tby = h2y - 2 * h1y + p1y,\n\t\t\t\tcy = h1y - p1y,\n\t\t\t\tac = ay * cx - ax * cy,\n\t\t\t\tab = ay * bx - ax * by,\n\t\t\t\tbc = by * cx - bx * cy;\n\t\t\tif (ac * ac - 4 * ab * bc < 0) {\n\t\t\t\tvar roots = [],\n\t\t\t\t\ttSplit,\n\t\t\t\t\tcount = Numerical.solveCubic(\n\t\t\t\t\t\t\tax * ax + ay * ay,\n\t\t\t\t\t\t\t3 * (ax * bx + ay * by),\n\t\t\t\t\t\t\t2 * (bx * bx + by * by) + ax * cx + ay * cy,\n\t\t\t\t\t\t\tbx * cx + by * cy,\n\t\t\t\t\t\t\troots, 0, 1);\n\t\t\t\tif (count > 0) {\n\t\t\t\t\tfor (var i = 0, maxCurvature = 0; i < count; i++) {\n\t\t\t\t\t\tvar curvature = Math.abs(\n\t\t\t\t\t\t\t\tc1.getCurvatureAtTime(roots[i]));\n\t\t\t\t\t\tif (curvature > maxCurvature) {\n\t\t\t\t\t\t\tmaxCurvature = curvature;\n\t\t\t\t\t\t\ttSplit = roots[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvar parts = Curve.subdivide(v1, tSplit);\n\t\t\t\t\tparam.excludeEnd = true;\n\t\t\t\t\tparam.renormalize = function(t1, t2) {\n\t\t\t\t\t\treturn [t1 * tSplit, t2 * (1 - tSplit) + tSplit];\n\t\t\t\t\t};\n\t\t\t\t\tCurve._getIntersections(parts[0], parts[1], c1, c1,\n\t\t\t\t\t\t\tlocations, param);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn locations;\n\t\t},\n\n\t\tgetOverlaps: function(v1, v2) {\n\t\t\tvar abs = Math.abs,\n\t\t\t\ttimeEpsilon = 4e-7,\n\t\t\t\tgeomEpsilon = 1e-7,\n\t\t\t\tstraight1 = Curve.isStraight(v1),\n\t\t\t\tstraight2 = Curve.isStraight(v2),\n\t\t\t\tstraightBoth = straight1 && straight2;\n\n\t\t\tfunction getSquaredLineLength(v) {\n\t\t\t\tvar x = v[6] - v[0],\n\t\t\t\t\ty = v[7] - v[1];\n\t\t\t\treturn x * x + y * y;\n\t\t\t}\n\n\t\t\tvar flip = getSquaredLineLength(v1) < getSquaredLineLength(v2),\n\t\t\t\tl1 = flip ? v2 : v1,\n\t\t\t\tl2 = flip ? v1 : v2,\n\t\t\t\tline = new Line(l1[0], l1[1], l1[6], l1[7]);\n\t\t\tif (line.getDistance(new Point(l2[0], l2[1])) < geomEpsilon &&\n\t\t\t\tline.getDistance(new Point(l2[6], l2[7])) < geomEpsilon) {\n\t\t\t\tif (!straightBoth &&\n\t\t\t\t\tline.getDistance(new Point(l1[2], l1[3])) < geomEpsilon &&\n\t\t\t\t\tline.getDistance(new Point(l1[4], l1[5])) < geomEpsilon &&\n\t\t\t\t\tline.getDistance(new Point(l2[2], l2[3])) < geomEpsilon &&\n\t\t\t\t\tline.getDistance(new Point(l2[4], l2[5])) < geomEpsilon) {\n\t\t\t\t\tstraight1 = straight2 = straightBoth = true;\n\t\t\t\t}\n\t\t\t} else if (straightBoth) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (straight1 ^ straight2) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tvar v = [v1, v2],\n\t\t\t\tpairs = [];\n\t\t\tfor (var i = 0, t1 = 0;\n\t\t\t\t\ti < 2 && pairs.length < 2;\n\t\t\t\t\ti += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {\n\t\t\t\tvar t2 = Curve.getTimeOf(v[i ^ 1], new Point(\n\t\t\t\t\t\tv[i][t1 === 0 ? 0 : 6],\n\t\t\t\t\t\tv[i][t1 === 0 ? 1 : 7]));\n\t\t\t\tif (t2 != null) {\n\t\t\t\t\tvar pair = i === 0 ? [t1, t2] : [t2, t1];\n\t\t\t\t\tif (!pairs.length ||\n\t\t\t\t\t\tabs(pair[0] - pairs[0][0]) > timeEpsilon &&\n\t\t\t\t\t\tabs(pair[1] - pairs[0][1]) > timeEpsilon)\n\t\t\t\t\t\tpairs.push(pair);\n\t\t\t\t}\n\t\t\t\tif (i === 1 && !pairs.length)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pairs.length !== 2) {\n\t\t\t\tpairs = null;\n\t\t\t} else if (!straightBoth) {\n\t\t\t\tvar o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),\n\t\t\t\t\to2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);\n\t\t\t\tif (abs(o2[2] - o1[2]) > geomEpsilon ||\n\t\t\t\t\tabs(o2[3] - o1[3]) > geomEpsilon ||\n\t\t\t\t\tabs(o2[4] - o1[4]) > geomEpsilon ||\n\t\t\t\t\tabs(o2[5] - o1[5]) > geomEpsilon)\n\t\t\t\t\tpairs = null;\n\t\t\t}\n\t\t\treturn pairs;\n\t\t}\n\t}};\n});\n\nvar CurveLocation = Base.extend({\n\t_class: 'CurveLocation',\n\tbeans: true,\n\n\tinitialize: function CurveLocation(curve, time, point, _overlap, _distance) {\n\t\tif (time > 0.9999996) {\n\t\t\tvar next = curve.getNext();\n\t\t\tif (next) {\n\t\t\t\ttime = 0;\n\t\t\t\tcurve = next;\n\t\t\t}\n\t\t}\n\t\tthis._setCurve(curve);\n\t\tthis._time = time;\n\t\tthis._point = point || curve.getPointAtTime(time);\n\t\tthis._overlap = _overlap;\n\t\tthis._distance = _distance;\n\t\tthis._intersection = this._next = this._previous = null;\n\t},\n\n\t_setCurve: function(curve) {\n\t\tvar path = curve._path;\n\t\tthis._path = path;\n\t\tthis._version = path ? path._version : 0;\n\t\tthis._curve = curve;\n\t\tthis._segment = null;\n\t\tthis._segment1 = curve._segment1;\n\t\tthis._segment2 = curve._segment2;\n\t},\n\n\t_setSegment: function(segment) {\n\t\tthis._setCurve(segment.getCurve());\n\t\tthis._segment = segment;\n\t\tthis._time = segment === this._segment1 ? 0 : 1;\n\t\tthis._point = segment._point.clone();\n\t},\n\n\tgetSegment: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\tsegment = this._segment;\n\t\tif (!segment) {\n\t\t\tvar time = this.getTime();\n\t\t\tif (time === 0) {\n\t\t\t\tsegment = curve._segment1;\n\t\t\t} else if (time === 1) {\n\t\t\t\tsegment = curve._segment2;\n\t\t\t} else if (time != null) {\n\t\t\t\tsegment = curve.getPartLength(0, time)\n\t\t\t\t\t< curve.getPartLength(time, 1)\n\t\t\t\t\t\t? curve._segment1\n\t\t\t\t\t\t: curve._segment2;\n\t\t\t}\n\t\t\tthis._segment = segment;\n\t\t}\n\t\treturn segment;\n\t},\n\n\tgetCurve: function() {\n\t\tvar path = this._path,\n\t\t\tthat = this;\n\t\tif (path && path._version !== this._version) {\n\t\t\tthis._time = this._curve = this._offset = null;\n\t\t}\n\n\t\tfunction trySegment(segment) {\n\t\t\tvar curve = segment && segment.getCurve();\n\t\t\tif (curve && (that._time = curve.getTimeOf(that._point))\n\t\t\t\t\t!= null) {\n\t\t\t\tthat._setCurve(curve);\n\t\t\t\tthat._segment = segment;\n\t\t\t\treturn curve;\n\t\t\t}\n\t\t}\n\n\t\treturn this._curve\n\t\t\t|| trySegment(this._segment)\n\t\t\t|| trySegment(this._segment1)\n\t\t\t|| trySegment(this._segment2.getPrevious());\n\t},\n\n\tgetPath: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve && curve._path;\n\t},\n\n\tgetIndex: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve && curve.getIndex();\n\t},\n\n\tgetTime: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\ttime = this._time;\n\t\treturn curve && time == null\n\t\t\t? this._time = curve.getTimeOf(this._point)\n\t\t\t: time;\n\t},\n\n\tgetParameter: '#getTime',\n\n\tgetPoint: function() {\n\t\treturn this._point;\n\t},\n\n\tgetOffset: function() {\n\t\tvar offset = this._offset;\n\t\tif (offset == null) {\n\t\t\toffset = 0;\n\t\t\tvar path = this.getPath(),\n\t\t\t\tindex = this.getIndex();\n\t\t\tif (path && index != null) {\n\t\t\t\tvar curves = path.getCurves();\n\t\t\t\tfor (var i = 0; i < index; i++)\n\t\t\t\t\toffset += curves[i].getLength();\n\t\t\t}\n\t\t\tthis._offset = offset += this.getCurveOffset();\n\t\t}\n\t\treturn offset;\n\t},\n\n\tgetCurveOffset: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\ttime = this.getTime();\n\t\treturn time != null && curve && curve.getPartLength(0, time);\n\t},\n\n\tgetIntersection: function() {\n\t\treturn this._intersection;\n\t},\n\n\tgetDistance: function() {\n\t\treturn this._distance;\n\t},\n\n\tdivide: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\tres = null;\n\t\tif (curve) {\n\t\t\tres = curve.divideAtTime(this.getTime());\n\t\t\tif (res)\n\t\t\t\tthis._setSegment(res._segment1);\n\t\t}\n\t\treturn res;\n\t},\n\n\tsplit: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve ? curve.splitAtTime(this.getTime()) : null;\n\t},\n\n\tequals: function(loc, _ignoreOther) {\n\t\tvar res = this === loc,\n\t\t\tepsilon = 1e-7;\n\t\tif (!res && loc instanceof CurveLocation\n\t\t\t\t&& this.getPath() === loc.getPath()\n\t\t\t\t&& this.getPoint().isClose(loc.getPoint(), epsilon)) {\n\t\t\tvar c1 = this.getCurve(),\n\t\t\t\tc2 = loc.getCurve(),\n\t\t\t\tabs = Math.abs,\n\t\t\t\tdiff = abs(\n\t\t\t\t\t((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())\n\t\t\t\t\t\t\t+ this.getTime()) -\n\t\t\t\t\t((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())\n\t\t\t\t\t\t\t+ loc.getTime()));\n\t\t\tres = (diff < 4e-7\n\t\t\t\t|| ((diff = abs(this.getOffset() - loc.getOffset())) < epsilon\n\t\t\t\t\t|| abs(this.getPath().getLength() - diff) < epsilon))\n\t\t\t\t&& (_ignoreOther\n\t\t\t\t\t|| (!this._intersection && !loc._intersection\n\t\t\t\t\t\t|| this._intersection && this._intersection.equals(\n\t\t\t\t\t\t\t\tloc._intersection, true)));\n\t\t}\n\t\treturn res;\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [],\n\t\t\tpoint = this.getPoint(),\n\t\t\tf = Formatter.instance;\n\t\tif (point)\n\t\t\tparts.push('point: ' + point);\n\t\tvar index = this.getIndex();\n\t\tif (index != null)\n\t\t\tparts.push('index: ' + index);\n\t\tvar time = this.getTime();\n\t\tif (time != null)\n\t\t\tparts.push('time: ' + f.number(time));\n\t\tif (this._distance != null)\n\t\t\tparts.push('distance: ' + f.number(this._distance));\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\tisTouching: function() {\n\t\tvar inter = this._intersection;\n\t\tif (inter && this.getTangent().isCollinear(inter.getTangent())) {\n\t\t\tvar curve1 = this.getCurve(),\n\t\t\t\tcurve2 = inter.getCurve();\n\t\t\treturn !(curve1.isStraight() && curve2.isStraight()\n\t\t\t\t\t&& curve1.getLine().intersect(curve2.getLine()));\n\t\t}\n\t\treturn false;\n\t},\n\n\tisCrossing: function() {\n\t\tvar inter = this._intersection;\n\t\tif (!inter)\n\t\t\treturn false;\n\t\tvar t1 = this.getTime(),\n\t\t\tt2 = inter.getTime(),\n\t\t\ttMin = 4e-7,\n\t\t\ttMax = 1 - tMin,\n\t\t\tt1Inside = t1 > tMin && t1 < tMax,\n\t\t\tt2Inside = t2 > tMin && t2 < tMax;\n\t\tif (t1Inside && t2Inside)\n\t\t\treturn !this.isTouching();\n\t\tvar c2 = this.getCurve(),\n\t\t\tc1 = t1 <= tMin ? c2.getPrevious() : c2,\n\t\t\tc4 = inter.getCurve(),\n\t\t\tc3 = t2 <= tMin ? c4.getPrevious() : c4;\n\t\tif (t1 >= tMax)\n\t\t\tc2 = c2.getNext();\n\t\tif (t2 >= tMax)\n\t\t\tc4 = c4.getNext();\n\t\tif (!c1 || !c2 || !c3 || !c4)\n\t\t\treturn false;\n\n\t\tfunction isInRange(angle, min, max) {\n\t\t\treturn min < max\n\t\t\t\t\t? angle > min && angle < max\n\t\t\t\t\t: angle > min || angle < max;\n\t\t}\n\n\t\tvar lenghts = [];\n\t\tif (!t1Inside)\n\t\t\tlenghts.push(c1.getLength(), c2.getLength());\n\t\tif (!t2Inside)\n\t\t\tlenghts.push(c3.getLength(), c4.getLength());\n\t\tvar pt = this.getPoint(),\n\t\t\toffset = Math.min.apply(Math, lenghts) / 64,\n\t\t\tv2 = t1Inside ? c2.getTangentAtTime(t1)\n\t\t\t\t\t: c2.getPointAt(offset).subtract(pt),\n\t\t\tv1 = t1Inside ? v2.negate()\n\t\t\t\t\t: c1.getPointAt(-offset).subtract(pt),\n\t\t\tv4 = t2Inside ? c4.getTangentAtTime(t2)\n\t\t\t\t\t: c4.getPointAt(offset).subtract(pt),\n\t\t\tv3 = t2Inside ? v4.negate()\n\t\t\t\t\t: c3.getPointAt(-offset).subtract(pt),\n\t\t\ta1 = v1.getAngle(),\n\t\t\ta2 = v2.getAngle(),\n\t\t\ta3 = v3.getAngle(),\n\t\t\ta4 = v4.getAngle();\n\t\treturn !!(t1Inside\n\t\t\t\t? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) &&\n\t\t\t\t (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3))\n\t\t\t\t: (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) &&\n\t\t\t\t (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1)));\n\t},\n\n\thasOverlap: function() {\n\t\treturn !!this._overlap;\n\t}\n}, Base.each(Curve._evaluateMethods, function(name) {\n\tvar get = name + 'At';\n\tthis[name] = function() {\n\t\tvar curve = this.getCurve(),\n\t\t\ttime = this.getTime();\n\t\treturn time != null && curve && curve[get](time, true);\n\t};\n}, {\n\tpreserve: true\n}),\nnew function() {\n\n\tfunction insert(locations, loc, merge) {\n\t\tvar length = locations.length,\n\t\t\tl = 0,\n\t\t\tr = length - 1;\n\n\t\tfunction search(index, dir) {\n\t\t\tfor (var i = index + dir; i >= -1 && i <= length; i += dir) {\n\t\t\t\tvar loc2 = locations[((i % length) + length) % length];\n\t\t\t\tif (!loc.getPoint().isClose(loc2.getPoint(),\n\t\t\t\t\t\t1e-7))\n\t\t\t\t\tbreak;\n\t\t\t\tif (loc.equals(loc2))\n\t\t\t\t\treturn loc2;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\twhile (l <= r) {\n\t\t\tvar m = (l + r) >>> 1,\n\t\t\t\tloc2 = locations[m],\n\t\t\t\tfound;\n\t\t\tif (merge && (found = loc.equals(loc2) ? loc2\n\t\t\t\t\t: (search(m, -1) || search(m, 1)))) {\n\t\t\t\tif (loc._overlap) {\n\t\t\t\t\tfound._overlap = found._intersection._overlap = true;\n\t\t\t\t}\n\t\t\t\treturn found;\n\t\t\t}\n\t\tvar path1 = loc.getPath(),\n\t\t\tpath2 = loc2.getPath(),\n\t\t\tdiff = path1 !== path2\n\t\t\t\t? path1._id - path2._id\n\t\t\t\t: (loc.getIndex() + loc.getTime())\n\t\t\t\t- (loc2.getIndex() + loc2.getTime());\n\t\t\tif (diff < 0) {\n\t\t\t\tr = m - 1;\n\t\t\t} else {\n\t\t\t\tl = m + 1;\n\t\t\t}\n\t\t}\n\t\tlocations.splice(l, 0, loc);\n\t\treturn loc;\n\t}\n\n\treturn { statics: {\n\t\tinsert: insert,\n\n\t\texpand: function(locations) {\n\t\t\tvar expanded = locations.slice();\n\t\t\tfor (var i = locations.length - 1; i >= 0; i--) {\n\t\t\t\tinsert(expanded, locations[i]._intersection, false);\n\t\t\t}\n\t\t\treturn expanded;\n\t\t}\n\t}};\n});\n\nvar PathItem = Item.extend({\n\t_class: 'PathItem',\n\t_selectBounds: false,\n\t_canScaleStroke: true,\n\n\tinitialize: function PathItem() {\n\t},\n\n\tstatics: {\n\n\t\tcreate: function(arg) {\n\t\t\tvar data,\n\t\t\t\tsegments,\n\t\t\t\tcompound;\n\t\t\tif (Base.isPlainObject(arg)) {\n\t\t\t\tsegments = arg.segments;\n\t\t\t\tdata = arg.pathData;\n\t\t\t} else if (Array.isArray(arg)) {\n\t\t\t\tsegments = arg;\n\t\t\t} else if (typeof arg === 'string') {\n\t\t\t\tdata = arg;\n\t\t\t}\n\t\t\tif (segments) {\n\t\t\t\tvar first = segments[0];\n\t\t\t\tcompound = first && Array.isArray(first[0]);\n\t\t\t} else if (data) {\n\t\t\t\tcompound = (data.match(/m/gi) || []).length > 1\n\t\t\t\t\t\t|| /z\\s*\\S+/i.test(data);\n\t\t\t}\n\t\t\tvar ctor = compound ? CompoundPath : Path;\n\t\t\treturn new ctor(arg);\n\t\t}\n\t},\n\n\t_asPathItem: function() {\n\t\treturn this;\n\t},\n\n\tisClockwise: function() {\n\t\treturn this.getArea() >= 0;\n\t},\n\n\tsetClockwise: function(clockwise) {\n\t\tif (this.isClockwise() != (clockwise = !!clockwise))\n\t\t\tthis.reverse();\n\t},\n\n\tsetPathData: function(data) {\n\n\t\tvar parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),\n\t\t\tcoords,\n\t\t\trelative = false,\n\t\t\tprevious,\n\t\t\tcontrol,\n\t\t\tcurrent = new Point(),\n\t\t\tstart = new Point();\n\n\t\tfunction getCoord(index, coord) {\n\t\t\tvar val = +coords[index];\n\t\t\tif (relative)\n\t\t\t\tval += current[coord];\n\t\t\treturn val;\n\t\t}\n\n\t\tfunction getPoint(index) {\n\t\t\treturn new Point(\n\t\t\t\tgetCoord(index, 'x'),\n\t\t\t\tgetCoord(index + 1, 'y')\n\t\t\t);\n\t\t}\n\n\t\tthis.clear();\n\n\t\tfor (var i = 0, l = parts && parts.length; i < l; i++) {\n\t\t\tvar part = parts[i],\n\t\t\t\tcommand = part[0],\n\t\t\t\tlower = command.toLowerCase();\n\t\t\tcoords = part.match(/[+-]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][+-]?\\d+)?/g);\n\t\t\tvar length = coords && coords.length;\n\t\t\trelative = command === lower;\n\t\t\tif (previous === 'z' && !/[mz]/.test(lower))\n\t\t\t\tthis.moveTo(current);\n\t\t\tswitch (lower) {\n\t\t\tcase 'm':\n\t\t\tcase 'l':\n\t\t\t\tvar move = lower === 'm';\n\t\t\t\tfor (var j = 0; j < length; j += 2)\n\t\t\t\t\tthis[!j && move ? 'moveTo' : 'lineTo'](\n\t\t\t\t\t\t\tcurrent = getPoint(j));\n\t\t\t\tcontrol = current;\n\t\t\t\tif (move)\n\t\t\t\t\tstart = current;\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\tcase 'v':\n\t\t\t\tvar coord = lower === 'h' ? 'x' : 'y';\n\t\t\t\tcurrent = current.clone();\n\t\t\t\tfor (var j = 0; j < length; j++) {\n\t\t\t\t\tcurrent[coord] = getCoord(j, coord);\n\t\t\t\t\tthis.lineTo(current);\n\t\t\t\t}\n\t\t\t\tcontrol = current;\n\t\t\t\tbreak;\n\t\t\tcase 'c':\n\t\t\t\tfor (var j = 0; j < length; j += 6) {\n\t\t\t\t\tthis.cubicCurveTo(\n\t\t\t\t\t\t\tgetPoint(j),\n\t\t\t\t\t\t\tcontrol = getPoint(j + 2),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 4));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tfor (var j = 0; j < length; j += 4) {\n\t\t\t\t\tthis.cubicCurveTo(\n\t\t\t\t\t\t\t/[cs]/.test(previous)\n\t\t\t\t\t\t\t\t\t? current.multiply(2).subtract(control)\n\t\t\t\t\t\t\t\t\t: current,\n\t\t\t\t\t\t\tcontrol = getPoint(j),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 2));\n\t\t\t\t\tprevious = lower;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'q':\n\t\t\t\tfor (var j = 0; j < length; j += 4) {\n\t\t\t\t\tthis.quadraticCurveTo(\n\t\t\t\t\t\t\tcontrol = getPoint(j),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 2));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 't':\n\t\t\t\tfor (var j = 0; j < length; j += 2) {\n\t\t\t\t\tthis.quadraticCurveTo(\n\t\t\t\t\t\t\tcontrol = (/[qt]/.test(previous)\n\t\t\t\t\t\t\t\t\t? current.multiply(2).subtract(control)\n\t\t\t\t\t\t\t\t\t: current),\n\t\t\t\t\t\t\tcurrent = getPoint(j));\n\t\t\t\t\tprevious = lower;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'a':\n\t\t\t\tfor (var j = 0; j < length; j += 7) {\n\t\t\t\t\tthis.arcTo(current = getPoint(j + 5),\n\t\t\t\t\t\t\tnew Size(+coords[j], +coords[j + 1]),\n\t\t\t\t\t\t\t+coords[j + 2], +coords[j + 4], +coords[j + 3]);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'z':\n\t\t\t\tthis.closePath(1e-12);\n\t\t\t\tcurrent = start;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprevious = lower;\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn !(this.hasFill() && this.hasStroke());\n\t},\n\n\t_contains: function(point) {\n\t\tvar winding = point.isInside(\n\t\t\t\tthis.getBounds({ internal: true, handle: true }))\n\t\t\t\t\t? this._getWinding(point)\n\t\t\t\t\t: {};\n\t\treturn !!(this.getFillRule() === 'evenodd'\n\t\t\t\t? winding.windingL & 1 || winding.windingR & 1\n\t\t\t\t: winding.winding);\n\t},\n\n\tgetIntersections: function(path, include, _matrix, _returnFirst) {\n\t\tvar self = this === path || !path,\n\t\t\tmatrix1 = this._matrix._orNullIfIdentity(),\n\t\t\tmatrix2 = self ? matrix1\n\t\t\t\t: (_matrix || path._matrix)._orNullIfIdentity();\n\t\tif (!self && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))\n\t\t\treturn [];\n\t\tvar curves1 = this.getCurves(),\n\t\t\tcurves2 = self ? curves1 : path.getCurves(),\n\t\t\tlength1 = curves1.length,\n\t\t\tlength2 = self ? length1 : curves2.length,\n\t\t\tvalues2 = [],\n\t\t\tarrays = [],\n\t\t\tlocations,\n\t\t\tpath;\n\t\tfor (var i = 0; i < length2; i++)\n\t\t\tvalues2[i] = curves2[i].getValues(matrix2);\n\t\tfor (var i = 0; i < length1; i++) {\n\t\t\tvar curve1 = curves1[i],\n\t\t\t\tvalues1 = self ? values2[i] : curve1.getValues(matrix1),\n\t\t\t\tpath1 = curve1.getPath();\n\t\t\tif (path1 !== path) {\n\t\t\t\tpath = path1;\n\t\t\t\tlocations = [];\n\t\t\t\tarrays.push(locations);\n\t\t\t}\n\t\t\tif (self) {\n\t\t\t\tCurve._getSelfIntersection(values1, curve1, locations, {\n\t\t\t\t\tinclude: include,\n\t\t\t\t\texcludeStart: length1 === 1 &&\n\t\t\t\t\t\t\tcurve1.getPoint1().equals(curve1.getPoint2())\n\t\t\t\t});\n\t\t\t}\n\t\t\tfor (var j = self ? i + 1 : 0; j < length2; j++) {\n\t\t\t\tif (_returnFirst && locations.length)\n\t\t\t\t\treturn locations;\n\t\t\t\tvar curve2 = curves2[j];\n\t\t\t\tCurve._getIntersections(\n\t\t\t\t\tvalues1, values2[j], curve1, curve2, locations,\n\t\t\t\t\t{\n\t\t\t\t\t\tinclude: include,\n\t\t\t\t\t\texcludeStart: self && curve1.getPrevious() === curve2,\n\t\t\t\t\t\texcludeEnd: self && curve1.getNext() === curve2\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tlocations = [];\n\t\tfor (var i = 0, l = arrays.length; i < l; i++) {\n\t\t\tlocations.push.apply(locations, arrays[i]);\n\t\t}\n\t\treturn locations;\n\t},\n\n\tgetCrossings: function(path) {\n\t\treturn this.getIntersections(path, function(inter) {\n\t\t\treturn inter._overlap || inter.isCrossing();\n\t\t});\n\t},\n\n\tgetNearestLocation: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcurves = this.getCurves(),\n\t\t\tminDist = Infinity,\n\t\t\tminLoc = null;\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar loc = curves[i].getNearestLocation(point);\n\t\t\tif (loc._distance < minDist) {\n\t\t\t\tminDist = loc._distance;\n\t\t\t\tminLoc = loc;\n\t\t\t}\n\t\t}\n\t\treturn minLoc;\n\t},\n\n\tgetNearestPoint: function() {\n\t\tvar loc = this.getNearestLocation.apply(this, arguments);\n\t\treturn loc ? loc.getPoint() : loc;\n\t},\n\n\tinterpolate: function(from, to, factor) {\n\t\tvar isPath = !this._children,\n\t\t\tname = isPath ? '_segments' : '_children',\n\t\t\titemsFrom = from[name],\n\t\t\titemsTo = to[name],\n\t\t\titems = this[name];\n\t\tif (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) {\n\t\t\tthrow new Error('Invalid operands in interpolate() call: ' +\n\t\t\t\t\tfrom + ', ' + to);\n\t\t}\n\t\tvar current = items.length,\n\t\t\tlength = itemsTo.length;\n\t\tif (current < length) {\n\t\t\tvar ctor = isPath ? Segment : Path;\n\t\t\tfor (var i = current; i < length; i++) {\n\t\t\t\tthis.add(new ctor());\n\t\t\t}\n\t\t} else if (current > length) {\n\t\t\tthis[isPath ? 'removeSegments' : 'removeChildren'](length, current);\n\t\t}\n\t\tfor (var i = 0; i < length; i++) {\n\t\t\titems[i].interpolate(itemsFrom[i], itemsTo[i], factor);\n\t\t}\n\t\tif (isPath) {\n\t\t\tthis.setClosed(from._closed);\n\t\t\tthis._changed(9);\n\t\t}\n\t},\n\n\tcompare: function(path) {\n\t\tvar ok = false;\n\t\tif (path) {\n\t\t\tvar paths1 = this._children || [this],\n\t\t\t\tpaths2 = path._children.slice() || [path],\n\t\t\t\tlength1 = paths1.length,\n\t\t\t\tlength2 = paths2.length,\n\t\t\t\tmatched = [],\n\t\t\t\tcount;\n\t\t\tok = true;\n\t\t\tfor (var i1 = length1 - 1; i1 >= 0 && ok; i1--) {\n\t\t\t\tvar path1 = paths1[i1];\n\t\t\t\tok = false;\n\t\t\t\tfor (var i2 = length2 - 1; i2 >= 0 && !ok; i2--) {\n\t\t\t\t\tif (path1.compare(paths2[i2])) {\n\t\t\t\t\t\tif (!matched[i2]) {\n\t\t\t\t\t\t\tmatched[i2] = true;\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tok = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tok = ok && count === length2;\n\t\t}\n\t\treturn ok;\n\t},\n\n});\n\nvar Path = PathItem.extend({\n\t_class: 'Path',\n\t_serializeFields: {\n\t\tsegments: [],\n\t\tclosed: false\n\t},\n\n\tinitialize: function Path(arg) {\n\t\tthis._closed = false;\n\t\tthis._segments = [];\n\t\tthis._version = 0;\n\t\tvar segments = Array.isArray(arg)\n\t\t\t? typeof arg[0] === 'object'\n\t\t\t\t? arg\n\t\t\t\t: arguments\n\t\t\t: arg && (arg.size === undefined && (arg.x !== undefined\n\t\t\t\t\t|| arg.point !== undefined))\n\t\t\t\t? arguments\n\t\t\t\t: null;\n\t\tif (segments && segments.length > 0) {\n\t\t\tthis.setSegments(segments);\n\t\t} else {\n\t\t\tthis._curves = undefined;\n\t\t\tthis._segmentSelection = 0;\n\t\t\tif (!segments && typeof arg === 'string') {\n\t\t\t\tthis.setPathData(arg);\n\t\t\t\targ = null;\n\t\t\t}\n\t\t}\n\t\tthis._initialize(!segments && arg);\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._closed === item._closed\n\t\t\t\t&& Base.equals(this._segments, item._segments);\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setSegments(source._segments);\n\t\tthis._closed = source._closed;\n\t},\n\n\t_changed: function _changed(flags) {\n\t\t_changed.base.call(this, flags);\n\t\tif (flags & 8) {\n\t\t\tthis._length = this._area = undefined;\n\t\t\tif (flags & 16) {\n\t\t\t\tthis._version++;\n\t\t\t} else if (this._curves) {\n\t\t\t for (var i = 0, l = this._curves.length; i < l; i++)\n\t\t\t\t\tthis._curves[i]._changed();\n\t\t\t}\n\t\t} else if (flags & 32) {\n\t\t\tthis._bounds = undefined;\n\t\t}\n\t},\n\n\tgetStyle: function() {\n\t\tvar parent = this._parent;\n\t\treturn (parent instanceof CompoundPath ? parent : this)._style;\n\t},\n\n\tgetSegments: function() {\n\t\treturn this._segments;\n\t},\n\n\tsetSegments: function(segments) {\n\t\tvar fullySelected = this.isFullySelected(),\n\t\t\tlength = segments && segments.length;\n\t\tthis._segments.length = 0;\n\t\tthis._segmentSelection = 0;\n\t\tthis._curves = undefined;\n\t\tif (length) {\n\t\t\tvar last = segments[length - 1];\n\t\t\tif (typeof last === 'boolean') {\n\t\t\t\tthis.setClosed(last);\n\t\t\t\tlength--;\n\t\t\t}\n\t\t\tthis._add(Segment.readList(segments, 0, {}, length));\n\t\t}\n\t\tif (fullySelected)\n\t\t\tthis.setFullySelected(true);\n\t},\n\n\tgetFirstSegment: function() {\n\t\treturn this._segments[0];\n\t},\n\n\tgetLastSegment: function() {\n\t\treturn this._segments[this._segments.length - 1];\n\t},\n\n\tgetCurves: function() {\n\t\tvar curves = this._curves,\n\t\t\tsegments = this._segments;\n\t\tif (!curves) {\n\t\t\tvar length = this._countCurves();\n\t\t\tcurves = this._curves = new Array(length);\n\t\t\tfor (var i = 0; i < length; i++)\n\t\t\t\tcurves[i] = new Curve(this, segments[i],\n\t\t\t\t\tsegments[i + 1] || segments[0]);\n\t\t}\n\t\treturn curves;\n\t},\n\n\tgetFirstCurve: function() {\n\t\treturn this.getCurves()[0];\n\t},\n\n\tgetLastCurve: function() {\n\t\tvar curves = this.getCurves();\n\t\treturn curves[curves.length - 1];\n\t},\n\n\tisClosed: function() {\n\t\treturn this._closed;\n\t},\n\n\tsetClosed: function(closed) {\n\t\tif (this._closed != (closed = !!closed)) {\n\t\t\tthis._closed = closed;\n\t\t\tif (this._curves) {\n\t\t\t\tvar length = this._curves.length = this._countCurves();\n\t\t\t\tif (closed)\n\t\t\t\t\tthis._curves[length - 1] = new Curve(this,\n\t\t\t\t\t\tthis._segments[length - 1], this._segments[0]);\n\t\t\t}\n\t\t\tthis._changed(25);\n\t\t}\n\t}\n}, {\n\tbeans: true,\n\n\tgetPathData: function(_matrix, _precision) {\n\t\tvar segments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tf = new Formatter(_precision),\n\t\t\tcoords = new Array(6),\n\t\t\tfirst = true,\n\t\t\tcurX, curY,\n\t\t\tprevX, prevY,\n\t\t\tinX, inY,\n\t\t\toutX, outY,\n\t\t\tparts = [];\n\n\t\tfunction addSegment(segment, skipLine) {\n\t\t\tsegment._transformCoordinates(_matrix, coords);\n\t\t\tcurX = coords[0];\n\t\t\tcurY = coords[1];\n\t\t\tif (first) {\n\t\t\t\tparts.push('M' + f.pair(curX, curY));\n\t\t\t\tfirst = false;\n\t\t\t} else {\n\t\t\t\tinX = coords[2];\n\t\t\t\tinY = coords[3];\n\t\t\t\tif (inX === curX && inY === curY\n\t\t\t\t\t\t&& outX === prevX && outY === prevY) {\n\t\t\t\t\tif (!skipLine) {\n\t\t\t\t\t\tvar dx = curX - prevX,\n\t\t\t\t\t\t\tdy = curY - prevY;\n\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t dx === 0 ? 'v' + f.number(dy)\n\t\t\t\t\t\t\t: dy === 0 ? 'h' + f.number(dx)\n\t\t\t\t\t\t\t: 'l' + f.pair(dx, dy));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparts.push('c' + f.pair(outX - prevX, outY - prevY)\n\t\t\t\t\t\t\t + ' ' + f.pair( inX - prevX, inY - prevY)\n\t\t\t\t\t\t\t + ' ' + f.pair(curX - prevX, curY - prevY));\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevX = curX;\n\t\t\tprevY = curY;\n\t\t\toutX = coords[4];\n\t\t\toutY = coords[5];\n\t\t}\n\n\t\tif (!length)\n\t\t\treturn '';\n\n\t\tfor (var i = 0; i < length; i++)\n\t\t\taddSegment(segments[i]);\n\t\tif (this._closed && length > 0) {\n\t\t\taddSegment(segments[0], true);\n\t\t\tparts.push('z');\n\t\t}\n\t\treturn parts.join('');\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._segments.length;\n\t},\n\n\t_transformContent: function(matrix) {\n\t\tvar segments = this._segments,\n\t\t\tcoords = new Array(6);\n\t\tfor (var i = 0, l = segments.length; i < l; i++)\n\t\t\tsegments[i]._transformCoordinates(matrix, coords, true);\n\t\treturn true;\n\t},\n\n\t_add: function(segs, index) {\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tamount = segs.length,\n\t\t\tappend = index == null,\n\t\t\tindex = append ? segments.length : index;\n\t\tfor (var i = 0; i < amount; i++) {\n\t\t\tvar segment = segs[i];\n\t\t\tif (segment._path)\n\t\t\t\tsegment = segs[i] = segment.clone();\n\t\t\tsegment._path = this;\n\t\t\tsegment._index = index + i;\n\t\t\tif (segment._selection)\n\t\t\t\tthis._updateSelection(segment, 0, segment._selection);\n\t\t}\n\t\tif (append) {\n\t\t\tsegments.push.apply(segments, segs);\n\t\t} else {\n\t\t\tsegments.splice.apply(segments, [index, 0].concat(segs));\n\t\t\tfor (var i = index + amount, l = segments.length; i < l; i++)\n\t\t\t\tsegments[i]._index = i;\n\t\t}\n\t\tif (curves) {\n\t\t\tvar total = this._countCurves(),\n\t\t\t\tstart = index > 0 && index + amount - 1 === total ? index - 1\n\t\t\t\t\t: index,\n\t\t\t\tinsert = start,\n\t\t\t\tend = Math.min(start + amount, total);\n\t\t\tif (segs._curves) {\n\t\t\t\tcurves.splice.apply(curves, [start, 0].concat(segs._curves));\n\t\t\t\tinsert += segs._curves.length;\n\t\t\t}\n\t\t\tfor (var i = insert; i < end; i++)\n\t\t\t\tcurves.splice(i, 0, new Curve(this, null, null));\n\t\t\tthis._adjustCurves(start, end);\n\t\t}\n\t\tthis._changed(25);\n\t\treturn segs;\n\t},\n\n\t_adjustCurves: function(start, end) {\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tcurve;\n\t\tfor (var i = start; i < end; i++) {\n\t\t\tcurve = curves[i];\n\t\t\tcurve._path = this;\n\t\t\tcurve._segment1 = segments[i];\n\t\t\tcurve._segment2 = segments[i + 1] || segments[0];\n\t\t\tcurve._changed();\n\t\t}\n\t\tif (curve = curves[this._closed && !start ? segments.length - 1\n\t\t\t\t: start - 1]) {\n\t\t\tcurve._segment2 = segments[start] || segments[0];\n\t\t\tcurve._changed();\n\t\t}\n\t\tif (curve = curves[end]) {\n\t\t\tcurve._segment1 = segments[end];\n\t\t\tcurve._changed();\n\t\t}\n\t},\n\n\t_countCurves: function() {\n\t\tvar length = this._segments.length;\n\t\treturn !this._closed && length > 0 ? length - 1 : length;\n\t},\n\n\tadd: function(segment1 ) {\n\t\treturn arguments.length > 1 && typeof segment1 !== 'number'\n\t\t\t? this._add(Segment.readList(arguments))\n\t\t\t: this._add([ Segment.read(arguments) ])[0];\n\t},\n\n\tinsert: function(index, segment1 ) {\n\t\treturn arguments.length > 2 && typeof segment1 !== 'number'\n\t\t\t? this._add(Segment.readList(arguments, 1), index)\n\t\t\t: this._add([ Segment.read(arguments, 1) ], index)[0];\n\t},\n\n\taddSegment: function() {\n\t\treturn this._add([ Segment.read(arguments) ])[0];\n\t},\n\n\tinsertSegment: function(index ) {\n\t\treturn this._add([ Segment.read(arguments, 1) ], index)[0];\n\t},\n\n\taddSegments: function(segments) {\n\t\treturn this._add(Segment.readList(segments));\n\t},\n\n\tinsertSegments: function(index, segments) {\n\t\treturn this._add(Segment.readList(segments), index);\n\t},\n\n\tremoveSegment: function(index) {\n\t\treturn this.removeSegments(index, index + 1)[0] || null;\n\t},\n\n\tremoveSegments: function(start, end, _includeCurves) {\n\t\tstart = start || 0;\n\t\tend = Base.pick(end, this._segments.length);\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tcount = segments.length,\n\t\t\tremoved = segments.splice(start, end - start),\n\t\t\tamount = removed.length;\n\t\tif (!amount)\n\t\t\treturn removed;\n\t\tfor (var i = 0; i < amount; i++) {\n\t\t\tvar segment = removed[i];\n\t\t\tif (segment._selection)\n\t\t\t\tthis._updateSelection(segment, segment._selection, 0);\n\t\t\tsegment._index = segment._path = null;\n\t\t}\n\t\tfor (var i = start, l = segments.length; i < l; i++)\n\t\t\tsegments[i]._index = i;\n\t\tif (curves) {\n\t\t\tvar index = start > 0 && end === count + (this._closed ? 1 : 0)\n\t\t\t\t\t? start - 1\n\t\t\t\t\t: start,\n\t\t\t\tcurves = curves.splice(index, amount);\n\t\t\tfor (var i = curves.length - 1; i >= 0; i--)\n\t\t\t\tcurves[i]._path = null;\n\t\t\tif (_includeCurves)\n\t\t\t\tremoved._curves = curves.slice(1);\n\t\t\tthis._adjustCurves(index, index);\n\t\t}\n\t\tthis._changed(25);\n\t\treturn removed;\n\t},\n\n\tclear: '#removeSegments',\n\n\thasHandles: function() {\n\t\tvar segments = this._segments;\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tif (segments[i].hasHandles())\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tclearHandles: function() {\n\t\tvar segments = this._segments;\n\t\tfor (var i = 0, l = segments.length; i < l; i++)\n\t\t\tsegments[i].clearHandles();\n\t},\n\n\tgetLength: function() {\n\t\tif (this._length == null) {\n\t\t\tvar curves = this.getCurves(),\n\t\t\t\tlength = 0;\n\t\t\tfor (var i = 0, l = curves.length; i < l; i++)\n\t\t\t\tlength += curves[i].getLength();\n\t\t\tthis._length = length;\n\t\t}\n\t\treturn this._length;\n\t},\n\n\tgetArea: function(_closed) {\n\t\tvar cached = _closed === undefined,\n\t\t\tarea = this._area;\n\t\tif (!cached || area == null) {\n\t\t\tvar segments = this._segments,\n\t\t\t\tcount = segments.length,\n\t\t\t\tclosed = cached ? this._closed : _closed,\n\t\t\t\tlast = count - 1;\n\t\t\tarea = 0;\n\t\t\tfor (var i = 0, l = closed ? count : last; i < l; i++) {\n\t\t\t\tarea += Curve.getArea(Curve.getValues(\n\t\t\t\t\t\tsegments[i], segments[i < last ? i + 1 : 0]));\n\t\t\t}\n\t\t\tif (cached)\n\t\t\t\tthis._area = area;\n\t\t}\n\t\treturn area;\n\t},\n\n\tisFullySelected: function() {\n\t\tvar length = this._segments.length;\n\t\treturn this.isSelected() && length > 0 && this._segmentSelection\n\t\t\t\t=== length * 7;\n\t},\n\n\tsetFullySelected: function(selected) {\n\t\tif (selected)\n\t\t\tthis._selectSegments(true);\n\t\tthis.setSelected(selected);\n\t},\n\n\tsetSelection: function setSelection(selection) {\n\t\tif (!(selection & 1))\n\t\t\tthis._selectSegments(false);\n\t\tsetSelection.base.call(this, selection);\n\t},\n\n\t_selectSegments: function(selected) {\n\t\tvar segments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tselection = selected ? 7 : 0;\n\t\tthis._segmentSelection = selection * length;\n\t\tfor (var i = 0; i < length; i++)\n\t\t\tsegments[i]._selection = selection;\n\t},\n\n\t_updateSelection: function(segment, oldSelection, newSelection) {\n\t\tsegment._selection = newSelection;\n\t\tvar selection = this._segmentSelection += newSelection - oldSelection;\n\t\tif (selection > 0)\n\t\t\tthis.setSelected(true);\n\t},\n\n\tsplitAt: function(location) {\n\t\tvar loc = typeof location === 'number'\n\t\t\t\t? this.getLocationAt(location) : location,\n\t\t\tindex = loc && loc.index,\n\t\t\ttime = loc && loc.time,\n\t\t\ttMin = 4e-7,\n\t\t\ttMax = 1 - tMin;\n\t\tif (time >= tMax) {\n\t\t\tindex++;\n\t\t\ttime = 0;\n\t\t}\n\t\tvar curves = this.getCurves();\n\t\tif (index >= 0 && index < curves.length) {\n\t\t\tif (time >= tMin) {\n\t\t\t\tcurves[index++].divideAtTime(time);\n\t\t\t}\n\t\t\tvar segs = this.removeSegments(index, this._segments.length, true),\n\t\t\t\tpath;\n\t\t\tif (this._closed) {\n\t\t\t\tthis.setClosed(false);\n\t\t\t\tpath = this;\n\t\t\t} else {\n\t\t\t\tpath = new Path(Item.NO_INSERT);\n\t\t\t\tpath.insertAbove(this);\n\t\t\t\tpath.copyAttributes(this);\n\t\t\t}\n\t\t\tpath._add(segs, 0);\n\t\t\tthis.addSegment(segs[0]);\n\t\t\treturn path;\n\t\t}\n\t\treturn null;\n\t},\n\n\tsplit: function(index, time) {\n\t\tvar curve,\n\t\t\tlocation = time === undefined ? index\n\t\t\t\t: (curve = this.getCurves()[index])\n\t\t\t\t\t&& curve.getLocationAtTime(time);\n\t\treturn location != null ? this.splitAt(location) : null;\n\t},\n\n\tjoin: function(path, tolerance) {\n\t\tvar epsilon = tolerance || 0;\n\t\tif (path && path !== this) {\n\t\t\tvar segments = path._segments,\n\t\t\t\tlast1 = this.getLastSegment(),\n\t\t\t\tlast2 = path.getLastSegment();\n\t\t\tif (!last2)\n\t\t\t\treturn this;\n\t\t\tif (last1 && last1._point.isClose(last2._point, epsilon))\n\t\t\t\tpath.reverse();\n\t\t\tvar first2 = path.getFirstSegment();\n\t\t\tif (last1 && last1._point.isClose(first2._point, epsilon)) {\n\t\t\t\tlast1.setHandleOut(first2._handleOut);\n\t\t\t\tthis._add(segments.slice(1));\n\t\t\t} else {\n\t\t\t\tvar first1 = this.getFirstSegment();\n\t\t\t\tif (first1 && first1._point.isClose(first2._point, epsilon))\n\t\t\t\t\tpath.reverse();\n\t\t\t\tlast2 = path.getLastSegment();\n\t\t\t\tif (first1 && first1._point.isClose(last2._point, epsilon)) {\n\t\t\t\t\tfirst1.setHandleIn(last2._handleIn);\n\t\t\t\t\tthis._add(segments.slice(0, segments.length - 1), 0);\n\t\t\t\t} else {\n\t\t\t\t\tthis._add(segments.slice());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (path._closed)\n\t\t\t\tthis._add([segments[0]]);\n\t\t\tpath.remove();\n\t\t}\n\t\tvar first = this.getFirstSegment(),\n\t\t\tlast = this.getLastSegment();\n\t\tif (first !== last && first._point.isClose(last._point, epsilon)) {\n\t\t\tfirst.setHandleIn(last._handleIn);\n\t\t\tlast.remove();\n\t\t\tthis.setClosed(true);\n\t\t}\n\t\treturn this;\n\t},\n\n\treduce: function(options) {\n\t\tvar curves = this.getCurves(),\n\t\t\tsimplify = options && options.simplify,\n\t\t\ttolerance = simplify ? 1e-7 : 0;\n\t\tfor (var i = curves.length - 1; i >= 0; i--) {\n\t\t\tvar curve = curves[i];\n\t\t\tif (!curve.hasHandles() && (curve.getLength() < tolerance\n\t\t\t\t\t|| simplify && curve.isCollinear(curve.getNext())))\n\t\t\t\tcurve.remove();\n\t\t}\n\t\treturn this;\n\t},\n\n\treverse: function() {\n\t\tthis._segments.reverse();\n\t\tfor (var i = 0, l = this._segments.length; i < l; i++) {\n\t\t\tvar segment = this._segments[i];\n\t\t\tvar handleIn = segment._handleIn;\n\t\t\tsegment._handleIn = segment._handleOut;\n\t\t\tsegment._handleOut = handleIn;\n\t\t\tsegment._index = i;\n\t\t}\n\t\tthis._curves = null;\n\t\tthis._changed(9);\n\t},\n\n\tflatten: function(flatness) {\n\t\tvar iterator = new PathIterator(this, flatness || 0.25, 256, true),\n\t\t\tparts = iterator.parts,\n\t\t\tlength = parts.length,\n\t\t\tsegments = [];\n\t\tfor (var i = 0; i < length; i++) {\n\t\t\tsegments.push(new Segment(parts[i].curve.slice(0, 2)));\n\t\t}\n\t\tif (!this._closed && length > 0) {\n\t\t\tsegments.push(new Segment(parts[length - 1].curve.slice(6)));\n\t\t}\n\t\tthis.setSegments(segments);\n\t},\n\n\tsimplify: function(tolerance) {\n\t\tvar segments = new PathFitter(this).fit(tolerance || 2.5);\n\t\tif (segments)\n\t\t\tthis.setSegments(segments);\n\t\treturn !!segments;\n\t},\n\n\tsmooth: function(options) {\n\t\tvar that = this,\n\t\t\topts = options || {},\n\t\t\ttype = opts.type || 'asymmetric',\n\t\t\tsegments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tclosed = this._closed;\n\n\t\tfunction getIndex(value, _default) {\n\t\t\tvar index = value && value.index;\n\t\t\tif (index != null) {\n\t\t\t\tvar path = value.path;\n\t\t\t\tif (path && path !== that)\n\t\t\t\t\tthrow new Error(value._class + ' ' + index + ' of ' + path\n\t\t\t\t\t\t\t+ ' is not part of ' + that);\n\t\t\t\tif (_default && value instanceof Curve)\n\t\t\t\t\tindex++;\n\t\t\t} else {\n\t\t\t\tindex = typeof value === 'number' ? value : _default;\n\t\t\t}\n\t\t\treturn Math.min(index < 0 && closed\n\t\t\t\t\t? index % length\n\t\t\t\t\t: index < 0 ? index + length : index, length - 1);\n\t\t}\n\n\t\tvar loop = closed && opts.from === undefined && opts.to === undefined,\n\t\t\tfrom = getIndex(opts.from, 0),\n\t\t\tto = getIndex(opts.to, length - 1);\n\n\t\tif (from > to) {\n\t\t\tif (closed) {\n\t\t\t\tfrom -= length;\n\t\t\t} else {\n\t\t\t\tvar tmp = from;\n\t\t\t\tfrom = to;\n\t\t\t\tto = tmp;\n\t\t\t}\n\t\t}\n\t\tif (/^(?:asymmetric|continuous)$/.test(type)) {\n\t\t\tvar asymmetric = type === 'asymmetric',\n\t\t\t\tmin = Math.min,\n\t\t\t\tamount = to - from + 1,\n\t\t\t\tn = amount - 1,\n\t\t\t\tpadding = loop ? min(amount, 4) : 1,\n\t\t\t\tpaddingLeft = padding,\n\t\t\t\tpaddingRight = padding,\n\t\t\t\tknots = [];\n\t\t\tif (!closed) {\n\t\t\t\tpaddingLeft = min(1, from);\n\t\t\t\tpaddingRight = min(1, length - to - 1);\n\t\t\t}\n\t\t\tn += paddingLeft + paddingRight;\n\t\t\tif (n <= 1)\n\t\t\t\treturn;\n\t\t\tfor (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {\n\t\t\t\tknots[i] = segments[(j < 0 ? j + length : j) % length]._point;\n\t\t\t}\n\n\t\t\tvar x = knots[0]._x + 2 * knots[1]._x,\n\t\t\t\ty = knots[0]._y + 2 * knots[1]._y,\n\t\t\t\tf = 2,\n\t\t\t\tn_1 = n - 1,\n\t\t\t\trx = [x],\n\t\t\t\try = [y],\n\t\t\t\trf = [f],\n\t\t\t\tpx = [],\n\t\t\t\tpy = [];\n\t\t\tfor (var i = 1; i < n; i++) {\n\t\t\t\tvar internal = i < n_1,\n\t\t\t\t\ta = internal ? 1 : asymmetric ? 1 : 2,\n\t\t\t\t\tb = internal ? 4 : asymmetric ? 2 : 7,\n\t\t\t\t\tu = internal ? 4 : asymmetric ? 3 : 8,\n\t\t\t\t\tv = internal ? 2 : asymmetric ? 0 : 1,\n\t\t\t\t\tm = a / f;\n\t\t\t\tf = rf[i] = b - m;\n\t\t\t\tx = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;\n\t\t\t\ty = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;\n\t\t\t}\n\n\t\t\tpx[n_1] = rx[n_1] / rf[n_1];\n\t\t\tpy[n_1] = ry[n_1] / rf[n_1];\n\t\t\tfor (var i = n - 2; i >= 0; i--) {\n\t\t\t\tpx[i] = (rx[i] - px[i + 1]) / rf[i];\n\t\t\t\tpy[i] = (ry[i] - py[i + 1]) / rf[i];\n\t\t\t}\n\t\t\tpx[n] = (3 * knots[n]._x - px[n_1]) / 2;\n\t\t\tpy[n] = (3 * knots[n]._y - py[n_1]) / 2;\n\n\t\t\tfor (var i = paddingLeft, max = n - paddingRight, j = from;\n\t\t\t\t\ti <= max; i++, j++) {\n\t\t\t\tvar segment = segments[j < 0 ? j + length : j],\n\t\t\t\t\tpt = segment._point,\n\t\t\t\t\thx = px[i] - pt._x,\n\t\t\t\t\thy = py[i] - pt._y;\n\t\t\t\tif (loop || i < max)\n\t\t\t\t\tsegment.setHandleOut(hx, hy);\n\t\t\t\tif (loop || i > paddingLeft)\n\t\t\t\t\tsegment.setHandleIn(-hx, -hy);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (var i = from; i <= to; i++) {\n\t\t\t\tsegments[i < 0 ? i + length : i].smooth(opts,\n\t\t\t\t\t\t!loop && i === from, !loop && i === to);\n\t\t\t}\n\t\t}\n\t},\n\n\ttoShape: function(insert) {\n\t\tif (!this._closed)\n\t\t\treturn null;\n\n\t\tvar segments = this._segments,\n\t\t\ttype,\n\t\t\tsize,\n\t\t\tradius,\n\t\t\ttopCenter;\n\n\t\tfunction isCollinear(i, j) {\n\t\t\tvar seg1 = segments[i],\n\t\t\t\tseg2 = seg1.getNext(),\n\t\t\t\tseg3 = segments[j],\n\t\t\t\tseg4 = seg3.getNext();\n\t\t\treturn seg1._handleOut.isZero() && seg2._handleIn.isZero()\n\t\t\t\t\t&& seg3._handleOut.isZero() && seg4._handleIn.isZero()\n\t\t\t\t\t&& seg2._point.subtract(seg1._point).isCollinear(\n\t\t\t\t\t\tseg4._point.subtract(seg3._point));\n\t\t}\n\n\t\tfunction isOrthogonal(i) {\n\t\t\tvar seg2 = segments[i],\n\t\t\t\tseg1 = seg2.getPrevious(),\n\t\t\t\tseg3 = seg2.getNext();\n\t\t\treturn seg1._handleOut.isZero() && seg2._handleIn.isZero()\n\t\t\t\t\t&& seg2._handleOut.isZero() && seg3._handleIn.isZero()\n\t\t\t\t\t&& seg2._point.subtract(seg1._point).isOrthogonal(\n\t\t\t\t\t\tseg3._point.subtract(seg2._point));\n\t\t}\n\n\t\tfunction isArc(i) {\n\t\t\tvar seg1 = segments[i],\n\t\t\t\tseg2 = seg1.getNext(),\n\t\t\t\thandle1 = seg1._handleOut,\n\t\t\t\thandle2 = seg2._handleIn,\n\t\t\t\tkappa = 0.5522847498307936;\n\t\t\tif (handle1.isOrthogonal(handle2)) {\n\t\t\t\tvar pt1 = seg1._point,\n\t\t\t\t\tpt2 = seg2._point,\n\t\t\t\t\tcorner = new Line(pt1, handle1, true).intersect(\n\t\t\t\t\t\t\tnew Line(pt2, handle2, true), true);\n\t\t\t\treturn corner && Numerical.isZero(handle1.getLength() /\n\t\t\t\t\t\tcorner.subtract(pt1).getLength() - kappa)\n\t\t\t\t\t&& Numerical.isZero(handle2.getLength() /\n\t\t\t\t\t\tcorner.subtract(pt2).getLength() - kappa);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tfunction getDistance(i, j) {\n\t\t\treturn segments[i]._point.getDistance(segments[j]._point);\n\t\t}\n\n\t\tif (!this.hasHandles() && segments.length === 4\n\t\t\t\t&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {\n\t\t\ttype = Shape.Rectangle;\n\t\t\tsize = new Size(getDistance(0, 3), getDistance(0, 1));\n\t\t\ttopCenter = segments[1]._point.add(segments[2]._point).divide(2);\n\t\t} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)\n\t\t\t\t&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {\n\t\t\ttype = Shape.Rectangle;\n\t\t\tsize = new Size(getDistance(1, 6), getDistance(0, 3));\n\t\t\tradius = size.subtract(new Size(getDistance(0, 7),\n\t\t\t\t\tgetDistance(1, 2))).divide(2);\n\t\t\ttopCenter = segments[3]._point.add(segments[4]._point).divide(2);\n\t\t} else if (segments.length === 4\n\t\t\t\t&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {\n\t\t\tif (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {\n\t\t\t\ttype = Shape.Circle;\n\t\t\t\tradius = getDistance(0, 2) / 2;\n\t\t\t} else {\n\t\t\t\ttype = Shape.Ellipse;\n\t\t\t\tradius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);\n\t\t\t}\n\t\t\ttopCenter = segments[1]._point;\n\t\t}\n\n\t\tif (type) {\n\t\t\tvar center = this.getPosition(true),\n\t\t\t\tshape = new type({\n\t\t\t\t\tcenter: center,\n\t\t\t\t\tsize: size,\n\t\t\t\t\tradius: radius,\n\t\t\t\t\tinsert: false\n\t\t\t\t});\n\t\t\tshape.copyAttributes(this, true);\n\t\t\tshape._matrix.prepend(this._matrix);\n\t\t\tshape.rotate(topCenter.subtract(center).getAngle() + 90);\n\t\t\tif (insert === undefined || insert)\n\t\t\t\tshape.insertAbove(this);\n\t\t\treturn shape;\n\t\t}\n\t\treturn null;\n\t},\n\n\ttoPath: '#clone',\n\n\tcompare: function compare(path) {\n\t\tif (!path || path instanceof CompoundPath)\n\t\t\treturn compare.base.call(this, path);\n\t\tvar curves1 = this.getCurves(),\n\t\t\tcurves2 = path.getCurves(),\n\t\t\tlength1 = curves1.length,\n\t\t\tlength2 = curves2.length;\n\t\tif (!length1 || !length2) {\n\t\t\treturn length1 ^ length2;\n\t\t}\n\t\tvar v1 = curves1[0].getValues(),\n\t\t\tvalues2 = [],\n\t\t\tpos1 = 0, pos2,\n\t\t\tend1 = 0, end2;\n\t\tfor (var i = 0; i < length2; i++) {\n\t\t\tvar v2 = curves2[i].getValues();\n\t\t\tvalues2.push(v2);\n\t\t\tvar overlaps = Curve.getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tpos2 = !i && overlaps[0][0] > 0 ? length2 - 1 : i;\n\t\t\t\tend2 = overlaps[0][1];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar abs = Math.abs,\n\t\t\tepsilon = 4e-7,\n\t\t\tv2 = values2[pos2],\n\t\t\tstart2;\n\t\twhile (v1 && v2) {\n\t\t\tvar overlaps = Curve.getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tvar t1 = overlaps[0][0];\n\t\t\t\tif (abs(t1 - end1) < epsilon) {\n\t\t\t\t\tend1 = overlaps[1][0];\n\t\t\t\t\tif (end1 === 1) {\n\t\t\t\t\t\tv1 = ++pos1 < length1 ? curves1[pos1].getValues() : null;\n\t\t\t\t\t\tend1 = 0;\n\t\t\t\t\t}\n\t\t\t\t\tvar t2 = overlaps[0][1];\n\t\t\t\t\tif (abs(t2 - end2) < epsilon) {\n\t\t\t\t\t\tif (!start2)\n\t\t\t\t\t\t\tstart2 = [pos2, t2];\n\t\t\t\t\t\tend2 = overlaps[1][1];\n\t\t\t\t\t\tif (end2 === 1) {\n\t\t\t\t\t\t\tif (++pos2 >= length2)\n\t\t\t\t\t\t\t\tpos2 = 0;\n\t\t\t\t\t\t\tv2 = values2[pos2] || curves2[pos2].getValues();\n\t\t\t\t\t\t\tend2 = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!v1) {\n\t\t\t\t\t\t\treturn start2[0] === pos2 && start2[1] === end2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\treturn false;\n\t},\n\n\t_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {\n\t\tvar that = this,\n\t\t\tstyle = this.getStyle(),\n\t\t\tsegments = this._segments,\n\t\t\tnumSegments = segments.length,\n\t\t\tclosed = this._closed,\n\t\t\ttolerancePadding = options._tolerancePadding,\n\t\t\tstrokePadding = tolerancePadding,\n\t\t\tjoin, cap, miterLimit,\n\t\t\tarea, loc, res,\n\t\t\thitStroke = options.stroke && style.hasStroke(),\n\t\t\thitFill = options.fill && style.hasFill(),\n\t\t\thitCurves = options.curves,\n\t\t\tstrokeRadius = hitStroke\n\t\t\t\t\t? style.getStrokeWidth() / 2\n\t\t\t\t\t: hitFill && options.tolerance > 0 || hitCurves\n\t\t\t\t\t\t? 0 : null;\n\t\tif (strokeRadius !== null) {\n\t\t\tif (strokeRadius > 0) {\n\t\t\t\tjoin = style.getStrokeJoin();\n\t\t\t\tcap = style.getStrokeCap();\n\t\t\t\tmiterLimit = strokeRadius * style.getMiterLimit();\n\t\t\t\tstrokePadding = strokePadding.add(\n\t\t\t\t\tPath._getStrokePadding(strokeRadius, strokeMatrix));\n\t\t\t} else {\n\t\t\t\tjoin = cap = 'round';\n\t\t\t}\n\t\t}\n\n\t\tfunction isCloseEnough(pt, padding) {\n\t\t\treturn point.subtract(pt).divide(padding).length <= 1;\n\t\t}\n\n\t\tfunction checkSegmentPoint(seg, pt, name) {\n\t\t\tif (!options.selected || pt.isSelected()) {\n\t\t\t\tvar anchor = seg._point;\n\t\t\t\tif (pt !== anchor)\n\t\t\t\t\tpt = pt.add(anchor);\n\t\t\t\tif (isCloseEnough(pt, strokePadding)) {\n\t\t\t\t\treturn new HitResult(name, that, {\n\t\t\t\t\t\tsegment: seg,\n\t\t\t\t\t\tpoint: pt\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction checkSegmentPoints(seg, ends) {\n\t\t\treturn (ends || options.segments)\n\t\t\t\t&& checkSegmentPoint(seg, seg._point, 'segment')\n\t\t\t\t|| (!ends && options.handles) && (\n\t\t\t\t\tcheckSegmentPoint(seg, seg._handleIn, 'handle-in') ||\n\t\t\t\t\tcheckSegmentPoint(seg, seg._handleOut, 'handle-out'));\n\t\t}\n\n\t\tfunction addToArea(point) {\n\t\t\tarea.add(point);\n\t\t}\n\n\t\tfunction checkSegmentStroke(segment) {\n\t\t\tif (join !== 'round' || cap !== 'round') {\n\t\t\t\tarea = new Path({ internal: true, closed: true });\n\t\t\t\tif (closed || segment._index > 0\n\t\t\t\t\t\t&& segment._index < numSegments - 1) {\n\t\t\t\t\tif (join !== 'round' && (segment._handleIn.isZero()\n\t\t\t\t\t\t\t|| segment._handleOut.isZero()))\n\t\t\t\t\t\tPath._addBevelJoin(segment, join, strokeRadius,\n\t\t\t\t\t\t\t miterLimit, null, strokeMatrix, addToArea, true);\n\t\t\t\t} else if (cap !== 'round') {\n\t\t\t\t\tPath._addSquareCap(segment, cap, strokeRadius, null,\n\t\t\t\t\t\t\tstrokeMatrix, addToArea, true);\n\t\t\t\t}\n\t\t\t\tif (!area.isEmpty()) {\n\t\t\t\t\tvar loc;\n\t\t\t\t\treturn area.contains(point)\n\t\t\t\t\t\t|| (loc = area.getNearestLocation(point))\n\t\t\t\t\t\t\t&& isCloseEnough(loc.getPoint(), tolerancePadding);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn isCloseEnough(segment._point, strokePadding);\n\t\t}\n\n\t\tif (options.ends && !options.segments && !closed) {\n\t\t\tif (res = checkSegmentPoints(segments[0], true)\n\t\t\t\t\t|| checkSegmentPoints(segments[numSegments - 1], true))\n\t\t\t\treturn res;\n\t\t} else if (options.segments || options.handles) {\n\t\t\tfor (var i = 0; i < numSegments; i++)\n\t\t\t\tif (res = checkSegmentPoints(segments[i]))\n\t\t\t\t\treturn res;\n\t\t}\n\t\tif (strokeRadius !== null) {\n\t\t\tloc = this.getNearestLocation(point);\n\t\t\tif (loc) {\n\t\t\t\tvar time = loc.getTime();\n\t\t\t\tif (time === 0 || time === 1 && numSegments > 1) {\n\t\t\t\t\tif (!checkSegmentStroke(loc.getSegment()))\n\t\t\t\t\t\tloc = null;\n\t\t\t\t} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {\n\t\t\t\t\tloc = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!loc && join === 'miter' && numSegments > 1) {\n\t\t\t\tfor (var i = 0; i < numSegments; i++) {\n\t\t\t\t\tvar segment = segments[i];\n\t\t\t\t\tif (point.getDistance(segment._point) <= miterLimit\n\t\t\t\t\t\t\t&& checkSegmentStroke(segment)) {\n\t\t\t\t\t\tloc = segment.getLocation();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn !loc && hitFill && this._contains(point)\n\t\t\t\t|| loc && !hitStroke && !hitCurves\n\t\t\t\t\t? new HitResult('fill', this)\n\t\t\t\t\t: loc\n\t\t\t\t\t\t? new HitResult(hitStroke ? 'stroke' : 'curve', this, {\n\t\t\t\t\t\t\tlocation: loc,\n\t\t\t\t\t\t\tpoint: loc.getPoint()\n\t\t\t\t\t\t})\n\t\t\t\t\t\t: null;\n\t}\n\n}, Base.each(Curve._evaluateMethods,\n\tfunction(name) {\n\t\tthis[name + 'At'] = function(offset) {\n\t\t\tvar loc = this.getLocationAt(offset);\n\t\t\treturn loc && loc[name]();\n\t\t};\n\t},\n{\n\tbeans: false,\n\n\tgetLocationOf: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcurves = this.getCurves();\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar loc = curves[i].getLocationOf(point);\n\t\t\tif (loc)\n\t\t\t\treturn loc;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetOffsetOf: function() {\n\t\tvar loc = this.getLocationOf.apply(this, arguments);\n\t\treturn loc ? loc.getOffset() : null;\n\t},\n\n\tgetLocationAt: function(offset) {\n\t\tvar curves = this.getCurves(),\n\t\t\tlength = 0;\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar start = length,\n\t\t\t\tcurve = curves[i];\n\t\t\tlength += curve.getLength();\n\t\t\tif (length > offset) {\n\t\t\t\treturn curve.getLocationAt(offset - start);\n\t\t\t}\n\t\t}\n\t\tif (curves.length > 0 && offset <= this.getLength())\n\t\t\treturn new CurveLocation(curves[curves.length - 1], 1);\n\t\treturn null;\n\t}\n\n}),\nnew function() {\n\n\tfunction drawHandles(ctx, segments, matrix, size) {\n\t\tvar half = size / 2,\n\t\t\tcoords = new Array(6),\n\t\t\tpX, pY;\n\n\t\tfunction drawHandle(index) {\n\t\t\tvar hX = coords[index],\n\t\t\t\thY = coords[index + 1];\n\t\t\tif (pX != hX || pY != hY) {\n\t\t\t\tctx.beginPath();\n\t\t\t\tctx.moveTo(pX, pY);\n\t\t\t\tctx.lineTo(hX, hY);\n\t\t\t\tctx.stroke();\n\t\t\t\tctx.beginPath();\n\t\t\t\tctx.arc(hX, hY, half, 0, Math.PI * 2, true);\n\t\t\t\tctx.fill();\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar segment = segments[i],\n\t\t\t\tselection = segment._selection;\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tpX = coords[0];\n\t\t\tpY = coords[1];\n\t\t\tif (selection & 2)\n\t\t\t\tdrawHandle(2);\n\t\t\tif (selection & 4)\n\t\t\t\tdrawHandle(4);\n\t\t\tctx.fillRect(pX - half, pY - half, size, size);\n\t\t\tif (!(selection & 1)) {\n\t\t\t\tvar fillStyle = ctx.fillStyle;\n\t\t\t\tctx.fillStyle = '#ffffff';\n\t\t\t\tctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);\n\t\t\t\tctx.fillStyle = fillStyle;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction drawSegments(ctx, path, matrix) {\n\t\tvar segments = path._segments,\n\t\t\tlength = segments.length,\n\t\t\tcoords = new Array(6),\n\t\t\tfirst = true,\n\t\t\tcurX, curY,\n\t\t\tprevX, prevY,\n\t\t\tinX, inY,\n\t\t\toutX, outY;\n\n\t\tfunction drawSegment(segment) {\n\t\t\tif (matrix) {\n\t\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\t\tcurX = coords[0];\n\t\t\t\tcurY = coords[1];\n\t\t\t} else {\n\t\t\t\tvar point = segment._point;\n\t\t\t\tcurX = point._x;\n\t\t\t\tcurY = point._y;\n\t\t\t}\n\t\t\tif (first) {\n\t\t\t\tctx.moveTo(curX, curY);\n\t\t\t\tfirst = false;\n\t\t\t} else {\n\t\t\t\tif (matrix) {\n\t\t\t\t\tinX = coords[2];\n\t\t\t\t\tinY = coords[3];\n\t\t\t\t} else {\n\t\t\t\t\tvar handle = segment._handleIn;\n\t\t\t\t\tinX = curX + handle._x;\n\t\t\t\t\tinY = curY + handle._y;\n\t\t\t\t}\n\t\t\t\tif (inX === curX && inY === curY\n\t\t\t\t\t\t&& outX === prevX && outY === prevY) {\n\t\t\t\t\tctx.lineTo(curX, curY);\n\t\t\t\t} else {\n\t\t\t\t\tctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevX = curX;\n\t\t\tprevY = curY;\n\t\t\tif (matrix) {\n\t\t\t\toutX = coords[4];\n\t\t\t\toutY = coords[5];\n\t\t\t} else {\n\t\t\t\tvar handle = segment._handleOut;\n\t\t\t\toutX = prevX + handle._x;\n\t\t\t\toutY = prevY + handle._y;\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0; i < length; i++)\n\t\t\tdrawSegment(segments[i]);\n\t\tif (path._closed && length > 0)\n\t\t\tdrawSegment(segments[0]);\n\t}\n\n\treturn {\n\t\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\t\tvar dontStart = param.dontStart,\n\t\t\t\tdontPaint = param.dontFinish || param.clip,\n\t\t\t\tstyle = this.getStyle(),\n\t\t\t\thasFill = style.hasFill(),\n\t\t\t\thasStroke = style.hasStroke(),\n\t\t\t\tdashArray = style.getDashArray(),\n\t\t\t\tdashLength = !paper.support.nativeDash && hasStroke\n\t\t\t\t\t\t&& dashArray && dashArray.length;\n\n\t\t\tif (!dontStart)\n\t\t\t\tctx.beginPath();\n\n\t\t\tif (hasFill || hasStroke && !dashLength || dontPaint) {\n\t\t\t\tdrawSegments(ctx, this, strokeMatrix);\n\t\t\t\tif (this._closed)\n\t\t\t\t\tctx.closePath();\n\t\t\t}\n\n\t\t\tfunction getOffset(i) {\n\t\t\t\treturn dashArray[((i % dashLength) + dashLength) % dashLength];\n\t\t\t}\n\n\t\t\tif (!dontPaint && (hasFill || hasStroke)) {\n\t\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\t\tif (hasFill) {\n\t\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t\t}\n\t\t\t\tif (hasStroke) {\n\t\t\t\t\tif (dashLength) {\n\t\t\t\t\t\tif (!dontStart)\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\tvar iterator = new PathIterator(this, 0.25, 32, false,\n\t\t\t\t\t\t\t\tstrokeMatrix),\n\t\t\t\t\t\t\tlength = iterator.length,\n\t\t\t\t\t\t\tfrom = -style.getDashOffset(), to,\n\t\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\tfrom = from % length;\n\t\t\t\t\t\twhile (from > 0) {\n\t\t\t\t\t\t\tfrom -= getOffset(i--) + getOffset(i--);\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile (from < length) {\n\t\t\t\t\t\t\tto = from + getOffset(i++);\n\t\t\t\t\t\t\tif (from > 0 || to > 0)\n\t\t\t\t\t\t\t\titerator.drawPart(ctx,\n\t\t\t\t\t\t\t\t\t\tMath.max(from, 0), Math.max(to, 0));\n\t\t\t\t\t\t\tfrom = to + getOffset(i++);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_drawSelected: function(ctx, matrix) {\n\t\t\tctx.beginPath();\n\t\t\tdrawSegments(ctx, this, matrix);\n\t\t\tctx.stroke();\n\t\t\tdrawHandles(ctx, this._segments, matrix, paper.settings.handleSize);\n\t\t}\n\t};\n},\nnew function() {\n\tfunction getCurrentSegment(that) {\n\t\tvar segments = that._segments;\n\t\tif (!segments.length)\n\t\t\tthrow new Error('Use a moveTo() command first');\n\t\treturn segments[segments.length - 1];\n\t}\n\n\treturn {\n\t\tmoveTo: function() {\n\t\t\tvar segments = this._segments;\n\t\t\tif (segments.length === 1)\n\t\t\t\tthis.removeSegment(0);\n\t\t\tif (!segments.length)\n\t\t\t\tthis._add([ new Segment(Point.read(arguments)) ]);\n\t\t},\n\n\t\tmoveBy: function() {\n\t\t\tthrow new Error('moveBy() is unsupported on Path items.');\n\t\t},\n\n\t\tlineTo: function() {\n\t\t\tthis._add([ new Segment(Point.read(arguments)) ]);\n\t\t},\n\n\t\tcubicCurveTo: function() {\n\t\t\tvar handle1 = Point.read(arguments),\n\t\t\t\thandle2 = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this);\n\t\t\tcurrent.setHandleOut(handle1.subtract(current._point));\n\t\t\tthis._add([ new Segment(to, handle2.subtract(to)) ]);\n\t\t},\n\n\t\tquadraticCurveTo: function() {\n\t\t\tvar handle = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.cubicCurveTo(\n\t\t\t\thandle.add(current.subtract(handle).multiply(1 / 3)),\n\t\t\t\thandle.add(to.subtract(handle).multiply(1 / 3)),\n\t\t\t\tto\n\t\t\t);\n\t\t},\n\n\t\tcurveTo: function() {\n\t\t\tvar through = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tt = Base.pick(Base.read(arguments), 0.5),\n\t\t\t\tt1 = 1 - t,\n\t\t\t\tcurrent = getCurrentSegment(this)._point,\n\t\t\t\thandle = through.subtract(current.multiply(t1 * t1))\n\t\t\t\t\t.subtract(to.multiply(t * t)).divide(2 * t * t1);\n\t\t\tif (handle.isNaN())\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Cannot put a curve through points with parameter = ' + t);\n\t\t\tthis.quadraticCurveTo(handle, to);\n\t\t},\n\n\t\tarcTo: function() {\n\t\t\tvar current = getCurrentSegment(this),\n\t\t\t\tfrom = current._point,\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tthrough,\n\t\t\t\tpeek = Base.peek(arguments),\n\t\t\t\tclockwise = Base.pick(peek, true),\n\t\t\t\tcenter, extent, vector, matrix;\n\t\t\tif (typeof clockwise === 'boolean') {\n\t\t\t\tvar middle = from.add(to).divide(2),\n\t\t\t\tthrough = middle.add(middle.subtract(from).rotate(\n\t\t\t\t\t\tclockwise ? -90 : 90));\n\t\t\t} else if (Base.remain(arguments) <= 2) {\n\t\t\t\tthrough = to;\n\t\t\t\tto = Point.read(arguments);\n\t\t\t} else {\n\t\t\t\tvar radius = Size.read(arguments),\n\t\t\t\t\tisZero = Numerical.isZero;\n\t\t\t\tif (isZero(radius.width) || isZero(radius.height))\n\t\t\t\t\treturn this.lineTo(to);\n\t\t\t\tvar rotation = Base.read(arguments),\n\t\t\t\t\tclockwise = !!Base.read(arguments),\n\t\t\t\t\tlarge = !!Base.read(arguments),\n\t\t\t\t\tmiddle = from.add(to).divide(2),\n\t\t\t\t\tpt = from.subtract(middle).rotate(-rotation),\n\t\t\t\t\tx = pt.x,\n\t\t\t\t\ty = pt.y,\n\t\t\t\t\tabs = Math.abs,\n\t\t\t\t\trx = abs(radius.width),\n\t\t\t\t\try = abs(radius.height),\n\t\t\t\t\trxSq = rx * rx,\n\t\t\t\t\trySq = ry * ry,\n\t\t\t\t\txSq = x * x,\n\t\t\t\t\tySq = y * y;\n\t\t\t\tvar factor = Math.sqrt(xSq / rxSq + ySq / rySq);\n\t\t\t\tif (factor > 1) {\n\t\t\t\t\trx *= factor;\n\t\t\t\t\try *= factor;\n\t\t\t\t\trxSq = rx * rx;\n\t\t\t\t\trySq = ry * ry;\n\t\t\t\t}\n\t\t\t\tfactor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /\n\t\t\t\t\t\t(rxSq * ySq + rySq * xSq);\n\t\t\t\tif (abs(factor) < 1e-12)\n\t\t\t\t\tfactor = 0;\n\t\t\t\tif (factor < 0)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Cannot create an arc with the given arguments');\n\t\t\t\tcenter = new Point(rx * y / ry, -ry * x / rx)\n\t\t\t\t\t\t.multiply((large === clockwise ? -1 : 1)\n\t\t\t\t\t\t\t* Math.sqrt(factor))\n\t\t\t\t\t\t.rotate(rotation).add(middle);\n\t\t\t\tmatrix = new Matrix().translate(center).rotate(rotation)\n\t\t\t\t\t\t.scale(rx, ry);\n\t\t\t\tvector = matrix._inverseTransform(from);\n\t\t\t\textent = vector.getDirectedAngle(matrix._inverseTransform(to));\n\t\t\t\tif (!clockwise && extent > 0)\n\t\t\t\t\textent -= 360;\n\t\t\t\telse if (clockwise && extent < 0)\n\t\t\t\t\textent += 360;\n\t\t\t}\n\t\t\tif (through) {\n\t\t\t\tvar l1 = new Line(from.add(through).divide(2),\n\t\t\t\t\t\t\tthrough.subtract(from).rotate(90), true),\n\t\t\t\t\tl2 = new Line(through.add(to).divide(2),\n\t\t\t\t\t\t\tto.subtract(through).rotate(90), true),\n\t\t\t\t\tline = new Line(from, to),\n\t\t\t\t\tthroughSide = line.getSide(through);\n\t\t\t\tcenter = l1.intersect(l2, true);\n\t\t\t\tif (!center) {\n\t\t\t\t\tif (!throughSide)\n\t\t\t\t\t\treturn this.lineTo(to);\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Cannot create an arc with the given arguments');\n\t\t\t\t}\n\t\t\t\tvector = from.subtract(center);\n\t\t\t\textent = vector.getDirectedAngle(to.subtract(center));\n\t\t\t\tvar centerSide = line.getSide(center);\n\t\t\t\tif (centerSide === 0) {\n\t\t\t\t\textent = throughSide * Math.abs(extent);\n\t\t\t\t} else if (throughSide === centerSide) {\n\t\t\t\t\textent += extent < 0 ? 360 : -360;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar ext = Math.abs(extent),\n\t\t\t\tcount = ext >= 360 ? 4 : Math.ceil(ext / 90),\n\t\t\t\tinc = extent / count,\n\t\t\t\thalf = inc * Math.PI / 360,\n\t\t\t\tz = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),\n\t\t\t\tsegments = [];\n\t\t\tfor (var i = 0; i <= count; i++) {\n\t\t\t\tvar pt = to,\n\t\t\t\t\tout = null;\n\t\t\t\tif (i < count) {\n\t\t\t\t\tout = vector.rotate(90).multiply(z);\n\t\t\t\t\tif (matrix) {\n\t\t\t\t\t\tpt = matrix._transformPoint(vector);\n\t\t\t\t\t\tout = matrix._transformPoint(vector.add(out))\n\t\t\t\t\t\t\t\t.subtract(pt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpt = center.add(vector);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!i) {\n\t\t\t\t\tcurrent.setHandleOut(out);\n\t\t\t\t} else {\n\t\t\t\t\tvar _in = vector.rotate(-90).multiply(z);\n\t\t\t\t\tif (matrix) {\n\t\t\t\t\t\t_in = matrix._transformPoint(vector.add(_in))\n\t\t\t\t\t\t\t\t.subtract(pt);\n\t\t\t\t\t}\n\t\t\t\t\tsegments.push(new Segment(pt, _in, out));\n\t\t\t\t}\n\t\t\t\tvector = vector.rotate(inc);\n\t\t\t}\n\t\t\tthis._add(segments);\n\t\t},\n\n\t\tlineBy: function() {\n\t\t\tvar to = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.lineTo(current.add(to));\n\t\t},\n\n\t\tcurveBy: function() {\n\t\t\tvar through = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tparameter = Base.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.curveTo(current.add(through), current.add(to), parameter);\n\t\t},\n\n\t\tcubicCurveBy: function() {\n\t\t\tvar handle1 = Point.read(arguments),\n\t\t\t\thandle2 = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.cubicCurveTo(current.add(handle1), current.add(handle2),\n\t\t\t\t\tcurrent.add(to));\n\t\t},\n\n\t\tquadraticCurveBy: function() {\n\t\t\tvar handle = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.quadraticCurveTo(current.add(handle), current.add(to));\n\t\t},\n\n\t\tarcBy: function() {\n\t\t\tvar current = getCurrentSegment(this)._point,\n\t\t\t\tpoint = current.add(Point.read(arguments)),\n\t\t\t\tclockwise = Base.pick(Base.peek(arguments), true);\n\t\t\tif (typeof clockwise === 'boolean') {\n\t\t\t\tthis.arcTo(point, clockwise);\n\t\t\t} else {\n\t\t\t\tthis.arcTo(point, current.add(Point.read(arguments)));\n\t\t\t}\n\t\t},\n\n\t\tclosePath: function(tolerance) {\n\t\t\tthis.setClosed(true);\n\t\t\tthis.join(this, tolerance);\n\t\t}\n\t};\n}, {\n\n\t_getBounds: function(matrix, options) {\n\t\tvar method = options.handle\n\t\t\t\t? 'getHandleBounds'\n\t\t\t\t: options.stroke\n\t\t\t\t? 'getStrokeBounds'\n\t\t\t\t: 'getBounds';\n\t\treturn Path[method](this._segments, this._closed, this, matrix, options);\n\t},\n\nstatics: {\n\tgetBounds: function(segments, closed, path, matrix, options, strokePadding) {\n\t\tvar first = segments[0];\n\t\tif (!first)\n\t\t\treturn new Rectangle();\n\t\tvar coords = new Array(6),\n\t\t\tprevCoords = first._transformCoordinates(matrix, new Array(6)),\n\t\t\tmin = prevCoords.slice(0, 2),\n\t\t\tmax = min.slice(),\n\t\t\troots = new Array(2);\n\n\t\tfunction processSegment(segment) {\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tfor (var i = 0; i < 2; i++) {\n\t\t\t\tCurve._addBounds(\n\t\t\t\t\tprevCoords[i],\n\t\t\t\t\tprevCoords[i + 4],\n\t\t\t\t\tcoords[i + 2],\n\t\t\t\t\tcoords[i],\n\t\t\t\t\ti, strokePadding ? strokePadding[i] : 0, min, max, roots);\n\t\t\t}\n\t\t\tvar tmp = prevCoords;\n\t\t\tprevCoords = coords;\n\t\t\tcoords = tmp;\n\t\t}\n\n\t\tfor (var i = 1, l = segments.length; i < l; i++)\n\t\t\tprocessSegment(segments[i]);\n\t\tif (closed)\n\t\t\tprocessSegment(first);\n\t\treturn new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);\n\t},\n\n\tgetStrokeBounds: function(segments, closed, path, matrix, options) {\n\t\tvar style = path.getStyle(),\n\t\t\tstroke = style.hasStroke(),\n\t\t\tstrokeWidth = style.getStrokeWidth(),\n\t\t\tstrokeMatrix = stroke && path._getStrokeMatrix(matrix, options),\n\t\t\tstrokePadding = stroke && Path._getStrokePadding(strokeWidth,\n\t\t\t\tstrokeMatrix),\n\t\t\tbounds = Path.getBounds(segments, closed, path, matrix, options,\n\t\t\t\tstrokePadding);\n\t\tif (!stroke)\n\t\t\treturn bounds;\n\t\tvar strokeRadius = strokeWidth / 2,\n\t\t\tjoin = style.getStrokeJoin(),\n\t\t\tcap = style.getStrokeCap(),\n\t\t\tmiterLimit = strokeRadius * style.getMiterLimit(),\n\t\t\tjoinBounds = new Rectangle(new Size(strokePadding));\n\n\t\tfunction addPoint(point) {\n\t\t\tbounds = bounds.include(point);\n\t\t}\n\n\t\tfunction addRound(segment) {\n\t\t\tbounds = bounds.unite(\n\t\t\t\t\tjoinBounds.setCenter(segment._point.transform(matrix)));\n\t\t}\n\n\t\tfunction addJoin(segment, join) {\n\t\t\tvar handleIn = segment._handleIn,\n\t\t\t\thandleOut = segment._handleOut;\n\t\t\tif (join === 'round' || !handleIn.isZero() && !handleOut.isZero()\n\t\t\t\t\t&& handleIn.isCollinear(handleOut)) {\n\t\t\t\taddRound(segment);\n\t\t\t} else {\n\t\t\t\tPath._addBevelJoin(segment, join, strokeRadius, miterLimit,\n\t\t\t\t\t\tmatrix, strokeMatrix, addPoint);\n\t\t\t}\n\t\t}\n\n\t\tfunction addCap(segment, cap) {\n\t\t\tif (cap === 'round') {\n\t\t\t\taddRound(segment);\n\t\t\t} else {\n\t\t\t\tPath._addSquareCap(segment, cap, strokeRadius, matrix,\n\t\t\t\t\t\tstrokeMatrix, addPoint);\n\t\t\t}\n\t\t}\n\n\t\tvar length = segments.length - (closed ? 0 : 1);\n\t\tfor (var i = 1; i < length; i++)\n\t\t\taddJoin(segments[i], join);\n\t\tif (closed) {\n\t\t\taddJoin(segments[0], join);\n\t\t} else if (length > 0) {\n\t\t\taddCap(segments[0], cap);\n\t\t\taddCap(segments[segments.length - 1], cap);\n\t\t}\n\t\treturn bounds;\n\t},\n\n\t_getStrokePadding: function(radius, matrix) {\n\t\tif (!matrix)\n\t\t\treturn [radius, radius];\n\t\tvar hor = new Point(radius, 0).transform(matrix),\n\t\t\tver = new Point(0, radius).transform(matrix),\n\t\t\tphi = hor.getAngleInRadians(),\n\t\t\ta = hor.getLength(),\n\t\t\tb = ver.getLength();\n\t\tvar sin = Math.sin(phi),\n\t\t\tcos = Math.cos(phi),\n\t\t\ttan = Math.tan(phi),\n\t\t\ttx = Math.atan2(b * tan, a),\n\t\t\tty = Math.atan2(b, tan * a);\n\t\treturn [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),\n\t\t\t\tMath.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];\n\t},\n\n\t_addBevelJoin: function(segment, join, radius, miterLimit, matrix,\n\t\t\tstrokeMatrix, addPoint, isArea) {\n\t\tvar curve2 = segment.getCurve(),\n\t\t\tcurve1 = curve2.getPrevious(),\n\t\t\tpoint = curve2.getPoint1().transform(matrix),\n\t\t\tnormal1 = curve1.getNormalAtTime(1).multiply(radius)\n\t\t\t\t.transform(strokeMatrix),\n\t\t\tnormal2 = curve2.getNormalAtTime(0).multiply(radius)\n\t\t\t\t.transform(strokeMatrix);\n\t\tif (normal1.getDirectedAngle(normal2) < 0) {\n\t\t\tnormal1 = normal1.negate();\n\t\t\tnormal2 = normal2.negate();\n\t\t}\n\t\tif (isArea) {\n\t\t\taddPoint(point);\n\t\t\taddPoint(point.add(normal1));\n\t\t}\n\t\tif (join === 'miter') {\n\t\t\tvar corner = new Line(point.add(normal1),\n\t\t\t\t\tnew Point(-normal1.y, normal1.x), true\n\t\t\t\t).intersect(new Line(point.add(normal2),\n\t\t\t\t\tnew Point(-normal2.y, normal2.x), true\n\t\t\t\t), true);\n\t\t\tif (corner && point.getDistance(corner) <= miterLimit) {\n\t\t\t\taddPoint(corner);\n\t\t\t\tif (!isArea)\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (!isArea)\n\t\t\taddPoint(point.add(normal1));\n\t\taddPoint(point.add(normal2));\n\t},\n\n\t_addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,\n\t\t\taddPoint, isArea) {\n\t\tvar point = segment._point.transform(matrix),\n\t\t\tloc = segment.getLocation(),\n\t\t\tnormal = loc.getNormal().multiply(radius).transform(strokeMatrix);\n\t\tif (isArea) {\n\t\t\taddPoint(point.subtract(normal));\n\t\t\taddPoint(point.add(normal));\n\t\t}\n\t\tif (cap === 'square') {\n\t\t\tpoint = point.add(normal.rotate(\n\t\t\t\t\tloc.getTime() === 0 ? -90 : 90));\n\t\t}\n\t\taddPoint(point.add(normal));\n\t\taddPoint(point.subtract(normal));\n\t},\n\n\tgetHandleBounds: function(segments, closed, path, matrix, options) {\n\t\tvar style = path.getStyle(),\n\t\t\tstroke = options.stroke && style.hasStroke(),\n\t\t\tstrokePadding,\n\t\t\tjoinPadding;\n\t\tif (stroke) {\n\t\t\tvar strokeMatrix = path._getStrokeMatrix(matrix, options),\n\t\t\t\tstrokeRadius = style.getStrokeWidth() / 2,\n\t\t\t\tjoinRadius = strokeRadius;\n\t\t\tif (style.getStrokeJoin() === 'miter')\n\t\t\t\tjoinRadius = strokeRadius * style.getMiterLimit();\n\t\t\tif (style.getStrokeCap() === 'square')\n\t\t\t\tjoinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));\n\t\t\tstrokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix);\n\t\t\tjoinPadding = Path._getStrokePadding(joinRadius, strokeMatrix);\n\t\t}\n\t\tvar coords = new Array(6),\n\t\t\tx1 = Infinity,\n\t\t\tx2 = -x1,\n\t\t\ty1 = x1,\n\t\t\ty2 = x2;\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar segment = segments[i];\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tfor (var j = 0; j < 6; j += 2) {\n\t\t\t\tvar padding = !j ? joinPadding : strokePadding,\n\t\t\t\t\tpaddingX = padding ? padding[0] : 0,\n\t\t\t\t\tpaddingY = padding ? padding[1] : 0,\n\t\t\t\t\tx = coords[j],\n\t\t\t\t\ty = coords[j + 1],\n\t\t\t\t\txn = x - paddingX,\n\t\t\t\t\txx = x + paddingX,\n\t\t\t\t\tyn = y - paddingY,\n\t\t\t\t\tyx = y + paddingY;\n\t\t\t\tif (xn < x1) x1 = xn;\n\t\t\t\tif (xx > x2) x2 = xx;\n\t\t\t\tif (yn < y1) y1 = yn;\n\t\t\t\tif (yx > y2) y2 = yx;\n\t\t\t}\n\t\t}\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t}\n}});\n\nPath.inject({ statics: new function() {\n\n\tvar kappa = 0.5522847498307936,\n\t\tellipseSegments = [\n\t\t\tnew Segment([-1, 0], [0, kappa ], [0, -kappa]),\n\t\t\tnew Segment([0, -1], [-kappa, 0], [kappa, 0 ]),\n\t\t\tnew Segment([1, 0], [0, -kappa], [0, kappa ]),\n\t\t\tnew Segment([0, 1], [kappa, 0 ], [-kappa, 0])\n\t\t];\n\n\tfunction createPath(segments, closed, args) {\n\t\tvar props = Base.getNamed(args),\n\t\t\tpath = new Path(props && props.insert === false && Item.NO_INSERT);\n\t\tpath._add(segments);\n\t\tpath._closed = closed;\n\t\treturn path.set(props);\n\t}\n\n\tfunction createEllipse(center, radius, args) {\n\t\tvar segments = new Array(4);\n\t\tfor (var i = 0; i < 4; i++) {\n\t\t\tvar segment = ellipseSegments[i];\n\t\t\tsegments[i] = new Segment(\n\t\t\t\tsegment._point.multiply(radius).add(center),\n\t\t\t\tsegment._handleIn.multiply(radius),\n\t\t\t\tsegment._handleOut.multiply(radius)\n\t\t\t);\n\t\t}\n\t\treturn createPath(segments, true, args);\n\t}\n\n\treturn {\n\t\tLine: function() {\n\t\t\treturn createPath([\n\t\t\t\tnew Segment(Point.readNamed(arguments, 'from')),\n\t\t\t\tnew Segment(Point.readNamed(arguments, 'to'))\n\t\t\t], false, arguments);\n\t\t},\n\n\t\tCircle: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius');\n\t\t\treturn createEllipse(center, new Size(radius), arguments);\n\t\t},\n\n\t\tRectangle: function() {\n\t\t\tvar rect = Rectangle.readNamed(arguments, 'rectangle'),\n\t\t\t\tradius = Size.readNamed(arguments, 'radius', 0,\n\t\t\t\t\t\t{ readNull: true }),\n\t\t\t\tbl = rect.getBottomLeft(true),\n\t\t\t\ttl = rect.getTopLeft(true),\n\t\t\t\ttr = rect.getTopRight(true),\n\t\t\t\tbr = rect.getBottomRight(true),\n\t\t\t\tsegments;\n\t\t\tif (!radius || radius.isZero()) {\n\t\t\t\tsegments = [\n\t\t\t\t\tnew Segment(bl),\n\t\t\t\t\tnew Segment(tl),\n\t\t\t\t\tnew Segment(tr),\n\t\t\t\t\tnew Segment(br)\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\tradius = Size.min(radius, rect.getSize(true).divide(2));\n\t\t\t\tvar rx = radius.width,\n\t\t\t\t\try = radius.height,\n\t\t\t\t\thx = rx * kappa,\n\t\t\t\t\thy = ry * kappa;\n\t\t\t\tsegments = [\n\t\t\t\t\tnew Segment(bl.add(rx, 0), null, [-hx, 0]),\n\t\t\t\t\tnew Segment(bl.subtract(0, ry), [0, hy]),\n\t\t\t\t\tnew Segment(tl.add(0, ry), null, [0, -hy]),\n\t\t\t\t\tnew Segment(tl.add(rx, 0), [-hx, 0], null),\n\t\t\t\t\tnew Segment(tr.subtract(rx, 0), null, [hx, 0]),\n\t\t\t\t\tnew Segment(tr.add(0, ry), [0, -hy], null),\n\t\t\t\t\tnew Segment(br.subtract(0, ry), null, [0, hy]),\n\t\t\t\t\tnew Segment(br.subtract(rx, 0), [hx, 0])\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn createPath(segments, true, arguments);\n\t\t},\n\n\t\tRoundRectangle: '#Rectangle',\n\n\t\tEllipse: function() {\n\t\t\tvar ellipse = Shape._readEllipse(arguments);\n\t\t\treturn createEllipse(ellipse.center, ellipse.radius, arguments);\n\t\t},\n\n\t\tOval: '#Ellipse',\n\n\t\tArc: function() {\n\t\t\tvar from = Point.readNamed(arguments, 'from'),\n\t\t\t\tthrough = Point.readNamed(arguments, 'through'),\n\t\t\t\tto = Point.readNamed(arguments, 'to'),\n\t\t\t\tprops = Base.getNamed(arguments),\n\t\t\t\tpath = new Path(props && props.insert === false\n\t\t\t\t\t\t&& Item.NO_INSERT);\n\t\t\tpath.moveTo(from);\n\t\t\tpath.arcTo(through, to);\n\t\t\treturn path.set(props);\n\t\t},\n\n\t\tRegularPolygon: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tsides = Base.readNamed(arguments, 'sides'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius'),\n\t\t\t\tstep = 360 / sides,\n\t\t\t\tthree = sides % 3 === 0,\n\t\t\t\tvector = new Point(0, three ? -radius : radius),\n\t\t\t\toffset = three ? -1 : 0.5,\n\t\t\t\tsegments = new Array(sides);\n\t\t\tfor (var i = 0; i < sides; i++)\n\t\t\t\tsegments[i] = new Segment(center.add(\n\t\t\t\t\tvector.rotate((i + offset) * step)));\n\t\t\treturn createPath(segments, true, arguments);\n\t\t},\n\n\t\tStar: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tpoints = Base.readNamed(arguments, 'points') * 2,\n\t\t\t\tradius1 = Base.readNamed(arguments, 'radius1'),\n\t\t\t\tradius2 = Base.readNamed(arguments, 'radius2'),\n\t\t\t\tstep = 360 / points,\n\t\t\t\tvector = new Point(0, -1),\n\t\t\t\tsegments = new Array(points);\n\t\t\tfor (var i = 0; i < points; i++)\n\t\t\t\tsegments[i] = new Segment(center.add(vector.rotate(step * i)\n\t\t\t\t\t\t.multiply(i % 2 ? radius2 : radius1)));\n\t\t\treturn createPath(segments, true, arguments);\n\t\t}\n\t};\n}});\n\nvar CompoundPath = PathItem.extend({\n\t_class: 'CompoundPath',\n\t_serializeFields: {\n\t\tchildren: []\n\t},\n\n\tinitialize: function CompoundPath(arg) {\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tif (!this._initialize(arg)) {\n\t\t\tif (typeof arg === 'string') {\n\t\t\t\tthis.setPathData(arg);\n\t\t\t} else {\n\t\t\t\tthis.addChildren(Array.isArray(arg) ? arg : arguments);\n\t\t\t}\n\t\t}\n\t},\n\n\tinsertChildren: function insertChildren(index, items) {\n\t\tvar list = items,\n\t\t\tfirst = list[0];\n\t\tif (first && typeof first[0] === 'number')\n\t\t\tlist = [list];\n\t\tfor (var i = items.length - 1; i >= 0; i--) {\n\t\t\tvar item = list[i];\n\t\t\tif (list === items && !(item instanceof Path))\n\t\t\t\tlist = Base.slice(list);\n\t\t\tif (Array.isArray(item)) {\n\t\t\t\tlist[i] = new Path({ segments: item, insert: false });\n\t\t\t} else if (item instanceof CompoundPath) {\n\t\t\t\tlist.splice.apply(list, [i, 1].concat(item.removeChildren()));\n\t\t\t\titem.remove();\n\t\t\t}\n\t\t}\n\t\treturn insertChildren.base.call(this, index, list);\n\t},\n\n\treduce: function reduce(options) {\n\t\tvar children = this._children;\n\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\tvar path = children[i].reduce(options);\n\t\t\tif (path.isEmpty())\n\t\t\t\tpath.remove();\n\t\t}\n\t\tif (!children.length) {\n\t\t\tvar path = new Path(Item.NO_INSERT);\n\t\t\tpath.copyAttributes(this);\n\t\t\tpath.insertAbove(this);\n\t\t\tthis.remove();\n\t\t\treturn path;\n\t\t}\n\t\treturn reduce.base.call(this);\n\t},\n\n\tisClosed: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tif (!children[i]._closed)\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tsetClosed: function(closed) {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tchildren[i].setClosed(closed);\n\t\t}\n\t},\n\n\tgetFirstSegment: function() {\n\t\tvar first = this.getFirstChild();\n\t\treturn first && first.getFirstSegment();\n\t},\n\n\tgetLastSegment: function() {\n\t\tvar last = this.getLastChild();\n\t\treturn last && last.getLastSegment();\n\t},\n\n\tgetCurves: function() {\n\t\tvar children = this._children,\n\t\t\tcurves = [];\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tcurves.push.apply(curves, children[i].getCurves());\n\t\treturn curves;\n\t},\n\n\tgetFirstCurve: function() {\n\t\tvar first = this.getFirstChild();\n\t\treturn first && first.getFirstCurve();\n\t},\n\n\tgetLastCurve: function() {\n\t\tvar last = this.getLastChild();\n\t\treturn last && last.getLastCurve();\n\t},\n\n\tgetArea: function() {\n\t\tvar children = this._children,\n\t\t\tarea = 0;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tarea += children[i].getArea();\n\t\treturn area;\n\t},\n\n\tgetLength: function() {\n\t\tvar children = this._children,\n\t\t\tlength = 0;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tlength += children[i].getLength();\n\t\treturn length;\n\t}\n}, {\n\tbeans: true,\n\n\tgetPathData: function(_matrix, _precision) {\n\t\tvar children = this._children,\n\t\t\tpaths = [];\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i],\n\t\t\t\tmx = child._matrix;\n\t\t\tpaths.push(child.getPathData(_matrix && !mx.isIdentity()\n\t\t\t\t\t? _matrix.appended(mx) : _matrix, _precision));\n\t\t}\n\t\treturn paths.join('');\n\t}\n}, {\n\t_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {\n\t\treturn _hitTestChildren.base.call(this, point,\n\t\t\t\toptions.class === Path || options.type === 'path' ? options\n\t\t\t\t\t: Base.set({}, options, { fill: false }),\n\t\t\t\tviewMatrix);\n\t},\n\n\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\tvar children = this._children;\n\t\tif (!children.length)\n\t\t\treturn;\n\n\t\tparam = param.extend({ dontStart: true, dontFinish: true });\n\t\tctx.beginPath();\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tchildren[i].draw(ctx, param, strokeMatrix);\n\n\t\tif (!param.clip) {\n\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\tvar style = this._style;\n\t\t\tif (style.hasFill()) {\n\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (style.hasStroke())\n\t\t\t\tctx.stroke();\n\t\t}\n\t},\n\n\t_drawSelected: function(ctx, matrix, selectionItems) {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i],\n\t\t\t\tmx = child._matrix;\n\t\t\tif (!selectionItems[child._id]) {\n\t\t\t\tchild._drawSelected(ctx, mx.isIdentity() ? matrix\n\t\t\t\t\t\t: matrix.appended(mx));\n\t\t\t}\n\t\t}\n\t}\n},\nnew function() {\n\tfunction getCurrentPath(that, check) {\n\t\tvar children = that._children;\n\t\tif (check && !children.length)\n\t\t\tthrow new Error('Use a moveTo() command first');\n\t\treturn children[children.length - 1];\n\t}\n\n\treturn Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',\n\t\t\t'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',\n\t\t\t'arcBy'],\n\t\tfunction(key) {\n\t\t\tthis[key] = function() {\n\t\t\t\tvar path = getCurrentPath(this, true);\n\t\t\t\tpath[key].apply(path, arguments);\n\t\t\t};\n\t\t}, {\n\t\t\tmoveTo: function() {\n\t\t\t\tvar current = getCurrentPath(this),\n\t\t\t\t\tpath = current && current.isEmpty() ? current\n\t\t\t\t\t\t\t: new Path(Item.NO_INSERT);\n\t\t\t\tif (path !== current)\n\t\t\t\t\tthis.addChild(path);\n\t\t\t\tpath.moveTo.apply(path, arguments);\n\t\t\t},\n\n\t\t\tmoveBy: function() {\n\t\t\t\tvar current = getCurrentPath(this, true),\n\t\t\t\t\tlast = current && current.getLastSegment(),\n\t\t\t\t\tpoint = Point.read(arguments);\n\t\t\t\tthis.moveTo(last ? point.add(last._point) : point);\n\t\t\t},\n\n\t\t\tclosePath: function(tolerance) {\n\t\t\t\tgetCurrentPath(this, true).closePath(tolerance);\n\t\t\t}\n\t\t}\n\t);\n}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {\n\tthis[key] = function(param) {\n\t\tvar children = this._children,\n\t\t\tres;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tres = children[i][key](param) || res;\n\t\t}\n\t\treturn res;\n\t};\n}, {}));\n\nPathItem.inject(new function() {\n\tvar min = Math.min,\n\t\tmax = Math.max,\n\t\tabs = Math.abs,\n\t\toperators = {\n\t\t\tunite: { 1: true },\n\t\t\tintersect: { 2: true },\n\t\t\tsubtract: { 1: true },\n\t\t\texclude: { 1: true }\n\t\t};\n\n\tfunction preparePath(path, closed) {\n\t\tvar res = path.clone(false).reduce({ simplify: true })\n\t\t\t\t.transform(null, true, true);\n\t\tif (closed)\n\t\t\tres.setClosed(true);\n\t\treturn closed\n\t\t\t? res.resolveCrossings().reorient(res.getFillRule() === 'nonzero')\n\t\t\t: res;\n\t}\n\n\tfunction createResult(ctor, paths, reduce, path1, path2) {\n\t\tvar result = new ctor(Item.NO_INSERT);\n\t\tresult.addChildren(paths, true);\n\t\tif (reduce)\n\t\t\tresult = result.reduce({ simplify: true });\n\t\tresult.insertAbove(path2 && path1.isSibling(path2)\n\t\t\t\t&& path1.getIndex() < path2.getIndex() ? path2 : path1);\n\t\tresult.copyAttributes(path1, true);\n\t\treturn result;\n\t}\n\n\tfunction computeBoolean(path1, path2, operation) {\n\t\tvar operator = operators[operation];\n\t\toperator[operation] = true;\n\t\tif (!path1.isClosed())\n\t\t\treturn computeOpenBoolean(path1, path2, operator);\n\t\tvar _path1 = preparePath(path1, true),\n\t\t\t_path2 = path2 && path1 !== path2 && preparePath(path2, true);\n\t\tif (_path2 && (operator.subtract || operator.exclude)\n\t\t\t\t^ (_path2.isClockwise() ^ _path1.isClockwise()))\n\t\t\t_path2.reverse();\n\t\tvar crossings = divideLocations(\n\t\t\t\tCurveLocation.expand(_path1.getCrossings(_path2))),\n\t\t\tpaths1 = _path1._children || [_path1],\n\t\t\tpaths2 = _path2 && (_path2._children || [_path2]),\n\t\t\tsegments = [],\n\t\t\tcurves = [],\n\t\t\tpaths;\n\n\t\tif (!crossings.length) {\n\t\t\tvar ok = true;\n\t\t\tif (paths2) {\n\t\t\t\tfor (var i1 = 0, l1 = paths1.length; i1 < l1 && ok; i1++) {\n\t\t\t\t\tvar bounds1 = paths1[i1].getBounds();\n\t\t\t\t\tfor (var i2 = 0, l2 = paths2.length; i2 < l2 && ok; i2++) {\n\t\t\t\t\t\tvar bounds2 = paths2[i2].getBounds();\n\t\t\t\t\t\tok = !bounds1._containsRectangle(bounds2) &&\n\t\t\t\t\t\t\t !bounds2._containsRectangle(bounds1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (ok) {\n\t\t\t\tpaths = operator.unite || operator.exclude ? [_path1, _path2]\n\t\t\t\t\t\t: operator.subtract ? [_path1]\n\t\t\t\t\t\t: operator.intersect ? [new Path(Item.NO_INSERT)]\n\t\t\t\t\t\t: null;\n\t\t\t}\n\t\t}\n\n\t\tfunction collect(paths) {\n\t\t\tfor (var i = 0, l = paths.length; i < l; i++) {\n\t\t\t\tvar path = paths[i];\n\t\t\t\tsegments.push.apply(segments, path._segments);\n\t\t\t\tcurves.push.apply(curves, path.getCurves());\n\t\t\t\tpath._overlapsOnly = path._validOverlapsOnly = true;\n\t\t\t}\n\t\t}\n\n\t\tif (!paths) {\n\t\t\tcollect(paths1);\n\t\t\tif (paths2)\n\t\t\t\tcollect(paths2);\n\t\t\tfor (var i = 0, l = crossings.length; i < l; i++) {\n\t\t\t\tpropagateWinding(crossings[i]._segment, _path1, _path2, curves,\n\t\t\t\t\t\toperator);\n\t\t\t}\n\t\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\t\tvar segment = segments[i],\n\t\t\t\t\tinter = segment._intersection;\n\t\t\t\tif (segment._winding == null) {\n\t\t\t\t\tpropagateWinding(segment, _path1, _path2, curves, operator);\n\t\t\t\t}\n\t\t\t\tif (!(inter && inter._overlap)) {\n\t\t\t\t\tvar path = segment._path;\n\t\t\t\t\tpath._overlapsOnly = false;\n\t\t\t\t\tif (operator[segment._winding.winding])\n\t\t\t\t\t\tpath._validOverlapsOnly = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpaths = tracePaths(segments, operator);\n\t\t}\n\n\t\treturn createResult(CompoundPath, paths, true, path1, path2);\n\t}\n\n\tfunction computeOpenBoolean(path1, path2, operator) {\n\t\tif (!path2 || !operator.subtract && !operator.intersect) {\n\t\t\tthrow new Error('Boolean operations on open paths only support ' +\n\t\t\t\t\t'subtraction and intersection with another path.');\n\t\t}\n\t\tvar _path1 = preparePath(path1, false),\n\t\t\t_path2 = preparePath(path2, false),\n\t\t\tcrossings = _path1.getCrossings(_path2),\n\t\t\tsub = operator.subtract,\n\t\t\tpaths = [];\n\n\t\tfunction addPath(path) {\n\t\t\tif (_path2.contains(path.getPointAt(path.getLength() / 2)) ^ sub) {\n\t\t\t\tpaths.unshift(path);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = crossings.length - 1; i >= 0; i--) {\n\t\t\tvar path = crossings[i].split();\n\t\t\tif (path) {\n\t\t\t\tif (addPath(path))\n\t\t\t\t\tpath.getFirstSegment().setHandleIn(0, 0);\n\t\t\t\t_path1.getLastSegment().setHandleOut(0, 0);\n\t\t\t}\n\t\t}\n\t\taddPath(_path1);\n\t\treturn createResult(Group, paths, false, path1, path2);\n\t}\n\n\tfunction linkIntersections(from, to) {\n\t\tvar prev = from;\n\t\twhile (prev) {\n\t\t\tif (prev === to)\n\t\t\t\treturn;\n\t\t\tprev = prev._previous;\n\t\t}\n\t\twhile (from._next && from._next !== to)\n\t\t\tfrom = from._next;\n\t\tif (!from._next) {\n\t\t\twhile (to._previous)\n\t\t\t\tto = to._previous;\n\t\t\tfrom._next = to;\n\t\t\tto._previous = from;\n\t\t}\n\t}\n\n\tfunction divideLocations(locations, include) {\n\t\tvar results = include && [],\n\t\t\ttMin = 4e-7,\n\t\t\ttMax = 1 - tMin,\n\t\t\tnoHandles = false,\n\t\t\tclearCurves = [],\n\t\t\tprevCurve,\n\t\t\tprevTime;\n\n\t\tfor (var i = locations.length - 1; i >= 0; i--) {\n\t\t\tvar loc = locations[i];\n\t\t\tif (include) {\n\t\t\t\tif (!include(loc))\n\t\t\t\t\tcontinue;\n\t\t\t\tresults.unshift(loc);\n\t\t\t}\n\t\t\tvar curve = loc._curve,\n\t\t\t\ttime = loc._time,\n\t\t\t\torigTime = time,\n\t\t\t\tsegment;\n\t\t\tif (curve !== prevCurve) {\n\t\t\t\tnoHandles = !curve.hasHandles();\n\t\t\t} else if (prevTime >= tMin && prevTime <= tMax ) {\n\t\t\t\ttime /= prevTime;\n\t\t\t}\n\t\t\tif (time < tMin) {\n\t\t\t\tsegment = curve._segment1;\n\t\t\t} else if (time > tMax) {\n\t\t\t\tsegment = curve._segment2;\n\t\t\t} else {\n\t\t\t\tvar newCurve = curve.divideAtTime(time, true);\n\t\t\t\tif (noHandles)\n\t\t\t\t\tclearCurves.push(curve, newCurve);\n\t\t\t\tsegment = newCurve._segment1;\n\t\t\t}\n\t\t\tloc._setSegment(segment);\n\t\t\tvar inter = segment._intersection,\n\t\t\t\tdest = loc._intersection;\n\t\t\tif (inter) {\n\t\t\t\tlinkIntersections(inter, dest);\n\t\t\t\tvar other = inter;\n\t\t\t\twhile (other) {\n\t\t\t\t\tlinkIntersections(other._intersection, inter);\n\t\t\t\t\tother = other._next;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsegment._intersection = dest;\n\t\t\t}\n\t\t\tprevCurve = curve;\n\t\t\tprevTime = origTime;\n\t\t}\n\t\tfor (var i = 0, l = clearCurves.length; i < l; i++) {\n\t\t\tclearCurves[i].clearHandles();\n\t\t}\n\t\treturn results || locations;\n\t}\n\n\tfunction getWinding(point, curves, dir, dontFlip) {\n\t\tvar epsilon = 1e-8,\n\t\t\tia = dir ? 1 : 0,\n\t\t\tio = dir ? 0 : 1,\n\t\t\tpv = [point.x, point.y],\n\t\t\tpa = pv[ia],\n\t\t\tpo = pv[io],\n\t\t\tpaL = pa - epsilon,\n\t\t\tpaR = pa + epsilon,\n\t\t\twindingL = 0,\n\t\t\twindingR = 0,\n\t\t\tpathWindingL = 0,\n\t\t\tpathWindingR = 0,\n\t\t\tonPath = false,\n\t\t\tonPathWinding = 0,\n\t\t\tonPathCount = 0,\n\t\t\troots = [],\n\t\t\tvPrev,\n\t\t\tvClose;\n\n\t\tfunction addWinding(v) {\n\t\t\tvar o0 = v[io],\n\t\t\t\to3 = v[io + 6];\n\t\t\tif (po < min(o0, o3) || po > max(o0, o3)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar a0 = v[ia],\n\t\t\t\ta1 = v[ia + 2],\n\t\t\t\ta2 = v[ia + 4],\n\t\t\t\ta3 = v[ia + 6];\n\t\t\tif (o0 === o3) {\n\t\t\t\tif (a1 < paR && a3 > paL || a3 < paR && a1 > paL) {\n\t\t\t\t\tonPath = true;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar t = po === o0 ? 0\n\t\t\t\t\t: po === o3 ? 1\n\t\t\t\t\t: paL > max(a0, a1, a2, a3) || paR < min(a0, a1, a2, a3)\n\t\t\t\t\t? 0.5\n\t\t\t\t\t: Curve.solveCubic(v, io, po, roots, 0, 1) === 1\n\t\t\t\t\t\t? roots[0]\n\t\t\t\t\t\t: 0.5,\n\t\t\t\ta = t === 0 ? a0\n\t\t\t\t\t: t === 1 ? a3\n\t\t\t\t\t: Curve.getPoint(v, t)[dir ? 'y' : 'x'],\n\t\t\t\twinding = o0 > o3 ? 1 : -1,\n\t\t\t\twindingPrev = vPrev[io] > vPrev[io + 6] ? 1 : -1,\n\t\t\t\ta3Prev = vPrev[ia + 6];\n\t\t\tif (po !== o0) {\n\t\t\t\tif (a < paL) {\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t} else if (a > paR) {\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t} else {\n\t\t\t\t\tonPath = true;\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t}\n\t\t\t} else if (winding !== windingPrev) {\n\t\t\t\tif (a3Prev < paR) {\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t}\n\t\t\t\tif (a3Prev > paL) {\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t}\n\t\t\t} else if (a3Prev < paL && a > paL || a3Prev > paR && a < paR) {\n\t\t\t\tonPath = true;\n\t\t\t\tif (a3Prev < paL) {\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t} else if (a3Prev > paR) {\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvPrev = v;\n\t\t\treturn !dontFlip && a > paL && a < paR\n\t\t\t\t\t&& Curve.getTangent(v, t)[dir ? 'x' : 'y'] === 0\n\t\t\t\t\t&& getWinding(point, curves, dir ? 0 : 1, true);\n\t\t}\n\n\t\tfunction handleCurve(v) {\n\t\t\tvar o0 = v[io],\n\t\t\t\to1 = v[io + 2],\n\t\t\t\to2 = v[io + 4],\n\t\t\t\to3 = v[io + 6];\n\t\t\tif (po <= max(o0, o1, o2, o3) && po >= min(o0, o1, o2, o3)) {\n\t\t\t\tvar a0 = v[ia],\n\t\t\t\t\ta1 = v[ia + 2],\n\t\t\t\t\ta2 = v[ia + 4],\n\t\t\t\t\ta3 = v[ia + 6],\n\t\t\t\t\tmonoCurves = paL > max(a0, a1, a2, a3) ||\n\t\t\t\t\t\t\t\t paR < min(a0, a1, a2, a3)\n\t\t\t\t\t\t\t? [v] : Curve.getMonoCurves(v, dir),\n\t\t\t\t\tres;\n\t\t\t\tfor (var i = 0, l = monoCurves.length; i < l; i++) {\n\t\t\t\t\tif (res = addWinding(monoCurves[i]))\n\t\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar curve = curves[i],\n\t\t\t\tpath = curve._path,\n\t\t\t\tv = curve.getValues(),\n\t\t\t\tres;\n\t\t\tif (!i || curves[i - 1]._path !== path) {\n\t\t\t\tvPrev = null;\n\t\t\t\tif (!path._closed) {\n\t\t\t\t\tvar p1 = path.getLastCurve().getPoint2(),\n\t\t\t\t\t\tp2 = curve.getPoint1(),\n\t\t\t\t\t\tx1 = p1._x, y1 = p1._y,\n\t\t\t\t\t\tx2 = p2._x, y2 = p2._y;\n\t\t\t\t\tvClose = [x1, y1, x1, y1, x2, y2, x2, y2];\n\t\t\t\t\tif (vClose[io] !== vClose[io + 6]) {\n\t\t\t\t\t\tvPrev = vClose;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!vPrev) {\n\t\t\t\t\tvPrev = v;\n\t\t\t\t\tvar prev = path.getLastCurve();\n\t\t\t\t\twhile (prev && prev !== curve) {\n\t\t\t\t\t\tvar v2 = prev.getValues();\n\t\t\t\t\t\tif (v2[io] !== v2[io + 6]) {\n\t\t\t\t\t\t\tvPrev = v2;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprev = prev.getPrevious();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (res = handleCurve(v))\n\t\t\t\treturn res;\n\n\t\t\tif (i + 1 === l || curves[i + 1]._path !== path) {\n\t\t\t\tif (vClose && (res = handleCurve(vClose)))\n\t\t\t\t\treturn res;\n\t\t\t\tif (onPath && !pathWindingL && !pathWindingR) {\n\t\t\t\t\tvar add = path.isClockwise() ^ dir ? 1 : -1;\n\t\t\t\t\twindingL += add;\n\t\t\t\t\twindingR -= add;\n\t\t\t\t\tonPathWinding += add;\n\t\t\t\t} else {\n\t\t\t\t\twindingL += pathWindingL;\n\t\t\t\t\twindingR += pathWindingR;\n\t\t\t\t\tpathWindingL = pathWindingR = 0;\n\t\t\t\t}\n\t\t\t\tif (onPath)\n\t\t\t\t\tonPathCount++;\n\t\t\t\tonPath = false;\n\t\t\t\tvClose = null;\n\t\t\t}\n\t\t}\n\t\tif (!windingL && !windingR) {\n\t\t\twindingL = windingR = onPathWinding;\n\t\t}\n\t\twindingL = windingL && (2 - abs(windingL) % 2);\n\t\twindingR = windingR && (2 - abs(windingR) % 2);\n\t\treturn {\n\t\t\twinding: max(windingL, windingR),\n\t\t\twindingL: windingL,\n\t\t\twindingR: windingR,\n\t\t\tonContour: !windingL ^ !windingR,\n\t\t\tonPathCount: onPathCount\n\t\t};\n\t}\n\n\tfunction propagateWinding(segment, path1, path2, curves, operator) {\n\t\tvar chain = [],\n\t\t\tstart = segment,\n\t\t\ttotalLength = 0,\n\t\t\twinding;\n\t\tdo {\n\t\t\tvar curve = segment.getCurve(),\n\t\t\t\tlength = curve.getLength();\n\t\t\tchain.push({ segment: segment, curve: curve, length: length });\n\t\t\ttotalLength += length;\n\t\t\tsegment = segment.getNext();\n\t\t} while (segment && !segment._intersection && segment !== start);\n\t\tvar length = totalLength / 2;\n\t\tfor (var j = 0, l = chain.length; j < l; j++) {\n\t\t\tvar entry = chain[j],\n\t\t\t\tcurveLength = entry.length;\n\t\t\tif (length <= curveLength) {\n\t\t\t\tvar curve = entry.curve,\n\t\t\t\t\tpath = curve._path,\n\t\t\t\t\tparent = path._parent,\n\t\t\t\t\tt = curve.getTimeAt(length),\n\t\t\t\t\tpt = curve.getPointAtTime(t),\n\t\t\t\t\tdir = abs(curve.getTangentAtTime(t).normalize().y) < 0.5\n\t\t\t\t\t\t\t? 1 : 0;\n\t\t\t\tif (parent instanceof CompoundPath)\n\t\t\t\t\tpath = parent;\n\t\t\t\twinding = !(operator.subtract && path2 && (\n\t\t\t\t\t\tpath === path1 && path2._getWinding(pt, dir).winding ||\n\t\t\t\t\t\tpath === path2 && !path1._getWinding(pt, dir).winding))\n\t\t\t\t\t\t\t? getWinding(pt, curves, dir)\n\t\t\t\t\t\t\t: { winding: 0 };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlength -= curveLength;\n\t\t}\n\t\tfor (var j = chain.length - 1; j >= 0; j--) {\n\t\t\tchain[j].segment._winding = winding;\n\t\t}\n\t}\n\n\tfunction tracePaths(segments, operator) {\n\t\tvar paths = [],\n\t\t\tstart,\n\t\t\totherStart;\n\n\t\tfunction isValid(seg, excludeContour) {\n\t\t\tvar winding;\n\t\t\treturn !!(seg && !seg._visited && (!operator\n\t\t\t\t\t|| operator[(winding = seg._winding).winding]\n\t\t\t\t\t|| !excludeContour && operator.unite && winding.onContour));\n\t\t}\n\n\t\tfunction isStart(seg) {\n\t\t\treturn seg === start || seg === otherStart;\n\t\t}\n\n\t\tfunction visitPath(path) {\n\t\t\tvar segments = path._segments;\n\t\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\t\tsegments[i]._visited = true;\n\t\t\t}\n\t\t}\n\n\t\tfunction findBestIntersection(inter, exclude) {\n\t\t\tif (!inter._next)\n\t\t\t\treturn inter;\n\t\t\twhile (inter) {\n\t\t\t\tvar seg = inter._segment,\n\t\t\t\t\tnextSeg = seg.getNext(),\n\t\t\t\t\tnextInter = nextSeg && nextSeg._intersection;\n\t\t\t\tif (seg !== exclude && (isStart(seg) || isStart(nextSeg)\n\t\t\t\t\t|| nextSeg && !seg._visited && !nextSeg._visited\n\t\t\t\t\t&& (!operator || isValid(seg) && (isValid(nextSeg)\n\t\t\t\t\t\t|| nextInter && isValid(nextInter._segment)))\n\t\t\t\t\t))\n\t\t\t\t\treturn inter;\n\t\t\t\tinter = inter._next;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\tsegments.sort(function(seg1, seg2) {\n\t\t\tvar inter1 = seg1._intersection,\n\t\t\t\tinter2 = seg2._intersection,\n\t\t\t\tover1 = !!(inter1 && inter1._overlap),\n\t\t\t\tover2 = !!(inter2 && inter2._overlap),\n\t\t\t\tpath1 = seg1._path,\n\t\t\t\tpath2 = seg2._path;\n\t\t\treturn over1 ^ over2\n\t\t\t\t\t? over1 ? 1 : -1\n\t\t\t\t\t: inter1 ^ inter2\n\t\t\t\t\t\t? inter1 ? 1 : -1\n\t\t\t\t\t\t: path1 !== path2\n\t\t\t\t\t\t\t? path1._id - path2._id\n\t\t\t\t\t\t\t: seg1._index - seg2._index;\n\t\t});\n\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar path = null,\n\t\t\t\tfinished = false,\n\t\t\t\tseg = segments[i],\n\t\t\t\tinter = seg._intersection,\n\t\t\t\thandleIn;\n\t\t\tif (!seg._visited && seg._path._overlapsOnly) {\n\t\t\t\tvar path1 = seg._path,\n\t\t\t\t\tpath2 = inter._segment._path;\n\t\t\t\tif (path1.compare(path2)) {\n\t\t\t\t\tif ((operator.unite || operator.intersect)\n\t\t\t\t\t\t\t&& path1.getArea()) {\n\t\t\t\t\t\tpaths.push(path1.clone(false));\n\t\t\t\t\t}\n\t\t\t\t\tvisitPath(path1);\n\t\t\t\t\tvisitPath(path2);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isValid(seg, true))\n\t\t\t\tcontinue;\n\t\t\tstart = otherStart = null;\n\t\t\twhile (true) {\n\t\t\t\tinter = inter && findBestIntersection(inter, seg) || inter;\n\t\t\t\tvar other = inter && inter._segment;\n\t\t\t\tif (isStart(seg)) {\n\t\t\t\t\tfinished = true;\n\t\t\t\t} else if (other) {\n\t\t\t\t\tif (isStart(other)) {\n\t\t\t\t\t\tfinished = true;\n\t\t\t\t\t\tseg = other;\n\t\t\t\t\t} else if (isValid(other, isValid(seg, true))) {\n\t\t\t\t\t\tif (operator\n\t\t\t\t\t\t\t\t&& (operator.intersect || operator.subtract)) {\n\t\t\t\t\t\t\tseg._visited = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tseg = other;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (finished || seg._visited) {\n\t\t\t\t\tseg._visited = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (seg._path._validOverlapsOnly && !isValid(seg))\n\t\t\t\t\tbreak;\n\t\t\t\tif (!path) {\n\t\t\t\t\tpath = new Path(Item.NO_INSERT);\n\t\t\t\t\tstart = seg;\n\t\t\t\t\totherStart = other;\n\t\t\t\t}\n\t\t\t\tvar next = seg.getNext();\n\t\t\t\tpath.add(new Segment(seg._point, handleIn,\n\t\t\t\t\t\tnext && seg._handleOut));\n\t\t\t\tseg._visited = true;\n\t\t\t\tseg = next || seg._path.getFirstSegment();\n\t\t\t\thandleIn = next && next._handleIn;\n\t\t\t\tinter = seg._intersection;\n\t\t\t}\n\t\t\tif (finished) {\n\t\t\t\tpath.firstSegment.setHandleIn(handleIn);\n\t\t\t\tpath.setClosed(true);\n\t\t\t} else if (path) {\n\t\t\t\tvar area = path.getArea(true);\n\t\t\t\tif (abs(area) >= 1e-7) {\n\t\t\t\t\tconsole.error('Boolean operation resulted in open path',\n\t\t\t\t\t\t\t'segments =', path._segments.length,\n\t\t\t\t\t\t\t'length =', path.getLength(),\n\t\t\t\t\t\t\t'area=', area);\n\t\t\t\t}\n\t\t\t\tpath = null;\n\t\t\t}\n\t\t\tif (path && (path._segments.length > 8\n\t\t\t\t\t|| !Numerical.isZero(path.getArea()))) {\n\t\t\t\tpaths.push(path);\n\t\t\t\tpath = null;\n\t\t\t}\n\t\t}\n\t\treturn paths;\n\t}\n\n\treturn {\n\t\t_getWinding: function(point, dir) {\n\t\t\treturn getWinding(point, this.getCurves(), dir);\n\t\t},\n\n\t\tunite: function(path) {\n\t\t\treturn computeBoolean(this, path, 'unite');\n\t\t},\n\n\t\tintersect: function(path) {\n\t\t\treturn computeBoolean(this, path, 'intersect');\n\t\t},\n\n\t\tsubtract: function(path) {\n\t\t\treturn computeBoolean(this, path, 'subtract');\n\t\t},\n\n\t\texclude: function(path) {\n\t\t\treturn computeBoolean(this, path, 'exclude');\n\t\t},\n\n\t\tdivide: function(path) {\n\t\t\treturn createResult(Group, [this.subtract(path),\n\t\t\t\t\tthis.intersect(path)], true, this, path);\n\t\t},\n\n\t\tresolveCrossings: function() {\n\t\t\tvar children = this._children,\n\t\t\t\tpaths = children || [this];\n\n\t\t\tfunction hasOverlap(seg) {\n\t\t\t\tvar inter = seg && seg._intersection;\n\t\t\t\treturn inter && inter._overlap;\n\t\t\t}\n\n\t\t\tvar hasOverlaps = false,\n\t\t\t\thasCrossings = false,\n\t\t\t\tintersections = this.getIntersections(null, function(inter) {\n\t\t\t\t\treturn inter._overlap && (hasOverlaps = true) ||\n\t\t\t\t\t\t\tinter.isCrossing() && (hasCrossings = true);\n\t\t\t\t});\n\t\t\tintersections = CurveLocation.expand(intersections);\n\t\t\tif (hasOverlaps) {\n\t\t\t\tvar overlaps = divideLocations(intersections, function(inter) {\n\t\t\t\t\treturn inter._overlap;\n\t\t\t\t});\n\t\t\t\tfor (var i = overlaps.length - 1; i >= 0; i--) {\n\t\t\t\t\tvar seg = overlaps[i]._segment,\n\t\t\t\t\t\tprev = seg.getPrevious(),\n\t\t\t\t\t\tnext = seg.getNext();\n\t\t\t\t\tif (seg._path && hasOverlap(prev) && hasOverlap(next)) {\n\t\t\t\t\t\tseg.remove();\n\t\t\t\t\t\tprev._handleOut._set(0, 0);\n\t\t\t\t\t\tnext._handleIn._set(0, 0);\n\t\t\t\t\t\tvar curve = prev.getCurve();\n\t\t\t\t\t\tif (curve.isStraight() && curve.getLength() === 0) {\n\t\t\t\t\t\t\tnext._handleIn.set(prev._handleIn);\n\t\t\t\t\t\t\tprev.remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hasCrossings) {\n\t\t\t\tdivideLocations(intersections, hasOverlaps && function(inter) {\n\t\t\t\t\tvar curve1 = inter.getCurve(),\n\t\t\t\t\t\tcurve2 = inter._intersection._curve,\n\t\t\t\t\t\tseg = inter._segment;\n\t\t\t\t\tif (curve1 && curve2 && curve1._path && curve2._path) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else if (seg) {\n\t\t\t\t\t\tseg._intersection = null;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tpaths = tracePaths(Base.each(paths, function(path) {\n\t\t\t\t\tthis.push.apply(this, path._segments);\n\t\t\t\t}, []));\n\t\t\t}\n\t\t\tvar length = paths.length,\n\t\t\t\titem;\n\t\t\tif (length > 1 && children) {\n\t\t\t\tif (paths !== children)\n\t\t\t\t\tthis.setChildren(paths);\n\t\t\t\titem = this;\n\t\t\t} else if (length === 1 && !children) {\n\t\t\t\tif (paths[0] !== this)\n\t\t\t\t\tthis.setSegments(paths[0].removeSegments());\n\t\t\t\titem = this;\n\t\t\t}\n\t\t\tif (!item) {\n\t\t\t\titem = new CompoundPath(Item.NO_INSERT);\n\t\t\t\titem.addChildren(paths);\n\t\t\t\titem = item.reduce();\n\t\t\t\titem.copyAttributes(this);\n\t\t\t\tthis.replaceWith(item);\n\t\t\t}\n\t\t\treturn item;\n\t\t},\n\n\t\treorient: function(nonZero) {\n\t\t\tvar children = this._children,\n\t\t\t\tlength = children && children.length;\n\t\t\tif (length > 1) {\n\t\t\t\tvar lookup = Base.each(children, function(path, i) {\n\t\t\t\t\t\tthis[path._id] = {\n\t\t\t\t\t\t\twinding: path.isClockwise() ? 1 : -1,\n\t\t\t\t\t\t\tindex: i\n\t\t\t\t\t\t};\n\t\t\t\t\t}, {}),\n\t\t\t\t\tsorted = this.removeChildren().sort(function (a, b) {\n\t\t\t\t\t\treturn abs(b.getArea()) - abs(a.getArea());\n\t\t\t\t\t}),\n\t\t\t\t\tfirst = sorted[0],\n\t\t\t\t\tpaths = [];\n\t\t\t\tpaths[lookup[first._id].index] = first;\n\t\t\t\tfor (var i1 = 1; i1 < length; i1++) {\n\t\t\t\t\tvar path1 = sorted[i1],\n\t\t\t\t\t\tentry1 = lookup[path1._id],\n\t\t\t\t\t\tpoint = path1.getInteriorPoint(),\n\t\t\t\t\t\tisContained = false,\n\t\t\t\t\t\tcontainer = null,\n\t\t\t\t\t\texclude = false;\n\t\t\t\t\tfor (var i2 = i1 - 1; i2 >= 0 && !container; i2--) {\n\t\t\t\t\t\tvar path2 = sorted[i2];\n\t\t\t\t\t\tif (path2.contains(point)) {\n\t\t\t\t\t\t\tvar entry2 = lookup[path2._id];\n\t\t\t\t\t\t\tif (nonZero && !isContained) {\n\t\t\t\t\t\t\t\tentry1.winding += entry2.winding;\n\t\t\t\t\t\t\t\tif (entry1.winding && entry2.winding) {\n\t\t\t\t\t\t\t\t\texclude = entry1.exclude = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tisContained = true;\n\t\t\t\t\t\t\tcontainer = !entry2.exclude && path2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!exclude) {\n\t\t\t\t\t\tpath1.setClockwise(container\n\t\t\t\t\t\t\t\t? !container.isClockwise()\n\t\t\t\t\t\t\t\t: first.isClockwise());\n\t\t\t\t\t\tpaths[entry1.index] = path1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.setChildren(paths);\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tgetInteriorPoint: function() {\n\t\t\tvar bounds = this.getBounds(),\n\t\t\t\tpoint = bounds.getCenter(true);\n\t\t\tif (!this.contains(point)) {\n\t\t\t\tvar curves = this.getCurves(),\n\t\t\t\t\ty = point.y,\n\t\t\t\t\tintercepts = [],\n\t\t\t\t\troots = [];\n\t\t\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\t\t\tvar v = curves[i].getValues(),\n\t\t\t\t\t\to0 = v[1],\n\t\t\t\t\t\to1 = v[3],\n\t\t\t\t\t\to2 = v[5],\n\t\t\t\t\t\to3 = v[7];\n\t\t\t\t\tif (y >= min(o0, o1, o2, o3) && y <= max(o0, o1, o2, o3)) {\n\t\t\t\t\t\tvar monoCurves = Curve.getMonoCurves(v);\n\t\t\t\t\t\tfor (var j = 0, m = monoCurves.length; j < m; j++) {\n\t\t\t\t\t\t\tvar mv = monoCurves[j],\n\t\t\t\t\t\t\t\tmo0 = mv[1],\n\t\t\t\t\t\t\t\tmo3 = mv[7];\n\t\t\t\t\t\t\tif ((mo0 !== mo3) &&\n\t\t\t\t\t\t\t\t(y >= mo0 && y <= mo3 || y >= mo3 && y <= mo0)){\n\t\t\t\t\t\t\t\tvar x = y === mo0 ? mv[0]\n\t\t\t\t\t\t\t\t\t: y === mo3 ? mv[6]\n\t\t\t\t\t\t\t\t\t: Curve.solveCubic(mv, 1, y, roots, 0, 1)\n\t\t\t\t\t\t\t\t\t\t=== 1\n\t\t\t\t\t\t\t\t\t\t? Curve.getPoint(mv, roots[0]).x\n\t\t\t\t\t\t\t\t\t\t: (mv[0] + mv[6]) / 2;\n\t\t\t\t\t\t\t\tintercepts.push(x);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (intercepts.length > 1) {\n\t\t\t\t\tintercepts.sort(function(a, b) { return a - b; });\n\t\t\t\t\tpoint.x = (intercepts[0] + intercepts[1]) / 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn point;\n\t\t}\n\t};\n});\n\nvar PathIterator = Base.extend({\n\t_class: 'PathIterator',\n\n\tinitialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) {\n\t\tvar curves = [],\n\t\t\tparts = [],\n\t\t\tlength = 0,\n\t\t\tminSpan = 1 / (maxRecursion || 32),\n\t\t\tsegments = path._segments,\n\t\t\tsegment1 = segments[0],\n\t\t\tsegment2;\n\n\t\tfunction addCurve(segment1, segment2) {\n\t\t\tvar curve = Curve.getValues(segment1, segment2, matrix);\n\t\t\tcurves.push(curve);\n\t\t\tcomputeParts(curve, segment1._index, 0, 1);\n\t\t}\n\n\t\tfunction computeParts(curve, index, t1, t2) {\n\t\t\tif ((t2 - t1) > minSpan\n\t\t\t\t\t&& !(ignoreStraight && Curve.isStraight(curve))\n\t\t\t\t\t&& !Curve.isFlatEnough(curve, flatness || 0.25)) {\n\t\t\t\tvar halves = Curve.subdivide(curve, 0.5),\n\t\t\t\t\ttMid = (t1 + t2) / 2;\n\t\t\t\tcomputeParts(halves[0], index, t1, tMid);\n\t\t\t\tcomputeParts(halves[1], index, tMid, t2);\n\t\t\t} else {\n\t\t\t\tvar dx = curve[6] - curve[0],\n\t\t\t\t\tdy = curve[7] - curve[1],\n\t\t\t\t\tdist = Math.sqrt(dx * dx + dy * dy);\n\t\t\t\tif (dist > 0) {\n\t\t\t\t\tlength += dist;\n\t\t\t\t\tparts.push({\n\t\t\t\t\t\toffset: length,\n\t\t\t\t\t\tcurve: curve,\n\t\t\t\t\t\tindex: index,\n\t\t\t\t\t\ttime: t2,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 1, l = segments.length; i < l; i++) {\n\t\t\tsegment2 = segments[i];\n\t\t\taddCurve(segment1, segment2);\n\t\t\tsegment1 = segment2;\n\t\t}\n\t\tif (path._closed)\n\t\t\taddCurve(segment2, segments[0]);\n\t\tthis.curves = curves;\n\t\tthis.parts = parts;\n\t\tthis.length = length;\n\t\tthis.index = 0;\n\t},\n\n\t_get: function(offset) {\n\t\tvar parts = this.parts,\n\t\t\tlength = parts.length,\n\t\t\tstart,\n\t\t\ti, j = this.index;\n\t\tfor (;;) {\n\t\t\ti = j;\n\t\t\tif (!j || parts[--j].offset < offset)\n\t\t\t\tbreak;\n\t\t}\n\t\tfor (; i < length; i++) {\n\t\t\tvar part = parts[i];\n\t\t\tif (part.offset >= offset) {\n\t\t\t\tthis.index = i;\n\t\t\t\tvar prev = parts[i - 1],\n\t\t\t\t\tprevTime = prev && prev.index === part.index ? prev.time : 0,\n\t\t\t\t\tprevOffset = prev ? prev.offset : 0;\n\t\t\t\treturn {\n\t\t\t\t\tindex: part.index,\n\t\t\t\t\ttime: prevTime + (part.time - prevTime)\n\t\t\t\t\t\t* (offset - prevOffset) / (part.offset - prevOffset)\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tindex: parts[length - 1].index,\n\t\t\ttime: 1\n\t\t};\n\t},\n\n\tdrawPart: function(ctx, from, to) {\n\t\tvar start = this._get(from),\n\t\t\tend = this._get(to);\n\t\tfor (var i = start.index, l = end.index; i <= l; i++) {\n\t\t\tvar curve = Curve.getPart(this.curves[i],\n\t\t\t\t\ti === start.index ? start.time : 0,\n\t\t\t\t\ti === end.index ? end.time : 1);\n\t\t\tif (i === start.index)\n\t\t\t\tctx.moveTo(curve[0], curve[1]);\n\t\t\tctx.bezierCurveTo.apply(ctx, curve.slice(2));\n\t\t}\n\t}\n}, Base.each(Curve._evaluateMethods,\n\tfunction(name) {\n\t\tthis[name + 'At'] = function(offset) {\n\t\t\tvar param = this._get(offset);\n\t\t\treturn Curve[name](this.curves[param.index], param.time);\n\t\t};\n\t}, {})\n);\n\nvar PathFitter = Base.extend({\n\tinitialize: function(path) {\n\t\tvar points = this.points = [],\n\t\t\tsegments = path._segments,\n\t\t\tclosed = path._closed;\n\t\tfor (var i = 0, prev, l = segments.length; i < l; i++) {\n\t\t\tvar point = segments[i].point;\n\t\t\tif (!prev || !prev.equals(point)) {\n\t\t\t\tpoints.push(prev = point.clone());\n\t\t\t}\n\t\t}\n\t\tif (closed) {\n\t\t\tpoints.unshift(points[points.length - 1]);\n\t\t\tpoints.push(points[1]);\n\t\t}\n\t\tthis.closed = closed;\n\t},\n\n\tfit: function(error) {\n\t\tvar points = this.points,\n\t\t\tlength = points.length,\n\t\t\tsegments = null;\n\t\tif (length > 0) {\n\t\t\tsegments = [new Segment(points[0])];\n\t\t\tif (length > 1) {\n\t\t\t\tthis.fitCubic(segments, error, 0, length - 1,\n\t\t\t\t\t\tpoints[1].subtract(points[0]),\n\t\t\t\t\t\tpoints[length - 2].subtract(points[length - 1]));\n\t\t\t\tif (this.closed) {\n\t\t\t\t\tsegments.shift();\n\t\t\t\t\tsegments.pop();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn segments;\n\t},\n\n\tfitCubic: function(segments, error, first, last, tan1, tan2) {\n\t\tvar points = this.points;\n\t\tif (last - first === 1) {\n\t\t\tvar pt1 = points[first],\n\t\t\t\tpt2 = points[last],\n\t\t\t\tdist = pt1.getDistance(pt2) / 3;\n\t\t\tthis.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),\n\t\t\t\t\tpt2.add(tan2.normalize(dist)), pt2]);\n\t\t\treturn;\n\t\t}\n\t\tvar uPrime = this.chordLengthParameterize(first, last),\n\t\t\tmaxError = Math.max(error, error * error),\n\t\t\tsplit,\n\t\t\tparametersInOrder = true;\n\t\tfor (var i = 0; i <= 4; i++) {\n\t\t\tvar curve = this.generateBezier(first, last, uPrime, tan1, tan2);\n\t\t\tvar max = this.findMaxError(first, last, curve, uPrime);\n\t\t\tif (max.error < error && parametersInOrder) {\n\t\t\t\tthis.addCurve(segments, curve);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsplit = max.index;\n\t\t\tif (max.error >= maxError)\n\t\t\t\tbreak;\n\t\t\tparametersInOrder = this.reparameterize(first, last, uPrime, curve);\n\t\t\tmaxError = max.error;\n\t\t}\n\t\tvar tanCenter = points[split - 1].subtract(points[split + 1]);\n\t\tthis.fitCubic(segments, error, first, split, tan1, tanCenter);\n\t\tthis.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);\n\t},\n\n\taddCurve: function(segments, curve) {\n\t\tvar prev = segments[segments.length - 1];\n\t\tprev.setHandleOut(curve[1].subtract(curve[0]));\n\t\tsegments.push(new Segment(curve[3], curve[2].subtract(curve[3])));\n\t},\n\n\tgenerateBezier: function(first, last, uPrime, tan1, tan2) {\n\t\tvar epsilon = 1e-12,\n\t\t\tabs = Math.abs,\n\t\t\tpoints = this.points,\n\t\t\tpt1 = points[first],\n\t\t\tpt2 = points[last],\n\t\t\tC = [[0, 0], [0, 0]],\n\t\t\tX = [0, 0];\n\n\t\tfor (var i = 0, l = last - first + 1; i < l; i++) {\n\t\t\tvar u = uPrime[i],\n\t\t\t\tt = 1 - u,\n\t\t\t\tb = 3 * u * t,\n\t\t\t\tb0 = t * t * t,\n\t\t\t\tb1 = b * t,\n\t\t\t\tb2 = b * u,\n\t\t\t\tb3 = u * u * u,\n\t\t\t\ta1 = tan1.normalize(b1),\n\t\t\t\ta2 = tan2.normalize(b2),\n\t\t\t\ttmp = points[first + i]\n\t\t\t\t\t.subtract(pt1.multiply(b0 + b1))\n\t\t\t\t\t.subtract(pt2.multiply(b2 + b3));\n\t\t\tC[0][0] += a1.dot(a1);\n\t\t\tC[0][1] += a1.dot(a2);\n\t\t\tC[1][0] = C[0][1];\n\t\t\tC[1][1] += a2.dot(a2);\n\t\t\tX[0] += a1.dot(tmp);\n\t\t\tX[1] += a2.dot(tmp);\n\t\t}\n\n\t\tvar detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],\n\t\t\talpha1, alpha2;\n\t\tif (abs(detC0C1) > epsilon) {\n\t\t\tvar detC0X = C[0][0] * X[1] - C[1][0] * X[0],\n\t\t\t\tdetXC1 = X[0] * C[1][1] - X[1] * C[0][1];\n\t\t\talpha1 = detXC1 / detC0C1;\n\t\t\talpha2 = detC0X / detC0C1;\n\t\t} else {\n\t\t\tvar c0 = C[0][0] + C[0][1],\n\t\t\t\tc1 = C[1][0] + C[1][1];\n\t\t\tif (abs(c0) > epsilon) {\n\t\t\t\talpha1 = alpha2 = X[0] / c0;\n\t\t\t} else if (abs(c1) > epsilon) {\n\t\t\t\talpha1 = alpha2 = X[1] / c1;\n\t\t\t} else {\n\t\t\t\talpha1 = alpha2 = 0;\n\t\t\t}\n\t\t}\n\n\t\tvar segLength = pt2.getDistance(pt1),\n\t\t\teps = epsilon * segLength,\n\t\t\thandle1,\n\t\t\thandle2;\n\t\tif (alpha1 < eps || alpha2 < eps) {\n\t\t\talpha1 = alpha2 = segLength / 3;\n\t\t} else {\n\t\t\tvar line = pt2.subtract(pt1);\n\t\t\thandle1 = tan1.normalize(alpha1);\n\t\t\thandle2 = tan2.normalize(alpha2);\n\t\t\tif (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {\n\t\t\t\talpha1 = alpha2 = segLength / 3;\n\t\t\t\thandle1 = handle2 = null;\n\t\t\t}\n\t\t}\n\n\t\treturn [pt1,\n\t\t\t\tpt1.add(handle1 || tan1.normalize(alpha1)),\n\t\t\t\tpt2.add(handle2 || tan2.normalize(alpha2)),\n\t\t\t\tpt2];\n\t},\n\n\treparameterize: function(first, last, u, curve) {\n\t\tfor (var i = first; i <= last; i++) {\n\t\t\tu[i - first] = this.findRoot(curve, this.points[i], u[i - first]);\n\t\t}\n\t\tfor (var i = 1, l = u.length; i < l; i++) {\n\t\t\tif (u[i] <= u[i - 1])\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tfindRoot: function(curve, point, u) {\n\t\tvar curve1 = [],\n\t\t\tcurve2 = [];\n\t\tfor (var i = 0; i <= 2; i++) {\n\t\t\tcurve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);\n\t\t}\n\t\tfor (var i = 0; i <= 1; i++) {\n\t\t\tcurve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);\n\t\t}\n\t\tvar pt = this.evaluate(3, curve, u),\n\t\t\tpt1 = this.evaluate(2, curve1, u),\n\t\t\tpt2 = this.evaluate(1, curve2, u),\n\t\t\tdiff = pt.subtract(point),\n\t\t\tdf = pt1.dot(pt1) + diff.dot(pt2);\n\t\tif (Math.abs(df) < 1e-6)\n\t\t\treturn u;\n\t\treturn u - diff.dot(pt1) / df;\n\t},\n\n\tevaluate: function(degree, curve, t) {\n\t\tvar tmp = curve.slice();\n\t\tfor (var i = 1; i <= degree; i++) {\n\t\t\tfor (var j = 0; j <= degree - i; j++) {\n\t\t\t\ttmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));\n\t\t\t}\n\t\t}\n\t\treturn tmp[0];\n\t},\n\n\tchordLengthParameterize: function(first, last) {\n\t\tvar u = [0];\n\t\tfor (var i = first + 1; i <= last; i++) {\n\t\t\tu[i - first] = u[i - first - 1]\n\t\t\t\t\t+ this.points[i].getDistance(this.points[i - 1]);\n\t\t}\n\t\tfor (var i = 1, m = last - first; i <= m; i++) {\n\t\t\tu[i] /= u[m];\n\t\t}\n\t\treturn u;\n\t},\n\n\tfindMaxError: function(first, last, curve, u) {\n\t\tvar index = Math.floor((last - first + 1) / 2),\n\t\t\tmaxDist = 0;\n\t\tfor (var i = first + 1; i < last; i++) {\n\t\t\tvar P = this.evaluate(3, curve, u[i - first]);\n\t\t\tvar v = P.subtract(this.points[i]);\n\t\t\tvar dist = v.x * v.x + v.y * v.y;\n\t\t\tif (dist >= maxDist) {\n\t\t\t\tmaxDist = dist;\n\t\t\t\tindex = i;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\terror: maxDist,\n\t\t\tindex: index\n\t\t};\n\t}\n});\n\nvar TextItem = Item.extend({\n\t_class: 'TextItem',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_serializeFields: {\n\t\tcontent: null\n\t},\n\t_boundsOptions: { stroke: false, handle: false },\n\n\tinitialize: function TextItem(arg) {\n\t\tthis._content = '';\n\t\tthis._lines = [];\n\t\tvar hasProps = arg && Base.isPlainObject(arg)\n\t\t\t\t&& arg.x === undefined && arg.y === undefined;\n\t\tthis._initialize(hasProps && arg, !hasProps && Point.read(arguments));\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._content === item._content;\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setContent(source._content);\n\t},\n\n\tgetContent: function() {\n\t\treturn this._content;\n\t},\n\n\tsetContent: function(content) {\n\t\tthis._content = '' + content;\n\t\tthis._lines = this._content.split(/\\r\\n|\\n|\\r/mg);\n\t\tthis._changed(265);\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._content;\n\t},\n\n\tgetCharacterStyle: '#getStyle',\n\tsetCharacterStyle: '#setStyle',\n\n\tgetParagraphStyle: '#getStyle',\n\tsetParagraphStyle: '#setStyle'\n});\n\nvar PointText = TextItem.extend({\n\t_class: 'PointText',\n\n\tinitialize: function PointText() {\n\t\tTextItem.apply(this, arguments);\n\t},\n\n\tgetPoint: function() {\n\t\tvar point = this._matrix.getTranslation();\n\t\treturn new LinkedPoint(point.x, point.y, this, 'setPoint');\n\t},\n\n\tsetPoint: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.translate(point.subtract(this._matrix.getTranslation()));\n\t},\n\n\t_draw: function(ctx, param, viewMatrix) {\n\t\tif (!this._content)\n\t\t\treturn;\n\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\tvar lines = this._lines,\n\t\t\tstyle = this._style,\n\t\t\thasFill = style.hasFill(),\n\t\t\thasStroke = style.hasStroke(),\n\t\t\tleading = style.getLeading(),\n\t\t\tshadowColor = ctx.shadowColor;\n\t\tctx.font = style.getFontStyle();\n\t\tctx.textAlign = style.getJustification();\n\t\tfor (var i = 0, l = lines.length; i < l; i++) {\n\t\t\tctx.shadowColor = shadowColor;\n\t\t\tvar line = lines[i];\n\t\t\tif (hasFill) {\n\t\t\t\tctx.fillText(line, 0, 0);\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (hasStroke)\n\t\t\t\tctx.strokeText(line, 0, 0);\n\t\t\tctx.translate(0, leading);\n\t\t}\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar style = this._style,\n\t\t\tlines = this._lines,\n\t\t\tnumLines = lines.length,\n\t\t\tjustification = style.getJustification(),\n\t\t\tleading = style.getLeading(),\n\t\t\twidth = this.getView().getTextWidth(style.getFontStyle(), lines),\n\t\t\tx = 0;\n\t\tif (justification !== 'left')\n\t\t\tx -= width / (justification === 'center' ? 2: 1);\n\t\tvar bounds = new Rectangle(x,\n\t\t\t\t\tnumLines ? - 0.75 * leading : 0,\n\t\t\t\t\twidth, numLines * leading);\n\t\treturn matrix ? matrix._transformBounds(bounds, bounds) : bounds;\n\t}\n});\n\nvar Color = Base.extend(new function() {\n\tvar types = {\n\t\tgray: ['gray'],\n\t\trgb: ['red', 'green', 'blue'],\n\t\thsb: ['hue', 'saturation', 'brightness'],\n\t\thsl: ['hue', 'saturation', 'lightness'],\n\t\tgradient: ['gradient', 'origin', 'destination', 'highlight']\n\t};\n\n\tvar componentParsers = {},\n\t\tcolorCache = {},\n\t\tcolorCtx;\n\n\tfunction fromCSS(string) {\n\t\tvar match = string.match(/^#(\\w{1,2})(\\w{1,2})(\\w{1,2})$/),\n\t\t\tcomponents;\n\t\tif (match) {\n\t\t\tcomponents = [0, 0, 0];\n\t\t\tfor (var i = 0; i < 3; i++) {\n\t\t\t\tvar value = match[i + 1];\n\t\t\t\tcomponents[i] = parseInt(value.length == 1\n\t\t\t\t\t\t? value + value : value, 16) / 255;\n\t\t\t}\n\t\t} else if (match = string.match(/^rgba?\\((.*)\\)$/)) {\n\t\t\tcomponents = match[1].split(',');\n\t\t\tfor (var i = 0, l = components.length; i < l; i++) {\n\t\t\t\tvar value = +components[i];\n\t\t\t\tcomponents[i] = i < 3 ? value / 255 : value;\n\t\t\t}\n\t\t} else if (window) {\n\t\t\tvar cached = colorCache[string];\n\t\t\tif (!cached) {\n\t\t\t\tif (!colorCtx) {\n\t\t\t\t\tcolorCtx = CanvasProvider.getContext(1, 1);\n\t\t\t\t\tcolorCtx.globalCompositeOperation = 'copy';\n\t\t\t\t}\n\t\t\t\tcolorCtx.fillStyle = 'rgba(0,0,0,0)';\n\t\t\t\tcolorCtx.fillStyle = string;\n\t\t\t\tcolorCtx.fillRect(0, 0, 1, 1);\n\t\t\t\tvar data = colorCtx.getImageData(0, 0, 1, 1).data;\n\t\t\t\tcached = colorCache[string] = [\n\t\t\t\t\tdata[0] / 255,\n\t\t\t\t\tdata[1] / 255,\n\t\t\t\t\tdata[2] / 255\n\t\t\t\t];\n\t\t\t}\n\t\t\tcomponents = cached.slice();\n\t\t} else {\n\t\t\tcomponents = [0, 0, 0];\n\t\t}\n\t\treturn components;\n\t}\n\n\tvar hsbIndices = [\n\t\t[0, 3, 1],\n\t\t[2, 0, 1],\n\t\t[1, 0, 3],\n\t\t[1, 2, 0],\n\t\t[3, 1, 0],\n\t\t[0, 1, 2]\n\t];\n\n\tvar converters = {\n\t\t'rgb-hsb': function(r, g, b) {\n\t\t\tvar max = Math.max(r, g, b),\n\t\t\t\tmin = Math.min(r, g, b),\n\t\t\t\tdelta = max - min,\n\t\t\t\th = delta === 0 ? 0\n\t\t\t\t\t: ( max == r ? (g - b) / delta + (g < b ? 6 : 0)\n\t\t\t\t\t\t: max == g ? (b - r) / delta + 2\n\t\t\t\t\t\t: (r - g) / delta + 4) * 60;\n\t\t\treturn [h, max === 0 ? 0 : delta / max, max];\n\t\t},\n\n\t\t'hsb-rgb': function(h, s, b) {\n\t\t\th = (((h / 60) % 6) + 6) % 6;\n\t\t\tvar i = Math.floor(h),\n\t\t\t\tf = h - i,\n\t\t\t\ti = hsbIndices[i],\n\t\t\t\tv = [\n\t\t\t\t\tb,\n\t\t\t\t\tb * (1 - s),\n\t\t\t\t\tb * (1 - s * f),\n\t\t\t\t\tb * (1 - s * (1 - f))\n\t\t\t\t];\n\t\t\treturn [v[i[0]], v[i[1]], v[i[2]]];\n\t\t},\n\n\t\t'rgb-hsl': function(r, g, b) {\n\t\t\tvar max = Math.max(r, g, b),\n\t\t\t\tmin = Math.min(r, g, b),\n\t\t\t\tdelta = max - min,\n\t\t\t\tachromatic = delta === 0,\n\t\t\t\th = achromatic ? 0\n\t\t\t\t\t: ( max == r ? (g - b) / delta + (g < b ? 6 : 0)\n\t\t\t\t\t\t: max == g ? (b - r) / delta + 2\n\t\t\t\t\t\t: (r - g) / delta + 4) * 60,\n\t\t\t\tl = (max + min) / 2,\n\t\t\t\ts = achromatic ? 0 : l < 0.5\n\t\t\t\t\t\t? delta / (max + min)\n\t\t\t\t\t\t: delta / (2 - max - min);\n\t\t\treturn [h, s, l];\n\t\t},\n\n\t\t'hsl-rgb': function(h, s, l) {\n\t\t\th = (((h / 360) % 1) + 1) % 1;\n\t\t\tif (s === 0)\n\t\t\t\treturn [l, l, l];\n\t\t\tvar t3s = [ h + 1 / 3, h, h - 1 / 3 ],\n\t\t\t\tt2 = l < 0.5 ? l * (1 + s) : l + s - l * s,\n\t\t\t\tt1 = 2 * l - t2,\n\t\t\t\tc = [];\n\t\t\tfor (var i = 0; i < 3; i++) {\n\t\t\t\tvar t3 = t3s[i];\n\t\t\t\tif (t3 < 0) t3 += 1;\n\t\t\t\tif (t3 > 1) t3 -= 1;\n\t\t\t\tc[i] = 6 * t3 < 1\n\t\t\t\t\t? t1 + (t2 - t1) * 6 * t3\n\t\t\t\t\t: 2 * t3 < 1\n\t\t\t\t\t\t? t2\n\t\t\t\t\t\t: 3 * t3 < 2\n\t\t\t\t\t\t\t? t1 + (t2 - t1) * ((2 / 3) - t3) * 6\n\t\t\t\t\t\t\t: t1;\n\t\t\t}\n\t\t\treturn c;\n\t\t},\n\n\t\t'rgb-gray': function(r, g, b) {\n\t\t\treturn [r * 0.2989 + g * 0.587 + b * 0.114];\n\t\t},\n\n\t\t'gray-rgb': function(g) {\n\t\t\treturn [g, g, g];\n\t\t},\n\n\t\t'gray-hsb': function(g) {\n\t\t\treturn [0, 0, g];\n\t\t},\n\n\t\t'gray-hsl': function(g) {\n\t\t\treturn [0, 0, g];\n\t\t},\n\n\t\t'gradient-rgb': function() {\n\t\t\treturn [];\n\t\t},\n\n\t\t'rgb-gradient': function() {\n\t\t\treturn [];\n\t\t}\n\n\t};\n\n\treturn Base.each(types, function(properties, type) {\n\t\tcomponentParsers[type] = [];\n\t\tBase.each(properties, function(name, index) {\n\t\t\tvar part = Base.capitalize(name),\n\t\t\t\thasOverlap = /^(hue|saturation)$/.test(name),\n\t\t\t\tparser = componentParsers[type][index] = name === 'gradient'\n\t\t\t\t\t? function(value) {\n\t\t\t\t\t\tvar current = this._components[0];\n\t\t\t\t\t\tvalue = Gradient.read(Array.isArray(value) ? value\n\t\t\t\t\t\t\t\t: arguments, 0, { readNull: true });\n\t\t\t\t\t\tif (current !== value) {\n\t\t\t\t\t\t\tif (current)\n\t\t\t\t\t\t\t\tcurrent._removeOwner(this);\n\t\t\t\t\t\t\tif (value)\n\t\t\t\t\t\t\t\tvalue._addOwner(this);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t\t: type === 'gradient'\n\t\t\t\t\t\t? function() {\n\t\t\t\t\t\t\treturn Point.read(arguments, 0, {\n\t\t\t\t\t\t\t\t\treadNull: name === 'highlight',\n\t\t\t\t\t\t\t\t\tclone: true\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\t: function(value) {\n\t\t\t\t\t\t\treturn value == null || isNaN(value) ? 0 : value;\n\t\t\t\t\t\t};\n\n\t\t\tthis['get' + part] = function() {\n\t\t\t\treturn this._type === type\n\t\t\t\t\t|| hasOverlap && /^hs[bl]$/.test(this._type)\n\t\t\t\t\t\t? this._components[index]\n\t\t\t\t\t\t: this._convert(type)[index];\n\t\t\t};\n\n\t\t\tthis['set' + part] = function(value) {\n\t\t\t\tif (this._type !== type\n\t\t\t\t\t\t&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {\n\t\t\t\t\tthis._components = this._convert(type);\n\t\t\t\t\tthis._properties = types[type];\n\t\t\t\t\tthis._type = type;\n\t\t\t\t}\n\t\t\t\tthis._components[index] = parser.call(this, value);\n\t\t\t\tthis._changed();\n\t\t\t};\n\t\t}, this);\n\t}, {\n\t\t_class: 'Color',\n\t\t_readIndex: true,\n\n\t\tinitialize: function Color(arg) {\n\t\t\tvar args = arguments,\n\t\t\t\treading = this.__read,\n\t\t\t\tread = 0,\n\t\t\t\ttype,\n\t\t\t\tcomponents,\n\t\t\t\talpha,\n\t\t\t\tvalues;\n\t\t\tif (Array.isArray(arg)) {\n\t\t\t\targs = arg;\n\t\t\t\targ = args[0];\n\t\t\t}\n\t\t\tvar argType = arg != null && typeof arg;\n\t\t\tif (argType === 'string' && arg in types) {\n\t\t\t\ttype = arg;\n\t\t\t\targ = args[1];\n\t\t\t\tif (Array.isArray(arg)) {\n\t\t\t\t\tcomponents = arg;\n\t\t\t\t\talpha = args[2];\n\t\t\t\t} else {\n\t\t\t\t\tif (reading)\n\t\t\t\t\t\tread = 1;\n\t\t\t\t\targs = Base.slice(args, 1);\n\t\t\t\t\targType = typeof arg;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!components) {\n\t\t\t\tvalues = argType === 'number'\n\t\t\t\t\t\t? args\n\t\t\t\t\t\t: argType === 'object' && arg.length != null\n\t\t\t\t\t\t\t? arg\n\t\t\t\t\t\t\t: null;\n\t\t\t\tif (values) {\n\t\t\t\t\tif (!type)\n\t\t\t\t\t\ttype = values.length >= 3\n\t\t\t\t\t\t\t\t? 'rgb'\n\t\t\t\t\t\t\t\t: 'gray';\n\t\t\t\t\tvar length = types[type].length;\n\t\t\t\t\talpha = values[length];\n\t\t\t\t\tif (reading) {\n\t\t\t\t\t\tread += values === arguments\n\t\t\t\t\t\t\t? length + (alpha != null ? 1 : 0)\n\t\t\t\t\t\t\t: 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (values.length > length)\n\t\t\t\t\t\tvalues = Base.slice(values, 0, length);\n\t\t\t\t} else if (argType === 'string') {\n\t\t\t\t\ttype = 'rgb';\n\t\t\t\t\tcomponents = fromCSS(arg);\n\t\t\t\t\tif (components.length === 4) {\n\t\t\t\t\t\talpha = components[3];\n\t\t\t\t\t\tcomponents.length--;\n\t\t\t\t\t}\n\t\t\t\t} else if (argType === 'object') {\n\t\t\t\t\tif (arg.constructor === Color) {\n\t\t\t\t\t\ttype = arg._type;\n\t\t\t\t\t\tcomponents = arg._components.slice();\n\t\t\t\t\t\talpha = arg._alpha;\n\t\t\t\t\t\tif (type === 'gradient') {\n\t\t\t\t\t\t\tfor (var i = 1, l = components.length; i < l; i++) {\n\t\t\t\t\t\t\t\tvar point = components[i];\n\t\t\t\t\t\t\t\tif (point)\n\t\t\t\t\t\t\t\t\tcomponents[i] = point.clone();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (arg.constructor === Gradient) {\n\t\t\t\t\t\ttype = 'gradient';\n\t\t\t\t\t\tvalues = args;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttype = 'hue' in arg\n\t\t\t\t\t\t\t? 'lightness' in arg\n\t\t\t\t\t\t\t\t? 'hsl'\n\t\t\t\t\t\t\t\t: 'hsb'\n\t\t\t\t\t\t\t: 'gradient' in arg || 'stops' in arg\n\t\t\t\t\t\t\t\t\t|| 'radial' in arg\n\t\t\t\t\t\t\t\t? 'gradient'\n\t\t\t\t\t\t\t\t: 'gray' in arg\n\t\t\t\t\t\t\t\t\t? 'gray'\n\t\t\t\t\t\t\t\t\t: 'rgb';\n\t\t\t\t\t\tvar properties = types[type],\n\t\t\t\t\t\t\tparsers = componentParsers[type];\n\t\t\t\t\t\tthis._components = components = [];\n\t\t\t\t\t\tfor (var i = 0, l = properties.length; i < l; i++) {\n\t\t\t\t\t\t\tvar value = arg[properties[i]];\n\t\t\t\t\t\t\tif (value == null && !i && type === 'gradient'\n\t\t\t\t\t\t\t\t\t&& 'stops' in arg) {\n\t\t\t\t\t\t\t\tvalue = {\n\t\t\t\t\t\t\t\t\tstops: arg.stops,\n\t\t\t\t\t\t\t\t\tradial: arg.radial\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvalue = parsers[i].call(this, value);\n\t\t\t\t\t\t\tif (value != null)\n\t\t\t\t\t\t\t\tcomponents[i] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\talpha = arg.alpha;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (reading && type)\n\t\t\t\t\tread = 1;\n\t\t\t}\n\t\t\tthis._type = type || 'rgb';\n\t\t\tif (!components) {\n\t\t\t\tthis._components = components = [];\n\t\t\t\tvar parsers = componentParsers[this._type];\n\t\t\t\tfor (var i = 0, l = parsers.length; i < l; i++) {\n\t\t\t\t\tvar value = parsers[i].call(this, values && values[i]);\n\t\t\t\t\tif (value != null)\n\t\t\t\t\t\tcomponents[i] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._components = components;\n\t\t\tthis._properties = types[this._type];\n\t\t\tthis._alpha = alpha;\n\t\t\tif (reading)\n\t\t\t\tthis.__read = read;\n\t\t\treturn this;\n\t\t},\n\n\t\tset: '#initialize',\n\n\t\t_serialize: function(options, dictionary) {\n\t\t\tvar components = this.getComponents();\n\t\t\treturn Base.serialize(\n\t\t\t\t\t/^(gray|rgb)$/.test(this._type)\n\t\t\t\t\t\t? components\n\t\t\t\t\t\t: [this._type].concat(components),\n\t\t\t\t\toptions, true, dictionary);\n\t\t},\n\n\t\t_changed: function() {\n\t\t\tthis._canvasStyle = null;\n\t\t\tif (this._owner)\n\t\t\t\tthis._owner._changed(65);\n\t\t},\n\n\t\t_convert: function(type) {\n\t\t\tvar converter;\n\t\t\treturn this._type === type\n\t\t\t\t\t? this._components.slice()\n\t\t\t\t\t: (converter = converters[this._type + '-' + type])\n\t\t\t\t\t\t? converter.apply(this, this._components)\n\t\t\t\t\t\t: converters['rgb-' + type].apply(this,\n\t\t\t\t\t\t\tconverters[this._type + '-rgb'].apply(this,\n\t\t\t\t\t\t\t\tthis._components));\n\t\t},\n\n\t\tconvert: function(type) {\n\t\t\treturn new Color(type, this._convert(type), this._alpha);\n\t\t},\n\n\t\tgetType: function() {\n\t\t\treturn this._type;\n\t\t},\n\n\t\tsetType: function(type) {\n\t\t\tthis._components = this._convert(type);\n\t\t\tthis._properties = types[type];\n\t\t\tthis._type = type;\n\t\t},\n\n\t\tgetComponents: function() {\n\t\t\tvar components = this._components.slice();\n\t\t\tif (this._alpha != null)\n\t\t\t\tcomponents.push(this._alpha);\n\t\t\treturn components;\n\t\t},\n\n\t\tgetAlpha: function() {\n\t\t\treturn this._alpha != null ? this._alpha : 1;\n\t\t},\n\n\t\tsetAlpha: function(alpha) {\n\t\t\tthis._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);\n\t\t\tthis._changed();\n\t\t},\n\n\t\thasAlpha: function() {\n\t\t\treturn this._alpha != null;\n\t\t},\n\n\t\tequals: function(color) {\n\t\t\tvar col = Base.isPlainValue(color, true)\n\t\t\t\t\t? Color.read(arguments)\n\t\t\t\t\t: color;\n\t\t\treturn col === this || col && this._class === col._class\n\t\t\t\t\t&& this._type === col._type\n\t\t\t\t\t&& this._alpha === col._alpha\n\t\t\t\t\t&& Base.equals(this._components, col._components)\n\t\t\t\t\t|| false;\n\t\t},\n\n\t\ttoString: function() {\n\t\t\tvar properties = this._properties,\n\t\t\t\tparts = [],\n\t\t\t\tisGradient = this._type === 'gradient',\n\t\t\t\tf = Formatter.instance;\n\t\t\tfor (var i = 0, l = properties.length; i < l; i++) {\n\t\t\t\tvar value = this._components[i];\n\t\t\t\tif (value != null)\n\t\t\t\t\tparts.push(properties[i] + ': '\n\t\t\t\t\t\t\t+ (isGradient ? value : f.number(value)));\n\t\t\t}\n\t\t\tif (this._alpha != null)\n\t\t\t\tparts.push('alpha: ' + f.number(this._alpha));\n\t\t\treturn '{ ' + parts.join(', ') + ' }';\n\t\t},\n\n\t\ttoCSS: function(hex) {\n\t\t\tvar components = this._convert('rgb'),\n\t\t\t\talpha = hex || this._alpha == null ? 1 : this._alpha;\n\t\t\tfunction convert(val) {\n\t\t\t\treturn Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);\n\t\t\t}\n\t\t\tcomponents = [\n\t\t\t\tconvert(components[0]),\n\t\t\t\tconvert(components[1]),\n\t\t\t\tconvert(components[2])\n\t\t\t];\n\t\t\tif (alpha < 1)\n\t\t\t\tcomponents.push(alpha < 0 ? 0 : alpha);\n\t\t\treturn hex\n\t\t\t\t\t? '#' + ((1 << 24) + (components[0] << 16)\n\t\t\t\t\t\t+ (components[1] << 8)\n\t\t\t\t\t\t+ components[2]).toString(16).slice(1)\n\t\t\t\t\t: (components.length == 4 ? 'rgba(' : 'rgb(')\n\t\t\t\t\t\t+ components.join(',') + ')';\n\t\t},\n\n\t\ttoCanvasStyle: function(ctx) {\n\t\t\tif (this._canvasStyle)\n\t\t\t\treturn this._canvasStyle;\n\t\t\tif (this._type !== 'gradient')\n\t\t\t\treturn this._canvasStyle = this.toCSS();\n\t\t\tvar components = this._components,\n\t\t\t\tgradient = components[0],\n\t\t\t\tstops = gradient._stops,\n\t\t\t\torigin = components[1],\n\t\t\t\tdestination = components[2],\n\t\t\t\tcanvasGradient;\n\t\t\tif (gradient._radial) {\n\t\t\t\tvar radius = destination.getDistance(origin),\n\t\t\t\t\thighlight = components[3];\n\t\t\t\tif (highlight) {\n\t\t\t\t\tvar vector = highlight.subtract(origin);\n\t\t\t\t\tif (vector.getLength() > radius)\n\t\t\t\t\t\thighlight = origin.add(vector.normalize(radius - 0.1));\n\t\t\t\t}\n\t\t\t\tvar start = highlight || origin;\n\t\t\t\tcanvasGradient = ctx.createRadialGradient(start.x, start.y,\n\t\t\t\t\t\t0, origin.x, origin.y, radius);\n\t\t\t} else {\n\t\t\t\tcanvasGradient = ctx.createLinearGradient(origin.x, origin.y,\n\t\t\t\t\t\tdestination.x, destination.y);\n\t\t\t}\n\t\t\tfor (var i = 0, l = stops.length; i < l; i++) {\n\t\t\t\tvar stop = stops[i];\n\t\t\t\tcanvasGradient.addColorStop(stop._offset || i / (l - 1),\n\t\t\t\t\t\tstop._color.toCanvasStyle());\n\t\t\t}\n\t\t\treturn this._canvasStyle = canvasGradient;\n\t\t},\n\n\t\ttransform: function(matrix) {\n\t\t\tif (this._type === 'gradient') {\n\t\t\t\tvar components = this._components;\n\t\t\t\tfor (var i = 1, l = components.length; i < l; i++) {\n\t\t\t\t\tvar point = components[i];\n\t\t\t\t\tmatrix._transformPoint(point, point, true);\n\t\t\t\t}\n\t\t\t\tthis._changed();\n\t\t\t}\n\t\t},\n\n\t\tstatics: {\n\t\t\t_types: types,\n\n\t\t\trandom: function() {\n\t\t\t\tvar random = Math.random;\n\t\t\t\treturn new Color(random(), random(), random());\n\t\t\t}\n\t\t}\n\t});\n},\nnew function() {\n\tvar operators = {\n\t\tadd: function(a, b) {\n\t\t\treturn a + b;\n\t\t},\n\n\t\tsubtract: function(a, b) {\n\t\t\treturn a - b;\n\t\t},\n\n\t\tmultiply: function(a, b) {\n\t\t\treturn a * b;\n\t\t},\n\n\t\tdivide: function(a, b) {\n\t\t\treturn a / b;\n\t\t}\n\t};\n\n\treturn Base.each(operators, function(operator, name) {\n\t\tthis[name] = function(color) {\n\t\t\tcolor = Color.read(arguments);\n\t\t\tvar type = this._type,\n\t\t\t\tcomponents1 = this._components,\n\t\t\t\tcomponents2 = color._convert(type);\n\t\t\tfor (var i = 0, l = components1.length; i < l; i++)\n\t\t\t\tcomponents2[i] = operator(components1[i], components2[i]);\n\t\t\treturn new Color(type, components2,\n\t\t\t\t\tthis._alpha != null\n\t\t\t\t\t\t\t? operator(this._alpha, color.getAlpha())\n\t\t\t\t\t\t\t: null);\n\t\t};\n\t}, {\n\t});\n});\n\nvar Gradient = Base.extend({\n\t_class: 'Gradient',\n\n\tinitialize: function Gradient(stops, radial) {\n\t\tthis._id = UID.get();\n\t\tif (stops && this._set(stops)) {\n\t\t\tstops = radial = null;\n\t\t}\n\t\tif (this._stops == null) {\n\t\t\tthis.setStops(stops || ['white', 'black']);\n\t\t}\n\t\tif (this._radial == null) {\n\t\t\tthis.setRadial(typeof radial === 'string' && radial === 'radial'\n\t\t\t\t\t|| radial || false);\n\t\t}\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn dictionary.add(this, function() {\n\t\t\treturn Base.serialize([this._stops, this._radial],\n\t\t\t\t\toptions, true, dictionary);\n\t\t});\n\t},\n\n\t_changed: function() {\n\t\tfor (var i = 0, l = this._owners && this._owners.length; i < l; i++) {\n\t\t\tthis._owners[i]._changed();\n\t\t}\n\t},\n\n\t_addOwner: function(color) {\n\t\tif (!this._owners)\n\t\t\tthis._owners = [];\n\t\tthis._owners.push(color);\n\t},\n\n\t_removeOwner: function(color) {\n\t\tvar index = this._owners ? this._owners.indexOf(color) : -1;\n\t\tif (index != -1) {\n\t\t\tthis._owners.splice(index, 1);\n\t\t\tif (!this._owners.length)\n\t\t\t\tthis._owners = undefined;\n\t\t}\n\t},\n\n\tclone: function() {\n\t\tvar stops = [];\n\t\tfor (var i = 0, l = this._stops.length; i < l; i++) {\n\t\t\tstops[i] = this._stops[i].clone();\n\t\t}\n\t\treturn new Gradient(stops, this._radial);\n\t},\n\n\tgetStops: function() {\n\t\treturn this._stops;\n\t},\n\n\tsetStops: function(stops) {\n\t\tif (stops.length < 2) {\n\t\t\tthrow new Error(\n\t\t\t\t\t'Gradient stop list needs to contain at least two stops.');\n\t\t}\n\t\tvar _stops = this._stops;\n\t\tif (_stops) {\n\t\t\tfor (var i = 0, l = _stops.length; i < l; i++)\n\t\t\t\t_stops[i]._owner = undefined;\n\t\t}\n\t\t_stops = this._stops = GradientStop.readList(stops, 0, { clone: true });\n\t\tfor (var i = 0, l = _stops.length; i < l; i++)\n\t\t\t_stops[i]._owner = this;\n\t\tthis._changed();\n\t},\n\n\tgetRadial: function() {\n\t\treturn this._radial;\n\t},\n\n\tsetRadial: function(radial) {\n\t\tthis._radial = radial;\n\t\tthis._changed();\n\t},\n\n\tequals: function(gradient) {\n\t\tif (gradient === this)\n\t\t\treturn true;\n\t\tif (gradient && this._class === gradient._class) {\n\t\t\tvar stops1 = this._stops,\n\t\t\t\tstops2 = gradient._stops,\n\t\t\t\tlength = stops1.length;\n\t\t\tif (length === stops2.length) {\n\t\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\t\tif (!stops1[i].equals(stops2[i]))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n});\n\nvar GradientStop = Base.extend({\n\t_class: 'GradientStop',\n\n\tinitialize: function GradientStop(arg0, arg1) {\n\t\tvar color = arg0,\n\t\t\toffset = arg1;\n\t\tif (typeof arg0 === 'object' && arg1 === undefined) {\n\t\t\tif (Array.isArray(arg0) && typeof arg0[0] !== 'number') {\n\t\t\t\tcolor = arg0[0];\n\t\t\t\toffset = arg0[1];\n\t\t\t} else if ('color' in arg0 || 'offset' in arg0\n\t\t\t\t\t|| 'rampPoint' in arg0) {\n\t\t\t\tcolor = arg0.color;\n\t\t\t\toffset = arg0.offset || arg0.rampPoint || 0;\n\t\t\t}\n\t\t}\n\t\tthis.setColor(color);\n\t\tthis.setOffset(offset);\n\t},\n\n\tclone: function() {\n\t\treturn new GradientStop(this._color.clone(), this._offset);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar color = this._color,\n\t\t\toffset = this._offset;\n\t\treturn Base.serialize(offset == null ? [color] : [color, offset],\n\t\t\t\toptions, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tif (this._owner)\n\t\t\tthis._owner._changed(65);\n\t},\n\n\tgetOffset: function() {\n\t\treturn this._offset;\n\t},\n\n\tsetOffset: function(offset) {\n\t\tthis._offset = offset;\n\t\tthis._changed();\n\t},\n\n\tgetRampPoint: '#getOffset',\n\tsetRampPoint: '#setOffset',\n\n\tgetColor: function() {\n\t\treturn this._color;\n\t},\n\n\tsetColor: function() {\n\t\tvar color = Color.read(arguments, 0, { clone: true });\n\t\tif (color)\n\t\t\tcolor._owner = this;\n\t\tthis._color = color;\n\t\tthis._changed();\n\t},\n\n\tequals: function(stop) {\n\t\treturn stop === this || stop && this._class === stop._class\n\t\t\t\t&& this._color.equals(stop._color)\n\t\t\t\t&& this._offset == stop._offset\n\t\t\t\t|| false;\n\t}\n});\n\nvar Style = Base.extend(new function() {\n\tvar itemDefaults = {\n\t\tfillColor: null,\n\t\tfillRule: 'nonzero',\n\t\tstrokeColor: null,\n\t\tstrokeWidth: 1,\n\t\tstrokeCap: 'butt',\n\t\tstrokeJoin: 'miter',\n\t\tstrokeScaling: true,\n\t\tmiterLimit: 10,\n\t\tdashOffset: 0,\n\t\tdashArray: [],\n\t\tshadowColor: null,\n\t\tshadowBlur: 0,\n\t\tshadowOffset: new Point(),\n\t\tselectedColor: null\n\t},\n\tgroupDefaults = Base.set({}, itemDefaults, {\n\t\tfontFamily: 'sans-serif',\n\t\tfontWeight: 'normal',\n\t\tfontSize: 12,\n\t\tleading: null,\n\t\tjustification: 'left'\n\t}),\n\ttextDefaults = Base.set({}, groupDefaults, {\n\t\tfillColor: new Color()\n\t}),\n\tflags = {\n\t\tstrokeWidth: 97,\n\t\tstrokeCap: 97,\n\t\tstrokeJoin: 97,\n\t\tstrokeScaling: 105,\n\t\tmiterLimit: 97,\n\t\tfontFamily: 9,\n\t\tfontWeight: 9,\n\t\tfontSize: 9,\n\t\tfont: 9,\n\t\tleading: 9,\n\t\tjustification: 9\n\t},\n\titem = {\n\t\tbeans: true\n\t},\n\tfields = {\n\t\t_class: 'Style',\n\t\tbeans: true,\n\n\t\tinitialize: function Style(style, _owner, _project) {\n\t\t\tthis._values = {};\n\t\t\tthis._owner = _owner;\n\t\t\tthis._project = _owner && _owner._project || _project\n\t\t\t\t\t|| paper.project;\n\t\t\tthis._defaults = !_owner || _owner instanceof Group ? groupDefaults\n\t\t\t\t\t: _owner instanceof TextItem ? textDefaults\n\t\t\t\t\t: itemDefaults;\n\t\t\tif (style)\n\t\t\t\tthis.set(style);\n\t\t}\n\t};\n\n\tBase.each(groupDefaults, function(value, key) {\n\t\tvar isColor = /Color$/.test(key),\n\t\t\tisPoint = key === 'shadowOffset',\n\t\t\tpart = Base.capitalize(key),\n\t\t\tflag = flags[key],\n\t\t\tset = 'set' + part,\n\t\t\tget = 'get' + part;\n\n\t\tfields[set] = function(value) {\n\t\t\tvar owner = this._owner,\n\t\t\t\tchildren = owner && owner._children;\n\t\t\tif (children && children.length > 0\n\t\t\t\t\t&& !(owner instanceof CompoundPath)) {\n\t\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\t\tchildren[i]._style[set](value);\n\t\t\t} else if (key in this._defaults) {\n\t\t\t\tvar old = this._values[key];\n\t\t\t\tif (old !== value) {\n\t\t\t\t\tif (isColor) {\n\t\t\t\t\t\tif (old && old._owner !== undefined)\n\t\t\t\t\t\t\told._owner = undefined;\n\t\t\t\t\t\tif (value && value.constructor === Color) {\n\t\t\t\t\t\t\tif (value._owner)\n\t\t\t\t\t\t\t\tvalue = value.clone();\n\t\t\t\t\t\t\tvalue._owner = owner;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._values[key] = value;\n\t\t\t\t\tif (owner)\n\t\t\t\t\t\towner._changed(flag || 65);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfields[get] = function(_dontMerge) {\n\t\t\tvar owner = this._owner,\n\t\t\t\tchildren = owner && owner._children,\n\t\t\t\tvalue;\n\t\t\tif (key in this._defaults && (!children || !children.length\n\t\t\t\t\t|| _dontMerge || owner instanceof CompoundPath)) {\n\t\t\t\tvar value = this._values[key];\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tvalue = this._defaults[key];\n\t\t\t\t\tif (value && value.clone)\n\t\t\t\t\t\tvalue = value.clone();\n\t\t\t\t} else {\n\t\t\t\t\tvar ctor = isColor ? Color : isPoint ? Point : null;\n\t\t\t\t\tif (ctor && !(value && value.constructor === ctor)) {\n\t\t\t\t\t\tthis._values[key] = value = ctor.read([value], 0,\n\t\t\t\t\t\t\t\t{ readNull: true, clone: true });\n\t\t\t\t\t\tif (value && isColor)\n\t\t\t\t\t\t\tvalue._owner = owner;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (children) {\n\t\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\t\tvar childValue = children[i]._style[get]();\n\t\t\t\t\tif (!i) {\n\t\t\t\t\t\tvalue = childValue;\n\t\t\t\t\t} else if (!Base.equals(value, childValue)) {\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn value;\n\t\t};\n\n\t\titem[get] = function(_dontMerge) {\n\t\t\treturn this._style[get](_dontMerge);\n\t\t};\n\n\t\titem[set] = function(value) {\n\t\t\tthis._style[set](value);\n\t\t};\n\t});\n\n\tBase.each({\n\t\tFont: 'FontFamily',\n\t\tWindingRule: 'FillRule'\n\t}, function(value, key) {\n\t\tvar get = 'get' + key,\n\t\t\tset = 'set' + key;\n\t\tfields[get] = item[get] = '#get' + value;\n\t\tfields[set] = item[set] = '#set' + value;\n\t});\n\n\tItem.inject(item);\n\treturn fields;\n}, {\n\tset: function(style) {\n\t\tthis._values = {};\n\t\tvar isStyle = style instanceof Style,\n\t\t\tvalues = isStyle ? style._values : style;\n\t\tif (values) {\n\t\t\tfor (var key in values) {\n\t\t\t\tif (key in this._defaults) {\n\t\t\t\t\tvar value = values[key];\n\t\t\t\t\tthis[key] = value && isStyle && value.clone\n\t\t\t\t\t\t\t? value.clone() : value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tequals: function(style) {\n\t\treturn style === this || style && this._class === style._class\n\t\t\t\t&& Base.equals(this._values, style._values)\n\t\t\t\t|| false;\n\t},\n\n\thasFill: function() {\n\t\tvar color = this.getFillColor();\n\t\treturn !!color && color.alpha > 0;\n\t},\n\n\thasStroke: function() {\n\t\tvar color = this.getStrokeColor();\n\t\treturn !!color && color.alpha > 0 && this.getStrokeWidth() > 0;\n\t},\n\n\thasShadow: function() {\n\t\tvar color = this.getShadowColor();\n\t\treturn !!color && color.alpha > 0 && (this.getShadowBlur() > 0\n\t\t\t\t|| !this.getShadowOffset().isZero());\n\t},\n\n\tgetView: function() {\n\t\treturn this._project._view;\n\t},\n\n\tgetFontStyle: function() {\n\t\tvar fontSize = this.getFontSize();\n\t\treturn this.getFontWeight()\n\t\t\t\t+ ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')\n\t\t\t\t+ this.getFontFamily();\n\t},\n\n\tgetFont: '#getFontFamily',\n\tsetFont: '#setFontFamily',\n\n\tgetLeading: function getLeading() {\n\t\tvar leading = getLeading.base.call(this),\n\t\t\tfontSize = this.getFontSize();\n\t\tif (/pt|em|%|px/.test(fontSize))\n\t\t\tfontSize = this.getView().getPixelSize(fontSize);\n\t\treturn leading != null ? leading : fontSize * 1.2;\n\t}\n\n});\n\nvar DomElement = new function() {\n\tfunction handlePrefix(el, name, set, value) {\n\t\tvar prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],\n\t\t\tsuffix = name[0].toUpperCase() + name.substring(1);\n\t\tfor (var i = 0; i < 6; i++) {\n\t\t\tvar prefix = prefixes[i],\n\t\t\t\tkey = prefix ? prefix + suffix : name;\n\t\t\tif (key in el) {\n\t\t\t\tif (set) {\n\t\t\t\t\tel[key] = value;\n\t\t\t\t} else {\n\t\t\t\t\treturn el[key];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tgetStyles: function(el) {\n\t\t\tvar doc = el && el.nodeType !== 9 ? el.ownerDocument : el,\n\t\t\t\tview = doc && doc.defaultView;\n\t\t\treturn view && view.getComputedStyle(el, '');\n\t\t},\n\n\t\tgetBounds: function(el, viewport) {\n\t\t\tvar doc = el.ownerDocument,\n\t\t\t\tbody = doc.body,\n\t\t\t\thtml = doc.documentElement,\n\t\t\t\trect;\n\t\t\ttry {\n\t\t\t\trect = el.getBoundingClientRect();\n\t\t\t} catch (e) {\n\t\t\t\trect = { left: 0, top: 0, width: 0, height: 0 };\n\t\t\t}\n\t\t\tvar x = rect.left - (html.clientLeft || body.clientLeft || 0),\n\t\t\t\ty = rect.top - (html.clientTop || body.clientTop || 0);\n\t\t\tif (!viewport) {\n\t\t\t\tvar view = doc.defaultView;\n\t\t\t\tx += view.pageXOffset || html.scrollLeft || body.scrollLeft;\n\t\t\t\ty += view.pageYOffset || html.scrollTop || body.scrollTop;\n\t\t\t}\n\t\t\treturn new Rectangle(x, y, rect.width, rect.height);\n\t\t},\n\n\t\tgetViewportBounds: function(el) {\n\t\t\tvar doc = el.ownerDocument,\n\t\t\t\tview = doc.defaultView,\n\t\t\t\thtml = doc.documentElement;\n\t\t\treturn new Rectangle(0, 0,\n\t\t\t\tview.innerWidth || html.clientWidth,\n\t\t\t\tview.innerHeight || html.clientHeight\n\t\t\t);\n\t\t},\n\n\t\tgetOffset: function(el, viewport) {\n\t\t\treturn DomElement.getBounds(el, viewport).getPoint();\n\t\t},\n\n\t\tgetSize: function(el) {\n\t\t\treturn DomElement.getBounds(el, true).getSize();\n\t\t},\n\n\t\tisInvisible: function(el) {\n\t\t\treturn DomElement.getSize(el).equals(new Size(0, 0));\n\t\t},\n\n\t\tisInView: function(el) {\n\t\t\treturn !DomElement.isInvisible(el)\n\t\t\t\t\t&& DomElement.getViewportBounds(el).intersects(\n\t\t\t\t\t\tDomElement.getBounds(el, true));\n\t\t},\n\n\t\tisInserted: function(el) {\n\t\t\treturn document.body.contains(el);\n\t\t},\n\n\t\tgetPrefixed: function(el, name) {\n\t\t\treturn el && handlePrefix(el, name);\n\t\t},\n\n\t\tsetPrefixed: function(el, name, value) {\n\t\t\tif (typeof name === 'object') {\n\t\t\t\tfor (var key in name)\n\t\t\t\t\thandlePrefix(el, key, true, name[key]);\n\t\t\t} else {\n\t\t\t\thandlePrefix(el, name, true, value);\n\t\t\t}\n\t\t}\n\t};\n};\n\nvar DomEvent = {\n\tadd: function(el, events) {\n\t\tif (el) {\n\t\t\tfor (var type in events) {\n\t\t\t\tvar func = events[type],\n\t\t\t\t\tparts = type.split(/[\\s,]+/g);\n\t\t\t\tfor (var i = 0, l = parts.length; i < l; i++)\n\t\t\t\t\tel.addEventListener(parts[i], func, false);\n\t\t\t}\n\t\t}\n\t},\n\n\tremove: function(el, events) {\n\t\tif (el) {\n\t\t\tfor (var type in events) {\n\t\t\t\tvar func = events[type],\n\t\t\t\t\tparts = type.split(/[\\s,]+/g);\n\t\t\t\tfor (var i = 0, l = parts.length; i < l; i++)\n\t\t\t\t\tel.removeEventListener(parts[i], func, false);\n\t\t\t}\n\t\t}\n\t},\n\n\tgetPoint: function(event) {\n\t\tvar pos = event.targetTouches\n\t\t\t\t? event.targetTouches.length\n\t\t\t\t\t? event.targetTouches[0]\n\t\t\t\t\t: event.changedTouches[0]\n\t\t\t\t: event;\n\t\treturn new Point(\n\t\t\tpos.pageX || pos.clientX + document.documentElement.scrollLeft,\n\t\t\tpos.pageY || pos.clientY + document.documentElement.scrollTop\n\t\t);\n\t},\n\n\tgetTarget: function(event) {\n\t\treturn event.target || event.srcElement;\n\t},\n\n\tgetRelatedTarget: function(event) {\n\t\treturn event.relatedTarget || event.toElement;\n\t},\n\n\tgetOffset: function(event, target) {\n\t\treturn DomEvent.getPoint(event).subtract(DomElement.getOffset(\n\t\t\t\ttarget || DomEvent.getTarget(event)));\n\t}\n};\n\nDomEvent.requestAnimationFrame = new function() {\n\tvar nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'),\n\t\trequested = false,\n\t\tcallbacks = [],\n\t\ttimer;\n\n\tfunction handleCallbacks() {\n\t\tvar functions = callbacks;\n\t\tcallbacks = [];\n\t\tfor (var i = 0, l = functions.length; i < l; i++)\n\t\t\tfunctions[i]();\n\t\trequested = nativeRequest && callbacks.length;\n\t\tif (requested)\n\t\t\tnativeRequest(handleCallbacks);\n\t}\n\n\treturn function(callback) {\n\t\tcallbacks.push(callback);\n\t\tif (nativeRequest) {\n\t\t\tif (!requested) {\n\t\t\t\tnativeRequest(handleCallbacks);\n\t\t\t\trequested = true;\n\t\t\t}\n\t\t} else if (!timer) {\n\t\t\ttimer = setInterval(handleCallbacks, 1000 / 60);\n\t\t}\n\t};\n};\n\nvar View = Base.extend(Emitter, {\n\t_class: 'View',\n\n\tinitialize: function View(project, element) {\n\n\t\tfunction getSize(name) {\n\t\t\treturn element[name] || parseInt(element.getAttribute(name), 10);\n\t\t}\n\n\t\tfunction getCanvasSize() {\n\t\t\tvar size = DomElement.getSize(element);\n\t\t\treturn size.isNaN() || size.isZero()\n\t\t\t\t\t? new Size(getSize('width'), getSize('height'))\n\t\t\t\t\t: size;\n\t\t}\n\n\t\tvar size;\n\t\tif (window && element) {\n\t\t\tthis._id = element.getAttribute('id');\n\t\t\tif (this._id == null)\n\t\t\t\telement.setAttribute('id', this._id = 'view-' + View._id++);\n\t\t\tDomEvent.add(element, this._viewEvents);\n\t\t\tvar none = 'none';\n\t\t\tDomElement.setPrefixed(element.style, {\n\t\t\t\tuserDrag: none,\n\t\t\t\tuserSelect: none,\n\t\t\t\ttouchCallout: none,\n\t\t\t\tcontentZooming: none,\n\t\t\t\ttapHighlightColor: 'rgba(0,0,0,0)'\n\t\t\t});\n\n\t\t\tif (PaperScope.hasAttribute(element, 'resize')) {\n\t\t\t\tvar that = this;\n\t\t\t\tDomEvent.add(window, this._windowEvents = {\n\t\t\t\t\tresize: function() {\n\t\t\t\t\t\tthat.setViewSize(getCanvasSize());\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsize = getCanvasSize();\n\n\t\t\tif (PaperScope.hasAttribute(element, 'stats')\n\t\t\t\t\t&& typeof Stats !== 'undefined') {\n\t\t\t\tthis._stats = new Stats();\n\t\t\t\tvar stats = this._stats.domElement,\n\t\t\t\t\tstyle = stats.style,\n\t\t\t\t\toffset = DomElement.getOffset(element);\n\t\t\t\tstyle.position = 'absolute';\n\t\t\t\tstyle.left = offset.x + 'px';\n\t\t\t\tstyle.top = offset.y + 'px';\n\t\t\t\tdocument.body.appendChild(stats);\n\t\t\t}\n\t\t} else {\n\t\t\tsize = new Size(element);\n\t\t\telement = null;\n\t\t}\n\t\tthis._project = project;\n\t\tthis._scope = project._scope;\n\t\tthis._element = element;\n\t\tif (!this._pixelRatio)\n\t\t\tthis._pixelRatio = window && window.devicePixelRatio || 1;\n\t\tthis._setElementSize(size.width, size.height);\n\t\tthis._viewSize = size;\n\t\tView._views.push(this);\n\t\tView._viewsById[this._id] = this;\n\t\t(this._matrix = new Matrix())._owner = this;\n\t\tif (!View._focused)\n\t\t\tView._focused = this;\n\t\tthis._frameItems = {};\n\t\tthis._frameItemCount = 0;\n\t\tthis._itemEvents = { native: {}, virtual: {} };\n\t\tthis._autoUpdate = !paper.agent.node;\n\t\tthis._needsUpdate = false;\n\t},\n\n\tremove: function() {\n\t\tif (!this._project)\n\t\t\treturn false;\n\t\tif (View._focused === this)\n\t\t\tView._focused = null;\n\t\tView._views.splice(View._views.indexOf(this), 1);\n\t\tdelete View._viewsById[this._id];\n\t\tvar project = this._project;\n\t\tif (project._view === this)\n\t\t\tproject._view = null;\n\t\tDomEvent.remove(this._element, this._viewEvents);\n\t\tDomEvent.remove(window, this._windowEvents);\n\t\tthis._element = this._project = null;\n\t\tthis.off('frame');\n\t\tthis._animate = false;\n\t\tthis._frameItems = {};\n\t\treturn true;\n\t},\n\n\t_events: Base.each(\n\t\tItem._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']),\n\t\tfunction(name) {\n\t\t\tthis[name] = {};\n\t\t}, {\n\t\t\tonFrame: {\n\t\t\t\tinstall: function() {\n\t\t\t\t\tthis.play();\n\t\t\t\t},\n\n\t\t\t\tuninstall: function() {\n\t\t\t\t\tthis.pause();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t),\n\n\t_animate: false,\n\t_time: 0,\n\t_count: 0,\n\n\tgetAutoUpdate: function() {\n\t\treturn this._autoUpdate;\n\t},\n\n\tsetAutoUpdate: function(autoUpdate) {\n\t\tthis._autoUpdate = autoUpdate;\n\t\tif (autoUpdate)\n\t\t\tthis.requestUpdate();\n\t},\n\n\tupdate: function() {\n\t},\n\n\tdraw: function() {\n\t\tthis.update();\n\t},\n\n\trequestUpdate: function() {\n\t\tif (!this._requested) {\n\t\t\tvar that = this;\n\t\t\tDomEvent.requestAnimationFrame(function() {\n\t\t\t\tthat._requested = false;\n\t\t\t\tif (that._animate) {\n\t\t\t\t\tthat.requestUpdate();\n\t\t\t\t\tvar element = that._element;\n\t\t\t\t\tif ((!DomElement.getPrefixed(document, 'hidden')\n\t\t\t\t\t\t\t|| PaperScope.getAttribute(element, 'keepalive')\n\t\t\t\t\t\t\t\t=== 'true') && DomElement.isInView(element)) {\n\t\t\t\t\t\tthat._handleFrame();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (that._autoUpdate)\n\t\t\t\t\tthat.update();\n\t\t\t});\n\t\t\tthis._requested = true;\n\t\t}\n\t},\n\n\tplay: function() {\n\t\tthis._animate = true;\n\t\tthis.requestUpdate();\n\t},\n\n\tpause: function() {\n\t\tthis._animate = false;\n\t},\n\n\t_handleFrame: function() {\n\t\tpaper = this._scope;\n\t\tvar now = Date.now() / 1000,\n\t\t\tdelta = this._last ? now - this._last : 0;\n\t\tthis._last = now;\n\t\tthis.emit('frame', new Base({\n\t\t\tdelta: delta,\n\t\t\ttime: this._time += delta,\n\t\t\tcount: this._count++\n\t\t}));\n\t\tif (this._stats)\n\t\t\tthis._stats.update();\n\t},\n\n\t_animateItem: function(item, animate) {\n\t\tvar items = this._frameItems;\n\t\tif (animate) {\n\t\t\titems[item._id] = {\n\t\t\t\titem: item,\n\t\t\t\ttime: 0,\n\t\t\t\tcount: 0\n\t\t\t};\n\t\t\tif (++this._frameItemCount === 1)\n\t\t\t\tthis.on('frame', this._handleFrameItems);\n\t\t} else {\n\t\t\tdelete items[item._id];\n\t\t\tif (--this._frameItemCount === 0) {\n\t\t\t\tthis.off('frame', this._handleFrameItems);\n\t\t\t}\n\t\t}\n\t},\n\n\t_handleFrameItems: function(event) {\n\t\tfor (var i in this._frameItems) {\n\t\t\tvar entry = this._frameItems[i];\n\t\t\tentry.item.emit('frame', new Base(event, {\n\t\t\t\ttime: entry.time += event.delta,\n\t\t\t\tcount: entry.count++\n\t\t\t}));\n\t\t}\n\t},\n\n\t_changed: function() {\n\t\tthis._project._changed(2049);\n\t\tthis._bounds = this._decomposed = undefined;\n\t},\n\n\tgetElement: function() {\n\t\treturn this._element;\n\t},\n\n\tgetPixelRatio: function() {\n\t\treturn this._pixelRatio;\n\t},\n\n\tgetResolution: function() {\n\t\treturn this._pixelRatio * 72;\n\t},\n\n\tgetViewSize: function() {\n\t\tvar size = this._viewSize;\n\t\treturn new LinkedSize(size.width, size.height, this, 'setViewSize');\n\t},\n\n\tsetViewSize: function() {\n\t\tvar size = Size.read(arguments),\n\t\t\twidth = size.width,\n\t\t\theight = size.height,\n\t\t\tdelta = size.subtract(this._viewSize);\n\t\tif (delta.isZero())\n\t\t\treturn;\n\t\tthis._setElementSize(width, height);\n\t\tthis._viewSize._set(width, height);\n\t\tthis.emit('resize', {\n\t\t\tsize: size,\n\t\t\tdelta: delta\n\t\t});\n\t\tthis._changed();\n\t\tif (this._autoUpdate)\n\t\t\tthis.requestUpdate();\n\t},\n\n\t_setElementSize: function(width, height) {\n\t\tvar element = this._element;\n\t\tif (element) {\n\t\t\tif (element.width !== width)\n\t\t\t\telement.width = width;\n\t\t\tif (element.height !== height)\n\t\t\t\telement.height = height;\n\t\t}\n\t},\n\n\tgetBounds: function() {\n\t\tif (!this._bounds)\n\t\t\tthis._bounds = this._matrix.inverted()._transformBounds(\n\t\t\t\t\tnew Rectangle(new Point(), this._viewSize));\n\t\treturn this._bounds;\n\t},\n\n\tgetSize: function() {\n\t\treturn this.getBounds().getSize();\n\t},\n\n\tisVisible: function() {\n\t\treturn DomElement.isInView(this._element);\n\t},\n\n\tisInserted: function() {\n\t\treturn DomElement.isInserted(this._element);\n\t},\n\n\tgetPixelSize: function(size) {\n\t\tvar element = this._element,\n\t\t\tpixels;\n\t\tif (element) {\n\t\t\tvar parent = element.parentNode,\n\t\t\t\ttemp = document.createElement('div');\n\t\t\ttemp.style.fontSize = size;\n\t\t\tparent.appendChild(temp);\n\t\t\tpixels = parseFloat(DomElement.getStyles(temp).fontSize);\n\t\t\tparent.removeChild(temp);\n\t\t} else {\n\t\t\tpixels = parseFloat(pixels);\n\t\t}\n\t\treturn pixels;\n\t},\n\n\tgetTextWidth: function(font, lines) {\n\t\treturn 0;\n\t}\n}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {\n\tvar rotate = key === 'rotate';\n\tthis[key] = function() {\n\t\tvar value = (rotate ? Base : Point).read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\treturn this.transform(new Matrix()[key](value,\n\t\t\t\tcenter || this.getCenter(true)));\n\t};\n}, {\n\t_decompose: function() {\n\t\treturn this._decomposed || (this._decomposed = this._matrix.decompose());\n\t},\n\n\ttranslate: function() {\n\t\tvar mx = new Matrix();\n\t\treturn this.transform(mx.translate.apply(mx, arguments));\n\t},\n\n\tgetCenter: function() {\n\t\treturn this.getBounds().getCenter();\n\t},\n\n\tsetCenter: function() {\n\t\tvar center = Point.read(arguments);\n\t\tthis.translate(this.getCenter().subtract(center));\n\t},\n\n\tgetZoom: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\tscaling = decomposed && decomposed.scaling;\n\t\treturn scaling ? (scaling.x + scaling.y) / 2 : 0;\n\t},\n\n\tsetZoom: function(zoom) {\n\t\tthis.transform(new Matrix().scale(zoom / this.getZoom(),\n\t\t\tthis.getCenter()));\n\t},\n\n\tgetRotation: function() {\n\t\tvar decomposed = this._decompose();\n\t\treturn decomposed && decomposed.rotation;\n\t},\n\n\tsetRotation: function(rotation) {\n\t\tvar current = this.getRotation();\n\t\tif (current != null && rotation != null) {\n\t\t\tthis.rotate(rotation - current);\n\t\t}\n\t},\n\n\tgetScaling: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\tscaling = decomposed && decomposed.scaling;\n\t\treturn scaling\n\t\t\t\t? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')\n\t\t\t\t: undefined;\n\t},\n\n\tsetScaling: function() {\n\t\tvar current = this.getScaling(),\n\t\t\tscaling = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tif (current && scaling) {\n\t\t\tthis.scale(scaling.x / current.x, scaling.y / current.y);\n\t\t}\n\t},\n\n\tgetMatrix: function() {\n\t\treturn this._matrix;\n\t},\n\n\tsetMatrix: function() {\n\t\tvar matrix = this._matrix;\n\t\tmatrix.initialize.apply(matrix, arguments);\n\t},\n\n\ttransform: function(matrix) {\n\t\tthis._matrix.append(matrix);\n\t},\n\n\tscrollBy: function() {\n\t\tthis.translate(Point.read(arguments).negate());\n\t}\n}), {\n\n\tprojectToView: function() {\n\t\treturn this._matrix._transformPoint(Point.read(arguments));\n\t},\n\n\tviewToProject: function() {\n\t\treturn this._matrix._inverseTransform(Point.read(arguments));\n\t},\n\n\tgetEventPoint: function(event) {\n\t\treturn this.viewToProject(DomEvent.getOffset(event, this._element));\n\t},\n\n}, {\n\tstatics: {\n\t\t_views: [],\n\t\t_viewsById: {},\n\t\t_id: 0,\n\n\t\tcreate: function(project, element) {\n\t\t\tif (document && typeof element === 'string')\n\t\t\t\telement = document.getElementById(element);\n\t\t\tvar ctor = window ? CanvasView : View;\n\t\t\treturn new ctor(project, element);\n\t\t}\n\t}\n},\nnew function() {\n\tif (!window)\n\t\treturn;\n\tvar prevFocus,\n\t\ttempFocus,\n\t\tdragging = false,\n\t\tmouseDown = false;\n\n\tfunction getView(event) {\n\t\tvar target = DomEvent.getTarget(event);\n\t\treturn target.getAttribute && View._viewsById[\n\t\t\t\ttarget.getAttribute('id')];\n\t}\n\n\tfunction updateFocus() {\n\t\tvar view = View._focused;\n\t\tif (!view || !view.isVisible()) {\n\t\t\tfor (var i = 0, l = View._views.length; i < l; i++) {\n\t\t\t\tif ((view = View._views[i]).isVisible()) {\n\t\t\t\t\tView._focused = tempFocus = view;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction handleMouseMove(view, event, point) {\n\t\tview._handleMouseEvent('mousemove', event, point);\n\t}\n\n\tvar navigator = window.navigator,\n\t\tmousedown, mousemove, mouseup;\n\tif (navigator.pointerEnabled || navigator.msPointerEnabled) {\n\t\tmousedown = 'pointerdown MSPointerDown';\n\t\tmousemove = 'pointermove MSPointerMove';\n\t\tmouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';\n\t} else {\n\t\tmousedown = 'touchstart';\n\t\tmousemove = 'touchmove';\n\t\tmouseup = 'touchend touchcancel';\n\t\tif (!('ontouchstart' in window && navigator.userAgent.match(\n\t\t\t\t/mobile|tablet|ip(ad|hone|od)|android|silk/i))) {\n\t\t\tmousedown += ' mousedown';\n\t\t\tmousemove += ' mousemove';\n\t\t\tmouseup += ' mouseup';\n\t\t}\n\t}\n\n\tvar viewEvents = {},\n\t\tdocEvents = {\n\t\t\tmouseout: function(event) {\n\t\t\t\tvar view = View._focused,\n\t\t\t\t\ttarget = DomEvent.getRelatedTarget(event);\n\t\t\t\tif (view && (!target || target.nodeName === 'HTML')) {\n\t\t\t\t\tvar offset = DomEvent.getOffset(event, view._element),\n\t\t\t\t\t\tx = offset.x,\n\t\t\t\t\t\tabs = Math.abs,\n\t\t\t\t\t\tax = abs(x),\n\t\t\t\t\t\tmax = 1 << 25,\n\t\t\t\t\t\tdiff = ax - max;\n\t\t\t\t\toffset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;\n\t\t\t\t\thandleMouseMove(view, event, view.viewToProject(offset));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tscroll: updateFocus\n\t\t};\n\n\tviewEvents[mousedown] = function(event) {\n\t\tvar view = View._focused = getView(event);\n\t\tif (!dragging) {\n\t\t\tdragging = true;\n\t\t\tview._handleMouseEvent('mousedown', event);\n\t\t}\n\t};\n\n\tdocEvents[mousemove] = function(event) {\n\t\tvar view = View._focused;\n\t\tif (!mouseDown) {\n\t\t\tvar target = getView(event);\n\t\t\tif (target) {\n\t\t\t\tif (view !== target) {\n\t\t\t\t\tif (view)\n\t\t\t\t\t\thandleMouseMove(view, event);\n\t\t\t\t\tif (!prevFocus)\n\t\t\t\t\t\tprevFocus = view;\n\t\t\t\t\tview = View._focused = tempFocus = target;\n\t\t\t\t}\n\t\t\t} else if (tempFocus && tempFocus === view) {\n\t\t\t\tif (prevFocus && !prevFocus.isInserted())\n\t\t\t\t\tprevFocus = null;\n\t\t\t\tview = View._focused = prevFocus;\n\t\t\t\tprevFocus = null;\n\t\t\t\tupdateFocus();\n\t\t\t}\n\t\t}\n\t\tif (view)\n\t\t\thandleMouseMove(view, event);\n\t};\n\n\tdocEvents[mousedown] = function() {\n\t\tmouseDown = true;\n\t};\n\n\tdocEvents[mouseup] = function(event) {\n\t\tvar view = View._focused;\n\t\tif (view && dragging)\n\t\t\tview._handleMouseEvent('mouseup', event);\n\t\tmouseDown = dragging = false;\n\t};\n\n\tDomEvent.add(document, docEvents);\n\n\tDomEvent.add(window, {\n\t\tload: updateFocus\n\t});\n\n\tvar called = false,\n\t\tprevented = false,\n\t\tfallbacks = {\n\t\t\tdoubleclick: 'click',\n\t\t\tmousedrag: 'mousemove'\n\t\t},\n\t\twasInView = false,\n\t\toverView,\n\t\tdownPoint,\n\t\tlastPoint,\n\t\tdownItem,\n\t\toverItem,\n\t\tdragItem,\n\t\tclickItem,\n\t\tclickTime,\n\t\tdblClick;\n\n\tfunction emitMouseEvent(obj, target, type, event, point, prevPoint,\n\t\t\tstopItem) {\n\t\tvar stopped = false,\n\t\t\tmouseEvent;\n\n\t\tfunction emit(obj, type) {\n\t\t\tif (obj.responds(type)) {\n\t\t\t\tif (!mouseEvent) {\n\t\t\t\t\tmouseEvent = new MouseEvent(type, event, point,\n\t\t\t\t\t\t\ttarget || obj,\n\t\t\t\t\t\t\tprevPoint ? point.subtract(prevPoint) : null);\n\t\t\t\t}\n\t\t\t\tif (obj.emit(type, mouseEvent)) {\n\t\t\t\t\tcalled = true;\n\t\t\t\t\tif (mouseEvent.prevented)\n\t\t\t\t\t\tprevented = true;\n\t\t\t\t\tif (mouseEvent.stopped)\n\t\t\t\t\t\treturn stopped = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar fallback = fallbacks[type];\n\t\t\t\tif (fallback)\n\t\t\t\t\treturn emit(obj, fallback);\n\t\t\t}\n\t\t}\n\n\t\twhile (obj && obj !== stopItem) {\n\t\t\tif (emit(obj, type))\n\t\t\t\tbreak;\n\t\t\tobj = obj._parent;\n\t\t}\n\t\treturn stopped;\n\t}\n\n\tfunction emitMouseEvents(view, hitItem, type, event, point, prevPoint) {\n\t\tview._project.removeOn(type);\n\t\tprevented = called = false;\n\t\treturn (dragItem && emitMouseEvent(dragItem, null, type, event,\n\t\t\t\t\tpoint, prevPoint)\n\t\t\t|| hitItem && hitItem !== dragItem\n\t\t\t\t&& !hitItem.isDescendant(dragItem)\n\t\t\t\t&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,\n\t\t\t\t\tpoint, prevPoint, dragItem)\n\t\t\t|| emitMouseEvent(view, dragItem || hitItem || view, type, event,\n\t\t\t\t\tpoint, prevPoint));\n\t}\n\n\tvar itemEventsMap = {\n\t\tmousedown: {\n\t\t\tmousedown: 1,\n\t\t\tmousedrag: 1,\n\t\t\tclick: 1,\n\t\t\tdoubleclick: 1\n\t\t},\n\t\tmouseup: {\n\t\t\tmouseup: 1,\n\t\t\tmousedrag: 1,\n\t\t\tclick: 1,\n\t\t\tdoubleclick: 1\n\t\t},\n\t\tmousemove: {\n\t\t\tmousedrag: 1,\n\t\t\tmousemove: 1,\n\t\t\tmouseenter: 1,\n\t\t\tmouseleave: 1\n\t\t}\n\t};\n\n\treturn {\n\t\t_viewEvents: viewEvents,\n\n\t\t_handleMouseEvent: function(type, event, point) {\n\t\t\tvar itemEvents = this._itemEvents,\n\t\t\t\thitItems = itemEvents.native[type],\n\t\t\t\tnativeMove = type === 'mousemove',\n\t\t\t\ttool = this._scope.tool,\n\t\t\t\tview = this;\n\n\t\t\tfunction responds(type) {\n\t\t\t\treturn itemEvents.virtual[type] || view.responds(type)\n\t\t\t\t\t\t|| tool && tool.responds(type);\n\t\t\t}\n\n\t\t\tif (nativeMove && dragging && responds('mousedrag'))\n\t\t\t\ttype = 'mousedrag';\n\t\t\tif (!point)\n\t\t\t\tpoint = this.getEventPoint(event);\n\n\t\t\tvar inView = this.getBounds().contains(point),\n\t\t\t\thit = hitItems && inView && view._project.hitTest(point, {\n\t\t\t\t\ttolerance: 0,\n\t\t\t\t\tfill: true,\n\t\t\t\t\tstroke: true\n\t\t\t\t}),\n\t\t\t\thitItem = hit && hit.item || null,\n\t\t\t\thandle = false,\n\t\t\t\tmouse = {};\n\t\t\tmouse[type.substr(5)] = true;\n\n\t\t\tif (hitItems && hitItem !== overItem) {\n\t\t\t\tif (overItem) {\n\t\t\t\t\temitMouseEvent(overItem, null, 'mouseleave', event, point);\n\t\t\t\t}\n\t\t\t\tif (hitItem) {\n\t\t\t\t\temitMouseEvent(hitItem, null, 'mouseenter', event, point);\n\t\t\t\t}\n\t\t\t\toverItem = hitItem;\n\t\t\t}\n\t\t\tif (wasInView ^ inView) {\n\t\t\t\temitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave',\n\t\t\t\t\t\tevent, point);\n\t\t\t\toverView = inView ? this : null;\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\tif ((inView || mouse.drag) && !point.equals(lastPoint)) {\n\t\t\t\temitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',\n\t\t\t\t\t\tevent, point, lastPoint);\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\twasInView = inView;\n\t\t\tif (mouse.down && inView || mouse.up && downPoint) {\n\t\t\t\temitMouseEvents(this, hitItem, type, event, point, downPoint);\n\t\t\t\tif (mouse.down) {\n\t\t\t\t\tdblClick = hitItem === clickItem\n\t\t\t\t\t\t&& (Date.now() - clickTime < 300);\n\t\t\t\t\tdownItem = clickItem = hitItem;\n\t\t\t\t\tdragItem = !prevented && hitItem;\n\t\t\t\t\tdownPoint = point;\n\t\t\t\t} else if (mouse.up) {\n\t\t\t\t\tif (!prevented && hitItem === downItem) {\n\t\t\t\t\t\tclickTime = Date.now();\n\t\t\t\t\t\temitMouseEvents(this, hitItem, dblClick ? 'doubleclick'\n\t\t\t\t\t\t\t\t: 'click', event, point, downPoint);\n\t\t\t\t\t\tdblClick = false;\n\t\t\t\t\t}\n\t\t\t\t\tdownItem = dragItem = null;\n\t\t\t\t}\n\t\t\t\twasInView = false;\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\tlastPoint = point;\n\t\t\tif (handle && tool) {\n\t\t\t\tcalled = tool._handleMouseEvent(type, event, point, mouse)\n\t\t\t\t\t|| called;\n\t\t\t}\n\n\t\t\tif (called && !mouse.move || mouse.down && responds('mouseup'))\n\t\t\t\tevent.preventDefault();\n\t\t},\n\n\t\t_handleKeyEvent: function(type, event, key, character) {\n\t\t\tvar scope = this._scope,\n\t\t\t\ttool = scope.tool,\n\t\t\t\tkeyEvent;\n\n\t\t\tfunction emit(obj) {\n\t\t\t\tif (obj.responds(type)) {\n\t\t\t\t\tpaper = scope;\n\t\t\t\t\tobj.emit(type, keyEvent = keyEvent\n\t\t\t\t\t\t\t|| new KeyEvent(type, event, key, character));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.isVisible()) {\n\t\t\t\temit(this);\n\t\t\t\tif (tool && tool.responds(type))\n\t\t\t\t\temit(tool);\n\t\t\t}\n\t\t},\n\n\t\t_countItemEvent: function(type, sign) {\n\t\t\tvar itemEvents = this._itemEvents,\n\t\t\t\tnative = itemEvents.native,\n\t\t\t\tvirtual = itemEvents.virtual;\n\t\t\tfor (var key in itemEventsMap) {\n\t\t\t\tnative[key] = (native[key] || 0)\n\t\t\t\t\t\t+ (itemEventsMap[key][type] || 0) * sign;\n\t\t\t}\n\t\t\tvirtual[type] = (virtual[type] || 0) + sign;\n\t\t},\n\n\t\tstatics: {\n\t\t\tupdateFocus: updateFocus\n\t\t}\n\t};\n});\n\nvar CanvasView = View.extend({\n\t_class: 'CanvasView',\n\n\tinitialize: function CanvasView(project, canvas) {\n\t\tif (!(canvas instanceof window.HTMLCanvasElement)) {\n\t\t\tvar size = Size.read(arguments, 1);\n\t\t\tif (size.isZero())\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Cannot create CanvasView with the provided argument: '\n\t\t\t\t\t\t+ Base.slice(arguments, 1));\n\t\t\tcanvas = CanvasProvider.getCanvas(size);\n\t\t}\n\t\tvar ctx = this._context = canvas.getContext('2d');\n\t\tctx.save();\n\t\tthis._pixelRatio = 1;\n\t\tif (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {\n\t\t\tvar deviceRatio = window.devicePixelRatio || 1,\n\t\t\t\tbackingStoreRatio = DomElement.getPrefixed(ctx,\n\t\t\t\t\t\t'backingStorePixelRatio') || 1;\n\t\t\tthis._pixelRatio = deviceRatio / backingStoreRatio;\n\t\t}\n\t\tView.call(this, project, canvas);\n\t\tthis._needsUpdate = true;\n\t},\n\n\tremove: function remove() {\n\t\tthis._context.restore();\n\t\treturn remove.base.call(this);\n\t},\n\n\t_setElementSize: function _setElementSize(width, height) {\n\t\tvar pixelRatio = this._pixelRatio;\n\t\t_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);\n\t\tif (pixelRatio !== 1) {\n\t\t\tvar element = this._element,\n\t\t\t\tctx = this._context;\n\t\t\tif (!PaperScope.hasAttribute(element, 'resize')) {\n\t\t\t\tvar style = element.style;\n\t\t\t\tstyle.width = width + 'px';\n\t\t\t\tstyle.height = height + 'px';\n\t\t\t}\n\t\t\tctx.restore();\n\t\t\tctx.save();\n\t\t\tctx.scale(pixelRatio, pixelRatio);\n\t\t}\n\t},\n\n\tgetPixelSize: function getPixelSize(size) {\n\t\tvar agent = paper.agent,\n\t\t\tpixels;\n\t\tif (agent && agent.firefox) {\n\t\t\tpixels = getPixelSize.base.call(this, size);\n\t\t} else {\n\t\t\tvar ctx = this._context,\n\t\t\t\tprevFont = ctx.font;\n\t\t\tctx.font = size + ' serif';\n\t\t\tpixels = parseFloat(ctx.font);\n\t\t\tctx.font = prevFont;\n\t\t}\n\t\treturn pixels;\n\t},\n\n\tgetTextWidth: function(font, lines) {\n\t\tvar ctx = this._context,\n\t\t\tprevFont = ctx.font,\n\t\t\twidth = 0;\n\t\tctx.font = font;\n\t\tfor (var i = 0, l = lines.length; i < l; i++)\n\t\t\twidth = Math.max(width, ctx.measureText(lines[i]).width);\n\t\tctx.font = prevFont;\n\t\treturn width;\n\t},\n\n\tupdate: function() {\n\t\tif (!this._needsUpdate)\n\t\t\treturn false;\n\t\tvar project = this._project,\n\t\t\tctx = this._context,\n\t\t\tsize = this._viewSize;\n\t\tctx.clearRect(0, 0, size.width + 1, size.height + 1);\n\t\tif (project)\n\t\t\tproject.draw(ctx, this._matrix, this._pixelRatio);\n\t\tthis._needsUpdate = false;\n\t\treturn true;\n\t}\n});\n\nvar Event = Base.extend({\n\t_class: 'Event',\n\n\tinitialize: function Event(event) {\n\t\tthis.event = event;\n\t\tthis.type = event && event.type;\n\t},\n\n\tprevented: false,\n\tstopped: false,\n\n\tpreventDefault: function() {\n\t\tthis.prevented = true;\n\t\tthis.event.preventDefault();\n\t},\n\n\tstopPropagation: function() {\n\t\tthis.stopped = true;\n\t\tthis.event.stopPropagation();\n\t},\n\n\tstop: function() {\n\t\tthis.stopPropagation();\n\t\tthis.preventDefault();\n\t},\n\n\tgetTimeStamp: function() {\n\t\treturn this.event.timeStamp;\n\t},\n\n\tgetModifiers: function() {\n\t\treturn Key.modifiers;\n\t}\n});\n\nvar KeyEvent = Event.extend({\n\t_class: 'KeyEvent',\n\n\tinitialize: function KeyEvent(type, event, key, character) {\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t\tthis.key = key;\n\t\tthis.character = character;\n\t},\n\n\ttoString: function() {\n\t\treturn \"{ type: '\" + this.type\n\t\t\t\t+ \"', key: '\" + this.key\n\t\t\t\t+ \"', character: '\" + this.character\n\t\t\t\t+ \"', modifiers: \" + this.getModifiers()\n\t\t\t\t+ \" }\";\n\t}\n});\n\nvar Key = new function() {\n\tvar keyLookup = {\n\t\t\t'\\t': 'tab',\n\t\t\t' ': 'space',\n\t\t\t'\\b': 'backspace',\n\t\t\t'\\x7f': 'delete',\n\t\t\t'Spacebar': 'space',\n\t\t\t'Del': 'delete',\n\t\t\t'Win': 'meta',\n\t\t\t'Esc': 'escape'\n\t\t},\n\n\t\tcharLookup = {\n\t\t\t'tab': '\\t',\n\t\t\t'space': ' ',\n\t\t\t'enter': '\\r'\n\t\t},\n\n\t\tkeyMap = {},\n\t\tcharMap = {},\n\t\tmetaFixMap,\n\t\tdownKey,\n\n\t\tmodifiers = new Base({\n\t\t\tshift: false,\n\t\t\tcontrol: false,\n\t\t\talt: false,\n\t\t\tmeta: false,\n\t\t\tcapsLock: false,\n\t\t\tspace: false\n\t\t}).inject({\n\t\t\toption: {\n\t\t\t\tget: function() {\n\t\t\t\t\treturn this.alt;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tcommand: {\n\t\t\t\tget: function() {\n\t\t\t\t\tvar agent = paper && paper.agent;\n\t\t\t\t\treturn agent && agent.mac ? this.meta : this.control;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\tfunction getKey(event) {\n\t\tvar key = event.key || event.keyIdentifier;\n\t\tkey = /^U\\+/.test(key)\n\t\t\t\t? String.fromCharCode(parseInt(key.substr(2), 16))\n\t\t\t\t: /^Arrow[A-Z]/.test(key) ? key.substr(5)\n\t\t\t\t: key === 'Unidentified' ? String.fromCharCode(event.keyCode)\n\t\t\t\t: key;\n\t\treturn keyLookup[key] ||\n\t\t\t\t(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());\n\t}\n\n\tfunction handleKey(down, key, character, event) {\n\t\tvar type = down ? 'keydown' : 'keyup',\n\t\t\tview = View._focused,\n\t\t\tname;\n\t\tkeyMap[key] = down;\n\t\tif (down) {\n\t\t\tcharMap[key] = character;\n\t\t} else {\n\t\t\tdelete charMap[key];\n\t\t}\n\t\tif (key.length > 1 && (name = Base.camelize(key)) in modifiers) {\n\t\t\tmodifiers[name] = down;\n\t\t\tvar agent = paper && paper.agent;\n\t\t\tif (name === 'meta' && agent && agent.mac) {\n\t\t\t\tif (down) {\n\t\t\t\t\tmetaFixMap = {};\n\t\t\t\t} else {\n\t\t\t\t\tfor (var k in metaFixMap) {\n\t\t\t\t\t\tif (k in charMap)\n\t\t\t\t\t\t\thandleKey(false, k, metaFixMap[k], event);\n\t\t\t\t\t}\n\t\t\t\t\tmetaFixMap = null;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (down && metaFixMap) {\n\t\t\tmetaFixMap[key] = character;\n\t\t}\n\t\tif (view) {\n\t\t\tview._handleKeyEvent(down ? 'keydown' : 'keyup', event, key,\n\t\t\t\t\tcharacter);\n\t\t}\n\t}\n\n\tDomEvent.add(document, {\n\t\tkeydown: function(event) {\n\t\t\tvar key = getKey(event),\n\t\t\t\tagent = paper && paper.agent;\n\t\t\tif (key.length > 1 || agent && (agent.chrome && (event.altKey\n\t\t\t\t\t\t|| agent.mac && event.metaKey\n\t\t\t\t\t\t|| !agent.mac && event.ctrlKey))) {\n\t\t\t\thandleKey(true, key,\n\t\t\t\t\t\tcharLookup[key] || (key.length > 1 ? '' : key), event);\n\t\t\t} else {\n\t\t\t\tdownKey = key;\n\t\t\t}\n\t\t},\n\n\t\tkeypress: function(event) {\n\t\t\tif (downKey) {\n\t\t\t\tvar key = getKey(event),\n\t\t\t\t\tcode = event.charCode,\n\t\t\t\t\tcharacter = code >= 32 ? String.fromCharCode(code)\n\t\t\t\t\t\t: key.length > 1 ? '' : key;\n\t\t\t\tif (key !== downKey) {\n\t\t\t\t\tkey = character.toLowerCase();\n\t\t\t\t}\n\t\t\t\thandleKey(true, key, character, event);\n\t\t\t\tdownKey = null;\n\t\t\t}\n\t\t},\n\n\t\tkeyup: function(event) {\n\t\t\tvar key = getKey(event);\n\t\t\tif (key in charMap)\n\t\t\t\thandleKey(false, key, charMap[key], event);\n\t\t}\n\t});\n\n\tDomEvent.add(window, {\n\t\tblur: function(event) {\n\t\t\tfor (var key in charMap)\n\t\t\t\thandleKey(false, key, charMap[key], event);\n\t\t}\n\t});\n\n\treturn {\n\t\tmodifiers: modifiers,\n\n\t\tisDown: function(key) {\n\t\t\treturn !!keyMap[key];\n\t\t}\n\t};\n};\n\nvar MouseEvent = Event.extend({\n\t_class: 'MouseEvent',\n\n\tinitialize: function MouseEvent(type, event, point, target, delta) {\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t\tthis.point = point;\n\t\tthis.target = target;\n\t\tthis.delta = delta;\n\t},\n\n\ttoString: function() {\n\t\treturn \"{ type: '\" + this.type\n\t\t\t\t+ \"', point: \" + this.point\n\t\t\t\t+ ', target: ' + this.target\n\t\t\t\t+ (this.delta ? ', delta: ' + this.delta : '')\n\t\t\t\t+ ', modifiers: ' + this.getModifiers()\n\t\t\t\t+ ' }';\n\t}\n});\n\nvar ToolEvent = Event.extend({\n\t_class: 'ToolEvent',\n\t_item: null,\n\n\tinitialize: function ToolEvent(tool, type, event) {\n\t\tthis.tool = tool;\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t},\n\n\t_choosePoint: function(point, toolPoint) {\n\t\treturn point ? point : toolPoint ? toolPoint.clone() : null;\n\t},\n\n\tgetPoint: function() {\n\t\treturn this._choosePoint(this._point, this.tool._point);\n\t},\n\n\tsetPoint: function(point) {\n\t\tthis._point = point;\n\t},\n\n\tgetLastPoint: function() {\n\t\treturn this._choosePoint(this._lastPoint, this.tool._lastPoint);\n\t},\n\n\tsetLastPoint: function(lastPoint) {\n\t\tthis._lastPoint = lastPoint;\n\t},\n\n\tgetDownPoint: function() {\n\t\treturn this._choosePoint(this._downPoint, this.tool._downPoint);\n\t},\n\n\tsetDownPoint: function(downPoint) {\n\t\tthis._downPoint = downPoint;\n\t},\n\n\tgetMiddlePoint: function() {\n\t\tif (!this._middlePoint && this.tool._lastPoint) {\n\t\t\treturn this.tool._point.add(this.tool._lastPoint).divide(2);\n\t\t}\n\t\treturn this._middlePoint;\n\t},\n\n\tsetMiddlePoint: function(middlePoint) {\n\t\tthis._middlePoint = middlePoint;\n\t},\n\n\tgetDelta: function() {\n\t\treturn !this._delta && this.tool._lastPoint\n\t\t\t\t? this.tool._point.subtract(this.tool._lastPoint)\n\t\t\t\t: this._delta;\n\t},\n\n\tsetDelta: function(delta) {\n\t\tthis._delta = delta;\n\t},\n\n\tgetCount: function() {\n\t\treturn this.tool[/^mouse(down|up)$/.test(this.type)\n\t\t\t\t? '_downCount' : '_moveCount'];\n\t},\n\n\tsetCount: function(count) {\n\t\tthis.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']\n\t\t\t= count;\n\t},\n\n\tgetItem: function() {\n\t\tif (!this._item) {\n\t\t\tvar result = this.tool._scope.project.hitTest(this.getPoint());\n\t\t\tif (result) {\n\t\t\t\tvar item = result.item,\n\t\t\t\t\tparent = item._parent;\n\t\t\t\twhile (/^(Group|CompoundPath)$/.test(parent._class)) {\n\t\t\t\t\titem = parent;\n\t\t\t\t\tparent = parent._parent;\n\t\t\t\t}\n\t\t\t\tthis._item = item;\n\t\t\t}\n\t\t}\n\t\treturn this._item;\n\t},\n\n\tsetItem: function(item) {\n\t\tthis._item = item;\n\t},\n\n\ttoString: function() {\n\t\treturn '{ type: ' + this.type\n\t\t\t\t+ ', point: ' + this.getPoint()\n\t\t\t\t+ ', count: ' + this.getCount()\n\t\t\t\t+ ', modifiers: ' + this.getModifiers()\n\t\t\t\t+ ' }';\n\t}\n});\n\nvar Tool = PaperScopeItem.extend({\n\t_class: 'Tool',\n\t_list: 'tools',\n\t_reference: 'tool',\n\t_events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',\n\t\t\t'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown',\n\t\t\t'onKeyUp'],\n\n\tinitialize: function Tool(props) {\n\t\tPaperScopeItem.call(this);\n\t\tthis._moveCount = -1;\n\t\tthis._downCount = -1;\n\t\tthis._set(props);\n\t},\n\n\tgetMinDistance: function() {\n\t\treturn this._minDistance;\n\t},\n\n\tsetMinDistance: function(minDistance) {\n\t\tthis._minDistance = minDistance;\n\t\tif (minDistance != null && this._maxDistance != null\n\t\t\t\t&& minDistance > this._maxDistance) {\n\t\t\tthis._maxDistance = minDistance;\n\t\t}\n\t},\n\n\tgetMaxDistance: function() {\n\t\treturn this._maxDistance;\n\t},\n\n\tsetMaxDistance: function(maxDistance) {\n\t\tthis._maxDistance = maxDistance;\n\t\tif (this._minDistance != null && maxDistance != null\n\t\t\t\t&& maxDistance < this._minDistance) {\n\t\t\tthis._minDistance = maxDistance;\n\t\t}\n\t},\n\n\tgetFixedDistance: function() {\n\t\treturn this._minDistance == this._maxDistance\n\t\t\t? this._minDistance : null;\n\t},\n\n\tsetFixedDistance: function(distance) {\n\t\tthis._minDistance = this._maxDistance = distance;\n\t},\n\n\t_handleMouseEvent: function(type, event, point, mouse) {\n\t\tpaper = this._scope;\n\t\tif (mouse.drag && !this.responds(type))\n\t\t\ttype = 'mousemove';\n\t\tvar move = mouse.move || mouse.drag,\n\t\t\tresponds = this.responds(type),\n\t\t\tminDistance = this.minDistance,\n\t\t\tmaxDistance = this.maxDistance,\n\t\t\tcalled = false,\n\t\t\ttool = this;\n\t\tfunction update(minDistance, maxDistance) {\n\t\t\tvar pt = point,\n\t\t\t\ttoolPoint = move ? tool._point : (tool._downPoint || pt);\n\t\t\tif (move) {\n\t\t\t\tif (tool._moveCount && pt.equals(toolPoint)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (toolPoint && (minDistance != null || maxDistance != null)) {\n\t\t\t\t\tvar vector = pt.subtract(toolPoint),\n\t\t\t\t\t\tdistance = vector.getLength();\n\t\t\t\t\tif (distance < (minDistance || 0))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (maxDistance) {\n\t\t\t\t\t\tpt = toolPoint.add(vector.normalize(\n\t\t\t\t\t\t\t\tMath.min(distance, maxDistance)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttool._moveCount++;\n\t\t\t}\n\t\t\ttool._point = pt;\n\t\t\ttool._lastPoint = toolPoint || pt;\n\t\t\tif (mouse.down) {\n\t\t\t\ttool._moveCount = -1;\n\t\t\t\ttool._downPoint = pt;\n\t\t\t\ttool._downCount++;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction emit() {\n\t\t\tif (responds) {\n\t\t\t\tcalled = tool.emit(type, new ToolEvent(tool, type, event))\n\t\t\t\t\t\t|| called;\n\t\t\t}\n\t\t}\n\n\t\tif (mouse.down) {\n\t\t\tupdate();\n\t\t\temit();\n\t\t} else if (mouse.up) {\n\t\t\tupdate(null, maxDistance);\n\t\t\temit();\n\t\t} else if (responds) {\n\t\t\twhile (update(minDistance, maxDistance))\n\t\t\t\temit();\n\t\t}\n\t\treturn called;\n\t}\n\n});\n\nvar Http = {\n\trequest: function(options) {\n\t\tvar xhr = new self.XMLHttpRequest();\n\t\txhr.open((options.method || 'get').toUpperCase(), options.url,\n\t\t\t\tBase.pick(options.async, true));\n\t\tif (options.mimeType)\n\t\t\txhr.overrideMimeType(options.mimeType);\n\t\txhr.onload = function() {\n\t\t\tvar status = xhr.status;\n\t\t\tif (status === 0 || status === 200) {\n\t\t\t\tif (options.onLoad) {\n\t\t\t\t\toptions.onLoad.call(xhr, xhr.responseText);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\txhr.onerror();\n\t\t\t}\n\t\t};\n\t\txhr.onerror = function() {\n\t\t\tvar status = xhr.status,\n\t\t\t\tmessage = 'Could not load \"' + options.url + '\" (Status: '\n\t\t\t\t\t\t+ status + ')';\n\t\t\tif (options.onError) {\n\t\t\t\toptions.onError(message, status);\n\t\t\t} else {\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\t\t};\n\t\treturn xhr.send(null);\n\t}\n};\n\nvar CanvasProvider = {\n\tcanvases: [],\n\n\tgetCanvas: function(width, height) {\n\t\tif (!window)\n\t\t\treturn null;\n\t\tvar canvas,\n\t\t\tclear = true;\n\t\tif (typeof width === 'object') {\n\t\t\theight = width.height;\n\t\t\twidth = width.width;\n\t\t}\n\t\tif (this.canvases.length) {\n\t\t\tcanvas = this.canvases.pop();\n\t\t} else {\n\t\t\tcanvas = document.createElement('canvas');\n\t\t\tclear = false;\n\t\t}\n\t\tvar ctx = canvas.getContext('2d');\n\t\tif (!ctx) {\n\t\t\tthrow new Error('Canvas ' + canvas +\n\t\t\t\t\t' is unable toprovide a 2D context.');\n\t\t}\n\t\tif (canvas.width === width && canvas.height === height) {\n\t\t\tif (clear)\n\t\t\t\tctx.clearRect(0, 0, width + 1, height + 1);\n\t\t} else {\n\t\t\tcanvas.width = width;\n\t\t\tcanvas.height = height;\n\t\t}\n\t\tctx.save();\n\t\treturn canvas;\n\t},\n\n\tgetContext: function(width, height) {\n\t\tvar canvas = this.getCanvas(width, height);\n\t\treturn canvas ? canvas.getContext('2d') : null;\n\t},\n\n\trelease: function(obj) {\n\t\tvar canvas = obj && obj.canvas ? obj.canvas : obj;\n\t\tif (canvas && canvas.getContext) {\n\t\t\tcanvas.getContext('2d').restore();\n\t\t\tthis.canvases.push(canvas);\n\t\t}\n\t}\n};\n\nvar BlendMode = new function() {\n\tvar min = Math.min,\n\t\tmax = Math.max,\n\t\tabs = Math.abs,\n\t\tsr, sg, sb, sa,\n\t\tbr, bg, bb, ba,\n\t\tdr, dg, db;\n\n\tfunction getLum(r, g, b) {\n\t\treturn 0.2989 * r + 0.587 * g + 0.114 * b;\n\t}\n\n\tfunction setLum(r, g, b, l) {\n\t\tvar d = l - getLum(r, g, b);\n\t\tdr = r + d;\n\t\tdg = g + d;\n\t\tdb = b + d;\n\t\tvar l = getLum(dr, dg, db),\n\t\t\tmn = min(dr, dg, db),\n\t\t\tmx = max(dr, dg, db);\n\t\tif (mn < 0) {\n\t\t\tvar lmn = l - mn;\n\t\t\tdr = l + (dr - l) * l / lmn;\n\t\t\tdg = l + (dg - l) * l / lmn;\n\t\t\tdb = l + (db - l) * l / lmn;\n\t\t}\n\t\tif (mx > 255) {\n\t\t\tvar ln = 255 - l,\n\t\t\t\tmxl = mx - l;\n\t\t\tdr = l + (dr - l) * ln / mxl;\n\t\t\tdg = l + (dg - l) * ln / mxl;\n\t\t\tdb = l + (db - l) * ln / mxl;\n\t\t}\n\t}\n\n\tfunction getSat(r, g, b) {\n\t\treturn max(r, g, b) - min(r, g, b);\n\t}\n\n\tfunction setSat(r, g, b, s) {\n\t\tvar col = [r, g, b],\n\t\t\tmx = max(r, g, b),\n\t\t\tmn = min(r, g, b),\n\t\t\tmd;\n\t\tmn = mn === r ? 0 : mn === g ? 1 : 2;\n\t\tmx = mx === r ? 0 : mx === g ? 1 : 2;\n\t\tmd = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;\n\t\tif (col[mx] > col[mn]) {\n\t\t\tcol[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);\n\t\t\tcol[mx] = s;\n\t\t} else {\n\t\t\tcol[md] = col[mx] = 0;\n\t\t}\n\t\tcol[mn] = 0;\n\t\tdr = col[0];\n\t\tdg = col[1];\n\t\tdb = col[2];\n\t}\n\n\tvar modes = {\n\t\tmultiply: function() {\n\t\t\tdr = br * sr / 255;\n\t\t\tdg = bg * sg / 255;\n\t\t\tdb = bb * sb / 255;\n\t\t},\n\n\t\tscreen: function() {\n\t\t\tdr = br + sr - (br * sr / 255);\n\t\t\tdg = bg + sg - (bg * sg / 255);\n\t\t\tdb = bb + sb - (bb * sb / 255);\n\t\t},\n\n\t\toverlay: function() {\n\t\t\tdr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;\n\t\t\tdg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;\n\t\t\tdb = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;\n\t\t},\n\n\t\t'soft-light': function() {\n\t\t\tvar t = sr * br / 255;\n\t\t\tdr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;\n\t\t\tt = sg * bg / 255;\n\t\t\tdg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;\n\t\t\tt = sb * bb / 255;\n\t\t\tdb = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;\n\t\t},\n\n\t\t'hard-light': function() {\n\t\t\tdr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;\n\t\t\tdg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;\n\t\t\tdb = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;\n\t\t},\n\n\t\t'color-dodge': function() {\n\t\t\tdr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));\n\t\t\tdg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));\n\t\t\tdb = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));\n\t\t},\n\n\t\t'color-burn': function() {\n\t\t\tdr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);\n\t\t\tdg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);\n\t\t\tdb = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);\n\t\t},\n\n\t\tdarken: function() {\n\t\t\tdr = br < sr ? br : sr;\n\t\t\tdg = bg < sg ? bg : sg;\n\t\t\tdb = bb < sb ? bb : sb;\n\t\t},\n\n\t\tlighten: function() {\n\t\t\tdr = br > sr ? br : sr;\n\t\t\tdg = bg > sg ? bg : sg;\n\t\t\tdb = bb > sb ? bb : sb;\n\t\t},\n\n\t\tdifference: function() {\n\t\t\tdr = br - sr;\n\t\t\tif (dr < 0)\n\t\t\t\tdr = -dr;\n\t\t\tdg = bg - sg;\n\t\t\tif (dg < 0)\n\t\t\t\tdg = -dg;\n\t\t\tdb = bb - sb;\n\t\t\tif (db < 0)\n\t\t\t\tdb = -db;\n\t\t},\n\n\t\texclusion: function() {\n\t\t\tdr = br + sr * (255 - br - br) / 255;\n\t\t\tdg = bg + sg * (255 - bg - bg) / 255;\n\t\t\tdb = bb + sb * (255 - bb - bb) / 255;\n\t\t},\n\n\t\thue: function() {\n\t\t\tsetSat(sr, sg, sb, getSat(br, bg, bb));\n\t\t\tsetLum(dr, dg, db, getLum(br, bg, bb));\n\t\t},\n\n\t\tsaturation: function() {\n\t\t\tsetSat(br, bg, bb, getSat(sr, sg, sb));\n\t\t\tsetLum(dr, dg, db, getLum(br, bg, bb));\n\t\t},\n\n\t\tluminosity: function() {\n\t\t\tsetLum(br, bg, bb, getLum(sr, sg, sb));\n\t\t},\n\n\t\tcolor: function() {\n\t\t\tsetLum(sr, sg, sb, getLum(br, bg, bb));\n\t\t},\n\n\t\tadd: function() {\n\t\t\tdr = min(br + sr, 255);\n\t\t\tdg = min(bg + sg, 255);\n\t\t\tdb = min(bb + sb, 255);\n\t\t},\n\n\t\tsubtract: function() {\n\t\t\tdr = max(br - sr, 0);\n\t\t\tdg = max(bg - sg, 0);\n\t\t\tdb = max(bb - sb, 0);\n\t\t},\n\n\t\taverage: function() {\n\t\t\tdr = (br + sr) / 2;\n\t\t\tdg = (bg + sg) / 2;\n\t\t\tdb = (bb + sb) / 2;\n\t\t},\n\n\t\tnegation: function() {\n\t\t\tdr = 255 - abs(255 - sr - br);\n\t\t\tdg = 255 - abs(255 - sg - bg);\n\t\t\tdb = 255 - abs(255 - sb - bb);\n\t\t}\n\t};\n\n\tvar nativeModes = this.nativeModes = Base.each([\n\t\t'source-over', 'source-in', 'source-out', 'source-atop',\n\t\t'destination-over', 'destination-in', 'destination-out',\n\t\t'destination-atop', 'lighter', 'darker', 'copy', 'xor'\n\t], function(mode) {\n\t\tthis[mode] = true;\n\t}, {});\n\n\tvar ctx = CanvasProvider.getContext(1, 1);\n\tif (ctx) {\n\t\tBase.each(modes, function(func, mode) {\n\t\t\tvar darken = mode === 'darken',\n\t\t\t\tok = false;\n\t\t\tctx.save();\n\t\t\ttry {\n\t\t\t\tctx.fillStyle = darken ? '#300' : '#a00';\n\t\t\t\tctx.fillRect(0, 0, 1, 1);\n\t\t\t\tctx.globalCompositeOperation = mode;\n\t\t\t\tif (ctx.globalCompositeOperation === mode) {\n\t\t\t\t\tctx.fillStyle = darken ? '#a00' : '#300';\n\t\t\t\t\tctx.fillRect(0, 0, 1, 1);\n\t\t\t\t\tok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken\n\t\t\t\t\t\t\t? 170 : 51;\n\t\t\t\t}\n\t\t\t} catch (e) {}\n\t\t\tctx.restore();\n\t\t\tnativeModes[mode] = ok;\n\t\t});\n\t\tCanvasProvider.release(ctx);\n\t}\n\n\tthis.process = function(mode, srcContext, dstContext, alpha, offset) {\n\t\tvar srcCanvas = srcContext.canvas,\n\t\t\tnormal = mode === 'normal';\n\t\tif (normal || nativeModes[mode]) {\n\t\t\tdstContext.save();\n\t\t\tdstContext.setTransform(1, 0, 0, 1, 0, 0);\n\t\t\tdstContext.globalAlpha = alpha;\n\t\t\tif (!normal)\n\t\t\t\tdstContext.globalCompositeOperation = mode;\n\t\t\tdstContext.drawImage(srcCanvas, offset.x, offset.y);\n\t\t\tdstContext.restore();\n\t\t} else {\n\t\t\tvar process = modes[mode];\n\t\t\tif (!process)\n\t\t\t\treturn;\n\t\t\tvar dstData = dstContext.getImageData(offset.x, offset.y,\n\t\t\t\t\tsrcCanvas.width, srcCanvas.height),\n\t\t\t\tdst = dstData.data,\n\t\t\t\tsrc = srcContext.getImageData(0, 0,\n\t\t\t\t\tsrcCanvas.width, srcCanvas.height).data;\n\t\t\tfor (var i = 0, l = dst.length; i < l; i += 4) {\n\t\t\t\tsr = src[i];\n\t\t\t\tbr = dst[i];\n\t\t\t\tsg = src[i + 1];\n\t\t\t\tbg = dst[i + 1];\n\t\t\t\tsb = src[i + 2];\n\t\t\t\tbb = dst[i + 2];\n\t\t\t\tsa = src[i + 3];\n\t\t\t\tba = dst[i + 3];\n\t\t\t\tprocess();\n\t\t\t\tvar a1 = sa * alpha / 255,\n\t\t\t\t\ta2 = 1 - a1;\n\t\t\t\tdst[i] = a1 * dr + a2 * br;\n\t\t\t\tdst[i + 1] = a1 * dg + a2 * bg;\n\t\t\t\tdst[i + 2] = a1 * db + a2 * bb;\n\t\t\t\tdst[i + 3] = sa * alpha + a2 * ba;\n\t\t\t}\n\t\t\tdstContext.putImageData(dstData, offset.x, offset.y);\n\t\t}\n\t};\n};\n\nvar SvgElement = new function() {\n\tvar svg = 'http://www.w3.org/2000/svg',\n\t\txmlns = 'http://www.w3.org/2000/xmlns',\n\t\txlink = 'http://www.w3.org/1999/xlink',\n\t\tattributeNamespace = {\n\t\t\thref: xlink,\n\t\t\txlink: xmlns,\n\t\t\txmlns: xmlns + '/',\n\t\t\t'xmlns:xlink': xmlns + '/'\n\t\t};\n\n\tfunction create(tag, attributes, formatter) {\n\t\treturn set(document.createElementNS(svg, tag), attributes, formatter);\n\t}\n\n\tfunction get(node, name) {\n\t\tvar namespace = attributeNamespace[name],\n\t\t\tvalue = namespace\n\t\t\t\t? node.getAttributeNS(namespace, name)\n\t\t\t\t: node.getAttribute(name);\n\t\treturn value === 'null' ? null : value;\n\t}\n\n\tfunction set(node, attributes, formatter) {\n\t\tfor (var name in attributes) {\n\t\t\tvar value = attributes[name],\n\t\t\t\tnamespace = attributeNamespace[name];\n\t\t\tif (typeof value === 'number' && formatter)\n\t\t\t\tvalue = formatter.number(value);\n\t\t\tif (namespace) {\n\t\t\t\tnode.setAttributeNS(namespace, name, value);\n\t\t\t} else {\n\t\t\t\tnode.setAttribute(name, value);\n\t\t\t}\n\t\t}\n\t\treturn node;\n\t}\n\n\treturn {\n\t\tsvg: svg,\n\t\txmlns: xmlns,\n\t\txlink: xlink,\n\n\t\tcreate: create,\n\t\tget: get,\n\t\tset: set\n\t};\n};\n\nvar SvgStyles = Base.each({\n\tfillColor: ['fill', 'color'],\n\tfillRule: ['fill-rule', 'string'],\n\tstrokeColor: ['stroke', 'color'],\n\tstrokeWidth: ['stroke-width', 'number'],\n\tstrokeCap: ['stroke-linecap', 'string'],\n\tstrokeJoin: ['stroke-linejoin', 'string'],\n\tstrokeScaling: ['vector-effect', 'lookup', {\n\t\ttrue: 'none',\n\t\tfalse: 'non-scaling-stroke'\n\t}, function(item, value) {\n\t\treturn !value\n\t\t\t\t&& (item instanceof PathItem\n\t\t\t\t\t|| item instanceof Shape\n\t\t\t\t\t|| item instanceof TextItem);\n\t}],\n\tmiterLimit: ['stroke-miterlimit', 'number'],\n\tdashArray: ['stroke-dasharray', 'array'],\n\tdashOffset: ['stroke-dashoffset', 'number'],\n\tfontFamily: ['font-family', 'string'],\n\tfontWeight: ['font-weight', 'string'],\n\tfontSize: ['font-size', 'number'],\n\tjustification: ['text-anchor', 'lookup', {\n\t\tleft: 'start',\n\t\tcenter: 'middle',\n\t\tright: 'end'\n\t}],\n\topacity: ['opacity', 'number'],\n\tblendMode: ['mix-blend-mode', 'style']\n}, function(entry, key) {\n\tvar part = Base.capitalize(key),\n\t\tlookup = entry[2];\n\tthis[key] = {\n\t\ttype: entry[1],\n\t\tproperty: key,\n\t\tattribute: entry[0],\n\t\ttoSVG: lookup,\n\t\tfromSVG: lookup && Base.each(lookup, function(value, name) {\n\t\t\tthis[value] = name;\n\t\t}, {}),\n\t\texportFilter: entry[3],\n\t\tget: 'get' + part,\n\t\tset: 'set' + part\n\t};\n}, {});\n\nnew function() {\n\tvar formatter;\n\n\tfunction getTransform(matrix, coordinates, center) {\n\t\tvar attrs = new Base(),\n\t\t\ttrans = matrix.getTranslation();\n\t\tif (coordinates) {\n\t\t\tmatrix = matrix._shiftless();\n\t\t\tvar point = matrix._inverseTransform(trans);\n\t\t\tattrs[center ? 'cx' : 'x'] = point.x;\n\t\t\tattrs[center ? 'cy' : 'y'] = point.y;\n\t\t\ttrans = null;\n\t\t}\n\t\tif (!matrix.isIdentity()) {\n\t\t\tvar decomposed = matrix.decompose();\n\t\t\tif (decomposed) {\n\t\t\t\tvar parts = [],\n\t\t\t\t\tangle = decomposed.rotation,\n\t\t\t\t\tscale = decomposed.scaling,\n\t\t\t\t\tskew = decomposed.skewing;\n\t\t\t\tif (trans && !trans.isZero())\n\t\t\t\t\tparts.push('translate(' + formatter.point(trans) + ')');\n\t\t\t\tif (angle)\n\t\t\t\t\tparts.push('rotate(' + formatter.number(angle) + ')');\n\t\t\t\tif (!Numerical.isZero(scale.x - 1)\n\t\t\t\t\t\t|| !Numerical.isZero(scale.y - 1))\n\t\t\t\t\tparts.push('scale(' + formatter.point(scale) +')');\n\t\t\t\tif (skew && skew.x)\n\t\t\t\t\tparts.push('skewX(' + formatter.number(skew.x) + ')');\n\t\t\t\tif (skew && skew.y)\n\t\t\t\t\tparts.push('skewY(' + formatter.number(skew.y) + ')');\n\t\t\t\tattrs.transform = parts.join(' ');\n\t\t\t} else {\n\t\t\t\tattrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';\n\t\t\t}\n\t\t}\n\t\treturn attrs;\n\t}\n\n\tfunction exportGroup(item, options) {\n\t\tvar attrs = getTransform(item._matrix),\n\t\t\tchildren = item._children;\n\t\tvar node = SvgElement.create('g', attrs, formatter);\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i];\n\t\t\tvar childNode = exportSVG(child, options);\n\t\t\tif (childNode) {\n\t\t\t\tif (child.isClipMask()) {\n\t\t\t\t\tvar clip = SvgElement.create('clipPath');\n\t\t\t\t\tclip.appendChild(childNode);\n\t\t\t\t\tsetDefinition(child, clip, 'clip');\n\t\t\t\t\tSvgElement.set(node, {\n\t\t\t\t\t\t'clip-path': 'url(#' + clip.id + ')'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tnode.appendChild(childNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn node;\n\t}\n\n\tfunction exportRaster(item, options) {\n\t\tvar attrs = getTransform(item._matrix, true),\n\t\t\tsize = item.getSize(),\n\t\t\timage = item.getImage();\n\t\tattrs.x -= size.width / 2;\n\t\tattrs.y -= size.height / 2;\n\t\tattrs.width = size.width;\n\t\tattrs.height = size.height;\n\t\tattrs.href = options.embedImages === false && image && image.src\n\t\t\t\t|| item.toDataURL();\n\t\treturn SvgElement.create('image', attrs, formatter);\n\t}\n\n\tfunction exportPath(item, options) {\n\t\tvar matchShapes = options.matchShapes;\n\t\tif (matchShapes) {\n\t\t\tvar shape = item.toShape(false);\n\t\t\tif (shape)\n\t\t\t\treturn exportShape(shape, options);\n\t\t}\n\t\tvar segments = item._segments,\n\t\t\tlength = segments.length,\n\t\t\ttype,\n\t\t\tattrs = getTransform(item._matrix);\n\t\tif (matchShapes && length >= 2 && !item.hasHandles()) {\n\t\t\tif (length > 2) {\n\t\t\t\ttype = item._closed ? 'polygon' : 'polyline';\n\t\t\t\tvar parts = [];\n\t\t\t\tfor(var i = 0; i < length; i++)\n\t\t\t\t\tparts.push(formatter.point(segments[i]._point));\n\t\t\t\tattrs.points = parts.join(' ');\n\t\t\t} else {\n\t\t\t\ttype = 'line';\n\t\t\t\tvar start = segments[0]._point,\n\t\t\t\t\tend = segments[1]._point;\n\t\t\t\tattrs.set({\n\t\t\t\t\tx1: start.x,\n\t\t\t\t\ty1: start.y,\n\t\t\t\t\tx2: end.x,\n\t\t\t\t\ty2: end.y\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\ttype = 'path';\n\t\t\tattrs.d = item.getPathData(null, options.precision);\n\t\t}\n\t\treturn SvgElement.create(type, attrs, formatter);\n\t}\n\n\tfunction exportShape(item) {\n\t\tvar type = item._type,\n\t\t\tradius = item._radius,\n\t\t\tattrs = getTransform(item._matrix, true, type !== 'rectangle');\n\t\tif (type === 'rectangle') {\n\t\t\ttype = 'rect';\n\t\t\tvar size = item._size,\n\t\t\t\twidth = size.width,\n\t\t\t\theight = size.height;\n\t\t\tattrs.x -= width / 2;\n\t\t\tattrs.y -= height / 2;\n\t\t\tattrs.width = width;\n\t\t\tattrs.height = height;\n\t\t\tif (radius.isZero())\n\t\t\t\tradius = null;\n\t\t}\n\t\tif (radius) {\n\t\t\tif (type === 'circle') {\n\t\t\t\tattrs.r = radius;\n\t\t\t} else {\n\t\t\t\tattrs.rx = radius.width;\n\t\t\t\tattrs.ry = radius.height;\n\t\t\t}\n\t\t}\n\t\treturn SvgElement.create(type, attrs, formatter);\n\t}\n\n\tfunction exportCompoundPath(item, options) {\n\t\tvar attrs = getTransform(item._matrix);\n\t\tvar data = item.getPathData(null, options.precision);\n\t\tif (data)\n\t\t\tattrs.d = data;\n\t\treturn SvgElement.create('path', attrs, formatter);\n\t}\n\n\tfunction exportSymbolItem(item, options) {\n\t\tvar attrs = getTransform(item._matrix, true),\n\t\t\tdefinition = item._definition,\n\t\t\tnode = getDefinition(definition, 'symbol'),\n\t\t\tdefinitionItem = definition._item,\n\t\t\tbounds = definitionItem.getBounds();\n\t\tif (!node) {\n\t\t\tnode = SvgElement.create('symbol', {\n\t\t\t\tviewBox: formatter.rectangle(bounds)\n\t\t\t});\n\t\t\tnode.appendChild(exportSVG(definitionItem, options));\n\t\t\tsetDefinition(definition, node, 'symbol');\n\t\t}\n\t\tattrs.href = '#' + node.id;\n\t\tattrs.x += bounds.x;\n\t\tattrs.y += bounds.y;\n\t\tattrs.width = bounds.width;\n\t\tattrs.height = bounds.height;\n\t\tattrs.overflow = 'visible';\n\t\treturn SvgElement.create('use', attrs, formatter);\n\t}\n\n\tfunction exportGradient(color) {\n\t\tvar gradientNode = getDefinition(color, 'color');\n\t\tif (!gradientNode) {\n\t\t\tvar gradient = color.getGradient(),\n\t\t\t\tradial = gradient._radial,\n\t\t\t\torigin = color.getOrigin(),\n\t\t\t\tdestination = color.getDestination(),\n\t\t\t\tattrs;\n\t\t\tif (radial) {\n\t\t\t\tattrs = {\n\t\t\t\t\tcx: origin.x,\n\t\t\t\t\tcy: origin.y,\n\t\t\t\t\tr: origin.getDistance(destination)\n\t\t\t\t};\n\t\t\t\tvar highlight = color.getHighlight();\n\t\t\t\tif (highlight) {\n\t\t\t\t\tattrs.fx = highlight.x;\n\t\t\t\t\tattrs.fy = highlight.y;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tattrs = {\n\t\t\t\t\tx1: origin.x,\n\t\t\t\t\ty1: origin.y,\n\t\t\t\t\tx2: destination.x,\n\t\t\t\t\ty2: destination.y\n\t\t\t\t};\n\t\t\t}\n\t\t\tattrs.gradientUnits = 'userSpaceOnUse';\n\t\t\tgradientNode = SvgElement.create((radial ? 'radial' : 'linear')\n\t\t\t\t\t+ 'Gradient', attrs, formatter);\n\t\t\tvar stops = gradient._stops;\n\t\t\tfor (var i = 0, l = stops.length; i < l; i++) {\n\t\t\t\tvar stop = stops[i],\n\t\t\t\t\tstopColor = stop._color,\n\t\t\t\t\talpha = stopColor.getAlpha();\n\t\t\t\tattrs = {\n\t\t\t\t\toffset: stop._offset || i / (l - 1)\n\t\t\t\t};\n\t\t\t\tif (stopColor)\n\t\t\t\t\tattrs['stop-color'] = stopColor.toCSS(true);\n\t\t\t\tif (alpha < 1)\n\t\t\t\t\tattrs['stop-opacity'] = alpha;\n\t\t\t\tgradientNode.appendChild(\n\t\t\t\t\t\tSvgElement.create('stop', attrs, formatter));\n\t\t\t}\n\t\t\tsetDefinition(color, gradientNode, 'color');\n\t\t}\n\t\treturn 'url(#' + gradientNode.id + ')';\n\t}\n\n\tfunction exportText(item) {\n\t\tvar node = SvgElement.create('text', getTransform(item._matrix, true),\n\t\t\t\tformatter);\n\t\tnode.textContent = item._content;\n\t\treturn node;\n\t}\n\n\tvar exporters = {\n\t\tGroup: exportGroup,\n\t\tLayer: exportGroup,\n\t\tRaster: exportRaster,\n\t\tPath: exportPath,\n\t\tShape: exportShape,\n\t\tCompoundPath: exportCompoundPath,\n\t\tSymbolItem: exportSymbolItem,\n\t\tPointText: exportText\n\t};\n\n\tfunction applyStyle(item, node, isRoot) {\n\t\tvar attrs = {},\n\t\t\tparent = !isRoot && item.getParent(),\n\t\t\tstyle = [];\n\n\t\tif (item._name != null)\n\t\t\tattrs.id = item._name;\n\n\t\tBase.each(SvgStyles, function(entry) {\n\t\t\tvar get = entry.get,\n\t\t\t\ttype = entry.type,\n\t\t\t\tvalue = item[get]();\n\t\t\tif (entry.exportFilter\n\t\t\t\t\t? entry.exportFilter(item, value)\n\t\t\t\t\t: !parent || !Base.equals(parent[get](), value)) {\n\t\t\t\tif (type === 'color' && value != null) {\n\t\t\t\t\tvar alpha = value.getAlpha();\n\t\t\t\t\tif (alpha < 1)\n\t\t\t\t\t\tattrs[entry.attribute + '-opacity'] = alpha;\n\t\t\t\t}\n\t\t\t\tif (type === 'style') {\n\t\t\t\t\tstyle.push(entry.attribute + ': ' + value);\n\t\t\t\t} else {\n\t\t\t\t\tattrs[entry.attribute] = value == null ? 'none'\n\t\t\t\t\t\t\t: type === 'color' ? value.gradient\n\t\t\t\t\t\t\t\t? exportGradient(value, item)\n\t\t\t\t\t\t\t\t: value.toCSS(true)\n\t\t\t\t\t\t\t: type === 'array' ? value.join(',')\n\t\t\t\t\t\t\t: type === 'lookup' ? entry.toSVG[value]\n\t\t\t\t\t\t\t: value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif (style.length)\n\t\t\tattrs.style = style.join(';');\n\n\t\tif (attrs.opacity === 1)\n\t\t\tdelete attrs.opacity;\n\n\t\tif (!item._visible)\n\t\t\tattrs.visibility = 'hidden';\n\n\t\treturn SvgElement.set(node, attrs, formatter);\n\t}\n\n\tvar definitions;\n\tfunction getDefinition(item, type) {\n\t\tif (!definitions)\n\t\t\tdefinitions = { ids: {}, svgs: {} };\n\t\tvar id = item._id || item.__id || (item.__id = UID.get('svg'));\n\t\treturn item && definitions.svgs[type + '-' + id];\n\t}\n\n\tfunction setDefinition(item, node, type) {\n\t\tif (!definitions)\n\t\t\tgetDefinition();\n\t\tvar typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;\n\t\tnode.id = type + '-' + typeId;\n\t\tdefinitions.svgs[type + '-' + (item._id || item.__id)] = node;\n\t}\n\n\tfunction exportDefinitions(node, options) {\n\t\tvar svg = node,\n\t\t\tdefs = null;\n\t\tif (definitions) {\n\t\t\tsvg = node.nodeName.toLowerCase() === 'svg' && node;\n\t\t\tfor (var i in definitions.svgs) {\n\t\t\t\tif (!defs) {\n\t\t\t\t\tif (!svg) {\n\t\t\t\t\t\tsvg = SvgElement.create('svg');\n\t\t\t\t\t\tsvg.appendChild(node);\n\t\t\t\t\t}\n\t\t\t\t\tdefs = svg.insertBefore(SvgElement.create('defs'),\n\t\t\t\t\t\t\tsvg.firstChild);\n\t\t\t\t}\n\t\t\t\tdefs.appendChild(definitions.svgs[i]);\n\t\t\t}\n\t\t\tdefinitions = null;\n\t\t}\n\t\treturn options.asString\n\t\t\t\t? new self.XMLSerializer().serializeToString(svg)\n\t\t\t\t: svg;\n\t}\n\n\tfunction exportSVG(item, options, isRoot) {\n\t\tvar exporter = exporters[item._class],\n\t\t\tnode = exporter && exporter(item, options);\n\t\tif (node) {\n\t\t\tvar onExport = options.onExport;\n\t\t\tif (onExport)\n\t\t\t\tnode = onExport(item, node, options) || node;\n\t\t\tvar data = JSON.stringify(item._data);\n\t\t\tif (data && data !== '{}' && data !== 'null')\n\t\t\t\tnode.setAttribute('data-paper-data', data);\n\t\t}\n\t\treturn node && applyStyle(item, node, isRoot);\n\t}\n\n\tfunction setOptions(options) {\n\t\tif (!options)\n\t\t\toptions = {};\n\t\tformatter = new Formatter(options.precision);\n\t\treturn options;\n\t}\n\n\tItem.inject({\n\t\texportSVG: function(options) {\n\t\t\toptions = setOptions(options);\n\t\t\treturn exportDefinitions(exportSVG(this, options, true), options);\n\t\t}\n\t});\n\n\tProject.inject({\n\t\texportSVG: function(options) {\n\t\t\toptions = setOptions(options);\n\t\t\tvar children = this._children,\n\t\t\t\tview = this.getView(),\n\t\t\t\tbounds = Base.pick(options.bounds, 'view'),\n\t\t\t\tmx = options.matrix || bounds === 'view' && view._matrix,\n\t\t\t\tmatrix = mx && Matrix.read([mx]),\n\t\t\t\trect = bounds === 'view'\n\t\t\t\t\t? new Rectangle([0, 0], view.getViewSize())\n\t\t\t\t\t: bounds === 'content'\n\t\t\t\t\t\t? Item._getBounds(children, matrix, { stroke: true })\n\t\t\t\t\t\t: Rectangle.read([bounds], 0, { readNull: true }),\n\t\t\t\tattrs = {\n\t\t\t\t\tversion: '1.1',\n\t\t\t\t\txmlns: SvgElement.svg,\n\t\t\t\t\t'xmlns:xlink': SvgElement.xlink,\n\t\t\t\t};\n\t\t\tif (rect) {\n\t\t\t\tattrs.width = rect.width;\n\t\t\t\tattrs.height = rect.height;\n\t\t\t\tif (rect.x || rect.y)\n\t\t\t\t\tattrs.viewBox = formatter.rectangle(rect);\n\t\t\t}\n\t\t\tvar node = SvgElement.create('svg', attrs, formatter),\n\t\t\t\tparent = node;\n\t\t\tif (matrix && !matrix.isIdentity()) {\n\t\t\t\tparent = node.appendChild(SvgElement.create('g',\n\t\t\t\t\t\tgetTransform(matrix), formatter));\n\t\t\t}\n\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\tparent.appendChild(exportSVG(children[i], options, true));\n\t\t\t}\n\t\t\treturn exportDefinitions(node, options);\n\t\t}\n\t});\n};\n\nnew function() {\n\n\tvar definitions = {},\n\t\trootSize;\n\n\tfunction getValue(node, name, isString, allowNull, allowPercent) {\n\t\tvar value = SvgElement.get(node, name),\n\t\t\tres = value == null\n\t\t\t\t? allowNull\n\t\t\t\t\t? null\n\t\t\t\t\t: isString ? '' : 0\n\t\t\t\t: isString\n\t\t\t\t\t? value\n\t\t\t\t\t: parseFloat(value);\n\t\treturn /%\\s*$/.test(value)\n\t\t\t? (res / 100) * (allowPercent ? 1\n\t\t\t\t: rootSize[/x|^width/.test(name) ? 'width' : 'height'])\n\t\t\t: res;\n\t}\n\n\tfunction getPoint(node, x, y, allowNull, allowPercent) {\n\t\tx = getValue(node, x || 'x', false, allowNull, allowPercent);\n\t\ty = getValue(node, y || 'y', false, allowNull, allowPercent);\n\t\treturn allowNull && (x == null || y == null) ? null\n\t\t\t\t: new Point(x, y);\n\t}\n\n\tfunction getSize(node, w, h, allowNull, allowPercent) {\n\t\tw = getValue(node, w || 'width', false, allowNull, allowPercent);\n\t\th = getValue(node, h || 'height', false, allowNull, allowPercent);\n\t\treturn allowNull && (w == null || h == null) ? null\n\t\t\t\t: new Size(w, h);\n\t}\n\n\tfunction convertValue(value, type, lookup) {\n\t\treturn value === 'none' ? null\n\t\t\t\t: type === 'number' ? parseFloat(value)\n\t\t\t\t: type === 'array' ?\n\t\t\t\t\tvalue ? value.split(/[\\s,]+/g).map(parseFloat) : []\n\t\t\t\t: type === 'color' ? getDefinition(value) || value\n\t\t\t\t: type === 'lookup' ? lookup[value]\n\t\t\t\t: value;\n\t}\n\n\tfunction importGroup(node, type, options, isRoot) {\n\t\tvar nodes = node.childNodes,\n\t\t\tisClip = type === 'clippath',\n\t\t\tisDefs = type === 'defs',\n\t\t\titem = new Group(),\n\t\t\tproject = item._project,\n\t\t\tcurrentStyle = project._currentStyle,\n\t\t\tchildren = [];\n\t\tif (!isClip && !isDefs) {\n\t\t\titem = applyAttributes(item, node, isRoot);\n\t\t\tproject._currentStyle = item._style.clone();\n\t\t}\n\t\tif (isRoot) {\n\t\t\tvar defs = node.querySelectorAll('defs');\n\t\t\tfor (var i = 0, l = defs.length; i < l; i++) {\n\t\t\t\timportNode(defs[i], options, false);\n\t\t\t}\n\t\t}\n\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\tvar childNode = nodes[i],\n\t\t\t\tchild;\n\t\t\tif (childNode.nodeType === 1\n\t\t\t\t\t&& !/^defs$/i.test(childNode.nodeName)\n\t\t\t\t\t&& (child = importNode(childNode, options, false))\n\t\t\t\t\t&& !(child instanceof SymbolDefinition))\n\t\t\t\tchildren.push(child);\n\t\t}\n\t\titem.addChildren(children);\n\t\tif (isClip)\n\t\t\titem = applyAttributes(item.reduce(), node, isRoot);\n\t\tproject._currentStyle = currentStyle;\n\t\tif (isClip || isDefs) {\n\t\t\titem.remove();\n\t\t\titem = null;\n\t\t}\n\t\treturn item;\n\t}\n\n\tfunction importPoly(node, type) {\n\t\tvar coords = node.getAttribute('points').match(\n\t\t\t\t\t/[+-]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][+-]?\\d+)?/g),\n\t\t\tpoints = [];\n\t\tfor (var i = 0, l = coords.length; i < l; i += 2)\n\t\t\tpoints.push(new Point(\n\t\t\t\t\tparseFloat(coords[i]),\n\t\t\t\t\tparseFloat(coords[i + 1])));\n\t\tvar path = new Path(points);\n\t\tif (type === 'polygon')\n\t\t\tpath.closePath();\n\t\treturn path;\n\t}\n\n\tfunction importPath(node) {\n\t\treturn PathItem.create(node.getAttribute('d'));\n\t}\n\n\tfunction importGradient(node, type) {\n\t\tvar id = (getValue(node, 'href', true) || '').substring(1),\n\t\t\tradial = type === 'radialgradient',\n\t\t\tgradient;\n\t\tif (id) {\n\t\t\tgradient = definitions[id].getGradient();\n\t\t\tif (gradient._radial ^ radial) {\n\t\t\t\tgradient = gradient.clone();\n\t\t\t\tgradient._radial = radial;\n\t\t\t}\n\t\t} else {\n\t\t\tvar nodes = node.childNodes,\n\t\t\t\tstops = [];\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tvar child = nodes[i];\n\t\t\t\tif (child.nodeType === 1)\n\t\t\t\t\tstops.push(applyAttributes(new GradientStop(), child));\n\t\t\t}\n\t\t\tgradient = new Gradient(stops, radial);\n\t\t}\n\t\tvar origin, destination, highlight,\n\t\t\tscaleToBounds = getValue(node, 'gradientUnits', true) !==\n\t\t\t\t'userSpaceOnUse';\n\t\tif (radial) {\n\t\t\torigin = getPoint(node, 'cx', 'cy', false, scaleToBounds);\n\t\t\tdestination = origin.add(\n\t\t\t\t\tgetValue(node, 'r', false, false, scaleToBounds), 0);\n\t\t\thighlight = getPoint(node, 'fx', 'fy', true, scaleToBounds);\n\t\t} else {\n\t\t\torigin = getPoint(node, 'x1', 'y1', false, scaleToBounds);\n\t\t\tdestination = getPoint(node, 'x2', 'y2', false, scaleToBounds);\n\t\t}\n\t\tvar color = applyAttributes(\n\t\t\t\tnew Color(gradient, origin, destination, highlight), node);\n\t\tcolor._scaleToBounds = scaleToBounds;\n\t\treturn null;\n\t}\n\n\tvar importers = {\n\t\t'#document': function (node, type, options, isRoot) {\n\t\t\tvar nodes = node.childNodes;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tvar child = nodes[i];\n\t\t\t\tif (child.nodeType === 1)\n\t\t\t\t\treturn importNode(child, options, isRoot);\n\t\t\t}\n\t\t},\n\t\tg: importGroup,\n\t\tsvg: importGroup,\n\t\tclippath: importGroup,\n\t\tpolygon: importPoly,\n\t\tpolyline: importPoly,\n\t\tpath: importPath,\n\t\tlineargradient: importGradient,\n\t\tradialgradient: importGradient,\n\n\t\timage: function (node) {\n\t\t\tvar raster = new Raster(getValue(node, 'href', true));\n\t\t\traster.on('load', function() {\n\t\t\t\tvar size = getSize(node);\n\t\t\t\tthis.setSize(size);\n\t\t\t\tvar center = this._matrix._transformPoint(\n\t\t\t\t\t\tgetPoint(node).add(size.divide(2)));\n\t\t\t\tthis.translate(center);\n\t\t\t});\n\t\t\treturn raster;\n\t\t},\n\n\t\tsymbol: function(node, type, options, isRoot) {\n\t\t\treturn new SymbolDefinition(\n\t\t\t\t\timportGroup(node, type, options, isRoot), true);\n\t\t},\n\n\t\tdefs: importGroup,\n\n\t\tuse: function(node) {\n\t\t\tvar id = (getValue(node, 'href', true) || '').substring(1),\n\t\t\t\tdefinition = definitions[id],\n\t\t\t\tpoint = getPoint(node);\n\t\t\treturn definition\n\t\t\t\t\t? definition instanceof SymbolDefinition\n\t\t\t\t\t\t? definition.place(point)\n\t\t\t\t\t\t: definition.clone().translate(point)\n\t\t\t\t\t: null;\n\t\t},\n\n\t\tcircle: function(node) {\n\t\t\treturn new Shape.Circle(\n\t\t\t\t\tgetPoint(node, 'cx', 'cy'),\n\t\t\t\t\tgetValue(node, 'r'));\n\t\t},\n\n\t\tellipse: function(node) {\n\t\t\treturn new Shape.Ellipse({\n\t\t\t\tcenter: getPoint(node, 'cx', 'cy'),\n\t\t\t\tradius: getSize(node, 'rx', 'ry')\n\t\t\t});\n\t\t},\n\n\t\trect: function(node) {\n\t\t\treturn new Shape.Rectangle(new Rectangle(\n\t\t\t\t\t\tgetPoint(node),\n\t\t\t\t\t\tgetSize(node)\n\t\t\t\t\t), getSize(node, 'rx', 'ry'));\n\t\t\t},\n\n\t\tline: function(node) {\n\t\t\treturn new Path.Line(\n\t\t\t\t\tgetPoint(node, 'x1', 'y1'),\n\t\t\t\t\tgetPoint(node, 'x2', 'y2'));\n\t\t},\n\n\t\ttext: function(node) {\n\t\t\tvar text = new PointText(getPoint(node).add(\n\t\t\t\t\tgetPoint(node, 'dx', 'dy')));\n\t\t\ttext.setContent(node.textContent.trim() || '');\n\t\t\treturn text;\n\t\t}\n\t};\n\n\tfunction applyTransform(item, value, name, node) {\n\t\tif (item.transform) {\n\t\t\tvar transforms = (node.getAttribute(name) || '').split(/\\)\\s*/g),\n\t\t\t\tmatrix = new Matrix();\n\t\t\tfor (var i = 0, l = transforms.length; i < l; i++) {\n\t\t\t\tvar transform = transforms[i];\n\t\t\t\tif (!transform)\n\t\t\t\t\tbreak;\n\t\t\t\tvar parts = transform.split(/\\(\\s*/),\n\t\t\t\t\tcommand = parts[0],\n\t\t\t\t\tv = parts[1].split(/[\\s,]+/g);\n\t\t\t\tfor (var j = 0, m = v.length; j < m; j++)\n\t\t\t\t\tv[j] = parseFloat(v[j]);\n\t\t\t\tswitch (command) {\n\t\t\t\tcase 'matrix':\n\t\t\t\t\tmatrix.append(\n\t\t\t\t\t\t\tnew Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'rotate':\n\t\t\t\t\tmatrix.rotate(v[0], v[1], v[2]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'translate':\n\t\t\t\t\tmatrix.translate(v[0], v[1]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'scale':\n\t\t\t\t\tmatrix.scale(v);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'skewX':\n\t\t\t\t\tmatrix.skew(v[0], 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'skewY':\n\t\t\t\t\tmatrix.skew(0, v[0]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\titem.transform(matrix);\n\t\t}\n\t}\n\n\tfunction applyOpacity(item, value, name) {\n\t\tvar key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor',\n\t\t\tcolor = item[key] && item[key]();\n\t\tif (color)\n\t\t\tcolor.setAlpha(parseFloat(value));\n\t}\n\n\tvar attributes = Base.set(Base.each(SvgStyles, function(entry) {\n\t\tthis[entry.attribute] = function(item, value) {\n\t\t\tif (item[entry.set]) {\n\t\t\t\titem[entry.set](convertValue(value, entry.type, entry.fromSVG));\n\t\t\t\tif (entry.type === 'color') {\n\t\t\t\t\tvar color = item[entry.get]();\n\t\t\t\t\tif (color) {\n\t\t\t\t\t\tif (color._scaleToBounds) {\n\t\t\t\t\t\t\tvar bounds = item.getBounds();\n\t\t\t\t\t\t\tcolor.transform(new Matrix()\n\t\t\t\t\t\t\t\t.translate(bounds.getPoint())\n\t\t\t\t\t\t\t\t.scale(bounds.getSize()));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (item instanceof Shape) {\n\t\t\t\t\t\t\tcolor.transform(new Matrix().translate(\n\t\t\t\t\t\t\t\titem.getPosition(true).negate()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}, {}), {\n\t\tid: function(item, value) {\n\t\t\tdefinitions[value] = item;\n\t\t\tif (item.setName)\n\t\t\t\titem.setName(value);\n\t\t},\n\n\t\t'clip-path': function(item, value) {\n\t\t\tvar clip = getDefinition(value);\n\t\t\tif (clip) {\n\t\t\t\tclip = clip.clone();\n\t\t\t\tclip.setClipMask(true);\n\t\t\t\tif (item instanceof Group) {\n\t\t\t\t\titem.insertChild(0, clip);\n\t\t\t\t} else {\n\t\t\t\t\treturn new Group(clip, item);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tgradientTransform: applyTransform,\n\t\ttransform: applyTransform,\n\n\t\t'fill-opacity': applyOpacity,\n\t\t'stroke-opacity': applyOpacity,\n\n\t\tvisibility: function(item, value) {\n\t\t\tif (item.setVisible)\n\t\t\t\titem.setVisible(value === 'visible');\n\t\t},\n\n\t\tdisplay: function(item, value) {\n\t\t\tif (item.setVisible)\n\t\t\t\titem.setVisible(value !== null);\n\t\t},\n\n\t\t'stop-color': function(item, value) {\n\t\t\tif (item.setColor)\n\t\t\t\titem.setColor(value);\n\t\t},\n\n\t\t'stop-opacity': function(item, value) {\n\t\t\tif (item._color)\n\t\t\t\titem._color.setAlpha(parseFloat(value));\n\t\t},\n\n\t\toffset: function(item, value) {\n\t\t\tif (item.setOffset) {\n\t\t\t\tvar percent = value.match(/(.*)%$/);\n\t\t\t\titem.setOffset(percent ? percent[1] / 100 : parseFloat(value));\n\t\t\t}\n\t\t},\n\n\t\tviewBox: function(item, value, name, node, styles) {\n\t\t\tvar rect = new Rectangle(convertValue(value, 'array')),\n\t\t\t\tsize = getSize(node, null, null, true),\n\t\t\t\tgroup,\n\t\t\t\tmatrix;\n\t\t\tif (item instanceof Group) {\n\t\t\t\tvar scale = size ? size.divide(rect.getSize()) : 1,\n\t\t\t\tmatrix = new Matrix().scale(scale)\n\t\t\t\t\t\t.translate(rect.getPoint().negate());\n\t\t\t\tgroup = item;\n\t\t\t} else if (item instanceof SymbolDefinition) {\n\t\t\t\tif (size)\n\t\t\t\t\trect.setSize(size);\n\t\t\t\tgroup = item._item;\n\t\t\t}\n\t\t\tif (group) {\n\t\t\t\tif (getAttribute(node, 'overflow', styles) !== 'visible') {\n\t\t\t\t\tvar clip = new Shape.Rectangle(rect);\n\t\t\t\t\tclip.setClipMask(true);\n\t\t\t\t\tgroup.addChild(clip);\n\t\t\t\t}\n\t\t\t\tif (matrix)\n\t\t\t\t\tgroup.transform(matrix);\n\t\t\t}\n\t\t}\n\t});\n\n\tfunction getAttribute(node, name, styles) {\n\t\tvar attr = node.attributes[name],\n\t\t\tvalue = attr && attr.value;\n\t\tif (!value) {\n\t\t\tvar style = Base.camelize(name);\n\t\t\tvalue = node.style[style];\n\t\t\tif (!value && styles.node[style] !== styles.parent[style])\n\t\t\t\tvalue = styles.node[style];\n\t\t}\n\t\treturn !value ? undefined\n\t\t\t\t: value === 'none' ? null\n\t\t\t\t: value;\n\t}\n\n\tfunction applyAttributes(item, node, isRoot) {\n\t\tvar parent = node.parentNode,\n\t\t\tstyles = {\n\t\t\t\tnode: DomElement.getStyles(node) || {},\n\t\t\t\tparent: !isRoot && !/^defs$/i.test(parent.tagName)\n\t\t\t\t\t\t&& DomElement.getStyles(parent) || {}\n\t\t\t};\n\t\tBase.each(attributes, function(apply, name) {\n\t\t\tvar value = getAttribute(node, name, styles);\n\t\t\titem = value !== undefined && apply(item, value, name, node, styles)\n\t\t\t\t\t|| item;\n\t\t});\n\t\treturn item;\n\t}\n\n\tfunction getDefinition(value) {\n\t\tvar match = value && value.match(/\\((?:[\"'#]*)([^\"')]+)/),\n\t\t\tname = match && match[1],\n\t\t\tres = name && definitions[window\n\t\t\t\t\t? name.replace(window.location.href.split('#')[0] + '#', '')\n\t\t\t\t\t: name];\n\t\tif (res && res._scaleToBounds) {\n\t\t\tres = res.clone();\n\t\t\tres._scaleToBounds = true;\n\t\t}\n\t\treturn res;\n\t}\n\n\tfunction importNode(node, options, isRoot) {\n\t\tvar type = node.nodeName.toLowerCase(),\n\t\t\tisElement = type !== '#document',\n\t\t\tbody = document.body,\n\t\t\tcontainer,\n\t\t\tparent,\n\t\t\tnext;\n\t\tif (isRoot && isElement) {\n\t\t\trootSize = getSize(node, null, null, true)\n\t\t\t\t\t|| paper.getView().getSize();\n\t\t\tcontainer = SvgElement.create('svg', {\n\t\t\t\tstyle: 'stroke-width: 1px; stroke-miterlimit: 10'\n\t\t\t});\n\t\t\tparent = node.parentNode;\n\t\t\tnext = node.nextSibling;\n\t\t\tcontainer.appendChild(node);\n\t\t\tbody.appendChild(container);\n\t\t}\n\t\tvar settings = paper.settings,\n\t\t\tapplyMatrix = settings.applyMatrix,\n\t\t\tinsertItems = settings.insertItems;\n\t\tsettings.applyMatrix = false;\n\t\tsettings.insertItems = false;\n\t\tvar importer = importers[type],\n\t\t\titem = importer && importer(node, type, options, isRoot) || null;\n\t\tsettings.insertItems = insertItems;\n\t\tsettings.applyMatrix = applyMatrix;\n\t\tif (item) {\n\t\t\tif (isElement && !(item instanceof Group))\n\t\t\t\titem = applyAttributes(item, node, isRoot);\n\t\t\tvar onImport = options.onImport,\n\t\t\t\tdata = isElement && node.getAttribute('data-paper-data');\n\t\t\tif (onImport)\n\t\t\t\titem = onImport(node, item, options) || item;\n\t\t\tif (options.expandShapes && item instanceof Shape) {\n\t\t\t\titem.remove();\n\t\t\t\titem = item.toPath();\n\t\t\t}\n\t\t\tif (data)\n\t\t\t\titem._data = JSON.parse(data);\n\t\t}\n\t\tif (container) {\n\t\t\tbody.removeChild(container);\n\t\t\tif (parent) {\n\t\t\t\tif (next) {\n\t\t\t\t\tparent.insertBefore(node, next);\n\t\t\t\t} else {\n\t\t\t\t\tparent.appendChild(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (isRoot) {\n\t\t\tdefinitions = {};\n\t\t\tif (item && Base.pick(options.applyMatrix, applyMatrix))\n\t\t\t\titem.matrix.apply(true, true);\n\t\t}\n\t\treturn item;\n\t}\n\n\tfunction importSVG(source, options, owner) {\n\t\tif (!source)\n\t\t\treturn null;\n\t\toptions = typeof options === 'function' ? { onLoad: options }\n\t\t\t\t: options || {};\n\t\tvar scope = paper,\n\t\t\titem = null;\n\n\t\tfunction onLoad(svg) {\n\t\t\ttry {\n\t\t\t\tvar node = typeof svg === 'object' ? svg : new self.DOMParser()\n\t\t\t\t\t\t.parseFromString(svg, 'image/svg+xml');\n\t\t\t\tif (!node.nodeName) {\n\t\t\t\t\tnode = null;\n\t\t\t\t\tthrow new Error('Unsupported SVG source: ' + source);\n\t\t\t\t}\n\t\t\t\tpaper = scope;\n\t\t\t\titem = importNode(node, options, true);\n\t\t\t\tif (!options || options.insert !== false) {\n\t\t\t\t\towner._insertItem(undefined, item);\n\t\t\t\t}\n\t\t\t\tvar onLoad = options.onLoad;\n\t\t\t\tif (onLoad)\n\t\t\t\t\tonLoad(item, svg);\n\t\t\t} catch (e) {\n\t\t\t\tonError(e);\n\t\t\t}\n\t\t}\n\n\t\tfunction onError(message, status) {\n\t\t\tvar onError = options.onError;\n\t\t\tif (onError) {\n\t\t\t\tonError(message, status);\n\t\t\t} else {\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\t\t}\n\n\t\tif (typeof source === 'string' && !/^.* symbol translation table */\n}\n\nfunction Data(source, dest) {\n this.source = source;\n this.sourceIndex = 0;\n this.tag = 0;\n this.bitcount = 0;\n \n this.dest = dest;\n this.destLen = 0;\n \n this.ltree = new Tree(); /* dynamic length/symbol tree */\n this.dtree = new Tree(); /* dynamic distance tree */\n}\n\n/* --------------------------------------------------- *\n * -- uninitialized global data (static structures) -- *\n * --------------------------------------------------- */\n\nvar sltree = new Tree();\nvar sdtree = new Tree();\n\n/* extra bits and base tables for length codes */\nvar length_bits = new Uint8Array(30);\nvar length_base = new Uint16Array(30);\n\n/* extra bits and base tables for distance codes */\nvar dist_bits = new Uint8Array(30);\nvar dist_base = new Uint16Array(30);\n\n/* special ordering of code length codes */\nvar clcidx = new Uint8Array([\n 16, 17, 18, 0, 8, 7, 9, 6,\n 10, 5, 11, 4, 12, 3, 13, 2,\n 14, 1, 15\n]);\n\n/* used by tinf_decode_trees, avoids allocations every call */\nvar code_tree = new Tree();\nvar lengths = new Uint8Array(288 + 32);\n\n/* ----------------------- *\n * -- utility functions -- *\n * ----------------------- */\n\n/* build extra bits and base tables */\nfunction tinf_build_bits_base(bits, base, delta, first) {\n var i, sum;\n\n /* build bits table */\n for (i = 0; i < delta; ++i) bits[i] = 0;\n for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta | 0;\n\n /* build base table */\n for (sum = first, i = 0; i < 30; ++i) {\n base[i] = sum;\n sum += 1 << bits[i];\n }\n}\n\n/* build the fixed huffman trees */\nfunction tinf_build_fixed_trees(lt, dt) {\n var i;\n\n /* build fixed length tree */\n for (i = 0; i < 7; ++i) lt.table[i] = 0;\n\n lt.table[7] = 24;\n lt.table[8] = 152;\n lt.table[9] = 112;\n\n for (i = 0; i < 24; ++i) lt.trans[i] = 256 + i;\n for (i = 0; i < 144; ++i) lt.trans[24 + i] = i;\n for (i = 0; i < 8; ++i) lt.trans[24 + 144 + i] = 280 + i;\n for (i = 0; i < 112; ++i) lt.trans[24 + 144 + 8 + i] = 144 + i;\n\n /* build fixed distance tree */\n for (i = 0; i < 5; ++i) dt.table[i] = 0;\n\n dt.table[5] = 32;\n\n for (i = 0; i < 32; ++i) dt.trans[i] = i;\n}\n\n/* given an array of code lengths, build a tree */\nvar offs = new Uint16Array(16);\n\nfunction tinf_build_tree(t, lengths, off, num) {\n var i, sum;\n\n /* clear code length count table */\n for (i = 0; i < 16; ++i) t.table[i] = 0;\n\n /* scan symbol lengths, and sum code length counts */\n for (i = 0; i < num; ++i) t.table[lengths[off + i]]++;\n\n t.table[0] = 0;\n\n /* compute offset table for distribution sort */\n for (sum = 0, i = 0; i < 16; ++i) {\n offs[i] = sum;\n sum += t.table[i];\n }\n\n /* create code->symbol translation table (symbols sorted by code) */\n for (i = 0; i < num; ++i) {\n if (lengths[off + i]) t.trans[offs[lengths[off + i]]++] = i;\n }\n}\n\n/* ---------------------- *\n * -- decode functions -- *\n * ---------------------- */\n\n/* get one bit from source stream */\nfunction tinf_getbit(d) {\n /* check if tag is empty */\n if (!d.bitcount--) {\n /* load next tag */\n d.tag = d.source[d.sourceIndex++];\n d.bitcount = 7;\n }\n\n /* shift bit out of tag */\n var bit = d.tag & 1;\n d.tag >>>= 1;\n\n return bit;\n}\n\n/* read a num bit value from a stream and add base */\nfunction tinf_read_bits(d, num, base) {\n if (!num)\n return base;\n\n while (d.bitcount < 24) {\n d.tag |= d.source[d.sourceIndex++] << d.bitcount;\n d.bitcount += 8;\n }\n\n var val = d.tag & (0xffff >>> (16 - num));\n d.tag >>>= num;\n d.bitcount -= num;\n return val + base;\n}\n\n/* given a data stream and a tree, decode a symbol */\nfunction tinf_decode_symbol(d, t) {\n while (d.bitcount < 24) {\n d.tag |= d.source[d.sourceIndex++] << d.bitcount;\n d.bitcount += 8;\n }\n \n var sum = 0, cur = 0, len = 0;\n var tag = d.tag;\n\n /* get more bits while code value is above sum */\n do {\n cur = 2 * cur + (tag & 1);\n tag >>>= 1;\n ++len;\n\n sum += t.table[len];\n cur -= t.table[len];\n } while (cur >= 0);\n \n d.tag = tag;\n d.bitcount -= len;\n\n return t.trans[sum + cur];\n}\n\n/* given a data stream, decode dynamic trees from it */\nfunction tinf_decode_trees(d, lt, dt) {\n var hlit, hdist, hclen;\n var i, num, length;\n\n /* get 5 bits HLIT (257-286) */\n hlit = tinf_read_bits(d, 5, 257);\n\n /* get 5 bits HDIST (1-32) */\n hdist = tinf_read_bits(d, 5, 1);\n\n /* get 4 bits HCLEN (4-19) */\n hclen = tinf_read_bits(d, 4, 4);\n\n for (i = 0; i < 19; ++i) lengths[i] = 0;\n\n /* read code lengths for code length alphabet */\n for (i = 0; i < hclen; ++i) {\n /* get 3 bits code length (0-7) */\n var clen = tinf_read_bits(d, 3, 0);\n lengths[clcidx[i]] = clen;\n }\n\n /* build code length tree */\n tinf_build_tree(code_tree, lengths, 0, 19);\n\n /* decode code lengths for the dynamic trees */\n for (num = 0; num < hlit + hdist;) {\n var sym = tinf_decode_symbol(d, code_tree);\n\n switch (sym) {\n case 16:\n /* copy previous code length 3-6 times (read 2 bits) */\n var prev = lengths[num - 1];\n for (length = tinf_read_bits(d, 2, 3); length; --length) {\n lengths[num++] = prev;\n }\n break;\n case 17:\n /* repeat code length 0 for 3-10 times (read 3 bits) */\n for (length = tinf_read_bits(d, 3, 3); length; --length) {\n lengths[num++] = 0;\n }\n break;\n case 18:\n /* repeat code length 0 for 11-138 times (read 7 bits) */\n for (length = tinf_read_bits(d, 7, 11); length; --length) {\n lengths[num++] = 0;\n }\n break;\n default:\n /* values 0-15 represent the actual code lengths */\n lengths[num++] = sym;\n break;\n }\n }\n\n /* build dynamic trees */\n tinf_build_tree(lt, lengths, 0, hlit);\n tinf_build_tree(dt, lengths, hlit, hdist);\n}\n\n/* ----------------------------- *\n * -- block inflate functions -- *\n * ----------------------------- */\n\n/* given a stream and two trees, inflate a block of data */\nfunction tinf_inflate_block_data(d, lt, dt) {\n while (1) {\n var sym = tinf_decode_symbol(d, lt);\n\n /* check for end of block */\n if (sym === 256) {\n return TINF_OK;\n }\n\n if (sym < 256) {\n d.dest[d.destLen++] = sym;\n } else {\n var length, dist, offs;\n var i;\n\n sym -= 257;\n\n /* possibly get more bits from length code */\n length = tinf_read_bits(d, length_bits[sym], length_base[sym]);\n\n dist = tinf_decode_symbol(d, dt);\n\n /* possibly get more bits from distance code */\n offs = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]);\n\n /* copy match */\n for (i = offs; i < offs + length; ++i) {\n d.dest[d.destLen++] = d.dest[i];\n }\n }\n }\n}\n\n/* inflate an uncompressed block of data */\nfunction tinf_inflate_uncompressed_block(d) {\n var length, invlength;\n var i;\n \n /* unread from bitbuffer */\n while (d.bitcount > 8) {\n d.sourceIndex--;\n d.bitcount -= 8;\n }\n\n /* get length */\n length = d.source[d.sourceIndex + 1];\n length = 256 * length + d.source[d.sourceIndex];\n\n /* get one's complement of length */\n invlength = d.source[d.sourceIndex + 3];\n invlength = 256 * invlength + d.source[d.sourceIndex + 2];\n\n /* check length */\n if (length !== (~invlength & 0x0000ffff))\n return TINF_DATA_ERROR;\n\n d.sourceIndex += 4;\n\n /* copy block */\n for (i = length; i; --i)\n d.dest[d.destLen++] = d.source[d.sourceIndex++];\n\n /* make sure we start next block on a byte boundary */\n d.bitcount = 0;\n\n return TINF_OK;\n}\n\n/* inflate stream from source to dest */\nfunction tinf_uncompress(source, dest) {\n var d = new Data(source, dest);\n var bfinal, btype, res;\n\n do {\n /* read final block flag */\n bfinal = tinf_getbit(d);\n\n /* read block type (2 bits) */\n btype = tinf_read_bits(d, 2, 0);\n\n /* decompress block */\n switch (btype) {\n case 0:\n /* decompress uncompressed block */\n res = tinf_inflate_uncompressed_block(d);\n break;\n case 1:\n /* decompress block with fixed huffman trees */\n res = tinf_inflate_block_data(d, sltree, sdtree);\n break;\n case 2:\n /* decompress block with dynamic huffman trees */\n tinf_decode_trees(d, d.ltree, d.dtree);\n res = tinf_inflate_block_data(d, d.ltree, d.dtree);\n break;\n default:\n res = TINF_DATA_ERROR;\n }\n\n if (res !== TINF_OK)\n throw new Error('Data error');\n\n } while (!bfinal);\n\n if (d.destLen < d.dest.length) {\n if (typeof d.dest.slice === 'function')\n return d.dest.slice(0, d.destLen);\n else\n return d.dest.subarray(0, d.destLen);\n }\n \n return d.dest;\n}\n\n/* -------------------- *\n * -- initialization -- *\n * -------------------- */\n\n/* build fixed huffman trees */\ntinf_build_fixed_trees(sltree, sdtree);\n\n/* build extra bits and base tables */\ntinf_build_bits_base(length_bits, length_base, 4, 3);\ntinf_build_bits_base(dist_bits, dist_base, 2, 1);\n\n/* fix a special case */\nlength_bits[28] = 0;\nlength_base[28] = 258;\n\nmodule.exports = tinf_uncompress;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/~/tiny-inflate/index.js\n ** module id = 3\n ** module chunks = 0\n **/","// Glyph encoding\n\n'use strict';\n\nvar cffStandardStrings = [\n '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',\n 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',\n 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',\n 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',\n 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',\n 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',\n 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling',\n 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft',\n 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph',\n 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand',\n 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring',\n 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE',\n 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',\n 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn',\n 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',\n 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex',\n 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',\n 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute',\n 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute',\n 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute',\n 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave',\n 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior',\n 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff', 'onedotenleader',\n 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',\n 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior',\n 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',\n 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl',\n 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',\n 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',\n 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',\n 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall',\n 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall',\n 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall',\n 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds',\n 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',\n 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',\n 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior',\n 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',\n 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall',\n 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall',\n 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',\n 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000',\n '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'];\n\nvar cffStandardEncoding = [\n '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',\n 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',\n 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',\n 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',\n 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',\n 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',\n 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',\n 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',\n 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger',\n 'daggerdbl', 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright',\n 'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde',\n 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron',\n 'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '',\n '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '',\n 'lslash', 'oslash', 'oe', 'germandbls'];\n\nvar cffExpertEncoding = [\n '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',\n '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior',\n 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader',\n 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',\n 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',\n 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior',\n 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',\n 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl',\n 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',\n 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',\n 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',\n 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '',\n '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',\n 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',\n 'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior',\n '', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',\n 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '',\n '', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',\n 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',\n 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',\n 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',\n 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',\n 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',\n 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall',\n 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',\n 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];\n\nvar standardNames = [\n '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',\n 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',\n 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',\n 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',\n 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',\n 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',\n 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',\n 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave',\n 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',\n 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis',\n 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section',\n 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal',\n 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation',\n 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown',\n 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright',\n 'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft',\n 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',\n 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase',\n 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',\n 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex',\n 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',\n 'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth',\n 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior',\n 'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla',\n 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];\n\n// This is the encoding used for fonts created from scratch.\n// It loops through all glyphs and finds the appropriate unicode value.\n// Since it's linear time, other encodings will be faster.\nfunction DefaultEncoding(font) {\n this.font = font;\n}\n\nDefaultEncoding.prototype.charToGlyphIndex = function(c) {\n var code = c.charCodeAt(0);\n var glyphs = this.font.glyphs;\n if (glyphs) {\n for (var i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs.get(i);\n for (var j = 0; j < glyph.unicodes.length; j += 1) {\n if (glyph.unicodes[j] === code) {\n return i;\n }\n }\n }\n } else {\n return null;\n }\n};\n\nfunction CmapEncoding(cmap) {\n this.cmap = cmap;\n}\n\nCmapEncoding.prototype.charToGlyphIndex = function(c) {\n return this.cmap.glyphIndexMap[c.charCodeAt(0)] || 0;\n};\n\nfunction CffEncoding(encoding, charset) {\n this.encoding = encoding;\n this.charset = charset;\n}\n\nCffEncoding.prototype.charToGlyphIndex = function(s) {\n var code = s.charCodeAt(0);\n var charName = this.encoding[code];\n return this.charset.indexOf(charName);\n};\n\nfunction GlyphNames(post) {\n var i;\n switch (post.version) {\n case 1:\n this.names = exports.standardNames.slice();\n break;\n case 2:\n this.names = new Array(post.numberOfGlyphs);\n for (i = 0; i < post.numberOfGlyphs; i++) {\n if (post.glyphNameIndex[i] < exports.standardNames.length) {\n this.names[i] = exports.standardNames[post.glyphNameIndex[i]];\n } else {\n this.names[i] = post.names[post.glyphNameIndex[i] - exports.standardNames.length];\n }\n }\n\n break;\n case 2.5:\n this.names = new Array(post.numberOfGlyphs);\n for (i = 0; i < post.numberOfGlyphs; i++) {\n this.names[i] = exports.standardNames[i + post.glyphNameIndex[i]];\n }\n\n break;\n case 3:\n this.names = [];\n break;\n }\n}\n\nGlyphNames.prototype.nameToGlyphIndex = function(name) {\n return this.names.indexOf(name);\n};\n\nGlyphNames.prototype.glyphIndexToName = function(gid) {\n return this.names[gid];\n};\n\nfunction addGlyphNames(font) {\n var glyph;\n var glyphIndexMap = font.tables.cmap.glyphIndexMap;\n var charCodes = Object.keys(glyphIndexMap);\n\n for (var i = 0; i < charCodes.length; i += 1) {\n var c = charCodes[i];\n var glyphIndex = glyphIndexMap[c];\n glyph = font.glyphs.get(glyphIndex);\n glyph.addUnicode(parseInt(c));\n }\n\n for (i = 0; i < font.glyphs.length; i += 1) {\n glyph = font.glyphs.get(i);\n if (font.cffEncoding) {\n glyph.name = font.cffEncoding.charset[i];\n } else if (font.glyphNames.names) {\n glyph.name = font.glyphNames.glyphIndexToName(i);\n }\n }\n}\n\nexports.cffStandardStrings = cffStandardStrings;\nexports.cffStandardEncoding = cffStandardEncoding;\nexports.cffExpertEncoding = cffExpertEncoding;\nexports.standardNames = standardNames;\nexports.DefaultEncoding = DefaultEncoding;\nexports.CmapEncoding = CmapEncoding;\nexports.CffEncoding = CffEncoding;\nexports.GlyphNames = GlyphNames;\nexports.addGlyphNames = addGlyphNames;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/encoding.js\n ** module id = 4\n ** module chunks = 0\n **/","// The Font object\n\n'use strict';\n\nvar path = require('./path');\nvar sfnt = require('./tables/sfnt');\nvar encoding = require('./encoding');\nvar glyphset = require('./glyphset');\nvar Substitution = require('./substitution');\nvar util = require('./util');\n\n// A Font represents a loaded OpenType font file.\n// It contains a set of glyphs and methods to draw text on a drawing context,\n// or to get a path representing the text.\nfunction Font(options) {\n options = options || {};\n\n if (!options.empty) {\n // Check that we've provided the minimum set of names.\n util.checkArgument(options.familyName, 'When creating a new Font object, familyName is required.');\n util.checkArgument(options.styleName, 'When creating a new Font object, styleName is required.');\n util.checkArgument(options.unitsPerEm, 'When creating a new Font object, unitsPerEm is required.');\n util.checkArgument(options.ascender, 'When creating a new Font object, ascender is required.');\n util.checkArgument(options.descender, 'When creating a new Font object, descender is required.');\n util.checkArgument(options.descender < 0, 'Descender should be negative (e.g. -512).');\n\n // OS X will complain if the names are empty, so we put a single space everywhere by default.\n this.names = {\n fontFamily: {en: options.familyName || ' '},\n fontSubfamily: {en: options.styleName || ' '},\n fullName: {en: options.fullName || options.familyName + ' ' + options.styleName},\n postScriptName: {en: options.postScriptName || options.familyName + options.styleName},\n designer: {en: options.designer || ' '},\n designerURL: {en: options.designerURL || ' '},\n manufacturer: {en: options.manufacturer || ' '},\n manufacturerURL: {en: options.manufacturerURL || ' '},\n license: {en: options.license || ' '},\n licenseURL: {en: options.licenseURL || ' '},\n version: {en: options.version || 'Version 0.1'},\n description: {en: options.description || ' '},\n copyright: {en: options.copyright || ' '},\n trademark: {en: options.trademark || ' '}\n };\n this.unitsPerEm = options.unitsPerEm || 1000;\n this.ascender = options.ascender;\n this.descender = options.descender;\n this.createdTimestamp = options.createdTimestamp;\n this.tables = { os2: {\n usWeightClass: options.weightClass || this.usWeightClasses.MEDIUM,\n usWidthClass: options.widthClass || this.usWidthClasses.MEDIUM,\n fsSelection: options.fsSelection || this.fsSelectionValues.REGULAR\n } };\n }\n\n this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported.\n this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);\n this.encoding = new encoding.DefaultEncoding(this);\n this.substitution = new Substitution(this);\n this.tables = this.tables || {};\n}\n\n// Check if the font has a glyph for the given character.\nFont.prototype.hasChar = function(c) {\n return this.encoding.charToGlyphIndex(c) !== null;\n};\n\n// Convert the given character to a single glyph index.\n// Note that this function assumes that there is a one-to-one mapping between\n// the given character and a glyph; for complex scripts this might not be the case.\nFont.prototype.charToGlyphIndex = function(s) {\n return this.encoding.charToGlyphIndex(s);\n};\n\n// Convert the given character to a single Glyph object.\n// Note that this function assumes that there is a one-to-one mapping between\n// the given character and a glyph; for complex scripts this might not be the case.\nFont.prototype.charToGlyph = function(c) {\n var glyphIndex = this.charToGlyphIndex(c);\n var glyph = this.glyphs.get(glyphIndex);\n if (!glyph) {\n // .notdef\n glyph = this.glyphs.get(0);\n }\n\n return glyph;\n};\n\n// Convert the given text to a list of Glyph objects.\n// Note that there is no strict one-to-one mapping between characters and\n// glyphs, so the list of returned glyphs can be larger or smaller than the\n// length of the given string.\nFont.prototype.stringToGlyphs = function(s) {\n var glyphs = [];\n for (var i = 0; i < s.length; i += 1) {\n var c = s[i];\n glyphs.push(this.charToGlyph(c));\n }\n\n return glyphs;\n};\n\nFont.prototype.nameToGlyphIndex = function(name) {\n return this.glyphNames.nameToGlyphIndex(name);\n};\n\nFont.prototype.nameToGlyph = function(name) {\n var glyphIndex = this.nametoGlyphIndex(name);\n var glyph = this.glyphs.get(glyphIndex);\n if (!glyph) {\n // .notdef\n glyph = this.glyphs.get(0);\n }\n\n return glyph;\n};\n\nFont.prototype.glyphIndexToName = function(gid) {\n if (!this.glyphNames.glyphIndexToName) {\n return '';\n }\n\n return this.glyphNames.glyphIndexToName(gid);\n};\n\n// Retrieve the value of the kerning pair between the left glyph (or its index)\n// and the right glyph (or its index). If no kerning pair is found, return 0.\n// The kerning value gets added to the advance width when calculating the spacing\n// between glyphs.\nFont.prototype.getKerningValue = function(leftGlyph, rightGlyph) {\n leftGlyph = leftGlyph.index || leftGlyph;\n rightGlyph = rightGlyph.index || rightGlyph;\n var gposKerning = this.getGposKerningValue;\n return gposKerning ? gposKerning(leftGlyph, rightGlyph) :\n (this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0);\n};\n\n// Helper function that invokes the given callback for each glyph in the given text.\n// The callback gets `(glyph, x, y, fontSize, options)`.\nFont.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) {\n x = x !== undefined ? x : 0;\n y = y !== undefined ? y : 0;\n fontSize = fontSize !== undefined ? fontSize : 72;\n options = options || {};\n var kerning = options.kerning === undefined ? true : options.kerning;\n var fontScale = 1 / this.unitsPerEm * fontSize;\n var glyphs = this.stringToGlyphs(text);\n for (var i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs[i];\n callback(glyph, x, y, fontSize, options);\n if (glyph.advanceWidth) {\n x += glyph.advanceWidth * fontScale;\n }\n\n if (kerning && i < glyphs.length - 1) {\n var kerningValue = this.getKerningValue(glyph, glyphs[i + 1]);\n x += kerningValue * fontScale;\n }\n }\n};\n\n// Create a Path object that represents the given text.\n//\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\n//\n// Returns a Path object.\nFont.prototype.getPath = function(text, x, y, fontSize, options) {\n var fullPath = new path.Path();\n this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {\n var glyphPath = glyph.getPath(gX, gY, gFontSize);\n fullPath.extend(glyphPath);\n });\n\n return fullPath;\n};\n\n// Create an array of Path objects that represent the glyps of a given text.\n//\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\n//\n// Returns an array of Path objects.\nFont.prototype.getPaths = function(text, x, y, fontSize, options) {\n var glyphPaths = [];\n this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {\n var glyphPath = glyph.getPath(gX, gY, gFontSize);\n glyphPaths.push(glyphPath);\n });\n\n return glyphPaths;\n};\n\n// Draw the text on the given drawing context.\n//\n// ctx - A 2D drawing context, like Canvas.\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\nFont.prototype.draw = function(ctx, text, x, y, fontSize, options) {\n this.getPath(text, x, y, fontSize, options).draw(ctx);\n};\n\n// Draw the points of all glyphs in the text.\n// On-curve points will be drawn in blue, off-curve points will be drawn in red.\n//\n// ctx - A 2D drawing context, like Canvas.\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\nFont.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {\n this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {\n glyph.drawPoints(ctx, gX, gY, gFontSize);\n });\n};\n\n// Draw lines indicating important font measurements for all glyphs in the text.\n// Black lines indicate the origin of the coordinate system (point 0,0).\n// Blue lines indicate the glyph bounding box.\n// Green line indicates the advance width of the glyph.\n//\n// ctx - A 2D drawing context, like Canvas.\n// text - The text to create.\n// x - Horizontal position of the beginning of the text. (default: 0)\n// y - Vertical position of the *baseline* of the text. (default: 0)\n// fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)\n// Options is an optional object that contains:\n// - kerning - Whether to take kerning information into account. (default: true)\nFont.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {\n this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {\n glyph.drawMetrics(ctx, gX, gY, gFontSize);\n });\n};\n\nFont.prototype.getEnglishName = function(name) {\n var translations = this.names[name];\n if (translations) {\n return translations.en;\n }\n};\n\n// Validate\nFont.prototype.validate = function() {\n var warnings = [];\n var _this = this;\n\n function assert(predicate, message) {\n if (!predicate) {\n warnings.push(message);\n }\n }\n\n function assertNamePresent(name) {\n var englishName = _this.getEnglishName(name);\n assert(englishName && englishName.trim().length > 0,\n 'No English ' + name + ' specified.');\n }\n\n // Identification information\n assertNamePresent('fontFamily');\n assertNamePresent('weightName');\n assertNamePresent('manufacturer');\n assertNamePresent('copyright');\n assertNamePresent('version');\n\n // Dimension information\n assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');\n};\n\n// Convert the font object to a SFNT data structure.\n// This structure contains all the necessary tables and metadata to create a binary OTF file.\nFont.prototype.toTables = function() {\n return sfnt.fontToTable(this);\n};\n\nFont.prototype.toBuffer = function() {\n console.warn('Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.');\n return this.toArrayBuffer();\n};\n\nFont.prototype.toArrayBuffer = function() {\n var sfntTable = this.toTables();\n var bytes = sfntTable.encode();\n var buffer = new ArrayBuffer(bytes.length);\n var intArray = new Uint8Array(buffer);\n for (var i = 0; i < bytes.length; i++) {\n intArray[i] = bytes[i];\n }\n\n return buffer;\n};\n\n// Initiate a download of the OpenType font.\nFont.prototype.download = function() {\n var familyName = this.getEnglishName('fontFamily');\n var styleName = this.getEnglishName('fontSubfamily');\n var fileName = familyName.replace(/\\s/g, '') + '-' + styleName + '.otf';\n var arrayBuffer = this.toArrayBuffer();\n\n if (util.isBrowser()) {\n window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;\n window.requestFileSystem(window.TEMPORARY, arrayBuffer.byteLength, function(fs) {\n fs.root.getFile(fileName, {create: true}, function(fileEntry) {\n fileEntry.createWriter(function(writer) {\n var dataView = new DataView(arrayBuffer);\n var blob = new Blob([dataView], {type: 'font/opentype'});\n writer.write(blob);\n\n writer.addEventListener('writeend', function() {\n // Navigating to the file will download it.\n location.href = fileEntry.toURL();\n }, false);\n });\n });\n },\n function(err) {\n throw err;\n });\n } else {\n var fs = require('fs');\n var buffer = util.arrayBufferToNodeBuffer(arrayBuffer);\n fs.writeFileSync(fileName, buffer);\n }\n};\n\nFont.prototype.fsSelectionValues = {\n ITALIC: 0x001, //1\n UNDERSCORE: 0x002, //2\n NEGATIVE: 0x004, //4\n OUTLINED: 0x008, //8\n STRIKEOUT: 0x010, //16\n BOLD: 0x020, //32\n REGULAR: 0x040, //64\n USER_TYPO_METRICS: 0x080, //128\n WWS: 0x100, //256\n OBLIQUE: 0x200 //512\n};\n\nFont.prototype.usWidthClasses = {\n ULTRA_CONDENSED: 1,\n EXTRA_CONDENSED: 2,\n CONDENSED: 3,\n SEMI_CONDENSED: 4,\n MEDIUM: 5,\n SEMI_EXPANDED: 6,\n EXPANDED: 7,\n EXTRA_EXPANDED: 8,\n ULTRA_EXPANDED: 9\n};\n\nFont.prototype.usWeightClasses = {\n THIN: 100,\n EXTRA_LIGHT: 200,\n LIGHT: 300,\n NORMAL: 400,\n MEDIUM: 500,\n SEMI_BOLD: 600,\n BOLD: 700,\n EXTRA_BOLD: 800,\n BLACK: 900\n};\n\nexports.Font = Font;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/font.js\n ** module id = 5\n ** module chunks = 0\n **/","// Geometric objects\n\n'use strict';\n\n// A bézier path containing a set of path commands similar to a SVG path.\n// Paths can be drawn on a context using `draw`.\nfunction Path() {\n this.commands = [];\n this.fill = 'black';\n this.stroke = null;\n this.strokeWidth = 1;\n}\n\nPath.prototype.moveTo = function(x, y) {\n this.commands.push({\n type: 'M',\n x: x,\n y: y\n });\n};\n\nPath.prototype.lineTo = function(x, y) {\n this.commands.push({\n type: 'L',\n x: x,\n y: y\n });\n};\n\nPath.prototype.curveTo = Path.prototype.bezierCurveTo = function(x1, y1, x2, y2, x, y) {\n this.commands.push({\n type: 'C',\n x1: x1,\n y1: y1,\n x2: x2,\n y2: y2,\n x: x,\n y: y\n });\n};\n\nPath.prototype.quadTo = Path.prototype.quadraticCurveTo = function(x1, y1, x, y) {\n this.commands.push({\n type: 'Q',\n x1: x1,\n y1: y1,\n x: x,\n y: y\n });\n};\n\nPath.prototype.close = Path.prototype.closePath = function() {\n this.commands.push({\n type: 'Z'\n });\n};\n\n// Add the given path or list of commands to the commands of this path.\nPath.prototype.extend = function(pathOrCommands) {\n if (pathOrCommands.commands) {\n pathOrCommands = pathOrCommands.commands;\n }\n\n Array.prototype.push.apply(this.commands, pathOrCommands);\n};\n\n// Draw the path to a 2D context.\nPath.prototype.draw = function(ctx) {\n ctx.beginPath();\n for (var i = 0; i < this.commands.length; i += 1) {\n var cmd = this.commands[i];\n if (cmd.type === 'M') {\n ctx.moveTo(cmd.x, cmd.y);\n } else if (cmd.type === 'L') {\n ctx.lineTo(cmd.x, cmd.y);\n } else if (cmd.type === 'C') {\n ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);\n } else if (cmd.type === 'Q') {\n ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);\n } else if (cmd.type === 'Z') {\n ctx.closePath();\n }\n }\n\n if (this.fill) {\n ctx.fillStyle = this.fill;\n ctx.fill();\n }\n\n if (this.stroke) {\n ctx.strokeStyle = this.stroke;\n ctx.lineWidth = this.strokeWidth;\n ctx.stroke();\n }\n};\n\n// Convert the Path to a string of path data instructions\n// See http://www.w3.org/TR/SVG/paths.html#PathData\n// Parameters:\n// - decimalPlaces: The amount of decimal places for floating-point values (default: 2)\nPath.prototype.toPathData = function(decimalPlaces) {\n decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;\n\n function floatToString(v) {\n if (Math.round(v) === v) {\n return '' + Math.round(v);\n } else {\n return v.toFixed(decimalPlaces);\n }\n }\n\n function packValues() {\n var s = '';\n for (var i = 0; i < arguments.length; i += 1) {\n var v = arguments[i];\n if (v >= 0 && i > 0) {\n s += ' ';\n }\n\n s += floatToString(v);\n }\n\n return s;\n }\n\n var d = '';\n for (var i = 0; i < this.commands.length; i += 1) {\n var cmd = this.commands[i];\n if (cmd.type === 'M') {\n d += 'M' + packValues(cmd.x, cmd.y);\n } else if (cmd.type === 'L') {\n d += 'L' + packValues(cmd.x, cmd.y);\n } else if (cmd.type === 'C') {\n d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);\n } else if (cmd.type === 'Q') {\n d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y);\n } else if (cmd.type === 'Z') {\n d += 'Z';\n }\n }\n\n return d;\n};\n\n// Convert the path to a SVG element, as a string.\n// Parameters:\n// - decimalPlaces: The amount of decimal places for floating-point values (default: 2)\nPath.prototype.toSVG = function(decimalPlaces) {\n var svg = ' r2.value.tag) {\n return 1;\n } else {\n return -1;\n }\n });\n\n sfnt.fields = sfnt.fields.concat(recordFields);\n sfnt.fields = sfnt.fields.concat(tableFields);\n return sfnt;\n}\n\n// Get the metrics for a character. If the string has more than one character\n// this function returns metrics for the first available character.\n// You can provide optional fallback metrics if no characters are available.\nfunction metricsForChar(font, chars, notFoundMetrics) {\n for (var i = 0; i < chars.length; i += 1) {\n var glyphIndex = font.charToGlyphIndex(chars[i]);\n if (glyphIndex > 0) {\n var glyph = font.glyphs.get(glyphIndex);\n return glyph.getMetrics();\n }\n }\n\n return notFoundMetrics;\n}\n\nfunction average(vs) {\n var sum = 0;\n for (var i = 0; i < vs.length; i += 1) {\n sum += vs[i];\n }\n\n return sum / vs.length;\n}\n\n// Convert the font object to a SFNT data structure.\n// This structure contains all the necessary tables and metadata to create a binary OTF file.\nfunction fontToSfntTable(font) {\n var xMins = [];\n var yMins = [];\n var xMaxs = [];\n var yMaxs = [];\n var advanceWidths = [];\n var leftSideBearings = [];\n var rightSideBearings = [];\n var firstCharIndex;\n var lastCharIndex = 0;\n var ulUnicodeRange1 = 0;\n var ulUnicodeRange2 = 0;\n var ulUnicodeRange3 = 0;\n var ulUnicodeRange4 = 0;\n\n for (var i = 0; i < font.glyphs.length; i += 1) {\n var glyph = font.glyphs.get(i);\n var unicode = glyph.unicode | 0;\n\n if (isNaN(glyph.advanceWidth)) {\n throw new Error('Glyph ' + glyph.name + ' (' + i + '): advanceWidth is not a number.');\n }\n\n if (firstCharIndex > unicode || firstCharIndex === undefined) {\n // ignore .notdef char\n if (unicode > 0) {\n firstCharIndex = unicode;\n }\n }\n\n if (lastCharIndex < unicode) {\n lastCharIndex = unicode;\n }\n\n var position = os2.getUnicodeRange(unicode);\n if (position < 32) {\n ulUnicodeRange1 |= 1 << position;\n } else if (position < 64) {\n ulUnicodeRange2 |= 1 << position - 32;\n } else if (position < 96) {\n ulUnicodeRange3 |= 1 << position - 64;\n } else if (position < 123) {\n ulUnicodeRange4 |= 1 << position - 96;\n } else {\n throw new Error('Unicode ranges bits > 123 are reserved for internal usage');\n }\n // Skip non-important characters.\n if (glyph.name === '.notdef') continue;\n var metrics = glyph.getMetrics();\n xMins.push(metrics.xMin);\n yMins.push(metrics.yMin);\n xMaxs.push(metrics.xMax);\n yMaxs.push(metrics.yMax);\n leftSideBearings.push(metrics.leftSideBearing);\n rightSideBearings.push(metrics.rightSideBearing);\n advanceWidths.push(glyph.advanceWidth);\n }\n\n var globals = {\n xMin: Math.min.apply(null, xMins),\n yMin: Math.min.apply(null, yMins),\n xMax: Math.max.apply(null, xMaxs),\n yMax: Math.max.apply(null, yMaxs),\n advanceWidthMax: Math.max.apply(null, advanceWidths),\n advanceWidthAvg: average(advanceWidths),\n minLeftSideBearing: Math.min.apply(null, leftSideBearings),\n maxLeftSideBearing: Math.max.apply(null, leftSideBearings),\n minRightSideBearing: Math.min.apply(null, rightSideBearings)\n };\n globals.ascender = font.ascender;\n globals.descender = font.descender;\n\n var headTable = head.make({\n flags: 3, // 00000011 (baseline for font at y=0; left sidebearing point at x=0)\n unitsPerEm: font.unitsPerEm,\n xMin: globals.xMin,\n yMin: globals.yMin,\n xMax: globals.xMax,\n yMax: globals.yMax,\n lowestRecPPEM: 3,\n createdTimestamp: font.createdTimestamp\n });\n\n var hheaTable = hhea.make({\n ascender: globals.ascender,\n descender: globals.descender,\n advanceWidthMax: globals.advanceWidthMax,\n minLeftSideBearing: globals.minLeftSideBearing,\n minRightSideBearing: globals.minRightSideBearing,\n xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin),\n numberOfHMetrics: font.glyphs.length\n });\n\n var maxpTable = maxp.make(font.glyphs.length);\n\n var os2Table = os2.make({\n xAvgCharWidth: Math.round(globals.advanceWidthAvg),\n usWeightClass: font.tables.os2.usWeightClass,\n usWidthClass: font.tables.os2.usWidthClass,\n usFirstCharIndex: firstCharIndex,\n usLastCharIndex: lastCharIndex,\n ulUnicodeRange1: ulUnicodeRange1,\n ulUnicodeRange2: ulUnicodeRange2,\n ulUnicodeRange3: ulUnicodeRange3,\n ulUnicodeRange4: ulUnicodeRange4,\n fsSelection: font.tables.os2.fsSelection, // REGULAR\n // See http://typophile.com/node/13081 for more info on vertical metrics.\n // We get metrics for typical characters (such as \"x\" for xHeight).\n // We provide some fallback characters if characters are unavailable: their\n // ordering was chosen experimentally.\n sTypoAscender: globals.ascender,\n sTypoDescender: globals.descender,\n sTypoLineGap: 0,\n usWinAscent: globals.yMax,\n usWinDescent: Math.abs(globals.yMin),\n ulCodePageRange1: 1, // FIXME: hard-code Latin 1 support for now\n sxHeight: metricsForChar(font, 'xyvw', {yMax: Math.round(globals.ascender / 2)}).yMax,\n sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals).yMax,\n usDefaultChar: font.hasChar(' ') ? 32 : 0, // Use space as the default character, if available.\n usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available.\n });\n\n var hmtxTable = hmtx.make(font.glyphs);\n var cmapTable = cmap.make(font.glyphs);\n\n var englishFamilyName = font.getEnglishName('fontFamily');\n var englishStyleName = font.getEnglishName('fontSubfamily');\n var englishFullName = englishFamilyName + ' ' + englishStyleName;\n var postScriptName = font.getEnglishName('postScriptName');\n if (!postScriptName) {\n postScriptName = englishFamilyName.replace(/\\s/g, '') + '-' + englishStyleName;\n }\n\n var names = {};\n for (var n in font.names) {\n names[n] = font.names[n];\n }\n\n if (!names.uniqueID) {\n names.uniqueID = {en: font.getEnglishName('manufacturer') + ':' + englishFullName};\n }\n\n if (!names.postScriptName) {\n names.postScriptName = {en: postScriptName};\n }\n\n if (!names.preferredFamily) {\n names.preferredFamily = font.names.fontFamily;\n }\n\n if (!names.preferredSubfamily) {\n names.preferredSubfamily = font.names.fontSubfamily;\n }\n\n var languageTags = [];\n var nameTable = _name.make(names, languageTags);\n var ltagTable = (languageTags.length > 0 ? ltag.make(languageTags) : undefined);\n\n var postTable = post.make();\n var cffTable = cff.make(font.glyphs, {\n version: font.getEnglishName('version'),\n fullName: englishFullName,\n familyName: englishFamilyName,\n weightName: englishStyleName,\n postScriptName: postScriptName,\n unitsPerEm: font.unitsPerEm,\n fontBBox: [0, globals.yMin, globals.ascender, globals.advanceWidthMax]\n });\n\n // The order does not matter because makeSfntTable() will sort them.\n var tables = [headTable, hheaTable, maxpTable, os2Table, nameTable, cmapTable, postTable, cffTable, hmtxTable];\n if (ltagTable) {\n tables.push(ltagTable);\n }\n // Optional tables\n if (font.tables.gsub) {\n tables.push(gsub.make(font.tables.gsub));\n }\n\n var sfntTable = makeSfntTable(tables);\n\n // Compute the font's checkSum and store it in head.checkSumAdjustment.\n var bytes = sfntTable.encode();\n var checkSum = computeCheckSum(bytes);\n var tableFields = sfntTable.fields;\n var checkSumAdjusted = false;\n for (i = 0; i < tableFields.length; i += 1) {\n if (tableFields[i].name === 'head table') {\n tableFields[i].value.checkSumAdjustment = 0xB1B0AFBA - checkSum;\n checkSumAdjusted = true;\n break;\n }\n }\n\n if (!checkSumAdjusted) {\n throw new Error('Could not find head table with checkSum to adjust.');\n }\n\n return sfntTable;\n}\n\nexports.computeCheckSum = computeCheckSum;\nexports.make = makeSfntTable;\nexports.fontToTable = fontToSfntTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/sfnt.js\n ** module id = 7\n ** module chunks = 0\n **/","// Run-time checking of preconditions.\n\n'use strict';\n\n// Precondition function that checks if the given predicate is true.\n// If not, it will throw an error.\nexports.argument = function(predicate, message) {\n if (!predicate) {\n throw new Error(message);\n }\n};\n\n// Precondition function that checks if the given assertion is true.\n// If not, it will throw an error.\nexports.assert = exports.argument;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/check.js\n ** module id = 8\n ** module chunks = 0\n **/","// Table metadata\n\n'use strict';\n\nvar check = require('./check');\nvar encode = require('./types').encode;\nvar sizeOf = require('./types').sizeOf;\n\nfunction Table(tableName, fields, options) {\n var i;\n for (i = 0; i < fields.length; i += 1) {\n var field = fields[i];\n this[field.name] = field.value;\n }\n\n this.tableName = tableName;\n this.fields = fields;\n if (options) {\n var optionKeys = Object.keys(options);\n for (i = 0; i < optionKeys.length; i += 1) {\n var k = optionKeys[i];\n var v = options[k];\n if (this[k] !== undefined) {\n this[k] = v;\n }\n }\n }\n}\n\nTable.prototype.encode = function() {\n return encode.TABLE(this);\n};\n\nTable.prototype.sizeOf = function() {\n return sizeOf.TABLE(this);\n};\n\nfunction ushortList(itemName, list, count) {\n if (count === undefined) {\n count = list.length;\n }\n var fields = new Array(list.length + 1);\n fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count};\n for (var i = 0; i < list.length; i++) {\n fields[i + 1] = {name: itemName + i, type: 'USHORT', value: list[i]};\n }\n return fields;\n}\n\nfunction tableList(itemName, records, itemCallback) {\n var count = records.length;\n var fields = new Array(count + 1);\n fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count};\n for (var i = 0; i < count; i++) {\n fields[i + 1] = {name: itemName + i, type: 'TABLE', value: itemCallback(records[i], i)};\n }\n return fields;\n}\n\nfunction recordList(itemName, records, itemCallback) {\n var count = records.length;\n var fields = [];\n fields[0] = {name: itemName + 'Count', type: 'USHORT', value: count};\n for (var i = 0; i < count; i++) {\n fields = fields.concat(itemCallback(records[i], i));\n }\n return fields;\n}\n\n// Common Layout Tables\nfunction Coverage(coverageTable) {\n if (coverageTable.format === 1) {\n Table.call(this, 'coverageTable',\n [{name: 'coverageFormat', type: 'USHORT', value: 1}]\n .concat(ushortList('glyph', coverageTable.glyphs))\n );\n } else {\n check.assert(false, 'Can\\'t create coverage table format 2 yet.');\n }\n}\nCoverage.prototype = Object.create(Table.prototype);\nCoverage.prototype.constructor = Coverage;\n\n// Missing: script list. See gsub.js\n\nfunction FeatureList(featureListTable) {\n Table.call(this, 'featureListTable',\n recordList('featureRecord', featureListTable, function(featureRecord, i) {\n var feature = featureRecord.feature;\n return [\n {name: 'featureTag' + i, type: 'TAG', value: featureRecord.tag},\n {name: 'feature' + i, type: 'TABLE', value: new Table('featureTable', [\n {name: 'featureParams', type: 'USHORT', value: feature.featureParams},\n ].concat(ushortList('lookupListIndex', feature.lookupListIndexes)))}\n ];\n })\n );\n}\nFeatureList.prototype = Object.create(Table.prototype);\nFeatureList.prototype.constructor = FeatureList;\n\nfunction LookupList(lookupListTable, subtableMakers) {\n Table.call(this, 'lookupListTable', tableList('lookup', lookupListTable, function(lookupTable) {\n return new Table('lookupTable', [\n {name: 'lookupType', type: 'USHORT', value: lookupTable.lookupType},\n {name: 'lookupFlag', type: 'USHORT', value: lookupTable.lookupFlag}\n ].concat(tableList('subtable', lookupTable.subtables, subtableMakers[lookupTable.lookupType])));\n }));\n}\nLookupList.prototype = Object.create(Table.prototype);\nLookupList.prototype.constructor = LookupList;\n\n// Record = same as Table, but inlined (a Table has an offset and its data is further in the stream)\n// Don't use offsets inside Records (probable bug), only in Tables.\nexports.Record = exports.Table = Table;\nexports.Coverage = Coverage;\nexports.FeatureList = FeatureList;\nexports.LookupList = LookupList;\n\nexports.ushortList = ushortList;\nexports.tableList = tableList;\nexports.recordList = recordList;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/table.js\n ** module id = 9\n ** module chunks = 0\n **/","// Data types used in the OpenType font file.\n// All OpenType fonts use Motorola-style byte ordering (Big Endian)\n\n/* global WeakMap */\n\n'use strict';\n\nvar check = require('./check');\n\nvar LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15\nvar LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31\n\nvar decode = {};\nvar encode = {};\nvar sizeOf = {};\n\n// Return a function that always returns the same value.\nfunction constant(v) {\n return function() {\n return v;\n };\n}\n\n// OpenType data types //////////////////////////////////////////////////////\n\n// Convert an 8-bit unsigned integer to a list of 1 byte.\nencode.BYTE = function(v) {\n check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');\n return [v];\n};\n\nsizeOf.BYTE = constant(1);\n\n// Convert a 8-bit signed integer to a list of 1 byte.\nencode.CHAR = function(v) {\n return [v.charCodeAt(0)];\n};\n\nsizeOf.CHAR = constant(1);\n\n// Convert an ASCII string to a list of bytes.\nencode.CHARARRAY = function(v) {\n var b = [];\n for (var i = 0; i < v.length; i += 1) {\n b.push(v.charCodeAt(i));\n }\n\n return b;\n};\n\nsizeOf.CHARARRAY = function(v) {\n return v.length;\n};\n\n// Convert a 16-bit unsigned integer to a list of 2 bytes.\nencode.USHORT = function(v) {\n return [(v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.USHORT = constant(2);\n\n// Convert a 16-bit signed integer to a list of 2 bytes.\nencode.SHORT = function(v) {\n // Two's complement\n if (v >= LIMIT16) {\n v = -(2 * LIMIT16 - v);\n }\n\n return [(v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.SHORT = constant(2);\n\n// Convert a 24-bit unsigned integer to a list of 3 bytes.\nencode.UINT24 = function(v) {\n return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.UINT24 = constant(3);\n\n// Convert a 32-bit unsigned integer to a list of 4 bytes.\nencode.ULONG = function(v) {\n return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.ULONG = constant(4);\n\n// Convert a 32-bit unsigned integer to a list of 4 bytes.\nencode.LONG = function(v) {\n // Two's complement\n if (v >= LIMIT32) {\n v = -(2 * LIMIT32 - v);\n }\n\n return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.LONG = constant(4);\n\nencode.FIXED = encode.ULONG;\nsizeOf.FIXED = sizeOf.ULONG;\n\nencode.FWORD = encode.SHORT;\nsizeOf.FWORD = sizeOf.SHORT;\n\nencode.UFWORD = encode.USHORT;\nsizeOf.UFWORD = sizeOf.USHORT;\n\n// FIXME Implement LONGDATETIME\n// Convert a 32-bit Apple Mac timestamp integer to a list of 8 bytes, 64-bit timestamp.\nencode.LONGDATETIME = function(v) {\n return [0, 0, 0, 0, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.LONGDATETIME = constant(8);\n\n// Convert a 4-char tag to a list of 4 bytes.\nencode.TAG = function(v) {\n check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');\n return [v.charCodeAt(0),\n v.charCodeAt(1),\n v.charCodeAt(2),\n v.charCodeAt(3)];\n};\n\nsizeOf.TAG = constant(4);\n\n// CFF data types ///////////////////////////////////////////////////////////\n\nencode.Card8 = encode.BYTE;\nsizeOf.Card8 = sizeOf.BYTE;\n\nencode.Card16 = encode.USHORT;\nsizeOf.Card16 = sizeOf.USHORT;\n\nencode.OffSize = encode.BYTE;\nsizeOf.OffSize = sizeOf.BYTE;\n\nencode.SID = encode.USHORT;\nsizeOf.SID = sizeOf.USHORT;\n\n// Convert a numeric operand or charstring number to a variable-size list of bytes.\nencode.NUMBER = function(v) {\n if (v >= -107 && v <= 107) {\n return [v + 139];\n } else if (v >= 108 && v <= 1131) {\n v = v - 108;\n return [(v >> 8) + 247, v & 0xFF];\n } else if (v >= -1131 && v <= -108) {\n v = -v - 108;\n return [(v >> 8) + 251, v & 0xFF];\n } else if (v >= -32768 && v <= 32767) {\n return encode.NUMBER16(v);\n } else {\n return encode.NUMBER32(v);\n }\n};\n\nsizeOf.NUMBER = function(v) {\n return encode.NUMBER(v).length;\n};\n\n// Convert a signed number between -32768 and +32767 to a three-byte value.\n// This ensures we always use three bytes, but is not the most compact format.\nencode.NUMBER16 = function(v) {\n return [28, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.NUMBER16 = constant(3);\n\n// Convert a signed number between -(2^31) and +(2^31-1) to a five-byte value.\n// This is useful if you want to be sure you always use four bytes,\n// at the expense of wasting a few bytes for smaller numbers.\nencode.NUMBER32 = function(v) {\n return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];\n};\n\nsizeOf.NUMBER32 = constant(5);\n\nencode.REAL = function(v) {\n var value = v.toString();\n\n // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)\n // This code converts it back to a number without the epsilon.\n var m = /\\.(\\d*?)(?:9{5,20}|0{5,20})\\d{0,2}(?:e(.+)|$)/.exec(value);\n if (m) {\n var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));\n value = (Math.round(v * epsilon) / epsilon).toString();\n }\n\n var nibbles = '';\n var i;\n var ii;\n for (i = 0, ii = value.length; i < ii; i += 1) {\n var c = value[i];\n if (c === 'e') {\n nibbles += value[++i] === '-' ? 'c' : 'b';\n } else if (c === '.') {\n nibbles += 'a';\n } else if (c === '-') {\n nibbles += 'e';\n } else {\n nibbles += c;\n }\n }\n\n nibbles += (nibbles.length & 1) ? 'f' : 'ff';\n var out = [30];\n for (i = 0, ii = nibbles.length; i < ii; i += 2) {\n out.push(parseInt(nibbles.substr(i, 2), 16));\n }\n\n return out;\n};\n\nsizeOf.REAL = function(v) {\n return encode.REAL(v).length;\n};\n\nencode.NAME = encode.CHARARRAY;\nsizeOf.NAME = sizeOf.CHARARRAY;\n\nencode.STRING = encode.CHARARRAY;\nsizeOf.STRING = sizeOf.CHARARRAY;\n\ndecode.UTF16 = function(data, offset, numBytes) {\n var codePoints = [];\n var numChars = numBytes / 2;\n for (var j = 0; j < numChars; j++, offset += 2) {\n codePoints[j] = data.getUint16(offset);\n }\n\n return String.fromCharCode.apply(null, codePoints);\n};\n\n// Convert a JavaScript string to UTF16-BE.\nencode.UTF16 = function(v) {\n var b = [];\n for (var i = 0; i < v.length; i += 1) {\n var codepoint = v.charCodeAt(i);\n b.push((codepoint >> 8) & 0xFF);\n b.push(codepoint & 0xFF);\n }\n\n return b;\n};\n\nsizeOf.UTF16 = function(v) {\n return v.length * 2;\n};\n\n// Data for converting old eight-bit Macintosh encodings to Unicode.\n// This representation is optimized for decoding; encoding is slower\n// and needs more memory. The assumption is that all opentype.js users\n// want to open fonts, but saving a font will be comperatively rare\n// so it can be more expensive. Keyed by IANA character set name.\n//\n// Python script for generating these strings:\n//\n// s = u''.join([chr(c).decode('mac_greek') for c in range(128, 256)])\n// print(s.encode('utf-8'))\nvar eightBitMacEncodings = {\n 'x-mac-croatian': // Python: 'mac_croatian'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø' +\n '¿¡¬√ƒ≈ƫȅ ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ',\n 'x-mac-cyrillic': // Python: 'mac_cyrillic'\n 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњ' +\n 'јЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю',\n 'x-mac-gaelic':\n // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/GAELIC.TXT\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæø' +\n 'ṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ',\n 'x-mac-greek': // Python: 'mac_greek'\n 'Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩ' +\n 'άΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ\\u00AD',\n 'x-mac-icelandic': // Python: 'mac_iceland'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüݰ¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +\n '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',\n 'x-mac-inuit':\n // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/INUIT.TXT\n 'ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗ' +\n 'ᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł',\n 'x-mac-ce': // Python: 'mac_latin2'\n 'ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅ' +\n 'ņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ',\n macintosh: // Python: 'mac_roman'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +\n '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',\n 'x-mac-romanian': // Python: 'mac_romanian'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș' +\n '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',\n 'x-mac-turkish': // Python: 'mac_turkish'\n 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' +\n '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ'\n};\n\n// Decodes an old-style Macintosh string. Returns either a Unicode JavaScript\n// string, or 'undefined' if the encoding is unsupported. For example, we do\n// not support Chinese, Japanese or Korean because these would need large\n// mapping tables.\ndecode.MACSTRING = function(dataView, offset, dataLength, encoding) {\n var table = eightBitMacEncodings[encoding];\n if (table === undefined) {\n return undefined;\n }\n\n var result = '';\n for (var i = 0; i < dataLength; i++) {\n var c = dataView.getUint8(offset + i);\n // In all eight-bit Mac encodings, the characters 0x00..0x7F are\n // mapped to U+0000..U+007F; we only need to look up the others.\n if (c <= 0x7F) {\n result += String.fromCharCode(c);\n } else {\n result += table[c & 0x7F];\n }\n }\n\n return result;\n};\n\n// Helper function for encode.MACSTRING. Returns a dictionary for mapping\n// Unicode character codes to their 8-bit MacOS equivalent. This table\n// is not exactly a super cheap data structure, but we do not care because\n// encoding Macintosh strings is only rarely needed in typical applications.\nvar macEncodingTableCache = typeof WeakMap === 'function' && new WeakMap();\nvar macEncodingCacheKeys;\nvar getMacEncodingTable = function(encoding) {\n // Since we use encoding as a cache key for WeakMap, it has to be\n // a String object and not a literal. And at least on NodeJS 2.10.1,\n // WeakMap requires that the same String instance is passed for cache hits.\n if (!macEncodingCacheKeys) {\n macEncodingCacheKeys = {};\n for (var e in eightBitMacEncodings) {\n /*jshint -W053 */ // Suppress \"Do not use String as a constructor.\"\n macEncodingCacheKeys[e] = new String(e);\n }\n }\n\n var cacheKey = macEncodingCacheKeys[encoding];\n if (cacheKey === undefined) {\n return undefined;\n }\n\n // We can't do \"if (cache.has(key)) {return cache.get(key)}\" here:\n // since garbage collection may run at any time, it could also kick in\n // between the calls to cache.has() and cache.get(). In that case,\n // we would return 'undefined' even though we do support the encoding.\n if (macEncodingTableCache) {\n var cachedTable = macEncodingTableCache.get(cacheKey);\n if (cachedTable !== undefined) {\n return cachedTable;\n }\n }\n\n var decodingTable = eightBitMacEncodings[encoding];\n if (decodingTable === undefined) {\n return undefined;\n }\n\n var encodingTable = {};\n for (var i = 0; i < decodingTable.length; i++) {\n encodingTable[decodingTable.charCodeAt(i)] = i + 0x80;\n }\n\n if (macEncodingTableCache) {\n macEncodingTableCache.set(cacheKey, encodingTable);\n }\n\n return encodingTable;\n};\n\n// Encodes an old-style Macintosh string. Returns a byte array upon success.\n// If the requested encoding is unsupported, or if the input string contains\n// a character that cannot be expressed in the encoding, the function returns\n// 'undefined'.\nencode.MACSTRING = function(str, encoding) {\n var table = getMacEncodingTable(encoding);\n if (table === undefined) {\n return undefined;\n }\n\n var result = [];\n for (var i = 0; i < str.length; i++) {\n var c = str.charCodeAt(i);\n\n // In all eight-bit Mac encodings, the characters 0x00..0x7F are\n // mapped to U+0000..U+007F; we only need to look up the others.\n if (c >= 0x80) {\n c = table[c];\n if (c === undefined) {\n // str contains a Unicode character that cannot be encoded\n // in the requested encoding.\n return undefined;\n }\n }\n\n result.push(c);\n }\n\n return result;\n};\n\nsizeOf.MACSTRING = function(str, encoding) {\n var b = encode.MACSTRING(str, encoding);\n if (b !== undefined) {\n return b.length;\n } else {\n return 0;\n }\n};\n\n// Convert a list of values to a CFF INDEX structure.\n// The values should be objects containing name / type / value.\nencode.INDEX = function(l) {\n var i;\n //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,\n // i, v;\n // Because we have to know which data type to use to encode the offsets,\n // we have to go through the values twice: once to encode the data and\n // calculate the offets, then again to encode the offsets using the fitting data type.\n var offset = 1; // First offset is always 1.\n var offsets = [offset];\n var data = [];\n for (i = 0; i < l.length; i += 1) {\n var v = encode.OBJECT(l[i]);\n Array.prototype.push.apply(data, v);\n offset += v.length;\n offsets.push(offset);\n }\n\n if (data.length === 0) {\n return [0, 0];\n }\n\n var encodedOffsets = [];\n var offSize = (1 + Math.floor(Math.log(offset) / Math.log(2)) / 8) | 0;\n var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];\n for (i = 0; i < offsets.length; i += 1) {\n var encodedOffset = offsetEncoder(offsets[i]);\n Array.prototype.push.apply(encodedOffsets, encodedOffset);\n }\n\n return Array.prototype.concat(encode.Card16(l.length),\n encode.OffSize(offSize),\n encodedOffsets,\n data);\n};\n\nsizeOf.INDEX = function(v) {\n return encode.INDEX(v).length;\n};\n\n// Convert an object to a CFF DICT structure.\n// The keys should be numeric.\n// The values should be objects containing name / type / value.\nencode.DICT = function(m) {\n var d = [];\n var keys = Object.keys(m);\n var length = keys.length;\n\n for (var i = 0; i < length; i += 1) {\n // Object.keys() return string keys, but our keys are always numeric.\n var k = parseInt(keys[i], 0);\n var v = m[k];\n // Value comes before the key.\n d = d.concat(encode.OPERAND(v.value, v.type));\n d = d.concat(encode.OPERATOR(k));\n }\n\n return d;\n};\n\nsizeOf.DICT = function(m) {\n return encode.DICT(m).length;\n};\n\nencode.OPERATOR = function(v) {\n if (v < 1200) {\n return [v];\n } else {\n return [12, v - 1200];\n }\n};\n\nencode.OPERAND = function(v, type) {\n var d = [];\n if (Array.isArray(type)) {\n for (var i = 0; i < type.length; i += 1) {\n check.argument(v.length === type.length, 'Not enough arguments given for type' + type);\n d = d.concat(encode.OPERAND(v[i], type[i]));\n }\n } else {\n if (type === 'SID') {\n d = d.concat(encode.NUMBER(v));\n } else if (type === 'offset') {\n // We make it easy for ourselves and always encode offsets as\n // 4 bytes. This makes offset calculation for the top dict easier.\n d = d.concat(encode.NUMBER32(v));\n } else if (type === 'number') {\n d = d.concat(encode.NUMBER(v));\n } else if (type === 'real') {\n d = d.concat(encode.REAL(v));\n } else {\n throw new Error('Unknown operand type ' + type);\n // FIXME Add support for booleans\n }\n }\n\n return d;\n};\n\nencode.OP = encode.BYTE;\nsizeOf.OP = sizeOf.BYTE;\n\n// memoize charstring encoding using WeakMap if available\nvar wmm = typeof WeakMap === 'function' && new WeakMap();\n// Convert a list of CharString operations to bytes.\nencode.CHARSTRING = function(ops) {\n // See encode.MACSTRING for why we don't do \"if (wmm && wmm.has(ops))\".\n if (wmm) {\n var cachedValue = wmm.get(ops);\n if (cachedValue !== undefined) {\n return cachedValue;\n }\n }\n\n var d = [];\n var length = ops.length;\n\n for (var i = 0; i < length; i += 1) {\n var op = ops[i];\n d = d.concat(encode[op.type](op.value));\n }\n\n if (wmm) {\n wmm.set(ops, d);\n }\n\n return d;\n};\n\nsizeOf.CHARSTRING = function(ops) {\n return encode.CHARSTRING(ops).length;\n};\n\n// Utility functions ////////////////////////////////////////////////////////\n\n// Convert an object containing name / type / value to bytes.\nencode.OBJECT = function(v) {\n var encodingFunction = encode[v.type];\n check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);\n return encodingFunction(v.value);\n};\n\nsizeOf.OBJECT = function(v) {\n var sizeOfFunction = sizeOf[v.type];\n check.argument(sizeOfFunction !== undefined, 'No sizeOf function for type ' + v.type);\n return sizeOfFunction(v.value);\n};\n\n// Convert a table object to bytes.\n// A table contains a list of fields containing the metadata (name, type and default value).\n// The table itself has the field values set as attributes.\nencode.TABLE = function(table) {\n var d = [];\n var length = table.fields.length;\n var subtables = [];\n var subtableOffsets = [];\n var i;\n\n for (i = 0; i < length; i += 1) {\n var field = table.fields[i];\n var encodingFunction = encode[field.type];\n check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type + ' (' + field.name + ')');\n var value = table[field.name];\n if (value === undefined) {\n value = field.value;\n }\n\n var bytes = encodingFunction(value);\n\n if (field.type === 'TABLE') {\n subtableOffsets.push(d.length);\n d = d.concat([0, 0]);\n subtables.push(bytes);\n } else {\n d = d.concat(bytes);\n }\n }\n\n for (i = 0; i < subtables.length; i += 1) {\n var o = subtableOffsets[i];\n var offset = d.length;\n check.argument(offset < 65536, 'Table ' + table.tableName + ' too big.');\n d[o] = offset >> 8;\n d[o + 1] = offset & 0xff;\n d = d.concat(subtables[i]);\n }\n\n return d;\n};\n\nsizeOf.TABLE = function(table) {\n var numBytes = 0;\n var length = table.fields.length;\n\n for (var i = 0; i < length; i += 1) {\n var field = table.fields[i];\n var sizeOfFunction = sizeOf[field.type];\n check.argument(sizeOfFunction !== undefined, 'No sizeOf function for field type ' + field.type + ' (' + field.name + ')');\n var value = table[field.name];\n if (value === undefined) {\n value = field.value;\n }\n\n numBytes += sizeOfFunction(value);\n\n // Subtables take 2 more bytes for offsets.\n if (field.type === 'TABLE') {\n numBytes += 2;\n }\n }\n\n return numBytes;\n};\n\nencode.RECORD = encode.TABLE;\nsizeOf.RECORD = sizeOf.TABLE;\n\n// Merge in a list of bytes.\nencode.LITERAL = function(v) {\n return v;\n};\n\nsizeOf.LITERAL = function(v) {\n return v.length;\n};\n\nexports.decode = decode;\nexports.encode = encode;\nexports.sizeOf = sizeOf;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/types.js\n ** module id = 10\n ** module chunks = 0\n **/","// The `cmap` table stores the mappings from characters to glyphs.\n// https://www.microsoft.com/typography/OTSPEC/cmap.htm\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the `cmap` table. This table stores the mappings from characters to glyphs.\n// There are many available formats, but we only support the Windows format 4.\n// This function returns a `CmapEncoding` object or null if no supported format could be found.\nfunction parseCmapTable(data, start) {\n var i;\n var cmap = {};\n cmap.version = parse.getUShort(data, start);\n check.argument(cmap.version === 0, 'cmap table version should be 0.');\n\n // The cmap table can contain many sub-tables, each with their own format.\n // We're only interested in a \"platform 3\" table. This is a Windows format.\n cmap.numTables = parse.getUShort(data, start + 2);\n var offset = -1;\n for (i = 0; i < cmap.numTables; i += 1) {\n var platformId = parse.getUShort(data, start + 4 + (i * 8));\n var encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2);\n if (platformId === 3 && (encodingId === 1 || encodingId === 0)) {\n offset = parse.getULong(data, start + 4 + (i * 8) + 4);\n break;\n }\n }\n\n if (offset === -1) {\n // There is no cmap table in the font that we support, so return null.\n // This font will be marked as unsupported.\n return null;\n }\n\n var p = new parse.Parser(data, start + offset);\n cmap.format = p.parseUShort();\n check.argument(cmap.format === 4, 'Only format 4 cmap tables are supported.');\n\n // Length in bytes of the sub-tables.\n cmap.length = p.parseUShort();\n cmap.language = p.parseUShort();\n\n // segCount is stored x 2.\n var segCount;\n cmap.segCount = segCount = p.parseUShort() >> 1;\n\n // Skip searchRange, entrySelector, rangeShift.\n p.skip('uShort', 3);\n\n // The \"unrolled\" mapping from character codes to glyph indices.\n cmap.glyphIndexMap = {};\n\n var endCountParser = new parse.Parser(data, start + offset + 14);\n var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);\n var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);\n var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);\n var glyphIndexOffset = start + offset + 16 + segCount * 8;\n for (i = 0; i < segCount - 1; i += 1) {\n var glyphIndex;\n var endCount = endCountParser.parseUShort();\n var startCount = startCountParser.parseUShort();\n var idDelta = idDeltaParser.parseShort();\n var idRangeOffset = idRangeOffsetParser.parseUShort();\n for (var c = startCount; c <= endCount; c += 1) {\n if (idRangeOffset !== 0) {\n // The idRangeOffset is relative to the current position in the idRangeOffset array.\n // Take the current offset in the idRangeOffset array.\n glyphIndexOffset = (idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2);\n\n // Add the value of the idRangeOffset, which will move us into the glyphIndex array.\n glyphIndexOffset += idRangeOffset;\n\n // Then add the character index of the current segment, multiplied by 2 for USHORTs.\n glyphIndexOffset += (c - startCount) * 2;\n glyphIndex = parse.getUShort(data, glyphIndexOffset);\n if (glyphIndex !== 0) {\n glyphIndex = (glyphIndex + idDelta) & 0xFFFF;\n }\n } else {\n glyphIndex = (c + idDelta) & 0xFFFF;\n }\n\n cmap.glyphIndexMap[c] = glyphIndex;\n }\n }\n\n return cmap;\n}\n\nfunction addSegment(t, code, glyphIndex) {\n t.segments.push({\n end: code,\n start: code,\n delta: -(code - glyphIndex),\n offset: 0\n });\n}\n\nfunction addTerminatorSegment(t) {\n t.segments.push({\n end: 0xFFFF,\n start: 0xFFFF,\n delta: 1,\n offset: 0\n });\n}\n\nfunction makeCmapTable(glyphs) {\n var i;\n var t = new table.Table('cmap', [\n {name: 'version', type: 'USHORT', value: 0},\n {name: 'numTables', type: 'USHORT', value: 1},\n {name: 'platformID', type: 'USHORT', value: 3},\n {name: 'encodingID', type: 'USHORT', value: 1},\n {name: 'offset', type: 'ULONG', value: 12},\n {name: 'format', type: 'USHORT', value: 4},\n {name: 'length', type: 'USHORT', value: 0},\n {name: 'language', type: 'USHORT', value: 0},\n {name: 'segCountX2', type: 'USHORT', value: 0},\n {name: 'searchRange', type: 'USHORT', value: 0},\n {name: 'entrySelector', type: 'USHORT', value: 0},\n {name: 'rangeShift', type: 'USHORT', value: 0}\n ]);\n\n t.segments = [];\n for (i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs.get(i);\n for (var j = 0; j < glyph.unicodes.length; j += 1) {\n addSegment(t, glyph.unicodes[j], i);\n }\n\n t.segments = t.segments.sort(function(a, b) {\n return a.start - b.start;\n });\n }\n\n addTerminatorSegment(t);\n\n var segCount;\n segCount = t.segments.length;\n t.segCountX2 = segCount * 2;\n t.searchRange = Math.pow(2, Math.floor(Math.log(segCount) / Math.log(2))) * 2;\n t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2);\n t.rangeShift = t.segCountX2 - t.searchRange;\n\n // Set up parallel segment arrays.\n var endCounts = [];\n var startCounts = [];\n var idDeltas = [];\n var idRangeOffsets = [];\n var glyphIds = [];\n\n for (i = 0; i < segCount; i += 1) {\n var segment = t.segments[i];\n endCounts = endCounts.concat({name: 'end_' + i, type: 'USHORT', value: segment.end});\n startCounts = startCounts.concat({name: 'start_' + i, type: 'USHORT', value: segment.start});\n idDeltas = idDeltas.concat({name: 'idDelta_' + i, type: 'SHORT', value: segment.delta});\n idRangeOffsets = idRangeOffsets.concat({name: 'idRangeOffset_' + i, type: 'USHORT', value: segment.offset});\n if (segment.glyphId !== undefined) {\n glyphIds = glyphIds.concat({name: 'glyph_' + i, type: 'USHORT', value: segment.glyphId});\n }\n }\n\n t.fields = t.fields.concat(endCounts);\n t.fields.push({name: 'reservedPad', type: 'USHORT', value: 0});\n t.fields = t.fields.concat(startCounts);\n t.fields = t.fields.concat(idDeltas);\n t.fields = t.fields.concat(idRangeOffsets);\n t.fields = t.fields.concat(glyphIds);\n\n t.length = 14 + // Subtable header\n endCounts.length * 2 +\n 2 + // reservedPad\n startCounts.length * 2 +\n idDeltas.length * 2 +\n idRangeOffsets.length * 2 +\n glyphIds.length * 2;\n\n return t;\n}\n\nexports.parse = parseCmapTable;\nexports.make = makeCmapTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/cmap.js\n ** module id = 11\n ** module chunks = 0\n **/","// Parsing utility functions\n\n'use strict';\n\nvar check = require('./check');\n\n// Retrieve an unsigned byte from the DataView.\nexports.getByte = function getByte(dataView, offset) {\n return dataView.getUint8(offset);\n};\n\nexports.getCard8 = exports.getByte;\n\n// Retrieve an unsigned 16-bit short from the DataView.\n// The value is stored in big endian.\nfunction getUShort(dataView, offset) {\n return dataView.getUint16(offset, false);\n}\n\nexports.getUShort = exports.getCard16 = getUShort;\n\n// Retrieve a signed 16-bit short from the DataView.\n// The value is stored in big endian.\nexports.getShort = function(dataView, offset) {\n return dataView.getInt16(offset, false);\n};\n\n// Retrieve an unsigned 32-bit long from the DataView.\n// The value is stored in big endian.\nexports.getULong = function(dataView, offset) {\n return dataView.getUint32(offset, false);\n};\n\n// Retrieve a 32-bit signed fixed-point number (16.16) from the DataView.\n// The value is stored in big endian.\nexports.getFixed = function(dataView, offset) {\n var decimal = dataView.getInt16(offset, false);\n var fraction = dataView.getUint16(offset + 2, false);\n return decimal + fraction / 65535;\n};\n\n// Retrieve a 4-character tag from the DataView.\n// Tags are used to identify tables.\nexports.getTag = function(dataView, offset) {\n var tag = '';\n for (var i = offset; i < offset + 4; i += 1) {\n tag += String.fromCharCode(dataView.getInt8(i));\n }\n\n return tag;\n};\n\n// Retrieve an offset from the DataView.\n// Offsets are 1 to 4 bytes in length, depending on the offSize argument.\nexports.getOffset = function(dataView, offset, offSize) {\n var v = 0;\n for (var i = 0; i < offSize; i += 1) {\n v <<= 8;\n v += dataView.getUint8(offset + i);\n }\n\n return v;\n};\n\n// Retrieve a number of bytes from start offset to the end offset from the DataView.\nexports.getBytes = function(dataView, startOffset, endOffset) {\n var bytes = [];\n for (var i = startOffset; i < endOffset; i += 1) {\n bytes.push(dataView.getUint8(i));\n }\n\n return bytes;\n};\n\n// Convert the list of bytes to a string.\nexports.bytesToString = function(bytes) {\n var s = '';\n for (var i = 0; i < bytes.length; i += 1) {\n s += String.fromCharCode(bytes[i]);\n }\n\n return s;\n};\n\nvar typeOffsets = {\n byte: 1,\n uShort: 2,\n short: 2,\n uLong: 4,\n fixed: 4,\n longDateTime: 8,\n tag: 4\n};\n\n// A stateful parser that changes the offset whenever a value is retrieved.\n// The data is a DataView.\nfunction Parser(data, offset) {\n this.data = data;\n this.offset = offset;\n this.relativeOffset = 0;\n}\n\nParser.prototype.parseByte = function() {\n var v = this.data.getUint8(this.offset + this.relativeOffset);\n this.relativeOffset += 1;\n return v;\n};\n\nParser.prototype.parseChar = function() {\n var v = this.data.getInt8(this.offset + this.relativeOffset);\n this.relativeOffset += 1;\n return v;\n};\n\nParser.prototype.parseCard8 = Parser.prototype.parseByte;\n\nParser.prototype.parseUShort = function() {\n var v = this.data.getUint16(this.offset + this.relativeOffset);\n this.relativeOffset += 2;\n return v;\n};\n\nParser.prototype.parseCard16 = Parser.prototype.parseUShort;\nParser.prototype.parseSID = Parser.prototype.parseUShort;\nParser.prototype.parseOffset16 = Parser.prototype.parseUShort;\n\nParser.prototype.parseShort = function() {\n var v = this.data.getInt16(this.offset + this.relativeOffset);\n this.relativeOffset += 2;\n return v;\n};\n\nParser.prototype.parseF2Dot14 = function() {\n var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;\n this.relativeOffset += 2;\n return v;\n};\n\nParser.prototype.parseULong = function() {\n var v = exports.getULong(this.data, this.offset + this.relativeOffset);\n this.relativeOffset += 4;\n return v;\n};\n\nParser.prototype.parseFixed = function() {\n var v = exports.getFixed(this.data, this.offset + this.relativeOffset);\n this.relativeOffset += 4;\n return v;\n};\n\nParser.prototype.parseString = function(length) {\n var dataView = this.data;\n var offset = this.offset + this.relativeOffset;\n var string = '';\n this.relativeOffset += length;\n for (var i = 0; i < length; i++) {\n string += String.fromCharCode(dataView.getUint8(offset + i));\n }\n\n return string;\n};\n\nParser.prototype.parseTag = function() {\n return this.parseString(4);\n};\n\n// LONGDATETIME is a 64-bit integer.\n// JavaScript and unix timestamps traditionally use 32 bits, so we\n// only take the last 32 bits.\n// + Since until 2038 those bits will be filled by zeros we can ignore them.\nParser.prototype.parseLongDateTime = function() {\n var v = exports.getULong(this.data, this.offset + this.relativeOffset + 4);\n // Subtract seconds between 01/01/1904 and 01/01/1970\n // to convert Apple Mac timstamp to Standard Unix timestamp\n v -= 2082844800;\n this.relativeOffset += 8;\n return v;\n};\n\nParser.prototype.parseVersion = function() {\n var major = getUShort(this.data, this.offset + this.relativeOffset);\n\n // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1\n // This returns the correct number if minor = 0xN000 where N is 0-9\n var minor = getUShort(this.data, this.offset + this.relativeOffset + 2);\n this.relativeOffset += 4;\n return major + minor / 0x1000 / 10;\n};\n\nParser.prototype.skip = function(type, amount) {\n if (amount === undefined) {\n amount = 1;\n }\n\n this.relativeOffset += typeOffsets[type] * amount;\n};\n\n///// Parsing lists and records ///////////////////////////////\n\n// Parse a list of 16 bit integers. The length of the list can be read on the stream\n// or provided as an argument.\nParser.prototype.parseOffset16List =\nParser.prototype.parseUShortList = function(count) {\n if (count === undefined) { count = this.parseUShort(); }\n var offsets = new Array(count);\n var dataView = this.data;\n var offset = this.offset + this.relativeOffset;\n for (var i = 0; i < count; i++) {\n offsets[i] = dataView.getUint16(offset);\n offset += 2;\n }\n\n this.relativeOffset += count * 2;\n return offsets;\n};\n\n/**\n * Parse a list of items.\n * Record count is optional, if omitted it is read from the stream.\n * itemCallback is one of the Parser methods.\n */\nParser.prototype.parseList = function(count, itemCallback) {\n if (!itemCallback) {\n itemCallback = count;\n count = this.parseUShort();\n }\n var list = new Array(count);\n for (var i = 0; i < count; i++) {\n list[i] = itemCallback.call(this);\n }\n return list;\n};\n\n/**\n * Parse a list of records.\n * Record count is optional, if omitted it is read from the stream.\n * Example of recordDescription: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }\n */\nParser.prototype.parseRecordList = function(count, recordDescription) {\n // If the count argument is absent, read it in the stream.\n if (!recordDescription) {\n recordDescription = count;\n count = this.parseUShort();\n }\n var records = new Array(count);\n var fields = Object.keys(recordDescription);\n for (var i = 0; i < count; i++) {\n var rec = {};\n for (var j = 0; j < fields.length; j++) {\n var fieldName = fields[j];\n var fieldType = recordDescription[fieldName];\n rec[fieldName] = fieldType.call(this);\n }\n records[i] = rec;\n }\n return records;\n};\n\n// Parse a data structure into an object\n// Example of description: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }\nParser.prototype.parseStruct = function(description) {\n if (typeof description === 'function') {\n return description.call(this);\n } else {\n var fields = Object.keys(description);\n var struct = {};\n for (var j = 0; j < fields.length; j++) {\n var fieldName = fields[j];\n var fieldType = description[fieldName];\n struct[fieldName] = fieldType.call(this);\n }\n return struct;\n }\n};\n\nParser.prototype.parsePointer = function(description) {\n var structOffset = this.parseOffset16();\n if (structOffset > 0) { // NULL offset => return indefined\n return new Parser(this.data, this.offset + structOffset).parseStruct(description);\n }\n};\n\n/**\n * Parse a list of offsets to lists of 16-bit integers,\n * or a list of offsets to lists of offsets to any kind of items.\n * If itemCallback is not provided, a list of list of UShort is assumed.\n * If provided, itemCallback is called on each item and must parse the item.\n * See examples in tables/gsub.js\n */\nParser.prototype.parseListOfLists = function(itemCallback) {\n var offsets = this.parseOffset16List();\n var count = offsets.length;\n var relativeOffset = this.relativeOffset;\n var list = new Array(count);\n for (var i = 0; i < count; i++) {\n var start = offsets[i];\n if (start === 0) { // NULL offset\n list[i] = undefined; // Add i as owned property to list. Convenient with assert.\n continue;\n }\n this.relativeOffset = start;\n if (itemCallback) {\n var subOffsets = this.parseOffset16List();\n var subList = new Array(subOffsets.length);\n for (var j = 0; j < subOffsets.length; j++) {\n this.relativeOffset = start + subOffsets[j];\n subList[j] = itemCallback.call(this);\n }\n list[i] = subList;\n } else {\n list[i] = this.parseUShortList();\n }\n }\n this.relativeOffset = relativeOffset;\n return list;\n};\n\n///// Complex tables parsing //////////////////////////////////\n\n// Parse a coverage table in a GSUB, GPOS or GDEF table.\n// https://www.microsoft.com/typography/OTSPEC/chapter2.htm\n// parser.offset must point to the start of the table containing the coverage.\nParser.prototype.parseCoverage = function() {\n var startOffset = this.offset + this.relativeOffset;\n var format = this.parseUShort();\n var count = this.parseUShort();\n if (format === 1) {\n return {\n format: 1,\n glyphs: this.parseUShortList(count)\n };\n } else if (format === 2) {\n var ranges = new Array(count);\n for (var i = 0; i < count; i++) {\n ranges[i] = {\n start: this.parseUShort(),\n end: this.parseUShort(),\n index: this.parseUShort()\n };\n }\n return {\n format: 2,\n ranges: ranges\n };\n }\n check.assert(false, '0x' + startOffset.toString(16) + ': Coverage format must be 1 or 2.');\n};\n\n// Parse a Class Definition Table in a GSUB, GPOS or GDEF table.\n// https://www.microsoft.com/typography/OTSPEC/chapter2.htm\nParser.prototype.parseClassDef = function() {\n var startOffset = this.offset + this.relativeOffset;\n var format = this.parseUShort();\n if (format === 1) {\n return {\n format: 1,\n startGlyph: this.parseUShort(),\n classes: this.parseUShortList()\n };\n } else if (format === 2) {\n return {\n format: 2,\n ranges: this.parseRecordList({\n start: Parser.uShort,\n end: Parser.uShort,\n classId: Parser.uShort\n })\n };\n }\n check.assert(false, '0x' + startOffset.toString(16) + ': ClassDef format must be 1 or 2.');\n};\n\n///// Static methods ///////////////////////////////////\n// These convenience methods can be used as callbacks and should be called with \"this\" context set to a Parser instance.\n\nParser.list = function(count, itemCallback) {\n return function() {\n return this.parseList(count, itemCallback);\n };\n};\n\nParser.recordList = function(count, recordDescription) {\n return function() {\n return this.parseRecordList(count, recordDescription);\n };\n};\n\nParser.pointer = function(description) {\n return function() {\n return this.parsePointer(description);\n };\n};\n\nParser.tag = Parser.prototype.parseTag;\nParser.byte = Parser.prototype.parseByte;\nParser.uShort = Parser.offset16 = Parser.prototype.parseUShort;\nParser.uShortList = Parser.prototype.parseUShortList;\nParser.struct = Parser.prototype.parseStruct;\nParser.coverage = Parser.prototype.parseCoverage;\nParser.classDef = Parser.prototype.parseClassDef;\n\n///// Script, Feature, Lookup lists ///////////////////////////////////////////////\n// https://www.microsoft.com/typography/OTSPEC/chapter2.htm\n\nvar langSysTable = {\n reserved: Parser.uShort,\n reqFeatureIndex: Parser.uShort,\n featureIndexes: Parser.uShortList\n};\n\nParser.prototype.parseScriptList = function() {\n return this.parsePointer(Parser.recordList({\n tag: Parser.tag,\n script: Parser.pointer({\n defaultLangSys: Parser.pointer(langSysTable),\n langSysRecords: Parser.recordList({\n tag: Parser.tag,\n langSys: Parser.pointer(langSysTable)\n })\n })\n }));\n};\n\nParser.prototype.parseFeatureList = function() {\n return this.parsePointer(Parser.recordList({\n tag: Parser.tag,\n feature: Parser.pointer({\n featureParams: Parser.offset16,\n lookupListIndexes: Parser.uShortList\n })\n }));\n};\n\nParser.prototype.parseLookupList = function(lookupTableParsers) {\n return this.parsePointer(Parser.list(Parser.pointer(function() {\n var lookupType = this.parseUShort();\n check.argument(1 <= lookupType && lookupType <= 8, 'GSUB lookup type ' + lookupType + ' unknown.');\n var lookupFlag = this.parseUShort();\n var useMarkFilteringSet = lookupFlag & 0x10;\n return {\n lookupType: lookupType,\n lookupFlag: lookupFlag,\n subtables: this.parseList(Parser.pointer(lookupTableParsers[lookupType])),\n markFilteringSet: useMarkFilteringSet ? this.parseUShort() : undefined\n };\n })));\n};\n\nexports.Parser = Parser;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/parse.js\n ** module id = 12\n ** module chunks = 0\n **/","// The `CFF` table contains the glyph outlines in PostScript format.\n// https://www.microsoft.com/typography/OTSPEC/cff.htm\n// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/cff.pdf\n// http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/type2.pdf\n\n'use strict';\n\nvar encoding = require('../encoding');\nvar glyphset = require('../glyphset');\nvar parse = require('../parse');\nvar path = require('../path');\nvar table = require('../table');\n\n// Custom equals function that can also check lists.\nfunction equals(a, b) {\n if (a === b) {\n return true;\n } else if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false;\n }\n\n for (var i = 0; i < a.length; i += 1) {\n if (!equals(a[i], b[i])) {\n return false;\n }\n }\n\n return true;\n } else {\n return false;\n }\n}\n\n// Parse a `CFF` INDEX array.\n// An index array consists of a list of offsets, then a list of objects at those offsets.\nfunction parseCFFIndex(data, start, conversionFn) {\n //var i, objectOffset, endOffset;\n var offsets = [];\n var objects = [];\n var count = parse.getCard16(data, start);\n var i;\n var objectOffset;\n var endOffset;\n if (count !== 0) {\n var offsetSize = parse.getByte(data, start + 2);\n objectOffset = start + ((count + 1) * offsetSize) + 2;\n var pos = start + 3;\n for (i = 0; i < count + 1; i += 1) {\n offsets.push(parse.getOffset(data, pos, offsetSize));\n pos += offsetSize;\n }\n\n // The total size of the index array is 4 header bytes + the value of the last offset.\n endOffset = objectOffset + offsets[count];\n } else {\n endOffset = start + 2;\n }\n\n for (i = 0; i < offsets.length - 1; i += 1) {\n var value = parse.getBytes(data, objectOffset + offsets[i], objectOffset + offsets[i + 1]);\n if (conversionFn) {\n value = conversionFn(value);\n }\n\n objects.push(value);\n }\n\n return {objects: objects, startOffset: start, endOffset: endOffset};\n}\n\n// Parse a `CFF` DICT real value.\nfunction parseFloatOperand(parser) {\n var s = '';\n var eof = 15;\n var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];\n while (true) {\n var b = parser.parseByte();\n var n1 = b >> 4;\n var n2 = b & 15;\n\n if (n1 === eof) {\n break;\n }\n\n s += lookup[n1];\n\n if (n2 === eof) {\n break;\n }\n\n s += lookup[n2];\n }\n\n return parseFloat(s);\n}\n\n// Parse a `CFF` DICT operand.\nfunction parseOperand(parser, b0) {\n var b1;\n var b2;\n var b3;\n var b4;\n if (b0 === 28) {\n b1 = parser.parseByte();\n b2 = parser.parseByte();\n return b1 << 8 | b2;\n }\n\n if (b0 === 29) {\n b1 = parser.parseByte();\n b2 = parser.parseByte();\n b3 = parser.parseByte();\n b4 = parser.parseByte();\n return b1 << 24 | b2 << 16 | b3 << 8 | b4;\n }\n\n if (b0 === 30) {\n return parseFloatOperand(parser);\n }\n\n if (b0 >= 32 && b0 <= 246) {\n return b0 - 139;\n }\n\n if (b0 >= 247 && b0 <= 250) {\n b1 = parser.parseByte();\n return (b0 - 247) * 256 + b1 + 108;\n }\n\n if (b0 >= 251 && b0 <= 254) {\n b1 = parser.parseByte();\n return -(b0 - 251) * 256 - b1 - 108;\n }\n\n throw new Error('Invalid b0 ' + b0);\n}\n\n// Convert the entries returned by `parseDict` to a proper dictionary.\n// If a value is a list of one, it is unpacked.\nfunction entriesToObject(entries) {\n var o = {};\n for (var i = 0; i < entries.length; i += 1) {\n var key = entries[i][0];\n var values = entries[i][1];\n var value;\n if (values.length === 1) {\n value = values[0];\n } else {\n value = values;\n }\n\n if (o.hasOwnProperty(key)) {\n throw new Error('Object ' + o + ' already has key ' + key);\n }\n\n o[key] = value;\n }\n\n return o;\n}\n\n// Parse a `CFF` DICT object.\n// A dictionary contains key-value pairs in a compact tokenized format.\nfunction parseCFFDict(data, start, size) {\n start = start !== undefined ? start : 0;\n var parser = new parse.Parser(data, start);\n var entries = [];\n var operands = [];\n size = size !== undefined ? size : data.length;\n\n while (parser.relativeOffset < size) {\n var op = parser.parseByte();\n\n // The first byte for each dict item distinguishes between operator (key) and operand (value).\n // Values <= 21 are operators.\n if (op <= 21) {\n // Two-byte operators have an initial escape byte of 12.\n if (op === 12) {\n op = 1200 + parser.parseByte();\n }\n\n entries.push([op, operands]);\n operands = [];\n } else {\n // Since the operands (values) come before the operators (keys), we store all operands in a list\n // until we encounter an operator.\n operands.push(parseOperand(parser, op));\n }\n }\n\n return entriesToObject(entries);\n}\n\n// Given a String Index (SID), return the value of the string.\n// Strings below index 392 are standard CFF strings and are not encoded in the font.\nfunction getCFFString(strings, index) {\n if (index <= 390) {\n index = encoding.cffStandardStrings[index];\n } else {\n index = strings[index - 391];\n }\n\n return index;\n}\n\n// Interpret a dictionary and return a new dictionary with readable keys and values for missing entries.\n// This function takes `meta` which is a list of objects containing `operand`, `name` and `default`.\nfunction interpretDict(dict, meta, strings) {\n var newDict = {};\n\n // Because we also want to include missing values, we start out from the meta list\n // and lookup values in the dict.\n for (var i = 0; i < meta.length; i += 1) {\n var m = meta[i];\n var value = dict[m.op];\n if (value === undefined) {\n value = m.value !== undefined ? m.value : null;\n }\n\n if (m.type === 'SID') {\n value = getCFFString(strings, value);\n }\n\n newDict[m.name] = value;\n }\n\n return newDict;\n}\n\n// Parse the CFF header.\nfunction parseCFFHeader(data, start) {\n var header = {};\n header.formatMajor = parse.getCard8(data, start);\n header.formatMinor = parse.getCard8(data, start + 1);\n header.size = parse.getCard8(data, start + 2);\n header.offsetSize = parse.getCard8(data, start + 3);\n header.startOffset = start;\n header.endOffset = start + 4;\n return header;\n}\n\nvar TOP_DICT_META = [\n {name: 'version', op: 0, type: 'SID'},\n {name: 'notice', op: 1, type: 'SID'},\n {name: 'copyright', op: 1200, type: 'SID'},\n {name: 'fullName', op: 2, type: 'SID'},\n {name: 'familyName', op: 3, type: 'SID'},\n {name: 'weight', op: 4, type: 'SID'},\n {name: 'isFixedPitch', op: 1201, type: 'number', value: 0},\n {name: 'italicAngle', op: 1202, type: 'number', value: 0},\n {name: 'underlinePosition', op: 1203, type: 'number', value: -100},\n {name: 'underlineThickness', op: 1204, type: 'number', value: 50},\n {name: 'paintType', op: 1205, type: 'number', value: 0},\n {name: 'charstringType', op: 1206, type: 'number', value: 2},\n {name: 'fontMatrix', op: 1207, type: ['real', 'real', 'real', 'real', 'real', 'real'], value: [0.001, 0, 0, 0.001, 0, 0]},\n {name: 'uniqueId', op: 13, type: 'number'},\n {name: 'fontBBox', op: 5, type: ['number', 'number', 'number', 'number'], value: [0, 0, 0, 0]},\n {name: 'strokeWidth', op: 1208, type: 'number', value: 0},\n {name: 'xuid', op: 14, type: [], value: null},\n {name: 'charset', op: 15, type: 'offset', value: 0},\n {name: 'encoding', op: 16, type: 'offset', value: 0},\n {name: 'charStrings', op: 17, type: 'offset', value: 0},\n {name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0]}\n];\n\nvar PRIVATE_DICT_META = [\n {name: 'subrs', op: 19, type: 'offset', value: 0},\n {name: 'defaultWidthX', op: 20, type: 'number', value: 0},\n {name: 'nominalWidthX', op: 21, type: 'number', value: 0}\n];\n\n// Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary.\n// The top dictionary contains the essential metadata for the font, together with the private dictionary.\nfunction parseCFFTopDict(data, strings) {\n var dict = parseCFFDict(data, 0, data.byteLength);\n return interpretDict(dict, TOP_DICT_META, strings);\n}\n\n// Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need.\nfunction parseCFFPrivateDict(data, start, size, strings) {\n var dict = parseCFFDict(data, start, size);\n return interpretDict(dict, PRIVATE_DICT_META, strings);\n}\n\n// Parse the CFF charset table, which contains internal names for all the glyphs.\n// This function will return a list of glyph names.\n// See Adobe TN #5176 chapter 13, \"Charsets\".\nfunction parseCFFCharset(data, start, nGlyphs, strings) {\n var i;\n var sid;\n var count;\n var parser = new parse.Parser(data, start);\n\n // The .notdef glyph is not included, so subtract 1.\n nGlyphs -= 1;\n var charset = ['.notdef'];\n\n var format = parser.parseCard8();\n if (format === 0) {\n for (i = 0; i < nGlyphs; i += 1) {\n sid = parser.parseSID();\n charset.push(getCFFString(strings, sid));\n }\n } else if (format === 1) {\n while (charset.length <= nGlyphs) {\n sid = parser.parseSID();\n count = parser.parseCard8();\n for (i = 0; i <= count; i += 1) {\n charset.push(getCFFString(strings, sid));\n sid += 1;\n }\n }\n } else if (format === 2) {\n while (charset.length <= nGlyphs) {\n sid = parser.parseSID();\n count = parser.parseCard16();\n for (i = 0; i <= count; i += 1) {\n charset.push(getCFFString(strings, sid));\n sid += 1;\n }\n }\n } else {\n throw new Error('Unknown charset format ' + format);\n }\n\n return charset;\n}\n\n// Parse the CFF encoding data. Only one encoding can be specified per font.\n// See Adobe TN #5176 chapter 12, \"Encodings\".\nfunction parseCFFEncoding(data, start, charset) {\n var i;\n var code;\n var enc = {};\n var parser = new parse.Parser(data, start);\n var format = parser.parseCard8();\n if (format === 0) {\n var nCodes = parser.parseCard8();\n for (i = 0; i < nCodes; i += 1) {\n code = parser.parseCard8();\n enc[code] = i;\n }\n } else if (format === 1) {\n var nRanges = parser.parseCard8();\n code = 1;\n for (i = 0; i < nRanges; i += 1) {\n var first = parser.parseCard8();\n var nLeft = parser.parseCard8();\n for (var j = first; j <= first + nLeft; j += 1) {\n enc[j] = code;\n code += 1;\n }\n }\n } else {\n throw new Error('Unknown encoding format ' + format);\n }\n\n return new encoding.CffEncoding(enc, charset);\n}\n\n// Take in charstring code and return a Glyph object.\n// The encoding is described in the Type 2 Charstring Format\n// https://www.microsoft.com/typography/OTSPEC/charstr2.htm\nfunction parseCFFCharstring(font, glyph, code) {\n var c1x;\n var c1y;\n var c2x;\n var c2y;\n var p = new path.Path();\n var stack = [];\n var nStems = 0;\n var haveWidth = false;\n var width = font.defaultWidthX;\n var open = false;\n var x = 0;\n var y = 0;\n\n function newContour(x, y) {\n if (open) {\n p.closePath();\n }\n\n p.moveTo(x, y);\n open = true;\n }\n\n function parseStems() {\n var hasWidthArg;\n\n // The number of stem operators on the stack is always even.\n // If the value is uneven, that means a width is specified.\n hasWidthArg = stack.length % 2 !== 0;\n if (hasWidthArg && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n }\n\n nStems += stack.length >> 1;\n stack.length = 0;\n haveWidth = true;\n }\n\n function parse(code) {\n var b1;\n var b2;\n var b3;\n var b4;\n var codeIndex;\n var subrCode;\n var jpx;\n var jpy;\n var c3x;\n var c3y;\n var c4x;\n var c4y;\n\n var i = 0;\n while (i < code.length) {\n var v = code[i];\n i += 1;\n switch (v) {\n case 1: // hstem\n parseStems();\n break;\n case 3: // vstem\n parseStems();\n break;\n case 4: // vmoveto\n if (stack.length > 1 && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n haveWidth = true;\n }\n\n y += stack.pop();\n newContour(x, y);\n break;\n case 5: // rlineto\n while (stack.length > 0) {\n x += stack.shift();\n y += stack.shift();\n p.lineTo(x, y);\n }\n\n break;\n case 6: // hlineto\n while (stack.length > 0) {\n x += stack.shift();\n p.lineTo(x, y);\n if (stack.length === 0) {\n break;\n }\n\n y += stack.shift();\n p.lineTo(x, y);\n }\n\n break;\n case 7: // vlineto\n while (stack.length > 0) {\n y += stack.shift();\n p.lineTo(x, y);\n if (stack.length === 0) {\n break;\n }\n\n x += stack.shift();\n p.lineTo(x, y);\n }\n\n break;\n case 8: // rrcurveto\n while (stack.length > 0) {\n c1x = x + stack.shift();\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + stack.shift();\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n case 10: // callsubr\n codeIndex = stack.pop() + font.subrsBias;\n subrCode = font.subrs[codeIndex];\n if (subrCode) {\n parse(subrCode);\n }\n\n break;\n case 11: // return\n return;\n case 12: // flex operators\n v = code[i];\n i += 1;\n switch (v) {\n case 35: // flex\n // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-\n c1x = x + stack.shift(); // dx1\n c1y = y + stack.shift(); // dy1\n c2x = c1x + stack.shift(); // dx2\n c2y = c1y + stack.shift(); // dy2\n jpx = c2x + stack.shift(); // dx3\n jpy = c2y + stack.shift(); // dy3\n c3x = jpx + stack.shift(); // dx4\n c3y = jpy + stack.shift(); // dy4\n c4x = c3x + stack.shift(); // dx5\n c4y = c3y + stack.shift(); // dy5\n x = c4x + stack.shift(); // dx6\n y = c4y + stack.shift(); // dy6\n stack.shift(); // flex depth\n p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);\n p.curveTo(c3x, c3y, c4x, c4y, x, y);\n break;\n case 34: // hflex\n // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-\n c1x = x + stack.shift(); // dx1\n c1y = y; // dy1\n c2x = c1x + stack.shift(); // dx2\n c2y = c1y + stack.shift(); // dy2\n jpx = c2x + stack.shift(); // dx3\n jpy = c2y; // dy3\n c3x = jpx + stack.shift(); // dx4\n c3y = c2y; // dy4\n c4x = c3x + stack.shift(); // dx5\n c4y = y; // dy5\n x = c4x + stack.shift(); // dx6\n p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);\n p.curveTo(c3x, c3y, c4x, c4y, x, y);\n break;\n case 36: // hflex1\n // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-\n c1x = x + stack.shift(); // dx1\n c1y = y + stack.shift(); // dy1\n c2x = c1x + stack.shift(); // dx2\n c2y = c1y + stack.shift(); // dy2\n jpx = c2x + stack.shift(); // dx3\n jpy = c2y; // dy3\n c3x = jpx + stack.shift(); // dx4\n c3y = c2y; // dy4\n c4x = c3x + stack.shift(); // dx5\n c4y = c3y + stack.shift(); // dy5\n x = c4x + stack.shift(); // dx6\n p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);\n p.curveTo(c3x, c3y, c4x, c4y, x, y);\n break;\n case 37: // flex1\n // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-\n c1x = x + stack.shift(); // dx1\n c1y = y + stack.shift(); // dy1\n c2x = c1x + stack.shift(); // dx2\n c2y = c1y + stack.shift(); // dy2\n jpx = c2x + stack.shift(); // dx3\n jpy = c2y + stack.shift(); // dy3\n c3x = jpx + stack.shift(); // dx4\n c3y = jpy + stack.shift(); // dy4\n c4x = c3x + stack.shift(); // dx5\n c4y = c3y + stack.shift(); // dy5\n if (Math.abs(c4x - x) > Math.abs(c4y - y)) {\n x = c4x + stack.shift();\n } else {\n y = c4y + stack.shift();\n }\n\n p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);\n p.curveTo(c3x, c3y, c4x, c4y, x, y);\n break;\n default:\n console.log('Glyph ' + glyph.index + ': unknown operator ' + 1200 + v);\n stack.length = 0;\n }\n break;\n case 14: // endchar\n if (stack.length > 0 && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n haveWidth = true;\n }\n\n if (open) {\n p.closePath();\n open = false;\n }\n\n break;\n case 18: // hstemhm\n parseStems();\n break;\n case 19: // hintmask\n case 20: // cntrmask\n parseStems();\n i += (nStems + 7) >> 3;\n break;\n case 21: // rmoveto\n if (stack.length > 2 && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n haveWidth = true;\n }\n\n y += stack.pop();\n x += stack.pop();\n newContour(x, y);\n break;\n case 22: // hmoveto\n if (stack.length > 1 && !haveWidth) {\n width = stack.shift() + font.nominalWidthX;\n haveWidth = true;\n }\n\n x += stack.pop();\n newContour(x, y);\n break;\n case 23: // vstemhm\n parseStems();\n break;\n case 24: // rcurveline\n while (stack.length > 2) {\n c1x = x + stack.shift();\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + stack.shift();\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n x += stack.shift();\n y += stack.shift();\n p.lineTo(x, y);\n break;\n case 25: // rlinecurve\n while (stack.length > 6) {\n x += stack.shift();\n y += stack.shift();\n p.lineTo(x, y);\n }\n\n c1x = x + stack.shift();\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + stack.shift();\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n break;\n case 26: // vvcurveto\n if (stack.length % 2) {\n x += stack.shift();\n }\n\n while (stack.length > 0) {\n c1x = x;\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x;\n y = c2y + stack.shift();\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n case 27: // hhcurveto\n if (stack.length % 2) {\n y += stack.shift();\n }\n\n while (stack.length > 0) {\n c1x = x + stack.shift();\n c1y = y;\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y;\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n case 28: // shortint\n b1 = code[i];\n b2 = code[i + 1];\n stack.push(((b1 << 24) | (b2 << 16)) >> 16);\n i += 2;\n break;\n case 29: // callgsubr\n codeIndex = stack.pop() + font.gsubrsBias;\n subrCode = font.gsubrs[codeIndex];\n if (subrCode) {\n parse(subrCode);\n }\n\n break;\n case 30: // vhcurveto\n while (stack.length > 0) {\n c1x = x;\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + (stack.length === 1 ? stack.shift() : 0);\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n if (stack.length === 0) {\n break;\n }\n\n c1x = x + stack.shift();\n c1y = y;\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n y = c2y + stack.shift();\n x = c2x + (stack.length === 1 ? stack.shift() : 0);\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n case 31: // hvcurveto\n while (stack.length > 0) {\n c1x = x + stack.shift();\n c1y = y;\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n y = c2y + stack.shift();\n x = c2x + (stack.length === 1 ? stack.shift() : 0);\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n if (stack.length === 0) {\n break;\n }\n\n c1x = x;\n c1y = y + stack.shift();\n c2x = c1x + stack.shift();\n c2y = c1y + stack.shift();\n x = c2x + stack.shift();\n y = c2y + (stack.length === 1 ? stack.shift() : 0);\n p.curveTo(c1x, c1y, c2x, c2y, x, y);\n }\n\n break;\n default:\n if (v < 32) {\n console.log('Glyph ' + glyph.index + ': unknown operator ' + v);\n } else if (v < 247) {\n stack.push(v - 139);\n } else if (v < 251) {\n b1 = code[i];\n i += 1;\n stack.push((v - 247) * 256 + b1 + 108);\n } else if (v < 255) {\n b1 = code[i];\n i += 1;\n stack.push(-(v - 251) * 256 - b1 - 108);\n } else {\n b1 = code[i];\n b2 = code[i + 1];\n b3 = code[i + 2];\n b4 = code[i + 3];\n i += 4;\n stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536);\n }\n }\n }\n }\n\n parse(code);\n\n glyph.advanceWidth = width;\n return p;\n}\n\n// Subroutines are encoded using the negative half of the number space.\n// See type 2 chapter 4.7 \"Subroutine operators\".\nfunction calcCFFSubroutineBias(subrs) {\n var bias;\n if (subrs.length < 1240) {\n bias = 107;\n } else if (subrs.length < 33900) {\n bias = 1131;\n } else {\n bias = 32768;\n }\n\n return bias;\n}\n\n// Parse the `CFF` table, which contains the glyph outlines in PostScript format.\nfunction parseCFFTable(data, start, font) {\n font.tables.cff = {};\n var header = parseCFFHeader(data, start);\n var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);\n var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);\n var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);\n var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);\n font.gsubrs = globalSubrIndex.objects;\n font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);\n\n var topDictData = new DataView(new Uint8Array(topDictIndex.objects[0]).buffer);\n var topDict = parseCFFTopDict(topDictData, stringIndex.objects);\n font.tables.cff.topDict = topDict;\n\n var privateDictOffset = start + topDict['private'][1];\n var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict['private'][0], stringIndex.objects);\n font.defaultWidthX = privateDict.defaultWidthX;\n font.nominalWidthX = privateDict.nominalWidthX;\n\n if (privateDict.subrs !== 0) {\n var subrOffset = privateDictOffset + privateDict.subrs;\n var subrIndex = parseCFFIndex(data, subrOffset);\n font.subrs = subrIndex.objects;\n font.subrsBias = calcCFFSubroutineBias(font.subrs);\n } else {\n font.subrs = [];\n font.subrsBias = 0;\n }\n\n // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.\n var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);\n font.nGlyphs = charStringsIndex.objects.length;\n\n var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);\n if (topDict.encoding === 0) { // Standard encoding\n font.cffEncoding = new encoding.CffEncoding(encoding.cffStandardEncoding, charset);\n } else if (topDict.encoding === 1) { // Expert encoding\n font.cffEncoding = new encoding.CffEncoding(encoding.cffExpertEncoding, charset);\n } else {\n font.cffEncoding = parseCFFEncoding(data, start + topDict.encoding, charset);\n }\n\n // Prefer the CMAP encoding to the CFF encoding.\n font.encoding = font.encoding || font.cffEncoding;\n\n font.glyphs = new glyphset.GlyphSet(font);\n for (var i = 0; i < font.nGlyphs; i += 1) {\n var charString = charStringsIndex.objects[i];\n font.glyphs.push(i, glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString));\n }\n}\n\n// Convert a string to a String ID (SID).\n// The list of strings is modified in place.\nfunction encodeString(s, strings) {\n var sid;\n\n // Is the string in the CFF standard strings?\n var i = encoding.cffStandardStrings.indexOf(s);\n if (i >= 0) {\n sid = i;\n }\n\n // Is the string already in the string index?\n i = strings.indexOf(s);\n if (i >= 0) {\n sid = i + encoding.cffStandardStrings.length;\n } else {\n sid = encoding.cffStandardStrings.length + strings.length;\n strings.push(s);\n }\n\n return sid;\n}\n\nfunction makeHeader() {\n return new table.Record('Header', [\n {name: 'major', type: 'Card8', value: 1},\n {name: 'minor', type: 'Card8', value: 0},\n {name: 'hdrSize', type: 'Card8', value: 4},\n {name: 'major', type: 'Card8', value: 1}\n ]);\n}\n\nfunction makeNameIndex(fontNames) {\n var t = new table.Record('Name INDEX', [\n {name: 'names', type: 'INDEX', value: []}\n ]);\n t.names = [];\n for (var i = 0; i < fontNames.length; i += 1) {\n t.names.push({name: 'name_' + i, type: 'NAME', value: fontNames[i]});\n }\n\n return t;\n}\n\n// Given a dictionary's metadata, create a DICT structure.\nfunction makeDict(meta, attrs, strings) {\n var m = {};\n for (var i = 0; i < meta.length; i += 1) {\n var entry = meta[i];\n var value = attrs[entry.name];\n if (value !== undefined && !equals(value, entry.value)) {\n if (entry.type === 'SID') {\n value = encodeString(value, strings);\n }\n\n m[entry.op] = {name: entry.name, type: entry.type, value: value};\n }\n }\n\n return m;\n}\n\n// The Top DICT houses the global font attributes.\nfunction makeTopDict(attrs, strings) {\n var t = new table.Record('Top DICT', [\n {name: 'dict', type: 'DICT', value: {}}\n ]);\n t.dict = makeDict(TOP_DICT_META, attrs, strings);\n return t;\n}\n\nfunction makeTopDictIndex(topDict) {\n var t = new table.Record('Top DICT INDEX', [\n {name: 'topDicts', type: 'INDEX', value: []}\n ]);\n t.topDicts = [{name: 'topDict_0', type: 'TABLE', value: topDict}];\n return t;\n}\n\nfunction makeStringIndex(strings) {\n var t = new table.Record('String INDEX', [\n {name: 'strings', type: 'INDEX', value: []}\n ]);\n t.strings = [];\n for (var i = 0; i < strings.length; i += 1) {\n t.strings.push({name: 'string_' + i, type: 'STRING', value: strings[i]});\n }\n\n return t;\n}\n\nfunction makeGlobalSubrIndex() {\n // Currently we don't use subroutines.\n return new table.Record('Global Subr INDEX', [\n {name: 'subrs', type: 'INDEX', value: []}\n ]);\n}\n\nfunction makeCharsets(glyphNames, strings) {\n var t = new table.Record('Charsets', [\n {name: 'format', type: 'Card8', value: 0}\n ]);\n for (var i = 0; i < glyphNames.length; i += 1) {\n var glyphName = glyphNames[i];\n var glyphSID = encodeString(glyphName, strings);\n t.fields.push({name: 'glyph_' + i, type: 'SID', value: glyphSID});\n }\n\n return t;\n}\n\nfunction glyphToOps(glyph) {\n var ops = [];\n var path = glyph.path;\n ops.push({name: 'width', type: 'NUMBER', value: glyph.advanceWidth});\n var x = 0;\n var y = 0;\n for (var i = 0; i < path.commands.length; i += 1) {\n var dx;\n var dy;\n var cmd = path.commands[i];\n if (cmd.type === 'Q') {\n // CFF only supports bézier curves, so convert the quad to a bézier.\n var _13 = 1 / 3;\n var _23 = 2 / 3;\n\n // We're going to create a new command so we don't change the original path.\n cmd = {\n type: 'C',\n x: cmd.x,\n y: cmd.y,\n x1: _13 * x + _23 * cmd.x1,\n y1: _13 * y + _23 * cmd.y1,\n x2: _13 * cmd.x + _23 * cmd.x1,\n y2: _13 * cmd.y + _23 * cmd.y1\n };\n }\n\n if (cmd.type === 'M') {\n dx = Math.round(cmd.x - x);\n dy = Math.round(cmd.y - y);\n ops.push({name: 'dx', type: 'NUMBER', value: dx});\n ops.push({name: 'dy', type: 'NUMBER', value: dy});\n ops.push({name: 'rmoveto', type: 'OP', value: 21});\n x = Math.round(cmd.x);\n y = Math.round(cmd.y);\n } else if (cmd.type === 'L') {\n dx = Math.round(cmd.x - x);\n dy = Math.round(cmd.y - y);\n ops.push({name: 'dx', type: 'NUMBER', value: dx});\n ops.push({name: 'dy', type: 'NUMBER', value: dy});\n ops.push({name: 'rlineto', type: 'OP', value: 5});\n x = Math.round(cmd.x);\n y = Math.round(cmd.y);\n } else if (cmd.type === 'C') {\n var dx1 = Math.round(cmd.x1 - x);\n var dy1 = Math.round(cmd.y1 - y);\n var dx2 = Math.round(cmd.x2 - cmd.x1);\n var dy2 = Math.round(cmd.y2 - cmd.y1);\n dx = Math.round(cmd.x - cmd.x2);\n dy = Math.round(cmd.y - cmd.y2);\n ops.push({name: 'dx1', type: 'NUMBER', value: dx1});\n ops.push({name: 'dy1', type: 'NUMBER', value: dy1});\n ops.push({name: 'dx2', type: 'NUMBER', value: dx2});\n ops.push({name: 'dy2', type: 'NUMBER', value: dy2});\n ops.push({name: 'dx', type: 'NUMBER', value: dx});\n ops.push({name: 'dy', type: 'NUMBER', value: dy});\n ops.push({name: 'rrcurveto', type: 'OP', value: 8});\n x = Math.round(cmd.x);\n y = Math.round(cmd.y);\n }\n\n // Contours are closed automatically.\n\n }\n\n ops.push({name: 'endchar', type: 'OP', value: 14});\n return ops;\n}\n\nfunction makeCharStringsIndex(glyphs) {\n var t = new table.Record('CharStrings INDEX', [\n {name: 'charStrings', type: 'INDEX', value: []}\n ]);\n\n for (var i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs.get(i);\n var ops = glyphToOps(glyph);\n t.charStrings.push({name: glyph.name, type: 'CHARSTRING', value: ops});\n }\n\n return t;\n}\n\nfunction makePrivateDict(attrs, strings) {\n var t = new table.Record('Private DICT', [\n {name: 'dict', type: 'DICT', value: {}}\n ]);\n t.dict = makeDict(PRIVATE_DICT_META, attrs, strings);\n return t;\n}\n\nfunction makeCFFTable(glyphs, options) {\n var t = new table.Table('CFF ', [\n {name: 'header', type: 'RECORD'},\n {name: 'nameIndex', type: 'RECORD'},\n {name: 'topDictIndex', type: 'RECORD'},\n {name: 'stringIndex', type: 'RECORD'},\n {name: 'globalSubrIndex', type: 'RECORD'},\n {name: 'charsets', type: 'RECORD'},\n {name: 'charStringsIndex', type: 'RECORD'},\n {name: 'privateDict', type: 'RECORD'}\n ]);\n\n var fontScale = 1 / options.unitsPerEm;\n // We use non-zero values for the offsets so that the DICT encodes them.\n // This is important because the size of the Top DICT plays a role in offset calculation,\n // and the size shouldn't change after we've written correct offsets.\n var attrs = {\n version: options.version,\n fullName: options.fullName,\n familyName: options.familyName,\n weight: options.weightName,\n fontBBox: options.fontBBox || [0, 0, 0, 0],\n fontMatrix: [fontScale, 0, 0, fontScale, 0, 0],\n charset: 999,\n encoding: 0,\n charStrings: 999,\n private: [0, 999]\n };\n\n var privateAttrs = {};\n\n var glyphNames = [];\n var glyph;\n\n // Skip first glyph (.notdef)\n for (var i = 1; i < glyphs.length; i += 1) {\n glyph = glyphs.get(i);\n glyphNames.push(glyph.name);\n }\n\n var strings = [];\n\n t.header = makeHeader();\n t.nameIndex = makeNameIndex([options.postScriptName]);\n var topDict = makeTopDict(attrs, strings);\n t.topDictIndex = makeTopDictIndex(topDict);\n t.globalSubrIndex = makeGlobalSubrIndex();\n t.charsets = makeCharsets(glyphNames, strings);\n t.charStringsIndex = makeCharStringsIndex(glyphs);\n t.privateDict = makePrivateDict(privateAttrs, strings);\n\n // Needs to come at the end, to encode all custom strings used in the font.\n t.stringIndex = makeStringIndex(strings);\n\n var startOffset = t.header.sizeOf() +\n t.nameIndex.sizeOf() +\n t.topDictIndex.sizeOf() +\n t.stringIndex.sizeOf() +\n t.globalSubrIndex.sizeOf();\n attrs.charset = startOffset;\n\n // We use the CFF standard encoding; proper encoding will be handled in cmap.\n attrs.encoding = 0;\n attrs.charStrings = attrs.charset + t.charsets.sizeOf();\n attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf();\n\n // Recreate the Top DICT INDEX with the correct offsets.\n topDict = makeTopDict(attrs, strings);\n t.topDictIndex = makeTopDictIndex(topDict);\n\n return t;\n}\n\nexports.parse = parseCFFTable;\nexports.make = makeCFFTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/cff.js\n ** module id = 13\n ** module chunks = 0\n **/","// The GlyphSet object\n\n'use strict';\n\nvar _glyph = require('./glyph');\n\n// Define a property on the glyph that depends on the path being loaded.\nfunction defineDependentProperty(glyph, externalName, internalName) {\n Object.defineProperty(glyph, externalName, {\n get: function() {\n // Request the path property to make sure the path is loaded.\n glyph.path; // jshint ignore:line\n return glyph[internalName];\n },\n set: function(newValue) {\n glyph[internalName] = newValue;\n },\n enumerable: true,\n configurable: true\n });\n}\n\n// A GlyphSet represents all glyphs available in the font, but modelled using\n// a deferred glyph loader, for retrieving glyphs only once they are absolutely\n// necessary, to keep the memory footprint down.\nfunction GlyphSet(font, glyphs) {\n this.font = font;\n this.glyphs = {};\n if (Array.isArray(glyphs)) {\n for (var i = 0; i < glyphs.length; i++) {\n this.glyphs[i] = glyphs[i];\n }\n }\n\n this.length = (glyphs && glyphs.length) || 0;\n}\n\nGlyphSet.prototype.get = function(index) {\n if (typeof this.glyphs[index] === 'function') {\n this.glyphs[index] = this.glyphs[index]();\n }\n\n return this.glyphs[index];\n};\n\nGlyphSet.prototype.push = function(index, loader) {\n this.glyphs[index] = loader;\n this.length++;\n};\n\nfunction glyphLoader(font, index) {\n return new _glyph.Glyph({index: index, font: font});\n}\n\n/**\n * Generate a stub glyph that can be filled with all metadata *except*\n * the \"points\" and \"path\" properties, which must be loaded only once\n * the glyph's path is actually requested for text shaping.\n */\n\nfunction ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {\n return function() {\n var glyph = new _glyph.Glyph({index: index, font: font});\n\n glyph.path = function() {\n parseGlyph(glyph, data, position);\n var path = buildPath(font.glyphs, glyph);\n path.unitsPerEm = font.unitsPerEm;\n return path;\n };\n\n defineDependentProperty(glyph, 'xMin', '_xMin');\n defineDependentProperty(glyph, 'xMax', '_xMax');\n defineDependentProperty(glyph, 'yMin', '_yMin');\n defineDependentProperty(glyph, 'yMax', '_yMax');\n\n return glyph;\n };\n}\n\nfunction cffGlyphLoader(font, index, parseCFFCharstring, charstring) {\n return function() {\n var glyph = new _glyph.Glyph({index: index, font: font});\n\n glyph.path = function() {\n var path = parseCFFCharstring(font, glyph, charstring);\n path.unitsPerEm = font.unitsPerEm;\n return path;\n };\n\n return glyph;\n };\n}\n\nexports.GlyphSet = GlyphSet;\nexports.glyphLoader = glyphLoader;\nexports.ttfGlyphLoader = ttfGlyphLoader;\nexports.cffGlyphLoader = cffGlyphLoader;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/glyphset.js\n ** module id = 14\n ** module chunks = 0\n **/","// The Glyph object\n\n'use strict';\n\nvar check = require('./check');\nvar draw = require('./draw');\nvar path = require('./path');\n\nfunction getPathDefinition(glyph, path) {\n var _path = path || { commands: [] };\n return {\n configurable: true,\n\n get: function() {\n if (typeof _path === 'function') {\n _path = _path();\n }\n\n return _path;\n },\n\n set: function(p) {\n _path = p;\n }\n };\n}\n\n// A Glyph is an individual mark that often corresponds to a character.\n// Some glyphs, such as ligatures, are a combination of many characters.\n// Glyphs are the basic building blocks of a font.\n//\n// The `Glyph` class contains utility methods for drawing the path and its points.\nfunction Glyph(options) {\n // By putting all the code on a prototype function (which is only declared once)\n // we reduce the memory requirements for larger fonts by some 2%\n this.bindConstructorValues(options);\n}\n\nGlyph.prototype.bindConstructorValues = function(options) {\n this.index = options.index || 0;\n\n // These three values cannnot be deferred for memory optimization:\n this.name = options.name || null;\n this.unicode = options.unicode || undefined;\n this.unicodes = options.unicodes || options.unicode !== undefined ? [options.unicode] : [];\n\n // But by binding these values only when necessary, we reduce can\n // the memory requirements by almost 3% for larger fonts.\n if (options.xMin) {\n this.xMin = options.xMin;\n }\n\n if (options.yMin) {\n this.yMin = options.yMin;\n }\n\n if (options.xMax) {\n this.xMax = options.xMax;\n }\n\n if (options.yMax) {\n this.yMax = options.yMax;\n }\n\n if (options.advanceWidth) {\n this.advanceWidth = options.advanceWidth;\n }\n\n // The path for a glyph is the most memory intensive, and is bound as a value\n // with a getter/setter to ensure we actually do path parsing only once the\n // path is actually needed by anything.\n Object.defineProperty(this, 'path', getPathDefinition(this, options.path));\n};\n\nGlyph.prototype.addUnicode = function(unicode) {\n if (this.unicodes.length === 0) {\n this.unicode = unicode;\n }\n\n this.unicodes.push(unicode);\n};\n\n// Convert the glyph to a Path we can draw on a drawing context.\n//\n// x - Horizontal position of the glyph. (default: 0)\n// y - Vertical position of the *baseline* of the glyph. (default: 0)\n// fontSize - Font size, in pixels (default: 72).\n// options - xScale and yScale to strech the glyph.\nGlyph.prototype.getPath = function(x, y, fontSize, options) {\n x = x !== undefined ? x : 0;\n y = y !== undefined ? y : 0;\n options = options !== undefined ? options : {xScale: 1.0, yScale: 1.0};\n fontSize = fontSize !== undefined ? fontSize : 72;\n var scale = 1 / this.path.unitsPerEm * fontSize;\n var xScale = options.xScale * scale;\n var yScale = options.yScale * scale;\n\n var p = new path.Path();\n var commands = this.path.commands;\n for (var i = 0; i < commands.length; i += 1) {\n var cmd = commands[i];\n if (cmd.type === 'M') {\n p.moveTo(x + (cmd.x * xScale), y + (-cmd.y * yScale));\n } else if (cmd.type === 'L') {\n p.lineTo(x + (cmd.x * xScale), y + (-cmd.y * yScale));\n } else if (cmd.type === 'Q') {\n p.quadraticCurveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale),\n x + (cmd.x * xScale), y + (-cmd.y * yScale));\n } else if (cmd.type === 'C') {\n p.curveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale),\n x + (cmd.x2 * xScale), y + (-cmd.y2 * yScale),\n x + (cmd.x * xScale), y + (-cmd.y * yScale));\n } else if (cmd.type === 'Z') {\n p.closePath();\n }\n }\n\n return p;\n};\n\n// Split the glyph into contours.\n// This function is here for backwards compatibility, and to\n// provide raw access to the TrueType glyph outlines.\nGlyph.prototype.getContours = function() {\n if (this.points === undefined) {\n return [];\n }\n\n var contours = [];\n var currentContour = [];\n for (var i = 0; i < this.points.length; i += 1) {\n var pt = this.points[i];\n currentContour.push(pt);\n if (pt.lastPointOfContour) {\n contours.push(currentContour);\n currentContour = [];\n }\n }\n\n check.argument(currentContour.length === 0, 'There are still points left in the current contour.');\n return contours;\n};\n\n// Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph.\nGlyph.prototype.getMetrics = function() {\n var commands = this.path.commands;\n var xCoords = [];\n var yCoords = [];\n for (var i = 0; i < commands.length; i += 1) {\n var cmd = commands[i];\n if (cmd.type !== 'Z') {\n xCoords.push(cmd.x);\n yCoords.push(cmd.y);\n }\n\n if (cmd.type === 'Q' || cmd.type === 'C') {\n xCoords.push(cmd.x1);\n yCoords.push(cmd.y1);\n }\n\n if (cmd.type === 'C') {\n xCoords.push(cmd.x2);\n yCoords.push(cmd.y2);\n }\n }\n\n var metrics = {\n xMin: Math.min.apply(null, xCoords),\n yMin: Math.min.apply(null, yCoords),\n xMax: Math.max.apply(null, xCoords),\n yMax: Math.max.apply(null, yCoords),\n leftSideBearing: this.leftSideBearing\n };\n\n if (!isFinite(metrics.xMin)) {\n metrics.xMin = 0;\n }\n\n if (!isFinite(metrics.xMax)) {\n metrics.xMax = this.advanceWidth;\n }\n\n if (!isFinite(metrics.yMin)) {\n metrics.yMin = 0;\n }\n\n if (!isFinite(metrics.yMax)) {\n metrics.yMax = 0;\n }\n\n metrics.rightSideBearing = this.advanceWidth - metrics.leftSideBearing - (metrics.xMax - metrics.xMin);\n return metrics;\n};\n\n// Draw the glyph on the given context.\n//\n// ctx - The drawing context.\n// x - Horizontal position of the glyph. (default: 0)\n// y - Vertical position of the *baseline* of the glyph. (default: 0)\n// fontSize - Font size, in pixels (default: 72).\n// options - xScale, yScale to strech the glyph\nGlyph.prototype.draw = function(ctx, x, y, fontSize, options) {\n this.getPath(x, y, fontSize, options).draw(ctx);\n};\n\n// Draw the points of the glyph.\n// On-curve points will be drawn in blue, off-curve points will be drawn in red.\n//\n// ctx - The drawing context.\n// x - Horizontal position of the glyph. (default: 0)\n// y - Vertical position of the *baseline* of the glyph. (default: 0)\n// fontSize - Font size, in pixels (default: 72).\nGlyph.prototype.drawPoints = function(ctx, x, y, fontSize) {\n\n function drawCircles(l, x, y, scale) {\n var PI_SQ = Math.PI * 2;\n ctx.beginPath();\n for (var j = 0; j < l.length; j += 1) {\n ctx.moveTo(x + (l[j].x * scale), y + (l[j].y * scale));\n ctx.arc(x + (l[j].x * scale), y + (l[j].y * scale), 2, 0, PI_SQ, false);\n }\n\n ctx.closePath();\n ctx.fill();\n }\n\n x = x !== undefined ? x : 0;\n y = y !== undefined ? y : 0;\n fontSize = fontSize !== undefined ? fontSize : 24;\n var scale = 1 / this.path.unitsPerEm * fontSize;\n\n var blueCircles = [];\n var redCircles = [];\n var path = this.path;\n for (var i = 0; i < path.commands.length; i += 1) {\n var cmd = path.commands[i];\n if (cmd.x !== undefined) {\n blueCircles.push({x: cmd.x, y: -cmd.y});\n }\n\n if (cmd.x1 !== undefined) {\n redCircles.push({x: cmd.x1, y: -cmd.y1});\n }\n\n if (cmd.x2 !== undefined) {\n redCircles.push({x: cmd.x2, y: -cmd.y2});\n }\n }\n\n ctx.fillStyle = 'blue';\n drawCircles(blueCircles, x, y, scale);\n ctx.fillStyle = 'red';\n drawCircles(redCircles, x, y, scale);\n};\n\n// Draw lines indicating important font measurements.\n// Black lines indicate the origin of the coordinate system (point 0,0).\n// Blue lines indicate the glyph bounding box.\n// Green line indicates the advance width of the glyph.\n//\n// ctx - The drawing context.\n// x - Horizontal position of the glyph. (default: 0)\n// y - Vertical position of the *baseline* of the glyph. (default: 0)\n// fontSize - Font size, in pixels (default: 72).\nGlyph.prototype.drawMetrics = function(ctx, x, y, fontSize) {\n var scale;\n x = x !== undefined ? x : 0;\n y = y !== undefined ? y : 0;\n fontSize = fontSize !== undefined ? fontSize : 24;\n scale = 1 / this.path.unitsPerEm * fontSize;\n ctx.lineWidth = 1;\n\n // Draw the origin\n ctx.strokeStyle = 'black';\n draw.line(ctx, x, -10000, x, 10000);\n draw.line(ctx, -10000, y, 10000, y);\n\n // This code is here due to memory optimization: by not using\n // defaults in the constructor, we save a notable amount of memory.\n var xMin = this.xMin || 0;\n var yMin = this.yMin || 0;\n var xMax = this.xMax || 0;\n var yMax = this.yMax || 0;\n var advanceWidth = this.advanceWidth || 0;\n\n // Draw the glyph box\n ctx.strokeStyle = 'blue';\n draw.line(ctx, x + (xMin * scale), -10000, x + (xMin * scale), 10000);\n draw.line(ctx, x + (xMax * scale), -10000, x + (xMax * scale), 10000);\n draw.line(ctx, -10000, y + (-yMin * scale), 10000, y + (-yMin * scale));\n draw.line(ctx, -10000, y + (-yMax * scale), 10000, y + (-yMax * scale));\n\n // Draw the advance width\n ctx.strokeStyle = 'green';\n draw.line(ctx, x + (advanceWidth * scale), -10000, x + (advanceWidth * scale), 10000);\n};\n\nexports.Glyph = Glyph;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/glyph.js\n ** module id = 15\n ** module chunks = 0\n **/","// Drawing utility functions.\n\n'use strict';\n\n// Draw a line on the given context from point `x1,y1` to point `x2,y2`.\nfunction line(ctx, x1, y1, x2, y2) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n}\n\nexports.line = line;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/draw.js\n ** module id = 16\n ** module chunks = 0\n **/","// The `head` table contains global information about the font.\n// https://www.microsoft.com/typography/OTSPEC/head.htm\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the header `head` table\nfunction parseHeadTable(data, start) {\n var head = {};\n var p = new parse.Parser(data, start);\n head.version = p.parseVersion();\n head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;\n head.checkSumAdjustment = p.parseULong();\n head.magicNumber = p.parseULong();\n check.argument(head.magicNumber === 0x5F0F3CF5, 'Font header has wrong magic number.');\n head.flags = p.parseUShort();\n head.unitsPerEm = p.parseUShort();\n head.created = p.parseLongDateTime();\n head.modified = p.parseLongDateTime();\n head.xMin = p.parseShort();\n head.yMin = p.parseShort();\n head.xMax = p.parseShort();\n head.yMax = p.parseShort();\n head.macStyle = p.parseUShort();\n head.lowestRecPPEM = p.parseUShort();\n head.fontDirectionHint = p.parseShort();\n head.indexToLocFormat = p.parseShort();\n head.glyphDataFormat = p.parseShort();\n return head;\n}\n\nfunction makeHeadTable(options) {\n // Apple Mac timestamp epoch is 01/01/1904 not 01/01/1970\n var timestamp = Math.round(new Date().getTime() / 1000) + 2082844800;\n var createdTimestamp = timestamp;\n\n if (options.createdTimestamp) {\n createdTimestamp = options.createdTimestamp + 2082844800;\n }\n\n return new table.Table('head', [\n {name: 'version', type: 'FIXED', value: 0x00010000},\n {name: 'fontRevision', type: 'FIXED', value: 0x00010000},\n {name: 'checkSumAdjustment', type: 'ULONG', value: 0},\n {name: 'magicNumber', type: 'ULONG', value: 0x5F0F3CF5},\n {name: 'flags', type: 'USHORT', value: 0},\n {name: 'unitsPerEm', type: 'USHORT', value: 1000},\n {name: 'created', type: 'LONGDATETIME', value: createdTimestamp},\n {name: 'modified', type: 'LONGDATETIME', value: timestamp},\n {name: 'xMin', type: 'SHORT', value: 0},\n {name: 'yMin', type: 'SHORT', value: 0},\n {name: 'xMax', type: 'SHORT', value: 0},\n {name: 'yMax', type: 'SHORT', value: 0},\n {name: 'macStyle', type: 'USHORT', value: 0},\n {name: 'lowestRecPPEM', type: 'USHORT', value: 0},\n {name: 'fontDirectionHint', type: 'SHORT', value: 2},\n {name: 'indexToLocFormat', type: 'SHORT', value: 0},\n {name: 'glyphDataFormat', type: 'SHORT', value: 0}\n ], options);\n}\n\nexports.parse = parseHeadTable;\nexports.make = makeHeadTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/head.js\n ** module id = 17\n ** module chunks = 0\n **/","// The `hhea` table contains information for horizontal layout.\n// https://www.microsoft.com/typography/OTSPEC/hhea.htm\n\n'use strict';\n\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the horizontal header `hhea` table\nfunction parseHheaTable(data, start) {\n var hhea = {};\n var p = new parse.Parser(data, start);\n hhea.version = p.parseVersion();\n hhea.ascender = p.parseShort();\n hhea.descender = p.parseShort();\n hhea.lineGap = p.parseShort();\n hhea.advanceWidthMax = p.parseUShort();\n hhea.minLeftSideBearing = p.parseShort();\n hhea.minRightSideBearing = p.parseShort();\n hhea.xMaxExtent = p.parseShort();\n hhea.caretSlopeRise = p.parseShort();\n hhea.caretSlopeRun = p.parseShort();\n hhea.caretOffset = p.parseShort();\n p.relativeOffset += 8;\n hhea.metricDataFormat = p.parseShort();\n hhea.numberOfHMetrics = p.parseUShort();\n return hhea;\n}\n\nfunction makeHheaTable(options) {\n return new table.Table('hhea', [\n {name: 'version', type: 'FIXED', value: 0x00010000},\n {name: 'ascender', type: 'FWORD', value: 0},\n {name: 'descender', type: 'FWORD', value: 0},\n {name: 'lineGap', type: 'FWORD', value: 0},\n {name: 'advanceWidthMax', type: 'UFWORD', value: 0},\n {name: 'minLeftSideBearing', type: 'FWORD', value: 0},\n {name: 'minRightSideBearing', type: 'FWORD', value: 0},\n {name: 'xMaxExtent', type: 'FWORD', value: 0},\n {name: 'caretSlopeRise', type: 'SHORT', value: 1},\n {name: 'caretSlopeRun', type: 'SHORT', value: 0},\n {name: 'caretOffset', type: 'SHORT', value: 0},\n {name: 'reserved1', type: 'SHORT', value: 0},\n {name: 'reserved2', type: 'SHORT', value: 0},\n {name: 'reserved3', type: 'SHORT', value: 0},\n {name: 'reserved4', type: 'SHORT', value: 0},\n {name: 'metricDataFormat', type: 'SHORT', value: 0},\n {name: 'numberOfHMetrics', type: 'USHORT', value: 0}\n ], options);\n}\n\nexports.parse = parseHheaTable;\nexports.make = makeHheaTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/hhea.js\n ** module id = 18\n ** module chunks = 0\n **/","// The `hmtx` table contains the horizontal metrics for all glyphs.\n// https://www.microsoft.com/typography/OTSPEC/hmtx.htm\n\n'use strict';\n\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the `hmtx` table, which contains the horizontal metrics for all glyphs.\n// This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph.\nfunction parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {\n var advanceWidth;\n var leftSideBearing;\n var p = new parse.Parser(data, start);\n for (var i = 0; i < numGlyphs; i += 1) {\n // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.\n if (i < numMetrics) {\n advanceWidth = p.parseUShort();\n leftSideBearing = p.parseShort();\n }\n\n var glyph = glyphs.get(i);\n glyph.advanceWidth = advanceWidth;\n glyph.leftSideBearing = leftSideBearing;\n }\n}\n\nfunction makeHmtxTable(glyphs) {\n var t = new table.Table('hmtx', []);\n for (var i = 0; i < glyphs.length; i += 1) {\n var glyph = glyphs.get(i);\n var advanceWidth = glyph.advanceWidth || 0;\n var leftSideBearing = glyph.leftSideBearing || 0;\n t.fields.push({name: 'advanceWidth_' + i, type: 'USHORT', value: advanceWidth});\n t.fields.push({name: 'leftSideBearing_' + i, type: 'SHORT', value: leftSideBearing});\n }\n\n return t;\n}\n\nexports.parse = parseHmtxTable;\nexports.make = makeHmtxTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/hmtx.js\n ** module id = 19\n ** module chunks = 0\n **/","// The `ltag` table stores IETF BCP-47 language tags. It allows supporting\n// languages for which TrueType does not assign a numeric code.\n// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html\n// http://www.w3.org/International/articles/language-tags/\n// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\nvar table = require('../table');\n\nfunction makeLtagTable(tags) {\n var result = new table.Table('ltag', [\n {name: 'version', type: 'ULONG', value: 1},\n {name: 'flags', type: 'ULONG', value: 0},\n {name: 'numTags', type: 'ULONG', value: tags.length}\n ]);\n\n var stringPool = '';\n var stringPoolOffset = 12 + tags.length * 4;\n for (var i = 0; i < tags.length; ++i) {\n var pos = stringPool.indexOf(tags[i]);\n if (pos < 0) {\n pos = stringPool.length;\n stringPool += tags[i];\n }\n\n result.fields.push({name: 'offset ' + i, type: 'USHORT', value: stringPoolOffset + pos});\n result.fields.push({name: 'length ' + i, type: 'USHORT', value: tags[i].length});\n }\n\n result.fields.push({name: 'stringPool', type: 'CHARARRAY', value: stringPool});\n return result;\n}\n\nfunction parseLtagTable(data, start) {\n var p = new parse.Parser(data, start);\n var tableVersion = p.parseULong();\n check.argument(tableVersion === 1, 'Unsupported ltag table version.');\n // The 'ltag' specification does not define any flags; skip the field.\n p.skip('uLong', 1);\n var numTags = p.parseULong();\n\n var tags = [];\n for (var i = 0; i < numTags; i++) {\n var tag = '';\n var offset = start + p.parseUShort();\n var length = p.parseUShort();\n for (var j = offset; j < offset + length; ++j) {\n tag += String.fromCharCode(data.getInt8(j));\n }\n\n tags.push(tag);\n }\n\n return tags;\n}\n\nexports.make = makeLtagTable;\nexports.parse = parseLtagTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/ltag.js\n ** module id = 20\n ** module chunks = 0\n **/","// The `maxp` table establishes the memory requirements for the font.\n// We need it just to get the number of glyphs in the font.\n// https://www.microsoft.com/typography/OTSPEC/maxp.htm\n\n'use strict';\n\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the maximum profile `maxp` table.\nfunction parseMaxpTable(data, start) {\n var maxp = {};\n var p = new parse.Parser(data, start);\n maxp.version = p.parseVersion();\n maxp.numGlyphs = p.parseUShort();\n if (maxp.version === 1.0) {\n maxp.maxPoints = p.parseUShort();\n maxp.maxContours = p.parseUShort();\n maxp.maxCompositePoints = p.parseUShort();\n maxp.maxCompositeContours = p.parseUShort();\n maxp.maxZones = p.parseUShort();\n maxp.maxTwilightPoints = p.parseUShort();\n maxp.maxStorage = p.parseUShort();\n maxp.maxFunctionDefs = p.parseUShort();\n maxp.maxInstructionDefs = p.parseUShort();\n maxp.maxStackElements = p.parseUShort();\n maxp.maxSizeOfInstructions = p.parseUShort();\n maxp.maxComponentElements = p.parseUShort();\n maxp.maxComponentDepth = p.parseUShort();\n }\n\n return maxp;\n}\n\nfunction makeMaxpTable(numGlyphs) {\n return new table.Table('maxp', [\n {name: 'version', type: 'FIXED', value: 0x00005000},\n {name: 'numGlyphs', type: 'USHORT', value: numGlyphs}\n ]);\n}\n\nexports.parse = parseMaxpTable;\nexports.make = makeMaxpTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/maxp.js\n ** module id = 21\n ** module chunks = 0\n **/","// The `name` naming table.\n// https://www.microsoft.com/typography/OTSPEC/name.htm\n\n'use strict';\n\nvar types = require('../types');\nvar decode = types.decode;\nvar encode = types.encode;\nvar parse = require('../parse');\nvar table = require('../table');\n\n// NameIDs for the name table.\nvar nameTableNames = [\n 'copyright', // 0\n 'fontFamily', // 1\n 'fontSubfamily', // 2\n 'uniqueID', // 3\n 'fullName', // 4\n 'version', // 5\n 'postScriptName', // 6\n 'trademark', // 7\n 'manufacturer', // 8\n 'designer', // 9\n 'description', // 10\n 'manufacturerURL', // 11\n 'designerURL', // 12\n 'license', // 13\n 'licenseURL', // 14\n 'reserved', // 15\n 'preferredFamily', // 16\n 'preferredSubfamily', // 17\n 'compatibleFullName', // 18\n 'sampleText', // 19\n 'postScriptFindFontName', // 20\n 'wwsFamily', // 21\n 'wwsSubfamily' // 22\n];\n\nvar macLanguages = {\n 0: 'en',\n 1: 'fr',\n 2: 'de',\n 3: 'it',\n 4: 'nl',\n 5: 'sv',\n 6: 'es',\n 7: 'da',\n 8: 'pt',\n 9: 'no',\n 10: 'he',\n 11: 'ja',\n 12: 'ar',\n 13: 'fi',\n 14: 'el',\n 15: 'is',\n 16: 'mt',\n 17: 'tr',\n 18: 'hr',\n 19: 'zh-Hant',\n 20: 'ur',\n 21: 'hi',\n 22: 'th',\n 23: 'ko',\n 24: 'lt',\n 25: 'pl',\n 26: 'hu',\n 27: 'es',\n 28: 'lv',\n 29: 'se',\n 30: 'fo',\n 31: 'fa',\n 32: 'ru',\n 33: 'zh',\n 34: 'nl-BE',\n 35: 'ga',\n 36: 'sq',\n 37: 'ro',\n 38: 'cz',\n 39: 'sk',\n 40: 'si',\n 41: 'yi',\n 42: 'sr',\n 43: 'mk',\n 44: 'bg',\n 45: 'uk',\n 46: 'be',\n 47: 'uz',\n 48: 'kk',\n 49: 'az-Cyrl',\n 50: 'az-Arab',\n 51: 'hy',\n 52: 'ka',\n 53: 'mo',\n 54: 'ky',\n 55: 'tg',\n 56: 'tk',\n 57: 'mn-CN',\n 58: 'mn',\n 59: 'ps',\n 60: 'ks',\n 61: 'ku',\n 62: 'sd',\n 63: 'bo',\n 64: 'ne',\n 65: 'sa',\n 66: 'mr',\n 67: 'bn',\n 68: 'as',\n 69: 'gu',\n 70: 'pa',\n 71: 'or',\n 72: 'ml',\n 73: 'kn',\n 74: 'ta',\n 75: 'te',\n 76: 'si',\n 77: 'my',\n 78: 'km',\n 79: 'lo',\n 80: 'vi',\n 81: 'id',\n 82: 'tl',\n 83: 'ms',\n 84: 'ms-Arab',\n 85: 'am',\n 86: 'ti',\n 87: 'om',\n 88: 'so',\n 89: 'sw',\n 90: 'rw',\n 91: 'rn',\n 92: 'ny',\n 93: 'mg',\n 94: 'eo',\n 128: 'cy',\n 129: 'eu',\n 130: 'ca',\n 131: 'la',\n 132: 'qu',\n 133: 'gn',\n 134: 'ay',\n 135: 'tt',\n 136: 'ug',\n 137: 'dz',\n 138: 'jv',\n 139: 'su',\n 140: 'gl',\n 141: 'af',\n 142: 'br',\n 143: 'iu',\n 144: 'gd',\n 145: 'gv',\n 146: 'ga',\n 147: 'to',\n 148: 'el-polyton',\n 149: 'kl',\n 150: 'az',\n 151: 'nn'\n};\n\n// MacOS language ID → MacOS script ID\n//\n// Note that the script ID is not sufficient to determine what encoding\n// to use in TrueType files. For some languages, MacOS used a modification\n// of a mainstream script. For example, an Icelandic name would be stored\n// with smRoman in the TrueType naming table, but the actual encoding\n// is a special Icelandic version of the normal Macintosh Roman encoding.\n// As another example, Inuktitut uses an 8-bit encoding for Canadian Aboriginal\n// Syllables but MacOS had run out of available script codes, so this was\n// done as a (pretty radical) \"modification\" of Ethiopic.\n//\n// http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt\nvar macLanguageToScript = {\n 0: 0, // langEnglish → smRoman\n 1: 0, // langFrench → smRoman\n 2: 0, // langGerman → smRoman\n 3: 0, // langItalian → smRoman\n 4: 0, // langDutch → smRoman\n 5: 0, // langSwedish → smRoman\n 6: 0, // langSpanish → smRoman\n 7: 0, // langDanish → smRoman\n 8: 0, // langPortuguese → smRoman\n 9: 0, // langNorwegian → smRoman\n 10: 5, // langHebrew → smHebrew\n 11: 1, // langJapanese → smJapanese\n 12: 4, // langArabic → smArabic\n 13: 0, // langFinnish → smRoman\n 14: 6, // langGreek → smGreek\n 15: 0, // langIcelandic → smRoman (modified)\n 16: 0, // langMaltese → smRoman\n 17: 0, // langTurkish → smRoman (modified)\n 18: 0, // langCroatian → smRoman (modified)\n 19: 2, // langTradChinese → smTradChinese\n 20: 4, // langUrdu → smArabic\n 21: 9, // langHindi → smDevanagari\n 22: 21, // langThai → smThai\n 23: 3, // langKorean → smKorean\n 24: 29, // langLithuanian → smCentralEuroRoman\n 25: 29, // langPolish → smCentralEuroRoman\n 26: 29, // langHungarian → smCentralEuroRoman\n 27: 29, // langEstonian → smCentralEuroRoman\n 28: 29, // langLatvian → smCentralEuroRoman\n 29: 0, // langSami → smRoman\n 30: 0, // langFaroese → smRoman (modified)\n 31: 4, // langFarsi → smArabic (modified)\n 32: 7, // langRussian → smCyrillic\n 33: 25, // langSimpChinese → smSimpChinese\n 34: 0, // langFlemish → smRoman\n 35: 0, // langIrishGaelic → smRoman (modified)\n 36: 0, // langAlbanian → smRoman\n 37: 0, // langRomanian → smRoman (modified)\n 38: 29, // langCzech → smCentralEuroRoman\n 39: 29, // langSlovak → smCentralEuroRoman\n 40: 0, // langSlovenian → smRoman (modified)\n 41: 5, // langYiddish → smHebrew\n 42: 7, // langSerbian → smCyrillic\n 43: 7, // langMacedonian → smCyrillic\n 44: 7, // langBulgarian → smCyrillic\n 45: 7, // langUkrainian → smCyrillic (modified)\n 46: 7, // langByelorussian → smCyrillic\n 47: 7, // langUzbek → smCyrillic\n 48: 7, // langKazakh → smCyrillic\n 49: 7, // langAzerbaijani → smCyrillic\n 50: 4, // langAzerbaijanAr → smArabic\n 51: 24, // langArmenian → smArmenian\n 52: 23, // langGeorgian → smGeorgian\n 53: 7, // langMoldavian → smCyrillic\n 54: 7, // langKirghiz → smCyrillic\n 55: 7, // langTajiki → smCyrillic\n 56: 7, // langTurkmen → smCyrillic\n 57: 27, // langMongolian → smMongolian\n 58: 7, // langMongolianCyr → smCyrillic\n 59: 4, // langPashto → smArabic\n 60: 4, // langKurdish → smArabic\n 61: 4, // langKashmiri → smArabic\n 62: 4, // langSindhi → smArabic\n 63: 26, // langTibetan → smTibetan\n 64: 9, // langNepali → smDevanagari\n 65: 9, // langSanskrit → smDevanagari\n 66: 9, // langMarathi → smDevanagari\n 67: 13, // langBengali → smBengali\n 68: 13, // langAssamese → smBengali\n 69: 11, // langGujarati → smGujarati\n 70: 10, // langPunjabi → smGurmukhi\n 71: 12, // langOriya → smOriya\n 72: 17, // langMalayalam → smMalayalam\n 73: 16, // langKannada → smKannada\n 74: 14, // langTamil → smTamil\n 75: 15, // langTelugu → smTelugu\n 76: 18, // langSinhalese → smSinhalese\n 77: 19, // langBurmese → smBurmese\n 78: 20, // langKhmer → smKhmer\n 79: 22, // langLao → smLao\n 80: 30, // langVietnamese → smVietnamese\n 81: 0, // langIndonesian → smRoman\n 82: 0, // langTagalog → smRoman\n 83: 0, // langMalayRoman → smRoman\n 84: 4, // langMalayArabic → smArabic\n 85: 28, // langAmharic → smEthiopic\n 86: 28, // langTigrinya → smEthiopic\n 87: 28, // langOromo → smEthiopic\n 88: 0, // langSomali → smRoman\n 89: 0, // langSwahili → smRoman\n 90: 0, // langKinyarwanda → smRoman\n 91: 0, // langRundi → smRoman\n 92: 0, // langNyanja → smRoman\n 93: 0, // langMalagasy → smRoman\n 94: 0, // langEsperanto → smRoman\n 128: 0, // langWelsh → smRoman (modified)\n 129: 0, // langBasque → smRoman\n 130: 0, // langCatalan → smRoman\n 131: 0, // langLatin → smRoman\n 132: 0, // langQuechua → smRoman\n 133: 0, // langGuarani → smRoman\n 134: 0, // langAymara → smRoman\n 135: 7, // langTatar → smCyrillic\n 136: 4, // langUighur → smArabic\n 137: 26, // langDzongkha → smTibetan\n 138: 0, // langJavaneseRom → smRoman\n 139: 0, // langSundaneseRom → smRoman\n 140: 0, // langGalician → smRoman\n 141: 0, // langAfrikaans → smRoman\n 142: 0, // langBreton → smRoman (modified)\n 143: 28, // langInuktitut → smEthiopic (modified)\n 144: 0, // langScottishGaelic → smRoman (modified)\n 145: 0, // langManxGaelic → smRoman (modified)\n 146: 0, // langIrishGaelicScript → smRoman (modified)\n 147: 0, // langTongan → smRoman\n 148: 6, // langGreekAncient → smRoman\n 149: 0, // langGreenlandic → smRoman\n 150: 0, // langAzerbaijanRoman → smRoman\n 151: 0 // langNynorsk → smRoman\n};\n\n// While Microsoft indicates a region/country for all its language\n// IDs, we omit the region code if it's equal to the \"most likely\n// region subtag\" according to Unicode CLDR. For scripts, we omit\n// the subtag if it is equal to the Suppress-Script entry in the\n// IANA language subtag registry for IETF BCP 47.\n//\n// For example, Microsoft states that its language code 0x041A is\n// Croatian in Croatia. We transform this to the BCP 47 language code 'hr'\n// and not 'hr-HR' because Croatia is the default country for Croatian,\n// according to Unicode CLDR. As another example, Microsoft states\n// that 0x101A is Croatian (Latin) in Bosnia-Herzegovina. We transform\n// this to 'hr-BA' and not 'hr-Latn-BA' because Latin is the default script\n// for the Croatian language, according to IANA.\n//\n// http://www.unicode.org/cldr/charts/latest/supplemental/likely_subtags.html\n// http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry\nvar windowsLanguages = {\n 0x0436: 'af',\n 0x041C: 'sq',\n 0x0484: 'gsw',\n 0x045E: 'am',\n 0x1401: 'ar-DZ',\n 0x3C01: 'ar-BH',\n 0x0C01: 'ar',\n 0x0801: 'ar-IQ',\n 0x2C01: 'ar-JO',\n 0x3401: 'ar-KW',\n 0x3001: 'ar-LB',\n 0x1001: 'ar-LY',\n 0x1801: 'ary',\n 0x2001: 'ar-OM',\n 0x4001: 'ar-QA',\n 0x0401: 'ar-SA',\n 0x2801: 'ar-SY',\n 0x1C01: 'aeb',\n 0x3801: 'ar-AE',\n 0x2401: 'ar-YE',\n 0x042B: 'hy',\n 0x044D: 'as',\n 0x082C: 'az-Cyrl',\n 0x042C: 'az',\n 0x046D: 'ba',\n 0x042D: 'eu',\n 0x0423: 'be',\n 0x0845: 'bn',\n 0x0445: 'bn-IN',\n 0x201A: 'bs-Cyrl',\n 0x141A: 'bs',\n 0x047E: 'br',\n 0x0402: 'bg',\n 0x0403: 'ca',\n 0x0C04: 'zh-HK',\n 0x1404: 'zh-MO',\n 0x0804: 'zh',\n 0x1004: 'zh-SG',\n 0x0404: 'zh-TW',\n 0x0483: 'co',\n 0x041A: 'hr',\n 0x101A: 'hr-BA',\n 0x0405: 'cs',\n 0x0406: 'da',\n 0x048C: 'prs',\n 0x0465: 'dv',\n 0x0813: 'nl-BE',\n 0x0413: 'nl',\n 0x0C09: 'en-AU',\n 0x2809: 'en-BZ',\n 0x1009: 'en-CA',\n 0x2409: 'en-029',\n 0x4009: 'en-IN',\n 0x1809: 'en-IE',\n 0x2009: 'en-JM',\n 0x4409: 'en-MY',\n 0x1409: 'en-NZ',\n 0x3409: 'en-PH',\n 0x4809: 'en-SG',\n 0x1C09: 'en-ZA',\n 0x2C09: 'en-TT',\n 0x0809: 'en-GB',\n 0x0409: 'en',\n 0x3009: 'en-ZW',\n 0x0425: 'et',\n 0x0438: 'fo',\n 0x0464: 'fil',\n 0x040B: 'fi',\n 0x080C: 'fr-BE',\n 0x0C0C: 'fr-CA',\n 0x040C: 'fr',\n 0x140C: 'fr-LU',\n 0x180C: 'fr-MC',\n 0x100C: 'fr-CH',\n 0x0462: 'fy',\n 0x0456: 'gl',\n 0x0437: 'ka',\n 0x0C07: 'de-AT',\n 0x0407: 'de',\n 0x1407: 'de-LI',\n 0x1007: 'de-LU',\n 0x0807: 'de-CH',\n 0x0408: 'el',\n 0x046F: 'kl',\n 0x0447: 'gu',\n 0x0468: 'ha',\n 0x040D: 'he',\n 0x0439: 'hi',\n 0x040E: 'hu',\n 0x040F: 'is',\n 0x0470: 'ig',\n 0x0421: 'id',\n 0x045D: 'iu',\n 0x085D: 'iu-Latn',\n 0x083C: 'ga',\n 0x0434: 'xh',\n 0x0435: 'zu',\n 0x0410: 'it',\n 0x0810: 'it-CH',\n 0x0411: 'ja',\n 0x044B: 'kn',\n 0x043F: 'kk',\n 0x0453: 'km',\n 0x0486: 'quc',\n 0x0487: 'rw',\n 0x0441: 'sw',\n 0x0457: 'kok',\n 0x0412: 'ko',\n 0x0440: 'ky',\n 0x0454: 'lo',\n 0x0426: 'lv',\n 0x0427: 'lt',\n 0x082E: 'dsb',\n 0x046E: 'lb',\n 0x042F: 'mk',\n 0x083E: 'ms-BN',\n 0x043E: 'ms',\n 0x044C: 'ml',\n 0x043A: 'mt',\n 0x0481: 'mi',\n 0x047A: 'arn',\n 0x044E: 'mr',\n 0x047C: 'moh',\n 0x0450: 'mn',\n 0x0850: 'mn-CN',\n 0x0461: 'ne',\n 0x0414: 'nb',\n 0x0814: 'nn',\n 0x0482: 'oc',\n 0x0448: 'or',\n 0x0463: 'ps',\n 0x0415: 'pl',\n 0x0416: 'pt',\n 0x0816: 'pt-PT',\n 0x0446: 'pa',\n 0x046B: 'qu-BO',\n 0x086B: 'qu-EC',\n 0x0C6B: 'qu',\n 0x0418: 'ro',\n 0x0417: 'rm',\n 0x0419: 'ru',\n 0x243B: 'smn',\n 0x103B: 'smj-NO',\n 0x143B: 'smj',\n 0x0C3B: 'se-FI',\n 0x043B: 'se',\n 0x083B: 'se-SE',\n 0x203B: 'sms',\n 0x183B: 'sma-NO',\n 0x1C3B: 'sms',\n 0x044F: 'sa',\n 0x1C1A: 'sr-Cyrl-BA',\n 0x0C1A: 'sr',\n 0x181A: 'sr-Latn-BA',\n 0x081A: 'sr-Latn',\n 0x046C: 'nso',\n 0x0432: 'tn',\n 0x045B: 'si',\n 0x041B: 'sk',\n 0x0424: 'sl',\n 0x2C0A: 'es-AR',\n 0x400A: 'es-BO',\n 0x340A: 'es-CL',\n 0x240A: 'es-CO',\n 0x140A: 'es-CR',\n 0x1C0A: 'es-DO',\n 0x300A: 'es-EC',\n 0x440A: 'es-SV',\n 0x100A: 'es-GT',\n 0x480A: 'es-HN',\n 0x080A: 'es-MX',\n 0x4C0A: 'es-NI',\n 0x180A: 'es-PA',\n 0x3C0A: 'es-PY',\n 0x280A: 'es-PE',\n 0x500A: 'es-PR',\n\n // Microsoft has defined two different language codes for\n // “Spanish with modern sorting” and “Spanish with traditional\n // sorting”. This makes sense for collation APIs, and it would be\n // possible to express this in BCP 47 language tags via Unicode\n // extensions (eg., es-u-co-trad is Spanish with traditional\n // sorting). However, for storing names in fonts, the distinction\n // does not make sense, so we give “es” in both cases.\n 0x0C0A: 'es',\n 0x040A: 'es',\n\n 0x540A: 'es-US',\n 0x380A: 'es-UY',\n 0x200A: 'es-VE',\n 0x081D: 'sv-FI',\n 0x041D: 'sv',\n 0x045A: 'syr',\n 0x0428: 'tg',\n 0x085F: 'tzm',\n 0x0449: 'ta',\n 0x0444: 'tt',\n 0x044A: 'te',\n 0x041E: 'th',\n 0x0451: 'bo',\n 0x041F: 'tr',\n 0x0442: 'tk',\n 0x0480: 'ug',\n 0x0422: 'uk',\n 0x042E: 'hsb',\n 0x0420: 'ur',\n 0x0843: 'uz-Cyrl',\n 0x0443: 'uz',\n 0x042A: 'vi',\n 0x0452: 'cy',\n 0x0488: 'wo',\n 0x0485: 'sah',\n 0x0478: 'ii',\n 0x046A: 'yo'\n};\n\n// Returns a IETF BCP 47 language code, for example 'zh-Hant'\n// for 'Chinese in the traditional script'.\nfunction getLanguageCode(platformID, languageID, ltag) {\n switch (platformID) {\n case 0: // Unicode\n if (languageID === 0xFFFF) {\n return 'und';\n } else if (ltag) {\n return ltag[languageID];\n }\n\n break;\n\n case 1: // Macintosh\n return macLanguages[languageID];\n\n case 3: // Windows\n return windowsLanguages[languageID];\n }\n\n return undefined;\n}\n\nvar utf16 = 'utf-16';\n\n// MacOS script ID → encoding. This table stores the default case,\n// which can be overridden by macLanguageEncodings.\nvar macScriptEncodings = {\n 0: 'macintosh', // smRoman\n 1: 'x-mac-japanese', // smJapanese\n 2: 'x-mac-chinesetrad', // smTradChinese\n 3: 'x-mac-korean', // smKorean\n 6: 'x-mac-greek', // smGreek\n 7: 'x-mac-cyrillic', // smCyrillic\n 9: 'x-mac-devanagai', // smDevanagari\n 10: 'x-mac-gurmukhi', // smGurmukhi\n 11: 'x-mac-gujarati', // smGujarati\n 12: 'x-mac-oriya', // smOriya\n 13: 'x-mac-bengali', // smBengali\n 14: 'x-mac-tamil', // smTamil\n 15: 'x-mac-telugu', // smTelugu\n 16: 'x-mac-kannada', // smKannada\n 17: 'x-mac-malayalam', // smMalayalam\n 18: 'x-mac-sinhalese', // smSinhalese\n 19: 'x-mac-burmese', // smBurmese\n 20: 'x-mac-khmer', // smKhmer\n 21: 'x-mac-thai', // smThai\n 22: 'x-mac-lao', // smLao\n 23: 'x-mac-georgian', // smGeorgian\n 24: 'x-mac-armenian', // smArmenian\n 25: 'x-mac-chinesesimp', // smSimpChinese\n 26: 'x-mac-tibetan', // smTibetan\n 27: 'x-mac-mongolian', // smMongolian\n 28: 'x-mac-ethiopic', // smEthiopic\n 29: 'x-mac-ce', // smCentralEuroRoman\n 30: 'x-mac-vietnamese', // smVietnamese\n 31: 'x-mac-extarabic' // smExtArabic\n};\n\n// MacOS language ID → encoding. This table stores the exceptional\n// cases, which override macScriptEncodings. For writing MacOS naming\n// tables, we need to emit a MacOS script ID. Therefore, we cannot\n// merge macScriptEncodings into macLanguageEncodings.\n//\n// http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt\nvar macLanguageEncodings = {\n 15: 'x-mac-icelandic', // langIcelandic\n 17: 'x-mac-turkish', // langTurkish\n 18: 'x-mac-croatian', // langCroatian\n 24: 'x-mac-ce', // langLithuanian\n 25: 'x-mac-ce', // langPolish\n 26: 'x-mac-ce', // langHungarian\n 27: 'x-mac-ce', // langEstonian\n 28: 'x-mac-ce', // langLatvian\n 30: 'x-mac-icelandic', // langFaroese\n 37: 'x-mac-romanian', // langRomanian\n 38: 'x-mac-ce', // langCzech\n 39: 'x-mac-ce', // langSlovak\n 40: 'x-mac-ce', // langSlovenian\n 143: 'x-mac-inuit', // langInuktitut\n 146: 'x-mac-gaelic' // langIrishGaelicScript\n};\n\nfunction getEncoding(platformID, encodingID, languageID) {\n switch (platformID) {\n case 0: // Unicode\n return utf16;\n\n case 1: // Apple Macintosh\n return macLanguageEncodings[languageID] || macScriptEncodings[encodingID];\n\n case 3: // Microsoft Windows\n if (encodingID === 1 || encodingID === 10) {\n return utf16;\n }\n\n break;\n }\n\n return undefined;\n}\n\n// Parse the naming `name` table.\n// FIXME: Format 1 additional fields are not supported yet.\n// ltag is the content of the `ltag' table, such as ['en', 'zh-Hans', 'de-CH-1904'].\nfunction parseNameTable(data, start, ltag) {\n var name = {};\n var p = new parse.Parser(data, start);\n var format = p.parseUShort();\n var count = p.parseUShort();\n var stringOffset = p.offset + p.parseUShort();\n for (var i = 0; i < count; i++) {\n var platformID = p.parseUShort();\n var encodingID = p.parseUShort();\n var languageID = p.parseUShort();\n var nameID = p.parseUShort();\n var property = nameTableNames[nameID] || nameID;\n var byteLength = p.parseUShort();\n var offset = p.parseUShort();\n var language = getLanguageCode(platformID, languageID, ltag);\n var encoding = getEncoding(platformID, encodingID, languageID);\n if (encoding !== undefined && language !== undefined) {\n var text;\n if (encoding === utf16) {\n text = decode.UTF16(data, stringOffset + offset, byteLength);\n } else {\n text = decode.MACSTRING(data, stringOffset + offset, byteLength, encoding);\n }\n\n if (text) {\n var translations = name[property];\n if (translations === undefined) {\n translations = name[property] = {};\n }\n\n translations[language] = text;\n }\n }\n }\n\n var langTagCount = 0;\n if (format === 1) {\n // FIXME: Also handle Microsoft's 'name' table 1.\n langTagCount = p.parseUShort();\n }\n\n return name;\n}\n\n// {23: 'foo'} → {'foo': 23}\n// ['bar', 'baz'] → {'bar': 0, 'baz': 1}\nfunction reverseDict(dict) {\n var result = {};\n for (var key in dict) {\n result[dict[key]] = parseInt(key);\n }\n\n return result;\n}\n\nfunction makeNameRecord(platformID, encodingID, languageID, nameID, length, offset) {\n return new table.Record('NameRecord', [\n {name: 'platformID', type: 'USHORT', value: platformID},\n {name: 'encodingID', type: 'USHORT', value: encodingID},\n {name: 'languageID', type: 'USHORT', value: languageID},\n {name: 'nameID', type: 'USHORT', value: nameID},\n {name: 'length', type: 'USHORT', value: length},\n {name: 'offset', type: 'USHORT', value: offset}\n ]);\n}\n\n// Finds the position of needle in haystack, or -1 if not there.\n// Like String.indexOf(), but for arrays.\nfunction findSubArray(needle, haystack) {\n var needleLength = needle.length;\n var limit = haystack.length - needleLength + 1;\n\n loop:\n for (var pos = 0; pos < limit; pos++) {\n for (; pos < limit; pos++) {\n for (var k = 0; k < needleLength; k++) {\n if (haystack[pos + k] !== needle[k]) {\n continue loop;\n }\n }\n\n return pos;\n }\n }\n\n return -1;\n}\n\nfunction addStringToPool(s, pool) {\n var offset = findSubArray(s, pool);\n if (offset < 0) {\n offset = pool.length;\n for (var i = 0, len = s.length; i < len; ++i) {\n pool.push(s[i]);\n }\n\n }\n\n return offset;\n}\n\nfunction makeNameTable(names, ltag) {\n var nameID;\n var nameIDs = [];\n\n var namesWithNumericKeys = {};\n var nameTableIds = reverseDict(nameTableNames);\n for (var key in names) {\n var id = nameTableIds[key];\n if (id === undefined) {\n id = key;\n }\n\n nameID = parseInt(id);\n namesWithNumericKeys[nameID] = names[key];\n nameIDs.push(nameID);\n }\n\n var macLanguageIds = reverseDict(macLanguages);\n var windowsLanguageIds = reverseDict(windowsLanguages);\n\n var nameRecords = [];\n var stringPool = [];\n\n for (var i = 0; i < nameIDs.length; i++) {\n nameID = nameIDs[i];\n var translations = namesWithNumericKeys[nameID];\n for (var lang in translations) {\n var text = translations[lang];\n\n // For MacOS, we try to emit the name in the form that was introduced\n // in the initial version of the TrueType spec (in the late 1980s).\n // However, this can fail for various reasons: the requested BCP 47\n // language code might not have an old-style Mac equivalent;\n // we might not have a codec for the needed character encoding;\n // or the name might contain characters that cannot be expressed\n // in the old-style Macintosh encoding. In case of failure, we emit\n // the name in a more modern fashion (Unicode encoding with BCP 47\n // language tags) that is recognized by MacOS 10.5, released in 2009.\n // If fonts were only read by operating systems, we could simply\n // emit all names in the modern form; this would be much easier.\n // However, there are many applications and libraries that read\n // 'name' tables directly, and these will usually only recognize\n // the ancient form (silently skipping the unrecognized names).\n var macPlatform = 1; // Macintosh\n var macLanguage = macLanguageIds[lang];\n var macScript = macLanguageToScript[macLanguage];\n var macEncoding = getEncoding(macPlatform, macScript, macLanguage);\n var macName = encode.MACSTRING(text, macEncoding);\n if (macName === undefined) {\n macPlatform = 0; // Unicode\n macLanguage = ltag.indexOf(lang);\n if (macLanguage < 0) {\n macLanguage = ltag.length;\n ltag.push(lang);\n }\n\n macScript = 4; // Unicode 2.0 and later\n macName = encode.UTF16(text);\n }\n\n var macNameOffset = addStringToPool(macName, stringPool);\n nameRecords.push(makeNameRecord(macPlatform, macScript, macLanguage,\n nameID, macName.length, macNameOffset));\n\n var winLanguage = windowsLanguageIds[lang];\n if (winLanguage !== undefined) {\n var winName = encode.UTF16(text);\n var winNameOffset = addStringToPool(winName, stringPool);\n nameRecords.push(makeNameRecord(3, 1, winLanguage,\n nameID, winName.length, winNameOffset));\n }\n }\n }\n\n nameRecords.sort(function(a, b) {\n return ((a.platformID - b.platformID) ||\n (a.encodingID - b.encodingID) ||\n (a.languageID - b.languageID) ||\n (a.nameID - b.nameID));\n });\n\n var t = new table.Table('name', [\n {name: 'format', type: 'USHORT', value: 0},\n {name: 'count', type: 'USHORT', value: nameRecords.length},\n {name: 'stringOffset', type: 'USHORT', value: 6 + nameRecords.length * 12}\n ]);\n\n for (var r = 0; r < nameRecords.length; r++) {\n t.fields.push({name: 'record_' + r, type: 'RECORD', value: nameRecords[r]});\n }\n\n t.fields.push({name: 'strings', type: 'LITERAL', value: stringPool});\n return t;\n}\n\nexports.parse = parseNameTable;\nexports.make = makeNameTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/name.js\n ** module id = 22\n ** module chunks = 0\n **/","// The `OS/2` table contains metrics required in OpenType fonts.\n// https://www.microsoft.com/typography/OTSPEC/os2.htm\n\n'use strict';\n\nvar parse = require('../parse');\nvar table = require('../table');\n\nvar unicodeRanges = [\n {begin: 0x0000, end: 0x007F}, // Basic Latin\n {begin: 0x0080, end: 0x00FF}, // Latin-1 Supplement\n {begin: 0x0100, end: 0x017F}, // Latin Extended-A\n {begin: 0x0180, end: 0x024F}, // Latin Extended-B\n {begin: 0x0250, end: 0x02AF}, // IPA Extensions\n {begin: 0x02B0, end: 0x02FF}, // Spacing Modifier Letters\n {begin: 0x0300, end: 0x036F}, // Combining Diacritical Marks\n {begin: 0x0370, end: 0x03FF}, // Greek and Coptic\n {begin: 0x2C80, end: 0x2CFF}, // Coptic\n {begin: 0x0400, end: 0x04FF}, // Cyrillic\n {begin: 0x0530, end: 0x058F}, // Armenian\n {begin: 0x0590, end: 0x05FF}, // Hebrew\n {begin: 0xA500, end: 0xA63F}, // Vai\n {begin: 0x0600, end: 0x06FF}, // Arabic\n {begin: 0x07C0, end: 0x07FF}, // NKo\n {begin: 0x0900, end: 0x097F}, // Devanagari\n {begin: 0x0980, end: 0x09FF}, // Bengali\n {begin: 0x0A00, end: 0x0A7F}, // Gurmukhi\n {begin: 0x0A80, end: 0x0AFF}, // Gujarati\n {begin: 0x0B00, end: 0x0B7F}, // Oriya\n {begin: 0x0B80, end: 0x0BFF}, // Tamil\n {begin: 0x0C00, end: 0x0C7F}, // Telugu\n {begin: 0x0C80, end: 0x0CFF}, // Kannada\n {begin: 0x0D00, end: 0x0D7F}, // Malayalam\n {begin: 0x0E00, end: 0x0E7F}, // Thai\n {begin: 0x0E80, end: 0x0EFF}, // Lao\n {begin: 0x10A0, end: 0x10FF}, // Georgian\n {begin: 0x1B00, end: 0x1B7F}, // Balinese\n {begin: 0x1100, end: 0x11FF}, // Hangul Jamo\n {begin: 0x1E00, end: 0x1EFF}, // Latin Extended Additional\n {begin: 0x1F00, end: 0x1FFF}, // Greek Extended\n {begin: 0x2000, end: 0x206F}, // General Punctuation\n {begin: 0x2070, end: 0x209F}, // Superscripts And Subscripts\n {begin: 0x20A0, end: 0x20CF}, // Currency Symbol\n {begin: 0x20D0, end: 0x20FF}, // Combining Diacritical Marks For Symbols\n {begin: 0x2100, end: 0x214F}, // Letterlike Symbols\n {begin: 0x2150, end: 0x218F}, // Number Forms\n {begin: 0x2190, end: 0x21FF}, // Arrows\n {begin: 0x2200, end: 0x22FF}, // Mathematical Operators\n {begin: 0x2300, end: 0x23FF}, // Miscellaneous Technical\n {begin: 0x2400, end: 0x243F}, // Control Pictures\n {begin: 0x2440, end: 0x245F}, // Optical Character Recognition\n {begin: 0x2460, end: 0x24FF}, // Enclosed Alphanumerics\n {begin: 0x2500, end: 0x257F}, // Box Drawing\n {begin: 0x2580, end: 0x259F}, // Block Elements\n {begin: 0x25A0, end: 0x25FF}, // Geometric Shapes\n {begin: 0x2600, end: 0x26FF}, // Miscellaneous Symbols\n {begin: 0x2700, end: 0x27BF}, // Dingbats\n {begin: 0x3000, end: 0x303F}, // CJK Symbols And Punctuation\n {begin: 0x3040, end: 0x309F}, // Hiragana\n {begin: 0x30A0, end: 0x30FF}, // Katakana\n {begin: 0x3100, end: 0x312F}, // Bopomofo\n {begin: 0x3130, end: 0x318F}, // Hangul Compatibility Jamo\n {begin: 0xA840, end: 0xA87F}, // Phags-pa\n {begin: 0x3200, end: 0x32FF}, // Enclosed CJK Letters And Months\n {begin: 0x3300, end: 0x33FF}, // CJK Compatibility\n {begin: 0xAC00, end: 0xD7AF}, // Hangul Syllables\n {begin: 0xD800, end: 0xDFFF}, // Non-Plane 0 *\n {begin: 0x10900, end: 0x1091F}, // Phoenicia\n {begin: 0x4E00, end: 0x9FFF}, // CJK Unified Ideographs\n {begin: 0xE000, end: 0xF8FF}, // Private Use Area (plane 0)\n {begin: 0x31C0, end: 0x31EF}, // CJK Strokes\n {begin: 0xFB00, end: 0xFB4F}, // Alphabetic Presentation Forms\n {begin: 0xFB50, end: 0xFDFF}, // Arabic Presentation Forms-A\n {begin: 0xFE20, end: 0xFE2F}, // Combining Half Marks\n {begin: 0xFE10, end: 0xFE1F}, // Vertical Forms\n {begin: 0xFE50, end: 0xFE6F}, // Small Form Variants\n {begin: 0xFE70, end: 0xFEFF}, // Arabic Presentation Forms-B\n {begin: 0xFF00, end: 0xFFEF}, // Halfwidth And Fullwidth Forms\n {begin: 0xFFF0, end: 0xFFFF}, // Specials\n {begin: 0x0F00, end: 0x0FFF}, // Tibetan\n {begin: 0x0700, end: 0x074F}, // Syriac\n {begin: 0x0780, end: 0x07BF}, // Thaana\n {begin: 0x0D80, end: 0x0DFF}, // Sinhala\n {begin: 0x1000, end: 0x109F}, // Myanmar\n {begin: 0x1200, end: 0x137F}, // Ethiopic\n {begin: 0x13A0, end: 0x13FF}, // Cherokee\n {begin: 0x1400, end: 0x167F}, // Unified Canadian Aboriginal Syllabics\n {begin: 0x1680, end: 0x169F}, // Ogham\n {begin: 0x16A0, end: 0x16FF}, // Runic\n {begin: 0x1780, end: 0x17FF}, // Khmer\n {begin: 0x1800, end: 0x18AF}, // Mongolian\n {begin: 0x2800, end: 0x28FF}, // Braille Patterns\n {begin: 0xA000, end: 0xA48F}, // Yi Syllables\n {begin: 0x1700, end: 0x171F}, // Tagalog\n {begin: 0x10300, end: 0x1032F}, // Old Italic\n {begin: 0x10330, end: 0x1034F}, // Gothic\n {begin: 0x10400, end: 0x1044F}, // Deseret\n {begin: 0x1D000, end: 0x1D0FF}, // Byzantine Musical Symbols\n {begin: 0x1D400, end: 0x1D7FF}, // Mathematical Alphanumeric Symbols\n {begin: 0xFF000, end: 0xFFFFD}, // Private Use (plane 15)\n {begin: 0xFE00, end: 0xFE0F}, // Variation Selectors\n {begin: 0xE0000, end: 0xE007F}, // Tags\n {begin: 0x1900, end: 0x194F}, // Limbu\n {begin: 0x1950, end: 0x197F}, // Tai Le\n {begin: 0x1980, end: 0x19DF}, // New Tai Lue\n {begin: 0x1A00, end: 0x1A1F}, // Buginese\n {begin: 0x2C00, end: 0x2C5F}, // Glagolitic\n {begin: 0x2D30, end: 0x2D7F}, // Tifinagh\n {begin: 0x4DC0, end: 0x4DFF}, // Yijing Hexagram Symbols\n {begin: 0xA800, end: 0xA82F}, // Syloti Nagri\n {begin: 0x10000, end: 0x1007F}, // Linear B Syllabary\n {begin: 0x10140, end: 0x1018F}, // Ancient Greek Numbers\n {begin: 0x10380, end: 0x1039F}, // Ugaritic\n {begin: 0x103A0, end: 0x103DF}, // Old Persian\n {begin: 0x10450, end: 0x1047F}, // Shavian\n {begin: 0x10480, end: 0x104AF}, // Osmanya\n {begin: 0x10800, end: 0x1083F}, // Cypriot Syllabary\n {begin: 0x10A00, end: 0x10A5F}, // Kharoshthi\n {begin: 0x1D300, end: 0x1D35F}, // Tai Xuan Jing Symbols\n {begin: 0x12000, end: 0x123FF}, // Cuneiform\n {begin: 0x1D360, end: 0x1D37F}, // Counting Rod Numerals\n {begin: 0x1B80, end: 0x1BBF}, // Sundanese\n {begin: 0x1C00, end: 0x1C4F}, // Lepcha\n {begin: 0x1C50, end: 0x1C7F}, // Ol Chiki\n {begin: 0xA880, end: 0xA8DF}, // Saurashtra\n {begin: 0xA900, end: 0xA92F}, // Kayah Li\n {begin: 0xA930, end: 0xA95F}, // Rejang\n {begin: 0xAA00, end: 0xAA5F}, // Cham\n {begin: 0x10190, end: 0x101CF}, // Ancient Symbols\n {begin: 0x101D0, end: 0x101FF}, // Phaistos Disc\n {begin: 0x102A0, end: 0x102DF}, // Carian\n {begin: 0x1F030, end: 0x1F09F} // Domino Tiles\n];\n\nfunction getUnicodeRange(unicode) {\n for (var i = 0; i < unicodeRanges.length; i += 1) {\n var range = unicodeRanges[i];\n if (unicode >= range.begin && unicode < range.end) {\n return i;\n }\n }\n\n return -1;\n}\n\n// Parse the OS/2 and Windows metrics `OS/2` table\nfunction parseOS2Table(data, start) {\n var os2 = {};\n var p = new parse.Parser(data, start);\n os2.version = p.parseUShort();\n os2.xAvgCharWidth = p.parseShort();\n os2.usWeightClass = p.parseUShort();\n os2.usWidthClass = p.parseUShort();\n os2.fsType = p.parseUShort();\n os2.ySubscriptXSize = p.parseShort();\n os2.ySubscriptYSize = p.parseShort();\n os2.ySubscriptXOffset = p.parseShort();\n os2.ySubscriptYOffset = p.parseShort();\n os2.ySuperscriptXSize = p.parseShort();\n os2.ySuperscriptYSize = p.parseShort();\n os2.ySuperscriptXOffset = p.parseShort();\n os2.ySuperscriptYOffset = p.parseShort();\n os2.yStrikeoutSize = p.parseShort();\n os2.yStrikeoutPosition = p.parseShort();\n os2.sFamilyClass = p.parseShort();\n os2.panose = [];\n for (var i = 0; i < 10; i++) {\n os2.panose[i] = p.parseByte();\n }\n\n os2.ulUnicodeRange1 = p.parseULong();\n os2.ulUnicodeRange2 = p.parseULong();\n os2.ulUnicodeRange3 = p.parseULong();\n os2.ulUnicodeRange4 = p.parseULong();\n os2.achVendID = String.fromCharCode(p.parseByte(), p.parseByte(), p.parseByte(), p.parseByte());\n os2.fsSelection = p.parseUShort();\n os2.usFirstCharIndex = p.parseUShort();\n os2.usLastCharIndex = p.parseUShort();\n os2.sTypoAscender = p.parseShort();\n os2.sTypoDescender = p.parseShort();\n os2.sTypoLineGap = p.parseShort();\n os2.usWinAscent = p.parseUShort();\n os2.usWinDescent = p.parseUShort();\n if (os2.version >= 1) {\n os2.ulCodePageRange1 = p.parseULong();\n os2.ulCodePageRange2 = p.parseULong();\n }\n\n if (os2.version >= 2) {\n os2.sxHeight = p.parseShort();\n os2.sCapHeight = p.parseShort();\n os2.usDefaultChar = p.parseUShort();\n os2.usBreakChar = p.parseUShort();\n os2.usMaxContent = p.parseUShort();\n }\n\n return os2;\n}\n\nfunction makeOS2Table(options) {\n return new table.Table('OS/2', [\n {name: 'version', type: 'USHORT', value: 0x0003},\n {name: 'xAvgCharWidth', type: 'SHORT', value: 0},\n {name: 'usWeightClass', type: 'USHORT', value: 0},\n {name: 'usWidthClass', type: 'USHORT', value: 0},\n {name: 'fsType', type: 'USHORT', value: 0},\n {name: 'ySubscriptXSize', type: 'SHORT', value: 650},\n {name: 'ySubscriptYSize', type: 'SHORT', value: 699},\n {name: 'ySubscriptXOffset', type: 'SHORT', value: 0},\n {name: 'ySubscriptYOffset', type: 'SHORT', value: 140},\n {name: 'ySuperscriptXSize', type: 'SHORT', value: 650},\n {name: 'ySuperscriptYSize', type: 'SHORT', value: 699},\n {name: 'ySuperscriptXOffset', type: 'SHORT', value: 0},\n {name: 'ySuperscriptYOffset', type: 'SHORT', value: 479},\n {name: 'yStrikeoutSize', type: 'SHORT', value: 49},\n {name: 'yStrikeoutPosition', type: 'SHORT', value: 258},\n {name: 'sFamilyClass', type: 'SHORT', value: 0},\n {name: 'bFamilyType', type: 'BYTE', value: 0},\n {name: 'bSerifStyle', type: 'BYTE', value: 0},\n {name: 'bWeight', type: 'BYTE', value: 0},\n {name: 'bProportion', type: 'BYTE', value: 0},\n {name: 'bContrast', type: 'BYTE', value: 0},\n {name: 'bStrokeVariation', type: 'BYTE', value: 0},\n {name: 'bArmStyle', type: 'BYTE', value: 0},\n {name: 'bLetterform', type: 'BYTE', value: 0},\n {name: 'bMidline', type: 'BYTE', value: 0},\n {name: 'bXHeight', type: 'BYTE', value: 0},\n {name: 'ulUnicodeRange1', type: 'ULONG', value: 0},\n {name: 'ulUnicodeRange2', type: 'ULONG', value: 0},\n {name: 'ulUnicodeRange3', type: 'ULONG', value: 0},\n {name: 'ulUnicodeRange4', type: 'ULONG', value: 0},\n {name: 'achVendID', type: 'CHARARRAY', value: 'XXXX'},\n {name: 'fsSelection', type: 'USHORT', value: 0},\n {name: 'usFirstCharIndex', type: 'USHORT', value: 0},\n {name: 'usLastCharIndex', type: 'USHORT', value: 0},\n {name: 'sTypoAscender', type: 'SHORT', value: 0},\n {name: 'sTypoDescender', type: 'SHORT', value: 0},\n {name: 'sTypoLineGap', type: 'SHORT', value: 0},\n {name: 'usWinAscent', type: 'USHORT', value: 0},\n {name: 'usWinDescent', type: 'USHORT', value: 0},\n {name: 'ulCodePageRange1', type: 'ULONG', value: 0},\n {name: 'ulCodePageRange2', type: 'ULONG', value: 0},\n {name: 'sxHeight', type: 'SHORT', value: 0},\n {name: 'sCapHeight', type: 'SHORT', value: 0},\n {name: 'usDefaultChar', type: 'USHORT', value: 0},\n {name: 'usBreakChar', type: 'USHORT', value: 0},\n {name: 'usMaxContext', type: 'USHORT', value: 0}\n ], options);\n}\n\nexports.unicodeRanges = unicodeRanges;\nexports.getUnicodeRange = getUnicodeRange;\nexports.parse = parseOS2Table;\nexports.make = makeOS2Table;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/os2.js\n ** module id = 23\n ** module chunks = 0\n **/","// The `post` table stores additional PostScript information, such as glyph names.\n// https://www.microsoft.com/typography/OTSPEC/post.htm\n\n'use strict';\n\nvar encoding = require('../encoding');\nvar parse = require('../parse');\nvar table = require('../table');\n\n// Parse the PostScript `post` table\nfunction parsePostTable(data, start) {\n var post = {};\n var p = new parse.Parser(data, start);\n var i;\n post.version = p.parseVersion();\n post.italicAngle = p.parseFixed();\n post.underlinePosition = p.parseShort();\n post.underlineThickness = p.parseShort();\n post.isFixedPitch = p.parseULong();\n post.minMemType42 = p.parseULong();\n post.maxMemType42 = p.parseULong();\n post.minMemType1 = p.parseULong();\n post.maxMemType1 = p.parseULong();\n switch (post.version) {\n case 1:\n post.names = encoding.standardNames.slice();\n break;\n case 2:\n post.numberOfGlyphs = p.parseUShort();\n post.glyphNameIndex = new Array(post.numberOfGlyphs);\n for (i = 0; i < post.numberOfGlyphs; i++) {\n post.glyphNameIndex[i] = p.parseUShort();\n }\n\n post.names = [];\n for (i = 0; i < post.numberOfGlyphs; i++) {\n if (post.glyphNameIndex[i] >= encoding.standardNames.length) {\n var nameLength = p.parseChar();\n post.names.push(p.parseString(nameLength));\n }\n }\n\n break;\n case 2.5:\n post.numberOfGlyphs = p.parseUShort();\n post.offset = new Array(post.numberOfGlyphs);\n for (i = 0; i < post.numberOfGlyphs; i++) {\n post.offset[i] = p.parseChar();\n }\n\n break;\n }\n return post;\n}\n\nfunction makePostTable() {\n return new table.Table('post', [\n {name: 'version', type: 'FIXED', value: 0x00030000},\n {name: 'italicAngle', type: 'FIXED', value: 0},\n {name: 'underlinePosition', type: 'FWORD', value: 0},\n {name: 'underlineThickness', type: 'FWORD', value: 0},\n {name: 'isFixedPitch', type: 'ULONG', value: 0},\n {name: 'minMemType42', type: 'ULONG', value: 0},\n {name: 'maxMemType42', type: 'ULONG', value: 0},\n {name: 'minMemType1', type: 'ULONG', value: 0},\n {name: 'maxMemType1', type: 'ULONG', value: 0}\n ]);\n}\n\nexports.parse = parsePostTable;\nexports.make = makePostTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/post.js\n ** module id = 24\n ** module chunks = 0\n **/","// The `GSUB` table contains ligatures, among other things.\n// https://www.microsoft.com/typography/OTSPEC/gsub.htm\n\n'use strict';\n\nvar check = require('../check');\nvar Parser = require('../parse').Parser;\nvar subtableParsers = new Array(9); // subtableParsers[0] is unused\nvar table = require('../table');\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS\nsubtableParsers[1] = function parseLookup1() {\n var start = this.offset + this.relativeOffset;\n var substFormat = this.parseUShort();\n if (substFormat === 1) {\n return {\n substFormat: 1,\n coverage: this.parsePointer(Parser.coverage),\n deltaGlyphId: this.parseUShort()\n };\n } else if (substFormat === 2) {\n return {\n substFormat: 2,\n coverage: this.parsePointer(Parser.coverage),\n substitute: this.parseOffset16List()\n };\n }\n check.assert(false, '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.');\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS\nsubtableParsers[2] = function parseLookup2() {\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB Multiple Substitution Subtable identifier-format must be 1');\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n sequences: this.parseListOfLists()\n };\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS\nsubtableParsers[3] = function parseLookup3() {\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB Alternate Substitution Subtable identifier-format must be 1');\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n alternateSets: this.parseListOfLists()\n };\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS\nsubtableParsers[4] = function parseLookup4() {\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB ligature table identifier-format must be 1');\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n ligatureSets: this.parseListOfLists(function() {\n return {\n ligGlyph: this.parseUShort(),\n components: this.parseUShortList(this.parseUShort() - 1)\n };\n })\n };\n};\n\nvar lookupRecordDesc = {\n sequenceIndex: Parser.uShort,\n lookupListIndex: Parser.uShort\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF\nsubtableParsers[5] = function parseLookup5() {\n var start = this.offset + this.relativeOffset;\n var substFormat = this.parseUShort();\n\n if (substFormat === 1) {\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n ruleSets: this.parseListOfLists(function() {\n var glyphCount = this.parseUShort();\n var substCount = this.parseUShort();\n return {\n input: this.parseUShortList(glyphCount - 1),\n lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)\n };\n })\n };\n } else if (substFormat === 2) {\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n classDef: this.parsePointer(Parser.classDef),\n classSets: this.parseListOfLists(function() {\n var glyphCount = this.parseUShort();\n var substCount = this.parseUShort();\n return {\n classes: this.parseUShortList(glyphCount - 1),\n lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)\n };\n })\n };\n } else if (substFormat === 3) {\n var glyphCount = this.parseUShort();\n var substCount = this.parseUShort();\n return {\n substFormat: substFormat,\n coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)),\n lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)\n };\n }\n check.assert(false, '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.');\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC\nsubtableParsers[6] = function parseLookup6() {\n // TODO add automated tests for lookup 6 : no examples in the MS doc.\n var start = this.offset + this.relativeOffset;\n var substFormat = this.parseUShort();\n if (substFormat === 1) {\n return {\n substFormat: 1,\n coverage: this.parsePointer(Parser.coverage),\n chainRuleSets: this.parseListOfLists(function() {\n return {\n backtrack: this.parseUShortList(),\n input: this.parseUShortList(this.parseShort() - 1),\n lookahead: this.parseUShortList(),\n lookupRecords: this.parseRecordList(lookupRecordDesc)\n };\n })\n };\n } else if (substFormat === 2) {\n return {\n substFormat: 2,\n coverage: this.parsePointer(Parser.coverage),\n backtrackClassDef: this.parsePointer(Parser.classDef),\n inputClassDef: this.parsePointer(Parser.classDef),\n lookaheadClassDef: this.parsePointer(Parser.classDef),\n chainClassSet: this.parseListOfLists(function() {\n return {\n backtrack: this.parseUShortList(),\n input: this.parseUShortList(this.parseShort() - 1),\n lookahead: this.parseUShortList(),\n lookupRecords: this.parseRecordList(lookupRecordDesc)\n };\n })\n };\n } else if (substFormat === 3) {\n return {\n substFormat: 3,\n backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n inputCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n lookupRecords: this.parseRecordList(lookupRecordDesc)\n };\n }\n check.assert(false, '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.');\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES\nsubtableParsers[7] = function parseLookup7() {\n // Extension Substitution subtable\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB Extension Substitution subtable identifier-format must be 1');\n var extensionLookupType = this.parseUShort();\n var extensionParser = new Parser(this.data, this.offset + this.parseULong());\n return {\n substFormat: 1,\n lookupType: extensionLookupType,\n extension: subtableParsers[extensionLookupType].call(extensionParser)\n };\n};\n\n// https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS\nsubtableParsers[8] = function parseLookup8() {\n var substFormat = this.parseUShort();\n check.argument(substFormat === 1, 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1');\n return {\n substFormat: substFormat,\n coverage: this.parsePointer(Parser.coverage),\n backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),\n substitutes: this.parseUShortList()\n };\n};\n\n// https://www.microsoft.com/typography/OTSPEC/gsub.htm\nfunction parseGsubTable(data, start) {\n start = start || 0;\n var p = new Parser(data, start);\n var tableVersion = p.parseVersion();\n check.argument(tableVersion === 1, 'Unsupported GSUB table version.');\n return {\n version: tableVersion,\n scripts: p.parseScriptList(),\n features: p.parseFeatureList(),\n lookups: p.parseLookupList(subtableParsers)\n };\n}\n\n// GSUB Writing //////////////////////////////////////////////\nvar subtableMakers = new Array(9);\n\nsubtableMakers[1] = function makeLookup1(subtable) {\n if (subtable.substFormat === 1) {\n return new table.Table('substitutionTable', [\n {name: 'substFormat', type: 'USHORT', value: 1},\n {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)},\n {name: 'deltaGlyphID', type: 'USHORT', value: subtable.deltaGlyphId}\n ]);\n } else {\n check.assert(false, 'Can\\'t write lookup type 1 subtable format 2.');\n }\n check.assert(false, 'Lookup type 1 substFormat must be 1 or 2.');\n};\n\nsubtableMakers[4] = function makeLookup4(subtable) {\n check.assert(subtable.substFormat === 1, 'Lookup type 4 substFormat must be 1.');\n return new table.Table('substitutionTable', [\n {name: 'substFormat', type: 'USHORT', value: 1},\n {name: 'coverage', type: 'TABLE', value: new table.Coverage(subtable.coverage)}\n ].concat(table.tableList('ligSet', subtable.ligatureSets, function(ligatureSet) {\n return new table.Table('ligatureSetTable', table.tableList('ligature', ligatureSet, function(ligature) {\n return new table.Table('ligatureTable',\n [{name: 'ligGlyph', type: 'USHORT', value: ligature.ligGlyph}]\n .concat(table.ushortList('component', ligature.components, ligature.components.length + 1))\n );\n }));\n })));\n};\n\nfunction makeGsubTable(gsub) {\n // Feature limitation - we can only write the table in the most simple cases.\n var onlyDfltScript = (gsub.scripts.length === 1 && gsub.scripts[0].tag === 'DFLT');\n check.assert(onlyDfltScript, 'Unable to write: GSUB table must contain only the DFLT script.');\n var dfltScript = gsub.scripts[0].script;\n var onlyDfltLang = (dfltScript.defaultLangSys && dfltScript.langSysRecords.length === 0);\n check.assert(onlyDfltLang, 'Unable to write: GSUB table must contain only the default language system.');\n\n for (var i = 0; i < gsub.lookups.length; i++) {\n var lookup = gsub.lookups[i];\n var canWriteLookup = (lookup.lookupType === 4);\n check.assert(canWriteLookup, 'Unable to write: GSUB table must contain only type 4 lookup tables');\n }\n\n var scriptList = new table.Table('scriptList', [\n {name: 'scriptCount', type: 'USHORT', value: 1},\n {name: 'scriptTag_0', type: 'TAG', value: 'DFLT'},\n {name: 'script_0', type: 'TABLE', value: new table.Table('scriptTable', [\n {name: 'defaultLangSys', type: 'TABLE', value: new table.Table('langSysTable', [\n {name: 'lookupOrder', type: 'USHORT', value: 0},\n {name: 'reqFeatureIndex', type: 'USHORT', value: 0xffff},\n {name: 'featureCount', type: 'USHORT', value: gsub.features.length},\n {name: 'featureIndex_0', type: 'USHORT', value: 0}\n ])},\n {name: 'langSysCount', type: 'USHORT', value: 0}\n ])},\n ]);\n\n var featureList = new table.FeatureList(gsub.features);\n var lookupList = new table.LookupList(gsub.lookups, subtableMakers);\n\n var gsubTable = new table.Table('GSUB', [\n {name: 'version', type: 'ULONG', value: 0x10000},\n {name: 'scripts', type: 'TABLE', value: scriptList},\n {name: 'features', type: 'TABLE', value: featureList},\n {name: 'lookups', type: 'TABLE', value: lookupList}\n ]);\n\n return gsubTable;\n}\n\nexports.parse = parseGsubTable;\nexports.make = makeGsubTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/gsub.js\n ** module id = 25\n ** module chunks = 0\n **/","// The Substitution object provides utility methods to manipulate\n// the GSUB substitution table.\n\n'use strict';\n\nvar check = require('./check');\nvar Layout = require('./layout');\n\nvar Substitution = function(font) {\n this.font = font;\n};\n\n// Check if 2 arrays of primitives are equal.\nfunction arraysEqual(ar1, ar2) {\n var n = ar1.length;\n if (n !== ar2.length) { return false; }\n for (var i = 0; i < n; i++) {\n if (ar1[i] !== ar2[i]) { return false; }\n }\n return true;\n}\n\nSubstitution.prototype = Layout;\n\n// Get or create the GSUB table.\nSubstitution.prototype.getGsubTable = function(create) {\n var gsub = this.font.tables.gsub;\n if (!gsub && create) {\n // Generate a default empty GSUB table with just a DFLT script and dflt lang sys.\n this.font.tables.gsub = gsub = {\n version: 1,\n scripts: [{\n tag: 'DFLT',\n script: {\n defaultLangSys: { reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: [] },\n langSysRecords: []\n }\n }],\n features: [],\n lookups: []\n };\n }\n return gsub;\n};\n\n/**\n * List all ligatures (lookup type 4) for a given script, language, and feature.\n * The result is an array of ligature objects like { sub: [ids], by: id }\n * @param {string} script\n * @param {string} language\n * @param {string} feature - 4-letter feature name (liga, rlig, dlig...)\n */\nSubstitution.prototype.getLigatures = function(script, language, feature) {\n var lookupTable = this.getLookupTable(script, language, feature, 4);\n if (!lookupTable) { return []; }\n var subtable = lookupTable.subtables[0];\n if (!subtable) { return []; }\n var glyphs = this.expandCoverage(subtable.coverage);\n var ligatureSets = subtable.ligatureSets;\n var ligatures = [];\n for (var i = 0; i < glyphs.length; i++) {\n var startGlyph = glyphs[i];\n var ligSet = ligatureSets[i];\n for (var j = 0; j < ligSet.length; j++) {\n var lig = ligSet[j];\n ligatures.push({\n sub: [startGlyph].concat(lig.components),\n by: lig.ligGlyph\n });\n }\n }\n return ligatures;\n};\n\n/**\n * Add a ligature (lookup type 4)\n * Ligatures with more components must be stored ahead of those with fewer components in order to be found\n * @param {string} [script='DFLT']\n * @param {string} [language='DFLT']\n * @param {object} ligature - { sub: [ids], by: id }\n */\nSubstitution.prototype.addLigature = function(script, language, feature, ligature) {\n var lookupTable = this.getLookupTable(script, language, feature, 4, true);\n var subtable = lookupTable.subtables[0];\n if (!subtable) {\n subtable = { // lookup type 4 subtable, format 1, coverage format 1\n substFormat: 1,\n coverage: { format: 1, glyphs: [] },\n ligatureSets: []\n };\n lookupTable.subtables[0] = subtable;\n }\n check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format);\n var coverageGlyph = ligature.sub[0];\n var ligComponents = ligature.sub.slice(1);\n var ligatureTable = {\n ligGlyph: ligature.by,\n components: ligComponents\n };\n var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);\n if (pos >= 0) {\n // ligatureSet already exists\n var ligatureSet = subtable.ligatureSets[pos];\n for (var i = 0; i < ligatureSet.length; i++) {\n // If ligature already exists, return.\n if (arraysEqual(ligatureSet[i].components, ligComponents)) {\n return;\n }\n }\n // ligature does not exist: add it.\n ligatureSet.push(ligatureTable);\n } else {\n // Create a new ligatureSet and add coverage for the first glyph.\n pos = -1 - pos;\n subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);\n subtable.ligatureSets.splice(pos, 0, [ligatureTable]);\n }\n};\n\n/**\n * List all feature data for a given script and language.\n * @param {string} [script='DFLT']\n * @param {string} [language='DFLT']\n * @param {string} feature - 4-letter feature name\n */\nSubstitution.prototype.getFeature = function(script, language, feature) {\n if (arguments.length === 1) {\n feature = arguments[0];\n script = language = 'DFLT';\n }\n switch (feature) {\n case 'dlig':\n case 'liga':\n case 'rlig': return this.getLigatures(script, language, feature);\n }\n};\n\n/**\n * Add a substitution to a feature for a given script and language.\n * The result is an array of ligature objects like { sub: [ids], by: id }\n * @param {string} [script='DFLT']\n * @param {string} [language='DFLT']\n * @param {string} feature - 4-letter feature name\n * @param {object} sub - the substitution to add\n */\nSubstitution.prototype.add = function(script, language, feature, sub) {\n if (arguments.length === 2) {\n feature = arguments[0];\n sub = arguments[1];\n script = language = 'DFLT';\n }\n switch (feature) {\n case 'dlig':\n case 'liga':\n case 'rlig': return this.addLigature(script, language, feature, sub);\n }\n};\n\nmodule.exports = Substitution;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/substitution.js\n ** module id = 26\n ** module chunks = 0\n **/","// The Layout object is the prototype of Substition objects, and provides utility methods to manipulate\n// common layout tables (GPOS, GSUB, GDEF...)\n\n'use strict';\n\nfunction searchTag(arr, tag) {\n /* jshint bitwise: false */\n var imin = 0;\n var imax = arr.length - 1;\n while (imin <= imax) {\n var imid = (imin + imax) >>> 1;\n var val = arr[imid].tag;\n if (val === tag) {\n return imid;\n } else if (val < tag) {\n imin = imid + 1;\n } else { imax = imid - 1; }\n }\n // Not found: return -1-insertion point\n return -imin - 1;\n}\n\nfunction binSearch(arr, value) {\n /* jshint bitwise: false */\n var imin = 0;\n var imax = arr.length - 1;\n while (imin <= imax) {\n var imid = (imin + imax) >>> 1;\n var val = arr[imid];\n if (val === value) {\n return imid;\n } else if (val < value) {\n imin = imid + 1;\n } else { imax = imid - 1; }\n }\n // Not found: return -1-insertion point\n return -imin - 1;\n}\n\nvar Layout = {\n // Binary search an object by \"tag\" property\n searchTag: searchTag,\n\n // Binary search in a list of numbers\n binSearch: binSearch,\n\n // Returns all scripts in the substitution table.\n getScriptNames: function() {\n var gsub = this.getGsubTable();\n if (!gsub) { return []; }\n return gsub.scripts.map(function(script) {\n return script.tag;\n });\n },\n\n /**\n * Returns all LangSysRecords in the given script.\n * @param {string} script - Use 'DFLT' for default script\n * @param {boolean} create - forces the creation of this script table if it doesn't exist.\n */\n getScriptTable: function(script, create) {\n var gsub = this.getGsubTable(create);\n if (gsub) {\n var scripts = gsub.scripts;\n var pos = searchTag(gsub.scripts, script);\n if (pos >= 0) {\n return scripts[pos].script;\n } else {\n var scr = {\n tag: script,\n script: {\n defaultLangSys: { reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: [] },\n langSysRecords: []\n }\n };\n scripts.splice(-1 - pos, 0, scr.script);\n return scr;\n }\n }\n },\n\n /**\n * Returns a language system table\n * @param {string} script - Use 'DFLT' for default script\n * @param {string} language - Use 'DFLT' for default language\n * @param {boolean} create - forces the creation of this langSysTable if it doesn't exist.\n */\n getLangSysTable: function(script, language, create) {\n var scriptTable = this.getScriptTable(script, create);\n if (scriptTable) {\n if (language === 'DFLT') {\n return scriptTable.defaultLangSys;\n }\n var pos = searchTag(scriptTable.langSysRecords, language);\n if (pos >= 0) {\n return scriptTable.langSysRecords[pos].langSys;\n } else if (create) {\n var langSysRecord = {\n tag: language,\n langSys: { reserved: 0, reqFeatureIndex: 0xffff, featureIndexes: [] }\n };\n scriptTable.langSysRecords.splice(-1 - pos, 0, langSysRecord);\n return langSysRecord.langSys;\n }\n }\n },\n\n /**\n * Get a specific feature table.\n *\n * @param {string} script - Use 'DFLT' for default script\n * @param {string} language - Use 'DFLT' for default language\n * @param {string} feature - One of the codes listed at https://www.microsoft.com/typography/OTSPEC/featurelist.htm\n * @param {boolean} create - forces the creation of the feature table if it doesn't exist.\n */\n getFeatureTable: function(script, language, feature, create) {\n var langSysTable = this.getLangSysTable(script, language, create);\n if (langSysTable) {\n var featureRecord;\n var featIndexes = langSysTable.featureIndexes;\n var allFeatures = this.font.tables.gsub.features;\n // The FeatureIndex array of indices is in arbitrary order,\n // even if allFeatures is sorted alphabetically by feature tag.\n for (var i = 0; i < featIndexes.length; i++) {\n featureRecord = allFeatures[featIndexes[i]];\n if (featureRecord.tag === feature) {\n return featureRecord.feature;\n }\n }\n if (create) {\n featureRecord = {\n tag: feature,\n feature: { params: 0, lookupListIndexes: [] }\n };\n var index = allFeatures.length;\n allFeatures.push(featureRecord);\n featIndexes.push(index);\n return featureRecord.feature;\n }\n }\n },\n\n /**\n * Get the first lookup table of a given type for a script/language/feature.\n * @param {string} script - Use 'DFLT' for default script\n * @param {string} language - Use 'DFLT' for default language\n * @param {string} feature - 4-letter feature code\n * @param {number} lookupType - 1 to 8\n * @param {boolean} create - forces the creation of the lookup table if it doesn't exist, with no subtables.\n */\n getLookupTable: function(script, language, feature, lookupType, create) {\n var featureTable = this.getFeatureTable(script, language, feature, create);\n if (featureTable) {\n var lookupTable;\n var lookupListIndexes = featureTable.lookupListIndexes;\n var allLookups = this.font.tables.gsub.lookups;\n // lookupListIndexes are in no particular order, so use naïve search.\n for (var i = 0; i < lookupListIndexes.length; i++) {\n lookupTable = allLookups[lookupListIndexes[i]];\n if (lookupTable.lookupType === lookupType) {\n return lookupTable;\n }\n }\n if (create) {\n lookupTable = {\n lookupType: lookupType,\n lookupFlag: 0,\n subtables: [],\n markFilteringSet: undefined\n };\n var index = allLookups.length;\n allLookups.push(lookupTable);\n lookupListIndexes.push(index);\n return lookupTable;\n }\n }\n },\n\n /**\n * Returns the list of glyph indexes of a coverage table.\n * Format 1: the list is stored raw\n * Format 2: compact list as range records.\n */\n expandCoverage: function(coverageTable) {\n if (coverageTable.format === 1) {\n return coverageTable.glyphs;\n } else {\n var glyphs = [];\n var ranges = coverageTable.ranges;\n for (var i = 0; i < ranges; i++) {\n var range = ranges[i];\n var start = range.start;\n var end = range.end;\n for (var j = start; j <= end; j++) {\n glyphs.push(j);\n }\n }\n return glyphs;\n }\n }\n\n};\n\nmodule.exports = Layout;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/layout.js\n ** module id = 27\n ** module chunks = 0\n **/","'use strict';\n\nexports.isBrowser = function() {\n return typeof window !== 'undefined';\n};\n\nexports.isNode = function() {\n return typeof window === 'undefined';\n};\n\nexports.nodeBufferToArrayBuffer = function(buffer) {\n var ab = new ArrayBuffer(buffer.length);\n var view = new Uint8Array(ab);\n for (var i = 0; i < buffer.length; ++i) {\n view[i] = buffer[i];\n }\n\n return ab;\n};\n\nexports.arrayBufferToNodeBuffer = function(ab) {\n var buffer = new Buffer(ab.byteLength);\n var view = new Uint8Array(ab);\n for (var i = 0; i < buffer.length; ++i) {\n buffer[i] = view[i];\n }\n\n return buffer;\n};\n\nexports.checkArgument = function(expression, message) {\n if (!expression) {\n throw message;\n }\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/util.js\n ** module id = 28\n ** module chunks = 0\n **/","/* (ignored) */\n\n\n/*****************\n ** WEBPACK FOOTER\n ** fs (ignored)\n ** module id = 29\n ** module chunks = 0\n **/","// The `fvar` table stores font variation axes and instances.\n// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fvar.html\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\nvar table = require('../table');\n\nfunction addName(name, names) {\n var nameString = JSON.stringify(name);\n var nameID = 256;\n for (var nameKey in names) {\n var n = parseInt(nameKey);\n if (!n || n < 256) {\n continue;\n }\n\n if (JSON.stringify(names[nameKey]) === nameString) {\n return n;\n }\n\n if (nameID <= n) {\n nameID = n + 1;\n }\n }\n\n names[nameID] = name;\n return nameID;\n}\n\nfunction makeFvarAxis(n, axis, names) {\n var nameID = addName(axis.name, names);\n return [\n {name: 'tag_' + n, type: 'TAG', value: axis.tag},\n {name: 'minValue_' + n, type: 'FIXED', value: axis.minValue << 16},\n {name: 'defaultValue_' + n, type: 'FIXED', value: axis.defaultValue << 16},\n {name: 'maxValue_' + n, type: 'FIXED', value: axis.maxValue << 16},\n {name: 'flags_' + n, type: 'USHORT', value: 0},\n {name: 'nameID_' + n, type: 'USHORT', value: nameID}\n ];\n}\n\nfunction parseFvarAxis(data, start, names) {\n var axis = {};\n var p = new parse.Parser(data, start);\n axis.tag = p.parseTag();\n axis.minValue = p.parseFixed();\n axis.defaultValue = p.parseFixed();\n axis.maxValue = p.parseFixed();\n p.skip('uShort', 1); // reserved for flags; no values defined\n axis.name = names[p.parseUShort()] || {};\n return axis;\n}\n\nfunction makeFvarInstance(n, inst, axes, names) {\n var nameID = addName(inst.name, names);\n var fields = [\n {name: 'nameID_' + n, type: 'USHORT', value: nameID},\n {name: 'flags_' + n, type: 'USHORT', value: 0}\n ];\n\n for (var i = 0; i < axes.length; ++i) {\n var axisTag = axes[i].tag;\n fields.push({\n name: 'axis_' + n + ' ' + axisTag,\n type: 'FIXED',\n value: inst.coordinates[axisTag] << 16\n });\n }\n\n return fields;\n}\n\nfunction parseFvarInstance(data, start, axes, names) {\n var inst = {};\n var p = new parse.Parser(data, start);\n inst.name = names[p.parseUShort()] || {};\n p.skip('uShort', 1); // reserved for flags; no values defined\n\n inst.coordinates = {};\n for (var i = 0; i < axes.length; ++i) {\n inst.coordinates[axes[i].tag] = p.parseFixed();\n }\n\n return inst;\n}\n\nfunction makeFvarTable(fvar, names) {\n var result = new table.Table('fvar', [\n {name: 'version', type: 'ULONG', value: 0x10000},\n {name: 'offsetToData', type: 'USHORT', value: 0},\n {name: 'countSizePairs', type: 'USHORT', value: 2},\n {name: 'axisCount', type: 'USHORT', value: fvar.axes.length},\n {name: 'axisSize', type: 'USHORT', value: 20},\n {name: 'instanceCount', type: 'USHORT', value: fvar.instances.length},\n {name: 'instanceSize', type: 'USHORT', value: 4 + fvar.axes.length * 4}\n ]);\n result.offsetToData = result.sizeOf();\n\n for (var i = 0; i < fvar.axes.length; i++) {\n result.fields = result.fields.concat(makeFvarAxis(i, fvar.axes[i], names));\n }\n\n for (var j = 0; j < fvar.instances.length; j++) {\n result.fields = result.fields.concat(makeFvarInstance(j, fvar.instances[j], fvar.axes, names));\n }\n\n return result;\n}\n\nfunction parseFvarTable(data, start, names) {\n var p = new parse.Parser(data, start);\n var tableVersion = p.parseULong();\n check.argument(tableVersion === 0x00010000, 'Unsupported fvar table version.');\n var offsetToData = p.parseOffset16();\n // Skip countSizePairs.\n p.skip('uShort', 1);\n var axisCount = p.parseUShort();\n var axisSize = p.parseUShort();\n var instanceCount = p.parseUShort();\n var instanceSize = p.parseUShort();\n\n var axes = [];\n for (var i = 0; i < axisCount; i++) {\n axes.push(parseFvarAxis(data, start + offsetToData + i * axisSize, names));\n }\n\n var instances = [];\n var instanceStart = start + offsetToData + axisCount * axisSize;\n for (var j = 0; j < instanceCount; j++) {\n instances.push(parseFvarInstance(data, instanceStart + j * instanceSize, axes, names));\n }\n\n return {axes: axes, instances: instances};\n}\n\nexports.make = makeFvarTable;\nexports.parse = parseFvarTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/fvar.js\n ** module id = 30\n ** module chunks = 0\n **/","// The `glyf` table describes the glyphs in TrueType outline format.\n// http://www.microsoft.com/typography/otspec/glyf.htm\n\n'use strict';\n\nvar check = require('../check');\nvar glyphset = require('../glyphset');\nvar parse = require('../parse');\nvar path = require('../path');\n\n// Parse the coordinate data for a glyph.\nfunction parseGlyphCoordinate(p, flag, previousValue, shortVectorBitMask, sameBitMask) {\n var v;\n if ((flag & shortVectorBitMask) > 0) {\n // The coordinate is 1 byte long.\n v = p.parseByte();\n // The `same` bit is re-used for short values to signify the sign of the value.\n if ((flag & sameBitMask) === 0) {\n v = -v;\n }\n\n v = previousValue + v;\n } else {\n // The coordinate is 2 bytes long.\n // If the `same` bit is set, the coordinate is the same as the previous coordinate.\n if ((flag & sameBitMask) > 0) {\n v = previousValue;\n } else {\n // Parse the coordinate as a signed 16-bit delta value.\n v = previousValue + p.parseShort();\n }\n }\n\n return v;\n}\n\n// Parse a TrueType glyph.\nfunction parseGlyph(glyph, data, start) {\n var p = new parse.Parser(data, start);\n glyph.numberOfContours = p.parseShort();\n glyph._xMin = p.parseShort();\n glyph._yMin = p.parseShort();\n glyph._xMax = p.parseShort();\n glyph._yMax = p.parseShort();\n var flags;\n var flag;\n if (glyph.numberOfContours > 0) {\n var i;\n // This glyph is not a composite.\n var endPointIndices = glyph.endPointIndices = [];\n for (i = 0; i < glyph.numberOfContours; i += 1) {\n endPointIndices.push(p.parseUShort());\n }\n\n glyph.instructionLength = p.parseUShort();\n glyph.instructions = [];\n for (i = 0; i < glyph.instructionLength; i += 1) {\n glyph.instructions.push(p.parseByte());\n }\n\n var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;\n flags = [];\n for (i = 0; i < numberOfCoordinates; i += 1) {\n flag = p.parseByte();\n flags.push(flag);\n // If bit 3 is set, we repeat this flag n times, where n is the next byte.\n if ((flag & 8) > 0) {\n var repeatCount = p.parseByte();\n for (var j = 0; j < repeatCount; j += 1) {\n flags.push(flag);\n i += 1;\n }\n }\n }\n\n check.argument(flags.length === numberOfCoordinates, 'Bad flags.');\n\n if (endPointIndices.length > 0) {\n var points = [];\n var point;\n // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.\n if (numberOfCoordinates > 0) {\n for (i = 0; i < numberOfCoordinates; i += 1) {\n flag = flags[i];\n point = {};\n point.onCurve = !!(flag & 1);\n point.lastPointOfContour = endPointIndices.indexOf(i) >= 0;\n points.push(point);\n }\n\n var px = 0;\n for (i = 0; i < numberOfCoordinates; i += 1) {\n flag = flags[i];\n point = points[i];\n point.x = parseGlyphCoordinate(p, flag, px, 2, 16);\n px = point.x;\n }\n\n var py = 0;\n for (i = 0; i < numberOfCoordinates; i += 1) {\n flag = flags[i];\n point = points[i];\n point.y = parseGlyphCoordinate(p, flag, py, 4, 32);\n py = point.y;\n }\n }\n\n glyph.points = points;\n } else {\n glyph.points = [];\n }\n } else if (glyph.numberOfContours === 0) {\n glyph.points = [];\n } else {\n glyph.isComposite = true;\n glyph.points = [];\n glyph.components = [];\n var moreComponents = true;\n while (moreComponents) {\n flags = p.parseUShort();\n var component = {\n glyphIndex: p.parseUShort(),\n xScale: 1,\n scale01: 0,\n scale10: 0,\n yScale: 1,\n dx: 0,\n dy: 0\n };\n if ((flags & 1) > 0) {\n // The arguments are words\n component.dx = p.parseShort();\n component.dy = p.parseShort();\n } else {\n // The arguments are bytes\n component.dx = p.parseChar();\n component.dy = p.parseChar();\n }\n\n if ((flags & 8) > 0) {\n // We have a scale\n component.xScale = component.yScale = p.parseF2Dot14();\n } else if ((flags & 64) > 0) {\n // We have an X / Y scale\n component.xScale = p.parseF2Dot14();\n component.yScale = p.parseF2Dot14();\n } else if ((flags & 128) > 0) {\n // We have a 2x2 transformation\n component.xScale = p.parseF2Dot14();\n component.scale01 = p.parseF2Dot14();\n component.scale10 = p.parseF2Dot14();\n component.yScale = p.parseF2Dot14();\n }\n\n glyph.components.push(component);\n moreComponents = !!(flags & 32);\n }\n }\n}\n\n// Transform an array of points and return a new array.\nfunction transformPoints(points, transform) {\n var newPoints = [];\n for (var i = 0; i < points.length; i += 1) {\n var pt = points[i];\n var newPt = {\n x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,\n y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,\n onCurve: pt.onCurve,\n lastPointOfContour: pt.lastPointOfContour\n };\n newPoints.push(newPt);\n }\n\n return newPoints;\n}\n\nfunction getContours(points) {\n var contours = [];\n var currentContour = [];\n for (var i = 0; i < points.length; i += 1) {\n var pt = points[i];\n currentContour.push(pt);\n if (pt.lastPointOfContour) {\n contours.push(currentContour);\n currentContour = [];\n }\n }\n\n check.argument(currentContour.length === 0, 'There are still points left in the current contour.');\n return contours;\n}\n\n// Convert the TrueType glyph outline to a Path.\nfunction getPath(points) {\n var p = new path.Path();\n if (!points) {\n return p;\n }\n\n var contours = getContours(points);\n for (var i = 0; i < contours.length; i += 1) {\n var contour = contours[i];\n var firstPt = contour[0];\n var lastPt = contour[contour.length - 1];\n var curvePt;\n var realFirstPoint;\n if (firstPt.onCurve) {\n curvePt = null;\n // The first point will be consumed by the moveTo command,\n // so skip it in the loop.\n realFirstPoint = true;\n } else {\n if (lastPt.onCurve) {\n // If the first point is off-curve and the last point is on-curve,\n // start at the last point.\n firstPt = lastPt;\n } else {\n // If both first and last points are off-curve, start at their middle.\n firstPt = { x: (firstPt.x + lastPt.x) / 2, y: (firstPt.y + lastPt.y) / 2 };\n }\n\n curvePt = firstPt;\n // The first point is synthesized, so don't skip the real first point.\n realFirstPoint = false;\n }\n\n p.moveTo(firstPt.x, firstPt.y);\n\n for (var j = realFirstPoint ? 1 : 0; j < contour.length; j += 1) {\n var pt = contour[j];\n var prevPt = j === 0 ? firstPt : contour[j - 1];\n if (prevPt.onCurve && pt.onCurve) {\n // This is a straight line.\n p.lineTo(pt.x, pt.y);\n } else if (prevPt.onCurve && !pt.onCurve) {\n curvePt = pt;\n } else if (!prevPt.onCurve && !pt.onCurve) {\n var midPt = { x: (prevPt.x + pt.x) / 2, y: (prevPt.y + pt.y) / 2 };\n p.quadraticCurveTo(prevPt.x, prevPt.y, midPt.x, midPt.y);\n curvePt = pt;\n } else if (!prevPt.onCurve && pt.onCurve) {\n // Previous point off-curve, this point on-curve.\n p.quadraticCurveTo(curvePt.x, curvePt.y, pt.x, pt.y);\n curvePt = null;\n } else {\n throw new Error('Invalid state.');\n }\n }\n\n if (firstPt !== lastPt) {\n // Connect the last and first points\n if (curvePt) {\n p.quadraticCurveTo(curvePt.x, curvePt.y, firstPt.x, firstPt.y);\n } else {\n p.lineTo(firstPt.x, firstPt.y);\n }\n }\n }\n\n p.closePath();\n return p;\n}\n\nfunction buildPath(glyphs, glyph) {\n if (glyph.isComposite) {\n for (var j = 0; j < glyph.components.length; j += 1) {\n var component = glyph.components[j];\n var componentGlyph = glyphs.get(component.glyphIndex);\n // Force the ttfGlyphLoader to parse the glyph.\n componentGlyph.getPath();\n if (componentGlyph.points) {\n var transformedPoints = transformPoints(componentGlyph.points, component);\n glyph.points = glyph.points.concat(transformedPoints);\n }\n }\n }\n\n return getPath(glyph.points);\n}\n\n// Parse all the glyphs according to the offsets from the `loca` table.\nfunction parseGlyfTable(data, start, loca, font) {\n var glyphs = new glyphset.GlyphSet(font);\n var i;\n\n // The last element of the loca table is invalid.\n for (i = 0; i < loca.length - 1; i += 1) {\n var offset = loca[i];\n var nextOffset = loca[i + 1];\n if (offset !== nextOffset) {\n glyphs.push(i, glyphset.ttfGlyphLoader(font, i, parseGlyph, data, start + offset, buildPath));\n } else {\n glyphs.push(i, glyphset.glyphLoader(font, i));\n }\n }\n\n return glyphs;\n}\n\nexports.parse = parseGlyfTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/glyf.js\n ** module id = 31\n ** module chunks = 0\n **/","// The `GPOS` table contains kerning pairs, among other things.\n// https://www.microsoft.com/typography/OTSPEC/gpos.htm\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\n\n// Parse ScriptList and FeatureList tables of GPOS, GSUB, GDEF, BASE, JSTF tables.\n// These lists are unused by now, this function is just the basis for a real parsing.\nfunction parseTaggedListTable(data, start) {\n var p = new parse.Parser(data, start);\n var n = p.parseUShort();\n var list = [];\n for (var i = 0; i < n; i++) {\n list[p.parseTag()] = { offset: p.parseUShort() };\n }\n\n return list;\n}\n\n// Parse a coverage table in a GSUB, GPOS or GDEF table.\n// Format 1 is a simple list of glyph ids,\n// Format 2 is a list of ranges. It is expanded in a list of glyphs, maybe not the best idea.\nfunction parseCoverageTable(data, start) {\n var p = new parse.Parser(data, start);\n var format = p.parseUShort();\n var count = p.parseUShort();\n if (format === 1) {\n return p.parseUShortList(count);\n } else if (format === 2) {\n var coverage = [];\n for (; count--;) {\n var begin = p.parseUShort();\n var end = p.parseUShort();\n var index = p.parseUShort();\n for (var i = begin; i <= end; i++) {\n coverage[index++] = i;\n }\n }\n\n return coverage;\n }\n}\n\n// Parse a Class Definition Table in a GSUB, GPOS or GDEF table.\n// Returns a function that gets a class value from a glyph ID.\nfunction parseClassDefTable(data, start) {\n var p = new parse.Parser(data, start);\n var format = p.parseUShort();\n if (format === 1) {\n // Format 1 specifies a range of consecutive glyph indices, one class per glyph ID.\n var startGlyph = p.parseUShort();\n var glyphCount = p.parseUShort();\n var classes = p.parseUShortList(glyphCount);\n return function(glyphID) {\n return classes[glyphID - startGlyph] || 0;\n };\n } else if (format === 2) {\n // Format 2 defines multiple groups of glyph indices that belong to the same class.\n var rangeCount = p.parseUShort();\n var startGlyphs = [];\n var endGlyphs = [];\n var classValues = [];\n for (var i = 0; i < rangeCount; i++) {\n startGlyphs[i] = p.parseUShort();\n endGlyphs[i] = p.parseUShort();\n classValues[i] = p.parseUShort();\n }\n\n return function(glyphID) {\n var l = 0;\n var r = startGlyphs.length - 1;\n while (l < r) {\n var c = (l + r + 1) >> 1;\n if (glyphID < startGlyphs[c]) {\n r = c - 1;\n } else {\n l = c;\n }\n }\n\n if (startGlyphs[l] <= glyphID && glyphID <= endGlyphs[l]) {\n return classValues[l] || 0;\n }\n\n return 0;\n };\n }\n}\n\n// Parse a pair adjustment positioning subtable, format 1 or format 2\n// The subtable is returned in the form of a lookup function.\nfunction parsePairPosSubTable(data, start) {\n var p = new parse.Parser(data, start);\n // This part is common to format 1 and format 2 subtables\n var format = p.parseUShort();\n var coverageOffset = p.parseUShort();\n var coverage = parseCoverageTable(data, start + coverageOffset);\n // valueFormat 4: XAdvance only, 1: XPlacement only, 0: no ValueRecord for second glyph\n // Only valueFormat1=4 and valueFormat2=0 is supported.\n var valueFormat1 = p.parseUShort();\n var valueFormat2 = p.parseUShort();\n var value1;\n var value2;\n if (valueFormat1 !== 4 || valueFormat2 !== 0) return;\n var sharedPairSets = {};\n if (format === 1) {\n // Pair Positioning Adjustment: Format 1\n var pairSetCount = p.parseUShort();\n var pairSet = [];\n // Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index\n var pairSetOffsets = p.parseOffset16List(pairSetCount);\n for (var firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) {\n var pairSetOffset = pairSetOffsets[firstGlyph];\n var sharedPairSet = sharedPairSets[pairSetOffset];\n if (!sharedPairSet) {\n // Parse a pairset table in a pair adjustment subtable format 1\n sharedPairSet = {};\n p.relativeOffset = pairSetOffset;\n var pairValueCount = p.parseUShort();\n for (; pairValueCount--;) {\n var secondGlyph = p.parseUShort();\n if (valueFormat1) value1 = p.parseShort();\n if (valueFormat2) value2 = p.parseShort();\n // We only support valueFormat1 = 4 and valueFormat2 = 0,\n // so value1 is the XAdvance and value2 is empty.\n sharedPairSet[secondGlyph] = value1;\n }\n }\n\n pairSet[coverage[firstGlyph]] = sharedPairSet;\n }\n\n return function(leftGlyph, rightGlyph) {\n var pairs = pairSet[leftGlyph];\n if (pairs) return pairs[rightGlyph];\n };\n } else if (format === 2) {\n // Pair Positioning Adjustment: Format 2\n var classDef1Offset = p.parseUShort();\n var classDef2Offset = p.parseUShort();\n var class1Count = p.parseUShort();\n var class2Count = p.parseUShort();\n var getClass1 = parseClassDefTable(data, start + classDef1Offset);\n var getClass2 = parseClassDefTable(data, start + classDef2Offset);\n\n // Parse kerning values by class pair.\n var kerningMatrix = [];\n for (var i = 0; i < class1Count; i++) {\n var kerningRow = kerningMatrix[i] = [];\n for (var j = 0; j < class2Count; j++) {\n if (valueFormat1) value1 = p.parseShort();\n if (valueFormat2) value2 = p.parseShort();\n // We only support valueFormat1 = 4 and valueFormat2 = 0,\n // so value1 is the XAdvance and value2 is empty.\n kerningRow[j] = value1;\n }\n }\n\n // Convert coverage list to a hash\n var covered = {};\n for (i = 0; i < coverage.length; i++) covered[coverage[i]] = 1;\n\n // Get the kerning value for a specific glyph pair.\n return function(leftGlyph, rightGlyph) {\n if (!covered[leftGlyph]) return;\n var class1 = getClass1(leftGlyph);\n var class2 = getClass2(rightGlyph);\n var kerningRow = kerningMatrix[class1];\n\n if (kerningRow) {\n return kerningRow[class2];\n }\n };\n }\n}\n\n// Parse a LookupTable (present in of GPOS, GSUB, GDEF, BASE, JSTF tables).\nfunction parseLookupTable(data, start) {\n var p = new parse.Parser(data, start);\n var lookupType = p.parseUShort();\n var lookupFlag = p.parseUShort();\n var useMarkFilteringSet = lookupFlag & 0x10;\n var subTableCount = p.parseUShort();\n var subTableOffsets = p.parseOffset16List(subTableCount);\n var table = {\n lookupType: lookupType,\n lookupFlag: lookupFlag,\n markFilteringSet: useMarkFilteringSet ? p.parseUShort() : -1\n };\n // LookupType 2, Pair adjustment\n if (lookupType === 2) {\n var subtables = [];\n for (var i = 0; i < subTableCount; i++) {\n subtables.push(parsePairPosSubTable(data, start + subTableOffsets[i]));\n }\n // Return a function which finds the kerning values in the subtables.\n table.getKerningValue = function(leftGlyph, rightGlyph) {\n for (var i = subtables.length; i--;) {\n var value = subtables[i](leftGlyph, rightGlyph);\n if (value !== undefined) return value;\n }\n\n return 0;\n };\n }\n\n return table;\n}\n\n// Parse the `GPOS` table which contains, among other things, kerning pairs.\n// https://www.microsoft.com/typography/OTSPEC/gpos.htm\nfunction parseGposTable(data, start, font) {\n var p = new parse.Parser(data, start);\n var tableVersion = p.parseFixed();\n check.argument(tableVersion === 1, 'Unsupported GPOS table version.');\n\n // ScriptList and FeatureList - ignored for now\n parseTaggedListTable(data, start + p.parseUShort());\n // 'kern' is the feature we are looking for.\n parseTaggedListTable(data, start + p.parseUShort());\n\n // LookupList\n var lookupListOffset = p.parseUShort();\n p.relativeOffset = lookupListOffset;\n var lookupCount = p.parseUShort();\n var lookupTableOffsets = p.parseOffset16List(lookupCount);\n var lookupListAbsoluteOffset = start + lookupListOffset;\n for (var i = 0; i < lookupCount; i++) {\n var table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]);\n if (table.lookupType === 2 && !font.getGposKerningValue) font.getGposKerningValue = table.getKerningValue;\n }\n}\n\nexports.parse = parseGposTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/gpos.js\n ** module id = 32\n ** module chunks = 0\n **/","// The `kern` table contains kerning pairs.\n// Note that some fonts use the GPOS OpenType layout table to specify kerning.\n// https://www.microsoft.com/typography/OTSPEC/kern.htm\n\n'use strict';\n\nvar check = require('../check');\nvar parse = require('../parse');\n\n// Parse the `kern` table which contains kerning pairs.\nfunction parseKernTable(data, start) {\n var pairs = {};\n var p = new parse.Parser(data, start);\n var tableVersion = p.parseUShort();\n check.argument(tableVersion === 0, 'Unsupported kern table version.');\n // Skip nTables.\n p.skip('uShort', 1);\n var subTableVersion = p.parseUShort();\n check.argument(subTableVersion === 0, 'Unsupported kern sub-table version.');\n // Skip subTableLength, subTableCoverage\n p.skip('uShort', 2);\n var nPairs = p.parseUShort();\n // Skip searchRange, entrySelector, rangeShift.\n p.skip('uShort', 3);\n for (var i = 0; i < nPairs; i += 1) {\n var leftIndex = p.parseUShort();\n var rightIndex = p.parseUShort();\n var value = p.parseShort();\n pairs[leftIndex + ',' + rightIndex] = value;\n }\n\n return pairs;\n}\n\nexports.parse = parseKernTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/kern.js\n ** module id = 33\n ** module chunks = 0\n **/","// The `loca` table stores the offsets to the locations of the glyphs in the font.\n// https://www.microsoft.com/typography/OTSPEC/loca.htm\n\n'use strict';\n\nvar parse = require('../parse');\n\n// Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font,\n// relative to the beginning of the glyphData table.\n// The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs)\n// The loca table has two versions: a short version where offsets are stored as uShorts, and a long\n// version where offsets are stored as uLongs. The `head` table specifies which version to use\n// (under indexToLocFormat).\nfunction parseLocaTable(data, start, numGlyphs, shortVersion) {\n var p = new parse.Parser(data, start);\n var parseFn = shortVersion ? p.parseUShort : p.parseULong;\n // There is an extra entry after the last index element to compute the length of the last glyph.\n // That's why we use numGlyphs + 1.\n var glyphOffsets = [];\n for (var i = 0; i < numGlyphs + 1; i += 1) {\n var glyphOffset = parseFn.call(p);\n if (shortVersion) {\n // The short table version stores the actual offset divided by 2.\n glyphOffset *= 2;\n }\n\n glyphOffsets.push(glyphOffset);\n }\n\n return glyphOffsets;\n}\n\nexports.parse = parseLocaTable;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ../opentype.js/src/tables/loca.js\n ** module id = 34\n ** module chunks = 0\n **/","/*!\n * Paper.js v0.10.2-develop - The Swiss Army Knife of Vector Graphics Scripting.\n * http://paperjs.org/\n *\n * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey\n * http://scratchdisk.com/ & http://jonathanpuckey.com/\n *\n * Distributed under the MIT license. See LICENSE file for details.\n *\n * All rights reserved.\n *\n * Date: Tue Jul 26 10:25:32 2016 +0200\n *\n ***\n *\n * Straps.js - Class inheritance library with support for bean-style accessors\n *\n * Copyright (c) 2006 - 2016 Juerg Lehni\n * http://scratchdisk.com/\n *\n * Distributed under the MIT license.\n *\n ***\n *\n * Acorn.js\n * http://marijnhaverbeke.nl/acorn/\n *\n * Acorn is a tiny, fast JavaScript parser written in JavaScript,\n * created by Marijn Haverbeke and released under an MIT license.\n *\n */\n\nvar paper = function(self, undefined) {\n\nself = self || require('./node/window.js');\n\nvar window = self.window,\n\tdocument = self.document;\n\nvar Base = new function() {\n\tvar hidden = /^(statics|enumerable|beans|preserve)$/,\n\t\tarray = [],\n\t\tslice = array.slice,\n\t\tcreate = Object.create,\n\t\tdescribe = Object.getOwnPropertyDescriptor,\n\t\tdefine = Object.defineProperty,\n\n\t\tforEach = array.forEach || function(iter, bind) {\n\t\t\tfor (var i = 0, l = this.length; i < l; i++) {\n\t\t\t\titer.call(bind, this[i], i, this);\n\t\t\t}\n\t\t},\n\n\t\tforIn = function(iter, bind) {\n\t\t\tfor (var i in this) {\n\t\t\t\tif (this.hasOwnProperty(i))\n\t\t\t\t\titer.call(bind, this[i], i, this);\n\t\t\t}\n\t\t},\n\n\t\tset = Object.assign || function(dst) {\n\t\t\tfor (var i = 1, l = arguments.length; i < l; i++) {\n\t\t\t\tvar src = arguments[i];\n\t\t\t\tfor (var key in src) {\n\t\t\t\t\tif (src.hasOwnProperty(key))\n\t\t\t\t\t\tdst[key] = src[key];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn dst;\n\t\t},\n\n\t\teach = function(obj, iter, bind) {\n\t\t\tif (obj) {\n\t\t\t\tvar desc = describe(obj, 'length');\n\t\t\t\t(desc && typeof desc.value === 'number' ? forEach : forIn)\n\t\t\t\t\t.call(obj, iter, bind = bind || obj);\n\t\t\t}\n\t\t\treturn bind;\n\t\t};\n\n\tfunction inject(dest, src, enumerable, beans, preserve) {\n\t\tvar beansNames = {};\n\n\t\tfunction field(name, val) {\n\t\t\tval = val || (val = describe(src, name))\n\t\t\t\t\t&& (val.get ? val : val.value);\n\t\t\tif (typeof val === 'string' && val[0] === '#')\n\t\t\t\tval = dest[val.substring(1)] || val;\n\t\t\tvar isFunc = typeof val === 'function',\n\t\t\t\tres = val,\n\t\t\t\tprev = preserve || isFunc && !val.base\n\t\t\t\t\t\t? (val && val.get ? name in dest : dest[name])\n\t\t\t\t\t\t: null,\n\t\t\t\tbean;\n\t\t\tif (!preserve || !prev) {\n\t\t\t\tif (isFunc && prev)\n\t\t\t\t\tval.base = prev;\n\t\t\t\tif (isFunc && beans !== false\n\t\t\t\t\t\t&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))\n\t\t\t\t\tbeansNames[bean[3].toLowerCase() + bean[4]] = bean[2];\n\t\t\t\tif (!res || isFunc || !res.get || typeof res.get !== 'function'\n\t\t\t\t\t\t|| !Base.isPlainObject(res))\n\t\t\t\t\tres = { value: res, writable: true };\n\t\t\t\tif ((describe(dest, name)\n\t\t\t\t\t\t|| { configurable: true }).configurable) {\n\t\t\t\t\tres.configurable = true;\n\t\t\t\t\tres.enumerable = enumerable;\n\t\t\t\t}\n\t\t\t\tdefine(dest, name, res);\n\t\t\t}\n\t\t}\n\t\tif (src) {\n\t\t\tfor (var name in src) {\n\t\t\t\tif (src.hasOwnProperty(name) && !hidden.test(name))\n\t\t\t\t\tfield(name);\n\t\t\t}\n\t\t\tfor (var name in beansNames) {\n\t\t\t\tvar part = beansNames[name],\n\t\t\t\t\tset = dest['set' + part],\n\t\t\t\t\tget = dest['get' + part] || set && dest['is' + part];\n\t\t\t\tif (get && (beans === true || get.length === 0))\n\t\t\t\t\tfield(name, { get: get, set: set });\n\t\t\t}\n\t\t}\n\t\treturn dest;\n\t}\n\n\tfunction Base() {\n\t\tfor (var i = 0, l = arguments.length; i < l; i++) {\n\t\t\tvar src = arguments[i];\n\t\t\tif (src)\n\t\t\t\tset(this, src);\n\t\t}\n\t\treturn this;\n\t}\n\n\treturn inject(Base, {\n\t\tinject: function(src) {\n\t\t\tif (src) {\n\t\t\t\tvar statics = src.statics === true ? src : src.statics,\n\t\t\t\t\tbeans = src.beans,\n\t\t\t\t\tpreserve = src.preserve;\n\t\t\t\tif (statics !== src)\n\t\t\t\t\tinject(this.prototype, src, src.enumerable, beans, preserve);\n\t\t\t\tinject(this, statics, true, beans, preserve);\n\t\t\t}\n\t\t\tfor (var i = 1, l = arguments.length; i < l; i++)\n\t\t\t\tthis.inject(arguments[i]);\n\t\t\treturn this;\n\t\t},\n\n\t\textend: function() {\n\t\t\tvar base = this,\n\t\t\t\tctor,\n\t\t\t\tproto;\n\t\t\tfor (var i = 0, obj, l = arguments.length;\n\t\t\t\t\ti < l && !(ctor && proto); i++) {\n\t\t\t\tobj = arguments[i];\n\t\t\t\tctor = ctor || obj.initialize;\n\t\t\t\tproto = proto || obj.prototype;\n\t\t\t}\n\t\t\tctor = ctor || function() {\n\t\t\t\tbase.apply(this, arguments);\n\t\t\t};\n\t\t\tproto = ctor.prototype = proto || create(this.prototype);\n\t\t\tdefine(proto, 'constructor',\n\t\t\t\t\t{ value: ctor, writable: true, configurable: true });\n\t\t\tinject(ctor, this, true);\n\t\t\tif (arguments.length)\n\t\t\t\tthis.inject.apply(ctor, arguments);\n\t\t\tctor.base = base;\n\t\t\treturn ctor;\n\t\t}\n\t}, true).inject({\n\t\tinitialize: Base,\n\n\t\tset: Base,\n\n\t\tinject: function() {\n\t\t\tfor (var i = 0, l = arguments.length; i < l; i++) {\n\t\t\t\tvar src = arguments[i];\n\t\t\t\tif (src) {\n\t\t\t\t\tinject(this, src, src.enumerable, src.beans, src.preserve);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\textend: function() {\n\t\t\tvar res = create(this);\n\t\t\treturn res.inject.apply(res, arguments);\n\t\t},\n\n\t\teach: function(iter, bind) {\n\t\t\treturn each(this, iter, bind);\n\t\t},\n\n\t\tclone: function() {\n\t\t\treturn new this.constructor(this);\n\t\t},\n\n\t\tstatics: {\n\t\t\tset: set,\n\t\t\teach: each,\n\t\t\tcreate: create,\n\t\t\tdefine: define,\n\t\t\tdescribe: describe,\n\n\t\t\tclone: function(obj) {\n\t\t\t\treturn set(new obj.constructor(), obj);\n\t\t\t},\n\n\t\t\tisPlainObject: function(obj) {\n\t\t\t\tvar ctor = obj != null && obj.constructor;\n\t\t\t\treturn ctor && (ctor === Object || ctor === Base\n\t\t\t\t\t\t|| ctor.name === 'Object');\n\t\t\t},\n\n\t\t\tpick: function(a, b) {\n\t\t\t\treturn a !== undefined ? a : b;\n\t\t\t},\n\n\t\t\tslice: function(list, begin, end) {\n\t\t\t\treturn slice.call(list, begin, end);\n\t\t\t}\n\t\t}\n\t});\n};\n\nif (typeof module !== 'undefined')\n\tmodule.exports = Base;\n\nBase.inject({\n\ttoString: function() {\n\t\treturn this._id != null\n\t\t\t? (this._class || 'Object') + (this._name\n\t\t\t\t? \" '\" + this._name + \"'\"\n\t\t\t\t: ' @' + this._id)\n\t\t\t: '{ ' + Base.each(this, function(value, key) {\n\t\t\t\tif (!/^_/.test(key)) {\n\t\t\t\t\tvar type = typeof value;\n\t\t\t\t\tthis.push(key + ': ' + (type === 'number'\n\t\t\t\t\t\t\t? Formatter.instance.number(value)\n\t\t\t\t\t\t\t: type === 'string' ? \"'\" + value + \"'\" : value));\n\t\t\t\t}\n\t\t\t}, []).join(', ') + ' }';\n\t},\n\n\tgetClassName: function() {\n\t\treturn this._class || '';\n\t},\n\n\timportJSON: function(json) {\n\t\treturn Base.importJSON(json, this);\n\t},\n\n\texportJSON: function(options) {\n\t\treturn Base.exportJSON(this, options);\n\t},\n\n\ttoJSON: function() {\n\t\treturn Base.serialize(this);\n\t},\n\n\tset: function(props, exclude) {\n\t\tif (props)\n\t\t\tBase.filter(this, props, exclude, this._prioritize);\n\t\treturn this;\n\t},\n\n\tstatics: {\n\n\t\texports: {\n\t\t\tenumerable: true\n\t\t},\n\n\t\textend: function extend() {\n\t\t\tvar res = extend.base.apply(this, arguments),\n\t\t\t\tname = res.prototype._class;\n\t\t\tif (name && !Base.exports[name])\n\t\t\t\tBase.exports[name] = res;\n\t\t\treturn res;\n\t\t},\n\n\t\tequals: function(obj1, obj2) {\n\t\t\tif (obj1 === obj2)\n\t\t\t\treturn true;\n\t\t\tif (obj1 && obj1.equals)\n\t\t\t\treturn obj1.equals(obj2);\n\t\t\tif (obj2 && obj2.equals)\n\t\t\t\treturn obj2.equals(obj1);\n\t\t\tif (obj1 && obj2\n\t\t\t\t\t&& typeof obj1 === 'object' && typeof obj2 === 'object') {\n\t\t\t\tif (Array.isArray(obj1) && Array.isArray(obj2)) {\n\t\t\t\t\tvar length = obj1.length;\n\t\t\t\t\tif (length !== obj2.length)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\twhile (length--) {\n\t\t\t\t\t\tif (!Base.equals(obj1[length], obj2[length]))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvar keys = Object.keys(obj1),\n\t\t\t\t\t\tlength = keys.length;\n\t\t\t\t\tif (length !== Object.keys(obj2).length)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\twhile (length--) {\n\t\t\t\t\t\tvar key = keys[length];\n\t\t\t\t\t\tif (!(obj2.hasOwnProperty(key)\n\t\t\t\t\t\t\t\t&& Base.equals(obj1[key], obj2[key])))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\n\t\tread: function(list, start, options, amount) {\n\t\t\tif (this === Base) {\n\t\t\t\tvar value = this.peek(list, start);\n\t\t\t\tlist.__index++;\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\tvar proto = this.prototype,\n\t\t\t\treadIndex = proto._readIndex,\n\t\t\t\tbegin = start || readIndex && list.__index || 0,\n\t\t\t\tlength = list.length,\n\t\t\t\tobj = list[begin];\n\t\t\tamount = amount || length - begin;\n\t\t\tif (obj instanceof this\n\t\t\t\t|| options && options.readNull && obj == null && amount <= 1) {\n\t\t\t\tif (readIndex)\n\t\t\t\t\tlist.__index = begin + 1;\n\t\t\t\treturn obj && options && options.clone ? obj.clone() : obj;\n\t\t\t}\n\t\t\tobj = Base.create(proto);\n\t\t\tif (readIndex)\n\t\t\t\tobj.__read = true;\n\t\t\tobj = obj.initialize.apply(obj, begin > 0 || begin + amount < length\n\t\t\t\t\t? Base.slice(list, begin, begin + amount)\n\t\t\t\t\t: list) || obj;\n\t\t\tif (readIndex) {\n\t\t\t\tlist.__index = begin + obj.__read;\n\t\t\t\tobj.__read = undefined;\n\t\t\t}\n\t\t\treturn obj;\n\t\t},\n\n\t\tpeek: function(list, start) {\n\t\t\treturn list[list.__index = start || list.__index || 0];\n\t\t},\n\n\t\tremain: function(list) {\n\t\t\treturn list.length - (list.__index || 0);\n\t\t},\n\n\t\treadList: function(list, start, options, amount) {\n\t\t\tvar res = [],\n\t\t\t\tentry,\n\t\t\t\tbegin = start || 0,\n\t\t\t\tend = amount ? begin + amount : list.length;\n\t\t\tfor (var i = begin; i < end; i++) {\n\t\t\t\tres.push(Array.isArray(entry = list[i])\n\t\t\t\t\t\t? this.read(entry, 0, options)\n\t\t\t\t\t\t: this.read(list, i, options, 1));\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\n\t\treadNamed: function(list, name, start, options, amount) {\n\t\t\tvar value = this.getNamed(list, name),\n\t\t\t\thasObject = value !== undefined;\n\t\t\tif (hasObject) {\n\t\t\t\tvar filtered = list._filtered;\n\t\t\t\tif (!filtered) {\n\t\t\t\t\tfiltered = list._filtered = Base.create(list[0]);\n\t\t\t\t\tfiltered._unfiltered = list[0];\n\t\t\t\t}\n\t\t\t\tfiltered[name] = undefined;\n\t\t\t}\n\t\t\treturn this.read(hasObject ? [value] : list, start, options, amount);\n\t\t},\n\n\t\tgetNamed: function(list, name) {\n\t\t\tvar arg = list[0];\n\t\t\tif (list._hasObject === undefined)\n\t\t\t\tlist._hasObject = list.length === 1 && Base.isPlainObject(arg);\n\t\t\tif (list._hasObject)\n\t\t\t\treturn name ? arg[name] : list._filtered || arg;\n\t\t},\n\n\t\thasNamed: function(list, name) {\n\t\t\treturn !!this.getNamed(list, name);\n\t\t},\n\n\t\tfilter: function(dest, source, exclude, prioritize) {\n\t\t\tvar processed;\n\n\t\t\tfunction handleKey(key) {\n\t\t\t\tif (!(exclude && key in exclude) &&\n\t\t\t\t\t!(processed && key in processed)) {\n\t\t\t\t\tvar value = source[key];\n\t\t\t\t\tif (value !== undefined)\n\t\t\t\t\t\tdest[key] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (prioritize) {\n\t\t\t\tvar keys = {};\n\t\t\t\tfor (var i = 0, key, l = prioritize.length; i < l; i++) {\n\t\t\t\t\tif ((key = prioritize[i]) in source) {\n\t\t\t\t\t\thandleKey(key);\n\t\t\t\t\t\tkeys[key] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tprocessed = keys;\n\t\t\t}\n\n\t\t\tObject.keys(source._unfiltered || source).forEach(handleKey);\n\t\t\treturn dest;\n\t\t},\n\n\t\tisPlainValue: function(obj, asString) {\n\t\t\treturn Base.isPlainObject(obj) || Array.isArray(obj)\n\t\t\t\t\t|| asString && typeof obj === 'string';\n\t\t},\n\n\t\tserialize: function(obj, options, compact, dictionary) {\n\t\t\toptions = options || {};\n\n\t\t\tvar isRoot = !dictionary,\n\t\t\t\tres;\n\t\t\tif (isRoot) {\n\t\t\t\toptions.formatter = new Formatter(options.precision);\n\t\t\t\tdictionary = {\n\t\t\t\t\tlength: 0,\n\t\t\t\t\tdefinitions: {},\n\t\t\t\t\treferences: {},\n\t\t\t\t\tadd: function(item, create) {\n\t\t\t\t\t\tvar id = '#' + item._id,\n\t\t\t\t\t\t\tref = this.references[id];\n\t\t\t\t\t\tif (!ref) {\n\t\t\t\t\t\t\tthis.length++;\n\t\t\t\t\t\t\tvar res = create.call(item),\n\t\t\t\t\t\t\t\tname = item._class;\n\t\t\t\t\t\t\tif (name && res[0] !== name)\n\t\t\t\t\t\t\t\tres.unshift(name);\n\t\t\t\t\t\t\tthis.definitions[id] = res;\n\t\t\t\t\t\t\tref = this.references[id] = [id];\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn ref;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (obj && obj._serialize) {\n\t\t\t\tres = obj._serialize(options, dictionary);\n\t\t\t\tvar name = obj._class;\n\t\t\t\tif (name && !obj._compactSerialize && (isRoot || !compact)\n\t\t\t\t\t\t&& res[0] !== name) {\n\t\t\t\t\tres.unshift(name);\n\t\t\t\t}\n\t\t\t} else if (Array.isArray(obj)) {\n\t\t\t\tres = [];\n\t\t\t\tfor (var i = 0, l = obj.length; i < l; i++)\n\t\t\t\t\tres[i] = Base.serialize(obj[i], options, compact,\n\t\t\t\t\t\t\tdictionary);\n\t\t\t} else if (Base.isPlainObject(obj)) {\n\t\t\t\tres = {};\n\t\t\t\tvar keys = Object.keys(obj);\n\t\t\t\tfor (var i = 0, l = keys.length; i < l; i++) {\n\t\t\t\t\tvar key = keys[i];\n\t\t\t\t\tres[key] = Base.serialize(obj[key], options, compact,\n\t\t\t\t\t\t\tdictionary);\n\t\t\t\t}\n\t\t\t} else if (typeof obj === 'number') {\n\t\t\t\tres = options.formatter.number(obj, options.precision);\n\t\t\t} else {\n\t\t\t\tres = obj;\n\t\t\t}\n\t\t\treturn isRoot && dictionary.length > 0\n\t\t\t\t\t? [['dictionary', dictionary.definitions], res]\n\t\t\t\t\t: res;\n\t\t},\n\n\t\tdeserialize: function(json, create, _data, _setDictionary, _isRoot) {\n\t\t\tvar res = json,\n\t\t\t\tisFirst = !_data,\n\t\t\t\thasDictionary = isFirst && json && json.length\n\t\t\t\t\t&& json[0][0] === 'dictionary';\n\t\t\t_data = _data || {};\n\t\t\tif (Array.isArray(json)) {\n\t\t\t\tvar type = json[0],\n\t\t\t\t\tisDictionary = type === 'dictionary';\n\t\t\t\tif (json.length == 1 && /^#/.test(type)) {\n\t\t\t\t\treturn _data.dictionary[type];\n\t\t\t\t}\n\t\t\t\ttype = Base.exports[type];\n\t\t\t\tres = [];\n\t\t\t\tfor (var i = type ? 1 : 0, l = json.length; i < l; i++) {\n\t\t\t\t\tres.push(Base.deserialize(json[i], create, _data,\n\t\t\t\t\t\t\tisDictionary, hasDictionary));\n\t\t\t\t}\n\t\t\t\tif (type) {\n\t\t\t\t\tvar args = res;\n\t\t\t\t\tif (create) {\n\t\t\t\t\t\tres = create(type, args, isFirst || _isRoot);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres = Base.create(type.prototype);\n\t\t\t\t\t\ttype.apply(res, args);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (Base.isPlainObject(json)) {\n\t\t\t\tres = {};\n\t\t\t\tif (_setDictionary)\n\t\t\t\t\t_data.dictionary = res;\n\t\t\t\tfor (var key in json)\n\t\t\t\t\tres[key] = Base.deserialize(json[key], create, _data);\n\t\t\t}\n\t\t\treturn hasDictionary ? res[1] : res;\n\t\t},\n\n\t\texportJSON: function(obj, options) {\n\t\t\tvar json = Base.serialize(obj, options);\n\t\t\treturn options && options.asString === false\n\t\t\t\t\t? json\n\t\t\t\t\t: JSON.stringify(json);\n\t\t},\n\n\t\timportJSON: function(json, target) {\n\t\t\treturn Base.deserialize(\n\t\t\t\t\ttypeof json === 'string' ? JSON.parse(json) : json,\n\t\t\t\t\tfunction(ctor, args, isRoot) {\n\t\t\t\t\t\tvar useTarget = isRoot && target\n\t\t\t\t\t\t\t\t&& target.constructor === ctor,\n\t\t\t\t\t\t\tobj = useTarget ? target\n\t\t\t\t\t\t\t\t: Base.create(ctor.prototype);\n\t\t\t\t\t\tif (args.length === 1 && obj instanceof Item\n\t\t\t\t\t\t\t\t&& (useTarget || !(obj instanceof Layer))) {\n\t\t\t\t\t\t\tvar arg = args[0];\n\t\t\t\t\t\t\tif (Base.isPlainObject(arg))\n\t\t\t\t\t\t\t\targ.insert = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t(useTarget ? obj.set : ctor).apply(obj, args);\n\t\t\t\t\t\tif (useTarget)\n\t\t\t\t\t\t\ttarget = null;\n\t\t\t\t\t\treturn obj;\n\t\t\t\t\t});\n\t\t},\n\n\t\tsplice: function(list, items, index, remove) {\n\t\t\tvar amount = items && items.length,\n\t\t\t\tappend = index === undefined;\n\t\t\tindex = append ? list.length : index;\n\t\t\tif (index > list.length)\n\t\t\t\tindex = list.length;\n\t\t\tfor (var i = 0; i < amount; i++)\n\t\t\t\titems[i]._index = index + i;\n\t\t\tif (append) {\n\t\t\t\tlist.push.apply(list, items);\n\t\t\t\treturn [];\n\t\t\t} else {\n\t\t\t\tvar args = [index, remove];\n\t\t\t\tif (items)\n\t\t\t\t\targs.push.apply(args, items);\n\t\t\t\tvar removed = list.splice.apply(list, args);\n\t\t\t\tfor (var i = 0, l = removed.length; i < l; i++)\n\t\t\t\t\tremoved[i]._index = undefined;\n\t\t\t\tfor (var i = index + amount, l = list.length; i < l; i++)\n\t\t\t\t\tlist[i]._index = i;\n\t\t\t\treturn removed;\n\t\t\t}\n\t\t},\n\n\t\tcapitalize: function(str) {\n\t\t\treturn str.replace(/\\b[a-z]/g, function(match) {\n\t\t\t\treturn match.toUpperCase();\n\t\t\t});\n\t\t},\n\n\t\tcamelize: function(str) {\n\t\t\treturn str.replace(/-(.)/g, function(all, chr) {\n\t\t\t\treturn chr.toUpperCase();\n\t\t\t});\n\t\t},\n\n\t\thyphenate: function(str) {\n\t\t\treturn str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n\t\t}\n\t}\n});\n\nvar Emitter = {\n\ton: function(type, func) {\n\t\tif (typeof type !== 'string') {\n\t\t\tBase.each(type, function(value, key) {\n\t\t\t\tthis.on(key, value);\n\t\t\t}, this);\n\t\t} else {\n\t\t\tvar types = this._eventTypes,\n\t\t\t\tentry = types && types[type],\n\t\t\t\thandlers = this._callbacks = this._callbacks || {};\n\t\t\thandlers = handlers[type] = handlers[type] || [];\n\t\t\tif (handlers.indexOf(func) === -1) {\n\t\t\t\thandlers.push(func);\n\t\t\t\tif (entry && entry.install && handlers.length === 1)\n\t\t\t\t\tentry.install.call(this, type);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\toff: function(type, func) {\n\t\tif (typeof type !== 'string') {\n\t\t\tBase.each(type, function(value, key) {\n\t\t\t\tthis.off(key, value);\n\t\t\t}, this);\n\t\t\treturn;\n\t\t}\n\t\tvar types = this._eventTypes,\n\t\t\tentry = types && types[type],\n\t\t\thandlers = this._callbacks && this._callbacks[type],\n\t\t\tindex;\n\t\tif (handlers) {\n\t\t\tif (!func || (index = handlers.indexOf(func)) !== -1\n\t\t\t\t\t&& handlers.length === 1) {\n\t\t\t\tif (entry && entry.uninstall)\n\t\t\t\t\tentry.uninstall.call(this, type);\n\t\t\t\tdelete this._callbacks[type];\n\t\t\t} else if (index !== -1) {\n\t\t\t\thandlers.splice(index, 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\tonce: function(type, func) {\n\t\treturn this.on(type, function() {\n\t\t\tfunc.apply(this, arguments);\n\t\t\tthis.off(type, func);\n\t\t});\n\t},\n\n\temit: function(type, event) {\n\t\tvar handlers = this._callbacks && this._callbacks[type];\n\t\tif (!handlers)\n\t\t\treturn false;\n\t\tvar args = Base.slice(arguments, 1),\n\t\t\tsetTarget = event && event.target && !event.currentTarget;\n\t\thandlers = handlers.slice();\n\t\tif (setTarget)\n\t\t\tevent.currentTarget = this;\n\t\tfor (var i = 0, l = handlers.length; i < l; i++) {\n\t\t\tif (handlers[i].apply(this, args) === false) {\n\t\t\t\tif (event && event.stop)\n\t\t\t\t\tevent.stop();\n\t\t\t\tbreak;\n\t\t }\n\t\t}\n\t\tif (setTarget)\n\t\t\tdelete event.currentTarget;\n\t\treturn true;\n\t},\n\n\tresponds: function(type) {\n\t\treturn !!(this._callbacks && this._callbacks[type]);\n\t},\n\n\tattach: '#on',\n\tdetach: '#off',\n\tfire: '#emit',\n\n\t_installEvents: function(install) {\n\t\tvar types = this._eventTypes,\n\t\t\thandlers = this._callbacks,\n\t\t\tkey = install ? 'install' : 'uninstall';\n\t\tif (types) {\n\t\t\tfor (var type in handlers) {\n\t\t\t\tif (handlers[type].length > 0) {\n\t\t\t\t\tvar entry = types[type],\n\t\t\t\t\t\tfunc = entry && entry[key];\n\t\t\t\t\tif (func)\n\t\t\t\t\t\tfunc.call(this, type);\n\t\t\t\t}\n\t\t}\n\t\t}\n\t},\n\n\tstatics: {\n\t\tinject: function inject(src) {\n\t\t\tvar events = src._events;\n\t\t\tif (events) {\n\t\t\t\tvar types = {};\n\t\t\t\tBase.each(events, function(entry, key) {\n\t\t\t\t\tvar isString = typeof entry === 'string',\n\t\t\t\t\t\tname = isString ? entry : key,\n\t\t\t\t\t\tpart = Base.capitalize(name),\n\t\t\t\t\t\ttype = name.substring(2).toLowerCase();\n\t\t\t\t\ttypes[type] = isString ? {} : entry;\n\t\t\t\t\tname = '_' + name;\n\t\t\t\t\tsrc['get' + part] = function() {\n\t\t\t\t\t\treturn this[name];\n\t\t\t\t\t};\n\t\t\t\t\tsrc['set' + part] = function(func) {\n\t\t\t\t\t\tvar prev = this[name];\n\t\t\t\t\t\tif (prev)\n\t\t\t\t\t\t\tthis.off(type, prev);\n\t\t\t\t\t\tif (func)\n\t\t\t\t\t\t\tthis.on(type, func);\n\t\t\t\t\t\tthis[name] = func;\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t\tsrc._eventTypes = types;\n\t\t\t}\n\t\t\treturn inject.base.apply(this, arguments);\n\t\t}\n\t}\n};\n\nvar PaperScope = Base.extend({\n\t_class: 'PaperScope',\n\n\tinitialize: function PaperScope() {\n\t\tpaper = this;\n\t\tthis.settings = new Base({\n\t\t\tapplyMatrix: true,\n\t\t\tinsertItems: true,\n\t\t\thandleSize: 4,\n\t\t\thitTolerance: 0\n\t\t});\n\t\tthis.project = null;\n\t\tthis.projects = [];\n\t\tthis.tools = [];\n\t\tthis.palettes = [];\n\t\tthis._id = PaperScope._id++;\n\t\tPaperScope._scopes[this._id] = this;\n\t\tvar proto = PaperScope.prototype;\n\t\tif (!this.support) {\n\t\t\tvar ctx = CanvasProvider.getContext(1, 1) || {};\n\t\t\tproto.support = {\n\t\t\t\tnativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,\n\t\t\t\tnativeBlendModes: BlendMode.nativeModes\n\t\t\t};\n\t\t\tCanvasProvider.release(ctx);\n\t\t}\n\t\tif (!this.agent) {\n\t\t\tvar user = self.navigator.userAgent.toLowerCase(),\n\t\t\t\tos = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],\n\t\t\t\tplatform = os === 'darwin' ? 'mac' : os,\n\t\t\t\tagent = proto.agent = proto.browser = { platform: platform };\n\t\t\tif (platform)\n\t\t\t\tagent[platform] = true;\n\t\t\tuser.replace(\n\t\t\t\t/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\\/?\\s*([.\\d]+)(?:.*version\\/([.\\d]+))?(?:.*rv\\:v?([.\\d]+))?/g,\n\t\t\t\tfunction(all, n, v1, v2, rv) {\n\t\t\t\t\tif (!agent.chrome) {\n\t\t\t\t\t\tvar v = n === 'opera' ? v2 :\n\t\t\t\t\t\t\t\t/^(node|trident)$/.test(n) ? rv : v1;\n\t\t\t\t\t\tagent.version = v;\n\t\t\t\t\t\tagent.versionNumber = parseFloat(v);\n\t\t\t\t\t\tn = n === 'trident' ? 'msie' : n;\n\t\t\t\t\t\tagent.name = n;\n\t\t\t\t\t\tagent[n] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t\tif (agent.chrome)\n\t\t\t\tdelete agent.webkit;\n\t\t\tif (agent.atom)\n\t\t\t\tdelete agent.chrome;\n\t\t}\n\t},\n\n\tversion: \"0.10.2-develop\",\n\n\tgetView: function() {\n\t\tvar project = this.project;\n\t\treturn project && project._view;\n\t},\n\n\tgetPaper: function() {\n\t\treturn this;\n\t},\n\n\texecute: function(code, options) {\n\t\tpaper.PaperScript.execute(code, this, options);\n\t\tView.updateFocus();\n\t},\n\n\tinstall: function(scope) {\n\t\tvar that = this;\n\t\tBase.each(['project', 'view', 'tool'], function(key) {\n\t\t\tBase.define(scope, key, {\n\t\t\t\tconfigurable: true,\n\t\t\t\tget: function() {\n\t\t\t\t\treturn that[key];\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\tfor (var key in this)\n\t\t\tif (!/^_/.test(key) && this[key])\n\t\t\t\tscope[key] = this[key];\n\t},\n\n\tsetup: function(element) {\n\t\tpaper = this;\n\t\tthis.project = new Project(element);\n\t\treturn this;\n\t},\n\n\tcreateCanvas: function(width, height) {\n\t\treturn CanvasProvider.getCanvas(width, height);\n\t},\n\n\tactivate: function() {\n\t\tpaper = this;\n\t},\n\n\tclear: function() {\n\t\tvar projects = this.projects,\n\t\t\ttools = this.tools,\n\t\t\tpalettes = this.palettes;\n\t\tfor (var i = projects.length - 1; i >= 0; i--)\n\t\t\tprojects[i].remove();\n\t\tfor (var i = tools.length - 1; i >= 0; i--)\n\t\t\ttools[i].remove();\n\t\tfor (var i = palettes.length - 1; i >= 0; i--)\n\t\t\tpalettes[i].remove();\n\t},\n\n\tremove: function() {\n\t\tthis.clear();\n\t\tdelete PaperScope._scopes[this._id];\n\t},\n\n\tstatics: new function() {\n\t\tfunction handleAttribute(name) {\n\t\t\tname += 'Attribute';\n\t\t\treturn function(el, attr) {\n\t\t\t\treturn el[name](attr) || el[name]('data-paper-' + attr);\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\t_scopes: {},\n\t\t\t_id: 0,\n\n\t\t\tget: function(id) {\n\t\t\t\treturn this._scopes[id] || null;\n\t\t\t},\n\n\t\t\tgetAttribute: handleAttribute('get'),\n\t\t\thasAttribute: handleAttribute('has')\n\t\t};\n\t}\n});\n\nvar PaperScopeItem = Base.extend(Emitter, {\n\n\tinitialize: function(activate) {\n\t\tthis._scope = paper;\n\t\tthis._index = this._scope[this._list].push(this) - 1;\n\t\tif (activate || !this._scope[this._reference])\n\t\t\tthis.activate();\n\t},\n\n\tactivate: function() {\n\t\tif (!this._scope)\n\t\t\treturn false;\n\t\tvar prev = this._scope[this._reference];\n\t\tif (prev && prev !== this)\n\t\t\tprev.emit('deactivate');\n\t\tthis._scope[this._reference] = this;\n\t\tthis.emit('activate', prev);\n\t\treturn true;\n\t},\n\n\tisActive: function() {\n\t\treturn this._scope[this._reference] === this;\n\t},\n\n\tremove: function() {\n\t\tif (this._index == null)\n\t\t\treturn false;\n\t\tBase.splice(this._scope[this._list], null, this._index, 1);\n\t\tif (this._scope[this._reference] == this)\n\t\t\tthis._scope[this._reference] = null;\n\t\tthis._scope = null;\n\t\treturn true;\n\t},\n\n\tgetView: function() {\n\t\treturn this._scope.getView();\n\t}\n});\n\nvar Formatter = Base.extend({\n\tinitialize: function(precision) {\n\t\tthis.precision = Base.pick(precision, 5);\n\t\tthis.multiplier = Math.pow(10, this.precision);\n\t},\n\n\tnumber: function(val) {\n\t\treturn this.precision < 16\n\t\t\t\t? Math.round(val * this.multiplier) / this.multiplier : val;\n\t},\n\n\tpair: function(val1, val2, separator) {\n\t\treturn this.number(val1) + (separator || ',') + this.number(val2);\n\t},\n\n\tpoint: function(val, separator) {\n\t\treturn this.number(val.x) + (separator || ',') + this.number(val.y);\n\t},\n\n\tsize: function(val, separator) {\n\t\treturn this.number(val.width) + (separator || ',')\n\t\t\t\t+ this.number(val.height);\n\t},\n\n\trectangle: function(val, separator) {\n\t\treturn this.point(val, separator) + (separator || ',')\n\t\t\t\t+ this.size(val, separator);\n\t}\n});\n\nFormatter.instance = new Formatter();\n\nvar Numerical = new function() {\n\n\tvar abscissas = [\n\t\t[ 0.5773502691896257645091488],\n\t\t[0,0.7745966692414833770358531],\n\t\t[ 0.3399810435848562648026658,0.8611363115940525752239465],\n\t\t[0,0.5384693101056830910363144,0.9061798459386639927976269],\n\t\t[ 0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],\n\t\t[0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],\n\t\t[ 0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],\n\t\t[0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],\n\t\t[ 0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],\n\t\t[0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],\n\t\t[ 0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],\n\t\t[0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],\n\t\t[ 0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],\n\t\t[0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],\n\t\t[ 0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]\n\t];\n\n\tvar weights = [\n\t\t[1],\n\t\t[0.8888888888888888888888889,0.5555555555555555555555556],\n\t\t[0.6521451548625461426269361,0.3478548451374538573730639],\n\t\t[0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],\n\t\t[0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],\n\t\t[0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],\n\t\t[0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],\n\t\t[0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],\n\t\t[0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],\n\t\t[0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],\n\t\t[0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],\n\t\t[0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],\n\t\t[0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],\n\t\t[0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],\n\t\t[0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]\n\t];\n\n\tvar abs = Math.abs,\n\t\tsqrt = Math.sqrt,\n\t\tpow = Math.pow,\n\t\tlog2 = Math.log2 || function(x) {\n\t\t\treturn Math.log(x) * Math.LOG2E;\n\t\t},\n\t\tEPSILON = 1e-12,\n\t\tMACHINE_EPSILON = 1.12e-16;\n\n\tfunction clamp(value, min, max) {\n\t\treturn value < min ? min : value > max ? max : value;\n\t}\n\n\tfunction getDiscriminant(a, b, c) {\n\t\tfunction split(v) {\n\t\t\tvar x = v * 134217729,\n\t\t\t\ty = v - x,\n\t\t\t\thi = y + x,\n\t\t\t\tlo = v - hi;\n\t\t\treturn [hi, lo];\n\t\t}\n\n\t\tvar D = b * b - a * c,\n\t\t\tE = b * b + a * c;\n\t\tif (abs(D) * 3 < E) {\n\t\t\tvar ad = split(a),\n\t\t\t\tbd = split(b),\n\t\t\t\tcd = split(c),\n\t\t\t\tp = b * b,\n\t\t\t\tdp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],\n\t\t\t\tq = a * c,\n\t\t\t\tdq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])\n\t\t\t\t\t\t+ ad[1] * cd[1];\n\t\t\tD = (p - q) + (dp - dq);\n\t\t}\n\t\treturn D;\n\t}\n\n\tfunction getNormalizationFactor() {\n\t\tvar norm = Math.max.apply(Math, arguments);\n\t\treturn norm && (norm < 1e-8 || norm > 1e8)\n\t\t\t\t? pow(2, -Math.round(log2(norm)))\n\t\t\t\t: 0;\n\t}\n\n\treturn {\n\t\tTOLERANCE: 1e-6,\n\t\tEPSILON: EPSILON,\n\t\tMACHINE_EPSILON: MACHINE_EPSILON,\n\t\tCURVETIME_EPSILON: 4e-7,\n\t\tGEOMETRIC_EPSILON: 1e-7,\n\t\tWINDING_EPSILON: 1e-8,\n\t\tTRIGONOMETRIC_EPSILON: 1e-8,\n\t\tCLIPPING_EPSILON: 1e-10,\n\t\tKAPPA: 4 * (sqrt(2) - 1) / 3,\n\n\t\tisZero: function(val) {\n\t\t\treturn val >= -EPSILON && val <= EPSILON;\n\t\t},\n\n\t\tclamp: clamp,\n\n\t\tintegrate: function(f, a, b, n) {\n\t\t\tvar x = abscissas[n - 2],\n\t\t\t\tw = weights[n - 2],\n\t\t\t\tA = (b - a) * 0.5,\n\t\t\t\tB = A + a,\n\t\t\t\ti = 0,\n\t\t\t\tm = (n + 1) >> 1,\n\t\t\t\tsum = n & 1 ? w[i++] * f(B) : 0;\n\t\t\twhile (i < m) {\n\t\t\t\tvar Ax = A * x[i];\n\t\t\t\tsum += w[i++] * (f(B + Ax) + f(B - Ax));\n\t\t\t}\n\t\t\treturn A * sum;\n\t\t},\n\n\t\tfindRoot: function(f, df, x, a, b, n, tolerance) {\n\t\t\tfor (var i = 0; i < n; i++) {\n\t\t\t\tvar fx = f(x),\n\t\t\t\t\tdx = fx / df(x),\n\t\t\t\t\tnx = x - dx;\n\t\t\t\tif (abs(dx) < tolerance)\n\t\t\t\t\treturn nx;\n\t\t\t\tif (fx > 0) {\n\t\t\t\t\tb = x;\n\t\t\t\t\tx = nx <= a ? (a + b) * 0.5 : nx;\n\t\t\t\t} else {\n\t\t\t\t\ta = x;\n\t\t\t\t\tx = nx >= b ? (a + b) * 0.5 : nx;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn x;\n\t\t},\n\n\t\tsolveQuadratic: function(a, b, c, roots, min, max) {\n\t\t\tvar x1, x2 = Infinity;\n\t\t\tif (abs(a) < EPSILON) {\n\t\t\t\tif (abs(b) < EPSILON)\n\t\t\t\t\treturn abs(c) < EPSILON ? -1 : 0;\n\t\t\t\tx1 = -c / b;\n\t\t\t} else {\n\t\t\t\tb *= -0.5;\n\t\t\t\tvar D = getDiscriminant(a, b, c);\n\t\t\t\tif (D && abs(D) < MACHINE_EPSILON) {\n\t\t\t\t\tvar f = getNormalizationFactor(abs(a), abs(b), abs(c));\n\t\t\t\t\tif (f) {\n\t\t\t\t\t\ta *= f;\n\t\t\t\t\t\tb *= f;\n\t\t\t\t\t\tc *= f;\n\t\t\t\t\t\tD = getDiscriminant(a, b, c);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (D >= -MACHINE_EPSILON) {\n\t\t\t\t\tvar Q = D < 0 ? 0 : sqrt(D),\n\t\t\t\t\t\tR = b + (b < 0 ? -Q : Q);\n\t\t\t\t\tif (R === 0) {\n\t\t\t\t\t\tx1 = c / a;\n\t\t\t\t\t\tx2 = -x1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tx1 = R / a;\n\t\t\t\t\t\tx2 = c / R;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar count = 0,\n\t\t\t\tboundless = min == null,\n\t\t\t\tminB = min - EPSILON,\n\t\t\t\tmaxB = max + EPSILON;\n\t\t\tif (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))\n\t\t\t\troots[count++] = boundless ? x1 : clamp(x1, min, max);\n\t\t\tif (x2 !== x1\n\t\t\t\t\t&& isFinite(x2) && (boundless || x2 > minB && x2 < maxB))\n\t\t\t\troots[count++] = boundless ? x2 : clamp(x2, min, max);\n\t\t\treturn count;\n\t\t},\n\n\t\tsolveCubic: function(a, b, c, d, roots, min, max) {\n\t\t\tvar f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),\n\t\t\t\tx, b1, c2, qd, q;\n\t\t\tif (f) {\n\t\t\t\ta *= f;\n\t\t\t\tb *= f;\n\t\t\t\tc *= f;\n\t\t\t\td *= f;\n\t\t\t}\n\n\t\t\tfunction evaluate(x0) {\n\t\t\t\tx = x0;\n\t\t\t\tvar tmp = a * x;\n\t\t\t\tb1 = tmp + b;\n\t\t\t\tc2 = b1 * x + c;\n\t\t\t\tqd = (tmp + b1) * x + c2;\n\t\t\t\tq = c2 * x + d;\n\t\t\t}\n\n\t\t\tif (abs(a) < EPSILON) {\n\t\t\t\ta = b;\n\t\t\t\tb1 = c;\n\t\t\t\tc2 = d;\n\t\t\t\tx = Infinity;\n\t\t\t} else if (abs(d) < EPSILON) {\n\t\t\t\tb1 = b;\n\t\t\t\tc2 = c;\n\t\t\t\tx = 0;\n\t\t\t} else {\n\t\t\t\tevaluate(-(b / a) / 3);\n\t\t\t\tvar t = q / a,\n\t\t\t\t\tr = pow(abs(t), 1/3),\n\t\t\t\t\ts = t < 0 ? -1 : 1,\n\t\t\t\t\ttd = -qd / a,\n\t\t\t\t\trd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,\n\t\t\t\t\tx0 = x - s * rd;\n\t\t\t\tif (x0 !== x) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tevaluate(x0);\n\t\t\t\t\t\tx0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);\n\t\t\t\t\t} while (s * x0 > s * x);\n\t\t\t\t\tif (abs(a) * x * x > abs(d / x)) {\n\t\t\t\t\t\tc2 = -d / x;\n\t\t\t\t\t\tb1 = (c2 - c) / x;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),\n\t\t\t\tboundless = min == null;\n\t\t\tif (isFinite(x) && (count === 0\n\t\t\t\t\t|| count > 0 && x !== roots[0] && x !== roots[1])\n\t\t\t\t\t&& (boundless || x > min - EPSILON && x < max + EPSILON))\n\t\t\t\troots[count++] = boundless ? x : clamp(x, min, max);\n\t\t\treturn count;\n\t\t}\n\t};\n};\n\nvar UID = {\n\t_id: 1,\n\t_pools: {},\n\n\tget: function(name) {\n\t\tif (name) {\n\t\t\tvar pool = this._pools[name];\n\t\t\tif (!pool)\n\t\t\t\tpool = this._pools[name] = { _id: 1 };\n\t\t\treturn pool._id++;\n\t\t} else {\n\t\t\treturn this._id++;\n\t\t}\n\t}\n};\n\nvar Point = Base.extend({\n\t_class: 'Point',\n\t_readIndex: true,\n\n\tinitialize: function Point(arg0, arg1) {\n\t\tvar type = typeof arg0,\n\t\t\treading = this.__read,\n\t\t\tread = 0;\n\t\tif (type === 'number') {\n\t\t\tvar hasY = typeof arg1 === 'number';\n\t\t\tthis._set(arg0, hasY ? arg1 : arg0);\n\t\t\tif (reading)\n\t\t\t\tread = hasY ? 2 : 1;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0);\n\t\t\tif (reading)\n\t\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else {\n\t\t\tvar obj = type === 'string' ? arg0.split(/[\\s,]+/) || [] : arg0;\n\t\t\tread = 1;\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\tthis._set(+obj[0], +(obj.length > 1 ? obj[1] : obj[0]));\n\t\t\t} else if ('x' in obj) {\n\t\t\t\tthis._set(obj.x || 0, obj.y || 0);\n\t\t\t} else if ('width' in obj) {\n\t\t\t\tthis._set(obj.width || 0, obj.height || 0);\n\t\t\t} else if ('angle' in obj) {\n\t\t\t\tthis._set(obj.length || 0, 0);\n\t\t\t\tthis.setAngle(obj.angle || 0);\n\t\t\t} else {\n\t\t\t\tthis._set(0, 0);\n\t\t\t\tread = 0;\n\t\t\t}\n\t\t}\n\t\tif (reading)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(x, y) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\treturn this;\n\t},\n\n\tequals: function(point) {\n\t\treturn this === point || point\n\t\t\t\t&& (this.x === point.x && this.y === point.y\n\t\t\t\t\t|| Array.isArray(point)\n\t\t\t\t\t\t&& this.x === point[0] && this.y === point[1])\n\t\t\t\t|| false;\n\t},\n\n\tclone: function() {\n\t\treturn new Point(this.x, this.y);\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.x), f.number(this.y)];\n\t},\n\n\tgetLength: function() {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y);\n\t},\n\n\tsetLength: function(length) {\n\t\tif (this.isZero()) {\n\t\t\tvar angle = this._angle || 0;\n\t\t\tthis._set(\n\t\t\t\tMath.cos(angle) * length,\n\t\t\t\tMath.sin(angle) * length\n\t\t\t);\n\t\t} else {\n\t\t\tvar scale = length / this.getLength();\n\t\t\tif (Numerical.isZero(scale))\n\t\t\t\tthis.getAngle();\n\t\t\tthis._set(\n\t\t\t\tthis.x * scale,\n\t\t\t\tthis.y * scale\n\t\t\t);\n\t\t}\n\t},\n\tgetAngle: function() {\n\t\treturn this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;\n\t},\n\n\tsetAngle: function(angle) {\n\t\tthis.setAngleInRadians.call(this, angle * Math.PI / 180);\n\t},\n\n\tgetAngleInDegrees: '#getAngle',\n\tsetAngleInDegrees: '#setAngle',\n\n\tgetAngleInRadians: function() {\n\t\tif (!arguments.length) {\n\t\t\treturn this.isZero()\n\t\t\t\t\t? this._angle || 0\n\t\t\t\t\t: this._angle = Math.atan2(this.y, this.x);\n\t\t} else {\n\t\t\tvar point = Point.read(arguments),\n\t\t\t\tdiv = this.getLength() * point.getLength();\n\t\t\tif (Numerical.isZero(div)) {\n\t\t\t\treturn NaN;\n\t\t\t} else {\n\t\t\t\tvar a = this.dot(point) / div;\n\t\t\t\treturn Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);\n\t\t\t}\n\t\t}\n\t},\n\n\tsetAngleInRadians: function(angle) {\n\t\tthis._angle = angle;\n\t\tif (!this.isZero()) {\n\t\t\tvar length = this.getLength();\n\t\t\tthis._set(\n\t\t\t\tMath.cos(angle) * length,\n\t\t\t\tMath.sin(angle) * length\n\t\t\t);\n\t\t}\n\t},\n\n\tgetQuadrant: function() {\n\t\treturn this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;\n\t}\n}, {\n\tbeans: false,\n\n\tgetDirectedAngle: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;\n\t},\n\n\tgetDistance: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tx = point.x - this.x,\n\t\t\ty = point.y - this.y,\n\t\t\td = x * x + y * y,\n\t\t\tsquared = Base.read(arguments);\n\t\treturn squared ? d : Math.sqrt(d);\n\t},\n\n\tnormalize: function(length) {\n\t\tif (length === undefined)\n\t\t\tlength = 1;\n\t\tvar current = this.getLength(),\n\t\t\tscale = current !== 0 ? length / current : 0,\n\t\t\tpoint = new Point(this.x * scale, this.y * scale);\n\t\tif (scale >= 0)\n\t\t\tpoint._angle = this._angle;\n\t\treturn point;\n\t},\n\n\trotate: function(angle, center) {\n\t\tif (angle === 0)\n\t\t\treturn this.clone();\n\t\tangle = angle * Math.PI / 180;\n\t\tvar point = center ? this.subtract(center) : this,\n\t\t\tsin = Math.sin(angle),\n\t\t\tcos = Math.cos(angle);\n\t\tpoint = new Point(\n\t\t\tpoint.x * cos - point.y * sin,\n\t\t\tpoint.x * sin + point.y * cos\n\t\t);\n\t\treturn center ? point.add(center) : point;\n\t},\n\n\ttransform: function(matrix) {\n\t\treturn matrix ? matrix._transformPoint(this) : this;\n\t},\n\n\tadd: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x + point.x, this.y + point.y);\n\t},\n\n\tsubtract: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x - point.x, this.y - point.y);\n\t},\n\n\tmultiply: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x * point.x, this.y * point.y);\n\t},\n\n\tdivide: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x / point.x, this.y / point.y);\n\t},\n\n\tmodulo: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x % point.x, this.y % point.y);\n\t},\n\n\tnegate: function() {\n\t\treturn new Point(-this.x, -this.y);\n\t},\n\n\tisInside: function() {\n\t\treturn Rectangle.read(arguments).contains(this);\n\t},\n\n\tisClose: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\ttolerance = Base.read(arguments);\n\t\treturn this.getDistance(point) <= tolerance;\n\t},\n\n\tisCollinear: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Point.isCollinear(this.x, this.y, point.x, point.y);\n\t},\n\n\tisColinear: '#isCollinear',\n\n\tisOrthogonal: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Point.isOrthogonal(this.x, this.y, point.x, point.y);\n\t},\n\n\tisZero: function() {\n\t\treturn Numerical.isZero(this.x) && Numerical.isZero(this.y);\n\t},\n\n\tisNaN: function() {\n\t\treturn isNaN(this.x) || isNaN(this.y);\n\t},\n\n\tdot: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn this.x * point.x + this.y * point.y;\n\t},\n\n\tcross: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn this.x * point.y - this.y * point.x;\n\t},\n\n\tproject: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tscale = point.isZero() ? 0 : this.dot(point) / point.dot(point);\n\t\treturn new Point(\n\t\t\tpoint.x * scale,\n\t\t\tpoint.y * scale\n\t\t);\n\t},\n\n\tstatics: {\n\t\tmin: function() {\n\t\t\tvar point1 = Point.read(arguments),\n\t\t\t\tpoint2 = Point.read(arguments);\n\t\t\treturn new Point(\n\t\t\t\tMath.min(point1.x, point2.x),\n\t\t\t\tMath.min(point1.y, point2.y)\n\t\t\t);\n\t\t},\n\n\t\tmax: function() {\n\t\t\tvar point1 = Point.read(arguments),\n\t\t\t\tpoint2 = Point.read(arguments);\n\t\t\treturn new Point(\n\t\t\t\tMath.max(point1.x, point2.x),\n\t\t\t\tMath.max(point1.y, point2.y)\n\t\t\t);\n\t\t},\n\n\t\trandom: function() {\n\t\t\treturn new Point(Math.random(), Math.random());\n\t\t},\n\n\t\tisCollinear: function(x1, y1, x2, y2) {\n\t\t\treturn Math.abs(x1 * y2 - y1 * x2)\n\t\t\t\t\t<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))\n\t\t\t\t\t\t* 1e-8;\n\t\t},\n\n\t\tisOrthogonal: function(x1, y1, x2, y2) {\n\t\t\treturn Math.abs(x1 * x2 + y1 * y2)\n\t\t\t\t\t<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))\n\t\t\t\t\t\t* 1e-8;\n\t\t}\n\t}\n}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {\n\tvar op = Math[key];\n\tthis[key] = function() {\n\t\treturn new Point(op(this.x), op(this.y));\n\t};\n}, {}));\n\nvar LinkedPoint = Point.extend({\n\tinitialize: function Point(x, y, owner, setter) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(x, y, _dontNotify) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t},\n\n\tgetX: function() {\n\t\treturn this._x;\n\t},\n\n\tsetX: function(x) {\n\t\tthis._x = x;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tgetY: function() {\n\t\treturn this._y;\n\t},\n\n\tsetY: function(y) {\n\t\tthis._y = y;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._owner._selection & this._getSelection());\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis._owner.changeSelection(this._getSelection(), selected);\n\t},\n\n\t_getSelection: function() {\n\t\treturn this._setter === 'setPosition' ? 4 : 0;\n\t}\n});\n\nvar Size = Base.extend({\n\t_class: 'Size',\n\t_readIndex: true,\n\n\tinitialize: function Size(arg0, arg1) {\n\t\tvar type = typeof arg0,\n\t\t\treading = this.__read,\n\t\t\tread = 0;\n\t\tif (type === 'number') {\n\t\t\tvar hasHeight = typeof arg1 === 'number';\n\t\t\tthis._set(arg0, hasHeight ? arg1 : arg0);\n\t\t\tif (reading)\n\t\t\t\tread = hasHeight ? 2 : 1;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0);\n\t\t\tif (reading)\n\t\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else {\n\t\t\tvar obj = type === 'string' ? arg0.split(/[\\s,]+/) || [] : arg0;\n\t\t\tread = 1;\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\tthis._set(+obj[0], +(obj.length > 1 ? obj[1] : obj[0]));\n\t\t\t} else if ('width' in obj) {\n\t\t\t\tthis._set(obj.width || 0, obj.height || 0);\n\t\t\t} else if ('x' in obj) {\n\t\t\t\tthis._set(obj.x || 0, obj.y || 0);\n\t\t\t} else {\n\t\t\t\tthis._set(0, 0);\n\t\t\t\tread = 0;\n\t\t\t}\n\t\t}\n\t\tif (reading)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(width, height) {\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\treturn this;\n\t},\n\n\tequals: function(size) {\n\t\treturn size === this || size && (this.width === size.width\n\t\t\t\t&& this.height === size.height\n\t\t\t\t|| Array.isArray(size) && this.width === size[0]\n\t\t\t\t\t&& this.height === size[1]) || false;\n\t},\n\n\tclone: function() {\n\t\treturn new Size(this.width, this.height);\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ width: ' + f.number(this.width)\n\t\t\t\t+ ', height: ' + f.number(this.height) + ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.width),\n\t\t\t\tf.number(this.height)];\n\t},\n\n\tadd: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width + size.width, this.height + size.height);\n\t},\n\n\tsubtract: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width - size.width, this.height - size.height);\n\t},\n\n\tmultiply: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width * size.width, this.height * size.height);\n\t},\n\n\tdivide: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width / size.width, this.height / size.height);\n\t},\n\n\tmodulo: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width % size.width, this.height % size.height);\n\t},\n\n\tnegate: function() {\n\t\treturn new Size(-this.width, -this.height);\n\t},\n\n\tisZero: function() {\n\t\treturn Numerical.isZero(this.width) && Numerical.isZero(this.height);\n\t},\n\n\tisNaN: function() {\n\t\treturn isNaN(this.width) || isNaN(this.height);\n\t},\n\n\tstatics: {\n\t\tmin: function(size1, size2) {\n\t\t\treturn new Size(\n\t\t\t\tMath.min(size1.width, size2.width),\n\t\t\t\tMath.min(size1.height, size2.height));\n\t\t},\n\n\t\tmax: function(size1, size2) {\n\t\t\treturn new Size(\n\t\t\t\tMath.max(size1.width, size2.width),\n\t\t\t\tMath.max(size1.height, size2.height));\n\t\t},\n\n\t\trandom: function() {\n\t\t\treturn new Size(Math.random(), Math.random());\n\t\t}\n\t}\n}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {\n\tvar op = Math[key];\n\tthis[key] = function() {\n\t\treturn new Size(op(this.width), op(this.height));\n\t};\n}, {}));\n\nvar LinkedSize = Size.extend({\n\tinitialize: function Size(width, height, owner, setter) {\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(width, height, _dontNotify) {\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t},\n\n\tgetWidth: function() {\n\t\treturn this._width;\n\t},\n\n\tsetWidth: function(width) {\n\t\tthis._width = width;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tgetHeight: function() {\n\t\treturn this._height;\n\t},\n\n\tsetHeight: function(height) {\n\t\tthis._height = height;\n\t\tthis._owner[this._setter](this);\n\t}\n});\n\nvar Rectangle = Base.extend({\n\t_class: 'Rectangle',\n\t_readIndex: true,\n\tbeans: true,\n\n\tinitialize: function Rectangle(arg0, arg1, arg2, arg3) {\n\t\tvar type = typeof arg0,\n\t\t\tread;\n\t\tif (type === 'number') {\n\t\t\tthis._set(arg0, arg1, arg2, arg3);\n\t\t\tread = 4;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0, 0, 0);\n\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else if (arguments.length === 1) {\n\t\t\tif (Array.isArray(arg0)) {\n\t\t\t\tthis._set.apply(this, arg0);\n\t\t\t\tread = 1;\n\t\t\t} else if (arg0.x !== undefined || arg0.width !== undefined) {\n\t\t\t\tthis._set(arg0.x || 0, arg0.y || 0,\n\t\t\t\t\t\targ0.width || 0, arg0.height || 0);\n\t\t\t\tread = 1;\n\t\t\t} else if (arg0.from === undefined && arg0.to === undefined) {\n\t\t\t\tthis._set(0, 0, 0, 0);\n\t\t\t\tBase.filter(this, arg0);\n\t\t\t\tread = 1;\n\t\t\t}\n\t\t}\n\t\tif (read === undefined) {\n\t\t\tvar frm = Point.readNamed(arguments, 'from'),\n\t\t\t\tnext = Base.peek(arguments),\n\t\t\t\tx = frm.x,\n\t\t\t\ty = frm.y,\n\t\t\t\twidth,\n\t\t\t\theight;\n\t\t\tif (next && next.x !== undefined\n\t\t\t\t\t|| Base.hasNamed(arguments, 'to')) {\n\t\t\t\tvar to = Point.readNamed(arguments, 'to');\n\t\t\t\twidth = to.x - x;\n\t\t\t\theight = to.y - y;\n\t\t\t\tif (width < 0) {\n\t\t\t\t\tx = to.x;\n\t\t\t\t\twidth = -width;\n\t\t\t\t}\n\t\t\t\tif (height < 0) {\n\t\t\t\t\ty = to.y;\n\t\t\t\t\theight = -height;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar size = Size.read(arguments);\n\t\t\t\twidth = size.width;\n\t\t\t\theight = size.height;\n\t\t\t}\n\t\t\tthis._set(x, y, width, height);\n\t\t\tread = arguments.__index;\n\t\t}\n\t\tif (this.__read)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(x, y, width, height) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\treturn this;\n\t},\n\n\tclone: function() {\n\t\treturn new Rectangle(this.x, this.y, this.width, this.height);\n\t},\n\n\tequals: function(rect) {\n\t\tvar rt = Base.isPlainValue(rect)\n\t\t\t\t? Rectangle.read(arguments)\n\t\t\t\t: rect;\n\t\treturn rt === this\n\t\t\t\t|| rt && this.x === rt.x && this.y === rt.y\n\t\t\t\t\t&& this.width === rt.width && this.height === rt.height\n\t\t\t\t|| false;\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ x: ' + f.number(this.x)\n\t\t\t\t+ ', y: ' + f.number(this.y)\n\t\t\t\t+ ', width: ' + f.number(this.width)\n\t\t\t\t+ ', height: ' + f.number(this.height)\n\t\t\t\t+ ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.x),\n\t\t\t\tf.number(this.y),\n\t\t\t\tf.number(this.width),\n\t\t\t\tf.number(this.height)];\n\t},\n\n\tgetPoint: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\treturn new ctor(this.x, this.y, this, 'setPoint');\n\t},\n\n\tsetPoint: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.x = point.x;\n\t\tthis.y = point.y;\n\t},\n\n\tgetSize: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Size : LinkedSize;\n\t\treturn new ctor(this.width, this.height, this, 'setSize');\n\t},\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments);\n\t\tif (this._fixX)\n\t\t\tthis.x += (this.width - size.width) * this._fixX;\n\t\tif (this._fixY)\n\t\t\tthis.y += (this.height - size.height) * this._fixY;\n\t\tthis.width = size.width;\n\t\tthis.height = size.height;\n\t\tthis._fixW = 1;\n\t\tthis._fixH = 1;\n\t},\n\n\tgetLeft: function() {\n\t\treturn this.x;\n\t},\n\n\tsetLeft: function(left) {\n\t\tif (!this._fixW)\n\t\t\tthis.width -= left - this.x;\n\t\tthis.x = left;\n\t\tthis._fixX = 0;\n\t},\n\n\tgetTop: function() {\n\t\treturn this.y;\n\t},\n\n\tsetTop: function(top) {\n\t\tif (!this._fixH)\n\t\t\tthis.height -= top - this.y;\n\t\tthis.y = top;\n\t\tthis._fixY = 0;\n\t},\n\n\tgetRight: function() {\n\t\treturn this.x + this.width;\n\t},\n\n\tsetRight: function(right) {\n\t\tif (this._fixX !== undefined && this._fixX !== 1)\n\t\t\tthis._fixW = 0;\n\t\tif (this._fixW)\n\t\t\tthis.x = right - this.width;\n\t\telse\n\t\t\tthis.width = right - this.x;\n\t\tthis._fixX = 1;\n\t},\n\n\tgetBottom: function() {\n\t\treturn this.y + this.height;\n\t},\n\n\tsetBottom: function(bottom) {\n\t\tif (this._fixY !== undefined && this._fixY !== 1)\n\t\t\tthis._fixH = 0;\n\t\tif (this._fixH)\n\t\t\tthis.y = bottom - this.height;\n\t\telse\n\t\t\tthis.height = bottom - this.y;\n\t\tthis._fixY = 1;\n\t},\n\n\tgetCenterX: function() {\n\t\treturn this.x + this.width * 0.5;\n\t},\n\n\tsetCenterX: function(x) {\n\t\tthis.x = x - this.width * 0.5;\n\t\tthis._fixX = 0.5;\n\t},\n\n\tgetCenterY: function() {\n\t\treturn this.y + this.height * 0.5;\n\t},\n\n\tsetCenterY: function(y) {\n\t\tthis.y = y - this.height * 0.5;\n\t\tthis._fixY = 0.5;\n\t},\n\n\tgetCenter: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\treturn new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');\n\t},\n\n\tsetCenter: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.setCenterX(point.x);\n\t\tthis.setCenterY(point.y);\n\t\treturn this;\n\t},\n\n\tgetArea: function() {\n\t\treturn this.width * this.height;\n\t},\n\n\tisEmpty: function() {\n\t\treturn this.width === 0 || this.height === 0;\n\t},\n\n\tcontains: function(arg) {\n\t\treturn arg && arg.width !== undefined\n\t\t\t\t|| (Array.isArray(arg) ? arg : arguments).length === 4\n\t\t\t\t? this._containsRectangle(Rectangle.read(arguments))\n\t\t\t\t: this._containsPoint(Point.read(arguments));\n\t},\n\n\t_containsPoint: function(point) {\n\t\tvar x = point.x,\n\t\t\ty = point.y;\n\t\treturn x >= this.x && y >= this.y\n\t\t\t\t&& x <= this.x + this.width\n\t\t\t\t&& y <= this.y + this.height;\n\t},\n\n\t_containsRectangle: function(rect) {\n\t\tvar x = rect.x,\n\t\t\ty = rect.y;\n\t\treturn x >= this.x && y >= this.y\n\t\t\t\t&& x + rect.width <= this.x + this.width\n\t\t\t\t&& y + rect.height <= this.y + this.height;\n\t},\n\n\tintersects: function() {\n\t\tvar rect = Rectangle.read(arguments);\n\t\treturn rect.x + rect.width > this.x\n\t\t\t\t&& rect.y + rect.height > this.y\n\t\t\t\t&& rect.x < this.x + this.width\n\t\t\t\t&& rect.y < this.y + this.height;\n\t},\n\n\ttouches: function() {\n\t\tvar rect = Rectangle.read(arguments);\n\t\treturn rect.x + rect.width >= this.x\n\t\t\t\t&& rect.y + rect.height >= this.y\n\t\t\t\t&& rect.x <= this.x + this.width\n\t\t\t\t&& rect.y <= this.y + this.height;\n\t},\n\n\tintersect: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tx1 = Math.max(this.x, rect.x),\n\t\t\ty1 = Math.max(this.y, rect.y),\n\t\t\tx2 = Math.min(this.x + this.width, rect.x + rect.width),\n\t\t\ty2 = Math.min(this.y + this.height, rect.y + rect.height);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\tunite: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tx1 = Math.min(this.x, rect.x),\n\t\t\ty1 = Math.min(this.y, rect.y),\n\t\t\tx2 = Math.max(this.x + this.width, rect.x + rect.width),\n\t\t\ty2 = Math.max(this.y + this.height, rect.y + rect.height);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\tinclude: function() {\n\t\tvar point = Point.read(arguments);\n\t\tvar x1 = Math.min(this.x, point.x),\n\t\t\ty1 = Math.min(this.y, point.y),\n\t\t\tx2 = Math.max(this.x + this.width, point.x),\n\t\t\ty2 = Math.max(this.y + this.height, point.y);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\texpand: function() {\n\t\tvar amount = Size.read(arguments),\n\t\t\thor = amount.width,\n\t\t\tver = amount.height;\n\t\treturn new Rectangle(this.x - hor / 2, this.y - ver / 2,\n\t\t\t\tthis.width + hor, this.height + ver);\n\t},\n\n\tscale: function(hor, ver) {\n\t\treturn this.expand(this.width * hor - this.width,\n\t\t\t\tthis.height * (ver === undefined ? hor : ver) - this.height);\n\t}\n}, Base.each([\n\t\t['Top', 'Left'], ['Top', 'Right'],\n\t\t['Bottom', 'Left'], ['Bottom', 'Right'],\n\t\t['Left', 'Center'], ['Top', 'Center'],\n\t\t['Right', 'Center'], ['Bottom', 'Center']\n\t],\n\tfunction(parts, index) {\n\t\tvar part = parts.join(''),\n\t\t\txFirst = /^[RL]/.test(part);\n\t\tif (index >= 4)\n\t\t\tparts[1] += xFirst ? 'Y' : 'X';\n\t\tvar x = parts[xFirst ? 0 : 1],\n\t\t\ty = parts[xFirst ? 1 : 0],\n\t\t\tgetX = 'get' + x,\n\t\t\tgetY = 'get' + y,\n\t\t\tsetX = 'set' + x,\n\t\t\tsetY = 'set' + y,\n\t\t\tget = 'get' + part,\n\t\t\tset = 'set' + part;\n\t\tthis[get] = function(_dontLink) {\n\t\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\t\treturn new ctor(this[getX](), this[getY](), this, set);\n\t\t};\n\t\tthis[set] = function() {\n\t\t\tvar point = Point.read(arguments);\n\t\t\tthis[setX](point.x);\n\t\t\tthis[setY](point.y);\n\t\t};\n\t}, {\n\t\tbeans: true\n\t}\n));\n\nvar LinkedRectangle = Rectangle.extend({\n\tinitialize: function Rectangle(x, y, width, height, owner, setter) {\n\t\tthis._set(x, y, width, height, true);\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(x, y, width, height, _dontNotify) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t}\n},\nnew function() {\n\tvar proto = Rectangle.prototype;\n\n\treturn Base.each(['x', 'y', 'width', 'height'], function(key) {\n\t\tvar part = Base.capitalize(key),\n\t\t\tinternal = '_' + key;\n\t\tthis['get' + part] = function() {\n\t\t\treturn this[internal];\n\t\t};\n\n\t\tthis['set' + part] = function(value) {\n\t\t\tthis[internal] = value;\n\t\t\tif (!this._dontNotify)\n\t\t\t\tthis._owner[this._setter](this);\n\t\t};\n\t}, Base.each(['Point', 'Size', 'Center',\n\t\t\t'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',\n\t\t\t'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',\n\t\t\t'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],\n\t\tfunction(key) {\n\t\t\tvar name = 'set' + key;\n\t\t\tthis[name] = function() {\n\t\t\t\tthis._dontNotify = true;\n\t\t\t\tproto[name].apply(this, arguments);\n\t\t\t\tthis._dontNotify = false;\n\t\t\t\tthis._owner[this._setter](this);\n\t\t\t};\n\t\t}, {\n\t\t\tisSelected: function() {\n\t\t\t\treturn !!(this._owner._selection & 2);\n\t\t\t},\n\n\t\t\tsetSelected: function(selected) {\n\t\t\t\tvar owner = this._owner;\n\t\t\t\tif (owner.changeSelection) {\n\t\t\t\t\towner.changeSelection(2, selected);\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t);\n});\n\nvar Matrix = Base.extend({\n\t_class: 'Matrix',\n\n\tinitialize: function Matrix(arg) {\n\t\tvar count = arguments.length,\n\t\t\tok = true;\n\t\tif (count === 6) {\n\t\t\tthis._set.apply(this, arguments);\n\t\t} else if (count === 1) {\n\t\t\tif (arg instanceof Matrix) {\n\t\t\t\tthis._set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty);\n\t\t\t} else if (Array.isArray(arg)) {\n\t\t\t\tthis._set.apply(this, arg);\n\t\t\t} else {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t} else if (!count) {\n\t\t\tthis.reset();\n\t\t} else {\n\t\t\tok = false;\n\t\t}\n\t\tif (!ok) {\n\t\t\tthrow new Error('Unsupported matrix parameters');\n\t\t}\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(a, b, c, d, tx, ty, _dontNotify) {\n\t\tthis._a = a;\n\t\tthis._b = b;\n\t\tthis._c = c;\n\t\tthis._d = d;\n\t\tthis._tx = tx;\n\t\tthis._ty = ty;\n\t\tif (!_dontNotify)\n\t\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this.getValues(), options, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tvar owner = this._owner;\n\t\tif (owner) {\n\t\t\tif (owner._applyMatrix) {\n\t\t\t\towner.transform(null, true);\n\t\t\t} else {\n\t\t\t\towner._changed(9);\n\t\t\t}\n\t\t}\n\t},\n\n\tclone: function() {\n\t\treturn new Matrix(this._a, this._b, this._c, this._d,\n\t\t\t\tthis._tx, this._ty);\n\t},\n\n\tequals: function(mx) {\n\t\treturn mx === this || mx && this._a === mx._a && this._b === mx._b\n\t\t\t\t&& this._c === mx._c && this._d === mx._d\n\t\t\t\t&& this._tx === mx._tx && this._ty === mx._ty;\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '[[' + [f.number(this._a), f.number(this._c),\n\t\t\t\t\tf.number(this._tx)].join(', ') + '], ['\n\t\t\t\t+ [f.number(this._b), f.number(this._d),\n\t\t\t\t\tf.number(this._ty)].join(', ') + ']]';\n\t},\n\n\treset: function(_dontNotify) {\n\t\tthis._a = this._d = 1;\n\t\tthis._b = this._c = this._tx = this._ty = 0;\n\t\tif (!_dontNotify)\n\t\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tapply: function(recursively, _setApplyMatrix) {\n\t\tvar owner = this._owner;\n\t\tif (owner) {\n\t\t\towner.transform(null, true, Base.pick(recursively, true),\n\t\t\t\t\t_setApplyMatrix);\n\t\t\treturn this.isIdentity();\n\t\t}\n\t\treturn false;\n\t},\n\n\ttranslate: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tx = point.x,\n\t\t\ty = point.y;\n\t\tthis._tx += x * this._a + y * this._c;\n\t\tthis._ty += x * this._b + y * this._d;\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tscale: function() {\n\t\tvar scale = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\tif (center)\n\t\t\tthis.translate(center);\n\t\tthis._a *= scale.x;\n\t\tthis._b *= scale.x;\n\t\tthis._c *= scale.y;\n\t\tthis._d *= scale.y;\n\t\tif (center)\n\t\t\tthis.translate(center.negate());\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\trotate: function(angle ) {\n\t\tangle *= Math.PI / 180;\n\t\tvar center = Point.read(arguments, 1),\n\t\t\tx = center.x,\n\t\t\ty = center.y,\n\t\t\tcos = Math.cos(angle),\n\t\t\tsin = Math.sin(angle),\n\t\t\ttx = x - x * cos + y * sin,\n\t\t\tty = y - x * sin - y * cos,\n\t\t\ta = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d;\n\t\tthis._a = cos * a + sin * c;\n\t\tthis._b = cos * b + sin * d;\n\t\tthis._c = -sin * a + cos * c;\n\t\tthis._d = -sin * b + cos * d;\n\t\tthis._tx += tx * a + ty * c;\n\t\tthis._ty += tx * b + ty * d;\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tshear: function() {\n\t\tvar shear = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\tif (center)\n\t\t\tthis.translate(center);\n\t\tvar a = this._a,\n\t\t\tb = this._b;\n\t\tthis._a += shear.y * this._c;\n\t\tthis._b += shear.y * this._d;\n\t\tthis._c += shear.x * a;\n\t\tthis._d += shear.x * b;\n\t\tif (center)\n\t\t\tthis.translate(center.negate());\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tskew: function() {\n\t\tvar skew = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true }),\n\t\t\ttoRadians = Math.PI / 180,\n\t\t\tshear = new Point(Math.tan(skew.x * toRadians),\n\t\t\t\tMath.tan(skew.y * toRadians));\n\t\treturn this.shear(shear, center);\n\t},\n\n\tappend: function(mx) {\n\t\tif (mx) {\n\t\t\tvar a1 = this._a,\n\t\t\t\tb1 = this._b,\n\t\t\t\tc1 = this._c,\n\t\t\t\td1 = this._d,\n\t\t\t\ta2 = mx._a,\n\t\t\t\tb2 = mx._c,\n\t\t\t\tc2 = mx._b,\n\t\t\t\td2 = mx._d,\n\t\t\t\ttx2 = mx._tx,\n\t\t\t\tty2 = mx._ty;\n\t\t\tthis._a = a2 * a1 + c2 * c1;\n\t\t\tthis._c = b2 * a1 + d2 * c1;\n\t\t\tthis._b = a2 * b1 + c2 * d1;\n\t\t\tthis._d = b2 * b1 + d2 * d1;\n\t\t\tthis._tx += tx2 * a1 + ty2 * c1;\n\t\t\tthis._ty += tx2 * b1 + ty2 * d1;\n\t\t\tthis._changed();\n\t\t}\n\t\treturn this;\n\t},\n\n\tprepend: function(mx) {\n\t\tif (mx) {\n\t\t\tvar a1 = this._a,\n\t\t\t\tb1 = this._b,\n\t\t\t\tc1 = this._c,\n\t\t\t\td1 = this._d,\n\t\t\t\ttx1 = this._tx,\n\t\t\t\tty1 = this._ty,\n\t\t\t\ta2 = mx._a,\n\t\t\t\tb2 = mx._c,\n\t\t\t\tc2 = mx._b,\n\t\t\t\td2 = mx._d,\n\t\t\t\ttx2 = mx._tx,\n\t\t\t\tty2 = mx._ty;\n\t\t\tthis._a = a2 * a1 + b2 * b1;\n\t\t\tthis._c = a2 * c1 + b2 * d1;\n\t\t\tthis._b = c2 * a1 + d2 * b1;\n\t\t\tthis._d = c2 * c1 + d2 * d1;\n\t\t\tthis._tx = a2 * tx1 + b2 * ty1 + tx2;\n\t\t\tthis._ty = c2 * tx1 + d2 * ty1 + ty2;\n\t\t\tthis._changed();\n\t\t}\n\t\treturn this;\n\t},\n\n\tappended: function(mx) {\n\t\treturn this.clone().append(mx);\n\t},\n\n\tprepended: function(mx) {\n\t\treturn this.clone().prepend(mx);\n\t},\n\n\tinvert: function() {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\ttx = this._tx,\n\t\t\tty = this._ty,\n\t\t\tdet = a * d - b * c,\n\t\t\tres = null;\n\t\tif (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {\n\t\t\tthis._a = d / det;\n\t\t\tthis._b = -b / det;\n\t\t\tthis._c = -c / det;\n\t\t\tthis._d = a / det;\n\t\t\tthis._tx = (c * ty - d * tx) / det;\n\t\t\tthis._ty = (b * tx - a * ty) / det;\n\t\t\tres = this;\n\t\t}\n\t\treturn res;\n\t},\n\n\tinverted: function() {\n\t\treturn this.clone().invert();\n\t},\n\n\tconcatenate: '#append',\n\tpreConcatenate: '#prepend',\n\tchain: '#appended',\n\n\t_shiftless: function() {\n\t\treturn new Matrix(this._a, this._b, this._c, this._d, 0, 0);\n\t},\n\n\t_orNullIfIdentity: function() {\n\t\treturn this.isIdentity() ? null : this;\n\t},\n\n\tisIdentity: function() {\n\t\treturn this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1\n\t\t\t\t&& this._tx === 0 && this._ty === 0;\n\t},\n\n\tisInvertible: function() {\n\t\tvar det = this._a * this._d - this._c * this._b;\n\t\treturn det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty);\n\t},\n\n\tisSingular: function() {\n\t\treturn !this.isInvertible();\n\t},\n\n\ttransform: function( src, dst, count) {\n\t\treturn arguments.length < 3\n\t\t\t? this._transformPoint(Point.read(arguments))\n\t\t\t: this._transformCoordinates(src, dst, count);\n\t},\n\n\t_transformPoint: function(point, dest, _dontNotify) {\n\t\tvar x = point.x,\n\t\t\ty = point.y;\n\t\tif (!dest)\n\t\t\tdest = new Point();\n\t\treturn dest._set(\n\t\t\t\tx * this._a + y * this._c + this._tx,\n\t\t\t\tx * this._b + y * this._d + this._ty,\n\t\t\t\t_dontNotify);\n\t},\n\n\t_transformCoordinates: function(src, dst, count) {\n\t\tfor (var i = 0, max = 2 * count; i < max; i += 2) {\n\t\t\tvar x = src[i],\n\t\t\t\ty = src[i + 1];\n\t\t\tdst[i] = x * this._a + y * this._c + this._tx;\n\t\t\tdst[i + 1] = x * this._b + y * this._d + this._ty;\n\t\t}\n\t\treturn dst;\n\t},\n\n\t_transformCorners: function(rect) {\n\t\tvar x1 = rect.x,\n\t\t\ty1 = rect.y,\n\t\t\tx2 = x1 + rect.width,\n\t\t\ty2 = y1 + rect.height,\n\t\t\tcoords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];\n\t\treturn this._transformCoordinates(coords, coords, 4);\n\t},\n\n\t_transformBounds: function(bounds, dest, _dontNotify) {\n\t\tvar coords = this._transformCorners(bounds),\n\t\t\tmin = coords.slice(0, 2),\n\t\t\tmax = min.slice();\n\t\tfor (var i = 2; i < 8; i++) {\n\t\t\tvar val = coords[i],\n\t\t\t\tj = i & 1;\n\t\t\tif (val < min[j]) {\n\t\t\t\tmin[j] = val;\n\t\t\t} else if (val > max[j]) {\n\t\t\t\tmax[j] = val;\n\t\t\t}\n\t\t}\n\t\tif (!dest)\n\t\t\tdest = new Rectangle();\n\t\treturn dest._set(min[0], min[1], max[0] - min[0], max[1] - min[1],\n\t\t\t\t_dontNotify);\n\t},\n\n\tinverseTransform: function() {\n\t\treturn this._inverseTransform(Point.read(arguments));\n\t},\n\n\t_inverseTransform: function(point, dest, _dontNotify) {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\ttx = this._tx,\n\t\t\tty = this._ty,\n\t\t\tdet = a * d - b * c,\n\t\t\tres = null;\n\t\tif (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {\n\t\t\tvar x = point.x - this._tx,\n\t\t\t\ty = point.y - this._ty;\n\t\t\tif (!dest)\n\t\t\t\tdest = new Point();\n\t\t\tres = dest._set(\n\t\t\t\t\t(x * d - y * c) / det,\n\t\t\t\t\t(y * a - x * b) / det,\n\t\t\t\t\t_dontNotify);\n\t\t}\n\t\treturn res;\n\t},\n\n\tdecompose: function() {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\tdet = a * d - b * c,\n\t\t\tsqrt = Math.sqrt,\n\t\t\tatan2 = Math.atan2,\n\t\t\tdegrees = 180 / Math.PI,\n\t\t\trotate,\n\t\t\tscale,\n\t\t\tskew;\n\t\tif (a !== 0 || b !== 0) {\n\t\t\tvar r = sqrt(a * a + b * b);\n\t\t\trotate = Math.acos(a / r) * (b > 0 ? 1 : -1);\n\t\t\tscale = [r, det / r];\n\t\t\tskew = [atan2(a * c + b * d, r * r), 0];\n\t\t} else if (c !== 0 || d !== 0) {\n\t\t\tvar s = sqrt(c * c + d * d);\n\t\t\trotate = Math.asin(c / s) * (d > 0 ? 1 : -1);\n\t\t\tscale = [det / s, s];\n\t\t\tskew = [0, atan2(a * c + b * d, s * s)];\n\t\t} else {\n\t\t\trotate = 0;\n\t\t\tskew = scale = [0, 0];\n\t\t}\n\t\treturn {\n\t\t\ttranslation: this.getTranslation(),\n\t\t\trotation: rotate * degrees,\n\t\t\tscaling: new Point(scale),\n\t\t\tskewing: new Point(skew[0] * degrees, skew[1] * degrees)\n\t\t};\n\t},\n\n\tgetValues: function() {\n\t\treturn [ this._a, this._b, this._c, this._d, this._tx, this._ty ];\n\t},\n\n\tgetTranslation: function() {\n\t\treturn new Point(this._tx, this._ty);\n\t},\n\n\tgetScaling: function() {\n\t\treturn (this.decompose() || {}).scaling;\n\t},\n\n\tgetRotation: function() {\n\t\treturn (this.decompose() || {}).rotation;\n\t},\n\n\tapplyToContext: function(ctx) {\n\t\tif (!this.isIdentity()) {\n\t\t\tctx.transform(this._a, this._b, this._c, this._d,\n\t\t\t\t\tthis._tx, this._ty);\n\t\t}\n\t}\n}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) {\n\tvar part = Base.capitalize(key),\n\t\tprop = '_' + key;\n\tthis['get' + part] = function() {\n\t\treturn this[prop];\n\t};\n\tthis['set' + part] = function(value) {\n\t\tthis[prop] = value;\n\t\tthis._changed();\n\t};\n}, {}));\n\nvar Line = Base.extend({\n\t_class: 'Line',\n\n\tinitialize: function Line(arg0, arg1, arg2, arg3, arg4) {\n\t\tvar asVector = false;\n\t\tif (arguments.length >= 4) {\n\t\t\tthis._px = arg0;\n\t\t\tthis._py = arg1;\n\t\t\tthis._vx = arg2;\n\t\t\tthis._vy = arg3;\n\t\t\tasVector = arg4;\n\t\t} else {\n\t\t\tthis._px = arg0.x;\n\t\t\tthis._py = arg0.y;\n\t\t\tthis._vx = arg1.x;\n\t\t\tthis._vy = arg1.y;\n\t\t\tasVector = arg2;\n\t\t}\n\t\tif (!asVector) {\n\t\t\tthis._vx -= this._px;\n\t\t\tthis._vy -= this._py;\n\t\t}\n\t},\n\n\tgetPoint: function() {\n\t\treturn new Point(this._px, this._py);\n\t},\n\n\tgetVector: function() {\n\t\treturn new Point(this._vx, this._vy);\n\t},\n\n\tgetLength: function() {\n\t\treturn this.getVector().getLength();\n\t},\n\n\tintersect: function(line, isInfinite) {\n\t\treturn Line.intersect(\n\t\t\t\tthis._px, this._py, this._vx, this._vy,\n\t\t\t\tline._px, line._py, line._vx, line._vy,\n\t\t\t\ttrue, isInfinite);\n\t},\n\n\tgetSide: function(point, isInfinite) {\n\t\treturn Line.getSide(\n\t\t\t\tthis._px, this._py, this._vx, this._vy,\n\t\t\t\tpoint.x, point.y, true, isInfinite);\n\t},\n\n\tgetDistance: function(point) {\n\t\treturn Math.abs(Line.getSignedDistance(\n\t\t\t\tthis._px, this._py, this._vx, this._vy,\n\t\t\t\tpoint.x, point.y, true));\n\t},\n\n\tisCollinear: function(line) {\n\t\treturn Point.isCollinear(this._vx, this._vy, line._vx, line._vy);\n\t},\n\n\tisOrthogonal: function(line) {\n\t\treturn Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);\n\t},\n\n\tstatics: {\n\t\tintersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,\n\t\t\t\tisInfinite) {\n\t\t\tif (!asVector) {\n\t\t\t\tv1x -= p1x;\n\t\t\t\tv1y -= p1y;\n\t\t\t\tv2x -= p2x;\n\t\t\t\tv2y -= p2y;\n\t\t\t}\n\t\t\tvar cross = v1x * v2y - v1y * v2x;\n\t\t\tif (!Numerical.isZero(cross)) {\n\t\t\t\tvar dx = p1x - p2x,\n\t\t\t\t\tdy = p1y - p2y,\n\t\t\t\t\tu1 = (v2x * dy - v2y * dx) / cross,\n\t\t\t\t\tu2 = (v1x * dy - v1y * dx) / cross,\n\t\t\t\t\tepsilon = 1e-12,\n\t\t\t\t\tuMin = -epsilon,\n\t\t\t\t\tuMax = 1 + epsilon;\n\t\t\t\tif (isInfinite\n\t\t\t\t\t\t|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {\n\t\t\t\t\tif (!isInfinite) {\n\t\t\t\t\t\tu1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;\n\t\t\t\t\t}\n\t\t\t\t\treturn new Point(\n\t\t\t\t\t\t\tp1x + u1 * v1x,\n\t\t\t\t\t\t\tp1y + u1 * v1y);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tgetSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {\n\t\t\tif (!asVector) {\n\t\t\t\tvx -= px;\n\t\t\t\tvy -= py;\n\t\t\t}\n\t\t\tvar v2x = x - px,\n\t\t\t\tv2y = y - py,\n\t\t\t\tccw = v2x * vy - v2y * vx;\n\t\t\tif (ccw === 0 && !isInfinite) {\n\t\t\t\tccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);\n\t\t\t\tif (ccw >= 0 && ccw <= 1)\n\t\t\t\t\tccw = 0;\n\t\t\t}\n\t\t\treturn ccw < 0 ? -1 : ccw > 0 ? 1 : 0;\n\t\t},\n\n\t\tgetSignedDistance: function(px, py, vx, vy, x, y, asVector) {\n\t\t\tif (!asVector) {\n\t\t\t\tvx -= px;\n\t\t\t\tvy -= py;\n\t\t\t}\n\t\t\treturn vx === 0 ? vy > 0 ? x - px : px - x\n\t\t\t\t : vy === 0 ? vx < 0 ? y - py : py - y\n\t\t\t\t : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);\n\t\t}\n\t}\n});\n\nvar Project = PaperScopeItem.extend({\n\t_class: 'Project',\n\t_list: 'projects',\n\t_reference: 'project',\n\t_compactSerialize: true,\n\n\tinitialize: function Project(element) {\n\t\tPaperScopeItem.call(this, true);\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tthis._activeLayer = null;\n\t\tthis._currentStyle = new Style(null, null, this);\n\t\tthis._view = View.create(this,\n\t\t\t\telement || CanvasProvider.getCanvas(1, 1));\n\t\tthis._selectionItems = {};\n\t\tthis._selectionCount = 0;\n\t\tthis._updateVersion = 0;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this._children, options, true, dictionary);\n\t},\n\n\t_changed: function(flags, item) {\n\t\tif (flags & 1) {\n\t\t\tvar view = this._view;\n\t\t\tif (view) {\n\t\t\t\tview._needsUpdate = true;\n\t\t\t\tif (!view._requested && view._autoUpdate)\n\t\t\t\t\tview.requestUpdate();\n\t\t\t}\n\t\t}\n\t\tvar changes = this._changes;\n\t\tif (changes && item) {\n\t\t\tvar changesById = this._changesById,\n\t\t\t\tid = item._id,\n\t\t\t\tentry = changesById[id];\n\t\t\tif (entry) {\n\t\t\t\tentry.flags |= flags;\n\t\t\t} else {\n\t\t\t\tchanges.push(changesById[id] = { item: item, flags: flags });\n\t\t\t}\n\t\t}\n\t},\n\n\tclear: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = children.length - 1; i >= 0; i--)\n\t\t\tchildren[i].remove();\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._children.length;\n\t},\n\n\tremove: function remove() {\n\t\tif (!remove.base.call(this))\n\t\t\treturn false;\n\t\tif (this._view)\n\t\t\tthis._view.remove();\n\t\treturn true;\n\t},\n\n\tgetView: function() {\n\t\treturn this._view;\n\t},\n\n\tgetCurrentStyle: function() {\n\t\treturn this._currentStyle;\n\t},\n\n\tsetCurrentStyle: function(style) {\n\t\tthis._currentStyle.set(style);\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index;\n\t},\n\n\tgetOptions: function() {\n\t\treturn this._scope.settings;\n\t},\n\n\tgetLayers: function() {\n\t\treturn this._children;\n\t},\n\n\tgetActiveLayer: function() {\n\t\treturn this._activeLayer || new Layer({ project: this, insert: true });\n\t},\n\n\tgetSymbolDefinitions: function() {\n\t\tvar definitions = [],\n\t\t\tids = {};\n\t\tthis.getItems({\n\t\t\tclass: SymbolItem,\n\t\t\tmatch: function(item) {\n\t\t\t\tvar definition = item._definition,\n\t\t\t\t\tid = definition._id;\n\t\t\t\tif (!ids[id]) {\n\t\t\t\t\tids[id] = true;\n\t\t\t\t\tdefinitions.push(definition);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\treturn definitions;\n\t},\n\n\tgetSymbols: 'getSymbolDefinitions',\n\n\tgetSelectedItems: function() {\n\t\tvar selectionItems = this._selectionItems,\n\t\t\titems = [];\n\t\tfor (var id in selectionItems) {\n\t\t\tvar item = selectionItems[id],\n\t\t\t\tselection = item._selection;\n\t\t\tif (selection & 1 && item.isInserted()) {\n\t\t\t\titems.push(item);\n\t\t\t} else if (!selection) {\n\t\t\t\tthis._updateSelection(item);\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t},\n\n\t_updateSelection: function(item) {\n\t\tvar id = item._id,\n\t\t\tselectionItems = this._selectionItems;\n\t\tif (item._selection) {\n\t\t\tif (selectionItems[id] !== item) {\n\t\t\t\tthis._selectionCount++;\n\t\t\t\tselectionItems[id] = item;\n\t\t\t}\n\t\t} else if (selectionItems[id] === item) {\n\t\t\tthis._selectionCount--;\n\t\t\tdelete selectionItems[id];\n\t\t}\n\t},\n\n\tselectAll: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tchildren[i].setFullySelected(true);\n\t},\n\n\tdeselectAll: function() {\n\t\tvar selectionItems = this._selectionItems;\n\t\tfor (var i in selectionItems)\n\t\t\tselectionItems[i].setFullySelected(false);\n\t},\n\n\taddLayer: function(layer) {\n\t\treturn this.insertLayer(undefined, layer);\n\t},\n\n\tinsertLayer: function(index, layer) {\n\t\tif (layer instanceof Layer) {\n\t\t\tlayer._remove(false, true);\n\t\t\tBase.splice(this._children, [layer], index, 0);\n\t\t\tlayer._setProject(this, true);\n\t\t\tvar name = layer._name;\n\t\t\tif (name)\n\t\t\t\tlayer.setName(name);\n\t\t\tif (this._changes)\n\t\t\t\tlayer._changed(5);\n\t\t\tif (!this._activeLayer)\n\t\t\t\tthis._activeLayer = layer;\n\t\t} else {\n\t\t\tlayer = null;\n\t\t}\n\t\treturn layer;\n\t},\n\n\t_insertItem: function(index, item, _created) {\n\t\titem = this.insertLayer(index, item)\n\t\t\t\t|| (this._activeLayer || this._insertItem(undefined,\n\t\t\t\t\t\tnew Layer(Item.NO_INSERT), true))\n\t\t\t\t\t\t.insertChild(index, item);\n\t\tif (_created && item.activate)\n\t\t\titem.activate();\n\t\treturn item;\n\t},\n\n\tgetItems: function(options) {\n\t\treturn Item._getItems(this, options);\n\t},\n\n\tgetItem: function(options) {\n\t\treturn Item._getItems(this, options, null, null, true)[0] || null;\n\t},\n\n\timportJSON: function(json) {\n\t\tthis.activate();\n\t\tvar layer = this._activeLayer;\n\t\treturn Base.importJSON(json, layer && layer.isEmpty() && layer);\n\t},\n\n\tremoveOn: function(type) {\n\t\tvar sets = this._removeSets;\n\t\tif (sets) {\n\t\t\tif (type === 'mouseup')\n\t\t\t\tsets.mousedrag = null;\n\t\t\tvar set = sets[type];\n\t\t\tif (set) {\n\t\t\t\tfor (var id in set) {\n\t\t\t\t\tvar item = set[id];\n\t\t\t\t\tfor (var key in sets) {\n\t\t\t\t\t\tvar other = sets[key];\n\t\t\t\t\t\tif (other && other != set)\n\t\t\t\t\t\t\tdelete other[item._id];\n\t\t\t\t\t}\n\t\t\t\t\titem.remove();\n\t\t\t\t}\n\t\t\t\tsets[type] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\tdraw: function(ctx, matrix, pixelRatio) {\n\t\tthis._updateVersion++;\n\t\tctx.save();\n\t\tmatrix.applyToContext(ctx);\n\t\tvar children = this._children,\n\t\t\tparam = new Base({\n\t\t\t\toffset: new Point(0, 0),\n\t\t\t\tpixelRatio: pixelRatio,\n\t\t\t\tviewMatrix: matrix.isIdentity() ? null : matrix,\n\t\t\t\tmatrices: [new Matrix()],\n\t\t\t\tupdateMatrix: true\n\t\t\t});\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tchildren[i].draw(ctx, param);\n\t\t}\n\t\tctx.restore();\n\n\t\tif (this._selectionCount > 0) {\n\t\t\tctx.save();\n\t\t\tctx.strokeWidth = 1;\n\t\t\tvar items = this._selectionItems,\n\t\t\t\tsize = this._scope.settings.handleSize,\n\t\t\t\tversion = this._updateVersion;\n\t\t\tfor (var id in items) {\n\t\t\t\titems[id]._drawSelection(ctx, matrix, size, items, version);\n\t\t\t}\n\t\t\tctx.restore();\n\t\t}\n\t}\n});\n\nvar Item = Base.extend(Emitter, {\n\tstatics: {\n\t\textend: function extend(src) {\n\t\t\tif (src._serializeFields)\n\t\t\t\tsrc._serializeFields = Base.set({},\n\t\t\t\t\tthis.prototype._serializeFields, src._serializeFields);\n\t\t\treturn extend.base.apply(this, arguments);\n\t\t},\n\n\t\tNO_INSERT: { insert: false }\n\t},\n\n\t_class: 'Item',\n\t_name: null,\n\t_applyMatrix: true,\n\t_canApplyMatrix: true,\n\t_canScaleStroke: false,\n\t_pivot: null,\n\t_visible: true,\n\t_blendMode: 'normal',\n\t_opacity: 1,\n\t_locked: false,\n\t_guide: false,\n\t_clipMask: false,\n\t_selection: 0,\n\t_selectBounds: true,\n\t_selectChildren: false,\n\t_serializeFields: {\n\t\tname: null,\n\t\tapplyMatrix: null,\n\t\tmatrix: new Matrix(),\n\t\tpivot: null,\n\t\tvisible: true,\n\t\tblendMode: 'normal',\n\t\topacity: 1,\n\t\tlocked: false,\n\t\tguide: false,\n\t\tclipMask: false,\n\t\tselected: false,\n\t\tdata: {}\n\t},\n\t_prioritize: ['applyMatrix']\n},\nnew function() {\n\tvar handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',\n\t\t\t'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'];\n\treturn Base.each(handlers,\n\t\tfunction(name) {\n\t\t\tthis._events[name] = {\n\t\t\t\tinstall: function(type) {\n\t\t\t\t\tthis.getView()._countItemEvent(type, 1);\n\t\t\t\t},\n\n\t\t\t\tuninstall: function(type) {\n\t\t\t\t\tthis.getView()._countItemEvent(type, -1);\n\t\t\t\t}\n\t\t\t};\n\t\t}, {\n\t\t\t_events: {\n\t\t\t\tonFrame: {\n\t\t\t\t\tinstall: function() {\n\t\t\t\t\t\tthis.getView()._animateItem(this, true);\n\t\t\t\t\t},\n\n\t\t\t\t\tuninstall: function() {\n\t\t\t\t\t\tthis.getView()._animateItem(this, false);\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tonLoad: {},\n\t\t\t\tonError: {}\n\t\t\t},\n\t\t\tstatics: {\n\t\t\t\t_itemHandlers: handlers\n\t\t\t}\n\t\t}\n\t);\n}, {\n\tinitialize: function Item() {\n\t},\n\n\t_initialize: function(props, point) {\n\t\tvar hasProps = props && Base.isPlainObject(props),\n\t\t\tinternal = hasProps && props.internal === true,\n\t\t\tmatrix = this._matrix = new Matrix(),\n\t\t\tproject = hasProps && props.project || paper.project,\n\t\t\tsettings = paper.settings;\n\t\tthis._id = internal ? null : UID.get();\n\t\tthis._parent = this._index = null;\n\t\tthis._applyMatrix = this._canApplyMatrix && settings.applyMatrix;\n\t\tif (point)\n\t\t\tmatrix.translate(point);\n\t\tmatrix._owner = this;\n\t\tthis._style = new Style(project._currentStyle, this, project);\n\t\tif (internal || hasProps && props.insert === false\n\t\t\t|| !settings.insertItems && !(hasProps && props.insert === true)) {\n\t\t\tthis._setProject(project);\n\t\t} else {\n\t\t\t(hasProps && props.parent || project)\n\t\t\t\t\t._insertItem(undefined, this, true);\n\t\t}\n\t\tif (hasProps && props !== Item.NO_INSERT) {\n\t\t\tthis.set(props, {\n\t\t\t\tinternal: true, insert: true, project: true, parent: true\n\t\t\t});\n\t\t}\n\t\treturn hasProps;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar props = {},\n\t\t\tthat = this;\n\n\t\tfunction serialize(fields) {\n\t\t\tfor (var key in fields) {\n\t\t\t\tvar value = that[key];\n\t\t\t\tif (!Base.equals(value, key === 'leading'\n\t\t\t\t\t\t? fields.fontSize * 1.2 : fields[key])) {\n\t\t\t\t\tprops[key] = Base.serialize(value, options,\n\t\t\t\t\t\t\tkey !== 'data', dictionary);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tserialize(this._serializeFields);\n\t\tif (!(this instanceof Group))\n\t\t\tserialize(this._style._defaults);\n\t\treturn [ this._class, props ];\n\t},\n\n\t_changed: function(flags) {\n\t\tvar symbol = this._symbol,\n\t\t\tcacheParent = this._parent || symbol,\n\t\t\tproject = this._project;\n\t\tif (flags & 8) {\n\t\t\tthis._bounds = this._position = this._decomposed =\n\t\t\t\t\tthis._globalMatrix = undefined;\n\t\t}\n\t\tif (cacheParent\n\t\t\t\t&& (flags & 40)) {\n\t\t\tItem._clearBoundsCache(cacheParent);\n\t\t}\n\t\tif (flags & 2) {\n\t\t\tItem._clearBoundsCache(this);\n\t\t}\n\t\tif (project)\n\t\t\tproject._changed(flags, this);\n\t\tif (symbol)\n\t\t\tsymbol._changed(flags);\n\t},\n\n\tgetId: function() {\n\t\treturn this._id;\n\t},\n\n\tgetName: function() {\n\t\treturn this._name;\n\t},\n\n\tsetName: function(name) {\n\n\t\tif (this._name)\n\t\t\tthis._removeNamed();\n\t\tif (name === (+name) + '')\n\t\t\tthrow new Error(\n\t\t\t\t\t'Names consisting only of numbers are not supported.');\n\t\tvar owner = this._getOwner();\n\t\tif (name && owner) {\n\t\t\tvar children = owner._children,\n\t\t\t\tnamedChildren = owner._namedChildren;\n\t\t\t(namedChildren[name] = namedChildren[name] || []).push(this);\n\t\t\tif (!(name in children))\n\t\t\t\tchildren[name] = this;\n\t\t}\n\t\tthis._name = name || undefined;\n\t\tthis._changed(128);\n\t},\n\n\tgetStyle: function() {\n\t\treturn this._style;\n\t},\n\n\tsetStyle: function(style) {\n\t\tthis.getStyle().set(style);\n\t}\n}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],\n\tfunction(name) {\n\t\tvar part = Base.capitalize(name),\n\t\t\tname = '_' + name;\n\t\tthis['get' + part] = function() {\n\t\t\treturn this[name];\n\t\t};\n\t\tthis['set' + part] = function(value) {\n\t\t\tif (value != this[name]) {\n\t\t\t\tthis[name] = value;\n\t\t\t\tthis._changed(name === '_locked'\n\t\t\t\t\t\t? 128 : 129);\n\t\t\t}\n\t\t};\n\t},\n{}), {\n\tbeans: true,\n\n\tgetSelection: function() {\n\t\treturn this._selection;\n\t},\n\n\tsetSelection: function(selection) {\n\t\tif (selection !== this._selection) {\n\t\t\tthis._selection = selection;\n\t\t\tvar project = this._project;\n\t\t\tif (project) {\n\t\t\t\tproject._updateSelection(this);\n\t\t\t\tthis._changed(129);\n\t\t\t}\n\t\t}\n\t},\n\n\tchangeSelection: function(flag, selected) {\n\t\tvar selection = this._selection;\n\t\tthis.setSelection(selected ? selection | flag : selection & ~flag);\n\t},\n\n\tisSelected: function() {\n\t\tif (this._selectChildren) {\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tif (children[i].isSelected())\n\t\t\t\t\treturn true;\n\t\t}\n\t\treturn !!(this._selection & 1);\n\t},\n\n\tsetSelected: function(selected) {\n\t\tif (this._selectChildren) {\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].setSelected(selected);\n\t\t}\n\t\tthis.changeSelection(1, selected);\n\t},\n\n\tisFullySelected: function() {\n\t\tvar children = this._children,\n\t\t\tselected = !!(this._selection & 1);\n\t\tif (children && selected) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tif (!children[i].isFullySelected())\n\t\t\t\t\treturn false;\n\t\t\treturn true;\n\t\t}\n\t\treturn selected;\n\t},\n\n\tsetFullySelected: function(selected) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].setFullySelected(selected);\n\t\t}\n\t\tthis.changeSelection(1, selected);\n\t},\n\n\tisClipMask: function() {\n\t\treturn this._clipMask;\n\t},\n\n\tsetClipMask: function(clipMask) {\n\t\tif (this._clipMask != (clipMask = !!clipMask)) {\n\t\t\tthis._clipMask = clipMask;\n\t\t\tif (clipMask) {\n\t\t\t\tthis.setFillColor(null);\n\t\t\t\tthis.setStrokeColor(null);\n\t\t\t}\n\t\t\tthis._changed(129);\n\t\t\tif (this._parent)\n\t\t\t\tthis._parent._changed(1024);\n\t\t}\n\t},\n\n\tgetData: function() {\n\t\tif (!this._data)\n\t\t\tthis._data = {};\n\t\treturn this._data;\n\t},\n\n\tsetData: function(data) {\n\t\tthis._data = data;\n\t},\n\n\tgetPosition: function(_dontLink) {\n\t\tvar position = this._position,\n\t\t\tctor = _dontLink ? Point : LinkedPoint;\n\t\tif (!position) {\n\t\t\tvar pivot = this._pivot;\n\t\t\tposition = this._position = pivot\n\t\t\t\t\t? this._matrix._transformPoint(pivot)\n\t\t\t\t\t: this.getBounds().getCenter(true);\n\t\t}\n\t\treturn new ctor(position.x, position.y, this, 'setPosition');\n\t},\n\n\tsetPosition: function() {\n\t\tthis.translate(Point.read(arguments).subtract(this.getPosition(true)));\n\t},\n\n\tgetPivot: function() {\n\t\tvar pivot = this._pivot;\n\t\treturn pivot\n\t\t\t\t? new LinkedPoint(pivot.x, pivot.y, this, 'setPivot')\n\t\t\t\t: null;\n\t},\n\n\tsetPivot: function() {\n\t\tthis._pivot = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tthis._position = undefined;\n\t}\n}, Base.each({\n\t\tgetStrokeBounds: { stroke: true },\n\t\tgetHandleBounds: { handle: true },\n\t\tgetInternalBounds: { internal: true }\n\t},\n\tfunction(options, key) {\n\t\tthis[key] = function(matrix) {\n\t\t\treturn this.getBounds(matrix, options);\n\t\t};\n\t},\n{\n\tbeans: true,\n\n\tgetBounds: function(matrix, options) {\n\t\tvar hasMatrix = options || matrix instanceof Matrix,\n\t\t\topts = Base.set({}, hasMatrix ? options : matrix,\n\t\t\t\t\tthis._boundsOptions);\n\t\tif (!opts.stroke || this.getStrokeScaling())\n\t\t\topts.cacheItem = this;\n\t\tvar bounds = this._getCachedBounds(hasMatrix && matrix, opts);\n\t\treturn !arguments.length\n\t\t\t\t? new LinkedRectangle(bounds.x, bounds.y, bounds.width,\n\t\t\t\t\t\tbounds.height, this, 'setBounds')\n\t\t\t\t: bounds;\n\t},\n\n\tsetBounds: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tbounds = this.getBounds(),\n\t\t\t_matrix = this._matrix,\n\t\t\tmatrix = new Matrix(),\n\t\t\tcenter = rect.getCenter();\n\t\tmatrix.translate(center);\n\t\tif (rect.width != bounds.width || rect.height != bounds.height) {\n\t\t\tif (!_matrix.isInvertible()) {\n\t\t\t\t_matrix.set(_matrix._backup\n\t\t\t\t\t\t|| new Matrix().translate(_matrix.getTranslation()));\n\t\t\t\tbounds = this.getBounds();\n\t\t\t}\n\t\t\tmatrix.scale(\n\t\t\t\t\tbounds.width !== 0 ? rect.width / bounds.width : 0,\n\t\t\t\t\tbounds.height !== 0 ? rect.height / bounds.height : 0);\n\t\t}\n\t\tcenter = bounds.getCenter();\n\t\tmatrix.translate(-center.x, -center.y);\n\t\tthis.transform(matrix);\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar children = this._children;\n\t\tif (!children || !children.length)\n\t\t\treturn new Rectangle();\n\t\tItem._updateBoundsCache(this, options.cacheItem);\n\t\treturn Item._getBounds(children, matrix, options);\n\t},\n\n\t_getCachedBounds: function(matrix, options) {\n\t\tmatrix = matrix && matrix._orNullIfIdentity();\n\t\tvar internal = options.internal,\n\t\t\tcacheItem = options.cacheItem,\n\t\t\t_matrix = internal ? null : this._matrix._orNullIfIdentity(),\n\t\t\tcacheKey = cacheItem && (!matrix || matrix.equals(_matrix)) && [\n\t\t\t\toptions.stroke ? 1 : 0,\n\t\t\t\toptions.handle ? 1 : 0,\n\t\t\t\tinternal ? 1 : 0\n\t\t\t].join('');\n\t\tItem._updateBoundsCache(this._parent || this._symbol, cacheItem);\n\t\tif (cacheKey && this._bounds && cacheKey in this._bounds)\n\t\t\treturn this._bounds[cacheKey].rect.clone();\n\t\tvar bounds = this._getBounds(matrix || _matrix, options);\n\t\tif (cacheKey) {\n\t\t\tif (!this._bounds)\n\t\t\t\tthis._bounds = {};\n\t\t\tvar cached = this._bounds[cacheKey] = {\n\t\t\t\trect: bounds.clone(),\n\t\t\t\tinternal: options.internal\n\t\t\t};\n\t\t}\n\t\treturn bounds;\n\t},\n\n\t_getStrokeMatrix: function(matrix, options) {\n\t\tvar parent = this.getStrokeScaling() ? null\n\t\t\t\t: options && options.internal ? this\n\t\t\t\t\t: this._parent || this._symbol && this._symbol._item,\n\t\t\tmx = parent ? parent.getViewMatrix().invert() : matrix;\n\t\treturn mx && mx._shiftless();\n\t},\n\n\tstatics: {\n\t\t_updateBoundsCache: function(parent, item) {\n\t\t\tif (parent && item) {\n\t\t\t\tvar id = item._id,\n\t\t\t\t\tref = parent._boundsCache = parent._boundsCache || {\n\t\t\t\t\t\tids: {},\n\t\t\t\t\t\tlist: []\n\t\t\t\t\t};\n\t\t\t\tif (!ref.ids[id]) {\n\t\t\t\t\tref.list.push(item);\n\t\t\t\t\tref.ids[id] = item;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_clearBoundsCache: function(item) {\n\t\t\tvar cache = item._boundsCache;\n\t\t\tif (cache) {\n\t\t\t\titem._bounds = item._position = item._boundsCache = undefined;\n\t\t\t\tfor (var i = 0, list = cache.list, l = list.length; i < l; i++){\n\t\t\t\t\tvar other = list[i];\n\t\t\t\t\tif (other !== item) {\n\t\t\t\t\t\tother._bounds = other._position = undefined;\n\t\t\t\t\t\tif (other._boundsCache)\n\t\t\t\t\t\t\tItem._clearBoundsCache(other);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_getBounds: function(items, matrix, options) {\n\t\t\tvar x1 = Infinity,\n\t\t\t\tx2 = -x1,\n\t\t\t\ty1 = x1,\n\t\t\t\ty2 = x2;\n\t\t\toptions = options || {};\n\t\t\tfor (var i = 0, l = items.length; i < l; i++) {\n\t\t\t\tvar item = items[i];\n\t\t\t\tif (item._visible && !item.isEmpty()) {\n\t\t\t\t\tvar rect = item._getCachedBounds(\n\t\t\t\t\t\tmatrix && matrix.appended(item._matrix), options);\n\t\t\t\t\tx1 = Math.min(rect.x, x1);\n\t\t\t\t\ty1 = Math.min(rect.y, y1);\n\t\t\t\t\tx2 = Math.max(rect.x + rect.width, x2);\n\t\t\t\t\ty2 = Math.max(rect.y + rect.height, y2);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn isFinite(x1)\n\t\t\t\t\t? new Rectangle(x1, y1, x2 - x1, y2 - y1)\n\t\t\t\t\t: new Rectangle();\n\t\t}\n\t}\n\n}), {\n\tbeans: true,\n\n\t_decompose: function() {\n\t\treturn this._decomposed || (this._decomposed = this._matrix.decompose());\n\t},\n\n\tgetRotation: function() {\n\t\tvar decomposed = this._decompose();\n\t\treturn decomposed && decomposed.rotation;\n\t},\n\n\tsetRotation: function(rotation) {\n\t\tvar current = this.getRotation();\n\t\tif (current != null && rotation != null) {\n\t\t\tthis.rotate(rotation - current);\n\t\t}\n\t},\n\n\tgetScaling: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\tscaling = decomposed && decomposed.scaling;\n\t\treturn scaling\n\t\t\t\t? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')\n\t\t\t\t: undefined;\n\t},\n\n\tsetScaling: function() {\n\t\tvar current = this.getScaling(),\n\t\t\tscaling = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tif (current && scaling) {\n\t\t\tthis.scale(scaling.x / current.x, scaling.y / current.y);\n\t\t}\n\t},\n\n\tgetMatrix: function() {\n\t\treturn this._matrix;\n\t},\n\n\tsetMatrix: function() {\n\t\tvar matrix = this._matrix;\n\t\tmatrix.initialize.apply(matrix, arguments);\n\t},\n\n\tgetGlobalMatrix: function(_dontClone) {\n\t\tvar matrix = this._globalMatrix,\n\t\t\tupdateVersion = this._project._updateVersion;\n\t\tif (matrix && matrix._updateVersion !== updateVersion)\n\t\t\tmatrix = null;\n\t\tif (!matrix) {\n\t\t\tmatrix = this._globalMatrix = this._matrix.clone();\n\t\t\tvar parent = this._parent;\n\t\t\tif (parent)\n\t\t\t\tmatrix.prepend(parent.getGlobalMatrix(true));\n\t\t\tmatrix._updateVersion = updateVersion;\n\t\t}\n\t\treturn _dontClone ? matrix : matrix.clone();\n\t},\n\n\tgetViewMatrix: function() {\n\t\treturn this.getGlobalMatrix().prepend(this.getView()._matrix);\n\t},\n\n\tgetApplyMatrix: function() {\n\t\treturn this._applyMatrix;\n\t},\n\n\tsetApplyMatrix: function(apply) {\n\t\tif (this._applyMatrix = this._canApplyMatrix && !!apply)\n\t\t\tthis.transform(null, true);\n\t},\n\n\tgetTransformContent: '#getApplyMatrix',\n\tsetTransformContent: '#setApplyMatrix',\n}, {\n\tgetProject: function() {\n\t\treturn this._project;\n\t},\n\n\t_setProject: function(project, installEvents) {\n\t\tif (this._project !== project) {\n\t\t\tif (this._project)\n\t\t\t\tthis._installEvents(false);\n\t\t\tthis._project = project;\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children && children.length; i < l; i++)\n\t\t\t\tchildren[i]._setProject(project);\n\t\t\tinstallEvents = true;\n\t\t}\n\t\tif (installEvents)\n\t\t\tthis._installEvents(true);\n\t},\n\n\tgetView: function() {\n\t\treturn this._project._view;\n\t},\n\n\t_installEvents: function _installEvents(install) {\n\t\t_installEvents.base.call(this, install);\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children && children.length; i < l; i++)\n\t\t\tchildren[i]._installEvents(install);\n\t},\n\n\tgetLayer: function() {\n\t\tvar parent = this;\n\t\twhile (parent = parent._parent) {\n\t\t\tif (parent instanceof Layer)\n\t\t\t\treturn parent;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetParent: function() {\n\t\treturn this._parent;\n\t},\n\n\tsetParent: function(item) {\n\t\treturn item.addChild(this);\n\t},\n\n\t_getOwner: '#getParent',\n\n\tgetChildren: function() {\n\t\treturn this._children;\n\t},\n\n\tsetChildren: function(items) {\n\t\tthis.removeChildren();\n\t\tthis.addChildren(items);\n\t},\n\n\tgetFirstChild: function() {\n\t\treturn this._children && this._children[0] || null;\n\t},\n\n\tgetLastChild: function() {\n\t\treturn this._children && this._children[this._children.length - 1]\n\t\t\t\t|| null;\n\t},\n\n\tgetNextSibling: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner && owner._children[this._index + 1] || null;\n\t},\n\n\tgetPreviousSibling: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner && owner._children[this._index - 1] || null;\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index;\n\t},\n\n\tequals: function(item) {\n\t\treturn item === this || item && this._class === item._class\n\t\t\t\t&& this._style.equals(item._style)\n\t\t\t\t&& this._matrix.equals(item._matrix)\n\t\t\t\t&& this._locked === item._locked\n\t\t\t\t&& this._visible === item._visible\n\t\t\t\t&& this._blendMode === item._blendMode\n\t\t\t\t&& this._opacity === item._opacity\n\t\t\t\t&& this._clipMask === item._clipMask\n\t\t\t\t&& this._guide === item._guide\n\t\t\t\t&& this._equals(item)\n\t\t\t\t|| false;\n\t},\n\n\t_equals: function(item) {\n\t\treturn Base.equals(this._children, item._children);\n\t},\n\n\tclone: function(options) {\n\t\tvar copy = new this.constructor(Item.NO_INSERT),\n\t\t\tchildren = this._children,\n\t\t\tinsert = Base.pick(options ? options.insert : undefined,\n\t\t\t\t\toptions === undefined || options === true),\n\t\t\tdeep = Base.pick(options ? options.deep : undefined, true);\n\t\tif (children)\n\t\t\tcopy.copyAttributes(this);\n\t\tif (!children || deep)\n\t\t\tcopy.copyContent(this);\n\t\tif (!children)\n\t\t\tcopy.copyAttributes(this);\n\t\tif (insert)\n\t\t\tcopy.insertAbove(this);\n\t\tvar name = this._name,\n\t\t\tparent = this._parent;\n\t\tif (name && parent) {\n\t\t\tvar children = parent._children,\n\t\t\t\torig = name,\n\t\t\t\ti = 1;\n\t\t\twhile (children[name])\n\t\t\t\tname = orig + ' ' + (i++);\n\t\t\tif (name !== orig)\n\t\t\t\tcopy.setName(name);\n\t\t}\n\t\treturn copy;\n\t},\n\n\tcopyContent: function(source) {\n\t\tvar children = source._children;\n\t\tfor (var i = 0, l = children && children.length; i < l; i++) {\n\t\t\tthis.addChild(children[i].clone(false), true);\n\t\t}\n\t},\n\n\tcopyAttributes: function(source, excludeMatrix) {\n\t\tthis.setStyle(source._style);\n\t\tvar keys = ['_locked', '_visible', '_blendMode', '_opacity',\n\t\t\t\t'_clipMask', '_guide'];\n\t\tfor (var i = 0, l = keys.length; i < l; i++) {\n\t\t\tvar key = keys[i];\n\t\t\tif (source.hasOwnProperty(key))\n\t\t\t\tthis[key] = source[key];\n\t\t}\n\t\tif (!excludeMatrix)\n\t\t\tthis._matrix.set(source._matrix);\n\t\tthis.setApplyMatrix(source._applyMatrix);\n\t\tthis.setPivot(source._pivot);\n\t\tthis.setSelection(source._selection);\n\t\tvar data = source._data,\n\t\t\tname = source._name;\n\t\tthis._data = data ? Base.clone(data) : null;\n\t\tif (name)\n\t\t\tthis.setName(name);\n\t},\n\n\trasterize: function(resolution, insert) {\n\t\tvar bounds = this.getStrokeBounds(),\n\t\t\tscale = (resolution || this.getView().getResolution()) / 72,\n\t\t\ttopLeft = bounds.getTopLeft().floor(),\n\t\t\tbottomRight = bounds.getBottomRight().ceil(),\n\t\t\tsize = new Size(bottomRight.subtract(topLeft)),\n\t\t\traster = new Raster(Item.NO_INSERT);\n\t\tif (!size.isZero()) {\n\t\t\tvar canvas = CanvasProvider.getCanvas(size.multiply(scale)),\n\t\t\t\tctx = canvas.getContext('2d'),\n\t\t\t\tmatrix = new Matrix().scale(scale).translate(topLeft.negate());\n\t\t\tctx.save();\n\t\t\tmatrix.applyToContext(ctx);\n\t\t\tthis.draw(ctx, new Base({ matrices: [matrix] }));\n\t\t\tctx.restore();\n\t\t\traster.setCanvas(canvas);\n\t\t}\n\t\traster.transform(new Matrix().translate(topLeft.add(size.divide(2)))\n\t\t\t\t.scale(1 / scale));\n\t\tif (insert === undefined || insert)\n\t\t\traster.insertAbove(this);\n\t\treturn raster;\n\t},\n\n\tcontains: function() {\n\t\treturn !!this._contains(\n\t\t\t\tthis._matrix._inverseTransform(Point.read(arguments)));\n\t},\n\n\t_contains: function(point) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\t\tif (children[i].contains(point))\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn point.isInside(this.getInternalBounds());\n\t},\n\n\tisInside: function() {\n\t\treturn Rectangle.read(arguments).contains(this.getBounds());\n\t},\n\n\t_asPathItem: function() {\n\t\treturn new Path.Rectangle({\n\t\t\trectangle: this.getInternalBounds(),\n\t\t\tmatrix: this._matrix,\n\t\t\tinsert: false,\n\t\t});\n\t},\n\n\tintersects: function(item, _matrix) {\n\t\tif (!(item instanceof Item))\n\t\t\treturn false;\n\t\treturn this._asPathItem().getIntersections(item._asPathItem(), null,\n\t\t\t\t_matrix, true).length > 0;\n\t}\n},\nnew function() {\n\tfunction hitTest() {\n\t\treturn this._hitTest(\n\t\t\t\tPoint.read(arguments),\n\t\t\t\tHitResult.getOptions(arguments));\n\t}\n\n\tfunction hitTestAll() {\n\t\tvar point = Point.read(arguments),\n\t\t\toptions = HitResult.getOptions(arguments),\n\t\t\tcallback = options.match,\n\t\t\tresults = [];\n\t\toptions = Base.set({}, options, {\n\t\t\tmatch: function(hit) {\n\t\t\t\tif (!callback || callback(hit))\n\t\t\t\t\tresults.push(hit);\n\t\t\t}\n\t\t});\n\t\tthis._hitTest(point, options);\n\t\treturn results;\n\t}\n\n\tfunction hitTestChildren(point, options, viewMatrix, _exclude) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\t\tvar child = children[i];\n\t\t\t\tvar res = child !== _exclude && child._hitTest(point, options,\n\t\t\t\t\t\tviewMatrix);\n\t\t\t\tif (res)\n\t\t\t\t\treturn res;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tProject.inject({\n\t\thitTest: hitTest,\n\t\thitTestAll: hitTestAll,\n\t\t_hitTest: hitTestChildren\n\t});\n\n\treturn {\n\t\thitTest: hitTest,\n\t\thitTestAll: hitTestAll,\n\t\t_hitTestChildren: hitTestChildren,\n\t};\n}, {\n\n\t_hitTest: function(point, options, parentViewMatrix) {\n\t\tif (this._locked || !this._visible || this._guide && !options.guides\n\t\t\t\t|| this.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar matrix = this._matrix,\n\t\t\tviewMatrix = parentViewMatrix\n\t\t\t\t\t? parentViewMatrix.appended(matrix)\n\t\t\t\t\t: this.getGlobalMatrix().prepend(this.getView()._matrix),\n\t\t\tstrokeMatrix = this.getStrokeScaling()\n\t\t\t\t\t? null\n\t\t\t\t\t: viewMatrix.inverted()._shiftless(),\n\t\t\ttolerance = Math.max(options.tolerance, 1e-6),\n\t\t\ttolerancePadding = options._tolerancePadding = new Size(\n\t\t\t\t\tPath._getStrokePadding(tolerance, strokeMatrix));\n\t\tpoint = matrix._inverseTransform(point);\n\t\tif (!point || !this._children &&\n\t\t\t!this.getBounds({ internal: true, stroke: true, handle: true })\n\t\t\t\t.expand(tolerancePadding.multiply(2))._containsPoint(point)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar checkSelf = !(options.guides && !this._guide\n\t\t\t\t|| options.selected && !this.isSelected()\n\t\t\t\t|| options.type && options.type !== Base.hyphenate(this._class)\n\t\t\t\t|| options.class && !(this instanceof options.class)),\n\t\t\tcallback = options.match,\n\t\t\tthat = this,\n\t\t\tbounds,\n\t\t\tres;\n\n\t\tfunction match(hit) {\n\t\t\treturn !callback || hit && callback(hit) ? hit : null;\n\t\t}\n\n\t\tfunction checkBounds(type, part) {\n\t\t\tvar pt = bounds['get' + part]();\n\t\t\tif (point.subtract(pt).divide(tolerancePadding).length <= 1) {\n\t\t\t\treturn new HitResult(type, that,\n\t\t\t\t\t\t{ name: Base.hyphenate(part), point: pt });\n\t\t\t}\n\t\t}\n\n\t\tif (checkSelf && (options.center || options.bounds) && this._parent) {\n\t\t\tbounds = this.getInternalBounds();\n\t\t\tif (options.center) {\n\t\t\t\tres = checkBounds('center', 'Center');\n\t\t\t}\n\t\t\tif (!res && options.bounds) {\n\t\t\t\tvar points = [\n\t\t\t\t\t'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',\n\t\t\t\t\t'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'\n\t\t\t\t];\n\t\t\t\tfor (var i = 0; i < 8 && !res; i++) {\n\t\t\t\t\tres = checkBounds('bounds', points[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tres = match(res);\n\t\t}\n\n\t\tif (!res) {\n\t\t\tres = this._hitTestChildren(point, options, viewMatrix)\n\t\t\t\t|| checkSelf\n\t\t\t\t\t&& match(this._hitTestSelf(point, options, viewMatrix,\n\t\t\t\t\t\tstrokeMatrix))\n\t\t\t\t|| null;\n\t\t}\n\t\tif (res && res.point) {\n\t\t\tres.point = matrix.transform(res.point);\n\t\t}\n\t\treturn res;\n\t},\n\n\t_hitTestSelf: function(point, options) {\n\t\tif (options.fill && this.hasFill() && this._contains(point))\n\t\t\treturn new HitResult('fill', this);\n\t},\n\n\tmatches: function(name, compare) {\n\t\tfunction matchObject(obj1, obj2) {\n\t\t\tfor (var i in obj1) {\n\t\t\t\tif (obj1.hasOwnProperty(i)) {\n\t\t\t\t\tvar val1 = obj1[i],\n\t\t\t\t\t\tval2 = obj2[i];\n\t\t\t\t\tif (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {\n\t\t\t\t\t\tif (!matchObject(val1, val2))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t} else if (!Base.equals(val1, val2)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tvar type = typeof name;\n\t\tif (type === 'object') {\n\t\t\tfor (var key in name) {\n\t\t\t\tif (name.hasOwnProperty(key) && !this.matches(key, name[key]))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t} else if (type === 'function') {\n\t\t\treturn name(this);\n\t\t} else if (name === 'match') {\n\t\t\treturn compare(this);\n\t\t} else {\n\t\t\tvar value = /^(empty|editable)$/.test(name)\n\t\t\t\t\t? this['is' + Base.capitalize(name)]()\n\t\t\t\t\t: name === 'type'\n\t\t\t\t\t\t? Base.hyphenate(this._class)\n\t\t\t\t\t\t: this[name];\n\t\t\tif (name === 'class') {\n\t\t\t\tif (typeof compare === 'function')\n\t\t\t\t\treturn this instanceof compare;\n\t\t\t\tvalue = this._class;\n\t\t\t}\n\t\t\tif (typeof compare === 'function') {\n\t\t\t\treturn !!compare(value);\n\t\t\t} else if (compare) {\n\t\t\t\tif (compare.test) {\n\t\t\t\t\treturn compare.test(value);\n\t\t\t\t} else if (Base.isPlainObject(compare)) {\n\t\t\t\t\treturn matchObject(compare, value);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Base.equals(value, compare);\n\t\t}\n\t},\n\n\tgetItems: function(options) {\n\t\treturn Item._getItems(this, options, this._matrix);\n\t},\n\n\tgetItem: function(options) {\n\t\treturn Item._getItems(this, options, this._matrix, null, true)[0]\n\t\t\t\t|| null;\n\t},\n\n\tstatics: {\n\t\t_getItems: function _getItems(item, options, matrix, param, firstOnly) {\n\t\t\tif (!param) {\n\t\t\t\tvar obj = typeof options === 'object' && options,\n\t\t\t\t\toverlapping = obj && obj.overlapping,\n\t\t\t\t\tinside = obj && obj.inside,\n\t\t\t\t\tbounds = overlapping || inside,\n\t\t\t\t\trect = bounds && Rectangle.read([bounds]);\n\t\t\t\tparam = {\n\t\t\t\t\titems: [],\n\t\t\t\t\trecursive: obj && obj.recursive !== false,\n\t\t\t\t\tinside: !!inside,\n\t\t\t\t\toverlapping: !!overlapping,\n\t\t\t\t\trect: rect,\n\t\t\t\t\tpath: overlapping && new Path.Rectangle({\n\t\t\t\t\t\trectangle: rect,\n\t\t\t\t\t\tinsert: false\n\t\t\t\t\t})\n\t\t\t\t};\n\t\t\t\tif (obj) {\n\t\t\t\t\toptions = Base.filter({}, options, {\n\t\t\t\t\t\trecursive: true, inside: true, overlapping: true\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar children = item._children,\n\t\t\t\titems = param.items,\n\t\t\t\trect = param.rect;\n\t\t\tmatrix = rect && (matrix || new Matrix());\n\t\t\tfor (var i = 0, l = children && children.length; i < l; i++) {\n\t\t\t\tvar child = children[i],\n\t\t\t\t\tchildMatrix = matrix && matrix.appended(child._matrix),\n\t\t\t\t\tadd = true;\n\t\t\t\tif (rect) {\n\t\t\t\t\tvar bounds = child.getBounds(childMatrix);\n\t\t\t\t\tif (!rect.intersects(bounds))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif (!(rect.contains(bounds)\n\t\t\t\t\t\t\t|| param.overlapping && (bounds.contains(rect)\n\t\t\t\t\t\t\t\t|| param.path.intersects(child, childMatrix))))\n\t\t\t\t\t\tadd = false;\n\t\t\t\t}\n\t\t\t\tif (add && child.matches(options)) {\n\t\t\t\t\titems.push(child);\n\t\t\t\t\tif (firstOnly)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (param.recursive !== false) {\n\t\t\t\t\t_getItems(child, options, childMatrix, param, firstOnly);\n\t\t\t\t}\n\t\t\t\tif (firstOnly && items.length > 0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn items;\n\t\t}\n\t}\n}, {\n\n\timportJSON: function(json) {\n\t\tvar res = Base.importJSON(json, this);\n\t\treturn res !== this ? this.addChild(res) : res;\n\t},\n\n\taddChild: function(item) {\n\t\treturn this.insertChild(undefined, item);\n\t},\n\n\tinsertChild: function(index, item) {\n\t\tvar res = item ? this.insertChildren(index, [item]) : null;\n\t\treturn res && res[0];\n\t},\n\n\taddChildren: function(items) {\n\t\treturn this.insertChildren(this._children.length, items);\n\t},\n\n\tinsertChildren: function(index, items) {\n\t\tvar children = this._children;\n\t\tif (children && items && items.length > 0) {\n\t\t\titems = Base.slice(items);\n\t\t\tfor (var i = items.length - 1; i >= 0; i--) {\n\t\t\t\tvar item = items[i];\n\t\t\t\tif (!item) {\n\t\t\t\t\titems.splice(i, 1);\n\t\t\t\t} else {\n\t\t\t\t\titem._remove(false, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tBase.splice(children, items, index, 0);\n\t\t\tvar project = this._project,\n\t\t\t\tnotifySelf = project._changes;\n\t\t\tfor (var i = 0, l = items.length; i < l; i++) {\n\t\t\t\tvar item = items[i],\n\t\t\t\t\tname = item._name;\n\t\t\t\titem._parent = this;\n\t\t\t\titem._setProject(project, true);\n\t\t\t\tif (name)\n\t\t\t\t\titem.setName(name);\n\t\t\t\tif (notifySelf)\n\t\t\t\t\tthis._changed(5);\n\t\t\t}\n\t\t\tthis._changed(11);\n\t\t} else {\n\t\t\titems = null;\n\t\t}\n\t\treturn items;\n\t},\n\n\t_insertItem: '#insertChild',\n\n\t_insertAt: function(item, offset) {\n\t\tvar owner = item && item._getOwner(),\n\t\t\tres = item !== this && owner ? this : null;\n\t\tif (res) {\n\t\t\tres._remove(false, true);\n\t\t\towner._insertItem(item._index + offset, res);\n\t\t}\n\t\treturn res;\n\t},\n\n\tinsertAbove: function(item) {\n\t\treturn this._insertAt(item, 1);\n\t},\n\n\tinsertBelow: function(item) {\n\t\treturn this._insertAt(item, 0);\n\t},\n\n\tsendToBack: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner ? owner._insertItem(0, this) : null;\n\t},\n\n\tbringToFront: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner ? owner._insertItem(undefined, this) : null;\n\t},\n\n\tappendTop: '#addChild',\n\n\tappendBottom: function(item) {\n\t\treturn this.insertChild(0, item);\n\t},\n\n\tmoveAbove: '#insertAbove',\n\n\tmoveBelow: '#insertBelow',\n\n\tcopyTo: function(owner) {\n\t\treturn owner._insertItem(undefined, this.clone(false));\n\t},\n\n\treduce: function(options) {\n\t\tvar children = this._children;\n\t\tif (children && children.length === 1) {\n\t\t\tvar child = children[0].reduce(options);\n\t\t\tif (this._parent) {\n\t\t\t\tchild.insertAbove(this);\n\t\t\t\tthis.remove();\n\t\t\t} else {\n\t\t\t\tchild.remove();\n\t\t\t}\n\t\t\treturn child;\n\t\t}\n\t\treturn this;\n\t},\n\n\t_removeNamed: function() {\n\t\tvar owner = this._getOwner();\n\t\tif (owner) {\n\t\t\tvar children = owner._children,\n\t\t\t\tnamedChildren = owner._namedChildren,\n\t\t\t\tname = this._name,\n\t\t\t\tnamedArray = namedChildren[name],\n\t\t\t\tindex = namedArray ? namedArray.indexOf(this) : -1;\n\t\t\tif (index !== -1) {\n\t\t\t\tif (children[name] == this)\n\t\t\t\t\tdelete children[name];\n\t\t\t\tnamedArray.splice(index, 1);\n\t\t\t\tif (namedArray.length) {\n\t\t\t\t\tchildren[name] = namedArray[0];\n\t\t\t\t} else {\n\t\t\t\t\tdelete namedChildren[name];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_remove: function(notifySelf, notifyParent) {\n\t\tvar owner = this._getOwner(),\n\t\t\tproject = this._project,\n\t\t\tindex = this._index;\n\t\tif (owner) {\n\t\t\tif (index != null) {\n\t\t\t\tif (project._activeLayer === this)\n\t\t\t\t\tproject._activeLayer = this.getNextSibling()\n\t\t\t\t\t\t\t|| this.getPreviousSibling();\n\t\t\t\tBase.splice(owner._children, null, index, 1);\n\t\t\t}\n\t\t\tif (this._name)\n\t\t\t\tthis._removeNamed();\n\t\t\tthis._installEvents(false);\n\t\t\tif (notifySelf && project._changes)\n\t\t\t\tthis._changed(5);\n\t\t\tif (notifyParent)\n\t\t\t\towner._changed(11, this);\n\t\t\tthis._parent = null;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tremove: function() {\n\t\treturn this._remove(true, true);\n\t},\n\n\treplaceWith: function(item) {\n\t\tvar ok = item && item.insertBelow(this);\n\t\tif (ok)\n\t\t\tthis.remove();\n\t\treturn ok;\n\t},\n\n\tremoveChildren: function(start, end) {\n\t\tif (!this._children)\n\t\t\treturn null;\n\t\tstart = start || 0;\n\t\tend = Base.pick(end, this._children.length);\n\t\tvar removed = Base.splice(this._children, null, start, end - start);\n\t\tfor (var i = removed.length - 1; i >= 0; i--) {\n\t\t\tremoved[i]._remove(true, false);\n\t\t}\n\t\tif (removed.length > 0)\n\t\t\tthis._changed(11);\n\t\treturn removed;\n\t},\n\n\tclear: '#removeChildren',\n\n\treverseChildren: function() {\n\t\tif (this._children) {\n\t\t\tthis._children.reverse();\n\t\t\tfor (var i = 0, l = this._children.length; i < l; i++)\n\t\t\t\tthis._children[i]._index = i;\n\t\t\tthis._changed(11);\n\t\t}\n\t},\n\n\tisEmpty: function() {\n\t\tvar children = this._children;\n\t\treturn !children || !children.length;\n\t},\n\n\tisEditable: function() {\n\t\tvar item = this;\n\t\twhile (item) {\n\t\t\tif (!item._visible || item._locked)\n\t\t\t\treturn false;\n\t\t\titem = item._parent;\n\t\t}\n\t\treturn true;\n\t},\n\n\thasFill: function() {\n\t\treturn this.getStyle().hasFill();\n\t},\n\n\thasStroke: function() {\n\t\treturn this.getStyle().hasStroke();\n\t},\n\n\thasShadow: function() {\n\t\treturn this.getStyle().hasShadow();\n\t},\n\n\t_getOrder: function(item) {\n\t\tfunction getList(item) {\n\t\t\tvar list = [];\n\t\t\tdo {\n\t\t\t\tlist.unshift(item);\n\t\t\t} while (item = item._parent);\n\t\t\treturn list;\n\t\t}\n\t\tvar list1 = getList(this),\n\t\t\tlist2 = getList(item);\n\t\tfor (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {\n\t\t\tif (list1[i] != list2[i]) {\n\t\t\t\treturn list1[i]._index < list2[i]._index ? 1 : -1;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t},\n\n\thasChildren: function() {\n\t\treturn this._children && this._children.length > 0;\n\t},\n\n\tisInserted: function() {\n\t\treturn this._parent ? this._parent.isInserted() : false;\n\t},\n\n\tisAbove: function(item) {\n\t\treturn this._getOrder(item) === -1;\n\t},\n\n\tisBelow: function(item) {\n\t\treturn this._getOrder(item) === 1;\n\t},\n\n\tisParent: function(item) {\n\t\treturn this._parent === item;\n\t},\n\n\tisChild: function(item) {\n\t\treturn item && item._parent === this;\n\t},\n\n\tisDescendant: function(item) {\n\t\tvar parent = this;\n\t\twhile (parent = parent._parent) {\n\t\t\tif (parent === item)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tisAncestor: function(item) {\n\t\treturn item ? item.isDescendant(this) : false;\n\t},\n\n\tisSibling: function(item) {\n\t\treturn this._parent === item._parent;\n\t},\n\n\tisGroupedWith: function(item) {\n\t\tvar parent = this._parent;\n\t\twhile (parent) {\n\t\t\tif (parent._parent\n\t\t\t\t&& /^(Group|Layer|CompoundPath)$/.test(parent._class)\n\t\t\t\t&& item.isDescendant(parent))\n\t\t\t\t\treturn true;\n\t\t\tparent = parent._parent;\n\t\t}\n\t\treturn false;\n\t},\n\n}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {\n\tvar rotate = key === 'rotate';\n\tthis[key] = function() {\n\t\tvar value = (rotate ? Base : Point).read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\treturn this.transform(new Matrix()[key](value,\n\t\t\t\tcenter || this.getPosition(true)));\n\t};\n}, {\n\ttranslate: function() {\n\t\tvar mx = new Matrix();\n\t\treturn this.transform(mx.translate.apply(mx, arguments));\n\t},\n\n\ttransform: function(matrix, _applyMatrix, _applyRecursively,\n\t\t\t_setApplyMatrix) {\n\t\tif (matrix && matrix.isIdentity())\n\t\t\tmatrix = null;\n\t\tvar _matrix = this._matrix,\n\t\t\tapplyMatrix = (_applyMatrix || this._applyMatrix)\n\t\t\t\t\t&& ((!_matrix.isIdentity() || matrix)\n\t\t\t\t\t\t|| _applyMatrix && _applyRecursively && this._children);\n\t\tif (!matrix && !applyMatrix)\n\t\t\treturn this;\n\t\tif (matrix) {\n\t\t\tif (!matrix.isInvertible() && _matrix.isInvertible())\n\t\t\t\t_matrix._backup = _matrix.getValues();\n\t\t\t_matrix.prepend(matrix);\n\t\t}\n\t\tif (applyMatrix = applyMatrix && this._transformContent(_matrix,\n\t\t\t\t\t_applyRecursively, _setApplyMatrix)) {\n\t\t\tvar pivot = this._pivot,\n\t\t\t\tstyle = this._style,\n\t\t\t\tfillColor = style.getFillColor(true),\n\t\t\t\tstrokeColor = style.getStrokeColor(true);\n\t\t\tif (pivot)\n\t\t\t\t_matrix._transformPoint(pivot, pivot, true);\n\t\t\tif (fillColor)\n\t\t\t\tfillColor.transform(_matrix);\n\t\t\tif (strokeColor)\n\t\t\t\tstrokeColor.transform(_matrix);\n\t\t\t_matrix.reset(true);\n\t\t\tif (_setApplyMatrix && this._canApplyMatrix)\n\t\t\t\tthis._applyMatrix = true;\n\t\t}\n\t\tvar bounds = this._bounds,\n\t\t\tposition = this._position;\n\t\tthis._changed(9);\n\t\tvar decomp = bounds && matrix && matrix.decompose();\n\t\tif (decomp && !decomp.shearing && decomp.rotation % 90 === 0) {\n\t\t\tfor (var key in bounds) {\n\t\t\t\tvar cache = bounds[key];\n\t\t\t\tif (applyMatrix || !cache.internal) {\n\t\t\t\t\tvar rect = cache.rect;\n\t\t\t\t\tmatrix._transformBounds(rect, rect);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar getter = this._boundsGetter,\n\t\t\t\trect = bounds[getter && getter.getBounds || getter || 'getBounds'];\n\t\t\tif (rect)\n\t\t\t\tthis._position = rect.getCenter(true);\n\t\t\tthis._bounds = bounds;\n\t\t} else if (matrix && position) {\n\t\t\tthis._position = matrix._transformPoint(position, position);\n\t\t}\n\t\treturn this;\n\t},\n\n\t_transformContent: function(matrix, applyRecursively, setApplyMatrix) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].transform(matrix, true, applyRecursively,\n\t\t\t\t\t\tsetApplyMatrix);\n\t\t\treturn true;\n\t\t}\n\t},\n\n\tglobalToLocal: function() {\n\t\treturn this.getGlobalMatrix(true)._inverseTransform(\n\t\t\t\tPoint.read(arguments));\n\t},\n\n\tlocalToGlobal: function() {\n\t\treturn this.getGlobalMatrix(true)._transformPoint(\n\t\t\t\tPoint.read(arguments));\n\t},\n\n\tparentToLocal: function() {\n\t\treturn this._matrix._inverseTransform(Point.read(arguments));\n\t},\n\n\tlocalToParent: function() {\n\t\treturn this._matrix._transformPoint(Point.read(arguments));\n\t},\n\n\tfitBounds: function(rectangle, fill) {\n\t\trectangle = Rectangle.read(arguments);\n\t\tvar bounds = this.getBounds(),\n\t\t\titemRatio = bounds.height / bounds.width,\n\t\t\trectRatio = rectangle.height / rectangle.width,\n\t\t\tscale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)\n\t\t\t\t\t? rectangle.width / bounds.width\n\t\t\t\t\t: rectangle.height / bounds.height,\n\t\t\tnewBounds = new Rectangle(new Point(),\n\t\t\t\t\tnew Size(bounds.width * scale, bounds.height * scale));\n\t\tnewBounds.setCenter(rectangle.getCenter());\n\t\tthis.setBounds(newBounds);\n\t}\n}), {\n\n\t_setStyles: function(ctx, param, viewMatrix) {\n\t\tvar style = this._style;\n\t\tif (style.hasFill()) {\n\t\t\tctx.fillStyle = style.getFillColor().toCanvasStyle(ctx);\n\t\t}\n\t\tif (style.hasStroke()) {\n\t\t\tctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx);\n\t\t\tctx.lineWidth = style.getStrokeWidth();\n\t\t\tvar strokeJoin = style.getStrokeJoin(),\n\t\t\t\tstrokeCap = style.getStrokeCap(),\n\t\t\t\tmiterLimit = style.getMiterLimit();\n\t\t\tif (strokeJoin)\n\t\t\t\tctx.lineJoin = strokeJoin;\n\t\t\tif (strokeCap)\n\t\t\t\tctx.lineCap = strokeCap;\n\t\t\tif (miterLimit)\n\t\t\t\tctx.miterLimit = miterLimit;\n\t\t\tif (paper.support.nativeDash) {\n\t\t\t\tvar dashArray = style.getDashArray(),\n\t\t\t\t\tdashOffset = style.getDashOffset();\n\t\t\t\tif (dashArray && dashArray.length) {\n\t\t\t\t\tif ('setLineDash' in ctx) {\n\t\t\t\t\t\tctx.setLineDash(dashArray);\n\t\t\t\t\t\tctx.lineDashOffset = dashOffset;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tctx.mozDash = dashArray;\n\t\t\t\t\t\tctx.mozDashOffset = dashOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (style.hasShadow()) {\n\t\t\tvar pixelRatio = param.pixelRatio || 1,\n\t\t\t\tmx = viewMatrix._shiftless().prepend(\n\t\t\t\t\tnew Matrix().scale(pixelRatio, pixelRatio)),\n\t\t\t\tblur = mx.transform(new Point(style.getShadowBlur(), 0)),\n\t\t\t\toffset = mx.transform(this.getShadowOffset());\n\t\t\tctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx);\n\t\t\tctx.shadowBlur = blur.getLength();\n\t\t\tctx.shadowOffsetX = offset.x;\n\t\t\tctx.shadowOffsetY = offset.y;\n\t\t}\n\t},\n\n\tdraw: function(ctx, param, parentStrokeMatrix) {\n\t\tvar updateVersion = this._updateVersion = this._project._updateVersion;\n\t\tif (!this._visible || this._opacity === 0)\n\t\t\treturn;\n\t\tvar matrices = param.matrices,\n\t\t\tviewMatrix = param.viewMatrix,\n\t\t\tmatrix = this._matrix,\n\t\t\tglobalMatrix = matrices[matrices.length - 1].appended(matrix);\n\t\tif (!globalMatrix.isInvertible())\n\t\t\treturn;\n\n\t\tviewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix)\n\t\t\t\t: globalMatrix;\n\n\t\tmatrices.push(globalMatrix);\n\t\tif (param.updateMatrix) {\n\t\t\tglobalMatrix._updateVersion = updateVersion;\n\t\t\tthis._globalMatrix = globalMatrix;\n\t\t}\n\n\t\tvar blendMode = this._blendMode,\n\t\t\topacity = this._opacity,\n\t\t\tnormalBlend = blendMode === 'normal',\n\t\t\tnativeBlend = BlendMode.nativeModes[blendMode],\n\t\t\tdirect = normalBlend && opacity === 1\n\t\t\t\t\t|| param.dontStart\n\t\t\t\t\t|| param.clip\n\t\t\t\t\t|| (nativeBlend || normalBlend && opacity < 1)\n\t\t\t\t\t\t&& this._canComposite(),\n\t\t\tpixelRatio = param.pixelRatio || 1,\n\t\t\tmainCtx, itemOffset, prevOffset;\n\t\tif (!direct) {\n\t\t\tvar bounds = this.getStrokeBounds(viewMatrix);\n\t\t\tif (!bounds.width || !bounds.height)\n\t\t\t\treturn;\n\t\t\tprevOffset = param.offset;\n\t\t\titemOffset = param.offset = bounds.getTopLeft().floor();\n\t\t\tmainCtx = ctx;\n\t\t\tctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)\n\t\t\t\t\t.multiply(pixelRatio));\n\t\t\tif (pixelRatio !== 1)\n\t\t\t\tctx.scale(pixelRatio, pixelRatio);\n\t\t}\n\t\tctx.save();\n\t\tvar strokeMatrix = parentStrokeMatrix\n\t\t\t\t? parentStrokeMatrix.appended(matrix)\n\t\t\t\t: this._canScaleStroke && !this.getStrokeScaling(true)\n\t\t\t\t\t&& viewMatrix,\n\t\t\tclip = !direct && param.clipItem,\n\t\t\ttransform = !strokeMatrix || clip;\n\t\tif (direct) {\n\t\t\tctx.globalAlpha = opacity;\n\t\t\tif (nativeBlend)\n\t\t\t\tctx.globalCompositeOperation = blendMode;\n\t\t} else if (transform) {\n\t\t\tctx.translate(-itemOffset.x, -itemOffset.y);\n\t\t}\n\t\tif (transform) {\n\t\t\t(direct ? matrix : viewMatrix).applyToContext(ctx);\n\t\t}\n\t\tif (clip) {\n\t\t\tparam.clipItem.draw(ctx, param.extend({ clip: true }));\n\t\t}\n\t\tif (strokeMatrix) {\n\t\t\tctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\n\t\t\tvar offset = param.offset;\n\t\t\tif (offset)\n\t\t\t\tctx.translate(-offset.x, -offset.y);\n\t\t}\n\t\tthis._draw(ctx, param, viewMatrix, strokeMatrix);\n\t\tctx.restore();\n\t\tmatrices.pop();\n\t\tif (param.clip && !param.dontFinish)\n\t\t\tctx.clip();\n\t\tif (!direct) {\n\t\t\tBlendMode.process(blendMode, ctx, mainCtx, opacity,\n\t\t\t\t\titemOffset.subtract(prevOffset).multiply(pixelRatio));\n\t\t\tCanvasProvider.release(ctx);\n\t\t\tparam.offset = prevOffset;\n\t\t}\n\t},\n\n\t_isUpdated: function(updateVersion) {\n\t\tvar parent = this._parent;\n\t\tif (parent instanceof CompoundPath)\n\t\t\treturn parent._isUpdated(updateVersion);\n\t\tvar updated = this._updateVersion === updateVersion;\n\t\tif (!updated && parent && parent._visible\n\t\t\t\t&& parent._isUpdated(updateVersion)) {\n\t\t\tthis._updateVersion = updateVersion;\n\t\t\tupdated = true;\n\t\t}\n\t\treturn updated;\n\t},\n\n\t_drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) {\n\t\tvar selection = this._selection,\n\t\t\titemSelected = selection & 1,\n\t\t\tboundsSelected = selection & 2\n\t\t\t\t\t|| itemSelected && this._selectBounds,\n\t\t\tpositionSelected = selection & 4;\n\t\tif (!this._drawSelected)\n\t\t\titemSelected = false;\n\t\tif ((itemSelected || boundsSelected || positionSelected)\n\t\t\t\t&& this._isUpdated(updateVersion)) {\n\t\t\tvar layer,\n\t\t\t\tcolor = this.getSelectedColor(true) || (layer = this.getLayer())\n\t\t\t\t\t&& layer.getSelectedColor(true),\n\t\t\t\tmx = matrix.appended(this.getGlobalMatrix(true)),\n\t\t\t\thalf = size / 2;\n\t\t\tctx.strokeStyle = ctx.fillStyle = color\n\t\t\t\t\t? color.toCanvasStyle(ctx) : '#009dec';\n\t\t\tif (itemSelected)\n\t\t\t\tthis._drawSelected(ctx, mx, selectionItems);\n\t\t\tif (positionSelected) {\n\t\t\t\tvar point = this.getPosition(true),\n\t\t\t\t\tx = point.x,\n\t\t\t\t\ty = point.y;\n\t\t\t\tctx.beginPath();\n\t\t\t\tctx.arc(x, y, half, 0, Math.PI * 2, true);\n\t\t\t\tctx.stroke();\n\t\t\t\tvar deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]],\n\t\t\t\t\tstart = half,\n\t\t\t\t\tend = size + 1;\n\t\t\t\tfor (var i = 0; i < 4; i++) {\n\t\t\t\t\tvar delta = deltas[i],\n\t\t\t\t\t\tdx = delta[0],\n\t\t\t\t\t\tdy = delta[1];\n\t\t\t\t\tctx.moveTo(x + dx * start, y + dy * start);\n\t\t\t\t\tctx.lineTo(x + dx * end, y + dy * end);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (boundsSelected) {\n\t\t\t\tvar coords = mx._transformCorners(this.getInternalBounds());\n\t\t\t\tctx.beginPath();\n\t\t\t\tfor (var i = 0; i < 8; i++) {\n\t\t\t\t\tctx[!i ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);\n\t\t\t\t}\n\t\t\t\tctx.closePath();\n\t\t\t\tctx.stroke();\n\t\t\t\tfor (var i = 0; i < 8; i++) {\n\t\t\t\t\tctx.fillRect(coords[i] - half, coords[++i] - half,\n\t\t\t\t\t\t\tsize, size);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn false;\n\t}\n}, Base.each(['down', 'drag', 'up', 'move'], function(key) {\n\tthis['removeOn' + Base.capitalize(key)] = function() {\n\t\tvar hash = {};\n\t\thash[key] = true;\n\t\treturn this.removeOn(hash);\n\t};\n}, {\n\n\tremoveOn: function(obj) {\n\t\tfor (var name in obj) {\n\t\t\tif (obj[name]) {\n\t\t\t\tvar key = 'mouse' + name,\n\t\t\t\t\tproject = this._project,\n\t\t\t\t\tsets = project._removeSets = project._removeSets || {};\n\t\t\t\tsets[key] = sets[key] || {};\n\t\t\t\tsets[key][this._id] = this;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n}));\n\nvar Group = Item.extend({\n\t_class: 'Group',\n\t_selectBounds: false,\n\t_selectChildren: true,\n\t_serializeFields: {\n\t\tchildren: []\n\t},\n\n\tinitialize: function Group(arg) {\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tif (!this._initialize(arg))\n\t\t\tthis.addChildren(Array.isArray(arg) ? arg : arguments);\n\t},\n\n\t_changed: function _changed(flags) {\n\t\t_changed.base.call(this, flags);\n\t\tif (flags & 1026) {\n\t\t\tthis._clipItem = undefined;\n\t\t}\n\t},\n\n\t_getClipItem: function() {\n\t\tvar clipItem = this._clipItem;\n\t\tif (clipItem === undefined) {\n\t\t\tclipItem = null;\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\tif (children[i]._clipMask) {\n\t\t\t\t\tclipItem = children[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._clipItem = clipItem;\n\t\t}\n\t\treturn clipItem;\n\t},\n\n\tisClipped: function() {\n\t\treturn !!this._getClipItem();\n\t},\n\n\tsetClipped: function(clipped) {\n\t\tvar child = this.getFirstChild();\n\t\tif (child)\n\t\t\tchild.setClipMask(clipped);\n\t},\n\n\t_getBounds: function _getBounds(matrix, options) {\n\t\tvar clipItem = this._getClipItem();\n\t\treturn clipItem\n\t\t\t? clipItem._getCachedBounds(\n\t\t\t\tmatrix && matrix.appended(clipItem._matrix),\n\t\t\t\tBase.set({}, options, { stroke: false }))\n\t\t\t: _getBounds.base.call(this, matrix, options);\n\t},\n\n\t_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {\n\t\tvar clipItem = this._getClipItem();\n\t\treturn (!clipItem || clipItem.contains(point))\n\t\t\t\t&& _hitTestChildren.base.call(this, point, options, viewMatrix,\n\t\t\t\t\tclipItem);\n\t},\n\n\t_draw: function(ctx, param) {\n\t\tvar clip = param.clip,\n\t\t\tclipItem = !clip && this._getClipItem();\n\t\tparam = param.extend({ clipItem: clipItem, clip: false });\n\t\tif (clip) {\n\t\t\tctx.beginPath();\n\t\t\tparam.dontStart = param.dontFinish = true;\n\t\t} else if (clipItem) {\n\t\t\tclipItem.draw(ctx, param.extend({ clip: true }));\n\t\t}\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar item = children[i];\n\t\t\tif (item !== clipItem)\n\t\t\t\titem.draw(ctx, param);\n\t\t}\n\t}\n});\n\nvar Layer = Group.extend({\n\t_class: 'Layer',\n\n\tinitialize: function Layer() {\n\t\tGroup.apply(this, arguments);\n\t},\n\n\t_getOwner: function() {\n\t\treturn this._parent || this._index != null && this._project;\n\t},\n\n\tisInserted: function isInserted() {\n\t\treturn this._parent ? isInserted.base.call(this) : this._index != null;\n\t},\n\n\tactivate: function() {\n\t\tthis._project._activeLayer = this;\n\t},\n\n\t_hitTestSelf: function() {\n\t}\n});\n\nvar Shape = Item.extend({\n\t_class: 'Shape',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_canScaleStroke: true,\n\t_serializeFields: {\n\t\ttype: null,\n\t\tsize: null,\n\t\tradius: null\n\t},\n\n\tinitialize: function Shape(props) {\n\t\tthis._initialize(props);\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._type === item._type\n\t\t\t&& this._size.equals(item._size)\n\t\t\t&& Base.equals(this._radius, item._radius);\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setType(source._type);\n\t\tthis.setSize(source._size);\n\t\tthis.setRadius(source._radius);\n\t},\n\n\tgetType: function() {\n\t\treturn this._type;\n\t},\n\n\tsetType: function(type) {\n\t\tthis._type = type;\n\t},\n\n\tgetShape: '#getType',\n\tsetShape: '#setType',\n\n\tgetSize: function() {\n\t\tvar size = this._size;\n\t\treturn new LinkedSize(size.width, size.height, this, 'setSize');\n\t},\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments);\n\t\tif (!this._size) {\n\t\t\tthis._size = size.clone();\n\t\t} else if (!this._size.equals(size)) {\n\t\t\tvar type = this._type,\n\t\t\t\twidth = size.width,\n\t\t\t\theight = size.height;\n\t\t\tif (type === 'rectangle') {\n\t\t\t\tthis._radius.set(Size.min(this._radius, size.divide(2)));\n\t\t\t} else if (type === 'circle') {\n\t\t\t\twidth = height = (width + height) / 2;\n\t\t\t\tthis._radius = width / 2;\n\t\t\t} else if (type === 'ellipse') {\n\t\t\t\tthis._radius._set(width / 2, height / 2);\n\t\t\t}\n\t\t\tthis._size._set(width, height);\n\t\t\tthis._changed(9);\n\t\t}\n\t},\n\n\tgetRadius: function() {\n\t\tvar rad = this._radius;\n\t\treturn this._type === 'circle'\n\t\t\t\t? rad\n\t\t\t\t: new LinkedSize(rad.width, rad.height, this, 'setRadius');\n\t},\n\n\tsetRadius: function(radius) {\n\t\tvar type = this._type;\n\t\tif (type === 'circle') {\n\t\t\tif (radius === this._radius)\n\t\t\t\treturn;\n\t\t\tvar size = radius * 2;\n\t\t\tthis._radius = radius;\n\t\t\tthis._size._set(size, size);\n\t\t} else {\n\t\t\tradius = Size.read(arguments);\n\t\t\tif (!this._radius) {\n\t\t\t\tthis._radius = radius.clone();\n\t\t\t} else {\n\t\t\t\tif (this._radius.equals(radius))\n\t\t\t\t\treturn;\n\t\t\t\tthis._radius.set(radius);\n\t\t\t\tif (type === 'rectangle') {\n\t\t\t\t\tvar size = Size.max(this._size, radius.multiply(2));\n\t\t\t\t\tthis._size.set(size);\n\t\t\t\t} else if (type === 'ellipse') {\n\t\t\t\t\tthis._size._set(radius.width * 2, radius.height * 2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._changed(9);\n\t},\n\n\tisEmpty: function() {\n\t\treturn false;\n\t},\n\n\ttoPath: function(insert) {\n\t\tvar path = new Path[Base.capitalize(this._type)]({\n\t\t\tcenter: new Point(),\n\t\t\tsize: this._size,\n\t\t\tradius: this._radius,\n\t\t\tinsert: false\n\t\t});\n\t\tpath.copyAttributes(this);\n\t\tif (paper.settings.applyMatrix)\n\t\t\tpath.setApplyMatrix(true);\n\t\tif (insert === undefined || insert)\n\t\t\tpath.insertAbove(this);\n\t\treturn path;\n\t},\n\n\ttoShape: '#clone',\n\n\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\tvar style = this._style,\n\t\t\thasFill = style.hasFill(),\n\t\t\thasStroke = style.hasStroke(),\n\t\t\tdontPaint = param.dontFinish || param.clip,\n\t\t\tuntransformed = !strokeMatrix;\n\t\tif (hasFill || hasStroke || dontPaint) {\n\t\t\tvar type = this._type,\n\t\t\t\tradius = this._radius,\n\t\t\t\tisCircle = type === 'circle';\n\t\t\tif (!param.dontStart)\n\t\t\t\tctx.beginPath();\n\t\t\tif (untransformed && isCircle) {\n\t\t\t\tctx.arc(0, 0, radius, 0, Math.PI * 2, true);\n\t\t\t} else {\n\t\t\t\tvar rx = isCircle ? radius : radius.width,\n\t\t\t\t\try = isCircle ? radius : radius.height,\n\t\t\t\t\tsize = this._size,\n\t\t\t\t\twidth = size.width,\n\t\t\t\t\theight = size.height;\n\t\t\t\tif (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {\n\t\t\t\t\tctx.rect(-width / 2, -height / 2, width, height);\n\t\t\t\t} else {\n\t\t\t\t\tvar x = width / 2,\n\t\t\t\t\t\ty = height / 2,\n\t\t\t\t\t\tkappa = 1 - 0.5522847498307936,\n\t\t\t\t\t\tcx = rx * kappa,\n\t\t\t\t\t\tcy = ry * kappa,\n\t\t\t\t\t\tc = [\n\t\t\t\t\t\t\t-x, -y + ry,\n\t\t\t\t\t\t\t-x, -y + cy,\n\t\t\t\t\t\t\t-x + cx, -y,\n\t\t\t\t\t\t\t-x + rx, -y,\n\t\t\t\t\t\t\tx - rx, -y,\n\t\t\t\t\t\t\tx - cx, -y,\n\t\t\t\t\t\t\tx, -y + cy,\n\t\t\t\t\t\t\tx, -y + ry,\n\t\t\t\t\t\t\tx, y - ry,\n\t\t\t\t\t\t\tx, y - cy,\n\t\t\t\t\t\t\tx - cx, y,\n\t\t\t\t\t\t\tx - rx, y,\n\t\t\t\t\t\t\t-x + rx, y,\n\t\t\t\t\t\t\t-x + cx, y,\n\t\t\t\t\t\t\t-x, y - cy,\n\t\t\t\t\t\t\t-x, y - ry\n\t\t\t\t\t\t];\n\t\t\t\t\tif (strokeMatrix)\n\t\t\t\t\t\tstrokeMatrix.transform(c, c, 32);\n\t\t\t\t\tctx.moveTo(c[0], c[1]);\n\t\t\t\t\tctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);\n\t\t\t\t\tif (x !== rx)\n\t\t\t\t\t\tctx.lineTo(c[8], c[9]);\n\t\t\t\t\tctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);\n\t\t\t\t\tif (y !== ry)\n\t\t\t\t\t\tctx.lineTo(c[16], c[17]);\n\t\t\t\t\tctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);\n\t\t\t\t\tif (x !== rx)\n\t\t\t\t\t\tctx.lineTo(c[24], c[25]);\n\t\t\t\t\tctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tctx.closePath();\n\t\t}\n\t\tif (!dontPaint && (hasFill || hasStroke)) {\n\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\tif (hasFill) {\n\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (hasStroke)\n\t\t\t\tctx.stroke();\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn !(this.hasFill() && this.hasStroke());\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar rect = new Rectangle(this._size).setCenter(0, 0),\n\t\t\tstyle = this._style,\n\t\t\tstrokeWidth = options.stroke && style.hasStroke()\n\t\t\t\t\t&& style.getStrokeWidth();\n\t\tif (matrix)\n\t\t\trect = matrix._transformBounds(rect);\n\t\treturn strokeWidth\n\t\t\t\t? rect.expand(Path._getStrokePadding(strokeWidth,\n\t\t\t\t\tthis._getStrokeMatrix(matrix, options)))\n\t\t\t\t: rect;\n\t}\n},\nnew function() {\n\tfunction getCornerCenter(that, point, expand) {\n\t\tvar radius = that._radius;\n\t\tif (!radius.isZero()) {\n\t\t\tvar halfSize = that._size.divide(2);\n\t\t\tfor (var i = 0; i < 4; i++) {\n\t\t\t\tvar dir = new Point(i & 1 ? 1 : -1, i > 1 ? 1 : -1),\n\t\t\t\t\tcorner = dir.multiply(halfSize),\n\t\t\t\t\tcenter = corner.subtract(dir.multiply(radius)),\n\t\t\t\t\trect = new Rectangle(corner, center);\n\t\t\t\tif ((expand ? rect.expand(expand) : rect).contains(point))\n\t\t\t\t\treturn center;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction isOnEllipseStroke(point, radius, padding, quadrant) {\n\t\tvar vector = point.divide(radius);\n\t\treturn (!quadrant || vector.quadrant === quadrant) &&\n\t\t\t\tvector.subtract(vector.normalize()).multiply(radius)\n\t\t\t\t\t.divide(padding).length <= 1;\n\t}\n\n\treturn {\n\t\t_contains: function _contains(point) {\n\t\t\tif (this._type === 'rectangle') {\n\t\t\t\tvar center = getCornerCenter(this, point);\n\t\t\t\treturn center\n\t\t\t\t\t\t? point.subtract(center).divide(this._radius)\n\t\t\t\t\t\t\t.getLength() <= 1\n\t\t\t\t\t\t: _contains.base.call(this, point);\n\t\t\t} else {\n\t\t\t\treturn point.divide(this.size).getLength() <= 0.5;\n\t\t\t}\n\t\t},\n\n\t\t_hitTestSelf: function _hitTestSelf(point, options, viewMatrix,\n\t\t\t\tstrokeMatrix) {\n\t\t\tvar hit = false,\n\t\t\t\tstyle = this._style,\n\t\t\t\thitStroke = options.stroke && style.hasStroke(),\n\t\t\t\thitFill = options.fill && style.hasFill();\n\t\t\tif (hitStroke || hitFill) {\n\t\t\t\tvar type = this._type,\n\t\t\t\t\tradius = this._radius,\n\t\t\t\t\tstrokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0,\n\t\t\t\t\tstrokePadding = options._tolerancePadding.add(\n\t\t\t\t\t\tPath._getStrokePadding(strokeRadius,\n\t\t\t\t\t\t\t!style.getStrokeScaling() && strokeMatrix));\n\t\t\t\tif (type === 'rectangle') {\n\t\t\t\t\tvar padding = strokePadding.multiply(2),\n\t\t\t\t\t\tcenter = getCornerCenter(this, point, padding);\n\t\t\t\t\tif (center) {\n\t\t\t\t\t\thit = isOnEllipseStroke(point.subtract(center), radius,\n\t\t\t\t\t\t\t\tstrokePadding, center.getQuadrant());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar rect = new Rectangle(this._size).setCenter(0, 0),\n\t\t\t\t\t\t\touter = rect.expand(padding),\n\t\t\t\t\t\t\tinner = rect.expand(padding.negate());\n\t\t\t\t\t\thit = outer._containsPoint(point)\n\t\t\t\t\t\t\t\t&& !inner._containsPoint(point);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\thit = isOnEllipseStroke(point, radius, strokePadding);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this)\n\t\t\t\t\t: _hitTestSelf.base.apply(this, arguments);\n\t\t}\n\t};\n}, {\n\nstatics: new function() {\n\tfunction createShape(type, point, size, radius, args) {\n\t\tvar item = new Shape(Base.getNamed(args));\n\t\titem._type = type;\n\t\titem._size = size;\n\t\titem._radius = radius;\n\t\treturn item.translate(point);\n\t}\n\n\treturn {\n\t\tCircle: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius');\n\t\t\treturn createShape('circle', center, new Size(radius * 2), radius,\n\t\t\t\t\targuments);\n\t\t},\n\n\t\tRectangle: function() {\n\t\t\tvar rect = Rectangle.readNamed(arguments, 'rectangle'),\n\t\t\t\tradius = Size.min(Size.readNamed(arguments, 'radius'),\n\t\t\t\t\t\trect.getSize(true).divide(2));\n\t\t\treturn createShape('rectangle', rect.getCenter(true),\n\t\t\t\t\trect.getSize(true), radius, arguments);\n\t\t},\n\n\t\tEllipse: function() {\n\t\t\tvar ellipse = Shape._readEllipse(arguments),\n\t\t\t\tradius = ellipse.radius;\n\t\t\treturn createShape('ellipse', ellipse.center, radius.multiply(2),\n\t\t\t\t\tradius, arguments);\n\t\t},\n\n\t\t_readEllipse: function(args) {\n\t\t\tvar center,\n\t\t\t\tradius;\n\t\t\tif (Base.hasNamed(args, 'radius')) {\n\t\t\t\tcenter = Point.readNamed(args, 'center');\n\t\t\t\tradius = Size.readNamed(args, 'radius');\n\t\t\t} else {\n\t\t\t\tvar rect = Rectangle.readNamed(args, 'rectangle');\n\t\t\t\tcenter = rect.getCenter(true);\n\t\t\t\tradius = rect.getSize(true).divide(2);\n\t\t\t}\n\t\t\treturn { center: center, radius: radius };\n\t\t}\n\t};\n}});\n\nvar Raster = Item.extend({\n\t_class: 'Raster',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_boundsOptions: { stroke: false, handle: false },\n\t_serializeFields: {\n\t\tcrossOrigin: null,\n\t\tsource: null\n\t},\n\t_prioritize: ['crossOrigin'],\n\n\tinitialize: function Raster(object, position) {\n\t\tif (!this._initialize(object,\n\t\t\t\tposition !== undefined && Point.read(arguments, 1))) {\n\t\t\tvar image = typeof object === 'string'\n\t\t\t\t\t? document.getElementById(object) : object;\n\t\t\tif (image) {\n\t\t\t\tthis.setImage(image);\n\t\t\t} else {\n\t\t\t\tthis.setSource(object);\n\t\t\t}\n\t\t}\n\t\tif (!this._size) {\n\t\t\tthis._size = new Size();\n\t\t\tthis._loaded = false;\n\t\t}\n\t},\n\n\t_equals: function(item) {\n\t\treturn this.getSource() === item.getSource();\n\t},\n\n\tcopyContent: function(source) {\n\t\tvar image = source._image,\n\t\t\tcanvas = source._canvas;\n\t\tif (image) {\n\t\t\tthis._setImage(image);\n\t\t} else if (canvas) {\n\t\t\tvar copyCanvas = CanvasProvider.getCanvas(source._size);\n\t\t\tcopyCanvas.getContext('2d').drawImage(canvas, 0, 0);\n\t\t\tthis._setImage(copyCanvas);\n\t\t}\n\t\tthis._crossOrigin = source._crossOrigin;\n\t},\n\n\tgetSize: function() {\n\t\tvar size = this._size;\n\t\treturn new LinkedSize(size ? size.width : 0, size ? size.height : 0,\n\t\t\t\tthis, 'setSize');\n\t},\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments);\n\t\tif (!size.equals(this._size)) {\n\t\t\tif (size.width > 0 && size.height > 0) {\n\t\t\t\tvar element = this.getElement();\n\t\t\t\tthis._setImage(CanvasProvider.getCanvas(size));\n\t\t\t\tif (element)\n\t\t\t\t\tthis.getContext(true).drawImage(element, 0, 0,\n\t\t\t\t\t\t\tsize.width, size.height);\n\t\t\t} else {\n\t\t\t\tif (this._canvas)\n\t\t\t\t\tCanvasProvider.release(this._canvas);\n\t\t\t\tthis._size = size.clone();\n\t\t\t}\n\t\t}\n\t},\n\n\tgetWidth: function() {\n\t\treturn this._size ? this._size.width : 0;\n\t},\n\n\tsetWidth: function(width) {\n\t\tthis.setSize(width, this.getHeight());\n\t},\n\n\tgetHeight: function() {\n\t\treturn this._size ? this._size.height : 0;\n\t},\n\n\tsetHeight: function(height) {\n\t\tthis.setSize(this.getWidth(), height);\n\t},\n\n\tgetLoaded: function() {\n\t\treturn this._loaded;\n\t},\n\n\tisEmpty: function() {\n\t\tvar size = this._size;\n\t\treturn !size || size.width === 0 && size.height === 0;\n\t},\n\n\tgetResolution: function() {\n\t\tvar matrix = this._matrix,\n\t\t\torig = new Point(0, 0).transform(matrix),\n\t\t\tu = new Point(1, 0).transform(matrix).subtract(orig),\n\t\t\tv = new Point(0, 1).transform(matrix).subtract(orig);\n\t\treturn new Size(\n\t\t\t72 / u.getLength(),\n\t\t\t72 / v.getLength()\n\t\t);\n\t},\n\n\tgetPpi: '#getResolution',\n\n\tgetImage: function() {\n\t\treturn this._image;\n\t},\n\n\tsetImage: function(image) {\n\t\tvar that = this;\n\n\t\tfunction emit(event) {\n\t\t\tvar view = that.getView(),\n\t\t\t\ttype = event && event.type || 'load';\n\t\t\tif (view && that.responds(type)) {\n\t\t\t\tpaper = view._scope;\n\t\t\t\tthat.emit(type, new Event(event));\n\t\t\t}\n\t\t}\n\n\t\tthis._setImage(image);\n\t\tif (this._loaded) {\n\t\t\tsetTimeout(emit, 0);\n\t\t} else if (image) {\n\t\t\tDomEvent.add(image, {\n\t\t\t\tload: function(event) {\n\t\t\t\t\tthat._setImage(image);\n\t\t\t\t\temit(event);\n\t\t\t\t},\n\t\t\t\terror: emit\n\t\t\t});\n\t\t}\n\t},\n\n\t_setImage: function(image) {\n\t\tif (this._canvas)\n\t\t\tCanvasProvider.release(this._canvas);\n\t\tif (image && image.getContext) {\n\t\t\tthis._image = null;\n\t\t\tthis._canvas = image;\n\t\t\tthis._loaded = true;\n\t\t} else {\n\t\t\tthis._image = image;\n\t\t\tthis._canvas = null;\n\t\t\tthis._loaded = !!(image && image.src && image.complete);\n\t\t}\n\t\tthis._size = new Size(\n\t\t\t\timage ? image.naturalWidth || image.width : 0,\n\t\t\t\timage ? image.naturalHeight || image.height : 0);\n\t\tthis._context = null;\n\t\tthis._changed(521);\n\t},\n\n\tgetCanvas: function() {\n\t\tif (!this._canvas) {\n\t\t\tvar ctx = CanvasProvider.getContext(this._size);\n\t\t\ttry {\n\t\t\t\tif (this._image)\n\t\t\t\t\tctx.drawImage(this._image, 0, 0);\n\t\t\t\tthis._canvas = ctx.canvas;\n\t\t\t} catch (e) {\n\t\t\t\tCanvasProvider.release(ctx);\n\t\t\t}\n\t\t}\n\t\treturn this._canvas;\n\t},\n\n\tsetCanvas: '#setImage',\n\n\tgetContext: function(modify) {\n\t\tif (!this._context)\n\t\t\tthis._context = this.getCanvas().getContext('2d');\n\t\tif (modify) {\n\t\t\tthis._image = null;\n\t\t\tthis._changed(513);\n\t\t}\n\t\treturn this._context;\n\t},\n\n\tsetContext: function(context) {\n\t\tthis._context = context;\n\t},\n\n\tgetSource: function() {\n\t\tvar image = this._image;\n\t\treturn image && image.src || this.toDataURL();\n\t},\n\n\tsetSource: function(src) {\n\t\tvar image = new self.Image(),\n\t\t\tcrossOrigin = this._crossOrigin;\n\t\tif (crossOrigin)\n\t\t\timage.crossOrigin = crossOrigin;\n\t\timage.src = src;\n\t\tthis.setImage(image);\n\t},\n\n\tgetCrossOrigin: function() {\n\t\tvar image = this._image;\n\t\treturn image && image.crossOrigin || this._crossOrigin || '';\n\t},\n\n\tsetCrossOrigin: function(crossOrigin) {\n\t\tthis._crossOrigin = crossOrigin;\n\t\tvar image = this._image;\n\t\tif (image)\n\t\t\timage.crossOrigin = crossOrigin;\n\t},\n\n\tgetElement: function() {\n\t\treturn this._canvas || this._loaded && this._image;\n\t}\n}, {\n\tbeans: false,\n\n\tgetSubCanvas: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tctx = CanvasProvider.getContext(rect.getSize());\n\t\tctx.drawImage(this.getCanvas(), rect.x, rect.y,\n\t\t\t\trect.width, rect.height, 0, 0, rect.width, rect.height);\n\t\treturn ctx.canvas;\n\t},\n\n\tgetSubRaster: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\traster = new Raster(Item.NO_INSERT);\n\t\traster._setImage(this.getSubCanvas(rect));\n\t\traster.translate(rect.getCenter().subtract(this.getSize().divide(2)));\n\t\traster._matrix.prepend(this._matrix);\n\t\traster.insertAbove(this);\n\t\treturn raster;\n\t},\n\n\ttoDataURL: function() {\n\t\tvar image = this._image,\n\t\t\tsrc = image && image.src;\n\t\tif (/^data:/.test(src))\n\t\t\treturn src;\n\t\tvar canvas = this.getCanvas();\n\t\treturn canvas ? canvas.toDataURL.apply(canvas, arguments) : null;\n\t},\n\n\tdrawImage: function(image ) {\n\t\tvar point = Point.read(arguments, 1);\n\t\tthis.getContext(true).drawImage(image, point.x, point.y);\n\t},\n\n\tgetAverageColor: function(object) {\n\t\tvar bounds, path;\n\t\tif (!object) {\n\t\t\tbounds = this.getBounds();\n\t\t} else if (object instanceof PathItem) {\n\t\t\tpath = object;\n\t\t\tbounds = object.getBounds();\n\t\t} else if (typeof object === 'object') {\n\t\t\tif ('width' in object) {\n\t\t\t\tbounds = new Rectangle(object);\n\t\t\t} else if ('x' in object) {\n\t\t\t\tbounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);\n\t\t\t}\n\t\t}\n\t\tif (!bounds)\n\t\t\treturn null;\n\t\tvar sampleSize = 32,\n\t\t\twidth = Math.min(bounds.width, sampleSize),\n\t\t\theight = Math.min(bounds.height, sampleSize);\n\t\tvar ctx = Raster._sampleContext;\n\t\tif (!ctx) {\n\t\t\tctx = Raster._sampleContext = CanvasProvider.getContext(\n\t\t\t\t\tnew Size(sampleSize));\n\t\t} else {\n\t\t\tctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);\n\t\t}\n\t\tctx.save();\n\t\tvar matrix = new Matrix()\n\t\t\t\t.scale(width / bounds.width, height / bounds.height)\n\t\t\t\t.translate(-bounds.x, -bounds.y);\n\t\tmatrix.applyToContext(ctx);\n\t\tif (path)\n\t\t\tpath.draw(ctx, new Base({ clip: true, matrices: [matrix] }));\n\t\tthis._matrix.applyToContext(ctx);\n\t\tvar element = this.getElement(),\n\t\t\tsize = this._size;\n\t\tif (element)\n\t\t\tctx.drawImage(element, -size.width / 2, -size.height / 2);\n\t\tctx.restore();\n\t\tvar pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),\n\t\t\t\tMath.ceil(height)).data,\n\t\t\tchannels = [0, 0, 0],\n\t\t\ttotal = 0;\n\t\tfor (var i = 0, l = pixels.length; i < l; i += 4) {\n\t\t\tvar alpha = pixels[i + 3];\n\t\t\ttotal += alpha;\n\t\t\talpha /= 255;\n\t\t\tchannels[0] += pixels[i] * alpha;\n\t\t\tchannels[1] += pixels[i + 1] * alpha;\n\t\t\tchannels[2] += pixels[i + 2] * alpha;\n\t\t}\n\t\tfor (var i = 0; i < 3; i++)\n\t\t\tchannels[i] /= total;\n\t\treturn total ? Color.read(channels) : null;\n\t},\n\n\tgetPixel: function() {\n\t\tvar point = Point.read(arguments);\n\t\tvar data = this.getContext().getImageData(point.x, point.y, 1, 1).data;\n\t\treturn new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],\n\t\t\t\tdata[3] / 255);\n\t},\n\n\tsetPixel: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcolor = Color.read(arguments),\n\t\t\tcomponents = color._convert('rgb'),\n\t\t\talpha = color._alpha,\n\t\t\tctx = this.getContext(true),\n\t\t\timageData = ctx.createImageData(1, 1),\n\t\t\tdata = imageData.data;\n\t\tdata[0] = components[0] * 255;\n\t\tdata[1] = components[1] * 255;\n\t\tdata[2] = components[2] * 255;\n\t\tdata[3] = alpha != null ? alpha * 255 : 255;\n\t\tctx.putImageData(imageData, point.x, point.y);\n\t},\n\n\tcreateImageData: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn this.getContext().createImageData(size.width, size.height);\n\t},\n\n\tgetImageData: function() {\n\t\tvar rect = Rectangle.read(arguments);\n\t\tif (rect.isEmpty())\n\t\t\trect = new Rectangle(this._size);\n\t\treturn this.getContext().getImageData(rect.x, rect.y,\n\t\t\t\trect.width, rect.height);\n\t},\n\n\tsetImageData: function(data ) {\n\t\tvar point = Point.read(arguments, 1);\n\t\tthis.getContext(true).putImageData(data, point.x, point.y);\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar rect = new Rectangle(this._size).setCenter(0, 0);\n\t\treturn matrix ? matrix._transformBounds(rect) : rect;\n\t},\n\n\t_hitTestSelf: function(point) {\n\t\tif (this._contains(point)) {\n\t\t\tvar that = this;\n\t\t\treturn new HitResult('pixel', that, {\n\t\t\t\toffset: point.add(that._size.divide(2)).round(),\n\t\t\t\tcolor: {\n\t\t\t\t\tget: function() {\n\t\t\t\t\t\treturn that.getPixel(this.offset);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\t_draw: function(ctx) {\n\t\tvar element = this.getElement();\n\t\tif (element) {\n\t\t\tctx.globalAlpha = this._opacity;\n\t\t\tctx.drawImage(element,\n\t\t\t\t\t-this._size.width / 2, -this._size.height / 2);\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn true;\n\t}\n});\n\nvar SymbolItem = Item.extend({\n\t_class: 'SymbolItem',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_boundsOptions: { stroke: true },\n\t_serializeFields: {\n\t\tsymbol: null\n\t},\n\n\tinitialize: function SymbolItem(arg0, arg1) {\n\t\tif (!this._initialize(arg0,\n\t\t\t\targ1 !== undefined && Point.read(arguments, 1)))\n\t\t\tthis.setDefinition(arg0 instanceof SymbolDefinition ?\n\t\t\t\t\targ0 : new SymbolDefinition(arg0));\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._definition === item._definition;\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setDefinition(source._definition);\n\t},\n\n\tgetDefinition: function() {\n\t\treturn this._definition;\n\t},\n\n\tsetDefinition: function(definition) {\n\t\tthis._definition = definition;\n\t\tthis._changed(9);\n\t},\n\n\tgetSymbol: '#getDefinition',\n\tsetSymbol: '#setDefinition',\n\n\tisEmpty: function() {\n\t\treturn this._definition._item.isEmpty();\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar item = this._definition._item;\n\t\treturn item._getCachedBounds(item._matrix.prepended(matrix), options);\n\t},\n\n\t_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {\n\t\tvar res = this._definition._item._hitTest(point, options, viewMatrix);\n\t\tif (res)\n\t\t\tres.item = this;\n\t\treturn res;\n\t},\n\n\t_draw: function(ctx, param) {\n\t\tthis._definition._item.draw(ctx, param);\n\t}\n\n});\n\nvar SymbolDefinition = Base.extend({\n\t_class: 'SymbolDefinition',\n\n\tinitialize: function SymbolDefinition(item, dontCenter) {\n\t\tthis._id = UID.get();\n\t\tthis.project = paper.project;\n\t\tif (item)\n\t\t\tthis.setItem(item, dontCenter);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn dictionary.add(this, function() {\n\t\t\treturn Base.serialize([this._class, this._item],\n\t\t\t\t\toptions, false, dictionary);\n\t\t});\n\t},\n\n\t_changed: function(flags) {\n\t\tif (flags & 8)\n\t\t\tItem._clearBoundsCache(this);\n\t\tif (flags & 1)\n\t\t\tthis.project._changed(flags);\n\t},\n\n\tgetItem: function() {\n\t\treturn this._item;\n\t},\n\n\tsetItem: function(item, _dontCenter) {\n\t\tif (item._symbol)\n\t\t\titem = item.clone();\n\t\tif (this._item)\n\t\t\tthis._item._symbol = null;\n\t\tthis._item = item;\n\t\titem.remove();\n\t\titem.setSelected(false);\n\t\tif (!_dontCenter)\n\t\t\titem.setPosition(new Point());\n\t\titem._symbol = this;\n\t\tthis._changed(9);\n\t},\n\n\tgetDefinition: '#getItem',\n\tsetDefinition: '#setItem',\n\n\tplace: function(position) {\n\t\treturn new SymbolItem(this, position);\n\t},\n\n\tclone: function() {\n\t\treturn new SymbolDefinition(this._item.clone(false));\n\t},\n\n\tequals: function(symbol) {\n\t\treturn symbol === this\n\t\t\t\t|| symbol && this._item.equals(symbol._item)\n\t\t\t\t|| false;\n\t}\n});\n\nvar HitResult = Base.extend({\n\t_class: 'HitResult',\n\n\tinitialize: function HitResult(type, item, values) {\n\t\tthis.type = type;\n\t\tthis.item = item;\n\t\tif (values) {\n\t\t\tvalues.enumerable = true;\n\t\t\tthis.inject(values);\n\t\t}\n\t},\n\n\tstatics: {\n\t\tgetOptions: function(args) {\n\t\t\tvar options = args && Base.read(args);\n\t\t\treturn Base.set({\n\t\t\t\ttype: null,\n\t\t\t\ttolerance: paper.settings.hitTolerance,\n\t\t\t\tfill: !options,\n\t\t\t\tstroke: !options,\n\t\t\t\tsegments: !options,\n\t\t\t\thandles: false,\n\t\t\t\tends: false,\n\t\t\t\tcenter: false,\n\t\t\t\tbounds: false,\n\t\t\t\tguides: false,\n\t\t\t\tselected: false\n\t\t\t}, options);\n\t\t}\n\t}\n});\n\nvar Segment = Base.extend({\n\t_class: 'Segment',\n\tbeans: true,\n\t_selection: 0,\n\n\tinitialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {\n\t\tvar count = arguments.length,\n\t\t\tpoint, handleIn, handleOut, selection;\n\t\tif (count > 0) {\n\t\t\tif (arg0 == null || typeof arg0 === 'object') {\n\t\t\t\tif (count === 1 && arg0 && 'point' in arg0) {\n\t\t\t\t\tpoint = arg0.point;\n\t\t\t\t\thandleIn = arg0.handleIn;\n\t\t\t\t\thandleOut = arg0.handleOut;\n\t\t\t\t\tselection = arg0.selection;\n\t\t\t\t} else {\n\t\t\t\t\tpoint = arg0;\n\t\t\t\t\thandleIn = arg1;\n\t\t\t\t\thandleOut = arg2;\n\t\t\t\t\tselection = arg3;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tpoint = [ arg0, arg1 ];\n\t\t\t\thandleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;\n\t\t\t\thandleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;\n\t\t\t}\n\t\t}\n\t\tnew SegmentPoint(point, this, '_point');\n\t\tnew SegmentPoint(handleIn, this, '_handleIn');\n\t\tnew SegmentPoint(handleOut, this, '_handleOut');\n\t\tif (selection)\n\t\t\tthis.setSelection(selection);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar point = this._point,\n\t\t\tselection = this._selection,\n\t\t\tobj = selection || this.hasHandles()\n\t\t\t\t\t? [point, this._handleIn, this._handleOut]\n\t\t\t\t\t: point;\n\t\tif (selection)\n\t\t\tobj.push(selection);\n\t\treturn Base.serialize(obj, options, true, dictionary);\n\t},\n\n\t_changed: function(point) {\n\t\tvar path = this._path;\n\t\tif (!path)\n\t\t\treturn;\n\t\tvar curves = path._curves,\n\t\t\tindex = this._index,\n\t\t\tcurve;\n\t\tif (curves) {\n\t\t\tif ((!point || point === this._point || point === this._handleIn)\n\t\t\t\t\t&& (curve = index > 0 ? curves[index - 1] : path._closed\n\t\t\t\t\t\t? curves[curves.length - 1] : null))\n\t\t\t\tcurve._changed();\n\t\t\tif ((!point || point === this._point || point === this._handleOut)\n\t\t\t\t\t&& (curve = curves[index]))\n\t\t\t\tcurve._changed();\n\t\t}\n\t\tpath._changed(25);\n\t},\n\n\tgetPoint: function() {\n\t\treturn this._point;\n\t},\n\n\tsetPoint: function() {\n\t\tthis._point.set(Point.read(arguments));\n\t},\n\n\tgetHandleIn: function() {\n\t\treturn this._handleIn;\n\t},\n\n\tsetHandleIn: function() {\n\t\tthis._handleIn.set(Point.read(arguments));\n\t},\n\n\tgetHandleOut: function() {\n\t\treturn this._handleOut;\n\t},\n\n\tsetHandleOut: function() {\n\t\tthis._handleOut.set(Point.read(arguments));\n\t},\n\n\thasHandles: function() {\n\t\treturn !this._handleIn.isZero() || !this._handleOut.isZero();\n\t},\n\n\tclearHandles: function() {\n\t\tthis._handleIn._set(0, 0);\n\t\tthis._handleOut._set(0, 0);\n\t},\n\n\tgetSelection: function() {\n\t\treturn this._selection;\n\t},\n\n\tsetSelection: function(selection) {\n\t\tvar oldSelection = this._selection,\n\t\t\tpath = this._path;\n\t\tthis._selection = selection = selection || 0;\n\t\tif (path && selection !== oldSelection) {\n\t\t\tpath._updateSelection(this, oldSelection, selection);\n\t\t\tpath._changed(129);\n\t\t}\n\t},\n\n\tchangeSelection: function(flag, selected) {\n\t\tvar selection = this._selection;\n\t\tthis.setSelection(selected ? selection | flag : selection & ~flag);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._selection & 7);\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis.changeSelection(7, selected);\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index !== undefined ? this._index : null;\n\t},\n\n\tgetPath: function() {\n\t\treturn this._path || null;\n\t},\n\n\tgetCurve: function() {\n\t\tvar path = this._path,\n\t\t\tindex = this._index;\n\t\tif (path) {\n\t\t\tif (index > 0 && !path._closed\n\t\t\t\t\t&& index === path._segments.length - 1)\n\t\t\t\tindex--;\n\t\t\treturn path.getCurves()[index] || null;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetLocation: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve\n\t\t\t\t? new CurveLocation(curve, this === curve._segment1 ? 0 : 1)\n\t\t\t\t: null;\n\t},\n\n\tgetNext: function() {\n\t\tvar segments = this._path && this._path._segments;\n\t\treturn segments && (segments[this._index + 1]\n\t\t\t\t|| this._path._closed && segments[0]) || null;\n\t},\n\n\tsmooth: function(options, _first, _last) {\n\t\tvar opts = options || {},\n\t\t\ttype = opts.type,\n\t\t\tfactor = opts.factor,\n\t\t\tprev = this.getPrevious(),\n\t\t\tnext = this.getNext(),\n\t\t\tp0 = (prev || this)._point,\n\t\t\tp1 = this._point,\n\t\t\tp2 = (next || this)._point,\n\t\t\td1 = p0.getDistance(p1),\n\t\t\td2 = p1.getDistance(p2);\n\t\tif (!type || type === 'catmull-rom') {\n\t\t\tvar a = factor === undefined ? 0.5 : factor,\n\t\t\t\td1_a = Math.pow(d1, a),\n\t\t\t\td1_2a = d1_a * d1_a,\n\t\t\t\td2_a = Math.pow(d2, a),\n\t\t\t\td2_2a = d2_a * d2_a;\n\t\t\tif (!_first && prev) {\n\t\t\t\tvar A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a,\n\t\t\t\t\tN = 3 * d2_a * (d2_a + d1_a);\n\t\t\t\tthis.setHandleIn(N !== 0\n\t\t\t\t\t? new Point(\n\t\t\t\t\t\t(d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x,\n\t\t\t\t\t\t(d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y)\n\t\t\t\t\t: new Point());\n\t\t\t}\n\t\t\tif (!_last && next) {\n\t\t\t\tvar A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a,\n\t\t\t\t\tN = 3 * d1_a * (d1_a + d2_a);\n\t\t\t\tthis.setHandleOut(N !== 0\n\t\t\t\t\t? new Point(\n\t\t\t\t\t\t(d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x,\n\t\t\t\t\t\t(d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y)\n\t\t\t\t\t: new Point());\n\t\t\t}\n\t\t} else if (type === 'geometric') {\n\t\t\tif (prev && next) {\n\t\t\t\tvar vector = p0.subtract(p2),\n\t\t\t\t\tt = factor === undefined ? 0.4 : factor,\n\t\t\t\t\tk = t * d1 / (d1 + d2);\n\t\t\t\tif (!_first)\n\t\t\t\t\tthis.setHandleIn(vector.multiply(k));\n\t\t\t\tif (!_last)\n\t\t\t\t\tthis.setHandleOut(vector.multiply(k - t));\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new Error('Smoothing method \\'' + type + '\\' not supported.');\n\t\t}\n\t},\n\n\tgetPrevious: function() {\n\t\tvar segments = this._path && this._path._segments;\n\t\treturn segments && (segments[this._index - 1]\n\t\t\t\t|| this._path._closed && segments[segments.length - 1]) || null;\n\t},\n\n\tisFirst: function() {\n\t\treturn !this._index;\n\t},\n\n\tisLast: function() {\n\t\tvar path = this._path;\n\t\treturn path && this._index === path._segments.length - 1 || false;\n\t},\n\n\treverse: function() {\n\t\tvar handleIn = this._handleIn,\n\t\t\thandleOut = this._handleOut,\n\t\t\ttmp = handleIn.clone();\n\t\thandleIn.set(handleOut);\n\t\thandleOut.set(tmp);\n\t},\n\n\treversed: function() {\n\t\treturn new Segment(this._point, this._handleOut, this._handleIn);\n\t},\n\n\tremove: function() {\n\t\treturn this._path ? !!this._path.removeSegment(this._index) : false;\n\t},\n\n\tclone: function() {\n\t\treturn new Segment(this._point, this._handleIn, this._handleOut);\n\t},\n\n\tequals: function(segment) {\n\t\treturn segment === this || segment && this._class === segment._class\n\t\t\t\t&& this._point.equals(segment._point)\n\t\t\t\t&& this._handleIn.equals(segment._handleIn)\n\t\t\t\t&& this._handleOut.equals(segment._handleOut)\n\t\t\t\t|| false;\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [ 'point: ' + this._point ];\n\t\tif (!this._handleIn.isZero())\n\t\t\tparts.push('handleIn: ' + this._handleIn);\n\t\tif (!this._handleOut.isZero())\n\t\t\tparts.push('handleOut: ' + this._handleOut);\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\ttransform: function(matrix) {\n\t\tthis._transformCoordinates(matrix, new Array(6), true);\n\t\tthis._changed();\n\t},\n\n\tinterpolate: function(from, to, factor) {\n\t\tvar u = 1 - factor,\n\t\t\tv = factor,\n\t\t\tpoint1 = from._point,\n\t\t\tpoint2 = to._point,\n\t\t\thandleIn1 = from._handleIn,\n\t\t\thandleIn2 = to._handleIn,\n\t\t\thandleOut2 = to._handleOut,\n\t\t\thandleOut1 = from._handleOut;\n\t\tthis._point._set(\n\t\t\t\tu * point1._x + v * point2._x,\n\t\t\t\tu * point1._y + v * point2._y, true);\n\t\tthis._handleIn._set(\n\t\t\t\tu * handleIn1._x + v * handleIn2._x,\n\t\t\t\tu * handleIn1._y + v * handleIn2._y, true);\n\t\tthis._handleOut._set(\n\t\t\t\tu * handleOut1._x + v * handleOut2._x,\n\t\t\t\tu * handleOut1._y + v * handleOut2._y, true);\n\t\tthis._changed();\n\t},\n\n\t_transformCoordinates: function(matrix, coords, change) {\n\t\tvar point = this._point,\n\t\t\thandleIn = !change || !this._handleIn.isZero()\n\t\t\t\t\t? this._handleIn : null,\n\t\t\thandleOut = !change || !this._handleOut.isZero()\n\t\t\t\t\t? this._handleOut : null,\n\t\t\tx = point._x,\n\t\t\ty = point._y,\n\t\t\ti = 2;\n\t\tcoords[0] = x;\n\t\tcoords[1] = y;\n\t\tif (handleIn) {\n\t\t\tcoords[i++] = handleIn._x + x;\n\t\t\tcoords[i++] = handleIn._y + y;\n\t\t}\n\t\tif (handleOut) {\n\t\t\tcoords[i++] = handleOut._x + x;\n\t\t\tcoords[i++] = handleOut._y + y;\n\t\t}\n\t\tif (matrix) {\n\t\t\tmatrix._transformCoordinates(coords, coords, i / 2);\n\t\t\tx = coords[0];\n\t\t\ty = coords[1];\n\t\t\tif (change) {\n\t\t\t\tpoint._x = x;\n\t\t\t\tpoint._y = y;\n\t\t\t\ti = 2;\n\t\t\t\tif (handleIn) {\n\t\t\t\t\thandleIn._x = coords[i++] - x;\n\t\t\t\t\thandleIn._y = coords[i++] - y;\n\t\t\t\t}\n\t\t\t\tif (handleOut) {\n\t\t\t\t\thandleOut._x = coords[i++] - x;\n\t\t\t\t\thandleOut._y = coords[i++] - y;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!handleIn) {\n\t\t\t\t\tcoords[i++] = x;\n\t\t\t\t\tcoords[i++] = y;\n\t\t\t\t}\n\t\t\t\tif (!handleOut) {\n\t\t\t\t\tcoords[i++] = x;\n\t\t\t\t\tcoords[i++] = y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn coords;\n\t}\n});\n\nvar SegmentPoint = Point.extend({\n\tinitialize: function SegmentPoint(point, owner, key) {\n\t\tvar x, y,\n\t\t\tselected;\n\t\tif (!point) {\n\t\t\tx = y = 0;\n\t\t} else if ((x = point[0]) !== undefined) {\n\t\t\ty = point[1];\n\t\t} else {\n\t\t\tvar pt = point;\n\t\t\tif ((x = pt.x) === undefined) {\n\t\t\t\tpt = Point.read(arguments);\n\t\t\t\tx = pt.x;\n\t\t\t}\n\t\t\ty = pt.y;\n\t\t\tselected = pt.selected;\n\t\t}\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner = owner;\n\t\towner[key] = this;\n\t\tif (selected)\n\t\t\tthis.setSelected(true);\n\t},\n\n\t_set: function(x, y) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner._changed(this);\n\t\treturn this;\n\t},\n\n\tgetX: function() {\n\t\treturn this._x;\n\t},\n\n\tsetX: function(x) {\n\t\tthis._x = x;\n\t\tthis._owner._changed(this);\n\t},\n\n\tgetY: function() {\n\t\treturn this._y;\n\t},\n\n\tsetY: function(y) {\n\t\tthis._y = y;\n\t\tthis._owner._changed(this);\n\t},\n\n\tisZero: function() {\n\t\treturn Numerical.isZero(this._x) && Numerical.isZero(this._y);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._owner._selection & this._getSelection());\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis._owner.changeSelection(this._getSelection(), selected);\n\t},\n\n\t_getSelection: function() {\n\t\tvar owner = this._owner;\n\t\treturn this === owner._point ? 1\n\t\t\t: this === owner._handleIn ? 2\n\t\t\t: this === owner._handleOut ? 4\n\t\t\t: 0;\n\t}\n});\n\nvar Curve = Base.extend({\n\t_class: 'Curve',\n\n\tinitialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {\n\t\tvar count = arguments.length,\n\t\t\tseg1, seg2,\n\t\t\tpoint1, point2,\n\t\t\thandle1, handle2;\n\t\tif (count === 3) {\n\t\t\tthis._path = arg0;\n\t\t\tseg1 = arg1;\n\t\t\tseg2 = arg2;\n\t\t} else if (!count) {\n\t\t\tseg1 = new Segment();\n\t\t\tseg2 = new Segment();\n\t\t} else if (count === 1) {\n\t\t\tif ('segment1' in arg0) {\n\t\t\t\tseg1 = new Segment(arg0.segment1);\n\t\t\t\tseg2 = new Segment(arg0.segment2);\n\t\t\t} else if ('point1' in arg0) {\n\t\t\t\tpoint1 = arg0.point1;\n\t\t\t\thandle1 = arg0.handle1;\n\t\t\t\thandle2 = arg0.handle2;\n\t\t\t\tpoint2 = arg0.point2;\n\t\t\t} else if (Array.isArray(arg0)) {\n\t\t\t\tpoint1 = [arg0[0], arg0[1]];\n\t\t\t\tpoint2 = [arg0[6], arg0[7]];\n\t\t\t\thandle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];\n\t\t\t\thandle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];\n\t\t\t}\n\t\t} else if (count === 2) {\n\t\t\tseg1 = new Segment(arg0);\n\t\t\tseg2 = new Segment(arg1);\n\t\t} else if (count === 4) {\n\t\t\tpoint1 = arg0;\n\t\t\thandle1 = arg1;\n\t\t\thandle2 = arg2;\n\t\t\tpoint2 = arg3;\n\t\t} else if (count === 8) {\n\t\t\tpoint1 = [arg0, arg1];\n\t\t\tpoint2 = [arg6, arg7];\n\t\t\thandle1 = [arg2 - arg0, arg3 - arg1];\n\t\t\thandle2 = [arg4 - arg6, arg5 - arg7];\n\t\t}\n\t\tthis._segment1 = seg1 || new Segment(point1, null, handle1);\n\t\tthis._segment2 = seg2 || new Segment(point2, handle2, null);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this.hasHandles()\n\t\t\t\t? [this.getPoint1(), this.getHandle1(), this.getHandle2(),\n\t\t\t\t\tthis.getPoint2()]\n\t\t\t\t: [this.getPoint1(), this.getPoint2()],\n\t\t\t\toptions, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tthis._length = this._bounds = undefined;\n\t},\n\n\tclone: function() {\n\t\treturn new Curve(this._segment1, this._segment2);\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [ 'point1: ' + this._segment1._point ];\n\t\tif (!this._segment1._handleOut.isZero())\n\t\t\tparts.push('handle1: ' + this._segment1._handleOut);\n\t\tif (!this._segment2._handleIn.isZero())\n\t\t\tparts.push('handle2: ' + this._segment2._handleIn);\n\t\tparts.push('point2: ' + this._segment2._point);\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\tremove: function() {\n\t\tvar removed = false;\n\t\tif (this._path) {\n\t\t\tvar segment2 = this._segment2,\n\t\t\t\thandleOut = segment2._handleOut;\n\t\t\tremoved = segment2.remove();\n\t\t\tif (removed)\n\t\t\t\tthis._segment1._handleOut.set(handleOut);\n\t\t}\n\t\treturn removed;\n\t},\n\n\tgetPoint1: function() {\n\t\treturn this._segment1._point;\n\t},\n\n\tsetPoint1: function() {\n\t\tthis._segment1._point.set(Point.read(arguments));\n\t},\n\n\tgetPoint2: function() {\n\t\treturn this._segment2._point;\n\t},\n\n\tsetPoint2: function() {\n\t\tthis._segment2._point.set(Point.read(arguments));\n\t},\n\n\tgetHandle1: function() {\n\t\treturn this._segment1._handleOut;\n\t},\n\n\tsetHandle1: function() {\n\t\tthis._segment1._handleOut.set(Point.read(arguments));\n\t},\n\n\tgetHandle2: function() {\n\t\treturn this._segment2._handleIn;\n\t},\n\n\tsetHandle2: function() {\n\t\tthis._segment2._handleIn.set(Point.read(arguments));\n\t},\n\n\tgetSegment1: function() {\n\t\treturn this._segment1;\n\t},\n\n\tgetSegment2: function() {\n\t\treturn this._segment2;\n\t},\n\n\tgetPath: function() {\n\t\treturn this._path;\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._segment1._index;\n\t},\n\n\tgetNext: function() {\n\t\tvar curves = this._path && this._path._curves;\n\t\treturn curves && (curves[this._segment1._index + 1]\n\t\t\t\t|| this._path._closed && curves[0]) || null;\n\t},\n\n\tgetPrevious: function() {\n\t\tvar curves = this._path && this._path._curves;\n\t\treturn curves && (curves[this._segment1._index - 1]\n\t\t\t\t|| this._path._closed && curves[curves.length - 1]) || null;\n\t},\n\n\tisFirst: function() {\n\t\treturn !this._segment1._index;\n\t},\n\n\tisLast: function() {\n\t\tvar path = this._path;\n\t\treturn path && this._segment1._index === path._curves.length - 1\n\t\t\t\t|| false;\n\t},\n\n\tisSelected: function() {\n\t\treturn this.getPoint1().isSelected()\n\t\t\t\t&& this.getHandle2().isSelected()\n\t\t\t\t&& this.getHandle2().isSelected()\n\t\t\t\t&& this.getPoint2().isSelected();\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis.getPoint1().setSelected(selected);\n\t\tthis.getHandle1().setSelected(selected);\n\t\tthis.getHandle2().setSelected(selected);\n\t\tthis.getPoint2().setSelected(selected);\n\t},\n\n\tgetValues: function(matrix) {\n\t\treturn Curve.getValues(this._segment1, this._segment2, matrix);\n\t},\n\n\tgetPoints: function() {\n\t\tvar coords = this.getValues(),\n\t\t\tpoints = [];\n\t\tfor (var i = 0; i < 8; i += 2)\n\t\t\tpoints.push(new Point(coords[i], coords[i + 1]));\n\t\treturn points;\n\t},\n\n\tgetLength: function() {\n\t\tif (this._length == null)\n\t\t\tthis._length = Curve.getLength(this.getValues(), 0, 1);\n\t\treturn this._length;\n\t},\n\n\tgetArea: function() {\n\t\treturn Curve.getArea(this.getValues());\n\t},\n\n\tgetLine: function() {\n\t\treturn new Line(this._segment1._point, this._segment2._point);\n\t},\n\n\tgetPart: function(from, to) {\n\t\treturn new Curve(Curve.getPart(this.getValues(), from, to));\n\t},\n\n\tgetPartLength: function(from, to) {\n\t\treturn Curve.getLength(this.getValues(), from, to);\n\t},\n\n\tgetIntersections: function(curve) {\n\t\treturn Curve._getIntersections(this.getValues(),\n\t\t\t\tcurve && curve !== this ? curve.getValues() : null,\n\t\t\t\tthis, curve, [], {});\n\t},\n\n\tdivideAt: function(location) {\n\t\treturn this.divideAtTime(location && location.curve === this\n\t\t\t\t? location.time : location);\n\t},\n\n\tdivideAtTime: function(time, _setHandles) {\n\t\tvar tMin = 4e-7,\n\t\t\ttMax = 1 - tMin,\n\t\t\tres = null;\n\t\tif (time >= tMin && time <= tMax) {\n\t\t\tvar parts = Curve.subdivide(this.getValues(), time),\n\t\t\t\tleft = parts[0],\n\t\t\t\tright = parts[1],\n\t\t\t\tsetHandles = _setHandles || this.hasHandles(),\n\t\t\t\tsegment1 = this._segment1,\n\t\t\t\tsegment2 = this._segment2,\n\t\t\t\tpath = this._path;\n\t\t\tif (setHandles) {\n\t\t\t\tsegment1._handleOut._set(left[2] - left[0], left[3] - left[1]);\n\t\t\t\tsegment2._handleIn._set(right[4] - right[6],right[5] - right[7]);\n\t\t\t}\n\t\t\tvar x = left[6], y = left[7],\n\t\t\t\tsegment = new Segment(new Point(x, y),\n\t\t\t\t\t\tsetHandles && new Point(left[4] - x, left[5] - y),\n\t\t\t\t\t\tsetHandles && new Point(right[2] - x, right[3] - y));\n\t\t\tif (path) {\n\t\t\t\tpath.insert(segment1._index + 1, segment);\n\t\t\t\tres = this.getNext();\n\t\t\t} else {\n\t\t\t\tthis._segment2 = segment;\n\t\t\t\tthis._changed();\n\t\t\t\tres = new Curve(segment, segment2);\n\t\t\t}\n\t\t}\n\t\treturn res;\n\t},\n\n\tsplitAt: function(location) {\n\t\treturn this._path ? this._path.splitAt(location) : null;\n\t},\n\n\tsplitAtTime: function(t) {\n\t\treturn this.splitAt(this.getLocationAtTime(t));\n\t},\n\n\tdivide: function(offset, isTime) {\n\t\treturn this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset\n\t\t\t\t: this.getTimeAt(offset));\n\t},\n\n\tsplit: function(offset, isTime) {\n\t\treturn this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset\n\t\t\t\t: this.getTimeAt(offset));\n\t},\n\n\treversed: function() {\n\t\treturn new Curve(this._segment2.reversed(), this._segment1.reversed());\n\t},\n\n\tclearHandles: function() {\n\t\tthis._segment1._handleOut._set(0, 0);\n\t\tthis._segment2._handleIn._set(0, 0);\n\t},\n\nstatics: {\n\tgetValues: function(segment1, segment2, matrix) {\n\t\tvar p1 = segment1._point,\n\t\t\th1 = segment1._handleOut,\n\t\t\th2 = segment2._handleIn,\n\t\t\tp2 = segment2._point,\n\t\t\tvalues = [\n\t\t\t\tp1._x, p1._y,\n\t\t\t\tp1._x + h1._x, p1._y + h1._y,\n\t\t\t\tp2._x + h2._x, p2._y + h2._y,\n\t\t\t\tp2._x, p2._y\n\t\t\t];\n\t\tif (matrix)\n\t\t\tmatrix._transformCoordinates(values, values, 4);\n\t\treturn values;\n\t},\n\n\tsubdivide: function(v, t) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7];\n\t\tif (t === undefined)\n\t\t\tt = 0.5;\n\t\tvar u = 1 - t,\n\t\t\tp3x = u * p1x + t * c1x, p3y = u * p1y + t * c1y,\n\t\t\tp4x = u * c1x + t * c2x, p4y = u * c1y + t * c2y,\n\t\t\tp5x = u * c2x + t * p2x, p5y = u * c2y + t * p2y,\n\t\t\tp6x = u * p3x + t * p4x, p6y = u * p3y + t * p4y,\n\t\t\tp7x = u * p4x + t * p5x, p7y = u * p4y + t * p5y,\n\t\t\tp8x = u * p6x + t * p7x, p8y = u * p6y + t * p7y;\n\t\treturn [\n\t\t\t[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y],\n\t\t\t[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y]\n\t\t];\n\t},\n\n\tgetMonoCurves: function(v, dir) {\n\t\tvar curves = [],\n\t\t\tio = dir ? 0 : 1,\n\t\t\to0 = v[io],\n\t\t\to1 = v[io + 2],\n\t\t\to2 = v[io + 4],\n\t\t\to3 = v[io + 6];\n\t\tif ((o0 >= o1) === (o1 >= o2) && (o1 >= o2) === (o2 >= o3)\n\t\t\t\t|| Curve.isStraight(v)) {\n\t\t\tcurves.push(v);\n\t\t} else {\n\t\t\tvar a = 3 * (o1 - o2) - o0 + o3,\n\t\t\t\tb = 2 * (o0 + o2) - 4 * o1,\n\t\t\t\tc = o1 - o0,\n\t\t\t\ttMin = 4e-7,\n\t\t\t\ttMax = 1 - tMin,\n\t\t\t\troots = [],\n\t\t\t\tn = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);\n\t\t\tif (!n) {\n\t\t\t\tcurves.push(v);\n\t\t\t} else {\n\t\t\t\troots.sort();\n\t\t\t\tvar t = roots[0],\n\t\t\t\t\tparts = Curve.subdivide(v, t);\n\t\t\t\tcurves.push(parts[0]);\n\t\t\t\tif (n > 1) {\n\t\t\t\t\tt = (roots[1] - t) / (1 - t);\n\t\t\t\t\tparts = Curve.subdivide(parts[1], t);\n\t\t\t\t\tcurves.push(parts[0]);\n\t\t\t\t}\n\t\t\t\tcurves.push(parts[1]);\n\t\t\t}\n\t\t}\n\t\treturn curves;\n\t},\n\n\tsolveCubic: function (v, coord, val, roots, min, max) {\n\t\tvar p1 = v[coord],\n\t\t\tc1 = v[coord + 2],\n\t\t\tc2 = v[coord + 4],\n\t\t\tp2 = v[coord + 6],\n\t\t\tres = 0;\n\t\tif ( !(p1 < val && p2 < val && c1 < val && c2 < val ||\n\t\t\t\tp1 > val && p2 > val && c1 > val && c2 > val)) {\n\t\t\tvar c = 3 * (c1 - p1),\n\t\t\t\tb = 3 * (c2 - c1) - c,\n\t\t\t\ta = p2 - p1 - c - b;\n\t\t\tres = Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);\n\t\t}\n\t\treturn res;\n\t},\n\n\tgetTimeOf: function(v, point) {\n\t\tvar p1 = new Point(v[0], v[1]),\n\t\t\tp2 = new Point(v[6], v[7]),\n\t\t\tepsilon = 1e-12,\n\t\t\tt = point.isClose(p1, epsilon) ? 0\n\t\t\t : point.isClose(p2, epsilon) ? 1\n\t\t\t : null;\n\t\tif (t !== null)\n\t\t\treturn t;\n\t\tvar coords = [point.x, point.y],\n\t\t\troots = [],\n\t\t\tgeomEpsilon = 1e-7;\n\t\tfor (var c = 0; c < 2; c++) {\n\t\t\tvar count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);\n\t\t\tfor (var i = 0; i < count; i++) {\n\t\t\t\tt = roots[i];\n\t\t\t\tif (point.isClose(Curve.getPoint(v, t), geomEpsilon))\n\t\t\t\t\treturn t;\n\t\t\t}\n\t\t}\n\t\treturn point.isClose(p1, geomEpsilon) ? 0\n\t\t\t : point.isClose(p2, geomEpsilon) ? 1\n\t\t\t : null;\n\t},\n\n\tgetNearestTime: function(v, point) {\n\t\tif (Curve.isStraight(v)) {\n\t\t\tvar p1x = v[0], p1y = v[1],\n\t\t\t\tp2x = v[6], p2y = v[7],\n\t\t\t\tvx = p2x - p1x, vy = p2y - p1y,\n\t\t\t\tdet = vx * vx + vy * vy;\n\t\t\tif (det === 0)\n\t\t\t\treturn 0;\n\t\t\tvar u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;\n\t\t\treturn u < 1e-12 ? 0\n\t\t\t\t : u > 0.999999999999 ? 1\n\t\t\t\t : Curve.getTimeOf(v,\n\t\t\t\t\tnew Point(p1x + u * vx, p1y + u * vy));\n\t\t}\n\n\t\tvar count = 100,\n\t\t\tminDist = Infinity,\n\t\t\tminT = 0;\n\n\t\tfunction refine(t) {\n\t\t\tif (t >= 0 && t <= 1) {\n\t\t\t\tvar dist = point.getDistance(Curve.getPoint(v, t), true);\n\t\t\t\tif (dist < minDist) {\n\t\t\t\t\tminDist = dist;\n\t\t\t\t\tminT = t;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0; i <= count; i++)\n\t\t\trefine(i / count);\n\n\t\tvar step = 1 / (count * 2);\n\t\twhile (step > 4e-7) {\n\t\t\tif (!refine(minT - step) && !refine(minT + step))\n\t\t\t\tstep /= 2;\n\t\t}\n\t\treturn minT;\n\t},\n\n\tgetPart: function(v, from, to) {\n\t\tvar flip = from > to;\n\t\tif (flip) {\n\t\t\tvar tmp = from;\n\t\t\tfrom = to;\n\t\t\tto = tmp;\n\t\t}\n\t\tif (from > 0)\n\t\t\tv = Curve.subdivide(v, from)[1];\n\t\tif (to < 1)\n\t\t\tv = Curve.subdivide(v, (to - from) / (1 - from))[0];\n\t\treturn flip\n\t\t\t\t? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]\n\t\t\t\t: v;\n\t},\n\n\tisFlatEnough: function(v, flatness) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7],\n\t\t\tux = 3 * c1x - 2 * p1x - p2x,\n\t\t\tuy = 3 * c1y - 2 * p1y - p2y,\n\t\t\tvx = 3 * c2x - 2 * p2x - p1x,\n\t\t\tvy = 3 * c2y - 2 * p2y - p1y;\n\t\treturn Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)\n\t\t\t\t<= 16 * flatness * flatness;\n\t},\n\n\tgetArea: function(v) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7];\n\t\treturn 3 * ((p2y - p1y) * (c1x + c2x) - (p2x - p1x) * (c1y + c2y)\n\t\t\t\t+ c1y * (p1x - c2x) - c1x * (p1y - c2y)\n\t\t\t\t+ p2y * (c2x + p1x / 3) - p2x * (c2y + p1y / 3)) / 20;\n\t},\n\n\tgetBounds: function(v) {\n\t\tvar min = v.slice(0, 2),\n\t\t\tmax = min.slice(),\n\t\t\troots = [0, 0];\n\t\tfor (var i = 0; i < 2; i++)\n\t\t\tCurve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],\n\t\t\t\t\ti, 0, min, max, roots);\n\t\treturn new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);\n\t},\n\n\t_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {\n\t\tfunction add(value, padding) {\n\t\t\tvar left = value - padding,\n\t\t\t\tright = value + padding;\n\t\t\tif (left < min[coord])\n\t\t\t\tmin[coord] = left;\n\t\t\tif (right > max[coord])\n\t\t\t\tmax[coord] = right;\n\t\t}\n\n\t\tpadding /= 2;\n\t\tvar minPad = min[coord] - padding,\n\t\t\tmaxPad = max[coord] + padding;\n\t\tif ( v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||\n\t\t\t\tv0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {\n\t\t\tif (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {\n\t\t\t\tadd(v0, padding);\n\t\t\t\tadd(v3, padding);\n\t\t\t} else {\n\t\t\t\tvar a = 3 * (v1 - v2) - v0 + v3,\n\t\t\t\t\tb = 2 * (v0 + v2) - 4 * v1,\n\t\t\t\t\tc = v1 - v0,\n\t\t\t\t\tcount = Numerical.solveQuadratic(a, b, c, roots),\n\t\t\t\t\ttMin = 4e-7,\n\t\t\t\t\ttMax = 1 - tMin;\n\t\t\t\tadd(v3, 0);\n\t\t\t\tfor (var i = 0; i < count; i++) {\n\t\t\t\t\tvar t = roots[i],\n\t\t\t\t\t\tu = 1 - t;\n\t\t\t\t\tif (tMin < t && t < tMax)\n\t\t\t\t\t\tadd(u * u * u * v0\n\t\t\t\t\t\t\t+ 3 * u * u * t * v1\n\t\t\t\t\t\t\t+ 3 * u * t * t * v2\n\t\t\t\t\t\t\t+ t * t * t * v3,\n\t\t\t\t\t\t\tpadding);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}}, Base.each(\n\t['getBounds', 'getStrokeBounds', 'getHandleBounds'],\n\tfunction(name) {\n\t\tthis[name] = function() {\n\t\t\tif (!this._bounds)\n\t\t\t\tthis._bounds = {};\n\t\t\tvar bounds = this._bounds[name];\n\t\t\tif (!bounds) {\n\t\t\t\tbounds = this._bounds[name] = Path[name](\n\t\t\t\t\t\t[this._segment1, this._segment2], false, this._path);\n\t\t\t}\n\t\t\treturn bounds.clone();\n\t\t};\n\t},\n{\n\n}), Base.each({\n\tisStraight: function(l, h1, h2) {\n\t\tif (h1.isZero() && h2.isZero()) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\tvar v = l.getVector(),\n\t\t\t\tepsilon = 1e-7;\n\t\t\tif (v.isZero()) {\n\t\t\t\treturn false;\n\t\t\t} else if (l.getDistance(h1) < epsilon\n\t\t\t\t\t&& l.getDistance(h2) < epsilon) {\n\t\t\t\tvar div = v.dot(v),\n\t\t\t\t\tp1 = v.dot(h1) / div,\n\t\t\t\t\tp2 = v.dot(h2) / div;\n\t\t\t\treturn p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t},\n\n\tisLinear: function(l, h1, h2) {\n\t\tvar third = l.getVector().divide(3);\n\t\treturn h1.equals(third) && h2.negate().equals(third);\n\t}\n}, function(test, name) {\n\tthis[name] = function() {\n\t\tvar seg1 = this._segment1,\n\t\t\tseg2 = this._segment2;\n\t\treturn test(new Line(seg1._point, seg2._point),\n\t\t\t\tseg1._handleOut, seg2._handleIn);\n\t};\n\n\tthis.statics[name] = function(v) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tp2x = v[6], p2y = v[7];\n\t\treturn test(new Line(p1x, p1y, p2x, p2y),\n\t\t\t\tnew Point(v[2] - p1x, v[3] - p1y),\n\t\t\t\tnew Point(v[4] - p2x, v[5] - p2y));\n\t};\n}, {\n\tstatics: {},\n\n\thasHandles: function() {\n\t\treturn !this._segment1._handleOut.isZero()\n\t\t\t\t|| !this._segment2._handleIn.isZero();\n\t},\n\n\tisCollinear: function(curve) {\n\t\treturn curve && this.isStraight() && curve.isStraight()\n\t\t\t\t&& this.getLine().isCollinear(curve.getLine());\n\t},\n\n\tisHorizontal: function() {\n\t\treturn this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)\n\t\t\t\t< 1e-8;\n\t},\n\n\tisVertical: function() {\n\t\treturn this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)\n\t\t\t\t< 1e-8;\n\t}\n}), {\n\tbeans: false,\n\n\tgetLocationAt: function(offset, _isTime) {\n\t\treturn this.getLocationAtTime(\n\t\t\t\t_isTime ? offset : this.getTimeAt(offset));\n\t},\n\n\tgetLocationAtTime: function(t) {\n\t\treturn t != null && t >= 0 && t <= 1\n\t\t\t\t? new CurveLocation(this, t)\n\t\t\t\t: null;\n\t},\n\n\tgetTimeAt: function(offset, start) {\n\t\treturn Curve.getTimeAt(this.getValues(), offset, start);\n\t},\n\n\tgetParameterAt: '#getTimeAt',\n\n\tgetOffsetAtTime: function(t) {\n\t\treturn this.getPartLength(0, t);\n\t},\n\n\tgetLocationOf: function() {\n\t\treturn this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));\n\t},\n\n\tgetOffsetOf: function() {\n\t\tvar loc = this.getLocationOf.apply(this, arguments);\n\t\treturn loc ? loc.getOffset() : null;\n\t},\n\n\tgetTimeOf: function() {\n\t\treturn Curve.getTimeOf(this.getValues(), Point.read(arguments));\n\t},\n\n\tgetParameterOf: '#getTimeOf',\n\n\tgetNearestLocation: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tvalues = this.getValues(),\n\t\t\tt = Curve.getNearestTime(values, point),\n\t\t\tpt = Curve.getPoint(values, t);\n\t\treturn new CurveLocation(this, t, pt, null, point.getDistance(pt));\n\t},\n\n\tgetNearestPoint: function() {\n\t\tvar loc = this.getNearestLocation.apply(this, arguments);\n\t\treturn loc ? loc.getPoint() : loc;\n\t}\n\n},\nnew function() {\n\tvar methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',\n\t\t'getWeightedNormal', 'getCurvature'];\n\treturn Base.each(methods,\n\t\tfunction(name) {\n\t\t\tthis[name + 'At'] = function(location, _isTime) {\n\t\t\t\tvar values = this.getValues();\n\t\t\t\treturn Curve[name](values, _isTime ? location\n\t\t\t\t\t\t: Curve.getTimeAt(values, location));\n\t\t\t};\n\n\t\t\tthis[name + 'AtTime'] = function(time) {\n\t\t\t\treturn Curve[name](this.getValues(), time);\n\t\t\t};\n\t\t}, {\n\t\t\tstatics: {\n\t\t\t\t_evaluateMethods: methods\n\t\t\t}\n\t\t}\n\t);\n},\nnew function() {\n\n\tfunction getLengthIntegrand(v) {\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7],\n\n\t\t\tax = 9 * (c1x - c2x) + 3 * (p2x - p1x),\n\t\t\tbx = 6 * (p1x + c2x) - 12 * c1x,\n\t\t\tcx = 3 * (c1x - p1x),\n\n\t\t\tay = 9 * (c1y - c2y) + 3 * (p2y - p1y),\n\t\t\tby = 6 * (p1y + c2y) - 12 * c1y,\n\t\t\tcy = 3 * (c1y - p1y);\n\n\t\treturn function(t) {\n\t\t\tvar dx = (ax * t + bx) * t + cx,\n\t\t\t\tdy = (ay * t + by) * t + cy;\n\t\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t\t};\n\t}\n\n\tfunction getIterations(a, b) {\n\t\treturn Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));\n\t}\n\n\tfunction evaluate(v, t, type, normalized) {\n\t\tif (t == null || t < 0 || t > 1)\n\t\t\treturn null;\n\t\tvar p1x = v[0], p1y = v[1],\n\t\t\tc1x = v[2], c1y = v[3],\n\t\t\tc2x = v[4], c2y = v[5],\n\t\t\tp2x = v[6], p2y = v[7],\n\t\t\tisZero = Numerical.isZero;\n\t\tif (isZero(c1x - p1x) && isZero(c1y - p1y)) {\n\t\t\tc1x = p1x;\n\t\t\tc1y = p1y;\n\t\t}\n\t\tif (isZero(c2x - p2x) && isZero(c2y - p2y)) {\n\t\t\tc2x = p2x;\n\t\t\tc2y = p2y;\n\t\t}\n\t\tvar cx = 3 * (c1x - p1x),\n\t\t\tbx = 3 * (c2x - c1x) - cx,\n\t\t\tax = p2x - p1x - cx - bx,\n\t\t\tcy = 3 * (c1y - p1y),\n\t\t\tby = 3 * (c2y - c1y) - cy,\n\t\t\tay = p2y - p1y - cy - by,\n\t\t\tx, y;\n\t\tif (type === 0) {\n\t\t\tx = t === 0 ? p1x : t === 1 ? p2x\n\t\t\t\t\t: ((ax * t + bx) * t + cx) * t + p1x;\n\t\t\ty = t === 0 ? p1y : t === 1 ? p2y\n\t\t\t\t\t: ((ay * t + by) * t + cy) * t + p1y;\n\t\t} else {\n\t\t\tvar tMin = 4e-7,\n\t\t\t\ttMax = 1 - tMin;\n\t\t\tif (t < tMin) {\n\t\t\t\tx = cx;\n\t\t\t\ty = cy;\n\t\t\t} else if (t > tMax) {\n\t\t\t\tx = 3 * (p2x - c2x);\n\t\t\t\ty = 3 * (p2y - c2y);\n\t\t\t} else {\n\t\t\t\tx = (3 * ax * t + 2 * bx) * t + cx;\n\t\t\t\ty = (3 * ay * t + 2 * by) * t + cy;\n\t\t\t}\n\t\t\tif (normalized) {\n\t\t\t\tif (x === 0 && y === 0 && (t < tMin || t > tMax)) {\n\t\t\t\t\tx = c2x - c1x;\n\t\t\t\t\ty = c2y - c1y;\n\t\t\t\t}\n\t\t\t\tvar len = Math.sqrt(x * x + y * y);\n\t\t\t\tif (len) {\n\t\t\t\t\tx /= len;\n\t\t\t\t\ty /= len;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (type === 3) {\n\t\t\t\tvar x2 = 6 * ax * t + 2 * bx,\n\t\t\t\t\ty2 = 6 * ay * t + 2 * by,\n\t\t\t\t\td = Math.pow(x * x + y * y, 3 / 2);\n\t\t\t\tx = d !== 0 ? (x * y2 - y * x2) / d : 0;\n\t\t\t\ty = 0;\n\t\t\t}\n\t\t}\n\t\treturn type === 2 ? new Point(y, -x) : new Point(x, y);\n\t}\n\n\treturn { statics: {\n\n\t\tgetLength: function(v, a, b, ds) {\n\t\t\tif (a === undefined)\n\t\t\t\ta = 0;\n\t\t\tif (b === undefined)\n\t\t\t\tb = 1;\n\t\t\tif (Curve.isStraight(v)) {\n\t\t\t\tvar c = v;\n\t\t\t\tif (b < 1) {\n\t\t\t\t\tc = Curve.subdivide(c, b)[0];\n\t\t\t\t\ta /= b;\n\t\t\t\t}\n\t\t\t\tif (a > 0) {\n\t\t\t\t\tc = Curve.subdivide(c, a)[1];\n\t\t\t\t}\n\t\t\t\tvar dx = c[6] - c[0],\n\t\t\t\t\tdy = c[7] - c[1];\n\t\t\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t\t\t}\n\t\t\treturn Numerical.integrate(ds || getLengthIntegrand(v), a, b,\n\t\t\t\t\tgetIterations(a, b));\n\t\t},\n\n\t\tgetTimeAt: function(v, offset, start) {\n\t\t\tif (start === undefined)\n\t\t\t\tstart = offset < 0 ? 1 : 0;\n\t\t\tif (offset === 0)\n\t\t\t\treturn start;\n\t\t\tvar abs = Math.abs,\n\t\t\t\tepsilon = 1e-12,\n\t\t\t\tforward = offset > 0,\n\t\t\t\ta = forward ? start : 0,\n\t\t\t\tb = forward ? 1 : start,\n\t\t\t\tds = getLengthIntegrand(v),\n\t\t\t\trangeLength = Curve.getLength(v, a, b, ds),\n\t\t\t\tdiff = abs(offset) - rangeLength;\n\t\t\tif (abs(diff) < epsilon) {\n\t\t\t\treturn forward ? b : a;\n\t\t\t} else if (diff > epsilon) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tvar guess = offset / rangeLength,\n\t\t\t\tlength = 0;\n\t\t\tfunction f(t) {\n\t\t\t\tlength += Numerical.integrate(ds, start, t,\n\t\t\t\t\t\tgetIterations(start, t));\n\t\t\t\tstart = t;\n\t\t\t\treturn length - offset;\n\t\t\t}\n\t\t\treturn Numerical.findRoot(f, ds, start + guess, a, b, 32,\n\t\t\t\t\t1e-12);\n\t\t},\n\n\t\tgetPoint: function(v, t) {\n\t\t\treturn evaluate(v, t, 0, false);\n\t\t},\n\n\t\tgetTangent: function(v, t) {\n\t\t\treturn evaluate(v, t, 1, true);\n\t\t},\n\n\t\tgetWeightedTangent: function(v, t) {\n\t\t\treturn evaluate(v, t, 1, false);\n\t\t},\n\n\t\tgetNormal: function(v, t) {\n\t\t\treturn evaluate(v, t, 2, true);\n\t\t},\n\n\t\tgetWeightedNormal: function(v, t) {\n\t\t\treturn evaluate(v, t, 2, false);\n\t\t},\n\n\t\tgetCurvature: function(v, t) {\n\t\t\treturn evaluate(v, t, 3, false).x;\n\t\t}\n\t}};\n},\nnew function() {\n\n\tfunction addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,\n\t\t\toverlap) {\n\t\tvar excludeStart = !overlap && param.excludeStart,\n\t\t\texcludeEnd = !overlap && param.excludeEnd,\n\t\t\ttMin = 4e-7,\n\t\t\ttMax = 1 - tMin;\n\t\tif (t1 == null)\n\t\t\tt1 = Curve.getTimeOf(v1, p1);\n\t\tif (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&\n\t\t\tt1 <= (excludeEnd ? tMax : 1)) {\n\t\t\tif (t2 == null)\n\t\t\t\tt2 = Curve.getTimeOf(v2, p2);\n\t\t\tif (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&\n\t\t\t\tt2 <= (excludeStart ? tMax : 1)) {\n\t\t\t\tvar renormalize = param.renormalize;\n\t\t\t\tif (renormalize) {\n\t\t\t\t\tvar res = renormalize(t1, t2);\n\t\t\t\t\tt1 = res[0];\n\t\t\t\t\tt2 = res[1];\n\t\t\t\t}\n\t\t\t\tvar loc1 = new CurveLocation(c1, t1,\n\t\t\t\t\t\tp1 || Curve.getPoint(v1, t1), overlap),\n\t\t\t\t\tloc2 = new CurveLocation(c2, t2,\n\t\t\t\t\t\tp2 || Curve.getPoint(v2, t2), overlap),\n\t\t\t\t\tflip = loc1.getPath() === loc2.getPath()\n\t\t\t\t\t\t&& loc1.getIndex() > loc2.getIndex(),\n\t\t\t\t\tloc = flip ? loc2 : loc1,\n\t\t\t\t\tinclude = param.include;\n\t\t\t\tloc1._intersection = loc2;\n\t\t\t\tloc2._intersection = loc1;\n\t\t\t\tif (!include || include(loc)) {\n\t\t\t\t\tCurveLocation.insert(locations, loc, true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction addCurveIntersections(v1, v2, c1, c2, locations, param, tMin, tMax,\n\t\t\tuMin, uMax, flip, recursion, calls) {\n\t\tif (++recursion >= 48 || ++calls > 4096)\n\t\t\treturn calls;\n\t\tvar q0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],\n\t\t\tgetSignedDistance = Line.getSignedDistance,\n\t\t\td1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),\n\t\t\td2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),\n\t\t\tfactor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,\n\t\t\tdMin = factor * Math.min(0, d1, d2),\n\t\t\tdMax = factor * Math.max(0, d1, d2),\n\t\t\tdp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),\n\t\t\tdp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),\n\t\t\tdp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),\n\t\t\tdp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),\n\t\t\thull = getConvexHull(dp0, dp1, dp2, dp3),\n\t\t\ttop = hull[0],\n\t\t\tbottom = hull[1],\n\t\t\ttMinClip,\n\t\t\ttMaxClip;\n\t\tif (d1 === 0 && d2 === 0\n\t\t\t\t&& dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0\n\t\t\t|| (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null\n\t\t\t|| (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),\n\t\t\t\tdMin, dMax)) == null)\n\t\t\treturn calls;\n\t\tvar tMinNew = tMin + (tMax - tMin) * tMinClip,\n\t\t\ttMaxNew = tMin + (tMax - tMin) * tMaxClip;\n\t\tif (Math.max(uMax - uMin, tMaxNew - tMinNew)\n\t\t\t\t< 1e-10) {\n\t\t\tvar t = (tMinNew + tMaxNew) / 2,\n\t\t\t\tu = (uMin + uMax) / 2;\n\t\t\tv1 = c1.getValues();\n\t\t\tv2 = c2.getValues();\n\t\t\taddLocation(locations, param,\n\t\t\t\t\tflip ? v2 : v1, flip ? c2 : c1, flip ? u : t, null,\n\t\t\t\t\tflip ? v1 : v2, flip ? c1 : c2, flip ? t : u, null);\n\t\t} else {\n\t\t\tv1 = Curve.getPart(v1, tMinClip, tMaxClip);\n\t\t\tif (tMaxClip - tMinClip > 0.8) {\n\t\t\t\tif (tMaxNew - tMinNew > uMax - uMin) {\n\t\t\t\t\tvar parts = Curve.subdivide(v1, 0.5),\n\t\t\t\t\t\tt = (tMinNew + tMaxNew) / 2;\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tv2, parts[0], c2, c1, locations, param,\n\t\t\t\t\t\t\tuMin, uMax, tMinNew, t, !flip, recursion, calls);\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tv2, parts[1], c2, c1, locations, param,\n\t\t\t\t\t\t\tuMin, uMax, t, tMaxNew, !flip, recursion, calls);\n\t\t\t\t} else {\n\t\t\t\t\tvar parts = Curve.subdivide(v2, 0.5),\n\t\t\t\t\t\tu = (uMin + uMax) / 2;\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tparts[0], v1, c2, c1, locations, param,\n\t\t\t\t\t\t\tuMin, u, tMinNew, tMaxNew, !flip, recursion, calls);\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tparts[1], v1, c2, c1, locations, param,\n\t\t\t\t\t\t\tu, uMax, tMinNew, tMaxNew, !flip, recursion, calls);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (uMax - uMin >= 1e-10) {\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\tv2, v1, c2, c1, locations, param,\n\t\t\t\t\t\tuMin, uMax, tMinNew, tMaxNew, !flip, recursion, calls);\n\t\t\t\t} else {\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\tv1, v2, c1, c2, locations, param,\n\t\t\t\t\t\ttMinNew, tMaxNew, uMin, uMax, flip, recursion, calls);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn calls;\n\t}\n\n\tfunction getConvexHull(dq0, dq1, dq2, dq3) {\n\t\tvar p0 = [ 0, dq0 ],\n\t\t\tp1 = [ 1 / 3, dq1 ],\n\t\t\tp2 = [ 2 / 3, dq2 ],\n\t\t\tp3 = [ 1, dq3 ],\n\t\t\tdist1 = dq1 - (2 * dq0 + dq3) / 3,\n\t\t\tdist2 = dq2 - (dq0 + 2 * dq3) / 3,\n\t\t\thull;\n\t\tif (dist1 * dist2 < 0) {\n\t\t\thull = [[p0, p1, p3], [p0, p2, p3]];\n\t\t} else {\n\t\t\tvar distRatio = dist1 / dist2;\n\t\t\thull = [\n\t\t\t\tdistRatio >= 2 ? [p0, p1, p3]\n\t\t\t\t: distRatio <= 0.5 ? [p0, p2, p3]\n\t\t\t\t: [p0, p1, p2, p3],\n\t\t\t\t[p0, p3]\n\t\t\t];\n\t\t}\n\t\treturn (dist1 || dist2) < 0 ? hull.reverse() : hull;\n\t}\n\n\tfunction clipConvexHull(hullTop, hullBottom, dMin, dMax) {\n\t\tif (hullTop[0][1] < dMin) {\n\t\t\treturn clipConvexHullPart(hullTop, true, dMin);\n\t\t} else if (hullBottom[0][1] > dMax) {\n\t\t\treturn clipConvexHullPart(hullBottom, false, dMax);\n\t\t} else {\n\t\t\treturn hullTop[0][0];\n\t\t}\n\t}\n\n\tfunction clipConvexHullPart(part, top, threshold) {\n\t\tvar px = part[0][0],\n\t\t\tpy = part[0][1];\n\t\tfor (var i = 1, l = part.length; i < l; i++) {\n\t\t\tvar qx = part[i][0],\n\t\t\t\tqy = part[i][1];\n\t\t\tif (top ? qy >= threshold : qy <= threshold) {\n\t\t\t\treturn qy === threshold ? qx\n\t\t\t\t\t\t: px + (threshold - py) * (qx - px) / (qy - py);\n\t\t\t}\n\t\t\tpx = qx;\n\t\t\tpy = qy;\n\t\t}\n\t\treturn null;\n\t}\n\n\tfunction addCurveLineIntersections(v1, v2, c1, c2, locations, param) {\n\t\tvar flip = Curve.isStraight(v1),\n\t\t\tvc = flip ? v2 : v1,\n\t\t\tvl = flip ? v1 : v2,\n\t\t\tlx1 = vl[0], ly1 = vl[1],\n\t\t\tlx2 = vl[6], ly2 = vl[7],\n\t\t\tldx = lx2 - lx1,\n\t\t\tldy = ly2 - ly1,\n\t\t\tangle = Math.atan2(-ldy, ldx),\n\t\t\tsin = Math.sin(angle),\n\t\t\tcos = Math.cos(angle),\n\t\t\trvc = [];\n\t\tfor(var i = 0; i < 8; i += 2) {\n\t\t\tvar x = vc[i] - lx1,\n\t\t\t\ty = vc[i + 1] - ly1;\n\t\t\trvc.push(\n\t\t\t\tx * cos - y * sin,\n\t\t\t\tx * sin + y * cos);\n\t\t}\n\t\tvar roots = [],\n\t\t\tcount = Curve.solveCubic(rvc, 1, 0, roots, 0, 1);\n\t\tfor (var i = 0; i < count; i++) {\n\t\t\tvar tc = roots[i],\n\t\t\t\tpc = Curve.getPoint(vc, tc),\n\t\t\t\ttl = Curve.getTimeOf(vl, pc);\n\t\t\tif (tl !== null) {\n\t\t\t\tvar pl = Curve.getPoint(vl, tl),\n\t\t\t\t\tt1 = flip ? tl : tc,\n\t\t\t\t\tt2 = flip ? tc : tl;\n\t\t\t\tif (!param.excludeEnd || t2 > Numerical.CURVETIME_EPSILON) {\n\t\t\t\t\taddLocation(locations, param,\n\t\t\t\t\t\t\tv1, c1, t1, flip ? pl : pc,\n\t\t\t\t\t\t\tv2, c2, t2, flip ? pc : pl);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction addLineIntersection(v1, v2, c1, c2, locations, param) {\n\t\tvar pt = Line.intersect(\n\t\t\t\tv1[0], v1[1], v1[6], v1[7],\n\t\t\t\tv2[0], v2[1], v2[6], v2[7]);\n\t\tif (pt) {\n\t\t\taddLocation(locations, param, v1, c1, null, pt, v2, c2, null, pt);\n\t\t}\n\t}\n\n\treturn { statics: {\n\t\t_getIntersections: function(v1, v2, c1, c2, locations, param) {\n\t\t\tif (!v2) {\n\t\t\t\treturn Curve._getSelfIntersection(v1, c1, locations, param);\n\t\t\t}\n\t\t\tvar epsilon = 1e-7,\n\t\t\t\tc1p1x = v1[0], c1p1y = v1[1],\n\t\t\t\tc1p2x = v1[6], c1p2y = v1[7],\n\t\t\t\tc2p1x = v2[0], c2p1y = v2[1],\n\t\t\t\tc2p2x = v2[6], c2p2y = v2[7],\n\t\t\t\tc1s1x = (3 * v1[2] + c1p1x) / 4,\n\t\t\t\tc1s1y = (3 * v1[3] + c1p1y) / 4,\n\t\t\t\tc1s2x = (3 * v1[4] + c1p2x) / 4,\n\t\t\t\tc1s2y = (3 * v1[5] + c1p2y) / 4,\n\t\t\t\tc2s1x = (3 * v2[2] + c2p1x) / 4,\n\t\t\t\tc2s1y = (3 * v2[3] + c2p1y) / 4,\n\t\t\t\tc2s2x = (3 * v2[4] + c2p2x) / 4,\n\t\t\t\tc2s2y = (3 * v2[5] + c2p2y) / 4,\n\t\t\t\tmin = Math.min,\n\t\t\t\tmax = Math.max;\n\t\t\tif (!( max(c1p1x, c1s1x, c1s2x, c1p2x) + epsilon >\n\t\t\t\t\tmin(c2p1x, c2s1x, c2s2x, c2p2x) &&\n\t\t\t\t\tmin(c1p1x, c1s1x, c1s2x, c1p2x) - epsilon <\n\t\t\t\t\tmax(c2p1x, c2s1x, c2s2x, c2p2x) &&\n\t\t\t\t\tmax(c1p1y, c1s1y, c1s2y, c1p2y) + epsilon >\n\t\t\t\t\tmin(c2p1y, c2s1y, c2s2y, c2p2y) &&\n\t\t\t\t\tmin(c1p1y, c1s1y, c1s2y, c1p2y) - epsilon <\n\t\t\t\t\tmax(c2p1y, c2s1y, c2s2y, c2p2y)))\n\t\t\t\treturn locations;\n\t\t\tvar overlaps = Curve.getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tfor (var i = 0; i < 2; i++) {\n\t\t\t\t\tvar overlap = overlaps[i];\n\t\t\t\t\taddLocation(locations, param,\n\t\t\t\t\t\tv1, c1, overlap[0], null,\n\t\t\t\t\t\tv2, c2, overlap[1], null, true);\n\t\t\t\t}\n\t\t\t\treturn locations;\n\t\t\t}\n\n\t\t\tvar straight1 = Curve.isStraight(v1),\n\t\t\t\tstraight2 = Curve.isStraight(v2),\n\t\t\t\tstraight = straight1 && straight2,\n\t\t\t\tbefore = locations.length;\n\t\t\t(straight\n\t\t\t\t? addLineIntersection\n\t\t\t\t: straight1 || straight2\n\t\t\t\t\t? addCurveLineIntersections\n\t\t\t\t\t: addCurveIntersections)(\n\t\t\t\t\t\tv1, v2, c1, c2, locations, param,\n\t\t\t\t\t\t0, 1, 0, 1, 0, 0, 0);\n\t\t\tif (straight && locations.length > before)\n\t\t\t\treturn locations;\n\t\t\tvar c1p1 = new Point(c1p1x, c1p1y),\n\t\t\t\tc1p2 = new Point(c1p2x, c1p2y),\n\t\t\t\tc2p1 = new Point(c2p1x, c2p1y),\n\t\t\t\tc2p2 = new Point(c2p2x, c2p2y);\n\t\t\tif (c1p1.isClose(c2p1, epsilon))\n\t\t\t\taddLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 0, c2p1);\n\t\t\tif (!param.excludeStart && c1p1.isClose(c2p2, epsilon))\n\t\t\t\taddLocation(locations, param, v1, c1, 0, c1p1, v2, c2, 1, c2p2);\n\t\t\tif (!param.excludeEnd && c1p2.isClose(c2p1, epsilon))\n\t\t\t\taddLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 0, c2p1);\n\t\t\tif (c1p2.isClose(c2p2, epsilon))\n\t\t\t\taddLocation(locations, param, v1, c1, 1, c1p2, v2, c2, 1, c2p2);\n\t\t\treturn locations;\n\t\t},\n\n\t\t_getSelfIntersection: function(v1, c1, locations, param) {\n\t\t\tvar p1x = v1[0], p1y = v1[1],\n\t\t\t\th1x = v1[2], h1y = v1[3],\n\t\t\t\th2x = v1[4], h2y = v1[5],\n\t\t\t\tp2x = v1[6], p2y = v1[7];\n\t\t\tvar line = new Line(p1x, p1y, p2x, p2y, false),\n\t\t\t\tside1 = line.getSide(new Point(h1x, h1y), true),\n\t\t\t\tside2 = line.getSide(new Point(h2x, h2y), true);\n\t\t\tif (side1 === side2) {\n\t\t\t\tvar edgeSum = (p1x - h2x) * (h1y - p2y)\n\t\t\t\t\t\t\t+ (h1x - p2x) * (h2y - p1y);\n\t\t\t\tif (edgeSum * side1 > 0)\n\t\t\t\t\treturn locations;\n\t\t\t}\n\t\t\tvar ax = p2x - 3 * h2x + 3 * h1x - p1x,\n\t\t\t\tbx = h2x - 2 * h1x + p1x,\n\t\t\t\tcx = h1x - p1x,\n\t\t\t\tay = p2y - 3 * h2y + 3 * h1y - p1y,\n\t\t\t\tby = h2y - 2 * h1y + p1y,\n\t\t\t\tcy = h1y - p1y,\n\t\t\t\tac = ay * cx - ax * cy,\n\t\t\t\tab = ay * bx - ax * by,\n\t\t\t\tbc = by * cx - bx * cy;\n\t\t\tif (ac * ac - 4 * ab * bc < 0) {\n\t\t\t\tvar roots = [],\n\t\t\t\t\ttSplit,\n\t\t\t\t\tcount = Numerical.solveCubic(\n\t\t\t\t\t\t\tax * ax + ay * ay,\n\t\t\t\t\t\t\t3 * (ax * bx + ay * by),\n\t\t\t\t\t\t\t2 * (bx * bx + by * by) + ax * cx + ay * cy,\n\t\t\t\t\t\t\tbx * cx + by * cy,\n\t\t\t\t\t\t\troots, 0, 1);\n\t\t\t\tif (count > 0) {\n\t\t\t\t\tfor (var i = 0, maxCurvature = 0; i < count; i++) {\n\t\t\t\t\t\tvar curvature = Math.abs(\n\t\t\t\t\t\t\t\tc1.getCurvatureAtTime(roots[i]));\n\t\t\t\t\t\tif (curvature > maxCurvature) {\n\t\t\t\t\t\t\tmaxCurvature = curvature;\n\t\t\t\t\t\t\ttSplit = roots[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvar parts = Curve.subdivide(v1, tSplit);\n\t\t\t\t\tparam.excludeEnd = true;\n\t\t\t\t\tparam.renormalize = function(t1, t2) {\n\t\t\t\t\t\treturn [t1 * tSplit, t2 * (1 - tSplit) + tSplit];\n\t\t\t\t\t};\n\t\t\t\t\tCurve._getIntersections(parts[0], parts[1], c1, c1,\n\t\t\t\t\t\t\tlocations, param);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn locations;\n\t\t},\n\n\t\tgetOverlaps: function(v1, v2) {\n\t\t\tvar abs = Math.abs,\n\t\t\t\ttimeEpsilon = 4e-7,\n\t\t\t\tgeomEpsilon = 1e-7,\n\t\t\t\tstraight1 = Curve.isStraight(v1),\n\t\t\t\tstraight2 = Curve.isStraight(v2),\n\t\t\t\tstraightBoth = straight1 && straight2;\n\n\t\t\tfunction getSquaredLineLength(v) {\n\t\t\t\tvar x = v[6] - v[0],\n\t\t\t\t\ty = v[7] - v[1];\n\t\t\t\treturn x * x + y * y;\n\t\t\t}\n\n\t\t\tvar flip = getSquaredLineLength(v1) < getSquaredLineLength(v2),\n\t\t\t\tl1 = flip ? v2 : v1,\n\t\t\t\tl2 = flip ? v1 : v2,\n\t\t\t\tline = new Line(l1[0], l1[1], l1[6], l1[7]);\n\t\t\tif (line.getDistance(new Point(l2[0], l2[1])) < geomEpsilon &&\n\t\t\t\tline.getDistance(new Point(l2[6], l2[7])) < geomEpsilon) {\n\t\t\t\tif (!straightBoth &&\n\t\t\t\t\tline.getDistance(new Point(l1[2], l1[3])) < geomEpsilon &&\n\t\t\t\t\tline.getDistance(new Point(l1[4], l1[5])) < geomEpsilon &&\n\t\t\t\t\tline.getDistance(new Point(l2[2], l2[3])) < geomEpsilon &&\n\t\t\t\t\tline.getDistance(new Point(l2[4], l2[5])) < geomEpsilon) {\n\t\t\t\t\tstraight1 = straight2 = straightBoth = true;\n\t\t\t\t}\n\t\t\t} else if (straightBoth) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (straight1 ^ straight2) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tvar v = [v1, v2],\n\t\t\t\tpairs = [];\n\t\t\tfor (var i = 0, t1 = 0;\n\t\t\t\t\ti < 2 && pairs.length < 2;\n\t\t\t\t\ti += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {\n\t\t\t\tvar t2 = Curve.getTimeOf(v[i ^ 1], new Point(\n\t\t\t\t\t\tv[i][t1 === 0 ? 0 : 6],\n\t\t\t\t\t\tv[i][t1 === 0 ? 1 : 7]));\n\t\t\t\tif (t2 != null) {\n\t\t\t\t\tvar pair = i === 0 ? [t1, t2] : [t2, t1];\n\t\t\t\t\tif (!pairs.length ||\n\t\t\t\t\t\tabs(pair[0] - pairs[0][0]) > timeEpsilon &&\n\t\t\t\t\t\tabs(pair[1] - pairs[0][1]) > timeEpsilon)\n\t\t\t\t\t\tpairs.push(pair);\n\t\t\t\t}\n\t\t\t\tif (i === 1 && !pairs.length)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pairs.length !== 2) {\n\t\t\t\tpairs = null;\n\t\t\t} else if (!straightBoth) {\n\t\t\t\tvar o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),\n\t\t\t\t\to2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);\n\t\t\t\tif (abs(o2[2] - o1[2]) > geomEpsilon ||\n\t\t\t\t\tabs(o2[3] - o1[3]) > geomEpsilon ||\n\t\t\t\t\tabs(o2[4] - o1[4]) > geomEpsilon ||\n\t\t\t\t\tabs(o2[5] - o1[5]) > geomEpsilon)\n\t\t\t\t\tpairs = null;\n\t\t\t}\n\t\t\treturn pairs;\n\t\t}\n\t}};\n});\n\nvar CurveLocation = Base.extend({\n\t_class: 'CurveLocation',\n\tbeans: true,\n\n\tinitialize: function CurveLocation(curve, time, point, _overlap, _distance) {\n\t\tif (time > 0.9999996) {\n\t\t\tvar next = curve.getNext();\n\t\t\tif (next) {\n\t\t\t\ttime = 0;\n\t\t\t\tcurve = next;\n\t\t\t}\n\t\t}\n\t\tthis._setCurve(curve);\n\t\tthis._time = time;\n\t\tthis._point = point || curve.getPointAtTime(time);\n\t\tthis._overlap = _overlap;\n\t\tthis._distance = _distance;\n\t\tthis._intersection = this._next = this._previous = null;\n\t},\n\n\t_setCurve: function(curve) {\n\t\tvar path = curve._path;\n\t\tthis._path = path;\n\t\tthis._version = path ? path._version : 0;\n\t\tthis._curve = curve;\n\t\tthis._segment = null;\n\t\tthis._segment1 = curve._segment1;\n\t\tthis._segment2 = curve._segment2;\n\t},\n\n\t_setSegment: function(segment) {\n\t\tthis._setCurve(segment.getCurve());\n\t\tthis._segment = segment;\n\t\tthis._time = segment === this._segment1 ? 0 : 1;\n\t\tthis._point = segment._point.clone();\n\t},\n\n\tgetSegment: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\tsegment = this._segment;\n\t\tif (!segment) {\n\t\t\tvar time = this.getTime();\n\t\t\tif (time === 0) {\n\t\t\t\tsegment = curve._segment1;\n\t\t\t} else if (time === 1) {\n\t\t\t\tsegment = curve._segment2;\n\t\t\t} else if (time != null) {\n\t\t\t\tsegment = curve.getPartLength(0, time)\n\t\t\t\t\t< curve.getPartLength(time, 1)\n\t\t\t\t\t\t? curve._segment1\n\t\t\t\t\t\t: curve._segment2;\n\t\t\t}\n\t\t\tthis._segment = segment;\n\t\t}\n\t\treturn segment;\n\t},\n\n\tgetCurve: function() {\n\t\tvar path = this._path,\n\t\t\tthat = this;\n\t\tif (path && path._version !== this._version) {\n\t\t\tthis._time = this._curve = this._offset = null;\n\t\t}\n\n\t\tfunction trySegment(segment) {\n\t\t\tvar curve = segment && segment.getCurve();\n\t\t\tif (curve && (that._time = curve.getTimeOf(that._point))\n\t\t\t\t\t!= null) {\n\t\t\t\tthat._setCurve(curve);\n\t\t\t\tthat._segment = segment;\n\t\t\t\treturn curve;\n\t\t\t}\n\t\t}\n\n\t\treturn this._curve\n\t\t\t|| trySegment(this._segment)\n\t\t\t|| trySegment(this._segment1)\n\t\t\t|| trySegment(this._segment2.getPrevious());\n\t},\n\n\tgetPath: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve && curve._path;\n\t},\n\n\tgetIndex: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve && curve.getIndex();\n\t},\n\n\tgetTime: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\ttime = this._time;\n\t\treturn curve && time == null\n\t\t\t? this._time = curve.getTimeOf(this._point)\n\t\t\t: time;\n\t},\n\n\tgetParameter: '#getTime',\n\n\tgetPoint: function() {\n\t\treturn this._point;\n\t},\n\n\tgetOffset: function() {\n\t\tvar offset = this._offset;\n\t\tif (offset == null) {\n\t\t\toffset = 0;\n\t\t\tvar path = this.getPath(),\n\t\t\t\tindex = this.getIndex();\n\t\t\tif (path && index != null) {\n\t\t\t\tvar curves = path.getCurves();\n\t\t\t\tfor (var i = 0; i < index; i++)\n\t\t\t\t\toffset += curves[i].getLength();\n\t\t\t}\n\t\t\tthis._offset = offset += this.getCurveOffset();\n\t\t}\n\t\treturn offset;\n\t},\n\n\tgetCurveOffset: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\ttime = this.getTime();\n\t\treturn time != null && curve && curve.getPartLength(0, time);\n\t},\n\n\tgetIntersection: function() {\n\t\treturn this._intersection;\n\t},\n\n\tgetDistance: function() {\n\t\treturn this._distance;\n\t},\n\n\tdivide: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\tres = null;\n\t\tif (curve) {\n\t\t\tres = curve.divideAtTime(this.getTime());\n\t\t\tif (res)\n\t\t\t\tthis._setSegment(res._segment1);\n\t\t}\n\t\treturn res;\n\t},\n\n\tsplit: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve ? curve.splitAtTime(this.getTime()) : null;\n\t},\n\n\tequals: function(loc, _ignoreOther) {\n\t\tvar res = this === loc,\n\t\t\tepsilon = 1e-7;\n\t\tif (!res && loc instanceof CurveLocation\n\t\t\t\t&& this.getPath() === loc.getPath()\n\t\t\t\t&& this.getPoint().isClose(loc.getPoint(), epsilon)) {\n\t\t\tvar c1 = this.getCurve(),\n\t\t\t\tc2 = loc.getCurve(),\n\t\t\t\tabs = Math.abs,\n\t\t\t\tdiff = abs(\n\t\t\t\t\t((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())\n\t\t\t\t\t\t\t+ this.getTime()) -\n\t\t\t\t\t((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())\n\t\t\t\t\t\t\t+ loc.getTime()));\n\t\t\tres = (diff < 4e-7\n\t\t\t\t|| ((diff = abs(this.getOffset() - loc.getOffset())) < epsilon\n\t\t\t\t\t|| abs(this.getPath().getLength() - diff) < epsilon))\n\t\t\t\t&& (_ignoreOther\n\t\t\t\t\t|| (!this._intersection && !loc._intersection\n\t\t\t\t\t\t|| this._intersection && this._intersection.equals(\n\t\t\t\t\t\t\t\tloc._intersection, true)));\n\t\t}\n\t\treturn res;\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [],\n\t\t\tpoint = this.getPoint(),\n\t\t\tf = Formatter.instance;\n\t\tif (point)\n\t\t\tparts.push('point: ' + point);\n\t\tvar index = this.getIndex();\n\t\tif (index != null)\n\t\t\tparts.push('index: ' + index);\n\t\tvar time = this.getTime();\n\t\tif (time != null)\n\t\t\tparts.push('time: ' + f.number(time));\n\t\tif (this._distance != null)\n\t\t\tparts.push('distance: ' + f.number(this._distance));\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\tisTouching: function() {\n\t\tvar inter = this._intersection;\n\t\tif (inter && this.getTangent().isCollinear(inter.getTangent())) {\n\t\t\tvar curve1 = this.getCurve(),\n\t\t\t\tcurve2 = inter.getCurve();\n\t\t\treturn !(curve1.isStraight() && curve2.isStraight()\n\t\t\t\t\t&& curve1.getLine().intersect(curve2.getLine()));\n\t\t}\n\t\treturn false;\n\t},\n\n\tisCrossing: function() {\n\t\tvar inter = this._intersection;\n\t\tif (!inter)\n\t\t\treturn false;\n\t\tvar t1 = this.getTime(),\n\t\t\tt2 = inter.getTime(),\n\t\t\ttMin = 4e-7,\n\t\t\ttMax = 1 - tMin,\n\t\t\tt1Inside = t1 > tMin && t1 < tMax,\n\t\t\tt2Inside = t2 > tMin && t2 < tMax;\n\t\tif (t1Inside && t2Inside)\n\t\t\treturn !this.isTouching();\n\t\tvar c2 = this.getCurve(),\n\t\t\tc1 = t1 <= tMin ? c2.getPrevious() : c2,\n\t\t\tc4 = inter.getCurve(),\n\t\t\tc3 = t2 <= tMin ? c4.getPrevious() : c4;\n\t\tif (t1 >= tMax)\n\t\t\tc2 = c2.getNext();\n\t\tif (t2 >= tMax)\n\t\t\tc4 = c4.getNext();\n\t\tif (!c1 || !c2 || !c3 || !c4)\n\t\t\treturn false;\n\n\t\tfunction isInRange(angle, min, max) {\n\t\t\treturn min < max\n\t\t\t\t\t? angle > min && angle < max\n\t\t\t\t\t: angle > min || angle < max;\n\t\t}\n\n\t\tvar lenghts = [];\n\t\tif (!t1Inside)\n\t\t\tlenghts.push(c1.getLength(), c2.getLength());\n\t\tif (!t2Inside)\n\t\t\tlenghts.push(c3.getLength(), c4.getLength());\n\t\tvar pt = this.getPoint(),\n\t\t\toffset = Math.min.apply(Math, lenghts) / 64,\n\t\t\tv2 = t1Inside ? c2.getTangentAtTime(t1)\n\t\t\t\t\t: c2.getPointAt(offset).subtract(pt),\n\t\t\tv1 = t1Inside ? v2.negate()\n\t\t\t\t\t: c1.getPointAt(-offset).subtract(pt),\n\t\t\tv4 = t2Inside ? c4.getTangentAtTime(t2)\n\t\t\t\t\t: c4.getPointAt(offset).subtract(pt),\n\t\t\tv3 = t2Inside ? v4.negate()\n\t\t\t\t\t: c3.getPointAt(-offset).subtract(pt),\n\t\t\ta1 = v1.getAngle(),\n\t\t\ta2 = v2.getAngle(),\n\t\t\ta3 = v3.getAngle(),\n\t\t\ta4 = v4.getAngle();\n\t\treturn !!(t1Inside\n\t\t\t\t? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) &&\n\t\t\t\t (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3))\n\t\t\t\t: (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) &&\n\t\t\t\t (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1)));\n\t},\n\n\thasOverlap: function() {\n\t\treturn !!this._overlap;\n\t}\n}, Base.each(Curve._evaluateMethods, function(name) {\n\tvar get = name + 'At';\n\tthis[name] = function() {\n\t\tvar curve = this.getCurve(),\n\t\t\ttime = this.getTime();\n\t\treturn time != null && curve && curve[get](time, true);\n\t};\n}, {\n\tpreserve: true\n}),\nnew function() {\n\n\tfunction insert(locations, loc, merge) {\n\t\tvar length = locations.length,\n\t\t\tl = 0,\n\t\t\tr = length - 1;\n\n\t\tfunction search(index, dir) {\n\t\t\tfor (var i = index + dir; i >= -1 && i <= length; i += dir) {\n\t\t\t\tvar loc2 = locations[((i % length) + length) % length];\n\t\t\t\tif (!loc.getPoint().isClose(loc2.getPoint(),\n\t\t\t\t\t\t1e-7))\n\t\t\t\t\tbreak;\n\t\t\t\tif (loc.equals(loc2))\n\t\t\t\t\treturn loc2;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\twhile (l <= r) {\n\t\t\tvar m = (l + r) >>> 1,\n\t\t\t\tloc2 = locations[m],\n\t\t\t\tfound;\n\t\t\tif (merge && (found = loc.equals(loc2) ? loc2\n\t\t\t\t\t: (search(m, -1) || search(m, 1)))) {\n\t\t\t\tif (loc._overlap) {\n\t\t\t\t\tfound._overlap = found._intersection._overlap = true;\n\t\t\t\t}\n\t\t\t\treturn found;\n\t\t\t}\n\t\tvar path1 = loc.getPath(),\n\t\t\tpath2 = loc2.getPath(),\n\t\t\tdiff = path1 !== path2\n\t\t\t\t? path1._id - path2._id\n\t\t\t\t: (loc.getIndex() + loc.getTime())\n\t\t\t\t- (loc2.getIndex() + loc2.getTime());\n\t\t\tif (diff < 0) {\n\t\t\t\tr = m - 1;\n\t\t\t} else {\n\t\t\t\tl = m + 1;\n\t\t\t}\n\t\t}\n\t\tlocations.splice(l, 0, loc);\n\t\treturn loc;\n\t}\n\n\treturn { statics: {\n\t\tinsert: insert,\n\n\t\texpand: function(locations) {\n\t\t\tvar expanded = locations.slice();\n\t\t\tfor (var i = locations.length - 1; i >= 0; i--) {\n\t\t\t\tinsert(expanded, locations[i]._intersection, false);\n\t\t\t}\n\t\t\treturn expanded;\n\t\t}\n\t}};\n});\n\nvar PathItem = Item.extend({\n\t_class: 'PathItem',\n\t_selectBounds: false,\n\t_canScaleStroke: true,\n\n\tinitialize: function PathItem() {\n\t},\n\n\tstatics: {\n\n\t\tcreate: function(arg) {\n\t\t\tvar data,\n\t\t\t\tsegments,\n\t\t\t\tcompound;\n\t\t\tif (Base.isPlainObject(arg)) {\n\t\t\t\tsegments = arg.segments;\n\t\t\t\tdata = arg.pathData;\n\t\t\t} else if (Array.isArray(arg)) {\n\t\t\t\tsegments = arg;\n\t\t\t} else if (typeof arg === 'string') {\n\t\t\t\tdata = arg;\n\t\t\t}\n\t\t\tif (segments) {\n\t\t\t\tvar first = segments[0];\n\t\t\t\tcompound = first && Array.isArray(first[0]);\n\t\t\t} else if (data) {\n\t\t\t\tcompound = (data.match(/m/gi) || []).length > 1\n\t\t\t\t\t\t|| /z\\s*\\S+/i.test(data);\n\t\t\t}\n\t\t\tvar ctor = compound ? CompoundPath : Path;\n\t\t\treturn new ctor(arg);\n\t\t}\n\t},\n\n\t_asPathItem: function() {\n\t\treturn this;\n\t},\n\n\tisClockwise: function() {\n\t\treturn this.getArea() >= 0;\n\t},\n\n\tsetClockwise: function(clockwise) {\n\t\tif (this.isClockwise() != (clockwise = !!clockwise))\n\t\t\tthis.reverse();\n\t},\n\n\tsetPathData: function(data) {\n\n\t\tvar parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),\n\t\t\tcoords,\n\t\t\trelative = false,\n\t\t\tprevious,\n\t\t\tcontrol,\n\t\t\tcurrent = new Point(),\n\t\t\tstart = new Point();\n\n\t\tfunction getCoord(index, coord) {\n\t\t\tvar val = +coords[index];\n\t\t\tif (relative)\n\t\t\t\tval += current[coord];\n\t\t\treturn val;\n\t\t}\n\n\t\tfunction getPoint(index) {\n\t\t\treturn new Point(\n\t\t\t\tgetCoord(index, 'x'),\n\t\t\t\tgetCoord(index + 1, 'y')\n\t\t\t);\n\t\t}\n\n\t\tthis.clear();\n\n\t\tfor (var i = 0, l = parts && parts.length; i < l; i++) {\n\t\t\tvar part = parts[i],\n\t\t\t\tcommand = part[0],\n\t\t\t\tlower = command.toLowerCase();\n\t\t\tcoords = part.match(/[+-]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][+-]?\\d+)?/g);\n\t\t\tvar length = coords && coords.length;\n\t\t\trelative = command === lower;\n\t\t\tif (previous === 'z' && !/[mz]/.test(lower))\n\t\t\t\tthis.moveTo(current);\n\t\t\tswitch (lower) {\n\t\t\tcase 'm':\n\t\t\tcase 'l':\n\t\t\t\tvar move = lower === 'm';\n\t\t\t\tfor (var j = 0; j < length; j += 2)\n\t\t\t\t\tthis[!j && move ? 'moveTo' : 'lineTo'](\n\t\t\t\t\t\t\tcurrent = getPoint(j));\n\t\t\t\tcontrol = current;\n\t\t\t\tif (move)\n\t\t\t\t\tstart = current;\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\tcase 'v':\n\t\t\t\tvar coord = lower === 'h' ? 'x' : 'y';\n\t\t\t\tcurrent = current.clone();\n\t\t\t\tfor (var j = 0; j < length; j++) {\n\t\t\t\t\tcurrent[coord] = getCoord(j, coord);\n\t\t\t\t\tthis.lineTo(current);\n\t\t\t\t}\n\t\t\t\tcontrol = current;\n\t\t\t\tbreak;\n\t\t\tcase 'c':\n\t\t\t\tfor (var j = 0; j < length; j += 6) {\n\t\t\t\t\tthis.cubicCurveTo(\n\t\t\t\t\t\t\tgetPoint(j),\n\t\t\t\t\t\t\tcontrol = getPoint(j + 2),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 4));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tfor (var j = 0; j < length; j += 4) {\n\t\t\t\t\tthis.cubicCurveTo(\n\t\t\t\t\t\t\t/[cs]/.test(previous)\n\t\t\t\t\t\t\t\t\t? current.multiply(2).subtract(control)\n\t\t\t\t\t\t\t\t\t: current,\n\t\t\t\t\t\t\tcontrol = getPoint(j),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 2));\n\t\t\t\t\tprevious = lower;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'q':\n\t\t\t\tfor (var j = 0; j < length; j += 4) {\n\t\t\t\t\tthis.quadraticCurveTo(\n\t\t\t\t\t\t\tcontrol = getPoint(j),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 2));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 't':\n\t\t\t\tfor (var j = 0; j < length; j += 2) {\n\t\t\t\t\tthis.quadraticCurveTo(\n\t\t\t\t\t\t\tcontrol = (/[qt]/.test(previous)\n\t\t\t\t\t\t\t\t\t? current.multiply(2).subtract(control)\n\t\t\t\t\t\t\t\t\t: current),\n\t\t\t\t\t\t\tcurrent = getPoint(j));\n\t\t\t\t\tprevious = lower;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'a':\n\t\t\t\tfor (var j = 0; j < length; j += 7) {\n\t\t\t\t\tthis.arcTo(current = getPoint(j + 5),\n\t\t\t\t\t\t\tnew Size(+coords[j], +coords[j + 1]),\n\t\t\t\t\t\t\t+coords[j + 2], +coords[j + 4], +coords[j + 3]);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'z':\n\t\t\t\tthis.closePath(1e-12);\n\t\t\t\tcurrent = start;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprevious = lower;\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn !(this.hasFill() && this.hasStroke());\n\t},\n\n\t_contains: function(point) {\n\t\tvar winding = point.isInside(\n\t\t\t\tthis.getBounds({ internal: true, handle: true }))\n\t\t\t\t\t? this._getWinding(point)\n\t\t\t\t\t: {};\n\t\treturn !!(this.getFillRule() === 'evenodd'\n\t\t\t\t? winding.windingL & 1 || winding.windingR & 1\n\t\t\t\t: winding.winding);\n\t},\n\n\tgetIntersections: function(path, include, _matrix, _returnFirst) {\n\t\tvar self = this === path || !path,\n\t\t\tmatrix1 = this._matrix._orNullIfIdentity(),\n\t\t\tmatrix2 = self ? matrix1\n\t\t\t\t: (_matrix || path._matrix)._orNullIfIdentity();\n\t\tif (!self && !this.getBounds(matrix1).touches(path.getBounds(matrix2)))\n\t\t\treturn [];\n\t\tvar curves1 = this.getCurves(),\n\t\t\tcurves2 = self ? curves1 : path.getCurves(),\n\t\t\tlength1 = curves1.length,\n\t\t\tlength2 = self ? length1 : curves2.length,\n\t\t\tvalues2 = [],\n\t\t\tarrays = [],\n\t\t\tlocations,\n\t\t\tpath;\n\t\tfor (var i = 0; i < length2; i++)\n\t\t\tvalues2[i] = curves2[i].getValues(matrix2);\n\t\tfor (var i = 0; i < length1; i++) {\n\t\t\tvar curve1 = curves1[i],\n\t\t\t\tvalues1 = self ? values2[i] : curve1.getValues(matrix1),\n\t\t\t\tpath1 = curve1.getPath();\n\t\t\tif (path1 !== path) {\n\t\t\t\tpath = path1;\n\t\t\t\tlocations = [];\n\t\t\t\tarrays.push(locations);\n\t\t\t}\n\t\t\tif (self) {\n\t\t\t\tCurve._getSelfIntersection(values1, curve1, locations, {\n\t\t\t\t\tinclude: include,\n\t\t\t\t\texcludeStart: length1 === 1 &&\n\t\t\t\t\t\t\tcurve1.getPoint1().equals(curve1.getPoint2())\n\t\t\t\t});\n\t\t\t}\n\t\t\tfor (var j = self ? i + 1 : 0; j < length2; j++) {\n\t\t\t\tif (_returnFirst && locations.length)\n\t\t\t\t\treturn locations;\n\t\t\t\tvar curve2 = curves2[j];\n\t\t\t\tCurve._getIntersections(\n\t\t\t\t\tvalues1, values2[j], curve1, curve2, locations,\n\t\t\t\t\t{\n\t\t\t\t\t\tinclude: include,\n\t\t\t\t\t\texcludeStart: self && curve1.getPrevious() === curve2,\n\t\t\t\t\t\texcludeEnd: self && curve1.getNext() === curve2\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tlocations = [];\n\t\tfor (var i = 0, l = arrays.length; i < l; i++) {\n\t\t\tlocations.push.apply(locations, arrays[i]);\n\t\t}\n\t\treturn locations;\n\t},\n\n\tgetCrossings: function(path) {\n\t\treturn this.getIntersections(path, function(inter) {\n\t\t\treturn inter._overlap || inter.isCrossing();\n\t\t});\n\t},\n\n\tgetNearestLocation: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcurves = this.getCurves(),\n\t\t\tminDist = Infinity,\n\t\t\tminLoc = null;\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar loc = curves[i].getNearestLocation(point);\n\t\t\tif (loc._distance < minDist) {\n\t\t\t\tminDist = loc._distance;\n\t\t\t\tminLoc = loc;\n\t\t\t}\n\t\t}\n\t\treturn minLoc;\n\t},\n\n\tgetNearestPoint: function() {\n\t\tvar loc = this.getNearestLocation.apply(this, arguments);\n\t\treturn loc ? loc.getPoint() : loc;\n\t},\n\n\tinterpolate: function(from, to, factor) {\n\t\tvar isPath = !this._children,\n\t\t\tname = isPath ? '_segments' : '_children',\n\t\t\titemsFrom = from[name],\n\t\t\titemsTo = to[name],\n\t\t\titems = this[name];\n\t\tif (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) {\n\t\t\tthrow new Error('Invalid operands in interpolate() call: ' +\n\t\t\t\t\tfrom + ', ' + to);\n\t\t}\n\t\tvar current = items.length,\n\t\t\tlength = itemsTo.length;\n\t\tif (current < length) {\n\t\t\tvar ctor = isPath ? Segment : Path;\n\t\t\tfor (var i = current; i < length; i++) {\n\t\t\t\tthis.add(new ctor());\n\t\t\t}\n\t\t} else if (current > length) {\n\t\t\tthis[isPath ? 'removeSegments' : 'removeChildren'](length, current);\n\t\t}\n\t\tfor (var i = 0; i < length; i++) {\n\t\t\titems[i].interpolate(itemsFrom[i], itemsTo[i], factor);\n\t\t}\n\t\tif (isPath) {\n\t\t\tthis.setClosed(from._closed);\n\t\t\tthis._changed(9);\n\t\t}\n\t},\n\n\tcompare: function(path) {\n\t\tvar ok = false;\n\t\tif (path) {\n\t\t\tvar paths1 = this._children || [this],\n\t\t\t\tpaths2 = path._children.slice() || [path],\n\t\t\t\tlength1 = paths1.length,\n\t\t\t\tlength2 = paths2.length,\n\t\t\t\tmatched = [],\n\t\t\t\tcount;\n\t\t\tok = true;\n\t\t\tfor (var i1 = length1 - 1; i1 >= 0 && ok; i1--) {\n\t\t\t\tvar path1 = paths1[i1];\n\t\t\t\tok = false;\n\t\t\t\tfor (var i2 = length2 - 1; i2 >= 0 && !ok; i2--) {\n\t\t\t\t\tif (path1.compare(paths2[i2])) {\n\t\t\t\t\t\tif (!matched[i2]) {\n\t\t\t\t\t\t\tmatched[i2] = true;\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tok = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tok = ok && count === length2;\n\t\t}\n\t\treturn ok;\n\t},\n\n});\n\nvar Path = PathItem.extend({\n\t_class: 'Path',\n\t_serializeFields: {\n\t\tsegments: [],\n\t\tclosed: false\n\t},\n\n\tinitialize: function Path(arg) {\n\t\tthis._closed = false;\n\t\tthis._segments = [];\n\t\tthis._version = 0;\n\t\tvar segments = Array.isArray(arg)\n\t\t\t? typeof arg[0] === 'object'\n\t\t\t\t? arg\n\t\t\t\t: arguments\n\t\t\t: arg && (arg.size === undefined && (arg.x !== undefined\n\t\t\t\t\t|| arg.point !== undefined))\n\t\t\t\t? arguments\n\t\t\t\t: null;\n\t\tif (segments && segments.length > 0) {\n\t\t\tthis.setSegments(segments);\n\t\t} else {\n\t\t\tthis._curves = undefined;\n\t\t\tthis._segmentSelection = 0;\n\t\t\tif (!segments && typeof arg === 'string') {\n\t\t\t\tthis.setPathData(arg);\n\t\t\t\targ = null;\n\t\t\t}\n\t\t}\n\t\tthis._initialize(!segments && arg);\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._closed === item._closed\n\t\t\t\t&& Base.equals(this._segments, item._segments);\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setSegments(source._segments);\n\t\tthis._closed = source._closed;\n\t},\n\n\t_changed: function _changed(flags) {\n\t\t_changed.base.call(this, flags);\n\t\tif (flags & 8) {\n\t\t\tthis._length = this._area = undefined;\n\t\t\tif (flags & 16) {\n\t\t\t\tthis._version++;\n\t\t\t} else if (this._curves) {\n\t\t\t for (var i = 0, l = this._curves.length; i < l; i++)\n\t\t\t\t\tthis._curves[i]._changed();\n\t\t\t}\n\t\t} else if (flags & 32) {\n\t\t\tthis._bounds = undefined;\n\t\t}\n\t},\n\n\tgetStyle: function() {\n\t\tvar parent = this._parent;\n\t\treturn (parent instanceof CompoundPath ? parent : this)._style;\n\t},\n\n\tgetSegments: function() {\n\t\treturn this._segments;\n\t},\n\n\tsetSegments: function(segments) {\n\t\tvar fullySelected = this.isFullySelected(),\n\t\t\tlength = segments && segments.length;\n\t\tthis._segments.length = 0;\n\t\tthis._segmentSelection = 0;\n\t\tthis._curves = undefined;\n\t\tif (length) {\n\t\t\tvar last = segments[length - 1];\n\t\t\tif (typeof last === 'boolean') {\n\t\t\t\tthis.setClosed(last);\n\t\t\t\tlength--;\n\t\t\t}\n\t\t\tthis._add(Segment.readList(segments, 0, {}, length));\n\t\t}\n\t\tif (fullySelected)\n\t\t\tthis.setFullySelected(true);\n\t},\n\n\tgetFirstSegment: function() {\n\t\treturn this._segments[0];\n\t},\n\n\tgetLastSegment: function() {\n\t\treturn this._segments[this._segments.length - 1];\n\t},\n\n\tgetCurves: function() {\n\t\tvar curves = this._curves,\n\t\t\tsegments = this._segments;\n\t\tif (!curves) {\n\t\t\tvar length = this._countCurves();\n\t\t\tcurves = this._curves = new Array(length);\n\t\t\tfor (var i = 0; i < length; i++)\n\t\t\t\tcurves[i] = new Curve(this, segments[i],\n\t\t\t\t\tsegments[i + 1] || segments[0]);\n\t\t}\n\t\treturn curves;\n\t},\n\n\tgetFirstCurve: function() {\n\t\treturn this.getCurves()[0];\n\t},\n\n\tgetLastCurve: function() {\n\t\tvar curves = this.getCurves();\n\t\treturn curves[curves.length - 1];\n\t},\n\n\tisClosed: function() {\n\t\treturn this._closed;\n\t},\n\n\tsetClosed: function(closed) {\n\t\tif (this._closed != (closed = !!closed)) {\n\t\t\tthis._closed = closed;\n\t\t\tif (this._curves) {\n\t\t\t\tvar length = this._curves.length = this._countCurves();\n\t\t\t\tif (closed)\n\t\t\t\t\tthis._curves[length - 1] = new Curve(this,\n\t\t\t\t\t\tthis._segments[length - 1], this._segments[0]);\n\t\t\t}\n\t\t\tthis._changed(25);\n\t\t}\n\t}\n}, {\n\tbeans: true,\n\n\tgetPathData: function(_matrix, _precision) {\n\t\tvar segments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tf = new Formatter(_precision),\n\t\t\tcoords = new Array(6),\n\t\t\tfirst = true,\n\t\t\tcurX, curY,\n\t\t\tprevX, prevY,\n\t\t\tinX, inY,\n\t\t\toutX, outY,\n\t\t\tparts = [];\n\n\t\tfunction addSegment(segment, skipLine) {\n\t\t\tsegment._transformCoordinates(_matrix, coords);\n\t\t\tcurX = coords[0];\n\t\t\tcurY = coords[1];\n\t\t\tif (first) {\n\t\t\t\tparts.push('M' + f.pair(curX, curY));\n\t\t\t\tfirst = false;\n\t\t\t} else {\n\t\t\t\tinX = coords[2];\n\t\t\t\tinY = coords[3];\n\t\t\t\tif (inX === curX && inY === curY\n\t\t\t\t\t\t&& outX === prevX && outY === prevY) {\n\t\t\t\t\tif (!skipLine) {\n\t\t\t\t\t\tvar dx = curX - prevX,\n\t\t\t\t\t\t\tdy = curY - prevY;\n\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t dx === 0 ? 'v' + f.number(dy)\n\t\t\t\t\t\t\t: dy === 0 ? 'h' + f.number(dx)\n\t\t\t\t\t\t\t: 'l' + f.pair(dx, dy));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparts.push('c' + f.pair(outX - prevX, outY - prevY)\n\t\t\t\t\t\t\t + ' ' + f.pair( inX - prevX, inY - prevY)\n\t\t\t\t\t\t\t + ' ' + f.pair(curX - prevX, curY - prevY));\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevX = curX;\n\t\t\tprevY = curY;\n\t\t\toutX = coords[4];\n\t\t\toutY = coords[5];\n\t\t}\n\n\t\tif (!length)\n\t\t\treturn '';\n\n\t\tfor (var i = 0; i < length; i++)\n\t\t\taddSegment(segments[i]);\n\t\tif (this._closed && length > 0) {\n\t\t\taddSegment(segments[0], true);\n\t\t\tparts.push('z');\n\t\t}\n\t\treturn parts.join('');\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._segments.length;\n\t},\n\n\t_transformContent: function(matrix) {\n\t\tvar segments = this._segments,\n\t\t\tcoords = new Array(6);\n\t\tfor (var i = 0, l = segments.length; i < l; i++)\n\t\t\tsegments[i]._transformCoordinates(matrix, coords, true);\n\t\treturn true;\n\t},\n\n\t_add: function(segs, index) {\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tamount = segs.length,\n\t\t\tappend = index == null,\n\t\t\tindex = append ? segments.length : index;\n\t\tfor (var i = 0; i < amount; i++) {\n\t\t\tvar segment = segs[i];\n\t\t\tif (segment._path)\n\t\t\t\tsegment = segs[i] = segment.clone();\n\t\t\tsegment._path = this;\n\t\t\tsegment._index = index + i;\n\t\t\tif (segment._selection)\n\t\t\t\tthis._updateSelection(segment, 0, segment._selection);\n\t\t}\n\t\tif (append) {\n\t\t\tsegments.push.apply(segments, segs);\n\t\t} else {\n\t\t\tsegments.splice.apply(segments, [index, 0].concat(segs));\n\t\t\tfor (var i = index + amount, l = segments.length; i < l; i++)\n\t\t\t\tsegments[i]._index = i;\n\t\t}\n\t\tif (curves) {\n\t\t\tvar total = this._countCurves(),\n\t\t\t\tstart = index > 0 && index + amount - 1 === total ? index - 1\n\t\t\t\t\t: index,\n\t\t\t\tinsert = start,\n\t\t\t\tend = Math.min(start + amount, total);\n\t\t\tif (segs._curves) {\n\t\t\t\tcurves.splice.apply(curves, [start, 0].concat(segs._curves));\n\t\t\t\tinsert += segs._curves.length;\n\t\t\t}\n\t\t\tfor (var i = insert; i < end; i++)\n\t\t\t\tcurves.splice(i, 0, new Curve(this, null, null));\n\t\t\tthis._adjustCurves(start, end);\n\t\t}\n\t\tthis._changed(25);\n\t\treturn segs;\n\t},\n\n\t_adjustCurves: function(start, end) {\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tcurve;\n\t\tfor (var i = start; i < end; i++) {\n\t\t\tcurve = curves[i];\n\t\t\tcurve._path = this;\n\t\t\tcurve._segment1 = segments[i];\n\t\t\tcurve._segment2 = segments[i + 1] || segments[0];\n\t\t\tcurve._changed();\n\t\t}\n\t\tif (curve = curves[this._closed && !start ? segments.length - 1\n\t\t\t\t: start - 1]) {\n\t\t\tcurve._segment2 = segments[start] || segments[0];\n\t\t\tcurve._changed();\n\t\t}\n\t\tif (curve = curves[end]) {\n\t\t\tcurve._segment1 = segments[end];\n\t\t\tcurve._changed();\n\t\t}\n\t},\n\n\t_countCurves: function() {\n\t\tvar length = this._segments.length;\n\t\treturn !this._closed && length > 0 ? length - 1 : length;\n\t},\n\n\tadd: function(segment1 ) {\n\t\treturn arguments.length > 1 && typeof segment1 !== 'number'\n\t\t\t? this._add(Segment.readList(arguments))\n\t\t\t: this._add([ Segment.read(arguments) ])[0];\n\t},\n\n\tinsert: function(index, segment1 ) {\n\t\treturn arguments.length > 2 && typeof segment1 !== 'number'\n\t\t\t? this._add(Segment.readList(arguments, 1), index)\n\t\t\t: this._add([ Segment.read(arguments, 1) ], index)[0];\n\t},\n\n\taddSegment: function() {\n\t\treturn this._add([ Segment.read(arguments) ])[0];\n\t},\n\n\tinsertSegment: function(index ) {\n\t\treturn this._add([ Segment.read(arguments, 1) ], index)[0];\n\t},\n\n\taddSegments: function(segments) {\n\t\treturn this._add(Segment.readList(segments));\n\t},\n\n\tinsertSegments: function(index, segments) {\n\t\treturn this._add(Segment.readList(segments), index);\n\t},\n\n\tremoveSegment: function(index) {\n\t\treturn this.removeSegments(index, index + 1)[0] || null;\n\t},\n\n\tremoveSegments: function(start, end, _includeCurves) {\n\t\tstart = start || 0;\n\t\tend = Base.pick(end, this._segments.length);\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tcount = segments.length,\n\t\t\tremoved = segments.splice(start, end - start),\n\t\t\tamount = removed.length;\n\t\tif (!amount)\n\t\t\treturn removed;\n\t\tfor (var i = 0; i < amount; i++) {\n\t\t\tvar segment = removed[i];\n\t\t\tif (segment._selection)\n\t\t\t\tthis._updateSelection(segment, segment._selection, 0);\n\t\t\tsegment._index = segment._path = null;\n\t\t}\n\t\tfor (var i = start, l = segments.length; i < l; i++)\n\t\t\tsegments[i]._index = i;\n\t\tif (curves) {\n\t\t\tvar index = start > 0 && end === count + (this._closed ? 1 : 0)\n\t\t\t\t\t? start - 1\n\t\t\t\t\t: start,\n\t\t\t\tcurves = curves.splice(index, amount);\n\t\t\tfor (var i = curves.length - 1; i >= 0; i--)\n\t\t\t\tcurves[i]._path = null;\n\t\t\tif (_includeCurves)\n\t\t\t\tremoved._curves = curves.slice(1);\n\t\t\tthis._adjustCurves(index, index);\n\t\t}\n\t\tthis._changed(25);\n\t\treturn removed;\n\t},\n\n\tclear: '#removeSegments',\n\n\thasHandles: function() {\n\t\tvar segments = this._segments;\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tif (segments[i].hasHandles())\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tclearHandles: function() {\n\t\tvar segments = this._segments;\n\t\tfor (var i = 0, l = segments.length; i < l; i++)\n\t\t\tsegments[i].clearHandles();\n\t},\n\n\tgetLength: function() {\n\t\tif (this._length == null) {\n\t\t\tvar curves = this.getCurves(),\n\t\t\t\tlength = 0;\n\t\t\tfor (var i = 0, l = curves.length; i < l; i++)\n\t\t\t\tlength += curves[i].getLength();\n\t\t\tthis._length = length;\n\t\t}\n\t\treturn this._length;\n\t},\n\n\tgetArea: function(_closed) {\n\t\tvar cached = _closed === undefined,\n\t\t\tarea = this._area;\n\t\tif (!cached || area == null) {\n\t\t\tvar segments = this._segments,\n\t\t\t\tcount = segments.length,\n\t\t\t\tclosed = cached ? this._closed : _closed,\n\t\t\t\tlast = count - 1;\n\t\t\tarea = 0;\n\t\t\tfor (var i = 0, l = closed ? count : last; i < l; i++) {\n\t\t\t\tarea += Curve.getArea(Curve.getValues(\n\t\t\t\t\t\tsegments[i], segments[i < last ? i + 1 : 0]));\n\t\t\t}\n\t\t\tif (cached)\n\t\t\t\tthis._area = area;\n\t\t}\n\t\treturn area;\n\t},\n\n\tisFullySelected: function() {\n\t\tvar length = this._segments.length;\n\t\treturn this.isSelected() && length > 0 && this._segmentSelection\n\t\t\t\t=== length * 7;\n\t},\n\n\tsetFullySelected: function(selected) {\n\t\tif (selected)\n\t\t\tthis._selectSegments(true);\n\t\tthis.setSelected(selected);\n\t},\n\n\tsetSelection: function setSelection(selection) {\n\t\tif (!(selection & 1))\n\t\t\tthis._selectSegments(false);\n\t\tsetSelection.base.call(this, selection);\n\t},\n\n\t_selectSegments: function(selected) {\n\t\tvar segments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tselection = selected ? 7 : 0;\n\t\tthis._segmentSelection = selection * length;\n\t\tfor (var i = 0; i < length; i++)\n\t\t\tsegments[i]._selection = selection;\n\t},\n\n\t_updateSelection: function(segment, oldSelection, newSelection) {\n\t\tsegment._selection = newSelection;\n\t\tvar selection = this._segmentSelection += newSelection - oldSelection;\n\t\tif (selection > 0)\n\t\t\tthis.setSelected(true);\n\t},\n\n\tsplitAt: function(location) {\n\t\tvar loc = typeof location === 'number'\n\t\t\t\t? this.getLocationAt(location) : location,\n\t\t\tindex = loc && loc.index,\n\t\t\ttime = loc && loc.time,\n\t\t\ttMin = 4e-7,\n\t\t\ttMax = 1 - tMin;\n\t\tif (time >= tMax) {\n\t\t\tindex++;\n\t\t\ttime = 0;\n\t\t}\n\t\tvar curves = this.getCurves();\n\t\tif (index >= 0 && index < curves.length) {\n\t\t\tif (time >= tMin) {\n\t\t\t\tcurves[index++].divideAtTime(time);\n\t\t\t}\n\t\t\tvar segs = this.removeSegments(index, this._segments.length, true),\n\t\t\t\tpath;\n\t\t\tif (this._closed) {\n\t\t\t\tthis.setClosed(false);\n\t\t\t\tpath = this;\n\t\t\t} else {\n\t\t\t\tpath = new Path(Item.NO_INSERT);\n\t\t\t\tpath.insertAbove(this);\n\t\t\t\tpath.copyAttributes(this);\n\t\t\t}\n\t\t\tpath._add(segs, 0);\n\t\t\tthis.addSegment(segs[0]);\n\t\t\treturn path;\n\t\t}\n\t\treturn null;\n\t},\n\n\tsplit: function(index, time) {\n\t\tvar curve,\n\t\t\tlocation = time === undefined ? index\n\t\t\t\t: (curve = this.getCurves()[index])\n\t\t\t\t\t&& curve.getLocationAtTime(time);\n\t\treturn location != null ? this.splitAt(location) : null;\n\t},\n\n\tjoin: function(path, tolerance) {\n\t\tvar epsilon = tolerance || 0;\n\t\tif (path && path !== this) {\n\t\t\tvar segments = path._segments,\n\t\t\t\tlast1 = this.getLastSegment(),\n\t\t\t\tlast2 = path.getLastSegment();\n\t\t\tif (!last2)\n\t\t\t\treturn this;\n\t\t\tif (last1 && last1._point.isClose(last2._point, epsilon))\n\t\t\t\tpath.reverse();\n\t\t\tvar first2 = path.getFirstSegment();\n\t\t\tif (last1 && last1._point.isClose(first2._point, epsilon)) {\n\t\t\t\tlast1.setHandleOut(first2._handleOut);\n\t\t\t\tthis._add(segments.slice(1));\n\t\t\t} else {\n\t\t\t\tvar first1 = this.getFirstSegment();\n\t\t\t\tif (first1 && first1._point.isClose(first2._point, epsilon))\n\t\t\t\t\tpath.reverse();\n\t\t\t\tlast2 = path.getLastSegment();\n\t\t\t\tif (first1 && first1._point.isClose(last2._point, epsilon)) {\n\t\t\t\t\tfirst1.setHandleIn(last2._handleIn);\n\t\t\t\t\tthis._add(segments.slice(0, segments.length - 1), 0);\n\t\t\t\t} else {\n\t\t\t\t\tthis._add(segments.slice());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (path._closed)\n\t\t\t\tthis._add([segments[0]]);\n\t\t\tpath.remove();\n\t\t}\n\t\tvar first = this.getFirstSegment(),\n\t\t\tlast = this.getLastSegment();\n\t\tif (first !== last && first._point.isClose(last._point, epsilon)) {\n\t\t\tfirst.setHandleIn(last._handleIn);\n\t\t\tlast.remove();\n\t\t\tthis.setClosed(true);\n\t\t}\n\t\treturn this;\n\t},\n\n\treduce: function(options) {\n\t\tvar curves = this.getCurves(),\n\t\t\tsimplify = options && options.simplify,\n\t\t\ttolerance = simplify ? 1e-7 : 0;\n\t\tfor (var i = curves.length - 1; i >= 0; i--) {\n\t\t\tvar curve = curves[i];\n\t\t\tif (!curve.hasHandles() && (curve.getLength() < tolerance\n\t\t\t\t\t|| simplify && curve.isCollinear(curve.getNext())))\n\t\t\t\tcurve.remove();\n\t\t}\n\t\treturn this;\n\t},\n\n\treverse: function() {\n\t\tthis._segments.reverse();\n\t\tfor (var i = 0, l = this._segments.length; i < l; i++) {\n\t\t\tvar segment = this._segments[i];\n\t\t\tvar handleIn = segment._handleIn;\n\t\t\tsegment._handleIn = segment._handleOut;\n\t\t\tsegment._handleOut = handleIn;\n\t\t\tsegment._index = i;\n\t\t}\n\t\tthis._curves = null;\n\t\tthis._changed(9);\n\t},\n\n\tflatten: function(flatness) {\n\t\tvar iterator = new PathIterator(this, flatness || 0.25, 256, true),\n\t\t\tparts = iterator.parts,\n\t\t\tlength = parts.length,\n\t\t\tsegments = [];\n\t\tfor (var i = 0; i < length; i++) {\n\t\t\tsegments.push(new Segment(parts[i].curve.slice(0, 2)));\n\t\t}\n\t\tif (!this._closed && length > 0) {\n\t\t\tsegments.push(new Segment(parts[length - 1].curve.slice(6)));\n\t\t}\n\t\tthis.setSegments(segments);\n\t},\n\n\tsimplify: function(tolerance) {\n\t\tvar segments = new PathFitter(this).fit(tolerance || 2.5);\n\t\tif (segments)\n\t\t\tthis.setSegments(segments);\n\t\treturn !!segments;\n\t},\n\n\tsmooth: function(options) {\n\t\tvar that = this,\n\t\t\topts = options || {},\n\t\t\ttype = opts.type || 'asymmetric',\n\t\t\tsegments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tclosed = this._closed;\n\n\t\tfunction getIndex(value, _default) {\n\t\t\tvar index = value && value.index;\n\t\t\tif (index != null) {\n\t\t\t\tvar path = value.path;\n\t\t\t\tif (path && path !== that)\n\t\t\t\t\tthrow new Error(value._class + ' ' + index + ' of ' + path\n\t\t\t\t\t\t\t+ ' is not part of ' + that);\n\t\t\t\tif (_default && value instanceof Curve)\n\t\t\t\t\tindex++;\n\t\t\t} else {\n\t\t\t\tindex = typeof value === 'number' ? value : _default;\n\t\t\t}\n\t\t\treturn Math.min(index < 0 && closed\n\t\t\t\t\t? index % length\n\t\t\t\t\t: index < 0 ? index + length : index, length - 1);\n\t\t}\n\n\t\tvar loop = closed && opts.from === undefined && opts.to === undefined,\n\t\t\tfrom = getIndex(opts.from, 0),\n\t\t\tto = getIndex(opts.to, length - 1);\n\n\t\tif (from > to) {\n\t\t\tif (closed) {\n\t\t\t\tfrom -= length;\n\t\t\t} else {\n\t\t\t\tvar tmp = from;\n\t\t\t\tfrom = to;\n\t\t\t\tto = tmp;\n\t\t\t}\n\t\t}\n\t\tif (/^(?:asymmetric|continuous)$/.test(type)) {\n\t\t\tvar asymmetric = type === 'asymmetric',\n\t\t\t\tmin = Math.min,\n\t\t\t\tamount = to - from + 1,\n\t\t\t\tn = amount - 1,\n\t\t\t\tpadding = loop ? min(amount, 4) : 1,\n\t\t\t\tpaddingLeft = padding,\n\t\t\t\tpaddingRight = padding,\n\t\t\t\tknots = [];\n\t\t\tif (!closed) {\n\t\t\t\tpaddingLeft = min(1, from);\n\t\t\t\tpaddingRight = min(1, length - to - 1);\n\t\t\t}\n\t\t\tn += paddingLeft + paddingRight;\n\t\t\tif (n <= 1)\n\t\t\t\treturn;\n\t\t\tfor (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {\n\t\t\t\tknots[i] = segments[(j < 0 ? j + length : j) % length]._point;\n\t\t\t}\n\n\t\t\tvar x = knots[0]._x + 2 * knots[1]._x,\n\t\t\t\ty = knots[0]._y + 2 * knots[1]._y,\n\t\t\t\tf = 2,\n\t\t\t\tn_1 = n - 1,\n\t\t\t\trx = [x],\n\t\t\t\try = [y],\n\t\t\t\trf = [f],\n\t\t\t\tpx = [],\n\t\t\t\tpy = [];\n\t\t\tfor (var i = 1; i < n; i++) {\n\t\t\t\tvar internal = i < n_1,\n\t\t\t\t\ta = internal ? 1 : asymmetric ? 1 : 2,\n\t\t\t\t\tb = internal ? 4 : asymmetric ? 2 : 7,\n\t\t\t\t\tu = internal ? 4 : asymmetric ? 3 : 8,\n\t\t\t\t\tv = internal ? 2 : asymmetric ? 0 : 1,\n\t\t\t\t\tm = a / f;\n\t\t\t\tf = rf[i] = b - m;\n\t\t\t\tx = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;\n\t\t\t\ty = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;\n\t\t\t}\n\n\t\t\tpx[n_1] = rx[n_1] / rf[n_1];\n\t\t\tpy[n_1] = ry[n_1] / rf[n_1];\n\t\t\tfor (var i = n - 2; i >= 0; i--) {\n\t\t\t\tpx[i] = (rx[i] - px[i + 1]) / rf[i];\n\t\t\t\tpy[i] = (ry[i] - py[i + 1]) / rf[i];\n\t\t\t}\n\t\t\tpx[n] = (3 * knots[n]._x - px[n_1]) / 2;\n\t\t\tpy[n] = (3 * knots[n]._y - py[n_1]) / 2;\n\n\t\t\tfor (var i = paddingLeft, max = n - paddingRight, j = from;\n\t\t\t\t\ti <= max; i++, j++) {\n\t\t\t\tvar segment = segments[j < 0 ? j + length : j],\n\t\t\t\t\tpt = segment._point,\n\t\t\t\t\thx = px[i] - pt._x,\n\t\t\t\t\thy = py[i] - pt._y;\n\t\t\t\tif (loop || i < max)\n\t\t\t\t\tsegment.setHandleOut(hx, hy);\n\t\t\t\tif (loop || i > paddingLeft)\n\t\t\t\t\tsegment.setHandleIn(-hx, -hy);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (var i = from; i <= to; i++) {\n\t\t\t\tsegments[i < 0 ? i + length : i].smooth(opts,\n\t\t\t\t\t\t!loop && i === from, !loop && i === to);\n\t\t\t}\n\t\t}\n\t},\n\n\ttoShape: function(insert) {\n\t\tif (!this._closed)\n\t\t\treturn null;\n\n\t\tvar segments = this._segments,\n\t\t\ttype,\n\t\t\tsize,\n\t\t\tradius,\n\t\t\ttopCenter;\n\n\t\tfunction isCollinear(i, j) {\n\t\t\tvar seg1 = segments[i],\n\t\t\t\tseg2 = seg1.getNext(),\n\t\t\t\tseg3 = segments[j],\n\t\t\t\tseg4 = seg3.getNext();\n\t\t\treturn seg1._handleOut.isZero() && seg2._handleIn.isZero()\n\t\t\t\t\t&& seg3._handleOut.isZero() && seg4._handleIn.isZero()\n\t\t\t\t\t&& seg2._point.subtract(seg1._point).isCollinear(\n\t\t\t\t\t\tseg4._point.subtract(seg3._point));\n\t\t}\n\n\t\tfunction isOrthogonal(i) {\n\t\t\tvar seg2 = segments[i],\n\t\t\t\tseg1 = seg2.getPrevious(),\n\t\t\t\tseg3 = seg2.getNext();\n\t\t\treturn seg1._handleOut.isZero() && seg2._handleIn.isZero()\n\t\t\t\t\t&& seg2._handleOut.isZero() && seg3._handleIn.isZero()\n\t\t\t\t\t&& seg2._point.subtract(seg1._point).isOrthogonal(\n\t\t\t\t\t\tseg3._point.subtract(seg2._point));\n\t\t}\n\n\t\tfunction isArc(i) {\n\t\t\tvar seg1 = segments[i],\n\t\t\t\tseg2 = seg1.getNext(),\n\t\t\t\thandle1 = seg1._handleOut,\n\t\t\t\thandle2 = seg2._handleIn,\n\t\t\t\tkappa = 0.5522847498307936;\n\t\t\tif (handle1.isOrthogonal(handle2)) {\n\t\t\t\tvar pt1 = seg1._point,\n\t\t\t\t\tpt2 = seg2._point,\n\t\t\t\t\tcorner = new Line(pt1, handle1, true).intersect(\n\t\t\t\t\t\t\tnew Line(pt2, handle2, true), true);\n\t\t\t\treturn corner && Numerical.isZero(handle1.getLength() /\n\t\t\t\t\t\tcorner.subtract(pt1).getLength() - kappa)\n\t\t\t\t\t&& Numerical.isZero(handle2.getLength() /\n\t\t\t\t\t\tcorner.subtract(pt2).getLength() - kappa);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tfunction getDistance(i, j) {\n\t\t\treturn segments[i]._point.getDistance(segments[j]._point);\n\t\t}\n\n\t\tif (!this.hasHandles() && segments.length === 4\n\t\t\t\t&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {\n\t\t\ttype = Shape.Rectangle;\n\t\t\tsize = new Size(getDistance(0, 3), getDistance(0, 1));\n\t\t\ttopCenter = segments[1]._point.add(segments[2]._point).divide(2);\n\t\t} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)\n\t\t\t\t&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {\n\t\t\ttype = Shape.Rectangle;\n\t\t\tsize = new Size(getDistance(1, 6), getDistance(0, 3));\n\t\t\tradius = size.subtract(new Size(getDistance(0, 7),\n\t\t\t\t\tgetDistance(1, 2))).divide(2);\n\t\t\ttopCenter = segments[3]._point.add(segments[4]._point).divide(2);\n\t\t} else if (segments.length === 4\n\t\t\t\t&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {\n\t\t\tif (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {\n\t\t\t\ttype = Shape.Circle;\n\t\t\t\tradius = getDistance(0, 2) / 2;\n\t\t\t} else {\n\t\t\t\ttype = Shape.Ellipse;\n\t\t\t\tradius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);\n\t\t\t}\n\t\t\ttopCenter = segments[1]._point;\n\t\t}\n\n\t\tif (type) {\n\t\t\tvar center = this.getPosition(true),\n\t\t\t\tshape = new type({\n\t\t\t\t\tcenter: center,\n\t\t\t\t\tsize: size,\n\t\t\t\t\tradius: radius,\n\t\t\t\t\tinsert: false\n\t\t\t\t});\n\t\t\tshape.copyAttributes(this, true);\n\t\t\tshape._matrix.prepend(this._matrix);\n\t\t\tshape.rotate(topCenter.subtract(center).getAngle() + 90);\n\t\t\tif (insert === undefined || insert)\n\t\t\t\tshape.insertAbove(this);\n\t\t\treturn shape;\n\t\t}\n\t\treturn null;\n\t},\n\n\ttoPath: '#clone',\n\n\tcompare: function compare(path) {\n\t\tif (!path || path instanceof CompoundPath)\n\t\t\treturn compare.base.call(this, path);\n\t\tvar curves1 = this.getCurves(),\n\t\t\tcurves2 = path.getCurves(),\n\t\t\tlength1 = curves1.length,\n\t\t\tlength2 = curves2.length;\n\t\tif (!length1 || !length2) {\n\t\t\treturn length1 ^ length2;\n\t\t}\n\t\tvar v1 = curves1[0].getValues(),\n\t\t\tvalues2 = [],\n\t\t\tpos1 = 0, pos2,\n\t\t\tend1 = 0, end2;\n\t\tfor (var i = 0; i < length2; i++) {\n\t\t\tvar v2 = curves2[i].getValues();\n\t\t\tvalues2.push(v2);\n\t\t\tvar overlaps = Curve.getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tpos2 = !i && overlaps[0][0] > 0 ? length2 - 1 : i;\n\t\t\t\tend2 = overlaps[0][1];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar abs = Math.abs,\n\t\t\tepsilon = 4e-7,\n\t\t\tv2 = values2[pos2],\n\t\t\tstart2;\n\t\twhile (v1 && v2) {\n\t\t\tvar overlaps = Curve.getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tvar t1 = overlaps[0][0];\n\t\t\t\tif (abs(t1 - end1) < epsilon) {\n\t\t\t\t\tend1 = overlaps[1][0];\n\t\t\t\t\tif (end1 === 1) {\n\t\t\t\t\t\tv1 = ++pos1 < length1 ? curves1[pos1].getValues() : null;\n\t\t\t\t\t\tend1 = 0;\n\t\t\t\t\t}\n\t\t\t\t\tvar t2 = overlaps[0][1];\n\t\t\t\t\tif (abs(t2 - end2) < epsilon) {\n\t\t\t\t\t\tif (!start2)\n\t\t\t\t\t\t\tstart2 = [pos2, t2];\n\t\t\t\t\t\tend2 = overlaps[1][1];\n\t\t\t\t\t\tif (end2 === 1) {\n\t\t\t\t\t\t\tif (++pos2 >= length2)\n\t\t\t\t\t\t\t\tpos2 = 0;\n\t\t\t\t\t\t\tv2 = values2[pos2] || curves2[pos2].getValues();\n\t\t\t\t\t\t\tend2 = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!v1) {\n\t\t\t\t\t\t\treturn start2[0] === pos2 && start2[1] === end2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\treturn false;\n\t},\n\n\t_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {\n\t\tvar that = this,\n\t\t\tstyle = this.getStyle(),\n\t\t\tsegments = this._segments,\n\t\t\tnumSegments = segments.length,\n\t\t\tclosed = this._closed,\n\t\t\ttolerancePadding = options._tolerancePadding,\n\t\t\tstrokePadding = tolerancePadding,\n\t\t\tjoin, cap, miterLimit,\n\t\t\tarea, loc, res,\n\t\t\thitStroke = options.stroke && style.hasStroke(),\n\t\t\thitFill = options.fill && style.hasFill(),\n\t\t\thitCurves = options.curves,\n\t\t\tstrokeRadius = hitStroke\n\t\t\t\t\t? style.getStrokeWidth() / 2\n\t\t\t\t\t: hitFill && options.tolerance > 0 || hitCurves\n\t\t\t\t\t\t? 0 : null;\n\t\tif (strokeRadius !== null) {\n\t\t\tif (strokeRadius > 0) {\n\t\t\t\tjoin = style.getStrokeJoin();\n\t\t\t\tcap = style.getStrokeCap();\n\t\t\t\tmiterLimit = strokeRadius * style.getMiterLimit();\n\t\t\t\tstrokePadding = strokePadding.add(\n\t\t\t\t\tPath._getStrokePadding(strokeRadius, strokeMatrix));\n\t\t\t} else {\n\t\t\t\tjoin = cap = 'round';\n\t\t\t}\n\t\t}\n\n\t\tfunction isCloseEnough(pt, padding) {\n\t\t\treturn point.subtract(pt).divide(padding).length <= 1;\n\t\t}\n\n\t\tfunction checkSegmentPoint(seg, pt, name) {\n\t\t\tif (!options.selected || pt.isSelected()) {\n\t\t\t\tvar anchor = seg._point;\n\t\t\t\tif (pt !== anchor)\n\t\t\t\t\tpt = pt.add(anchor);\n\t\t\t\tif (isCloseEnough(pt, strokePadding)) {\n\t\t\t\t\treturn new HitResult(name, that, {\n\t\t\t\t\t\tsegment: seg,\n\t\t\t\t\t\tpoint: pt\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction checkSegmentPoints(seg, ends) {\n\t\t\treturn (ends || options.segments)\n\t\t\t\t&& checkSegmentPoint(seg, seg._point, 'segment')\n\t\t\t\t|| (!ends && options.handles) && (\n\t\t\t\t\tcheckSegmentPoint(seg, seg._handleIn, 'handle-in') ||\n\t\t\t\t\tcheckSegmentPoint(seg, seg._handleOut, 'handle-out'));\n\t\t}\n\n\t\tfunction addToArea(point) {\n\t\t\tarea.add(point);\n\t\t}\n\n\t\tfunction checkSegmentStroke(segment) {\n\t\t\tif (join !== 'round' || cap !== 'round') {\n\t\t\t\tarea = new Path({ internal: true, closed: true });\n\t\t\t\tif (closed || segment._index > 0\n\t\t\t\t\t\t&& segment._index < numSegments - 1) {\n\t\t\t\t\tif (join !== 'round' && (segment._handleIn.isZero()\n\t\t\t\t\t\t\t|| segment._handleOut.isZero()))\n\t\t\t\t\t\tPath._addBevelJoin(segment, join, strokeRadius,\n\t\t\t\t\t\t\t miterLimit, null, strokeMatrix, addToArea, true);\n\t\t\t\t} else if (cap !== 'round') {\n\t\t\t\t\tPath._addSquareCap(segment, cap, strokeRadius, null,\n\t\t\t\t\t\t\tstrokeMatrix, addToArea, true);\n\t\t\t\t}\n\t\t\t\tif (!area.isEmpty()) {\n\t\t\t\t\tvar loc;\n\t\t\t\t\treturn area.contains(point)\n\t\t\t\t\t\t|| (loc = area.getNearestLocation(point))\n\t\t\t\t\t\t\t&& isCloseEnough(loc.getPoint(), tolerancePadding);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn isCloseEnough(segment._point, strokePadding);\n\t\t}\n\n\t\tif (options.ends && !options.segments && !closed) {\n\t\t\tif (res = checkSegmentPoints(segments[0], true)\n\t\t\t\t\t|| checkSegmentPoints(segments[numSegments - 1], true))\n\t\t\t\treturn res;\n\t\t} else if (options.segments || options.handles) {\n\t\t\tfor (var i = 0; i < numSegments; i++)\n\t\t\t\tif (res = checkSegmentPoints(segments[i]))\n\t\t\t\t\treturn res;\n\t\t}\n\t\tif (strokeRadius !== null) {\n\t\t\tloc = this.getNearestLocation(point);\n\t\t\tif (loc) {\n\t\t\t\tvar time = loc.getTime();\n\t\t\t\tif (time === 0 || time === 1 && numSegments > 1) {\n\t\t\t\t\tif (!checkSegmentStroke(loc.getSegment()))\n\t\t\t\t\t\tloc = null;\n\t\t\t\t} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {\n\t\t\t\t\tloc = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!loc && join === 'miter' && numSegments > 1) {\n\t\t\t\tfor (var i = 0; i < numSegments; i++) {\n\t\t\t\t\tvar segment = segments[i];\n\t\t\t\t\tif (point.getDistance(segment._point) <= miterLimit\n\t\t\t\t\t\t\t&& checkSegmentStroke(segment)) {\n\t\t\t\t\t\tloc = segment.getLocation();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn !loc && hitFill && this._contains(point)\n\t\t\t\t|| loc && !hitStroke && !hitCurves\n\t\t\t\t\t? new HitResult('fill', this)\n\t\t\t\t\t: loc\n\t\t\t\t\t\t? new HitResult(hitStroke ? 'stroke' : 'curve', this, {\n\t\t\t\t\t\t\tlocation: loc,\n\t\t\t\t\t\t\tpoint: loc.getPoint()\n\t\t\t\t\t\t})\n\t\t\t\t\t\t: null;\n\t}\n\n}, Base.each(Curve._evaluateMethods,\n\tfunction(name) {\n\t\tthis[name + 'At'] = function(offset) {\n\t\t\tvar loc = this.getLocationAt(offset);\n\t\t\treturn loc && loc[name]();\n\t\t};\n\t},\n{\n\tbeans: false,\n\n\tgetLocationOf: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcurves = this.getCurves();\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar loc = curves[i].getLocationOf(point);\n\t\t\tif (loc)\n\t\t\t\treturn loc;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetOffsetOf: function() {\n\t\tvar loc = this.getLocationOf.apply(this, arguments);\n\t\treturn loc ? loc.getOffset() : null;\n\t},\n\n\tgetLocationAt: function(offset) {\n\t\tvar curves = this.getCurves(),\n\t\t\tlength = 0;\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar start = length,\n\t\t\t\tcurve = curves[i];\n\t\t\tlength += curve.getLength();\n\t\t\tif (length > offset) {\n\t\t\t\treturn curve.getLocationAt(offset - start);\n\t\t\t}\n\t\t}\n\t\tif (curves.length > 0 && offset <= this.getLength())\n\t\t\treturn new CurveLocation(curves[curves.length - 1], 1);\n\t\treturn null;\n\t}\n\n}),\nnew function() {\n\n\tfunction drawHandles(ctx, segments, matrix, size) {\n\t\tvar half = size / 2,\n\t\t\tcoords = new Array(6),\n\t\t\tpX, pY;\n\n\t\tfunction drawHandle(index) {\n\t\t\tvar hX = coords[index],\n\t\t\t\thY = coords[index + 1];\n\t\t\tif (pX != hX || pY != hY) {\n\t\t\t\tctx.beginPath();\n\t\t\t\tctx.moveTo(pX, pY);\n\t\t\t\tctx.lineTo(hX, hY);\n\t\t\t\tctx.stroke();\n\t\t\t\tctx.beginPath();\n\t\t\t\tctx.arc(hX, hY, half, 0, Math.PI * 2, true);\n\t\t\t\tctx.fill();\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar segment = segments[i],\n\t\t\t\tselection = segment._selection;\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tpX = coords[0];\n\t\t\tpY = coords[1];\n\t\t\tif (selection & 2)\n\t\t\t\tdrawHandle(2);\n\t\t\tif (selection & 4)\n\t\t\t\tdrawHandle(4);\n\t\t\tctx.fillRect(pX - half, pY - half, size, size);\n\t\t\tif (!(selection & 1)) {\n\t\t\t\tvar fillStyle = ctx.fillStyle;\n\t\t\t\tctx.fillStyle = '#ffffff';\n\t\t\t\tctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);\n\t\t\t\tctx.fillStyle = fillStyle;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction drawSegments(ctx, path, matrix) {\n\t\tvar segments = path._segments,\n\t\t\tlength = segments.length,\n\t\t\tcoords = new Array(6),\n\t\t\tfirst = true,\n\t\t\tcurX, curY,\n\t\t\tprevX, prevY,\n\t\t\tinX, inY,\n\t\t\toutX, outY;\n\n\t\tfunction drawSegment(segment) {\n\t\t\tif (matrix) {\n\t\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\t\tcurX = coords[0];\n\t\t\t\tcurY = coords[1];\n\t\t\t} else {\n\t\t\t\tvar point = segment._point;\n\t\t\t\tcurX = point._x;\n\t\t\t\tcurY = point._y;\n\t\t\t}\n\t\t\tif (first) {\n\t\t\t\tctx.moveTo(curX, curY);\n\t\t\t\tfirst = false;\n\t\t\t} else {\n\t\t\t\tif (matrix) {\n\t\t\t\t\tinX = coords[2];\n\t\t\t\t\tinY = coords[3];\n\t\t\t\t} else {\n\t\t\t\t\tvar handle = segment._handleIn;\n\t\t\t\t\tinX = curX + handle._x;\n\t\t\t\t\tinY = curY + handle._y;\n\t\t\t\t}\n\t\t\t\tif (inX === curX && inY === curY\n\t\t\t\t\t\t&& outX === prevX && outY === prevY) {\n\t\t\t\t\tctx.lineTo(curX, curY);\n\t\t\t\t} else {\n\t\t\t\t\tctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevX = curX;\n\t\t\tprevY = curY;\n\t\t\tif (matrix) {\n\t\t\t\toutX = coords[4];\n\t\t\t\toutY = coords[5];\n\t\t\t} else {\n\t\t\t\tvar handle = segment._handleOut;\n\t\t\t\toutX = prevX + handle._x;\n\t\t\t\toutY = prevY + handle._y;\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0; i < length; i++)\n\t\t\tdrawSegment(segments[i]);\n\t\tif (path._closed && length > 0)\n\t\t\tdrawSegment(segments[0]);\n\t}\n\n\treturn {\n\t\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\t\tvar dontStart = param.dontStart,\n\t\t\t\tdontPaint = param.dontFinish || param.clip,\n\t\t\t\tstyle = this.getStyle(),\n\t\t\t\thasFill = style.hasFill(),\n\t\t\t\thasStroke = style.hasStroke(),\n\t\t\t\tdashArray = style.getDashArray(),\n\t\t\t\tdashLength = !paper.support.nativeDash && hasStroke\n\t\t\t\t\t\t&& dashArray && dashArray.length;\n\n\t\t\tif (!dontStart)\n\t\t\t\tctx.beginPath();\n\n\t\t\tif (hasFill || hasStroke && !dashLength || dontPaint) {\n\t\t\t\tdrawSegments(ctx, this, strokeMatrix);\n\t\t\t\tif (this._closed)\n\t\t\t\t\tctx.closePath();\n\t\t\t}\n\n\t\t\tfunction getOffset(i) {\n\t\t\t\treturn dashArray[((i % dashLength) + dashLength) % dashLength];\n\t\t\t}\n\n\t\t\tif (!dontPaint && (hasFill || hasStroke)) {\n\t\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\t\tif (hasFill) {\n\t\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t\t}\n\t\t\t\tif (hasStroke) {\n\t\t\t\t\tif (dashLength) {\n\t\t\t\t\t\tif (!dontStart)\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\tvar iterator = new PathIterator(this, 0.25, 32, false,\n\t\t\t\t\t\t\t\tstrokeMatrix),\n\t\t\t\t\t\t\tlength = iterator.length,\n\t\t\t\t\t\t\tfrom = -style.getDashOffset(), to,\n\t\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\tfrom = from % length;\n\t\t\t\t\t\twhile (from > 0) {\n\t\t\t\t\t\t\tfrom -= getOffset(i--) + getOffset(i--);\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile (from < length) {\n\t\t\t\t\t\t\tto = from + getOffset(i++);\n\t\t\t\t\t\t\tif (from > 0 || to > 0)\n\t\t\t\t\t\t\t\titerator.drawPart(ctx,\n\t\t\t\t\t\t\t\t\t\tMath.max(from, 0), Math.max(to, 0));\n\t\t\t\t\t\t\tfrom = to + getOffset(i++);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_drawSelected: function(ctx, matrix) {\n\t\t\tctx.beginPath();\n\t\t\tdrawSegments(ctx, this, matrix);\n\t\t\tctx.stroke();\n\t\t\tdrawHandles(ctx, this._segments, matrix, paper.settings.handleSize);\n\t\t}\n\t};\n},\nnew function() {\n\tfunction getCurrentSegment(that) {\n\t\tvar segments = that._segments;\n\t\tif (!segments.length)\n\t\t\tthrow new Error('Use a moveTo() command first');\n\t\treturn segments[segments.length - 1];\n\t}\n\n\treturn {\n\t\tmoveTo: function() {\n\t\t\tvar segments = this._segments;\n\t\t\tif (segments.length === 1)\n\t\t\t\tthis.removeSegment(0);\n\t\t\tif (!segments.length)\n\t\t\t\tthis._add([ new Segment(Point.read(arguments)) ]);\n\t\t},\n\n\t\tmoveBy: function() {\n\t\t\tthrow new Error('moveBy() is unsupported on Path items.');\n\t\t},\n\n\t\tlineTo: function() {\n\t\t\tthis._add([ new Segment(Point.read(arguments)) ]);\n\t\t},\n\n\t\tcubicCurveTo: function() {\n\t\t\tvar handle1 = Point.read(arguments),\n\t\t\t\thandle2 = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this);\n\t\t\tcurrent.setHandleOut(handle1.subtract(current._point));\n\t\t\tthis._add([ new Segment(to, handle2.subtract(to)) ]);\n\t\t},\n\n\t\tquadraticCurveTo: function() {\n\t\t\tvar handle = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.cubicCurveTo(\n\t\t\t\thandle.add(current.subtract(handle).multiply(1 / 3)),\n\t\t\t\thandle.add(to.subtract(handle).multiply(1 / 3)),\n\t\t\t\tto\n\t\t\t);\n\t\t},\n\n\t\tcurveTo: function() {\n\t\t\tvar through = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tt = Base.pick(Base.read(arguments), 0.5),\n\t\t\t\tt1 = 1 - t,\n\t\t\t\tcurrent = getCurrentSegment(this)._point,\n\t\t\t\thandle = through.subtract(current.multiply(t1 * t1))\n\t\t\t\t\t.subtract(to.multiply(t * t)).divide(2 * t * t1);\n\t\t\tif (handle.isNaN())\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Cannot put a curve through points with parameter = ' + t);\n\t\t\tthis.quadraticCurveTo(handle, to);\n\t\t},\n\n\t\tarcTo: function() {\n\t\t\tvar current = getCurrentSegment(this),\n\t\t\t\tfrom = current._point,\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tthrough,\n\t\t\t\tpeek = Base.peek(arguments),\n\t\t\t\tclockwise = Base.pick(peek, true),\n\t\t\t\tcenter, extent, vector, matrix;\n\t\t\tif (typeof clockwise === 'boolean') {\n\t\t\t\tvar middle = from.add(to).divide(2),\n\t\t\t\tthrough = middle.add(middle.subtract(from).rotate(\n\t\t\t\t\t\tclockwise ? -90 : 90));\n\t\t\t} else if (Base.remain(arguments) <= 2) {\n\t\t\t\tthrough = to;\n\t\t\t\tto = Point.read(arguments);\n\t\t\t} else {\n\t\t\t\tvar radius = Size.read(arguments),\n\t\t\t\t\tisZero = Numerical.isZero;\n\t\t\t\tif (isZero(radius.width) || isZero(radius.height))\n\t\t\t\t\treturn this.lineTo(to);\n\t\t\t\tvar rotation = Base.read(arguments),\n\t\t\t\t\tclockwise = !!Base.read(arguments),\n\t\t\t\t\tlarge = !!Base.read(arguments),\n\t\t\t\t\tmiddle = from.add(to).divide(2),\n\t\t\t\t\tpt = from.subtract(middle).rotate(-rotation),\n\t\t\t\t\tx = pt.x,\n\t\t\t\t\ty = pt.y,\n\t\t\t\t\tabs = Math.abs,\n\t\t\t\t\trx = abs(radius.width),\n\t\t\t\t\try = abs(radius.height),\n\t\t\t\t\trxSq = rx * rx,\n\t\t\t\t\trySq = ry * ry,\n\t\t\t\t\txSq = x * x,\n\t\t\t\t\tySq = y * y;\n\t\t\t\tvar factor = Math.sqrt(xSq / rxSq + ySq / rySq);\n\t\t\t\tif (factor > 1) {\n\t\t\t\t\trx *= factor;\n\t\t\t\t\try *= factor;\n\t\t\t\t\trxSq = rx * rx;\n\t\t\t\t\trySq = ry * ry;\n\t\t\t\t}\n\t\t\t\tfactor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /\n\t\t\t\t\t\t(rxSq * ySq + rySq * xSq);\n\t\t\t\tif (abs(factor) < 1e-12)\n\t\t\t\t\tfactor = 0;\n\t\t\t\tif (factor < 0)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Cannot create an arc with the given arguments');\n\t\t\t\tcenter = new Point(rx * y / ry, -ry * x / rx)\n\t\t\t\t\t\t.multiply((large === clockwise ? -1 : 1)\n\t\t\t\t\t\t\t* Math.sqrt(factor))\n\t\t\t\t\t\t.rotate(rotation).add(middle);\n\t\t\t\tmatrix = new Matrix().translate(center).rotate(rotation)\n\t\t\t\t\t\t.scale(rx, ry);\n\t\t\t\tvector = matrix._inverseTransform(from);\n\t\t\t\textent = vector.getDirectedAngle(matrix._inverseTransform(to));\n\t\t\t\tif (!clockwise && extent > 0)\n\t\t\t\t\textent -= 360;\n\t\t\t\telse if (clockwise && extent < 0)\n\t\t\t\t\textent += 360;\n\t\t\t}\n\t\t\tif (through) {\n\t\t\t\tvar l1 = new Line(from.add(through).divide(2),\n\t\t\t\t\t\t\tthrough.subtract(from).rotate(90), true),\n\t\t\t\t\tl2 = new Line(through.add(to).divide(2),\n\t\t\t\t\t\t\tto.subtract(through).rotate(90), true),\n\t\t\t\t\tline = new Line(from, to),\n\t\t\t\t\tthroughSide = line.getSide(through);\n\t\t\t\tcenter = l1.intersect(l2, true);\n\t\t\t\tif (!center) {\n\t\t\t\t\tif (!throughSide)\n\t\t\t\t\t\treturn this.lineTo(to);\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Cannot create an arc with the given arguments');\n\t\t\t\t}\n\t\t\t\tvector = from.subtract(center);\n\t\t\t\textent = vector.getDirectedAngle(to.subtract(center));\n\t\t\t\tvar centerSide = line.getSide(center);\n\t\t\t\tif (centerSide === 0) {\n\t\t\t\t\textent = throughSide * Math.abs(extent);\n\t\t\t\t} else if (throughSide === centerSide) {\n\t\t\t\t\textent += extent < 0 ? 360 : -360;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar ext = Math.abs(extent),\n\t\t\t\tcount = ext >= 360 ? 4 : Math.ceil(ext / 90),\n\t\t\t\tinc = extent / count,\n\t\t\t\thalf = inc * Math.PI / 360,\n\t\t\t\tz = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),\n\t\t\t\tsegments = [];\n\t\t\tfor (var i = 0; i <= count; i++) {\n\t\t\t\tvar pt = to,\n\t\t\t\t\tout = null;\n\t\t\t\tif (i < count) {\n\t\t\t\t\tout = vector.rotate(90).multiply(z);\n\t\t\t\t\tif (matrix) {\n\t\t\t\t\t\tpt = matrix._transformPoint(vector);\n\t\t\t\t\t\tout = matrix._transformPoint(vector.add(out))\n\t\t\t\t\t\t\t\t.subtract(pt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpt = center.add(vector);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!i) {\n\t\t\t\t\tcurrent.setHandleOut(out);\n\t\t\t\t} else {\n\t\t\t\t\tvar _in = vector.rotate(-90).multiply(z);\n\t\t\t\t\tif (matrix) {\n\t\t\t\t\t\t_in = matrix._transformPoint(vector.add(_in))\n\t\t\t\t\t\t\t\t.subtract(pt);\n\t\t\t\t\t}\n\t\t\t\t\tsegments.push(new Segment(pt, _in, out));\n\t\t\t\t}\n\t\t\t\tvector = vector.rotate(inc);\n\t\t\t}\n\t\t\tthis._add(segments);\n\t\t},\n\n\t\tlineBy: function() {\n\t\t\tvar to = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.lineTo(current.add(to));\n\t\t},\n\n\t\tcurveBy: function() {\n\t\t\tvar through = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tparameter = Base.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.curveTo(current.add(through), current.add(to), parameter);\n\t\t},\n\n\t\tcubicCurveBy: function() {\n\t\t\tvar handle1 = Point.read(arguments),\n\t\t\t\thandle2 = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.cubicCurveTo(current.add(handle1), current.add(handle2),\n\t\t\t\t\tcurrent.add(to));\n\t\t},\n\n\t\tquadraticCurveBy: function() {\n\t\t\tvar handle = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.quadraticCurveTo(current.add(handle), current.add(to));\n\t\t},\n\n\t\tarcBy: function() {\n\t\t\tvar current = getCurrentSegment(this)._point,\n\t\t\t\tpoint = current.add(Point.read(arguments)),\n\t\t\t\tclockwise = Base.pick(Base.peek(arguments), true);\n\t\t\tif (typeof clockwise === 'boolean') {\n\t\t\t\tthis.arcTo(point, clockwise);\n\t\t\t} else {\n\t\t\t\tthis.arcTo(point, current.add(Point.read(arguments)));\n\t\t\t}\n\t\t},\n\n\t\tclosePath: function(tolerance) {\n\t\t\tthis.setClosed(true);\n\t\t\tthis.join(this, tolerance);\n\t\t}\n\t};\n}, {\n\n\t_getBounds: function(matrix, options) {\n\t\tvar method = options.handle\n\t\t\t\t? 'getHandleBounds'\n\t\t\t\t: options.stroke\n\t\t\t\t? 'getStrokeBounds'\n\t\t\t\t: 'getBounds';\n\t\treturn Path[method](this._segments, this._closed, this, matrix, options);\n\t},\n\nstatics: {\n\tgetBounds: function(segments, closed, path, matrix, options, strokePadding) {\n\t\tvar first = segments[0];\n\t\tif (!first)\n\t\t\treturn new Rectangle();\n\t\tvar coords = new Array(6),\n\t\t\tprevCoords = first._transformCoordinates(matrix, new Array(6)),\n\t\t\tmin = prevCoords.slice(0, 2),\n\t\t\tmax = min.slice(),\n\t\t\troots = new Array(2);\n\n\t\tfunction processSegment(segment) {\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tfor (var i = 0; i < 2; i++) {\n\t\t\t\tCurve._addBounds(\n\t\t\t\t\tprevCoords[i],\n\t\t\t\t\tprevCoords[i + 4],\n\t\t\t\t\tcoords[i + 2],\n\t\t\t\t\tcoords[i],\n\t\t\t\t\ti, strokePadding ? strokePadding[i] : 0, min, max, roots);\n\t\t\t}\n\t\t\tvar tmp = prevCoords;\n\t\t\tprevCoords = coords;\n\t\t\tcoords = tmp;\n\t\t}\n\n\t\tfor (var i = 1, l = segments.length; i < l; i++)\n\t\t\tprocessSegment(segments[i]);\n\t\tif (closed)\n\t\t\tprocessSegment(first);\n\t\treturn new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);\n\t},\n\n\tgetStrokeBounds: function(segments, closed, path, matrix, options) {\n\t\tvar style = path.getStyle(),\n\t\t\tstroke = style.hasStroke(),\n\t\t\tstrokeWidth = style.getStrokeWidth(),\n\t\t\tstrokeMatrix = stroke && path._getStrokeMatrix(matrix, options),\n\t\t\tstrokePadding = stroke && Path._getStrokePadding(strokeWidth,\n\t\t\t\tstrokeMatrix),\n\t\t\tbounds = Path.getBounds(segments, closed, path, matrix, options,\n\t\t\t\tstrokePadding);\n\t\tif (!stroke)\n\t\t\treturn bounds;\n\t\tvar strokeRadius = strokeWidth / 2,\n\t\t\tjoin = style.getStrokeJoin(),\n\t\t\tcap = style.getStrokeCap(),\n\t\t\tmiterLimit = strokeRadius * style.getMiterLimit(),\n\t\t\tjoinBounds = new Rectangle(new Size(strokePadding));\n\n\t\tfunction addPoint(point) {\n\t\t\tbounds = bounds.include(point);\n\t\t}\n\n\t\tfunction addRound(segment) {\n\t\t\tbounds = bounds.unite(\n\t\t\t\t\tjoinBounds.setCenter(segment._point.transform(matrix)));\n\t\t}\n\n\t\tfunction addJoin(segment, join) {\n\t\t\tvar handleIn = segment._handleIn,\n\t\t\t\thandleOut = segment._handleOut;\n\t\t\tif (join === 'round' || !handleIn.isZero() && !handleOut.isZero()\n\t\t\t\t\t&& handleIn.isCollinear(handleOut)) {\n\t\t\t\taddRound(segment);\n\t\t\t} else {\n\t\t\t\tPath._addBevelJoin(segment, join, strokeRadius, miterLimit,\n\t\t\t\t\t\tmatrix, strokeMatrix, addPoint);\n\t\t\t}\n\t\t}\n\n\t\tfunction addCap(segment, cap) {\n\t\t\tif (cap === 'round') {\n\t\t\t\taddRound(segment);\n\t\t\t} else {\n\t\t\t\tPath._addSquareCap(segment, cap, strokeRadius, matrix,\n\t\t\t\t\t\tstrokeMatrix, addPoint);\n\t\t\t}\n\t\t}\n\n\t\tvar length = segments.length - (closed ? 0 : 1);\n\t\tfor (var i = 1; i < length; i++)\n\t\t\taddJoin(segments[i], join);\n\t\tif (closed) {\n\t\t\taddJoin(segments[0], join);\n\t\t} else if (length > 0) {\n\t\t\taddCap(segments[0], cap);\n\t\t\taddCap(segments[segments.length - 1], cap);\n\t\t}\n\t\treturn bounds;\n\t},\n\n\t_getStrokePadding: function(radius, matrix) {\n\t\tif (!matrix)\n\t\t\treturn [radius, radius];\n\t\tvar hor = new Point(radius, 0).transform(matrix),\n\t\t\tver = new Point(0, radius).transform(matrix),\n\t\t\tphi = hor.getAngleInRadians(),\n\t\t\ta = hor.getLength(),\n\t\t\tb = ver.getLength();\n\t\tvar sin = Math.sin(phi),\n\t\t\tcos = Math.cos(phi),\n\t\t\ttan = Math.tan(phi),\n\t\t\ttx = Math.atan2(b * tan, a),\n\t\t\tty = Math.atan2(b, tan * a);\n\t\treturn [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),\n\t\t\t\tMath.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];\n\t},\n\n\t_addBevelJoin: function(segment, join, radius, miterLimit, matrix,\n\t\t\tstrokeMatrix, addPoint, isArea) {\n\t\tvar curve2 = segment.getCurve(),\n\t\t\tcurve1 = curve2.getPrevious(),\n\t\t\tpoint = curve2.getPoint1().transform(matrix),\n\t\t\tnormal1 = curve1.getNormalAtTime(1).multiply(radius)\n\t\t\t\t.transform(strokeMatrix),\n\t\t\tnormal2 = curve2.getNormalAtTime(0).multiply(radius)\n\t\t\t\t.transform(strokeMatrix);\n\t\tif (normal1.getDirectedAngle(normal2) < 0) {\n\t\t\tnormal1 = normal1.negate();\n\t\t\tnormal2 = normal2.negate();\n\t\t}\n\t\tif (isArea) {\n\t\t\taddPoint(point);\n\t\t\taddPoint(point.add(normal1));\n\t\t}\n\t\tif (join === 'miter') {\n\t\t\tvar corner = new Line(point.add(normal1),\n\t\t\t\t\tnew Point(-normal1.y, normal1.x), true\n\t\t\t\t).intersect(new Line(point.add(normal2),\n\t\t\t\t\tnew Point(-normal2.y, normal2.x), true\n\t\t\t\t), true);\n\t\t\tif (corner && point.getDistance(corner) <= miterLimit) {\n\t\t\t\taddPoint(corner);\n\t\t\t\tif (!isArea)\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (!isArea)\n\t\t\taddPoint(point.add(normal1));\n\t\taddPoint(point.add(normal2));\n\t},\n\n\t_addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,\n\t\t\taddPoint, isArea) {\n\t\tvar point = segment._point.transform(matrix),\n\t\t\tloc = segment.getLocation(),\n\t\t\tnormal = loc.getNormal().multiply(radius).transform(strokeMatrix);\n\t\tif (isArea) {\n\t\t\taddPoint(point.subtract(normal));\n\t\t\taddPoint(point.add(normal));\n\t\t}\n\t\tif (cap === 'square') {\n\t\t\tpoint = point.add(normal.rotate(\n\t\t\t\t\tloc.getTime() === 0 ? -90 : 90));\n\t\t}\n\t\taddPoint(point.add(normal));\n\t\taddPoint(point.subtract(normal));\n\t},\n\n\tgetHandleBounds: function(segments, closed, path, matrix, options) {\n\t\tvar style = path.getStyle(),\n\t\t\tstroke = options.stroke && style.hasStroke(),\n\t\t\tstrokePadding,\n\t\t\tjoinPadding;\n\t\tif (stroke) {\n\t\t\tvar strokeMatrix = path._getStrokeMatrix(matrix, options),\n\t\t\t\tstrokeRadius = style.getStrokeWidth() / 2,\n\t\t\t\tjoinRadius = strokeRadius;\n\t\t\tif (style.getStrokeJoin() === 'miter')\n\t\t\t\tjoinRadius = strokeRadius * style.getMiterLimit();\n\t\t\tif (style.getStrokeCap() === 'square')\n\t\t\t\tjoinRadius = Math.max(joinRadius, strokeRadius * Math.sqrt(2));\n\t\t\tstrokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix);\n\t\t\tjoinPadding = Path._getStrokePadding(joinRadius, strokeMatrix);\n\t\t}\n\t\tvar coords = new Array(6),\n\t\t\tx1 = Infinity,\n\t\t\tx2 = -x1,\n\t\t\ty1 = x1,\n\t\t\ty2 = x2;\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar segment = segments[i];\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tfor (var j = 0; j < 6; j += 2) {\n\t\t\t\tvar padding = !j ? joinPadding : strokePadding,\n\t\t\t\t\tpaddingX = padding ? padding[0] : 0,\n\t\t\t\t\tpaddingY = padding ? padding[1] : 0,\n\t\t\t\t\tx = coords[j],\n\t\t\t\t\ty = coords[j + 1],\n\t\t\t\t\txn = x - paddingX,\n\t\t\t\t\txx = x + paddingX,\n\t\t\t\t\tyn = y - paddingY,\n\t\t\t\t\tyx = y + paddingY;\n\t\t\t\tif (xn < x1) x1 = xn;\n\t\t\t\tif (xx > x2) x2 = xx;\n\t\t\t\tif (yn < y1) y1 = yn;\n\t\t\t\tif (yx > y2) y2 = yx;\n\t\t\t}\n\t\t}\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t}\n}});\n\nPath.inject({ statics: new function() {\n\n\tvar kappa = 0.5522847498307936,\n\t\tellipseSegments = [\n\t\t\tnew Segment([-1, 0], [0, kappa ], [0, -kappa]),\n\t\t\tnew Segment([0, -1], [-kappa, 0], [kappa, 0 ]),\n\t\t\tnew Segment([1, 0], [0, -kappa], [0, kappa ]),\n\t\t\tnew Segment([0, 1], [kappa, 0 ], [-kappa, 0])\n\t\t];\n\n\tfunction createPath(segments, closed, args) {\n\t\tvar props = Base.getNamed(args),\n\t\t\tpath = new Path(props && props.insert === false && Item.NO_INSERT);\n\t\tpath._add(segments);\n\t\tpath._closed = closed;\n\t\treturn path.set(props);\n\t}\n\n\tfunction createEllipse(center, radius, args) {\n\t\tvar segments = new Array(4);\n\t\tfor (var i = 0; i < 4; i++) {\n\t\t\tvar segment = ellipseSegments[i];\n\t\t\tsegments[i] = new Segment(\n\t\t\t\tsegment._point.multiply(radius).add(center),\n\t\t\t\tsegment._handleIn.multiply(radius),\n\t\t\t\tsegment._handleOut.multiply(radius)\n\t\t\t);\n\t\t}\n\t\treturn createPath(segments, true, args);\n\t}\n\n\treturn {\n\t\tLine: function() {\n\t\t\treturn createPath([\n\t\t\t\tnew Segment(Point.readNamed(arguments, 'from')),\n\t\t\t\tnew Segment(Point.readNamed(arguments, 'to'))\n\t\t\t], false, arguments);\n\t\t},\n\n\t\tCircle: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius');\n\t\t\treturn createEllipse(center, new Size(radius), arguments);\n\t\t},\n\n\t\tRectangle: function() {\n\t\t\tvar rect = Rectangle.readNamed(arguments, 'rectangle'),\n\t\t\t\tradius = Size.readNamed(arguments, 'radius', 0,\n\t\t\t\t\t\t{ readNull: true }),\n\t\t\t\tbl = rect.getBottomLeft(true),\n\t\t\t\ttl = rect.getTopLeft(true),\n\t\t\t\ttr = rect.getTopRight(true),\n\t\t\t\tbr = rect.getBottomRight(true),\n\t\t\t\tsegments;\n\t\t\tif (!radius || radius.isZero()) {\n\t\t\t\tsegments = [\n\t\t\t\t\tnew Segment(bl),\n\t\t\t\t\tnew Segment(tl),\n\t\t\t\t\tnew Segment(tr),\n\t\t\t\t\tnew Segment(br)\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\tradius = Size.min(radius, rect.getSize(true).divide(2));\n\t\t\t\tvar rx = radius.width,\n\t\t\t\t\try = radius.height,\n\t\t\t\t\thx = rx * kappa,\n\t\t\t\t\thy = ry * kappa;\n\t\t\t\tsegments = [\n\t\t\t\t\tnew Segment(bl.add(rx, 0), null, [-hx, 0]),\n\t\t\t\t\tnew Segment(bl.subtract(0, ry), [0, hy]),\n\t\t\t\t\tnew Segment(tl.add(0, ry), null, [0, -hy]),\n\t\t\t\t\tnew Segment(tl.add(rx, 0), [-hx, 0], null),\n\t\t\t\t\tnew Segment(tr.subtract(rx, 0), null, [hx, 0]),\n\t\t\t\t\tnew Segment(tr.add(0, ry), [0, -hy], null),\n\t\t\t\t\tnew Segment(br.subtract(0, ry), null, [0, hy]),\n\t\t\t\t\tnew Segment(br.subtract(rx, 0), [hx, 0])\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn createPath(segments, true, arguments);\n\t\t},\n\n\t\tRoundRectangle: '#Rectangle',\n\n\t\tEllipse: function() {\n\t\t\tvar ellipse = Shape._readEllipse(arguments);\n\t\t\treturn createEllipse(ellipse.center, ellipse.radius, arguments);\n\t\t},\n\n\t\tOval: '#Ellipse',\n\n\t\tArc: function() {\n\t\t\tvar from = Point.readNamed(arguments, 'from'),\n\t\t\t\tthrough = Point.readNamed(arguments, 'through'),\n\t\t\t\tto = Point.readNamed(arguments, 'to'),\n\t\t\t\tprops = Base.getNamed(arguments),\n\t\t\t\tpath = new Path(props && props.insert === false\n\t\t\t\t\t\t&& Item.NO_INSERT);\n\t\t\tpath.moveTo(from);\n\t\t\tpath.arcTo(through, to);\n\t\t\treturn path.set(props);\n\t\t},\n\n\t\tRegularPolygon: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tsides = Base.readNamed(arguments, 'sides'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius'),\n\t\t\t\tstep = 360 / sides,\n\t\t\t\tthree = sides % 3 === 0,\n\t\t\t\tvector = new Point(0, three ? -radius : radius),\n\t\t\t\toffset = three ? -1 : 0.5,\n\t\t\t\tsegments = new Array(sides);\n\t\t\tfor (var i = 0; i < sides; i++)\n\t\t\t\tsegments[i] = new Segment(center.add(\n\t\t\t\t\tvector.rotate((i + offset) * step)));\n\t\t\treturn createPath(segments, true, arguments);\n\t\t},\n\n\t\tStar: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tpoints = Base.readNamed(arguments, 'points') * 2,\n\t\t\t\tradius1 = Base.readNamed(arguments, 'radius1'),\n\t\t\t\tradius2 = Base.readNamed(arguments, 'radius2'),\n\t\t\t\tstep = 360 / points,\n\t\t\t\tvector = new Point(0, -1),\n\t\t\t\tsegments = new Array(points);\n\t\t\tfor (var i = 0; i < points; i++)\n\t\t\t\tsegments[i] = new Segment(center.add(vector.rotate(step * i)\n\t\t\t\t\t\t.multiply(i % 2 ? radius2 : radius1)));\n\t\t\treturn createPath(segments, true, arguments);\n\t\t}\n\t};\n}});\n\nvar CompoundPath = PathItem.extend({\n\t_class: 'CompoundPath',\n\t_serializeFields: {\n\t\tchildren: []\n\t},\n\n\tinitialize: function CompoundPath(arg) {\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tif (!this._initialize(arg)) {\n\t\t\tif (typeof arg === 'string') {\n\t\t\t\tthis.setPathData(arg);\n\t\t\t} else {\n\t\t\t\tthis.addChildren(Array.isArray(arg) ? arg : arguments);\n\t\t\t}\n\t\t}\n\t},\n\n\tinsertChildren: function insertChildren(index, items) {\n\t\tvar list = items,\n\t\t\tfirst = list[0];\n\t\tif (first && typeof first[0] === 'number')\n\t\t\tlist = [list];\n\t\tfor (var i = items.length - 1; i >= 0; i--) {\n\t\t\tvar item = list[i];\n\t\t\tif (list === items && !(item instanceof Path))\n\t\t\t\tlist = Base.slice(list);\n\t\t\tif (Array.isArray(item)) {\n\t\t\t\tlist[i] = new Path({ segments: item, insert: false });\n\t\t\t} else if (item instanceof CompoundPath) {\n\t\t\t\tlist.splice.apply(list, [i, 1].concat(item.removeChildren()));\n\t\t\t\titem.remove();\n\t\t\t}\n\t\t}\n\t\treturn insertChildren.base.call(this, index, list);\n\t},\n\n\treduce: function reduce(options) {\n\t\tvar children = this._children;\n\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\tvar path = children[i].reduce(options);\n\t\t\tif (path.isEmpty())\n\t\t\t\tpath.remove();\n\t\t}\n\t\tif (!children.length) {\n\t\t\tvar path = new Path(Item.NO_INSERT);\n\t\t\tpath.copyAttributes(this);\n\t\t\tpath.insertAbove(this);\n\t\t\tthis.remove();\n\t\t\treturn path;\n\t\t}\n\t\treturn reduce.base.call(this);\n\t},\n\n\tisClosed: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tif (!children[i]._closed)\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tsetClosed: function(closed) {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tchildren[i].setClosed(closed);\n\t\t}\n\t},\n\n\tgetFirstSegment: function() {\n\t\tvar first = this.getFirstChild();\n\t\treturn first && first.getFirstSegment();\n\t},\n\n\tgetLastSegment: function() {\n\t\tvar last = this.getLastChild();\n\t\treturn last && last.getLastSegment();\n\t},\n\n\tgetCurves: function() {\n\t\tvar children = this._children,\n\t\t\tcurves = [];\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tcurves.push.apply(curves, children[i].getCurves());\n\t\treturn curves;\n\t},\n\n\tgetFirstCurve: function() {\n\t\tvar first = this.getFirstChild();\n\t\treturn first && first.getFirstCurve();\n\t},\n\n\tgetLastCurve: function() {\n\t\tvar last = this.getLastChild();\n\t\treturn last && last.getLastCurve();\n\t},\n\n\tgetArea: function() {\n\t\tvar children = this._children,\n\t\t\tarea = 0;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tarea += children[i].getArea();\n\t\treturn area;\n\t},\n\n\tgetLength: function() {\n\t\tvar children = this._children,\n\t\t\tlength = 0;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tlength += children[i].getLength();\n\t\treturn length;\n\t}\n}, {\n\tbeans: true,\n\n\tgetPathData: function(_matrix, _precision) {\n\t\tvar children = this._children,\n\t\t\tpaths = [];\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i],\n\t\t\t\tmx = child._matrix;\n\t\t\tpaths.push(child.getPathData(_matrix && !mx.isIdentity()\n\t\t\t\t\t? _matrix.appended(mx) : _matrix, _precision));\n\t\t}\n\t\treturn paths.join('');\n\t}\n}, {\n\t_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {\n\t\treturn _hitTestChildren.base.call(this, point,\n\t\t\t\toptions.class === Path || options.type === 'path' ? options\n\t\t\t\t\t: Base.set({}, options, { fill: false }),\n\t\t\t\tviewMatrix);\n\t},\n\n\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\tvar children = this._children;\n\t\tif (!children.length)\n\t\t\treturn;\n\n\t\tparam = param.extend({ dontStart: true, dontFinish: true });\n\t\tctx.beginPath();\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tchildren[i].draw(ctx, param, strokeMatrix);\n\n\t\tif (!param.clip) {\n\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\tvar style = this._style;\n\t\t\tif (style.hasFill()) {\n\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (style.hasStroke())\n\t\t\t\tctx.stroke();\n\t\t}\n\t},\n\n\t_drawSelected: function(ctx, matrix, selectionItems) {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i],\n\t\t\t\tmx = child._matrix;\n\t\t\tif (!selectionItems[child._id]) {\n\t\t\t\tchild._drawSelected(ctx, mx.isIdentity() ? matrix\n\t\t\t\t\t\t: matrix.appended(mx));\n\t\t\t}\n\t\t}\n\t}\n},\nnew function() {\n\tfunction getCurrentPath(that, check) {\n\t\tvar children = that._children;\n\t\tif (check && !children.length)\n\t\t\tthrow new Error('Use a moveTo() command first');\n\t\treturn children[children.length - 1];\n\t}\n\n\treturn Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',\n\t\t\t'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',\n\t\t\t'arcBy'],\n\t\tfunction(key) {\n\t\t\tthis[key] = function() {\n\t\t\t\tvar path = getCurrentPath(this, true);\n\t\t\t\tpath[key].apply(path, arguments);\n\t\t\t};\n\t\t}, {\n\t\t\tmoveTo: function() {\n\t\t\t\tvar current = getCurrentPath(this),\n\t\t\t\t\tpath = current && current.isEmpty() ? current\n\t\t\t\t\t\t\t: new Path(Item.NO_INSERT);\n\t\t\t\tif (path !== current)\n\t\t\t\t\tthis.addChild(path);\n\t\t\t\tpath.moveTo.apply(path, arguments);\n\t\t\t},\n\n\t\t\tmoveBy: function() {\n\t\t\t\tvar current = getCurrentPath(this, true),\n\t\t\t\t\tlast = current && current.getLastSegment(),\n\t\t\t\t\tpoint = Point.read(arguments);\n\t\t\t\tthis.moveTo(last ? point.add(last._point) : point);\n\t\t\t},\n\n\t\t\tclosePath: function(tolerance) {\n\t\t\t\tgetCurrentPath(this, true).closePath(tolerance);\n\t\t\t}\n\t\t}\n\t);\n}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {\n\tthis[key] = function(param) {\n\t\tvar children = this._children,\n\t\t\tres;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tres = children[i][key](param) || res;\n\t\t}\n\t\treturn res;\n\t};\n}, {}));\n\nPathItem.inject(new function() {\n\tvar min = Math.min,\n\t\tmax = Math.max,\n\t\tabs = Math.abs,\n\t\toperators = {\n\t\t\tunite: { 1: true },\n\t\t\tintersect: { 2: true },\n\t\t\tsubtract: { 1: true },\n\t\t\texclude: { 1: true }\n\t\t};\n\n\tfunction preparePath(path, closed) {\n\t\tvar res = path.clone(false).reduce({ simplify: true })\n\t\t\t\t.transform(null, true, true);\n\t\tif (closed)\n\t\t\tres.setClosed(true);\n\t\treturn closed\n\t\t\t? res.resolveCrossings().reorient(res.getFillRule() === 'nonzero')\n\t\t\t: res;\n\t}\n\n\tfunction createResult(ctor, paths, reduce, path1, path2) {\n\t\tvar result = new ctor(Item.NO_INSERT);\n\t\tresult.addChildren(paths, true);\n\t\tif (reduce)\n\t\t\tresult = result.reduce({ simplify: true });\n\t\tresult.insertAbove(path2 && path1.isSibling(path2)\n\t\t\t\t&& path1.getIndex() < path2.getIndex() ? path2 : path1);\n\t\tresult.copyAttributes(path1, true);\n\t\treturn result;\n\t}\n\n\tfunction computeBoolean(path1, path2, operation) {\n\t\tvar operator = operators[operation];\n\t\toperator[operation] = true;\n\t\tif (!path1.isClosed())\n\t\t\treturn computeOpenBoolean(path1, path2, operator);\n\t\tvar _path1 = preparePath(path1, true),\n\t\t\t_path2 = path2 && path1 !== path2 && preparePath(path2, true);\n\t\tif (_path2 && (operator.subtract || operator.exclude)\n\t\t\t\t^ (_path2.isClockwise() ^ _path1.isClockwise()))\n\t\t\t_path2.reverse();\n\t\tvar crossings = divideLocations(\n\t\t\t\tCurveLocation.expand(_path1.getCrossings(_path2))),\n\t\t\tpaths1 = _path1._children || [_path1],\n\t\t\tpaths2 = _path2 && (_path2._children || [_path2]),\n\t\t\tsegments = [],\n\t\t\tcurves = [],\n\t\t\tpaths;\n\n\t\tif (!crossings.length) {\n\t\t\tvar ok = true;\n\t\t\tif (paths2) {\n\t\t\t\tfor (var i1 = 0, l1 = paths1.length; i1 < l1 && ok; i1++) {\n\t\t\t\t\tvar bounds1 = paths1[i1].getBounds();\n\t\t\t\t\tfor (var i2 = 0, l2 = paths2.length; i2 < l2 && ok; i2++) {\n\t\t\t\t\t\tvar bounds2 = paths2[i2].getBounds();\n\t\t\t\t\t\tok = !bounds1._containsRectangle(bounds2) &&\n\t\t\t\t\t\t\t !bounds2._containsRectangle(bounds1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (ok) {\n\t\t\t\tpaths = operator.unite || operator.exclude ? [_path1, _path2]\n\t\t\t\t\t\t: operator.subtract ? [_path1]\n\t\t\t\t\t\t: operator.intersect ? [new Path(Item.NO_INSERT)]\n\t\t\t\t\t\t: null;\n\t\t\t}\n\t\t}\n\n\t\tfunction collect(paths) {\n\t\t\tfor (var i = 0, l = paths.length; i < l; i++) {\n\t\t\t\tvar path = paths[i];\n\t\t\t\tsegments.push.apply(segments, path._segments);\n\t\t\t\tcurves.push.apply(curves, path.getCurves());\n\t\t\t\tpath._overlapsOnly = path._validOverlapsOnly = true;\n\t\t\t}\n\t\t}\n\n\t\tif (!paths) {\n\t\t\tcollect(paths1);\n\t\t\tif (paths2)\n\t\t\t\tcollect(paths2);\n\t\t\tfor (var i = 0, l = crossings.length; i < l; i++) {\n\t\t\t\tpropagateWinding(crossings[i]._segment, _path1, _path2, curves,\n\t\t\t\t\t\toperator);\n\t\t\t}\n\t\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\t\tvar segment = segments[i],\n\t\t\t\t\tinter = segment._intersection;\n\t\t\t\tif (segment._winding == null) {\n\t\t\t\t\tpropagateWinding(segment, _path1, _path2, curves, operator);\n\t\t\t\t}\n\t\t\t\tif (!(inter && inter._overlap)) {\n\t\t\t\t\tvar path = segment._path;\n\t\t\t\t\tpath._overlapsOnly = false;\n\t\t\t\t\tif (operator[segment._winding.winding])\n\t\t\t\t\t\tpath._validOverlapsOnly = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpaths = tracePaths(segments, operator);\n\t\t}\n\n\t\treturn createResult(CompoundPath, paths, true, path1, path2);\n\t}\n\n\tfunction computeOpenBoolean(path1, path2, operator) {\n\t\tif (!path2 || !operator.subtract && !operator.intersect) {\n\t\t\tthrow new Error('Boolean operations on open paths only support ' +\n\t\t\t\t\t'subtraction and intersection with another path.');\n\t\t}\n\t\tvar _path1 = preparePath(path1, false),\n\t\t\t_path2 = preparePath(path2, false),\n\t\t\tcrossings = _path1.getCrossings(_path2),\n\t\t\tsub = operator.subtract,\n\t\t\tpaths = [];\n\n\t\tfunction addPath(path) {\n\t\t\tif (_path2.contains(path.getPointAt(path.getLength() / 2)) ^ sub) {\n\t\t\t\tpaths.unshift(path);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = crossings.length - 1; i >= 0; i--) {\n\t\t\tvar path = crossings[i].split();\n\t\t\tif (path) {\n\t\t\t\tif (addPath(path))\n\t\t\t\t\tpath.getFirstSegment().setHandleIn(0, 0);\n\t\t\t\t_path1.getLastSegment().setHandleOut(0, 0);\n\t\t\t}\n\t\t}\n\t\taddPath(_path1);\n\t\treturn createResult(Group, paths, false, path1, path2);\n\t}\n\n\tfunction linkIntersections(from, to) {\n\t\tvar prev = from;\n\t\twhile (prev) {\n\t\t\tif (prev === to)\n\t\t\t\treturn;\n\t\t\tprev = prev._previous;\n\t\t}\n\t\twhile (from._next && from._next !== to)\n\t\t\tfrom = from._next;\n\t\tif (!from._next) {\n\t\t\twhile (to._previous)\n\t\t\t\tto = to._previous;\n\t\t\tfrom._next = to;\n\t\t\tto._previous = from;\n\t\t}\n\t}\n\n\tfunction divideLocations(locations, include) {\n\t\tvar results = include && [],\n\t\t\ttMin = 4e-7,\n\t\t\ttMax = 1 - tMin,\n\t\t\tnoHandles = false,\n\t\t\tclearCurves = [],\n\t\t\tprevCurve,\n\t\t\tprevTime;\n\n\t\tfor (var i = locations.length - 1; i >= 0; i--) {\n\t\t\tvar loc = locations[i];\n\t\t\tif (include) {\n\t\t\t\tif (!include(loc))\n\t\t\t\t\tcontinue;\n\t\t\t\tresults.unshift(loc);\n\t\t\t}\n\t\t\tvar curve = loc._curve,\n\t\t\t\ttime = loc._time,\n\t\t\t\torigTime = time,\n\t\t\t\tsegment;\n\t\t\tif (curve !== prevCurve) {\n\t\t\t\tnoHandles = !curve.hasHandles();\n\t\t\t} else if (prevTime >= tMin && prevTime <= tMax ) {\n\t\t\t\ttime /= prevTime;\n\t\t\t}\n\t\t\tif (time < tMin) {\n\t\t\t\tsegment = curve._segment1;\n\t\t\t} else if (time > tMax) {\n\t\t\t\tsegment = curve._segment2;\n\t\t\t} else {\n\t\t\t\tvar newCurve = curve.divideAtTime(time, true);\n\t\t\t\tif (noHandles)\n\t\t\t\t\tclearCurves.push(curve, newCurve);\n\t\t\t\tsegment = newCurve._segment1;\n\t\t\t}\n\t\t\tloc._setSegment(segment);\n\t\t\tvar inter = segment._intersection,\n\t\t\t\tdest = loc._intersection;\n\t\t\tif (inter) {\n\t\t\t\tlinkIntersections(inter, dest);\n\t\t\t\tvar other = inter;\n\t\t\t\twhile (other) {\n\t\t\t\t\tlinkIntersections(other._intersection, inter);\n\t\t\t\t\tother = other._next;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsegment._intersection = dest;\n\t\t\t}\n\t\t\tprevCurve = curve;\n\t\t\tprevTime = origTime;\n\t\t}\n\t\tfor (var i = 0, l = clearCurves.length; i < l; i++) {\n\t\t\tclearCurves[i].clearHandles();\n\t\t}\n\t\treturn results || locations;\n\t}\n\n\tfunction getWinding(point, curves, dir, dontFlip) {\n\t\tvar epsilon = 1e-8,\n\t\t\tia = dir ? 1 : 0,\n\t\t\tio = dir ? 0 : 1,\n\t\t\tpv = [point.x, point.y],\n\t\t\tpa = pv[ia],\n\t\t\tpo = pv[io],\n\t\t\tpaL = pa - epsilon,\n\t\t\tpaR = pa + epsilon,\n\t\t\twindingL = 0,\n\t\t\twindingR = 0,\n\t\t\tpathWindingL = 0,\n\t\t\tpathWindingR = 0,\n\t\t\tonPath = false,\n\t\t\tonPathWinding = 0,\n\t\t\tonPathCount = 0,\n\t\t\troots = [],\n\t\t\tvPrev,\n\t\t\tvClose;\n\n\t\tfunction addWinding(v) {\n\t\t\tvar o0 = v[io],\n\t\t\t\to3 = v[io + 6];\n\t\t\tif (po < min(o0, o3) || po > max(o0, o3)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar a0 = v[ia],\n\t\t\t\ta1 = v[ia + 2],\n\t\t\t\ta2 = v[ia + 4],\n\t\t\t\ta3 = v[ia + 6];\n\t\t\tif (o0 === o3) {\n\t\t\t\tif (a1 < paR && a3 > paL || a3 < paR && a1 > paL) {\n\t\t\t\t\tonPath = true;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar t = po === o0 ? 0\n\t\t\t\t\t: po === o3 ? 1\n\t\t\t\t\t: paL > max(a0, a1, a2, a3) || paR < min(a0, a1, a2, a3)\n\t\t\t\t\t? 0.5\n\t\t\t\t\t: Curve.solveCubic(v, io, po, roots, 0, 1) === 1\n\t\t\t\t\t\t? roots[0]\n\t\t\t\t\t\t: 0.5,\n\t\t\t\ta = t === 0 ? a0\n\t\t\t\t\t: t === 1 ? a3\n\t\t\t\t\t: Curve.getPoint(v, t)[dir ? 'y' : 'x'],\n\t\t\t\twinding = o0 > o3 ? 1 : -1,\n\t\t\t\twindingPrev = vPrev[io] > vPrev[io + 6] ? 1 : -1,\n\t\t\t\ta3Prev = vPrev[ia + 6];\n\t\t\tif (po !== o0) {\n\t\t\t\tif (a < paL) {\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t} else if (a > paR) {\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t} else {\n\t\t\t\t\tonPath = true;\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t}\n\t\t\t} else if (winding !== windingPrev) {\n\t\t\t\tif (a3Prev < paR) {\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t}\n\t\t\t\tif (a3Prev > paL) {\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t}\n\t\t\t} else if (a3Prev < paL && a > paL || a3Prev > paR && a < paR) {\n\t\t\t\tonPath = true;\n\t\t\t\tif (a3Prev < paL) {\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t} else if (a3Prev > paR) {\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvPrev = v;\n\t\t\treturn !dontFlip && a > paL && a < paR\n\t\t\t\t\t&& Curve.getTangent(v, t)[dir ? 'x' : 'y'] === 0\n\t\t\t\t\t&& getWinding(point, curves, dir ? 0 : 1, true);\n\t\t}\n\n\t\tfunction handleCurve(v) {\n\t\t\tvar o0 = v[io],\n\t\t\t\to1 = v[io + 2],\n\t\t\t\to2 = v[io + 4],\n\t\t\t\to3 = v[io + 6];\n\t\t\tif (po <= max(o0, o1, o2, o3) && po >= min(o0, o1, o2, o3)) {\n\t\t\t\tvar a0 = v[ia],\n\t\t\t\t\ta1 = v[ia + 2],\n\t\t\t\t\ta2 = v[ia + 4],\n\t\t\t\t\ta3 = v[ia + 6],\n\t\t\t\t\tmonoCurves = paL > max(a0, a1, a2, a3) ||\n\t\t\t\t\t\t\t\t paR < min(a0, a1, a2, a3)\n\t\t\t\t\t\t\t? [v] : Curve.getMonoCurves(v, dir),\n\t\t\t\t\tres;\n\t\t\t\tfor (var i = 0, l = monoCurves.length; i < l; i++) {\n\t\t\t\t\tif (res = addWinding(monoCurves[i]))\n\t\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar curve = curves[i],\n\t\t\t\tpath = curve._path,\n\t\t\t\tv = curve.getValues(),\n\t\t\t\tres;\n\t\t\tif (!i || curves[i - 1]._path !== path) {\n\t\t\t\tvPrev = null;\n\t\t\t\tif (!path._closed) {\n\t\t\t\t\tvar p1 = path.getLastCurve().getPoint2(),\n\t\t\t\t\t\tp2 = curve.getPoint1(),\n\t\t\t\t\t\tx1 = p1._x, y1 = p1._y,\n\t\t\t\t\t\tx2 = p2._x, y2 = p2._y;\n\t\t\t\t\tvClose = [x1, y1, x1, y1, x2, y2, x2, y2];\n\t\t\t\t\tif (vClose[io] !== vClose[io + 6]) {\n\t\t\t\t\t\tvPrev = vClose;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!vPrev) {\n\t\t\t\t\tvPrev = v;\n\t\t\t\t\tvar prev = path.getLastCurve();\n\t\t\t\t\twhile (prev && prev !== curve) {\n\t\t\t\t\t\tvar v2 = prev.getValues();\n\t\t\t\t\t\tif (v2[io] !== v2[io + 6]) {\n\t\t\t\t\t\t\tvPrev = v2;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprev = prev.getPrevious();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (res = handleCurve(v))\n\t\t\t\treturn res;\n\n\t\t\tif (i + 1 === l || curves[i + 1]._path !== path) {\n\t\t\t\tif (vClose && (res = handleCurve(vClose)))\n\t\t\t\t\treturn res;\n\t\t\t\tif (onPath && !pathWindingL && !pathWindingR) {\n\t\t\t\t\tvar add = path.isClockwise() ^ dir ? 1 : -1;\n\t\t\t\t\twindingL += add;\n\t\t\t\t\twindingR -= add;\n\t\t\t\t\tonPathWinding += add;\n\t\t\t\t} else {\n\t\t\t\t\twindingL += pathWindingL;\n\t\t\t\t\twindingR += pathWindingR;\n\t\t\t\t\tpathWindingL = pathWindingR = 0;\n\t\t\t\t}\n\t\t\t\tif (onPath)\n\t\t\t\t\tonPathCount++;\n\t\t\t\tonPath = false;\n\t\t\t\tvClose = null;\n\t\t\t}\n\t\t}\n\t\tif (!windingL && !windingR) {\n\t\t\twindingL = windingR = onPathWinding;\n\t\t}\n\t\twindingL = windingL && (2 - abs(windingL) % 2);\n\t\twindingR = windingR && (2 - abs(windingR) % 2);\n\t\treturn {\n\t\t\twinding: max(windingL, windingR),\n\t\t\twindingL: windingL,\n\t\t\twindingR: windingR,\n\t\t\tonContour: !windingL ^ !windingR,\n\t\t\tonPathCount: onPathCount\n\t\t};\n\t}\n\n\tfunction propagateWinding(segment, path1, path2, curves, operator) {\n\t\tvar chain = [],\n\t\t\tstart = segment,\n\t\t\ttotalLength = 0,\n\t\t\twinding;\n\t\tdo {\n\t\t\tvar curve = segment.getCurve(),\n\t\t\t\tlength = curve.getLength();\n\t\t\tchain.push({ segment: segment, curve: curve, length: length });\n\t\t\ttotalLength += length;\n\t\t\tsegment = segment.getNext();\n\t\t} while (segment && !segment._intersection && segment !== start);\n\t\tvar length = totalLength / 2;\n\t\tfor (var j = 0, l = chain.length; j < l; j++) {\n\t\t\tvar entry = chain[j],\n\t\t\t\tcurveLength = entry.length;\n\t\t\tif (length <= curveLength) {\n\t\t\t\tvar curve = entry.curve,\n\t\t\t\t\tpath = curve._path,\n\t\t\t\t\tparent = path._parent,\n\t\t\t\t\tt = curve.getTimeAt(length),\n\t\t\t\t\tpt = curve.getPointAtTime(t),\n\t\t\t\t\tdir = abs(curve.getTangentAtTime(t).normalize().y) < 0.5\n\t\t\t\t\t\t\t? 1 : 0;\n\t\t\t\tif (parent instanceof CompoundPath)\n\t\t\t\t\tpath = parent;\n\t\t\t\twinding = !(operator.subtract && path2 && (\n\t\t\t\t\t\tpath === path1 && path2._getWinding(pt, dir).winding ||\n\t\t\t\t\t\tpath === path2 && !path1._getWinding(pt, dir).winding))\n\t\t\t\t\t\t\t? getWinding(pt, curves, dir)\n\t\t\t\t\t\t\t: { winding: 0 };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlength -= curveLength;\n\t\t}\n\t\tfor (var j = chain.length - 1; j >= 0; j--) {\n\t\t\tchain[j].segment._winding = winding;\n\t\t}\n\t}\n\n\tfunction tracePaths(segments, operator) {\n\t\tvar paths = [],\n\t\t\tstart,\n\t\t\totherStart;\n\n\t\tfunction isValid(seg, excludeContour) {\n\t\t\tvar winding;\n\t\t\treturn !!(seg && !seg._visited && (!operator\n\t\t\t\t\t|| operator[(winding = seg._winding).winding]\n\t\t\t\t\t|| !excludeContour && operator.unite && winding.onContour));\n\t\t}\n\n\t\tfunction isStart(seg) {\n\t\t\treturn seg === start || seg === otherStart;\n\t\t}\n\n\t\tfunction visitPath(path) {\n\t\t\tvar segments = path._segments;\n\t\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\t\tsegments[i]._visited = true;\n\t\t\t}\n\t\t}\n\n\t\tfunction findBestIntersection(inter, exclude) {\n\t\t\tif (!inter._next)\n\t\t\t\treturn inter;\n\t\t\twhile (inter) {\n\t\t\t\tvar seg = inter._segment,\n\t\t\t\t\tnextSeg = seg.getNext(),\n\t\t\t\t\tnextInter = nextSeg && nextSeg._intersection;\n\t\t\t\tif (seg !== exclude && (isStart(seg) || isStart(nextSeg)\n\t\t\t\t\t|| nextSeg && !seg._visited && !nextSeg._visited\n\t\t\t\t\t&& (!operator || isValid(seg) && (isValid(nextSeg)\n\t\t\t\t\t\t|| nextInter && isValid(nextInter._segment)))\n\t\t\t\t\t))\n\t\t\t\t\treturn inter;\n\t\t\t\tinter = inter._next;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\tsegments.sort(function(seg1, seg2) {\n\t\t\tvar inter1 = seg1._intersection,\n\t\t\t\tinter2 = seg2._intersection,\n\t\t\t\tover1 = !!(inter1 && inter1._overlap),\n\t\t\t\tover2 = !!(inter2 && inter2._overlap),\n\t\t\t\tpath1 = seg1._path,\n\t\t\t\tpath2 = seg2._path;\n\t\t\treturn over1 ^ over2\n\t\t\t\t\t? over1 ? 1 : -1\n\t\t\t\t\t: inter1 ^ inter2\n\t\t\t\t\t\t? inter1 ? 1 : -1\n\t\t\t\t\t\t: path1 !== path2\n\t\t\t\t\t\t\t? path1._id - path2._id\n\t\t\t\t\t\t\t: seg1._index - seg2._index;\n\t\t});\n\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar path = null,\n\t\t\t\tfinished = false,\n\t\t\t\tseg = segments[i],\n\t\t\t\tinter = seg._intersection,\n\t\t\t\thandleIn;\n\t\t\tif (!seg._visited && seg._path._overlapsOnly) {\n\t\t\t\tvar path1 = seg._path,\n\t\t\t\t\tpath2 = inter._segment._path;\n\t\t\t\tif (path1.compare(path2)) {\n\t\t\t\t\tif ((operator.unite || operator.intersect)\n\t\t\t\t\t\t\t&& path1.getArea()) {\n\t\t\t\t\t\tpaths.push(path1.clone(false));\n\t\t\t\t\t}\n\t\t\t\t\tvisitPath(path1);\n\t\t\t\t\tvisitPath(path2);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isValid(seg, true))\n\t\t\t\tcontinue;\n\t\t\tstart = otherStart = null;\n\t\t\twhile (true) {\n\t\t\t\tinter = inter && findBestIntersection(inter, seg) || inter;\n\t\t\t\tvar other = inter && inter._segment;\n\t\t\t\tif (isStart(seg)) {\n\t\t\t\t\tfinished = true;\n\t\t\t\t} else if (other) {\n\t\t\t\t\tif (isStart(other)) {\n\t\t\t\t\t\tfinished = true;\n\t\t\t\t\t\tseg = other;\n\t\t\t\t\t} else if (isValid(other, isValid(seg, true))) {\n\t\t\t\t\t\tif (operator\n\t\t\t\t\t\t\t\t&& (operator.intersect || operator.subtract)) {\n\t\t\t\t\t\t\tseg._visited = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tseg = other;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (finished || seg._visited) {\n\t\t\t\t\tseg._visited = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (seg._path._validOverlapsOnly && !isValid(seg))\n\t\t\t\t\tbreak;\n\t\t\t\tif (!path) {\n\t\t\t\t\tpath = new Path(Item.NO_INSERT);\n\t\t\t\t\tstart = seg;\n\t\t\t\t\totherStart = other;\n\t\t\t\t}\n\t\t\t\tvar next = seg.getNext();\n\t\t\t\tpath.add(new Segment(seg._point, handleIn,\n\t\t\t\t\t\tnext && seg._handleOut));\n\t\t\t\tseg._visited = true;\n\t\t\t\tseg = next || seg._path.getFirstSegment();\n\t\t\t\thandleIn = next && next._handleIn;\n\t\t\t\tinter = seg._intersection;\n\t\t\t}\n\t\t\tif (finished) {\n\t\t\t\tpath.firstSegment.setHandleIn(handleIn);\n\t\t\t\tpath.setClosed(true);\n\t\t\t} else if (path) {\n\t\t\t\tvar area = path.getArea(true);\n\t\t\t\tif (abs(area) >= 1e-7) {\n\t\t\t\t\tconsole.error('Boolean operation resulted in open path',\n\t\t\t\t\t\t\t'segments =', path._segments.length,\n\t\t\t\t\t\t\t'length =', path.getLength(),\n\t\t\t\t\t\t\t'area=', area);\n\t\t\t\t}\n\t\t\t\tpath = null;\n\t\t\t}\n\t\t\tif (path && (path._segments.length > 8\n\t\t\t\t\t|| !Numerical.isZero(path.getArea()))) {\n\t\t\t\tpaths.push(path);\n\t\t\t\tpath = null;\n\t\t\t}\n\t\t}\n\t\treturn paths;\n\t}\n\n\treturn {\n\t\t_getWinding: function(point, dir) {\n\t\t\treturn getWinding(point, this.getCurves(), dir);\n\t\t},\n\n\t\tunite: function(path) {\n\t\t\treturn computeBoolean(this, path, 'unite');\n\t\t},\n\n\t\tintersect: function(path) {\n\t\t\treturn computeBoolean(this, path, 'intersect');\n\t\t},\n\n\t\tsubtract: function(path) {\n\t\t\treturn computeBoolean(this, path, 'subtract');\n\t\t},\n\n\t\texclude: function(path) {\n\t\t\treturn computeBoolean(this, path, 'exclude');\n\t\t},\n\n\t\tdivide: function(path) {\n\t\t\treturn createResult(Group, [this.subtract(path),\n\t\t\t\t\tthis.intersect(path)], true, this, path);\n\t\t},\n\n\t\tresolveCrossings: function() {\n\t\t\tvar children = this._children,\n\t\t\t\tpaths = children || [this];\n\n\t\t\tfunction hasOverlap(seg) {\n\t\t\t\tvar inter = seg && seg._intersection;\n\t\t\t\treturn inter && inter._overlap;\n\t\t\t}\n\n\t\t\tvar hasOverlaps = false,\n\t\t\t\thasCrossings = false,\n\t\t\t\tintersections = this.getIntersections(null, function(inter) {\n\t\t\t\t\treturn inter._overlap && (hasOverlaps = true) ||\n\t\t\t\t\t\t\tinter.isCrossing() && (hasCrossings = true);\n\t\t\t\t});\n\t\t\tintersections = CurveLocation.expand(intersections);\n\t\t\tif (hasOverlaps) {\n\t\t\t\tvar overlaps = divideLocations(intersections, function(inter) {\n\t\t\t\t\treturn inter._overlap;\n\t\t\t\t});\n\t\t\t\tfor (var i = overlaps.length - 1; i >= 0; i--) {\n\t\t\t\t\tvar seg = overlaps[i]._segment,\n\t\t\t\t\t\tprev = seg.getPrevious(),\n\t\t\t\t\t\tnext = seg.getNext();\n\t\t\t\t\tif (seg._path && hasOverlap(prev) && hasOverlap(next)) {\n\t\t\t\t\t\tseg.remove();\n\t\t\t\t\t\tprev._handleOut._set(0, 0);\n\t\t\t\t\t\tnext._handleIn._set(0, 0);\n\t\t\t\t\t\tvar curve = prev.getCurve();\n\t\t\t\t\t\tif (curve.isStraight() && curve.getLength() === 0) {\n\t\t\t\t\t\t\tnext._handleIn.set(prev._handleIn);\n\t\t\t\t\t\t\tprev.remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hasCrossings) {\n\t\t\t\tdivideLocations(intersections, hasOverlaps && function(inter) {\n\t\t\t\t\tvar curve1 = inter.getCurve(),\n\t\t\t\t\t\tcurve2 = inter._intersection._curve,\n\t\t\t\t\t\tseg = inter._segment;\n\t\t\t\t\tif (curve1 && curve2 && curve1._path && curve2._path) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else if (seg) {\n\t\t\t\t\t\tseg._intersection = null;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tpaths = tracePaths(Base.each(paths, function(path) {\n\t\t\t\t\tthis.push.apply(this, path._segments);\n\t\t\t\t}, []));\n\t\t\t}\n\t\t\tvar length = paths.length,\n\t\t\t\titem;\n\t\t\tif (length > 1 && children) {\n\t\t\t\tif (paths !== children)\n\t\t\t\t\tthis.setChildren(paths);\n\t\t\t\titem = this;\n\t\t\t} else if (length === 1 && !children) {\n\t\t\t\tif (paths[0] !== this)\n\t\t\t\t\tthis.setSegments(paths[0].removeSegments());\n\t\t\t\titem = this;\n\t\t\t}\n\t\t\tif (!item) {\n\t\t\t\titem = new CompoundPath(Item.NO_INSERT);\n\t\t\t\titem.addChildren(paths);\n\t\t\t\titem = item.reduce();\n\t\t\t\titem.copyAttributes(this);\n\t\t\t\tthis.replaceWith(item);\n\t\t\t}\n\t\t\treturn item;\n\t\t},\n\n\t\treorient: function(nonZero) {\n\t\t\tvar children = this._children,\n\t\t\t\tlength = children && children.length;\n\t\t\tif (length > 1) {\n\t\t\t\tvar lookup = Base.each(children, function(path, i) {\n\t\t\t\t\t\tthis[path._id] = {\n\t\t\t\t\t\t\twinding: path.isClockwise() ? 1 : -1,\n\t\t\t\t\t\t\tindex: i\n\t\t\t\t\t\t};\n\t\t\t\t\t}, {}),\n\t\t\t\t\tsorted = this.removeChildren().sort(function (a, b) {\n\t\t\t\t\t\treturn abs(b.getArea()) - abs(a.getArea());\n\t\t\t\t\t}),\n\t\t\t\t\tfirst = sorted[0],\n\t\t\t\t\tpaths = [];\n\t\t\t\tpaths[lookup[first._id].index] = first;\n\t\t\t\tfor (var i1 = 1; i1 < length; i1++) {\n\t\t\t\t\tvar path1 = sorted[i1],\n\t\t\t\t\t\tentry1 = lookup[path1._id],\n\t\t\t\t\t\tpoint = path1.getInteriorPoint(),\n\t\t\t\t\t\tisContained = false,\n\t\t\t\t\t\tcontainer = null,\n\t\t\t\t\t\texclude = false;\n\t\t\t\t\tfor (var i2 = i1 - 1; i2 >= 0 && !container; i2--) {\n\t\t\t\t\t\tvar path2 = sorted[i2];\n\t\t\t\t\t\tif (path2.contains(point)) {\n\t\t\t\t\t\t\tvar entry2 = lookup[path2._id];\n\t\t\t\t\t\t\tif (nonZero && !isContained) {\n\t\t\t\t\t\t\t\tentry1.winding += entry2.winding;\n\t\t\t\t\t\t\t\tif (entry1.winding && entry2.winding) {\n\t\t\t\t\t\t\t\t\texclude = entry1.exclude = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tisContained = true;\n\t\t\t\t\t\t\tcontainer = !entry2.exclude && path2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!exclude) {\n\t\t\t\t\t\tpath1.setClockwise(container\n\t\t\t\t\t\t\t\t? !container.isClockwise()\n\t\t\t\t\t\t\t\t: first.isClockwise());\n\t\t\t\t\t\tpaths[entry1.index] = path1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.setChildren(paths);\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tgetInteriorPoint: function() {\n\t\t\tvar bounds = this.getBounds(),\n\t\t\t\tpoint = bounds.getCenter(true);\n\t\t\tif (!this.contains(point)) {\n\t\t\t\tvar curves = this.getCurves(),\n\t\t\t\t\ty = point.y,\n\t\t\t\t\tintercepts = [],\n\t\t\t\t\troots = [];\n\t\t\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\t\t\tvar v = curves[i].getValues(),\n\t\t\t\t\t\to0 = v[1],\n\t\t\t\t\t\to1 = v[3],\n\t\t\t\t\t\to2 = v[5],\n\t\t\t\t\t\to3 = v[7];\n\t\t\t\t\tif (y >= min(o0, o1, o2, o3) && y <= max(o0, o1, o2, o3)) {\n\t\t\t\t\t\tvar monoCurves = Curve.getMonoCurves(v);\n\t\t\t\t\t\tfor (var j = 0, m = monoCurves.length; j < m; j++) {\n\t\t\t\t\t\t\tvar mv = monoCurves[j],\n\t\t\t\t\t\t\t\tmo0 = mv[1],\n\t\t\t\t\t\t\t\tmo3 = mv[7];\n\t\t\t\t\t\t\tif ((mo0 !== mo3) &&\n\t\t\t\t\t\t\t\t(y >= mo0 && y <= mo3 || y >= mo3 && y <= mo0)){\n\t\t\t\t\t\t\t\tvar x = y === mo0 ? mv[0]\n\t\t\t\t\t\t\t\t\t: y === mo3 ? mv[6]\n\t\t\t\t\t\t\t\t\t: Curve.solveCubic(mv, 1, y, roots, 0, 1)\n\t\t\t\t\t\t\t\t\t\t=== 1\n\t\t\t\t\t\t\t\t\t\t? Curve.getPoint(mv, roots[0]).x\n\t\t\t\t\t\t\t\t\t\t: (mv[0] + mv[6]) / 2;\n\t\t\t\t\t\t\t\tintercepts.push(x);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (intercepts.length > 1) {\n\t\t\t\t\tintercepts.sort(function(a, b) { return a - b; });\n\t\t\t\t\tpoint.x = (intercepts[0] + intercepts[1]) / 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn point;\n\t\t}\n\t};\n});\n\nvar PathIterator = Base.extend({\n\t_class: 'PathIterator',\n\n\tinitialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) {\n\t\tvar curves = [],\n\t\t\tparts = [],\n\t\t\tlength = 0,\n\t\t\tminSpan = 1 / (maxRecursion || 32),\n\t\t\tsegments = path._segments,\n\t\t\tsegment1 = segments[0],\n\t\t\tsegment2;\n\n\t\tfunction addCurve(segment1, segment2) {\n\t\t\tvar curve = Curve.getValues(segment1, segment2, matrix);\n\t\t\tcurves.push(curve);\n\t\t\tcomputeParts(curve, segment1._index, 0, 1);\n\t\t}\n\n\t\tfunction computeParts(curve, index, t1, t2) {\n\t\t\tif ((t2 - t1) > minSpan\n\t\t\t\t\t&& !(ignoreStraight && Curve.isStraight(curve))\n\t\t\t\t\t&& !Curve.isFlatEnough(curve, flatness || 0.25)) {\n\t\t\t\tvar halves = Curve.subdivide(curve, 0.5),\n\t\t\t\t\ttMid = (t1 + t2) / 2;\n\t\t\t\tcomputeParts(halves[0], index, t1, tMid);\n\t\t\t\tcomputeParts(halves[1], index, tMid, t2);\n\t\t\t} else {\n\t\t\t\tvar dx = curve[6] - curve[0],\n\t\t\t\t\tdy = curve[7] - curve[1],\n\t\t\t\t\tdist = Math.sqrt(dx * dx + dy * dy);\n\t\t\t\tif (dist > 0) {\n\t\t\t\t\tlength += dist;\n\t\t\t\t\tparts.push({\n\t\t\t\t\t\toffset: length,\n\t\t\t\t\t\tcurve: curve,\n\t\t\t\t\t\tindex: index,\n\t\t\t\t\t\ttime: t2,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 1, l = segments.length; i < l; i++) {\n\t\t\tsegment2 = segments[i];\n\t\t\taddCurve(segment1, segment2);\n\t\t\tsegment1 = segment2;\n\t\t}\n\t\tif (path._closed)\n\t\t\taddCurve(segment2, segments[0]);\n\t\tthis.curves = curves;\n\t\tthis.parts = parts;\n\t\tthis.length = length;\n\t\tthis.index = 0;\n\t},\n\n\t_get: function(offset) {\n\t\tvar parts = this.parts,\n\t\t\tlength = parts.length,\n\t\t\tstart,\n\t\t\ti, j = this.index;\n\t\tfor (;;) {\n\t\t\ti = j;\n\t\t\tif (!j || parts[--j].offset < offset)\n\t\t\t\tbreak;\n\t\t}\n\t\tfor (; i < length; i++) {\n\t\t\tvar part = parts[i];\n\t\t\tif (part.offset >= offset) {\n\t\t\t\tthis.index = i;\n\t\t\t\tvar prev = parts[i - 1],\n\t\t\t\t\tprevTime = prev && prev.index === part.index ? prev.time : 0,\n\t\t\t\t\tprevOffset = prev ? prev.offset : 0;\n\t\t\t\treturn {\n\t\t\t\t\tindex: part.index,\n\t\t\t\t\ttime: prevTime + (part.time - prevTime)\n\t\t\t\t\t\t* (offset - prevOffset) / (part.offset - prevOffset)\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tindex: parts[length - 1].index,\n\t\t\ttime: 1\n\t\t};\n\t},\n\n\tdrawPart: function(ctx, from, to) {\n\t\tvar start = this._get(from),\n\t\t\tend = this._get(to);\n\t\tfor (var i = start.index, l = end.index; i <= l; i++) {\n\t\t\tvar curve = Curve.getPart(this.curves[i],\n\t\t\t\t\ti === start.index ? start.time : 0,\n\t\t\t\t\ti === end.index ? end.time : 1);\n\t\t\tif (i === start.index)\n\t\t\t\tctx.moveTo(curve[0], curve[1]);\n\t\t\tctx.bezierCurveTo.apply(ctx, curve.slice(2));\n\t\t}\n\t}\n}, Base.each(Curve._evaluateMethods,\n\tfunction(name) {\n\t\tthis[name + 'At'] = function(offset) {\n\t\t\tvar param = this._get(offset);\n\t\t\treturn Curve[name](this.curves[param.index], param.time);\n\t\t};\n\t}, {})\n);\n\nvar PathFitter = Base.extend({\n\tinitialize: function(path) {\n\t\tvar points = this.points = [],\n\t\t\tsegments = path._segments,\n\t\t\tclosed = path._closed;\n\t\tfor (var i = 0, prev, l = segments.length; i < l; i++) {\n\t\t\tvar point = segments[i].point;\n\t\t\tif (!prev || !prev.equals(point)) {\n\t\t\t\tpoints.push(prev = point.clone());\n\t\t\t}\n\t\t}\n\t\tif (closed) {\n\t\t\tpoints.unshift(points[points.length - 1]);\n\t\t\tpoints.push(points[1]);\n\t\t}\n\t\tthis.closed = closed;\n\t},\n\n\tfit: function(error) {\n\t\tvar points = this.points,\n\t\t\tlength = points.length,\n\t\t\tsegments = null;\n\t\tif (length > 0) {\n\t\t\tsegments = [new Segment(points[0])];\n\t\t\tif (length > 1) {\n\t\t\t\tthis.fitCubic(segments, error, 0, length - 1,\n\t\t\t\t\t\tpoints[1].subtract(points[0]),\n\t\t\t\t\t\tpoints[length - 2].subtract(points[length - 1]));\n\t\t\t\tif (this.closed) {\n\t\t\t\t\tsegments.shift();\n\t\t\t\t\tsegments.pop();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn segments;\n\t},\n\n\tfitCubic: function(segments, error, first, last, tan1, tan2) {\n\t\tvar points = this.points;\n\t\tif (last - first === 1) {\n\t\t\tvar pt1 = points[first],\n\t\t\t\tpt2 = points[last],\n\t\t\t\tdist = pt1.getDistance(pt2) / 3;\n\t\t\tthis.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),\n\t\t\t\t\tpt2.add(tan2.normalize(dist)), pt2]);\n\t\t\treturn;\n\t\t}\n\t\tvar uPrime = this.chordLengthParameterize(first, last),\n\t\t\tmaxError = Math.max(error, error * error),\n\t\t\tsplit,\n\t\t\tparametersInOrder = true;\n\t\tfor (var i = 0; i <= 4; i++) {\n\t\t\tvar curve = this.generateBezier(first, last, uPrime, tan1, tan2);\n\t\t\tvar max = this.findMaxError(first, last, curve, uPrime);\n\t\t\tif (max.error < error && parametersInOrder) {\n\t\t\t\tthis.addCurve(segments, curve);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsplit = max.index;\n\t\t\tif (max.error >= maxError)\n\t\t\t\tbreak;\n\t\t\tparametersInOrder = this.reparameterize(first, last, uPrime, curve);\n\t\t\tmaxError = max.error;\n\t\t}\n\t\tvar tanCenter = points[split - 1].subtract(points[split + 1]);\n\t\tthis.fitCubic(segments, error, first, split, tan1, tanCenter);\n\t\tthis.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);\n\t},\n\n\taddCurve: function(segments, curve) {\n\t\tvar prev = segments[segments.length - 1];\n\t\tprev.setHandleOut(curve[1].subtract(curve[0]));\n\t\tsegments.push(new Segment(curve[3], curve[2].subtract(curve[3])));\n\t},\n\n\tgenerateBezier: function(first, last, uPrime, tan1, tan2) {\n\t\tvar epsilon = 1e-12,\n\t\t\tabs = Math.abs,\n\t\t\tpoints = this.points,\n\t\t\tpt1 = points[first],\n\t\t\tpt2 = points[last],\n\t\t\tC = [[0, 0], [0, 0]],\n\t\t\tX = [0, 0];\n\n\t\tfor (var i = 0, l = last - first + 1; i < l; i++) {\n\t\t\tvar u = uPrime[i],\n\t\t\t\tt = 1 - u,\n\t\t\t\tb = 3 * u * t,\n\t\t\t\tb0 = t * t * t,\n\t\t\t\tb1 = b * t,\n\t\t\t\tb2 = b * u,\n\t\t\t\tb3 = u * u * u,\n\t\t\t\ta1 = tan1.normalize(b1),\n\t\t\t\ta2 = tan2.normalize(b2),\n\t\t\t\ttmp = points[first + i]\n\t\t\t\t\t.subtract(pt1.multiply(b0 + b1))\n\t\t\t\t\t.subtract(pt2.multiply(b2 + b3));\n\t\t\tC[0][0] += a1.dot(a1);\n\t\t\tC[0][1] += a1.dot(a2);\n\t\t\tC[1][0] = C[0][1];\n\t\t\tC[1][1] += a2.dot(a2);\n\t\t\tX[0] += a1.dot(tmp);\n\t\t\tX[1] += a2.dot(tmp);\n\t\t}\n\n\t\tvar detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],\n\t\t\talpha1, alpha2;\n\t\tif (abs(detC0C1) > epsilon) {\n\t\t\tvar detC0X = C[0][0] * X[1] - C[1][0] * X[0],\n\t\t\t\tdetXC1 = X[0] * C[1][1] - X[1] * C[0][1];\n\t\t\talpha1 = detXC1 / detC0C1;\n\t\t\talpha2 = detC0X / detC0C1;\n\t\t} else {\n\t\t\tvar c0 = C[0][0] + C[0][1],\n\t\t\t\tc1 = C[1][0] + C[1][1];\n\t\t\tif (abs(c0) > epsilon) {\n\t\t\t\talpha1 = alpha2 = X[0] / c0;\n\t\t\t} else if (abs(c1) > epsilon) {\n\t\t\t\talpha1 = alpha2 = X[1] / c1;\n\t\t\t} else {\n\t\t\t\talpha1 = alpha2 = 0;\n\t\t\t}\n\t\t}\n\n\t\tvar segLength = pt2.getDistance(pt1),\n\t\t\teps = epsilon * segLength,\n\t\t\thandle1,\n\t\t\thandle2;\n\t\tif (alpha1 < eps || alpha2 < eps) {\n\t\t\talpha1 = alpha2 = segLength / 3;\n\t\t} else {\n\t\t\tvar line = pt2.subtract(pt1);\n\t\t\thandle1 = tan1.normalize(alpha1);\n\t\t\thandle2 = tan2.normalize(alpha2);\n\t\t\tif (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {\n\t\t\t\talpha1 = alpha2 = segLength / 3;\n\t\t\t\thandle1 = handle2 = null;\n\t\t\t}\n\t\t}\n\n\t\treturn [pt1,\n\t\t\t\tpt1.add(handle1 || tan1.normalize(alpha1)),\n\t\t\t\tpt2.add(handle2 || tan2.normalize(alpha2)),\n\t\t\t\tpt2];\n\t},\n\n\treparameterize: function(first, last, u, curve) {\n\t\tfor (var i = first; i <= last; i++) {\n\t\t\tu[i - first] = this.findRoot(curve, this.points[i], u[i - first]);\n\t\t}\n\t\tfor (var i = 1, l = u.length; i < l; i++) {\n\t\t\tif (u[i] <= u[i - 1])\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tfindRoot: function(curve, point, u) {\n\t\tvar curve1 = [],\n\t\t\tcurve2 = [];\n\t\tfor (var i = 0; i <= 2; i++) {\n\t\t\tcurve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);\n\t\t}\n\t\tfor (var i = 0; i <= 1; i++) {\n\t\t\tcurve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);\n\t\t}\n\t\tvar pt = this.evaluate(3, curve, u),\n\t\t\tpt1 = this.evaluate(2, curve1, u),\n\t\t\tpt2 = this.evaluate(1, curve2, u),\n\t\t\tdiff = pt.subtract(point),\n\t\t\tdf = pt1.dot(pt1) + diff.dot(pt2);\n\t\tif (Math.abs(df) < 1e-6)\n\t\t\treturn u;\n\t\treturn u - diff.dot(pt1) / df;\n\t},\n\n\tevaluate: function(degree, curve, t) {\n\t\tvar tmp = curve.slice();\n\t\tfor (var i = 1; i <= degree; i++) {\n\t\t\tfor (var j = 0; j <= degree - i; j++) {\n\t\t\t\ttmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));\n\t\t\t}\n\t\t}\n\t\treturn tmp[0];\n\t},\n\n\tchordLengthParameterize: function(first, last) {\n\t\tvar u = [0];\n\t\tfor (var i = first + 1; i <= last; i++) {\n\t\t\tu[i - first] = u[i - first - 1]\n\t\t\t\t\t+ this.points[i].getDistance(this.points[i - 1]);\n\t\t}\n\t\tfor (var i = 1, m = last - first; i <= m; i++) {\n\t\t\tu[i] /= u[m];\n\t\t}\n\t\treturn u;\n\t},\n\n\tfindMaxError: function(first, last, curve, u) {\n\t\tvar index = Math.floor((last - first + 1) / 2),\n\t\t\tmaxDist = 0;\n\t\tfor (var i = first + 1; i < last; i++) {\n\t\t\tvar P = this.evaluate(3, curve, u[i - first]);\n\t\t\tvar v = P.subtract(this.points[i]);\n\t\t\tvar dist = v.x * v.x + v.y * v.y;\n\t\t\tif (dist >= maxDist) {\n\t\t\t\tmaxDist = dist;\n\t\t\t\tindex = i;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\terror: maxDist,\n\t\t\tindex: index\n\t\t};\n\t}\n});\n\nvar TextItem = Item.extend({\n\t_class: 'TextItem',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_serializeFields: {\n\t\tcontent: null\n\t},\n\t_boundsOptions: { stroke: false, handle: false },\n\n\tinitialize: function TextItem(arg) {\n\t\tthis._content = '';\n\t\tthis._lines = [];\n\t\tvar hasProps = arg && Base.isPlainObject(arg)\n\t\t\t\t&& arg.x === undefined && arg.y === undefined;\n\t\tthis._initialize(hasProps && arg, !hasProps && Point.read(arguments));\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._content === item._content;\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setContent(source._content);\n\t},\n\n\tgetContent: function() {\n\t\treturn this._content;\n\t},\n\n\tsetContent: function(content) {\n\t\tthis._content = '' + content;\n\t\tthis._lines = this._content.split(/\\r\\n|\\n|\\r/mg);\n\t\tthis._changed(265);\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._content;\n\t},\n\n\tgetCharacterStyle: '#getStyle',\n\tsetCharacterStyle: '#setStyle',\n\n\tgetParagraphStyle: '#getStyle',\n\tsetParagraphStyle: '#setStyle'\n});\n\nvar PointText = TextItem.extend({\n\t_class: 'PointText',\n\n\tinitialize: function PointText() {\n\t\tTextItem.apply(this, arguments);\n\t},\n\n\tgetPoint: function() {\n\t\tvar point = this._matrix.getTranslation();\n\t\treturn new LinkedPoint(point.x, point.y, this, 'setPoint');\n\t},\n\n\tsetPoint: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.translate(point.subtract(this._matrix.getTranslation()));\n\t},\n\n\t_draw: function(ctx, param, viewMatrix) {\n\t\tif (!this._content)\n\t\t\treturn;\n\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\tvar lines = this._lines,\n\t\t\tstyle = this._style,\n\t\t\thasFill = style.hasFill(),\n\t\t\thasStroke = style.hasStroke(),\n\t\t\tleading = style.getLeading(),\n\t\t\tshadowColor = ctx.shadowColor;\n\t\tctx.font = style.getFontStyle();\n\t\tctx.textAlign = style.getJustification();\n\t\tfor (var i = 0, l = lines.length; i < l; i++) {\n\t\t\tctx.shadowColor = shadowColor;\n\t\t\tvar line = lines[i];\n\t\t\tif (hasFill) {\n\t\t\t\tctx.fillText(line, 0, 0);\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (hasStroke)\n\t\t\t\tctx.strokeText(line, 0, 0);\n\t\t\tctx.translate(0, leading);\n\t\t}\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar style = this._style,\n\t\t\tlines = this._lines,\n\t\t\tnumLines = lines.length,\n\t\t\tjustification = style.getJustification(),\n\t\t\tleading = style.getLeading(),\n\t\t\twidth = this.getView().getTextWidth(style.getFontStyle(), lines),\n\t\t\tx = 0;\n\t\tif (justification !== 'left')\n\t\t\tx -= width / (justification === 'center' ? 2: 1);\n\t\tvar bounds = new Rectangle(x,\n\t\t\t\t\tnumLines ? - 0.75 * leading : 0,\n\t\t\t\t\twidth, numLines * leading);\n\t\treturn matrix ? matrix._transformBounds(bounds, bounds) : bounds;\n\t}\n});\n\nvar Color = Base.extend(new function() {\n\tvar types = {\n\t\tgray: ['gray'],\n\t\trgb: ['red', 'green', 'blue'],\n\t\thsb: ['hue', 'saturation', 'brightness'],\n\t\thsl: ['hue', 'saturation', 'lightness'],\n\t\tgradient: ['gradient', 'origin', 'destination', 'highlight']\n\t};\n\n\tvar componentParsers = {},\n\t\tcolorCache = {},\n\t\tcolorCtx;\n\n\tfunction fromCSS(string) {\n\t\tvar match = string.match(/^#(\\w{1,2})(\\w{1,2})(\\w{1,2})$/),\n\t\t\tcomponents;\n\t\tif (match) {\n\t\t\tcomponents = [0, 0, 0];\n\t\t\tfor (var i = 0; i < 3; i++) {\n\t\t\t\tvar value = match[i + 1];\n\t\t\t\tcomponents[i] = parseInt(value.length == 1\n\t\t\t\t\t\t? value + value : value, 16) / 255;\n\t\t\t}\n\t\t} else if (match = string.match(/^rgba?\\((.*)\\)$/)) {\n\t\t\tcomponents = match[1].split(',');\n\t\t\tfor (var i = 0, l = components.length; i < l; i++) {\n\t\t\t\tvar value = +components[i];\n\t\t\t\tcomponents[i] = i < 3 ? value / 255 : value;\n\t\t\t}\n\t\t} else if (window) {\n\t\t\tvar cached = colorCache[string];\n\t\t\tif (!cached) {\n\t\t\t\tif (!colorCtx) {\n\t\t\t\t\tcolorCtx = CanvasProvider.getContext(1, 1);\n\t\t\t\t\tcolorCtx.globalCompositeOperation = 'copy';\n\t\t\t\t}\n\t\t\t\tcolorCtx.fillStyle = 'rgba(0,0,0,0)';\n\t\t\t\tcolorCtx.fillStyle = string;\n\t\t\t\tcolorCtx.fillRect(0, 0, 1, 1);\n\t\t\t\tvar data = colorCtx.getImageData(0, 0, 1, 1).data;\n\t\t\t\tcached = colorCache[string] = [\n\t\t\t\t\tdata[0] / 255,\n\t\t\t\t\tdata[1] / 255,\n\t\t\t\t\tdata[2] / 255\n\t\t\t\t];\n\t\t\t}\n\t\t\tcomponents = cached.slice();\n\t\t} else {\n\t\t\tcomponents = [0, 0, 0];\n\t\t}\n\t\treturn components;\n\t}\n\n\tvar hsbIndices = [\n\t\t[0, 3, 1],\n\t\t[2, 0, 1],\n\t\t[1, 0, 3],\n\t\t[1, 2, 0],\n\t\t[3, 1, 0],\n\t\t[0, 1, 2]\n\t];\n\n\tvar converters = {\n\t\t'rgb-hsb': function(r, g, b) {\n\t\t\tvar max = Math.max(r, g, b),\n\t\t\t\tmin = Math.min(r, g, b),\n\t\t\t\tdelta = max - min,\n\t\t\t\th = delta === 0 ? 0\n\t\t\t\t\t: ( max == r ? (g - b) / delta + (g < b ? 6 : 0)\n\t\t\t\t\t\t: max == g ? (b - r) / delta + 2\n\t\t\t\t\t\t: (r - g) / delta + 4) * 60;\n\t\t\treturn [h, max === 0 ? 0 : delta / max, max];\n\t\t},\n\n\t\t'hsb-rgb': function(h, s, b) {\n\t\t\th = (((h / 60) % 6) + 6) % 6;\n\t\t\tvar i = Math.floor(h),\n\t\t\t\tf = h - i,\n\t\t\t\ti = hsbIndices[i],\n\t\t\t\tv = [\n\t\t\t\t\tb,\n\t\t\t\t\tb * (1 - s),\n\t\t\t\t\tb * (1 - s * f),\n\t\t\t\t\tb * (1 - s * (1 - f))\n\t\t\t\t];\n\t\t\treturn [v[i[0]], v[i[1]], v[i[2]]];\n\t\t},\n\n\t\t'rgb-hsl': function(r, g, b) {\n\t\t\tvar max = Math.max(r, g, b),\n\t\t\t\tmin = Math.min(r, g, b),\n\t\t\t\tdelta = max - min,\n\t\t\t\tachromatic = delta === 0,\n\t\t\t\th = achromatic ? 0\n\t\t\t\t\t: ( max == r ? (g - b) / delta + (g < b ? 6 : 0)\n\t\t\t\t\t\t: max == g ? (b - r) / delta + 2\n\t\t\t\t\t\t: (r - g) / delta + 4) * 60,\n\t\t\t\tl = (max + min) / 2,\n\t\t\t\ts = achromatic ? 0 : l < 0.5\n\t\t\t\t\t\t? delta / (max + min)\n\t\t\t\t\t\t: delta / (2 - max - min);\n\t\t\treturn [h, s, l];\n\t\t},\n\n\t\t'hsl-rgb': function(h, s, l) {\n\t\t\th = (((h / 360) % 1) + 1) % 1;\n\t\t\tif (s === 0)\n\t\t\t\treturn [l, l, l];\n\t\t\tvar t3s = [ h + 1 / 3, h, h - 1 / 3 ],\n\t\t\t\tt2 = l < 0.5 ? l * (1 + s) : l + s - l * s,\n\t\t\t\tt1 = 2 * l - t2,\n\t\t\t\tc = [];\n\t\t\tfor (var i = 0; i < 3; i++) {\n\t\t\t\tvar t3 = t3s[i];\n\t\t\t\tif (t3 < 0) t3 += 1;\n\t\t\t\tif (t3 > 1) t3 -= 1;\n\t\t\t\tc[i] = 6 * t3 < 1\n\t\t\t\t\t? t1 + (t2 - t1) * 6 * t3\n\t\t\t\t\t: 2 * t3 < 1\n\t\t\t\t\t\t? t2\n\t\t\t\t\t\t: 3 * t3 < 2\n\t\t\t\t\t\t\t? t1 + (t2 - t1) * ((2 / 3) - t3) * 6\n\t\t\t\t\t\t\t: t1;\n\t\t\t}\n\t\t\treturn c;\n\t\t},\n\n\t\t'rgb-gray': function(r, g, b) {\n\t\t\treturn [r * 0.2989 + g * 0.587 + b * 0.114];\n\t\t},\n\n\t\t'gray-rgb': function(g) {\n\t\t\treturn [g, g, g];\n\t\t},\n\n\t\t'gray-hsb': function(g) {\n\t\t\treturn [0, 0, g];\n\t\t},\n\n\t\t'gray-hsl': function(g) {\n\t\t\treturn [0, 0, g];\n\t\t},\n\n\t\t'gradient-rgb': function() {\n\t\t\treturn [];\n\t\t},\n\n\t\t'rgb-gradient': function() {\n\t\t\treturn [];\n\t\t}\n\n\t};\n\n\treturn Base.each(types, function(properties, type) {\n\t\tcomponentParsers[type] = [];\n\t\tBase.each(properties, function(name, index) {\n\t\t\tvar part = Base.capitalize(name),\n\t\t\t\thasOverlap = /^(hue|saturation)$/.test(name),\n\t\t\t\tparser = componentParsers[type][index] = name === 'gradient'\n\t\t\t\t\t? function(value) {\n\t\t\t\t\t\tvar current = this._components[0];\n\t\t\t\t\t\tvalue = Gradient.read(Array.isArray(value) ? value\n\t\t\t\t\t\t\t\t: arguments, 0, { readNull: true });\n\t\t\t\t\t\tif (current !== value) {\n\t\t\t\t\t\t\tif (current)\n\t\t\t\t\t\t\t\tcurrent._removeOwner(this);\n\t\t\t\t\t\t\tif (value)\n\t\t\t\t\t\t\t\tvalue._addOwner(this);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t\t: type === 'gradient'\n\t\t\t\t\t\t? function() {\n\t\t\t\t\t\t\treturn Point.read(arguments, 0, {\n\t\t\t\t\t\t\t\t\treadNull: name === 'highlight',\n\t\t\t\t\t\t\t\t\tclone: true\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\t: function(value) {\n\t\t\t\t\t\t\treturn value == null || isNaN(value) ? 0 : value;\n\t\t\t\t\t\t};\n\n\t\t\tthis['get' + part] = function() {\n\t\t\t\treturn this._type === type\n\t\t\t\t\t|| hasOverlap && /^hs[bl]$/.test(this._type)\n\t\t\t\t\t\t? this._components[index]\n\t\t\t\t\t\t: this._convert(type)[index];\n\t\t\t};\n\n\t\t\tthis['set' + part] = function(value) {\n\t\t\t\tif (this._type !== type\n\t\t\t\t\t\t&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {\n\t\t\t\t\tthis._components = this._convert(type);\n\t\t\t\t\tthis._properties = types[type];\n\t\t\t\t\tthis._type = type;\n\t\t\t\t}\n\t\t\t\tthis._components[index] = parser.call(this, value);\n\t\t\t\tthis._changed();\n\t\t\t};\n\t\t}, this);\n\t}, {\n\t\t_class: 'Color',\n\t\t_readIndex: true,\n\n\t\tinitialize: function Color(arg) {\n\t\t\tvar args = arguments,\n\t\t\t\treading = this.__read,\n\t\t\t\tread = 0,\n\t\t\t\ttype,\n\t\t\t\tcomponents,\n\t\t\t\talpha,\n\t\t\t\tvalues;\n\t\t\tif (Array.isArray(arg)) {\n\t\t\t\targs = arg;\n\t\t\t\targ = args[0];\n\t\t\t}\n\t\t\tvar argType = arg != null && typeof arg;\n\t\t\tif (argType === 'string' && arg in types) {\n\t\t\t\ttype = arg;\n\t\t\t\targ = args[1];\n\t\t\t\tif (Array.isArray(arg)) {\n\t\t\t\t\tcomponents = arg;\n\t\t\t\t\talpha = args[2];\n\t\t\t\t} else {\n\t\t\t\t\tif (reading)\n\t\t\t\t\t\tread = 1;\n\t\t\t\t\targs = Base.slice(args, 1);\n\t\t\t\t\targType = typeof arg;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!components) {\n\t\t\t\tvalues = argType === 'number'\n\t\t\t\t\t\t? args\n\t\t\t\t\t\t: argType === 'object' && arg.length != null\n\t\t\t\t\t\t\t? arg\n\t\t\t\t\t\t\t: null;\n\t\t\t\tif (values) {\n\t\t\t\t\tif (!type)\n\t\t\t\t\t\ttype = values.length >= 3\n\t\t\t\t\t\t\t\t? 'rgb'\n\t\t\t\t\t\t\t\t: 'gray';\n\t\t\t\t\tvar length = types[type].length;\n\t\t\t\t\talpha = values[length];\n\t\t\t\t\tif (reading) {\n\t\t\t\t\t\tread += values === arguments\n\t\t\t\t\t\t\t? length + (alpha != null ? 1 : 0)\n\t\t\t\t\t\t\t: 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (values.length > length)\n\t\t\t\t\t\tvalues = Base.slice(values, 0, length);\n\t\t\t\t} else if (argType === 'string') {\n\t\t\t\t\ttype = 'rgb';\n\t\t\t\t\tcomponents = fromCSS(arg);\n\t\t\t\t\tif (components.length === 4) {\n\t\t\t\t\t\talpha = components[3];\n\t\t\t\t\t\tcomponents.length--;\n\t\t\t\t\t}\n\t\t\t\t} else if (argType === 'object') {\n\t\t\t\t\tif (arg.constructor === Color) {\n\t\t\t\t\t\ttype = arg._type;\n\t\t\t\t\t\tcomponents = arg._components.slice();\n\t\t\t\t\t\talpha = arg._alpha;\n\t\t\t\t\t\tif (type === 'gradient') {\n\t\t\t\t\t\t\tfor (var i = 1, l = components.length; i < l; i++) {\n\t\t\t\t\t\t\t\tvar point = components[i];\n\t\t\t\t\t\t\t\tif (point)\n\t\t\t\t\t\t\t\t\tcomponents[i] = point.clone();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (arg.constructor === Gradient) {\n\t\t\t\t\t\ttype = 'gradient';\n\t\t\t\t\t\tvalues = args;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttype = 'hue' in arg\n\t\t\t\t\t\t\t? 'lightness' in arg\n\t\t\t\t\t\t\t\t? 'hsl'\n\t\t\t\t\t\t\t\t: 'hsb'\n\t\t\t\t\t\t\t: 'gradient' in arg || 'stops' in arg\n\t\t\t\t\t\t\t\t\t|| 'radial' in arg\n\t\t\t\t\t\t\t\t? 'gradient'\n\t\t\t\t\t\t\t\t: 'gray' in arg\n\t\t\t\t\t\t\t\t\t? 'gray'\n\t\t\t\t\t\t\t\t\t: 'rgb';\n\t\t\t\t\t\tvar properties = types[type],\n\t\t\t\t\t\t\tparsers = componentParsers[type];\n\t\t\t\t\t\tthis._components = components = [];\n\t\t\t\t\t\tfor (var i = 0, l = properties.length; i < l; i++) {\n\t\t\t\t\t\t\tvar value = arg[properties[i]];\n\t\t\t\t\t\t\tif (value == null && !i && type === 'gradient'\n\t\t\t\t\t\t\t\t\t&& 'stops' in arg) {\n\t\t\t\t\t\t\t\tvalue = {\n\t\t\t\t\t\t\t\t\tstops: arg.stops,\n\t\t\t\t\t\t\t\t\tradial: arg.radial\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvalue = parsers[i].call(this, value);\n\t\t\t\t\t\t\tif (value != null)\n\t\t\t\t\t\t\t\tcomponents[i] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\talpha = arg.alpha;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (reading && type)\n\t\t\t\t\tread = 1;\n\t\t\t}\n\t\t\tthis._type = type || 'rgb';\n\t\t\tif (!components) {\n\t\t\t\tthis._components = components = [];\n\t\t\t\tvar parsers = componentParsers[this._type];\n\t\t\t\tfor (var i = 0, l = parsers.length; i < l; i++) {\n\t\t\t\t\tvar value = parsers[i].call(this, values && values[i]);\n\t\t\t\t\tif (value != null)\n\t\t\t\t\t\tcomponents[i] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._components = components;\n\t\t\tthis._properties = types[this._type];\n\t\t\tthis._alpha = alpha;\n\t\t\tif (reading)\n\t\t\t\tthis.__read = read;\n\t\t\treturn this;\n\t\t},\n\n\t\tset: '#initialize',\n\n\t\t_serialize: function(options, dictionary) {\n\t\t\tvar components = this.getComponents();\n\t\t\treturn Base.serialize(\n\t\t\t\t\t/^(gray|rgb)$/.test(this._type)\n\t\t\t\t\t\t? components\n\t\t\t\t\t\t: [this._type].concat(components),\n\t\t\t\t\toptions, true, dictionary);\n\t\t},\n\n\t\t_changed: function() {\n\t\t\tthis._canvasStyle = null;\n\t\t\tif (this._owner)\n\t\t\t\tthis._owner._changed(65);\n\t\t},\n\n\t\t_convert: function(type) {\n\t\t\tvar converter;\n\t\t\treturn this._type === type\n\t\t\t\t\t? this._components.slice()\n\t\t\t\t\t: (converter = converters[this._type + '-' + type])\n\t\t\t\t\t\t? converter.apply(this, this._components)\n\t\t\t\t\t\t: converters['rgb-' + type].apply(this,\n\t\t\t\t\t\t\tconverters[this._type + '-rgb'].apply(this,\n\t\t\t\t\t\t\t\tthis._components));\n\t\t},\n\n\t\tconvert: function(type) {\n\t\t\treturn new Color(type, this._convert(type), this._alpha);\n\t\t},\n\n\t\tgetType: function() {\n\t\t\treturn this._type;\n\t\t},\n\n\t\tsetType: function(type) {\n\t\t\tthis._components = this._convert(type);\n\t\t\tthis._properties = types[type];\n\t\t\tthis._type = type;\n\t\t},\n\n\t\tgetComponents: function() {\n\t\t\tvar components = this._components.slice();\n\t\t\tif (this._alpha != null)\n\t\t\t\tcomponents.push(this._alpha);\n\t\t\treturn components;\n\t\t},\n\n\t\tgetAlpha: function() {\n\t\t\treturn this._alpha != null ? this._alpha : 1;\n\t\t},\n\n\t\tsetAlpha: function(alpha) {\n\t\t\tthis._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);\n\t\t\tthis._changed();\n\t\t},\n\n\t\thasAlpha: function() {\n\t\t\treturn this._alpha != null;\n\t\t},\n\n\t\tequals: function(color) {\n\t\t\tvar col = Base.isPlainValue(color, true)\n\t\t\t\t\t? Color.read(arguments)\n\t\t\t\t\t: color;\n\t\t\treturn col === this || col && this._class === col._class\n\t\t\t\t\t&& this._type === col._type\n\t\t\t\t\t&& this.getAlpha() === col.getAlpha()\n\t\t\t\t\t&& Base.equals(this._components, col._components)\n\t\t\t\t\t|| false;\n\t\t},\n\n\t\ttoString: function() {\n\t\t\tvar properties = this._properties,\n\t\t\t\tparts = [],\n\t\t\t\tisGradient = this._type === 'gradient',\n\t\t\t\tf = Formatter.instance;\n\t\t\tfor (var i = 0, l = properties.length; i < l; i++) {\n\t\t\t\tvar value = this._components[i];\n\t\t\t\tif (value != null)\n\t\t\t\t\tparts.push(properties[i] + ': '\n\t\t\t\t\t\t\t+ (isGradient ? value : f.number(value)));\n\t\t\t}\n\t\t\tif (this._alpha != null)\n\t\t\t\tparts.push('alpha: ' + f.number(this._alpha));\n\t\t\treturn '{ ' + parts.join(', ') + ' }';\n\t\t},\n\n\t\ttoCSS: function(hex) {\n\t\t\tvar components = this._convert('rgb'),\n\t\t\t\talpha = hex || this._alpha == null ? 1 : this._alpha;\n\t\t\tfunction convert(val) {\n\t\t\t\treturn Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);\n\t\t\t}\n\t\t\tcomponents = [\n\t\t\t\tconvert(components[0]),\n\t\t\t\tconvert(components[1]),\n\t\t\t\tconvert(components[2])\n\t\t\t];\n\t\t\tif (alpha < 1)\n\t\t\t\tcomponents.push(alpha < 0 ? 0 : alpha);\n\t\t\treturn hex\n\t\t\t\t\t? '#' + ((1 << 24) + (components[0] << 16)\n\t\t\t\t\t\t+ (components[1] << 8)\n\t\t\t\t\t\t+ components[2]).toString(16).slice(1)\n\t\t\t\t\t: (components.length == 4 ? 'rgba(' : 'rgb(')\n\t\t\t\t\t\t+ components.join(',') + ')';\n\t\t},\n\n\t\ttoCanvasStyle: function(ctx) {\n\t\t\tif (this._canvasStyle)\n\t\t\t\treturn this._canvasStyle;\n\t\t\tif (this._type !== 'gradient')\n\t\t\t\treturn this._canvasStyle = this.toCSS();\n\t\t\tvar components = this._components,\n\t\t\t\tgradient = components[0],\n\t\t\t\tstops = gradient._stops,\n\t\t\t\torigin = components[1],\n\t\t\t\tdestination = components[2],\n\t\t\t\tcanvasGradient;\n\t\t\tif (gradient._radial) {\n\t\t\t\tvar radius = destination.getDistance(origin),\n\t\t\t\t\thighlight = components[3];\n\t\t\t\tif (highlight) {\n\t\t\t\t\tvar vector = highlight.subtract(origin);\n\t\t\t\t\tif (vector.getLength() > radius)\n\t\t\t\t\t\thighlight = origin.add(vector.normalize(radius - 0.1));\n\t\t\t\t}\n\t\t\t\tvar start = highlight || origin;\n\t\t\t\tcanvasGradient = ctx.createRadialGradient(start.x, start.y,\n\t\t\t\t\t\t0, origin.x, origin.y, radius);\n\t\t\t} else {\n\t\t\t\tcanvasGradient = ctx.createLinearGradient(origin.x, origin.y,\n\t\t\t\t\t\tdestination.x, destination.y);\n\t\t\t}\n\t\t\tfor (var i = 0, l = stops.length; i < l; i++) {\n\t\t\t\tvar stop = stops[i];\n\t\t\t\tcanvasGradient.addColorStop(stop._offset || i / (l - 1),\n\t\t\t\t\t\tstop._color.toCanvasStyle());\n\t\t\t}\n\t\t\treturn this._canvasStyle = canvasGradient;\n\t\t},\n\n\t\ttransform: function(matrix) {\n\t\t\tif (this._type === 'gradient') {\n\t\t\t\tvar components = this._components;\n\t\t\t\tfor (var i = 1, l = components.length; i < l; i++) {\n\t\t\t\t\tvar point = components[i];\n\t\t\t\t\tmatrix._transformPoint(point, point, true);\n\t\t\t\t}\n\t\t\t\tthis._changed();\n\t\t\t}\n\t\t},\n\n\t\tstatics: {\n\t\t\t_types: types,\n\n\t\t\trandom: function() {\n\t\t\t\tvar random = Math.random;\n\t\t\t\treturn new Color(random(), random(), random());\n\t\t\t}\n\t\t}\n\t});\n},\nnew function() {\n\tvar operators = {\n\t\tadd: function(a, b) {\n\t\t\treturn a + b;\n\t\t},\n\n\t\tsubtract: function(a, b) {\n\t\t\treturn a - b;\n\t\t},\n\n\t\tmultiply: function(a, b) {\n\t\t\treturn a * b;\n\t\t},\n\n\t\tdivide: function(a, b) {\n\t\t\treturn a / b;\n\t\t}\n\t};\n\n\treturn Base.each(operators, function(operator, name) {\n\t\tthis[name] = function(color) {\n\t\t\tcolor = Color.read(arguments);\n\t\t\tvar type = this._type,\n\t\t\t\tcomponents1 = this._components,\n\t\t\t\tcomponents2 = color._convert(type);\n\t\t\tfor (var i = 0, l = components1.length; i < l; i++)\n\t\t\t\tcomponents2[i] = operator(components1[i], components2[i]);\n\t\t\treturn new Color(type, components2,\n\t\t\t\t\tthis._alpha != null\n\t\t\t\t\t\t\t? operator(this._alpha, color.getAlpha())\n\t\t\t\t\t\t\t: null);\n\t\t};\n\t}, {\n\t});\n});\n\nvar Gradient = Base.extend({\n\t_class: 'Gradient',\n\n\tinitialize: function Gradient(stops, radial) {\n\t\tthis._id = UID.get();\n\t\tif (stops && Base.isPlainObject(stops)) {\n\t\t\tthis.set(stops);\n\t\t\tstops = radial = null;\n\t\t}\n\t\tif (this._stops == null) {\n\t\t\tthis.setStops(stops || ['white', 'black']);\n\t\t}\n\t\tif (this._radial == null) {\n\t\t\tthis.setRadial(typeof radial === 'string' && radial === 'radial'\n\t\t\t\t\t|| radial || false);\n\t\t}\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn dictionary.add(this, function() {\n\t\t\treturn Base.serialize([this._stops, this._radial],\n\t\t\t\t\toptions, true, dictionary);\n\t\t});\n\t},\n\n\t_changed: function() {\n\t\tfor (var i = 0, l = this._owners && this._owners.length; i < l; i++) {\n\t\t\tthis._owners[i]._changed();\n\t\t}\n\t},\n\n\t_addOwner: function(color) {\n\t\tif (!this._owners)\n\t\t\tthis._owners = [];\n\t\tthis._owners.push(color);\n\t},\n\n\t_removeOwner: function(color) {\n\t\tvar index = this._owners ? this._owners.indexOf(color) : -1;\n\t\tif (index != -1) {\n\t\t\tthis._owners.splice(index, 1);\n\t\t\tif (!this._owners.length)\n\t\t\t\tthis._owners = undefined;\n\t\t}\n\t},\n\n\tclone: function() {\n\t\tvar stops = [];\n\t\tfor (var i = 0, l = this._stops.length; i < l; i++) {\n\t\t\tstops[i] = this._stops[i].clone();\n\t\t}\n\t\treturn new Gradient(stops, this._radial);\n\t},\n\n\tgetStops: function() {\n\t\treturn this._stops;\n\t},\n\n\tsetStops: function(stops) {\n\t\tif (stops.length < 2) {\n\t\t\tthrow new Error(\n\t\t\t\t\t'Gradient stop list needs to contain at least two stops.');\n\t\t}\n\t\tvar _stops = this._stops;\n\t\tif (_stops) {\n\t\t\tfor (var i = 0, l = _stops.length; i < l; i++)\n\t\t\t\t_stops[i]._owner = undefined;\n\t\t}\n\t\t_stops = this._stops = GradientStop.readList(stops, 0, { clone: true });\n\t\tfor (var i = 0, l = _stops.length; i < l; i++)\n\t\t\t_stops[i]._owner = this;\n\t\tthis._changed();\n\t},\n\n\tgetRadial: function() {\n\t\treturn this._radial;\n\t},\n\n\tsetRadial: function(radial) {\n\t\tthis._radial = radial;\n\t\tthis._changed();\n\t},\n\n\tequals: function(gradient) {\n\t\tif (gradient === this)\n\t\t\treturn true;\n\t\tif (gradient && this._class === gradient._class) {\n\t\t\tvar stops1 = this._stops,\n\t\t\t\tstops2 = gradient._stops,\n\t\t\t\tlength = stops1.length;\n\t\t\tif (length === stops2.length) {\n\t\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\t\tif (!stops1[i].equals(stops2[i]))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n});\n\nvar GradientStop = Base.extend({\n\t_class: 'GradientStop',\n\n\tinitialize: function GradientStop(arg0, arg1) {\n\t\tvar color = arg0,\n\t\t\toffset = arg1;\n\t\tif (typeof arg0 === 'object' && arg1 === undefined) {\n\t\t\tif (Array.isArray(arg0) && typeof arg0[0] !== 'number') {\n\t\t\t\tcolor = arg0[0];\n\t\t\t\toffset = arg0[1];\n\t\t\t} else if ('color' in arg0 || 'offset' in arg0\n\t\t\t\t\t|| 'rampPoint' in arg0) {\n\t\t\t\tcolor = arg0.color;\n\t\t\t\toffset = arg0.offset || arg0.rampPoint || 0;\n\t\t\t}\n\t\t}\n\t\tthis.setColor(color);\n\t\tthis.setOffset(offset);\n\t},\n\n\tclone: function() {\n\t\treturn new GradientStop(this._color.clone(), this._offset);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar color = this._color,\n\t\t\toffset = this._offset;\n\t\treturn Base.serialize(offset == null ? [color] : [color, offset],\n\t\t\t\toptions, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tif (this._owner)\n\t\t\tthis._owner._changed(65);\n\t},\n\n\tgetOffset: function() {\n\t\treturn this._offset;\n\t},\n\n\tsetOffset: function(offset) {\n\t\tthis._offset = offset;\n\t\tthis._changed();\n\t},\n\n\tgetRampPoint: '#getOffset',\n\tsetRampPoint: '#setOffset',\n\n\tgetColor: function() {\n\t\treturn this._color;\n\t},\n\n\tsetColor: function() {\n\t\tvar color = Color.read(arguments, 0, { clone: true });\n\t\tif (color)\n\t\t\tcolor._owner = this;\n\t\tthis._color = color;\n\t\tthis._changed();\n\t},\n\n\tequals: function(stop) {\n\t\treturn stop === this || stop && this._class === stop._class\n\t\t\t\t&& this._color.equals(stop._color)\n\t\t\t\t&& this._offset == stop._offset\n\t\t\t\t|| false;\n\t}\n});\n\nvar Style = Base.extend(new function() {\n\tvar itemDefaults = {\n\t\tfillColor: null,\n\t\tfillRule: 'nonzero',\n\t\tstrokeColor: null,\n\t\tstrokeWidth: 1,\n\t\tstrokeCap: 'butt',\n\t\tstrokeJoin: 'miter',\n\t\tstrokeScaling: true,\n\t\tmiterLimit: 10,\n\t\tdashOffset: 0,\n\t\tdashArray: [],\n\t\tshadowColor: null,\n\t\tshadowBlur: 0,\n\t\tshadowOffset: new Point(),\n\t\tselectedColor: null\n\t},\n\tgroupDefaults = Base.set({}, itemDefaults, {\n\t\tfontFamily: 'sans-serif',\n\t\tfontWeight: 'normal',\n\t\tfontSize: 12,\n\t\tleading: null,\n\t\tjustification: 'left'\n\t}),\n\ttextDefaults = Base.set({}, groupDefaults, {\n\t\tfillColor: new Color()\n\t}),\n\tflags = {\n\t\tstrokeWidth: 97,\n\t\tstrokeCap: 97,\n\t\tstrokeJoin: 97,\n\t\tstrokeScaling: 105,\n\t\tmiterLimit: 97,\n\t\tfontFamily: 9,\n\t\tfontWeight: 9,\n\t\tfontSize: 9,\n\t\tfont: 9,\n\t\tleading: 9,\n\t\tjustification: 9\n\t},\n\titem = {\n\t\tbeans: true\n\t},\n\tfields = {\n\t\t_class: 'Style',\n\t\tbeans: true,\n\n\t\tinitialize: function Style(style, _owner, _project) {\n\t\t\tthis._values = {};\n\t\t\tthis._owner = _owner;\n\t\t\tthis._project = _owner && _owner._project || _project\n\t\t\t\t\t|| paper.project;\n\t\t\tthis._defaults = !_owner || _owner instanceof Group ? groupDefaults\n\t\t\t\t\t: _owner instanceof TextItem ? textDefaults\n\t\t\t\t\t: itemDefaults;\n\t\t\tif (style)\n\t\t\t\tthis.set(style);\n\t\t}\n\t};\n\n\tBase.each(groupDefaults, function(value, key) {\n\t\tvar isColor = /Color$/.test(key),\n\t\t\tisPoint = key === 'shadowOffset',\n\t\t\tpart = Base.capitalize(key),\n\t\t\tflag = flags[key],\n\t\t\tset = 'set' + part,\n\t\t\tget = 'get' + part;\n\n\t\tfields[set] = function(value) {\n\t\t\tvar owner = this._owner,\n\t\t\t\tchildren = owner && owner._children;\n\t\t\tif (children && children.length > 0\n\t\t\t\t\t&& !(owner instanceof CompoundPath)) {\n\t\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\t\tchildren[i]._style[set](value);\n\t\t\t} else if (key in this._defaults) {\n\t\t\t\tvar old = this._values[key];\n\t\t\t\tif (old !== value) {\n\t\t\t\t\tif (isColor) {\n\t\t\t\t\t\tif (old && old._owner !== undefined)\n\t\t\t\t\t\t\told._owner = undefined;\n\t\t\t\t\t\tif (value && value.constructor === Color) {\n\t\t\t\t\t\t\tif (value._owner)\n\t\t\t\t\t\t\t\tvalue = value.clone();\n\t\t\t\t\t\t\tvalue._owner = owner;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._values[key] = value;\n\t\t\t\t\tif (owner)\n\t\t\t\t\t\towner._changed(flag || 65);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfields[get] = function(_dontMerge) {\n\t\t\tvar owner = this._owner,\n\t\t\t\tchildren = owner && owner._children,\n\t\t\t\tvalue;\n\t\t\tif (key in this._defaults && (!children || !children.length\n\t\t\t\t\t|| _dontMerge || owner instanceof CompoundPath)) {\n\t\t\t\tvar value = this._values[key];\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tvalue = this._defaults[key];\n\t\t\t\t\tif (value && value.clone)\n\t\t\t\t\t\tvalue = value.clone();\n\t\t\t\t} else {\n\t\t\t\t\tvar ctor = isColor ? Color : isPoint ? Point : null;\n\t\t\t\t\tif (ctor && !(value && value.constructor === ctor)) {\n\t\t\t\t\t\tthis._values[key] = value = ctor.read([value], 0,\n\t\t\t\t\t\t\t\t{ readNull: true, clone: true });\n\t\t\t\t\t\tif (value && isColor)\n\t\t\t\t\t\t\tvalue._owner = owner;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (children) {\n\t\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\t\tvar childValue = children[i]._style[get]();\n\t\t\t\t\tif (!i) {\n\t\t\t\t\t\tvalue = childValue;\n\t\t\t\t\t} else if (!Base.equals(value, childValue)) {\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn value;\n\t\t};\n\n\t\titem[get] = function(_dontMerge) {\n\t\t\treturn this._style[get](_dontMerge);\n\t\t};\n\n\t\titem[set] = function(value) {\n\t\t\tthis._style[set](value);\n\t\t};\n\t});\n\n\tBase.each({\n\t\tFont: 'FontFamily',\n\t\tWindingRule: 'FillRule'\n\t}, function(value, key) {\n\t\tvar get = 'get' + key,\n\t\t\tset = 'set' + key;\n\t\tfields[get] = item[get] = '#get' + value;\n\t\tfields[set] = item[set] = '#set' + value;\n\t});\n\n\tItem.inject(item);\n\treturn fields;\n}, {\n\tset: function(style) {\n\t\tthis._values = {};\n\t\tvar isStyle = style instanceof Style,\n\t\t\tvalues = isStyle ? style._values : style;\n\t\tif (values) {\n\t\t\tfor (var key in values) {\n\t\t\t\tif (key in this._defaults) {\n\t\t\t\t\tvar value = values[key];\n\t\t\t\t\tthis[key] = value && isStyle && value.clone\n\t\t\t\t\t\t\t? value.clone() : value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tequals: function(style) {\n\t\tfunction compare(style1, style2, secondary) {\n\t\t\tvar values1 = style1._values,\n\t\t\t\tvalues2 = style2._values,\n\t\t\t\tdefaults2 = style2._defaults;\n\t\t\tfor (var key in values1) {\n\t\t\t\tvar value1 = values1[key],\n\t\t\t\t\tvalue2 = values2[key];\n\t\t\t\tif (!(secondary && key in values2) && !Base.equals(value1,\n\t\t\t\t\t\tvalue2 === undefined ? defaults2[key] : value2))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\treturn style === this || style && this._class === style._class\n\t\t\t\t&& compare(this, style)\n\t\t\t\t&& compare(style, this, true)\n\t\t\t\t|| false;\n\t},\n\n\thasFill: function() {\n\t\tvar color = this.getFillColor();\n\t\treturn !!color && color.alpha > 0;\n\t},\n\n\thasStroke: function() {\n\t\tvar color = this.getStrokeColor();\n\t\treturn !!color && color.alpha > 0 && this.getStrokeWidth() > 0;\n\t},\n\n\thasShadow: function() {\n\t\tvar color = this.getShadowColor();\n\t\treturn !!color && color.alpha > 0 && (this.getShadowBlur() > 0\n\t\t\t\t|| !this.getShadowOffset().isZero());\n\t},\n\n\tgetView: function() {\n\t\treturn this._project._view;\n\t},\n\n\tgetFontStyle: function() {\n\t\tvar fontSize = this.getFontSize();\n\t\treturn this.getFontWeight()\n\t\t\t\t+ ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')\n\t\t\t\t+ this.getFontFamily();\n\t},\n\n\tgetFont: '#getFontFamily',\n\tsetFont: '#setFontFamily',\n\n\tgetLeading: function getLeading() {\n\t\tvar leading = getLeading.base.call(this),\n\t\t\tfontSize = this.getFontSize();\n\t\tif (/pt|em|%|px/.test(fontSize))\n\t\t\tfontSize = this.getView().getPixelSize(fontSize);\n\t\treturn leading != null ? leading : fontSize * 1.2;\n\t}\n\n});\n\nvar DomElement = new function() {\n\tfunction handlePrefix(el, name, set, value) {\n\t\tvar prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],\n\t\t\tsuffix = name[0].toUpperCase() + name.substring(1);\n\t\tfor (var i = 0; i < 6; i++) {\n\t\t\tvar prefix = prefixes[i],\n\t\t\t\tkey = prefix ? prefix + suffix : name;\n\t\t\tif (key in el) {\n\t\t\t\tif (set) {\n\t\t\t\t\tel[key] = value;\n\t\t\t\t} else {\n\t\t\t\t\treturn el[key];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tgetStyles: function(el) {\n\t\t\tvar doc = el && el.nodeType !== 9 ? el.ownerDocument : el,\n\t\t\t\tview = doc && doc.defaultView;\n\t\t\treturn view && view.getComputedStyle(el, '');\n\t\t},\n\n\t\tgetBounds: function(el, viewport) {\n\t\t\tvar doc = el.ownerDocument,\n\t\t\t\tbody = doc.body,\n\t\t\t\thtml = doc.documentElement,\n\t\t\t\trect;\n\t\t\ttry {\n\t\t\t\trect = el.getBoundingClientRect();\n\t\t\t} catch (e) {\n\t\t\t\trect = { left: 0, top: 0, width: 0, height: 0 };\n\t\t\t}\n\t\t\tvar x = rect.left - (html.clientLeft || body.clientLeft || 0),\n\t\t\t\ty = rect.top - (html.clientTop || body.clientTop || 0);\n\t\t\tif (!viewport) {\n\t\t\t\tvar view = doc.defaultView;\n\t\t\t\tx += view.pageXOffset || html.scrollLeft || body.scrollLeft;\n\t\t\t\ty += view.pageYOffset || html.scrollTop || body.scrollTop;\n\t\t\t}\n\t\t\treturn new Rectangle(x, y, rect.width, rect.height);\n\t\t},\n\n\t\tgetViewportBounds: function(el) {\n\t\t\tvar doc = el.ownerDocument,\n\t\t\t\tview = doc.defaultView,\n\t\t\t\thtml = doc.documentElement;\n\t\t\treturn new Rectangle(0, 0,\n\t\t\t\tview.innerWidth || html.clientWidth,\n\t\t\t\tview.innerHeight || html.clientHeight\n\t\t\t);\n\t\t},\n\n\t\tgetOffset: function(el, viewport) {\n\t\t\treturn DomElement.getBounds(el, viewport).getPoint();\n\t\t},\n\n\t\tgetSize: function(el) {\n\t\t\treturn DomElement.getBounds(el, true).getSize();\n\t\t},\n\n\t\tisInvisible: function(el) {\n\t\t\treturn DomElement.getSize(el).equals(new Size(0, 0));\n\t\t},\n\n\t\tisInView: function(el) {\n\t\t\treturn !DomElement.isInvisible(el)\n\t\t\t\t\t&& DomElement.getViewportBounds(el).intersects(\n\t\t\t\t\t\tDomElement.getBounds(el, true));\n\t\t},\n\n\t\tisInserted: function(el) {\n\t\t\treturn document.body.contains(el);\n\t\t},\n\n\t\tgetPrefixed: function(el, name) {\n\t\t\treturn el && handlePrefix(el, name);\n\t\t},\n\n\t\tsetPrefixed: function(el, name, value) {\n\t\t\tif (typeof name === 'object') {\n\t\t\t\tfor (var key in name)\n\t\t\t\t\thandlePrefix(el, key, true, name[key]);\n\t\t\t} else {\n\t\t\t\thandlePrefix(el, name, true, value);\n\t\t\t}\n\t\t}\n\t};\n};\n\nvar DomEvent = {\n\tadd: function(el, events) {\n\t\tif (el) {\n\t\t\tfor (var type in events) {\n\t\t\t\tvar func = events[type],\n\t\t\t\t\tparts = type.split(/[\\s,]+/g);\n\t\t\t\tfor (var i = 0, l = parts.length; i < l; i++)\n\t\t\t\t\tel.addEventListener(parts[i], func, false);\n\t\t\t}\n\t\t}\n\t},\n\n\tremove: function(el, events) {\n\t\tif (el) {\n\t\t\tfor (var type in events) {\n\t\t\t\tvar func = events[type],\n\t\t\t\t\tparts = type.split(/[\\s,]+/g);\n\t\t\t\tfor (var i = 0, l = parts.length; i < l; i++)\n\t\t\t\t\tel.removeEventListener(parts[i], func, false);\n\t\t\t}\n\t\t}\n\t},\n\n\tgetPoint: function(event) {\n\t\tvar pos = event.targetTouches\n\t\t\t\t? event.targetTouches.length\n\t\t\t\t\t? event.targetTouches[0]\n\t\t\t\t\t: event.changedTouches[0]\n\t\t\t\t: event;\n\t\treturn new Point(\n\t\t\tpos.pageX || pos.clientX + document.documentElement.scrollLeft,\n\t\t\tpos.pageY || pos.clientY + document.documentElement.scrollTop\n\t\t);\n\t},\n\n\tgetTarget: function(event) {\n\t\treturn event.target || event.srcElement;\n\t},\n\n\tgetRelatedTarget: function(event) {\n\t\treturn event.relatedTarget || event.toElement;\n\t},\n\n\tgetOffset: function(event, target) {\n\t\treturn DomEvent.getPoint(event).subtract(DomElement.getOffset(\n\t\t\t\ttarget || DomEvent.getTarget(event)));\n\t}\n};\n\nDomEvent.requestAnimationFrame = new function() {\n\tvar nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'),\n\t\trequested = false,\n\t\tcallbacks = [],\n\t\ttimer;\n\n\tfunction handleCallbacks() {\n\t\tvar functions = callbacks;\n\t\tcallbacks = [];\n\t\tfor (var i = 0, l = functions.length; i < l; i++)\n\t\t\tfunctions[i]();\n\t\trequested = nativeRequest && callbacks.length;\n\t\tif (requested)\n\t\t\tnativeRequest(handleCallbacks);\n\t}\n\n\treturn function(callback) {\n\t\tcallbacks.push(callback);\n\t\tif (nativeRequest) {\n\t\t\tif (!requested) {\n\t\t\t\tnativeRequest(handleCallbacks);\n\t\t\t\trequested = true;\n\t\t\t}\n\t\t} else if (!timer) {\n\t\t\ttimer = setInterval(handleCallbacks, 1000 / 60);\n\t\t}\n\t};\n};\n\nvar View = Base.extend(Emitter, {\n\t_class: 'View',\n\n\tinitialize: function View(project, element) {\n\n\t\tfunction getSize(name) {\n\t\t\treturn element[name] || parseInt(element.getAttribute(name), 10);\n\t\t}\n\n\t\tfunction getCanvasSize() {\n\t\t\tvar size = DomElement.getSize(element);\n\t\t\treturn size.isNaN() || size.isZero()\n\t\t\t\t\t? new Size(getSize('width'), getSize('height'))\n\t\t\t\t\t: size;\n\t\t}\n\n\t\tvar size;\n\t\tif (window && element) {\n\t\t\tthis._id = element.getAttribute('id');\n\t\t\tif (this._id == null)\n\t\t\t\telement.setAttribute('id', this._id = 'view-' + View._id++);\n\t\t\tDomEvent.add(element, this._viewEvents);\n\t\t\tvar none = 'none';\n\t\t\tDomElement.setPrefixed(element.style, {\n\t\t\t\tuserDrag: none,\n\t\t\t\tuserSelect: none,\n\t\t\t\ttouchCallout: none,\n\t\t\t\tcontentZooming: none,\n\t\t\t\ttapHighlightColor: 'rgba(0,0,0,0)'\n\t\t\t});\n\n\t\t\tif (PaperScope.hasAttribute(element, 'resize')) {\n\t\t\t\tvar that = this;\n\t\t\t\tDomEvent.add(window, this._windowEvents = {\n\t\t\t\t\tresize: function() {\n\t\t\t\t\t\tthat.setViewSize(getCanvasSize());\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsize = getCanvasSize();\n\n\t\t\tif (PaperScope.hasAttribute(element, 'stats')\n\t\t\t\t\t&& typeof Stats !== 'undefined') {\n\t\t\t\tthis._stats = new Stats();\n\t\t\t\tvar stats = this._stats.domElement,\n\t\t\t\t\tstyle = stats.style,\n\t\t\t\t\toffset = DomElement.getOffset(element);\n\t\t\t\tstyle.position = 'absolute';\n\t\t\t\tstyle.left = offset.x + 'px';\n\t\t\t\tstyle.top = offset.y + 'px';\n\t\t\t\tdocument.body.appendChild(stats);\n\t\t\t}\n\t\t} else {\n\t\t\tsize = new Size(element);\n\t\t\telement = null;\n\t\t}\n\t\tthis._project = project;\n\t\tthis._scope = project._scope;\n\t\tthis._element = element;\n\t\tif (!this._pixelRatio)\n\t\t\tthis._pixelRatio = window && window.devicePixelRatio || 1;\n\t\tthis._setElementSize(size.width, size.height);\n\t\tthis._viewSize = size;\n\t\tView._views.push(this);\n\t\tView._viewsById[this._id] = this;\n\t\t(this._matrix = new Matrix())._owner = this;\n\t\tif (!View._focused)\n\t\t\tView._focused = this;\n\t\tthis._frameItems = {};\n\t\tthis._frameItemCount = 0;\n\t\tthis._itemEvents = { native: {}, virtual: {} };\n\t\tthis._autoUpdate = !paper.agent.node;\n\t\tthis._needsUpdate = false;\n\t},\n\n\tremove: function() {\n\t\tif (!this._project)\n\t\t\treturn false;\n\t\tif (View._focused === this)\n\t\t\tView._focused = null;\n\t\tView._views.splice(View._views.indexOf(this), 1);\n\t\tdelete View._viewsById[this._id];\n\t\tvar project = this._project;\n\t\tif (project._view === this)\n\t\t\tproject._view = null;\n\t\tDomEvent.remove(this._element, this._viewEvents);\n\t\tDomEvent.remove(window, this._windowEvents);\n\t\tthis._element = this._project = null;\n\t\tthis.off('frame');\n\t\tthis._animate = false;\n\t\tthis._frameItems = {};\n\t\treturn true;\n\t},\n\n\t_events: Base.each(\n\t\tItem._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']),\n\t\tfunction(name) {\n\t\t\tthis[name] = {};\n\t\t}, {\n\t\t\tonFrame: {\n\t\t\t\tinstall: function() {\n\t\t\t\t\tthis.play();\n\t\t\t\t},\n\n\t\t\t\tuninstall: function() {\n\t\t\t\t\tthis.pause();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t),\n\n\t_animate: false,\n\t_time: 0,\n\t_count: 0,\n\n\tgetAutoUpdate: function() {\n\t\treturn this._autoUpdate;\n\t},\n\n\tsetAutoUpdate: function(autoUpdate) {\n\t\tthis._autoUpdate = autoUpdate;\n\t\tif (autoUpdate)\n\t\t\tthis.requestUpdate();\n\t},\n\n\tupdate: function() {\n\t},\n\n\tdraw: function() {\n\t\tthis.update();\n\t},\n\n\trequestUpdate: function() {\n\t\tif (!this._requested) {\n\t\t\tvar that = this;\n\t\t\tDomEvent.requestAnimationFrame(function() {\n\t\t\t\tthat._requested = false;\n\t\t\t\tif (that._animate) {\n\t\t\t\t\tthat.requestUpdate();\n\t\t\t\t\tvar element = that._element;\n\t\t\t\t\tif ((!DomElement.getPrefixed(document, 'hidden')\n\t\t\t\t\t\t\t|| PaperScope.getAttribute(element, 'keepalive')\n\t\t\t\t\t\t\t\t=== 'true') && DomElement.isInView(element)) {\n\t\t\t\t\t\tthat._handleFrame();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (that._autoUpdate)\n\t\t\t\t\tthat.update();\n\t\t\t});\n\t\t\tthis._requested = true;\n\t\t}\n\t},\n\n\tplay: function() {\n\t\tthis._animate = true;\n\t\tthis.requestUpdate();\n\t},\n\n\tpause: function() {\n\t\tthis._animate = false;\n\t},\n\n\t_handleFrame: function() {\n\t\tpaper = this._scope;\n\t\tvar now = Date.now() / 1000,\n\t\t\tdelta = this._last ? now - this._last : 0;\n\t\tthis._last = now;\n\t\tthis.emit('frame', new Base({\n\t\t\tdelta: delta,\n\t\t\ttime: this._time += delta,\n\t\t\tcount: this._count++\n\t\t}));\n\t\tif (this._stats)\n\t\t\tthis._stats.update();\n\t},\n\n\t_animateItem: function(item, animate) {\n\t\tvar items = this._frameItems;\n\t\tif (animate) {\n\t\t\titems[item._id] = {\n\t\t\t\titem: item,\n\t\t\t\ttime: 0,\n\t\t\t\tcount: 0\n\t\t\t};\n\t\t\tif (++this._frameItemCount === 1)\n\t\t\t\tthis.on('frame', this._handleFrameItems);\n\t\t} else {\n\t\t\tdelete items[item._id];\n\t\t\tif (--this._frameItemCount === 0) {\n\t\t\t\tthis.off('frame', this._handleFrameItems);\n\t\t\t}\n\t\t}\n\t},\n\n\t_handleFrameItems: function(event) {\n\t\tfor (var i in this._frameItems) {\n\t\t\tvar entry = this._frameItems[i];\n\t\t\tentry.item.emit('frame', new Base(event, {\n\t\t\t\ttime: entry.time += event.delta,\n\t\t\t\tcount: entry.count++\n\t\t\t}));\n\t\t}\n\t},\n\n\t_changed: function() {\n\t\tthis._project._changed(2049);\n\t\tthis._bounds = this._decomposed = undefined;\n\t},\n\n\tgetElement: function() {\n\t\treturn this._element;\n\t},\n\n\tgetPixelRatio: function() {\n\t\treturn this._pixelRatio;\n\t},\n\n\tgetResolution: function() {\n\t\treturn this._pixelRatio * 72;\n\t},\n\n\tgetViewSize: function() {\n\t\tvar size = this._viewSize;\n\t\treturn new LinkedSize(size.width, size.height, this, 'setViewSize');\n\t},\n\n\tsetViewSize: function() {\n\t\tvar size = Size.read(arguments),\n\t\t\twidth = size.width,\n\t\t\theight = size.height,\n\t\t\tdelta = size.subtract(this._viewSize);\n\t\tif (delta.isZero())\n\t\t\treturn;\n\t\tthis._setElementSize(width, height);\n\t\tthis._viewSize._set(width, height);\n\t\tthis.emit('resize', {\n\t\t\tsize: size,\n\t\t\tdelta: delta\n\t\t});\n\t\tthis._changed();\n\t\tif (this._autoUpdate)\n\t\t\tthis.requestUpdate();\n\t},\n\n\t_setElementSize: function(width, height) {\n\t\tvar element = this._element;\n\t\tif (element) {\n\t\t\tif (element.width !== width)\n\t\t\t\telement.width = width;\n\t\t\tif (element.height !== height)\n\t\t\t\telement.height = height;\n\t\t}\n\t},\n\n\tgetBounds: function() {\n\t\tif (!this._bounds)\n\t\t\tthis._bounds = this._matrix.inverted()._transformBounds(\n\t\t\t\t\tnew Rectangle(new Point(), this._viewSize));\n\t\treturn this._bounds;\n\t},\n\n\tgetSize: function() {\n\t\treturn this.getBounds().getSize();\n\t},\n\n\tisVisible: function() {\n\t\treturn DomElement.isInView(this._element);\n\t},\n\n\tisInserted: function() {\n\t\treturn DomElement.isInserted(this._element);\n\t},\n\n\tgetPixelSize: function(size) {\n\t\tvar element = this._element,\n\t\t\tpixels;\n\t\tif (element) {\n\t\t\tvar parent = element.parentNode,\n\t\t\t\ttemp = document.createElement('div');\n\t\t\ttemp.style.fontSize = size;\n\t\t\tparent.appendChild(temp);\n\t\t\tpixels = parseFloat(DomElement.getStyles(temp).fontSize);\n\t\t\tparent.removeChild(temp);\n\t\t} else {\n\t\t\tpixels = parseFloat(pixels);\n\t\t}\n\t\treturn pixels;\n\t},\n\n\tgetTextWidth: function(font, lines) {\n\t\treturn 0;\n\t}\n}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {\n\tvar rotate = key === 'rotate';\n\tthis[key] = function() {\n\t\tvar value = (rotate ? Base : Point).read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\treturn this.transform(new Matrix()[key](value,\n\t\t\t\tcenter || this.getCenter(true)));\n\t};\n}, {\n\t_decompose: function() {\n\t\treturn this._decomposed || (this._decomposed = this._matrix.decompose());\n\t},\n\n\ttranslate: function() {\n\t\tvar mx = new Matrix();\n\t\treturn this.transform(mx.translate.apply(mx, arguments));\n\t},\n\n\tgetCenter: function() {\n\t\treturn this.getBounds().getCenter();\n\t},\n\n\tsetCenter: function() {\n\t\tvar center = Point.read(arguments);\n\t\tthis.translate(this.getCenter().subtract(center));\n\t},\n\n\tgetZoom: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\tscaling = decomposed && decomposed.scaling;\n\t\treturn scaling ? (scaling.x + scaling.y) / 2 : 0;\n\t},\n\n\tsetZoom: function(zoom) {\n\t\tthis.transform(new Matrix().scale(zoom / this.getZoom(),\n\t\t\tthis.getCenter()));\n\t},\n\n\tgetRotation: function() {\n\t\tvar decomposed = this._decompose();\n\t\treturn decomposed && decomposed.rotation;\n\t},\n\n\tsetRotation: function(rotation) {\n\t\tvar current = this.getRotation();\n\t\tif (current != null && rotation != null) {\n\t\t\tthis.rotate(rotation - current);\n\t\t}\n\t},\n\n\tgetScaling: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\tscaling = decomposed && decomposed.scaling;\n\t\treturn scaling\n\t\t\t\t? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')\n\t\t\t\t: undefined;\n\t},\n\n\tsetScaling: function() {\n\t\tvar current = this.getScaling(),\n\t\t\tscaling = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tif (current && scaling) {\n\t\t\tthis.scale(scaling.x / current.x, scaling.y / current.y);\n\t\t}\n\t},\n\n\tgetMatrix: function() {\n\t\treturn this._matrix;\n\t},\n\n\tsetMatrix: function() {\n\t\tvar matrix = this._matrix;\n\t\tmatrix.initialize.apply(matrix, arguments);\n\t},\n\n\ttransform: function(matrix) {\n\t\tthis._matrix.append(matrix);\n\t},\n\n\tscrollBy: function() {\n\t\tthis.translate(Point.read(arguments).negate());\n\t}\n}), {\n\n\tprojectToView: function() {\n\t\treturn this._matrix._transformPoint(Point.read(arguments));\n\t},\n\n\tviewToProject: function() {\n\t\treturn this._matrix._inverseTransform(Point.read(arguments));\n\t},\n\n\tgetEventPoint: function(event) {\n\t\treturn this.viewToProject(DomEvent.getOffset(event, this._element));\n\t},\n\n}, {\n\tstatics: {\n\t\t_views: [],\n\t\t_viewsById: {},\n\t\t_id: 0,\n\n\t\tcreate: function(project, element) {\n\t\t\tif (document && typeof element === 'string')\n\t\t\t\telement = document.getElementById(element);\n\t\t\tvar ctor = window ? CanvasView : View;\n\t\t\treturn new ctor(project, element);\n\t\t}\n\t}\n},\nnew function() {\n\tif (!window)\n\t\treturn;\n\tvar prevFocus,\n\t\ttempFocus,\n\t\tdragging = false,\n\t\tmouseDown = false;\n\n\tfunction getView(event) {\n\t\tvar target = DomEvent.getTarget(event);\n\t\treturn target.getAttribute && View._viewsById[\n\t\t\t\ttarget.getAttribute('id')];\n\t}\n\n\tfunction updateFocus() {\n\t\tvar view = View._focused;\n\t\tif (!view || !view.isVisible()) {\n\t\t\tfor (var i = 0, l = View._views.length; i < l; i++) {\n\t\t\t\tif ((view = View._views[i]).isVisible()) {\n\t\t\t\t\tView._focused = tempFocus = view;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction handleMouseMove(view, event, point) {\n\t\tview._handleMouseEvent('mousemove', event, point);\n\t}\n\n\tvar navigator = window.navigator,\n\t\tmousedown, mousemove, mouseup;\n\tif (navigator.pointerEnabled || navigator.msPointerEnabled) {\n\t\tmousedown = 'pointerdown MSPointerDown';\n\t\tmousemove = 'pointermove MSPointerMove';\n\t\tmouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';\n\t} else {\n\t\tmousedown = 'touchstart';\n\t\tmousemove = 'touchmove';\n\t\tmouseup = 'touchend touchcancel';\n\t\tif (!('ontouchstart' in window && navigator.userAgent.match(\n\t\t\t\t/mobile|tablet|ip(ad|hone|od)|android|silk/i))) {\n\t\t\tmousedown += ' mousedown';\n\t\t\tmousemove += ' mousemove';\n\t\t\tmouseup += ' mouseup';\n\t\t}\n\t}\n\n\tvar viewEvents = {},\n\t\tdocEvents = {\n\t\t\tmouseout: function(event) {\n\t\t\t\tvar view = View._focused,\n\t\t\t\t\ttarget = DomEvent.getRelatedTarget(event);\n\t\t\t\tif (view && (!target || target.nodeName === 'HTML')) {\n\t\t\t\t\tvar offset = DomEvent.getOffset(event, view._element),\n\t\t\t\t\t\tx = offset.x,\n\t\t\t\t\t\tabs = Math.abs,\n\t\t\t\t\t\tax = abs(x),\n\t\t\t\t\t\tmax = 1 << 25,\n\t\t\t\t\t\tdiff = ax - max;\n\t\t\t\t\toffset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;\n\t\t\t\t\thandleMouseMove(view, event, view.viewToProject(offset));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tscroll: updateFocus\n\t\t};\n\n\tviewEvents[mousedown] = function(event) {\n\t\tvar view = View._focused = getView(event);\n\t\tif (!dragging) {\n\t\t\tdragging = true;\n\t\t\tview._handleMouseEvent('mousedown', event);\n\t\t}\n\t};\n\n\tdocEvents[mousemove] = function(event) {\n\t\tvar view = View._focused;\n\t\tif (!mouseDown) {\n\t\t\tvar target = getView(event);\n\t\t\tif (target) {\n\t\t\t\tif (view !== target) {\n\t\t\t\t\tif (view)\n\t\t\t\t\t\thandleMouseMove(view, event);\n\t\t\t\t\tif (!prevFocus)\n\t\t\t\t\t\tprevFocus = view;\n\t\t\t\t\tview = View._focused = tempFocus = target;\n\t\t\t\t}\n\t\t\t} else if (tempFocus && tempFocus === view) {\n\t\t\t\tif (prevFocus && !prevFocus.isInserted())\n\t\t\t\t\tprevFocus = null;\n\t\t\t\tview = View._focused = prevFocus;\n\t\t\t\tprevFocus = null;\n\t\t\t\tupdateFocus();\n\t\t\t}\n\t\t}\n\t\tif (view)\n\t\t\thandleMouseMove(view, event);\n\t};\n\n\tdocEvents[mousedown] = function() {\n\t\tmouseDown = true;\n\t};\n\n\tdocEvents[mouseup] = function(event) {\n\t\tvar view = View._focused;\n\t\tif (view && dragging)\n\t\t\tview._handleMouseEvent('mouseup', event);\n\t\tmouseDown = dragging = false;\n\t};\n\n\tDomEvent.add(document, docEvents);\n\n\tDomEvent.add(window, {\n\t\tload: updateFocus\n\t});\n\n\tvar called = false,\n\t\tprevented = false,\n\t\tfallbacks = {\n\t\t\tdoubleclick: 'click',\n\t\t\tmousedrag: 'mousemove'\n\t\t},\n\t\twasInView = false,\n\t\toverView,\n\t\tdownPoint,\n\t\tlastPoint,\n\t\tdownItem,\n\t\toverItem,\n\t\tdragItem,\n\t\tclickItem,\n\t\tclickTime,\n\t\tdblClick;\n\n\tfunction emitMouseEvent(obj, target, type, event, point, prevPoint,\n\t\t\tstopItem) {\n\t\tvar stopped = false,\n\t\t\tmouseEvent;\n\n\t\tfunction emit(obj, type) {\n\t\t\tif (obj.responds(type)) {\n\t\t\t\tif (!mouseEvent) {\n\t\t\t\t\tmouseEvent = new MouseEvent(type, event, point,\n\t\t\t\t\t\t\ttarget || obj,\n\t\t\t\t\t\t\tprevPoint ? point.subtract(prevPoint) : null);\n\t\t\t\t}\n\t\t\t\tif (obj.emit(type, mouseEvent)) {\n\t\t\t\t\tcalled = true;\n\t\t\t\t\tif (mouseEvent.prevented)\n\t\t\t\t\t\tprevented = true;\n\t\t\t\t\tif (mouseEvent.stopped)\n\t\t\t\t\t\treturn stopped = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar fallback = fallbacks[type];\n\t\t\t\tif (fallback)\n\t\t\t\t\treturn emit(obj, fallback);\n\t\t\t}\n\t\t}\n\n\t\twhile (obj && obj !== stopItem) {\n\t\t\tif (emit(obj, type))\n\t\t\t\tbreak;\n\t\t\tobj = obj._parent;\n\t\t}\n\t\treturn stopped;\n\t}\n\n\tfunction emitMouseEvents(view, hitItem, type, event, point, prevPoint) {\n\t\tview._project.removeOn(type);\n\t\tprevented = called = false;\n\t\treturn (dragItem && emitMouseEvent(dragItem, null, type, event,\n\t\t\t\t\tpoint, prevPoint)\n\t\t\t|| hitItem && hitItem !== dragItem\n\t\t\t\t&& !hitItem.isDescendant(dragItem)\n\t\t\t\t&& emitMouseEvent(hitItem, null, fallbacks[type] || type, event,\n\t\t\t\t\tpoint, prevPoint, dragItem)\n\t\t\t|| emitMouseEvent(view, dragItem || hitItem || view, type, event,\n\t\t\t\t\tpoint, prevPoint));\n\t}\n\n\tvar itemEventsMap = {\n\t\tmousedown: {\n\t\t\tmousedown: 1,\n\t\t\tmousedrag: 1,\n\t\t\tclick: 1,\n\t\t\tdoubleclick: 1\n\t\t},\n\t\tmouseup: {\n\t\t\tmouseup: 1,\n\t\t\tmousedrag: 1,\n\t\t\tclick: 1,\n\t\t\tdoubleclick: 1\n\t\t},\n\t\tmousemove: {\n\t\t\tmousedrag: 1,\n\t\t\tmousemove: 1,\n\t\t\tmouseenter: 1,\n\t\t\tmouseleave: 1\n\t\t}\n\t};\n\n\treturn {\n\t\t_viewEvents: viewEvents,\n\n\t\t_handleMouseEvent: function(type, event, point) {\n\t\t\tvar itemEvents = this._itemEvents,\n\t\t\t\thitItems = itemEvents.native[type],\n\t\t\t\tnativeMove = type === 'mousemove',\n\t\t\t\ttool = this._scope.tool,\n\t\t\t\tview = this;\n\n\t\t\tfunction responds(type) {\n\t\t\t\treturn itemEvents.virtual[type] || view.responds(type)\n\t\t\t\t\t\t|| tool && tool.responds(type);\n\t\t\t}\n\n\t\t\tif (nativeMove && dragging && responds('mousedrag'))\n\t\t\t\ttype = 'mousedrag';\n\t\t\tif (!point)\n\t\t\t\tpoint = this.getEventPoint(event);\n\n\t\t\tvar inView = this.getBounds().contains(point),\n\t\t\t\thit = hitItems && inView && view._project.hitTest(point, {\n\t\t\t\t\ttolerance: 0,\n\t\t\t\t\tfill: true,\n\t\t\t\t\tstroke: true\n\t\t\t\t}),\n\t\t\t\thitItem = hit && hit.item || null,\n\t\t\t\thandle = false,\n\t\t\t\tmouse = {};\n\t\t\tmouse[type.substr(5)] = true;\n\n\t\t\tif (hitItems && hitItem !== overItem) {\n\t\t\t\tif (overItem) {\n\t\t\t\t\temitMouseEvent(overItem, null, 'mouseleave', event, point);\n\t\t\t\t}\n\t\t\t\tif (hitItem) {\n\t\t\t\t\temitMouseEvent(hitItem, null, 'mouseenter', event, point);\n\t\t\t\t}\n\t\t\t\toverItem = hitItem;\n\t\t\t}\n\t\t\tif (wasInView ^ inView) {\n\t\t\t\temitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave',\n\t\t\t\t\t\tevent, point);\n\t\t\t\toverView = inView ? this : null;\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\tif ((inView || mouse.drag) && !point.equals(lastPoint)) {\n\t\t\t\temitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',\n\t\t\t\t\t\tevent, point, lastPoint);\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\twasInView = inView;\n\t\t\tif (mouse.down && inView || mouse.up && downPoint) {\n\t\t\t\temitMouseEvents(this, hitItem, type, event, point, downPoint);\n\t\t\t\tif (mouse.down) {\n\t\t\t\t\tdblClick = hitItem === clickItem\n\t\t\t\t\t\t&& (Date.now() - clickTime < 300);\n\t\t\t\t\tdownItem = clickItem = hitItem;\n\t\t\t\t\tdragItem = !prevented && hitItem;\n\t\t\t\t\tdownPoint = point;\n\t\t\t\t} else if (mouse.up) {\n\t\t\t\t\tif (!prevented && hitItem === downItem) {\n\t\t\t\t\t\tclickTime = Date.now();\n\t\t\t\t\t\temitMouseEvents(this, hitItem, dblClick ? 'doubleclick'\n\t\t\t\t\t\t\t\t: 'click', event, point, downPoint);\n\t\t\t\t\t\tdblClick = false;\n\t\t\t\t\t}\n\t\t\t\t\tdownItem = dragItem = null;\n\t\t\t\t}\n\t\t\t\twasInView = false;\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\tlastPoint = point;\n\t\t\tif (handle && tool) {\n\t\t\t\tcalled = tool._handleMouseEvent(type, event, point, mouse)\n\t\t\t\t\t|| called;\n\t\t\t}\n\n\t\t\tif (called && !mouse.move || mouse.down && responds('mouseup'))\n\t\t\t\tevent.preventDefault();\n\t\t},\n\n\t\t_handleKeyEvent: function(type, event, key, character) {\n\t\t\tvar scope = this._scope,\n\t\t\t\ttool = scope.tool,\n\t\t\t\tkeyEvent;\n\n\t\t\tfunction emit(obj) {\n\t\t\t\tif (obj.responds(type)) {\n\t\t\t\t\tpaper = scope;\n\t\t\t\t\tobj.emit(type, keyEvent = keyEvent\n\t\t\t\t\t\t\t|| new KeyEvent(type, event, key, character));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.isVisible()) {\n\t\t\t\temit(this);\n\t\t\t\tif (tool && tool.responds(type))\n\t\t\t\t\temit(tool);\n\t\t\t}\n\t\t},\n\n\t\t_countItemEvent: function(type, sign) {\n\t\t\tvar itemEvents = this._itemEvents,\n\t\t\t\tnative = itemEvents.native,\n\t\t\t\tvirtual = itemEvents.virtual;\n\t\t\tfor (var key in itemEventsMap) {\n\t\t\t\tnative[key] = (native[key] || 0)\n\t\t\t\t\t\t+ (itemEventsMap[key][type] || 0) * sign;\n\t\t\t}\n\t\t\tvirtual[type] = (virtual[type] || 0) + sign;\n\t\t},\n\n\t\tstatics: {\n\t\t\tupdateFocus: updateFocus\n\t\t}\n\t};\n});\n\nvar CanvasView = View.extend({\n\t_class: 'CanvasView',\n\n\tinitialize: function CanvasView(project, canvas) {\n\t\tif (!(canvas instanceof window.HTMLCanvasElement)) {\n\t\t\tvar size = Size.read(arguments, 1);\n\t\t\tif (size.isZero())\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Cannot create CanvasView with the provided argument: '\n\t\t\t\t\t\t+ Base.slice(arguments, 1));\n\t\t\tcanvas = CanvasProvider.getCanvas(size);\n\t\t}\n\t\tvar ctx = this._context = canvas.getContext('2d');\n\t\tctx.save();\n\t\tthis._pixelRatio = 1;\n\t\tif (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {\n\t\t\tvar deviceRatio = window.devicePixelRatio || 1,\n\t\t\t\tbackingStoreRatio = DomElement.getPrefixed(ctx,\n\t\t\t\t\t\t'backingStorePixelRatio') || 1;\n\t\t\tthis._pixelRatio = deviceRatio / backingStoreRatio;\n\t\t}\n\t\tView.call(this, project, canvas);\n\t\tthis._needsUpdate = true;\n\t},\n\n\tremove: function remove() {\n\t\tthis._context.restore();\n\t\treturn remove.base.call(this);\n\t},\n\n\t_setElementSize: function _setElementSize(width, height) {\n\t\tvar pixelRatio = this._pixelRatio;\n\t\t_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);\n\t\tif (pixelRatio !== 1) {\n\t\t\tvar element = this._element,\n\t\t\t\tctx = this._context;\n\t\t\tif (!PaperScope.hasAttribute(element, 'resize')) {\n\t\t\t\tvar style = element.style;\n\t\t\t\tstyle.width = width + 'px';\n\t\t\t\tstyle.height = height + 'px';\n\t\t\t}\n\t\t\tctx.restore();\n\t\t\tctx.save();\n\t\t\tctx.scale(pixelRatio, pixelRatio);\n\t\t}\n\t},\n\n\tgetPixelSize: function getPixelSize(size) {\n\t\tvar agent = paper.agent,\n\t\t\tpixels;\n\t\tif (agent && agent.firefox) {\n\t\t\tpixels = getPixelSize.base.call(this, size);\n\t\t} else {\n\t\t\tvar ctx = this._context,\n\t\t\t\tprevFont = ctx.font;\n\t\t\tctx.font = size + ' serif';\n\t\t\tpixels = parseFloat(ctx.font);\n\t\t\tctx.font = prevFont;\n\t\t}\n\t\treturn pixels;\n\t},\n\n\tgetTextWidth: function(font, lines) {\n\t\tvar ctx = this._context,\n\t\t\tprevFont = ctx.font,\n\t\t\twidth = 0;\n\t\tctx.font = font;\n\t\tfor (var i = 0, l = lines.length; i < l; i++)\n\t\t\twidth = Math.max(width, ctx.measureText(lines[i]).width);\n\t\tctx.font = prevFont;\n\t\treturn width;\n\t},\n\n\tupdate: function() {\n\t\tif (!this._needsUpdate)\n\t\t\treturn false;\n\t\tvar project = this._project,\n\t\t\tctx = this._context,\n\t\t\tsize = this._viewSize;\n\t\tctx.clearRect(0, 0, size.width + 1, size.height + 1);\n\t\tif (project)\n\t\t\tproject.draw(ctx, this._matrix, this._pixelRatio);\n\t\tthis._needsUpdate = false;\n\t\treturn true;\n\t}\n});\n\nvar Event = Base.extend({\n\t_class: 'Event',\n\n\tinitialize: function Event(event) {\n\t\tthis.event = event;\n\t\tthis.type = event && event.type;\n\t},\n\n\tprevented: false,\n\tstopped: false,\n\n\tpreventDefault: function() {\n\t\tthis.prevented = true;\n\t\tthis.event.preventDefault();\n\t},\n\n\tstopPropagation: function() {\n\t\tthis.stopped = true;\n\t\tthis.event.stopPropagation();\n\t},\n\n\tstop: function() {\n\t\tthis.stopPropagation();\n\t\tthis.preventDefault();\n\t},\n\n\tgetTimeStamp: function() {\n\t\treturn this.event.timeStamp;\n\t},\n\n\tgetModifiers: function() {\n\t\treturn Key.modifiers;\n\t}\n});\n\nvar KeyEvent = Event.extend({\n\t_class: 'KeyEvent',\n\n\tinitialize: function KeyEvent(type, event, key, character) {\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t\tthis.key = key;\n\t\tthis.character = character;\n\t},\n\n\ttoString: function() {\n\t\treturn \"{ type: '\" + this.type\n\t\t\t\t+ \"', key: '\" + this.key\n\t\t\t\t+ \"', character: '\" + this.character\n\t\t\t\t+ \"', modifiers: \" + this.getModifiers()\n\t\t\t\t+ \" }\";\n\t}\n});\n\nvar Key = new function() {\n\tvar keyLookup = {\n\t\t\t'\\t': 'tab',\n\t\t\t' ': 'space',\n\t\t\t'\\b': 'backspace',\n\t\t\t'\\x7f': 'delete',\n\t\t\t'Spacebar': 'space',\n\t\t\t'Del': 'delete',\n\t\t\t'Win': 'meta',\n\t\t\t'Esc': 'escape'\n\t\t},\n\n\t\tcharLookup = {\n\t\t\t'tab': '\\t',\n\t\t\t'space': ' ',\n\t\t\t'enter': '\\r'\n\t\t},\n\n\t\tkeyMap = {},\n\t\tcharMap = {},\n\t\tmetaFixMap,\n\t\tdownKey,\n\n\t\tmodifiers = new Base({\n\t\t\tshift: false,\n\t\t\tcontrol: false,\n\t\t\talt: false,\n\t\t\tmeta: false,\n\t\t\tcapsLock: false,\n\t\t\tspace: false\n\t\t}).inject({\n\t\t\toption: {\n\t\t\t\tget: function() {\n\t\t\t\t\treturn this.alt;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tcommand: {\n\t\t\t\tget: function() {\n\t\t\t\t\tvar agent = paper && paper.agent;\n\t\t\t\t\treturn agent && agent.mac ? this.meta : this.control;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\tfunction getKey(event) {\n\t\tvar key = event.key || event.keyIdentifier;\n\t\tkey = /^U\\+/.test(key)\n\t\t\t\t? String.fromCharCode(parseInt(key.substr(2), 16))\n\t\t\t\t: /^Arrow[A-Z]/.test(key) ? key.substr(5)\n\t\t\t\t: key === 'Unidentified' ? String.fromCharCode(event.keyCode)\n\t\t\t\t: key;\n\t\treturn keyLookup[key] ||\n\t\t\t\t(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());\n\t}\n\n\tfunction handleKey(down, key, character, event) {\n\t\tvar type = down ? 'keydown' : 'keyup',\n\t\t\tview = View._focused,\n\t\t\tname;\n\t\tkeyMap[key] = down;\n\t\tif (down) {\n\t\t\tcharMap[key] = character;\n\t\t} else {\n\t\t\tdelete charMap[key];\n\t\t}\n\t\tif (key.length > 1 && (name = Base.camelize(key)) in modifiers) {\n\t\t\tmodifiers[name] = down;\n\t\t\tvar agent = paper && paper.agent;\n\t\t\tif (name === 'meta' && agent && agent.mac) {\n\t\t\t\tif (down) {\n\t\t\t\t\tmetaFixMap = {};\n\t\t\t\t} else {\n\t\t\t\t\tfor (var k in metaFixMap) {\n\t\t\t\t\t\tif (k in charMap)\n\t\t\t\t\t\t\thandleKey(false, k, metaFixMap[k], event);\n\t\t\t\t\t}\n\t\t\t\t\tmetaFixMap = null;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (down && metaFixMap) {\n\t\t\tmetaFixMap[key] = character;\n\t\t}\n\t\tif (view) {\n\t\t\tview._handleKeyEvent(down ? 'keydown' : 'keyup', event, key,\n\t\t\t\t\tcharacter);\n\t\t}\n\t}\n\n\tDomEvent.add(document, {\n\t\tkeydown: function(event) {\n\t\t\tvar key = getKey(event),\n\t\t\t\tagent = paper && paper.agent;\n\t\t\tif (key.length > 1 || agent && (agent.chrome && (event.altKey\n\t\t\t\t\t\t|| agent.mac && event.metaKey\n\t\t\t\t\t\t|| !agent.mac && event.ctrlKey))) {\n\t\t\t\thandleKey(true, key,\n\t\t\t\t\t\tcharLookup[key] || (key.length > 1 ? '' : key), event);\n\t\t\t} else {\n\t\t\t\tdownKey = key;\n\t\t\t}\n\t\t},\n\n\t\tkeypress: function(event) {\n\t\t\tif (downKey) {\n\t\t\t\tvar key = getKey(event),\n\t\t\t\t\tcode = event.charCode,\n\t\t\t\t\tcharacter = code >= 32 ? String.fromCharCode(code)\n\t\t\t\t\t\t: key.length > 1 ? '' : key;\n\t\t\t\tif (key !== downKey) {\n\t\t\t\t\tkey = character.toLowerCase();\n\t\t\t\t}\n\t\t\t\thandleKey(true, key, character, event);\n\t\t\t\tdownKey = null;\n\t\t\t}\n\t\t},\n\n\t\tkeyup: function(event) {\n\t\t\tvar key = getKey(event);\n\t\t\tif (key in charMap)\n\t\t\t\thandleKey(false, key, charMap[key], event);\n\t\t}\n\t});\n\n\tDomEvent.add(window, {\n\t\tblur: function(event) {\n\t\t\tfor (var key in charMap)\n\t\t\t\thandleKey(false, key, charMap[key], event);\n\t\t}\n\t});\n\n\treturn {\n\t\tmodifiers: modifiers,\n\n\t\tisDown: function(key) {\n\t\t\treturn !!keyMap[key];\n\t\t}\n\t};\n};\n\nvar MouseEvent = Event.extend({\n\t_class: 'MouseEvent',\n\n\tinitialize: function MouseEvent(type, event, point, target, delta) {\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t\tthis.point = point;\n\t\tthis.target = target;\n\t\tthis.delta = delta;\n\t},\n\n\ttoString: function() {\n\t\treturn \"{ type: '\" + this.type\n\t\t\t\t+ \"', point: \" + this.point\n\t\t\t\t+ ', target: ' + this.target\n\t\t\t\t+ (this.delta ? ', delta: ' + this.delta : '')\n\t\t\t\t+ ', modifiers: ' + this.getModifiers()\n\t\t\t\t+ ' }';\n\t}\n});\n\nvar ToolEvent = Event.extend({\n\t_class: 'ToolEvent',\n\t_item: null,\n\n\tinitialize: function ToolEvent(tool, type, event) {\n\t\tthis.tool = tool;\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t},\n\n\t_choosePoint: function(point, toolPoint) {\n\t\treturn point ? point : toolPoint ? toolPoint.clone() : null;\n\t},\n\n\tgetPoint: function() {\n\t\treturn this._choosePoint(this._point, this.tool._point);\n\t},\n\n\tsetPoint: function(point) {\n\t\tthis._point = point;\n\t},\n\n\tgetLastPoint: function() {\n\t\treturn this._choosePoint(this._lastPoint, this.tool._lastPoint);\n\t},\n\n\tsetLastPoint: function(lastPoint) {\n\t\tthis._lastPoint = lastPoint;\n\t},\n\n\tgetDownPoint: function() {\n\t\treturn this._choosePoint(this._downPoint, this.tool._downPoint);\n\t},\n\n\tsetDownPoint: function(downPoint) {\n\t\tthis._downPoint = downPoint;\n\t},\n\n\tgetMiddlePoint: function() {\n\t\tif (!this._middlePoint && this.tool._lastPoint) {\n\t\t\treturn this.tool._point.add(this.tool._lastPoint).divide(2);\n\t\t}\n\t\treturn this._middlePoint;\n\t},\n\n\tsetMiddlePoint: function(middlePoint) {\n\t\tthis._middlePoint = middlePoint;\n\t},\n\n\tgetDelta: function() {\n\t\treturn !this._delta && this.tool._lastPoint\n\t\t\t\t? this.tool._point.subtract(this.tool._lastPoint)\n\t\t\t\t: this._delta;\n\t},\n\n\tsetDelta: function(delta) {\n\t\tthis._delta = delta;\n\t},\n\n\tgetCount: function() {\n\t\treturn this.tool[/^mouse(down|up)$/.test(this.type)\n\t\t\t\t? '_downCount' : '_moveCount'];\n\t},\n\n\tsetCount: function(count) {\n\t\tthis.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']\n\t\t\t= count;\n\t},\n\n\tgetItem: function() {\n\t\tif (!this._item) {\n\t\t\tvar result = this.tool._scope.project.hitTest(this.getPoint());\n\t\t\tif (result) {\n\t\t\t\tvar item = result.item,\n\t\t\t\t\tparent = item._parent;\n\t\t\t\twhile (/^(Group|CompoundPath)$/.test(parent._class)) {\n\t\t\t\t\titem = parent;\n\t\t\t\t\tparent = parent._parent;\n\t\t\t\t}\n\t\t\t\tthis._item = item;\n\t\t\t}\n\t\t}\n\t\treturn this._item;\n\t},\n\n\tsetItem: function(item) {\n\t\tthis._item = item;\n\t},\n\n\ttoString: function() {\n\t\treturn '{ type: ' + this.type\n\t\t\t\t+ ', point: ' + this.getPoint()\n\t\t\t\t+ ', count: ' + this.getCount()\n\t\t\t\t+ ', modifiers: ' + this.getModifiers()\n\t\t\t\t+ ' }';\n\t}\n});\n\nvar Tool = PaperScopeItem.extend({\n\t_class: 'Tool',\n\t_list: 'tools',\n\t_reference: 'tool',\n\t_events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',\n\t\t\t'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown',\n\t\t\t'onKeyUp'],\n\n\tinitialize: function Tool(props) {\n\t\tPaperScopeItem.call(this);\n\t\tthis._moveCount = -1;\n\t\tthis._downCount = -1;\n\t\tthis.set(props);\n\t},\n\n\tgetMinDistance: function() {\n\t\treturn this._minDistance;\n\t},\n\n\tsetMinDistance: function(minDistance) {\n\t\tthis._minDistance = minDistance;\n\t\tif (minDistance != null && this._maxDistance != null\n\t\t\t\t&& minDistance > this._maxDistance) {\n\t\t\tthis._maxDistance = minDistance;\n\t\t}\n\t},\n\n\tgetMaxDistance: function() {\n\t\treturn this._maxDistance;\n\t},\n\n\tsetMaxDistance: function(maxDistance) {\n\t\tthis._maxDistance = maxDistance;\n\t\tif (this._minDistance != null && maxDistance != null\n\t\t\t\t&& maxDistance < this._minDistance) {\n\t\t\tthis._minDistance = maxDistance;\n\t\t}\n\t},\n\n\tgetFixedDistance: function() {\n\t\treturn this._minDistance == this._maxDistance\n\t\t\t? this._minDistance : null;\n\t},\n\n\tsetFixedDistance: function(distance) {\n\t\tthis._minDistance = this._maxDistance = distance;\n\t},\n\n\t_handleMouseEvent: function(type, event, point, mouse) {\n\t\tpaper = this._scope;\n\t\tif (mouse.drag && !this.responds(type))\n\t\t\ttype = 'mousemove';\n\t\tvar move = mouse.move || mouse.drag,\n\t\t\tresponds = this.responds(type),\n\t\t\tminDistance = this.minDistance,\n\t\t\tmaxDistance = this.maxDistance,\n\t\t\tcalled = false,\n\t\t\ttool = this;\n\t\tfunction update(minDistance, maxDistance) {\n\t\t\tvar pt = point,\n\t\t\t\ttoolPoint = move ? tool._point : (tool._downPoint || pt);\n\t\t\tif (move) {\n\t\t\t\tif (tool._moveCount && pt.equals(toolPoint)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (toolPoint && (minDistance != null || maxDistance != null)) {\n\t\t\t\t\tvar vector = pt.subtract(toolPoint),\n\t\t\t\t\t\tdistance = vector.getLength();\n\t\t\t\t\tif (distance < (minDistance || 0))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (maxDistance) {\n\t\t\t\t\t\tpt = toolPoint.add(vector.normalize(\n\t\t\t\t\t\t\t\tMath.min(distance, maxDistance)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttool._moveCount++;\n\t\t\t}\n\t\t\ttool._point = pt;\n\t\t\ttool._lastPoint = toolPoint || pt;\n\t\t\tif (mouse.down) {\n\t\t\t\ttool._moveCount = -1;\n\t\t\t\ttool._downPoint = pt;\n\t\t\t\ttool._downCount++;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction emit() {\n\t\t\tif (responds) {\n\t\t\t\tcalled = tool.emit(type, new ToolEvent(tool, type, event))\n\t\t\t\t\t\t|| called;\n\t\t\t}\n\t\t}\n\n\t\tif (mouse.down) {\n\t\t\tupdate();\n\t\t\temit();\n\t\t} else if (mouse.up) {\n\t\t\tupdate(null, maxDistance);\n\t\t\temit();\n\t\t} else if (responds) {\n\t\t\twhile (update(minDistance, maxDistance))\n\t\t\t\temit();\n\t\t}\n\t\treturn called;\n\t}\n\n});\n\nvar Http = {\n\trequest: function(options) {\n\t\tvar xhr = new self.XMLHttpRequest();\n\t\txhr.open((options.method || 'get').toUpperCase(), options.url,\n\t\t\t\tBase.pick(options.async, true));\n\t\tif (options.mimeType)\n\t\t\txhr.overrideMimeType(options.mimeType);\n\t\txhr.onload = function() {\n\t\t\tvar status = xhr.status;\n\t\t\tif (status === 0 || status === 200) {\n\t\t\t\tif (options.onLoad) {\n\t\t\t\t\toptions.onLoad.call(xhr, xhr.responseText);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\txhr.onerror();\n\t\t\t}\n\t\t};\n\t\txhr.onerror = function() {\n\t\t\tvar status = xhr.status,\n\t\t\t\tmessage = 'Could not load \"' + options.url + '\" (Status: '\n\t\t\t\t\t\t+ status + ')';\n\t\t\tif (options.onError) {\n\t\t\t\toptions.onError(message, status);\n\t\t\t} else {\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\t\t};\n\t\treturn xhr.send(null);\n\t}\n};\n\nvar CanvasProvider = {\n\tcanvases: [],\n\n\tgetCanvas: function(width, height) {\n\t\tif (!window)\n\t\t\treturn null;\n\t\tvar canvas,\n\t\t\tclear = true;\n\t\tif (typeof width === 'object') {\n\t\t\theight = width.height;\n\t\t\twidth = width.width;\n\t\t}\n\t\tif (this.canvases.length) {\n\t\t\tcanvas = this.canvases.pop();\n\t\t} else {\n\t\t\tcanvas = document.createElement('canvas');\n\t\t\tclear = false;\n\t\t}\n\t\tvar ctx = canvas.getContext('2d');\n\t\tif (!ctx) {\n\t\t\tthrow new Error('Canvas ' + canvas +\n\t\t\t\t\t' is unable toprovide a 2D context.');\n\t\t}\n\t\tif (canvas.width === width && canvas.height === height) {\n\t\t\tif (clear)\n\t\t\t\tctx.clearRect(0, 0, width + 1, height + 1);\n\t\t} else {\n\t\t\tcanvas.width = width;\n\t\t\tcanvas.height = height;\n\t\t}\n\t\tctx.save();\n\t\treturn canvas;\n\t},\n\n\tgetContext: function(width, height) {\n\t\tvar canvas = this.getCanvas(width, height);\n\t\treturn canvas ? canvas.getContext('2d') : null;\n\t},\n\n\trelease: function(obj) {\n\t\tvar canvas = obj && obj.canvas ? obj.canvas : obj;\n\t\tif (canvas && canvas.getContext) {\n\t\t\tcanvas.getContext('2d').restore();\n\t\t\tthis.canvases.push(canvas);\n\t\t}\n\t}\n};\n\nvar BlendMode = new function() {\n\tvar min = Math.min,\n\t\tmax = Math.max,\n\t\tabs = Math.abs,\n\t\tsr, sg, sb, sa,\n\t\tbr, bg, bb, ba,\n\t\tdr, dg, db;\n\n\tfunction getLum(r, g, b) {\n\t\treturn 0.2989 * r + 0.587 * g + 0.114 * b;\n\t}\n\n\tfunction setLum(r, g, b, l) {\n\t\tvar d = l - getLum(r, g, b);\n\t\tdr = r + d;\n\t\tdg = g + d;\n\t\tdb = b + d;\n\t\tvar l = getLum(dr, dg, db),\n\t\t\tmn = min(dr, dg, db),\n\t\t\tmx = max(dr, dg, db);\n\t\tif (mn < 0) {\n\t\t\tvar lmn = l - mn;\n\t\t\tdr = l + (dr - l) * l / lmn;\n\t\t\tdg = l + (dg - l) * l / lmn;\n\t\t\tdb = l + (db - l) * l / lmn;\n\t\t}\n\t\tif (mx > 255) {\n\t\t\tvar ln = 255 - l,\n\t\t\t\tmxl = mx - l;\n\t\t\tdr = l + (dr - l) * ln / mxl;\n\t\t\tdg = l + (dg - l) * ln / mxl;\n\t\t\tdb = l + (db - l) * ln / mxl;\n\t\t}\n\t}\n\n\tfunction getSat(r, g, b) {\n\t\treturn max(r, g, b) - min(r, g, b);\n\t}\n\n\tfunction setSat(r, g, b, s) {\n\t\tvar col = [r, g, b],\n\t\t\tmx = max(r, g, b),\n\t\t\tmn = min(r, g, b),\n\t\t\tmd;\n\t\tmn = mn === r ? 0 : mn === g ? 1 : 2;\n\t\tmx = mx === r ? 0 : mx === g ? 1 : 2;\n\t\tmd = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;\n\t\tif (col[mx] > col[mn]) {\n\t\t\tcol[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);\n\t\t\tcol[mx] = s;\n\t\t} else {\n\t\t\tcol[md] = col[mx] = 0;\n\t\t}\n\t\tcol[mn] = 0;\n\t\tdr = col[0];\n\t\tdg = col[1];\n\t\tdb = col[2];\n\t}\n\n\tvar modes = {\n\t\tmultiply: function() {\n\t\t\tdr = br * sr / 255;\n\t\t\tdg = bg * sg / 255;\n\t\t\tdb = bb * sb / 255;\n\t\t},\n\n\t\tscreen: function() {\n\t\t\tdr = br + sr - (br * sr / 255);\n\t\t\tdg = bg + sg - (bg * sg / 255);\n\t\t\tdb = bb + sb - (bb * sb / 255);\n\t\t},\n\n\t\toverlay: function() {\n\t\t\tdr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;\n\t\t\tdg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;\n\t\t\tdb = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;\n\t\t},\n\n\t\t'soft-light': function() {\n\t\t\tvar t = sr * br / 255;\n\t\t\tdr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;\n\t\t\tt = sg * bg / 255;\n\t\t\tdg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;\n\t\t\tt = sb * bb / 255;\n\t\t\tdb = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;\n\t\t},\n\n\t\t'hard-light': function() {\n\t\t\tdr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;\n\t\t\tdg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;\n\t\t\tdb = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;\n\t\t},\n\n\t\t'color-dodge': function() {\n\t\t\tdr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));\n\t\t\tdg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));\n\t\t\tdb = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));\n\t\t},\n\n\t\t'color-burn': function() {\n\t\t\tdr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);\n\t\t\tdg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);\n\t\t\tdb = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);\n\t\t},\n\n\t\tdarken: function() {\n\t\t\tdr = br < sr ? br : sr;\n\t\t\tdg = bg < sg ? bg : sg;\n\t\t\tdb = bb < sb ? bb : sb;\n\t\t},\n\n\t\tlighten: function() {\n\t\t\tdr = br > sr ? br : sr;\n\t\t\tdg = bg > sg ? bg : sg;\n\t\t\tdb = bb > sb ? bb : sb;\n\t\t},\n\n\t\tdifference: function() {\n\t\t\tdr = br - sr;\n\t\t\tif (dr < 0)\n\t\t\t\tdr = -dr;\n\t\t\tdg = bg - sg;\n\t\t\tif (dg < 0)\n\t\t\t\tdg = -dg;\n\t\t\tdb = bb - sb;\n\t\t\tif (db < 0)\n\t\t\t\tdb = -db;\n\t\t},\n\n\t\texclusion: function() {\n\t\t\tdr = br + sr * (255 - br - br) / 255;\n\t\t\tdg = bg + sg * (255 - bg - bg) / 255;\n\t\t\tdb = bb + sb * (255 - bb - bb) / 255;\n\t\t},\n\n\t\thue: function() {\n\t\t\tsetSat(sr, sg, sb, getSat(br, bg, bb));\n\t\t\tsetLum(dr, dg, db, getLum(br, bg, bb));\n\t\t},\n\n\t\tsaturation: function() {\n\t\t\tsetSat(br, bg, bb, getSat(sr, sg, sb));\n\t\t\tsetLum(dr, dg, db, getLum(br, bg, bb));\n\t\t},\n\n\t\tluminosity: function() {\n\t\t\tsetLum(br, bg, bb, getLum(sr, sg, sb));\n\t\t},\n\n\t\tcolor: function() {\n\t\t\tsetLum(sr, sg, sb, getLum(br, bg, bb));\n\t\t},\n\n\t\tadd: function() {\n\t\t\tdr = min(br + sr, 255);\n\t\t\tdg = min(bg + sg, 255);\n\t\t\tdb = min(bb + sb, 255);\n\t\t},\n\n\t\tsubtract: function() {\n\t\t\tdr = max(br - sr, 0);\n\t\t\tdg = max(bg - sg, 0);\n\t\t\tdb = max(bb - sb, 0);\n\t\t},\n\n\t\taverage: function() {\n\t\t\tdr = (br + sr) / 2;\n\t\t\tdg = (bg + sg) / 2;\n\t\t\tdb = (bb + sb) / 2;\n\t\t},\n\n\t\tnegation: function() {\n\t\t\tdr = 255 - abs(255 - sr - br);\n\t\t\tdg = 255 - abs(255 - sg - bg);\n\t\t\tdb = 255 - abs(255 - sb - bb);\n\t\t}\n\t};\n\n\tvar nativeModes = this.nativeModes = Base.each([\n\t\t'source-over', 'source-in', 'source-out', 'source-atop',\n\t\t'destination-over', 'destination-in', 'destination-out',\n\t\t'destination-atop', 'lighter', 'darker', 'copy', 'xor'\n\t], function(mode) {\n\t\tthis[mode] = true;\n\t}, {});\n\n\tvar ctx = CanvasProvider.getContext(1, 1);\n\tif (ctx) {\n\t\tBase.each(modes, function(func, mode) {\n\t\t\tvar darken = mode === 'darken',\n\t\t\t\tok = false;\n\t\t\tctx.save();\n\t\t\ttry {\n\t\t\t\tctx.fillStyle = darken ? '#300' : '#a00';\n\t\t\t\tctx.fillRect(0, 0, 1, 1);\n\t\t\t\tctx.globalCompositeOperation = mode;\n\t\t\t\tif (ctx.globalCompositeOperation === mode) {\n\t\t\t\t\tctx.fillStyle = darken ? '#a00' : '#300';\n\t\t\t\t\tctx.fillRect(0, 0, 1, 1);\n\t\t\t\t\tok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken\n\t\t\t\t\t\t\t? 170 : 51;\n\t\t\t\t}\n\t\t\t} catch (e) {}\n\t\t\tctx.restore();\n\t\t\tnativeModes[mode] = ok;\n\t\t});\n\t\tCanvasProvider.release(ctx);\n\t}\n\n\tthis.process = function(mode, srcContext, dstContext, alpha, offset) {\n\t\tvar srcCanvas = srcContext.canvas,\n\t\t\tnormal = mode === 'normal';\n\t\tif (normal || nativeModes[mode]) {\n\t\t\tdstContext.save();\n\t\t\tdstContext.setTransform(1, 0, 0, 1, 0, 0);\n\t\t\tdstContext.globalAlpha = alpha;\n\t\t\tif (!normal)\n\t\t\t\tdstContext.globalCompositeOperation = mode;\n\t\t\tdstContext.drawImage(srcCanvas, offset.x, offset.y);\n\t\t\tdstContext.restore();\n\t\t} else {\n\t\t\tvar process = modes[mode];\n\t\t\tif (!process)\n\t\t\t\treturn;\n\t\t\tvar dstData = dstContext.getImageData(offset.x, offset.y,\n\t\t\t\t\tsrcCanvas.width, srcCanvas.height),\n\t\t\t\tdst = dstData.data,\n\t\t\t\tsrc = srcContext.getImageData(0, 0,\n\t\t\t\t\tsrcCanvas.width, srcCanvas.height).data;\n\t\t\tfor (var i = 0, l = dst.length; i < l; i += 4) {\n\t\t\t\tsr = src[i];\n\t\t\t\tbr = dst[i];\n\t\t\t\tsg = src[i + 1];\n\t\t\t\tbg = dst[i + 1];\n\t\t\t\tsb = src[i + 2];\n\t\t\t\tbb = dst[i + 2];\n\t\t\t\tsa = src[i + 3];\n\t\t\t\tba = dst[i + 3];\n\t\t\t\tprocess();\n\t\t\t\tvar a1 = sa * alpha / 255,\n\t\t\t\t\ta2 = 1 - a1;\n\t\t\t\tdst[i] = a1 * dr + a2 * br;\n\t\t\t\tdst[i + 1] = a1 * dg + a2 * bg;\n\t\t\t\tdst[i + 2] = a1 * db + a2 * bb;\n\t\t\t\tdst[i + 3] = sa * alpha + a2 * ba;\n\t\t\t}\n\t\t\tdstContext.putImageData(dstData, offset.x, offset.y);\n\t\t}\n\t};\n};\n\nvar SvgElement = new function() {\n\tvar svg = 'http://www.w3.org/2000/svg',\n\t\txmlns = 'http://www.w3.org/2000/xmlns',\n\t\txlink = 'http://www.w3.org/1999/xlink',\n\t\tattributeNamespace = {\n\t\t\thref: xlink,\n\t\t\txlink: xmlns,\n\t\t\txmlns: xmlns + '/',\n\t\t\t'xmlns:xlink': xmlns + '/'\n\t\t};\n\n\tfunction create(tag, attributes, formatter) {\n\t\treturn set(document.createElementNS(svg, tag), attributes, formatter);\n\t}\n\n\tfunction get(node, name) {\n\t\tvar namespace = attributeNamespace[name],\n\t\t\tvalue = namespace\n\t\t\t\t? node.getAttributeNS(namespace, name)\n\t\t\t\t: node.getAttribute(name);\n\t\treturn value === 'null' ? null : value;\n\t}\n\n\tfunction set(node, attributes, formatter) {\n\t\tfor (var name in attributes) {\n\t\t\tvar value = attributes[name],\n\t\t\t\tnamespace = attributeNamespace[name];\n\t\t\tif (typeof value === 'number' && formatter)\n\t\t\t\tvalue = formatter.number(value);\n\t\t\tif (namespace) {\n\t\t\t\tnode.setAttributeNS(namespace, name, value);\n\t\t\t} else {\n\t\t\t\tnode.setAttribute(name, value);\n\t\t\t}\n\t\t}\n\t\treturn node;\n\t}\n\n\treturn {\n\t\tsvg: svg,\n\t\txmlns: xmlns,\n\t\txlink: xlink,\n\n\t\tcreate: create,\n\t\tget: get,\n\t\tset: set\n\t};\n};\n\nvar SvgStyles = Base.each({\n\tfillColor: ['fill', 'color'],\n\tfillRule: ['fill-rule', 'string'],\n\tstrokeColor: ['stroke', 'color'],\n\tstrokeWidth: ['stroke-width', 'number'],\n\tstrokeCap: ['stroke-linecap', 'string'],\n\tstrokeJoin: ['stroke-linejoin', 'string'],\n\tstrokeScaling: ['vector-effect', 'lookup', {\n\t\ttrue: 'none',\n\t\tfalse: 'non-scaling-stroke'\n\t}, function(item, value) {\n\t\treturn !value\n\t\t\t\t&& (item instanceof PathItem\n\t\t\t\t\t|| item instanceof Shape\n\t\t\t\t\t|| item instanceof TextItem);\n\t}],\n\tmiterLimit: ['stroke-miterlimit', 'number'],\n\tdashArray: ['stroke-dasharray', 'array'],\n\tdashOffset: ['stroke-dashoffset', 'number'],\n\tfontFamily: ['font-family', 'string'],\n\tfontWeight: ['font-weight', 'string'],\n\tfontSize: ['font-size', 'number'],\n\tjustification: ['text-anchor', 'lookup', {\n\t\tleft: 'start',\n\t\tcenter: 'middle',\n\t\tright: 'end'\n\t}],\n\topacity: ['opacity', 'number'],\n\tblendMode: ['mix-blend-mode', 'style']\n}, function(entry, key) {\n\tvar part = Base.capitalize(key),\n\t\tlookup = entry[2];\n\tthis[key] = {\n\t\ttype: entry[1],\n\t\tproperty: key,\n\t\tattribute: entry[0],\n\t\ttoSVG: lookup,\n\t\tfromSVG: lookup && Base.each(lookup, function(value, name) {\n\t\t\tthis[value] = name;\n\t\t}, {}),\n\t\texportFilter: entry[3],\n\t\tget: 'get' + part,\n\t\tset: 'set' + part\n\t};\n}, {});\n\nnew function() {\n\tvar formatter;\n\n\tfunction getTransform(matrix, coordinates, center) {\n\t\tvar attrs = new Base(),\n\t\t\ttrans = matrix.getTranslation();\n\t\tif (coordinates) {\n\t\t\tmatrix = matrix._shiftless();\n\t\t\tvar point = matrix._inverseTransform(trans);\n\t\t\tattrs[center ? 'cx' : 'x'] = point.x;\n\t\t\tattrs[center ? 'cy' : 'y'] = point.y;\n\t\t\ttrans = null;\n\t\t}\n\t\tif (!matrix.isIdentity()) {\n\t\t\tvar decomposed = matrix.decompose();\n\t\t\tif (decomposed) {\n\t\t\t\tvar parts = [],\n\t\t\t\t\tangle = decomposed.rotation,\n\t\t\t\t\tscale = decomposed.scaling,\n\t\t\t\t\tskew = decomposed.skewing;\n\t\t\t\tif (trans && !trans.isZero())\n\t\t\t\t\tparts.push('translate(' + formatter.point(trans) + ')');\n\t\t\t\tif (angle)\n\t\t\t\t\tparts.push('rotate(' + formatter.number(angle) + ')');\n\t\t\t\tif (!Numerical.isZero(scale.x - 1)\n\t\t\t\t\t\t|| !Numerical.isZero(scale.y - 1))\n\t\t\t\t\tparts.push('scale(' + formatter.point(scale) +')');\n\t\t\t\tif (skew && skew.x)\n\t\t\t\t\tparts.push('skewX(' + formatter.number(skew.x) + ')');\n\t\t\t\tif (skew && skew.y)\n\t\t\t\t\tparts.push('skewY(' + formatter.number(skew.y) + ')');\n\t\t\t\tattrs.transform = parts.join(' ');\n\t\t\t} else {\n\t\t\t\tattrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';\n\t\t\t}\n\t\t}\n\t\treturn attrs;\n\t}\n\n\tfunction exportGroup(item, options) {\n\t\tvar attrs = getTransform(item._matrix),\n\t\t\tchildren = item._children;\n\t\tvar node = SvgElement.create('g', attrs, formatter);\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i];\n\t\t\tvar childNode = exportSVG(child, options);\n\t\t\tif (childNode) {\n\t\t\t\tif (child.isClipMask()) {\n\t\t\t\t\tvar clip = SvgElement.create('clipPath');\n\t\t\t\t\tclip.appendChild(childNode);\n\t\t\t\t\tsetDefinition(child, clip, 'clip');\n\t\t\t\t\tSvgElement.set(node, {\n\t\t\t\t\t\t'clip-path': 'url(#' + clip.id + ')'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tnode.appendChild(childNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn node;\n\t}\n\n\tfunction exportRaster(item, options) {\n\t\tvar attrs = getTransform(item._matrix, true),\n\t\t\tsize = item.getSize(),\n\t\t\timage = item.getImage();\n\t\tattrs.x -= size.width / 2;\n\t\tattrs.y -= size.height / 2;\n\t\tattrs.width = size.width;\n\t\tattrs.height = size.height;\n\t\tattrs.href = options.embedImages === false && image && image.src\n\t\t\t\t|| item.toDataURL();\n\t\treturn SvgElement.create('image', attrs, formatter);\n\t}\n\n\tfunction exportPath(item, options) {\n\t\tvar matchShapes = options.matchShapes;\n\t\tif (matchShapes) {\n\t\t\tvar shape = item.toShape(false);\n\t\t\tif (shape)\n\t\t\t\treturn exportShape(shape, options);\n\t\t}\n\t\tvar segments = item._segments,\n\t\t\tlength = segments.length,\n\t\t\ttype,\n\t\t\tattrs = getTransform(item._matrix);\n\t\tif (matchShapes && length >= 2 && !item.hasHandles()) {\n\t\t\tif (length > 2) {\n\t\t\t\ttype = item._closed ? 'polygon' : 'polyline';\n\t\t\t\tvar parts = [];\n\t\t\t\tfor(var i = 0; i < length; i++)\n\t\t\t\t\tparts.push(formatter.point(segments[i]._point));\n\t\t\t\tattrs.points = parts.join(' ');\n\t\t\t} else {\n\t\t\t\ttype = 'line';\n\t\t\t\tvar start = segments[0]._point,\n\t\t\t\t\tend = segments[1]._point;\n\t\t\t\tattrs.set({\n\t\t\t\t\tx1: start.x,\n\t\t\t\t\ty1: start.y,\n\t\t\t\t\tx2: end.x,\n\t\t\t\t\ty2: end.y\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\ttype = 'path';\n\t\t\tattrs.d = item.getPathData(null, options.precision);\n\t\t}\n\t\treturn SvgElement.create(type, attrs, formatter);\n\t}\n\n\tfunction exportShape(item) {\n\t\tvar type = item._type,\n\t\t\tradius = item._radius,\n\t\t\tattrs = getTransform(item._matrix, true, type !== 'rectangle');\n\t\tif (type === 'rectangle') {\n\t\t\ttype = 'rect';\n\t\t\tvar size = item._size,\n\t\t\t\twidth = size.width,\n\t\t\t\theight = size.height;\n\t\t\tattrs.x -= width / 2;\n\t\t\tattrs.y -= height / 2;\n\t\t\tattrs.width = width;\n\t\t\tattrs.height = height;\n\t\t\tif (radius.isZero())\n\t\t\t\tradius = null;\n\t\t}\n\t\tif (radius) {\n\t\t\tif (type === 'circle') {\n\t\t\t\tattrs.r = radius;\n\t\t\t} else {\n\t\t\t\tattrs.rx = radius.width;\n\t\t\t\tattrs.ry = radius.height;\n\t\t\t}\n\t\t}\n\t\treturn SvgElement.create(type, attrs, formatter);\n\t}\n\n\tfunction exportCompoundPath(item, options) {\n\t\tvar attrs = getTransform(item._matrix);\n\t\tvar data = item.getPathData(null, options.precision);\n\t\tif (data)\n\t\t\tattrs.d = data;\n\t\treturn SvgElement.create('path', attrs, formatter);\n\t}\n\n\tfunction exportSymbolItem(item, options) {\n\t\tvar attrs = getTransform(item._matrix, true),\n\t\t\tdefinition = item._definition,\n\t\t\tnode = getDefinition(definition, 'symbol'),\n\t\t\tdefinitionItem = definition._item,\n\t\t\tbounds = definitionItem.getBounds();\n\t\tif (!node) {\n\t\t\tnode = SvgElement.create('symbol', {\n\t\t\t\tviewBox: formatter.rectangle(bounds)\n\t\t\t});\n\t\t\tnode.appendChild(exportSVG(definitionItem, options));\n\t\t\tsetDefinition(definition, node, 'symbol');\n\t\t}\n\t\tattrs.href = '#' + node.id;\n\t\tattrs.x += bounds.x;\n\t\tattrs.y += bounds.y;\n\t\tattrs.width = bounds.width;\n\t\tattrs.height = bounds.height;\n\t\tattrs.overflow = 'visible';\n\t\treturn SvgElement.create('use', attrs, formatter);\n\t}\n\n\tfunction exportGradient(color) {\n\t\tvar gradientNode = getDefinition(color, 'color');\n\t\tif (!gradientNode) {\n\t\t\tvar gradient = color.getGradient(),\n\t\t\t\tradial = gradient._radial,\n\t\t\t\torigin = color.getOrigin(),\n\t\t\t\tdestination = color.getDestination(),\n\t\t\t\tattrs;\n\t\t\tif (radial) {\n\t\t\t\tattrs = {\n\t\t\t\t\tcx: origin.x,\n\t\t\t\t\tcy: origin.y,\n\t\t\t\t\tr: origin.getDistance(destination)\n\t\t\t\t};\n\t\t\t\tvar highlight = color.getHighlight();\n\t\t\t\tif (highlight) {\n\t\t\t\t\tattrs.fx = highlight.x;\n\t\t\t\t\tattrs.fy = highlight.y;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tattrs = {\n\t\t\t\t\tx1: origin.x,\n\t\t\t\t\ty1: origin.y,\n\t\t\t\t\tx2: destination.x,\n\t\t\t\t\ty2: destination.y\n\t\t\t\t};\n\t\t\t}\n\t\t\tattrs.gradientUnits = 'userSpaceOnUse';\n\t\t\tgradientNode = SvgElement.create((radial ? 'radial' : 'linear')\n\t\t\t\t\t+ 'Gradient', attrs, formatter);\n\t\t\tvar stops = gradient._stops;\n\t\t\tfor (var i = 0, l = stops.length; i < l; i++) {\n\t\t\t\tvar stop = stops[i],\n\t\t\t\t\tstopColor = stop._color,\n\t\t\t\t\talpha = stopColor.getAlpha();\n\t\t\t\tattrs = {\n\t\t\t\t\toffset: stop._offset || i / (l - 1)\n\t\t\t\t};\n\t\t\t\tif (stopColor)\n\t\t\t\t\tattrs['stop-color'] = stopColor.toCSS(true);\n\t\t\t\tif (alpha < 1)\n\t\t\t\t\tattrs['stop-opacity'] = alpha;\n\t\t\t\tgradientNode.appendChild(\n\t\t\t\t\t\tSvgElement.create('stop', attrs, formatter));\n\t\t\t}\n\t\t\tsetDefinition(color, gradientNode, 'color');\n\t\t}\n\t\treturn 'url(#' + gradientNode.id + ')';\n\t}\n\n\tfunction exportText(item) {\n\t\tvar node = SvgElement.create('text', getTransform(item._matrix, true),\n\t\t\t\tformatter);\n\t\tnode.textContent = item._content;\n\t\treturn node;\n\t}\n\n\tvar exporters = {\n\t\tGroup: exportGroup,\n\t\tLayer: exportGroup,\n\t\tRaster: exportRaster,\n\t\tPath: exportPath,\n\t\tShape: exportShape,\n\t\tCompoundPath: exportCompoundPath,\n\t\tSymbolItem: exportSymbolItem,\n\t\tPointText: exportText\n\t};\n\n\tfunction applyStyle(item, node, isRoot) {\n\t\tvar attrs = {},\n\t\t\tparent = !isRoot && item.getParent(),\n\t\t\tstyle = [];\n\n\t\tif (item._name != null)\n\t\t\tattrs.id = item._name;\n\n\t\tBase.each(SvgStyles, function(entry) {\n\t\t\tvar get = entry.get,\n\t\t\t\ttype = entry.type,\n\t\t\t\tvalue = item[get]();\n\t\t\tif (entry.exportFilter\n\t\t\t\t\t? entry.exportFilter(item, value)\n\t\t\t\t\t: !parent || !Base.equals(parent[get](), value)) {\n\t\t\t\tif (type === 'color' && value != null) {\n\t\t\t\t\tvar alpha = value.getAlpha();\n\t\t\t\t\tif (alpha < 1)\n\t\t\t\t\t\tattrs[entry.attribute + '-opacity'] = alpha;\n\t\t\t\t}\n\t\t\t\tif (type === 'style') {\n\t\t\t\t\tstyle.push(entry.attribute + ': ' + value);\n\t\t\t\t} else {\n\t\t\t\t\tattrs[entry.attribute] = value == null ? 'none'\n\t\t\t\t\t\t\t: type === 'color' ? value.gradient\n\t\t\t\t\t\t\t\t? exportGradient(value, item)\n\t\t\t\t\t\t\t\t: value.toCSS(true)\n\t\t\t\t\t\t\t: type === 'array' ? value.join(',')\n\t\t\t\t\t\t\t: type === 'lookup' ? entry.toSVG[value]\n\t\t\t\t\t\t\t: value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif (style.length)\n\t\t\tattrs.style = style.join(';');\n\n\t\tif (attrs.opacity === 1)\n\t\t\tdelete attrs.opacity;\n\n\t\tif (!item._visible)\n\t\t\tattrs.visibility = 'hidden';\n\n\t\treturn SvgElement.set(node, attrs, formatter);\n\t}\n\n\tvar definitions;\n\tfunction getDefinition(item, type) {\n\t\tif (!definitions)\n\t\t\tdefinitions = { ids: {}, svgs: {} };\n\t\tvar id = item._id || item.__id || (item.__id = UID.get('svg'));\n\t\treturn item && definitions.svgs[type + '-' + id];\n\t}\n\n\tfunction setDefinition(item, node, type) {\n\t\tif (!definitions)\n\t\t\tgetDefinition();\n\t\tvar typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;\n\t\tnode.id = type + '-' + typeId;\n\t\tdefinitions.svgs[type + '-' + (item._id || item.__id)] = node;\n\t}\n\n\tfunction exportDefinitions(node, options) {\n\t\tvar svg = node,\n\t\t\tdefs = null;\n\t\tif (definitions) {\n\t\t\tsvg = node.nodeName.toLowerCase() === 'svg' && node;\n\t\t\tfor (var i in definitions.svgs) {\n\t\t\t\tif (!defs) {\n\t\t\t\t\tif (!svg) {\n\t\t\t\t\t\tsvg = SvgElement.create('svg');\n\t\t\t\t\t\tsvg.appendChild(node);\n\t\t\t\t\t}\n\t\t\t\t\tdefs = svg.insertBefore(SvgElement.create('defs'),\n\t\t\t\t\t\t\tsvg.firstChild);\n\t\t\t\t}\n\t\t\t\tdefs.appendChild(definitions.svgs[i]);\n\t\t\t}\n\t\t\tdefinitions = null;\n\t\t}\n\t\treturn options.asString\n\t\t\t\t? new self.XMLSerializer().serializeToString(svg)\n\t\t\t\t: svg;\n\t}\n\n\tfunction exportSVG(item, options, isRoot) {\n\t\tvar exporter = exporters[item._class],\n\t\t\tnode = exporter && exporter(item, options);\n\t\tif (node) {\n\t\t\tvar onExport = options.onExport;\n\t\t\tif (onExport)\n\t\t\t\tnode = onExport(item, node, options) || node;\n\t\t\tvar data = JSON.stringify(item._data);\n\t\t\tif (data && data !== '{}' && data !== 'null')\n\t\t\t\tnode.setAttribute('data-paper-data', data);\n\t\t}\n\t\treturn node && applyStyle(item, node, isRoot);\n\t}\n\n\tfunction setOptions(options) {\n\t\tif (!options)\n\t\t\toptions = {};\n\t\tformatter = new Formatter(options.precision);\n\t\treturn options;\n\t}\n\n\tItem.inject({\n\t\texportSVG: function(options) {\n\t\t\toptions = setOptions(options);\n\t\t\treturn exportDefinitions(exportSVG(this, options, true), options);\n\t\t}\n\t});\n\n\tProject.inject({\n\t\texportSVG: function(options) {\n\t\t\toptions = setOptions(options);\n\t\t\tvar children = this._children,\n\t\t\t\tview = this.getView(),\n\t\t\t\tbounds = Base.pick(options.bounds, 'view'),\n\t\t\t\tmx = options.matrix || bounds === 'view' && view._matrix,\n\t\t\t\tmatrix = mx && Matrix.read([mx]),\n\t\t\t\trect = bounds === 'view'\n\t\t\t\t\t? new Rectangle([0, 0], view.getViewSize())\n\t\t\t\t\t: bounds === 'content'\n\t\t\t\t\t\t? Item._getBounds(children, matrix, { stroke: true })\n\t\t\t\t\t\t: Rectangle.read([bounds], 0, { readNull: true }),\n\t\t\t\tattrs = {\n\t\t\t\t\tversion: '1.1',\n\t\t\t\t\txmlns: SvgElement.svg,\n\t\t\t\t\t'xmlns:xlink': SvgElement.xlink,\n\t\t\t\t};\n\t\t\tif (rect) {\n\t\t\t\tattrs.width = rect.width;\n\t\t\t\tattrs.height = rect.height;\n\t\t\t\tif (rect.x || rect.y)\n\t\t\t\t\tattrs.viewBox = formatter.rectangle(rect);\n\t\t\t}\n\t\t\tvar node = SvgElement.create('svg', attrs, formatter),\n\t\t\t\tparent = node;\n\t\t\tif (matrix && !matrix.isIdentity()) {\n\t\t\t\tparent = node.appendChild(SvgElement.create('g',\n\t\t\t\t\t\tgetTransform(matrix), formatter));\n\t\t\t}\n\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\tparent.appendChild(exportSVG(children[i], options, true));\n\t\t\t}\n\t\t\treturn exportDefinitions(node, options);\n\t\t}\n\t});\n};\n\nnew function() {\n\n\tvar definitions = {},\n\t\trootSize;\n\n\tfunction getValue(node, name, isString, allowNull, allowPercent) {\n\t\tvar value = SvgElement.get(node, name),\n\t\t\tres = value == null\n\t\t\t\t? allowNull\n\t\t\t\t\t? null\n\t\t\t\t\t: isString ? '' : 0\n\t\t\t\t: isString\n\t\t\t\t\t? value\n\t\t\t\t\t: parseFloat(value);\n\t\treturn /%\\s*$/.test(value)\n\t\t\t? (res / 100) * (allowPercent ? 1\n\t\t\t\t: rootSize[/x|^width/.test(name) ? 'width' : 'height'])\n\t\t\t: res;\n\t}\n\n\tfunction getPoint(node, x, y, allowNull, allowPercent) {\n\t\tx = getValue(node, x || 'x', false, allowNull, allowPercent);\n\t\ty = getValue(node, y || 'y', false, allowNull, allowPercent);\n\t\treturn allowNull && (x == null || y == null) ? null\n\t\t\t\t: new Point(x, y);\n\t}\n\n\tfunction getSize(node, w, h, allowNull, allowPercent) {\n\t\tw = getValue(node, w || 'width', false, allowNull, allowPercent);\n\t\th = getValue(node, h || 'height', false, allowNull, allowPercent);\n\t\treturn allowNull && (w == null || h == null) ? null\n\t\t\t\t: new Size(w, h);\n\t}\n\n\tfunction convertValue(value, type, lookup) {\n\t\treturn value === 'none' ? null\n\t\t\t\t: type === 'number' ? parseFloat(value)\n\t\t\t\t: type === 'array' ?\n\t\t\t\t\tvalue ? value.split(/[\\s,]+/g).map(parseFloat) : []\n\t\t\t\t: type === 'color' ? getDefinition(value) || value\n\t\t\t\t: type === 'lookup' ? lookup[value]\n\t\t\t\t: value;\n\t}\n\n\tfunction importGroup(node, type, options, isRoot) {\n\t\tvar nodes = node.childNodes,\n\t\t\tisClip = type === 'clippath',\n\t\t\tisDefs = type === 'defs',\n\t\t\titem = new Group(),\n\t\t\tproject = item._project,\n\t\t\tcurrentStyle = project._currentStyle,\n\t\t\tchildren = [];\n\t\tif (!isClip && !isDefs) {\n\t\t\titem = applyAttributes(item, node, isRoot);\n\t\t\tproject._currentStyle = item._style.clone();\n\t\t}\n\t\tif (isRoot) {\n\t\t\tvar defs = node.querySelectorAll('defs');\n\t\t\tfor (var i = 0, l = defs.length; i < l; i++) {\n\t\t\t\timportNode(defs[i], options, false);\n\t\t\t}\n\t\t}\n\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\tvar childNode = nodes[i],\n\t\t\t\tchild;\n\t\t\tif (childNode.nodeType === 1\n\t\t\t\t\t&& !/^defs$/i.test(childNode.nodeName)\n\t\t\t\t\t&& (child = importNode(childNode, options, false))\n\t\t\t\t\t&& !(child instanceof SymbolDefinition))\n\t\t\t\tchildren.push(child);\n\t\t}\n\t\titem.addChildren(children);\n\t\tif (isClip)\n\t\t\titem = applyAttributes(item.reduce(), node, isRoot);\n\t\tproject._currentStyle = currentStyle;\n\t\tif (isClip || isDefs) {\n\t\t\titem.remove();\n\t\t\titem = null;\n\t\t}\n\t\treturn item;\n\t}\n\n\tfunction importPoly(node, type) {\n\t\tvar coords = node.getAttribute('points').match(\n\t\t\t\t\t/[+-]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][+-]?\\d+)?/g),\n\t\t\tpoints = [];\n\t\tfor (var i = 0, l = coords.length; i < l; i += 2)\n\t\t\tpoints.push(new Point(\n\t\t\t\t\tparseFloat(coords[i]),\n\t\t\t\t\tparseFloat(coords[i + 1])));\n\t\tvar path = new Path(points);\n\t\tif (type === 'polygon')\n\t\t\tpath.closePath();\n\t\treturn path;\n\t}\n\n\tfunction importPath(node) {\n\t\treturn PathItem.create(node.getAttribute('d'));\n\t}\n\n\tfunction importGradient(node, type) {\n\t\tvar id = (getValue(node, 'href', true) || '').substring(1),\n\t\t\tradial = type === 'radialgradient',\n\t\t\tgradient;\n\t\tif (id) {\n\t\t\tgradient = definitions[id].getGradient();\n\t\t\tif (gradient._radial ^ radial) {\n\t\t\t\tgradient = gradient.clone();\n\t\t\t\tgradient._radial = radial;\n\t\t\t}\n\t\t} else {\n\t\t\tvar nodes = node.childNodes,\n\t\t\t\tstops = [];\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tvar child = nodes[i];\n\t\t\t\tif (child.nodeType === 1)\n\t\t\t\t\tstops.push(applyAttributes(new GradientStop(), child));\n\t\t\t}\n\t\t\tgradient = new Gradient(stops, radial);\n\t\t}\n\t\tvar origin, destination, highlight,\n\t\t\tscaleToBounds = getValue(node, 'gradientUnits', true) !==\n\t\t\t\t'userSpaceOnUse';\n\t\tif (radial) {\n\t\t\torigin = getPoint(node, 'cx', 'cy', false, scaleToBounds);\n\t\t\tdestination = origin.add(\n\t\t\t\t\tgetValue(node, 'r', false, false, scaleToBounds), 0);\n\t\t\thighlight = getPoint(node, 'fx', 'fy', true, scaleToBounds);\n\t\t} else {\n\t\t\torigin = getPoint(node, 'x1', 'y1', false, scaleToBounds);\n\t\t\tdestination = getPoint(node, 'x2', 'y2', false, scaleToBounds);\n\t\t}\n\t\tvar color = applyAttributes(\n\t\t\t\tnew Color(gradient, origin, destination, highlight), node);\n\t\tcolor._scaleToBounds = scaleToBounds;\n\t\treturn null;\n\t}\n\n\tvar importers = {\n\t\t'#document': function (node, type, options, isRoot) {\n\t\t\tvar nodes = node.childNodes;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tvar child = nodes[i];\n\t\t\t\tif (child.nodeType === 1)\n\t\t\t\t\treturn importNode(child, options, isRoot);\n\t\t\t}\n\t\t},\n\t\tg: importGroup,\n\t\tsvg: importGroup,\n\t\tclippath: importGroup,\n\t\tpolygon: importPoly,\n\t\tpolyline: importPoly,\n\t\tpath: importPath,\n\t\tlineargradient: importGradient,\n\t\tradialgradient: importGradient,\n\n\t\timage: function (node) {\n\t\t\tvar raster = new Raster(getValue(node, 'href', true));\n\t\t\traster.on('load', function() {\n\t\t\t\tvar size = getSize(node);\n\t\t\t\tthis.setSize(size);\n\t\t\t\tvar center = this._matrix._transformPoint(\n\t\t\t\t\t\tgetPoint(node).add(size.divide(2)));\n\t\t\t\tthis.translate(center);\n\t\t\t});\n\t\t\treturn raster;\n\t\t},\n\n\t\tsymbol: function(node, type, options, isRoot) {\n\t\t\treturn new SymbolDefinition(\n\t\t\t\t\timportGroup(node, type, options, isRoot), true);\n\t\t},\n\n\t\tdefs: importGroup,\n\n\t\tuse: function(node) {\n\t\t\tvar id = (getValue(node, 'href', true) || '').substring(1),\n\t\t\t\tdefinition = definitions[id],\n\t\t\t\tpoint = getPoint(node);\n\t\t\treturn definition\n\t\t\t\t\t? definition instanceof SymbolDefinition\n\t\t\t\t\t\t? definition.place(point)\n\t\t\t\t\t\t: definition.clone().translate(point)\n\t\t\t\t\t: null;\n\t\t},\n\n\t\tcircle: function(node) {\n\t\t\treturn new Shape.Circle(\n\t\t\t\t\tgetPoint(node, 'cx', 'cy'),\n\t\t\t\t\tgetValue(node, 'r'));\n\t\t},\n\n\t\tellipse: function(node) {\n\t\t\treturn new Shape.Ellipse({\n\t\t\t\tcenter: getPoint(node, 'cx', 'cy'),\n\t\t\t\tradius: getSize(node, 'rx', 'ry')\n\t\t\t});\n\t\t},\n\n\t\trect: function(node) {\n\t\t\treturn new Shape.Rectangle(new Rectangle(\n\t\t\t\t\t\tgetPoint(node),\n\t\t\t\t\t\tgetSize(node)\n\t\t\t\t\t), getSize(node, 'rx', 'ry'));\n\t\t\t},\n\n\t\tline: function(node) {\n\t\t\treturn new Path.Line(\n\t\t\t\t\tgetPoint(node, 'x1', 'y1'),\n\t\t\t\t\tgetPoint(node, 'x2', 'y2'));\n\t\t},\n\n\t\ttext: function(node) {\n\t\t\tvar text = new PointText(getPoint(node).add(\n\t\t\t\t\tgetPoint(node, 'dx', 'dy')));\n\t\t\ttext.setContent(node.textContent.trim() || '');\n\t\t\treturn text;\n\t\t}\n\t};\n\n\tfunction applyTransform(item, value, name, node) {\n\t\tif (item.transform) {\n\t\t\tvar transforms = (node.getAttribute(name) || '').split(/\\)\\s*/g),\n\t\t\t\tmatrix = new Matrix();\n\t\t\tfor (var i = 0, l = transforms.length; i < l; i++) {\n\t\t\t\tvar transform = transforms[i];\n\t\t\t\tif (!transform)\n\t\t\t\t\tbreak;\n\t\t\t\tvar parts = transform.split(/\\(\\s*/),\n\t\t\t\t\tcommand = parts[0],\n\t\t\t\t\tv = parts[1].split(/[\\s,]+/g);\n\t\t\t\tfor (var j = 0, m = v.length; j < m; j++)\n\t\t\t\t\tv[j] = parseFloat(v[j]);\n\t\t\t\tswitch (command) {\n\t\t\t\tcase 'matrix':\n\t\t\t\t\tmatrix.append(\n\t\t\t\t\t\t\tnew Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'rotate':\n\t\t\t\t\tmatrix.rotate(v[0], v[1], v[2]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'translate':\n\t\t\t\t\tmatrix.translate(v[0], v[1]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'scale':\n\t\t\t\t\tmatrix.scale(v);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'skewX':\n\t\t\t\t\tmatrix.skew(v[0], 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'skewY':\n\t\t\t\t\tmatrix.skew(0, v[0]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\titem.transform(matrix);\n\t\t}\n\t}\n\n\tfunction applyOpacity(item, value, name) {\n\t\tvar key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor',\n\t\t\tcolor = item[key] && item[key]();\n\t\tif (color)\n\t\t\tcolor.setAlpha(parseFloat(value));\n\t}\n\n\tvar attributes = Base.set(Base.each(SvgStyles, function(entry) {\n\t\tthis[entry.attribute] = function(item, value) {\n\t\t\tif (item[entry.set]) {\n\t\t\t\titem[entry.set](convertValue(value, entry.type, entry.fromSVG));\n\t\t\t\tif (entry.type === 'color') {\n\t\t\t\t\tvar color = item[entry.get]();\n\t\t\t\t\tif (color) {\n\t\t\t\t\t\tif (color._scaleToBounds) {\n\t\t\t\t\t\t\tvar bounds = item.getBounds();\n\t\t\t\t\t\t\tcolor.transform(new Matrix()\n\t\t\t\t\t\t\t\t.translate(bounds.getPoint())\n\t\t\t\t\t\t\t\t.scale(bounds.getSize()));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (item instanceof Shape) {\n\t\t\t\t\t\t\tcolor.transform(new Matrix().translate(\n\t\t\t\t\t\t\t\titem.getPosition(true).negate()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}, {}), {\n\t\tid: function(item, value) {\n\t\t\tdefinitions[value] = item;\n\t\t\tif (item.setName)\n\t\t\t\titem.setName(value);\n\t\t},\n\n\t\t'clip-path': function(item, value) {\n\t\t\tvar clip = getDefinition(value);\n\t\t\tif (clip) {\n\t\t\t\tclip = clip.clone();\n\t\t\t\tclip.setClipMask(true);\n\t\t\t\tif (item instanceof Group) {\n\t\t\t\t\titem.insertChild(0, clip);\n\t\t\t\t} else {\n\t\t\t\t\treturn new Group(clip, item);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tgradientTransform: applyTransform,\n\t\ttransform: applyTransform,\n\n\t\t'fill-opacity': applyOpacity,\n\t\t'stroke-opacity': applyOpacity,\n\n\t\tvisibility: function(item, value) {\n\t\t\tif (item.setVisible)\n\t\t\t\titem.setVisible(value === 'visible');\n\t\t},\n\n\t\tdisplay: function(item, value) {\n\t\t\tif (item.setVisible)\n\t\t\t\titem.setVisible(value !== null);\n\t\t},\n\n\t\t'stop-color': function(item, value) {\n\t\t\tif (item.setColor)\n\t\t\t\titem.setColor(value);\n\t\t},\n\n\t\t'stop-opacity': function(item, value) {\n\t\t\tif (item._color)\n\t\t\t\titem._color.setAlpha(parseFloat(value));\n\t\t},\n\n\t\toffset: function(item, value) {\n\t\t\tif (item.setOffset) {\n\t\t\t\tvar percent = value.match(/(.*)%$/);\n\t\t\t\titem.setOffset(percent ? percent[1] / 100 : parseFloat(value));\n\t\t\t}\n\t\t},\n\n\t\tviewBox: function(item, value, name, node, styles) {\n\t\t\tvar rect = new Rectangle(convertValue(value, 'array')),\n\t\t\t\tsize = getSize(node, null, null, true),\n\t\t\t\tgroup,\n\t\t\t\tmatrix;\n\t\t\tif (item instanceof Group) {\n\t\t\t\tvar scale = size ? size.divide(rect.getSize()) : 1,\n\t\t\t\tmatrix = new Matrix().scale(scale)\n\t\t\t\t\t\t.translate(rect.getPoint().negate());\n\t\t\t\tgroup = item;\n\t\t\t} else if (item instanceof SymbolDefinition) {\n\t\t\t\tif (size)\n\t\t\t\t\trect.setSize(size);\n\t\t\t\tgroup = item._item;\n\t\t\t}\n\t\t\tif (group) {\n\t\t\t\tif (getAttribute(node, 'overflow', styles) !== 'visible') {\n\t\t\t\t\tvar clip = new Shape.Rectangle(rect);\n\t\t\t\t\tclip.setClipMask(true);\n\t\t\t\t\tgroup.addChild(clip);\n\t\t\t\t}\n\t\t\t\tif (matrix)\n\t\t\t\t\tgroup.transform(matrix);\n\t\t\t}\n\t\t}\n\t});\n\n\tfunction getAttribute(node, name, styles) {\n\t\tvar attr = node.attributes[name],\n\t\t\tvalue = attr && attr.value;\n\t\tif (!value) {\n\t\t\tvar style = Base.camelize(name);\n\t\t\tvalue = node.style[style];\n\t\t\tif (!value && styles.node[style] !== styles.parent[style])\n\t\t\t\tvalue = styles.node[style];\n\t\t}\n\t\treturn !value ? undefined\n\t\t\t\t: value === 'none' ? null\n\t\t\t\t: value;\n\t}\n\n\tfunction applyAttributes(item, node, isRoot) {\n\t\tvar parent = node.parentNode,\n\t\t\tstyles = {\n\t\t\t\tnode: DomElement.getStyles(node) || {},\n\t\t\t\tparent: !isRoot && !/^defs$/i.test(parent.tagName)\n\t\t\t\t\t\t&& DomElement.getStyles(parent) || {}\n\t\t\t};\n\t\tBase.each(attributes, function(apply, name) {\n\t\t\tvar value = getAttribute(node, name, styles);\n\t\t\titem = value !== undefined && apply(item, value, name, node, styles)\n\t\t\t\t\t|| item;\n\t\t});\n\t\treturn item;\n\t}\n\n\tfunction getDefinition(value) {\n\t\tvar match = value && value.match(/\\((?:[\"'#]*)([^\"')]+)/),\n\t\t\tname = match && match[1],\n\t\t\tres = name && definitions[window\n\t\t\t\t\t? name.replace(window.location.href.split('#')[0] + '#', '')\n\t\t\t\t\t: name];\n\t\tif (res && res._scaleToBounds) {\n\t\t\tres = res.clone();\n\t\t\tres._scaleToBounds = true;\n\t\t}\n\t\treturn res;\n\t}\n\n\tfunction importNode(node, options, isRoot) {\n\t\tvar type = node.nodeName.toLowerCase(),\n\t\t\tisElement = type !== '#document',\n\t\t\tbody = document.body,\n\t\t\tcontainer,\n\t\t\tparent,\n\t\t\tnext;\n\t\tif (isRoot && isElement) {\n\t\t\trootSize = getSize(node, null, null, true)\n\t\t\t\t\t|| paper.getView().getSize();\n\t\t\tcontainer = SvgElement.create('svg', {\n\t\t\t\tstyle: 'stroke-width: 1px; stroke-miterlimit: 10'\n\t\t\t});\n\t\t\tparent = node.parentNode;\n\t\t\tnext = node.nextSibling;\n\t\t\tcontainer.appendChild(node);\n\t\t\tbody.appendChild(container);\n\t\t}\n\t\tvar settings = paper.settings,\n\t\t\tapplyMatrix = settings.applyMatrix,\n\t\t\tinsertItems = settings.insertItems;\n\t\tsettings.applyMatrix = false;\n\t\tsettings.insertItems = false;\n\t\tvar importer = importers[type],\n\t\t\titem = importer && importer(node, type, options, isRoot) || null;\n\t\tsettings.insertItems = insertItems;\n\t\tsettings.applyMatrix = applyMatrix;\n\t\tif (item) {\n\t\t\tif (isElement && !(item instanceof Group))\n\t\t\t\titem = applyAttributes(item, node, isRoot);\n\t\t\tvar onImport = options.onImport,\n\t\t\t\tdata = isElement && node.getAttribute('data-paper-data');\n\t\t\tif (onImport)\n\t\t\t\titem = onImport(node, item, options) || item;\n\t\t\tif (options.expandShapes && item instanceof Shape) {\n\t\t\t\titem.remove();\n\t\t\t\titem = item.toPath();\n\t\t\t}\n\t\t\tif (data)\n\t\t\t\titem._data = JSON.parse(data);\n\t\t}\n\t\tif (container) {\n\t\t\tbody.removeChild(container);\n\t\t\tif (parent) {\n\t\t\t\tif (next) {\n\t\t\t\t\tparent.insertBefore(node, next);\n\t\t\t\t} else {\n\t\t\t\t\tparent.appendChild(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (isRoot) {\n\t\t\tdefinitions = {};\n\t\t\tif (item && Base.pick(options.applyMatrix, applyMatrix))\n\t\t\t\titem.matrix.apply(true, true);\n\t\t}\n\t\treturn item;\n\t}\n\n\tfunction importSVG(source, options, owner) {\n\t\tif (!source)\n\t\t\treturn null;\n\t\toptions = typeof options === 'function' ? { onLoad: options }\n\t\t\t\t: options || {};\n\t\tvar scope = paper,\n\t\t\titem = null;\n\n\t\tfunction onLoad(svg) {\n\t\t\ttry {\n\t\t\t\tvar node = typeof svg === 'object' ? svg : new self.DOMParser()\n\t\t\t\t\t\t.parseFromString(svg, 'image/svg+xml');\n\t\t\t\tif (!node.nodeName) {\n\t\t\t\t\tnode = null;\n\t\t\t\t\tthrow new Error('Unsupported SVG source: ' + source);\n\t\t\t\t}\n\t\t\t\tpaper = scope;\n\t\t\t\titem = importNode(node, options, true);\n\t\t\t\tif (!options || options.insert !== false) {\n\t\t\t\t\towner._insertItem(undefined, item);\n\t\t\t\t}\n\t\t\t\tvar onLoad = options.onLoad;\n\t\t\t\tif (onLoad)\n\t\t\t\t\tonLoad(item, svg);\n\t\t\t} catch (e) {\n\t\t\t\tonError(e);\n\t\t\t}\n\t\t}\n\n\t\tfunction onError(message, status) {\n\t\t\tvar onError = options.onError;\n\t\t\tif (onError) {\n\t\t\t\tonError(message, status);\n\t\t\t} else {\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\t\t}\n\n\t\tif (typeof source === 'string' && !/^.*