author | Carsten "Tomcat" Book <cbook@mozilla.com> |
Thu, 24 Oct 2013 07:05:29 +0200 | |
changeset 165732 | 19fd3388c3729fbc8dd4a52376c964aa495a2a25 |
parent 165651 | ea2c865af416e353db131bbfc0a898af7f571af1 (current diff) |
parent 165731 | 9d1266f5c051ad7f05c9df990dc39dca18dfa08f (diff) |
child 165733 | 5a9ac6fed6ff179b0b91d4ef9a11cb014471a6e3 |
child 165739 | 5d5591687e676247c617f98f0a02c744250285d1 |
child 165879 | a884fbbc334ae339ac6c9d631a3e8290b4166850 |
child 165921 | d3100c2edc814845300b37bdd2c2054f64391689 |
child 170486 | 75aeed86188a11c702ca0fb404d7986b096999aa |
child 177486 | 8de9317c8bcd7d58d45e9bf2f0e78699458756d6 |
push id | 3066 |
push user | akeybl@mozilla.com |
push date | Mon, 09 Dec 2013 19:58:46 +0000 |
treeherder | mozilla-beta@a31a0dce83aa [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 27.0a1 |
first release with | nightly linux32
19fd3388c372
/
27.0a1
/
20131024030204
/
files
nightly linux64
19fd3388c372
/
27.0a1
/
20131024030204
/
files
nightly mac
19fd3388c372
/
27.0a1
/
20131024030204
/
files
nightly win32
19fd3388c372
/
27.0a1
/
20131024030204
/
files
nightly win64
19fd3388c372
/
27.0a1
/
20131024030204
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
27.0a1
/
20131024030204
/
pushlog to previous
nightly linux64
27.0a1
/
20131024030204
/
pushlog to previous
nightly mac
27.0a1
/
20131024030204
/
pushlog to previous
nightly win32
27.0a1
/
20131024030204
/
pushlog to previous
nightly win64
27.0a1
/
20131024030204
/
pushlog to previous
|
dom/webidl/moz.build | file | annotate | diff | comparison | revisions | |
mobile/android/fonts/OpenSans-Bold.ttf | file | annotate | diff | comparison | revisions | |
mobile/android/fonts/OpenSans-BoldItalic.ttf | file | annotate | diff | comparison | revisions | |
mobile/android/fonts/OpenSans-Italic.ttf | file | annotate | diff | comparison | revisions | |
mobile/android/fonts/OpenSans-Light.ttf | file | annotate | diff | comparison | revisions | |
mobile/android/fonts/OpenSans-LightItalic.ttf | file | annotate | diff | comparison | revisions | |
mobile/android/fonts/OpenSans-Regular.ttf | file | annotate | diff | comparison | revisions | |
modules/libpref/src/init/all.js | file | annotate | diff | comparison | revisions | |
netwerk/build/nsNetModule.cpp | file | annotate | diff | comparison | revisions |
--- a/accessible/src/atk/moz.build +++ b/accessible/src/atk/moz.build @@ -11,31 +11,31 @@ EXPORTS.mozilla.a11y += [ 'HyperTextAccessibleWrap.h', ] CPP_SOURCES += [ 'AccessibleWrap.cpp', 'ApplicationAccessibleWrap.cpp', 'AtkSocketAccessible.cpp', 'DocAccessibleWrap.cpp', - 'Platform.cpp', - 'RootAccessibleWrap.cpp', - 'UtilInterface.cpp', 'nsMaiHyperlink.cpp', 'nsMaiInterfaceAction.cpp', 'nsMaiInterfaceComponent.cpp', 'nsMaiInterfaceDocument.cpp', 'nsMaiInterfaceEditableText.cpp', 'nsMaiInterfaceHyperlinkImpl.cpp', 'nsMaiInterfaceHypertext.cpp', 'nsMaiInterfaceImage.cpp', 'nsMaiInterfaceSelection.cpp', 'nsMaiInterfaceTable.cpp', 'nsMaiInterfaceText.cpp', 'nsMaiInterfaceValue.cpp', + 'Platform.cpp', + 'RootAccessibleWrap.cpp', + 'UtilInterface.cpp', ] LIBRARY_NAME = 'accessibility_toolkit_s' LIBXUL_LIBRARY = True LOCAL_INCLUDES += [ '../base',
--- a/accessible/src/base/moz.build +++ b/accessible/src/base/moz.build @@ -5,18 +5,18 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. include('../shared.mozbuild') MODULE = 'accessibility' EXPORTS += [ 'AccEvent.h', + 'nsAccessibilityService.h', 'nsAccessNode.h', - 'nsAccessibilityService.h', ] EXPORTS.mozilla.a11y += [ 'AccTypes.h', 'DocManager.h', 'FocusManager.h', 'Platform.h', 'RelationType.h',
--- a/accessible/src/generic/moz.build +++ b/accessible/src/generic/moz.build @@ -8,19 +8,19 @@ MODULE = 'accessibility' EXPORTS.mozilla.a11y += [ 'Accessible.h', 'DocAccessible.h', 'HyperTextAccessible.h', ] CPP_SOURCES += [ - 'ARIAGridAccessible.cpp', 'Accessible.cpp', 'ApplicationAccessible.cpp', + 'ARIAGridAccessible.cpp', 'BaseAccessibles.cpp', 'DocAccessible.cpp', 'FormControlAccessible.cpp', 'HyperTextAccessible.cpp', 'ImageAccessible.cpp', 'OuterDocAccessible.cpp', 'RootAccessible.cpp', 'TableCellAccessible.cpp',
--- a/accessible/src/mac/moz.build +++ b/accessible/src/mac/moz.build @@ -16,23 +16,23 @@ EXPORTS.mozilla.a11y += [ ] LIBRARY_NAME = 'accessibility_toolkit_s' CMMSRCS += [ 'AccessibleWrap.mm', 'DocAccessibleWrap.mm', 'MacUtils.mm', - 'Platform.mm', - 'RootAccessibleWrap.mm', 'mozAccessible.mm', 'mozActionElements.mm', 'mozDocAccessible.mm', 'mozHTMLAccessible.mm', 'mozTextAccessible.mm', + 'Platform.mm', + 'RootAccessibleWrap.mm', ] LIBXUL_LIBRARY = True LOCAL_INCLUDES += [ '../base', '../generic', '../html',
--- a/accessible/src/windows/msaa/moz.build +++ b/accessible/src/windows/msaa/moz.build @@ -15,28 +15,28 @@ EXPORTS.mozilla.a11y += [ 'Compatibility.h', 'HyperTextAccessibleWrap.h', ] CPP_SOURCES += [ 'AccessibleWrap.cpp', 'ApplicationAccessibleWrap.cpp', 'ARIAGridAccessibleWrap.cpp', + 'Compatibility.cpp', 'DocAccessibleWrap.cpp', + 'EnumVariant.cpp', 'HTMLTableAccessibleWrap.cpp', 'HTMLWin32ObjectAccessible.cpp', 'HyperTextAccessibleWrap.cpp', 'ImageAccessibleWrap.cpp', 'IUnknownImpl.cpp', 'nsWinUtils.cpp', - 'Compatibility.cpp', - 'EnumVariant.cpp', 'Platform.cpp', + 'RootAccessibleWrap.cpp', 'ServiceProvider.cpp', - 'RootAccessibleWrap.cpp', 'TextLeafAccessibleWrap.cpp', ] if CONFIG['MOZ_XUL']: CPP_SOURCES += [ 'XULListboxAccessibleWrap.cpp', 'XULMenuAccessibleWrap.cpp', 'XULTreeGridAccessibleWrap.cpp',
--- a/accessible/src/windows/sdn/sdnAccessible.cpp +++ b/accessible/src/windows/sdn/sdnAccessible.cpp @@ -511,18 +511,18 @@ sdnAccessible::get_language(BSTR __RPC_F if (!aLanguage) return E_INVALIDARG; *aLanguage = nullptr; if (IsDefunct()) return CO_E_OBJNOTCONNECTED; nsAutoString language; - if (mNode->IsElement()) - nsCoreUtils::GetLanguageFor(mNode->AsElement(), nullptr, language); + if (mNode->IsContent()) + nsCoreUtils::GetLanguageFor(mNode->AsContent(), nullptr, language); if (language.IsEmpty()) { // Nothing found, so use document's language mNode->OwnerDoc()->GetHeaderData(nsGkAtoms::headerContentLanguage, language); } if (language.IsEmpty()) return S_FALSE;
--- a/browser/components/sessionstore/src/moz.build +++ b/browser/components/sessionstore/src/moz.build @@ -8,30 +8,30 @@ EXTRA_COMPONENTS += [ 'nsSessionStartup.js', 'nsSessionStore.js', 'nsSessionStore.manifest', ] JS_MODULES_PATH = 'modules/sessionstore' EXTRA_JS_MODULES = [ + '_SessionFile.jsm', 'DocShellCapabilities.jsm', 'DocumentUtils.jsm', 'Messenger.jsm', 'PageStyle.jsm', 'PrivacyLevel.jsm', 'RecentlyClosedTabsAndWindowsMenuUtils.jsm', 'SessionCookies.jsm', 'SessionHistory.jsm', 'SessionMigration.jsm', 'SessionStorage.jsm', 'SessionWorker.js', 'TabStateCache.jsm', 'TextAndScrollData.jsm', 'XPathGenerator.jsm', - '_SessionFile.jsm', ] EXTRA_PP_JS_MODULES += [ 'SessionSaver.jsm', 'SessionStore.jsm', ]
--- a/browser/extensions/shumway/content/ShumwayStreamConverter.jsm +++ b/browser/extensions/shumway/content/ShumwayStreamConverter.jsm @@ -36,16 +36,19 @@ const MAX_CLIPBOARD_DATA_SIZE = 8000; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Services.jsm'); Cu.import('resource://gre/modules/NetUtil.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils', 'resource://gre/modules/PrivateBrowsingUtils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'ShumwayTelemetry', + 'resource://shumway/ShumwayTelemetry.jsm'); + let appInfo = Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULAppInfo); let Svc = {}; XPCOMUtils.defineLazyServiceGetter(Svc, 'mime', '@mozilla.org/mime;1', 'nsIMIMEService'); let profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); function getBoolPref(pref, def) { @@ -191,16 +194,22 @@ function ChromeActions(url, window, docu this.baseUrl = url; this.isOverlay = false; this.isPausedAtStart = false; this.window = window; this.document = document; this.externalComInitialized = false; this.allowScriptAccess = false; this.crossdomainRequestsCache = Object.create(null); + this.telemetry = { + startTime: Date.now(), + features: [], + errors: [], + pageIndex: 0 + }; } ChromeActions.prototype = { getBoolPref: function (data) { if (!/^shumway\./.test(data.pref)) { return null; } return getBoolPref(data.pref, data.def); @@ -230,49 +239,56 @@ ChromeActions.prototype = { // TODO flash cross-origin request if (url === this.url) { // allow downloading for the original file return callback({success: true}); } // allows downloading from the same origin - var urlPrefix = /^(https?):\/\/([A-Za-z0-9\-_\.\[\]]+)/i.exec(url); - var basePrefix = /^(https?):\/\/([A-Za-z0-9\-_\.\[\]]+)/i.exec(this.url); - if (basePrefix && urlPrefix && basePrefix[0] === urlPrefix[0]) { + var parsedUrl, parsedBaseUrl; + try { + parsedUrl = NetUtil.newURI(url); + } catch (ex) { /* skipping invalid urls */ } + try { + parsedBaseUrl = NetUtil.newURI(this.url); + } catch (ex) { /* skipping invalid urls */ } + + if (parsedUrl && parsedBaseUrl && + parsedUrl.prePath === parsedBaseUrl.prePath) { return callback({success: true}); } // additionally using internal whitelist var whitelist = getStringPref('shumway.whitelist', ''); - if (whitelist && urlPrefix) { + if (whitelist && parsedUrl) { var whitelisted = whitelist.split(',').some(function (i) { - return domainMatches(urlPrefix[2], i); + return domainMatches(parsedUrl.host, i); }); if (whitelisted) { return callback({success: true}); } } - if (!checkPolicyFile || !urlPrefix || !basePrefix) { + if (!checkPolicyFile || !parsedUrl || !parsedBaseUrl) { return callback({success: false}); } // we can request crossdomain.xml - fetchPolicyFile(urlPrefix[0] + '/crossdomain.xml', this.crossdomainRequestsCache, + fetchPolicyFile(parsedUrl.prePath + '/crossdomain.xml', this.crossdomainRequestsCache, function (policy, error) { if (!policy || policy.siteControl === 'none') { return callback({success: false}); } // TODO assuming master-only, there are also 'by-content-type', 'all', etc. var allowed = policy.allowAccessFrom.some(function (i) { - return domainMatches(basePrefix[2], i.domain) && - (!i.secure || basePrefix[1].toLowerCase() === 'https'); + return domainMatches(parsedBaseUrl.host, i.domain) && + (!i.secure || parsedBaseUrl.scheme.toLowerCase() === 'https'); }); return callback({success: allowed}); }.bind(this)); }, loadFile: function loadFile(data) { var url = data.url; var checkPolicyFile = data.checkPolicyFile; var sessionId = data.sessionId; @@ -329,22 +345,24 @@ ChromeActions.prototype = { performXHR(); } else { log("data access id prohibited to " + url + " from " + baseUrl); win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "error", error: "only original swf file or file from the same origin loading supported"}, "*"); } }); }, - fallback: function() { + fallback: function(automatic) { var obj = this.window.frameElement; var doc = obj.ownerDocument; var e = doc.createEvent("CustomEvent"); e.initCustomEvent("MozPlayPlugin", true, true, null); obj.dispatchEvent(e); + + ShumwayTelemetry.onFallback(!automatic); }, setClipboard: function (data) { if (typeof data !== 'string' || data.length > MAX_CLIPBOARD_DATA_SIZE || !this.document.hasFocus()) { return; } // TODO other security checks? @@ -360,16 +378,55 @@ ChromeActions.prototype = { let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper); clipboard.copyString(data); }, endActivation: function () { if (ActivationQueue.currentNonActive === this) { ActivationQueue.activateNext(); } }, + reportTelemetry: function (data) { + var topic = data.topic; + switch (topic) { + case 'firstFrame': + var time = Date.now() - this.telemetry.startTime; + ShumwayTelemetry.onFirstFrame(time); + break; + case 'parseInfo': + ShumwayTelemetry.onParseInfo({ + parseTime: +data.parseTime, + size: +data.bytesTotal, + swfVersion: data.swfVersion|0, + frameRate: +data.frameRate, + width: data.width|0, + height: data.height|0, + bannerType: data.bannerType|0, + isAvm2: !!data.isAvm2 + }); + break; + case 'feature': + var featureType = data.feature|0; + var MIN_FEATURE_TYPE = 0, MAX_FEATURE_TYPE = 999; + if (featureType >= MIN_FEATURE_TYPE && featureType <= MAX_FEATURE_TYPE && + !this.telemetry.features[featureType]) { + this.telemetry.features[featureType] = true; // record only one feature per SWF + ShumwayTelemetry.onFeature(featureType); + } + break; + case 'error': + var errorType = data.error|0; + var MIN_ERROR_TYPE = 0, MAX_ERROR_TYPE = 2; + if (errorType >= MIN_ERROR_TYPE && errorType <= MAX_ERROR_TYPE && + !this.telemetry.errors[errorType]) { + this.telemetry.errors[errorType] = true; // record only one report per SWF + ShumwayTelemetry.onError(errorType); + } + break; + } + }, externalCom: function (data) { if (!this.allowScriptAccess) return; // TODO check security ? var parentWindow = this.window.parent.wrappedJSObject; var embedTag = this.embedTag.wrappedJSObject; switch (data.action) { @@ -447,16 +504,24 @@ var ActivationQueue = { return this.nonActive[this.initializing]; }, enqueue: function ActivationQueue_enqueue(actions) { this.nonActive.push(actions); if (this.nonActive.length === 1) { this.activateNext(); } }, + findLastOnPage: function ActivationQueue_findLastOnPage(baseUrl) { + for (var i = this.nonActive.length - 1; i >= 0; i--) { + if (this.nonActive[i].baseUrl === baseUrl) { + return this.nonActive[i]; + } + } + return null; + }, activateNext: function ActivationQueue_activateNext() { function weightInstance(actions) { // set of heuristics for find the most important instance to load var weight = 0; // using linear distance to the top-left of the view area if (actions.embedTag) { var window = actions.window; var clientRect = actions.embedTag.getBoundingClientRect(); @@ -809,20 +874,31 @@ ShumwayStreamConverterBase.prototype = { onStopRequest: function() { var domWindow = getDOMWindow(channel); if (domWindow.document.documentURIObject.equals(channel.originalURI)) { // Double check the url is still the correct one. let actions = converter.createChromeActions(domWindow, domWindow.document, converter.getUrlHint(originalURI)); if (!isShumwayEnabledFor(actions)) { - actions.fallback(); + actions.fallback(true); return; } + // Report telemetry on amount of swfs on the page + if (actions.isOverlay) { + // Looking for last actions with same baseUrl + var prevPageActions = ActivationQueue.findLastOnPage(actions.baseUrl); + var pageIndex = !prevPageActions ? 1 : (prevPageActions.telemetry.pageIndex + 1); + actions.telemetry.pageIndex = pageIndex; + ShumwayTelemetry.onPageIndex(pageIndex); + } else { + ShumwayTelemetry.onPageIndex(0); + } + actions.activationCallback = function(domWindow, isSimpleMode) { delete this.activationCallback; activateShumwayScripts(domWindow, isSimpleMode); }.bind(actions, domWindow, isSimpleMode); ActivationQueue.enqueue(actions); let requestListener = new RequestListener(actions); domWindow.addEventListener('shumway.message', function(event) {
new file mode 100644 --- /dev/null +++ b/browser/extensions/shumway/content/ShumwayTelemetry.jsm @@ -0,0 +1,73 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2013 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* jshint esnext:true */ + +'use strict'; + +this.EXPORTED_SYMBOLS = ['ShumwayTelemetry']; + +const Cu = Components.utils; +Cu.import('resource://gre/modules/Services.jsm'); + +const BANNER_SIZES = [ + "88x31", "120x60", "120x90", "120x240", "120x600", "125x125", "160x600", + "180x150", "234x60", "240x400", "250x250", "300x100", "300x250", "300x600", + "300x1050", "336x280", "468x60", "550x480", "720x100", "728x90", "970x90", + "970x250"]; + +function getBannerType(width, height) { + return BANNER_SIZES.indexOf(width + 'x' + height) + 1; +} + +this.ShumwayTelemetry = { + onFirstFrame: function (timeToDisplay) { + var histogram = Services.telemetry.getHistogramById("SHUMWAY_TIME_TO_VIEW_MS"); + histogram.add(timeToDisplay); + }, + onParseInfo: function (parseInfo) { + var histogram = Services.telemetry.getHistogramById("SHUMWAY_PARSING_MS"); + histogram.add(parseInfo.parseTime); + var histogram = Services.telemetry.getHistogramById("SHUMWAY_SWF_SIZE_KB"); + histogram.add(parseInfo.size / 1024); + var histogram = Services.telemetry.getHistogramById("SHUMWAY_SWF_VERSION"); + histogram.add(parseInfo.swfVersion); + var histogram = Services.telemetry.getHistogramById("SHUMWAY_SWF_FRAME_RATE"); + histogram.add(parseInfo.frameRate); + var histogram = Services.telemetry.getHistogramById("SHUMWAY_SWF_AREA"); + histogram.add(parseInfo.width * parseInfo.height); + var histogram = Services.telemetry.getHistogramById("SHUMWAY_SWF_BANNER"); + histogram.add(getBannerType(parseInfo.width, parseInfo.height)); + var histogram = Services.telemetry.getHistogramById("SHUMWAY_SWF_AVM2"); + histogram.add(parseInfo.isAvm2); + }, + onError: function (errorType) { + var histogram = Services.telemetry.getHistogramById("SHUMWAY_ERROR"); + histogram.add(errorType); + }, + onPageIndex: function (pageIndex) { + var histogram = Services.telemetry.getHistogramById("SHUMWAY_SWF_INDEX_ON_PAGE"); + histogram.add(pageIndex); + }, + onFeature: function (featureType) { + var histogram = Services.telemetry.getHistogramById("SHUMWAY_FEATURE_USED"); + histogram.add(featureType); + }, + onFallback: function (userAction) { + var histogram = Services.telemetry.getHistogramById("SHUMWAY_FALLBACK"); + histogram.add(userAction); + } +};
index a452e2b10f82e5b07f3bd261cb98b1555fc31848..0f9c67914b5135a8fbda922d10a03e2335fef5a1 GIT binary patch literal 26518 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
--- a/browser/extensions/shumway/content/shumway-worker.js +++ b/browser/extensions/shumway/content/shumway-worker.js @@ -218,16 +218,19 @@ var Promise = function PromiseClosure() subpromises[i].fulfill(value); } delete subject.subpromises; } function propagateRejected(subject, reason) { subject.subpromisesReason = reason; var subpromises = subject.subpromises; if (!subpromises) { + if (!true) { + console.warn(reason); + } return; } for (var i = 0; i < subpromises.length; i++) { subpromises[i].reject(reason); } delete subject.subpromises; } function performCall(callback, arg, subject) { @@ -430,16 +433,28 @@ QuadTree.prototype._subdivide = function var midX = this.x + halfWidth; var midY = this.y + halfHeight; var level = this.level + 1; this.nodes[0] = new QuadTree(midX, this.y, halfWidth, halfHeight, level); this.nodes[1] = new QuadTree(this.x, this.y, halfWidth, halfHeight, level); this.nodes[2] = new QuadTree(this.x, midY, halfWidth, halfHeight, level); this.nodes[3] = new QuadTree(midX, midY, halfWidth, halfHeight, level); }; +var EXTERNAL_INTERFACE_FEATURE = 1; +var CLIPBOARD_FEATURE = 2; +var SHAREDOBJECT_FEATURE = 3; +var VIDEO_FEATURE = 4; +var SOUND_FEATURE = 5; +var NETCONNECTION_FEATURE = 6; +if (!this.performance) { + this.performance = {}; +} +if (!this.performance.now) { + this.performance.now = Date.now; +} var create = Object.create; var defineProperty = Object.defineProperty; var keys = Object.keys; var isArray = Array.isArray; var fromCharCode = String.fromCharCode; var logE = Math.log; var max = Math.max; var min = Math.min; @@ -904,19 +919,20 @@ function defineFont(tag, dictionary) { indices.push(i); } ranges.push([ UAC_OFFSET, UAC_OFFSET + glyphCount - 1, indices ]); } - var ascent = Math.ceil(tag.ascent / 20) || 1024; - var descent = -Math.ceil(tag.descent / 20) || 0; - var leading = Math.floor(tag.leading / 20) || 0; + var resolution = tag.resolution || 1; + var ascent = Math.ceil(tag.ascent / resolution) || 1024; + var descent = -Math.ceil(tag.descent / resolution) | 0; + var leading = tag.leading / resolution | 0; tables['OS/2'] = '\0\x01\0\0' + toString16(tag.bold ? 700 : 400) + '\0\x05' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0\0\0\0\0\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + 'ALF ' + toString16((tag.italic ? 1 : 0) | (tag.bold ? 32 : 0)) + toString16(codes[0]) + toString16(codes[codes.length - 1]) + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(ascent) + toString16(-descent) + '\0\0\0\0' + '\0\0\0\0'; ; var startCount = ''; var endCount = ''; var idDelta = ''; var idRangeOffset = ''; var i = 0; var range; @@ -937,17 +953,16 @@ function defineFont(tag, dictionary) { var searchRange = maxPower2(segCount) * 2; var rangeShift = 2 * segCount - searchRange; var format314 = '\0\0' + toString16(segCount * 2) + toString16(searchRange) + toString16(logE(segCount) / logE(2)) + toString16(rangeShift) + endCount + '\0\0' + startCount + idDelta + idRangeOffset; ; tables['cmap'] = '\0\0\0\x01\0\x03\0\x01\0\0\0\f\0\x04' + toString16(format314.length + 4) + format314; ; var glyf = '\0\x01\0\0\0\0\0\0\0\0\0\0\0\x001\0'; var loca = '\0\0'; - var resolution = tag.resolution || 1; var offset = 16; var maxPoints = 0; var xMins = []; var xMaxs = []; var yMins = []; var yMaxs = []; var maxContours = 0; var i = 0; @@ -1062,20 +1077,19 @@ function defineFont(tag, dictionary) { yMaxs.push(yMax); if (numberOfContours > maxContours) maxContours = numberOfContours; if (endPoint > maxPoints) maxPoints = endPoint; } loca += toString16(offset / 2); tables['glyf'] = glyf; - tables['head'] = '\0\x01\0\0\0\x01\0\0\0\0\0\0_\x0f<\xf5\0\v\x04\0\0\0\0\0' + toString32(+new Date()) + '\0\0\0\0' + toString32(+new Date()) + toString16(min.apply(null, xMins)) + toString16(min.apply(null, yMins)) + toString16(max.apply(null, xMaxs)) + toString16(max.apply(null, yMaxs)) + toString16((tag.italic ? 2 : 0) | (tag.bold ? 1 : 0)) + '\0\b' + '\0\x02' + '\0\0' + '\0\0'; + tables['head'] = '\0\x01\0\0\0\x01\0\0\0\0\0\0_\x0f<\xf5\0\v\x04\0\0\0\0\0' + toString32(Date.now()) + '\0\0\0\0' + toString32(Date.now()) + toString16(min.apply(null, xMins)) + toString16(min.apply(null, yMins)) + toString16(max.apply(null, xMaxs)) + toString16(max.apply(null, yMaxs)) + toString16((tag.italic ? 2 : 0) | (tag.bold ? 1 : 0)) + '\0\b' + '\0\x02' + '\0\0' + '\0\0'; ; var advance = tag.advance; - var resolution = tag.resolution || 1; tables['hhea'] = '\0\x01\0\0' + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(advance ? max.apply(null, advance) : 1024) + '\0\0' + '\0\0' + '\x03\xb8' + '\0\x01' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + toString16(glyphCount + 1); ; var hmtx = '\0\0\0\0'; for (var i = 0; i < glyphCount; ++i) hmtx += toString16(advance ? advance[i] / resolution : 1024) + '\0\0'; tables['hmtx'] = hmtx; if (tag.kerning) { var kerning = tag.kerning; @@ -1142,26 +1156,28 @@ function defineFont(tag, dictionary) { while (offset & 3) ++offset; offset += length; } var otf = header + data; var unitPerEm = 1024; var metrics = { ascent: ascent / unitPerEm, - descent: descent / unitPerEm, + descent: -descent / unitPerEm, leading: leading / unitPerEm }; return { type: 'font', id: tag.id, name: fontName, uniqueName: psName + uniqueId, codes: codes, metrics: metrics, + bold: tag.bold === 1, + italic: tag.italic === 1, data: otf }; } function getUint16(buff, pos) { return buff[pos] << 8 | buff[pos + 1]; } function parseJpegChunks(imgDef, bytes) { var i = 0; @@ -1229,18 +1245,18 @@ function defineLabel(tag, dictionary) { var m = tag.matrix; var cmds = [ 'c.save()', 'c.transform(' + [ m.a, m.b, m.c, m.d, - m.tx, - m.ty + m.tx / 20, + m.ty / 20 ].join(',') + ')', 'c.scale(0.05, 0.05)' ]; var dependencies = []; var x = 0; var y = 0; var i = 0; var record; @@ -1722,19 +1738,18 @@ SegmentedPath.prototype = { } }; var SHAPE_MOVE_TO = 1; var SHAPE_LINE_TO = 2; var SHAPE_CURVE_TO = 3; var SHAPE_WIDE_MOVE_TO = 4; var SHAPE_WIDE_LINE_TO = 5; var SHAPE_CUBIC_CURVE_TO = 6; -var SHAPE_ROUND_CORNER = 7; -var SHAPE_CIRCLE = 8; -var SHAPE_ELLIPSE = 9; +var SHAPE_CIRCLE = 7; +var SHAPE_ELLIPSE = 8; function ShapePath(fillStyle, lineStyle, commandsCount, dataLength, isMorph) { this.fillStyle = fillStyle; this.lineStyle = lineStyle; if (commandsCount) { this.commands = new Uint8Array(commandsCount); this.data = new Int32Array(dataLength); this.morphData = isMorph ? new Int32Array(dataLength) : null; } else { @@ -1773,20 +1788,16 @@ ShapePath.prototype = { var y2 = y + h; this.commands.push(SHAPE_MOVE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO); this.data.push(x, y, x2, y, x2, y2, x, y2, x, y); }, circle: function (x, y, radius) { this.commands.push(SHAPE_CIRCLE); this.data.push(x, y, radius); }, - drawRoundCorner: function (cornerX, cornerY, curveEndX, curveEndY, radiusX, radiusY) { - this.commands.push(SHAPE_ROUND_CORNER); - this.data.push(cornerX, cornerY, curveEndX, curveEndY, radiusX, radiusY); - }, ellipse: function (x, y, radiusX, radiusY) { this.commands.push(SHAPE_ELLIPSE); this.data.push(x, y, radiusX, radiusY); }, draw: function (ctx, clip, ratio, colorTransform) { if (clip && !this.fillStyle) { return; } @@ -1818,19 +1829,16 @@ ShapePath.prototype = { k += 2; break; case SHAPE_CURVE_TO: ctx.quadraticCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20); break; case SHAPE_CUBIC_CURVE_TO: ctx.bezierCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20); break; - case SHAPE_ROUND_CORNER: - ctx.arcTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20); - break; case SHAPE_CIRCLE: if (formOpen) { ctx.lineTo(formOpenX, formOpenY); formOpen = false; } ctx.moveTo((data[k] + data[k + 2]) / 20, data[k + 1] / 20); ctx.arc(data[k++] / 20, data[k++] / 20, data[k++] / 20, 0, Math.PI * 2, false); break; @@ -1883,16 +1891,17 @@ ShapePath.prototype = { console.warn('Drawing command not supported for morph shapes: ' + commands[j]); } } } if (!clip) { var fillStyle = this.fillStyle; if (fillStyle) { colorTransform.setFillStyle(ctx, fillStyle.style); + ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = fillStyle.smooth; var m = fillStyle.transform; ctx.save(); colorTransform.setAlpha(ctx); if (m) { ctx.transform(m.a, m.b, m.c, m.d, m.e / 20, m.f / 20); } ctx.fill(); ctx.restore(); @@ -2012,43 +2021,16 @@ ShapePath.prototype = { } var roots = cubicXAtY(fromX, fromY, cpX, cpY, cp2X, cp2Y, toX, toY, y); for (var i = roots.length; i--;) { if (roots[i] >= x) { inside = !inside; } } break; - case SHAPE_ROUND_CORNER: - cpX = data[dataIndex++]; - cpY = data[dataIndex++]; - toX = data[dataIndex++]; - toY = data[dataIndex++]; - rX = data[dataIndex++]; - rY = data[dataIndex++]; - if (toY > y === fromY > y || fromX < x && toX < x) { - break; - } - if (fromX >= x && toX >= x) { - inside = !inside; - break; - } - if (toX > fromX === toY > fromY) { - cp2X = fromX; - cp2Y = toY; - } else { - cp2X = toX; - cp2Y = fromY; - } - localX = x - cp2X; - localY = y - cp2Y; - if (localX * localX / (rX * rX) + localY * localY / (rY * rY) <= 1 !== localX <= 0) { - inside = !inside; - } - break; case SHAPE_CIRCLE: toX = data[dataIndex++]; toY = data[dataIndex++]; var r = data[dataIndex++]; localX = x - toX; localY = y - toY; if (localX * localX + localY * localY < r * r) { inside = !inside; @@ -2201,46 +2183,16 @@ ShapePath.prototype = { if (curveY < minY || curveY > maxY) { continue; } if ((x - curveX) * (x - curveX) + (y - curveY) * (y - curveY) < halfWidthSq) { return true; } } break; - case SHAPE_ROUND_CORNER: - cpX = data[dataIndex++]; - cpY = data[dataIndex++]; - toX = data[dataIndex++]; - toY = data[dataIndex++]; - rX = data[dataIndex++]; - rY = data[dataIndex++]; - if (maxX < fromX && maxX < toX || minX > fromX && minX > toX || maxY < fromY && maxY < toY || minY > fromY && minY > toY) { - break; - } - if (toX > fromX === toY > fromY) { - cp2X = fromX; - cp2Y = toY; - } else { - cp2X = toX; - cp2Y = fromY; - } - localX = Math.abs(x - cp2X); - localY = Math.abs(y - cp2Y); - localX -= halfWidth; - localY -= halfWidth; - if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) { - break; - } - localX += width; - localY += width; - if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) { - return true; - } - break; case SHAPE_CIRCLE: cpX = data[dataIndex++]; cpY = data[dataIndex++]; var r = data[dataIndex++]; toX = cpX + r; toY = cpY; if (maxX < cpX - r || minX > cpX + r || maxY < cpY - r || minY > cpY + r) { break; @@ -2292,17 +2244,17 @@ ShapePath.prototype = { } return bounds; }, _calculateBounds: function () { var commands = this.commands; var data = this.data; var length = commands.length; var bounds; - if (commands[0] === SHAPE_MOVE_TO || commands[0] > SHAPE_ROUND_CORNER) { + if (commands[0] === SHAPE_MOVE_TO || commands[0] > SHAPE_CUBIC_CURVE_TO) { bounds = { xMin: data[0], yMin: data[1] }; } else { bounds = { xMin: 0, yMin: 0 @@ -2363,19 +2315,16 @@ ShapePath.prototype = { } if (cpY < fromY || cp2Y < fromY || cpY > toY || cp2Y > toY) { extremes = cubicBezierExtremes(fromY, cpY, cp2Y, toY); for (i = extremes.length; i--;) { extendBoundsByY(bounds, extremes[i]); } } break; - case SHAPE_ROUND_CORNER: - dataIndex += 6; - break; case SHAPE_CIRCLE: toX = data[dataIndex++]; toY = data[dataIndex++]; var radius = data[dataIndex++]; extendBoundsByPoint(bounds, toX - radius, toY - radius); extendBoundsByPoint(bounds, toX + radius, toY + radius); toX += radius; break; @@ -2643,17 +2592,17 @@ function finishShapePaths(paths, diction path.morphData = untypedPath.morphData; } path.fillStyle && initStyle(path.fillStyle, dictionary); path.lineStyle && initStyle(path.lineStyle, dictionary); path.fullyInitialized = true; } } var inWorker = typeof window === 'undefined'; -var factoryCtx = !inWorker ? document.createElement('canvas').getContext('kanvas-2d') : null; +var factoryCtx = !inWorker ? document.createElement('canvas').getContext('2d') : null; function buildLinearGradientFactory(colorStops) { var defaultGradient = factoryCtx.createLinearGradient(-1, 0, 1, 0); for (var i = 0; i < colorStops.length; i++) { defaultGradient.addColorStop(colorStops[i].ratio, colorStops[i].color); } var fn = function createLinearGradient(ctx, colorTransform) { var gradient = ctx.createLinearGradient(-1, 0, 1, 0); for (var i = 0; i < colorStops.length; i++) { @@ -3489,18 +3438,33 @@ var LoaderDefinition = function () { type: 'frame' }; break; } } }, oncomplete: function (result) { commitData(result); + var stats; + if (typeof result.swfVersion === 'number') { + var bbox = result.bbox; + stats = { + topic: 'parseInfo', + parseTime: result.parseTime, + bytesTotal: result.bytesTotal, + swfVersion: result.swfVersion, + frameRate: result.frameRate, + width: (bbox.xMax - bbox.xMin) / 20, + height: (bbox.yMax - bbox.yMin) / 20, + isAvm2: !(!result.fileAttributes.doAbc) + }; + } commitData({ - command: 'complete' + command: 'complete', + stats: stats }); } }; } function parseBytes(bytes) { SWF.parse(bytes, createParsingContext()); } if (isWorker || !flash.net.URLRequest.class.isInstanceOf(request)) { @@ -3605,16 +3569,20 @@ var LoaderDefinition = function () { if (type === 'frameConstructed') { frameConstructed.resolve(); avm2.systemDomain.onMessage.unregister('frameConstructed', waitForFrame); } }); Promise.when(frameConstructed, this._lastPromise).then(function () { this.contentLoaderInfo._dispatchEvent('complete'); }.bind(this)); + var stats = data.stats; + if (stats) { + TelemetryService.reportTelemetry(stats); + } this._worker && this._worker.terminate(); break; case 'empty': this._lastPromise = new Promise(); this._lastPromise.resolve(); break; case 'error': this.contentLoaderInfo._dispatchEvent('ioError', flash.events.IOErrorEvent); @@ -4002,16 +3970,18 @@ var LoaderDefinition = function () { }, 200); promiseQueue.push(fontPromise); } } className = 'flash.text.Font'; props.name = symbol.name; props.uniqueName = symbol.uniqueName; props.charset = symbol.charset; + props.bold = symbol.bold; + props.italic = symbol.italic; props.metrics = symbol.metrics; this._registerFont(className, props); break; case 'image': var img = new Image(); var imgPromise = new Promise(); img.onload = function () { if (symbol.mask) { @@ -4174,16 +4144,19 @@ var LoaderDefinition = function () { }); loader._dictionary[0] = documentPromise; loader._lastPromise = documentPromise; loader._vmPromise = vmPromise; loader._isAvm2Enabled = info.fileAttributes.doAbc; this._setup(); }, _load: function (request, checkPolicyFile, applicationDomain, securityDomain, deblockingFilter) { + if (!isWorker && flash.net.URLRequest.class.isInstanceOf(request)) { + this._contentLoaderInfo._url = request._url; + } if (!isWorker && WORKERS_ENABLED) { var loader = this; var worker = loader._worker = new Worker(SHUMWAY_ROOT + LOADER_PATH); worker.onmessage = function (evt) { loader._commitData(evt.data); }; if (flash.net.URLRequest.class.isInstanceOf(request)) { var session = FileLoadingService.createSession(); @@ -4261,17 +4234,17 @@ var LoaderDefinition = function () { _getJPEGLoaderContextdeblockingfilter: function (context) { return 0; }, _load: def._load, _loadBytes: function _loadBytes(bytes, checkPolicyFile, applicationDomain, securityDomain, requestedContentParent, parameters, deblockingFilter, allowLoadBytesCodeExecution, imageDecodingPolicy) { def._load(bytes.a); }, _unload: function _unload(halt, gc) { - notImplemented('Loader._unload'); + somewhatImplemented('Loader._unload, do we even need to do anything here?'); }, _close: function _close() { somewhatImplemented('Loader._close'); }, _getUncaughtErrorEvents: function _getUncaughtErrorEvents() { somewhatImplemented('Loader._getUncaughtErrorEvents'); return this._uncaughtErrorEvents; }, @@ -4921,187 +4894,23 @@ var tagHandler = function (global) { $29.depth = readUi16($bytes, $stream); var $30 = $29.matrix = {}; matrix($bytes, $stream, $30, swfVersion, tagCode); if (tagCode === 34) { var $31 = $29.cxform = {}; cxform($bytes, $stream, $31, swfVersion, tagCode); } if (hasFilters) { - $29.filterCount = readUi8($bytes, $stream); - var $32 = $29.filters = {}; - var type = $32.type = readUi8($bytes, $stream); - switch (type) { - case 0: - if (type === 4 || type === 7) { - count = readUi8($bytes, $stream); - } else { - count = 1; - } - var $33 = $32.colors = []; - var $34 = count; - while ($34--) { - var $35 = {}; - rgba($bytes, $stream, $35, swfVersion, tagCode); - $33.push($35); - } - if (type === 3) { - var $36 = $32.higlightColor = {}; - rgba($bytes, $stream, $36, swfVersion, tagCode); - } - if (type === 4 || type === 7) { - var $37 = $32.ratios = []; - var $38 = count; - while ($38--) { - $37.push(readUi8($bytes, $stream)); - } - } - $32.blurX = readFixed($bytes, $stream); - $32.blurY = readFixed($bytes, $stream); - if (type !== 2) { - $32.angle = readFixed($bytes, $stream); - $32.distance = readFixed($bytes, $stream); - } - $32.strength = readFixed8($bytes, $stream); - $32.innerShadow = readUb($bytes, $stream, 1); - $32.knockout = readUb($bytes, $stream, 1); - $32.compositeSource = readUb($bytes, $stream, 1); - if (type === 3) { - $32.onTop = readUb($bytes, $stream, 1); - } else { - var reserved = readUb($bytes, $stream, 1); - } - if (type === 4 || type === 7) { - $32.passes = readUb($bytes, $stream, 4); - } else { - var reserved = readUb($bytes, $stream, 4); - } - break; - case 1: - $32.blurX = readFixed($bytes, $stream); - $32.blurY = readFixed($bytes, $stream); - $32.passes = readUb($bytes, $stream, 5); - var reserved = readUb($bytes, $stream, 3); - break; - case 2: - case 3: - case 4: - if (type === 4 || type === 7) { - count = readUi8($bytes, $stream); - } else { - count = 1; - } - var $39 = $32.colors = []; - var $40 = count; - while ($40--) { - var $41 = {}; - rgba($bytes, $stream, $41, swfVersion, tagCode); - $39.push($41); - } - if (type === 3) { - var $42 = $32.higlightColor = {}; - rgba($bytes, $stream, $42, swfVersion, tagCode); - } - if (type === 4 || type === 7) { - var $43 = $32.ratios = []; - var $44 = count; - while ($44--) { - $43.push(readUi8($bytes, $stream)); - } - } - $32.blurX = readFixed($bytes, $stream); - $32.blurY = readFixed($bytes, $stream); - if (type !== 2) { - $32.angle = readFixed($bytes, $stream); - $32.distance = readFixed($bytes, $stream); - } - $32.strength = readFixed8($bytes, $stream); - $32.innerShadow = readUb($bytes, $stream, 1); - $32.knockout = readUb($bytes, $stream, 1); - $32.compositeSource = readUb($bytes, $stream, 1); - if (type === 3) { - $32.onTop = readUb($bytes, $stream, 1); - } else { - var reserved = readUb($bytes, $stream, 1); - } - if (type === 4 || type === 7) { - $32.passes = readUb($bytes, $stream, 4); - } else { - var reserved = readUb($bytes, $stream, 4); - } - break; - case 5: - var columns = $32.columns = readUi8($bytes, $stream); - var rows = $32.rows = readUi8($bytes, $stream); - $32.divisor = readFloat($bytes, $stream); - $32.bias = readFloat($bytes, $stream); - var $45 = $32.weights = []; - var $46 = columns * rows; - while ($46--) { - $45.push(readFloat($bytes, $stream)); - } - var $47 = $32.defaultColor = {}; - rgba($bytes, $stream, $47, swfVersion, tagCode); - var reserved = readUb($bytes, $stream, 6); - $32.clamp = readUb($bytes, $stream, 1); - $32.preserveAlpha = readUb($bytes, $stream, 1); - break; - case 6: - var $48 = $32.matrix = []; - var $49 = 20; - while ($49--) { - $48.push(readFloat($bytes, $stream)); - } - break; - case 7: - if (type === 4 || type === 7) { - count = readUi8($bytes, $stream); - } else { - count = 1; - } - var $50 = $32.colors = []; - var $51 = count; - while ($51--) { - var $52 = {}; - rgba($bytes, $stream, $52, swfVersion, tagCode); - $50.push($52); - } - if (type === 3) { - var $53 = $32.higlightColor = {}; - rgba($bytes, $stream, $53, swfVersion, tagCode); - } - if (type === 4 || type === 7) { - var $54 = $32.ratios = []; - var $55 = count; - while ($55--) { - $54.push(readUi8($bytes, $stream)); - } - } - $32.blurX = readFixed($bytes, $stream); - $32.blurY = readFixed($bytes, $stream); - if (type !== 2) { - $32.angle = readFixed($bytes, $stream); - $32.distance = readFixed($bytes, $stream); - } - $32.strength = readFixed8($bytes, $stream); - $32.innerShadow = readUb($bytes, $stream, 1); - $32.knockout = readUb($bytes, $stream, 1); - $32.compositeSource = readUb($bytes, $stream, 1); - if (type === 3) { - $32.onTop = readUb($bytes, $stream, 1); - } else { - var reserved = readUb($bytes, $stream, 1); - } - if (type === 4 || type === 7) { - $32.passes = readUb($bytes, $stream, 4); - } else { - var reserved = readUb($bytes, $stream, 4); - } - break; - default: + var count = readUi8($bytes, $stream); + var $2 = $.filters = []; + var $3 = count; + while ($3--) { + var $4 = {}; + anyFilter($bytes, $stream, $4, swfVersion, tagCode); + $2.push($4); } } if (blend) { $29.blendMode = readUi8($bytes, $stream); } } $28.push($29); } while (!eob); @@ -6433,17 +6242,18 @@ CompressedPipe.prototype = { this.state.bitLength = stream.bitLength; } buffer.removeHead(stream.pos); this.target.push(output.data.subarray(lastAvailable, output.available), progressInfo); } }; function BodyParser(swfVersion, length, options) { this.swf = { - swfVersion: swfVersion + swfVersion: swfVersion, + parseTime: 0 }; this.buffer = new HeadTailBuffer(32768); this.initialize = true; this.totalRead = 0; this.length = length; this.options = options; } BodyParser.prototype = { @@ -6484,17 +6294,19 @@ BodyParser.prototype = { } else { buffer.push(data); stream = buffer.createStream(); } if (progressInfo) { swf.bytesLoaded = progressInfo.bytesLoaded; swf.bytesTotal = progressInfo.bytesTotal; } + var readStartTime = performance.now(); readTags(swf, stream, swfVersion, options.onprogress); + swf.parseTime += performance.now() - readStartTime; var read = stream.pos; buffer.removeHead(read); this.totalRead += read; if (this.totalRead >= this.length && options.oncomplete) { options.oncomplete(swf); } } };
--- a/browser/extensions/shumway/content/shumway.js +++ b/browser/extensions/shumway/content/shumway.js @@ -151,1604 +151,16 @@ for (var i = 0; i < size; i++) view._bytes[offset + i] = temp[size - 1 - i]; } } function fail(msg) { throw new Error(msg); } }(this)); -; -var Kanvas = Kanvas || function (doc, undefined) { - var PATH_OP_CLOSE = 0; - var PATH_OP_MOVE = 1; - var PATH_OP_LINE = 2; - var PATH_OP_CURVE = 3; - var PATH_OP_BEZIER = 4; - var PATH_OP_ARCTO = 5; - var PATH_OP_RECT = 6; - var PATH_OP_ARC = 7; - var PATH_OP_ELLIPSE = 8; - var PATH_OP_TRANSFORM = 9; - var PI = Math.PI; - var PI_DOUBLE = PI * 2; - var PI_HALF = PI / 2; - var SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; - var Kanvas = { - VERSION: '0.0.0' - }; - var nativeCanvas = doc.createElement('canvas'); - var nativeCanvasClass = nativeCanvas.constructor; - var native2dCtx = nativeCanvas.getContext('2d'); - var native2dCtxClass = native2dCtx.constructor; - var nativeCanvasProto = nativeCanvasClass.prototype; - var native2dCtxProto = native2dCtxClass.prototype; - var kanvas2dCtxProto = Object.create(null); - var nativePathClass = typeof Path === 'undefined' ? undefined : Path; - var nativePathProto = nativePathClass && nativePathClass.prototype; - var kanvasPathProto = Object.create(null); - var shimCurrentTransform = !('currentTransform' in native2dCtx); - var shimResetTransform = !('resetTransform' in native2dCtxProto); - var shimEllipticalArcTo = false; - try { - native2dCtx.arcTo(0, 0, 1, 1, 1, -1); - } catch (e) { - shimEllipticalArcTo = true; - } - var shimEllipse = !('ellipse' in native2dCtxProto); - var shimPath = !nativePathClass; - var shimBounds = shimPath; - var shimStrokePath = shimPath; - if (!shimPath) { - shimBounds = !('getBounds' in nativePathProto); - shimStrokePath = !('StrokePath' in nativePathProto); - shimPath = shimBounds || shimStrokePath; - } - var shimHitRegions = !('addHitRegions' in native2dCtxProto); - var defineProp = Object.defineProperty; - var getOwnPropDesc = Object.getOwnPropertyDescriptor; - var getOwnPropNames = Object.getOwnPropertyNames; - var transformClass, idTransform, pathClass; - function defineLazyProp(obj, prop, desc) { - defineProp(obj, prop, { - get: function () { - if (this === obj) - return; - var existing = getOwnPropDesc(this, prop); - if (existing && 'value' in existing) { - return existing.value; - } - var val; - if (desc.get) { - val = desc.get.call(this); - defineProp(this, prop, { - value: val, - writable: desc.writable, - configurable: desc.configurable, - enumerable: desc.enumerable - }); - } else { - val = desc.value; - } - return val; - }, - configurable: true - }); - } - function mixinProps(dest, source) { - var props = getOwnPropNames(source); - for (var i = 0; i < props.length; i++) { - var key = props[i]; - var desc = getOwnPropDesc(source, key); - safeReplaceProp(dest, key, desc); - } - } - function safeReplaceProp(obj, prop, desc) { - if (prop in obj) { - defineProp(obj, '_' + prop, { - value: obj[prop], - configurable: true - }); - } - defineProp(obj, prop, desc); - } - function tmplf(format) { - if (arguments.length === 1) - return tmplf.bind(null, format); - var params = [ - '_' - ]; - var args = [ - mapf - ]; - for (var i = 1; i < arguments.length; i++) { - params[i] = '$' + i; - args[i] = arguments[i]; - } - return Function(params.join(','), 'return "' + format.replace(/\$(\$|[1-9]\d*|\(((?:(['"]).*?\3|.)*?);\))|"/g, function sub(match, p1, p2) { - if (p1) { - if (p1 === '$') - return p1; - if (p2) - return '"+(' + p2 + ')+"'; - return '"+' + match + '+"'; - } - return '\\"'; - }) + '"').apply(null, args); - } - function mapf(array, format, separator) { - if (+array == array) - array = Array(array); - else if (typeof array === 'string') - array = array.split(','); - if (format) - array = array.map(tmplf(format)); - if (separator !== undefined) - return array.join(separator); - return array; - } - function evalf(format) { - return (1, eval)('1,' + tmplf.apply(null, arguments)); - } - function parseSvgDataStr(sink, d) { - var chunks = (d + '').match(/[a-z][^a-z]*/gi); - var x0 = 0; - var y0 = 0; - var cpx = 0; - var cpy = 0; - var x = 0; - var y = 0; - for (var i = 0; i < chunks.length; i++) { - var seg = chunks[i]; - var cmd = seg[0].toUpperCase(); - if (cmd === 'Z') { - sink.closePath(); - continue; - } - var abs = cmd === seg[0]; - var args = seg.slice(1).trim().replace(/(\d)-/g, '$1 -').split(/,|\s/).map(parseFloat); - var narg = args.length; - var j = 0; - while (j < narg) { - x0 = x; - y0 = y; - if (abs) - x = y = 0; - switch (cmd) { - case 'A': - var rx = args[j++]; - var ry = args[j++]; - var rotation = args[j++] * PI / 180; - var large = args[j++]; - var sweep = args[j++]; - x += args[j++]; - y += args[j++]; - var u = Math.cos(rotation); - var v = Math.sin(rotation); - var h1x = (x0 - x) / 2; - var h1y = (y0 - y) / 2; - var x1 = u * h1x + v * h1y; - var y1 = -v * h1x + u * h1y; - var prx = rx * rx; - var pry = ry * ry; - var plx = x1 * x1; - var ply = y1 * y1; - var pl = plx / prx + ply / pry; - if (pl > 1) { - rx *= Math.sqrt(pl); - ry *= Math.sqrt(pl); - prx = rx * rx; - pry = ry * ry; - } - var sq = (prx * pry - prx * ply - pry * plx) / (prx * ply + pry * plx); - var coef = (large === sweep ? -1 : 1) * (sq < 0 ? 0 : Math.sqrt(sq)); - var ox = coef * rx * y1 / ry; - var oy = coef * -ry * x1 / rx; - var h2x = (x0 + x) / 2; - var h2y = (y0 + y) / 2; - var cx = u * ox - v * oy + h2x; - var cy = v * ox + u * oy + h2y; - var ux = (x1 - ox) / rx; - var uy = (y1 - oy) / ry; - var vx = (-x1 - ox) / rx; - var vy = (-y1 - oy) / ry; - var n0 = Math.sqrt(ux * ux + uy * uy); - var a0 = (uy < 0 ? -1 : 1) * Math.acos(ux / n0); - var n1 = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)); - var p = ux * vx + uy * vy; - var aext = (ux * vy - uy * vx < 0 ? -1 : 1) * Math.acos(p / n1); - if (sweep) { - if (aext < 0) - aext += PI_DOUBLE; - } else if (aext > 0) { - aext += PI_DOUBLE; - } - var a1 = a0 + aext; - sink.ellipse(cx, cy, rx, ry, rotation, a0, a1, !sweep); - break; - case 'C': - var x1 = x + args[j++]; - var y1 = y + args[j++]; - cpx = x + args[j++]; - cpy = y + args[j++]; - x += args[j++]; - y += args[j++]; - sink.bezierCurveTo(x1, y1, cpx, cpy, x, y); - break; - case 'H': - x += args[j++]; - sink.lineTo(x, y); - break; - case 'L': - x += args[j++]; - y += args[j++]; - sink.lineTo(x, y); - break; - case 'M': - x += args[j++]; - y += args[j++]; - sink.moveTo(x, y); - break; - case 'Q': - cpx = x + args[j++]; - cpy = y + args[j++]; - x += args[j++]; - y += args[j++]; - sink.quadraticCurveTo(cpx, cpy, x, y); - break; - case 'S': - var x1 = x0 * 2 - cpx; - var y1 = y0 * 2 - cpy; - cpx = x + args[j++]; - cpy = y + args[j++]; - x += args[j++]; - y += args[j++]; - sink.bezierCurveTo(x1, y1, cpx, cpy, x, y); - break; - case 'T': - cpx = x0 * 2 - cpx; - cpy = y0 * 2 - cpy; - x += args[j++]; - y += args[j++]; - sink.quadraticCurveTo(cpx, cpy, x, y); - break; - case 'V': - y += args[j++]; - sink.lineTo(x, y); - break; - default: - return; - } - } - } - } - function arcToCurveSegs(sink, cx, cy, r, a0, a1, ccw, m11, m12, m21, m22, tx, ty) { - var x = cx + Math.cos(a0) * r; - var y = cy + Math.sin(a0) * r; - var x1 = x * m11 + y * m12 + tx; - var y1 = x * m21 + y * m22 + ty; - if (ccw) { - if (a0 < a1) - a0 += Math.ceil((a1 - a0) / PI_DOUBLE + 0.1) * PI_DOUBLE; - if (a0 - a1 > PI_DOUBLE) - a1 = a0 - PI_DOUBLE; - } else { - if (a1 < a0) - a1 += Math.ceil((a0 - a1) / PI_DOUBLE + 0.1) * PI_DOUBLE; - if (a1 - a0 > PI_DOUBLE) - a1 = a0 + PI_DOUBLE; - } - var sweep = Math.abs(a1 - a0); - var dir = ccw ? -1 : 1; - while (sweep > 0) { - a1 = a0 + (sweep > PI_HALF ? PI_HALF : sweep) * dir; - var kappa = 4 / 3 * Math.tan((a1 - a0) / 4) * r; - var cos0 = Math.cos(a0); - var sin0 = Math.sin(a0); - var cp1x = cx + cos0 * r + -sin0 * kappa; - var cp1y = cy + sin0 * r + cos0 * kappa; - var cos1 = Math.cos(a1); - var sin1 = Math.sin(a1); - x = cx + cos1 * r; - y = cy + sin1 * r; - var cp2x = x + sin1 * kappa; - var cp2y = y + -cos1 * kappa; - var x2 = x * m11 + y * m12 + tx; - var y2 = x * m21 + y * m22 + ty; - sink._curveSeg(x1, y1, cp1x * m11 + cp1y * m12 + tx, cp1x * m21 + cp1y * m22 + ty, cp2x * m11 + cp2y * m12 + tx, cp2x * m21 + cp2y * m22 + ty, x2, y2); - x1 = x2; - y1 = y2; - a0 = a1; - sweep -= PI_HALF; - } - } - function getDerivativeRoots(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y) { - var res = []; - var dn1x = -x0 + 3 * cp1x - 3 * cp2x + x; - if (dn1x) { - var txl = -x0 + 2 * cp1x - cp2x; - var txr = -Math.sqrt(-x0 * (cp2x - x) + cp1x * cp1x - cp1x * (cp2x + x) + cp2x * cp2x); - var r1 = (txl + txr) / dn1x; - if (r1 > 0 && r1 < 1) - res.push(r1); - var r2 = (txl - txr) / dn1x; - if (r2 > 0 && r2 < 1) - res.push(r2); - } - var dn2x = x0 - 3 * cp1x + 3 * cp2x - x; - if (dn2x) { - var r3 = (x0 - 2 * cp1x + cp2x) / dn2x; - if (r3 > 0 && r3 < 1) - res.push(r3); - } - var dn1y = -y0 + 3 * cp1x - 3 * cp2x + y; - if (dn1y) { - var tyl = -y0 + 2 * cp1y - cp2y; - var tyr = -Math.sqrt(-y0 * (cp2y - y) + cp1y * cp1y - cp1y * (cp2y + y) + cp2y * cp2y); - var r4 = (tyl + tyr) / dn1y; - if (r4 > 0 && r4 < 1) - res.push(r4); - var r5 = (tyl - tyr) / dn1y; - if (r5 > 0 && r5 < 1) - res.push(r5); - } - var dn2y = y0 - 3 * cp1y + 3 * cp2y - y; - if (dn2y) { - var r6 = (y0 - 2 * cp1y + cp2y) / dn2y; - if (r6 > 0 && r6 < 1) - res.push(r6); - } - return res; - } - function getRoots(a, b, c, d) { - var res = []; - var bb = 6 * a - 12 * b + 6 * c; - var aa = -3 * a + 9 * b - 9 * c + 3 * d; - var cc = 3 * b - 3 * a; - if (aa == 0) { - if (bb == 0) { - return res; - } - var t = -cc / bb; - if (0 < t && t < 1) { - res.push(t); - } - return res; - } - var b2ac = Math.pow(bb, 2) - 4 * cc * aa; - if (b2ac < 0) { - return res; - } - var t1 = (-bb + Math.sqrt(b2ac)) / (2 * aa); - if (0 < t1 && t1 < 1) { - res.push(t1); - } - var t2 = (-bb - Math.sqrt(b2ac)) / (2 * aa); - if (0 < t2 && t2 < 1) { - res.push(t2); - } - ; - return res; - } - function computeCubicBaseValue(t, a, b, c, d) { - var mt = 1 - t; - return mt * mt * mt * a + 3 * mt * mt * t * b + 3 * mt * t * t * c + t * t * t * d; - } - function findCubicRoot(a, b, c, d, offset) { - var t = 1; - do { - var r = t; - var depth = 1; - do { - var tt = r; - var f = computeCubicBaseValue(tt, a, b, c, d) - offset; - var t2 = tt * tt; - var t6 = 6 * tt; - var t12 = 2 * t6; - var t92 = t2 * 9; - var mt2 = (tt - 1) * (tt - 1); - var df = 3 * d * t2 + c * (t6 - t92) + b * (t92 - t12 + 3) - 3 * a * mt2; - r = tt - f / df; - if (!df) - return -1; - if (depth > 12) { - if (Math.abs(tt - r) < 0.001) - break; - return -1; - } - } while (Math.abs(tt - r) > 0.0001); - if (r < 0 || r > 1) - continue; - var y = computeCubicBaseValue(r, a, b, c, d); - var dy = offset - y; - if (dy * dy > 1) - continue; - return r; - } while (t--); - return -1; - } - function scaleCurve(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y, distance) { - var pas = getAngularDir(cp1x - x0, cp1y - y0) + PI_HALF; - var pdxs = Math.cos(pas); - var pdys = Math.sin(pas); - var pae = getAngularDir(x - cp2x, y - cp2y) + PI_HALF; - var pdxe = Math.cos(pae); - var pdye = Math.sin(pae); - if (pdxs == pdxe && pdys == pdye) - return null; - var sx, sy; - if (pdxs == pdxe || pdys == pdye) { - sx = (x0 + x) / 2; - sy = (y0 + y) / 2; - } else { - var s = getLineIntersect(x0, y0, x0 + pdxs, y0 + pdys, x + pdxe, y + pdye, x, y); - sx = s[0]; - sy = s[1]; - } - var a1 = getAngularDir(x0 - sx, y0 - sy); - var a2 = getAngularDir(cp1x - sx, cp1y - sy); - var a3 = getAngularDir(cp2x - sx, cp2y - sy); - var a4 = getAngularDir(x - sx, y - sy); - if (a1 === a2 || a2 > a3) - distance = -distance; - var nax = x0 - distance * Math.cos(a1); - var nay = y0 - distance * Math.sin(a1); - var ndx = x - distance * Math.cos(a4); - var ndy = y - distance * Math.sin(a4); - var nbx, nby, ncx, ncy; - var nb = getLineIntersect(nax, nay, nax + (cp1x - x0), nay + (cp1y - y0), sx, sy, cp1x, cp1y); - if (nb) { - nbx = nb[0]; - nby = nb[1]; - } else { - nbx = nax; - nby = nay; - } - var nc = getLineIntersect(ndx, ndy, ndx + (cp2x - x), ndy + (cp2y - y), sx, sy, cp2x, cp2y); - if (nc) { - ncx = nc[0]; - ncy = nc[1]; - } else { - ncx = ndx; - ncy = ndy; - } - return [ - nax, - nay, - nbx, - nby, - ncx, - ncy, - ndx, - ndy - ]; - } - function getAngularDir(x, y) { - var d1 = 0; - var d2 = PI_HALF; - var d3 = PI; - var d4 = 3 * PI_HALF; - var angle = 0; - var ax = Math.abs(x); - var ay = Math.abs(y); - if (!x) - angle = y >= 0 ? d2 : d4; - else if (!y) - angle = x >= 0 ? d1 : d3; - else if (x > 0 && y > 0) - angle = d1 + Math.atan(ay / ax); - else if (x < 0 && y < 0) - angle = d3 + Math.atan(ay / ax); - else if (x < 0 && y > 0) - angle = d2 + Math.atan(ax / ay); - else if (x > 0 && y < 0) - angle = d4 + Math.atan(ax / ay); - return (angle + PI_DOUBLE) % PI_DOUBLE; - } - function getLineIntersect(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) { - var nx = (ax1 * ay2 - ay1 * ax2) * (bx1 - bx2) - (ax1 - ax2) * (bx1 * by2 - by1 * bx2); - var ny = (ax1 * ay2 - ay1 * ax2) * (by1 - by2) - (ay1 - ay2) * (bx1 * by2 - by1 * bx2); - var dn = (ax1 - ax2) * (by1 - by2) - (ay1 - ay2) * (bx1 - bx2); - if (!dn) - return null; - var px = nx / dn; - var py = ny / dn; - return [ - px, - py - ]; - } - function buildOutline(sink, data, styles) { - sink.moveTo(data[1], data[2]); - for (var i = 0; i < data.length;) { - var npoint = data[i]; - var x0 = data[i + 1]; - var y0 = data[i + 2]; - var a1x, a1y, a2x, a2y; - if (npoint === 2) { - var x = data[i + 3]; - var y = data[i + 4]; - sink.lineTo(x, y); - a1x = x0; - a1y = y0; - a2x = x; - a2y = y; - i += 5; - } else { - var cp1x = data[i + 3]; - var cp1y = data[i + 4]; - var cp2x = data[i + 5]; - var cp2y = data[i + 6]; - var x = data[i + 7]; - var y = data[i + 8]; - sink.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); - a1x = cp2x; - a1y = cp2y; - a2x = x; - a2y = y; - i += 9; - } - var lineJoin = styles.lineJoin || 'bevel'; - var p = i % data.length; - var b1x = data[p + 1]; - var b1y = data[p + 2]; - if (~(~(a2x + 0.5)) === ~(~(b1x + 0.5)) && ~(~(a2y + 0.5)) === ~(~(b1y + 0.5))) - continue; - var b2x = data[p + 3]; - var b2y = data[p + 4]; - var a1 = a2y - a1y; - var b1 = -(a2x - a1x); - var c1 = a1x * a2y - a2x * a1y; - var a2 = b2y - b1y; - var b2 = -(b2x - b1x); - var c2 = b1x * b2y - b2x * b1y; - var d = a1 * b2 - b1 * a2; - if (!d) { - sink.lineTo(b1x, b1y); - } else { - var x = (c1 * b2 - b1 * c2) / d; - var y = (a1 * c2 - c1 * a2) / d; - var ona = !(x < a1x && x < a2x || x > a1x && x > a2x || y < a1y && y < a2y || y > a1y && y > a2y); - var onb = !(x < b1x && x < b2x || x > b1x && x > b2x || y < b1y && y < b2y || y > b1y && y > b2y); - if (!ona && !onb) { - switch (lineJoin) { - case 'bevel': - sink.lineTo(b1x, b1y); - break; - case 'round': - sink.quadraticCurveTo(x, y, b1x, b1y); - break; - case 'miter': - default: - var a = -a2y - b1y; - var b = a2x - b1x; - var d = Math.sqrt(a * a + b * b); - var miterLen = (a * (x - b1x) + b * (y - b1y)) / d; - var maxLen = styles.miterLimit * styles.lineWidth / 2; - if (miterLen > maxLen) { - var p2 = maxLen / miterLen; - var p1 = 1 - p2; - sink.lineTo(a2x * p1 + x * p2, a2y * p1 + y * p2); - sink.lineTo(b1x * p1 + x * p2, b1y * p1 + y * p2); - } else { - sink.lineTo(x, y); - } - sink.lineTo(b1x, b1y); - break; - } - } else { - if (ona) - sink.lineTo(x, y); - sink.lineTo(b1x, b1y); - } - } - } - sink.closePath(); - } - function addLineCap(data, x, y, styles) { - var p = data.length; - var x1 = data[p - 4]; - var y1 = data[p - 3]; - var x2 = data[p - 2]; - var y2 = data[p - 1]; - switch (styles.lineCap) { - case 'round': - var cx = (x2 + x) / 2; - var cy = (y2 + y) / 2; - var a0 = Math.atan2(y2 - cy, x2 - cx); - var a1 = Math.atan2(y - cy, x - cx); - var sweep = Math.abs(a1 - a0); - var r = styles.lineWidth / 2; - while (sweep > 0) { - a1 = a0 + (sweep > PI_HALF ? PI_HALF : sweep); - var kappa = 4 / 3 * Math.tan((a1 - a0) / 4) * r; - var cos0 = Math.cos(a0); - var sin0 = Math.sin(a0); - var cp1x = cx + cos0 * r + -sin0 * kappa; - var cp1y = cy + sin0 * r + cos0 * kappa; - var cos1 = Math.cos(a1); - var sin1 = Math.sin(a1); - var x = cx + cos1 * r; - var y = cy + sin1 * r; - var cp2x = x + sin1 * kappa; - var cp2y = y + -cos1 * kappa; - data[p] = 4; - data[p + 1] = x2; - data[p + 2] = y2; - data[p + 3] = cp1x; - data[p + 4] = cp1y; - data[p + 5] = cp2x; - data[p + 6] = cp2y; - data[p + 7] = x; - data[p + 8] = y; - p += 9; - x2 = x; - y2 = y; - a0 = a1; - sweep -= PI_HALF; - } - break; - case 'square': - var distance = styles.lineWidth / 2; - var dx = x2 - x1; - var dy = y2 - y1; - var d = Math.sqrt(dx * dx + dy * dy); - var x3 = x2 + dx * distance / d; - var y3 = y2 + dy * distance / d; - var x4 = x + dx * distance / d; - var y4 = y + dy * distance / d; - data[p] = 2; - data[p + 1] = x2; - data[p + 2] = y2; - data[p + 3] = x3; - data[p + 4] = y3; - data[p + 5] = 2; - data[p + 6] = x3; - data[p + 7] = y3; - data[p + 8] = x4; - data[p + 9] = y4; - x2 = x4; - y2 = y4; - p += 10; - case 'none': - default: - data[p] = 2; - data[p + 1] = x2; - data[p + 2] = y2; - data[p + 3] = x; - data[p + 4] = y; - break; - } - } - var borrowSVGMatrix = !('currentTransform' in native2dCtxProto); - if (!borrowSVGMatrix) { - try { - idTransform = new SVGMatrix(); - transformClass = idTransform.constructor; - } catch (e) { - borrowSVGMatrix = true; - } - } - if (borrowSVGMatrix) { - var svgElement = doc.createElementNS(SVG_NAMESPACE, 'svg'); - transformClass = function SVGMatrix() { - return svgElement.createSVGMatrix(); - }; - transformClass.prototype = SVGMatrix.prototype; - idTransform = new transformClass(); - } - if (shimCurrentTransform) { - defineLazyProp(kanvas2dCtxProto, '_ct', { - get: function () { - return new transformClass(); - } - }); - defineLazyProp(kanvas2dCtxProto, '_ctm', { - get: function () { - return new Float32Array([ - 1, - 0, - 0, - 1, - 0, - 0 - ]); - } - }); - defineLazyProp(kanvas2dCtxProto, '_stack', { - get: Array - }); - defineProp(kanvas2dCtxProto, 'currentTransform', { - get: function () { - return this._ct; - }, - set: function (val) { - if (!(val instanceof transformClass)) - throw new TypeError(); - if (this._ct === val) - return; - this.setTransform(val.a, val.b, val.c, val.d, val.e, val.f); - } - }); - kanvas2dCtxProto.save = function () { - this._save(); - var ctm = this._ctm; - this._stack.push([ - ctm[0], - ctm[1], - ctm[2], - ctm[3], - ctm[4], - ctm[5] - ]); - }; - kanvas2dCtxProto.restore = function () { - this._restore(); - var stack = this._stack; - if (stack.length) { - var m = stack.pop(); - this.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]); - } - }; - kanvas2dCtxProto.scale = function (x, y) { - var ctm = this._ctm; - this.setTransform(ctm[0] * x, ctm[1] * x, ctm[2] * y, ctm[3] * y, ctm[4], ctm[5]); - }; - kanvas2dCtxProto.rotate = function (angle) { - var ctm = this._ctm; - var u = Math.cos(angle); - var v = Math.sin(angle); - this.setTransform(ctm[0] * u + ctm[2] * v, ctm[1] * u + ctm[3] * v, ctm[0] * -v + ctm[2] * u, ctm[1] * -v + ctm[3] * u, ctm[4], ctm[5]); - }; - kanvas2dCtxProto.translate = function (x, y) { - var ctm = this._ctm; - this.setTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[0] * x + ctm[2] * y + ctm[4], ctm[1] * x + ctm[3] * y + ctm[5]); - }; - kanvas2dCtxProto.transform = function (a, b, c, d, e, f) { - var ctm = this._ctm; - this.setTransform(ctm[0] * a + ctm[2] * b, ctm[1] * a + ctm[3] * b, ctm[0] * c + ctm[2] * d, ctm[1] * c + ctm[3] * d, ctm[0] * e + ctm[2] * f + ctm[4], ctm[1] * e + ctm[3] * f + ctm[5]); - }; - kanvas2dCtxProto.setTransform = function (a, b, c, d, e, f) { - this._setTransform(a, b, c, d, e, f); - var ct = this._ct; - var ctm = this._ctm; - ct.a = ctm[0] = a; - ct.b = ctm[1] = b; - ct.c = ctm[2] = c; - ct.d = ctm[3] = d; - ct.e = ctm[4] = e; - ct.f = ctm[5] = f; - }; - shimResetTransform = true; - } - if (shimResetTransform) { - kanvas2dCtxProto.resetTransform = function () { - this.setTransform(1, 0, 0, 1, 0, 0); - }; - } - if (shimEllipticalArcTo) { - kanvas2dCtxProto.arcTo = function (x1, y1, x2, y2, rx, ry, rotation) { - if (rx < 0 || ry < 0) - throw new RangeError(); - var x0 = x1; - var y0 = y1; - var m11 = 1; - var m12 = 0; - var m21 = 0; - var m22 = 1; - var tx = 0; - var ty = 0; - var ops = this._ops; - var p = ops.length; - while (p) { - switch (ops[p - 1]) { - case PATH_OP_CLOSE: - p = ops[p - 2]; - if (p) { - x0 = ops[p]; - y0 = ops[p + 1]; - } - break; - case PATH_OP_RECT: - x0 = ops[p - 5]; - y0 = ops[p - 4]; - break; - case PATH_OP_ARC: - var r = ops[p - 5]; - var a = ops[p - 3]; - x0 = ops[p - 7] + Math.cos(a) * r; - y0 = ops[p - 6] + Math.sin(a) * r; - break; - case PATH_OP_ELLIPSE: - var sx = ops[p - 7]; - var sy = ops[p - 6]; - var rot = ops[p - 5]; - var a = ops[p - 3]; - var u = Math.cos(rot); - var v = Math.sin(rot); - var x = Math.cos(a); - var y = Math.sin(a); - x0 = x * u * sx + y * v * sy + ops[p - 9]; - y0 = x * -v * sx + y * u * sy + ops[p - 8]; - break; - case PATH_OP_TRANSFORM: - var a = ops[p - 7]; - var b = ops[p - 6]; - var c = ops[p - 5]; - var d = ops[p - 4]; - var e = ops[p - 3]; - var f = ops[p - 2]; - p -= 8; - continue; - default: - x0 = ops[p - 3]; - y0 = ops[p - 2]; - } - break; - } - if (x1 === x0 && y1 === y0) { - this.moveTo(x1, y1); - return; - } - var dir = (x2 - x1) * (y0 - y1) + (y2 - y1) * (x1 - x0); - if (x1 === x0 && y1 === y0 || x1 === x2 && y1 === y2 || !rx || !ry || !dir) { - this.lineTo(x1, y1); - return; - } - if (rx !== ry) { - var scale = ry / rx; - m22 = Math.cos(-rotation); - m12 = Math.sin(-rotation); - m11 = m22 / scale; - m21 = -m12 / scale; - var ox1 = x0; - x0 = (ox1 * m22 - y0 * m12) * scale; - y0 = ox1 * m12 + y0 * m22; - var ox2 = x1; - x1 = (ox2 * m22 - y1 * m12) * scale; - y1 = ox2 * m12 + y1 * m22; - var ox3 = x2; - x2 = (ox3 * m22 - y2 * m12) * scale; - y2 = ox3 * m12 + y2 * m22; - } - var pa = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1); - var pb = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); - var pc = (x0 - x2) * (x0 - x2) + (y0 - y2) * (y0 - y2); - var cosx = (pa + pb - pc) / (2 * Math.sqrt(pa * pb)); - var sinx = Math.sqrt(1 - cosx * cosx); - var d = ry / ((1 - cosx) / sinx); - var sqa = Math.sqrt(pa); - var anx = (x1 - x0) / sqa; - var any = (y1 - y0) / sqa; - var sqb = Math.sqrt(pb); - var bnx = (x1 - x2) / sqb; - var bny = (y1 - y2) / sqb; - var x3 = x1 - anx * d; - var y3 = y1 - any * d; - var x4 = x1 - bnx * d; - var y4 = y1 - bny * d; - var ccw = dir < 0; - var cx = x3 + any * ry * (ccw ? 1 : -1); - var cy = y3 - anx * ry * (ccw ? 1 : -1); - var a0 = Math.atan2(y3 - cy, x3 - cx); - var a1 = Math.atan2(y4 - cy, x4 - cx); - this.save(); - this.transform(m11, m12, m21, m22, 0, 0); - this.lineTo(x3, y3); - this.arc(cx, cy, ry, a0, a1, ccw); - this.restore(); - }; - } - if (shimEllipse) { - kanvas2dCtxProto.ellipse = function (cx, cy, rx, ry, rotation, a0, a1, ccw) { - if (rx < 0 || ry < 0) - throw new RangeError(); - if (rx === ry) { - this.arc(cx, cy, rx, a0, a1, ccw); - return; - } - var u = Math.cos(rotation); - var v = Math.sin(rotation); - this.save(); - this.transform(u * rx, v * rx, -v * ry, u * ry, cx, cy); - this.arc(0, 0, 1, a0, a1, ccw); - this.restore(); - }; - } - if (shimPath) { - pathClass = function Path(d) { - if (!(this instanceof Path)) - return new Path(d); - var obj = this; - if (nativePathClass) { - obj = new nativePathClass(); - mixinProps(obj, kanvasPathProto); - } - if (arguments.length) { - if (d instanceof Path) - obj.addPath(d); - else { - Timer.start('parseSvgDataStr'); - parseSvgDataStr(obj, d); - Timer.stop(); - } - } - return obj; - }; - pathClass.prototype = nativePathProto || kanvasPathProto; - defineLazyProp(kanvasPathProto, '_state', { - get: function () { - return new Float32Array([ - 65535, - 65535, - -65535, - -65535, - 0, - 0 - ]); - } - }); - defineLazyProp(kanvasPathProto, '_segs', { - get: Array - }); - kanvasPathProto._lineSeg = function (x0, y0, x, y, close) { - var state = this._state; - if (x0 < state[0]) - state[0] = x0; - if (y0 < state[1]) - state[1] = y0; - if (x0 > state[2]) - state[2] = x0; - if (y0 > state[3]) - state[3] = y0; - if (x < state[0]) - state[0] = x; - if (y < state[1]) - state[1] = y; - if (x > state[2]) - state[2] = x; - if (y > state[3]) - state[3] = y; - var segs = this._segs; - var p = segs.length; - segs[p] = 2; - segs[p + 1] = x0; - segs[p + 2] = y0; - segs[p + 3] = x; - segs[p + 4] = y; - if (close) - segs[p + 5] = 0; - state[4] = x; - state[5] = y; - }; - kanvasPathProto._curveSeg = function (x0, y0, cp1x, cp1y, cp2x, cp2y, x, y) { - var state = this._state; - var segs = this._segs; - var p = segs.length; - if (x0 < state[0]) - state[0] = x0; - if (y0 < state[1]) - state[1] = y0; - if (x0 > state[2]) - state[2] = x0; - if (y0 > state[3]) - state[3] = y0; - var roots = getDerivativeRoots(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y); - if (!roots.length) { - roots = getRoots(x0, cp1x, cp2x, x); - for (var i = 0; i < roots.length; i++) { - var t = roots[i]; - var x = computeCubicBaseValue(t, x0, cp1x, cp2x, x); - if (x < state[0]) - state[0] = x; - if (x > state[2]) - state[2] = x; - } - roots = getRoots(y0, cp1y, cp2y, y); - for (var i = 0; i < roots.length; i++) { - var t = roots[i]; - var y = computeCubicBaseValue(t, y0, cp1y, cp2y, y); - if (y < state[1]) - state[1] = y; - if (y > state[3]) - state[3] = y; - } - if (x < state[0]) - state[0] = x; - if (y < state[1]) - state[1] = y; - if (x > state[2]) - state[2] = x; - if (y > state[3]) - state[3] = y; - segs[p] = 4; - segs[p + 1] = x0; - segs[p + 2] = y0; - segs[p + 3] = cp1x; - segs[p + 4] = cp1y; - segs[p + 5] = cp2x; - segs[p + 6] = cp2y; - segs[p + 7] = x; - segs[p + 8] = y; - state[4] = x; - state[5] = y; - return; - } - for (var i = 0; i <= roots.length; i++) { - var t = roots[i] || 1; - if (t > 0 && t <= 1) { - segs[p] = 4; - segs[p + 1] = x0; - segs[p + 2] = y0; - var mt = 1 - t; - var mx1 = mt * x0 + t * cp1x; - var my1 = mt * y0 + t * cp1y; - var mx2 = mt * cp1x + t * cp2x; - var my2 = mt * cp1y + t * cp2y; - cp2x = mt * cp2x + t * x; - cp2y = mt * cp2y + t * y; - var pcx = mt * mx1 + t * mx2; - var pcy = mt * my1 + t * my2; - cp1x = mt * mx2 + t * cp2x; - cp1y = mt * my2 + t * cp2y; - x0 = mt * pcx + t * cp1x; - y0 = mt * pcy + t * cp1y; - if (x0 < state[0]) - state[0] = x0; - if (y0 < state[1]) - state[1] = y0; - if (x0 > state[2]) - state[2] = x0; - if (y0 > state[3]) - state[3] = y0; - segs[p + 3] = mx1; - segs[p + 4] = my1; - segs[p + 5] = pcx; - segs[p + 6] = pcy; - segs[p + 7] = x0; - segs[p + 8] = y0; - p += 9; - } - } - state[4] = x; - state[5] = y; - }; - kanvasPathProto.closePath = function () { - if (this._sp) { - this._lineSeg(this._state[4], this._state[5], this._ops[this._sp], this._ops[this._sp + 1], true); - } - }; - kanvasPathProto.moveTo = function (x, y) { - this._state[4] = x; - this._state[5] = y; - }; - kanvasPathProto.lineTo = function (x, y) { - if (this._sp) { - this._lineSeg(this._state[4], this._state[5], x, y); - } else { - this._state[4] = x; - this._state[5] = y; - } - }; - kanvasPathProto.quadraticCurveTo = function (cpx, cpy, x, y) { - var x0, y0; - if (this._sp) { - x0 = this._state[4]; - y0 = this._state[5]; - } else { - x0 = cpx; - y0 = cpy; - } - var cp1x = x0 + 2 / 3 * (cpx - x0); - var cp1y = y0 + 2 / 3 * (cpy - y0); - var cp2x = cp1x + (x - x0) / 3; - var cp2y = cp1y + (y - y0) / 3; - this._curveSeg(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y); - }; - kanvasPathProto.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) { - var x0, y0; - if (this._sp) { - x0 = this._state[4]; - y0 = this._state[5]; - } else { - x0 = cp1x; - y0 = cp1y; - } - this._curveSeg(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y); - }; - kanvasPathProto.arcTo = function (x1, y1, x2, y2, rx, ry, rotation) { - if (arguments.length < 7) { - ry = rx; - rotation = 0; - } - if (rx < 0 || ry < 0) - throw new RangeError(); - var x0, y0; - if (this._sp) { - x0 = this._state[4]; - y0 = this._state[5]; - } else { - x0 = x1; - y0 = y1; - } - if (x1 === x0 && y1 === y0) - return; - var dir = (x2 - x1) * (y0 - y1) + (y2 - y1) * (x1 - x0); - if (x1 === x0 && y1 === y0 || x1 === x2 && y1 === y2 || !rx || !ry || !dir) { - this.lineTo(x1, y1); - return; - } - if (rx !== ry) { - var scale = ry / rx; - var u = Math.cos(-rotation); - var v = Math.sin(-rotation); - var ox1 = x0; - x0 = (ox1 * u - y0 * v) * scale; - y0 = ox1 * v + y0 * u; - var ox2 = x1; - x1 = (ox2 * u - y1 * v) * scale; - y1 = ox2 * v + y1 * u; - var ox3 = x2; - x2 = (ox3 * u - y2 * v) * scale; - y2 = ox3 * v + y2 * u; - } else { - var scale = 1; - var u = 1; - var v = 0; - } - var pa = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1); - var pb = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); - var pc = (x0 - x2) * (x0 - x2) + (y0 - y2) * (y0 - y2); - var cosx = (pa + pb - pc) / (2 * Math.sqrt(pa * pb)); - var sinx = Math.sqrt(1 - cosx * cosx); - var d = ry / ((1 - cosx) / sinx); - var anx = (x1 - x0) / Math.sqrt(pa); - var any = (y1 - y0) / Math.sqrt(pa); - var bnx = (x1 - x2) / Math.sqrt(pb); - var bny = (y1 - y2) / Math.sqrt(pb); - var x3 = x1 - anx * d; - var y3 = y1 - any * d; - var x4 = x1 - bnx * d; - var y4 = y1 - bny * d; - var ccw = dir < 0; - var cx = x3 + any * ry * (ccw ? 1 : -1); - var cy = y3 - anx * ry * (ccw ? 1 : -1); - var a0 = Math.atan2(y3 - cy, x3 - cx); - var a1 = Math.atan2(y4 - cy, x4 - cx); - var m11 = u / scale; - var m21 = -v / scale; - this._lineSeg(x0 * m11 + y0 * v, x0 * m21 + y0 * u, x3 * m11 + y3 * v, x3 * m21 + y3 * u); - arcToCurveSegs(this, cx, cy, ry, a0, a1, ccw, m11, v, m21, u, 0, 0); - }; - kanvasPathProto.rect = function (x, y, w, h) { - var tr = x + w; - var br = y + h; - this._lineSeg(x, y, tr, y); - this._lineSeg(tr, y, tr, br); - this._lineSeg(tr, br, x, br); - this._lineSeg(x, br, x, y, true); - }; - kanvasPathProto.arc = function (cx, cy, r, a0, a1, ccw) { - arcToCurveSegs(this, cx, cy, r, a0, a1, ccw, 1, 0, 0, 1, 0, 0); - if (a1 - a0 === PI_DOUBLE) - this._segs.push(0); - }; - kanvasPathProto.ellipse = function (x, y, rx, ry, rotation, a0, a1, ccw) { - var u = Math.cos(rotation); - var v = Math.sin(rotation); - var m11 = u * rx; - var m12 = v * ry; - var m21 = -v * rx; - var m22 = u * ry; - arcToCurveSegs(this, 0, 0, 1, a0, a1, ccw, m11, m12, m21, m22, x, y); - }; - kanvasPathProto.isPointInPath = function (x, y, winding) { - var state = this._state; - if (x < state[0] || y < state[1] || x > state[2] || y > state[3]) - return false; - var wn = 0; - var segs = this._segs; - for (var i = 0; i < segs.length; i++) { - var npoint = segs[i]; - if (!npoint) - continue; - var x0 = segs[i + 1]; - var y0 = segs[i + 2]; - if (npoint === 2) { - var x1 = segs[i + 3]; - var y1 = segs[i + 4]; - if (y0 <= y) { - if (y1 > y) { - if ((x1 - x0) * (y - y0) - (x - x0) * (y1 - y0) > 0) - ++wn; - } - } else { - if (y1 <= y) { - if ((x1 - x0) * (y - y0) - (x - x0) * (y1 - y0) < 0) - --wn; - } - } - i += 4; - } else { - var cp1x = segs[i + 3]; - var cp1y = segs[i + 4]; - var cp2x = segs[i + 5]; - var cp2y = segs[i + 6]; - var x1 = segs[i + 7]; - var y1 = segs[i + 8]; - if (y0 <= y) { - if (y1 > y) { - var t = findCubicRoot(y0, cp1y, cp2y, y1, y); - if (t > -1 && computeCubicBaseValue(t, x0, cp1x, cp1x, x1) > x) - ++wn; - } - } else { - if (y1 <= y) { - var t = findCubicRoot(y0, cp1y, cp2y, y1, y); - if (t > -1 && computeCubicBaseValue(t, x0, cp1x, cp1x, x1) > x) - --wn; - } - } - x0 = x1; - y0 = y1; - i += 8; - } - } - return !(!wn); - }; - if (shimBounds) { - kanvasPathProto.getBounds = function () { - var state = this._state; - return { - x: state[0], - y: state[1], - width: state[2] - state[0], - height: state[3] - state[1] - }; - }; - } - if (shimStrokePath) { - kanvasPathProto.strokePath = function (styles, transformation) { - if (!styles || !styles.lineWidth) - return; - if (arguments.length > 2) { - if (!(transform instanceof transformClass)) - throw new TypeError(); - } - var path = new pathClass(); - var distance = styles.lineWidth / 2; - var segs = this._segs; - var outer = []; - var inner = []; - var p = 0; - var x, y; - for (var i = 0; i < segs.length;) { - var npoint = segs[i]; - if (!npoint) { - if (outer.length) { - buildOutline(path, outer, styles); - inner.reverse(); - buildOutline(path, inner, styles); - outer = []; - inner = []; - p = 0; - } - i++; - continue; - } - var x0 = segs[i + 1]; - var y0 = segs[i + 2]; - if (x !== x0 || y !== y0) { - if (outer.length) { - inner.reverse(); - addLineCap(inner, outer[1], outer[2], styles); - addLineCap(outer, inner[1], inner[2], styles); - [].push.apply(outer, inner); - buildOutline(path, outer, styles); - outer = []; - inner = []; - p = 0; - } - } - if (npoint === 2) { - x = segs[i + 3]; - y = segs[i + 4]; - var dx = x - x0; - var dy = y - y0; - if (dx || dy) { - var k = distance / Math.sqrt(dx * dx + dy * dy); - dx *= k; - dy *= k; - outer[p] = 2; - outer[p + 1] = x0 + dy; - outer[p + 2] = y0 - dx; - outer[p + 3] = x + dy; - outer[p + 4] = y - dx; - inner[p] = y0 + dx; - inner[p + 1] = x0 - dy; - inner[p + 2] = y + dx; - inner[p + 3] = x - dy; - inner[p + 4] = 2; - } - p += 5; - i += 5; - } else { - var cp1x = segs[i + 3]; - var cp1y = segs[i + 4]; - var cp2x = segs[i + 5]; - var cp2y = segs[i + 6]; - x = segs[i + 7]; - y = segs[i + 8]; - var sc1 = scaleCurve(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y, distance); - var sc2 = scaleCurve(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y, -distance); - if (sc1 && sc2) { - outer[p] = 4; - outer[p + 1] = sc1[0]; - outer[p + 2] = sc1[1]; - outer[p + 3] = sc1[2]; - outer[p + 4] = sc1[3]; - outer[p + 5] = sc1[4]; - outer[p + 6] = sc1[5]; - outer[p + 7] = sc1[6]; - outer[p + 8] = sc1[7]; - inner[p] = sc2[1]; - inner[p + 1] = sc2[0]; - inner[p + 2] = sc2[3]; - inner[p + 3] = sc2[2]; - inner[p + 4] = sc2[5]; - inner[p + 5] = sc2[4]; - inner[p + 6] = sc2[7]; - inner[p + 7] = sc2[6]; - inner[p + 8] = 4; - } - p += 9; - i += 9; - } - } - if (outer.length) { - inner.reverse(); - addLineCap(inner, outer[1], outer[2], styles); - addLineCap(outer, inner[1], inner[2], styles); - [].push.apply(outer, inner); - buildOutline(path, outer, styles); - } - return path; - }; - } - defineProp(kanvas2dCtxProto, 'currentPath', { - get: function () { - var path = new pathClass(); - path._copyFrom(this); - return path; - }, - set: function (val) { - if (!(val instanceof pathClass)) - throw new TypeError(); - this.beginPath(); - this._copyFrom(val); - } - }); - kanvas2dCtxProto.beginPath = function () { - this._beginPath(); - this._ops = this._ops.slice(this._tp - 1, this._tp + 1); - this._sp = this._tp = 0; - }; - kanvas2dCtxProto.addPath = function (path) { - if (!(path instanceof pathClass)) - throw new TypeError(); - this.closePath(); - this._addFrom(path); - }; - } - if (shimEllipticalArcTo || shimPath) { - var recorderProto = Object.create(null); - defineLazyProp(recorderProto, '_ops', { - get: Array, - writable: true - }); - defineProp(recorderProto, '_sp', { - value: 0, - writable: true - }); - var pathMethods = [ - [ - PATH_OP_CLOSE, - 'closePath', - '', - true - ], - [ - PATH_OP_MOVE, - 'moveTo', - 'x,y', - true - ], - [ - PATH_OP_LINE, - 'lineTo', - 'x,y' - ], - [ - PATH_OP_CURVE, - 'quadraticCurveTo', - 'cpx,cpy,x,y' - ], - [ - PATH_OP_BEZIER, - 'bezierCurveTo', - 'cp1x,cp1y,cp2x,cp2y,x,y' - ], - [ - PATH_OP_ARCTO, - 'arcTo', - 'x1,y1,x2,y2,rx,ry,rotation' - ], - [ - PATH_OP_RECT, - 'rect', - 'x,y,w,h' - ], - [ - PATH_OP_ARC, - 'arc', - 'cx,cy,r,a0,a1,ccw' - ], - [ - PATH_OP_ELLIPSE, - 'ellipse', - 'cx,cy,rx,ry,rotation,a0,a1,ccw' - ] - ]; - var opArgPartial = 'o[p+$($2+1;)]'; - pathMethods.forEach(function (tuple) { - var code = tuple[0]; - var name = tuple[1]; - var params = tuple[2]; - var move = tuple[3]; - var tmpl = tmplf('function($2){this._$1($2);$$1;var o=this._ops,p=o.length;o[p]=$3,$(_($4,$6+"=+$1");),o[p+$(_($4).length+1;)]=$3;$($2&&!$5?"if(!this._sp)":"";)this._sp=p+1}', name, params, code, params || 'this._sp', move, opArgPartial); - var fn = evalf(tmpl, ''); - kanvas2dCtxProto[name] = fn; - if (nativePathClass && /{([\s\S]*)}/.test(kanvasPathProto[name])) - kanvasPathProto[name] = evalf(tmpl, RegExp.$1); - else - safeReplaceProp(kanvasPathProto, name, { - value: fn - }); - }); - defineProp(recorderProto, '_tp', { - value: 0, - writable: true - }); - var transformProps = 'a,b,c,d,e,f'; - var transformTmpl = tmplf('function($$2){this._$$1($$2);var t=this.currentTransform,o=this._ops,p=o.length$3;if(o[p-1]===$1)$(_($2,$4+$6););else o[p]=$1,$(_($2,$5+$6);),o[p+7]=$1,this._tp=p+1}', PATH_OP_TRANSFORM, transformProps, shimCurrentTransform ? ',m=this._ctm' : '', 'o[p-$(7-$2;)]', opArgPartial, '=$1=t.$1' + (shimCurrentTransform ? '=m[$2]=$1' : '')); - if (!shimCurrentTransform) { - [ - [ - 'scale', - 'x,y' - ], - [ - 'rotate', - 'angle' - ], - [ - 'translate', - 'x,y' - ], - [ - 'transform', - transformProps - ], - [ - 'resetTransform', - '' - ] - ].forEach(function (tuple) { - var name = tuple[0]; - var params = tuple[1]; - if (!(name in kanvas2dCtxProto)) - kanvas2dCtxProto[name] = evalf(transformTmpl, name, params); - }); - } - kanvas2dCtxProto.setTransform = evalf(transformTmpl, 'setTransform', transformProps); - var concatPathTmpl = tmplf('function(path){this.beginPath();var o=path._ops,p=0;while(p<o.length)switch(o[p]){$(_($1,"case $($1[0];):this._$($1[1];)($(_($1[2],\'"+$3+"\');));p+=$(_($1[2]).length+2;);break;","");)default:this._$$1($(_($2,$3);));p+=8}}', pathMethods, transformProps, opArgPartial); - defineProp(recorderProto, '_copyFrom', { - value: evalf(concatPathTmpl, 'setTransform') - }); - defineProp(recorderProto, '_addFrom', { - value: evalf(concatPathTmpl, 'transform') - }); - mixinProps(kanvas2dCtxProto, recorderProto); - mixinProps(kanvasPathProto, recorderProto); - } - if (shimHitRegions) { - defineLazyProp(kanvas2dCtxProto, '_map', { - get: function () { - var c = this.canvas; - var hrlist = this._hrlist; - c.addEventListener('mousemove', function (e) { - var x = e.clientX - c.offsetLeft; - var y = e.clientY - c.offsetTop; - var px = map.getImageData(x, y, 1, 1).data; - var p = (px[0] << 16 | px[1] << 8 | px[2]) / 255; - var region = hrlist[p - 1]; - if (region) { - e.region = region.id; - if (region.control) { - var evt = doc.createEvent('MouseEvents'); - evt.initMouseEvent('mousemove', e.bubbles, e.cancelable, e.view, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, c); - region.control.dispatchEvent(evt); - } - } else { - e.region = ''; - } - }, true); - var c2 = this.canvas.cloneNode(); - var map = c2.getContext('kanvas-2d'); - return map; - } - }); - defineLazyProp(kanvas2dCtxProto, '_hrlist', { - get: Array - }); - kanvas2dCtxProto.addHitRegion = function (options) { - if (typeof options !== 'object') - return; - var path = options.path || this.currentPath; - var color = (this._hrlist.length + 1) * 255; - var map = this._map; - var ct = this.currentTransform; - map.beginPath(); - map.setTransform(ct.a, ct.b, ct.c, ct.d, ct.e, ct.f); - map.addPath(path); - map.fillStyle = '#' + ('000000' + color.toString(16)).substr(-6); - map.fill(); - this._hrlist.push({ - color: color, - bounding: path.getBounds(), - id: options.id || '', - parent: options.parent || null, - cursor: options.cursor || 'inherit', - control: options.control || null - }); - }; - kanvas2dCtxProto.removeHitRegion = function (options) { - if (options.id) - delete this._hrlist[options.id]; - }; - kanvas2dCtxProto.clearRect = function (x, y, w, h) { - this._clearRect(x, y, w, h); - this._map._clearRect(x, y, w, h); - }; - } - defineProp(nativeCanvasProto, '_pctx', { - value: null - }); - nativeCanvasProto._getContext = nativeCanvasProto.getContext; - nativeCanvasProto.getContext = function (ctxId) { - var pctx = this._pctx; - var ctx; - if (ctxId === 'kanvas-2d') { - ctx = this._getContext('2d'); - if (pctx) - return pctx === ctx ? ctx : null; - mixinProps(ctx, kanvas2dCtxProto); - } else { - ctx = this._getContext.apply(this, arguments); - } - if (!pctx && ctx !== null) - defineProp(ctx, '_pctx', { - value: ctx - }); - return ctx; - }; - Kanvas.SVGMatrix = transformClass; - Kanvas.Path = pathClass; - return Kanvas; - }(document); (function (exports) { var ArgumentParser = function () { var Argument = function () { function argument(shortName, longName, type, options) { this.shortName = shortName; this.longName = longName; this.type = type; options = options || {}; @@ -2660,19 +1072,20 @@ function defineFont(tag, dictionary) { indices.push(i); } ranges.push([ UAC_OFFSET, UAC_OFFSET + glyphCount - 1, indices ]); } - var ascent = Math.ceil(tag.ascent / 20) || 1024; - var descent = -Math.ceil(tag.descent / 20) || 0; - var leading = Math.floor(tag.leading / 20) || 0; + var resolution = tag.resolution || 1; + var ascent = Math.ceil(tag.ascent / resolution) || 1024; + var descent = -Math.ceil(tag.descent / resolution) | 0; + var leading = tag.leading / resolution | 0; tables['OS/2'] = '\0\x01\0\0' + toString16(tag.bold ? 700 : 400) + '\0\x05' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0\0\0\0\0\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + 'ALF ' + toString16((tag.italic ? 1 : 0) | (tag.bold ? 32 : 0)) + toString16(codes[0]) + toString16(codes[codes.length - 1]) + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(ascent) + toString16(-descent) + '\0\0\0\0' + '\0\0\0\0'; ; var startCount = ''; var endCount = ''; var idDelta = ''; var idRangeOffset = ''; var i = 0; var range; @@ -2693,17 +1106,16 @@ function defineFont(tag, dictionary) { var searchRange = maxPower2(segCount) * 2; var rangeShift = 2 * segCount - searchRange; var format314 = '\0\0' + toString16(segCount * 2) + toString16(searchRange) + toString16(logE(segCount) / logE(2)) + toString16(rangeShift) + endCount + '\0\0' + startCount + idDelta + idRangeOffset; ; tables['cmap'] = '\0\0\0\x01\0\x03\0\x01\0\0\0\f\0\x04' + toString16(format314.length + 4) + format314; ; var glyf = '\0\x01\0\0\0\0\0\0\0\0\0\0\0\x001\0'; var loca = '\0\0'; - var resolution = tag.resolution || 1; var offset = 16; var maxPoints = 0; var xMins = []; var xMaxs = []; var yMins = []; var yMaxs = []; var maxContours = 0; var i = 0; @@ -2818,20 +1230,19 @@ function defineFont(tag, dictionary) { yMaxs.push(yMax); if (numberOfContours > maxContours) maxContours = numberOfContours; if (endPoint > maxPoints) maxPoints = endPoint; } loca += toString16(offset / 2); tables['glyf'] = glyf; - tables['head'] = '\0\x01\0\0\0\x01\0\0\0\0\0\0_\x0f<\xf5\0\v\x04\0\0\0\0\0' + toString32(+new Date()) + '\0\0\0\0' + toString32(+new Date()) + toString16(min.apply(null, xMins)) + toString16(min.apply(null, yMins)) + toString16(max.apply(null, xMaxs)) + toString16(max.apply(null, yMaxs)) + toString16((tag.italic ? 2 : 0) | (tag.bold ? 1 : 0)) + '\0\b' + '\0\x02' + '\0\0' + '\0\0'; + tables['head'] = '\0\x01\0\0\0\x01\0\0\0\0\0\0_\x0f<\xf5\0\v\x04\0\0\0\0\0' + toString32(Date.now()) + '\0\0\0\0' + toString32(Date.now()) + toString16(min.apply(null, xMins)) + toString16(min.apply(null, yMins)) + toString16(max.apply(null, xMaxs)) + toString16(max.apply(null, yMaxs)) + toString16((tag.italic ? 2 : 0) | (tag.bold ? 1 : 0)) + '\0\b' + '\0\x02' + '\0\0' + '\0\0'; ; var advance = tag.advance; - var resolution = tag.resolution || 1; tables['hhea'] = '\0\x01\0\0' + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(advance ? max.apply(null, advance) : 1024) + '\0\0' + '\0\0' + '\x03\xb8' + '\0\x01' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + toString16(glyphCount + 1); ; var hmtx = '\0\0\0\0'; for (var i = 0; i < glyphCount; ++i) hmtx += toString16(advance ? advance[i] / resolution : 1024) + '\0\0'; tables['hmtx'] = hmtx; if (tag.kerning) { var kerning = tag.kerning; @@ -2898,26 +1309,28 @@ function defineFont(tag, dictionary) { while (offset & 3) ++offset; offset += length; } var otf = header + data; var unitPerEm = 1024; var metrics = { ascent: ascent / unitPerEm, - descent: descent / unitPerEm, + descent: -descent / unitPerEm, leading: leading / unitPerEm }; return { type: 'font', id: tag.id, name: fontName, uniqueName: psName + uniqueId, codes: codes, metrics: metrics, + bold: tag.bold === 1, + italic: tag.italic === 1, data: otf }; } function getUint16(buff, pos) { return buff[pos] << 8 | buff[pos + 1]; } function parseJpegChunks(imgDef, bytes) { var i = 0; @@ -2985,18 +1398,18 @@ function defineLabel(tag, dictionary) { var m = tag.matrix; var cmds = [ 'c.save()', 'c.transform(' + [ m.a, m.b, m.c, m.d, - m.tx, - m.ty + m.tx / 20, + m.ty / 20 ].join(',') + ')', 'c.scale(0.05, 0.05)' ]; var dependencies = []; var x = 0; var y = 0; var i = 0; var record; @@ -3478,19 +1891,18 @@ SegmentedPath.prototype = { } }; var SHAPE_MOVE_TO = 1; var SHAPE_LINE_TO = 2; var SHAPE_CURVE_TO = 3; var SHAPE_WIDE_MOVE_TO = 4; var SHAPE_WIDE_LINE_TO = 5; var SHAPE_CUBIC_CURVE_TO = 6; -var SHAPE_ROUND_CORNER = 7; -var SHAPE_CIRCLE = 8; -var SHAPE_ELLIPSE = 9; +var SHAPE_CIRCLE = 7; +var SHAPE_ELLIPSE = 8; function ShapePath(fillStyle, lineStyle, commandsCount, dataLength, isMorph) { this.fillStyle = fillStyle; this.lineStyle = lineStyle; if (commandsCount) { this.commands = new Uint8Array(commandsCount); this.data = new Int32Array(dataLength); this.morphData = isMorph ? new Int32Array(dataLength) : null; } else { @@ -3529,20 +1941,16 @@ ShapePath.prototype = { var y2 = y + h; this.commands.push(SHAPE_MOVE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO); this.data.push(x, y, x2, y, x2, y2, x, y2, x, y); }, circle: function (x, y, radius) { this.commands.push(SHAPE_CIRCLE); this.data.push(x, y, radius); }, - drawRoundCorner: function (cornerX, cornerY, curveEndX, curveEndY, radiusX, radiusY) { - this.commands.push(SHAPE_ROUND_CORNER); - this.data.push(cornerX, cornerY, curveEndX, curveEndY, radiusX, radiusY); - }, ellipse: function (x, y, radiusX, radiusY) { this.commands.push(SHAPE_ELLIPSE); this.data.push(x, y, radiusX, radiusY); }, draw: function (ctx, clip, ratio, colorTransform) { if (clip && !this.fillStyle) { return; } @@ -3574,19 +1982,16 @@ ShapePath.prototype = { k += 2; break; case SHAPE_CURVE_TO: ctx.quadraticCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20); break; case SHAPE_CUBIC_CURVE_TO: ctx.bezierCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20); break; - case SHAPE_ROUND_CORNER: - ctx.arcTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20); - break; case SHAPE_CIRCLE: if (formOpen) { ctx.lineTo(formOpenX, formOpenY); formOpen = false; } ctx.moveTo((data[k] + data[k + 2]) / 20, data[k + 1] / 20); ctx.arc(data[k++] / 20, data[k++] / 20, data[k++] / 20, 0, Math.PI * 2, false); break; @@ -3639,16 +2044,17 @@ ShapePath.prototype = { console.warn('Drawing command not supported for morph shapes: ' + commands[j]); } } } if (!clip) { var fillStyle = this.fillStyle; if (fillStyle) { colorTransform.setFillStyle(ctx, fillStyle.style); + ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = fillStyle.smooth; var m = fillStyle.transform; ctx.save(); colorTransform.setAlpha(ctx); if (m) { ctx.transform(m.a, m.b, m.c, m.d, m.e / 20, m.f / 20); } ctx.fill(); ctx.restore(); @@ -3768,43 +2174,16 @@ ShapePath.prototype = { } var roots = cubicXAtY(fromX, fromY, cpX, cpY, cp2X, cp2Y, toX, toY, y); for (var i = roots.length; i--;) { if (roots[i] >= x) { inside = !inside; } } break; - case SHAPE_ROUND_CORNER: - cpX = data[dataIndex++]; - cpY = data[dataIndex++]; - toX = data[dataIndex++]; - toY = data[dataIndex++]; - rX = data[dataIndex++]; - rY = data[dataIndex++]; - if (toY > y === fromY > y || fromX < x && toX < x) { - break; - } - if (fromX >= x && toX >= x) { - inside = !inside; - break; - } - if (toX > fromX === toY > fromY) { - cp2X = fromX; - cp2Y = toY; - } else { - cp2X = toX; - cp2Y = fromY; - } - localX = x - cp2X; - localY = y - cp2Y; - if (localX * localX / (rX * rX) + localY * localY / (rY * rY) <= 1 !== localX <= 0) { - inside = !inside; - } - break; case SHAPE_CIRCLE: toX = data[dataIndex++]; toY = data[dataIndex++]; var r = data[dataIndex++]; localX = x - toX; localY = y - toY; if (localX * localX + localY * localY < r * r) { inside = !inside; @@ -3957,46 +2336,16 @@ ShapePath.prototype = { if (curveY < minY || curveY > maxY) { continue; } if ((x - curveX) * (x - curveX) + (y - curveY) * (y - curveY) < halfWidthSq) { return true; } } break; - case SHAPE_ROUND_CORNER: - cpX = data[dataIndex++]; - cpY = data[dataIndex++]; - toX = data[dataIndex++]; - toY = data[dataIndex++]; - rX = data[dataIndex++]; - rY = data[dataIndex++]; - if (maxX < fromX && maxX < toX || minX > fromX && minX > toX || maxY < fromY && maxY < toY || minY > fromY && minY > toY) { - break; - } - if (toX > fromX === toY > fromY) { - cp2X = fromX; - cp2Y = toY; - } else { - cp2X = toX; - cp2Y = fromY; - } - localX = Math.abs(x - cp2X); - localY = Math.abs(y - cp2Y); - localX -= halfWidth; - localY -= halfWidth; - if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) { - break; - } - localX += width; - localY += width; - if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) { - return true; - } - break; case SHAPE_CIRCLE: cpX = data[dataIndex++]; cpY = data[dataIndex++]; var r = data[dataIndex++]; toX = cpX + r; toY = cpY; if (maxX < cpX - r || minX > cpX + r || maxY < cpY - r || minY > cpY + r) { break; @@ -4048,17 +2397,17 @@ ShapePath.prototype = { } return bounds; }, _calculateBounds: function () { var commands = this.commands; var data = this.data; var length = commands.length; var bounds; - if (commands[0] === SHAPE_MOVE_TO || commands[0] > SHAPE_ROUND_CORNER) { + if (commands[0] === SHAPE_MOVE_TO || commands[0] > SHAPE_CUBIC_CURVE_TO) { bounds = { xMin: data[0], yMin: data[1] }; } else { bounds = { xMin: 0, yMin: 0 @@ -4119,19 +2468,16 @@ ShapePath.prototype = { } if (cpY < fromY || cp2Y < fromY || cpY > toY || cp2Y > toY) { extremes = cubicBezierExtremes(fromY, cpY, cp2Y, toY); for (i = extremes.length; i--;) { extendBoundsByY(bounds, extremes[i]); } } break; - case SHAPE_ROUND_CORNER: - dataIndex += 6; - break; case SHAPE_CIRCLE: toX = data[dataIndex++]; toY = data[dataIndex++]; var radius = data[dataIndex++]; extendBoundsByPoint(bounds, toX - radius, toY - radius); extendBoundsByPoint(bounds, toX + radius, toY + radius); toX += radius; break; @@ -4399,17 +2745,17 @@ function finishShapePaths(paths, diction path.morphData = untypedPath.morphData; } path.fillStyle && initStyle(path.fillStyle, dictionary); path.lineStyle && initStyle(path.lineStyle, dictionary); path.fullyInitialized = true; } } var inWorker = typeof window === 'undefined'; -var factoryCtx = !inWorker ? document.createElement('canvas').getContext('kanvas-2d') : null; +var factoryCtx = !inWorker ? document.createElement('canvas').getContext('2d') : null; function buildLinearGradientFactory(colorStops) { var defaultGradient = factoryCtx.createLinearGradient(-1, 0, 1, 0); for (var i = 0; i < colorStops.length; i++) { defaultGradient.addColorStop(colorStops[i].ratio, colorStops[i].color); } var fn = function createLinearGradient(ctx, colorTransform) { var gradient = ctx.createLinearGradient(-1, 0, 1, 0); for (var i = 0; i < colorStops.length; i++) { @@ -5109,17 +3455,17 @@ if (isWorker) { onloaded(null, null, error); }; session.pushAsync(data); session.close(); }; } SWF.embed = function (file, doc, container, options) { var canvas = doc.createElement('canvas'); - var ctx = canvas.getContext('kanvas-2d'); + var ctx = canvas.getContext('2d'); var loader = new flash.display.Loader(); var loaderInfo = loader.contentLoaderInfo; var stage = new flash.display.Stage(); stage._loader = loader; loaderInfo._parameters = options.movieParams; loaderInfo._url = options.url || (typeof file === 'string' ? file : null); loaderInfo._loaderURL = options.loaderURL || loaderInfo._url; var pixelRatio = 'devicePixelRatio' in window ? window.devicePixelRatio : 1; @@ -5156,53 +3502,53 @@ SWF.embed = function (file, doc, contain canvasHolder.style.height = stage._stageHeight / 20 + 'px'; } canvas.width = stage._stageWidth * pixelRatio / 20; canvas.height = stage._stageHeight * pixelRatio / 20; } container.setAttribute('style', 'position: relative'); canvas.addEventListener('click', function () { ShumwayKeyboardListener.focus = stage; - stage._clickTarget._dispatchEvent(new flash.events.MouseEvent('click')); + stage._mouseTarget._dispatchEvent('click'); }); canvas.addEventListener('dblclick', function () { - if (stage._clickTarget._doubleClickEnabled) { - stage._clickTarget._dispatchEvent(new flash.events.MouseEvent('doubleClick')); + if (stage._mouseTarget._doubleClickEnabled) { + stage._mouseTarget._dispatchEvent('doubleClick'); } }); canvas.addEventListener('mousedown', function () { - if (stage._clickTarget._buttonMode) { - stage._clickTarget._gotoButtonState('down'); - } - stage._clickTarget._dispatchEvent(new flash.events.MouseEvent('mouseDown')); + if (stage._mouseTarget._buttonMode) { + stage._mouseTarget._gotoButtonState('down'); + } + stage._mouseTarget._dispatchEvent('mouseDown'); }); canvas.addEventListener('mousemove', function (domEvt) { var node = this; var left = 0; var top = 0; if (node.offsetParent) { do { left += node.offsetLeft; top += node.offsetTop; } while (node = node.offsetParent); } - var canvasState = stage._canvasState; - var mouseX = ((domEvt.pageX - left) * pixelRatio - canvasState.offsetX) / canvasState.scaleX; - var mouseY = ((domEvt.pageY - top) * pixelRatio - canvasState.offsetY) / canvasState.scaleY; + var m = stage._concatenatedTransform; + var mouseX = ((domEvt.pageX - left) * pixelRatio - m.tx) / m.a; + var mouseY = ((domEvt.pageY - top) * pixelRatio - m.ty) / m.d; if (mouseX !== stage._mouseX || mouseY !== stage._mouseY) { stage._mouseMoved = true; stage._mouseX = mouseX * 20; stage._mouseY = mouseY * 20; } }); canvas.addEventListener('mouseup', function () { - if (stage._clickTarget._buttonMode) { - stage._clickTarget._gotoButtonState('over'); - } - stage._clickTarget._dispatchEvent(new flash.events.MouseEvent('mouseUp')); + if (stage._mouseTarget._buttonMode) { + stage._mouseTarget._gotoButtonState('over'); + } + stage._mouseTarget._dispatchEvent('mouseUp'); }); canvas.addEventListener('mouseover', function () { stage._mouseMoved = true; stage._mouseOver = true; }); canvas.addEventListener('mouseout', function () { stage._mouseMoved = true; stage._mouseOver = false; @@ -5267,17 +3613,17 @@ if (typeof FirefoxCom !== 'undefined') { var CanvasCache = { cache: [], getCanvas: function getCanvas(protoCanvas) { var tempCanvas = this.cache.shift(); if (!tempCanvas) { tempCanvas = { canvas: document.createElement('canvas') }; - tempCanvas.ctx = tempCanvas.canvas.getContext('kanvas-2d'); + tempCanvas.ctx = tempCanvas.canvas.getContext('2d'); } tempCanvas.canvas.width = protoCanvas.width; tempCanvas.canvas.height = protoCanvas.height; tempCanvas.ctx.save(); return tempCanvas; }, releaseCanvas: function releaseCanvas(tempCanvas) { tempCanvas.ctx.restore(); @@ -5303,38 +3649,28 @@ function visitContainer(container, visit } if (visitor.ignoreVisibleAttribute || child._visible && !child._maskedObject) { var isContainer = flash.display.DisplayObjectContainer.class.isInstanceOf(child) || flash.display.SimpleButton.class.isInstanceOf(child); visitor.visit(child, isContainer, visitContainer, context); } } visitor.childrenEnd(container); } +var BlendModeNameMap = { + 'normal': 'normal', + 'multiply': 'multiply', + 'screen': 'screen', + 'lighten': 'lighten', + 'darken': 'darken', + 'difference': 'difference', + 'overlay': 'overlay', + 'hardlight': 'hard-light' + }; function getBlendModeName(blendMode) { - var blendModeClass = flash.display.BlendMode.class; - if (blendMode === blendModeClass.NORMAL) { - return 'normal'; - } - switch (blendMode) { - case blendModeClass.MULTIPLY: - return 'multiply'; - case blendModeClass.SCREEN: - return 'screen'; - case blendModeClass.LIGHTEN: - return 'lighten'; - case blendModeClass.DARKEN: - return 'darken'; - case blendModeClass.DIFFERENCE: - return 'difference'; - case blendModeClass.OVERLAY: - return 'overlay'; - case blendModeClass.HARDLIGHT: - return 'hard-light'; - } - return 'normal'; + return BlendModeNameMap[blendMode] || 'normal'; } function RenderVisitor(root, ctx, invalidPath, refreshStage) { this.root = root; this.ctx = ctx; this.depth = 0; this.invalidPath = invalidPath; this.refreshStage = refreshStage; this.clipDepth = null; @@ -5451,27 +3787,28 @@ RenderVisitor.prototype = { ctx.clip(); context.isClippingMask = parentHasClippingMask; context.colorTransform = parentColorTransform; return; } ctx.save(); ctx.globalCompositeOperation = getBlendModeName(child._blendMode); if (child._mask) { + var m = child._parent._getConcatenatedTransform(true); var tempCanvas, tempCtx, maskCanvas, maskCtx; maskCanvas = CanvasCache.getCanvas(ctx.canvas); maskCtx = maskCanvas.ctx; - maskCtx.currentTransform = ctx.currentTransform; + maskCtx.setTransform(m.a, m.b, m.c, m.d, m.tx, m.ty); var isMaskContainer = flash.display.DisplayObjectContainer.class.isInstanceOf(child._mask) || flash.display.SimpleButton.class.isInstanceOf(child._mask); this.ctx = maskCtx; this.visit(child._mask, isMaskContainer, visitContainer, new RenderingContext(this.refreshStage)); this.ctx = ctx; tempCanvas = CanvasCache.getCanvas(ctx.canvas); tempCtx = tempCanvas.ctx; - tempCtx.currentTransform = ctx.currentTransform; + tempCtx.setTransform(m.a, m.b, m.c, m.d, m.tx, m.ty); renderDisplayObject(child, tempCtx, context); if (isContainer) { this.ctx = tempCtx; visitContainer(child, this, context); this.ctx = ctx; } tempCtx.globalCompositeOperation = 'destination-in'; tempCtx.setTransform(1, 0, 0, 1, 0, 0); @@ -5745,39 +4082,37 @@ function renderStage(stage, ctx, events) if (align.indexOf('T') >= 0) { offsetY = 0; } else if (align.indexOf('B') >= 0) { offsetY = frameHeight - scaleY * stage._stageHeight / 20; } else { offsetY = (frameHeight - scaleY * stage._stageHeight / 20) / 2; } ctx.setTransform(scaleX, 0, 0, scaleY, offsetX, offsetY); - stage._canvasState = { - canvas: ctx.canvas, - scaleX: scaleX, - scaleY: scaleY, - offsetX: offsetX, - offsetY: offsetY - }; + var m = stage._concatenatedTransform; + m.a = scaleX; + m.d = scaleY; + m.tx = offsetX; + m.ty = offsetY; } updateRenderTransform(); var frameTime = 0; var maxDelay = 1000 / stage._frameRate; var nextRenderAt = performance.now(); var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || window.setTimeout; var renderDummyBalls; var dummyBalls; if (typeof FirefoxCom !== 'undefined' && FirefoxCom.requestSync('getBoolPref', { pref: 'shumway.dummyMode', def: false })) { var radius = 10; var speed = 1; - var canvasState = stage._canvasState; - var scaleX = canvasState.scaleX, scaleY = canvasState.scaleY; + var m = stage._concatenatedTransform; + var scaleX = m.a, scaleY = m.d; dummyBalls = []; for (var i = 0; i < 10; i++) { dummyBalls.push({ position: { x: radius + Math.random() * ((ctx.canvas.width - 2 * radius) / scaleX), y: radius + Math.random() * ((ctx.canvas.height - 2 * radius) / scaleY) }, velocity: { @@ -5876,19 +4211,21 @@ function renderStage(stage, ctx, events) stage._deferRenderEvent = false; domain.broadcastMessage('render', 'render'); } if (isCanvasVisible(ctx.canvas) && (refreshStage || renderFrame)) { var invalidPath = null; if (!disablePreVisitor.value) { traceRenderer.value && frameWriter.enter('> Pre Visitor'); fps && fps.enter('PRE'); - invalidPath = stage._processInvalidRegions(); + invalidPath = stage._processInvalidRegions(true); fps && fps.leave('PRE'); traceRenderer.value && frameWriter.leave('< Pre Visitor'); + } else { + stage._processInvalidRegions(false); } if (!disableRenderVisitor.value) { fps && fps.enter('RENDER'); traceRenderer.value && frameWriter.enter('> Render Visitor'); new RenderVisitor(stage, ctx, invalidPath, refreshStage).start(); traceRenderer.value && frameWriter.leave('< Render Visitor'); fps && fps.leave('RENDER'); } @@ -6155,187 +4492,23 @@ var tagHandler = function (global) { $29.depth = readUi16($bytes, $stream); var $30 = $29.matrix = {}; matrix($bytes, $stream, $30, swfVersion, tagCode); if (tagCode === 34) { var $31 = $29.cxform = {}; cxform($bytes, $stream, $31, swfVersion, tagCode); } if (hasFilters) { - $29.filterCount = readUi8($bytes, $stream); - var $32 = $29.filters = {}; - var type = $32.type = readUi8($bytes, $stream); - switch (type) { - case 0: - if (type === 4 || type === 7) { - count = readUi8($bytes, $stream); - } else { - count = 1; - } - var $33 = $32.colors = []; - var $34 = count; - while ($34--) { - var $35 = {}; - rgba($bytes, $stream, $35, swfVersion, tagCode); - $33.push($35); - } - if (type === 3) { - var $36 = $32.higlightColor = {}; - rgba($bytes, $stream, $36, swfVersion, tagCode); - } - if (type === 4 || type === 7) { - var $37 = $32.ratios = []; - var $38 = count; - while ($38--) { - $37.push(readUi8($bytes, $stream)); - } - } - $32.blurX = readFixed($bytes, $stream); - $32.blurY = readFixed($bytes, $stream); - if (type !== 2) { - $32.angle = readFixed($bytes, $stream); - $32.distance = readFixed($bytes, $stream); - } - $32.strength = readFixed8($bytes, $stream); - $32.innerShadow = readUb($bytes, $stream, 1); - $32.knockout = readUb($bytes, $stream, 1); - $32.compositeSource = readUb($bytes, $stream, 1); - if (type === 3) { - $32.onTop = readUb($bytes, $stream, 1); - } else { - var reserved = readUb($bytes, $stream, 1); - } - if (type === 4 || type === 7) { - $32.passes = readUb($bytes, $stream, 4); - } else { - var reserved = readUb($bytes, $stream, 4); - } - break; - case 1: - $32.blurX = readFixed($bytes, $stream); - $32.blurY = readFixed($bytes, $stream); - $32.passes = readUb($bytes, $stream, 5); - var reserved = readUb($bytes, $stream, 3); - break; - case 2: - case 3: - case 4: - if (type === 4 || type === 7) { - count = readUi8($bytes, $stream); - } else { - count = 1; - } - var $39 = $32.colors = []; - var $40 = count; - while ($40--) { - var $41 = {}; - rgba($bytes, $stream, $41, swfVersion, tagCode); - $39.push($41); - } - if (type === 3) { - var $42 = $32.higlightColor = {}; - rgba($bytes, $stream, $42, swfVersion, tagCode); - } - if (type === 4 || type === 7) { - var $43 = $32.ratios = []; - var $44 = count; - while ($44--) { - $43.push(readUi8($bytes, $stream)); - } - } - $32.blurX = readFixed($bytes, $stream); - $32.blurY = readFixed($bytes, $stream); - if (type !== 2) { - $32.angle = readFixed($bytes, $stream); - $32.distance = readFixed($bytes, $stream); - } - $32.strength = readFixed8($bytes, $stream); - $32.innerShadow = readUb($bytes, $stream, 1); - $32.knockout = readUb($bytes, $stream, 1); - $32.compositeSource = readUb($bytes, $stream, 1); - if (type === 3) { - $32.onTop = readUb($bytes, $stream, 1); - } else { - var reserved = readUb($bytes, $stream, 1); - } - if (type === 4 || type === 7) { - $32.passes = readUb($bytes, $stream, 4); - } else { - var reserved = readUb($bytes, $stream, 4); - } - break; - case 5: - var columns = $32.columns = readUi8($bytes, $stream); - var rows = $32.rows = readUi8($bytes, $stream); - $32.divisor = readFloat($bytes, $stream); - $32.bias = readFloat($bytes, $stream); - var $45 = $32.weights = []; - var $46 = columns * rows; - while ($46--) { - $45.push(readFloat($bytes, $stream)); - } - var $47 = $32.defaultColor = {}; - rgba($bytes, $stream, $47, swfVersion, tagCode); - var reserved = readUb($bytes, $stream, 6); - $32.clamp = readUb($bytes, $stream, 1); - $32.preserveAlpha = readUb($bytes, $stream, 1); - break; - case 6: - var $48 = $32.matrix = []; - var $49 = 20; - while ($49--) { - $48.push(readFloat($bytes, $stream)); - } - break; - case 7: - if (type === 4 || type === 7) { - count = readUi8($bytes, $stream); - } else { - count = 1; - } - var $50 = $32.colors = []; - var $51 = count; - while ($51--) { - var $52 = {}; - rgba($bytes, $stream, $52, swfVersion, tagCode); - $50.push($52); - } - if (type === 3) { - var $53 = $32.higlightColor = {}; - rgba($bytes, $stream, $53, swfVersion, tagCode); - } - if (type === 4 || type === 7) { - var $54 = $32.ratios = []; - var $55 = count; - while ($55--) { - $54.push(readUi8($bytes, $stream)); - } - } - $32.blurX = readFixed($bytes, $stream); - $32.blurY = readFixed($bytes, $stream); - if (type !== 2) { - $32.angle = readFixed($bytes, $stream); - $32.distance = readFixed($bytes, $stream); - } - $32.strength = readFixed8($bytes, $stream); - $32.innerShadow = readUb($bytes, $stream, 1); - $32.knockout = readUb($bytes, $stream, 1); - $32.compositeSource = readUb($bytes, $stream, 1); - if (type === 3) { - $32.onTop = readUb($bytes, $stream, 1); - } else { - var reserved = readUb($bytes, $stream, 1); - } - if (type === 4 || type === 7) { - $32.passes = readUb($bytes, $stream, 4); - } else { - var reserved = readUb($bytes, $stream, 4); - } - break; - default: + var count = readUi8($bytes, $stream); + var $2 = $.filters = []; + var $3 = count; + while ($3--) { + var $4 = {}; + anyFilter($bytes, $stream, $4, swfVersion, tagCode); + $2.push($4); } } if (blend) { $29.blendMode = readUi8($bytes, $stream); } } $28.push($29); } while (!eob); @@ -7663,17 +5836,18 @@ CompressedPipe.prototype = { this.state.bitLength = stream.bitLength; } buffer.removeHead(stream.pos); this.target.push(output.data.subarray(lastAvailable, output.available), progressInfo); } }; function BodyParser(swfVersion, length, options) { this.swf = { - swfVersion: swfVersion + swfVersion: swfVersion, + parseTime: 0 }; this.buffer = new HeadTailBuffer(32768); this.initialize = true; this.totalRead = 0; this.length = length; this.options = options; } BodyParser.prototype = { @@ -7714,17 +5888,19 @@ BodyParser.prototype = { } else { buffer.push(data); stream = buffer.createStream(); } if (progressInfo) { swf.bytesLoaded = progressInfo.bytesLoaded; swf.bytesTotal = progressInfo.bytesTotal; } + var readStartTime = performance.now(); readTags(swf, stream, swfVersion, options.onprogress); + swf.parseTime += performance.now() - readStartTime; var read = stream.pos; buffer.removeHead(read); this.totalRead += read; if (this.totalRead >= this.length && options.oncomplete) { options.oncomplete(swf); } } }; @@ -8065,16 +6241,17 @@ function as2ToBoolean(value) { case 'null': return false; case 'boolean': return value; case 'number': return value !== 0 && !isNaN(value); case 'string': return value.length !== 0; + case 'movieclip': case 'object': return true; } } function as2ToNumber(value) { value = as2ToPrimitive(value); switch (as2GetType(value)) { case 'undefined': @@ -8308,17 +6485,17 @@ function interpretActions(actionsData, s var newScope = {}; newScope.asSetPublicProperty('this', this); newScope.asSetPublicProperty('arguments', arguments); newScope.asSetPublicProperty('super', AS2_SUPER_STUB); newScope.asSetPublicProperty('__class', ownerClass); var newScopeContainer = scopeContainer.create(newScope); var i; for (i = 0; i < arguments.length || i < parametersNames.length; i++) { - newScope[parametersNames[i]] = arguments[i]; + newScope.asSetPublicProperty(parametersNames[i], arguments[i]); } var registers = []; if (registersAllocation) { for (i = 0; i < registersAllocation.length; i++) { var registerAllocation = registersAllocation[i]; if (!registerAllocation) { continue; } @@ -8420,47 +6597,72 @@ function interpretActions(actionsData, s return { obj: obj, name: resolvedName || name, resolved: resolved }; } return null; } + function getThis() { + var _this = scope.asGetPublicProperty('this'); + if (_this) { + return _this; + } + for (var p = scopeContainer; p; p = p.next) { + resolvedName = as2ResolveProperty(p.scope, 'this'); + if (resolvedName !== null) { + return p.scope.asGetPublicProperty(resolvedName); + } + } + } function getVariable(variableName) { if (scope.asHasProperty(undefined, variableName, 0)) { return scope.asGetPublicProperty(variableName); } var target = resolveVariableName(variableName); if (target) { return target.obj.asGetPublicProperty(target.name); } + var resolvedName, _this = getThis(); for (var p = scopeContainer; p; p = p.next) { - var resolvedName = as2ResolveProperty(p.scope, variableName); + resolvedName = as2ResolveProperty(p.scope, variableName); if (resolvedName !== null) { return p.scope.asGetPublicProperty(resolvedName); } } + if (_this && (resolvedName = as2ResolveProperty(_this, variableName))) { + return _this.asGetPublicProperty(resolvedName); + } var mc = isAS2MovieClip(defaultTarget) && defaultTarget.$lookupChild(variableName); if (mc) { return mc; } } function setVariable(variableName, value) { if (scope.asHasProperty(undefined, variableName, 0)) { scope.asSetPublicProperty(variableName, value); return; } var target = resolveVariableName(variableName, true); if (target) { target.obj.asSetPublicProperty(target.name, value); return; } - var _this = scope.asGetPublicProperty('this') || getVariable('this'); - _this.asSetPublicProperty(variableName, value); + var resolvedName, _this = getThis(); + if (_this && (resolvedName = as2ResolveProperty(_this, variableName))) { + return _this.asSetPublicProperty(resolvedName, value); + } + for (var p = scopeContainer; p.next; p = p.next) { + resolvedName = as2ResolveProperty(p.scope, variableName); + if (resolvedName !== null) { + return p.scope.asSetPublicProperty(resolvedName, value); + } + } + (_this || scope).asSetPublicProperty(variableName, value); } function getFunction(functionName) { var fn = getVariable(functionName); if (!(fn instanceof Function)) { throw new Error('Function "' + functionName + '" is not found'); } return fn; } @@ -8551,17 +6753,19 @@ function interpretActions(actionsData, s var frame, type, count, index, target, method, constr, codeSize, offset; var name, variableName, methodName, functionName, targetName; var paramName, resolvedName, objectName; var value, a, b, c, f, sa, sb, obj, args, fn, result, flags, i; var dragParams, register; switch (actionCode | 0) { case 129: frame = stream.readUI16(); - methodName = stream.readUI8() === 6 ? 'gotoAndPlay' : 'gotoAndStop'; + var nextActionCode = stream.readUI8(); + nextPosition++; + methodName = nextActionCode === 6 ? 'gotoAndPlay' : 'gotoAndStop'; _global[methodName](frame + 1); break; case 131: var urlString = stream.readString(); var targetString = stream.readString(); _global.getURL(urlString, targetString); break; case 4: @@ -8809,17 +7013,17 @@ function interpretActions(actionsData, s case 36: var depth = stack.pop(); target = stack.pop(); var source = stack.pop(); _global.duplicateMovieClip(source, target, depth); break; case 37: target = stack.pop(); - _global.unloadMovie(target); + _global.removeMovieClip(target); break; case 39: target = stack.pop(); var lockcenter = stack.pop(); var constrain = !stack.pop() ? null : { y2: stack.pop(), x2: stack.pop(), y1: stack.pop(), @@ -9267,16 +7471,21 @@ function interpretActions(actionsData, s } } catch (e) { if (!AVM1_ERRORS_IGNORED && !currentContext.isTryCatchListening || e instanceof AS2CriticalError) { throw e; } if (e instanceof AS2Error) { throw e; } + var AVM1_ERROR_TYPE = 1; + TelemetryService.reportTelemetry({ + topic: 'error', + error: AVM1_ERROR_TYPE + }); stream.position = nextPosition; if (stackItemsExpected > 0) { while (stackItemsExpected--) { stack.push(undefined); } } if (!recoveringFromError) { if (currentContext.errorsIgnored++ >= MAX_AVM1_ERRORS_LIMIT) { @@ -9452,16 +7661,22 @@ if (!inBrowser) { info: print, warn: function (x) { if (traceWarnings.value) { print(x); } } }; } +if (!this.performance) { + this.performance = {}; +} +if (!this.performance.now) { + this.performance.now = Date.now; +} function backtrace() { try { throw new Error(); } catch (e) { return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; } } function error(message) { @@ -9632,22 +7847,22 @@ function defineNewNonEnumerableProperty( } function isNullOrUndefined(value) { return value == undefined; } function isPowerOfTwo(x) { return x && (x & x - 1) === 0; } function time(fn, count) { - var start = new Date(); + var start = performance.now(); for (var i = 0; i < count; i++) { fn(); } - var time = (new Date() - start) / count; - console.info('Took: ' + time + 'ms.'); + var time = (performance.now() - start) / count; + console.info('Took: ' + time.toFixed(2) + 'ms.'); return time; } function clamp(x, min, max) { if (x < min) { return min; } else if (x > max) { return max; } @@ -9674,19 +7889,30 @@ function toKeyValueArray(o) { o[k] ]); } } return a; } function isNumeric(x) { if (typeof x === 'number') { - return true; - } else if (typeof x === 'string') { - return !isNaN(parseInt(x, 10)); + return x === (x | 0); + } + if (typeof x === 'string' && x.length) { + if (x === '0') { + return true; + } + if (x[0] >= '1' && x[0] <= '9') { + for (var i = 1; i < x.length; i++) { + if (!(x[i] >= '1' && x[i] <= '9')) { + return false; + } + } + return true; + } } return false; } function boxValue(value) { if (isNullOrUndefined(value)) { return value; } return Object(value); @@ -9698,34 +7924,18 @@ function isString(value) { return typeof value === 'string'; } function isFunction(value) { return typeof value === 'function'; } function isNumber(value) { return typeof value === 'number'; } -function toDouble(x) { - return toNumber(x); -} function toNumber(x) { - return typeof x === 'number' ? x : Number(x); -} -function toBoolean(x) { - return !(!x); -} -function toUint(x) { - x = x | 0; - return x < 0 ? x + 4294967296 : x; -} -function toInt(x) { - return x | 0; -} -function toString(x) { - return String(x); + return +x; } function setBitFlags(flags, flag, value) { return value ? flags | flag : flags & ~flag; } function getBitFlags(flags, flag) { return !(!(flags & flag)); } function popManyInto(src, count, dst) { @@ -9915,26 +8125,35 @@ function utf8encode(bytes) { do { var mask = currentPrefix >> 1 | 128; if ((b1 & mask) === currentPrefix) break; currentPrefix = currentPrefix >> 1 | 128; --validBits; } while (validBits >= 0); if (validBits <= 0) { - throw 'Invalid UTF8 character'; + str += String.fromCharCode(b1); + continue; } var code = b1 & (1 << validBits) - 1; + var invalid = false; for (var i = 5; i >= validBits; --i) { var bi = bytes[j++]; if ((bi & 192) != 128) { - throw 'Invalid UTF8 character sequence'; + invalid = true; + break; } code = code << 6 | bi & 63; } + if (invalid) { + for (var k = j - (7 - i); k < j; ++k) { + str += String.fromCharCode(bytes[k] & 255); + } + continue; + } if (code >= 65536) { str += String.fromCharCode(code - 65536 >> 10 & 1023 | 55296, code & 1023 | 56320); } else { str += String.fromCharCode(code); } } } return str; @@ -10678,49 +8897,54 @@ var CircularBuffer = function () { return this.index + 1 & mask === this.start; }; circularBuffer.prototype.isEmpty = function () { return this.index === this.start; }; return circularBuffer; }(); (function (exports) { + if (!performance) { + performance = { + now: Date.now + }; + } var Timer = function () { var base = new timer(null, 'Total'), top = base; var flat = new timer(null, 'Flat'), flatStack = []; function timer(parent, name) { this.parent = parent; this.timers = {}; this.name = name; this.begin = 0; this.last = 0; this.total = 0; this.count = 0; } timer.flat = flat; function getTicks() { - return new Date().getTime(); + return performance.now(); } timer.prototype.start = function () { this.begin = getTicks(); }; timer.prototype.stop = function () { this.last = getTicks() - this.begin; this.total += this.last; this.count += 1; }; timer.time = function (name, fn) { timer.start(name); fn(); timer.stop(); }; timer.start = function (name) { - top = name in top.timers ? top.timers[name] : top.timers[name] = new timer(top, name); + top = top.timers[name] || (top.timers[name] = new timer(top, name)); top.start(); - var tmp = name in flat.timers ? flat.timers[name] : flat.timers[name] = new timer(flat, name); + var tmp = flat.timers[name] || (flat.timers[name] = new timer(flat, name)); tmp.start(); flatStack.push(tmp); }; timer.stop = function () { top.stop(); top = top.parent; flatStack.pop().stop(); }; @@ -11721,20 +9945,16 @@ var Errors = { InvalidSocketError: { code: 2002, message: 'Operation attempted on invalid socket.' }, InvalidSocketPortError: { code: 2003, message: 'Invalid socket port number specified.' }, - InvalidParamError: { - code: 2004, - message: 'One of the parameters is invalid.' - }, ParamTypeError: { code: 2005, message: 'Parameter %1 is of the incorrect type. Should be type %2.' }, HasStyleSheetError: { code: 2009, message: 'This method cannot be used on a text field with a style sheet.' }, @@ -11981,20 +10201,16 @@ var Errors = { CloseNotConnectedError: { code: 2083, message: 'Close failed because the object is not connected.' }, ArgumentSizeError: { code: 2084, message: 'The AMF encoding of the arguments cannot exceed 40K.' }, - EmptyStringError: { - code: 2085, - message: 'Parameter %1 must be non-empty string.' - }, FileReferenceProhibitedError: { code: 2086, message: 'A setting in the mms.cfg file prohibits this FileReference request.' }, DownloadFileNameProhibitedError: { code: 2087, message: 'The FileReference.download() file name contains prohibited characters.' }, @@ -12277,20 +10493,16 @@ var Errors = { FragmentMissing: { code: 2171, message: 'The Shader object contains no byte code to execute.' }, FragmentAlreadyRunning: { code: 2172, message: 'The ShaderJob is already running or finished.' }, - ReadExternalNotImplementedError: { - code: 2173, - message: 'Unable to read object in stream. The class %1 does not implement flash.utils.IExternalizable but is aliased to an externalizable class.' - }, FileReferenceBusyError: { code: 2174, message: 'Only one download, upload, load or save operation can be active at a time on each FileReference.' }, UnformattedElementError: { code: 2175, message: 'One or more elements of the content of the TextBlock has a null ElementFormat.' }, @@ -15266,16 +13478,23 @@ var Multiname = function () { } mn = mn.qualifiedName = qualifyNameInternal(mn.namespaces[0].qualifiedName, name); } return mn; }; multiname.qualifyName = function qualifyName(namespace, name) { return qualifyNameInternal(namespace.qualifiedName, name); }; + multiname.stripPublicQualifier = function stripPublicQualifier(qn) { + var index = qn.indexOf(PUBLIC_QUALIFIED_NAME_PREFIX); + if (index !== 0) { + return undefined; + } + return qn.substring(PUBLIC_QUALIFIED_NAME_PREFIX.length); + }; multiname.fromQualifiedName = function fromQualifiedName(qn) { if (qn instanceof Multiname) { return qn; } true; var a = qn.indexOf('$'); if (a < 0 || !ShumwayNamespace.PREFIXES[qn.substring(0, a)]) { return undefined; @@ -15295,17 +13514,16 @@ var Multiname = function () { }; multiname.PUBLIC_QUALIFIED_NAME_PREFIX = PUBLIC_QUALIFIED_NAME_PREFIX; multiname.getPublicQualifiedName = function getPublicQualifiedName(name) { if (isNumeric(name)) { return toNumber(name); } else if (name !== null && isObject(name)) { return name; } - true; return PUBLIC_QUALIFIED_NAME_PREFIX + name; }; multiname.isPublicQualifiedName = function isPublicQualifiedName(qn) { return typeof qn === 'number' || isNumeric(qn) || qn.indexOf(PUBLIC_QUALIFIED_NAME_PREFIX) === 0; }; multiname.getAccessModifier = function getAccessModifier(mn) { true; if (typeof mn === 'number' || typeof mn === 'string' || mn instanceof Number) { @@ -23871,23 +22089,22 @@ var createName = function createName(nam value: value }); buildReturnStop(); break; case 30: case 35: index = pop(); object = pop(); - push(call(globalProperty(op === OP_nextname ? 'nextName' : 'nextValue'), null, [ - object, + push(new IR.CallProperty(region, state.store, object, constant(op === OP_nextname ? 'asNextName' : 'asNextValue'), [ index - ])); + ], IR.Flags.PRISTINE)); break; case 50: - var temp = call(globalProperty('hasNext2'), null, [ + var temp = call(globalProperty('asHasNext2'), null, [ local[bc.object], local[bc.index] ]); local[bc.object] = getJSProperty(temp, 'object'); push(local[bc.index] = getJSProperty(temp, 'index')); break; case 32: push(Null); @@ -25988,17 +24205,17 @@ var Compiler = new (function () { }; IR.CallProperty.prototype.compile = function (cx) { var object = compileValue(this.object, cx); var name = compileValue(this.name, cx); var callee = property(object, name); var args = this.args.map(function (arg) { return compileValue(arg, cx); }); - if (this.pristine) { + if (this.flags & IR.Flags.PRISTINE) { return call(callee, args); } else { return callCall(callee, object, args); } }; IR.ASCallProperty.prototype.compile = function (cx) { var object = compileValue(this.object, cx); var args = this.args.map(function (arg) { @@ -26099,26 +24316,26 @@ var Compiler = new (function () { object, name ]); }; IR.ASSetSlot.prototype.compile = function (cx) { var object = compileValue(this.object, cx); var name = compileValue(this.name, cx); var value = compileValue(this.value, cx); - return call(id('setSlot'), [ + return call(id('asSetSlot'), [ object, name, value ]); }; IR.ASGetSlot.prototype.compile = function (cx) { var object = compileValue(this.object, cx); var name = compileValue(this.name, cx); - return call(id('getSlot'), [ + return call(id('asGetSlot'), [ object, name ]); }; IR.Projection.prototype.compile = function (cx) { true; true; return compileValue(this.argument.scope, cx); @@ -27952,24 +26169,19 @@ var globalMultinameAnalysis = runtimeOpt var traceInlineCaching = runtimeOptions.register(new Option('tic', 'traceInlineCaching', 'boolean', false, 'Trace inline caching execution.')); var compilerEnableExceptions = runtimeOptions.register(new Option('cex', 'exceptions', 'boolean', false, 'Compile functions with catch blocks.')); var compilerMaximumMethodSize = runtimeOptions.register(new Option('cmms', 'maximumMethodSize', 'number', 4 * 1024, 'Compiler maximum method size.')); var jsGlobal = function () { return this || (1, eval)('this'); }(); var VM_SLOTS = 'vm slots'; var VM_LENGTH = 'vm length'; -var VM_TRAITS = 'vm traits'; var VM_BINDINGS = 'vm bindings'; var VM_NATIVE_PROTOTYPE_FLAG = 'vm native prototype'; -var VM_ENUMERATION_KEYS = 'vm enumeration keys'; -var VM_TOMBSTONE = createEmptyObject(); var VM_OPEN_METHODS = 'vm open methods'; -var VM_NEXT_NAME = 'vm next name'; -var VM_NEXT_NAME_INDEX = 'vm next name index'; var VM_IS_CLASS = 'vm is class'; var VM_OPEN_METHOD_PREFIX = 'open_'; var VM_NATIVE_BUILTINS = [ Object, Number, Boolean, String, Array, @@ -28154,23 +26366,29 @@ function resolveMultinameProperty(namesp return Multiname.getPublicQualifiedName(name); } else { return namespaces[0].qualifiedName + '$' + name; } } function asGetPublicProperty(name) { return this.asGetProperty(undefined, name, 0); } -function asGetProperty(namespaces, name, flags, isMethod) { +function asGetProperty(namespaces, name, flags) { var resolved = this.resolveMultinameProperty(namespaces, name, flags); if (this.asGetNumericProperty && Multiname.isNumeric(resolved)) { return this.asGetNumericProperty(resolved); } return this[resolved]; } +function asGetPropertyLikelyNumeric(namespaces, name, flags) { + if (typeof name === 'number') { + return this.asGetNumericProperty(name); + } + return asGetProperty.call(this, namespaces, name, flags); +} function asGetResolvedStringProperty(resolved) { true; return this[resolved]; } function asCallResolvedStringProperty(resolved, isLex, args) { var receiver = isLex ? null : this; var openMethods = this[VM_OPEN_METHODS]; var method; @@ -28199,16 +26417,23 @@ function asSetProperty(namespaces, name, name = String(name); } var resolved = this.resolveMultinameProperty(namespaces, name, flags); if (this.asSetNumericProperty && Multiname.isNumeric(resolved)) { return this.asSetNumericProperty(resolved, value); } this[resolved] = value; } +function asSetPropertyLikelyNumeric(namespaces, name, flags, value) { + if (typeof name === 'number') { + this.asSetNumericProperty(name, value); + return; + } + return asSetProperty.call(this, namespaces, name, flags, value); +} function asDefinePublicProperty(name, descriptor) { return this.asDefineProperty(undefined, name, 0, descriptor); } function asDefineProperty(namespaces, name, flags, descriptor) { if (typeof name === 'object') { name = String(name); } var resolved = this.resolveMultinameProperty(namespaces, name, flags); @@ -28277,93 +26502,70 @@ function asHasProperty(namespaces, name, } if (nonProxy) { return nonProxyingHasProperty(this, this.resolveMultinameProperty(namespaces, name, flags)); } else { return this.resolveMultinameProperty(namespaces, name, flags) in this; } } function asDeleteProperty(namespaces, name, flags) { - if (this.deleteProperty) { - return this.deleteProperty(namespaces, name, flags); - } - if (this.indexDelete && Multiname.isNumeric(name)) { - return this.indexDelete(name); - } var resolved = this.resolveMultinameProperty(namespaces, name, flags); - if (this[VM_ENUMERATION_KEYS]) { - var index = this[VM_ENUMERATION_KEYS].indexOf(resolved); - if (index >= 0) { - this[VM_ENUMERATION_KEYS][index] = VM_TOMBSTONE; - } - } return delete this[resolved]; } function asGetNumericProperty(i) { return this[i]; } function asSetNumericProperty(i, v) { this[i] = v; } function asGetDescendants(namespaces, name, flags) { notImplemented('asGetDescendants'); } +function asNextNameIndex(index) { + if (index === 0) { + defineNonEnumerableProperty(this, 'enumerableKeys', this.asGetEnumerableKeys()); + } + var enumerableKeys = this.enumerableKeys; + while (index < enumerableKeys.length) { + if (this.asHasProperty(undefined, enumerableKeys[index], 0)) { + return index + 1; + } + index++; + } + return 0; +} function asNextName(index) { - notImplemented('asNextName'); -} -function asNextNameIndex(index) { - notImplemented('asNextNameIndex'); + var enumerableKeys = this.enumerableKeys; + true; + return enumerableKeys[index - 1]; } function asNextValue(index) { - notImplemented('asNextValue'); + return this.asGetPublicProperty(this.asNextName(index)); +} +function asGetEnumerableKeys() { + var boxedValue = this.valueOf(); + if (typeof boxedValue === 'string' || typeof boxedValue === 'number') { + return []; + } + var keys = Object.keys(this); + var result = []; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (isNumeric(key)) { + result.push(key); + } else { + var name = Multiname.stripPublicQualifier(key); + if (name !== undefined) { + result.push(name); + } + } + } + return result; } function initializeGlobalObject(global) { - function getEnumerationKeys(object) { - if (object.node && object.node.childNodes) { - object = object.node.childNodes; - } - var keys = []; - var boxedValue = object.valueOf(); - if (typeof boxedValue === 'string' || typeof boxedValue === 'number') { - return []; - } - if (object.getEnumerationKeys) { - return object.getEnumerationKeys(); - } - for (var key in object) { - if (isNumeric(key)) { - keys.push(Number(key)); - } else if (Multiname.isPublicQualifiedName(key)) { - if (object[VM_BINDINGS] && object[VM_BINDINGS].indexOf(key) >= 0) { - continue; - } - keys.push(key.substr(Multiname.PUBLIC_QUALIFIED_NAME_PREFIX.length)); - } - } - return keys; - } - defineReadOnlyProperty(global.Object.prototype, VM_NEXT_NAME_INDEX, function (index) { - if (index === 0) { - this[VM_ENUMERATION_KEYS] = getEnumerationKeys(this); - } - var keys = this[VM_ENUMERATION_KEYS]; - while (index < keys.length) { - if (keys[index] !== VM_TOMBSTONE) { - return index + 1; - } - index++; - } - delete this[VM_ENUMERATION_KEYS]; - return 0; - }); - defineReadOnlyProperty(global.Object.prototype, VM_NEXT_NAME, function (index) { - var keys = this[VM_ENUMERATION_KEYS]; - true; - return keys[index - 1]; - }); var originals = global[VM_NATIVE_BUILTIN_ORIGINALS] = createEmptyObject(); VM_NATIVE_BUILTIN_SURROGATES.forEach(function (surrogate) { var object = surrogate.object; originals[object.name] = createEmptyObject(); surrogate.methods.forEach(function (originalFunctionName) { var originalFunction = object.prototype[originalFunctionName]; originals[object.name][originalFunctionName] = originalFunction; var overrideFunctionName = Multiname.getPublicQualifiedName(originalFunctionName); @@ -28390,35 +26592,54 @@ function initializeGlobalObject(global) defineNonEnumerableProperty(global.Object.prototype, 'asDefineProperty', asDefineProperty); defineNonEnumerableProperty(global.Object.prototype, 'asDefinePublicProperty', asDefinePublicProperty); defineNonEnumerableProperty(global.Object.prototype, 'asCallProperty', asCallProperty); defineNonEnumerableProperty(global.Object.prototype, 'asCallPublicProperty', asCallPublicProperty); defineNonEnumerableProperty(global.Object.prototype, 'asCallResolvedStringProperty', asCallResolvedStringProperty); defineNonEnumerableProperty(global.Object.prototype, 'asConstructProperty', asConstructProperty); defineNonEnumerableProperty(global.Object.prototype, 'asHasProperty', asHasProperty); defineNonEnumerableProperty(global.Object.prototype, 'asDeleteProperty', asDeleteProperty); + defineNonEnumerableProperty(global.Object.prototype, 'asNextName', asNextName); + defineNonEnumerableProperty(global.Object.prototype, 'asNextValue', asNextValue); + defineNonEnumerableProperty(global.Object.prototype, 'asNextNameIndex', asNextNameIndex); + defineNonEnumerableProperty(global.Object.prototype, 'asGetEnumerableKeys', asGetEnumerableKeys); [ 'Array', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray', 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array', 'Float32Array', 'Float64Array' ].forEach(function (name) { if (!(name in global)) { - console.error(name + ' was not found in globals'); + print(name + ' was not found in globals'); return; } defineNonEnumerableProperty(global[name].prototype, 'asGetNumericProperty', asGetNumericProperty); defineNonEnumerableProperty(global[name].prototype, 'asSetNumericProperty', asSetNumericProperty); + defineNonEnumerableProperty(global[name].prototype, 'asGetProperty', asGetPropertyLikelyNumeric); + defineNonEnumerableProperty(global[name].prototype, 'asSetProperty', asSetPropertyLikelyNumeric); }); + Array.prototype.asGetProperty = function (namespaces, name, flags) { + if (typeof name === 'number') { + return this[name]; + } + return asGetProperty.call(this, namespaces, name, flags); + }; + Array.prototype.asSetProperty = function (namespaces, name, flags, value) { + if (typeof name === 'number') { + this[name] = value; + return; + } + return asSetProperty.call(this, namespaces, name, flags, value); + }; } initializeGlobalObject(jsGlobal); function isNativePrototype(object) { return Object.prototype.hasOwnProperty.call(object, VM_NATIVE_PROTOTYPE_FLAG); } function asTypeOf(x) { if (x) { if (x.constructor === String) { @@ -28439,51 +26660,66 @@ function publicizeProperties(object) { var k = keys[i]; if (!Multiname.isPublicQualifiedName(k)) { var v = object[k]; object[Multiname.getPublicQualifiedName(k)] = v; delete object[k]; } } } -function getSlot(object, index) { +function asGetSlot(object, index) { return object[object[VM_SLOTS][index].name]; } -function setSlot(object, index, value) { +function asSetSlot(object, index, value) { var binding = object[VM_SLOTS][index]; if (binding.const) { return; } var name = binding.name; var type = binding.type; if (type && type.coerce) { object[name] = type.coerce(value); } else { object[name] = value; } } -function nextName(object, index) { - return object[VM_NEXT_NAME](index); -} -function nextValue(object, index) { - return object.asGetProperty(undefined, object[VM_NEXT_NAME](index)); -} -function hasNext2(object, index) { - if (object === null || object === undefined) { +function asHasNext2(object, index) { + if (isNullOrUndefined(object)) { return { index: 0, object: null }; } object = boxValue(object); - true; - true; + var nextIndex = object.asNextNameIndex(index); + if (nextIndex > 0) { + return { + index: nextIndex, + object: object + }; + } + while (true) { + var object = Object.getPrototypeOf(object); + if (!object) { + return { + index: 0, + object: null + }; + } + nextIndex = object.asNextNameIndex(0); + if (nextIndex > 0) { + return { + index: nextIndex, + object: object + }; + } + } return { - index: object[VM_NEXT_NAME_INDEX](index), - object: object + index: 0, + object: null }; } function getDescendants(object, mn) { if (!isXMLType(object)) { throw 'Not XML object in getDescendants'; } return object.descendants(mn); } @@ -29337,23 +27573,23 @@ function asCoerce(type, value) { } } function asCoerceString(x) { if (typeof x === 'string') { return x; } else if (x == undefined) { return null; } - return String(x); + return x + ''; } function asCoerceInt(x) { return x | 0; } function asCoerceUint(x) { - return toUint(x); + return x >>> 0; } function asCoerceNumber(x) { return +x; } function asCoerceBoolean(x) { return !(!x); } function asCoerceObject(x) { @@ -29756,22 +27992,39 @@ var TypedArrayVector = function () { this._checkFixed(); this._slide(arguments.length); this.offset -= arguments.length; this.length += arguments.length; for (var i = 0; i < arguments.length; i++) { this.buffer[this.offset + i] = arguments[i]; } }; + vector.prototype.asGetEnumerableKeys = function () { + if (vector.prototype === this) { + return Object.prototype.asGetEnumerableKeys.call(this); + } + var keys = []; + for (var i = 0; i < this.length; i++) { + keys.push(i); + } + return keys; + }; + vector.prototype.asHasProperty = function (namespaces, name, flags) { + if (vector.prototype === this || !isNumeric(name)) { + return Object.prototype.asHasProperty.call(this, namespaces, name, flags); + } + var index = toNumber(name); + return index >= 0 && index < this._length; + }; Object.defineProperty(vector.prototype, 'length', { get: function () { return this._length; }, set: function (length) { - length = toUint(length); + length = length >>> 0; if (length > this._length) { this._ensureCapacity(length); for (var i = this.offset + this._length, j = this.offset + length; i < j; i++) { this.buffer[i] = this.defaultValue; } } this._length = length; } @@ -29783,19 +28036,29 @@ var TypedArrayVector = function () { var right = this.offset + index + deleteCount; var slice = this.buffer.subarray(right, right + this._length - index - deleteCount); this.buffer.set(slice, this.offset + index + insertCount); this._length += insertCount - deleteCount; for (var i = 0; i < insertCount; i++) { this.buffer[this.offset + index + i] = args.asGetNumericProperty(offset + i); } }; + vector.prototype.asGetEnumerableKeys = function () { + if (vector.prototype === this) { + return Object.prototype.asGetEnumerableKeys.call(this); + } + var keys = []; + for (var i = 0; i < this._length; i++) { + keys.push(i); + } + return keys; + }; return vector; }(); -var typedArrayVectorTemplate = 'var EXTRA_CAPACITY=4,INITIAL_CAPACITY=10;function vector(a,b){a|=0;this.fixed=!!b;this.buffer=new Int32Array(Math.max(INITIAL_CAPACITY,a+EXTRA_CAPACITY));this.offset=0;this._length=a;this.defaultValue=0}vector.callable=function(a){if(a instanceof vector)return a;var b=a.asGetProperty(void 0,"length");if(void 0!==b){for(var c=new vector(b,!1),d=0;d<b;d++)c.asSetNumericProperty(d,a.asGetPublicProperty(d));return c}unexpected()}; vector.prototype.internalToString=function(){for(var a="",b=this.offset,c=b+this._length,d=0;d<this.buffer.length;d++)d===b&&(a+="["),d===c&&(a+="]"),a+=this.buffer[d],d<this.buffer.length-1&&(a+=",");this.offset+this._length===this.buffer.length&&(a+="]");return a+": offset: "+this.offset+", length: "+this._length+", capacity: "+this.buffer.length};vector.prototype.toString=function(){for(var a="",b=0;b<this._length;b++)a+=this.buffer[this.offset+b],b<this._length-1&&(a+=",");return a}; vector.prototype._view=function(){return this.buffer.subarray(this.offset,this.offset+this._length)};vector.prototype._ensureCapacity=function(a){var b=this.offset+a;b<this.buffer.length||(a<=this.buffer.length?(b=this.buffer.length-a>>2,this.buffer.set(this._view(),b),this.offset=b):(a=3*this.buffer.length>>2,a<b&&(a=b),b=new Int32Array(a),b.set(this.buffer,0),this.buffer=b))};vector.prototype.concat=function(){notImplemented("TypedArrayVector.concat")}; vector.prototype.every=function(a,b){for(var c=0;c<this._length;c++)if(!a.call(b,this.asGetNumericProperty(c),c,this))return!1;return!0};vector.prototype.filter=function(a,b){for(var c=new vector,d=0;d<this._length;d++)a.call(b,this.asGetNumericProperty(d),d,this)&&c.push(this.asGetNumericProperty(d));return c};vector.prototype.forEach=function(a,b){for(var c=0;c<this._length;c++)a.call(b,this.asGetNumericProperty(c),c,this)};vector.prototype.join=function(a){notImplemented("TypedArrayVector.join")}; vector.prototype.indexOf=function(a,b){notImplemented("TypedArrayVector.indexOf")};vector.prototype.lastIndexOf=function(a,b){notImplemented("TypedArrayVector.lastIndexOf")};vector.prototype.map=function(a,b){notImplemented("TypedArrayVector.map")};vector.prototype.push=function(){this._ensureCapacity(this._length+arguments.length);for(var a=0;a<arguments.length;a++)this.buffer[this.offset+this._length++]=arguments[a]}; vector.prototype.pop=function(){this._checkFixed();if(0===this._length)return this.defaultValue;this._length--;return this.buffer[this.offset+this._length]};vector.prototype.reverse=function(){for(var a=this.offset,b=this.offset+this._length-1,c=this.buffer;a<b;){var d=c[a];c[a]=c[b];c[b]=d;a++;b--}};vector.CASEINSENSITIVE=1;vector.DESCENDING=2;vector.UNIQUESORT=4;vector.RETURNINDEXEDARRAY=8;vector.NUMERIC=16;function defaultCompareFunction(a,b){return String(a).localeCompare(String(b))} function compare(a,b,c,d){assertNotImplemented(!(c&vector.CASEINSENSITIVE),"CASEINSENSITIVE");assertNotImplemented(!(c&vector.UNIQUESORT),"UNIQUESORT");assertNotImplemented(!(c&vector.RETURNINDEXEDARRAY),"RETURNINDEXEDARRAY");var f=0;d||(d=defaultCompareFunction);c&vector.NUMERIC?(a=toNumber(a),b=toNumber(b),f=a<b?-1:a>b?1:0):f=d(a,b);c&vector.DESCENDING&&(f*=-1);return f} function _sort(a){for(var b=[],c=-1,d=0,f=a.length-1,e,g,h,k;;)if(100>=f-d){for(g=d+1;g<=f;g++){h=a[g];for(e=g-1;e>=d&&a[e]>h;)a[e+1]=a[e--];a[e+1]=h}if(-1==c)break;f=b[c--];d=b[c--]}else{k=d+f>>1;e=d+1;g=f;h=a[k];a[k]=a[e];a[e]=h;a[d]>a[f]&&(h=a[d],a[d]=a[f],a[f]=h);a[e]>a[f]&&(h=a[e],a[e]=a[f],a[f]=h);a[d]>a[e]&&(h=a[d],a[d]=a[e],a[e]=h);for(k=a[e];;){do e++;while(a[e]<k);do g--;while(a[g]>k);if(g<e)break;h=a[e];a[e]=a[g];a[g]=h}a[d+1]=a[g];a[g]=k;f-e+1>=g-d?(b[++c]=e,b[++c]=f,f=g-1):(b[++c]=d, b[++c]=g-1,d=e)}return a}vector.prototype._sortNumeric=function(a){_sort(this._view());a&&this.reverse()};vector.prototype.sort=function(){if(0===arguments.length)return Array.prototype.sort.call(this._view());var a,b=0;arguments[0]instanceof Function?a=arguments[0]:isNumber(arguments[0])&&(b=arguments[0]);isNumber(arguments[1])&&(b=arguments[1]);if(b&TypedArrayVector.NUMERIC)return this._sortNumeric(b&vector.DESCENDING);Array.prototype.sort.call(this._view(),function(c,d){return compare(c,d,b,a)})}; vector.prototype.asGetNumericProperty=function(a){return this.buffer[this.offset+a]};vector.prototype.asSetNumericProperty=function(a,b){a===this._length&&(this._ensureCapacity(this._length+1),this._length++);this.buffer[this.offset+a]=b};vector.prototype.shift=function(){this._checkFixed();if(0!==this._length)return this._length--,this.buffer[this.offset++]}; vector.prototype._checkFixed=function(){if(this.fixed){var a=Errors.VectorFixedError;throwErrorFromVM(AVM2.currentDomain(),"RangeError",getErrorMessage(a.code),a.code)}};vector.prototype._slide=function(a){this.buffer.set(this._view(),this.offset+a);this.offset+=a};vector.prototype.unshift=function(){this._checkFixed();this._slide(arguments.length);this.offset-=arguments.length;this.length+=arguments.length;for(var a=0;a<arguments.length;a++)this.buffer[this.offset+a]=arguments[a]}; Object.defineProperty(vector.prototype,"length",{get:function(){return this._length},set:function(a){a=toUint(a);if(a>this._length){this._ensureCapacity(a);for(var b=this.offset+this._length,c=this.offset+a;b<c;b++)this.buffer[b]=this.defaultValue}this._length=a}}); vector.prototype._spliceHelper=function(a,b,c,d,f){b=clamp(b,0,d.length-f);c=clamp(c,0,this._length-a);this._ensureCapacity(this._length-c+b);var e=this.offset+a+c,e=this.buffer.subarray(e,e+this._length-a-c);this.buffer.set(e,this.offset+a+b);this._length+=b-c;for(c=0;c<b;c++)this.buffer[this.offset+a+c]=d.asGetNumericProperty(f+c)};'; +var typedArrayVectorTemplate = 'var EXTRA_CAPACITY=4,INITIAL_CAPACITY=10;function vector(a,b){a|=0;this.fixed=!!b;this.buffer=new Int32Array(Math.max(INITIAL_CAPACITY,a+EXTRA_CAPACITY));this.offset=0;this._length=a;this.defaultValue=0}vector.callable=function(a){if(a instanceof vector)return a;var b=a.asGetProperty(void 0,"length");if(void 0!==b){for(var c=new vector(b,!1),d=0;d<b;d++)c.asSetNumericProperty(d,a.asGetPublicProperty(d));return c}unexpected()}; vector.prototype.internalToString=function(){for(var a="",b=this.offset,c=b+this._length,d=0;d<this.buffer.length;d++)d===b&&(a+="["),d===c&&(a+="]"),a+=this.buffer[d],d<this.buffer.length-1&&(a+=",");this.offset+this._length===this.buffer.length&&(a+="]");return a+": offset: "+this.offset+", length: "+this._length+", capacity: "+this.buffer.length};vector.prototype.toString=function(){for(var a="",b=0;b<this._length;b++)a+=this.buffer[this.offset+b],b<this._length-1&&(a+=",");return a}; vector.prototype._view=function(){return this.buffer.subarray(this.offset,this.offset+this._length)};vector.prototype._ensureCapacity=function(a){var b=this.offset+a;b<this.buffer.length||(a<=this.buffer.length?(b=this.buffer.length-a>>2,this.buffer.set(this._view(),b),this.offset=b):(a=3*this.buffer.length>>2,a<b&&(a=b),b=new Int32Array(a),b.set(this.buffer,0),this.buffer=b))};vector.prototype.concat=function(){notImplemented("TypedArrayVector.concat")}; vector.prototype.every=function(a,b){for(var c=0;c<this._length;c++)if(!a.call(b,this.asGetNumericProperty(c),c,this))return!1;return!0};vector.prototype.filter=function(a,b){for(var c=new vector,d=0;d<this._length;d++)a.call(b,this.asGetNumericProperty(d),d,this)&&c.push(this.asGetNumericProperty(d));return c};vector.prototype.forEach=function(a,b){for(var c=0;c<this._length;c++)a.call(b,this.asGetNumericProperty(c),c,this)};vector.prototype.join=function(a){notImplemented("TypedArrayVector.join")}; vector.prototype.indexOf=function(a,b){notImplemented("TypedArrayVector.indexOf")};vector.prototype.lastIndexOf=function(a,b){notImplemented("TypedArrayVector.lastIndexOf")};vector.prototype.map=function(a,b){notImplemented("TypedArrayVector.map")};vector.prototype.push=function(){this._ensureCapacity(this._length+arguments.length);for(var a=0;a<arguments.length;a++)this.buffer[this.offset+this._length++]=arguments[a]}; vector.prototype.pop=function(){this._checkFixed();if(0===this._length)return this.defaultValue;this._length--;return this.buffer[this.offset+this._length]};vector.prototype.reverse=function(){for(var a=this.offset,b=this.offset+this._length-1,c=this.buffer;a<b;){var d=c[a];c[a]=c[b];c[b]=d;a++;b--}};vector.CASEINSENSITIVE=1;vector.DESCENDING=2;vector.UNIQUESORT=4;vector.RETURNINDEXEDARRAY=8;vector.NUMERIC=16;function defaultCompareFunction(a,b){return String(a).localeCompare(String(b))} function compare(a,b,c,d){assertNotImplemented(!(c&vector.CASEINSENSITIVE),"CASEINSENSITIVE");assertNotImplemented(!(c&vector.UNIQUESORT),"UNIQUESORT");assertNotImplemented(!(c&vector.RETURNINDEXEDARRAY),"RETURNINDEXEDARRAY");var f=0;d||(d=defaultCompareFunction);c&vector.NUMERIC?(a=toNumber(a),b=toNumber(b),f=a<b?-1:a>b?1:0):f=d(a,b);c&vector.DESCENDING&&(f*=-1);return f} function _sort(a){for(var b=[],c=-1,d=0,f=a.length-1,e,g,h,k;;)if(100>=f-d){for(g=d+1;g<=f;g++){h=a[g];for(e=g-1;e>=d&&a[e]>h;)a[e+1]=a[e--];a[e+1]=h}if(-1==c)break;f=b[c--];d=b[c--]}else{k=d+f>>1;e=d+1;g=f;h=a[k];a[k]=a[e];a[e]=h;a[d]>a[f]&&(h=a[d],a[d]=a[f],a[f]=h);a[e]>a[f]&&(h=a[e],a[e]=a[f],a[f]=h);a[d]>a[e]&&(h=a[d],a[d]=a[e],a[e]=h);for(k=a[e];;){do e++;while(a[e]<k);do g--;while(a[g]>k);if(g<e)break;h=a[e];a[e]=a[g];a[g]=h}a[d+1]=a[g];a[g]=k;f-e+1>=g-d?(b[++c]=e,b[++c]=f,f=g-1):(b[++c]=d, b[++c]=g-1,d=e)}return a}vector.prototype._sortNumeric=function(a){_sort(this._view());a&&this.reverse()};vector.prototype.sort=function(){if(0===arguments.length)return Array.prototype.sort.call(this._view());var a,b=0;arguments[0]instanceof Function?a=arguments[0]:isNumber(arguments[0])&&(b=arguments[0]);isNumber(arguments[1])&&(b=arguments[1]);if(b&TypedArrayVector.NUMERIC)return this._sortNumeric(b&vector.DESCENDING);Array.prototype.sort.call(this._view(),function(c,d){return compare(c,d,b,a)})}; vector.prototype.asGetNumericProperty=function(a){return this.buffer[this.offset+a]};vector.prototype.asSetNumericProperty=function(a,b){a===this._length&&(this._ensureCapacity(this._length+1),this._length++);this.buffer[this.offset+a]=b};vector.prototype.shift=function(){this._checkFixed();if(0!==this._length)return this._length--,this.buffer[this.offset++]}; vector.prototype._checkFixed=function(){if(this.fixed){var a=Errors.VectorFixedError;throwErrorFromVM(AVM2.currentDomain(),"RangeError",getErrorMessage(a.code),a.code)}};vector.prototype._slide=function(a){this.buffer.set(this._view(),this.offset+a);this.offset+=a};vector.prototype.unshift=function(){this._checkFixed();this._slide(arguments.length);this.offset-=arguments.length;this.length+=arguments.length;for(var a=0;a<arguments.length;a++)this.buffer[this.offset+a]=arguments[a]}; vector.prototype.asGetEnumerableKeys=function(){if(vector.prototype===this)return Object.prototype.asGetEnumerableKeys.call(this);for(var a=[],b=0;b<this.length;b++)a.push(b);return a};vector.prototype.asHasProperty=function(a,b,c){if(vector.prototype===this||!isNumeric(b))return Object.prototype.asHasProperty.call(this,a,b,c);a=toNumber(b);return 0<=a&&a<this._length}; Object.defineProperty(vector.prototype,"length",{get:function(){return this._length},set:function(a){a>>>=0;if(a>this._length){this._ensureCapacity(a);for(var b=this.offset+this._length,c=this.offset+a;b<c;b++)this.buffer[b]=this.defaultValue}this._length=a}}); vector.prototype._spliceHelper=function(a,b,c,d,f){b=clamp(b,0,d.length-f);c=clamp(c,0,this._length-a);this._ensureCapacity(this._length-c+b);var e=this.offset+a+c,e=this.buffer.subarray(e,e+this._length-a-c);this.buffer.set(e,this.offset+a+b);this._length+=b-c;for(c=0;c<b;c++)this.buffer[this.offset+a+c]=d.asGetNumericProperty(f+c)}; vector.prototype.asGetEnumerableKeys=function(){if(vector.prototype===this)return Object.prototype.asGetEnumerableKeys.call(this);for(var a=[],b=0;b<this._length;b++)a.push(b);return a};'; var Int32Vector = new Function(typedArrayVectorTemplate.replace(/Int32Array/g, 'Int32Array') + ' return vector;')(); var Uint32Vector = new Function(typedArrayVectorTemplate.replace(/Int32Array/g, 'Uint32Array') + ' return vector;')(); var Float64Vector = new Function(typedArrayVectorTemplate.replace(/Int32Array/g, 'Float64Array') + ' return vector;')(); var GenericVector = function () { function vector(length, fixed, type) { length = length | 0; this.fixed = !(!fixed); this.buffer = new Array(length); @@ -29961,17 +28224,17 @@ var GenericVector = function () { } this.buffer.unshift.apply(this.buffer, items); }; Object.defineProperty(vector.prototype, 'length', { get: function () { return this.buffer.length; }, set: function (length) { - length = toUint(length); + length = length >>> 0; if (length > this.buffer.length) { for (var i = this.buffer.length; i < length; i++) { this.buffer[i] = this.defaultValue; } } else { this.buffer.length = length; } true; @@ -29984,25 +28247,87 @@ var GenericVector = function () { for (var i = 0; i < insertCount; i++) { items.push(this._coerce(args.asGetNumericProperty(offset + i))); } this.buffer.splice.apply(this.buffer, [ index, deleteCount ].concat(items)); }; - vector.prototype.getEnumerationKeys = function () { + vector.prototype.asGetEnumerableKeys = function () { + if (vector.prototype === this) { + return Object.prototype.asGetEnumerableKeys.call(this); + } var keys = []; for (var i = 0; i < this.buffer.length; i++) { keys.push(i); } return keys; }; + vector.prototype.asHasProperty = function (namespaces, name, flags) { + if (vector.prototype === this || !isNumeric(name)) { + return Object.prototype.asHasProperty.call(this, namespaces, name, flags); + } + var index = toNumber(name); + return index >= 0 && index < this.buffer.length; + }; return vector; }(); +Int32Vector.prototype.asGetProperty = function (namespaces, name, flags) { + if (typeof name === 'number') { + return this.asGetNumericProperty(name); + } + return asGetProperty.call(this, namespaces, name, flags); +}; +Int32Vector.prototype.asSetProperty = function (namespaces, name, flags, value) { + if (typeof name === 'number') { + this.asSetNumericProperty(name, value); + return; + } + return asSetProperty.call(this, namespaces, name, flags, value); +}; +Uint32Vector.prototype.asGetProperty = function (namespaces, name, flags) { + if (typeof name === 'number') { + return this.asGetNumericProperty(name); + } + return asGetProperty.call(this, namespaces, name, flags); +}; +Uint32Vector.prototype.asSetProperty = function (namespaces, name, flags, value) { + if (typeof name === 'number') { + this.asSetNumericProperty(name, value); + return; + } + return asSetProperty.call(this, namespaces, name, flags, value); +}; +Float64Vector.prototype.asGetProperty = function (namespaces, name, flags) { + if (typeof name === 'number') { + return this.asGetNumericProperty(name); + } + return asGetProperty.call(this, namespaces, name, flags); +}; +Float64Vector.prototype.asSetProperty = function (namespaces, name, flags, value) { + if (typeof name === 'number') { + this.asSetNumericProperty(name, value); + return; + } + return asSetProperty.call(this, namespaces, name, flags, value); +}; +GenericVector.prototype.asGetProperty = function (namespaces, name, flags) { + if (typeof name === 'number') { + return this.asGetNumericProperty(name); + } + return asGetProperty.call(this, namespaces, name, flags); +}; +GenericVector.prototype.asSetProperty = function (namespaces, name, flags, value) { + if (typeof name === 'number') { + this.asSetNumericProperty(name, value); + return; + } + return asSetProperty.call(this, namespaces, name, flags, value); +}; var XMLClass, XMLListClass, QNameClass, ASXML, XML, ASXMLList, XMLList; var isXMLType, isXMLName, XMLParser; (function () { function XMLEncoder(ancestorNamespaces, indentLevel, prettyPrinting) { var indent = '\n '; function visit(node, encode) { if (node.isXML) { switch (node.kind) { @@ -30661,17 +28986,20 @@ var isXMLType, isXMLName, XMLParser; this.children.forEach(function (v) { if (v.kind === 'element') { result = false; } }); } return result; }; - Xp.getEnumerationKeys = function getEnumerationKeys() { + Xp.asGetEnumerableKeys = function asGetEnumerableKeys() { + if (Xp === this) { + return Object.prototype.asGetEnumerableKeys.call(this); + } var keys = []; this.children.forEach(function (v, i) { keys.push(v.name); }); return keys; }; function setAttribute(node, name, value) { if (node.nodeType === Node.DOCUMENT_NODE) { @@ -31518,17 +29846,20 @@ var isXMLType, isXMLName, XMLParser; if (base.isXMLList && base.length() > 1) { return null; } base.setProperty(targetProperty, ''); target = base.getProperty(targetProperty); } return target; }; - XLp.getEnumerationKeys = function getEnumerationKeys() { + XLp.asGetEnumerableKeys = function asGetEnumerableKeys() { + if (XLp === this) { + return Object.prototype.asGetEnumerableKeys.call(this); + } var keys = []; this.children.forEach(function (v, i) { keys.push(i); }); return keys; }; c.native = { instance: { @@ -32602,17 +30933,20 @@ function DictionaryClass(domain, scope, } this.map.delete(Object(name)); var i; if (!this.weakKeys && (i = this.keys.indexOf(name)) >= 0) { this.keys.splice(i, 1); } return true; }); - defineNonEnumerableProperty(prototype, 'getEnumerationKeys', function () { + defineNonEnumerableProperty(prototype, 'asGetEnumerableKeys', function () { + if (prototype === this) { + return Object.prototype.asGetEnumerableKeys.call(this); + } var primitiveMapKeys = []; for (var k in this.primitiveMap) { primitiveMapKeys.push(k); } return primitiveMapKeys.concat(this.keys); }); c.native = { instance: { @@ -33057,20 +31391,20 @@ var natives = function () { return Object(value) instanceof Number; }; c.isInstance = function (value) { return Object(value) instanceof Number; }; return c; } function Int(x) { - return toNumber(x) | 0; + return x | 0; } function boxedInt(x) { - return Object(Int(x)); + return Object(x | 0); } function intClass(runtime, scope, instanceConstructor, baseClass) { var c = new Class('int', boxedInt, C(Int)); c.extendBuiltin(baseClass); c.defaultValue = 0; c.coerce = Int; c.isInstanceOf = function (value) { return false; @@ -33079,20 +31413,20 @@ var natives = function () { if (value instanceof Number) { value = value.valueOf(); } return (value | 0) === value; }; return c; } function Uint(x) { - return toNumber(x) >>> 0; + return x >>> 0; } function boxedUint(x) { - return Object(Uint(x)); + return Object(x >>> 0); } function uintClass(runtime, scope, instanceConstructor, baseClass) { var c = new Class('uint', boxedUint, C(Uint)); c.extend(baseClass); c.defaultValue = 0; c.isInstanceOf = function (value) { return false; }; @@ -33236,45 +31570,44 @@ var natives = function () { } else if (typeof uriValue === 'object') { prefix = uriValue.prefix; if (uriValue instanceof ShumwayNamespace) { uri = uriValue.originalURI; } else if (uriValue instanceof QName) { uri = uriValue.uri; } } else { - uri = toString(uriValue); + uri = uriValue + ''; if (uri === '') { prefix = ''; } else { prefix = undefined; } } } else { if (typeof uriValue === 'object' && uriValue instanceof QName && uriValue.uri !== null) { uri = uriValue.uri; } else { - uri = toString(uriValue); + uri = uriValue + ''; } if (uri === '') { - if (prefixValue === undefined || toString(prefixValue) === '') { + if (prefixValue === undefined || prefixValue + '' === '') { prefix = ''; } else { throw 'type error'; } } else if (prefixValue === undefined || prefixValue === '') { prefix = undefined; } else if (false && !isXMLName(prefixValue)) { prefix = undefined; } else { - prefix = toString(prefixValue); - } - } - var ns = ShumwayNamespace.createNamespace(uri, prefix); - return ns; + prefix = prefixValue + ''; + } + } + return ShumwayNamespace.createNamespace(uri, prefix); }; var c = new Class('Namespace', ASNamespace, C(ASNamespace)); c.extendNative(baseClass, ShumwayNamespace); var Np = ShumwayNamespace.prototype; c.native = { instance: { prefix: { get: Np.getPrefix @@ -33282,27 +31615,54 @@ var natives = function () { uri: { get: Np.getURI } } }; return c; } function JSONClass(runtime, scope, instanceConstructor, baseClass) { + function transformJSValueToAS(value) { + if (typeof value !== 'object') { + return value; + } + var keys = Object.keys(value); + var result = value instanceof Array ? [] : {}; + for (var i = 0; i < keys.length; i++) { + result.asSetPublicProperty(keys[i], transformJSValueToAS(value[keys[i]])); + } + return result; + } + function transformASValueToJS(value) { + if (typeof value !== 'object') { + return value; + } + var keys = Object.keys(value); + var result = value instanceof Array ? [] : {}; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var jsKey = key; + if (!isNumeric(key)) { + jsKey = fromResolvedName(key); + } + result[jsKey] = transformASValueToJS(value[key]); + } + return result; + } function ASJSON() { } var c = new Class('JSON', ASJSON, C(ASJSON)); c.extend(baseClass); c.native = { static: { parseCore: function parseCore(text) { - return JSON.parse(text); + return transformJSValueToAS(JSON.parse(text)); }, stringifySpecializedToString: function stringifySpecializedToString(value, replacerArray, replacerFunction, gap) { - return JSON.stringify(value, replacerFunction, gap); + return JSON.stringify(transformASValueToJS(value), replacerFunction, gap); } } }; return c; } function CapabilitiesClass(runtime, scope, instanceConstructor, baseClass) { function Capabilities() { } @@ -34774,19 +33134,16 @@ function traceStatistics(writer, abc) { definedProperties: definedProperties, libraryClasses: libraryClassCounter.counts, librarySuperClasses: librarySuperClassCounter.counts, libraryMethods: libraryMethodCounter.counts, libraryProperties: libraryProperties.counts, operations: opCounter.counts }, null, 2)); } -var interpreterOptions = systemOptions.register(new OptionSet('Interpreter Options')); -var traceInterpreter = interpreterOptions.register(new Option('ti', 'traceInterpreter', 'number', 0, 'trace interpreter execution')); -var interpretedBytecode = 0; var Interpreter = new (function () { function Interpreter() { } function popName(stack, mn) { if (Multiname.isRuntime(mn)) { var namespaces = mn.namespaces, name = mn.name; var flags = mn.flags & Multiname.ATTRIBUTE; if (Multiname.isRuntimeName(mn)) { @@ -34827,17 +33184,16 @@ var Interpreter = new (function () { Counter.count('Interpret Method'); var abc = method.abc; var ints = abc.constantPool.ints; var uints = abc.constantPool.uints; var doubles = abc.constantPool.doubles; var strings = abc.constantPool.strings; var methods = abc.methods; var multinames = abc.constantPool.multinames; - var runtime = abc.runtime; var domain = abc.domain; var exceptions = method.exceptions; var locals = [ $this ]; var stack = [], scopeStack = new ScopeStack(savedScope); var parameterCount = method.parameters.length; var argCount = methodArgs.length; @@ -34854,30 +33210,30 @@ var Interpreter = new (function () { } locals.push(value); } if (method.needsRest()) { locals.push(sliceArguments(methodArgs, parameterCount)); } else if (method.needsArguments()) { locals.push(sliceArguments(methodArgs, 0)); } - var obj, type, index, multiname, res, a, b, args = [], name, tmpMultiname = Multiname.TEMPORARY, property; + var obj, index, multiname, res, a, b, args = [], name; + var tmpMultiname = Multiname.TEMPORARY; var bytecodes = method.analysis.bytecodes; interpret: for (var pc = 0, end = bytecodes.length; pc < end;) { - interpretedBytecode++; try { var bc = bytecodes[pc]; var op = bc.op; switch (op | 0) { case 3: throw stack.pop(); case 4: name = popName(stack, multinames[bc.index]); - stack.push(getSuper(savedScope, stack.pop(), name)); + stack[stack.length - 1] = getSuper(savedScope, stack[stack.length - 1], name); break; case 5: value = stack.pop(); name = popName(stack, multinames[bc.index]); setSuper(savedScope, stack.pop(), name, value); break; case 8: locals[bc.index] = undefined; @@ -34961,26 +33317,24 @@ var Interpreter = new (function () { case 28: scopeStack.push(boxValue(stack.pop()), true); break; case 29: scopeStack.pop(); break; case 30: index = stack.pop(); - obj = stack.pop(); - stack.push(nextName(obj, index)); + stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asNextName(index); break; case 35: index = stack.pop(); - obj = stack.pop(); - stack.push(nextValue(obj, index)); + stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asNextValue(index); break; case 50: - res = hasNext2(locals[bc.object], locals[bc.index]); + res = asHasNext2(locals[bc.object], locals[bc.index]); locals[bc.object] = res.object; locals[bc.index] = res.index; stack.push(!(!res.index)); break; case 32: stack.push(null); break; case 33: @@ -35010,58 +33364,62 @@ var Interpreter = new (function () { break; case 40: stack.push(NaN); break; case 41: stack.pop(); break; case 42: - stack.push(stack.top()); + stack.push(stack[stack.length - 1]); break; case 43: - stack.push(stack.pop(), stack.pop()); + obj = stack[stack.length - 1]; + stack[stack.length - 1] = stack[stack.length - 2]; + stack[stack.length - 2] = obj; break; case 48: scopeStack.push(boxValue(stack.pop())); break; case 64: stack.push(createFunction(methods[bc.index], scopeStack.topScope(), true)); break; case 65: popManyInto(stack, bc.argCount, args); obj = stack.pop(); - stack.push(stack.pop().apply(obj, args)); + stack[stack.length - 1] = stack[stack.length - 1].apply(obj, args); break; case 66: popManyInto(stack, bc.argCount, args); - stack.push(construct(stack.pop(), args)); + stack[stack.length - 1] = construct(stack[stack.length - 1], args); break; case 69: popManyInto(stack, bc.argCount, args); name = popName(stack, multinames[bc.index]); - obj = stack.pop(); - stack.push(getSuper(savedScope, obj, name).apply(obj, args)); + obj = stack[stack.length - 1]; + stack[stack.length - 1] = getSuper(savedScope, obj, name).apply(obj, args); break; case 71: return; case 72: if (method.returnType) { return asCoerceByMultiname(domain, method.returnType, stack.pop()); } return stack.pop(); case 73: popManyInto(stack, bc.argCount, args); obj = stack.pop(); savedScope.object.baseClass.instanceConstructorNoInitialize.apply(obj, args); break; case 74: popManyInto(stack, bc.argCount, args); popNameInto(stack, multinames[bc.index], tmpMultiname); - stack.push(boxValue(stack.pop()).asConstructProperty(tmpMultiname.namespaces, tmpMultiname.name, tmpMultiname.flags, args)); + obj = boxValue(stack[stack.length - 1]); + obj = obj.asConstructProperty(tmpMultiname.namespaces, tmpMultiname.name, tmpMultiname.flags, args); + stack[stack.length - 1] = obj; break; case 75: notImplemented(); break; case 76: case 70: case 79: popManyInto(stack, bc.argCount, args); @@ -35074,17 +33432,17 @@ var Interpreter = new (function () { case 78: popManyInto(stack, bc.argCount, args); name = popName(stack, multinames[bc.index]); obj = stack.pop(); getSuper(savedScope, obj, name).apply(obj, args); break; case 83: popManyInto(stack, bc.argCount, args); - stack.push(applyType(domain, stack.pop(), args)); + stack[stack.length - 1] = applyType(domain, stack[stack.length - 1], args); break; case 85: obj = {}; for (var i = 0; i < bc.argCount; i++) { value = stack.pop(); obj[Multiname.getPublicQualifiedName(stack.pop())] = value; } stack.push(obj); @@ -35095,17 +33453,17 @@ var Interpreter = new (function () { obj.push.apply(obj, args); stack.push(obj); break; case 87: true; stack.push(createActivation(method)); break; case 88: - stack.push(createClass(abc.classes[bc.index], stack.pop(), scopeStack.topScope())); + stack[stack.length - 1] = createClass(abc.classes[bc.index], stack[stack.length - 1], scopeStack.topScope()); break; case 89: name = popName(stack, multinames[bc.index]); stack.push(getDescendants(stack.pop(), name)); break; case 90: true; stack.push(exceptions[bc.index].scopeObject); @@ -35134,229 +33492,177 @@ var Interpreter = new (function () { case 100: stack.push(savedScope.global.object); break; case 101: stack.push(scopeStack.get(bc.index)); break; case 102: popNameInto(stack, multinames[bc.index], tmpMultiname); - stack.push(boxValue(stack.pop()).asGetProperty(tmpMultiname.namespaces, tmpMultiname.name, tmpMultiname.flags)); + stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asGetProperty(tmpMultiname.namespaces, tmpMultiname.name, tmpMultiname.flags); break; case 106: popNameInto(stack, multinames[bc.index], tmpMultiname); - stack.push(boxValue(stack.pop()).asDeleteProperty(tmpMultiname.namespaces, tmpMultiname.name, tmpMultiname.flags)); + stack[stack.length - 1] = boxValue(stack[stack.length - 1]).asDeleteProperty(tmpMultiname.namespaces, tmpMultiname.name, tmpMultiname.flags); break; case 108: - stack.push(getSlot(stack.pop(), bc.index)); + stack[stack.length - 1] = asGetSlot(stack[stack.length - 1], bc.index); break; case 109: value = stack.pop(); obj = stack.pop(); - setSlot(obj, bc.index, value); + asSetSlot(obj, bc.index, value); break; case 112: - stack.push(String(stack.pop())); + stack[stack.length - 1] = stack[stack.length - 1] + ''; break; case 131: case 115: - stack.push(asCoerceInt(stack.pop())); + stack[stack.length - 1] |= 0; break; case 136: case 116: - stack.push(asCoerceUint(stack.pop())); + stack[stack.length - 1] >>>= 0; break; case 132: case 117: - stack.push(asCoerceNumber(stack.pop())); + stack[stack.length - 1] = +stack[stack.length - 1]; break; case 129: case 118: - stack.push(asCoerceBoolean(stack.pop())); + stack[stack.length - 1] = !(!stack[stack.length - 1]); break; case 120: - stack.push(checkFilter(stack.pop())); + stack[stack.length - 1] = checkFilter(stack[stack.length - 1]); break; case 128: - stack.push(asCoerce(domain.getType(multinames[bc.index]), stack.pop())); + stack[stack.length - 1] = asCoerce(domain.getType(multinames[bc.index]), stack[stack.length - 1]); break; case 130: break; case 133: - stack.push(asCoerceString(stack.pop())); + stack[stack.length - 1] = asCoerceString(stack[stack.length - 1]); break; case 135: - stack.push(asAsType(stack.pop(), stack.pop())); + stack[stack.length - 2] = asAsType(stack.pop(), stack[stack.length - 1]); break; case 137: - obj = stack.pop(); - stack.push(obj == undefined ? null : obj); + obj = stack[stack.length - 1]; + stack[stack.length - 1] = obj == undefined ? null : obj; break; case 144: - stack.push(-stack.pop()); + stack[stack.length - 1] = -stack[stack.length - 1]; break; case 145: - a = stack.pop(); - stack.push(a + 1); + ++stack[stack.length - 1]; break; case 146: ++locals[bc.index]; break; case 147: - stack.push(1); - b = stack.pop(); - a = stack.pop(); - stack.push(a - b); + --stack[stack.length - 1]; break; case 148: --locals[bc.index]; break; case 149: - stack.push(asTypeOf(stack.pop())); + stack[stack.length - 1] = asTypeOf(stack[stack.length - 1]); break; case 150: - stack.push(!stack.pop()); + stack[stack.length - 1] = !stack[stack.length - 1]; break; case 151: - stack.push(~stack.pop()); + stack[stack.length - 1] = ~stack[stack.length - 1]; break; case 160: - b = stack.pop(); - a = stack.pop(); - stack.push(asAdd(a, b)); + stack[stack.length - 2] = asAdd(stack[stack.length - 2], stack.pop()); break; case 161: - b = stack.pop(); - a = stack.pop(); - stack.push(a - b); + stack[stack.length - 2] -= stack.pop(); break; case 162: - b = stack.pop(); - a = stack.pop(); - stack.push(a * b); + stack[stack.length - 2] *= stack.pop(); break; case 163: - b = stack.pop(); - a = stack.pop(); - stack.push(a / b); + stack[stack.length - 2] /= stack.pop(); break; case 164: - b = stack.pop(); - a = stack.pop(); - stack.push(a % b); + stack[stack.length - 2] %= stack.pop(); break; case 165: - b = stack.pop(); - a = stack.pop(); - stack.push(a << b); + stack[stack.length - 2] <<= stack.pop(); break; case 166: - b = stack.pop(); - a = stack.pop(); - stack.push(a >> b); + stack[stack.length - 2] >>= stack.pop(); break; case 167: - b = stack.pop(); - a = stack.pop(); - stack.push(a >>> b); + stack[stack.length - 2] >>>= stack.pop(); break; case 168: - b = stack.pop(); - a = stack.pop(); - stack.push(a & b); + stack[stack.length - 2] &= stack.pop(); break; case 169: - b = stack.pop(); - a = stack.pop(); - stack.push(a | b); + stack[stack.length - 2] |= stack.pop(); break; case 170: - b = stack.pop(); - a = stack.pop(); - stack.push(a ^ b); + stack[stack.length - 2] ^= stack.pop(); break; case 171: - b = stack.pop(); - a = stack.pop(); - stack.push(a == b); + stack[stack.length - 2] = stack[stack.length - 2] == stack.pop(); break; case 172: - b = stack.pop(); - a = stack.pop(); - stack.push(a === b); + stack[stack.length - 2] = stack[stack.length - 2] === stack.pop(); break; case 173: - b = stack.pop(); - a = stack.pop(); - stack.push(a < b); + stack[stack.length - 2] = stack[stack.length - 2] < stack.pop(); break; case 174: - b = stack.pop(); - a = stack.pop(); - stack.push(a <= b); + stack[stack.length - 2] = stack[stack.length - 2] <= stack.pop(); break; case 175: - b = stack.pop(); - a = stack.pop(); - stack.push(a > b); + stack[stack.length - 2] = stack[stack.length - 2] > stack.pop(); break; case 176: - b = stack.pop(); - a = stack.pop(); - stack.push(a >= b); + stack[stack.length - 2] = stack[stack.length - 2] >= stack.pop(); break; case 177: - stack.push(asIsInstanceOf(stack.pop(), stack.pop())); + stack[stack.length - 2] = asIsInstanceOf(stack.pop(), stack[stack.length - 1]); break; case 178: - stack.push(asIsType(domain.getType(multinames[bc.index]), stack.pop())); + stack[stack.length - 1] = asIsType(domain.getType(multinames[bc.index]), stack[stack.length - 1]); break; case 179: - stack.push(asIsType(stack.pop(), stack.pop())); + stack[stack.length - 2] = asIsType(stack.pop(), stack[stack.length - 1]); break; case 180: - stack.push(boxValue(stack.pop()).asHasProperty(null, stack.pop())); + stack[stack.length - 2] = boxValue(stack.pop()).asHasProperty(null, stack[stack.length - 1]); break; case 192: - stack.push(stack.pop() | 0); - stack.push(1); - b = stack.pop(); - a = stack.pop(); - stack.push(a + b); + stack[stack.length - 1] = (stack[stack.length - 1] | 0) + 1; break; case 193: - stack.push(stack.pop() | 0); - stack.push(1); - b = stack.pop(); - a = stack.pop(); - stack.push(a - b); + stack[stack.length - 1] = (stack[stack.length - 1] | 0) - 1; break; case 194: locals[bc.index] = (locals[bc.index] | 0) + 1; break; case 195: locals[bc.index] = (locals[bc.index] | 0) - 1; break; case 196: - stack.push(~(stack.pop() | 0)); + stack[stack.length - 1] = ~stack[stack.length - 1]; break; case 197: - b = stack.pop(); - a = stack.pop(); - stack.push(a + b | 0); + stack[stack.length - 2] = stack[stack.length - 2] + stack.pop() | 0; break; case 198: - b = stack.pop(); - a = stack.pop(); - stack.push(a - b | 0); + stack[stack.length - 2] = stack[stack.length - 2] - stack.pop() | 0; break; case 199: - b = stack.pop(); - a = stack.pop(); - stack.push(a * b | 0); + stack[stack.length - 2] = stack[stack.length - 2] * stack.pop() | 0; break; case 208: case 209: case 210: case 211: stack.push(locals[op - OP_getlocal0]); break; case 212: @@ -38956,16 +37262,19 @@ var Promise = function PromiseClosure() subpromises[i].fulfill(value); } delete subject.subpromises; } function propagateRejected(subject, reason) { subject.subpromisesReason = reason; var subpromises = subject.subpromises; if (!subpromises) { + if (!true) { + console.warn(reason); + } return; } for (var i = 0; i < subpromises.length; i++) { subpromises[i].reject(reason); } delete subject.subpromises; } function performCall(callback, arg, subject) { @@ -39168,16 +37477,28 @@ QuadTree.prototype._subdivide = function var midX = this.x + halfWidth; var midY = this.y + halfHeight; var level = this.level + 1; this.nodes[0] = new QuadTree(midX, this.y, halfWidth, halfHeight, level); this.nodes[1] = new QuadTree(this.x, this.y, halfWidth, halfHeight, level); this.nodes[2] = new QuadTree(this.x, midY, halfWidth, halfHeight, level); this.nodes[3] = new QuadTree(midX, midY, halfWidth, halfHeight, level); }; +var EXTERNAL_INTERFACE_FEATURE = 1; +var CLIPBOARD_FEATURE = 2; +var SHAREDOBJECT_FEATURE = 3; +var VIDEO_FEATURE = 4; +var SOUND_FEATURE = 5; +var NETCONNECTION_FEATURE = 6; +if (!this.performance) { + this.performance = {}; +} +if (!this.performance.now) { + this.performance.now = Date.now; +} { var BitmapDefinition = function () { function setBitmapData(value) { if (this._bitmapData) { this._bitmapData._changeNotificationTarget = null; } this._bitmapData = value; if (this._bitmapData) { @@ -39204,37 +37525,52 @@ QuadTree.prototype._subdivide = function return { __class__: 'flash.display.Bitmap', draw: function (ctx, ratio, colorTransform) { if (!this._bitmapData) { return; } ctx.save(); if (this._pixelSnapping === 'auto' || this._pixelSnapping === 'always') { - var transform = ctx.currentTransform; + var transform = this._getConcatenatedTransform(true); var EPSILON = 0.001; if (Math.abs(Math.abs(transform.a) - 1) <= EPSILON && Math.abs(Math.abs(transform.d) - 1) <= EPSILON && Math.abs(transform.b) <= EPSILON && Math.abs(transform.c) <= EPSILON) { - ctx.setTransform(transform.a < 0 ? -1 : 1, 0, 0, transform.d < 0 ? -1 : 1, transform.e | 0, transform.f | 0); + ctx.setTransform(transform.a < 0 ? -1 : 1, 0, 0, transform.d < 0 ? -1 : 1, transform.tx / 20 | 0, transform.ty / 20 | 0); } } colorTransform.setAlpha(ctx, true); + ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = this._smoothing; ctx.drawImage(this._bitmapData._drawable, 0, 0); + ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = false; ctx.restore(); traceRenderer.value && frameWriter.writeLn('Bitmap.draw() snapping: ' + this._pixelSnapping + ', dimensions: ' + this._bitmapData._drawable.width + ' x ' + this._bitmapData._drawable.height); FrameCounter.count('Bitmap.draw()'); }, initialize: function () { }, __glue__: { native: { static: {}, instance: { ctor: function (bitmapData, pixelSnapping, smoothing) { - this._pixelSnapping = pixelSnapping; - this._smoothing = smoothing; + if (pixelSnapping === 'never' || pixelSnapping === 'always') { + this._pixelSnapping = pixelSnapping; + } else { + this._pixelSnapping = 'auto'; + } + this._smoothing = !(!smoothing); + if (!bitmapData && this.symbol) { + var symbol = this.symbol; + bitmapData = new flash.display.BitmapData(symbol.width, symbol.height); + bitmapData._ctx.imageSmoothingEnabled = this._smoothing; + bitmapData._ctx.mozImageSmoothingEnabled = this._smoothing; + bitmapData._ctx.drawImage(symbol.img, 0, 0); + bitmapData._ctx.imageSmoothingEnabled = false; + bitmapData._ctx.mozImageSmoothingEnabled = false; + } setBitmapData.call(this, bitmapData || null); }, pixelSnapping: { get: function pixelSnapping() { return this._pixelSnapping; }, set: function pixelSnapping(value) { this._pixelSnapping = value; @@ -39283,28 +37619,28 @@ var BitmapDataDefinition = function () { if (this._drawable === null) throw ArgumentError(); }, ctor: function (width, height, transparent, backgroundColor) { if (this._img) { width = this._img.naturalWidth || this._img.width; height = this._img.naturalHeight || this._img.height; } else if (isNaN(width + height) || width <= 0 || height <= 0) { - throw ArgumentError(); + throwError('ArgumentError', Errors.ArgumentError); } this._transparent = transparent === undefined ? true : !(!transparent); this._backgroundColor = backgroundColor === undefined ? 4294967295 : backgroundColor; if (!this._transparent) { this._backgroundColor |= 4278190080; } if (this._skipCopyToCanvas) { this._drawable = this._img; } else { var canvas = document.createElement('canvas'); - this._ctx = canvas.getContext('kanvas-2d'); + this._ctx = canvas.getContext('2d'); canvas.width = width | 0; canvas.height = height | 0; this._drawable = canvas; if (!this._transparent || !this._img && this._backgroundColor) { this.fillRect(new flash.geom.Rectangle(0, 0, width | 0, height | 0), this._backgroundColor); } if (this._img) { this._ctx.drawImage(this._img, 0, 0); @@ -39314,32 +37650,35 @@ var BitmapDataDefinition = function () { dispose: function () { this._ctx = null; this._drawable.width = 0; this._drawable.height = 0; this._drawable = null; }, draw: function (source, matrix, colorTransform, blendMode, clipRect, smoothing) { this._checkCanvas(); - this._ctx.save(); - this._ctx.beginPath(); + var ctx = this._ctx; + ctx.save(); + ctx.beginPath(); if (clipRect && clipRect.width > 0 && clipRect.height > 0) { - this._ctx.rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height); - this._ctx.clip(); + ctx.rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height); + ctx.clip(); } if (matrix) { - this._ctx.transform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); - } - this._ctx.globalCompositeOperation = getBlendModeName(blendMode); + ctx.transform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); + } + ctx.globalCompositeOperation = getBlendModeName(blendMode); + ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = !(!smoothing); if (flash.display.BitmapData.class.isInstanceOf(source)) { - this._ctx.drawImage(source._drawable, 0, 0); - } else { - new RenderVisitor(source, this._ctx, null, true).startFragment(); - } - this._ctx.restore(); + ctx.drawImage(source._drawable, 0, 0); + } else { + new RenderVisitor(source, ctx, null, true).startFragment(); + } + ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = false; + ctx.restore(); this._invalidate(); }, fillRect: function (rect, color) { this._checkCanvas(); if (!this._transparent) { color |= 4278190080; } var ctx = this._ctx; @@ -39534,17 +37873,16 @@ var DisplayObjectDefinition = function ( c: 0, d: 1, tx: 0, ty: 0, invalid: true }; this._current3DTransform = null; this._cxform = null; - this._depth = null; this._graphics = null; this._filters = []; this._loader = null; this._mouseChildren = true; this._mouseOver = false; this._mouseX = 0; this._mouseY = 0; this._name = null; @@ -39562,16 +37900,17 @@ var DisplayObjectDefinition = function ( this._wasCachedAsBitmap = false; this._destroyed = false; this._maskedObject = null; this._scrollRect = null; this._invalid = false; this._region = null; this._level = -1; this._index = -1; + this._depth = -1; blendModes = [ blendModeClass.NORMAL, blendModeClass.NORMAL, blendModeClass.LAYER, blendModeClass.MULTIPLY, blendModeClass.SCREEN, blendModeClass.LIGHTEN, blendModeClass.DARKEN, @@ -39588,23 +37927,23 @@ var DisplayObjectDefinition = function ( var s = this.symbol; if (s) { this._animated = s.animated || false; this._bbox = s.bbox || null; this._blendMode = this._resolveBlendMode(s.blendMode); this._children = s.children || []; this._clipDepth = s.clipDepth || null; this._cxform = s.cxform || null; - this._depth = s.depth || null; this._loader = s.loader || null; this._name = s.name || null; this._owned = s.owned || false; this._parent = s.parent || null; this._level = isNaN(s.level) ? -1 : s.level; this._index = isNaN(s.index) ? -1 : s.index; + this._depth = isNaN(s.depth) ? -1 : s.depth; this._root = s.root || null; this._stage = s.stage || null; var scale9Grid = s.scale9Grid; if (scale9Grid) { this._scale9Grid = new flash.geom.Rectangle(scale9Grid.left, scale9Grid.top, scale9Grid.right - scale9Grid.left, scale9Grid.bottom - scale9Grid.top); } var matrix = s.currentTransform; if (matrix) { @@ -39664,52 +38003,81 @@ var DisplayObjectDefinition = function ( this._removeEventListenerImpl(type, listener, useCapture); if (type in broadcastedEvents && !this._listeners[type]) { avm2.systemDomain.onMessage.unregister(type, this._onBroadcastMessage); } }, _resolveBlendMode: function (blendModeNumeric) { return blendModes[blendModeNumeric] || flash.display.BlendMode.class.NORMAL; }, - _getConcatenatedTransform: function () { - if (!this._concatenatedTransform.invalid) { - return this._concatenatedTransform; - } - var stack = [ - this - ]; - var m; - var currentNode = this._parent; - while (currentNode) { - if (currentNode._concatenatedTransform.invalid) { - stack.push(currentNode); - } - currentNode = currentNode._parent; - } - while (stack.length) { - var node = stack.pop(); - m = node._concatenatedTransform; - var m2 = node._currentTransform; - if (node._parent) { - var m3 = node._parent._concatenatedTransform; - m.a = m2.a * m3.a + m2.b * m3.c; - m.b = m2.a * m3.b + m2.b * m3.d; - m.c = m2.c * m3.a + m2.d * m3.c; - m.d = m2.d * m3.d + m2.c * m3.b; - m.tx = m2.tx * m3.a + m3.tx + m2.ty * m3.c; - m.ty = m2.ty * m3.d + m3.ty + m2.tx * m3.b; - } else { + _getConcatenatedTransform: function (toDeviceSpace) { + var stage = this._stage; + if (this === this._stage) { + return toDeviceSpace ? this._concatenatedTransform : this._currentTransform; + } + var m, m2; + if (this._concatenatedTransform.invalid) { + if (this._parent === stage) { + m = this._concatenatedTransform; + m2 = this._currentTransform; m.a = m2.a; m.b = m2.b; m.c = m2.c; m.d = m2.d; m.tx = m2.tx; m.ty = m2.ty; - } - m.invalid = false; + } else { + var stack = [ + this + ]; + var currentNode = this._parent; + while (currentNode !== stage) { + if (currentNode._concatenatedTransform.invalid) { + stack.push(currentNode); + } + currentNode = currentNode._parent; + } + while (stack.length) { + var node = stack.pop(); + m = node._concatenatedTransform; + m2 = node._currentTransform; + if (node._parent) { + if (node._parent !== this._stage) { + var m3 = node._parent._concatenatedTransform; + m.a = m2.a * m3.a + m2.b * m3.c; + m.b = m2.a * m3.b + m2.b * m3.d; + m.c = m2.c * m3.a + m2.d * m3.c; + m.d = m2.d * m3.d + m2.c * m3.b; + m.tx = m2.tx * m3.a + m3.tx + m2.ty * m3.c; + m.ty = m2.ty * m3.d + m3.ty + m2.tx * m3.b; + } + } else { + m.a = m2.a; + m.b = m2.b; + m.c = m2.c; + m.d = m2.d; + m.tx = m2.tx; + m.ty = m2.ty; + } + m.invalid = false; + } + } + } else { + m = this._concatenatedTransform; + } + if (toDeviceSpace && stage) { + m2 = stage._concatenatedTransform; + return { + a: m.a * m2.a, + b: m.b * m2.d, + c: m.c * m2.a, + d: m.d * m2.d, + tx: m.tx * m2.a + m2.tx, + ty: m.ty * m2.d + m2.ty + }; } return m; }, _applyCurrentTransform: function (targetCoordSpace, point1, pointN) { var m; if (targetCoordSpace && targetCoordSpace !== this._parent) { m = this._getConcatenatedTransform(); } else { @@ -40371,24 +38739,24 @@ var DisplayObjectContainerDefinition = f get textSnapshot() { notImplemented(); }, addChild: function (child) { return this.addChildAt(child, this._children.length); }, addChildAt: function (child, index) { if (child === this) { - throw ArgumentError(); + throwError('ArgumentError', Errors.CantAddSelfError); } if (child._parent === this) { return this.setChildIndex(child, index); } var children = this._children; if (index < 0 || index > children.length) { - throw RangeError(); + throwError('RangeError', Errors.ParamRangeError); } if (child._index > -1) { var LoaderClass = avm2.systemDomain.getClass('flash.display.Loader'); if (LoaderClass.isInstanceOf(child._parent)) { def.removeChild.call(child._parent, child); } else { child._parent.removeChild(child); } @@ -40415,17 +38783,17 @@ var DisplayObjectContainerDefinition = f notImplemented(); }, contains: function (child) { return child._parent === this; }, getChildAt: function (index) { var children = this._children; if (index < 0 || index > children.length) { - throw RangeError(); + throwError('RangeError', Errors.ParamRangeError); } var child = children[index]; if (!flash.display.DisplayObject.class.isInstanceOf(child)) { return null; } return child; }, getChildByName: function (name) { @@ -40435,33 +38803,33 @@ var DisplayObjectContainerDefinition = f if (child.name === name) { return this.getChildAt(i); } } return null; }, getChildIndex: function (child) { if (child._parent !== this) { - throw ArgumentError(); + throwError('ArgumentError', Errors.NotAChildError); } return this._sparse ? this._children.indexOf(child) : child._index; }, getObjectsUnderPoint: function (pt) { notImplemented(); }, removeChild: function (child) { if (child._parent !== this) { - throw ArgumentError(); + throwError('ArgumentError', Errors.NotAChildError); } return this.removeChildAt(this.getChildIndex(child)); }, removeChildAt: function (index) { var children = this._children; if (index < 0 || index >= children.length) { - throw RangeError(); + throwError('RangeError', Errors.ParamRangeError); } var child = children[index]; child._dispatchEvent('removed'); if (this._stage) { this._stage._removeFromStage(child); } if (!this._sparse) { for (var i = children.length; i && i > index; i--) { @@ -40473,25 +38841,25 @@ var DisplayObjectContainerDefinition = f child._parent = null; child._index = -1; child._invalidateTransform(); this._invalidateBounds(); return child; }, setChildIndex: function (child, index) { if (child._parent !== this) { - throw ArgumentError(); + throwError('ArgumentError', Errors.NotAChildError); } var currentIndex = this.getChildIndex(child); if (currentIndex === index) { return; } var children = this._children; if (index < 0 || index > children.length) { - throw RangeError(); + throwError('RangeError', Errors.ParamRangeError); } children.splice(currentIndex, 1); children.splice(index, 0, child); if (!this._sparse) { var i = currentIndex < index ? currentIndex : index; while (i < children.length) { children[i]._index = i++; } @@ -40499,33 +38867,33 @@ var DisplayObjectContainerDefinition = f child._owned = false; child._invalidate(); return child; }, removeChildren: function (begin, end) { var children = this._children; var numChildren = children.length; if (begin < 0 || begin > numChildren || end < 0 || end < begin || end > numChildren) { - throw RangeError(); + throwError('RangeError', Errors.ParamRangeError); } for (var i = begin; i < end; i++) { this.removeChildAt(i); } }, swapChildren: function (child1, child2) { if (child1._parent !== this || child2._parent !== this) { - throw ArgumentError(); + throwError('ArgumentError', Errors.NotAChildError); } this.swapChildrenAt(this.getChildIndex(child1), this.getChildIndex(child2)); }, swapChildrenAt: function (index1, index2) { var children = this._children; var numChildren = children.length; if (index1 < 0 || index1 > numChildren || index2 < 0 || index2 > numChildren) { - throw RangeError(); + throwError('RangeError', Errors.ParamRangeError); } var child1 = children[index1]; var child2 = children[index2]; children[index1] = child2; children[index2] = child1; child1._index = index2; child2._index = index1; child1._owned = false; @@ -40650,22 +39018,24 @@ var GraphicsDefinition = function () { if (alpha === undefined) alpha = 1; this.beginPath(); this._currentPath.fillStyle = alpha ? { style: rgbIntAlphaToStr(color, alpha) } : null; }, beginGradientFill: function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) { + var style = createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos); this.beginPath(); - this._currentPath.fillStyle = createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos); + this._currentPath.fillStyle = style; }, beginBitmapFill: function (bitmap, matrix, repeat, smooth) { this.beginPath(); - this._currentPath.fillStyle = createPatternStyle(bitmap, matrix, repeat, smooth); + repeat = repeat !== false; + this._currentPath.fillStyle = createPatternStyle(bitmap, matrix, repeat, !(!smooth)); }, clear: function () { this._invalidate(); this._paths = []; this._currentPath = null; this.beginPath(); }, copyFrom: function (sourceGraphics) { @@ -40693,85 +39063,114 @@ var GraphicsDefinition = function () { this._invalidate(); this.beginPath(); this._currentPath.fillRule = winding || GRAPHICS_PATH_WINDING_EVEN_ODD; this._currentPath.commands = commands; this._currentPath.data = data; }, drawRect: function (x, y, w, h) { if (isNaN(w + h)) - throw ArgumentError(); + throwError('ArgumentError', Errors.InvalidParamError); this._invalidate(); this._currentPath.rect(x * 20 | 0, y * 20 | 0, w * 20 | 0, h * 20 | 0); }, drawRoundRect: function (x, y, w, h, ellipseWidth, ellipseHeight) { if (isNaN(w + h + ellipseWidth) || ellipseHeight !== undefined && isNaN(ellipseHeight)) { - throw ArgumentError(); + throwError('ArgumentError', Errors.InvalidParamError); } this._invalidate(); - var x2 = (x + w) * 20 | 0; - var y2 = (y + h) * 20 | 0; + if (ellipseHeight === undefined) { + ellipseHeight = ellipseWidth; + } x = x * 20 | 0; y = y * 20 | 0; + w = w * 20 | 0; + h = h * 20 | 0; + if (!ellipseHeight || !ellipseWidth) { + this._currentPath.rect(x, y, w, h); + return; + } var radiusX = ellipseWidth / 2 * 20 | 0; var radiusY = ellipseHeight / 2 * 20 | 0; - if (w === ellipseWidth && h === ellipseHeight) { - if (ellipseWidth === ellipseHeight) + var hw = w / 2 | 0; + var hh = h / 2 | 0; + if (radiusX > hw) { + radiusX = hw; + } + if (radiusY > hh) { + radiusY = hh; + } + if (hw === radiusX && hh === radiusY) { + if (radiusX === radiusY) this._currentPath.circle(x + radiusX, y + radiusY, radiusX); else - this._currentPath.ellipse(x + radiusX, y + radiusY, radiusX, radiusY, 0, Math.PI * 2); - return; - } - this._currentPath.moveTo(x2, y2 - radiusY); - this._currentPath.drawRoundCorner(x2, y2, x2 - radiusX, y2, radiusX, radiusY); - this._currentPath.lineTo(x + radiusX, y2); - this._currentPath.drawRoundCorner(x, y2, x, y2 - radiusY, radiusX, radiusY); - this._currentPath.lineTo(x, y + radiusY); - this._currentPath.drawRoundCorner(x, y, x + radiusX, y, radiusX, radiusY); - this._currentPath.lineTo(x2 - radiusX, y); - this._currentPath.drawRoundCorner(x2, y, x2, y + radiusY, radiusX, radiusY); - this._currentPath.lineTo(x2, y2 - radiusY); + this._currentPath.ellipse(x + radiusX, y + radiusY, radiusX, radiusY); + return; + } + var right = x + w; + var bottom = y + h; + var xlw = x + radiusX; + var xrw = right - radiusX; + var ytw = y + radiusY; + var ybw = bottom - radiusY; + this._currentPath.moveTo(right, ybw); + this._currentPath.curveTo(right, bottom, xrw, bottom); + this._currentPath.lineTo(xlw, bottom); + this._currentPath.curveTo(x, bottom, x, ybw); + this._currentPath.lineTo(x, ytw); + this._currentPath.curveTo(x, y, xlw, y); + this._currentPath.lineTo(xrw, y); + this._currentPath.curveTo(right, y, right, ytw); + this._currentPath.lineTo(right, ybw); }, drawRoundRectComplex: function (x, y, w, h, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius) { if (isNaN(w + h + topLeftRadius + topRightRadius + bottomLeftRadius + bottomRightRadius)) { - throw ArgumentError(); + throwError('ArgumentError', Errors.InvalidParamError); } this._invalidate(); - var x2 = (x + w) * 20 | 0; - var y2 = (y + h) * 20 | 0; x = x * 20 | 0; y = y * 20 | 0; + w = w * 20 | 0; + h = h * 20 | 0; + if (!topLeftRadius && !topRightRadius && !bottomLeftRadius && !bottomRightRadius) { + this._currentPath.rect(x, y, w, h); + return; + } topLeftRadius = topLeftRadius * 20 | 0; topRightRadius = topRightRadius * 20 | 0; bottomLeftRadius = bottomLeftRadius * 20 | 0; bottomRightRadius = bottomRightRadius * 20 | 0; - this._currentPath.moveTo(x2, y2 - bottomRightRadius); - this._currentPath.drawRoundCorner(x2, y2, x2 - bottomRightRadius, y2, bottomRightRadius); - this._currentPath.lineTo(x + bottomLeftRadius, y2); - this._currentPath.drawRoundCorner(x, y2, x, y2 - bottomLeftRadius, bottomLeftRadius); + var right = x + w; + var bottom = y + h; + var xtl = x + topLeftRadius; + this._currentPath.moveTo(right, bottom - bottomRightRadius); + this._currentPath.curveTo(right, bottom, right - bottomRightRadius, bottom); + this._currentPath.lineTo(x + bottomLeftRadius, bottom); + this._currentPath.curveTo(x, bottom, x, bottom - bottomLeftRadius); this._currentPath.lineTo(x, y + topLeftRadius); - this._currentPath.drawRoundCorner(x, y, x + topLeftRadius, y, topLeftRadius); - this._currentPath.lineTo(x2 - topRightRadius, y); - this._currentPath.drawRoundCorner(x2, y, x2, y + topRightRadius, topRightRadius); - this._currentPath.lineTo(x2, y2 - bottomRightRadius); + this._currentPath.curveTo(x, y, xtl, y); + this._currentPath.lineTo(right - topRightRadius, y); + this._currentPath.curveTo(right, y, right, y + topRightRadius); + this._currentPath.lineTo(right, bottom - bottomRightRadius); }, drawTriangles: function (vertices, indices, uvtData, culling) { notImplemented('Graphics#drawTriangles'); }, endFill: function () { this.beginPath(); this._currentPath.fillStyle = null; }, lineBitmapStyle: function (bitmap, matrix, repeat, smooth) { this.beginPath(); this._currentPath.lineStyle = createPatternStyle(bitmap, matrix, repeat, smooth); }, lineGradientStyle: function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) { + var style = createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos); this.beginPath(); - this._currentPath.lineStyle = createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos); + this._currentPath.lineStyle = style; }, lineStyle: function (width, color, alpha, pxHinting, scale, cap, joint, mlimit) { this.beginPath(); if (width) { if (alpha === undefined) alpha = 1; if (mlimit === undefined) mlimit = 3; @@ -40805,22 +39204,24 @@ var GraphicsDefinition = function () { } if (this.bbox) { return this.bbox; } var subpaths = this._paths; var xMins = [], yMins = [], xMaxs = [], yMaxs = []; for (var i = 0, n = subpaths.length; i < n; i++) { var path = subpaths[i]; - var b = path.getBounds(true); - if (b) { - xMins.push(b.xMin); - yMins.push(b.yMin); - xMaxs.push(b.xMax); - yMaxs.push(b.yMax); + if (path.commands.length) { + var b = path.getBounds(true); + if (b) { + xMins.push(b.xMin); + yMins.push(b.yMin); + xMaxs.push(b.xMax); + yMaxs.push(b.yMax); + } } } if (xMins.length === 0) { return 0; } var xMin = Math.min.apply(Math, xMins); var yMin = Math.min.apply(Math, yMins); var xMax = Math.max.apply(Math, xMaxs); @@ -40878,34 +39279,38 @@ function createPatternStyle(bitmap, matr b: 0, c: 0, d: 1, e: 0, f: 0 }; return { style: pattern, - transform: transform + transform: transform, + smooth: smooth }; } function createGradientStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPos) { + type === null || type === undefined && throwError('TypeError', Errors.NullPointerError, 'type'); + colors === null || type === undefined && throwError('TypeError', Errors.NullPointerError, 'colors'); + if (!(type === 'linear' || type === 'radial')) { + throwError('ArgumentError', Errors.InvalidEnumError, 'type'); + } var colorStops = []; for (var i = 0, n = colors.length; i < n; i++) { colorStops.push({ ratio: ratios[i] / 255, color: rgbIntAlphaToStr(colors[i], alphas[i]) }); } var gradientConstructor; if (type === 'linear') { gradientConstructor = buildLinearGradientFactory(colorStops); - } else if (type == 'radial') { + } else { gradientConstructor = buildRadialGradientFactory(focalPos || 0, colorStops); - } else { - throw ArgumentError(); } var scale = 819.2; var transform = matrix ? { a: scale * matrix.a, b: scale * matrix.b, c: scale * matrix.c, d: scale * matrix.d, e: matrix.tx, @@ -41336,18 +39741,33 @@ var LoaderDefinition = function () { type: 'frame' }; break; } } }, oncomplete: function (result) { commitData(result); + var stats; + if (typeof result.swfVersion === 'number') { + var bbox = result.bbox; + stats = { + topic: 'parseInfo', + parseTime: result.parseTime, + bytesTotal: result.bytesTotal, + swfVersion: result.swfVersion, + frameRate: result.frameRate, + width: (bbox.xMax - bbox.xMin) / 20, + height: (bbox.yMax - bbox.yMin) / 20, + isAvm2: !(!result.fileAttributes.doAbc) + }; + } commitData({ - command: 'complete' + command: 'complete', + stats: stats }); } }; } function parseBytes(bytes) { SWF.parse(bytes, createParsingContext()); } if (isWorker || !flash.net.URLRequest.class.isInstanceOf(request)) { @@ -41452,16 +39872,20 @@ var LoaderDefinition = function () { if (type === 'frameConstructed') { frameConstructed.resolve(); avm2.systemDomain.onMessage.unregister('frameConstructed', waitForFrame); } }); Promise.when(frameConstructed, this._lastPromise).then(function () { this.contentLoaderInfo._dispatchEvent('complete'); }.bind(this)); + var stats = data.stats; + if (stats) { + TelemetryService.reportTelemetry(stats); + } this._worker && this._worker.terminate(); break; case 'empty': this._lastPromise = new Promise(); this._lastPromise.resolve(); break; case 'error': this.contentLoaderInfo._dispatchEvent('ioError', flash.events.IOErrorEvent); @@ -41849,16 +40273,18 @@ var LoaderDefinition = function () { }, 200); promiseQueue.push(fontPromise); } } className = 'flash.text.Font'; props.name = symbol.name; props.uniqueName = symbol.uniqueName; props.charset = symbol.charset; + props.bold = symbol.bold; + props.italic = symbol.italic; props.metrics = symbol.metrics; this._registerFont(className, props); break; case 'image': var img = new Image(); var imgPromise = new Promise(); img.onload = function () { if (symbol.mask) { @@ -42021,16 +40447,19 @@ var LoaderDefinition = function () { }); loader._dictionary[0] = documentPromise; loader._lastPromise = documentPromise; loader._vmPromise = vmPromise; loader._isAvm2Enabled = info.fileAttributes.doAbc; this._setup(); }, _load: function (request, checkPolicyFile, applicationDomain, securityDomain, deblockingFilter) { + if (!isWorker && flash.net.URLRequest.class.isInstanceOf(request)) { + this._contentLoaderInfo._url = request._url; + } if (!isWorker && WORKERS_ENABLED) { var loader = this; var worker = loader._worker = new Worker(SHUMWAY_ROOT + LOADER_PATH); worker.onmessage = function (evt) { loader._commitData(evt.data); }; if (flash.net.URLRequest.class.isInstanceOf(request)) { var session = FileLoadingService.createSession(); @@ -42108,17 +40537,17 @@ var LoaderDefinition = function () { _getJPEGLoaderContextdeblockingfilter: function (context) { return 0; }, _load: def._load, _loadBytes: function _loadBytes(bytes, checkPolicyFile, applicationDomain, securityDomain, requestedContentParent, parameters, deblockingFilter, allowLoadBytesCodeExecution, imageDecodingPolicy) { def._load(bytes.a); }, _unload: function _unload(halt, gc) { - notImplemented('Loader._unload'); + somewhatImplemented('Loader._unload, do we even need to do anything here?'); }, _close: function _close() { somewhatImplemented('Loader._close'); }, _getUncaughtErrorEvents: function _getUncaughtErrorEvents() { somewhatImplemented('Loader._getUncaughtErrorEvents'); return this._uncaughtErrorEvents; }, @@ -42202,19 +40631,16 @@ var LoaderInfoDefinition = function () { }, applicationDomain: { get: function applicationDomain() { return new flash.system.ApplicationDomain(avm2.applicationDomain); } }, swfVersion: { get: function swfVersion() { - if (!this._swfVersion) { - throw Error(); - } return this._swfVersion; } }, actionScriptVersion: { get: function actionScriptVersion() { return this._actionScriptVersion; } }, @@ -42376,16 +40802,17 @@ var MovieClipDefinition = function () { this._onExecuteFrame = function onExecuteFrame() { self._removeEventListener('executeFrame', onExecuteFrame); self._allowFrameNavigation = false; self._callFrame(self._currentFrame); self._allowFrameNavigation = true; if (self._playHead !== self._currentFrame) { self._gotoFrame(self._playHead, true); } + self._postConstructChildren(); }; this._addEventListener('executeFrame', this._onExecuteFrame); if (this._totalFrames <= 1) { return this; } this._onAdvanceFrame = function onAdvanceFrame() { var frameNum = self._playHead + 1; if (frameNum > self._totalFrames) { @@ -42411,34 +40838,41 @@ var MovieClipDefinition = function () { this.play(); }, _declareChildren: function declareChildren(nextFrameNum) { var currentFrame = this._currentFrame; if (nextFrameNum === currentFrame) { return; } var timeline = this._timeline; - var currentDisplayList = timeline[currentFrame - 1]; var nextDisplayList = timeline[nextFrameNum - 1]; - if (nextDisplayList === currentDisplayList) { - return; - } + if (nextDisplayList === timeline[currentFrame - 1]) { + return; + } + var prevDisplayListItem = null; + var currentDisplayListItem = this._currentDisplayList; var children = this._children; - var depths = nextFrameNum > currentFrame ? nextDisplayList.depths : currentDisplayList.depths; - var depthMap = this._depthMap; + var depths = nextDisplayList.depths; var index = children.length; var i = depths.length; while (i--) { - var depth = depths[i]; - var currentCmd = currentDisplayList[depth]; + var depth = depths[i], depthInt = depth | 0; + while (currentDisplayListItem && currentDisplayListItem.depth > depthInt) { + prevDisplayListItem = currentDisplayListItem; + currentDisplayListItem = currentDisplayListItem.next; + } + var currentChild = null; + if (currentDisplayListItem && currentDisplayListItem.depth === depthInt) { + currentChild = currentDisplayListItem.obj; + if (currentChild && currentChild._owned) { + index = this.getChildIndex(currentChild); + } + } + var currentCmd = currentDisplayListItem && currentDisplayListItem.depth === depthInt ? currentDisplayListItem.cmd : null; var nextCmd = nextDisplayList[depth]; - var currentChild = depthMap[depth]; - if (currentChild && currentChild._owned) { - index = this.getChildIndex(currentChild); - } if (!nextCmd || nextCmd === currentCmd) { continue; } if (currentCmd && currentChild && currentChild._animated && nextCmd.symbolId === currentCmd.symbolId && nextCmd.ratio === currentCmd.ratio) { currentChild._invalidate(); currentChild._invalidateBounds(); if (nextCmd.hasMatrix) { var m = nextCmd.matrix; @@ -42469,38 +40903,69 @@ var MovieClipDefinition = function () { if (nextCmd.hasName) { currentChild.name = nextCmd.name; } if (nextCmd.blend) { currentChild.blendMode = this._resolveBlendMode(nextCmd.blendMode); } continue; } - this._addTimelineChild(nextCmd, index); + var newDisplayListItem = this._addTimelineChild(nextCmd, index); + newDisplayListItem.next = currentDisplayListItem; + if (prevDisplayListItem) { + prevDisplayListItem.next = newDisplayListItem; + } else { + this._currentDisplayList = newDisplayListItem; + } + prevDisplayListItem = newDisplayListItem; } }, _destructChildren: function destructChildren(nextFrameNum) { var currentFrame = this._currentFrame; if (nextFrameNum === currentFrame) { return; } var timeline = this._timeline; - var currentDisplayList = timeline[currentFrame - 1]; var nextDisplayList = timeline[nextFrameNum - 1]; - if (nextDisplayList === currentDisplayList) { - return; - } - var depths = nextFrameNum > currentFrame ? currentDisplayList.depths : nextDisplayList.depths; - for (var i = 0; i < depths.length; i++) { - var depth = depths[i]; - var currentCmd = currentDisplayList[depth]; + if (nextDisplayList === timeline[currentFrame - 1]) { + return; + } + var prevDisplayListItem = null; + var currentDisplayListItem = this._currentDisplayList; + var toRemove = null; + while (currentDisplayListItem) { + var depth = currentDisplayListItem.depth; + var currentCmd = currentDisplayListItem.cmd; var nextCmd = nextDisplayList[depth]; - if (currentCmd && (!nextCmd || nextCmd.symbolId !== currentCmd.symbolId || nextCmd.ratio !== currentCmd.ratio)) { - this._removeTimelineChild(currentCmd); - } + if (!nextCmd || nextCmd.symbolId !== currentCmd.symbolId || nextCmd.ratio !== currentCmd.ratio) { + var nextDisplayListItem = currentDisplayListItem.next; + if (prevDisplayListItem) { + prevDisplayListItem.next = nextDisplayListItem; + } else { + this._currentDisplayList = nextDisplayListItem; + } + currentDisplayListItem.next = toRemove; + toRemove = currentDisplayListItem; + currentDisplayListItem = nextDisplayListItem; + } else { + prevDisplayListItem = currentDisplayListItem; + currentDisplayListItem = currentDisplayListItem.next; + } + } + while (toRemove) { + var child = toRemove.obj; + if (child) { + this._sparse = true; + this.removeChild(child); + child.destroy(); + if (child._isPlaying) { + child.stop(); + } + } + toRemove = toRemove.next; } }, _gotoFrame: function gotoFrame(frameNum, execute) { var enterFrame = frameNum !== this._currentFrame; if (this._allowFrameNavigation || !this._loader._isAvm2Enabled) { if (enterFrame) { this._destructChildren(frameNum); this._declareChildren(frameNum); @@ -42515,16 +40980,17 @@ var MovieClipDefinition = function () { domain.broadcastMessage('frameConstructed'); domain.broadcastMessage('executeFrame'); domain.broadcastMessage('exitFrame'); return; } if (enterFrame && (execute || !this._loader._isAvm2Enabled)) { this._callFrame(frameNum); } + this._postConstructChildren(); return; } if (enterFrame) { this._playHead = frameNum; } }, _enterFrame: function navigate(frameNum) { if (frameNum === this._currentFrame) { @@ -42562,16 +41028,21 @@ var MovieClipDefinition = function () { } if (frame in this._frameScripts) { var scripts = this._frameScripts[frame]; try { for (var i = 0, n = scripts.length; i < n; i++) { scripts[i].call(this); } } catch (e) { + var AVM2_ERROR_TYPE = 2; + TelemetryService.reportTelemetry({ + topic: 'error', + error: AVM2_ERROR_TYPE + }); if (false) { console.error('error ' + e + ', stack: \n' + e.stack); } this.stop(); throw e; } } }, @@ -42889,22 +41360,17 @@ var MovieClipDefinition = function () { play: def.play, stop: def.stop, nextFrame: def.nextFrame, prevFrame: def.prevFrame, gotoAndPlay: def.gotoAndPlay, gotoAndStop: def.gotoAndStop, addFrameScript: def.addFrameScript, prevScene: def.prevScene, - nextScene: def.nextScene, - _depth: { - get: function () { - return this._depth; - } - } + nextScene: def.nextScene } } }; return def; }.call(this); var NativeMenuDefinition = function () { return { __class__: 'flash.display.NativeMenu', @@ -43305,43 +41771,45 @@ var SimpleButtonDefinition = function () var SpriteDefinition = function () { var def = { __class__: 'flash.display.Sprite', initialize: function () { this._buttonMode = false; this._hitArea = null; this._useHandCursor = true; this._hitTarget = null; - this._depthMap = {}; + this._currentDisplayList = null; var s = this.symbol; if (s) { this._graphics = s.graphics || new flash.display.Graphics(); if (s.timeline) { var displayList = s.timeline[0]; if (displayList) { var depths = displayList.depths; for (var i = 0; i < depths.length; i++) { var cmd = displayList[depths[i]]; if (cmd) { - this._addTimelineChild(cmd); + var displayListItem = this._addTimelineChild(cmd); + displayListItem.next = this._currentDisplayList; + this._currentDisplayList = displayListItem; } } } } } else { this._graphics = new flash.display.Graphics(); } this._graphics._parent = this; }, _addTimelineChild: function addTimelineChild(cmd, index) { var symbolPromise = cmd.promise; var symbolInfo = symbolPromise.value; var props = Object.create(symbolInfo.props); + props.symbolId = cmd.symbolId; props.depth = cmd.depth; - props.symbolId = cmd.symbolId; if (cmd.clip) { props.clipDepth = cmd.clipDepth; } if (cmd.hasCxform) { props.cxform = cmd.cxform; } if (cmd.hasMatrix) { props.currentTransform = cmd.matrix; @@ -43350,58 +41818,45 @@ var SpriteDefinition = function () { props.name = cmd.name; } if (cmd.hasRatio) { props.ratio = cmd.ratio / 65535; } if (cmd.blend) { props.blendMode = cmd.blendMode; } - var child = { + var displayListItem = { + cmd: cmd, + depth: cmd.depth, className: symbolInfo.className, + props: props, events: cmd.events, - props: props + obj: null }; if (index !== undefined) { - this._children.splice(index, 0, child); - } else { - this._children.push(child); + this._children.splice(index, 0, displayListItem); + } else { + this._children.push(displayListItem); } this._sparse = true; - }, - _removeTimelineChild: function removeTimelineChild(cmd) { - var child = this._depthMap[cmd.depth]; - if (!child) { - return; - } - this._depthMap[child._depth] = null; - child._depth = null; - if (!child._owned) { - return; - } - this._sparse = true; - this.removeChild(child); - child.destroy(); - if (child._isPlaying) { - child.stop(); - } + return displayListItem; }, _constructChildren: function () { if (!this._sparse) { return; } var loader = this._loader; var children = this._children; for (var i = 0; i < children.length; i++) { - var symbolInfo = children[i]; - if (flash.display.DisplayObject.class.isInstanceOf(symbolInfo)) { - symbolInfo._index = i; - } else { - var symbolClass = avm2.systemDomain.findClass(symbolInfo.className) ? avm2.systemDomain.getClass(symbolInfo.className) : avm2.applicationDomain.getClass(symbolInfo.className); - var props = Object.create(symbolInfo.props); + var displayListItem = children[i]; + if (flash.display.DisplayObject.class.isInstanceOf(displayListItem)) { + displayListItem._index = i; + } else { + var symbolClass = avm2.systemDomain.findClass(displayListItem.className) ? avm2.systemDomain.getClass(displayListItem.className) : avm2.applicationDomain.getClass(displayListItem.className); + var props = Object.create(displayListItem.props); var name = props.name; props.animated = true; props.owned = true; props.parent = this; props.stage = this._stage; if (this._level > -1) { props.level = this._level + 1; } @@ -43412,56 +41867,74 @@ var SpriteDefinition = function () { } symbolClass.instanceConstructor.call(instance); if (flash.display.BitmapData.class.isInstanceOf(instance)) { var bitmapData = instance; instance = flash.display.Bitmap.class.createAsSymbol(props); flash.display.Bitmap.class.instanceConstructor.call(instance, bitmapData); } if (!loader._isAvm2Enabled) { - this._initAvm1Bindings(instance, name, symbolInfo.events); + this._initAvm1Bindings(instance, name, displayListItem.events); instance._dispatchEvent('init'); instance._dispatchEvent('construct'); - } - instance._dispatchEvent('load'); + instance._needLoadEvent = true; + } else { + instance._dispatchEvent('load'); + } instance._dispatchEvent('added'); if (this._stage) { this._stage._addToStage(instance); } children[i] = instance; - this._depthMap[instance._depth] = instance; + displayListItem.obj = instance; } } this._sparse = false; }, + _postConstructChildren: function () { + var loader = this._loader; + if (!loader || loader._isAvm2Enabled) { + return; + } + var children = this._children; + for (var i = 0; i < children.length; i++) { + var instance = children[i]; + if (instance._needLoadEvent) { + delete instance._needLoadEvent; + instance._dispatchEvent('load'); + } + } + }, _duplicate: function (name, depth, initObject) { var loader = this._loader; var parent = this._parent; var children = parent._children; var symbolClass = this.class; var symbolInfo = this.symbol; var props = Object.create(symbolInfo); props.name = name; + props.parent = parent; props.depth = depth; - props.parent = parent; var instance = symbolClass.createAsSymbol(props); - if (name) - parent[Multiname.getPublicQualifiedName(name)] = instance; + if (name && loader && !loader._isAvm2Enabled && !parent.asHasProperty(undefined, name, 0, false)) { + parent.asSetPublicProperty(name, instance); + } symbolClass.instanceConstructor.call(instance); + instance._index = children.length; + children.push(instance); if (!loader._isAvm2Enabled) { parent._initAvm1Bindings(instance, name, symbolInfo && symbolInfo.events); instance._dispatchEvent('init'); instance._dispatchEvent('construct'); } instance._dispatchEvent('load'); instance._dispatchEvent('added'); if (this._stage) { instance._invalidate(); } - children.push(instance); return instance; }, _insertChildAtDepth: function (child, depth) { this.addChild(child); var name = child._name; var loader = this._loader; if (name && loader && !loader._isAvm2Enabled && !this._getAS2Object().asHasProperty(undefined, name, 0, true)) { this._getAS2Object().asSetPublicProperty(name, child._getAS2Object()); @@ -43480,32 +41953,33 @@ var SpriteDefinition = function () { variableName = targetPath.pop(); if (targetPath[0] == '_root' || targetPath[0] === '') { clip = this.root._getAS2Object(); targetPath.shift(); if (targetPath[0] === '') { targetPath.shift(); } } else { - clip = instance._getAS2Object(); + clip = this._getAS2Object(); } while (targetPath.length > 0) { var childName = targetPath.shift(); clip = clip.asGetPublicProperty(childName) || clip[childName]; if (!clip) { throw new Error('Cannot find ' + childName + ' variable'); } } - } else - clip = instance._getAS2Object(); + } else { + clip = this._getAS2Object(); + } if (!clip.asHasProperty(undefined, variableName, 0)) { clip.asSetPublicProperty(variableName, instance.text); } instance._addEventListener('advanceFrame', function () { - instance.text = clip.asGetPublicProperty(variableName); + instance.text = '' + clip.asGetPublicProperty(variableName); }); } if (events) { var eventsBound = []; for (var i = 0; i < events.length; i++) { var event = events[i]; if (event.eoe) { break; @@ -43515,27 +41989,32 @@ var SpriteDefinition = function () { }.bind(instance, event.actionsData); for (var eventName in event) { if (eventName.indexOf('on') !== 0 || !event[eventName]) continue; var avm2EventName = eventName[2].toLowerCase() + eventName.substring(3); if (avm2EventName === 'enterFrame') { avm2EventName = 'frameConstructed'; } - instance._addEventListener(avm2EventName, fn, false); + var avm2EventTarget = instance; + if (avm2EventName === 'mouseDown' || avm2EventName === 'mouseUp' || avm2EventName === 'mouseMove') { + avm2EventTarget = this._stage; + } + avm2EventTarget._addEventListener(avm2EventName, fn, false); eventsBound.push({ name: avm2EventName, - fn: fn + fn: fn, + target: avm2EventTarget }); } } if (eventsBound.length > 0) { instance._addEventListener('removed', function (eventsBound) { for (var i = 0; i < eventsBound.length; i++) { - instance._removeEventListener(eventsBound[i].name, eventsBound[i].fn, false); + eventsBound[i].target._removeEventListener(eventsBound[i].name, eventsBound[i].fn, false); } }.bind(instance, eventsBound), false); } } if (name) { this._getAS2Object().asSetPublicProperty(name, instance._getAS2Object()); } }, @@ -43632,17 +42111,17 @@ var StageDefinition = function () { this._colorCorrection = 'default'; this._stageFocusRect = true; this._fullScreenSourceRect = null; this._wmodeGPU = false; this._root = null; this._qtree = null; this._invalidObjects = []; this._mouseMoved = false; - this._clickTarget = this; + this._mouseTarget = this; this._cursor = 'auto'; this._concatenatedTransform.invalid = false; }, _setup: function setup(ctx, options) { this._qtree = new QuadTree(0, 0, this._stageWidth, this._stageHeight, 0); this._invalid = true; }, _addToStage: function addToStage(displayObject) { @@ -43674,17 +42153,17 @@ var StageDefinition = function () { }, _invalidateOnStage: function invalidateOnStage(displayObject) { if (displayObject._invalid) { return; } displayObject._invalid = true; this._invalidObjects.push(displayObject); }, - _processInvalidRegions: function processInvalidRegions() { + _processInvalidRegions: function processInvalidRegions(createInvalidPath) { var objects = this._invalidObjects; var regions = []; while (objects.length) { var displayObject = objects.shift(); if (displayObject._children.length) { var children = displayObject._children; for (var i = 0; i < children.length; i++) { var child = children[i]; @@ -43722,16 +42201,19 @@ var StageDefinition = function () { currentRegion.obj = displayObject; displayObject._region = currentRegion; } regions.push(currentRegion); } else { displayObject._invalid = false; } } + if (!createInvalidPath) { + return; + } var invalidPath = new ShapePath(); for (var i = 0; i < regions.length; i++) { var region = regions[i]; var xMin = region.xMin - region.xMin % 20 - 40; var yMin = region.yMin - region.yMin % 20 - 40; var xMax = region.xMax - region.xMax % 20 + 80; var yMax = region.yMax - region.yMax % 20 + 80; var neighbours = this._qtree.retrieve(xMin, yMin, xMax, yMax); @@ -43804,63 +42286,58 @@ var StageDefinition = function () { break; } } if (!target) { target = this; } else if (target._hitTarget) { target = target._hitTarget; } - if (target === this._clickTarget) { - target._dispatchEvent(new flash.events.MouseEvent('mouseMove')); - } else { - if (this._clickTarget._buttonMode) { - this._clickTarget._gotoButtonState('up'); - } - this._clickTarget._dispatchEvent(new flash.events.MouseEvent('mouseOut')); - var nodeLeft = this._clickTarget; + if (target === this._mouseTarget) { + target._dispatchEvent('mouseMove'); + } else { + if (this._mouseTarget._buttonMode) { + this._mouseTarget._gotoButtonState('up'); + } + this._mouseTarget._dispatchEvent('mouseOut'); + var nodeLeft = this._mouseTarget; var containerLeft = nodeLeft._parent; var nodeEntered = target; var containerEntered = nodeEntered._parent; var cursor = 'auto'; while (nodeLeft._level >= 0 && nodeLeft !== containerEntered) { if (nodeLeft._hasEventListener('rollOut')) { - nodeLeft._dispatchEvent(new flash.events.MouseEvent('rollOut', false)); + nodeLeft._dispatchEvent('rollOut'); } nodeLeft = nodeLeft._parent; } while (nodeEntered._level >= 0 && nodeEntered !== containerLeft) { if (nodeEntered._hasEventListener('rollOver')) { - nodeEntered._dispatchEvent(new flash.events.MouseEvent('rollOver', false)); + nodeEntered._dispatchEvent('rollOver'); } if (nodeEntered._buttonMode && nodeEntered._useHandCursor) { cursor = 'pointer'; } nodeEntered = nodeEntered._parent; } if (target._buttonMode) { target._gotoButtonState('over'); } - target._dispatchEvent(new flash.events.MouseEvent('mouseOver')); - this._clickTarget = target; + target._dispatchEvent('mouseOver'); + this._mouseTarget = target; this._cursor = cursor; } }, _as2SetLevel: function (level, loader) { somewhatImplemented('Stage._as2SetLevel'); this.addChild(loader); }, __glue__: { native: { instance: { - $canvasState: { - get: function () { - return this._canvasState; - } - }, invalidate: function invalidate() { this._invalid = true; this._deferRenderEvent = true; }, isFocusInaccessible: function isFocusInaccessible() { notImplemented('Stage.isFocusInaccessible'); }, set_displayState: function set_displayState(value) { @@ -44143,21 +42620,41 @@ var StageDefinition = function () { clone: 'open public clone' } } } }; }.call(this); } var EventDispatcherDefinition = function () { + var mouseEvents = { + click: true, + contextMenu: true, + doubleClick: true, + middleClick: true, + middleMouseDown: true, + middleMouseUp: true, + mouseDown: true, + mouseMove: true, + mouseOut: true, + mouseOver: true, + mouseUp: true, + mouseWheel: true, + releaseOutside: true, + rightClick: true, + rightMouseDown: true, + rightMouseUp: true, + rollOut: false, + rollOver: false + }; function doDispatchEvent(dispatcher, event, eventClass) { var target = dispatcher._target; var type = event._type || event; var listeners = dispatcher._listeners[type]; - if (event._bubbles) { + if (typeof event === 'string' && mouseEvents[event] || event._bubbles) { var ancestors = []; var currentNode = target._parent; while (currentNode) { if (currentNode._hasEventListener(type)) { ancestors.push(currentNode); } currentNode = currentNode._parent; } @@ -44196,17 +42693,29 @@ var EventDispatcherDefinition = function if (!methodInfo.parameters[0].isUsed) { item.handleEvent(); continue; } } } if (needsInit) { if (typeof event === 'string') { - event = eventClass ? new eventClass(event) : new flash.events.Event(event); + if (eventClass) { + event = new eventClass(event); + } else { + if (event in mouseEvents) { + event = new flash.events.MouseEvent(event, mouseEvents[event]); + if (target._stage) { + event._localX = target.mouseX; + event._localY = target.mouseY; + } + } else { + event = new flash.events.Event(event); + } + } } else if (event._target) { event = event.clone(); } event._target = target; event._currentTarget = currentTarget || target; event._eventPhase = eventPhase || 2; needsInit = false; } @@ -44222,17 +42731,17 @@ var EventDispatcherDefinition = function __class__: 'flash.events.EventDispatcher', initialize: function () { this._target = this; this._listeners = {}; this._captureListeners = {}; }, _addEventListenerImpl: function addEventListenerImpl(type, listener, useCapture, priority) { if (typeof listener !== 'function') { - throw new ArgumentError(); + throwError('TypeError', Errors.CheckTypeFailedError, listener, 'Function'); } var listeners = useCapture ? this._captureListeners : this._listeners; var queue = listeners[type]; var listenerObj = { handleEvent: listener, priority: priority || 0 }; if (queue) { @@ -44254,17 +42763,17 @@ var EventDispatcherDefinition = function ]; } }, _addEventListener: function addEventListener(type, listener, useCapture, priority) { this._addEventListenerImpl(type, listener, useCapture, priority); }, _removeEventListenerImpl: function removeEventListenerImpl(type, listener, useCapture) { if (typeof listener !== 'function') { - return; + throwError('TypeError', Errors.CheckTypeFailedError, listener, 'Function'); } var listeners = useCapture ? this._captureListeners : this._listeners; var queue = listeners[type]; if (queue) { for (var i = 0; i < queue.length; i++) { var item = queue[i]; if (item.handleEvent === listener) { queue.splice(i, 1); @@ -44367,43 +42876,55 @@ var KeyboardEventDefinition = function ( } } } }; }.call(this); var MouseEventDefinition = function () { return { __class__: 'flash.events.MouseEvent', + initialize: function () { + this._localX = NaN; + this._localY = NaN; + }, __glue__: { native: { instance: { updateAfterEvent: function updateAfterEvent() { }, getStageX: function getStageX() { - return this._target.stage._mouseX / 20; + if (this._target) { + var m = this._target._getConcatenatedTransform(); + var x = m.a * this._localX + m.c * this._localY + m.tx; + return x / 20; + } + return this._localX / 20; }, getStageY: function getStageY() { - return this._target.stage._mouseY / 20; + if (this._target) { + var m = this._target._getConcatenatedTransform(); + var y = m.d * this._localY + m.b * this._localX + m.ty; + return y / 20; + } + return this._localY / 20; }, localX: { get: function localX() { - var x = isNaN(this._localX) ? this._target.mouseX : this._localX; - return x / 20; + return this._localX / 20; }, set: function localX(value) { this._localX = value * 20 | 0; } }, localY: { get: function localY() { - var y = isNaN(this._localY) ? this._target.mouseY : this._localY; - return y / 20; + return this._localY / 20; }, set: function localY(value) { - this._localY = value * 20 / 0; + this._localY = value * 20 | 0; } } } }, script: { static: Glue.ALL } } @@ -44454,16 +42975,20 @@ var TimerEventDefinition = function () { initialize: function () { }, __glue__: { native: { static: { _initJS: function _initJS() { if (initialized) return; + TelemetryService.reportTelemetry({ + topic: 'feature', + feature: EXTERNAL_INTERFACE_FEATURE + }); initialized = true; FirefoxCom.initJS(callIn); }, _getPropNames: function _getPropNames(obj) { var keys = []; forEachPublicProperty(obj, function (key) { keys.push(key); }); @@ -45273,18 +43798,19 @@ var TransformDefinition = function () { if (cxform) { return new flash.geom.ColorTransform(cxform.redMultiplier / 256, cxform.greenMultiplier / 256, cxform.blueMultiplier / 256, cxform.alphaMultiplier / 256, cxform.redOffset, cxform.greenOffset, cxform.blueOffset, cxform.alphaOffset); } else { return new flash.geom.ColorTransform(); } }, set colorTransform(val) { var CTClass = avm2.systemDomain.getClass('flash.geom.ColorTransform'); - if (!CTClass.isInstanceOf(val)) - throw TypeError(); + if (!CTClass.isInstanceOf(val)) { + throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.ColorTransform'); + } this._target._cxform = { redMultiplier: val.redMultiplier * 256, greenMultiplier: val.greenMultiplier * 256, blueMultiplier: val.blueMultiplier * 256, alphaMultiplier: val.alphaMultiplier * 256, redOffset: val.redOffset, greenOffset: val.greenOffset, blueOffset: val.blueOffset, @@ -45307,18 +43833,19 @@ var TransformDefinition = function () { get matrix() { if (this._target._current3DTransform) { return null; } var m = this._target._currentTransform; return new flash.geom.Matrix(m.a, m.b, m.c, m.d, m.tx / 20, m.ty / 20); }, set matrix(val) { - if (!flash.geom.Matrix.class.isInstanceOf(val)) - throw TypeError(); + if (!flash.geom.Matrix.class.isInstanceOf(val)) { + throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.Matrix'); + } var target = this._target; target._invalidate(); var a = val.a; var b = val.b; var c = val.c; var d = val.d; var tx = val.tx * 20 | 0; var ty = val.ty * 20 | 0; @@ -45339,18 +43866,19 @@ var TransformDefinition = function () { target._current3DTransform = null; }, get matrix3D() { var m = this._target._current3DTransform; return m && m.clone(); }, set matrix3D(val) { var Matrix3DClass = avm2.systemDomain.getClass('flash.geom.Matrix3D'); - if (!Matrix3DClass.isInstanceOf(val)) - throw TypeError(); + if (!Matrix3DClass.isInstanceOf(val)) { + throwError('TypeError', Errors.CheckTypeFailedError, val, 'flash.geom.Matrix3D'); + } var raw = val.rawData; this.matrix = new flash.geom.Matrix(raw.asGetPublicProperty(0), raw.asGetPublicProperty(1), raw.asGetPublicProperty(4), raw.asGetPublicProperty(5), raw.asGetPublicProperty(12), raw.asGetPublicProperty(13)); this._target._current3DTransform = val; }, ctor: function (target) { this._target = target; target._transform = this; } @@ -45448,16 +43976,20 @@ var SoundDefinition = function () { soundData.mimeType = s.packaged.mimeType; } var _this = this; getAudioDescription(soundData, function (description) { _this._length = description.duration; }); this._soundData = soundData; } + TelemetryService.reportTelemetry({ + topic: 'feature', + feature: SOUND_FEATURE + }); }, close: function close() { somewhatImplemented('Sound.close'); }, extract: function extract(target, length, startPosition) { notImplemented('Sound.extract'); }, _load: function _load(request, checkPolicyFile, bufferTime) { @@ -45511,20 +44043,20 @@ var SoundDefinition = function () { } if (mp3DecodingSession) { mp3DecodingSession.close(); } }); stream.load(request); }, loadCompressedDataFromByteArray: function loadCompressedDataFromByteArray(bytes, bytesLength) { - throw 'Not implemented: loadCompressedDataFromByteArray'; + notImplemented('Sound#loadCompressedDataFromByteArray'); }, loadPCMFromByteArray: function loadPCMFromByteArray(bytes, samples, format, stereo, sampleRate) { - throw 'Not implemented: loadPCMFromByteArray'; + notImplemented('Sound#loadPCMFromByteArray'); }, play: function play(startTime, loops, soundTransform) { startTime = startTime || 0; loops = loops || 0; var channel = new flash.media.SoundChannel(); channel._sound = this; channel._soundTransform = isNullOrUndefined(soundTransform) ? new flash.media.SoundTransform() : soundTransform; this._playQueue.push({ @@ -45544,20 +44076,20 @@ var SoundDefinition = function () { }, get bytesTotal() { return this._bytesTotal; }, get id3() { return this._id3; }, get isBuffering() { - throw 'Not implemented: isBuffering'; + notImplemented('Sound#isBuffering'); }, get isURLInaccessible() { - throw 'Not implemented: isURLInaccessible'; + notImplemented('Sound#isURLInaccessible'); }, get length() { return this._length; }, get url() { return this._url; } }; @@ -46203,16 +44735,20 @@ var StageVideoDefinition = function () { } } } }; }.call(this); var VideoDefinition = function () { var def = { initialize: function initialize() { + TelemetryService.reportTelemetry({ + topic: 'feature', + feature: VIDEO_FEATURE + }); }, attachNetStream: function (netStream) { this._netStream = netStream; netStream._videoReady.then(function (element) { this._element = element; netStream._videoMetadataReady.then(function (url) { this._element.width = this._videoWidth = this._element.videoWidth; this._element.height = this._videoHeight = this._element.videoHeight; @@ -46251,26 +44787,26 @@ var VideoDefinition = function () { if (width > 0 && height > 0) { ctx.save(); ctx.beginPath(); ctx.rect(0, 0, width, height); ctx.clip(); ctx.clearRect(0, 0, width, height); ctx.restore(); } - var matrix = ctx.currentTransform; + var matrix = this._getConcatenatedTransform(true); var sx = width / this._videoWidth; var sy = height / this._videoHeight; var scaleFactor = this.stage && this.stage._contentsScaleFactor || 1; var a = sx * matrix.a / scaleFactor; var b = sx * matrix.b / scaleFactor; var c = sy * matrix.c / scaleFactor; var d = sy * matrix.d / scaleFactor; - var e = matrix.e / scaleFactor; - var f = matrix.f / scaleFactor; + var e = matrix.tx / 20 / scaleFactor; + var f = matrix.ty / 20 / scaleFactor; var cssTransform = 'transform: matrix(' + a + ',' + b + ',' + c + ',' + d + ',' + e + ',' + f + ');'; if (this._currentCssTransform !== cssTransform) { this._currentCssTransform = cssTransform; this._element.setAttribute('style', 'position: absolute; top:0; left:0; z-index: -100;transform-origin: 0px 0px 0;' + cssTransform + '-webkit-transform-origin: 0px 0px 0; -webkit-' + cssTransform); } } }; def.__glue__ = { @@ -46360,16 +44896,20 @@ var VideoDefinition = function () { } }; }.call(this); } var NetConnectionDefinition = function () { return { __class__: 'flash.net.NetConnection', initialize: function () { + TelemetryService.reportTelemetry({ + topic: 'feature', + feature: NETCONNECTION_FEATURE + }); }, _invoke: function (index, args) { var simulated = false, result; switch (index) { case 2: simulated = true; break; } @@ -46976,16 +45516,20 @@ var SharedObjectDefinition = function () } return { __class__: 'flash.net.SharedObject', initialize: function () { this._data = {}; this._objectEncoding = _defaultObjectEncoding; this._data[Multiname.getPublicQualifiedName('levelCompleted')] = 32; this._data[Multiname.getPublicQualifiedName('completeLevels')] = 32; + TelemetryService.reportTelemetry({ + topic: 'feature', + feature: SHAREDOBJECT_FEATURE + }); }, __glue__: { native: { static: { deleteAll: function deleteAll(url) { notImplemented('SharedObject.deleteAll'); }, getDiskUsage: function getDiskUsage(url) { @@ -47241,17 +45785,17 @@ var URLStreamDefinition = function () { self._stream = new Stream(new ArrayBuffer(0), 0, 0, 0); } self._dispatchEvent(new flash.events.Event('complete', false, false)); }; session.open(request._toFileRequest()); this._session = session; }, readBoolean: function readBoolean() { - throw 'Not implemented: URLStream.readBoolean'; + notImplemented('URLStream.readBoolean'); }, readByte: function readByte() { var stream = this._stream; stream.ensure(1); return stream.bytes[stream.pos++]; }, readBytes: function readBytes(bytes, offset, length) { if (length < 0) @@ -47260,50 +45804,50 @@ var URLStreamDefinition = function () { if (!length) length = stream.remaining(); else stream.ensure(length); bytes.writeRawBytes(stream.bytes.subarray(stream.pos, stream.pos + length), offset, length); stream.pos += length; }, readDouble: function readDouble() { - throw 'Not implemented: URLStream.readDouble'; + notImplemented('URLStream.readDouble'); }, readFloat: function readFloat() { - throw 'Not implemented: URLStream.readFloat'; + notImplemented('URLStream.readFloat'); }, readInt: function readInt() { - throw 'Not implemented: URLStream.readInt'; + notImplemented('URLStream.readInt'); }, readMultiByte: function readMultiByte(length, charSet) { - throw 'Not implemented: URLStream.readMultiByte'; + notImplemented('URLStream.readMultiByte'); }, readObject: function readObject() { - throw 'Not implemented: URLStream.readObject'; + notImplemented('URLStream.readObject'); }, readShort: function readShort() { - throw 'Not implemented: URLStream.readShort'; + notImplemented('URLStream.readShort'); }, readUTF: function readUTF() { return this.readUTFBytes(this.readUnsignedShort()); }, readUTFBytes: function readUTFBytes(length) { if (length < 0) throw 'Invalid length argument'; var stream = this._stream; stream.ensure(length); var str = utf8encode(stream.bytes.subarray(stream.pos, stream.pos + length)); stream.pos += length; return str; }, readUnsignedByte: function readUnsignedByte() { - throw 'Not implemented: URLStream.readUnsignedByte'; + notImplemented('URLStream.readUnsignedByte'); }, readUnsignedInt: function readUnsignedInt() { - throw 'Not implemented: URLStream.readUnsignedInt'; + notImplemented('URLStream.readUnsignedInt'); }, readUnsignedShort: function readUnsignedShort() { var stream = this._stream; stream.ensure(2); var result = stream.getUint16(stream.pos, this._littleEndian); stream.pos += 2; return result; }, @@ -47315,20 +45859,20 @@ var URLStreamDefinition = function () { }, get endian() { return this._littleEndian ? 'littleEndian' : 'bigEndian'; }, set endian(val) { this._littleEndian = val == 'littleEndian'; }, get objectEncoding() { - throw 'Not implemented: URLStream.objectEncoding$get'; + notImplemented('URLStream.objectEncoding'); }, set objectEncoding(val) { - throw 'Not implemented: URLStream.objectEncoding$set'; + notImplemented('URLStream.objectEncoding'); } }; var desc = Object.getOwnPropertyDescriptor; def.__glue__ = { native: { instance: { close: def.close, load: def.load, @@ -47617,16 +46161,20 @@ var SystemDefinition = function () { __class__: 'flash.system.System', initialize: function () { }, __glue__: { native: { static: { setClipboard: function setClipboard(string) { FirefoxCom.request('setClipboard', string); + TelemetryService.reportTelemetry({ + topic: 'feature', + feature: CLIPBOARD_FEATURE + }); }, pause: function pause() { notImplemented('System.pause'); }, resume: function resume() { notImplemented('System.resume'); }, exit: function exit(code) { @@ -47686,71 +46234,3147 @@ var SystemDefinition = function () { instance: {} } } }; }.call(this); { var FontDefinition = function () { var fonts = []; + var fontsByUniqueName = Object.create(null); + var fontsByNameStyleType = Object.create(null); + var _deviceFontMetrics; var def = { __class__: 'flash.text.Font', initialize: function () { var s = this.symbol; if (s) { this._fontName = s.name || null; this._uniqueName = s.uniqueName; - this._metrics = s.metrics; + if (s.bold) { + if (s.italic) { + this._fontStyle = 'boldItalic'; + } else { + this._fontStyle = 'bold'; + } + } else if (s.italic) { + this._fontStyle = 'italic'; + } else { + this._fontStyle = 'regular'; + } + var metrics = s.metrics; + metrics.height = metrics.ascent + metrics.descent + metrics.leading; + this._metrics = metrics; + this._fontType = 'embedded'; fonts.push(this); + fontsByUniqueName[this._uniqueName] = this; + var ident = this._fontName.toLowerCase() + '_' + this._fontStyle + '_embedded'; + fontsByNameStyleType[ident] = this; } }, get fontName() { return this._fontName; }, get fontStyle() { return this._fontStyle; }, get fontType() { return this._fontType; }, hasGlyphs: function hasGlyphs(str) { return true; + }, + getFont: function (name, style, embedded) { + var ident = name.toLowerCase() + '_' + style + (embedded ? '_embedded' : '_device'); + var font = fontsByNameStyleType[ident]; + if (font) { + return font; + } + font = new flash.text.Font(); + font._fontName = font._uniqueName = name; + font._fontStyle = style; + font._fontType = 'device'; + var metrics = deviceFontMetrics()[name]; + if (!metrics) { + metrics = deviceFontMetrics().serif; + font._fontName = font._uniqueName = 'serif'; + } + font._metrics = { + ascent: metrics[0], + descent: metrics[1], + leading: metrics[2] + }; + font._metrics.height = metrics[0] + metrics[1] + metrics[2]; + fontsByNameStyleType[ident] = font; + return font; + }, + getFontByUniqueName: function (name) { + return fontsByUniqueName[name]; } }; function enumerateFonts(device) { return fonts.slice(); } function registerFont(font) { - throw 'Not implemented: registerFont'; - } - function findFont(fn) { - var font; - fonts.some(function (f) { - return fn(f) && (font = f, true); - }); - return font; + somewhatImplemented('Font.registerFont'); + } + function deviceFontMetrics() { + if (_deviceFontMetrics) { + return _deviceFontMetrics; + } + var userAgent = window.navigator.userAgent; + if (userAgent.indexOf('Windows') > -1) { + _deviceFontMetrics = DEVICE_FONT_METRICS_WIN; + } else if (/(Macintosh|iPad|iPhone|iPod|Android)/.test(userAgent)) { + _deviceFontMetrics = DEVICE_FONT_METRICS_MAC; + } else { + _deviceFontMetrics = DEVICE_FONT_METRICS_LINUX; + } + return _deviceFontMetrics; } var desc = Object.getOwnPropertyDescriptor; def.__glue__ = { native: { instance: { fontName: desc(def, 'fontName'), fontStyle: desc(def, 'fontStyle'), fontType: desc(def, 'fontType'), hasGlyphs: def.hasGlyphs }, static: { enumerateFonts: enumerateFonts, - registerFont: registerFont, - _findFont: findFont + registerFont: registerFont } } }; return def; }.call(this); + var DEVICE_FONT_METRICS_WIN = { + 'serif': [ + 1, + 0.25, + 0 + ], + 'sans-serif': [ + 1, + 0.25, + 0 + ], + 'monospace': [ + 1, + 0.25, + 0 + ], + 'birch std': [ + 0.9167, + 0.25, + 0 + ], + 'blackoak std': [ + 1, + 0.3333, + 0 + ], + 'chaparral pro': [ + 0.8333, + 0.3333, + 0 + ], + 'chaparral pro light': [ + 0.8333, + 0.3333, + 0 + ], + 'charlemagne std': [ + 0.9167, + 0.25, + 0 + ], + 'cooper std black': [ + 0.9167, + 0.25, + 0 + ], + 'giddyup std': [ + 0.8333, + 0.3333, + 0 + ], + 'hobo std': [ + 1.0833, + 0.3333, + 0 + ], + 'kozuka gothic pro b': [ + 1, + 0.4167, + 0 + ], + 'kozuka gothic pro el': [ + 1.0833, + 0.25, + 0 + ], + 'kozuka gothic pro h': [ + 1, + 0.4167, + 0 + ], + 'kozuka gothic pro l': [ + 1, + 0.3333, + 0 + ], + 'kozuka gothic pro m': [ + 1.0833, + 0.3333, + 0 + ], + 'kozuka gothic pro r': [ + 1, + 0.3333, + 0 + ], + 'kozuka mincho pro b': [ + 1.0833, + 0.25, + 0 + ], + 'kozuka mincho pro el': [ + 1.0833, + 0.25, + 0 + ], + 'kozuka mincho pro h': [ + 1.1667, + 0.25, + 0 + ], + 'kozuka mincho pro l': [ + 1.0833, + 0.25, + 0 + ], + 'kozuka mincho pro m': [ + 1.0833, + 0.25, + 0 + ], + 'kozuka mincho pro r': [ + 1.0833, + 0.25, + 0 + ], + 'mesquite std': [ + 0.9167, + 0.25, + 0 + ], + 'minion pro cond': [ + 1, + 0.3333, + 0 + ], + 'minion pro med': [ + 1, + 0.3333, + 0 + ], + 'minion pro smbd': [ + 1, + 0.3333, + 0 + ], + 'myriad arabic': [ + 1, + 0.4167, + 0 + ], + 'nueva std': [ + 0.75, + 0.25, + 0 + ], + 'nueva std cond': [ + 0.75, + 0.25, + 0 + ], + 'ocr a std': [ + 0.8333, + 0.25, + 0 + ], + 'orator std': [ + 1.0833, + 0.25, + 0 + ], + 'poplar std': [ + 0.9167, + 0.25, + 0 + ], + 'prestige elite std': [ + 0.9167, + 0.25, + 0 + ], + 'rosewood std regular': [ + 0.8333, + 0.3333, + 0 + ], + 'stencil std': [ + 1, + 0.3333, + 0 + ], + 'trajan pro': [ + 1, + 0.25, + 0 + ], + 'kozuka gothic pr6n b': [ + 1.4167, + 0.4167, + 0 + ], + 'kozuka gothic pr6n el': [ + 1.4167, + 0.3333, + 0 + ], + 'kozuka gothic pr6n h': [ + 1.4167, + 0.4167, + 0 + ], + 'kozuka gothic pr6n l': [ + 1.4167, + 0.3333, + 0 + ], + 'kozuka gothic pr6n m': [ + 1.5, + 0.3333, + 0 + ], + 'kozuka gothic pr6n r': [ + 1.4167, + 0.3333, + 0 + ], + 'kozuka mincho pr6n b': [ + 1.3333, + 0.3333, + 0 + ], + 'kozuka mincho pr6n el': [ + 1.3333, + 0.3333, + 0 + ], + 'kozuka mincho pr6n h': [ + 1.4167, + 0.3333, + 0 + ], + 'kozuka mincho pr6n l': [ + 1.3333, + 0.3333, + 0 + ], + 'kozuka mincho pr6n m': [ + 1.3333, + 0.3333, + 0 + ], + 'kozuka mincho pr6n r': [ + 1.3333, + 0.3333, + 0 + ], + 'letter gothic std': [ + 1, + 0.25, + 0 + ], + 'minion pro': [ + 1, + 0.3333, + 0 + ], + 'myriad hebrew': [ + 0.8333, + 0.3333, + 0 + ], + 'myriad pro': [ + 0.9167, + 0.25, + 0 + ], + 'myriad pro cond': [ + 0.9167, + 0.25, + 0 + ], + 'myriad pro light': [ + 1, + 0.25, + 0 + ], + 'marlett': [ + 1, + 0, + 0 + ], + 'arial': [ + 1, + 0.25, + 0 + ], + 'arabic transparent': [ + 1, + 0.25, + 0 + ], + 'arial baltic': [ + 1, + 0.25, + 0 + ], + 'arial ce': [ + 1, + 0.25, + 0 + ], + 'arial cyr': [ + 1, + 0.25, + 0 + ], + 'arial greek': [ + 1, + 0.25, + 0 + ], + 'arial tur': [ + 1, + 0.25, + 0 + ], + 'batang': [ + 0.8333, + 0.1667, + 0 + ], + 'batangche': [ + 0.8333, + 0.1667, + 0 + ], + 'gungsuh': [ + 0.8333, + 0.1667, + 0 + ], + 'gungsuhche': [ + 0.8333, + 0.1667, + 0 + ], + 'courier new': [ + 1, + 0.25, + 0 + ], + 'courier new baltic': [ + 1, + 0.25, + 0 + ], + 'courier new ce': [ + 1, + 0.25, + 0 + ], + 'courier new cyr': [ + 1, + 0.25, + 0 + ], + 'courier new greek': [ + 1, + 0.25, + 0 + ], + 'courier new tur': [ + 1, + 0.25, + 0 + ], + 'daunpenh': [ + 0.6667, + 0.6667, + 0 + ], + 'dokchampa': [ + 1.4167, + 0.5833, + 0 + ], + 'estrangelo edessa': [ + 0.75, + 0.3333, + 0 + ], + 'euphemia': [ + 1.0833, + 0.3333, + 0 + ], + 'gautami': [ + 1.1667, + 0.8333, + 0 + ], + 'vani': [ + 1.0833, + 0.75, + 0 + ], + 'gulim': [ + 0.8333, + 0.1667, + 0 + ], + 'gulimche': [ + 0.8333, + 0.1667, + 0 + ], + 'dotum': [ + 0.8333, + 0.1667, + 0 + ], + 'dotumche': [ + 0.8333, + 0.1667, + 0 + ], + 'impact': [ + 1.0833, + 0.25, + 0 + ], + 'iskoola pota': [ + 1, + 0.3333, + 0 + ], + 'kalinga': [ + 1.0833, + 0.5, + 0 + ], + 'kartika': [ + 1, + 0.4167, + 0 + ], + 'khmer ui': [ + 1.0833, + 0.3333, + 0 + ], + 'lao ui': [ + 1, + 0.25, + 0 + ], + 'latha': [ + 1.0833, + 0.4167, + 0 + ], + 'lucida console': [ + 0.75, + 0.25, + 0 + ], + 'malgun gothic': [ + 1, + 0.25, + 0 + ], + 'mangal': [ + 1.0833, + 0.3333, + 0 + ], + 'meiryo': [ + 1.0833, + 0.4167, + 0 + ], + 'meiryo ui': [ + 1, + 0.25, + 0 + ], + 'microsoft himalaya': [ + 0.5833, + 0.4167, + 0 + ], + 'microsoft jhenghei': [ + 1, + 0.3333, + 0 + ], + 'microsoft yahei': [ + 1.0833, + 0.3333, + 0 + ], + 'mingliu': [ + 0.8333, + 0.1667, + 0 + ], + 'pmingliu': [ + 0.8333, + 0.1667, + 0 + ], + 'mingliu_hkscs': [ + 0.8333, + 0.1667, + 0 + ], + 'mingliu-extb': [ + 0.8333, + 0.1667, + 0 + ], + 'pmingliu-extb': [ + 0.8333, + 0.1667, + 0 + ], + 'mingliu_hkscs-extb': [ + 0.8333, + 0.1667, + 0 + ], + 'mongolian baiti': [ + 0.8333, + 0.25, + 0 + ], + 'ms gothic': [ + 0.8333, + 0.1667, + 0 + ], + 'ms pgothic': [ + 0.8333, + 0.1667, + 0 + ], + 'ms ui gothic': [ + 0.8333, + 0.1667, + 0 + ], + 'ms mincho': [ + 0.8333, + 0.1667, + 0 + ], + 'ms pmincho': [ + 0.8333, + 0.1667, + 0 + ], + 'mv boli': [ + 1.1667, + 0.25, + 0 + ], + 'microsoft new tai lue': [ + 1, + 0.4167, + 0 + ], + 'nyala': [ + 0.9167, + 0.3333, + 0 + ], + 'microsoft phagspa': [ + 1.0833, + 0.25, + 0 + ], + 'plantagenet cherokee': [ + 1, + 0.4167, + 0 + ], + 'raavi': [ + 1.0833, + 0.6667, + 0 + ], + 'segoe script': [ + 1.0833, + 0.5, + 0 + ], + 'segoe ui': [ + 1, + 0.25, + 0 + ], + 'segoe ui semibold': [ + 1, + 0.25, + 0 + ], + 'segoe ui light': [ + 1, + 0.25, + 0 + ], + 'segoe ui symbol': [ + 1, + 0.25, + 0 + ], + 'shruti': [ + 1.0833, + 0.5, + 0 + ], + 'simsun': [ + 0.8333, + 0.1667, + 0 + ], + 'nsimsun': [ + 0.8333, + 0.1667, + 0 + ], + 'simsun-extb': [ + 0.8333, + 0.1667, + 0 + ], + 'sylfaen': [ + 1, + 0.3333, + 0 + ], + 'microsoft tai le': [ + 1, + 0.3333, + 0 + ], + 'times new roman': [ + 1, + 0.25, + 0 + ], + 'times new roman baltic': [ + 1, + 0.25, + 0 + ], + 'times new roman ce': [ + 1, + 0.25, + 0 + ], + 'times new roman cyr': [ + 1, + 0.25, + 0 + ], + 'times new roman greek': [ + 1, + 0.25, + 0 + ], + 'times new roman tur': [ + 1, + 0.25, + 0 + ], + 'tunga': [ + 1.0833, + 0.75, + 0 + ], + 'vrinda': [ + 1, + 0.4167, + 0 + ], + 'shonar bangla': [ + 0.8333, + 0.5, + 0 + ], + 'microsoft yi baiti': [ + 0.8333, + 0.1667, + 0 + ], + 'tahoma': [ + 1, + 0.1667, + 0 + ], + 'microsoft sans serif': [ + 1.0833, + 0.1667, + 0 + ], + 'angsana new': [ + 0.9167, + 0.4167, + 0 + ], + 'aparajita': [ + 0.75, + 0.4167, + 0 + ], + 'cordia new': [ + 0.9167, + 0.5, + 0 + ], + 'ebrima': [ + 1.0833, + 0.5, + 0 + ], + 'gisha': [ + 0.9167, + 0.25, + 0 + ], + 'kokila': [ + 0.8333, + 0.3333, + 0 + ], + 'leelawadee': [ + 0.9167, + 0.25, + 0 + ], + 'microsoft uighur': [ + 1.0833, + 0.5, + 0 + ], + 'moolboran': [ + 0.6667, + 0.6667, + 0 + ], + 'symbol': [ + 1, + 0.25, + 0 + ], + 'utsaah': [ + 0.8333, + 0.4167, + 0 + ], + 'vijaya': [ + 1.0833, + 0.25, + 0 + ], + 'wingdings': [ + 0.9167, + 0.25, + 0 + ], + 'andalus': [ + 1.3333, + 0.4167, + 0 + ], + 'arabic typesetting': [ + 0.8333, + 0.5, + 0 + ], + 'simplified arabic': [ + 1.3333, + 0.5, + 0 + ], + 'simplified arabic fixed': [ + 1, + 0.4167, + 0 + ], + 'sakkal majalla': [ + 0.9167, + 0.5, + 0 + ], + 'traditional arabic': [ + 1.3333, + 0.5, + 0 + ], + 'aharoni': [ + 0.75, + 0.25, + 0 + ], + 'david': [ + 0.75, + 0.25, + 0 + ], + 'frankruehl': [ + 0.75, + 0.25, + 0 + ], + 'fangsong': [ + 0.8333, + 0.1667, + 0 + ], + 'simhei': [ + 0.8333, + 0.1667, + 0 + ], + 'kaiti': [ + 0.8333, + 0.1667, + 0 + ], + 'browallia new': [ + 0.8333, + 0.4167, + 0 + ], + 'lucida sans unicode': [ + 1.0833, + 0.25, + 0 + ], + 'arial black': [ + 1.0833, + 0.3333, + 0 + ], + 'calibri': [ + 0.9167, + 0.25, + 0 + ], + 'cambria': [ + 0.9167, + 0.25, + 0 + ], + 'cambria math': [ + 3.0833, + 2.5, + 0 + ], + 'candara': [ + 0.9167, + 0.25, + 0 + ], + 'comic sans ms': [ + 1.0833, + 0.3333, + 0 + ], + 'consolas': [ + 0.9167, + 0.25, + 0 + ], + 'constantia': [ + 0.9167, + 0.25, + 0 + ], + 'corbel': [ + 0.9167, + 0.25, + 0 + ], + 'franklin gothic medium': [ + 1, + 0.3333, + 0 + ], + 'gabriola': [ + 1.1667, + 0.6667, + 0 + ], + 'georgia': [ + 1, + 0.25, + 0 + ], + 'palatino linotype': [ + 1.0833, + 0.3333, + 0 + ], + 'segoe print': [ + 1.25, + 0.5, + 0 + ], + 'trebuchet ms': [ + 1.0833, + 0.4167, + 0 + ], + 'verdana': [ + 1, + 0.1667, + 0 + ], + 'webdings': [ + 1.0833, + 0.5, + 0 + ], + 'lucida bright': [ + 0.9167, + 0.25, + 0 + ], + 'lucida sans': [ + 0.9167, + 0.25, + 0 + ], + 'lucida sans typewriter': [ + 0.9167, + 0.25, + 0 + ], + 'gentium basic': [ + 0.8333, + 0.25, + 0 + ], + 'dejavu serif condensed': [ + 0.9167, + 0.25, + 0 + ], + 'arimo': [ + 1, + 0.25, + 0 + ], + 'dejavu sans condensed': [ + 0.9167, + 0.25, + 0 + ], + 'dejavu sans': [ + 0.9167, + 0.25, + 0 + ], + 'dejavu sans light': [ + 0.9167, + 0.25, + 0 + ], + 'opensymbol': [ + 0.8333, + 0.1667, + 0 + ], + 'gentium book basic': [ + 0.8333, + 0.25, + 0 + ], + 'dejavu sans mono': [ + 0.9167, + 0.25, + 0 + ], + 'dejavu serif': [ + 0.9167, + 0.25, + 0 + ], + 'calibri light': [ + 0.9167, + 0.25, + 0 + ] + }; + var DEVICE_FONT_METRICS_MAC = { + 'al bayan plain': [ + 1, + 0.5, + 0 + ], + 'al bayan bold': [ + 1, + 0.5833, + 0 + ], + 'american typewriter': [ + 0.9167, + 0.25, + 0 + ], + 'american typewriter bold': [ + 0.9167, + 0.25, + 0 + ], + 'american typewriter condensed': [ + 0.9167, + 0.25, + 0 + ], + 'american typewriter condensed bold': [ + 0.9167, + 0.25, + 0 + ], + 'american typewriter condensed light': [ + 0.8333, + 0.25, + 0 + ], + 'american typewriter light': [ + 0.9167, + 0.25, + 0 + ], + 'andale mono': [ + 0.9167, + 0.25, + 0 + ], + 'apple symbols': [ + 0.6667, + 0.25, + 0 + ], + 'arial bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'arial bold': [ + 0.9167, + 0.25, + 0 + ], + 'arial italic': [ + 0.9167, + 0.25, + 0 + ], + 'arial hebrew': [ + 0.75, + 0.3333, + 0 + ], + 'arial hebrew bold': [ + 0.75, + 0.3333, + 0 + ], + 'arial': [ + 0.9167, + 0.25, + 0 + ], + 'arial narrow': [ + 0.9167, + 0.25, + 0 + ], + 'arial narrow bold': [ + 0.9167, + 0.25, + 0 + ], + 'arial narrow bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'arial narrow italic': [ + 0.9167, + 0.25, + 0 + ], + 'arial rounded mt bold': [ + 0.9167, + 0.25, + 0 + ], + 'arial unicode ms': [ + 1.0833, + 0.25, + 0 + ], + 'avenir black': [ + 1, + 0.3333, + 0 + ], + 'avenir black oblique': [ + 1, + 0.3333, + 0 + ], + 'avenir book': [ + 1, + 0.3333, + 0 + ], + 'avenir book oblique': [ + 1, + 0.3333, + 0 + ], + 'avenir heavy': [ + 1, + 0.3333, + 0 + ], + 'avenir heavy oblique': [ + 1, + 0.3333, + 0 + ], + 'avenir light': [ + 1, + 0.3333, + 0 + ], + 'avenir light oblique': [ + 1, + 0.3333, + 0 + ], + 'avenir medium': [ + 1, + 0.3333, + 0 + ], + 'avenir medium oblique': [ + 1, + 0.3333, + 0 + ], + 'avenir oblique': [ + 1, + 0.3333, + 0 + ], + 'avenir roman': [ + 1, + 0.3333, + 0 + ], + 'avenir next bold': [ + 1, + 0.3333, + 0 + ], + 'avenir next bold italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next demi bold': [ + 1, + 0.3333, + 0 + ], + 'avenir next demi bold italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next heavy': [ + 1, + 0.3333, + 0 + ], + 'avenir next heavy italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next medium': [ + 1, + 0.3333, + 0 + ], + 'avenir next medium italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next regular': [ + 1, + 0.3333, + 0 + ], + 'avenir next ultra light': [ + 1, + 0.3333, + 0 + ], + 'avenir next ultra light italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed bold': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed bold italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed demi bold': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed demi bold italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed heavy': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed heavy italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed medium': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed medium italic': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed regular': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed ultra light': [ + 1, + 0.3333, + 0 + ], + 'avenir next condensed ultra light italic': [ + 1, + 0.3333, + 0 + ], + 'ayuthaya': [ + 1.0833, + 0.3333, + 0 + ], + 'baghdad': [ + 0.9167, + 0.4167, + 0 + ], + 'bangla mn': [ + 0.9167, + 0.6667, + 0 + ], + 'bangla mn bold': [ + 0.9167, + 0.6667, + 0 + ], + 'bangla sangam mn': [ + 0.9167, + 0.4167, + 0 + ], + 'bangla sangam mn bold': [ + 0.9167, + 0.4167, + 0 + ], + 'baskerville': [ + 0.9167, + 0.25, + 0 + ], + 'baskerville bold': [ + 0.9167, + 0.25, + 0 + ], + 'baskerville bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'baskerville italic': [ + 0.9167, + 0.25, + 0 + ], + 'baskerville semibold': [ + 0.9167, + 0.25, + 0 + ], + 'baskerville semibold italic': [ + 0.9167, + 0.25, + 0 + ], + 'big caslon medium': [ + 0.9167, + 0.25, + 0 + ], + 'brush script mt italic': [ + 0.9167, + 0.3333, + 0 + ], + 'chalkboard': [ + 1, + 0.25, + 0 + ], + 'chalkboard bold': [ + 1, + 0.25, + 0 + ], + 'chalkboard se bold': [ + 1.1667, + 0.25, + 0 + ], + 'chalkboard se light': [ + 1.1667, + 0.25, + 0 + ], + 'chalkboard se regular': [ + 1.1667, + 0.25, + 0 + ], + 'chalkduster': [ + 1, + 0.25, + 0 + ], + 'charcoal cy': [ + 1, + 0.25, + 0 + ], + 'cochin': [ + 0.9167, + 0.25, + 0 + ], + 'cochin bold': [ + 0.9167, + 0.25, + 0 + ], + 'cochin bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'cochin italic': [ + 0.9167, + 0.25, + 0 + ], + 'comic sans ms': [ + 1.0833, + 0.25, + 0 + ], + 'comic sans ms bold': [ + 1.0833, + 0.25, + 0 + ], + 'copperplate': [ + 0.75, + 0.25, + 0 + ], + 'copperplate bold': [ + 0.75, + 0.25, + 0 + ], + 'copperplate light': [ + 0.75, + 0.25, + 0 + ], + 'corsiva hebrew': [ + 0.6667, + 0.3333, + 0 + ], + 'corsiva hebrew bold': [ + 0.6667, + 0.3333, + 0 + ], + 'courier': [ + 0.75, + 0.25, + 0 + ], + 'courier bold': [ + 0.75, + 0.25, + 0 + ], + 'courier bold oblique': [ + 0.75, + 0.25, + 0 + ], + 'courier oblique': [ + 0.75, + 0.25, + 0 + ], + 'courier new bold italic': [ + 0.8333, + 0.3333, + 0 + ], + 'courier new bold': [ + 0.8333, + 0.3333, + 0 + ], + 'courier new italic': [ + 0.8333, + 0.3333, + 0 + ], + 'courier new': [ + 0.8333, + 0.3333, + 0 + ], + 'biaukai': [ + 0.8333, + 0.1667, + 0 + ], + 'damascus': [ + 0.5833, + 0.4167, + 0 + ], + 'damascus bold': [ + 0.5833, + 0.4167, + 0 + ], + 'decotype naskh': [ + 1.1667, + 0.6667, + 0 + ], + 'devanagari mt': [ + 0.9167, + 0.6667, + 0 + ], + 'devanagari mt bold': [ + 0.9167, + 0.6667, + 0 + ], + 'devanagari sangam mn': [ + 0.9167, + 0.4167, + 0 + ], + 'devanagari sangam mn bold': [ + 0.9167, + 0.4167, + 0 + ], + 'didot': [ + 0.9167, + 0.3333, + 0 + ], + 'didot bold': [ + 1, + 0.3333, + 0 + ], + 'didot italic': [ + 0.9167, + 0.25, + 0 + ], + 'euphemia ucas': [ + 1.0833, + 0.25, + 0 + ], + 'euphemia ucas bold': [ + 1.0833, + 0.25, + 0 + ], + 'euphemia ucas italic': [ + 1.0833, + 0.25, + 0 + ], + 'futura condensed extrabold': [ + 1, + 0.25, + 0 + ], + 'futura condensed medium': [ + 1, + 0.25, + 0 + ], + 'futura medium': [ + 1, + 0.25, + 0 + ], + 'futura medium italic': [ + 1, + 0.25, + 0 + ], + 'gb18030 bitmap': [ + 1, + 0.6667, + 0 + ], + 'geeza pro': [ + 0.9167, + 0.3333, + 0 + ], + 'geeza pro bold': [ + 0.9167, + 0.3333, + 0 + ], + 'geneva': [ + 1, + 0.25, + 0 + ], + 'geneva cy': [ + 1, + 0.25, + 0 + ], + 'georgia': [ + 0.9167, + 0.25, + 0 + ], + 'georgia bold': [ + 0.9167, + 0.25, + 0 + ], + 'georgia bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'georgia italic': [ + 0.9167, + 0.25, + 0 + ], + 'gill sans': [ + 0.9167, + 0.25, + 0 + ], + 'gill sans bold': [ + 0.9167, + 0.25, + 0 + ], + 'gill sans bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'gill sans italic': [ + 0.9167, + 0.25, + 0 + ], + 'gill sans light': [ + 0.9167, + 0.25, + 0 + ], + 'gill sans light italic': [ + 0.9167, + 0.25, + 0 + ], + 'gujarati mt': [ + 0.9167, + 0.6667, + 0 + ], + 'gujarati mt bold': [ + 0.9167, + 0.6667, + 0 + ], + 'gujarati sangam mn': [ + 0.8333, + 0.4167, + 0 + ], + 'gujarati sangam mn bold': [ + 0.8333, + 0.4167, + 0 + ], + 'gurmukhi mn': [ + 0.9167, + 0.25, + 0 + ], + 'gurmukhi mn bold': [ + 0.9167, + 0.25, + 0 + ], + 'gurmukhi sangam mn': [ + 0.9167, + 0.3333, + 0 + ], + 'gurmukhi sangam mn bold': [ + 0.9167, + 0.3333, + 0 + ], + 'helvetica': [ + 0.75, + 0.25, + 0 + ], + 'helvetica bold': [ + 0.75, + 0.25, + 0 + ], + 'helvetica bold oblique': [ + 0.75, + 0.25, + 0 + ], + 'helvetica light': [ + 0.75, + 0.25, + 0 + ], + 'helvetica light oblique': [ + 0.75, + 0.25, + 0 + ], + 'helvetica oblique': [ + 0.75, + 0.25, + 0 + ], + 'helvetica neue': [ + 0.9167, + 0.25, + 0 + ], + 'helvetica neue bold': [ + 1, + 0.25, + 0 + ], + 'helvetica neue bold italic': [ + 1, + 0.25, + 0 + ], + 'helvetica neue condensed black': [ + 1, + 0.25, + 0 + ], + 'helvetica neue condensed bold': [ + 1, + 0.25, + 0 + ], + 'helvetica neue italic': [ + 0.9167, + 0.25, + 0 + ], + 'helvetica neue light': [ + 1, + 0.25, + 0 + ], + 'helvetica neue light italic': [ + 0.9167, + 0.25, + 0 + ], + 'helvetica neue medium': [ + 1, + 0.25, + 0 + ], + 'helvetica neue ultralight': [ + 0.9167, + 0.25, + 0 + ], + 'helvetica neue ultralight italic': [ + 0.9167, + 0.25, + 0 + ], + 'herculanum': [ + 0.8333, + 0.1667, + 0 + ], + 'hiragino kaku gothic pro w3': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino kaku gothic pro w6': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino kaku gothic pron w3': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino kaku gothic pron w6': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino kaku gothic std w8': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino kaku gothic stdn w8': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino maru gothic pro w4': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino maru gothic pron w4': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino mincho pro w3': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino mincho pro w6': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino mincho pron w3': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino mincho pron w6': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino sans gb w3': [ + 0.9167, + 0.0833, + 0 + ], + 'hiragino sans gb w6': [ + 0.9167, + 0.0833, + 0 + ], + 'hoefler text black': [ + 0.75, + 0.25, + 0 + ], + 'hoefler text black italic': [ + 0.75, + 0.25, + 0 + ], + 'hoefler text italic': [ + 0.75, + 0.25, + 0 + ], + 'hoefler text ornaments': [ + 0.8333, + 0.1667, + 0 + ], + 'hoefler text': [ + 0.75, + 0.25, + 0 + ], + 'impact': [ + 1, + 0.25, + 0 + ], + 'inaimathi': [ + 0.8333, + 0.4167, + 0 + ], + 'headlinea regular': [ + 0.8333, + 0.1667, + 0 + ], + 'pilgi regular': [ + 0.8333, + 0.25, + 0 + ], + 'gungseo regular': [ + 0.8333, + 0.25, + 0 + ], + 'pcmyungjo regular': [ + 0.8333, + 0.25, + 0 + ], + 'kailasa regular': [ + 1.0833, + 0.5833, + 0 + ], + 'kannada mn': [ + 0.9167, + 0.25, + 0 + ], + 'kannada mn bold': [ + 0.9167, + 0.25, + 0 + ], + 'kannada sangam mn': [ + 1, + 0.5833, + 0 + ], + 'kannada sangam mn bold': [ + 1, + 0.5833, + 0 + ], + 'kefa bold': [ + 0.9167, + 0.25, + 0 + ], + 'kefa regular': [ + 0.9167, + 0.25, + 0 + ], + 'khmer mn': [ + 1, + 0.6667, + 0 + ], + 'khmer mn bold': [ + 1, + 0.6667, + 0 + ], + 'khmer sangam mn': [ + 1.0833, + 0.6667, + 0 + ], + 'kokonor regular': [ + 1.0833, + 0.5833, + 0 + ], + 'krungthep': [ + 1, + 0.25, + 0 + ], + 'kufistandardgk': [ + 0.9167, + 0.5, + 0 + ], + 'lao mn': [ + 0.9167, + 0.4167, + 0 + ], + 'lao mn bold': [ + 0.9167, + 0.4167, + 0 + ], + 'lao sangam mn': [ + 1, + 0.3333, + 0 + ], + 'apple ligothic medium': [ + 0.8333, + 0.1667, + 0 + ], + 'lihei pro': [ + 0.8333, + 0.1667, + 0 + ], + 'lisong pro': [ + 0.8333, + 0.1667, + 0 + ], + 'lucida grande': [ + 1, + 0.25, + 0 + ], + 'lucida grande bold': [ + 1, + 0.25, + 0 + ], + 'malayalam mn': [ + 1, + 0.4167, + 0 + ], + 'malayalam mn bold': [ + 1, + 0.4167, + 0 + ], + 'malayalam sangam mn': [ + 0.8333, + 0.4167, + 0 + ], + 'malayalam sangam mn bold': [ + 0.8333, + 0.4167, + 0 + ], + 'marion bold': [ + 0.6667, + 0.3333, + 0 + ], + 'marion italic': [ + 0.6667, + 0.3333, + 0 + ], + 'marion regular': [ + 0.6667, + 0.3333, + 0 + ], + 'marker felt thin': [ + 0.8333, + 0.25, + 0 + ], + 'marker felt wide': [ + 0.9167, + 0.25, + 0 + ], + 'menlo bold': [ + 0.9167, + 0.25, + 0 + ], + 'menlo bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'menlo italic': [ + 0.9167, + 0.25, + 0 + ], + 'menlo regular': [ + 0.9167, + 0.25, + 0 + ], + 'microsoft sans serif': [ + 0.9167, + 0.25, + 0 + ], + 'monaco': [ + 1, + 0.25, + 0 + ], + 'gurmukhi mt': [ + 0.8333, + 0.4167, + 0 + ], + 'mshtakan': [ + 0.9167, + 0.25, + 0 + ], + 'mshtakan bold': [ + 0.9167, + 0.25, + 0 + ], + 'mshtakan boldoblique': [ + 0.9167, + 0.25, + 0 + ], + 'mshtakan oblique': [ + 0.9167, + 0.25, + 0 + ], + 'myanmar mn': [ + 1, + 0.4167, + 0 + ], + 'myanmar mn bold': [ + 1, + 0.4167, + 0 + ], + 'myanmar sangam mn': [ + 0.9167, + 0.4167, + 0 + ], + 'nadeem': [ + 0.9167, + 0.4167, + 0 + ], + 'nanum brush script': [ + 0.9167, + 0.25, + 0 + ], + 'nanumgothic': [ + 0.9167, + 0.25, + 0 + ], + 'nanumgothic bold': [ + 0.9167, + 0.25, + 0 + ], + 'nanumgothic extrabold': [ + 0.9167, + 0.25, + 0 + ], + 'nanummyeongjo': [ + 0.9167, + 0.25, + 0 + ], + 'nanummyeongjo bold': [ + 0.9167, + 0.25, + 0 + ], + 'nanummyeongjo extrabold': [ + 0.9167, + 0.25, + 0 + ], + 'nanum pen script': [ + 0.9167, + 0.25, + 0 + ], + 'optima bold': [ + 0.9167, + 0.25, + 0 + ], + 'optima bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'optima extrablack': [ + 1, + 0.25, + 0 + ], + 'optima italic': [ + 0.9167, + 0.25, + 0 + ], + 'optima regular': [ + 0.9167, + 0.25, + 0 + ], + 'oriya mn': [ + 0.9167, + 0.25, + 0 + ], + 'oriya mn bold': [ + 0.9167, + 0.25, + 0 + ], + 'oriya sangam mn': [ + 0.8333, + 0.4167, + 0 + ], + 'oriya sangam mn bold': [ + 0.8333, + 0.4167, + 0 + ], + 'osaka': [ + 1, + 0.25, + 0 + ], + 'osaka-mono': [ + 0.8333, + 0.1667, + 0 + ], + 'palatino bold': [ + 0.8333, + 0.25, + 0 + ], + 'palatino bold italic': [ + 0.8333, + 0.25, + 0 + ], + 'palatino italic': [ + 0.8333, + 0.25, + 0 + ], + 'palatino': [ + 0.8333, + 0.25, + 0 + ], + 'papyrus': [ + 0.9167, + 0.5833, + 0 + ], + 'papyrus condensed': [ + 0.9167, + 0.5833, + 0 + ], + 'plantagenet cherokee': [ + 0.6667, + 0.25, + 0 + ], + 'raanana': [ + 0.75, + 0.25, + 0 + ], + 'raanana bold': [ + 0.75, + 0.25, + 0 + ], + 'hei regular': [ + 0.8333, + 0.1667, + 0 + ], + 'kai regular': [ + 0.8333, + 0.1667, + 0 + ], + 'stfangsong': [ + 0.8333, + 0.1667, + 0 + ], + 'stheiti': [ + 0.8333, + 0.1667, + 0 + ], + 'heiti sc light': [ + 0.8333, + 0.1667, + 0 + ], + 'heiti sc medium': [ + 0.8333, + 0.1667, + 0 + ], + 'heiti tc light': [ + 0.8333, + 0.1667, + 0 + ], + 'heiti tc medium': [ + 0.8333, + 0.1667, + 0 + ], + 'stkaiti': [ + 0.8333, + 0.1667, + 0 + ], + 'kaiti sc black': [ + 1.0833, + 0.3333, + 0 + ], + 'kaiti sc bold': [ + 1.0833, + 0.3333, + 0 + ], + 'kaiti sc regular': [ + 1.0833, + 0.3333, + 0 + ], + 'stsong': [ + 0.8333, + 0.1667, + 0 + ], + 'songti sc black': [ + 1.0833, + 0.3333, + 0 + ], + 'songti sc bold': [ + 1.0833, + 0.3333, + 0 + ], + 'songti sc light': [ + 1.0833, + 0.3333, + 0 + ], + 'songti sc regular': [ + 1.0833, + 0.3333, + 0 + ], + 'stxihei': [ + 0.8333, + 0.1667, + 0 + ], + 'sathu': [ + 0.9167, + 0.3333, + 0 + ], + 'silom': [ + 1, + 0.3333, + 0 + ], + 'sinhala mn': [ + 0.9167, + 0.25, + 0 + ], + 'sinhala mn bold': [ + 0.9167, + 0.25, + 0 + ], + 'sinhala sangam mn': [ + 1.1667, + 0.3333, + 0 + ], + 'sinhala sangam mn bold': [ + 1.1667, + 0.3333, + 0 + ], + 'skia regular': [ + 0.75, + 0.25, + 0 + ], + 'symbol': [ + 0.6667, + 0.3333, + 0 + ], + 'tahoma negreta': [ + 1, + 0.1667, + 0 + ], + 'tamil mn': [ + 0.9167, + 0.25, + 0 + ], + 'tamil mn bold': [ + 0.9167, + 0.25, + 0 + ], + 'tamil sangam mn': [ + 0.75, + 0.25, + 0 + ], + 'tamil sangam mn bold': [ + 0.75, + 0.25, + 0 + ], + 'telugu mn': [ + 0.9167, + 0.25, + 0 + ], + 'telugu mn bold': [ + 0.9167, + 0.25, + 0 + ], + 'telugu sangam mn': [ + 1, + 0.5833, + 0 + ], + 'telugu sangam mn bold': [ + 1, + 0.5833, + 0 + ], + 'thonburi': [ + 1.0833, + 0.25, + 0 + ], + 'thonburi bold': [ + 1.0833, + 0.25, + 0 + ], + 'times bold': [ + 0.75, + 0.25, + 0 + ], + 'times bold italic': [ + 0.75, + 0.25, + 0 + ], + 'times italic': [ + 0.75, + 0.25, + 0 + ], + 'times roman': [ + 0.75, + 0.25, + 0 + ], + 'times new roman bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'times new roman bold': [ + 0.9167, + 0.25, + 0 + ], + 'times new roman italic': [ + 0.9167, + 0.25, + 0 + ], + 'times new roman': [ + 0.9167, + 0.25, + 0 + ], + 'trebuchet ms bold italic': [ + 0.9167, + 0.25, + 0 + ], + 'trebuchet ms': [ + 0.9167, + 0.25, + 0 + ], + 'trebuchet ms bold': [ + 0.9167, + 0.25, + 0 + ], + 'trebuchet ms italic': [ + 0.9167, + 0.25, + 0 + ], + 'verdana': [ + 1, + 0.25, + 0 + ], + 'verdana bold': [ + 1, + 0.25, + 0 + ], + 'verdana bold italic': [ + 1, + 0.25, + 0 + ], + 'verdana italic': [ + 1, + 0.25, + 0 + ], + 'webdings': [ + 0.8333, + 0.1667, + 0 + ], + 'wingdings 2': [ + 0.8333, + 0.25, + 0 + ], + 'wingdings 3': [ + 0.9167, + 0.25, + 0 + ], + 'yuppy sc regular': [ + 1.0833, + 0.3333, + 0 + ], + 'yuppy tc regular': [ + 1.0833, + 0.3333, + 0 + ], + 'zapf dingbats': [ + 0.8333, + 0.1667, + 0 + ], + 'zapfino': [ + 1.9167, + 1.5, + 0 + ] + }; + var DEVICE_FONT_METRICS_LINUX = { + 'kacstfarsi': [ + 1.0831, + 0.5215, + 0 + ], + 'meera': [ + 0.682, + 0.4413, + 0 + ], + 'freemono': [ + 0.8023, + 0.2006, + 0 + ], + 'undotum': [ + 1.0029, + 0.2808, + 0 + ], + 'loma': [ + 1.1634, + 0.4814, + 0 + ], + 'century schoolbook l': [ + 1.0029, + 0.3209, + 0 + ], + 'kacsttitlel': [ + 1.0831, + 0.5215,