author | Wes Kocher <wkocher@mozilla.com> |
Mon, 06 Feb 2017 17:52:26 -0800 | |
changeset 479884 | 330ab4695793c499110152a6582afca8e87ae46c |
parent 479883 | f3da0505833f946d1b1767986ebb8e3d7a63f5c1 (current diff) |
parent 479651 | af8a2573d0f1e9cc6f2ba0ab67d7a702a197f177 (diff) |
child 479885 | 270900fec93245a4c8e93df3e74be837735766d7 |
push id | 44393 |
push user | VYV03354@nifty.ne.jp |
push date | Tue, 07 Feb 2017 13:53:48 +0000 |
reviewers | merge |
milestone | 54.0a1 |
dom/base/nsContentUtils.cpp | file | annotate | diff | comparison | revisions | |
dom/base/nsContentUtils.h | file | annotate | diff | comparison | revisions | |
security/nss/coreconf/sanitizers.mk | file | annotate | diff | comparison | revisions |
--- a/.cron.yml +++ b/.cron.yml @@ -20,8 +20,18 @@ jobs: treeherder-symbol: Na triggered-by: nightly target-tasks-method: nightly_fennec run-on-projects: - mozilla-central - date when: [] # never (temporary) + - name: nightly-mochitest-valgrind + job: + type: decision-task + treeherder-symbol: Vg + target-tasks-method: mochitest_valgrind + run-on-projects: + - mozilla-central + when: + - {hour: 16, minute: 0} + - {hour: 4, minute: 0}
--- a/.eslintignore +++ b/.eslintignore @@ -110,17 +110,16 @@ devtools/server/actors/object.js devtools/server/actors/script.js devtools/server/actors/styleeditor.js devtools/server/actors/stylesheets.js devtools/server/tests/browser/** !devtools/server/tests/browser/browser_webextension_inspected_window.js devtools/server/tests/mochitest/** devtools/server/tests/unit/** devtools/shared/heapsnapshot/** -devtools/shared/transport/tests/unit/** devtools/shared/webconsole/test/** # Ignore devtools pre-processed files devtools/client/framework/toolbox-process-window.js devtools/client/performance/system.js devtools/client/webide/webide-prefs.js devtools/client/preferences/**
--- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -698,16 +698,17 @@ aria-label="&urlbar.viewSiteInfo.label;" onclick="gIdentityHandler.handleIdentityButtonEvent(event);" onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);" ondragstart="gIdentityHandler.onDragStart(event);"> <image id="identity-icon" consumeanchor="identity-box" onclick="PageProxyClickHandler(event);"/> <image id="sharing-icon" mousethrough="always"/> + <image id="tracking-protection-icon"/> <box id="blocked-permissions-container" align="center"> <image data-permission-id="geo" class="blocked-permission-icon geo-icon" role="button" tooltiptext="&urlbar.geolocationBlocked.tooltip;"/> <image data-permission-id="desktop-notification" class="blocked-permission-icon desktop-notification-icon" role="button" tooltiptext="&urlbar.webNotificationsBlocked.tooltip;"/> <image data-permission-id="camera" class="blocked-permission-icon camera-icon" role="button" tooltiptext="&urlbar.cameraBlocked.tooltip;"/> <image data-permission-id="indexedDB" class="blocked-permission-icon indexedDB-icon" role="button" @@ -746,17 +747,16 @@ tooltiptext="&urlbar.servicesNotificationAnchor.tooltip;"/> <image id="translate-notification-icon" class="notification-anchor-icon translation-icon" role="button" tooltiptext="&urlbar.translateNotificationAnchor.tooltip;"/> <image id="translated-notification-icon" class="notification-anchor-icon translation-icon in-use" role="button" tooltiptext="&urlbar.translatedNotificationAnchor.tooltip;"/> <image id="eme-notification-icon" class="notification-anchor-icon drm-icon" role="button" tooltiptext="&urlbar.emeNotificationAnchor.tooltip;"/> </box> - <image id="tracking-protection-icon"/> <image id="connection-icon"/> <hbox id="identity-icon-labels"> <label id="identity-icon-label" class="plain" flex="1"/> <label id="identity-icon-country-label" class="plain"/> </hbox> </box> <box id="urlbar-display-box" align="center"> <label id="switchtab" class="urlbar-display urlbar-display-switchtab" value="&urlbar.switchToTab.label;"/>
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js +++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js @@ -316,17 +316,17 @@ var gTests = [ yield checkSharingUI({audio: true, screen: "Screen"}); yield closeStream(); } }, { desc: "getUserMedia screen: clicking through without selecting a screen denies", - run: function* checkReloading() { + run: function* checkClickThroughDenies() { let promise = promisePopupNotificationShown("webRTC-shareDevices"); yield promiseRequestDevice(false, true, null, "screen"); yield promise; yield expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(false, false, true); yield promiseMessage(permissionError, () => { PopupNotifications.panel.firstChild.button.click();
--- a/browser/base/content/test/webrtc/head.js +++ b/browser/base/content/test/webrtc/head.js @@ -402,22 +402,24 @@ function* closeStream(aAlreadyClosed, aF if (promises) yield Promise.all(promises); yield* assertWebRTCIndicatorStatus(null); } function* reloadAndAssertClosedStreams() { info("reloading the web page"); - let promise = promiseObserverCalled("recording-device-events"); + let promises = [ + promiseObserverCalled("recording-device-events"), + promiseObserverCalled("recording-window-ended") + ]; yield ContentTask.spawn(gBrowser.selectedBrowser, null, "() => content.location.reload()"); - yield promise; + yield Promise.all(promises); - yield expectObserverCalled("recording-window-ended"); yield expectNoObserverCalled(); yield checkNotSharing(); } function checkDeviceSelectors(aAudio, aVideo, aScreen) { let micSelector = document.getElementById("webRTC-selectMicrophone"); if (aAudio) ok(!micSelector.hidden, "microphone selector visible");
new file mode 100644 --- /dev/null +++ b/browser/config/mozconfigs/linux64/debug-qr @@ -0,0 +1,3 @@ +. "$topsrcdir/browser/config/mozconfigs/linux64/debug" + +ac_add_options --enable-webrender
new file mode 100644 --- /dev/null +++ b/browser/config/mozconfigs/linux64/opt-qr @@ -0,0 +1,3 @@ +. "$topsrcdir/browser/config/mozconfigs/linux64/nightly" + +ac_add_options --enable-webrender
new file mode 100644 --- /dev/null +++ b/browser/config/mozconfigs/macosx64/debug-qr @@ -0,0 +1,3 @@ +. "$topsrcdir/browser/config/mozconfigs/macosx64/debug" + +ac_add_options --enable-webrender
new file mode 100644 --- /dev/null +++ b/browser/config/mozconfigs/macosx64/opt-qr @@ -0,0 +1,3 @@ +. "$topsrcdir/browser/config/mozconfigs/macosx64/nightly" + +ac_add_options --enable-webrender
new file mode 100644 --- /dev/null +++ b/browser/config/mozconfigs/win64/debug-qr @@ -0,0 +1,3 @@ +. "$topsrcdir/browser/config/mozconfigs/win64/debug" + +ac_add_options --enable-webrender
new file mode 100644 --- /dev/null +++ b/browser/config/mozconfigs/win64/opt-qr @@ -0,0 +1,3 @@ +. "$topsrcdir/browser/config/mozconfigs/win64/nightly" + +ac_add_options --enable-webrender
--- a/browser/modules/E10SUtils.jsm +++ b/browser/modules/E10SUtils.jsm @@ -8,18 +8,22 @@ this.EXPORTED_SYMBOLS = ["E10SUtils"]; const {interfaces: Ci, utils: Cu, classes: Cc} = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyPreferenceGetter(this, "useRemoteWebExtensions", "extensions.webextensions.remote", false); +XPCOMUtils.defineLazyPreferenceGetter(this, "useSeparateFileUriProcess", + "browser.tabs.remote.separateFileUriProcess", false); XPCOMUtils.defineLazyModuleGetter(this, "Utils", "resource://gre/modules/sessionstore/Utils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "console", + "resource://gre/modules/Console.jsm"); function getAboutModule(aURL) { // Needs to match NS_GetAboutModuleName let moduleName = aURL.path.replace(/[#?].*/, "").toLowerCase(); let contract = "@mozilla.org/network/protocol/about;1?what=" + moduleName; try { return Cc[contract].getService(Ci.nsIAboutModule); } catch (e) { @@ -51,112 +55,125 @@ this.E10SUtils = { canLoadURIInProcess(aURL, aProcess) { let remoteType = aProcess == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT ? DEFAULT_REMOTE_TYPE : NOT_REMOTE; return remoteType == this.getRemoteTypeForURI(aURL, true, remoteType); }, getRemoteTypeForURI(aURL, aMultiProcess, - aPreferredRemoteType = DEFAULT_REMOTE_TYPE) { + aPreferredRemoteType = DEFAULT_REMOTE_TYPE) { if (!aMultiProcess) { return NOT_REMOTE; } // loadURI in browser.xml treats null as about:blank if (!aURL) { aURL = "about:blank"; } - // Javascript urls can load in any process, they apply to the current document - if (aURL.startsWith("javascript:")) { - return aPreferredRemoteType; - } - - // We need data: URI's to load in a remote process, because some of our - // tests rely on this. For blob: URI's, load them in their originating - // process unless it is non-remote. In that case, favor a remote (sandboxed) - // process with fewer privileges to limit exposure. - if (aURL.startsWith("data:") || aURL.startsWith("blob:")) { - return aPreferredRemoteType == NOT_REMOTE ? DEFAULT_REMOTE_TYPE - : aPreferredRemoteType; - } - - if (aURL.startsWith("file:")) { - return Services.prefs.getBoolPref("browser.tabs.remote.separateFileUriProcess") - ? FILE_REMOTE_TYPE : DEFAULT_REMOTE_TYPE; + let uri; + try { + uri = Services.io.newURI(aURL); + } catch (e) { + // If we have an invalid URI, it's still possible that it might get + // fixed-up into a valid URI later on. However, we don't want to return + // aPreferredRemoteType here, in case the URI gets fixed-up into + // something that wouldn't normally run in that process. + return DEFAULT_REMOTE_TYPE; } - if (aURL.startsWith("about:")) { - // We need to special case about:blank because it needs to load in any. - if (aURL == "about:blank") { - return aPreferredRemoteType; - } + return this.getRemoteTypeForURIObject(uri, aMultiProcess, + aPreferredRemoteType); + }, - let url = Services.io.newURI(aURL); - let module = getAboutModule(url); - // If the module doesn't exist then an error page will be loading, that - // should be ok to load in any process - if (!module) { - return aPreferredRemoteType; - } - - let flags = module.getURIFlags(url); - if (flags & Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD) { - return DEFAULT_REMOTE_TYPE; - } - - // If the about page can load in parent or child, it should be safe to - // load in any remote type. - if (flags & Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD) { - return aPreferredRemoteType; - } - + getRemoteTypeForURIObject(aURI, aMultiProcess, + aPreferredRemoteType = DEFAULT_REMOTE_TYPE) { + if (!aMultiProcess) { return NOT_REMOTE; } - if (aURL.startsWith("chrome:")) { - let url; - try { - // This can fail for invalid Chrome URIs, in which case we will end up - // not loading anything anyway. - url = Services.io.newURI(aURL); - } catch (ex) { + switch (aURI.scheme) { + case "javascript": + // javascript URIs can load in any, they apply to the current document. return aPreferredRemoteType; - } + + case "data": + case "blob": + // We need data: and blob: URIs to load in any remote process, because + // they need to be able to load in whatever is the current process + // unless it is non-remote. In that case we don't want to load them in + // the parent process, so we load them in the default remote process, + // which is sandboxed and limits any risk. + return aPreferredRemoteType == NOT_REMOTE ? DEFAULT_REMOTE_TYPE + : aPreferredRemoteType; - let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]. - getService(Ci.nsIXULChromeRegistry); - if (chromeReg.mustLoadURLRemotely(url)) { - return DEFAULT_REMOTE_TYPE; - } + case "file": + return useSeparateFileUriProcess ? FILE_REMOTE_TYPE + : DEFAULT_REMOTE_TYPE; + + case "about": + let module = getAboutModule(aURI); + // If the module doesn't exist then an error page will be loading, that + // should be ok to load in any process + if (!module) { + return aPreferredRemoteType; + } + + let flags = module.getURIFlags(aURI); + if (flags & Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD) { + return DEFAULT_REMOTE_TYPE; + } - if (chromeReg.canLoadURLRemotely(url) && - aPreferredRemoteType != NOT_REMOTE) { - return DEFAULT_REMOTE_TYPE; - } + // If the about page can load in parent or child, it should be safe to + // load in any remote type. + if (flags & Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD) { + return aPreferredRemoteType; + } + + return NOT_REMOTE; - return NOT_REMOTE; - } + case "chrome": + let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]. + getService(Ci.nsIXULChromeRegistry); + if (chromeReg.mustLoadURLRemotely(aURI)) { + return DEFAULT_REMOTE_TYPE; + } + + if (chromeReg.canLoadURLRemotely(aURI) && + aPreferredRemoteType != NOT_REMOTE) { + return DEFAULT_REMOTE_TYPE; + } - if (aURL.startsWith("moz-extension:")) { - return useRemoteWebExtensions ? EXTENSION_REMOTE_TYPE : NOT_REMOTE; - } + return NOT_REMOTE; + + case "moz-extension": + return useRemoteWebExtensions ? EXTENSION_REMOTE_TYPE : NOT_REMOTE; - if (aURL.startsWith("view-source:")) { - return this.getRemoteTypeForURI(aURL.substr("view-source:".length), - aMultiProcess, aPreferredRemoteType); + default: + // For any other nested URIs, we use the innerURI to determine the + // remote type. In theory we should use the innermost URI, but some URIs + // have fake inner URIs (e.g. about URIs with inner moz-safe-about) and + // if such URIs are wrapped in other nested schemes like view-source:, + // we don't want to "skip" past "about:" by going straight to the + // innermost URI. Any URIs like this will need to be handled in the + // cases above, so we don't still end up using the fake inner URI here. + if (aURI instanceof Ci.nsINestedURI) { + let innerURI = aURI.QueryInterface(Ci.nsINestedURI).innerURI; + return this.getRemoteTypeForURIObject(innerURI, aMultiProcess, + aPreferredRemoteType); + } + + return validatedWebRemoteType(aPreferredRemoteType); } - - return validatedWebRemoteType(aPreferredRemoteType); }, shouldLoadURIInThisProcess(aURI) { let remoteType = Services.appinfo.remoteType; - return remoteType == this.getRemoteTypeForURI(aURI.spec, true, remoteType); + return remoteType == this.getRemoteTypeForURIObject(aURI, true, remoteType); }, shouldLoadURI(aDocShell, aURI, aReferrer) { // Inner frames should always load in the current process if (aDocShell.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeParent) return true; // If we are in a Large-Allocation process, and it wouldn't be content visible
new file mode 100644 --- /dev/null +++ b/browser/modules/test/xpcshell/test_E10SUtils_nested_URIs.js @@ -0,0 +1,94 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ + +const {utils: Cu, interfaces: Ci} = Components; + +Cu.import("resource:///modules/E10SUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +var TEST_PREFERRED_REMOTE_TYPES = [ + E10SUtils.WEB_REMOTE_TYPE, + E10SUtils.NOT_REMOTE, + "fakeRemoteType", +] + +// These test cases give a nestedURL and a plainURL that should always load in +// the same remote type. By making these tests comparisons, they should work +// with any pref combination. +var TEST_CASES = [ + { + nestedURL: "jar:file:///some.file!/", + plainURL: "file:///some.file", + }, + { + nestedURL: "jar:jar:file:///some.file!/!/", + plainURL: "file:///some.file", + }, + { + nestedURL: "jar:http://some.site/file!/", + plainURL: "http://some.site/file", + }, + { + nestedURL: "feed:http://some.site", + plainURL: "http://some.site", + }, + { + nestedURL: "pcast:http://some.site", + plainURL: "http://some.site", + }, + { + nestedURL: "view-source:http://some.site", + plainURL: "http://some.site", + }, + { + nestedURL: "view-source:file:///some.file", + plainURL: "file:///some.file", + }, + { + nestedURL: "view-source:about:home", + plainURL: "about:home", + }, + { + nestedURL: "view-source:about:robots", + plainURL: "about:robots", + }, + { + nestedURL: "view-source:feed:http://some.site", + plainURL: "http://some.site", + }, + { + nestedURL: "view-source:pcast:http://some.site", + plainURL: "http://some.site", + }, +] + +function run_test() { + for (let testCase of TEST_CASES) { + for (let preferredRemoteType of TEST_PREFERRED_REMOTE_TYPES) { + let plainUri = Services.io.newURI(testCase.plainURL); + let plainRemoteType = + E10SUtils.getRemoteTypeForURIObject(plainUri, true, preferredRemoteType); + + let nestedUri = Services.io.newURI(testCase.nestedURL); + let nestedRemoteType = + E10SUtils.getRemoteTypeForURIObject(nestedUri, true, preferredRemoteType); + + let nestedStr = nestedUri.scheme + ":"; + do { + nestedUri = nestedUri.QueryInterface(Ci.nsINestedURI).innerURI; + if (nestedUri.scheme == "about") { + nestedStr += nestedUri.spec; + break; + } + + nestedStr += nestedUri.scheme + ":"; + } while (nestedUri instanceof Ci.nsINestedURI); + + let plainStr = plainUri.scheme == "about" ? plainUri.spec + : plainUri.scheme + ":"; + equal(nestedRemoteType, plainRemoteType, + `Check that ${nestedStr} loads in same remote type as ${plainStr}` + + ` with preferred remote type: ${preferredRemoteType}`); + } + } +}
--- a/browser/modules/test/xpcshell/xpcshell.ini +++ b/browser/modules/test/xpcshell/xpcshell.ini @@ -1,10 +1,11 @@ [DEFAULT] head = firefox-appdir = browser skip-if = toolkit == 'android' [test_AttributionCode.js] skip-if = os != 'win' [test_DirectoryLinksProvider.js] +[test_E10SUtils_nested_URIs.js] [test_SitePermissions.js] [test_LaterRun.js]
--- a/config/system-headers +++ b/config/system-headers @@ -484,16 +484,17 @@ ft2build.h fts.h gconf/gconf-client.h Gdiplus.h gdk/gdk.h gdk/gdkkeysyms.h gdk/gdkprivate.h gdk/gdkx.h gdk/gdkdirectfb.h +gdk/gdkwayland.h gdk-pixbuf/gdk-pixbuf.h Gestalt.h getopt.h glibconfig.h glib.h glib-object.h gmodule.h gnome.h
--- a/devtools/shared/transport/tests/unit/head_dbg.js +++ b/devtools/shared/transport/tests/unit/head_dbg.js @@ -1,262 +1,157 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; +/* exported Cr, CC, NetUtil, defer, errorCount, initTestDebuggerServer, + writeTestTempFile, socket_transport, local_transport, really_long +*/ + var Cc = Components.classes; var Ci = Components.interfaces; var Cu = Components.utils; var Cr = Components.results; var CC = Components.Constructor; const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {}); const { NetUtil } = require("resource://gre/modules/NetUtil.jsm"); const promise = require("promise"); const defer = require("devtools/shared/defer"); const { Task } = require("devtools/shared/task"); const Services = require("Services"); -const DevToolsUtils = require("devtools/shared/DevToolsUtils"); // We do not want to log packets by default, because in some tests, // we can be sending large amounts of data. The test harness has // trouble dealing with logging all the data, and we end up with // intermittent time outs (e.g. bug 775924). // Services.prefs.setBoolPref("devtools.debugger.log", true); // Services.prefs.setBoolPref("devtools.debugger.log.verbose", true); // Enable remote debugging for the relevant tests. Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true); const { DebuggerServer } = require("devtools/server/main"); const { DebuggerClient } = require("devtools/shared/client/main"); -function testExceptionHook(ex) { - try { - do_report_unexpected_exception(ex); - } catch (ex) { - return {throw: ex}; +// Convert an nsIScriptError 'flags' value into an appropriate string. +function scriptErrorFlagsToKind(flags) { + let kind; + if (flags & Ci.nsIScriptError.warningFlag) { + kind = "warning"; } - return undefined; -} + if (flags & Ci.nsIScriptError.exceptionFlag) { + kind = "exception"; + } else { + kind = "error"; + } -// Convert an nsIScriptError 'aFlags' value into an appropriate string. -function scriptErrorFlagsToKind(aFlags) { - var kind; - if (aFlags & Ci.nsIScriptError.warningFlag) - kind = "warning"; - if (aFlags & Ci.nsIScriptError.exceptionFlag) - kind = "exception"; - else - kind = "error"; - - if (aFlags & Ci.nsIScriptError.strictFlag) + if (flags & Ci.nsIScriptError.strictFlag) { kind = "strict " + kind; + } return kind; } // Register a console listener, so console messages don't just disappear // into the ether. var errorCount = 0; var listener = { - observe: function (aMessage) { + observe: function (message) { errorCount++; + let string = ""; try { // If we've been given an nsIScriptError, then we can print out // something nicely formatted, for tools like Emacs to pick up. - var scriptError = aMessage.QueryInterface(Ci.nsIScriptError); - dump(aMessage.sourceName + ":" + aMessage.lineNumber + ": " + - scriptErrorFlagsToKind(aMessage.flags) + ": " + - aMessage.errorMessage + "\n"); - var string = aMessage.errorMessage; + message.QueryInterface(Ci.nsIScriptError); + dump(message.sourceName + ":" + message.lineNumber + ": " + + scriptErrorFlagsToKind(message.flags) + ": " + + message.errorMessage + "\n"); + string = message.errorMessage; } catch (x) { // Be a little paranoid with message, as the whole goal here is to lose // no information. try { - var string = "" + aMessage.message; - } catch (x) { - var string = "<error converting error message to string>"; + string = message.message; + } catch (e) { + string = "<error converting error message to string>"; } } // Make sure we exit all nested event loops so that the test can finish. while (DebuggerServer.xpcInspector.eventLoopNestLevel > 0) { DebuggerServer.xpcInspector.exitNestedEventLoop(); } // Throw in most cases, but ignore the "strict" messages - if (!(aMessage.flags & Ci.nsIScriptError.strictFlag)) { + if (!(message.flags & Ci.nsIScriptError.strictFlag)) { do_throw("head_dbg.js got console message: " + string + "\n"); } } }; var consoleService = Cc["@mozilla.org/consoleservice;1"] .getService(Ci.nsIConsoleService); consoleService.registerListener(listener); -function check_except(func) { - try { - func(); - } catch (e) { - do_check_true(true); - return; - } - dump("Should have thrown an exception: " + func.toString()); - do_check_true(false); -} - -function testGlobal(aName) { - let systemPrincipal = Cc["@mozilla.org/systemprincipal;1"] - .createInstance(Ci.nsIPrincipal); - - let sandbox = Cu.Sandbox(systemPrincipal); - sandbox.__name = aName; - return sandbox; -} - -function addTestGlobal(aName) -{ - let global = testGlobal(aName); - DebuggerServer.addTestGlobal(global); - return global; -} - -// List the DebuggerClient |aClient|'s tabs, look for one whose title is -// |aTitle|, and apply |aCallback| to the packet's entry for that tab. -function getTestTab(aClient, aTitle, aCallback) { - aClient.listTabs(function (aResponse) { - for (let tab of aResponse.tabs) { - if (tab.title === aTitle) { - aCallback(tab); - return; - } - } - aCallback(null); - }); -} - -// Attach to |aClient|'s tab whose title is |aTitle|; pass |aCallback| the -// response packet and a TabClient instance referring to that tab. -function attachTestTab(aClient, aTitle, aCallback) { - getTestTab(aClient, aTitle, function (aTab) { - aClient.attachTab(aTab.actor, aCallback); - }); -} - -// Attach to |aClient|'s tab whose title is |aTitle|, and then attach to -// that tab's thread. Pass |aCallback| the thread attach response packet, a -// TabClient referring to the tab, and a ThreadClient referring to the -// thread. -function attachTestThread(aClient, aTitle, aCallback) { - attachTestTab(aClient, aTitle, function (aResponse, aTabClient) { - function onAttach(aResponse, aThreadClient) { - aCallback(aResponse, aTabClient, aThreadClient); - } - aTabClient.attachThread({ useSourceMaps: true }, onAttach); - }); -} - -// Attach to |aClient|'s tab whose title is |aTitle|, attach to the tab's -// thread, and then resume it. Pass |aCallback| the thread's response to -// the 'resume' packet, a TabClient for the tab, and a ThreadClient for the -// thread. -function attachTestTabAndResume(aClient, aTitle, aCallback) { - attachTestThread(aClient, aTitle, function (aResponse, aTabClient, aThreadClient) { - aThreadClient.resume(function (aResponse) { - aCallback(aResponse, aTabClient, aThreadClient); - }); - }); -} - /** * Initialize the testing debugger server. */ function initTestDebuggerServer() { DebuggerServer.registerModule("devtools/server/actors/script", { prefix: "script", constructor: "ScriptActor", type: { global: true, tab: true } }); DebuggerServer.registerModule("xpcshell-test/testactors"); // Allow incoming connections. DebuggerServer.init(); } -function finishClient(aClient) { - aClient.close().then(function () { - do_test_finished(); - }); -} - -/** - * Takes a relative file path and returns the absolute file url for it. - */ -function getFileUrl(aName, aAllowMissing = false) { - let file = do_get_file(aName, aAllowMissing); - return Services.io.newFileURI(file).spec; -} - -/** - * Returns the full path of the file with the specified name in a - * platform-independent and URL-like form. - */ -function getFilePath(aName, aAllowMissing = false) { - let file = do_get_file(aName, aAllowMissing); - let path = Services.io.newFileURI(file).spec; - let filePrePath = "file://"; - if ("nsILocalFileWin" in Ci && - file instanceof Ci.nsILocalFileWin) { - filePrePath += "/"; - } - return path.slice(filePrePath.length); -} - /** * Wrapper around do_get_file to prefix files with the name of current test to * avoid collisions when running in parallel. */ function getTestTempFile(fileName, allowMissing) { let thisTest = _TEST_FILE.toString().replace(/\\/g, "/"); thisTest = thisTest.substring(thisTest.lastIndexOf("/") + 1); thisTest = thisTest.replace(/\..*$/, ""); return do_get_file(fileName + "-" + thisTest, allowMissing); } -function writeTestTempFile(aFileName, aContent) { - let file = getTestTempFile(aFileName, true); +function writeTestTempFile(fileName, content) { + let file = getTestTempFile(fileName, true); let stream = Cc["@mozilla.org/network/file-output-stream;1"] .createInstance(Ci.nsIFileOutputStream); stream.init(file, -1, -1, 0); try { do { - let numWritten = stream.write(aContent, aContent.length); - aContent = aContent.slice(numWritten); - } while (aContent.length > 0); + let numWritten = stream.write(content, content.length); + content = content.slice(numWritten); + } while (content.length > 0); } finally { stream.close(); } } /** * Transport Factories ***/ var socket_transport = Task.async(function* () { if (!DebuggerServer.listeningSockets) { let AuthenticatorType = DebuggerServer.Authenticators.get("PROMPT"); let authenticator = new AuthenticatorType.Server(); authenticator.allowConnection = () => { return DebuggerServer.AuthenticationResult.ALLOW; }; - let listener = DebuggerServer.createListener(); - listener.portOrPath = -1; - listener.authenticator = authenticator; - yield listener.open(); + let debuggerListener = DebuggerServer.createListener(); + debuggerListener.portOrPath = -1; + debuggerListener.authenticator = authenticator; + yield debuggerListener.open(); } let port = DebuggerServer._listeners[0].port; do_print("Debugger server port is " + port); return DebuggerClient.socketConnect({ host: "127.0.0.1", port }); }); function local_transport() { return promise.resolve(DebuggerServer.connectPipe());
--- a/devtools/shared/transport/tests/unit/test_bulk_error.js +++ b/devtools/shared/transport/tests/unit/test_bulk_error.js @@ -68,18 +68,18 @@ function json_reply(client, response) { actor: response.testBulk, type: "jsonReply", length: reallyLong.length }); // Send bulk data to server let copyDeferred = defer(); request.on("bulk-send-ready", ({writer, done}) => { - let input = Cc["@mozilla.org/io/string-input-stream;1"]. - createInstance(Ci.nsIStringInputStream); + let input = Cc["@mozilla.org/io/string-input-stream;1"] + .createInstance(Ci.nsIStringInputStream); input.setData(reallyLong, reallyLong.length); try { writer.copyFrom(input, () => { input.close(); done(); }); do_throw(new Error("Copying should fail, the stream is not async.")); } catch (e) {
--- a/devtools/shared/transport/tests/unit/test_client_server_bulk.js +++ b/devtools/shared/transport/tests/unit/test_client_server_bulk.js @@ -145,35 +145,37 @@ var test_bulk_request_cs = Task.async(fu let transport = yield transportFactory(); let client = new DebuggerClient(transport); client.connect().then(([app, traits]) => { do_check_eq(traits.bulk, true); client.listTabs(clientDeferred.resolve); }); + function bulkSendReadyCallback({copyFrom}) { + NetUtil.asyncFetch({ + uri: NetUtil.newURI(getTestTempFile("bulk-input")), + loadUsingSystemPrincipal: true + }, input => { + copyFrom(input).then(() => { + input.close(); + bulkCopyDeferred.resolve(); + }); + }); + } + clientDeferred.promise.then(response => { let request = client.startBulkRequest({ actor: response.testBulk, type: actorType, length: really_long().length }); // Send bulk data to server - request.on("bulk-send-ready", ({copyFrom}) => { - NetUtil.asyncFetch({ - uri: NetUtil.newURI(getTestTempFile("bulk-input")), - loadUsingSystemPrincipal: true - }, input => { - copyFrom(input).then(() => { - input.close(); - bulkCopyDeferred.resolve(); - }); - }); - }); + request.on("bulk-send-ready", bulkSendReadyCallback); // Set up reply handling for this type replyHandlers[replyType](request).then(() => { client.close(); transport.close(); }); }).then(null, do_throw);
--- a/devtools/shared/transport/tests/unit/test_dbgsocket.js +++ b/devtools/shared/transport/tests/unit/test_dbgsocket.js @@ -1,28 +1,27 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; var gPort; var gExtraListener; -function run_test() -{ +function run_test() { do_print("Starting test at " + new Date().toTimeString()); initTestDebuggerServer(); add_task(test_socket_conn); add_task(test_socket_shutdown); add_test(test_pipe_conn); run_next_test(); } -function* test_socket_conn() -{ +function* test_socket_conn() { do_check_eq(DebuggerServer.listeningSockets, 0); let AuthenticatorType = DebuggerServer.Authenticators.get("PROMPT"); let authenticator = new AuthenticatorType.Server(); authenticator.allowConnection = () => { return DebuggerServer.AuthenticationResult.ALLOW; }; let listener = DebuggerServer.createListener(); do_check_true(listener); @@ -48,77 +47,74 @@ function* test_socket_conn() // Assert that connection settings are available on transport object let settings = transport.connectionSettings; do_check_eq(settings.host, "127.0.0.1"); do_check_eq(settings.port, gPort); let closedDeferred = defer(); transport.hooks = { - onPacket: function (aPacket) { - this.onPacket = function (aPacket) { - do_check_eq(aPacket.unicode, unicodeString); + onPacket: function (packet) { + this.onPacket = function ({unicode}) { + do_check_eq(unicode, unicodeString); transport.close(); }; // Verify that things work correctly when bigger than the output // transport buffers and when transporting unicode... transport.send({to: "root", type: "echo", reallylong: really_long(), unicode: unicodeString}); - do_check_eq(aPacket.from, "root"); + do_check_eq(packet.from, "root"); }, - onClosed: function (aStatus) { + onClosed: function (status) { closedDeferred.resolve(); }, }; transport.ready(); return closedDeferred.promise; } -function* test_socket_shutdown() -{ +function* test_socket_shutdown() { do_check_eq(DebuggerServer.listeningSockets, 2); gExtraListener.close(); do_check_eq(DebuggerServer.listeningSockets, 1); do_check_true(DebuggerServer.closeAllListeners()); do_check_eq(DebuggerServer.listeningSockets, 0); // Make sure closing the listener twice does nothing. do_check_false(DebuggerServer.closeAllListeners()); do_check_eq(DebuggerServer.listeningSockets, 0); do_print("Connecting to a server socket at " + new Date().toTimeString()); try { - let transport = yield DebuggerClient.socketConnect({ + yield DebuggerClient.socketConnect({ host: "127.0.0.1", port: gPort }); } catch (e) { if (e.result == Cr.NS_ERROR_CONNECTION_REFUSED || e.result == Cr.NS_ERROR_NET_TIMEOUT) { // The connection should be refused here, but on slow or overloaded // machines it may just time out. do_check_true(true); return; - } else { - throw e; } + throw e; } // Shouldn't reach this, should never connect. do_check_true(false); } -function test_pipe_conn() -{ +function test_pipe_conn() { let transport = DebuggerServer.connectPipe(); transport.hooks = { - onPacket: function (aPacket) { - do_check_eq(aPacket.from, "root"); + onPacket: function (packet) { + do_check_eq(packet.from, "root"); transport.close(); }, - onClosed: function (aStatus) { + onClosed: function (status) { run_next_test(); } }; transport.ready(); }
--- a/devtools/shared/transport/tests/unit/test_dbgsocket_connection_drop.js +++ b/devtools/shared/transport/tests/unit/test_dbgsocket_connection_drop.js @@ -2,16 +2,17 @@ * Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Bug 755412 - checks if the server drops the connection on an improperly * framed packet, i.e. when the length header is invalid. */ +"use strict"; const { RawPacket } = require("devtools/shared/transport/packets"); function run_test() { do_print("Starting test at " + new Date().toTimeString()); initTestDebuggerServer(); add_task(test_socket_conn_drops_after_invalid_header); @@ -56,26 +57,26 @@ var test_helper = Task.async(function* ( listener.open(); let transport = yield DebuggerClient.socketConnect({ host: "127.0.0.1", port: listener.port }); let closedDeferred = defer(); transport.hooks = { - onPacket: function (aPacket) { - this.onPacket = function (aPacket) { + onPacket: function (packet) { + this.onPacket = function () { do_throw(new Error("This connection should be dropped.")); transport.close(); }; // Inject the payload directly into the stream. transport._outgoing.push(new RawPacket(transport, payload)); transport._flushOutgoing(); }, - onClosed: function (aStatus) { + onClosed: function (status) { do_check_true(true); closedDeferred.resolve(); }, }; transport.ready(); return closedDeferred.promise; });
--- a/devtools/shared/transport/tests/unit/test_delimited_read.js +++ b/devtools/shared/transport/tests/unit/test_delimited_read.js @@ -1,10 +1,11 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; const StreamUtils = require("devtools/shared/transport/stream-utils"); const StringInputStream = CC("@mozilla.org/io/string-input-stream;1", "nsIStringInputStream", "setData"); function run_test() { add_task(function* () {
--- a/devtools/shared/transport/tests/unit/test_no_bulk.js +++ b/devtools/shared/transport/tests/unit/test_no_bulk.js @@ -15,24 +15,22 @@ function run_test() { }); run_next_test(); } /** * Tests ***/ var test_bulk_send_error = Task.async(function* (transportFactory) { - let deferred = defer(); let transport = yield transportFactory(); let client = new DebuggerClient(transport); return client.connect().then(([app, traits]) => { do_check_false(traits.bulk); try { client.startBulkRequest(); do_throw(new Error("Can't use bulk since server doesn't support it")); } catch (e) { do_check_true(true); } - }); });
--- a/devtools/shared/transport/tests/unit/test_packet.js +++ b/devtools/shared/transport/tests/unit/test_packet.js @@ -1,10 +1,11 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; const { JSONPacket, BulkPacket } = require("devtools/shared/transport/packets"); function run_test() { add_test(test_packet_done); run_next_test(); }
--- a/devtools/shared/transport/tests/unit/test_transport_bulk.js +++ b/devtools/shared/transport/tests/unit/test_transport_bulk.js @@ -69,19 +69,19 @@ var test_bulk_transfer_transport = Task. clientDeferred.resolve(); }; transport.close(); }); } // Client transport.hooks = { - onPacket: function (aPacket) { + onPacket: function (packet) { // We've received the initial start up packet - do_check_eq(aPacket.from, "root"); + do_check_eq(packet.from, "root"); // Server do_check_eq(Object.keys(DebuggerServer._connections).length, 1); do_print(Object.keys(DebuggerServer._connections)); for (let connId in DebuggerServer._connections) { DebuggerServer._connections[connId].onBulkPacket = on_bulk_packet; }
--- a/devtools/shared/transport/tests/unit/testactors-no-bulk.js +++ b/devtools/shared/transport/tests/unit/testactors-no-bulk.js @@ -1,19 +1,20 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; const { RootActor } = require("devtools/server/actors/root"); const { DebuggerServer } = require("devtools/server/main"); /** * Root actor that doesn't have the bulk trait. */ -function createRootActor(aConnection) { - let root = new RootActor(aConnection, { +function createRootActor(connection) { + let root = new RootActor(connection, { globalActorFactories: DebuggerServer.globalActorFactories }); root.applicationType = "xpcshell-tests"; root.traits = { bulk: false }; return root; }
--- a/devtools/shared/transport/tests/unit/testactors.js +++ b/devtools/shared/transport/tests/unit/testactors.js @@ -1,72 +1,73 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; const { ActorPool, appendExtraActors, createExtraActors } = require("devtools/server/actors/common"); const { RootActor } = require("devtools/server/actors/root"); const { ThreadActor } = require("devtools/server/actors/script"); const { DebuggerServer } = require("devtools/server/main"); const promise = require("promise"); var gTestGlobals = []; -DebuggerServer.addTestGlobal = function (aGlobal) { - gTestGlobals.push(aGlobal); +DebuggerServer.addTestGlobal = function (global) { + gTestGlobals.push(global); }; // A mock tab list, for use by tests. This simply presents each global in // gTestGlobals as a tab, and the list is fixed: it never calls its // onListChanged handler. // // As implemented now, we consult gTestGlobals when we're constructed, not // when we're iterated over, so tests have to add their globals before the // root actor is created. -function TestTabList(aConnection) { - this.conn = aConnection; +function TestTabList(connection) { + this.conn = connection; // An array of actors for each global added with // DebuggerServer.addTestGlobal. this._tabActors = []; // A pool mapping those actors' names to the actors. - this._tabActorPool = new ActorPool(aConnection); + this._tabActorPool = new ActorPool(connection); for (let global of gTestGlobals) { - let actor = new TestTabActor(aConnection, global); + let actor = new TestTabActor(connection, global); actor.selected = false; this._tabActors.push(actor); this._tabActorPool.addActor(actor); } if (this._tabActors.length > 0) { this._tabActors[0].selected = true; } - aConnection.addActorPool(this._tabActorPool); + connection.addActorPool(this._tabActorPool); } TestTabList.prototype = { constructor: TestTabList, getList: function () { return promise.resolve([...this._tabActors]); } }; -function createRootActor(aConnection) { - let root = new RootActor(aConnection, { - tabList: new TestTabList(aConnection), +function createRootActor(connection) { + let root = new RootActor(connection, { + tabList: new TestTabList(connection), globalActorFactories: DebuggerServer.globalActorFactories }); root.applicationType = "xpcshell-tests"; return root; } -function TestTabActor(aConnection, aGlobal) { - this.conn = aConnection; - this._global = aGlobal; +function TestTabActor(connection, global) { + this.conn = connection; + this._global = global; this._threadActor = new ThreadActor(this, this._global); this.conn.addActor(this._threadActor); this._attached = false; this._extraActors = {}; } TestTabActor.prototype = { constructor: TestTabActor, @@ -91,28 +92,28 @@ TestTabActor.prototype = { this.conn.addActorPool(this._tabActorPool); } this._appendExtraActors(response); return response; }, - onAttach: function (aRequest) { + onAttach: function (request) { this._attached = true; let response = { type: "tabAttached", threadActor: this._threadActor.actorID }; this._appendExtraActors(response); return response; }, - onDetach: function (aRequest) { + onDetach: function (request) { if (!this._attached) { - return { "error":"wrongState" }; + return { "error": "wrongState" }; } return { type: "detached" }; }, /* Support for DebuggerServer.addTabActor. */ _createExtraActors: createExtraActors, _appendExtraActors: appendExtraActors };
--- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -7567,17 +7567,23 @@ nsDocShell::EndPageLoad(nsIWebProgress* nsIChannel* aChannel, nsresult aStatus) { if (!aChannel) { return NS_ERROR_NULL_POINTER; } nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel); if (reporter) { - reporter->FlushConsoleReports(GetDocument()); + nsCOMPtr<nsILoadGroup> loadGroup; + aChannel->GetLoadGroup(getter_AddRefs(loadGroup)); + if (loadGroup) { + reporter->FlushConsoleReports(loadGroup); + } else { + reporter->FlushConsoleReports(GetDocument()); + } } nsCOMPtr<nsIURI> url; nsresult rv = aChannel->GetURI(getter_AddRefs(url)); if (NS_FAILED(rv)) { return rv; }
--- a/dom/base/TimeoutManager.cpp +++ b/dom/base/TimeoutManager.cpp @@ -928,28 +928,38 @@ TimeoutManager::Timeouts::ResetTimersFor // Since we reset When() we need to move |timeout| to the right // place in the list so that it remains sorted by When(). // Get the pointer to the next timeout now, before we move the // current timeout in the list. Timeout* nextTimeout = timeout->getNext(); - // It is safe to remove and re-insert because When() is now - // strictly smaller than it used to be, so we know we'll insert - // |timeout| before nextTimeout. - NS_ASSERTION(!nextTimeout || - timeout->When() < nextTimeout->When(), "How did that happen?"); - timeout->remove(); - // Insert() will addref |timeout| and reset mFiringDepth. Make sure to - // undo that after calling it. - uint32_t firingDepth = timeout->mFiringDepth; - Insert(timeout, aSortBy); - timeout->mFiringDepth = firingDepth; - timeout->Release(); + // Since we are only reducing intervals in this method we can + // make an optimization here. If the reduction does not cause us + // to fall before our previous timeout then we do not have to + // remove and re-insert the current timeout. This is important + // because re-insertion makes this algorithm O(n^2). Since we + // will typically be shifting a lot of timers at once this + // optimization saves us a lot of work. + Timeout* prevTimeout = timeout->getPrevious(); + if (prevTimeout && prevTimeout->When() > timeout->When()) { + // It is safe to remove and re-insert because When() is now + // strictly smaller than it used to be, so we know we'll insert + // |timeout| before nextTimeout. + NS_ASSERTION(!nextTimeout || + timeout->When() < nextTimeout->When(), "How did that happen?"); + timeout->remove(); + // Insert() will addref |timeout| and reset mFiringDepth. Make sure to + // undo that after calling it. + uint32_t firingDepth = timeout->mFiringDepth; + Insert(timeout, aSortBy); + timeout->mFiringDepth = firingDepth; + timeout->Release(); + } nsresult rv = timeout->InitTimer(aQueue, delay.ToMilliseconds()); if (NS_FAILED(rv)) { NS_WARNING("Error resetting non background timer for DOM timeout!"); return rv; }
--- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -1792,18 +1792,17 @@ nsContentUtils::ParseLegacyFontSize(cons return clamped(value, 1, 7); } /* static */ bool nsContentUtils::IsControlledByServiceWorker(nsIDocument* aDocument) { - if (aDocument && - aDocument->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId) { + if (nsContentUtils::IsInPrivateBrowsing(aDocument)) { return false; } RefPtr<workers::ServiceWorkerManager> swm = workers::ServiceWorkerManager::GetInstance(); MOZ_ASSERT(swm); ErrorResult rv; @@ -3201,16 +3200,50 @@ nsContentUtils::GetOriginAttributes(nsIL nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); if (loadContext && loadContext->GetOriginAttributes(attrs)) { attrs.StripAttributes(OriginAttributes::STRIP_ADDON_ID); } } return attrs; } +// static +bool +nsContentUtils::IsInPrivateBrowsing(nsIDocument* aDoc) +{ + if (!aDoc) { + return false; + } + + nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup(); + if (loadGroup) { + return IsInPrivateBrowsing(loadGroup); + } + + nsCOMPtr<nsIChannel> channel = aDoc->GetChannel(); + return channel && NS_UsePrivateBrowsing(channel); +} + +// static +bool +nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) +{ + if (!aLoadGroup) { + return false; + } + bool isPrivate = false; + nsCOMPtr<nsIInterfaceRequestor> callbacks; + aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); + if (callbacks) { + nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); + isPrivate = loadContext && loadContext->UsePrivateBrowsing(); + } + return isPrivate; +} + bool nsContentUtils::DocumentInactiveForImageLoads(nsIDocument* aDocument) { if (aDocument && !IsChromeDoc(aDocument) && !aDocument->IsResourceDoc()) { nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aDocument->GetScopeObject()); return !win || !win->GetDocShell(); } @@ -3220,36 +3253,19 @@ nsContentUtils::DocumentInactiveForImage imgLoader* nsContentUtils::GetImgLoaderForDocument(nsIDocument* aDoc) { NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aDoc), nullptr); if (!aDoc) { return imgLoader::NormalLoader(); } - - nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup(); - if (loadGroup) { - nsCOMPtr<nsIInterfaceRequestor> callbacks; - loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); - if (callbacks) { - nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); - if (loadContext && loadContext->UsePrivateBrowsing()) { - return imgLoader::PrivateBrowsingLoader(); - } - } - return imgLoader::NormalLoader(); - } - - nsCOMPtr<nsIChannel> channel = aDoc->GetChannel(); - if (channel && NS_UsePrivateBrowsing(channel)) { - return imgLoader::PrivateBrowsingLoader(); - } - - return imgLoader::NormalLoader(); + bool isPrivate = IsInPrivateBrowsing(aDoc); + return isPrivate ? imgLoader::PrivateBrowsingLoader() + : imgLoader::NormalLoader(); } // static imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel, nsIDocument* aContext) { NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aContext), nullptr); @@ -3671,16 +3687,32 @@ nsContentUtils::ReportToConsoleNonLocali uint64_t innerWindowID = 0; if (aDocument) { if (!aURI) { aURI = aDocument->GetDocumentURI(); } innerWindowID = aDocument->InnerWindowID(); } + return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory, + innerWindowID, aURI, aSourceLine, + aLineNumber, aColumnNumber, aLocationMode); +} + +/* static */ nsresult +nsContentUtils::ReportToConsoleByWindowID(const nsAString& aErrorText, + uint32_t aErrorFlags, + const nsACString& aCategory, + uint64_t aInnerWindowID, + nsIURI* aURI, + const nsAFlatString& aSourceLine, + uint32_t aLineNumber, + uint32_t aColumnNumber, + MissingErrorLocationMode aLocationMode) +{ nsresult rv; if (!sConsoleService) { // only need to bother null-checking here rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService); NS_ENSURE_SUCCESS(rv, rv); } nsAutoCString spec; if (!aLineNumber && aLocationMode == eUSE_CALLING_LOCATION) { @@ -3697,17 +3729,17 @@ nsContentUtils::ReportToConsoleNonLocali do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = errorObject->InitWithWindowID(aErrorText, NS_ConvertUTF8toUTF16(spec), // file name aSourceLine, aLineNumber, aColumnNumber, aErrorFlags, aCategory, - innerWindowID); + aInnerWindowID); NS_ENSURE_SUCCESS(rv, rv); return sConsoleService->LogMessage(errorObject); } void nsContentUtils::LogMessageToConsole(const char* aMsg) { @@ -7336,18 +7368,28 @@ nsContentUtils::GetInnerWindowID(nsIRequ nsCOMPtr<nsILoadGroup> loadGroup; nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup)); if (NS_FAILED(rv) || !loadGroup) { return 0; } + return GetInnerWindowID(loadGroup); +} + +uint64_t +nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) +{ + if (!aLoadGroup) { + return 0; + } + nsCOMPtr<nsIInterfaceRequestor> callbacks; - rv = loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); + nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); if (NS_FAILED(rv) || !callbacks) { return 0; } nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks); if (!loadContext) { return 0; } @@ -8620,17 +8662,17 @@ nsContentUtils::InternalStorageAllowedFo if (aWindow) { // If the document is sandboxed, then it is not permitted to use storage nsIDocument* document = aWindow->GetExtantDoc(); if (document->GetSandboxFlags() & SANDBOXED_ORIGIN) { return StorageAccess::eDeny; } // Check if we are in private browsing, and record that fact - if (document->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId) { + if (IsInPrivateBrowsing(document)) { access = StorageAccess::ePrivateBrowsing; } } nsCOMPtr<nsIPermissionManager> permissionManager = services::GetPermissionManager(); if (!permissionManager) { return StorageAccess::eDeny;
--- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -817,16 +817,26 @@ public: /** * Returns origin attributes of the load group. **/ static mozilla::OriginAttributes GetOriginAttributes(nsILoadGroup* aLoadGroup); /** + * Returns true if this document is in a Private Browsing window. + */ + static bool IsInPrivateBrowsing(nsIDocument* aDoc); + + /** + * Returns true if this loadGroup uses Private Browsing. + */ + static bool IsInPrivateBrowsing(nsILoadGroup* aLoadGroup); + + /** * If aNode is not an element, return true exactly when aContent's binding * parent is null. * * If aNode is an element, return true exactly when aContent's binding parent * is the same as aNode's. * * This method is particularly useful for callers who are trying to ensure * that they are working with a non-anonymous descendant of a given node. If @@ -884,16 +894,47 @@ public: const nsAFlatString& aSourceLine = EmptyString(), uint32_t aLineNumber = 0, uint32_t aColumnNumber = 0, MissingErrorLocationMode aLocationMode = eUSE_CALLING_LOCATION); /** + * Report a non-localized error message to the error console base on the + * innerWindowID. + * @param aErrorText the error message + * @param aErrorFlags See nsIScriptError. + * @param aCategory Name of module reporting error. + * @param [aInnerWindowID] Inner window ID for document which triggered the + * message. + * @param [aURI=nullptr] (Optional) URI of resource containing error. + * @param [aSourceLine=EmptyString()] (Optional) The text of the line that + contains the error (may be empty). + * @param [aLineNumber=0] (Optional) Line number within resource + containing error. + * @param [aColumnNumber=0] (Optional) Column number within resource + containing error. + If aURI is null, then aDocument->GetDocumentURI() is used. + * @param [aLocationMode] (Optional) Specifies the behavior if + error location information is omitted. + */ + static nsresult ReportToConsoleByWindowID(const nsAString& aErrorText, + uint32_t aErrorFlags, + const nsACString& aCategory, + uint64_t aInnerWindowID, + nsIURI* aURI = nullptr, + const nsAFlatString& aSourceLine + = EmptyString(), + uint32_t aLineNumber = 0, + uint32_t aColumnNumber = 0, + MissingErrorLocationMode aLocationMode + = eUSE_CALLING_LOCATION); + + /** * Report a localized error message to the error console. * @param aErrorFlags See nsIScriptError. * @param aCategory Name of module reporting error. * @param aDocument Reference to the document which triggered the message. * @param aFile Properties file containing localized message. * @param aMessageName Name of localized message. * @param [aParams=nullptr] (Optional) Parameters to be substituted into localized message. @@ -2446,21 +2487,26 @@ public: /** * Returns whether a given header is forbidden for an XHR or fetch * response. */ static bool IsForbiddenResponseHeader(const nsACString& aHeader); /** - * Returns the inner window ID for the window associated with a request, + * Returns the inner window ID for the window associated with a request. */ static uint64_t GetInnerWindowID(nsIRequest* aRequest); /** + * Returns the inner window ID for the window associated with a load group. + */ + static uint64_t GetInnerWindowID(nsILoadGroup* aLoadGroup); + + /** * If the hostname for aURI is an IPv6 it encloses it in brackets, * otherwise it just outputs the hostname in aHost. */ static nsresult GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost); static nsresult GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost); /* * Call the given callback on all remote children of the given top-level
--- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -2483,17 +2483,22 @@ nsScriptLoader::OnStreamComplete(nsIIncr MOZ_ASSERT(mReporter); nsAutoCString sourceUri; if (mDocument && mDocument->GetDocumentURI()) { mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); } rv = aSRIDataVerifier->Verify(aRequest->mIntegrity, channel, sourceUri, mReporter); - mReporter->FlushConsoleReports(mDocument); + if (channelRequest) { + mReporter->FlushReportsToConsole( + nsContentUtils::GetInnerWindowID(channelRequest)); + } else { + mReporter->FlushConsoleReports(mDocument); + } if (NS_FAILED(rv)) { rv = NS_ERROR_SRI_CORRUPT; } } else { nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo(); if (loadInfo->GetEnforceSRI()) { MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
--- a/dom/console/ConsoleReportCollector.cpp +++ b/dom/console/ConsoleReportCollector.cpp @@ -34,64 +34,85 @@ ConsoleReportCollector::AddConsoleReport mPendingReports.AppendElement(PendingReport(aErrorFlags, aCategory, aPropertiesFile, aSourceFileURI, aLineNumber, aColumnNumber, aMessageName, aStringParams)); } void -ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument, - ReportAction aAction) +ConsoleReportCollector::FlushReportsToConsole(uint64_t aInnerWindowID, + ReportAction aAction) { - MOZ_ASSERT(NS_IsMainThread()); - nsTArray<PendingReport> reports; { MutexAutoLock lock(mMutex); if (aAction == ReportAction::Forget) { mPendingReports.SwapElements(reports); } else { reports = mPendingReports; } } for (uint32_t i = 0; i < reports.Length(); ++i) { PendingReport& report = reports[i]; + nsXPIDLString errorText; + nsresult rv; + if (!report.mStringParams.IsEmpty()) { + rv = nsContentUtils::FormatLocalizedString(report.mPropertiesFile, + report.mMessageName.get(), + report.mStringParams, + errorText); + } else { + rv = nsContentUtils::GetLocalizedString(report.mPropertiesFile, + report.mMessageName.get(), + errorText); + } + if (NS_WARN_IF(NS_FAILED(rv))) { + continue; + } + // It would be nice if we did not have to do this since ReportToConsole() // just turns around and converts it back to a spec. nsCOMPtr<nsIURI> uri; if (!report.mSourceFileURI.IsEmpty()) { nsresult rv = NS_NewURI(getter_AddRefs(uri), report.mSourceFileURI); MOZ_ALWAYS_SUCCEEDS(rv); if (NS_FAILED(rv)) { continue; } } - // Convert back from nsTArray<nsString> to the char16_t** format required - // by our l10n libraries and ReportToConsole. (bug 1219762) - UniquePtr<const char16_t*[]> params; - uint32_t paramsLength = report.mStringParams.Length(); - if (paramsLength > 0) { - params = MakeUnique<const char16_t*[]>(paramsLength); - for (uint32_t j = 0; j < paramsLength; ++j) { - params[j] = report.mStringParams[j].get(); - } - } + nsContentUtils::ReportToConsoleByWindowID(errorText, + report.mErrorFlags, + report.mCategory, + aInnerWindowID, + uri, + EmptyString(), + report.mLineNumber, + report.mColumnNumber); + } +} - nsContentUtils::ReportToConsole(report.mErrorFlags, report.mCategory, - aDocument, report.mPropertiesFile, - report.mMessageName.get(), - params.get(), - paramsLength, uri, EmptyString(), - report.mLineNumber, report.mColumnNumber); - } +void +ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument, + ReportAction aAction) +{ + MOZ_ASSERT(NS_IsMainThread()); + + FlushReportsToConsole(aDocument ? aDocument->InnerWindowID() : 0, aAction); +} + +void +ConsoleReportCollector::FlushConsoleReports(nsILoadGroup* aLoadGroup, + ReportAction aAction) +{ + FlushReportsToConsole(nsContentUtils::GetInnerWindowID(aLoadGroup), aAction); } void ConsoleReportCollector::FlushConsoleReports(nsIConsoleReportCollector* aCollector) { MOZ_ASSERT(aCollector); nsTArray<PendingReport> reports; @@ -106,81 +127,16 @@ ConsoleReportCollector::FlushConsoleRepo aCollector->AddConsoleReport(report.mErrorFlags, report.mCategory, report.mPropertiesFile, report.mSourceFileURI, report.mLineNumber, report.mColumnNumber, report.mMessageName, report.mStringParams); } } void -ConsoleReportCollector::FlushReportsByWindowId(uint64_t aWindowId, - ReportAction aAction) -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsTArray<PendingReport> reports; - - { - MutexAutoLock lock(mMutex); - if (aAction == ReportAction::Forget) { - mPendingReports.SwapElements(reports); - } else { - reports = mPendingReports; - } - } - - nsCOMPtr<nsIConsoleService> consoleService = - do_GetService(NS_CONSOLESERVICE_CONTRACTID); - if (!consoleService) { - NS_WARNING("GetConsoleService failed"); - return; - } - - nsresult rv; - for (uint32_t i = 0; i < reports.Length(); ++i) { - PendingReport& report = reports[i]; - - nsXPIDLString errorText; - if (!report.mStringParams.IsEmpty()) { - rv = nsContentUtils::FormatLocalizedString(report.mPropertiesFile, - report.mMessageName.get(), - report.mStringParams, - errorText); - } else { - rv = nsContentUtils::GetLocalizedString(report.mPropertiesFile, - report.mMessageName.get(), - errorText); - } - if (NS_WARN_IF(NS_FAILED(rv))) { - continue; - } - - nsCOMPtr<nsIScriptError> errorObject = - do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - continue; - } - - rv = errorObject->InitWithWindowID(errorText, - NS_ConvertUTF8toUTF16(report.mSourceFileURI), - EmptyString(), - report.mLineNumber, - report.mColumnNumber, - report.mErrorFlags, - report.mCategory, - aWindowId); - if (NS_WARN_IF(NS_FAILED(rv))) { - continue; - } - - consoleService->LogMessage(errorObject); - } -} - -void ConsoleReportCollector::ClearConsoleReports() { MutexAutoLock lock(mMutex); mPendingReports.Clear(); } ConsoleReportCollector::~ConsoleReportCollector()
--- a/dom/console/ConsoleReportCollector.h +++ b/dom/console/ConsoleReportCollector.h @@ -22,27 +22,31 @@ public: AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory, nsContentUtils::PropertiesFile aPropertiesFile, const nsACString& aSourceFileURI, uint32_t aLineNumber, uint32_t aColumnNumber, const nsACString& aMessageName, const nsTArray<nsString>& aStringParams) override; void + FlushReportsToConsole(uint64_t aInnerWindowID, + ReportAction aAction = ReportAction::Forget) override; + + void FlushConsoleReports(nsIDocument* aDocument, ReportAction aAction = ReportAction::Forget) override; void + FlushConsoleReports(nsILoadGroup* aLoadGroup, + ReportAction aAction = ReportAction::Forget) override; + + void FlushConsoleReports(nsIConsoleReportCollector* aCollector) override; void - FlushReportsByWindowId(uint64_t aWindowId, - ReportAction aAction = ReportAction::Forget) override; - - void ClearConsoleReports() override; private: ~ConsoleReportCollector(); struct PendingReport { PendingReport(uint32_t aErrorFlags, const nsACString& aCategory,
--- a/dom/console/nsIConsoleReportCollector.h +++ b/dom/console/nsIConsoleReportCollector.h @@ -69,47 +69,58 @@ public: // An enum calss to indicate whether should free the pending reports or not. // Forget Free the pending reports. // Save Keep the pending reports. enum class ReportAction { Forget, Save }; + // Flush all pending reports to the console. May be called from any thread. + // + // aInnerWindowID A inner window ID representing where to flush the reports. + // aAction An action to determine whether to reserve the pending + // reports. Defalut action is to forget the report. + virtual void + FlushReportsToConsole(uint64_t aInnerWindowID, + ReportAction aAction = ReportAction::Forget) = 0; + // Flush all pending reports to the console. Main thread only. // // aDocument An optional document representing where to flush the // reports. If provided, then the corresponding window's // web console will get the reports. Otherwise the reports // go to the browser console. // aAction An action to determine whether to reserve the pending // reports. Defalut action is to forget the report. virtual void FlushConsoleReports(nsIDocument* aDocument, ReportAction aAction = ReportAction::Forget) = 0; + // Flush all pending reports to the console. May be called from any thread. + // + // aLoadGroup An optional loadGroup representing where to flush the + // reports. If provided, then the corresponding window's + // web console will get the reports. Otherwise the reports + // go to the browser console. + // aAction An action to determine whether to reserve the pending + // reports. Defalut action is to forget the report. + virtual void + FlushConsoleReports(nsILoadGroup* aLoadGroup, + ReportAction aAction = ReportAction::Forget) = 0; + + // Flush all pending reports to another collector. May be called from any // thread. // // aCollector A required collector object that will effectively take // ownership of our currently console reports. virtual void FlushConsoleReports(nsIConsoleReportCollector* aCollector) = 0; - // Flush all pending reports to the console accroding to window ID. Main - // thread only. - // - // aWindowId A window ID representing where to flush the reports and it's - // typically the inner window ID. - // - // aAction An action to decide whether free the pending reports or not. - virtual void - FlushReportsByWindowId(uint64_t aWindowId, - ReportAction aAction = ReportAction::Forget) = 0; - // Clear all pending reports. virtual void ClearConsoleReports() = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIConsoleReportCollector, NS_NSICONSOLEREPORTCOLLECTOR_IID) #endif // nsIConsoleReportCollector_h
--- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -95,41 +95,41 @@ private: FlushConsoleReport() override; }; class MainThreadFetchResolver final : public FetchDriverObserver { RefPtr<Promise> mPromise; RefPtr<Response> mResponse; - nsCOMPtr<nsIDocument> mDocument; + nsCOMPtr<nsILoadGroup> mLoadGroup; NS_DECL_OWNINGTHREAD public: explicit MainThreadFetchResolver(Promise* aPromise); void OnResponseAvailableInternal(InternalResponse* aResponse) override; - void SetDocument(nsIDocument* aDocument) + void SetLoadGroup(nsILoadGroup* aLoadGroup) { - mDocument = aDocument; + mLoadGroup = aLoadGroup; } virtual void OnResponseEnd() override { FlushConsoleReport(); } private: ~MainThreadFetchResolver(); void FlushConsoleReport() override { - mReporter->FlushConsoleReports(mDocument); + mReporter->FlushConsoleReports(mLoadGroup); } }; class MainThreadFetchRunnable : public Runnable { RefPtr<WorkerFetchResolver> mResolver; RefPtr<InternalRequest> mRequest; @@ -233,17 +233,17 @@ FetchRequest(nsIGlobalObject* aGlobal, c } } Telemetry::Accumulate(Telemetry::FETCH_IS_MAINTHREAD, 1); RefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p); RefPtr<FetchDriver> fetch = new FetchDriver(r, principal, loadGroup); fetch->SetDocument(doc); - resolver->SetDocument(doc); + resolver->SetLoadGroup(loadGroup); aRv = fetch->Fetch(resolver); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } else { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); @@ -448,40 +448,40 @@ WorkerFetchResolver::FlushConsoleReport( MOZ_ASSERT(mPromiseProxy); if(!mReporter) { return; } workers::WorkerPrivate* worker = mPromiseProxy->GetWorkerPrivate(); if (!worker) { - mReporter->FlushConsoleReports((nsIDocument*)nullptr); + mReporter->FlushReportsToConsole(0); return; } if (worker->IsServiceWorker()) { // Flush to service worker RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); if (!swm) { - mReporter->FlushConsoleReports((nsIDocument*)nullptr); + mReporter->FlushReportsToConsole(0); return; } swm->FlushReportsToAllClients(worker->WorkerName(), mReporter); return; } if (worker->IsSharedWorker()) { // Flush to shared worker worker->FlushReportsToSharedWorkers(mReporter); return; } // Flush to dedicated worker - mReporter->FlushConsoleReports(worker->GetDocument()); + mReporter->FlushConsoleReports(worker->GetLoadGroup()); } nsresult ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& aBodyInit, nsIInputStream** aStream, nsCString& aContentTypeWithCharset, uint64_t& aContentLength) {
--- a/dom/file/File.cpp +++ b/dom/file/File.cpp @@ -31,16 +31,17 @@ #include "nsPrintfCString.h" #include "mozilla/SHA1.h" #include "mozilla/CheckedInt.h" #include "mozilla/Preferences.h" #include "mozilla/Attributes.h" #include "mozilla/dom/BlobBinding.h" #include "mozilla/dom/DOMError.h" #include "mozilla/dom/FileBinding.h" +#include "mozilla/dom/FileSystemUtils.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRunnable.h" #include "nsThreadUtils.h" #include "nsStreamUtils.h" #include "SlicedInputStream.h" namespace mozilla { namespace dom { @@ -465,25 +466,28 @@ File::WrapObject(JSContext* aCx, JS::Han void File::GetName(nsAString& aFileName) const { mImpl->GetName(aFileName); } void -File::GetPath(nsAString& aPath) const +File::GetRelativePath(nsAString& aPath) const { - mImpl->GetPath(aPath); -} + aPath.Truncate(); -void -File::SetPath(const nsAString& aPath) -{ - mImpl->SetPath(aPath); + nsAutoString path; + mImpl->GetDOMPath(path); + + // WebkitRelativePath doesn't start with '/' + if (!path.IsEmpty()) { + MOZ_ASSERT(path[0] == FILESYSTEM_DOM_PATH_SEPARATOR_CHAR); + aPath.Assign(Substring(path, 1)); + } } Date File::GetLastModifiedDate(ErrorResult& aRv) { int64_t value = GetLastModified(aRv); if (aRv.Failed()) { return Date(); @@ -665,24 +669,24 @@ NS_IMPL_ISUPPORTS_INHERITED0(BlobImplFil void BlobImplBase::GetName(nsAString& aName) const { MOZ_ASSERT(mIsFile, "Should only be called on files"); aName = mName; } void -BlobImplBase::GetPath(nsAString& aPath) const +BlobImplBase::GetDOMPath(nsAString& aPath) const { MOZ_ASSERT(mIsFile, "Should only be called on files"); aPath = mPath; } void -BlobImplBase::SetPath(const nsAString& aPath) +BlobImplBase::SetDOMPath(const nsAString& aPath) { MOZ_ASSERT(mIsFile, "Should only be called on files"); mPath = aPath; } void BlobImplBase::GetMozFullPath(nsAString& aFileName, SystemCallerGuarantee /* unused */,
--- a/dom/file/File.h +++ b/dom/file/File.h @@ -220,23 +220,17 @@ public: ErrorResult& aRv); void GetName(nsAString& aName) const; int64_t GetLastModified(ErrorResult& aRv); Date GetLastModifiedDate(ErrorResult& aRv); - // GetPath and SetPath are currently used only for the webkitRelativePath - // attribute and they are only used when this File object is created from a - // Directory, generated by a Directory Picker. - - void GetPath(nsAString& aName) const; - - void SetPath(const nsAString& aName); + void GetRelativePath(nsAString& aPath) const; void GetMozFullPath(nsAString& aFilename, SystemCallerGuarantee aGuarantee, ErrorResult& aRv) const; void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv) const; protected: virtual bool HasFileInterface() const override { return true; } @@ -255,19 +249,19 @@ class BlobImpl : public nsISupports public: NS_DECLARE_STATIC_IID_ACCESSOR(BLOBIMPL_IID) NS_DECL_THREADSAFE_ISUPPORTS BlobImpl() {} virtual void GetName(nsAString& aName) const = 0; - virtual void GetPath(nsAString& aName) const = 0; + virtual void GetDOMPath(nsAString& aName) const = 0; - virtual void SetPath(const nsAString& aName) = 0; + virtual void SetDOMPath(const nsAString& aName) = 0; virtual int64_t GetLastModified(ErrorResult& aRv) = 0; virtual void SetLastModified(int64_t aLastModified) = 0; virtual void GetMozFullPath(nsAString& aName, SystemCallerGuarantee /* unused */, ErrorResult& aRv) const = 0; @@ -401,19 +395,19 @@ public: { MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice"); // Ensure non-null mContentType by default mContentType.SetIsVoid(false); } virtual void GetName(nsAString& aName) const override; - virtual void GetPath(nsAString& aName) const override; + virtual void GetDOMPath(nsAString& aName) const override; - virtual void SetPath(const nsAString& aName) override; + virtual void SetDOMPath(const nsAString& aName) override; virtual int64_t GetLastModified(ErrorResult& aRv) override; virtual void SetLastModified(int64_t aLastModified) override; virtual void GetMozFullPath(nsAString& aName, SystemCallerGuarantee /* unused */, ErrorResult& aRv) const override;
--- a/dom/file/ipc/Blob.cpp +++ b/dom/file/ipc/Blob.cpp @@ -2066,20 +2066,20 @@ public: NoteDyingActor(); NS_DECL_ISUPPORTS_INHERITED void GetName(nsAString& aName) const override; void - GetPath(nsAString& aPath) const override; + GetDOMPath(nsAString& aPath) const override; void - SetPath(const nsAString& aPath) override; + SetDOMPath(const nsAString& aPath) override; int64_t GetLastModified(ErrorResult& aRv) override; void SetLastModified(int64_t aLastModified) override; void @@ -2170,27 +2170,27 @@ private: * BlobChild::RemoteBlobImpl ******************************************************************************/ BlobChild:: RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor, BlobImpl* aRemoteBlobImpl, const nsAString& aName, const nsAString& aContentType, - const nsAString& aPath, + const nsAString& aDOMPath, uint64_t aLength, int64_t aModDate, BlobImplIsDirectory aIsDirectory, bool aIsSameProcessBlob) : BlobImplBase(aName, aContentType, aLength, aModDate) , mWorkerPrivate(nullptr) , mMutex("BlobChild::RemoteBlobImpl::mMutex") , mIsSlice(false), mIsDirectory(aIsDirectory == eDirectory) { - SetPath(aPath); + SetDOMPath(aDOMPath); if (aIsSameProcessBlob) { MOZ_ASSERT(aRemoteBlobImpl); mSameProcessBlobImpl = aRemoteBlobImpl; MOZ_ASSERT(gProcessType == GeckoProcessType_Default); } else { mDifferentProcessBlobImpl = aRemoteBlobImpl; } @@ -2838,26 +2838,26 @@ void BlobParent:: RemoteBlobImpl::GetName(nsAString& aName) const { mBlobImpl->GetName(aName); } void BlobParent:: -RemoteBlobImpl::GetPath(nsAString& aPath) const +RemoteBlobImpl::GetDOMPath(nsAString& aPath) const { - mBlobImpl->GetPath(aPath); + mBlobImpl->GetDOMPath(aPath); } void BlobParent:: -RemoteBlobImpl::SetPath(const nsAString& aPath) +RemoteBlobImpl::SetDOMPath(const nsAString& aPath) { - mBlobImpl->SetPath(aPath); + mBlobImpl->SetDOMPath(aPath); } int64_t BlobParent:: RemoteBlobImpl::GetLastModified(ErrorResult& aRv) { return mBlobImpl->GetLastModified(aRv); } @@ -3191,28 +3191,28 @@ BlobChild::CommonInit(BlobChild* aOther, uint64_t length = otherImpl->GetSize(rv); MOZ_ASSERT(!rv.Failed()); RemoteBlobImpl* remoteBlob = nullptr; if (otherImpl->IsFile()) { nsAutoString name; otherImpl->GetName(name); - nsAutoString path; - otherImpl->GetPath(path); + nsAutoString domPath; + otherImpl->GetDOMPath(domPath); int64_t modDate = otherImpl->GetLastModified(rv); MOZ_ASSERT(!rv.Failed()); RemoteBlobImpl::BlobImplIsDirectory directory = otherImpl->IsDirectory() ? RemoteBlobImpl::BlobImplIsDirectory::eDirectory : RemoteBlobImpl::BlobImplIsDirectory::eNotDirectory; remoteBlob = - new RemoteBlobImpl(this, otherImpl, name, contentType, path, + new RemoteBlobImpl(this, otherImpl, name, contentType, domPath, length, modDate, directory, false /* SameProcessBlobImpl */); } else { remoteBlob = new RemoteBlobImpl(this, otherImpl, contentType, length, false /* SameProcessBlobImpl */); } // This RemoteBlob must be kept alive untill RecvCreatedFromKnownBlob is @@ -3286,33 +3286,33 @@ BlobChild::CommonInit(const ChildBlobCon nsString contentType; blobImpl->GetType(contentType); if (blobImpl->IsFile()) { nsAutoString name; blobImpl->GetName(name); - nsAutoString path; - blobImpl->GetPath(path); + nsAutoString domPath; + blobImpl->GetDOMPath(domPath); int64_t lastModifiedDate = blobImpl->GetLastModified(rv); MOZ_ASSERT(!rv.Failed()); RemoteBlobImpl::BlobImplIsDirectory directory = blobImpl->IsDirectory() ? RemoteBlobImpl::BlobImplIsDirectory::eDirectory : RemoteBlobImpl::BlobImplIsDirectory::eNotDirectory; remoteBlob = new RemoteBlobImpl(this, blobImpl, name, contentType, - path, + domPath, size, lastModifiedDate, directory, true /* SameProcessBlobImpl */); } else { remoteBlob = new RemoteBlobImpl(this, blobImpl, contentType, size, true /* SameProcessBlobImpl */); } @@ -3485,24 +3485,24 @@ BlobChild::GetOrCreateFromImpl(ChildMana ErrorResult rv; uint64_t length = aBlobImpl->GetSize(rv); MOZ_ASSERT(!rv.Failed()); if (aBlobImpl->IsFile()) { nsAutoString name; aBlobImpl->GetName(name); - nsAutoString path; - aBlobImpl->GetPath(path); + nsAutoString domPath; + aBlobImpl->GetDOMPath(domPath); int64_t modDate = aBlobImpl->GetLastModified(rv); MOZ_ASSERT(!rv.Failed()); blobParams = - FileBlobConstructorParams(name, contentType, path, length, modDate, + FileBlobConstructorParams(name, contentType, domPath, length, modDate, aBlobImpl->IsDirectory(), blobData); } else { blobParams = NormalBlobConstructorParams(contentType, length, blobData); } } auto* actor = new BlobChild(aManager, aBlobImpl); @@ -4038,24 +4038,24 @@ BlobParent::GetOrCreateFromImpl(ParentMa ErrorResult rv; uint64_t length = aBlobImpl->GetSize(rv); MOZ_ASSERT(!rv.Failed()); if (aBlobImpl->IsFile()) { nsAutoString name; aBlobImpl->GetName(name); - nsAutoString path; - aBlobImpl->GetPath(path); + nsAutoString domPath; + aBlobImpl->GetDOMPath(domPath); int64_t modDate = aBlobImpl->GetLastModified(rv); MOZ_ASSERT(!rv.Failed()); blobParams = - FileBlobConstructorParams(name, contentType, path, length, modDate, + FileBlobConstructorParams(name, contentType, domPath, length, modDate, aBlobImpl->IsDirectory(), void_t()); } else { blobParams = NormalBlobConstructorParams(contentType, length, void_t()); } } } nsID id;
--- a/dom/file/moz.build +++ b/dom/file/moz.build @@ -18,16 +18,17 @@ EXPORTS += [ 'nsHostObjectURI.h', ] EXPORTS.mozilla.dom += [ 'BlobSet.h', 'File.h', 'FileList.h', 'FileReader.h', + 'MultipartBlobImpl.h', 'MutableBlobStorage.h', 'MutableBlobStreamListener.h', ] UNIFIED_SOURCES += [ 'BlobSet.cpp', 'File.cpp', 'FileList.cpp',
--- a/dom/filesystem/GetDirectoryListingTask.cpp +++ b/dom/filesystem/GetDirectoryListingTask.cpp @@ -247,17 +247,17 @@ GetDirectoryListingTaskParent::GetSucces // This is specific for unix root filesystem. if (!mDOMPath.EqualsLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL)) { filePath.AppendLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL); } nsAutoString name; blobImpl->GetName(name); filePath.Append(name); - blobImpl->SetPath(filePath); + blobImpl->SetDOMPath(filePath); fileData.blobParent() = BlobParent::GetOrCreate(mRequestParent->Manager(), blobImpl); inputs.AppendElement(fileData); } else { MOZ_ASSERT(mTargetData[i].mType == FileOrDirectoryPath::eDirectoryPath); FileSystemDirectoryListingResponseDirectory directoryData; directoryData.directoryRealPath() = mTargetData[i].mPath;
--- a/dom/filesystem/GetFilesHelper.cpp +++ b/dom/filesystem/GetFilesHelper.cpp @@ -272,27 +272,27 @@ GetFilesHelper::RunIO() MOZ_ASSERT(!mListingCompleted); nsCOMPtr<nsIFile> file; mErrorResult = NS_NewLocalFile(mDirectoryPath, true, getter_AddRefs(file)); if (NS_WARN_IF(NS_FAILED(mErrorResult))) { return; } - nsAutoString path; - mErrorResult = file->GetLeafName(path); + nsAutoString leafName; + mErrorResult = file->GetLeafName(leafName); if (NS_WARN_IF(NS_FAILED(mErrorResult))) { return; } - if (path.IsEmpty()) { - path.AppendLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL); - } + nsAutoString domPath; + domPath.AssignLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL); + domPath.Append(leafName); - mErrorResult = ExploreDirectory(path, file); + mErrorResult = ExploreDirectory(domPath, file); } void GetFilesHelper::RunMainThread() { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mDirectoryPath.IsEmpty()); MOZ_ASSERT(!mListingCompleted); @@ -379,17 +379,17 @@ GetFilesHelperBase::ExploreDirectory(con nsAutoString leafName; if (NS_WARN_IF(NS_FAILED(currFile->GetLeafName(leafName)))) { continue; } domPath.Append(leafName); if (isFile) { RefPtr<BlobImpl> blobImpl = new BlobImplFile(currFile); - blobImpl->SetPath(domPath); + blobImpl->SetDOMPath(domPath); if (!mTargetBlobImplArray.AppendElement(blobImpl, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } continue; }
--- a/dom/filesystem/compat/FileSystemFileEntry.cpp +++ b/dom/filesystem/compat/FileSystemFileEntry.cpp @@ -2,43 +2,74 @@ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "FileSystemFileEntry.h" #include "CallbackRunnables.h" #include "mozilla/dom/File.h" +#include "mozilla/dom/MultipartBlobImpl.h" #include "mozilla/dom/FileSystemFileEntryBinding.h" namespace mozilla { namespace dom { namespace { class FileCallbackRunnable final : public Runnable { public: - FileCallbackRunnable(FileCallback* aCallback, File* aFile) + FileCallbackRunnable(FileCallback* aCallback, ErrorCallback* aErrorCallback, + File* aFile) : mCallback(aCallback) + , mErrorCallback(aErrorCallback) , mFile(aFile) { MOZ_ASSERT(aCallback); MOZ_ASSERT(aFile); } NS_IMETHOD Run() override { - mCallback->HandleEvent(*mFile); + // Here we clone the File object. + + nsAutoString name; + mFile->GetName(name); + + nsAutoString type; + mFile->GetType(type); + + nsTArray<RefPtr<BlobImpl>> blobImpls; + blobImpls.AppendElement(mFile->Impl()); + + ErrorResult rv; + RefPtr<BlobImpl> blobImpl = + MultipartBlobImpl::Create(Move(blobImpls), name, type, rv); + if (NS_WARN_IF(rv.Failed())) { + if (mErrorCallback) { + RefPtr<DOMException> exception = + DOMException::Create(rv.StealNSResult()); + mErrorCallback->HandleEvent(*exception); + } + + return NS_OK; + } + + RefPtr<File> file = File::Create(mFile->GetParentObject(), blobImpl); + MOZ_ASSERT(file); + + mCallback->HandleEvent(*file); return NS_OK; } private: RefPtr<FileCallback> mCallback; + RefPtr<ErrorCallback> mErrorCallback; RefPtr<File> mFile; }; } // anonymous namespace NS_IMPL_CYCLE_COLLECTION_INHERITED(FileSystemFileEntry, FileSystemEntry, mFile) NS_IMPL_ADDREF_INHERITED(FileSystemFileEntry, FileSystemEntry) @@ -72,17 +103,17 @@ void FileSystemFileEntry::GetName(nsAString& aName, ErrorResult& aRv) const { mFile->GetName(aName); } void FileSystemFileEntry::GetFullPath(nsAString& aPath, ErrorResult& aRv) const { - mFile->GetPath(aPath); + mFile->Impl()->GetDOMPath(aPath); if (aPath.IsEmpty()) { // We're under the root directory. webkitRelativePath // (implemented as GetPath) is for cases when file is selected because its // ancestor directory is selected. But that is not the case here, so need to // manually prepend '/'. nsAutoString name; mFile->GetName(name); aPath.AssignLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL); @@ -90,15 +121,18 @@ FileSystemFileEntry::GetFullPath(nsAStri } } void FileSystemFileEntry::GetFile(FileCallback& aSuccessCallback, const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const { RefPtr<FileCallbackRunnable> runnable = - new FileCallbackRunnable(&aSuccessCallback, mFile); + new FileCallbackRunnable(&aSuccessCallback, + aErrorCallback.WasPassed() + ? &aErrorCallback.Value() : nullptr, + mFile); DebugOnly<nsresult> rv = NS_DispatchToMainThread(runnable); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed"); } } // dom namespace } // mozilla namespace
--- a/dom/filesystem/compat/tests/test_basic.html +++ b/dom/filesystem/compat/tests/test_basic.html @@ -403,16 +403,35 @@ function test_getParent(entry, parentEnt } else { test_getParent(e, parentEntry, false); } }, function(e) { ok(false, "This should not happen."); }); } +function test_webkitRelativePath() { + fileEntry.file(function(file1) { + ok(file1, "We have a file here!"); + ok(!file1.webkitRelativePath, "webkitRelativePath is an empty string"); + + fileEntry.file(function(file2) { + ok(file2, "We have a file here!"); + ok(!file2.webkitRelativePath, "webkitRelativePath is an empty string"); + isnot(file1, file2, "The 2 files are not the same"); + + next(); + }, function() { + ok(false, "Something when wrong!"); + }); + }, function() { + ok(false, "Something when wrong!"); + }); +} + var tests = [ setup_tests, populate_entries, test_entries, test_fileEntry, test_fileEntry_file, @@ -447,16 +466,18 @@ var tests = [ test_root_getDirectory_securityError, test_root_getDirectory_typeMismatchError, test_root_getDirectory_nonValidPath, test_root_getDirectory_nonExistingPath, test_root_getDirectory_simple, test_root_getDirectory_deep, + test_webkitRelativePath, + cleanUpTestingFiles, ]; function next() { if (!tests.length) { SimpleTest.finish(); return; }
--- a/dom/filesystem/tests/filesystem_commons.js +++ b/dom/filesystem/tests/filesystem_commons.js @@ -1,12 +1,18 @@ function createPath(parentDir, dirOrFile) { return parentDir.path + (parentDir.path == '/' ? '' : '/') + dirOrFile.name; } +function createRelativePath(parentDir, dirOrFile) { + let path = createPath(parentDir, dirOrFile); + is(path[0], "/", "The full path should start with '/'"); + return path.substring(1); +} + function setup_tests(aNext) { SimpleTest.requestLongerTimeout(2); SpecialPowers.pushPrefEnv({"set": [["dom.input.dirpicker", true], ["dom.webkitBlink.dirPicker.enabled", true]]}, aNext); } function test_basic(aDirectory, aNext) { ok(aDirectory, "Directory exists."); @@ -24,17 +30,17 @@ function test_getFilesAndDirectories(aDi if (data[i] instanceof Directory) { isnot(data[i].name, '/', "Subdirectory should be called with the leafname"); isnot(data[i].path, '/', "Subdirectory path should be called with the leafname"); isnot(data[i].path, dir.path, "Subdirectory path should contain the parent path."); is(data[i].path, createPath(dir, data[i]), "Subdirectory path should be called parentdir.path + '/' + leafname: " + data[i].path); } if (data[i] instanceof File) { - is(data[i].webkitRelativePath, createPath(dir, data[i]), "File.webkitRelativePath should be called: parentdir.path + '/' + file.name: " + data[i].webkitRelativePath); + is(data[i].webkitRelativePath, createRelativePath(dir, data[i]), "File.webkitRelativePath should be called: parentdir.path + '/' + file.name: " + data[i].webkitRelativePath); } } } ); } aDirectory.getFilesAndDirectories().then( function(data) { @@ -46,34 +52,35 @@ function test_getFilesAndDirectories(aDi isnot(data[i].name, '/', "Subdirectory should be called with the leafname"); is(data[i].path, createPath(aDirectory, data[i]), "Subdirectory path should be called parentdir.path + '/' + leafname: " + data[i].path); if (aRecursive) { promises.push(checkSubDir(data[i])); } } if (data[i] instanceof File) { - is(data[i].webkitRelativePath, createPath(aDirectory, data[i]), "File.webkitRelativePath should be called '/' + file.name: " + data[i].webkitRelativePath); + is(data[i].webkitRelativePath, createRelativePath(aDirectory, data[i]), "File.webkitRelativePath should be called file.name: " + data[i].webkitRelativePath); } } return Promise.all(promises); }, function() { ok(false, "Something when wrong"); } ).then(aNext); } function test_getFiles(aDirectory, aRecursive, aNext) { aDirectory.getFiles(aRecursive).then( function(data) { for (var i = 0; i < data.length; ++i) { ok(data[i] instanceof File, "File: " + data[i].name); - ok(data[i].webkitRelativePath.indexOf(aDirectory.path) == 0 && + is(aDirectory.path[0], '/', "Directory path must start with '/'"); + ok(data[i].webkitRelativePath.indexOf(aDirectory.path.substring(1)) == 0 && data[i].webkitRelativePath.indexOf('/' + data[i].name) + ('/' + data[i].name).length == data[i].webkitRelativePath.length, "File.webkitRelativePath should be called dir.path + '/' + file.name: " + data[i].webkitRelativePath); } }, function() { ok(false, "Something when wrong"); } ).then(aNext);
--- a/dom/html/HTMLFormSubmission.cpp +++ b/dom/html/HTMLFormSubmission.cpp @@ -506,21 +506,21 @@ FSMultipartFormData::AddNameBlobOrNullPa nsAutoCString contentType; nsCOMPtr<nsIInputStream> fileStream; if (aBlob) { nsAutoString filename16; RefPtr<File> file = aBlob->ToFile(); if (file) { - nsAutoString path; - file->GetPath(path); + nsAutoString relativePath; + file->GetRelativePath(relativePath); if (Directory::WebkitBlinkDirectoryPickerEnabled(nullptr, nullptr) && - !path.IsEmpty()) { - filename16 = path; + !relativePath.IsEmpty()) { + filename16 = relativePath; } if (filename16.IsEmpty()) { RetrieveFileName(aBlob, filename16); } } rv = EncodeVal(filename16, filename, true);
--- a/dom/indexedDB/FileSnapshot.h +++ b/dom/indexedDB/FileSnapshot.h @@ -55,25 +55,25 @@ private: // BlobImpl virtual void GetName(nsAString& aName) const override { mBlobImpl->GetName(aName); } virtual void - GetPath(nsAString& aPath) const override + GetDOMPath(nsAString& aPath) const override { - mBlobImpl->GetPath(aPath); + mBlobImpl->GetDOMPath(aPath); } virtual void - SetPath(const nsAString& aPath) override + SetDOMPath(const nsAString& aPath) override { - mBlobImpl->SetPath(aPath); + mBlobImpl->SetDOMPath(aPath); } virtual int64_t GetLastModified(ErrorResult& aRv) override { return mBlobImpl->GetLastModified(aRv); }
--- a/dom/security/test/contentverifier/browser.ini +++ b/dom/security/test/contentverifier/browser.ini @@ -11,11 +11,9 @@ support-files = file_about_newtab_sri.html file_about_newtab_sri_signature goodChain.pem head.js script.js style.css [browser_verify_content_about_newtab.js] -skip-if = true # This started permafailing randomly (Bug 1336654) [browser_verify_content_about_newtab2.js] -skip-if = true # This started permafailing randomly (Bug 1336654)
--- a/dom/security/test/contentverifier/file_about_newtab_good_signature +++ b/dom/security/test/contentverifier/file_about_newtab_good_signature @@ -1,1 +1,1 @@ --mqpvTYdZX4HYQDW1nScojL7ICw5yj8UF2gzxyLbSCx9UIfHH-gWZ40F_PFtqjHxoC1J3dHDb3VedVhOYczdaLrNKbRvPrlnkdGx7Rl8qEBrtZpF1py1Z9uAGoCrgUHa \ No newline at end of file +HUndgHvxHNMiAe1SXoeyOOraUJCdxHqWkAYTu0Cq1KpAHcWZEVelNTvyXGbTLWj8btsmqNLAm08UlyK43q_2oO9DQfez3Fo8DhsKvm7TqgSXCkhUoxsYNanxWXhqw-Jw \ No newline at end of file
--- a/dom/security/test/contentverifier/goodChain.pem +++ b/dom/security/test/contentverifier/goodChain.pem @@ -1,51 +1,51 @@ -----BEGIN CERTIFICATE----- -MIICUzCCAT2gAwIBAgIUNy0IWlDRDL53zwvj1lq0GCpIe2EwCwYJKoZIhvcNAQEL -MBExDzANBgNVBAMMBmludC1DQTAiGA8yMDE0MTEyNzAwMDAwMFoYDzIwMTcwMjA0 +MIICUzCCAT2gAwIBAgIUJ1BtYqWRwUsVaZCGPp9eTHIC04QwCwYJKoZIhvcNAQEL +MBExDzANBgNVBAMMBmludC1DQTAiGA8yMDE1MTEyODAwMDAwMFoYDzIwMTgwMjA1 MDAwMDAwWjAUMRIwEAYDVQQDDAllZS1pbnQtQ0EwdjAQBgcqhkjOPQIBBgUrgQQA IgNiAAShaHJDNitcexiJ83kVRhWhxz+0je6GPgIpFdtgjiUt5LcTLajOmOgxU05q nAwLCcjWOa3oMgbluoE0c6EfozDgXajJbkOD/ieHPalxA74oiM/wAvBa9xof3cyD dKpuqc6jTjBMMBMGA1UdJQQMMAoGCCsGAQUFBwMDMDUGA1UdEQQuMCyCKnJlbW90 ZW5ld3RhYi5jb250ZW50LXNpZ25hdHVyZS5tb3ppbGxhLm9yZzALBgkqhkiG9w0B -AQsDggEBAIeB4WKghknsrow+lj3qzDiHrPBc9AMlb4aZvS6yzazmXr80rXxnsKkb -ZV1PW/cU6xXH5srWHpfJwypvvYS74btNtuacjKVH2AJdua4482WQIi9gCkXIufRx -2nSS6pYgYZ4vD+yG8v+3SCChOCXnLjRaN9WxMi8tldbOW9pH44O3vrSSL70pQ2Ph -8ncUbUbCNNtYhtOe2Z4XT9Cswmfkf4OIQ3gy9eYK2ySEUWP+lHs9KnnNXrLcA/ae -cSUdI00i3C3OS9yldeyNHzVb8mSsZ5d1WkJrkf/hnXWGrMHRTtlJlG7t7cN8S0Oi -tQoinJyxrZ+zabFIyl/euDc+Y/dijOU= +AQsDggEBALiLck6k50ok9ahVq45P3feY1PeUXcIYZkJd8aPDYM+0kfg5+JyJBykA +mtHWPE1QQjs7VRMfaLfu04E4UJMI2V1AON1qtgR9BQLctW85KFACg2omfiCKwJh0 +5Q8cxBFx9BpNMayqLJwHttB6oluxZFTB8CL/hfpbYpHz1bMEDCVSRP588YBrc8mV +OLqzQK+k3ewwGvfD6SvXmTny37MxqwxdTPFJNnpqzKAsQIvz8Skic9BkA1NFk0Oq +lsKKoiibbOCmwS9XY/laAkBaC3winuhciYAC0ImAopZ4PBCU0AOHGrNbhZXWYQxt +uHBj34FqvIRCqgM06JCEwN0ULgix4kI= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIC0TCCAbugAwIBAgIULYyr3v/0zZ+XiR22NH7hOcnj2FcwCwYJKoZIhvcNAQEL -MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw +MIIC0TCCAbugAwIBAgIUPcKbBQpKwTzrrlqzM+d3z5DWiNUwCwYJKoZIhvcNAQEL +MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw MDBaMBExDzANBgNVBAMMBmludC1DQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72x nAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sgw0nk27lM wmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9uYhheZCxV5A90jvF 4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20 yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xx j5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAAaMlMCMwDAYDVR0TBAUwAwEB/zAT -BgNVHSUEDDAKBggrBgEFBQcDAzALBgkqhkiG9w0BAQsDggEBADfRBKSM08JF6vqz -0EA+KNc0XIEAWApuHuwX6XXWeLgo6QN4E/9qfrsaO+C366WT+JDsjDOi40wW46SA -XbguxtZQeZasNDUWp/leZix4RSJoHB7OllG1rgZJfN76zKVaXRGUmyQObkMMOJZe -wIA0OBURT8ik9Z89pD0IWrqscds71Edfjt0hHgg63wVvIaklReZXvFOD3VmSCPNn -2wB6ZzECcbhJpnzxZdsoMSGH0C6apYnNNTjqZjO90JVm/Ph/7nbi/KncYXA6ccl6 -Jz2mfiAquWIua2+CzBGbqjZVSATTpWCp+cXQJE1xka+hWUaL5HPTq1bTULRFlauZ -HGl5lJk= +BgNVHSUEDDAKBggrBgEFBQcDAzALBgkqhkiG9w0BAQsDggEBADDPjITgz8joxLRW +wpLxELKSgO/KQ6iAXztjMHq9ovT7Fy0fqBnQ1mMVFr+sBXLgtUCM45aip6PjhUXc +zs5Dq5STg+kz7qtmAjEQvOPcyictbgdu/K7+uMhXQhlzhOgyW88Uk5vrAezNTc/e +TvSmWp1FcgVAfaeMN/90nzD1KIHoUt7zqZIz9ub8jXPVzQNZq4vh33smZhmbdTdV +DaHUyef5cR1VTEGB+L1qzUIQqpHmD4UkMNP1nYedWfauiQhRt6Ql3rJSCRuEvsOA +iBTJlwai/EFwfyfHkOV2GNgv+A5wHHEjBtF5c4PCxQEL5Vw+mfZHLsDVqF3279ZY +lQ6jQ9g= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIICzTCCAbegAwIBAgIUIVkGGA8HiO3RIKGjdOjVi+d6EVkwCwYJKoZIhvcNAQEL -MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw +MIICzTCCAbegAwIBAgIUKRLJoCmk0A6PHrNc8CxFn//4BYcwCwYJKoZIhvcNAQEL +MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTUxMTI4MDAwMDAwWhgPMjAxODAyMDUwMDAw MDBaMA0xCzAJBgNVBAMMAmNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAuohRqESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptu Gobya+KvWnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO 7RWCD/F+rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgf qDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/yt HSXTCe+5Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcx uLP+SSP6clHEMdUDrNoYCjXtjQIDAQABoyUwIzAMBgNVHRMEBTADAQH/MBMGA1Ud -JQQMMAoGCCsGAQUFBwMDMAsGCSqGSIb3DQEBCwOCAQEAlpbRzRIPnf43AwGfMvKP -zOtntRy2nE9GlmY9I00uioHUnUrPLs8aw3UDtyiDWMGqcYysXGx9EX2Vk0POS4gf -G6PA95F6GxTtbzIEZmTPVuzA/cfc9HU3HXDPqh+dySJ8/Ta4c4vX1lgeGGAvstNe -q+9DaCGXs8MqMF8KtXNmOm3eS9q622hKEvTVEoxqj1t365kwKHaNpbObddQ6Xcny -akvfh2L+8QbJSflcm8fL/JTup/2/cRG1ytOsaiXEr9JBEITOtQO0Ot/4Qzq+MJjv -weaJ3hZ0c+cTy3tEvt+I7+lnW4Q5dB7aLR2/BZfLubhxz1SUVMuHfLH64fc0Uf1Q -Nw== +JQQMMAoGCCsGAQUFBwMDMAsGCSqGSIb3DQEBCwOCAQEAABgMK6EyVIXTjD5qaxPO +DWz6yREACmAQBcowKWvfhwgi27DPSXyFGDbzTPEo+7RrIcXJkVAhLouGT51fCwTZ +zb6Sgf6ztX7VSppY9AT4utvlZKP1xQ5WhIYsMtdHCHLHIkRjeWyoBEfUx50UXNLK +Snl+A02GKYWiX+TLLg2DPN2s7v/mm8NLMQNgUlL7KakB2FHFyPa8otPpL4llg7UJ +iBTVQ0c3JoiVbwZaY1Z8QinfMXUrTK9egUC4BAcId1dE8glzA5RRlw1fTLWpGApt +hUmbDnl9N2a9NhGX323ypNzIATexafipzWe7bc4u/+bFdrUqnKUoEka73pZBdHdA +FQ== -----END CERTIFICATE-----
--- a/dom/security/test/contentverifier/head.js +++ b/dom/security/test/contentverifier/head.js @@ -78,17 +78,17 @@ function* doTest(aExpectedStrings, reloa aboutNewTabService.newTabURL = aNewTabPref; } // set prefs yield pushPrefs( ["browser.newtabpage.remote.content-signing-test", true], ["browser.newtabpage.remote", true], ["security.content.signature.root_hash", - "65:AE:D8:1E:B5:12:AE:B0:6B:38:58:BC:7C:47:35:3D:D4:EA:25:F1:63:DA:08:BB:86:3A:2E:97:39:66:8F:55"]); + "CC:BE:04:87:74:B2:98:24:4A:C6:7A:71:BC:6F:DB:D6:C0:48:17:29:57:51:96:47:38:CC:24:C8:E4:F9:DD:CB"]); if (aNewTabPref === URI_BAD_CSP) { // Use stricter CSP to test CSP violation. yield pushPrefs(["security.signed_content.CSP.default", "script-src 'self'; style-src 'self'"]); } else { // Use weaker CSP to test normal content. yield pushPrefs(["security.signed_content.CSP.default", "script-src 'self' 'unsafe-inline'; style-src 'self'"]); }
--- a/dom/webidl/File.webidl +++ b/dom/webidl/File.webidl @@ -28,17 +28,17 @@ dictionary ChromeFilePropertyBag : FileP DOMString name = ""; }; // Mozilla extensions partial interface File { [GetterThrows, Deprecated="FileLastModifiedDate"] readonly attribute Date lastModifiedDate; - [BinaryName="path", Func="mozilla::dom::Directory::WebkitBlinkDirectoryPickerEnabled"] + [BinaryName="relativePath", Func="mozilla::dom::Directory::WebkitBlinkDirectoryPickerEnabled"] readonly attribute USVString webkitRelativePath; [GetterThrows, ChromeOnly, NeedsCallerType] readonly attribute DOMString mozFullPath; [ChromeOnly, Throws, NeedsCallerType] static File createFromNsIFile(nsIFile file, optional ChromeFilePropertyBag options);
--- a/dom/workers/ServiceWorkerContainer.cpp +++ b/dom/workers/ServiceWorkerContainer.cpp @@ -44,17 +44,17 @@ ServiceWorkerContainer::IsEnabled(JSCont JS::Rooted<JSObject*> global(aCx, aGlobal); nsCOMPtr<nsPIDOMWindowInner> window = Navigator::GetWindowFromGlobal(global); if (!window) { return false; } nsIDocument* doc = window->GetExtantDoc(); - if (!doc || doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId) { + if (!doc || nsContentUtils::IsInPrivateBrowsing(doc)) { return false; } return Preferences::GetBool("dom.serviceWorkers.enabled", false); } ServiceWorkerContainer::ServiceWorkerContainer(nsPIDOMWindowInner* aWindow) : DOMEventTargetHelper(aWindow)
--- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -1649,20 +1649,21 @@ ServiceWorkerManager::FlushReportsToAllC continue; } nsCOMPtr<nsIDocument> doc = do_QueryInterface(iter.Key()); if (!doc || !doc->IsCurrentActiveDocument() || !doc->GetWindow()) { continue; } - windows.AppendElement(doc->InnerWindowID()); - - aReporter->FlushConsoleReports(doc, - nsIConsoleReportCollector::ReportAction::Save); + uint64_t innerWindowId = doc->InnerWindowID(); + windows.AppendElement(innerWindowId); + + aReporter->FlushReportsToConsole( + innerWindowId, nsIConsoleReportCollector::ReportAction::Save); } // Report to any documents that have called .register() for this scope. They // may not be controlled, but will still want to see error reports. WeakDocumentList* regList = mRegisteringDocuments.Get(aScope); if (regList) { for (int32_t i = regList->Length() - 1; i >= 0; --i) { nsCOMPtr<nsIDocument> doc = do_QueryReferent(regList->ElementAt(i)); @@ -1677,18 +1678,18 @@ ServiceWorkerManager::FlushReportsToAllC uint64_t innerWindowId = doc->InnerWindowID(); if (windows.Contains(innerWindowId)) { continue; } windows.AppendElement(innerWindowId); - aReporter->FlushConsoleReports(doc, - nsIConsoleReportCollector::ReportAction::Save); + aReporter->FlushReportsToConsole( + innerWindowId, nsIConsoleReportCollector::ReportAction::Save); } if (regList->IsEmpty()) { regList = nullptr; nsAutoPtr<WeakDocumentList> doomed; mRegisteringDocuments.RemoveAndForget(aScope, doomed); } } @@ -1707,25 +1708,25 @@ ServiceWorkerManager::FlushReportsToAllC uint64_t innerWindowId = nsContentUtils::GetInnerWindowID(inner); if (innerWindowId == 0 || windows.Contains(innerWindowId)) { continue; } windows.AppendElement(innerWindowId); - aReporter->FlushReportsByWindowId(innerWindowId, - nsIConsoleReportCollector::ReportAction::Save); + aReporter->FlushReportsToConsole( + innerWindowId, nsIConsoleReportCollector::ReportAction::Save); } } // If there are no documents to report to, at least report something to the // browser console. if (windows.IsEmpty()) { - aReporter->FlushConsoleReports((nsIDocument*)nullptr); + aReporter->FlushReportsToConsole(0); return; } aReporter->ClearConsoleReports(); } void ServiceWorkerManager::HandleError(JSContext* aCx, @@ -2555,17 +2556,17 @@ ServiceWorkerManager::IsAvailable(nsIPri return registration && registration->GetActive(); } bool ServiceWorkerManager::IsControlled(nsIDocument* aDoc, ErrorResult& aRv) { MOZ_ASSERT(aDoc); - if (aDoc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId) { + if (nsContentUtils::IsInPrivateBrowsing(aDoc)) { // Handle the case where a service worker was previously registered in // a non-private window (bug 1255621). return false; } RefPtr<ServiceWorkerRegistrationInfo> registration; nsresult rv = GetDocumentRegistration(aDoc, getter_AddRefs(registration)); if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)) {
--- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3730,25 +3730,26 @@ WorkerPrivateParent<Derived>::FlushRepor } bool reportErrorToBrowserConsole = true; // Flush the reports. for (uint32_t index = 0; index < windowActions.Length(); index++) { WindowAction& windowAction = windowActions[index]; - aReporter->FlushConsoleReports(windowAction.mWindow->GetExtantDoc(), - nsIConsoleReportCollector::ReportAction::Save); + aReporter->FlushReportsToConsole( + windowAction.mWindow->WindowID(), + nsIConsoleReportCollector::ReportAction::Save); reportErrorToBrowserConsole = false; } // Finally report to broswer console if there is no any window or shared // worker. if (reportErrorToBrowserConsole) { - aReporter->FlushConsoleReports((nsIDocument*)nullptr); + aReporter->FlushReportsToConsole(0); return; } aReporter->ClearConsoleReports(); } template <class Derived> NS_IMPL_ADDREF_INHERITED(WorkerPrivateParent<Derived>, DOMEventTargetHelper)
new file mode 100644 --- /dev/null +++ b/embedding/moz.build @@ -0,0 +1,3 @@ +with Files("**"): + BUG_COMPONENT = ("Core", "General") +
--- a/gfx/skia/skia/src/ports/SkScalerContext_win_dw.cpp +++ b/gfx/skia/skia/src/ports/SkScalerContext_win_dw.cpp @@ -677,20 +677,23 @@ static void bilevel_to_bw(const uint8_t* template<bool APPLY_PREBLEND> static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) { const size_t dstRB = glyph.rowBytes(); const U16CPU width = glyph.fWidth; uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage); for (U16CPU y = 0; y < glyph.fHeight; y++) { for (U16CPU i = 0; i < width; i++) { - U8CPU r = *(src++); - U8CPU g = *(src++); - U8CPU b = *(src++); - dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8); + U8CPU g = src[1]; + src += 3; + + // Ignore the R, B channels. It looks the closest to what + // D2D with grayscale AA has. But there's no way + // to just get a grayscale AA alpha texture from a glyph run. + dst[i] = sk_apply_lut_if<APPLY_PREBLEND>(g, table8); } dst = (uint8_t*)((char*)dst + dstRB); } } template<bool APPLY_PREBLEND, bool RGB> static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
--- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -2068,25 +2068,25 @@ gfxFont::Draw(const gfxTextRun *aTextRun if (aTextRun->UseCenterBaseline()) { gfxPoint baseAdj(0, (metrics.emAscent - metrics.emDescent) / 2); mat.Translate(baseAdj); } aRunParams.context->SetMatrix(mat); } - UniquePtr<SVGContextPaint> contextPaint; + RefPtr<SVGContextPaint> contextPaint; if (fontParams.haveSVGGlyphs && !fontParams.contextPaint) { // If no pattern is specified for fill, use the current pattern NS_ASSERTION((int(aRunParams.drawMode) & int(DrawMode::GLYPH_STROKE)) == 0, "no pattern supplied for stroking text"); RefPtr<gfxPattern> fillPattern = aRunParams.context->GetPattern(); - contextPaint.reset( + contextPaint = new SimpleTextContextPaint(fillPattern, nullptr, - aRunParams.context->CurrentMatrix())); + aRunParams.context->CurrentMatrix()); fontParams.contextPaint = contextPaint.get(); } // Synthetic-bold strikes are each offset one device pixel in run direction. // (these values are only needed if IsSyntheticBold() is true) if (IsSyntheticBold()) { double xscale = CalcXScale(aRunParams.context->GetDrawTarget()); fontParams.synBoldOnePixelOffset = aRunParams.direction * xscale;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "webrender" +version = "0.11.1" +authors = ["Glenn Watson <gw@intuitionlibrary.com>"] +license = "MPL-2.0" +repository = "https://github.com/servo/webrender" +build = "build.rs" +workspace = ".." + +[features] +default = ["codegen", "freetype-lib"] +codegen = ["webrender_traits/codegen"] +freetype-lib = ["freetype/servo-freetype-sys"] +serde_derive = ["webrender_traits/serde_derive"] + +[dependencies] +app_units = "0.3" +bincode = "0.6" +bit-set = "0.4" +byteorder = "0.5" +euclid = "0.10.3" +fnv="1.0" +gleam = "0.2.30" +lazy_static = "0.2" +log = "0.3" +num-traits = "0.1.32" +offscreen_gl_context = {version = "0.5", features = ["serde_serialization", "osmesa"]} +time = "0.1" +threadpool = "1.3.2" +webrender_traits = {path = "../webrender_traits", default-features = false} +bitflags = "0.7" + +[dev-dependencies] +angle = {git = "https://github.com/servo/angle", branch = "servo"} + +[target.'cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))'.dependencies] +freetype = { version = "0.2", default-features = false } + +[target.'cfg(target_os = "windows")'.dependencies] +dwrote = "0.1.5" + +[target.'cfg(target_os = "macos")'.dependencies] +core-graphics = "0.5.0" +core-text = "2.0"
new file mode 100644 --- /dev/null +++ b/gfx/webrender/build.rs @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::env; +use std::path::{Path, PathBuf}; +use std::io::prelude::*; +use std::fs::{canonicalize, read_dir, File}; + +fn write_shaders(glsl_files: Vec<PathBuf>, shader_file_path: &Path) { + let mut shader_file = File::create(shader_file_path).unwrap(); + + write!(shader_file, "/// AUTO GENERATED BY build.rs\n\n").unwrap(); + write!(shader_file, "use std::collections::HashMap;\n").unwrap(); + write!(shader_file, "lazy_static! {{\n").unwrap(); + write!(shader_file, " pub static ref SHADERS: HashMap<&'static str, &'static str> = {{\n").unwrap(); + write!(shader_file, " let mut h = HashMap::with_capacity({});\n", glsl_files.len()).unwrap(); + for glsl in glsl_files { + let shader_name = glsl.file_name().unwrap().to_str().unwrap(); + // strip .glsl + let shader_name = shader_name.replace(".glsl", ""); + let full_path = canonicalize(&glsl).unwrap(); + let full_name = full_path.as_os_str().to_str().unwrap(); + // if someone is building on a network share, I'm sorry. + let full_name = full_name.replace("\\\\?\\", ""); + let full_name = full_name.replace("\\", "/"); + write!(shader_file, " h.insert(\"{}\", include_str!(\"{}\"));\n", + shader_name, full_name).unwrap(); + } + write!(shader_file, " h\n").unwrap(); + write!(shader_file, " }};\n").unwrap(); + write!(shader_file, "}}\n").unwrap(); +} + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap_or("out".to_owned()); + + let shaders_file = Path::new(&out_dir).join("shaders.rs"); + let mut glsl_files = vec![]; + + println!("cargo:rerun-if-changed=res"); + let res_dir = Path::new("res"); + for entry in read_dir(res_dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + + if entry.file_name().to_str().unwrap().ends_with(".glsl") { + println!("cargo:rerun-if-changed={}", path.display()); + glsl_files.push(path.to_owned()); + } + } + + write_shaders(glsl_files, &shaders_file); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/clip_shared.glsl @@ -0,0 +1,91 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifdef WR_VERTEX_SHADER + +#define SEGMENT_ALL 0 +#define SEGMENT_CORNER_TL 1 +#define SEGMENT_CORNER_TR 2 +#define SEGMENT_CORNER_BL 3 +#define SEGMENT_CORNER_BR 4 + +in int aClipRenderTaskIndex; +in int aClipLayerIndex; +in int aClipDataIndex; +in int aClipSegmentIndex; + +struct CacheClipInstance { + int render_task_index; + int layer_index; + int data_index; + int segment_index; +}; + +CacheClipInstance fetch_clip_item(int index) { + CacheClipInstance cci; + + cci.render_task_index = aClipRenderTaskIndex; + cci.layer_index = aClipLayerIndex; + cci.data_index = aClipDataIndex; + cci.segment_index = aClipSegmentIndex; + + return cci; +} + +// The transformed vertex function that always covers the whole clip area, +// which is the intersection of all clip instances of a given primitive +TransformVertexInfo write_clip_tile_vertex(vec4 local_clip_rect, + Layer layer, + ClipArea area, + int segment_index) { + vec2 lp0_base = local_clip_rect.xy; + vec2 lp1_base = local_clip_rect.xy + local_clip_rect.zw; + + vec2 lp0 = clamp_rect(lp0_base, layer.local_clip_rect); + vec2 lp1 = clamp_rect(lp1_base, layer.local_clip_rect); + vec4 clipped_local_rect = vec4(lp0, lp1 - lp0); + + vec2 outer_p0 = area.screen_origin_target_index.xy; + vec2 outer_p1 = outer_p0 + area.task_bounds.zw - area.task_bounds.xy; + vec2 inner_p0 = area.inner_rect.xy; + vec2 inner_p1 = area.inner_rect.zw; + + vec2 p0, p1; + switch (segment_index) { + case SEGMENT_ALL: + p0 = outer_p0; + p1 = outer_p1; + break; + case SEGMENT_CORNER_TL: + p0 = outer_p0; + p1 = inner_p0; + break; + case SEGMENT_CORNER_BL: + p0 = vec2(outer_p0.x, outer_p1.y); + p1 = vec2(inner_p0.x, inner_p1.y); + break; + case SEGMENT_CORNER_TR: + p0 = vec2(outer_p1.x, outer_p1.y); + p1 = vec2(inner_p1.x, inner_p1.y); + break; + case SEGMENT_CORNER_BR: + p0 = vec2(outer_p1.x, outer_p0.y); + p1 = vec2(inner_p1.x, inner_p0.y); + break; + } + + vec2 actual_pos = mix(p0, p1, aPosition.xy); + + vec4 layer_pos = get_layer_pos(actual_pos / uDevicePixelRatio, layer); + + // compute the point position in side the layer, in CSS space + vec2 vertex_pos = actual_pos + area.task_bounds.xy - area.screen_origin_target_index.xy; + + gl_Position = uTransform * vec4(vertex_pos, 0.0, 1); + + return TransformVertexInfo(layer_pos.xyw, actual_pos, clipped_local_rect); +} + +#endif //WR_VERTEX_SHADER
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_blur.fs.glsl @@ -0,0 +1,40 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// TODO(gw): Write a fast path blur that handles smaller blur radii +// with a offset / weight uniform table and a constant +// loop iteration count! + +// TODO(gw): Make use of the bilinear sampling trick to reduce +// the number of texture fetches needed for a gaussian blur. + +float gauss(float x, float sigma) { + return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma)); +} + +void main(void) { + vec4 cache_sample = texture(sCache, vUv); + vec4 color = vec4(cache_sample.rgb, 1.0) * (cache_sample.a * gauss(0.0, vSigma)); + + for (int i=1 ; i < vBlurRadius ; ++i) { + vec2 offset = vec2(float(i)) * vOffsetScale; + + vec2 st0 = clamp(vUv.xy + offset, vUvRect.xy, vUvRect.zw); + vec4 color0 = texture(sCache, vec3(st0, vUv.z)); + + vec2 st1 = clamp(vUv.xy - offset, vUvRect.xy, vUvRect.zw); + vec4 color1 = texture(sCache, vec3(st1, vUv.z)); + + // Alpha must be premultiplied in order to properly blur the alpha channel. + float weight = gauss(float(i), vSigma); + color += vec4(color0.rgb * color0.a, color0.a) * weight; + color += vec4(color1.rgb * color1.a, color1.a) * weight; + } + + // Unpremultiply the alpha. + color.rgb /= color.a; + + oFragColor = color; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_blur.glsl @@ -0,0 +1,10 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec3 vUv; +flat varying vec4 vUvRect; +flat varying vec2 vOffsetScale; +flat varying float vSigma; +flat varying int vBlurRadius;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_blur.vs.glsl @@ -0,0 +1,65 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Applies a separable gaussian blur in one direction, as specified +// by the dir field in the blur command. + +#define DIR_HORIZONTAL 0 +#define DIR_VERTICAL 1 + +in int aBlurRenderTaskIndex; +in int aBlurSourceTaskIndex; +in int aBlurDirection; + +struct BlurCommand { + int task_id; + int src_task_id; + int dir; +}; + +BlurCommand fetch_blur() { + BlurCommand blur; + + blur.task_id = aBlurRenderTaskIndex; + blur.src_task_id = aBlurSourceTaskIndex; + blur.dir = aBlurDirection; + + return blur; +} + +void main(void) { + BlurCommand cmd = fetch_blur(); + RenderTaskData task = fetch_render_task(cmd.task_id); + RenderTaskData src_task = fetch_render_task(cmd.src_task_id); + + vec4 local_rect = task.data0; + + vec2 pos = mix(local_rect.xy, + local_rect.xy + local_rect.zw, + aPosition.xy); + + vec2 texture_size = vec2(textureSize(sCache, 0).xy); + vUv.z = src_task.data1.x; + vBlurRadius = int(task.data1.y); + vSigma = task.data1.y * 0.5; + + switch (cmd.dir) { + case DIR_HORIZONTAL: + vOffsetScale = vec2(1.0 / texture_size.x, 0.0); + break; + case DIR_VERTICAL: + vOffsetScale = vec2(0.0, 1.0 / texture_size.y); + break; + } + + vUvRect = vec4(src_task.data0.xy, src_task.data0.xy + src_task.data0.zw); + vUvRect /= texture_size.xyxy; + + vec2 uv0 = src_task.data0.xy / texture_size; + vec2 uv1 = (src_task.data0.xy + src_task.data0.zw) / texture_size; + vUv.xy = mix(uv0, uv1, aPosition.xy); + + gl_Position = uTransform * vec4(pos, 0.0, 1.0); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_box_shadow.fs.glsl @@ -0,0 +1,148 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// See http://asciimath.org to render the equations here. + +// The Gaussian function used for blurring: +// +// G_sigma(x) = 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) +float gauss(float x, float sigma) { + float sigmaPow2 = sigma * sigma; + return 1.0 / sqrt(6.283185307179586 * sigmaPow2) * exp(-(x * x) / (2.0 * sigmaPow2)); +} + +// An approximation of the error function, which is related to the integral of the Gaussian +// function: +// +// "erf"(x) = 2/sqrt(pi) int_0^x e^(-t^2) dt +// ~~ 1 - 1 / (1 + a_1 x + a_2 x^2 + a_3 x^3 + a_4 x^4)^4 +// +// where: +// +// a_1 = 0.278393, a_2 = 0.230389, a_3 = 0.000972, a_4 = 0.078108 +// +// This approximation is accurate to `5 xx 10^-4`, more than accurate enough for our purposes. +// +// See: https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions +float erf(float x) { + bool negative = x < 0.0; + if (negative) + x = -x; + float x2 = x * x; + float x3 = x2 * x; + float x4 = x2 * x2; + float denom = 1.0 + 0.278393 * x + 0.230389 * x2 + 0.000972 * x3 + 0.078108 * x4; + float result = 1.0 - 1.0 / (denom * denom * denom * denom); + return negative ? -result : result; +} + +// A useful helper for calculating integrals of the Gaussian function via the error function: +// +// "erf"_sigma(x) = 2 int 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) dx +// = "erf"(x/(sigma sqrt(2))) +float erfSigma(float x, float sigma) { + return erf(x / (sigma * 1.4142135623730951)); +} + +// Returns the blurred color value from the box itself (not counting any rounded corners). `p_0` is +// the vector distance to the top left corner of the box; `p_1` is the vector distance to its +// bottom right corner. +// +// "colorFromRect"_sigma(p_0, p_1) +// = int_{p_{0_y}}^{p_{1_y}} int_{p_{1_x}}^{p_{0_x}} G_sigma(y) G_sigma(x) dx dy +// = 1/4 ("erf"_sigma(p_{1_x}) - "erf"_sigma(p_{0_x})) +// ("erf"_sigma(p_{1_y}) - "erf"_sigma(p_{0_y})) +float colorFromRect(vec2 p0, vec2 p1, float sigma) { + return (erfSigma(p1.x, sigma) - erfSigma(p0.x, sigma)) * + (erfSigma(p1.y, sigma) - erfSigma(p0.y, sigma)) / 4.0; +} + +// Returns the `x` coordinate on the ellipse with the given radii for the given `y` coordinate: +// +// "ellipsePoint"(y, y_0, a, b) = a sqrt(1 - ((y - y_0) / b)^2) +float ellipsePoint(float y, float y0, vec2 radii) { + float bStep = (y - y0) / radii.y; + return radii.x * sqrt(1.0 - bStep * bStep); +} + +// A helper function to compute the value that needs to be subtracted to accommodate the border +// corners. +// +// "colorCutout"_sigma(x_{0_l}, x_{0_r}, y_0, y_{min}, y_{max}, a, b) +// = int_{y_{min}}^{y_{max}} +// int_{x_{0_r} + "ellipsePoint"(y, y_0, a, b)}^{x_{0_r} + a} G_sigma(y) G_sigma(x) dx +// + int_{x_{0_l} - a}^{x_{0_l} - "ellipsePoint"(y, y_0, a, b)} G_sigma(y) G_sigma(x) +// dx dy +// = int_{y_{min}}^{y_{max}} 1/2 G_sigma(y) +// ("erf"_sigma(x_{0_r} + a) - "erf"_sigma(x_{0_r} + "ellipsePoint"(y, y_0, a, b)) + +// "erf"_sigma(x_{0_l} - "ellipsePoint"(y, y_0, a, b)) - "erf"_sigma(x_{0_l} - a)) +// +// with the outer integral evaluated numerically. +float colorCutoutGeneral(float x0l, + float x0r, + float y0, + float yMin, + float yMax, + vec2 radii, + float sigma) { + float sum = 0.0; + for (float y = yMin; y <= yMax; y += 1.0) { + float xEllipsePoint = ellipsePoint(y, y0, radii); + sum += gauss(y, sigma) * + (erfSigma(x0r + radii.x, sigma) - erfSigma(x0r + xEllipsePoint, sigma) + + erfSigma(x0l - xEllipsePoint, sigma) - erfSigma(x0l - radii.x, sigma)); + } + return sum / 2.0; +} + +// The value that needs to be subtracted to accommodate the top border corners. +float colorCutoutTop(float x0l, float x0r, float y0, vec2 radii, float sigma) { + return colorCutoutGeneral(x0l, x0r, y0, y0, y0 + radii.y, radii, sigma); +} + +// The value that needs to be subtracted to accommodate the bottom border corners. +float colorCutoutBottom(float x0l, float x0r, float y0, vec2 radii, float sigma) { + return colorCutoutGeneral(x0l, x0r, y0, y0 - radii.y, y0, radii, sigma); +} + +// The blurred color value for the point at `pos` with the top left corner of the box at +// `p_{0_"rect"}` and the bottom right corner of the box at `p_{1_"rect"}`. +float color(vec2 pos, vec2 p0Rect, vec2 p1Rect, vec2 radii, float sigma) { + // Compute the vector distances `p_0` and `p_1`. + vec2 p0 = p0Rect - pos, p1 = p1Rect - pos; + + // Compute the basic color `"colorFromRect"_sigma(p_0, p_1)`. This is all we have to do if + // the box is unrounded. + float cRect = colorFromRect(p0, p1, sigma); + if (radii.x == 0.0 || radii.y == 0.0) + return cRect; + + // Compute the inner corners of the box, taking border radii into account: `x_{0_l}`, + // `y_{0_t}`, `x_{0_r}`, and `y_{0_b}`. + float x0l = p0.x + radii.x; + float y0t = p1.y - radii.y; + float x0r = p1.x - radii.x; + float y0b = p0.y + radii.y; + + // Compute the final color: + // + // "colorFromRect"_sigma(p_0, p_1) - + // ("colorCutoutTop"_sigma(x_{0_l}, x_{0_r}, y_{0_t}, a, b) + + // "colorCutoutBottom"_sigma(x_{0_l}, x_{0_r}, y_{0_b}, a, b)) + float cCutoutTop = colorCutoutTop(x0l, x0r, y0t, radii, sigma); + float cCutoutBottom = colorCutoutBottom(x0l, x0r, y0b, radii, sigma); + return cRect - (cCutoutTop + cCutoutBottom); +} + +void main(void) { + vec2 pos = vPos.xy; + vec2 p0Rect = vBoxShadowRect.xy, p1Rect = vBoxShadowRect.zw; + vec2 radii = vBorderRadii.xy; + float sigma = vBlurRadius / 2.0; + float value = color(pos, p0Rect, p1Rect, radii, sigma); + + value = max(value, 0.0); + oFragColor = vec4(1.0, 1.0, 1.0, vInverted == 1.0 ? 1.0 - value : value); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_box_shadow.glsl @@ -0,0 +1,10 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec2 vPos; +flat varying vec2 vBorderRadii; +flat varying float vBlurRadius; +flat varying vec4 vBoxShadowRect; +flat varying float vInverted;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_box_shadow.vs.glsl @@ -0,0 +1,31 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + CachePrimitiveInstance cpi = fetch_cache_instance(); + RenderTaskData task = fetch_render_task(cpi.render_task_index); + BoxShadow bs = fetch_boxshadow(cpi.specific_prim_index); + + vec2 p0 = task.data0.xy; + vec2 p1 = p0 + task.data0.zw; + + vec2 pos = mix(p0, p1, aPosition.xy); + + vBorderRadii = bs.border_radius_edge_size_blur_radius_inverted.xx; + vBlurRadius = bs.border_radius_edge_size_blur_radius_inverted.z; + vInverted = bs.border_radius_edge_size_blur_radius_inverted.w; + vBoxShadowRect = vec4(bs.bs_rect.xy, bs.bs_rect.xy + bs.bs_rect.zw); + + // The fragment shader expects logical units, beginning at where the + // blur radius begins. + // The first path of the equation gets the virtual position in + // logical pixels within the patch rectangle (accounting for + // bilinear offset). Then we add the start position of the + // box shadow rect and subtract the blur radius to get the + // virtual coordinates that the FS expects. + vPos = (pos - 1.0 - p0) / uDevicePixelRatio + bs.bs_rect.xy - vec2(2.0 * vBlurRadius); + + gl_Position = uTransform * vec4(pos, 0.0, 1.0); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_clip_image.fs.glsl @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + float alpha = 1.f; + vec2 local_pos = init_transform_fs(vPos, vLocalRect, alpha); + + bool repeat_mask = false; //TODO + vec2 clamped_mask_uv = repeat_mask ? fract(vClipMaskUv.xy) : + clamp(vClipMaskUv.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)); + vec2 source_uv = clamped_mask_uv * vClipMaskUvRect.zw + vClipMaskUvRect.xy; + float clip_alpha = texture(sMask, source_uv).r; //careful: texture has type A8 + + oFragColor = vec4(min(alpha, clip_alpha), 1.0, 1.0, 1.0); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_clip_image.glsl @@ -0,0 +1,9 @@ +#line 1 + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec3 vPos; +flat varying vec4 vLocalRect; +flat varying vec4 vClipMaskUvRect;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_clip_image.vs.glsl @@ -0,0 +1,39 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +struct ImageMaskData { + vec4 uv_rect; + vec4 local_rect; +}; + +ImageMaskData fetch_mask_data(int index) { + ImageMaskData info; + + ivec2 uv = get_fetch_uv_2(index); + + info.uv_rect = texelFetchOffset(sData32, uv, 0, ivec2(0, 0)); + info.local_rect = texelFetchOffset(sData32, uv, 0, ivec2(1, 0)); + + return info; +} + +void main(void) { + CacheClipInstance cci = fetch_clip_item(gl_InstanceID); + ClipArea area = fetch_clip_area(cci.render_task_index); + Layer layer = fetch_layer(cci.layer_index); + ImageMaskData mask = fetch_mask_data(cci.data_index); + vec4 local_rect = mask.local_rect; + + TransformVertexInfo vi = write_clip_tile_vertex(local_rect, + layer, + area, + cci.segment_index); + vLocalRect = vi.clipped_local_rect; + vPos = vi.local_pos; + + vClipMaskUv = vec3((vPos.xy / vPos.z - local_rect.xy) / local_rect.zw, 0.0); + vec2 texture_size = vec2(textureSize(sMask, 0)); + vClipMaskUvRect = mask.uv_rect / texture_size.xyxy; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_clip_rectangle.fs.glsl @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +float rounded_rect(vec2 pos) { + vec2 ref_tl = vClipRect.xy + vec2( vClipRadius.x, vClipRadius.x); + vec2 ref_tr = vClipRect.zy + vec2(-vClipRadius.y, vClipRadius.y); + vec2 ref_br = vClipRect.zw + vec2(-vClipRadius.z, -vClipRadius.z); + vec2 ref_bl = vClipRect.xw + vec2( vClipRadius.w, -vClipRadius.w); + + float d_tl = distance(pos, ref_tl); + float d_tr = distance(pos, ref_tr); + float d_br = distance(pos, ref_br); + float d_bl = distance(pos, ref_bl); + + float pixels_per_fragment = length(fwidth(pos.xy)); + float nudge = 0.5 * pixels_per_fragment; + vec4 distances = vec4(d_tl, d_tr, d_br, d_bl) - vClipRadius + nudge; + + bvec4 is_out = bvec4(pos.x < ref_tl.x && pos.y < ref_tl.y, + pos.x > ref_tr.x && pos.y < ref_tr.y, + pos.x > ref_br.x && pos.y > ref_br.y, + pos.x < ref_bl.x && pos.y > ref_bl.y); + + float distance_from_border = dot(vec4(is_out), + max(vec4(0.0, 0.0, 0.0, 0.0), distances)); + + // Move the distance back into pixels. + distance_from_border /= pixels_per_fragment; + // Apply a more gradual fade out to transparent. + //distance_from_border -= 0.5; + + return 1.0 - smoothstep(0.0, 1.0, distance_from_border); +} + + +void main(void) { + float alpha = 1.f; + vec2 local_pos = init_transform_fs(vPos, vLocalRect, alpha); + + float clip_alpha = rounded_rect(local_pos); + + oFragColor = vec4(min(alpha, clip_alpha), 0.0, 0.0, 1.0); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_clip_rectangle.glsl @@ -0,0 +1,10 @@ +#line 1 + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec3 vPos; +flat varying vec4 vLocalRect; +flat varying vec4 vClipRect; +flat varying vec4 vClipRadius;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_clip_rectangle.vs.glsl @@ -0,0 +1,78 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +struct ClipRect { + vec4 rect; + vec4 dummy; +}; + +ClipRect fetch_clip_rect(int index) { + ClipRect rect; + + ivec2 uv = get_fetch_uv_2(index); + + rect.rect = texelFetchOffset(sData32, uv, 0, ivec2(0, 0)); + //rect.dummy = texelFetchOffset(sData32, uv, 0, ivec2(1, 0)); + rect.dummy = vec4(0.0, 0.0, 0.0, 0.0); + + return rect; +} + +struct ClipCorner { + vec4 rect; + vec4 outer_inner_radius; +}; + +ClipCorner fetch_clip_corner(int index) { + ClipCorner corner; + + ivec2 uv = get_fetch_uv_2(index); + + corner.rect = texelFetchOffset(sData32, uv, 0, ivec2(0, 0)); + corner.outer_inner_radius = texelFetchOffset(sData32, uv, 0, ivec2(1, 0)); + + return corner; +} + +struct ClipData { + ClipRect rect; + ClipCorner top_left; + ClipCorner top_right; + ClipCorner bottom_left; + ClipCorner bottom_right; +}; + +ClipData fetch_clip(int index) { + ClipData clip; + + clip.rect = fetch_clip_rect(index + 0); + clip.top_left = fetch_clip_corner(index + 1); + clip.top_right = fetch_clip_corner(index + 2); + clip.bottom_left = fetch_clip_corner(index + 3); + clip.bottom_right = fetch_clip_corner(index + 4); + + return clip; +} + +void main(void) { + CacheClipInstance cci = fetch_clip_item(gl_InstanceID); + ClipArea area = fetch_clip_area(cci.render_task_index); + Layer layer = fetch_layer(cci.layer_index); + ClipData clip = fetch_clip(cci.data_index); + vec4 local_rect = clip.rect.rect; + + TransformVertexInfo vi = write_clip_tile_vertex(local_rect, + layer, + area, + cci.segment_index); + vLocalRect = vi.clipped_local_rect; + vPos = vi.local_pos; + + vClipRect = vec4(local_rect.xy, local_rect.xy + local_rect.zw); + vClipRadius = vec4(clip.top_left.outer_inner_radius.x, + clip.top_right.outer_inner_radius.x, + clip.bottom_right.outer_inner_radius.x, + clip.bottom_left.outer_inner_radius.x); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_text_run.fs.glsl @@ -0,0 +1,9 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + float a = texture(sColor0, vUv).a; + oFragColor = vec4(vColor.rgb, vColor.a * a); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_text_run.glsl @@ -0,0 +1,7 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec2 vUv; +flat varying vec4 vColor;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/cs_text_run.vs.glsl @@ -0,0 +1,36 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Draw a text run to a cache target. These are always +// drawn un-transformed. These are used for effects such +// as text-shadow. + +void main(void) { + CachePrimitiveInstance cpi = fetch_cache_instance(); + RenderTaskData task = fetch_render_task(cpi.render_task_index); + TextRun text = fetch_text_run(cpi.specific_prim_index); + Glyph glyph = fetch_glyph(cpi.sub_index); + PrimitiveGeometry pg = fetch_prim_geometry(cpi.global_prim_index); + ResourceRect res = fetch_resource_rect(cpi.user_data.x); + + // Glyphs size is already in device-pixels. + // The render task origin is in device-pixels. Offset that by + // the glyph offset, relative to its primitive bounding rect. + vec2 size = res.uv_rect.zw - res.uv_rect.xy; + vec2 origin = task.data0.xy + uDevicePixelRatio * (glyph.offset.xy - pg.local_rect.xy); + vec4 local_rect = vec4(origin, size); + + vec2 texture_size = vec2(textureSize(sColor0, 0)); + vec2 st0 = res.uv_rect.xy / texture_size; + vec2 st1 = res.uv_rect.zw / texture_size; + + vec2 pos = mix(local_rect.xy, + local_rect.xy + local_rect.zw, + aPosition.xy); + vUv = mix(st0, st1, aPosition.xy); + vColor = text.color; + + gl_Position = uTransform * vec4(pos, 0.0, 1.0); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/debug_color.fs.glsl @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec4 vColor; + +void main(void) +{ + oFragColor = vColor; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/debug_color.vs.glsl @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +in vec4 aColor; +varying vec4 vColor; + +void main(void) +{ + vColor = aColor; + vec4 pos = vec4(aPosition, 1.0); + pos.xy = floor(pos.xy * uDevicePixelRatio + 0.5) / uDevicePixelRatio; + gl_Position = uTransform * pos; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/debug_font.fs.glsl @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec2 vColorTexCoord; +varying vec4 vColor; + +void main(void) +{ +#ifdef SERVO_ES2 + float alpha = texture(sColor0, vColorTexCoord.xy).a; +#else + float alpha = texture(sColor0, vColorTexCoord.xy).r; +#endif + oFragColor = vec4(vColor.xyz, vColor.w * alpha); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/debug_font.vs.glsl @@ -0,0 +1,18 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +in vec4 aColor; +in vec4 aColorTexCoord; + +varying vec2 vColorTexCoord; +varying vec4 vColor; + +void main(void) +{ + vColor = aColor; + vColorTexCoord = aColorTexCoord.xy; + vec4 pos = vec4(aPosition, 1.0); + pos.xy = floor(pos.xy * uDevicePixelRatio + 0.5) / uDevicePixelRatio; + gl_Position = uTransform * pos; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/prim_shared.glsl @@ -0,0 +1,665 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#if defined(GL_ES) + #if GL_ES == 1 + #ifdef GL_FRAGMENT_PRECISION_HIGH + precision highp sampler2DArray; + #else + precision mediump sampler2DArray; + #endif + #endif +#endif + +#define PST_TOP_LEFT 0 +#define PST_TOP 1 +#define PST_TOP_RIGHT 2 +#define PST_RIGHT 3 +#define PST_BOTTOM_RIGHT 4 +#define PST_BOTTOM 5 +#define PST_BOTTOM_LEFT 6 +#define PST_LEFT 7 + +#define BORDER_LEFT 0 +#define BORDER_TOP 1 +#define BORDER_RIGHT 2 +#define BORDER_BOTTOM 3 + +#define UV_NORMALIZED uint(0) +#define UV_PIXEL uint(1) + +#define MAX_STOPS_PER_ANGLE_GRADIENT 8 +#define MAX_STOPS_PER_RADIAL_GRADIENT 8 + +uniform sampler2DArray sCache; + +flat varying vec4 vClipMaskUvBounds; +varying vec3 vClipMaskUv; + +#ifdef WR_VERTEX_SHADER + +#define VECS_PER_LAYER 13 +#define VECS_PER_RENDER_TASK 3 +#define VECS_PER_PRIM_GEOM 2 + +#define GRADIENT_HORIZONTAL 0 +#define GRADIENT_VERTICAL 1 +#define GRADIENT_ROTATED 2 + +uniform sampler2D sLayers; +uniform sampler2D sRenderTasks; +uniform sampler2D sPrimGeometry; + +uniform sampler2D sData16; +uniform sampler2D sData32; +uniform sampler2D sData64; +uniform sampler2D sData128; +uniform sampler2D sResourceRects; + +// Instanced attributes +in int aGlobalPrimId; +in int aPrimitiveAddress; +in int aTaskIndex; +in int aClipTaskIndex; +in int aLayerIndex; +in int aElementIndex; +in ivec2 aUserData; +in int aZIndex; + +// get_fetch_uv is a macro to work around a macOS Intel driver parsing bug. +// TODO: convert back to a function once the driver issues are resolved, if ever. +// https://github.com/servo/webrender/pull/623 +// https://github.com/servo/servo/issues/13953 +#define get_fetch_uv(i, vpi) ivec2(vpi * (i % (WR_MAX_VERTEX_TEXTURE_WIDTH/vpi)), i / (WR_MAX_VERTEX_TEXTURE_WIDTH/vpi)) + +ivec2 get_fetch_uv_1(int index) { + return get_fetch_uv(index, 1); +} + +ivec2 get_fetch_uv_2(int index) { + return get_fetch_uv(index, 2); +} + +ivec2 get_fetch_uv_4(int index) { + return get_fetch_uv(index, 4); +} + +ivec2 get_fetch_uv_8(int index) { + return get_fetch_uv(index, 8); +} + +struct Layer { + mat4 transform; + mat4 inv_transform; + vec4 local_clip_rect; + vec4 screen_vertices[4]; +}; + +Layer fetch_layer(int index) { + Layer layer; + + // Create a UV base coord for each 8 texels. + // This is required because trying to use an offset + // of more than 8 texels doesn't work on some versions + // of OSX. + ivec2 uv = get_fetch_uv(index, VECS_PER_LAYER); + ivec2 uv0 = ivec2(uv.x + 0, uv.y); + ivec2 uv1 = ivec2(uv.x + 8, uv.y); + + layer.transform[0] = texelFetchOffset(sLayers, uv0, 0, ivec2(0, 0)); + layer.transform[1] = texelFetchOffset(sLayers, uv0, 0, ivec2(1, 0)); + layer.transform[2] = texelFetchOffset(sLayers, uv0, 0, ivec2(2, 0)); + layer.transform[3] = texelFetchOffset(sLayers, uv0, 0, ivec2(3, 0)); + + layer.inv_transform[0] = texelFetchOffset(sLayers, uv0, 0, ivec2(4, 0)); + layer.inv_transform[1] = texelFetchOffset(sLayers, uv0, 0, ivec2(5, 0)); + layer.inv_transform[2] = texelFetchOffset(sLayers, uv0, 0, ivec2(6, 0)); + layer.inv_transform[3] = texelFetchOffset(sLayers, uv0, 0, ivec2(7, 0)); + + layer.local_clip_rect = texelFetchOffset(sLayers, uv1, 0, ivec2(0, 0)); + + layer.screen_vertices[0] = texelFetchOffset(sLayers, uv1, 0, ivec2(1, 0)); + layer.screen_vertices[1] = texelFetchOffset(sLayers, uv1, 0, ivec2(2, 0)); + layer.screen_vertices[2] = texelFetchOffset(sLayers, uv1, 0, ivec2(3, 0)); + layer.screen_vertices[3] = texelFetchOffset(sLayers, uv1, 0, ivec2(4, 0)); + + return layer; +} + +struct RenderTaskData { + vec4 data0; + vec4 data1; + vec4 data2; +}; + +RenderTaskData fetch_render_task(int index) { + RenderTaskData task; + + ivec2 uv = get_fetch_uv(index, VECS_PER_RENDER_TASK); + + task.data0 = texelFetchOffset(sRenderTasks, uv, 0, ivec2(0, 0)); + task.data1 = texelFetchOffset(sRenderTasks, uv, 0, ivec2(1, 0)); + task.data2 = texelFetchOffset(sRenderTasks, uv, 0, ivec2(2, 0)); + + return task; +} + +struct Tile { + vec4 screen_origin_task_origin; + vec4 size_target_index; +}; + +Tile fetch_tile(int index) { + RenderTaskData task = fetch_render_task(index); + + Tile tile; + tile.screen_origin_task_origin = task.data0; + tile.size_target_index = task.data1; + + return tile; +} + +struct ClipArea { + vec4 task_bounds; + vec4 screen_origin_target_index; + vec4 inner_rect; +}; + +ClipArea fetch_clip_area(int index) { + ClipArea area; + + if (index == 0x7FFFFFFF) { //special sentinel task index + area.task_bounds = vec4(0.0, 0.0, 0.0, 0.0); + area.screen_origin_target_index = vec4(0.0, 0.0, 0.0, 0.0); + area.inner_rect = vec4(0.0); + } else { + RenderTaskData task = fetch_render_task(index); + area.task_bounds = task.data0; + area.screen_origin_target_index = task.data1; + area.inner_rect = task.data2; + } + + return area; +} + +struct Gradient { + vec4 start_end_point; + vec4 kind; +}; + +Gradient fetch_gradient(int index) { + Gradient gradient; + + ivec2 uv = get_fetch_uv_2(index); + + gradient.start_end_point = texelFetchOffset(sData32, uv, 0, ivec2(0, 0)); + gradient.kind = texelFetchOffset(sData32, uv, 0, ivec2(1, 0)); + + return gradient; +} + +struct GradientStop { + vec4 color; + vec4 offset; +}; + +GradientStop fetch_gradient_stop(int index) { + GradientStop stop; + + ivec2 uv = get_fetch_uv_2(index); + + stop.color = texelFetchOffset(sData32, uv, 0, ivec2(0, 0)); + stop.offset = texelFetchOffset(sData32, uv, 0, ivec2(1, 0)); + + return stop; +} + +struct RadialGradient { + vec4 start_end_center; + vec4 start_end_radius; +}; + +RadialGradient fetch_radial_gradient(int index) { + RadialGradient gradient; + + ivec2 uv = get_fetch_uv_2(index); + + gradient.start_end_center = texelFetchOffset(sData32, uv, 0, ivec2(0, 0)); + gradient.start_end_radius = texelFetchOffset(sData32, uv, 0, ivec2(1, 0)); + + return gradient; +} + +struct Glyph { + vec4 offset; +}; + +Glyph fetch_glyph(int index) { + Glyph glyph; + + ivec2 uv = get_fetch_uv_1(index); + + glyph.offset = texelFetchOffset(sData16, uv, 0, ivec2(0, 0)); + + return glyph; +} + +vec4 fetch_instance_geometry(int index) { + ivec2 uv = get_fetch_uv_1(index); + + vec4 rect = texelFetchOffset(sData16, uv, 0, ivec2(0, 0)); + + return rect; +} + +struct PrimitiveGeometry { + vec4 local_rect; + vec4 local_clip_rect; +}; + +PrimitiveGeometry fetch_prim_geometry(int index) { + PrimitiveGeometry pg; + + ivec2 uv = get_fetch_uv(index, VECS_PER_PRIM_GEOM); + + pg.local_rect = texelFetchOffset(sPrimGeometry, uv, 0, ivec2(0, 0)); + pg.local_clip_rect = texelFetchOffset(sPrimGeometry, uv, 0, ivec2(1, 0)); + + return pg; +} + +struct PrimitiveInstance { + int global_prim_index; + int specific_prim_index; + int render_task_index; + int clip_task_index; + int layer_index; + int sub_index; + int z; + ivec2 user_data; +}; + +PrimitiveInstance fetch_prim_instance() { + PrimitiveInstance pi; + + pi.global_prim_index = aGlobalPrimId; + pi.specific_prim_index = aPrimitiveAddress; + pi.render_task_index = aTaskIndex; + pi.clip_task_index = aClipTaskIndex; + pi.layer_index = aLayerIndex; + pi.sub_index = aElementIndex; + pi.user_data = aUserData; + pi.z = aZIndex; + + return pi; +} + +struct CachePrimitiveInstance { + int global_prim_index; + int specific_prim_index; + int render_task_index; + int sub_index; + ivec2 user_data; +}; + +CachePrimitiveInstance fetch_cache_instance() { + CachePrimitiveInstance cpi; + + PrimitiveInstance pi = fetch_prim_instance(); + + cpi.global_prim_index = pi.global_prim_index; + cpi.specific_prim_index = pi.specific_prim_index; + cpi.render_task_index = pi.render_task_index; + cpi.sub_index = pi.sub_index; + cpi.user_data = pi.user_data; + + return cpi; +} + +struct Primitive { + Layer layer; + Tile tile; + ClipArea clip_area; + vec4 local_rect; + vec4 local_clip_rect; + int prim_index; + // when sending multiple primitives of the same type (e.g. border segments) + // this index allows the vertex shader to recognize the difference + int sub_index; + ivec2 user_data; + float z; +}; + +Primitive load_primitive_custom(PrimitiveInstance pi) { + Primitive prim; + + prim.layer = fetch_layer(pi.layer_index); + prim.tile = fetch_tile(pi.render_task_index); + prim.clip_area = fetch_clip_area(pi.clip_task_index); + + PrimitiveGeometry pg = fetch_prim_geometry(pi.global_prim_index); + prim.local_rect = pg.local_rect; + prim.local_clip_rect = pg.local_clip_rect; + + prim.prim_index = pi.specific_prim_index; + prim.sub_index = pi.sub_index; + prim.user_data = pi.user_data; + prim.z = float(pi.z); + + return prim; +} + +Primitive load_primitive() { + PrimitiveInstance pi = fetch_prim_instance(); + + return load_primitive_custom(pi); +} + + +// Return the intersection of the plane (set up by "normal" and "point") +// with the ray (set up by "ray_origin" and "ray_dir"), +// writing the resulting scaler into "t". +bool ray_plane(vec3 normal, vec3 point, vec3 ray_origin, vec3 ray_dir, out float t) +{ + float denom = dot(normal, ray_dir); + if (denom > 1e-6) { + vec3 d = point - ray_origin; + t = dot(d, normal) / denom; + return t >= 0.0; + } + + return false; +} + +// Apply the inverse transform "inv_transform" +// to the reference point "ref" in CSS space, +// producing a local point on a layer plane, +// set by a base point "a" and a normal "n". +vec4 untransform(vec2 ref, vec3 n, vec3 a, mat4 inv_transform) { + vec3 p = vec3(ref, -10000.0); + vec3 d = vec3(0, 0, 1.0); + + float t = 0.0; + // get an intersection of the layer plane with Z axis vector, + // originated from the "ref" point + ray_plane(n, a, p, d, t); + float z = p.z + d.z * t; // Z of the visible point on the layer + + vec4 r = inv_transform * vec4(ref, z, 1.0); + return r; +} + +// Given a CSS space position, transform it back into the layer space. +vec4 get_layer_pos(vec2 pos, Layer layer) { + // get 3 of the layer corners in CSS space + vec3 a = layer.screen_vertices[0].xyz / layer.screen_vertices[0].w; + vec3 b = layer.screen_vertices[3].xyz / layer.screen_vertices[3].w; + vec3 c = layer.screen_vertices[2].xyz / layer.screen_vertices[2].w; + // get the normal to the layer plane + vec3 n = normalize(cross(b-a, c-a)); + return untransform(pos, n, a, layer.inv_transform); +} + +vec2 clamp_rect(vec2 point, vec4 rect) { + return clamp(point, rect.xy, rect.xy + rect.zw); +} + +struct Rect { + vec2 p0; + vec2 p1; +}; + +struct VertexInfo { + Rect local_rect; + vec2 local_clamped_pos; + vec2 global_clamped_pos; +}; + +VertexInfo write_vertex(vec4 instance_rect, + vec4 local_clip_rect, + float z, + Layer layer, + Tile tile) { + vec2 p0 = floor(0.5 + instance_rect.xy * uDevicePixelRatio) / uDevicePixelRatio; + vec2 p1 = floor(0.5 + (instance_rect.xy + instance_rect.zw) * uDevicePixelRatio) / uDevicePixelRatio; + + vec2 local_pos = mix(p0, p1, aPosition.xy); + + vec2 cp0 = floor(0.5 + local_clip_rect.xy * uDevicePixelRatio) / uDevicePixelRatio; + vec2 cp1 = floor(0.5 + (local_clip_rect.xy + local_clip_rect.zw) * uDevicePixelRatio) / uDevicePixelRatio; + local_pos = clamp(local_pos, cp0, cp1); + + local_pos = clamp_rect(local_pos, layer.local_clip_rect); + + vec4 world_pos = layer.transform * vec4(local_pos, 0.0, 1.0); + world_pos.xyz /= world_pos.w; + + vec2 device_pos = world_pos.xy * uDevicePixelRatio; + + vec2 clamped_pos = clamp(device_pos, + tile.screen_origin_task_origin.xy, + tile.screen_origin_task_origin.xy + tile.size_target_index.xy); + + vec4 local_clamped_pos = layer.inv_transform * vec4(clamped_pos / uDevicePixelRatio, world_pos.z, 1); + local_clamped_pos.xyz /= local_clamped_pos.w; + + vec2 final_pos = clamped_pos + tile.screen_origin_task_origin.zw - tile.screen_origin_task_origin.xy; + + gl_Position = uTransform * vec4(final_pos, z, 1.0); + + VertexInfo vi = VertexInfo(Rect(p0, p1), local_clamped_pos.xy, clamped_pos.xy); + return vi; +} + +#ifdef WR_FEATURE_TRANSFORM + +struct TransformVertexInfo { + vec3 local_pos; + vec2 global_clamped_pos; + vec4 clipped_local_rect; +}; + +TransformVertexInfo write_transform_vertex(vec4 instance_rect, + vec4 local_clip_rect, + float z, + Layer layer, + Tile tile) { + vec2 lp0_base = instance_rect.xy; + vec2 lp1_base = instance_rect.xy + instance_rect.zw; + + vec2 lp0 = clamp_rect(clamp_rect(lp0_base, local_clip_rect), + layer.local_clip_rect); + vec2 lp1 = clamp_rect(clamp_rect(lp1_base, local_clip_rect), + layer.local_clip_rect); + + vec4 clipped_local_rect = vec4(lp0, lp1 - lp0); + + vec2 p0 = lp0; + vec2 p1 = vec2(lp1.x, lp0.y); + vec2 p2 = vec2(lp0.x, lp1.y); + vec2 p3 = lp1; + + vec4 t0 = layer.transform * vec4(p0, 0, 1); + vec4 t1 = layer.transform * vec4(p1, 0, 1); + vec4 t2 = layer.transform * vec4(p2, 0, 1); + vec4 t3 = layer.transform * vec4(p3, 0, 1); + + vec2 tp0 = t0.xy / t0.w; + vec2 tp1 = t1.xy / t1.w; + vec2 tp2 = t2.xy / t2.w; + vec2 tp3 = t3.xy / t3.w; + + // compute a CSS space aligned bounding box + vec2 min_pos = min(min(tp0.xy, tp1.xy), min(tp2.xy, tp3.xy)); + vec2 max_pos = max(max(tp0.xy, tp1.xy), max(tp2.xy, tp3.xy)); + + // clamp to the tile boundaries, in device space + vec2 min_pos_clamped = clamp(min_pos * uDevicePixelRatio, + tile.screen_origin_task_origin.xy, + tile.screen_origin_task_origin.xy + tile.size_target_index.xy); + + vec2 max_pos_clamped = clamp(max_pos * uDevicePixelRatio, + tile.screen_origin_task_origin.xy, + tile.screen_origin_task_origin.xy + tile.size_target_index.xy); + + // compute the device space position of this vertex + vec2 clamped_pos = mix(min_pos_clamped, + max_pos_clamped, + aPosition.xy); + + // compute the point position in side the layer, in CSS space + vec4 layer_pos = get_layer_pos(clamped_pos / uDevicePixelRatio, layer); + + // apply the task offset + vec2 final_pos = clamped_pos + tile.screen_origin_task_origin.zw - tile.screen_origin_task_origin.xy; + + gl_Position = uTransform * vec4(final_pos, z, 1.0); + + return TransformVertexInfo(layer_pos.xyw, clamped_pos, clipped_local_rect); +} + +#endif //WR_FEATURE_TRANSFORM + +struct ResourceRect { + vec4 uv_rect; +}; + +ResourceRect fetch_resource_rect(int index) { + ResourceRect rect; + + ivec2 uv = get_fetch_uv_1(index); + + rect.uv_rect = texelFetchOffset(sResourceRects, uv, 0, ivec2(0, 0)); + + return rect; +} + +struct Rectangle { + vec4 color; +}; + +Rectangle fetch_rectangle(int index) { + Rectangle rect; + + ivec2 uv = get_fetch_uv_1(index); + + rect.color = texelFetchOffset(sData16, uv, 0, ivec2(0, 0)); + + return rect; +} + +struct TextRun { + vec4 color; +}; + +TextRun fetch_text_run(int index) { + TextRun text; + + ivec2 uv = get_fetch_uv_1(index); + + text.color = texelFetchOffset(sData16, uv, 0, ivec2(0, 0)); + + return text; +} + +struct Image { + vec4 stretch_size_and_tile_spacing; // Size of the actual image and amount of space between + // tiled instances of this image. +}; + +Image fetch_image(int index) { + Image image; + + ivec2 uv = get_fetch_uv_1(index); + + image.stretch_size_and_tile_spacing = texelFetchOffset(sData16, uv, 0, ivec2(0, 0)); + + return image; +} + +// YUV color spaces +#define YUV_REC601 1 +#define YUV_REC709 2 + +struct YuvImage { + vec4 y_st_rect; + vec4 u_st_rect; + vec4 v_st_rect; + vec2 size; + int color_space; +}; + +YuvImage fetch_yuv_image(int index) { + YuvImage image; + + ivec2 uv = get_fetch_uv_4(index); + + image.y_st_rect = texelFetchOffset(sData64, uv, 0, ivec2(0, 0)); + image.u_st_rect = texelFetchOffset(sData64, uv, 0, ivec2(1, 0)); + image.v_st_rect = texelFetchOffset(sData64, uv, 0, ivec2(2, 0)); + vec4 size_color_space = texelFetchOffset(sData64, uv, 0, ivec2(3, 0)); + image.size = size_color_space.xy; + image.color_space = int(size_color_space.z); + + return image; +} + +struct BoxShadow { + vec4 src_rect; + vec4 bs_rect; + vec4 color; + vec4 border_radius_edge_size_blur_radius_inverted; +}; + +BoxShadow fetch_boxshadow(int index) { + BoxShadow bs; + + ivec2 uv = get_fetch_uv_4(index); + + bs.src_rect = texelFetchOffset(sData64, uv, 0, ivec2(0, 0)); + bs.bs_rect = texelFetchOffset(sData64, uv, 0, ivec2(1, 0)); + bs.color = texelFetchOffset(sData64, uv, 0, ivec2(2, 0)); + bs.border_radius_edge_size_blur_radius_inverted = texelFetchOffset(sData64, uv, 0, ivec2(3, 0)); + + return bs; +} + +void write_clip(vec2 global_pos, ClipArea area) { + vec2 texture_size = vec2(textureSize(sCache, 0).xy); + vec2 uv = global_pos + area.task_bounds.xy - area.screen_origin_target_index.xy; + vClipMaskUvBounds = area.task_bounds / texture_size.xyxy; + vClipMaskUv = vec3(uv / texture_size, area.screen_origin_target_index.z); +} +#endif //WR_VERTEX_SHADER + +#ifdef WR_FRAGMENT_SHADER +float distance_from_rect(vec2 p, vec2 origin, vec2 size) { + vec2 clamped = clamp(p, origin, origin + size); + return distance(clamped, p); +} + +vec2 init_transform_fs(vec3 local_pos, vec4 local_rect, out float fragment_alpha) { + fragment_alpha = 1.0; + vec2 pos = local_pos.xy / local_pos.z; + + float border_distance = distance_from_rect(pos, local_rect.xy, local_rect.zw); + if (border_distance != 0.0) { + float delta = length(fwidth(local_pos.xy)); + fragment_alpha = 1.0 - smoothstep(0.0, 1.0, border_distance / delta * 2.0); + } + + return pos; +} + +float do_clip() { + // anything outside of the mask is considered transparent + bvec4 inside = lessThanEqual( + vec4(vClipMaskUvBounds.xy, vClipMaskUv.xy), + vec4(vClipMaskUv.xy, vClipMaskUvBounds.zw)); + // check for the dummy bounds, which are given to the opaque objects + return vClipMaskUvBounds.xy == vClipMaskUvBounds.zw ? 1.0: + all(inside) ? textureLod(sCache, vClipMaskUv, 0.0).r : 0.0; +} +#endif //WR_FRAGMENT_SHADER
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_angle_gradient.fs.glsl @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +float offset(int index) { + return vOffsets[index / 4][index % 4]; +} + +float linearStep(float lo, float hi, float x) { + float d = hi - lo; + float v = x - lo; + if (d != 0.0) { + v /= d; + } + return clamp(v, 0.0, 1.0); +} + +void main(void) { + float angle = atan(-vEndPoint.y + vStartPoint.y, + vEndPoint.x - vStartPoint.x); + float sa = sin(angle); + float ca = cos(angle); + + float sx = vStartPoint.x * ca - vStartPoint.y * sa; + float ex = vEndPoint.x * ca - vEndPoint.y * sa; + float d = ex - sx; + + float x = vPos.x * ca - vPos.y * sa; + + oFragColor = mix(vColors[0], + vColors[1], + linearStep(sx + d * offset(0), sx + d * offset(1), x)); + + for (int i=1 ; i < vStopCount-1 ; ++i) { + oFragColor = mix(oFragColor, + vColors[i+1], + linearStep(sx + d * offset(i), sx + d * offset(i+1), x)); + } +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_angle_gradient.glsl @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +flat varying int vStopCount; +flat varying float vAngle; +flat varying vec2 vStartPoint; +flat varying vec2 vEndPoint; +varying vec2 vPos; +flat varying vec4 vColors[MAX_STOPS_PER_ANGLE_GRADIENT]; +flat varying vec4 vOffsets[MAX_STOPS_PER_ANGLE_GRADIENT/4];
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_angle_gradient.vs.glsl @@ -0,0 +1,33 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + Primitive prim = load_primitive(); + Gradient gradient = fetch_gradient(prim.prim_index); + + VertexInfo vi = write_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + + vStopCount = int(prim.user_data.x); + vPos = vi.local_clamped_pos; + + // Snap the start/end points to device pixel units. + // I'm not sure this is entirely correct, but the + // old render path does this, and it is needed to + // make the angle gradient ref tests pass. It might + // be better to fix this higher up in DL construction + // and not snap here? + vStartPoint = floor(0.5 + gradient.start_end_point.xy * uDevicePixelRatio) / uDevicePixelRatio; + vEndPoint = floor(0.5 + gradient.start_end_point.zw * uDevicePixelRatio) / uDevicePixelRatio; + + for (int i=0 ; i < vStopCount ; ++i) { + GradientStop stop = fetch_gradient_stop(prim.sub_index + i); + vColors[i] = stop.color; + vOffsets[i/4][i%4] = stop.offset.x; + } +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_blend.fs.glsl @@ -0,0 +1,138 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +vec3 rgbToHsv(vec3 c) { + float value = max(max(c.r, c.g), c.b); + + float chroma = value - min(min(c.r, c.g), c.b); + if (chroma == 0.0) { + return vec3(0.0); + } + float saturation = chroma / value; + + float hue; + if (c.r == value) + hue = (c.g - c.b) / chroma; + else if (c.g == value) + hue = 2.0 + (c.b - c.r) / chroma; + else // if (c.b == value) + hue = 4.0 + (c.r - c.g) / chroma; + + hue *= 1.0/6.0; + if (hue < 0.0) + hue += 1.0; + return vec3(hue, saturation, value); +} + +vec3 hsvToRgb(vec3 c) { + if (c.s == 0.0) { + return vec3(c.z); + } + + float hue = c.x * 6.0; + int sector = int(hue); + float residualHue = hue - float(sector); + + vec3 pqt = c.z * vec3(1.0 - c.y, 1.0 - c.y * residualHue, 1.0 - c.y * (1.0 - residualHue)); + switch (sector) { + case 0: + return vec3(c.z, pqt.z, pqt.x); + case 1: + return vec3(pqt.y, c.z, pqt.x); + case 2: + return vec3(pqt.x, c.z, pqt.z); + case 3: + return vec3(pqt.x, pqt.y, c.z); + case 4: + return vec3(pqt.z, pqt.x, c.z); + default: + return vec3(c.z, pqt.x, pqt.y); + } +} + +vec4 Blur(float radius, vec2 direction) { + // TODO(gw): Support blur in WR2! + return vec4(1.0); +} + +vec4 Contrast(vec4 Cs, float amount) { + return vec4(Cs.rgb * amount - 0.5 * amount + 0.5, 1.0); +} + +vec4 Grayscale(vec4 Cs, float amount) { + float ia = 1.0 - amount; + return mat4(vec4(0.2126 + 0.7874 * ia, 0.2126 - 0.2126 * ia, 0.2126 - 0.2126 * ia, 0.0), + vec4(0.7152 - 0.7152 * ia, 0.7152 + 0.2848 * ia, 0.7152 - 0.7152 * ia, 0.0), + vec4(0.0722 - 0.0722 * ia, 0.0722 - 0.0722 * ia, 0.0722 + 0.9278 * ia, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)) * Cs; +} + +vec4 HueRotate(vec4 Cs, float amount) { + vec3 CsHsv = rgbToHsv(Cs.rgb); + CsHsv.x = mod(CsHsv.x + amount / 6.283185307179586, 1.0); + return vec4(hsvToRgb(CsHsv), Cs.a); +} + +vec4 Invert(vec4 Cs, float amount) { + return mix(Cs, vec4(1.0, 1.0, 1.0, Cs.a) - vec4(Cs.rgb, 0.0), amount); +} + +vec4 Saturate(vec4 Cs, float amount) { + return vec4(hsvToRgb(min(vec3(1.0, amount, 1.0) * rgbToHsv(Cs.rgb), vec3(1.0))), Cs.a); +} + +vec4 Sepia(vec4 Cs, float amount) { + float ia = 1.0 - amount; + return mat4(vec4(0.393 + 0.607 * ia, 0.349 - 0.349 * ia, 0.272 - 0.272 * ia, 0.0), + vec4(0.769 - 0.769 * ia, 0.686 + 0.314 * ia, 0.534 - 0.534 * ia, 0.0), + vec4(0.189 - 0.189 * ia, 0.168 - 0.168 * ia, 0.131 + 0.869 * ia, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)) * Cs; +} + +vec4 Brightness(vec4 Cs, float amount) { + return vec4(Cs.rgb * amount, Cs.a); +} + +vec4 Opacity(vec4 Cs, float amount) { + return vec4(Cs.rgb, Cs.a * amount); +} + +void main(void) { + vec4 Cs = texture(sCache, vUv); + + if (Cs.a == 0.0) { + discard; + } + + switch (vOp) { + case 0: + // Gaussian blur is specially handled: + oFragColor = Cs;// Blur(vAmount, vec2(0,0)); + break; + case 1: + oFragColor = Contrast(Cs, vAmount); + break; + case 2: + oFragColor = Grayscale(Cs, vAmount); + break; + case 3: + oFragColor = HueRotate(Cs, vAmount); + break; + case 4: + oFragColor = Invert(Cs, vAmount); + break; + case 5: + oFragColor = Saturate(Cs, vAmount); + break; + case 6: + oFragColor = Sepia(Cs, vAmount); + break; + case 7: + oFragColor = Brightness(Cs, vAmount); + break; + case 8: + oFragColor = Opacity(Cs, vAmount); + break; + } +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_blend.glsl @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec3 vUv; +flat varying float vAmount; +flat varying int vOp;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_blend.vs.glsl @@ -0,0 +1,46 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +struct Blend { + ivec4 src_id_target_id_op_amount; + int z; +}; + +Blend fetch_blend() { + PrimitiveInstance pi = fetch_prim_instance(); + + Blend blend; + blend.src_id_target_id_op_amount = ivec4(pi.user_data.x, + pi.render_task_index, + pi.sub_index, + pi.user_data.y); + blend.z = pi.z; + + return blend; +} + +void main(void) { + Blend blend = fetch_blend(); + Tile src = fetch_tile(blend.src_id_target_id_op_amount.x); + Tile dest = fetch_tile(blend.src_id_target_id_op_amount.y); + + vec2 dest_origin = dest.screen_origin_task_origin.zw - + dest.screen_origin_task_origin.xy + + src.screen_origin_task_origin.xy; + + vec2 local_pos = mix(dest_origin, + dest_origin + src.size_target_index.xy, + aPosition.xy); + + vec2 texture_size = vec2(textureSize(sCache, 0)); + vec2 st0 = src.screen_origin_task_origin.zw / texture_size; + vec2 st1 = (src.screen_origin_task_origin.zw + src.size_target_index.xy) / texture_size; + vUv = vec3(mix(st0, st1, aPosition.xy), src.size_target_index.z); + + vOp = blend.src_id_target_id_op_amount.z; + vAmount = float(blend.src_id_target_id_op_amount.w) / 65535.0; + + gl_Position = uTransform * vec4(local_pos, blend.z, 1.0); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_border.fs.glsl @@ -0,0 +1,408 @@ +#line 1 + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Border styles as defined in webrender_traits/types.rs +#define BORDER_STYLE_NONE 0 +#define BORDER_STYLE_SOLID 1 +#define BORDER_STYLE_DOUBLE 2 +#define BORDER_STYLE_DOTTED 3 +#define BORDER_STYLE_DASHED 4 +#define BORDER_STYLE_HIDDEN 5 +#define BORDER_STYLE_GROOVE 6 +#define BORDER_STYLE_RIDGE 7 +#define BORDER_STYLE_INSET 8 +#define BORDER_STYLE_OUTSET 9 + +void discard_pixels_in_rounded_borders(vec2 local_pos) { + float distanceFromRef = distance(vRefPoint, local_pos); + if (vRadii.x > 0.0 && (distanceFromRef > vRadii.x || distanceFromRef < vRadii.z)) { + discard; + } +} + +vec4 get_fragment_color(float distanceFromMixLine, float pixelsPerFragment) { + // Here we are mixing between the two border colors. We need to convert + // distanceFromMixLine it to pixel space to properly anti-alias and then push + // it between the limits accepted by `mix`. + float colorMix = min(max(distanceFromMixLine / pixelsPerFragment, -0.5), 0.5) + 0.5; + return mix(vHorizontalColor, vVerticalColor, colorMix); +} + +float alpha_for_solid_border(float distance_from_ref, + float inner_radius, + float outer_radius, + float pixels_per_fragment) { + // We want to start anti-aliasing one pixel in from the border. + float nudge = pixels_per_fragment; + inner_radius += nudge; + outer_radius -= nudge; + + if (distance_from_ref < outer_radius && distance_from_ref > inner_radius) { + return 1.0; + } + + float distance_from_border = max(distance_from_ref - outer_radius, + inner_radius - distance_from_ref); + + // Move the distance back into pixels. + distance_from_border /= pixels_per_fragment; + + // Apply a more gradual fade out to transparent. + // distance_from_border -= 0.5; + + return 1.0 - smoothstep(0.0, 1.0, distance_from_border); +} + +float alpha_for_solid_border_corner(vec2 local_pos, + float inner_radius, + float outer_radius, + float pixels_per_fragment) { + float distance_from_ref = distance(vRefPoint, local_pos); + return alpha_for_solid_border(distance_from_ref, inner_radius, outer_radius, pixels_per_fragment); +} + +vec4 draw_dotted_edge(vec2 local_pos, vec4 piece_rect, float pixels_per_fragment) { + // We don't use pixels_per_fragment here, since it can change along the edge + // of a transformed border edge. We want this calculation to be consistent + // across the entire edge so that the positioning of the dots stays the same. + float two_pixels = 2.0 * length(fwidth(vLocalPos.xy)); + + // Circle diameter is stroke width, minus a couple pixels to account for anti-aliasing. + float circle_diameter = max(piece_rect.z - two_pixels, min(piece_rect.z, two_pixels)); + + // We want to spread the circles across the edge, but keep one circle diameter at the end + // reserved for two half-circles which connect to the corners. + float edge_available = piece_rect.w - (circle_diameter * 2.0); + float number_of_circles = floor(edge_available / (circle_diameter * 2.0)); + + // Here we are initializing the distance from the y coordinate of the center of the circle to + // the closest end half-circle. + vec2 relative_pos = local_pos - piece_rect.xy; + float y_distance = min(relative_pos.y, piece_rect.w - relative_pos.y); + + if (number_of_circles > 0.0) { + // Spread the circles throughout the edge, to distribute the extra space evenly. We want + // to ensure that we have at last two pixels of space for each circle so that they aren't + // touching. + float space_for_each_circle = ceil(max(edge_available / number_of_circles, two_pixels)); + + float first_half_circle_space = circle_diameter; + + float circle_index = (relative_pos.y - first_half_circle_space) / space_for_each_circle; + circle_index = floor(clamp(circle_index, 0.0, number_of_circles - 1.0)); + + float circle_y_pos = + circle_index * space_for_each_circle + (space_for_each_circle / 2.0) + circle_diameter; + y_distance = min(abs(circle_y_pos - relative_pos.y), y_distance); + } + + float distance_from_circle_center = length(vec2(relative_pos.x - (piece_rect.z / 2.0), y_distance)); + float distance_from_circle_edge = distance_from_circle_center - (circle_diameter / 2.0); + + // Don't anti-alias if the circle diameter is small to avoid a blur of color. + if (circle_diameter < two_pixels && distance_from_circle_edge > 0.0) + return vec4(0.0); + + // Move the distance back into pixels. + distance_from_circle_edge /= pixels_per_fragment; + + float alpha = 1.0 - smoothstep(0.0, 1.0, min(1.0, max(0.0, distance_from_circle_edge))); + return vHorizontalColor * vec4(1.0, 1.0, 1.0, alpha); +} + +vec4 draw_dashed_edge(float position, float border_width, float pixels_per_fragment) { + // TODO: Investigate exactly what FF does. + float size = border_width * 3.0; + float segment = floor(position / size); + + float alpha = alpha_for_solid_border(position, + segment * size, + (segment + 1.0) * size, + pixels_per_fragment); + + if (mod(segment + 2.0, 2.0) == 0.0) { + return vHorizontalColor * vec4(1.0, 1.0, 1.0, 1.0 - alpha); + } else { + return vHorizontalColor * vec4(1.0, 1.0, 1.0, alpha); + } +} + +void draw_dashed_or_dotted_border(vec2 local_pos, float distance_from_mix_line) { + // This is the conversion factor for transformations and device pixel scaling. + float pixels_per_fragment = length(fwidth(local_pos.xy)); + + switch (vBorderPart) { + // These are the layer tile part PrimitivePart as uploaded by the tiling.rs + case PST_TOP_LEFT: + case PST_TOP_RIGHT: + case PST_BOTTOM_LEFT: + case PST_BOTTOM_RIGHT: + { + oFragColor = get_fragment_color(distance_from_mix_line, pixels_per_fragment); + if (vRadii.x > 0.0) { + oFragColor *= vec4(1.0, 1.0, 1.0, alpha_for_solid_border_corner(local_pos, + vRadii.z, + vRadii.x, + pixels_per_fragment)); + } + + break; + } + case PST_BOTTOM: + case PST_TOP: { + if (vBorderStyle == BORDER_STYLE_DASHED) { + oFragColor = draw_dashed_edge(vLocalPos.x - vPieceRect.x, + vPieceRect.w, + pixels_per_fragment); + } else { + oFragColor = draw_dotted_edge(local_pos.yx, vPieceRect.yxwz, pixels_per_fragment); + } + break; + } + case PST_LEFT: + case PST_RIGHT: + { + if (vBorderStyle == BORDER_STYLE_DASHED) { + oFragColor = draw_dashed_edge(vLocalPos.y - vPieceRect.y, + vPieceRect.z, + pixels_per_fragment); + } else { + oFragColor = draw_dotted_edge(local_pos.xy, vPieceRect.xyzw, pixels_per_fragment); + } + break; + } + } +} + +vec4 draw_double_edge(float pos, + float len, + float distance_from_mix_line, + float pixels_per_fragment) { + float total_border_width = len; + float one_third_width = total_border_width / 3.0; + + // Contribution of the outer border segment. + float alpha = alpha_for_solid_border(pos, + total_border_width - one_third_width, + total_border_width, + pixels_per_fragment); + + // Contribution of the inner border segment. + alpha += alpha_for_solid_border(pos, 0.0, one_third_width, pixels_per_fragment); + return get_fragment_color(distance_from_mix_line, pixels_per_fragment) * vec4(1.0, 1.0, 1.0, alpha); +} + +vec4 draw_double_edge_vertical(vec2 local_pos, + float distance_from_mix_line, + float pixels_per_fragment) { + // Get our position within this specific segment + float position = local_pos.x - vLocalRect.x; + return draw_double_edge(position, vLocalRect.z, distance_from_mix_line, pixels_per_fragment); +} + +vec4 draw_double_edge_horizontal(vec2 local_pos, + float distance_from_mix_line, + float pixels_per_fragment) { + // Get our position within this specific segment + float position = local_pos.y - vLocalRect.y; + return draw_double_edge(position, vLocalRect.w, distance_from_mix_line, pixels_per_fragment); +} + +vec4 draw_double_edge_corner_with_radius(vec2 local_pos, + float distance_from_mix_line, + float pixels_per_fragment) { + float total_border_width = vRadii.x - vRadii.z; + float one_third_width = total_border_width / 3.0; + + // Contribution of the outer border segment. + float alpha = alpha_for_solid_border_corner(local_pos, + vRadii.x - one_third_width, + vRadii.x, + pixels_per_fragment); + + // Contribution of the inner border segment. + alpha += alpha_for_solid_border_corner(local_pos, + vRadii.z, + vRadii.z + one_third_width, + pixels_per_fragment); + return get_fragment_color(distance_from_mix_line, pixels_per_fragment) * vec4(1.0, 1.0, 1.0, alpha); +} + +vec4 draw_double_edge_corner(vec2 local_pos, + float distance_from_mix_line, + float pixels_per_fragment) { + if (vRadii.x > 0.0) { + return draw_double_edge_corner_with_radius(local_pos, + distance_from_mix_line, + pixels_per_fragment); + } + + bool is_vertical = (vBorderPart == PST_TOP_LEFT) ? distance_from_mix_line < 0.0 : + distance_from_mix_line >= 0.0; + if (is_vertical) { + return draw_double_edge_vertical(local_pos, distance_from_mix_line, pixels_per_fragment); + } else { + return draw_double_edge_horizontal(local_pos, distance_from_mix_line, pixels_per_fragment); + } +} + +void draw_double_border(float distance_from_mix_line, vec2 local_pos) { + float pixels_per_fragment = length(fwidth(local_pos.xy)); + switch (vBorderPart) { + // These are the layer tile part PrimitivePart as uploaded by the tiling.rs + case PST_TOP_LEFT: + case PST_TOP_RIGHT: + case PST_BOTTOM_LEFT: + case PST_BOTTOM_RIGHT: + { + oFragColor = draw_double_edge_corner(local_pos, distance_from_mix_line, pixels_per_fragment); + break; + } + case PST_BOTTOM: + case PST_TOP: + { + oFragColor = draw_double_edge_horizontal(local_pos, + distance_from_mix_line, + pixels_per_fragment); + break; + } + case PST_LEFT: + case PST_RIGHT: + { + oFragColor = draw_double_edge_vertical(local_pos, + distance_from_mix_line, + pixels_per_fragment); + break; + } + } +} + +void draw_solid_border(float distanceFromMixLine, vec2 localPos) { + switch (vBorderPart) { + case PST_TOP_LEFT: + case PST_TOP_RIGHT: + case PST_BOTTOM_LEFT: + case PST_BOTTOM_RIGHT: { + // This is the conversion factor for transformations and device pixel scaling. + float pixelsPerFragment = length(fwidth(localPos.xy)); + oFragColor = get_fragment_color(distanceFromMixLine, pixelsPerFragment); + + if (vRadii.x > 0.0) { + float alpha = alpha_for_solid_border_corner(localPos, vRadii.z, vRadii.x, pixelsPerFragment); + oFragColor *= vec4(1.0, 1.0, 1.0, alpha); + } + + break; + } + default: + oFragColor = vHorizontalColor; + discard_pixels_in_rounded_borders(localPos); + } +} + +vec4 draw_mixed_edge(float distance, float border_len, vec4 color, vec2 brightness_mod) { + float modulator = distance / border_len > 0.5 ? brightness_mod.x : brightness_mod.y; + return vec4(color.xyz * modulator, color.a); +} + +void draw_mixed_border(float distanceFromMixLine, float distanceFromMiddle, vec2 localPos, vec2 brightness_mod) { + switch (vBorderPart) { + case PST_TOP_LEFT: + case PST_TOP_RIGHT: + case PST_BOTTOM_LEFT: + case PST_BOTTOM_RIGHT: { + // This is the conversion factor for transformations and device pixel scaling. + float pixelsPerFragment = length(fwidth(localPos.xy)); + vec4 color = get_fragment_color(distanceFromMixLine, pixelsPerFragment); + + float distance = distance(vRefPoint, localPos) - vRadii.z; + float length = vRadii.x - vRadii.z; + if (distanceFromMiddle < 0.0) { + distance = length - distance; + } + + oFragColor = 0.0 <= distance && distance <= length ? + draw_mixed_edge(distance, length, color, brightness_mod) : vec4(0.0, 0.0, 0.0, 0.0); + break; + } + case PST_BOTTOM: + case PST_TOP: { + oFragColor = draw_mixed_edge(localPos.y - vPieceRect.y, vPieceRect.w, vVerticalColor, brightness_mod); + break; + } + case PST_LEFT: + case PST_RIGHT: { + oFragColor = draw_mixed_edge(localPos.x - vPieceRect.x, vPieceRect.z, vHorizontalColor, brightness_mod); + break; + } + } +} + +// TODO: Investigate performance of this shader and see +// if it's worthwhile splitting it / removing branches etc. +void main(void) { +#ifdef WR_FEATURE_TRANSFORM + float alpha = 0.0; + vec2 local_pos = init_transform_fs(vLocalPos, vLocalRect, alpha); +#else + vec2 local_pos = vLocalPos; +#endif + +#ifdef WR_FEATURE_TRANSFORM + // TODO(gw): Support other border styles for transformed elements. + float distance_from_mix_line = (local_pos.x - vPieceRect.x) * vPieceRect.w - + (local_pos.y - vPieceRect.y) * vPieceRect.z; + distance_from_mix_line /= vPieceRectHypotenuseLength; + float distance_from_middle = (local_pos.x - vLocalRect.x) + + (local_pos.y - vLocalRect.y) - + 0.5 * (vLocalRect.z + vLocalRect.w); +#else + float distance_from_mix_line = vDistanceFromMixLine; + float distance_from_middle = vDistanceFromMiddle; +#endif + + vec2 brightness_mod = vec2(0.7, 1.3); + + // Note: we can't pass-through in the following cases, + // because Angle doesn't support it and fails to compile the shaders. + switch (vBorderStyle) { + case BORDER_STYLE_DASHED: + draw_dashed_or_dotted_border(local_pos, distance_from_mix_line); + break; + case BORDER_STYLE_DOTTED: + draw_dashed_or_dotted_border(local_pos, distance_from_mix_line); + break; + case BORDER_STYLE_DOUBLE: + draw_double_border(distance_from_mix_line, local_pos); + break; + case BORDER_STYLE_OUTSET: + draw_solid_border(distance_from_mix_line, local_pos); + break; + case BORDER_STYLE_INSET: + draw_solid_border(distance_from_mix_line, local_pos); + break; + case BORDER_STYLE_SOLID: + draw_solid_border(distance_from_mix_line, local_pos); + break; + case BORDER_STYLE_NONE: + draw_solid_border(distance_from_mix_line, local_pos); + break; + case BORDER_STYLE_GROOVE: + draw_mixed_border(distance_from_mix_line, distance_from_middle, local_pos, brightness_mod.yx); + break; + case BORDER_STYLE_RIDGE: + draw_mixed_border(distance_from_mix_line, distance_from_middle, local_pos, brightness_mod.xy); + break; + case BORDER_STYLE_HIDDEN: + discard; + default: + discard; + } + +#ifdef WR_FEATURE_TRANSFORM + oFragColor *= vec4(1.0, 1.0, 1.0, alpha); +#endif +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_border.glsl @@ -0,0 +1,33 @@ +#line 1 + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// These are not changing. +flat varying vec4 vVerticalColor; // The vertical color, e.g. top/bottom +flat varying vec4 vHorizontalColor; // The horizontal color e.g. left/right +flat varying vec4 vRadii; // The border radius from CSS border-radius +flat varying vec4 vLocalRect; // The rect of the border (x, y, w, h) in local space. + +// for corners, this is the beginning of the corner. +// For the lines, this is the top left of the line. +flat varying vec2 vRefPoint; +flat varying int vBorderStyle; +flat varying int vBorderPart; // Which part of the border we're drawing. + +flat varying vec4 vPieceRect; + +// These are in device space +#ifdef WR_FEATURE_TRANSFORM +varying vec3 vLocalPos; // The clamped position in local space. +flat varying float vPieceRectHypotenuseLength; +#else +varying vec2 vLocalPos; // The clamped position in local space. + +// These two are interpolated +varying float vDistanceFromMixLine; // This is the distance from the line where two colors + // meet in border corners. +varying float vDistanceFromMiddle; // This is the distance from the line between the top + // left corner and the bottom right. +#endif
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_border.vs.glsl @@ -0,0 +1,226 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +struct Border { + vec4 style; + vec4 widths; + vec4 colors[4]; + vec4 radii[2]; +}; + +Border fetch_border(int index) { + Border border; + + ivec2 uv = get_fetch_uv_8(index); + + border.style = texelFetchOffset(sData128, uv, 0, ivec2(0, 0)); + border.widths = texelFetchOffset(sData128, uv, 0, ivec2(1, 0)); + border.colors[0] = texelFetchOffset(sData128, uv, 0, ivec2(2, 0)); + border.colors[1] = texelFetchOffset(sData128, uv, 0, ivec2(3, 0)); + border.colors[2] = texelFetchOffset(sData128, uv, 0, ivec2(4, 0)); + border.colors[3] = texelFetchOffset(sData128, uv, 0, ivec2(5, 0)); + border.radii[0] = texelFetchOffset(sData128, uv, 0, ivec2(6, 0)); + border.radii[1] = texelFetchOffset(sData128, uv, 0, ivec2(7, 0)); + + return border; +} + +void main(void) { + Primitive prim = load_primitive(); + Border border = fetch_border(prim.prim_index); + int sub_part = prim.sub_index; + + vec2 tl_outer = prim.local_rect.xy; + vec2 tl_inner = tl_outer + vec2(max(border.radii[0].x, border.widths.x), + max(border.radii[0].y, border.widths.y)); + + vec2 tr_outer = vec2(prim.local_rect.x + prim.local_rect.z, + prim.local_rect.y); + vec2 tr_inner = tr_outer + vec2(-max(border.radii[0].z, border.widths.z), + max(border.radii[0].w, border.widths.y)); + + vec2 br_outer = vec2(prim.local_rect.x + prim.local_rect.z, + prim.local_rect.y + prim.local_rect.w); + vec2 br_inner = br_outer - vec2(max(border.radii[1].x, border.widths.z), + max(border.radii[1].y, border.widths.w)); + + vec2 bl_outer = vec2(prim.local_rect.x, + prim.local_rect.y + prim.local_rect.w); + vec2 bl_inner = bl_outer + vec2(max(border.radii[1].z, border.widths.x), + -max(border.radii[1].w, border.widths.w)); + + vec4 segment_rect; + switch (sub_part) { + case PST_TOP_LEFT: + segment_rect = vec4(tl_outer, tl_inner - tl_outer); + vBorderStyle = int(border.style.x); + vHorizontalColor = border.colors[BORDER_LEFT]; + vVerticalColor = border.colors[BORDER_TOP]; + vRadii = vec4(border.radii[0].xy, + border.radii[0].xy - border.widths.xy); + break; + case PST_TOP_RIGHT: + segment_rect = vec4(tr_inner.x, + tr_outer.y, + tr_outer.x - tr_inner.x, + tr_inner.y - tr_outer.y); + vBorderStyle = int(border.style.y); + vHorizontalColor = border.colors[BORDER_TOP]; + vVerticalColor = border.colors[BORDER_RIGHT]; + vRadii = vec4(border.radii[0].zw, + border.radii[0].zw - border.widths.zy); + break; + case PST_BOTTOM_RIGHT: + segment_rect = vec4(br_inner, br_outer - br_inner); + vBorderStyle = int(border.style.z); + vHorizontalColor = border.colors[BORDER_BOTTOM]; + vVerticalColor = border.colors[BORDER_RIGHT]; + vRadii = vec4(border.radii[1].xy, + border.radii[1].xy - border.widths.zw); + break; + case PST_BOTTOM_LEFT: + segment_rect = vec4(bl_outer.x, + bl_inner.y, + bl_inner.x - bl_outer.x, + bl_outer.y - bl_inner.y); + vBorderStyle = int(border.style.w); + vHorizontalColor = border.colors[BORDER_BOTTOM]; + vVerticalColor = border.colors[BORDER_LEFT]; + vRadii = vec4(border.radii[1].zw, + border.radii[1].zw - border.widths.xw); + break; + case PST_LEFT: + segment_rect = vec4(tl_outer.x, + tl_inner.y, + border.widths.x, + bl_inner.y - tl_inner.y); + vBorderStyle = int(border.style.x); + vHorizontalColor = border.colors[BORDER_LEFT]; + vVerticalColor = border.colors[BORDER_LEFT]; + vRadii = vec4(0.0); + break; + case PST_RIGHT: + segment_rect = vec4(tr_outer.x - border.widths.z, + tr_inner.y, + border.widths.z, + br_inner.y - tr_inner.y); + vBorderStyle = int(border.style.z); + vHorizontalColor = border.colors[BORDER_RIGHT]; + vVerticalColor = border.colors[BORDER_RIGHT]; + vRadii = vec4(0.0); + break; + case PST_BOTTOM: + segment_rect = vec4(bl_inner.x, + bl_outer.y - border.widths.w, + br_inner.x - bl_inner.x, + border.widths.w); + vBorderStyle = int(border.style.w); + vHorizontalColor = border.colors[BORDER_BOTTOM]; + vVerticalColor = border.colors[BORDER_BOTTOM]; + vRadii = vec4(0.0); + break; + case PST_TOP: + segment_rect = vec4(tl_inner.x, + tl_outer.y, + tr_inner.x - tl_inner.x, + border.widths.y); + vBorderStyle = int(border.style.y); + vHorizontalColor = border.colors[BORDER_TOP]; + vVerticalColor = border.colors[BORDER_TOP]; + vRadii = vec4(0.0); + break; + } + +#ifdef WR_FEATURE_TRANSFORM + TransformVertexInfo vi = write_transform_vertex(segment_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalPos = vi.local_pos; + + // Local space + vLocalRect = vi.clipped_local_rect; +#else + VertexInfo vi = write_vertex(segment_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalPos = vi.local_clamped_pos.xy; + + // Local space + vLocalRect = prim.local_rect; +#endif + + float x0, y0, x1, y1; + switch (sub_part) { + // These are the layer tile part PrimitivePart as uploaded by the tiling.rs + case PST_TOP_LEFT: + x0 = segment_rect.x; + y0 = segment_rect.y; + // These are width / heights + x1 = segment_rect.x + segment_rect.z; + y1 = segment_rect.y + segment_rect.w; + + // The radius here is the border-radius. This is 0, so vRefPoint will + // just be the top left (x,y) corner. + vRefPoint = vec2(x0, y0) + vRadii.xy; + break; + case PST_TOP_RIGHT: + x0 = segment_rect.x + segment_rect.z; + y0 = segment_rect.y; + x1 = segment_rect.x; + y1 = segment_rect.y + segment_rect.w; + vRefPoint = vec2(x0, y0) + vec2(-vRadii.x, vRadii.y); + break; + case PST_BOTTOM_LEFT: + x0 = segment_rect.x; + y0 = segment_rect.y + segment_rect.w; + x1 = segment_rect.x + segment_rect.z; + y1 = segment_rect.y; + vRefPoint = vec2(x0, y0) + vec2(vRadii.x, -vRadii.y); + break; + case PST_BOTTOM_RIGHT: + x0 = segment_rect.x; + y0 = segment_rect.y; + x1 = segment_rect.x + segment_rect.z; + y1 = segment_rect.y + segment_rect.w; + vRefPoint = vec2(x1, y1) + vec2(-vRadii.x, -vRadii.y); + break; + case PST_TOP: + case PST_LEFT: + case PST_BOTTOM: + case PST_RIGHT: + vRefPoint = segment_rect.xy; + x0 = segment_rect.x; + y0 = segment_rect.y; + x1 = segment_rect.x + segment_rect.z; + y1 = segment_rect.y + segment_rect.w; + break; + } + + // y1 - y0 is the height of the corner / line + // x1 - x0 is the width of the corner / line. + float width = x1 - x0; + float height = y1 - y0; + + vBorderPart = sub_part; + vPieceRect = vec4(x0, y0, width, height); + + // The fragment shader needs to calculate the distance from the bisecting line + // to properly mix border colors. For transformed borders, we calculate this distance + // in the fragment shader itself. For non-transformed borders, we can use the + // interpolator. +#ifdef WR_FEATURE_TRANSFORM + vPieceRectHypotenuseLength = sqrt(pow(width, 2.0) + pow(height, 2.0)); +#else + vDistanceFromMixLine = (vi.local_clamped_pos.x - x0) * height - + (vi.local_clamped_pos.y - y0) * width; + vDistanceFromMiddle = (vi.local_clamped_pos.x - vLocalRect.x) + + (vi.local_clamped_pos.y - vLocalRect.y) - + 0.5 * (vLocalRect.z + vLocalRect.w); +#endif +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_box_shadow.fs.glsl @@ -0,0 +1,9 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + vec2 uv = min(vec2(1.0), vMirrorPoint - abs(vUv.xy - vMirrorPoint)); + uv = mix(vCacheUvRectCoords.xy, vCacheUvRectCoords.zw, uv); + oFragColor = vColor * texture(sCache, vec3(uv, vUv.z)); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_box_shadow.glsl @@ -0,0 +1,9 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +flat varying vec4 vColor; + +varying vec3 vUv; +flat varying vec2 vMirrorPoint; +flat varying vec4 vCacheUvRectCoords;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_box_shadow.vs.glsl @@ -0,0 +1,32 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + Primitive prim = load_primitive(); + BoxShadow bs = fetch_boxshadow(prim.prim_index); + vec4 segment_rect = fetch_instance_geometry(prim.sub_index); + + VertexInfo vi = write_vertex(segment_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + + RenderTaskData child_task = fetch_render_task(prim.user_data.x); + vUv.z = child_task.data1.x; + + // Constant offsets to inset from bilinear filtering border. + vec2 patch_origin = child_task.data0.xy + vec2(1.0); + vec2 patch_size_device_pixels = child_task.data0.zw - vec2(2.0); + vec2 patch_size = patch_size_device_pixels / uDevicePixelRatio; + + vUv.xy = (vi.local_clamped_pos - prim.local_rect.xy) / patch_size; + vMirrorPoint = 0.5 * prim.local_rect.zw / patch_size; + + vec2 texture_size = vec2(textureSize(sCache, 0)); + vCacheUvRectCoords = vec4(patch_origin, patch_origin + patch_size_device_pixels) / texture_size.xyxy; + + vColor = bs.color; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_cache_image.fs.glsl @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + oFragColor = texture(sCache, vUv); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_cache_image.glsl @@ -0,0 +1,5 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec3 vUv;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_cache_image.vs.glsl @@ -0,0 +1,28 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Draw a cached primitive (e.g. a blurred text run) from the +// target cache to the framebuffer, applying tile clip boundaries. + +void main(void) { + Primitive prim = load_primitive(); + + VertexInfo vi = write_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + + RenderTaskData child_task = fetch_render_task(prim.user_data.x); + vUv.z = child_task.data1.x; + + vec2 texture_size = vec2(textureSize(sCache, 0)); + vec2 uv0 = child_task.data0.xy / texture_size; + vec2 uv1 = (child_task.data0.xy + child_task.data0.zw) / texture_size; + + vec2 f = (vi.local_clamped_pos - prim.local_rect.xy) / prim.local_rect.zw; + + vUv.xy = mix(uv0, uv1, f); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_clear.fs.glsl @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + oFragColor = vec4(1.0, 1.0, 1.0, 1.0); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_clear.glsl @@ -0,0 +1,3 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_clear.vs.glsl @@ -0,0 +1,14 @@ +#line 1 + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +in ivec4 aClearRectangle; + +void main() { + vec4 rect = vec4(aClearRectangle); + + vec4 pos = vec4(mix(rect.xy, rect.xy + rect.zw, aPosition.xy), 0, 1); + gl_Position = uTransform * pos; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_composite.fs.glsl @@ -0,0 +1,219 @@ +#line 1 + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +float gauss(float x, float sigma) { + if (sigma == 0.0) + return 1.0; + return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma)); +} + +vec3 Multiply(vec3 Cb, vec3 Cs) { + return Cb * Cs; +} + +vec3 Screen(vec3 Cb, vec3 Cs) { + return Cb + Cs - (Cb * Cs); +} + +vec3 HardLight(vec3 Cb, vec3 Cs) { + vec3 m = Multiply(Cb, 2.0 * Cs); + vec3 s = Screen(Cb, 2.0 * Cs - 1.0); + vec3 edge = vec3(0.5, 0.5, 0.5); + return mix(m, s, step(edge, Cs)); +} + +// TODO: Worth doing with mix/step? Check GLSL output. +float ColorDodge(float Cb, float Cs) { + if (Cb == 0.0) + return 0.0; + else if (Cs == 1.0) + return 1.0; + else + return min(1.0, Cb / (1.0 - Cs)); +} + +// TODO: Worth doing with mix/step? Check GLSL output. +float ColorBurn(float Cb, float Cs) { + if (Cb == 1.0) + return 1.0; + else if (Cs == 0.0) + return 0.0; + else + return 1.0 - min(1.0, (1.0 - Cb) / Cs); +} + +float SoftLight(float Cb, float Cs) { + if (Cs <= 0.5) { + return Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb); + } else { + float D; + + if (Cb <= 0.25) + D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb; + else + D = sqrt(Cb); + + return Cb + (2.0 * Cs - 1.0) * (D - Cb); + } +} + +vec3 Difference(vec3 Cb, vec3 Cs) { + return abs(Cb - Cs); +} + +vec3 Exclusion(vec3 Cb, vec3 Cs) { + return Cb + Cs - 2.0 * Cb * Cs; +} + +// These functions below are taken from the spec. +// There's probably a much quicker way to implement +// them in GLSL... +float Sat(vec3 c) { + return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b)); +} + +float Lum(vec3 c) { + vec3 f = vec3(0.3, 0.59, 0.11); + return dot(c, f); +} + +vec3 ClipColor(vec3 C) { + float L = Lum(C); + float n = min(C.r, min(C.g, C.b)); + float x = max(C.r, max(C.g, C.b)); + + if (n < 0.0) + C = L + (((C - L) * L) / (L - n)); + + if (x > 1.0) + C = L + (((C - L) * (1.0 - L)) / (x - L)); + + return C; +} + +vec3 SetLum(vec3 C, float l) { + float d = l - Lum(C); + return ClipColor(C + d); +} + +void SetSatInner(inout float Cmin, inout float Cmid, inout float Cmax, float s) { + if (Cmax > Cmin) { + Cmid = (((Cmid - Cmin) * s) / (Cmax - Cmin)); + Cmax = s; + } else { + Cmid = 0.0; + Cmax = 0.0; + } + Cmin = 0.0; +} + +vec3 SetSat(vec3 C, float s) { + if (C.r <= C.g) { + if (C.g <= C.b) { + SetSatInner(C.r, C.g, C.b, s); + } else { + if (C.r <= C.b) { + SetSatInner(C.r, C.b, C.g, s); + } else { + SetSatInner(C.b, C.r, C.g, s); + } + } + } else { + if (C.r <= C.b) { + SetSatInner(C.g, C.r, C.b, s); + } else { + if (C.g <= C.b) { + SetSatInner(C.g, C.b, C.r, s); + } else { + SetSatInner(C.b, C.g, C.r, s); + } + } + } + return C; +} + +vec3 Hue(vec3 Cb, vec3 Cs) { + return SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb)); +} + +vec3 Saturation(vec3 Cb, vec3 Cs) { + return SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb)); +} + +vec3 Color(vec3 Cb, vec3 Cs) { + return SetLum(Cs, Lum(Cb)); +} + +vec3 Luminosity(vec3 Cb, vec3 Cs) { + return SetLum(Cb, Lum(Cs)); +} + +void main(void) { + vec4 Cb = texture(sCache, vUv0); + + if (vUv1.x < vUv1Rect.x || + vUv1.x > vUv1Rect.z || + vUv1.y < vUv1Rect.y || + vUv1.y > vUv1Rect.w) { + oFragColor = Cb; + return; + } + + vec4 Cs = texture(sCache, vUv1); + + // Return yellow if none of the branches match (shouldn't happen). + vec4 result = vec4(1.0, 1.0, 0.0, 1.0); + + switch (vOp) { + case 1: + result.rgb = Multiply(Cb.rgb, Cs.rgb); + break; + case 2: + result.rgb = Screen(Cb.rgb, Cs.rgb); + break; + case 3: + result.rgb = HardLight(Cs.rgb, Cb.rgb); // Overlay is inverse of Hardlight + break; + case 6: + result.r = ColorDodge(Cb.r, Cs.r); + result.g = ColorDodge(Cb.g, Cs.g); + result.b = ColorDodge(Cb.b, Cs.b); + break; + case 7: + result.r = ColorBurn(Cb.r, Cs.r); + result.g = ColorBurn(Cb.g, Cs.g); + result.b = ColorBurn(Cb.b, Cs.b); + break; + case 8: + result.rgb = HardLight(Cb.rgb, Cs.rgb); + break; + case 9: + result.r = SoftLight(Cb.r, Cs.r); + result.g = SoftLight(Cb.g, Cs.g); + result.b = SoftLight(Cb.b, Cs.b); + break; + case 10: + result.rgb = Difference(Cb.rgb, Cs.rgb); + break; + case 11: + result.rgb = Exclusion(Cb.rgb, Cs.rgb); + break; + case 12: + result.rgb = Hue(Cb.rgb, Cs.rgb); + break; + case 13: + result.rgb = Saturation(Cb.rgb, Cs.rgb); + break; + case 14: + result.rgb = Color(Cb.rgb, Cs.rgb); + break; + case 15: + result.rgb = Luminosity(Cb.rgb, Cs.rgb); + break; + } + + oFragColor = result; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_composite.glsl @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec3 vUv0; +varying vec3 vUv1; +flat varying vec4 vUv1Rect; +flat varying int vOp;
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_composite.vs.glsl @@ -0,0 +1,50 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +struct Composite { + ivec4 src0_src1_target_id_op; + int z; +}; + +Composite fetch_composite() { + PrimitiveInstance pi = fetch_prim_instance(); + + Composite composite; + composite.src0_src1_target_id_op = ivec4(pi.user_data.xy, + pi.render_task_index, + pi.sub_index); + composite.z = pi.z; + + return composite; +} + +void main(void) { + Composite composite = fetch_composite(); + Tile src0 = fetch_tile(composite.src0_src1_target_id_op.x); + Tile src1 = fetch_tile(composite.src0_src1_target_id_op.y); + Tile dest = fetch_tile(composite.src0_src1_target_id_op.z); + + vec2 local_pos = mix(dest.screen_origin_task_origin.zw, + dest.screen_origin_task_origin.zw + dest.size_target_index.xy, + aPosition.xy); + + vec2 texture_size = vec2(textureSize(sCache, 0)); + vec2 st0 = src0.screen_origin_task_origin.zw / texture_size; + vec2 st1 = (src0.screen_origin_task_origin.zw + src0.size_target_index.xy) / texture_size; + vUv0 = vec3(mix(st0, st1, aPosition.xy), src0.size_target_index.z); + + st0 = vec2(src1.screen_origin_task_origin.zw) / texture_size; + st1 = vec2(src1.screen_origin_task_origin.zw + src1.size_target_index.xy) / texture_size; + vec2 local_virtual_pos = mix(dest.screen_origin_task_origin.xy, + dest.screen_origin_task_origin.xy + dest.size_target_index.xy, + aPosition.xy); + vec2 f = (local_virtual_pos - src1.screen_origin_task_origin.xy) / src1.size_target_index.xy; + vUv1 = vec3(mix(st0, st1, f), src1.size_target_index.z); + vUv1Rect = vec4(st0, st1); + + vOp = composite.src0_src1_target_id_op.w; + + gl_Position = uTransform * vec4(local_pos, composite.z, 1.0); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_gradient.fs.glsl @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { +#ifdef WR_FEATURE_TRANSFORM + float alpha = 0.0; + vec2 local_pos = init_transform_fs(vLocalPos, vLocalRect, alpha); +#else + float alpha = 1.0; + vec2 local_pos = vPos; +#endif + + alpha = min(alpha, do_clip()); + oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_gradient.glsl @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec4 vColor; + +#ifdef WR_FEATURE_TRANSFORM +varying vec3 vLocalPos; +flat varying vec4 vLocalRect; +#else +varying vec2 vPos; +#endif
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_gradient.vs.glsl @@ -0,0 +1,72 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + Primitive prim = load_primitive(); + Gradient gradient = fetch_gradient(prim.prim_index); + + GradientStop g0 = fetch_gradient_stop(prim.sub_index + 0); + GradientStop g1 = fetch_gradient_stop(prim.sub_index + 1); + + vec4 segment_rect; + switch (int(gradient.kind.x)) { + case GRADIENT_HORIZONTAL: { + float x0 = mix(gradient.start_end_point.x, + gradient.start_end_point.z, + g0.offset.x); + float x1 = mix(gradient.start_end_point.x, + gradient.start_end_point.z, + g1.offset.x); + segment_rect.yw = prim.local_rect.yw; + segment_rect.x = x0; + segment_rect.z = x1 - x0; + } break; + case GRADIENT_VERTICAL: { + float y0 = mix(gradient.start_end_point.y, + gradient.start_end_point.w, + g0.offset.x); + float y1 = mix(gradient.start_end_point.y, + gradient.start_end_point.w, + g1.offset.x); + segment_rect.xz = prim.local_rect.xz; + segment_rect.y = y0; + segment_rect.w = y1 - y0; + } break; + } + +#ifdef WR_FEATURE_TRANSFORM + TransformVertexInfo vi = write_transform_vertex(segment_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalRect = vi.clipped_local_rect; + vLocalPos = vi.local_pos; + vec2 f = (vi.local_pos.xy - prim.local_rect.xy) / prim.local_rect.zw; +#else + VertexInfo vi = write_vertex(segment_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + + vec2 f = (vi.local_clamped_pos - segment_rect.xy) / segment_rect.zw; + vPos = vi.local_clamped_pos; +#endif + + write_clip(vi.global_clamped_pos, prim.clip_area); + + switch (int(gradient.kind.x)) { + case GRADIENT_HORIZONTAL: + vColor = mix(g0.color, g1.color, f.x); + break; + case GRADIENT_VERTICAL: + vColor = mix(g0.color, g1.color, f.y); + break; + case GRADIENT_ROTATED: + vColor = vec4(1.0, 0.0, 1.0, 1.0); + break; + } +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_image.fs.glsl @@ -0,0 +1,31 @@ +#line 1 + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { +#ifdef WR_FEATURE_TRANSFORM + float alpha = 0.0; + vec2 pos = init_transform_fs(vLocalPos, vLocalRect, alpha); + + // We clamp the texture coordinate calculation here to the local rectangle boundaries, + // which makes the edge of the texture stretch instead of repeat. + vec2 relative_pos_in_rect = + clamp(pos, vLocalRect.xy, vLocalRect.xy + vLocalRect.zw) - vLocalRect.xy; +#else + float alpha = 1.0; + vec2 relative_pos_in_rect = vLocalPos; +#endif + + alpha = min(alpha, do_clip()); + + // We calculate the particular tile this fragment belongs to, taking into + // account the spacing in between tiles. We only paint if our fragment does + // not fall into that spacing. + vec2 position_in_tile = mod(relative_pos_in_rect, vStretchSize + vTileSpacing); + vec2 st = vTextureOffset + ((position_in_tile / vStretchSize) * vTextureSize); + alpha = alpha * float(all(bvec2(step(position_in_tile, vStretchSize)))); + + oFragColor = vec4(1.0, 1.0, 1.0, alpha) * texture(sColor0, st); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_image.glsl @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +flat varying vec2 vTextureOffset; // Offset of this image into the texture atlas. +flat varying vec2 vTextureSize; // Size of the image in the texture atlas. +flat varying vec2 vTileSpacing; // Amount of space between tiled instances of this image. + +#ifdef WR_FEATURE_TRANSFORM +varying vec3 vLocalPos; +flat varying vec4 vLocalRect; +flat varying vec2 vStretchSize; +#else +varying vec2 vLocalPos; +flat varying vec2 vStretchSize; +#endif
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_image.vs.glsl @@ -0,0 +1,39 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + Primitive prim = load_primitive(); + Image image = fetch_image(prim.prim_index); + ResourceRect res = fetch_resource_rect(prim.user_data.x); + +#ifdef WR_FEATURE_TRANSFORM + TransformVertexInfo vi = write_transform_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalRect = vi.clipped_local_rect; + vLocalPos = vi.local_pos; +#else + VertexInfo vi = write_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalPos = vi.local_clamped_pos - vi.local_rect.p0; +#endif + + write_clip(vi.global_clamped_pos, prim.clip_area); + + // vUv will contain how many times this image has wrapped around the image size. + vec2 texture_size = vec2(textureSize(sColor0, 0)); + vec2 st0 = res.uv_rect.xy / texture_size; + vec2 st1 = res.uv_rect.zw / texture_size; + + vTextureSize = st1 - st0; + vTextureOffset = st0; + vTileSpacing = image.stretch_size_and_tile_spacing.zw; + vStretchSize = image.stretch_size_and_tile_spacing.xy; +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_radial_gradient.fs.glsl @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +float offset(int index) { + return vOffsets[index / 4][index % 4]; +} + +float linearStep(float lo, float hi, float x) { + float d = hi - lo; + float v = x - lo; + if (d != 0.0) { + v /= d; + } + return clamp(v, 0.0, 1.0); +} + +void main(void) { + vec2 cd = vEndCenter - vStartCenter; + vec2 pd = vPos - vStartCenter; + float rd = vEndRadius - vStartRadius; + + // Solve for t in length(t * cd - pd) = vStartRadius + t * rd + // using a quadratic equation in form of At^2 - 2Bt + C = 0 + float A = dot(cd, cd) - rd * rd; + float B = dot(pd, cd) + vStartRadius * rd; + float C = dot(pd, pd) - vStartRadius * vStartRadius; + + float x; + if (A == 0.0) { + // Since A is 0, just solve for -2Bt + C = 0 + if (B == 0.0) { + discard; + } + float t = 0.5 * C / B; + if (vStartRadius + rd * t >= 0.0) { + x = t; + } else { + discard; + } + } else { + float discr = B * B - A * C; + if (discr < 0.0) { + discard; + } + discr = sqrt(discr); + float t0 = (B + discr) / A; + float t1 = (B - discr) / A; + if (vStartRadius + rd * t0 >= 0.0) { + x = t0; + } else if (vStartRadius + rd * t1 >= 0.0) { + x = t1; + } else { + discard; + } + } + + oFragColor = mix(vColors[0], + vColors[1], + linearStep(offset(0), offset(1), x)); + + for (int i=1 ; i < vStopCount-1 ; ++i) { + oFragColor = mix(oFragColor, + vColors[i+1], + linearStep(offset(i), offset(i+1), x)); + } +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_radial_gradient.glsl @@ -0,0 +1,12 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +flat varying int vStopCount; +flat varying vec2 vStartCenter; +flat varying vec2 vEndCenter; +flat varying float vStartRadius; +flat varying float vEndRadius; +varying vec2 vPos; +flat varying vec4 vColors[MAX_STOPS_PER_RADIAL_GRADIENT]; +flat varying vec4 vOffsets[MAX_STOPS_PER_RADIAL_GRADIENT/4];
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_radial_gradient.vs.glsl @@ -0,0 +1,35 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + Primitive prim = load_primitive(); + RadialGradient gradient = fetch_radial_gradient(prim.prim_index); + + VertexInfo vi = write_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + + vStopCount = int(prim.user_data.x); + vPos = vi.local_clamped_pos; + + // Snap the start/end points to device pixel units. + // I'm not sure this is entirely correct, but the + // old render path does this, and it is needed to + // make the angle gradient ref tests pass. It might + // be better to fix this higher up in DL construction + // and not snap here? + vStartCenter = floor(0.5 + gradient.start_end_center.xy * uDevicePixelRatio) / uDevicePixelRatio; + vEndCenter = floor(0.5 + gradient.start_end_center.zw * uDevicePixelRatio) / uDevicePixelRatio; + vStartRadius = gradient.start_end_radius.x; + vEndRadius = gradient.start_end_radius.y; + + for (int i=0 ; i < vStopCount ; ++i) { + GradientStop stop = fetch_gradient_stop(prim.sub_index + i); + vColors[i] = stop.color; + vOffsets[i/4][i%4] = stop.offset.x; + } +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_rectangle.fs.glsl @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + float alpha = 1.0; +#ifdef WR_FEATURE_TRANSFORM + alpha = 0.0; + init_transform_fs(vLocalPos, vLocalRect, alpha); +#endif + +#ifdef WR_FEATURE_CLIP + alpha = min(alpha, do_clip()); +#endif + oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_rectangle.glsl @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec4 vColor; + +#ifdef WR_FEATURE_TRANSFORM +varying vec3 vLocalPos; +flat varying vec4 vLocalRect; +#endif
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_rectangle.vs.glsl @@ -0,0 +1,29 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + Primitive prim = load_primitive(); + Rectangle rect = fetch_rectangle(prim.prim_index); + vColor = rect.color; +#ifdef WR_FEATURE_TRANSFORM + TransformVertexInfo vi = write_transform_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalRect = vi.clipped_local_rect; + vLocalPos = vi.local_pos; +#else + VertexInfo vi = write_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); +#endif + +#ifdef WR_FEATURE_CLIP + write_clip(vi.global_clamped_pos, prim.clip_area); +#endif +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_text_run.fs.glsl @@ -0,0 +1,20 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { +#ifdef WR_FEATURE_SUBPIXEL_AA + //note: the blend mode is not compatible with clipping + oFragColor = texture(sColor0, vUv); +#else + float alpha = texture(sColor0, vUv).a; +#ifdef WR_FEATURE_TRANSFORM + float a = 0.0; + init_transform_fs(vLocalPos, vLocalRect, a); + alpha *= a; +#endif + vec4 color = vColor; + alpha = min(alpha, do_clip()); + oFragColor = vec4(vColor.rgb, vColor.a * alpha); +#endif +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_text_run.glsl @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +flat varying vec4 vColor; +varying vec2 vUv; + +#ifdef WR_FEATURE_TRANSFORM +varying vec3 vLocalPos; +flat varying vec4 vLocalRect; +#endif
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_text_run.vs.glsl @@ -0,0 +1,40 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + Primitive prim = load_primitive(); + TextRun text = fetch_text_run(prim.prim_index); + Glyph glyph = fetch_glyph(prim.sub_index); + ResourceRect res = fetch_resource_rect(prim.user_data.x); + + vec4 local_rect = vec4(glyph.offset.xy, (res.uv_rect.zw - res.uv_rect.xy) / uDevicePixelRatio); + +#ifdef WR_FEATURE_TRANSFORM + TransformVertexInfo vi = write_transform_vertex(local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalRect = vi.clipped_local_rect; + vLocalPos = vi.local_pos; + vec2 f = (vi.local_pos.xy / vi.local_pos.z - local_rect.xy) / local_rect.zw; +#else + VertexInfo vi = write_vertex(local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vec2 f = (vi.local_clamped_pos - vi.local_rect.p0) / (vi.local_rect.p1 - vi.local_rect.p0); +#endif + + write_clip(vi.global_clamped_pos, prim.clip_area); + + vec2 texture_size = vec2(textureSize(sColor0, 0)); + vec2 st0 = res.uv_rect.xy / texture_size; + vec2 st1 = res.uv_rect.zw / texture_size; + + vColor = text.color; + vUv = mix(st0, st1, f); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_yuv_image.fs.glsl @@ -0,0 +1,33 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { +#ifdef WR_FEATURE_TRANSFORM + float alpha = 0.0; + vec2 pos = init_transform_fs(vLocalPos, vLocalRect, alpha); + + // We clamp the texture coordinate calculation here to the local rectangle boundaries, + // which makes the edge of the texture stretch instead of repeat. + vec2 relative_pos_in_rect = + clamp(pos, vLocalRect.xy, vLocalRect.xy + vLocalRect.zw) - vLocalRect.xy; +#else + float alpha = 1.0;; + vec2 relative_pos_in_rect = vLocalPos; +#endif + + alpha = min(alpha, do_clip()); + + vec2 st_y = vTextureOffsetY + relative_pos_in_rect / vStretchSize * vTextureSizeY; + vec2 st_u = vTextureOffsetU + relative_pos_in_rect / vStretchSize * vTextureSizeUv; + vec2 st_v = vTextureOffsetV + relative_pos_in_rect / vStretchSize * vTextureSizeUv; + + float y = texture(sColor0, st_y).r; + float u = texture(sColor1, st_u).r; + float v = texture(sColor2, st_v).r; + + // See the vertex shader for an explanation of where the constants come from. + vec3 rgb = vYuvColorMatrix * vec3(y - 0.06275, u - 0.50196, v - 0.50196); + oFragColor = vec4(rgb, alpha); +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_yuv_image.glsl @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +flat varying vec2 vTextureOffsetY; // Offset of the y plane into the texture atlas. +flat varying vec2 vTextureOffsetU; // Offset of the u plane into the texture atlas. +flat varying vec2 vTextureOffsetV; // Offset of the v plane into the texture atlas. +flat varying vec2 vTextureSizeY; // Size of the y plane in the texture atlas. +flat varying vec2 vTextureSizeUv; // Size of the u and v planes in the texture atlas. +flat varying vec2 vStretchSize; + +flat varying mat3 vYuvColorMatrix; + +#ifdef WR_FEATURE_TRANSFORM +varying vec3 vLocalPos; +flat varying vec4 vLocalRect; +#else +varying vec2 vLocalPos; +#endif
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/ps_yuv_image.vs.glsl @@ -0,0 +1,77 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + Primitive prim = load_primitive(); +#ifdef WR_FEATURE_TRANSFORM + TransformVertexInfo vi = write_transform_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalRect = vi.clipped_local_rect; + vLocalPos = vi.local_pos; +#else + VertexInfo vi = write_vertex(prim.local_rect, + prim.local_clip_rect, + prim.z, + prim.layer, + prim.tile); + vLocalPos = vi.local_clamped_pos - vi.local_rect.p0; +#endif + + YuvImage image = fetch_yuv_image(prim.prim_index); + + vec2 y_texture_size = vec2(textureSize(sColor0, 0)); + vec2 y_st0 = image.y_st_rect.xy / y_texture_size; + vec2 y_st1 = image.y_st_rect.zw / y_texture_size; + + vTextureSizeY = y_st1 - y_st0; + vTextureOffsetY = y_st0; + + vec2 uv_texture_size = vec2(textureSize(sColor1, 0)); + vec2 u_st0 = image.u_st_rect.xy / uv_texture_size; + vec2 u_st1 = image.u_st_rect.zw / uv_texture_size; + + vec2 v_st0 = image.v_st_rect.xy / uv_texture_size; + vec2 v_st1 = image.v_st_rect.zw / uv_texture_size; + + // This assumes the U and V surfaces have the same size. + vTextureSizeUv = u_st1 - u_st0; + vTextureOffsetU = u_st0; + vTextureOffsetV = v_st0; + + vStretchSize = image.size; + + // The constants added to the Y, U and V components are applied in the fragment shader. + if (image.color_space == YUV_REC601) { + // From Rec601: + // [R] [1.1643835616438356, 0.0, 1.5960267857142858 ] [Y - 16] + // [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708 ] x [U - 128] + // [B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [V - 128] + // + // For the range [0,1] instead of [0,255]. + vYuvColorMatrix = mat3( + 1.16438, 0.0, 1.59603, + 1.16438, -0.39176, -0.81297, + 1.16438, 2.01723, 0.0 + ); + } else { // if (image.color_space == YUV_REC709) + // From Rec709: + // [R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [Y - 16] + // [G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444 ] x [U - 128] + // [B] [1.1643835616438356, 2.1124017857142854, 0.0 ] [V - 128] + // + // For the range [0,1] instead of [0,255]: + vYuvColorMatrix = mat3( + 1.16438, 0.0, 1.79274, + 1.16438, -0.21325, -0.53291, + 1.16438, 2.11240, 0.0 + ); + } + + write_clip(vi.global_clamped_pos, prim.clip_area); + +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/shared.glsl @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//====================================================================================== +// Vertex shader attributes and uniforms +//====================================================================================== +#ifdef WR_VERTEX_SHADER + #define varying out + + // Uniform inputs + uniform mat4 uTransform; // Orthographic projection + uniform float uDevicePixelRatio; + + // Attribute inputs + in vec3 aPosition; +#endif + +//====================================================================================== +// Fragment shader attributes and uniforms +//====================================================================================== +#ifdef WR_FRAGMENT_SHADER + precision highp float; + + #define varying in + + // Uniform inputs + + // Fragment shader outputs + out vec4 oFragColor; +#endif + +//====================================================================================== +// Shared shader uniforms +//====================================================================================== +uniform sampler2D sColor0; +uniform sampler2D sColor1; +uniform sampler2D sColor2; +uniform sampler2D sMask; + +//====================================================================================== +// Interpolator definitions +//====================================================================================== + +//====================================================================================== +// VS only types and UBOs +//====================================================================================== + +//====================================================================================== +// VS only functions +//======================================================================================
new file mode 100644 --- /dev/null +++ b/gfx/webrender/res/shared_other.glsl @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//====================================================================================== +// Vertex shader attributes and uniforms +//====================================================================================== +#ifdef WR_VERTEX_SHADER +#endif + +//====================================================================================== +// Fragment shader attributes and uniforms +//====================================================================================== +#ifdef WR_FRAGMENT_SHADER +#endif + +//====================================================================================== +// Interpolator definitions +//====================================================================================== + +//====================================================================================== +// VS only types and UBOs +//====================================================================================== + +//====================================================================================== +// VS only functions +//====================================================================================== + +//====================================================================================== +// FS only functions +//====================================================================================== +#ifdef WR_FRAGMENT_SHADER +#endif
new file mode 100644 --- /dev/null +++ b/gfx/webrender/src/batch_builder.rs @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::f32; +use webrender_traits::{ColorF, BorderStyle}; +use webrender_traits::{BorderSide}; + +//const BORDER_DASH_SIZE: f32 = 3.0; + +pub trait BorderSideHelpers { + fn border_color(&self, + scale_factor_0: f32, + scale_factor_1: f32, + black_color_0: f32, + black_color_1: f32) -> ColorF; +} + +impl BorderSideHelpers for BorderSide { + fn border_color(&self, + scale_factor_0: f32, + scale_factor_1: f32, + black_color_0: f32, + black_color_1: f32) -> ColorF { + match self.style { + BorderStyle::Inset => { + if self.color.r != 0.0 || self.color.g != 0.0 || self.color.b != 0.0 { + self.color.scale_rgb(scale_factor_1) + } else { + ColorF::new(black_color_0, black_color_0, black_color_0, self.color.a) + } + } + BorderStyle::Outset => { + if self.color.r != 0.0 || self.color.g != 0.0 || self.color.b != 0.0 { + self.color.scale_rgb(scale_factor_0) + } else { + ColorF::new(black_color_1, black_color_1, black_color_1, self.color.a) + } + } + _ => self.color, + } + } +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/src/debug_colors.rs @@ -0,0 +1,158 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#![allow(dead_code)] + +use webrender_traits::ColorF; + +// A subset of the standard CSS colors, useful for defining GPU tag colors etc. + +pub const INDIGO: ColorF = ColorF { r: 0.294117647059, g: 0.0, b: 0.509803921569, a: 1.0 }; +pub const GOLD: ColorF = ColorF { r: 1.0, g: 0.843137254902, b: 0.0, a: 1.0 }; +pub const FIREBRICK: ColorF = ColorF { r: 0.698039215686, g: 0.133333333333, b: 0.133333333333, a: 1.0 }; +pub const INDIANRED: ColorF = ColorF { r: 0.803921568627, g: 0.360784313725, b: 0.360784313725, a: 1.0 }; +pub const YELLOW: ColorF = ColorF { r: 1.0, g: 1.0, b: 0.0, a: 1.0 }; +pub const DARKOLIVEGREEN: ColorF = ColorF { r: 0.333333333333, g: 0.419607843137, b: 0.18431372549, a: 1.0 }; +pub const DARKSEAGREEN: ColorF = ColorF { r: 0.560784313725, g: 0.737254901961, b: 0.560784313725, a: 1.0 }; +pub const SLATEGREY: ColorF = ColorF { r: 0.439215686275, g: 0.501960784314, b: 0.564705882353, a: 1.0 }; +pub const DARKSLATEGREY: ColorF = ColorF { r: 0.18431372549, g: 0.309803921569, b: 0.309803921569, a: 1.0 }; +pub const MEDIUMVIOLETRED: ColorF = ColorF { r: 0.780392156863, g: 0.0823529411765, b: 0.521568627451, a: 1.0 }; +pub const MEDIUMORCHID: ColorF = ColorF { r: 0.729411764706, g: 0.333333333333, b: 0.827450980392, a: 1.0 }; +pub const CHARTREUSE: ColorF = ColorF { r: 0.498039215686, g: 1.0, b: 0.0, a: 1.0 }; +pub const MEDIUMSLATEBLUE: ColorF = ColorF { r: 0.482352941176, g: 0.407843137255, b: 0.933333333333, a: 1.0 }; +pub const BLACK: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }; +pub const SPRINGGREEN: ColorF = ColorF { r: 0.0, g: 1.0, b: 0.498039215686, a: 1.0 }; +pub const CRIMSON: ColorF = ColorF { r: 0.862745098039, g: 0.078431372549, b: 0.235294117647, a: 1.0 }; +pub const LIGHTSALMON: ColorF = ColorF { r: 1.0, g: 0.627450980392, b: 0.478431372549, a: 1.0 }; +pub const BROWN: ColorF = ColorF { r: 0.647058823529, g: 0.164705882353, b: 0.164705882353, a: 1.0 }; +pub const TURQUOISE: ColorF = ColorF { r: 0.250980392157, g: 0.878431372549, b: 0.81568627451, a: 1.0 }; +pub const OLIVEDRAB: ColorF = ColorF { r: 0.419607843137, g: 0.556862745098, b: 0.137254901961, a: 1.0 }; +pub const CYAN: ColorF = ColorF { r: 0.0, g: 1.0, b: 1.0, a: 1.0 }; +pub const SILVER: ColorF = ColorF { r: 0.752941176471, g: 0.752941176471, b: 0.752941176471, a: 1.0 }; +pub const SKYBLUE: ColorF = ColorF { r: 0.529411764706, g: 0.807843137255, b: 0.921568627451, a: 1.0 }; +pub const GRAY: ColorF = ColorF { r: 0.501960784314, g: 0.501960784314, b: 0.501960784314, a: 1.0 }; +pub const DARKTURQUOISE: ColorF = ColorF { r: 0.0, g: 0.807843137255, b: 0.819607843137, a: 1.0 }; +pub const GOLDENROD: ColorF = ColorF { r: 0.854901960784, g: 0.647058823529, b: 0.125490196078, a: 1.0 }; +pub const DARKGREEN: ColorF = ColorF { r: 0.0, g: 0.392156862745, b: 0.0, a: 1.0 }; +pub const DARKVIOLET: ColorF = ColorF { r: 0.580392156863, g: 0.0, b: 0.827450980392, a: 1.0 }; +pub const DARKGRAY: ColorF = ColorF { r: 0.662745098039, g: 0.662745098039, b: 0.662745098039, a: 1.0 }; +pub const LIGHTPINK: ColorF = ColorF { r: 1.0, g: 0.713725490196, b: 0.756862745098, a: 1.0 }; +pub const TEAL: ColorF = ColorF { r: 0.0, g: 0.501960784314, b: 0.501960784314, a: 1.0 }; +pub const DARKMAGENTA: ColorF = ColorF { r: 0.545098039216, g: 0.0, b: 0.545098039216, a: 1.0 }; +pub const LIGHTGOLDENRODYELLOW: ColorF = ColorF { r: 0.980392156863, g: 0.980392156863, b: 0.823529411765, a: 1.0 }; +pub const LAVENDER: ColorF = ColorF { r: 0.901960784314, g: 0.901960784314, b: 0.980392156863, a: 1.0 }; +pub const YELLOWGREEN: ColorF = ColorF { r: 0.603921568627, g: 0.803921568627, b: 0.196078431373, a: 1.0 }; +pub const THISTLE: ColorF = ColorF { r: 0.847058823529, g: 0.749019607843, b: 0.847058823529, a: 1.0 }; +pub const VIOLET: ColorF = ColorF { r: 0.933333333333, g: 0.509803921569, b: 0.933333333333, a: 1.0 }; +pub const NAVY: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.501960784314, a: 1.0 }; +pub const DIMGREY: ColorF = ColorF { r: 0.411764705882, g: 0.411764705882, b: 0.411764705882, a: 1.0 }; +pub const ORCHID: ColorF = ColorF { r: 0.854901960784, g: 0.439215686275, b: 0.839215686275, a: 1.0 }; +pub const BLUE: ColorF = ColorF { r: 0.0, g: 0.0, b: 1.0, a: 1.0 }; +pub const GHOSTWHITE: ColorF = ColorF { r: 0.972549019608, g: 0.972549019608, b: 1.0, a: 1.0 }; +pub const HONEYDEW: ColorF = ColorF { r: 0.941176470588, g: 1.0, b: 0.941176470588, a: 1.0 }; +pub const CORNFLOWERBLUE: ColorF = ColorF { r: 0.392156862745, g: 0.58431372549, b: 0.929411764706, a: 1.0 }; +pub const DARKBLUE: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.545098039216, a: 1.0 }; +pub const DARKKHAKI: ColorF = ColorF { r: 0.741176470588, g: 0.717647058824, b: 0.419607843137, a: 1.0 }; +pub const MEDIUMPURPLE: ColorF = ColorF { r: 0.576470588235, g: 0.439215686275, b: 0.858823529412, a: 1.0 }; +pub const CORNSILK: ColorF = ColorF { r: 1.0, g: 0.972549019608, b: 0.862745098039, a: 1.0 }; +pub const RED: ColorF = ColorF { r: 1.0, g: 0.0, b: 0.0, a: 1.0 }; +pub const BISQUE: ColorF = ColorF { r: 1.0, g: 0.894117647059, b: 0.76862745098, a: 1.0 }; +pub const SLATEGRAY: ColorF = ColorF { r: 0.439215686275, g: 0.501960784314, b: 0.564705882353, a: 1.0 }; +pub const DARKCYAN: ColorF = ColorF { r: 0.0, g: 0.545098039216, b: 0.545098039216, a: 1.0 }; +pub const KHAKI: ColorF = ColorF { r: 0.941176470588, g: 0.901960784314, b: 0.549019607843, a: 1.0 }; +pub const WHEAT: ColorF = ColorF { r: 0.960784313725, g: 0.870588235294, b: 0.701960784314, a: 1.0 }; +pub const DEEPSKYBLUE: ColorF = ColorF { r: 0.0, g: 0.749019607843, b: 1.0, a: 1.0 }; +pub const REBECCAPURPLE: ColorF = ColorF { r: 0.4, g: 0.2, b: 0.6, a: 1.0 }; +pub const DARKRED: ColorF = ColorF { r: 0.545098039216, g: 0.0, b: 0.0, a: 1.0 }; +pub const STEELBLUE: ColorF = ColorF { r: 0.274509803922, g: 0.509803921569, b: 0.705882352941, a: 1.0 }; +pub const ALICEBLUE: ColorF = ColorF { r: 0.941176470588, g: 0.972549019608, b: 1.0, a: 1.0 }; +pub const LIGHTSLATEGREY: ColorF = ColorF { r: 0.466666666667, g: 0.533333333333, b: 0.6, a: 1.0 }; +pub const GAINSBORO: ColorF = ColorF { r: 0.862745098039, g: 0.862745098039, b: 0.862745098039, a: 1.0 }; +pub const MEDIUMTURQUOISE: ColorF = ColorF { r: 0.282352941176, g: 0.819607843137, b: 0.8, a: 1.0 }; +pub const FLORALWHITE: ColorF = ColorF { r: 1.0, g: 0.980392156863, b: 0.941176470588, a: 1.0 }; +pub const CORAL: ColorF = ColorF { r: 1.0, g: 0.498039215686, b: 0.313725490196, a: 1.0 }; +pub const PURPLE: ColorF = ColorF { r: 0.501960784314, g: 0.0, b: 0.501960784314, a: 1.0 }; +pub const LIGHTGREY: ColorF = ColorF { r: 0.827450980392, g: 0.827450980392, b: 0.827450980392, a: 1.0 }; +pub const LIGHTCYAN: ColorF = ColorF { r: 0.878431372549, g: 1.0, b: 1.0, a: 1.0 }; +pub const DARKSALMON: ColorF = ColorF { r: 0.913725490196, g: 0.588235294118, b: 0.478431372549, a: 1.0 }; +pub const BEIGE: ColorF = ColorF { r: 0.960784313725, g: 0.960784313725, b: 0.862745098039, a: 1.0 }; +pub const AZURE: ColorF = ColorF { r: 0.941176470588, g: 1.0, b: 1.0, a: 1.0 }; +pub const LIGHTSTEELBLUE: ColorF = ColorF { r: 0.690196078431, g: 0.76862745098, b: 0.870588235294, a: 1.0 }; +pub const OLDLACE: ColorF = ColorF { r: 0.992156862745, g: 0.960784313725, b: 0.901960784314, a: 1.0 }; +pub const GREENYELLOW: ColorF = ColorF { r: 0.678431372549, g: 1.0, b: 0.18431372549, a: 1.0 }; +pub const ROYALBLUE: ColorF = ColorF { r: 0.254901960784, g: 0.411764705882, b: 0.882352941176, a: 1.0 }; +pub const LIGHTSEAGREEN: ColorF = ColorF { r: 0.125490196078, g: 0.698039215686, b: 0.666666666667, a: 1.0 }; +pub const MISTYROSE: ColorF = ColorF { r: 1.0, g: 0.894117647059, b: 0.882352941176, a: 1.0 }; +pub const SIENNA: ColorF = ColorF { r: 0.627450980392, g: 0.321568627451, b: 0.176470588235, a: 1.0 }; +pub const LIGHTCORAL: ColorF = ColorF { r: 0.941176470588, g: 0.501960784314, b: 0.501960784314, a: 1.0 }; +pub const ORANGERED: ColorF = ColorF { r: 1.0, g: 0.270588235294, b: 0.0, a: 1.0 }; +pub const NAVAJOWHITE: ColorF = ColorF { r: 1.0, g: 0.870588235294, b: 0.678431372549, a: 1.0 }; +pub const LIME: ColorF = ColorF { r: 0.0, g: 1.0, b: 0.0, a: 1.0 }; +pub const PALEGREEN: ColorF = ColorF { r: 0.596078431373, g: 0.98431372549, b: 0.596078431373, a: 1.0 }; +pub const BURLYWOOD: ColorF = ColorF { r: 0.870588235294, g: 0.721568627451, b: 0.529411764706, a: 1.0 }; +pub const SEASHELL: ColorF = ColorF { r: 1.0, g: 0.960784313725, b: 0.933333333333, a: 1.0 }; +pub const MEDIUMSPRINGGREEN: ColorF = ColorF { r: 0.0, g: 0.980392156863, b: 0.603921568627, a: 1.0 }; +pub const FUCHSIA: ColorF = ColorF { r: 1.0, g: 0.0, b: 1.0, a: 1.0 }; +pub const PAPAYAWHIP: ColorF = ColorF { r: 1.0, g: 0.937254901961, b: 0.835294117647, a: 1.0 }; +pub const BLANCHEDALMOND: ColorF = ColorF { r: 1.0, g: 0.921568627451, b: 0.803921568627, a: 1.0 }; +pub const PERU: ColorF = ColorF { r: 0.803921568627, g: 0.521568627451, b: 0.247058823529, a: 1.0 }; +pub const AQUAMARINE: ColorF = ColorF { r: 0.498039215686, g: 1.0, b: 0.83137254902, a: 1.0 }; +pub const WHITE: ColorF = ColorF { r: 1.0, g: 1.0, b: 1.0, a: 1.0 }; +pub const DARKSLATEGRAY: ColorF = ColorF { r: 0.18431372549, g: 0.309803921569, b: 0.309803921569, a: 1.0 }; +pub const TOMATO: ColorF = ColorF { r: 1.0, g: 0.388235294118, b: 0.278431372549, a: 1.0 }; +pub const IVORY: ColorF = ColorF { r: 1.0, g: 1.0, b: 0.941176470588, a: 1.0 }; +pub const DODGERBLUE: ColorF = ColorF { r: 0.117647058824, g: 0.564705882353, b: 1.0, a: 1.0 }; +pub const LEMONCHIFFON: ColorF = ColorF { r: 1.0, g: 0.980392156863, b: 0.803921568627, a: 1.0 }; +pub const CHOCOLATE: ColorF = ColorF { r: 0.823529411765, g: 0.411764705882, b: 0.117647058824, a: 1.0 }; +pub const ORANGE: ColorF = ColorF { r: 1.0, g: 0.647058823529, b: 0.0, a: 1.0 }; +pub const FORESTGREEN: ColorF = ColorF { r: 0.133333333333, g: 0.545098039216, b: 0.133333333333, a: 1.0 }; +pub const DARKGREY: ColorF = ColorF { r: 0.662745098039, g: 0.662745098039, b: 0.662745098039, a: 1.0 }; +pub const OLIVE: ColorF = ColorF { r: 0.501960784314, g: 0.501960784314, b: 0.0, a: 1.0 }; +pub const MINTCREAM: ColorF = ColorF { r: 0.960784313725, g: 1.0, b: 0.980392156863, a: 1.0 }; +pub const ANTIQUEWHITE: ColorF = ColorF { r: 0.980392156863, g: 0.921568627451, b: 0.843137254902, a: 1.0 }; +pub const DARKORANGE: ColorF = ColorF { r: 1.0, g: 0.549019607843, b: 0.0, a: 1.0 }; +pub const CADETBLUE: ColorF = ColorF { r: 0.372549019608, g: 0.619607843137, b: 0.627450980392, a: 1.0 }; +pub const MOCCASIN: ColorF = ColorF { r: 1.0, g: 0.894117647059, b: 0.709803921569, a: 1.0 }; +pub const LIMEGREEN: ColorF = ColorF { r: 0.196078431373, g: 0.803921568627, b: 0.196078431373, a: 1.0 }; +pub const SADDLEBROWN: ColorF = ColorF { r: 0.545098039216, g: 0.270588235294, b: 0.0745098039216, a: 1.0 }; +pub const GREY: ColorF = ColorF { r: 0.501960784314, g: 0.501960784314, b: 0.501960784314, a: 1.0 }; +pub const DARKSLATEBLUE: ColorF = ColorF { r: 0.282352941176, g: 0.239215686275, b: 0.545098039216, a: 1.0 }; +pub const LIGHTSKYBLUE: ColorF = ColorF { r: 0.529411764706, g: 0.807843137255, b: 0.980392156863, a: 1.0 }; +pub const DEEPPINK: ColorF = ColorF { r: 1.0, g: 0.078431372549, b: 0.576470588235, a: 1.0 }; +pub const PLUM: ColorF = ColorF { r: 0.866666666667, g: 0.627450980392, b: 0.866666666667, a: 1.0 }; +pub const AQUA: ColorF = ColorF { r: 0.0, g: 1.0, b: 1.0, a: 1.0 }; +pub const DARKGOLDENROD: ColorF = ColorF { r: 0.721568627451, g: 0.525490196078, b: 0.043137254902, a: 1.0 }; +pub const MAROON: ColorF = ColorF { r: 0.501960784314, g: 0.0, b: 0.0, a: 1.0 }; +pub const SANDYBROWN: ColorF = ColorF { r: 0.956862745098, g: 0.643137254902, b: 0.376470588235, a: 1.0 }; +pub const MAGENTA: ColorF = ColorF { r: 1.0, g: 0.0, b: 1.0, a: 1.0 }; +pub const TAN: ColorF = ColorF { r: 0.823529411765, g: 0.705882352941, b: 0.549019607843, a: 1.0 }; +pub const ROSYBROWN: ColorF = ColorF { r: 0.737254901961, g: 0.560784313725, b: 0.560784313725, a: 1.0 }; +pub const PINK: ColorF = ColorF { r: 1.0, g: 0.752941176471, b: 0.796078431373, a: 1.0 }; +pub const LIGHTBLUE: ColorF = ColorF { r: 0.678431372549, g: 0.847058823529, b: 0.901960784314, a: 1.0 }; +pub const PALEVIOLETRED: ColorF = ColorF { r: 0.858823529412, g: 0.439215686275, b: 0.576470588235, a: 1.0 }; +pub const MEDIUMSEAGREEN: ColorF = ColorF { r: 0.235294117647, g: 0.701960784314, b: 0.443137254902, a: 1.0 }; +pub const SLATEBLUE: ColorF = ColorF { r: 0.41568627451, g: 0.352941176471, b: 0.803921568627, a: 1.0 }; +pub const DIMGRAY: ColorF = ColorF { r: 0.411764705882, g: 0.411764705882, b: 0.411764705882, a: 1.0 }; +pub const POWDERBLUE: ColorF = ColorF { r: 0.690196078431, g: 0.878431372549, b: 0.901960784314, a: 1.0 }; +pub const SEAGREEN: ColorF = ColorF { r: 0.180392156863, g: 0.545098039216, b: 0.341176470588, a: 1.0 }; +pub const SNOW: ColorF = ColorF { r: 1.0, g: 0.980392156863, b: 0.980392156863, a: 1.0 }; +pub const MEDIUMBLUE: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.803921568627, a: 1.0 }; +pub const MIDNIGHTBLUE: ColorF = ColorF { r: 0.0980392156863, g: 0.0980392156863, b: 0.439215686275, a: 1.0 }; +pub const PALETURQUOISE: ColorF = ColorF { r: 0.686274509804, g: 0.933333333333, b: 0.933333333333, a: 1.0 }; +pub const PALEGOLDENROD: ColorF = ColorF { r: 0.933333333333, g: 0.909803921569, b: 0.666666666667, a: 1.0 }; +pub const WHITESMOKE: ColorF = ColorF { r: 0.960784313725, g: 0.960784313725, b: 0.960784313725, a: 1.0 }; +pub const DARKORCHID: ColorF = ColorF { r: 0.6, g: 0.196078431373, b: 0.8, a: 1.0 }; +pub const SALMON: ColorF = ColorF { r: 0.980392156863, g: 0.501960784314, b: 0.447058823529, a: 1.0 }; +pub const LIGHTSLATEGRAY: ColorF = ColorF { r: 0.466666666667, g: 0.533333333333, b: 0.6, a: 1.0 }; +pub const LAWNGREEN: ColorF = ColorF { r: 0.486274509804, g: 0.988235294118, b: 0.0, a: 1.0 }; +pub const LIGHTGREEN: ColorF = ColorF { r: 0.564705882353, g: 0.933333333333, b: 0.564705882353, a: 1.0 }; +pub const LIGHTGRAY: ColorF = ColorF { r: 0.827450980392, g: 0.827450980392, b: 0.827450980392, a: 1.0 }; +pub const HOTPINK: ColorF = ColorF { r: 1.0, g: 0.411764705882, b: 0.705882352941, a: 1.0 }; +pub const LIGHTYELLOW: ColorF = ColorF { r: 1.0, g: 1.0, b: 0.878431372549, a: 1.0 }; +pub const LAVENDERBLUSH: ColorF = ColorF { r: 1.0, g: 0.941176470588, b: 0.960784313725, a: 1.0 }; +pub const LINEN: ColorF = ColorF { r: 0.980392156863, g: 0.941176470588, b: 0.901960784314, a: 1.0 }; +pub const MEDIUMAQUAMARINE: ColorF = ColorF { r: 0.4, g: 0.803921568627, b: 0.666666666667, a: 1.0 }; +pub const GREEN: ColorF = ColorF { r: 0.0, g: 0.501960784314, b: 0.0, a: 1.0 }; +pub const BLUEVIOLET: ColorF = ColorF { r: 0.541176470588, g: 0.16862745098, b: 0.886274509804, a: 1.0 }; +pub const PEACHPUFF: ColorF = ColorF { r: 1.0, g: 0.854901960784, b: 0.725490196078, a: 1.0 };
new file mode 100644 --- /dev/null +++ b/gfx/webrender/src/debug_font_data.rs @@ -0,0 +1,1914 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[derive(Debug)] +pub struct BakedGlyph { + pub x0: u32, + pub y0: u32, + pub x1: u32, + pub y1: u32, + pub xo: f32, + pub yo: f32, + pub xa: f32, +} + +pub const FIRST_GLYPH_INDEX: u32 = 32; +pub const BMP_WIDTH: u32 = 128; +pub const BMP_HEIGHT: u32 = 128; +pub const FONT_SIZE: u32 = 19; + +pub const GLYPHS: [BakedGlyph; 96] = [ + BakedGlyph { + x0: 1, + y0: 1, + x1: 1, + y1: 1, + xo: 0.000000, + yo: 0.000000, + xa: 3.864407, + }, + BakedGlyph { + x0: 2, + y0: 1, + x1: 5, + y1: 14, + xo: 1.000000, + yo: -12.000000, + xa: 4.644068, + }, + BakedGlyph { + x0: 6, + y0: 1, + x1: 11, + y1: 6, + xo: 1.000000, + yo: -13.000000, + xa: 6.644068, + }, + BakedGlyph { + x0: 12, + y0: 1, + x1: 23, + y1: 13, + xo: 0.000000, + yo: -12.000000, + xa: 11.067797, + }, + BakedGlyph { + x0: 24, + y0: 1, + x1: 32, + y1: 17, + xo: 1.000000, + yo: -14.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 33, + y0: 1, + x1: 46, + y1: 14, + xo: 1.000000, + yo: -12.000000, + xa: 14.084745, + }, + BakedGlyph { + x0: 47, + y0: 1, + x1: 58, + y1: 14, + xo: 0.000000, + yo: -12.000000, + xa: 10.983051, + }, + BakedGlyph { + x0: 59, + y0: 1, + x1: 61, + y1: 6, + xo: 1.000000, + yo: -13.000000, + xa: 4.067797, + }, + BakedGlyph { + x0: 62, + y0: 1, + x1: 67, + y1: 19, + xo: 1.000000, + yo: -14.000000, + xa: 5.254237, + }, + BakedGlyph { + x0: 68, + y0: 1, + x1: 72, + y1: 19, + xo: 0.000000, + yo: -14.000000, + xa: 5.254237, + }, + BakedGlyph { + x0: 73, + y0: 1, + x1: 81, + y1: 8, + xo: 0.000000, + yo: -12.000000, + xa: 8.000000, + }, + BakedGlyph { + x0: 82, + y0: 1, + x1: 91, + y1: 11, + xo: 0.000000, + yo: -10.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 92, + y0: 1, + x1: 95, + y1: 6, + xo: 0.000000, + yo: -2.000000, + xa: 4.169492, + }, + BakedGlyph { + x0: 96, + y0: 1, + x1: 101, + y1: 3, + xo: 0.000000, + yo: -6.000000, + xa: 4.779661, + }, + BakedGlyph { + x0: 102, + y0: 1, + x1: 105, + y1: 4, + xo: 1.000000, + yo: -2.000000, + xa: 4.169492, + }, + BakedGlyph { + x0: 106, + y0: 1, + x1: 114, + y1: 19, + xo: -1.000000, + yo: -14.000000, + xa: 6.084746, + }, + BakedGlyph { + x0: 115, + y0: 1, + x1: 123, + y1: 14, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 1, + y0: 20, + x1: 6, + y1: 32, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 7, + y0: 20, + x1: 15, + y1: 32, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 16, + y0: 20, + x1: 24, + y1: 33, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 25, + y0: 20, + x1: 34, + y1: 32, + xo: 0.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 35, + y0: 20, + x1: 43, + y1: 33, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 44, + y0: 20, + x1: 52, + y1: 33, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 53, + y0: 20, + x1: 61, + y1: 32, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 62, + y0: 20, + x1: 70, + y1: 33, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 71, + y0: 20, + x1: 79, + y1: 33, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 80, + y0: 20, + x1: 83, + y1: 30, + xo: 1.000000, + yo: -9.000000, + xa: 4.169492, + }, + BakedGlyph { + x0: 84, + y0: 20, + x1: 88, + y1: 32, + xo: 0.000000, + yo: -9.000000, + xa: 4.169492, + }, + BakedGlyph { + x0: 89, + y0: 20, + x1: 98, + y1: 28, + xo: 0.000000, + yo: -9.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 99, + y0: 20, + x1: 108, + y1: 26, + xo: 0.000000, + yo: -8.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 109, + y0: 20, + x1: 118, + y1: 28, + xo: 0.000000, + yo: -9.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 119, + y0: 20, + x1: 125, + y1: 33, + xo: 0.000000, + yo: -12.000000, + xa: 6.440678, + }, + BakedGlyph { + x0: 1, + y0: 34, + x1: 15, + y1: 49, + xo: 1.000000, + yo: -12.000000, + xa: 15.932203, + }, + BakedGlyph { + x0: 16, + y0: 34, + x1: 27, + y1: 46, + xo: 0.000000, + yo: -12.000000, + xa: 10.864407, + }, + BakedGlyph { + x0: 28, + y0: 34, + x1: 37, + y1: 47, + xo: 1.000000, + yo: -12.000000, + xa: 10.677966, + }, + BakedGlyph { + x0: 38, + y0: 34, + x1: 47, + y1: 47, + xo: 1.000000, + yo: -12.000000, + xa: 10.322034, + }, + BakedGlyph { + x0: 48, + y0: 34, + x1: 58, + y1: 47, + xo: 1.000000, + yo: -12.000000, + xa: 11.898305, + }, + BakedGlyph { + x0: 59, + y0: 34, + x1: 67, + y1: 46, + xo: 1.000000, + yo: -12.000000, + xa: 9.406779, + }, + BakedGlyph { + x0: 68, + y0: 34, + x1: 76, + y1: 46, + xo: 1.000000, + yo: -12.000000, + xa: 8.813560, + }, + BakedGlyph { + x0: 77, + y0: 34, + x1: 86, + y1: 47, + xo: 1.000000, + yo: -12.000000, + xa: 11.152542, + }, + BakedGlyph { + x0: 87, + y0: 34, + x1: 97, + y1: 46, + xo: 1.000000, + yo: -12.000000, + xa: 11.728813, + }, + BakedGlyph { + x0: 98, + y0: 34, + x1: 100, + y1: 46, + xo: 1.000000, + yo: -12.000000, + xa: 4.203390, + }, + BakedGlyph { + x0: 101, + y0: 34, + x1: 108, + y1: 47, + xo: 0.000000, + yo: -12.000000, + xa: 8.254237, + }, + BakedGlyph { + x0: 109, + y0: 34, + x1: 118, + y1: 46, + xo: 1.000000, + yo: -12.000000, + xa: 10.152542, + }, + BakedGlyph { + x0: 1, + y0: 50, + x1: 9, + y1: 62, + xo: 1.000000, + yo: -12.000000, + xa: 8.508474, + }, + BakedGlyph { + x0: 10, + y0: 50, + x1: 23, + y1: 62, + xo: 1.000000, + yo: -12.000000, + xa: 14.661017, + }, + BakedGlyph { + x0: 24, + y0: 50, + x1: 34, + y1: 62, + xo: 1.000000, + yo: -12.000000, + xa: 12.016949, + }, + BakedGlyph { + x0: 35, + y0: 50, + x1: 47, + y1: 63, + xo: 1.000000, + yo: -12.000000, + xa: 13.118644, + }, + BakedGlyph { + x0: 48, + y0: 50, + x1: 57, + y1: 62, + xo: 1.000000, + yo: -12.000000, + xa: 10.033898, + }, + BakedGlyph { + x0: 58, + y0: 50, + x1: 70, + y1: 66, + xo: 1.000000, + yo: -12.000000, + xa: 13.118644, + }, + BakedGlyph { + x0: 71, + y0: 50, + x1: 81, + y1: 62, + xo: 1.000000, + yo: -12.000000, + xa: 10.474576, + }, + BakedGlyph { + x0: 82, + y0: 50, + x1: 91, + y1: 63, + xo: 0.000000, + yo: -12.000000, + xa: 8.762712, + }, + BakedGlyph { + x0: 92, + y0: 50, + x1: 101, + y1: 62, + xo: 0.000000, + yo: -12.000000, + xa: 9.288136, + }, + BakedGlyph { + x0: 102, + y0: 50, + x1: 112, + y1: 63, + xo: 1.000000, + yo: -12.000000, + xa: 11.525424, + }, + BakedGlyph { + x0: 113, + y0: 50, + x1: 124, + y1: 62, + xo: 0.000000, + yo: -12.000000, + xa: 10.576271, + }, + BakedGlyph { + x0: 1, + y0: 67, + x1: 16, + y1: 79, + xo: 0.000000, + yo: -12.000000, + xa: 15.610169, + }, + BakedGlyph { + x0: 17, + y0: 67, + x1: 27, + y1: 79, + xo: 0.000000, + yo: -12.000000, + xa: 10.305085, + }, + BakedGlyph { + x0: 28, + y0: 67, + x1: 38, + y1: 79, + xo: 0.000000, + yo: -12.000000, + xa: 9.644068, + }, + BakedGlyph { + x0: 39, + y0: 67, + x1: 48, + y1: 79, + xo: 0.000000, + yo: -12.000000, + xa: 9.491526, + }, + BakedGlyph { + x0: 49, + y0: 67, + x1: 54, + y1: 85, + xo: 1.000000, + yo: -14.000000, + xa: 5.254237, + }, + BakedGlyph { + x0: 55, + y0: 67, + x1: 63, + y1: 85, + xo: -1.000000, + yo: -14.000000, + xa: 6.084746, + }, + BakedGlyph { + x0: 64, + y0: 67, + x1: 68, + y1: 85, + xo: 0.000000, + yo: -14.000000, + xa: 5.254237, + }, + BakedGlyph { + x0: 69, + y0: 67, + x1: 77, + y1: 74, + xo: 1.000000, + yo: -12.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 78, + y0: 67, + x1: 88, + y1: 69, + xo: -1.000000, + yo: 2.000000, + xa: 8.305085, + }, + BakedGlyph { + x0: 89, + y0: 67, + x1: 93, + y1: 72, + xo: 1.000000, + yo: -14.000000, + xa: 6.372881, + }, + BakedGlyph { + x0: 94, + y0: 67, + x1: 102, + y1: 77, + xo: 0.000000, + yo: -9.000000, + xa: 8.627119, + }, + BakedGlyph { + x0: 103, + y0: 67, + x1: 111, + y1: 82, + xo: 1.000000, + yo: -14.000000, + xa: 9.881356, + }, + BakedGlyph { + x0: 112, + y0: 67, + x1: 120, + y1: 77, + xo: 0.000000, + yo: -9.000000, + xa: 7.796610, + }, + BakedGlyph { + x0: 1, + y0: 86, + x1: 10, + y1: 101, + xo: 0.000000, + yo: -14.000000, + xa: 9.881356, + }, + BakedGlyph { + x0: 11, + y0: 86, + x1: 20, + y1: 96, + xo: 0.000000, + yo: -9.000000, + xa: 9.288136, + }, + BakedGlyph { + x0: 21, + y0: 86, + x1: 27, + y1: 100, + xo: 1.000000, + yo: -14.000000, + xa: 6.372881, + }, + BakedGlyph { + x0: 28, + y0: 86, + x1: 37, + y1: 99, + xo: 0.000000, + yo: -9.000000, + xa: 9.711864, + }, + BakedGlyph { + x0: 38, + y0: 86, + x1: 46, + y1: 100, + xo: 1.000000, + yo: -14.000000, + xa: 9.644068, + }, + BakedGlyph { + x0: 47, + y0: 86, + x1: 49, + y1: 99, + xo: 1.000000, + yo: -13.000000, + xa: 4.016949, + }, + BakedGlyph { + x0: 50, + y0: 86, + x1: 55, + y1: 103, + xo: -2.000000, + yo: -13.000000, + xa: 4.016949, + }, + BakedGlyph { + x0: 56, + y0: 86, + x1: 64, + y1: 100, + xo: 1.000000, + yo: -14.000000, + xa: 8.389831, + }, + BakedGlyph { + x0: 65, + y0: 86, + x1: 68, + y1: 101, + xo: 1.000000, + yo: -14.000000, + xa: 4.322034, + }, + BakedGlyph { + x0: 69, + y0: 86, + x1: 82, + y1: 95, + xo: 1.000000, + yo: -9.000000, + xa: 14.627119, + }, + BakedGlyph { + x0: 83, + y0: 86, + x1: 91, + y1: 95, + xo: 1.000000, + yo: -9.000000, + xa: 9.644068, + }, + BakedGlyph { + x0: 92, + y0: 86, + x1: 101, + y1: 96, + xo: 0.000000, + yo: -9.000000, + xa: 9.864407, + }, + BakedGlyph { + x0: 102, + y0: 86, + x1: 110, + y1: 99, + xo: 1.000000, + yo: -9.000000, + xa: 9.881356, + }, + BakedGlyph { + x0: 111, + y0: 86, + x1: 120, + y1: 99, + xo: 0.000000, + yo: -9.000000, + xa: 9.881356, + }, + BakedGlyph { + x0: 1, + y0: 104, + x1: 7, + y1: 113, + xo: 1.000000, + yo: -9.000000, + xa: 6.338983, + }, + BakedGlyph { + x0: 8, + y0: 104, + x1: 15, + y1: 114, + xo: 0.000000, + yo: -9.000000, + xa: 7.254237, + }, + BakedGlyph { + x0: 16, + y0: 104, + x1: 22, + y1: 117, + xo: 1.000000, + yo: -12.000000, + xa: 6.559322, + }, + BakedGlyph { + x0: 23, + y0: 104, + x1: 31, + y1: 114, + xo: 1.000000, + yo: -9.000000, + xa: 9.644068, + }, + BakedGlyph { + x0: 32, + y0: 104, + x1: 40, + y1: 113, + xo: 0.000000, + yo: -9.000000, + xa: 8.135593, + }, + BakedGlyph { + x0: 41, + y0: 104, + x1: 54, + y1: 113, + xo: 0.000000, + yo: -9.000000, + xa: 13.135593, + }, + BakedGlyph { + x0: 55, + y0: 104, + x1: 63, + y1: 113, + xo: 0.000000, + yo: -9.000000, + xa: 8.457627, + }, + BakedGlyph { + x0: 64, + y0: 104, + x1: 72, + y1: 117, + xo: 0.000000, + yo: -9.000000, + xa: 8.033898, + }, + BakedGlyph { + x0: 73, + y0: 104, + x1: 81, + y1: 113, + xo: 0.000000, + yo: -9.000000, + xa: 7.711864, + }, + BakedGlyph { + x0: 82, + y0: 104, + x1: 88, + y1: 122, + xo: 0.000000, + yo: -14.000000, + xa: 5.406780, + }, + BakedGlyph { + x0: 89, + y0: 104, + x1: 91, + y1: 122, + xo: 1.000000, + yo: -14.000000, + xa: 4.440678, + }, + BakedGlyph { + x0: 92, + y0: 104, + x1: 97, + y1: 122, + xo: 0.000000, + yo: -14.000000, + xa: 5.406780, + }, + BakedGlyph { + x0: 98, + y0: 104, + x1: 107, + y1: 108, + xo: 0.000000, + yo: -7.000000, + xa: 9.559322, + }, + BakedGlyph { + x0: 108, + y0: 104, + x1: 116, + y1: 117, + xo: 0.000000, + yo: -13.000000, + xa: 8.474576, + }, +]; + +pub const FONT_BITMAP: [u8; 16384] = [ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x34,0xae,0x00,0x00,0x81,0x90,0x00,0xe0,0x31,0x00,0x00,0x00,0x00,0x06, + 0xba,0x05,0x00,0x00,0xa2,0x23,0x00,0x00,0x00,0x00,0x00,0x1a,0x0d,0x00,0x00,0x00, + 0x00,0x16,0xb2,0xec,0xbc,0x1f,0x00,0x00,0x00,0x49,0x8c,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0d,0x9d,0xeb,0xe5,0x89,0x03,0x00,0x00,0x00,0x00,0x81,0x90,0x00,0x00,0x00, + 0x00,0x13,0x00,0x00,0x11,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x6b,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0x00,0x00,0x4a,0x76,0x00, + 0x3b,0x70,0x70,0x70,0x22,0x00,0x56,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x2d,0x1e,0x00,0x00,0x18,0xac,0xea,0xd2,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x45,0xe9,0x00,0x00,0x8a,0x99,0x00,0xf6,0x2d,0x00,0x00,0x00,0x00,0x2f, + 0xd8,0x00,0x00,0x08,0xf7,0x09,0x00,0x00,0x00,0x00,0x00,0xad,0x52,0x00,0x00,0x00, + 0x00,0xa5,0x8f,0x0c,0x7d,0xba,0x00,0x00,0x06,0xda,0x3d,0x00,0x00,0x00,0x00,0x00, + 0x00,0x92,0xb9,0x20,0x28,0xd7,0x64,0x00,0x00,0x00,0x00,0x8a,0x99,0x00,0x00,0x00, + 0x28,0xdd,0x03,0x00,0xa5,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x45,0x00,0x00,0x00,0x00,0x00,0x80,0xaa,0x00, + 0x54,0xa0,0xa0,0xa0,0x31,0x00,0xbb,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0xe0,0x34,0x00,0x0b,0xd7,0x95,0x1d,0x40,0xe1,0x6d,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x45,0xe9,0x00,0x00,0x7a,0x88,0x00,0xe6,0x1c,0x00,0x00,0x00,0x00,0x60, + 0xa8,0x00,0x00,0x34,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0xb2,0x6b,0x0b,0x00,0x00, + 0x00,0xea,0x22,0x00,0x10,0xf7,0x05,0x00,0x73,0xab,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xd6,0x50,0x00,0x00,0x81,0x98,0x00,0x00,0x00,0x00,0x7a,0x88,0x00,0x00,0x00, + 0xb4,0x6a,0x00,0x00,0x2e,0xe4,0x0d,0x00,0x00,0x24,0xcd,0x61,0x65,0x62,0x61,0xcd, + 0x24,0x00,0x00,0x00,0x00,0x00,0xb6,0x45,0x00,0x00,0x00,0x00,0x00,0x9b,0x83,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c, + 0xda,0x00,0x00,0x5e,0xd0,0x03,0x00,0x00,0x49,0xe6,0x04,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x44,0xe9,0x00,0x00,0x5a,0x67,0x00,0xbf,0x02,0x00,0x1b,0x86,0x86,0xc4, + 0xc5,0x86,0x86,0xb0,0xd9,0x86,0x24,0x00,0x00,0x57,0xc9,0xea,0xd3,0xef,0x85,0x00, + 0x00,0xed,0x1e,0x00,0x0d,0xf7,0x07,0x15,0xe8,0x21,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xbf,0x65,0x00,0x00,0xc6,0x6a,0x00,0x00,0x00,0x00,0x5a,0x67,0x00,0x00,0x47, + 0xd7,0x04,0x00,0x00,0x00,0x9d,0x85,0x00,0x00,0x0d,0x55,0x8d,0xcc,0xcc,0x8c,0x54, + 0x0d,0x00,0x00,0x00,0x00,0x00,0xb6,0x45,0x00,0x00,0x00,0x00,0x01,0xe0,0x2e,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96, + 0x81,0x00,0x00,0xb7,0x80,0x00,0x00,0x00,0x04,0xf1,0x45,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x3d,0xe3,0x00,0x00,0x0f,0x12,0x00,0x21,0x00,0x00,0x13,0x5f,0x5f,0xe0, + 0x86,0x5f,0x5f,0xc2,0x9f,0x5f,0x1a,0x00,0x16,0xf9,0x3d,0x01,0x00,0x03,0x13,0x00, + 0x00,0xae,0x80,0x04,0x6c,0xc4,0x00,0x96,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x56,0xe2,0x1f,0x8e,0xc2,0x06,0x00,0x00,0x00,0x00,0x0f,0x12,0x00,0x00,0xc7, + 0x4f,0x00,0x00,0x00,0x00,0x1a,0xee,0x0d,0x00,0x00,0x00,0x3b,0xb4,0xb5,0x37,0x00, + 0x00,0x00,0x05,0x5f,0x5f,0x5f,0xd1,0x8a,0x5f,0x5f,0x3a,0x00,0x0b,0x76,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xea, + 0x27,0x00,0x00,0xd8,0x4f,0x00,0x00,0x00,0x00,0xc2,0x67,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x35,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xf2, + 0x16,0x00,0x00,0xc6,0x3f,0x00,0x00,0x00,0x65,0xc3,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x1f,0xc7,0xef,0xd1,0x29,0x2c,0xe4,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0d,0xd1,0xfa,0x8f,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xf6, + 0x0a,0x00,0x00,0x00,0x00,0x00,0xca,0x3b,0x00,0x00,0x23,0xec,0x3c,0x3d,0xea,0x21, + 0x00,0x00,0x07,0x93,0x93,0x93,0xe0,0xb0,0x93,0x93,0x5a,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0xcd, + 0x00,0x00,0x00,0xf0,0x3e,0x00,0x00,0x00,0x00,0xb0,0x7f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x25,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0xe4, + 0x00,0x00,0x03,0xf4,0x0f,0x00,0x00,0x00,0x4d,0xec,0x20,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x06,0x00,0x00,0xba,0x63,0x07,0x82,0xc2,0x8d,0x0c,0x00,0x00,0x00, + 0x24,0xda,0x7b,0x97,0xc2,0x0b,0x00,0x01,0xa2,0x03,0x00,0x00,0x00,0x00,0x2a,0xe1, + 0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0x69,0x00,0x00,0x0a,0x5b,0x00,0x00,0x5d,0x0a, + 0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa4,0x74, + 0x00,0x00,0x00,0xf6,0x3a,0x00,0x00,0x00,0x00,0xab,0x85,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x09,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1e,0x67,0xbe, + 0x1e,0x1e,0x40,0xe4,0x1e,0x1e,0x08,0x00,0x01,0x96,0xf2,0x91,0x2b,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4c,0xce,0x02,0x8c,0xb1,0x37,0xa3,0xa2,0x00,0x00,0x00, + 0xc6,0x75,0x00,0x01,0x9c,0xbe,0x0a,0x28,0xd1,0x00,0x00,0x00,0x00,0x00,0x57,0xbc, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7d,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0xf1,0x1c, + 0x00,0x00,0x00,0xde,0x49,0x00,0x00,0x00,0x00,0xbc,0x6d,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xcb,0xea,0xe2, + 0xcb,0xcb,0xe1,0xeb,0xcb,0xcb,0x37,0x00,0x00,0x00,0x2d,0x93,0xee,0xb4,0x1f,0x00, + 0x00,0x00,0x00,0x00,0x05,0xd8,0x40,0x00,0xe2,0x2e,0x00,0x19,0xf5,0x02,0x00,0x13, + 0xff,0x1d,0x00,0x00,0x02,0xa1,0xbb,0x94,0x7b,0x00,0x00,0x00,0x00,0x00,0x84,0x96, + 0x00,0x00,0x00,0x00,0x00,0x00,0x56,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xc0,0x00, + 0x00,0x00,0x00,0xc4,0x6e,0x00,0x00,0x00,0x00,0xe2,0x53,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x52, + 0x00,0x00,0x8b,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xa7,0xd7,0x04, + 0x00,0x00,0x00,0x00,0x70,0xad,0x00,0x00,0xf2,0x15,0x00,0x06,0xf7,0x0a,0x00,0x10, + 0xff,0x23,0x00,0x00,0x00,0x03,0xb2,0xfb,0x13,0x00,0x00,0x00,0x00,0x00,0x7e,0x9b, + 0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb3,0x67,0x00, + 0x00,0x00,0x00,0x77,0xb5,0x00,0x00,0x00,0x2b,0xf5,0x0f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x8c,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x20, + 0x00,0x00,0xbd,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xfc,0x2c, + 0x00,0x00,0x00,0x13,0xe7,0x23,0x00,0x00,0xc1,0x5c,0x00,0x47,0xd7,0x00,0x00,0x00, + 0xb5,0xaf,0x0d,0x00,0x0a,0x60,0xe1,0xbd,0xa5,0x01,0x00,0x00,0x00,0x00,0x51,0xc1, + 0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xf4,0x13,0x00, + 0x00,0x00,0x00,0x19,0xf3,0x57,0x00,0x0b,0xc0,0x98,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7f,0xfe,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xec,0x00, + 0x00,0x01,0xee,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xef,0x0c, + 0x00,0x00,0x00,0x94,0x8a,0x00,0x00,0x00,0x35,0xe8,0xc4,0xed,0x44,0x00,0x00,0x00, + 0x15,0xa9,0xf1,0xdc,0xea,0xaf,0x1e,0x07,0xc7,0x73,0x00,0x00,0x00,0x00,0x24,0xe6, + 0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xb3,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3c,0xea,0xdb,0xf2,0xae,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x02,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0x9b,0x61,0x52,0x6c,0xd1,0x89,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x34,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x1b,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xf4, + 0x0d,0x00,0x00,0x00,0x00,0x00,0xcf,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc1,0x5a,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x02,0x2c,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x69,0x8f,0xe2,0xa5,0x28,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xba, + 0x5e,0x00,0x00,0x00,0x00,0x26,0xe9,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0xf2,0x0b,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x52,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35, + 0xe1,0x0a,0x00,0x00,0x00,0xaf,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xa6,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x46,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xa1,0x7d,0x00,0x00,0x3e,0xd9,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x4d,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1a,0xd2,0x03,0x00,0xa0,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2a,0xed,0x06,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x05,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x1a,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x28,0xb6,0x00,0x14,0x93,0xe1,0xe8,0x99,0x42,0x00,0x00,0x00, + 0x2b,0xaa,0xea,0xf3,0xca,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0xbd, + 0x30,0x00,0x00,0x00,0x63,0xbe,0xbe,0xbe,0xbe,0x94,0x00,0x00,0x00,0x00,0x00,0x0d, + 0x5a,0x8c,0x92,0x00,0x00,0x9e,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0x3a,0x00,0x00,0x39, + 0xbe,0xed,0xde,0x94,0x0f,0x00,0x00,0x00,0x47,0xc5,0xf0,0xce,0x62,0x00,0x00,0x00, + 0x6a,0x88,0x00,0x00,0x00,0x6a,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x2a,0x29,0x00,0x02,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x18,0x00,0x00,0x4a,0x0a, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xd0,0xf3,0xe5,0xa3,0x17,0x00,0x00,0x00, + 0x00,0x00,0x00,0x36,0xe8,0xfb,0x00,0x98,0x8a,0x21,0x16,0x68,0xfb,0x1d,0x00,0x00, + 0x3a,0x6a,0x22,0x11,0x62,0xf8,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xd7,0xed, + 0x41,0x00,0x00,0x00,0x8e,0x8e,0x38,0x38,0x38,0x2c,0x00,0x00,0x00,0x00,0x42,0xdd, + 0xa9,0x5c,0x2b,0x00,0x00,0x39,0x45,0x45,0x45,0x45,0x5a,0xf1,0x24,0x00,0x25,0xef, + 0x54,0x05,0x17,0xad,0xb3,0x00,0x00,0x3e,0xe9,0x46,0x08,0x39,0xe1,0x65,0x00,0x00, + 0xaf,0xd8,0x00,0x00,0x00,0xaf,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x50,0xbc, + 0xe2,0x4f,0x00,0x0a,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0x7c,0x00,0x02,0xaa,0xe9, + 0x8b,0x21,0x00,0x00,0x00,0x00,0x00,0x32,0x49,0x0e,0x16,0xae,0xb1,0x00,0x00,0x00, + 0x00,0x0d,0xad,0xdf,0x61,0xfb,0x00,0x02,0x00,0x00,0x00,0x00,0xba,0x7a,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xac,0x86,0x00,0x00,0x00,0x00,0x00,0x05,0xc6,0x50,0xd4, + 0x41,0x00,0x00,0x00,0x9b,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xf1,0x36, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xae,0x71,0x00,0x00,0x7d,0xa3, + 0x00,0x00,0x00,0x18,0xff,0x13,0x00,0xb6,0x78,0x00,0x00,0x00,0x4b,0xe0,0x04,0x00, + 0x02,0x05,0x00,0x00,0x00,0x02,0x05,0x00,0x00,0x00,0x00,0x13,0x76,0xdf,0xbe,0x53, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d, + 0x84,0xe6,0xb1,0x45,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xeb,0x00,0x00,0x00, + 0x00,0x01,0x58,0x08,0x1e,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0xa8,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xaa,0x70,0x00,0x00,0x00,0x00,0x00,0x87,0x8a,0x00,0xd4, + 0x41,0x00,0x00,0x00,0xad,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xd0,0x54,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xd4,0x02,0x00,0x00,0x8b,0x93, + 0x00,0x00,0x00,0x1e,0xff,0x18,0x00,0xe2,0x4c,0x00,0x00,0x00,0x06,0xfb,0x24,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x9d,0xe9,0x94,0x2a,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x06,0x5b,0xc5,0xd6,0x4e,0x00,0x00,0x00,0x00,0x00,0x75,0xbd,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x69,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3e,0xe4,0x1c,0x00,0x00,0x00,0x00,0x39,0xd0,0x07,0x00,0xd4, + 0x41,0x00,0x00,0x00,0xc5,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0xeb,0x04,0x01, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xcc,0x58,0x00,0x00,0x00,0x45,0xe5, + 0x1a,0x00,0x00,0x74,0xc5,0x00,0x00,0xd2,0x80,0x00,0x00,0x00,0x00,0xe9,0x41,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0xd8,0xcb,0x58,0x06,0x00,0x00, + 0x00,0x00,0x00,0x08,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x5c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x21,0x89,0xef,0x73,0x00,0x00,0x00,0x00,0x2b,0xe6,0x32,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfb,0x00,0x00,0x00,0x00,0x00,0x70,0xd1,0x06,0x00,0x00, + 0x00,0x00,0x82,0xd2,0xed,0x2e,0x00,0x00,0x00,0x00,0x03,0xcd,0x3d,0x00,0x00,0xd4, + 0x41,0x00,0x00,0x00,0xc5,0xf6,0xe8,0xb5,0x3e,0x00,0x00,0x00,0x71,0xdc,0xc6,0xef, + 0xf3,0xc1,0x30,0x00,0x00,0x00,0x00,0x00,0x48,0xd8,0x02,0x00,0x00,0x00,0x00,0x5c, + 0xe9,0x8e,0x7d,0xd8,0x20,0x00,0x00,0x82,0xd4,0x1c,0x00,0x00,0x16,0xed,0x39,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x46,0xb3,0xe4,0x81,0x1b, + 0x00,0x00,0x00,0x05,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x37,0x00,0x00,0x00,0x01, + 0x47,0xb2,0xe5,0x81,0x1a,0x00,0x00,0x00,0x00,0x1d,0xdf,0x49,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfb,0x00,0x00,0x00,0x00,0x67,0xe2,0x1f,0x00,0x00,0x00, + 0x00,0x00,0x25,0x4b,0x95,0xea,0x3f,0x00,0x00,0x00,0x63,0xac,0x00,0x00,0x00,0xd4, + 0x41,0x00,0x00,0x00,0x00,0x00,0x17,0x6c,0xee,0x5c,0x00,0x00,0x94,0xb6,0x29,0x02, + 0x1d,0x8a,0xef,0x11,0x00,0x00,0x00,0x00,0xaf,0x78,0x00,0x00,0x00,0x00,0x03,0x9e, + 0xc5,0x6f,0xc8,0xc2,0x19,0x00,0x00,0x0c,0xab,0xfd,0xc6,0xcd,0xdb,0xff,0x17,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x8d,0xea, + 0xab,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x71,0xda, + 0xc7,0x5b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x76,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfb,0x00,0x00,0x00,0x6f,0xe1,0x24,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x6a,0xe0,0x01,0x00,0x02,0xd9,0x45,0x16,0x16,0x16,0xd7, + 0x51,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0xed,0x01,0x00,0xa1,0x81,0x00,0x00, + 0x00,0x06,0xf1,0x65,0x00,0x00,0x00,0x0d,0xf6,0x20,0x00,0x00,0x00,0x00,0x76,0xc8, + 0x07,0x00,0x00,0x63,0xe6,0x0a,0x00,0x00,0x00,0x16,0x3b,0x26,0x3e,0xf2,0x00,0x00, + 0x56,0x70,0x00,0x00,0x00,0x4a,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b, + 0x66,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x35, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xea,0x11,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfb,0x00,0x00,0x59,0xe6,0x23,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x18,0xff,0x1c,0x00,0x1f,0xcf,0xcf,0xcf,0xcf,0xcf,0xf7, + 0xdc,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xff,0x20,0x00,0x64,0x92,0x00,0x00, + 0x00,0x00,0xb4,0x81,0x00,0x00,0x00,0x5a,0xc7,0x00,0x00,0x00,0x00,0x00,0xca,0x72, + 0x00,0x00,0x00,0x00,0xdc,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x8d,0x9b,0x00,0x00, + 0xbb,0xe4,0x00,0x00,0x00,0x80,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfb,0x00,0x13,0xec,0x3a,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4c,0xfc,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd4, + 0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xfe,0x0d,0x00,0x21,0xcc,0x00,0x00, + 0x00,0x00,0xca,0x63,0x00,0x00,0x00,0x9b,0x8e,0x00,0x00,0x00,0x00,0x00,0xca,0x5e, + 0x00,0x00,0x00,0x00,0xce,0x54,0x00,0x00,0x00,0x00,0x00,0x41,0xed,0x18,0x00,0x00, + 0x09,0x11,0x00,0x00,0x00,0x9b,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfb,0x00,0x6d,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x25,0x04,0x00,0x01,0x32,0xc1,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd4, + 0x41,0x00,0x00,0x22,0x06,0x00,0x00,0x10,0xb0,0xac,0x00,0x00,0x00,0xdd,0x5b,0x00, + 0x00,0x4b,0xec,0x10,0x00,0x00,0x00,0xc6,0x63,0x00,0x00,0x00,0x00,0x00,0x7a,0xcb, + 0x11,0x00,0x00,0x52,0xeb,0x14,0x00,0x00,0x03,0x22,0x88,0xda,0x4b,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0xe0,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x8e,0x2b,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xfb,0x00,0x9b,0xfb,0xf6,0xf6,0xf6,0xf6,0xf6,0x21,0x00, + 0xa4,0xf0,0xcc,0xe7,0xfd,0x9d,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd4, + 0x41,0x00,0x00,0x8f,0xf2,0xce,0xd2,0xf4,0xa2,0x13,0x00,0x00,0x00,0x33,0xe0,0xd8, + 0xcd,0xe0,0x3a,0x00,0x00,0x00,0x01,0xf1,0x38,0x00,0x00,0x00,0x00,0x00,0x04,0x91, + 0xea,0xbe,0xcf,0xdc,0x3f,0x00,0x00,0x52,0xe1,0xbf,0x89,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0b,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0xfe,0x70,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x17,0x39,0x2e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x12,0x37,0x30,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x24, + 0x28,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0e,0x34,0x24,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0e,0x7d,0xb2,0xdc,0xe5,0xb8,0x84,0x14,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x30,0xbd,0x15,0x00,0x00,0x00,0x00,0x00,0x45,0xb2,0xce,0xd4, + 0xc2,0x9a,0x42,0x00,0x00,0x00,0x00,0x00,0x12,0x90,0xce,0xf7,0xea,0xb6,0x4c,0x00, + 0x45,0xb1,0xcb,0xd0,0xb0,0x8b,0x34,0x00,0x00,0x00,0x00,0x5a,0xbe,0xbe,0xbe,0xbe, + 0xbe,0xbe,0x3a,0x00,0x5a,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0x2a,0x00,0x00,0x00,0x11, + 0x8e,0xcb,0xf4,0xdf,0xbb,0x5f,0x00,0x5a,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0xb4, + 0x27,0x00,0x5a,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x94,0x00,0x5a,0x81,0x00, + 0x00,0x00,0x00,0x21,0xb7,0x2f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x54,0xe4,0x9c,0x4a,0x1d,0x13,0x45,0x8c,0xe7,0x5c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa6,0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x79,0xc0,0x2c,0x27, + 0x39,0x74,0xeb,0x79,0x00,0x00,0x00,0x37,0xe5,0x9f,0x43,0x16,0x29,0x63,0x62,0x00, + 0x79,0xc1,0x31,0x2d,0x4f,0x7b,0xe7,0xa6,0x0f,0x00,0x00,0x79,0xc2,0x41,0x41,0x41, + 0x41,0x41,0x14,0x00,0x79,0xc2,0x41,0x41,0x41,0x41,0x41,0x0e,0x00,0x00,0x37,0xe4, + 0x9e,0x3b,0x13,0x28,0x5b,0x83,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xc7,0x00,0x79,0xad,0x00, + 0x00,0x00,0x1b,0xda,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x39,0xeb,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0xe5,0x44,0x00,0x00, + 0x00,0x00,0x00,0x1f,0xed,0x45,0xea,0x09,0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00, + 0x00,0x00,0x42,0xf4,0x06,0x00,0x08,0xd9,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x10,0xb6,0xa5,0x00,0x00,0x79,0xad,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xda,0x73, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xc7,0x00,0x79,0xad,0x00, + 0x00,0x1b,0xd9,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x07,0xd6,0x67,0x00,0x00,0x19,0x63,0x86,0x70,0x36,0x00,0x53,0xe2,0x0e,0x00, + 0x00,0x00,0x00,0x89,0x93,0x00,0xcb,0x61,0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00, + 0x00,0x00,0x1b,0xfd,0x13,0x00,0x72,0xd4,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x19,0xf0,0x4d,0x00,0x79,0xad,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x72,0xd1,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xc7,0x00,0x79,0xad,0x00, + 0x1d,0xd9,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4f,0xd4,0x02,0x00,0x3f,0xe7,0x94,0x64,0x8d,0xe1,0x00,0x00,0xc8,0x50,0x00, + 0x00,0x00,0x08,0xea,0x29,0x00,0x60,0xc9,0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00, + 0x00,0x00,0x80,0xc2,0x00,0x00,0xac,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x8d,0x00,0x79,0xad,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x81,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xc7,0x00,0x79,0xad,0x22, + 0xda,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x7b,0x99,0x00,0x05,0xdc,0x5a,0x00,0x00,0x34,0xe1,0x00,0x00,0x91,0x82,0x00, + 0x00,0x00,0x5d,0xc5,0x00,0x00,0x0b,0xf1,0x32,0x00,0x00,0x00,0x79,0xdf,0x9c,0x9c, + 0xa6,0xd5,0xcc,0x12,0x00,0x00,0xd7,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xbb,0x00,0x79,0xe3,0xa9,0xa9,0xa9, + 0xa9,0x75,0x00,0x00,0x79,0xdf,0x9c,0x9c,0x9c,0x9c,0x5c,0x00,0x00,0xd7,0x5c,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xe2,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xfa, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xc7,0x00,0x79,0xcf,0xe6, + 0x5b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xa7,0x70,0x00,0x2b,0xf3,0x01,0x00,0x00,0x34,0xe1,0x00,0x00,0x6c,0xab,0x00, + 0x00,0x00,0xc1,0x64,0x00,0x00,0x00,0x99,0x97,0x00,0x00,0x00,0x79,0xcc,0x5f,0x5f, + 0x66,0x80,0xd4,0xc1,0x0f,0x00,0xe2,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xc6,0x00,0x79,0xc7,0x52,0x52,0x52, + 0x52,0x39,0x00,0x00,0x79,0xcd,0x63,0x63,0x63,0x63,0x3b,0x00,0x00,0xe2,0x52,0x00, + 0x00,0x00,0x00,0x00,0x16,0x8f,0x00,0x79,0xca,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0xf7, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xc7,0x00,0x79,0xc5,0xba, + 0xd2,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xb9,0x60,0x00,0x3d,0xe4,0x00,0x00,0x00,0x34,0xe1,0x00,0x00,0x79,0x98,0x00, + 0x00,0x24,0xfb,0x41,0x34,0x34,0x34,0x68,0xf0,0x0a,0x00,0x00,0x79,0xad,0x00,0x00, + 0x00,0x00,0x08,0xce,0x80,0x00,0xbb,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x98,0x00,0x79,0xad,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x72,0x00, + 0x00,0x00,0x00,0x00,0x27,0xff,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xc7,0x00,0x79,0xad,0x01, + 0x74,0xea,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8f,0x87,0x00,0x16,0xfd,0x15,0x00,0x00,0x34,0xe1,0x00,0x00,0xb4,0x6d,0x00, + 0x00,0x85,0xe3,0xc7,0xc7,0xc7,0xc7,0xc7,0xee,0x5e,0x00,0x00,0x79,0xad,0x00,0x00, + 0x00,0x00,0x00,0x89,0xb2,0x00,0x90,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x07,0xdb,0x66,0x00,0x79,0xad,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0xaf,0x00, + 0x00,0x00,0x00,0x00,0x27,0xff,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xc0,0x00,0x79,0xad,0x00, + 0x00,0x50,0xec,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x64,0xb2,0x00,0x00,0xa8,0xae,0x0e,0x00,0x3d,0xfb,0x16,0x4b,0xec,0x0f,0x00, + 0x02,0xe2,0x46,0x00,0x00,0x00,0x00,0x00,0x7c,0xbf,0x00,0x00,0x79,0xad,0x00,0x00, + 0x00,0x00,0x00,0xb4,0x90,0x00,0x21,0xf5,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x86,0xce,0x06,0x00,0x79,0xad,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xf6,0x32, + 0x00,0x00,0x00,0x00,0x27,0xff,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0xa5,0x00,0x79,0xad,0x00, + 0x00,0x00,0x52,0xee,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x2a,0xf3,0x24,0x00,0x0f,0x96,0xe4,0xe3,0xc4,0xa4,0xf0,0xcd,0x33,0x00,0x00, + 0x45,0xe5,0x03,0x00,0x00,0x00,0x00,0x00,0x21,0xfd,0x22,0x00,0x79,0xad,0x00,0x00, + 0x00,0x21,0x8d,0xed,0x2a,0x00,0x00,0x74,0xec,0x50,0x04,0x00,0x00,0x11,0x33,0x00, + 0x79,0xad,0x00,0x00,0x0d,0x37,0xb5,0xdf,0x27,0x00,0x00,0x79,0xad,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xec, + 0x53,0x05,0x00,0x00,0x28,0xff,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x4f,0x28,0x00,0x04,0x48,0xf5,0x51,0x00,0x79,0xad,0x00, + 0x00,0x00,0x00,0x6e,0xe1,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x8a,0xbf,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xa4,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0x81,0x00,0x65,0xf3,0xeb,0xe4, + 0xef,0xe5,0x97,0x29,0x00,0x00,0x00,0x00,0x4c,0xdd,0xf5,0xd1,0xe2,0xf7,0x95,0x00, + 0x65,0xf3,0xef,0xeb,0xf0,0xcc,0x74,0x07,0x00,0x00,0x00,0x79,0xff,0xff,0xff,0xff, + 0xff,0xff,0xbe,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4b, + 0xd9,0xf7,0xd1,0xd4,0xf2,0xd1,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, + 0x34,0x00,0x79,0xad,0x00,0x75,0xf0,0xd8,0xe9,0xfd,0x86,0x02,0x00,0x79,0xad,0x00, + 0x00,0x00,0x00,0x00,0xad,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x08,0xcf,0xbd,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x11,0x15, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x3a,0x30,0x0a,0x00,0x00, + 0x00,0x02,0x10,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x10,0x34,0x24,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x30,0x33,0x0b,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x07,0x78,0xeb,0xba,0x91,0x72,0x7c,0x72,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x12,0x41,0x68,0x84,0x76,0x44,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x5a,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb7,0x37,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x6e,0x77,0x00,0x00,0x5a,0x8e,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7a,0x5d,0x00,0x00,0x00,0x13,0x93,0xcd,0xf3,0xd3,0x9e,0x1e,0x00,0x00,0x00,0x00, + 0x44,0xaf,0xca,0xd3,0xbc,0x9b,0x39,0x00,0x00,0x00,0x00,0x00,0x13,0x93,0xcd,0xf3, + 0xd3,0x9e,0x1e,0x00,0x00,0x00,0x00,0x44,0xaf,0xca,0xd3,0xbc,0x99,0x36,0x00,0x00, + 0x00,0x00,0x00,0x09,0x63,0xab,0xee,0xed,0xb8,0x4b,0x00,0x00,0x84,0xbe,0xbe,0xbe, + 0xbe,0xbe,0xbe,0xbe,0xbb,0x00,0x64,0x77,0x00,0x00,0x00,0x00,0x00,0x13,0xbe,0x0a, + 0x00,0x85,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xb1,0x34,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0xff,0xc4,0x01,0x00,0x00, + 0x00,0x00,0x00,0x1a,0xf4,0xb2,0x00,0x00,0x79,0xff,0x78,0x00,0x00,0x00,0x00,0x00, + 0xa4,0x7d,0x00,0x00,0x3c,0xe8,0x9c,0x3f,0x16,0x39,0x8c,0xee,0x4f,0x00,0x00,0x00, + 0x79,0xc2,0x34,0x2b,0x3d,0x7d,0xed,0x83,0x00,0x00,0x00,0x3c,0xe8,0x9c,0x3f,0x16, + 0x39,0x8c,0xee,0x4f,0x00,0x00,0x00,0x79,0xc2,0x35,0x2b,0x3c,0x7b,0xed,0x78,0x00, + 0x00,0x00,0x00,0x6a,0xc2,0x30,0x08,0x1e,0x5e,0x58,0x00,0x00,0x2d,0x41,0x41,0x41, + 0xf2,0x6b,0x41,0x41,0x40,0x00,0x86,0xa0,0x00,0x00,0x00,0x00,0x00,0x1a,0xff,0x0d, + 0x00,0x63,0xe1,0x01,0x00,0x00,0x00,0x00,0x00,0x3d,0xed,0x07,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xef,0xdd,0x4e,0x00,0x00, + 0x00,0x00,0x00,0x98,0xcd,0xc8,0x00,0x00,0x79,0xc4,0xe6,0x4b,0x00,0x00,0x00,0x00, + 0xa4,0x7d,0x00,0x09,0xdd,0x71,0x00,0x00,0x00,0x00,0x00,0x53,0xed,0x16,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x32,0xfe,0x27,0x00,0x09,0xdd,0x71,0x00,0x00,0x00, + 0x00,0x00,0x53,0xed,0x16,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x3b,0xfd,0x1a, + 0x00,0x00,0x02,0xd8,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x86,0xa0,0x00,0x00,0x00,0x00,0x00,0x1a,0xff,0x0d, + 0x00,0x0f,0xf7,0x3a,0x00,0x00,0x00,0x00,0x00,0x95,0x98,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xd8,0x61,0xcb,0x01,0x00, + 0x00,0x00,0x1f,0xea,0x4a,0xdd,0x00,0x00,0x79,0xa9,0x3d,0xe9,0x1f,0x00,0x00,0x00, + 0xa4,0x7d,0x00,0x76,0xd4,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x94,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0xdc,0x5b,0x00,0x76,0xd4,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0xb9,0x94,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0xeb,0x49, + 0x00,0x00,0x09,0xfc,0x2f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x86,0xa0,0x00,0x00,0x00,0x00,0x00,0x1a,0xff,0x0d, + 0x00,0x00,0xac,0x93,0x00,0x00,0x00,0x00,0x04,0xe9,0x3c,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0xc4,0x05,0xdf,0x4a,0x00, + 0x00,0x00,0x97,0x84,0x27,0xf3,0x00,0x00,0x79,0xa9,0x00,0x79,0xc8,0x06,0x00,0x00, + 0xa4,0x7d,0x00,0xad,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xcb,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x01,0xed,0x47,0x00,0xad,0x81,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x62,0xcb,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x09,0xf9,0x1f, + 0x00,0x00,0x00,0xaf,0xc5,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x86,0xa0,0x00,0x00,0x00,0x00,0x00,0x1a,0xff,0x0d, + 0x00,0x00,0x4f,0xea,0x05,0x00,0x00,0x00,0x49,0xdc,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xb1,0x00,0x6a,0xc2,0x00, + 0x00,0x18,0xed,0x15,0x14,0xff,0x09,0x00,0x79,0xa9,0x00,0x02,0xbc,0x88,0x00,0x00, + 0xa4,0x7d,0x00,0xd8,0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0xf4,0x02,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x75,0xeb,0x10,0x00,0xd8,0x5c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x3e,0xf4,0x02,0x00,0x79,0xad,0x00,0x00,0x00,0x08,0x95,0xc4,0x00, + 0x00,0x00,0x00,0x0e,0x9f,0xf5,0x9e,0x2f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x86,0xa0,0x00,0x00,0x00,0x00,0x00,0x1a,0xff,0x0d, + 0x00,0x00,0x05,0xe8,0x4a,0x00,0x00,0x00,0xa4,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0x9d,0x00,0x09,0xe8,0x3a, + 0x00,0x88,0x92,0x00,0x03,0xfd,0x1b,0x00,0x79,0xa9,0x00,0x00,0x1b,0xea,0x3c,0x00, + 0xa4,0x7d,0x00,0xe1,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xfa,0x05,0x00, + 0x79,0xd9,0x8a,0x90,0xa1,0xdb,0xda,0x38,0x00,0x00,0xe2,0x54,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x35,0xfc,0x06,0x00,0x79,0xe9,0xba,0xbd,0xc9,0xf2,0x90,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x25,0x92,0xf2,0xa9,0x12,0x00,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x86,0xa0,0x00,0x00,0x00,0x00,0x00,0x1a,0xff,0x0d, + 0x00,0x00,0x00,0x8c,0xa9,0x00,0x00,0x0f,0xf3,0x1e,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x90,0x00,0x00,0x79,0xb0, + 0x0d,0xea,0x1f,0x00,0x00,0xf2,0x29,0x00,0x79,0xa9,0x00,0x00,0x00,0x57,0xdc,0x0b, + 0xa4,0x7d,0x00,0xb8,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xd6,0x00,0x00, + 0x79,0xd2,0x75,0x6f,0x5a,0x37,0x01,0x00,0x00,0x00,0xb9,0x77,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x59,0xdc,0x00,0x00,0x79,0xc2,0x41,0x40,0x4a,0xf0,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xc5,0xb4,0x00,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x84,0xa4,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0x0b, + 0x00,0x00,0x00,0x29,0xf7,0x12,0x00,0x66,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0x85,0x00,0x00,0x10,0xf0, + 0x96,0xa0,0x00,0x00,0x00,0xe7,0x38,0x00,0x79,0xa9,0x00,0x00,0x00,0x00,0xab,0x8a, + 0xa4,0x7d,0x00,0x8b,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xa9,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0xb8,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x9a,0xab,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x62,0xe3,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xfd,0x0c,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x6b,0xc2,0x00,0x00,0x00,0x00,0x00,0x3e,0xef,0x00, + 0x00,0x00,0x00,0x00,0xbe,0x6e,0x00,0xca,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9f,0x7a,0x00,0x00,0x00,0x8e, + 0xff,0x2d,0x00,0x00,0x00,0xdb,0x47,0x00,0x79,0xa9,0x00,0x00,0x00,0x00,0x16,0xe8, + 0xcf,0x7d,0x00,0x1d,0xf3,0x43,0x00,0x00,0x00,0x00,0x00,0x29,0xf7,0x31,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0xf4,0x43,0x00,0x00,0x00, + 0x00,0x00,0x29,0xf9,0x32,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0xb1,0xa4,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3a,0xe9,0x09,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x3e,0xf3,0x16,0x00,0x00,0x00,0x00,0x86,0xc0,0x00, + 0x00,0x00,0x00,0x00,0x55,0xd7,0x35,0xe4,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x6f,0x00,0x00,0x00,0x15, + 0x46,0x00,0x00,0x00,0x00,0xd0,0x56,0x00,0x79,0xa9,0x00,0x00,0x00,0x00,0x00,0x61, + 0xff,0x7d,0x00,0x00,0x6b,0xf1,0x5c,0x05,0x00,0x03,0x4c,0xe9,0x84,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xf1,0x5c,0x05,0x00, + 0x03,0x4c,0xe9,0x84,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x1b,0xf0,0x44, + 0x00,0x00,0x15,0x47,0x02,0x00,0x00,0x15,0xb7,0x7b,0x00,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x00,0xc4,0xb7,0x14,0x00,0x00,0x4f,0xf5,0x4a,0x00, + 0x00,0x00,0x00,0x00,0x04,0xe1,0xd3,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x79,0xff,0xff,0xff,0xff,0xff,0xff,0x34,0x00,0xbb,0x64,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc4,0x65,0x00,0x79,0xa9,0x00,0x00,0x00,0x00,0x00,0x01, + 0xc4,0x7d,0x00,0x00,0x00,0x41,0xd4,0xf7,0xd4,0xf4,0xde,0x52,0x00,0x00,0x00,0x00, + 0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xd4,0xf7,0xd4, + 0xf4,0xd5,0x5f,0x00,0x00,0x00,0x00,0x79,0xad,0x00,0x00,0x00,0x00,0x00,0x75,0xcc, + 0x01,0x00,0x33,0xda,0xee,0xc9,0xd9,0xdc,0x99,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0xee,0x38,0x00,0x00,0x00,0x00,0x00,0x13,0xaf,0xf6,0xd5,0xe7,0xeb,0x58,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x75,0xf7,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x35,0x15,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x94, + 0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1b,0x38,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x32,0x1f,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12, + 0xd6,0xa9,0x37,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0a,0x75,0xce,0xf0,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x3e,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0xb1, + 0x00,0x18,0xba,0x29,0x00,0x00,0x00,0x00,0x07,0xac,0x40,0x00,0x77,0x85,0x00,0x00, + 0x00,0x00,0x00,0x07,0xb2,0x32,0x00,0x06,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0x7a, + 0x00,0x15,0x45,0x45,0x45,0x08,0x00,0x18,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3c,0x45,0x45,0x27,0x00,0x00,0x00,0x07,0xb1,0x65,0x00,0x00,0x00,0x00,0x12,0xcf, + 0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0x51,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x1c, + 0xc9,0xea,0xe5,0xad,0x20,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1e,0xa5,0xde,0xea,0xc5,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x2c,0xfc,0x09,0x00,0x00,0x00,0x00,0x39,0x1d,0x00,0x00,0x00,0x00,0x62,0xc5, + 0x00,0x00,0x81,0xc9,0x04,0x00,0x00,0x00,0x87,0xbb,0x01,0x00,0x28,0xf8,0x29,0x00, + 0x00,0x00,0x00,0x6f,0xc4,0x01,0x00,0x02,0x41,0x41,0x41,0x41,0x41,0x49,0xe8,0x72, + 0x00,0x4e,0xe4,0x93,0x93,0x11,0x00,0x20,0xee,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7f,0x93,0xc8,0x8f,0x00,0x00,0x00,0x75,0xae,0xe3,0x14,0x00,0x00,0x00,0x03,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x0d,0x00,0xae,0x6d,0x00,0x00,0x00,0x00,0x09, + 0x35,0x12,0x1b,0x8f,0xd4,0x03,0x00,0x89,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x1f,0xeb,0xb4,0x47,0x13,0x3e,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x05,0xf9,0x33,0x00,0x00,0x00,0x05,0xec,0x96,0x00,0x00,0x00,0x00,0x94,0x96, + 0x00,0x00,0x05,0xcd,0x78,0x00,0x00,0x37,0xec,0x1d,0x00,0x00,0x00,0x95,0xa9,0x00, + 0x00,0x00,0x0c,0xe7,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa4,0xaa,0x01, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0xc4,0x51,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x14,0xe3,0x19,0x7d,0x93,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xe0,0x76,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x05,0xef,0x2b,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xa3,0xb3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xd2,0x62,0x00,0x00,0x00,0x47,0xee,0xe7,0x02,0x00,0x00,0x00,0xc7,0x66, + 0x00,0x00,0x00,0x2c,0xf1,0x2b,0x08,0xd6,0x5d,0x00,0x00,0x00,0x00,0x15,0xee,0x35, + 0x00,0x00,0x81,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xd9,0x0d,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x6b,0xab,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x92,0x7e,0x00,0x0a,0xdf,0x27,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0xc2,0x3d,0x00,0x00,0x00, + 0x03,0x27,0x3b,0x24,0xd7,0x44,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xe6,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x9f,0x96,0x00,0x00,0x00,0x9c,0x7a,0xe1,0x3e,0x00,0x00,0x04,0xf5,0x31, + 0x00,0x00,0x00,0x00,0x75,0xcb,0x8e,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0xcd, + 0x03,0x23,0xe7,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0xee,0x2f,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x16,0xf2,0x0e,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x26,0xe0,0x0b,0x00,0x00,0x61,0xb0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x45, + 0xde,0xd0,0xb7,0xce,0xfc,0x45,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0xfe,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x6a,0xca,0x00,0x00,0x05,0xec,0x22,0x8d,0x92,0x00,0x00,0x2d,0xf5,0x05, + 0x00,0x00,0x00,0x00,0x03,0xcb,0xf2,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xc7, + 0x6e,0xb5,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xd0,0x6d,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0xb7,0x60,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0xaf,0x62,0x00,0x00,0x00,0x02,0xd0,0x3f,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xf0, + 0x54,0x00,0x00,0x00,0xd4,0x45,0x00,0x8a,0xb6,0xa9,0xdd,0xd7,0x9c,0x15,0x00,0x00, + 0x00,0xf0,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x34,0xf9,0x09,0x00,0x48,0xc6,0x00,0x33,0xe4,0x03,0x00,0x66,0xc3,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xeb,0xe9,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e, + 0xf4,0xc9,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0xb9,0x01,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xba,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x31,0x03,0x00,0x00,0x00,0x00,0x26,0x0d,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xfc, + 0x04,0x00,0x00,0x00,0xd4,0x45,0x00,0x8a,0xdb,0x56,0x19,0x2e,0x95,0xe3,0x11,0x00, + 0x00,0xbf,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x04,0xf0,0x41,0x00,0xa7,0x6a,0x00,0x00,0xd6,0x4a,0x00,0xa5,0x84,0x00, + 0x00,0x00,0x00,0x02,0xbd,0x79,0x49,0xe9,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc0,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xec,0x1c,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xf3,0x18,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xf1, + 0x58,0x00,0x00,0x00,0xd4,0x45,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xb4,0x83,0x00, + 0x00,0x42,0xef,0x4c,0x01,0x00,0x0b,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xb2,0x7f,0x12,0xef,0x12,0x00,0x00,0x76,0xaf,0x00,0xe4,0x41,0x00, + 0x00,0x00,0x00,0x6f,0xc7,0x03,0x00,0x9b,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xbe,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xcf,0x66,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x6e,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4b, + 0xe4,0xdf,0xce,0xdb,0xf0,0x39,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x5b,0xc7,0x00, + 0x00,0x00,0x50,0xe1,0xf1,0xda,0xee,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x6d,0xc7,0x6c,0xa2,0x00,0x00,0x00,0x17,0xf6,0x3e,0xf4,0x08,0x00, + 0x00,0x00,0x1c,0xed,0x29,0x00,0x00,0x0f,0xe4,0x52,0x00,0x00,0x00,0x00,0x00,0x00, + 0xbe,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xc3,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0xc8,0x00,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x1f,0x2c,0x1a,0x01,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x44,0xe8,0x00, + 0x00,0x00,0x00,0x00,0x15,0x23,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x1c,0xfb,0xd9,0x3a,0x00,0x00,0x00,0x00,0xaa,0xd7,0xad,0x00,0x00, + 0x00,0x00,0xa8,0x82,0x00,0x00,0x00,0x00,0x53,0xdf,0x09,0x00,0x00,0x00,0x00,0x00, + 0xbe,0x68,0x00,0x00,0x00,0x00,0x00,0x12,0xec,0x32,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xef,0x23,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x80,0xcd,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xc6,0xd0,0x00,0x00,0x00,0x00,0x00,0x3e,0xff,0x5c,0x00,0x00, + 0x00,0x40,0xe4,0x0a,0x00,0x00,0x00,0x00,0x00,0xbd,0x80,0x00,0x00,0x00,0x00,0x00, + 0xbe,0x68,0x00,0x00,0x00,0x00,0x00,0x59,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9e,0x7d,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xd3,0x96,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xd6,0x00,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x26,0x8e,0xf0,0x19,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe7,0x31,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6e,0xf4,0xdc,0xd5,0xfd,0xc8,0x2d,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0x8b,0x00,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1d,0x2d,0x0f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xe3,0x02,0x00, + 0x00,0x00,0x7d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4e,0xec,0xb6,0xb6,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xdc,0x40,0x00, + 0x9d,0xb6,0xda,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0b,0x23,0x23,0x23,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x10,0x00, + 0x1e,0x23,0x23,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0c,0x00,0x00,0x00,0x24,0xae,0xe4, + 0xa9,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x14,0x11,0x00,0x00,0x00,0x00,0x17,0x98, + 0xd1,0xe4,0xce,0xa5,0x20,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14, + 0x14,0x00,0x00,0x00,0x00,0x14,0x14,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x02,0x0e,0x00,0x00,0x48,0xb3,0xd3,0xe5,0xa4,0x3e,0x2f,0xa4,0xdd,0xdb,0xa5, + 0x17,0x00,0x00,0x48,0xb1,0xd2,0xe6,0xcf,0x8e,0x09,0x00,0x00,0x00,0x00,0x1b,0xa3, + 0xdf,0xd8,0x94,0x0e,0x00,0x00,0x49,0xb7,0xd7,0xe7,0xc5,0x80,0x08,0x00,0x00,0x00, + 0x00,0x11,0x8f,0xcb,0xe7,0xd4,0xb1,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x6c,0x00,0x00,0x1f,0xed,0x72,0x18, + 0x55,0xd2,0x8a,0x00,0x00,0x00,0x56,0xbc,0xe7,0xec,0x4e,0x00,0x00,0x1d,0xe9,0x93, + 0x30,0x18,0x2f,0xe3,0x41,0x00,0x89,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6, + 0xb6,0x00,0x00,0x00,0x00,0xb6,0xb6,0x00,0x89,0x8f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8d,0x8a,0x00,0x00,0x8a,0xab,0x24,0x18,0x43,0xe0,0xe3,0x5f,0x20,0x29,0xa4, + 0xc8,0x00,0x00,0x8a,0xac,0x25,0x17,0x35,0xbd,0xab,0x00,0x00,0x00,0x1b,0xea,0xb6, + 0x3e,0x4d,0xc7,0xd6,0x09,0x00,0x8a,0xac,0x25,0x1c,0x6c,0xd3,0xcf,0x07,0x00,0x00, + 0x15,0xe3,0xc8,0x60,0x19,0x29,0xc3,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0xa5,0x8c,0x00,0x00, + 0x00,0x46,0xf7,0x0d,0x00,0x0a,0xf1,0x45,0x03,0x01,0x04,0x00,0x00,0xa4,0xa1,0x00, + 0x00,0x00,0x00,0xd8,0x41,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33, + 0x33,0x00,0x00,0x00,0x00,0x33,0x33,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x68,0xbf,0x00,0x00,0x00,0x11, + 0xfb,0x1f,0x00,0x8a,0x8f,0x00,0x00,0x00,0x1d,0xfa,0x18,0x00,0x00,0x9f,0xb8,0x00, + 0x00,0x00,0x00,0xdb,0x78,0x00,0x8a,0x8f,0x00,0x00,0x00,0x03,0xe8,0x78,0x00,0x00, + 0x9b,0xcd,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0xe3,0x4b,0x16,0x16, + 0x16,0x1c,0xf5,0x2f,0x00,0x4d,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0xe9,0x3e,0x00, + 0x00,0x00,0x00,0xd8,0x41,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x3d,0xe0,0x00,0x00,0x00,0x00, + 0xe2,0x3a,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xe4,0x3a,0x00,0x00,0xe4,0x6e,0x00, + 0x00,0x00,0x00,0x90,0xbf,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x98,0xc1,0x00,0x00, + 0xe2,0x79,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x08,0xfe,0xdd,0xd8,0xd8, + 0xd8,0xd8,0xd8,0x3a,0x00,0x87,0x92,0x00,0x00,0x00,0x00,0x00,0x07,0xfe,0x24,0x00, + 0x00,0x00,0x00,0xd8,0x41,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69, + 0x6d,0x00,0x00,0x00,0x00,0x69,0x6d,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x31,0xe9,0x00,0x00,0x00,0x00, + 0xd5,0x45,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xd2,0x49,0x00,0x08,0xfe,0x2e,0x00, + 0x00,0x00,0x00,0x50,0xe3,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x4b,0xe7,0x00,0x08, + 0xfe,0x2d,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x22,0xa8,0xdd,0xd8,0x9d,0xc7,0x6c,0x00,0x00,0xf3,0x4f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x8a,0xe4,0xc2,0xc2,0xc2,0x10,0x00,0x00,0xe3,0x45,0x00, + 0x00,0x00,0x00,0xd8,0x41,0x00,0x8a,0xcf,0xc2,0xe4,0xce,0x8e,0x0a,0x00,0x00,0x8a, + 0x8f,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x8a,0x8f,0x00,0x00,0x0d,0xad,0x43,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x30,0xe9,0x00,0x00,0x00,0x00, + 0xd4,0x45,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xcf,0x49,0x00,0x00,0xee,0x5b,0x00, + 0x00,0x00,0x00,0x7e,0xca,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x50,0xd2,0x00,0x00, + 0xf2,0x32,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x24,0xed,0x7f,0x28,0x1d,0x62,0xe8,0x6c,0x00,0x00,0xc3,0xa2,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x8a,0xa2,0x2b,0x2b,0x2b,0x04,0x00,0x00,0xa3,0xaf,0x00, + 0x00,0x00,0x00,0xd9,0x41,0x00,0x8a,0xba,0x37,0x18,0x35,0xbd,0xae,0x00,0x00,0x8a, + 0x8f,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x8a,0x8f,0x00,0x09,0xbd,0x7e,0x00,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x30,0xe9,0x00,0x00,0x00,0x00, + 0xd4,0x45,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xcf,0x49,0x00,0x00,0xba,0xa5,0x00, + 0x00,0x00,0x00,0xc8,0x94,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x93,0xa0,0x00,0x00, + 0xc2,0x74,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xa5,0x95,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x46,0xf1,0x75,0x1b, + 0x00,0x03,0x18,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xe1,0xb6, + 0x62,0x6e,0xb6,0xff,0x41,0x00,0x8a,0x8f,0x00,0x00,0x00,0x1d,0xfb,0x18,0x00,0x8a, + 0x8f,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x8a,0x8f,0x08,0xb8,0x85,0x00,0x00,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x30,0xe9,0x00,0x00,0x00,0x00, + 0xd4,0x45,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xcf,0x49,0x00,0x00,0x36,0xf2,0x77, + 0x0f,0x18,0x87,0xf1,0x1a,0x00,0x8a,0xbf,0x18,0x00,0x00,0x4f,0xf2,0x28,0x00,0x00, + 0x44,0xeb,0x39,0x00,0x00,0x22,0xd4,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xe8,0x3d,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x4d,0xdd,0xfc, + 0xdb,0xf2,0x7a,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x6f, + 0x9e,0x9c,0x55,0xde,0x3d,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xe4,0x3a,0x00,0x8a, + 0x8f,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x8a,0x97,0xb6,0x88,0x00,0x00,0x00,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x30,0xe9,0x00,0x00,0x00,0x00, + 0xd4,0x45,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xcf,0x49,0x00,0x00,0x00,0x48,0xe3, + 0xf0,0xf7,0xd4,0x32,0x00,0x00,0x8a,0xd3,0xe7,0xd5,0xea,0xdd,0x40,0x00,0x00,0x00, + 0x00,0x56,0xe8,0xe4,0xd9,0xdf,0xdc,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x08,0xff,0x25,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x10, + 0x25,0x09,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x27,0xff,0x1c,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xd2,0x49,0x00,0x8a, + 0x8f,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x8a,0xdf,0xf4,0x38,0x00,0x00,0x00,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1e,0x17,0x00,0x00,0x00,0x00,0x8a,0x8f,0x02,0x20,0x19,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x1f,0x1b,0x01,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xed,0x62,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x09,0x00, + 0x00,0x1f,0x9e,0xcc,0x01,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xcf,0x49,0x00,0x8a, + 0x8f,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x8a,0x8f,0x4f,0xed,0x48,0x00,0x00,0x00, + 0x00,0x8f,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xb8,0xb5,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0xf2,0xd8, + 0xdc,0xd3,0x8e,0x22,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xcf,0x49,0x00,0x8a, + 0x8f,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x8a,0x8f,0x00,0x3e,0xed,0x3b,0x00,0x00, + 0x00,0x8e,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xad,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x31,0xf6,0x7f,0x1c,0x00,0x00,0xae,0x6c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x22, + 0x18,0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xcf,0x49,0x00,0x8a, + 0x8f,0x00,0x00,0x00,0x00,0x8a,0x8e,0x00,0x8a,0x8f,0x00,0x00,0x52,0xe7,0x1d,0x00, + 0x00,0x7b,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x3f,0xd8,0xfc,0xd2,0xe0,0xf1,0x55,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0xcf,0x49,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xa6,0x69,0x00,0x8a,0x8f,0x00,0x00,0x00,0x92,0xbc,0x01, + 0x00,0x1f,0xdf,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x13,0x2d,0x1a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1c,0xe0,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0xd1,0xe1,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x1e,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x3d,0xac,0xd3,0xe8,0xd1,0x0b,0x00,0x00,0x2a,0x91,0xdc,0xe5,0xbd,0x0a,0x00, + 0x3e,0x3e,0x00,0x00,0x00,0x00,0x00,0x7d,0x59,0x00,0x00,0x00,0x00,0xb2,0x24,0x00, + 0x6b,0x76,0x00,0x00,0x00,0x00,0x4f,0x86,0x00,0x62,0x7e,0x00,0x00,0x00,0x01,0xb6, + 0x24,0x00,0x00,0x00,0x54,0x7c,0x00,0x17,0xbc,0x26,0x00,0x00,0x00,0x92,0x57,0x00, + 0x6b,0x77,0x00,0x00,0x00,0x00,0x6a,0x6a,0x00,0x14,0xc2,0xc2,0xc2,0xc2,0xc2,0xaf, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x07,0x00,0x15,0x34,0x00,0x0d,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x15,0x1a,0x00,0x00,0x00,0x01,0x00,0x00,0x1c,0xb6,0xb6,0xb6, + 0xb6,0xb6,0xb6,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8a,0xab,0x1f,0x13,0x2a,0x00,0x00,0x00,0xc2,0x66,0x0a,0x16,0x44,0x00,0x00, + 0x9c,0x7d,0x00,0x00,0x00,0x00,0x00,0xa4,0x75,0x00,0x00,0x00,0x00,0xe9,0x30,0x00, + 0x4d,0xd4,0x00,0x00,0x00,0x00,0xa3,0x6f,0x00,0x41,0xda,0x00,0x00,0x00,0x27,0xff, + 0x5f,0x00,0x00,0x00,0xa5,0x63,0x00,0x00,0x7b,0xc6,0x03,0x00,0x5c,0xd0,0x06,0x00, + 0x4d,0xd8,0x00,0x00,0x00,0x00,0xc1,0x51,0x00,0x04,0x2b,0x2b,0x2b,0x2d,0xcd,0x96, + 0x00,0x00,0x00,0x00,0x11,0xba,0xd8,0x35,0x00,0x4e,0xbe,0x00,0xb0,0xdc,0x48,0x00, + 0x00,0x00,0x00,0x71,0xdc,0xde,0xb6,0x21,0x00,0x60,0x8a,0x00,0x27,0xbc,0x23,0x23, + 0x23,0x23,0x53,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x1c,0xfa,0x04,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x7d,0x00,0x00,0x00,0x00,0x00,0xa4,0x75,0x00,0x00,0x00,0x00,0xe9,0x30,0x00, + 0x0b,0xf6,0x1c,0x00,0x00,0x02,0xe8,0x25,0x00,0x06,0xf2,0x1d,0x00,0x00,0x6a,0xe9, + 0x9d,0x00,0x00,0x01,0xe5,0x1b,0x00,0x00,0x03,0xc6,0x76,0x1c,0xe7,0x2d,0x00,0x00, + 0x0b,0xf5,0x26,0x00,0x00,0x07,0xf4,0x11,0x00,0x00,0x00,0x00,0x00,0x7e,0xc1,0x05, + 0x00,0x00,0x00,0x00,0x78,0xaa,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x46,0xdb,0x00, + 0x00,0x00,0x0a,0xdb,0x0c,0x02,0x69,0xe5,0xc0,0xdb,0x21,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x02,0xd4,0xa4,0x1b,0x00,0x00,0x00,0x00, + 0x9c,0xe0,0xc2,0xc2,0xbf,0x00,0x00,0xa4,0x75,0x00,0x00,0x00,0x00,0xe9,0x30,0x00, + 0x00,0xad,0x6b,0x00,0x00,0x3c,0xce,0x00,0x00,0x00,0xb1,0x67,0x00,0x00,0xb1,0x67, + 0xe4,0x01,0x00,0x31,0xd1,0x00,0x00,0x00,0x00,0x25,0xec,0xc9,0x75,0x00,0x00,0x00, + 0x00,0xa8,0x7b,0x00,0x00,0x3e,0xcc,0x00,0x00,0x00,0x00,0x00,0x41,0xe4,0x19,0x00, + 0x00,0x00,0x00,0x00,0x9e,0x70,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x08,0xfe,0x06, + 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x2e,0x0a,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x99,0xf2,0xa7,0x26,0x00,0x00, + 0x9c,0x93,0x2b,0x2b,0x2a,0x00,0x00,0xa4,0x75,0x00,0x00,0x00,0x00,0xe9,0x30,0x00, + 0x00,0x56,0xc1,0x00,0x00,0x91,0x75,0x00,0x00,0x00,0x6a,0xb5,0x00,0x0a,0xe7,0x08, + 0xd7,0x32,0x00,0x7d,0x88,0x00,0x00,0x00,0x00,0x00,0xb2,0xfc,0x24,0x00,0x00,0x00, + 0x00,0x4d,0xd9,0x01,0x00,0x81,0x8a,0x00,0x00,0x00,0x00,0x13,0xe4,0x44,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa4,0x69,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x01,0xff,0x0d, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x84,0xf1,0x2b,0x00, + 0x9c,0x7d,0x00,0x00,0x00,0x00,0x00,0x9b,0x84,0x00,0x00,0x00,0x00,0xe9,0x30,0x00, + 0x00,0x08,0xec,0x22,0x05,0xe4,0x19,0x00,0x00,0x00,0x17,0xf4,0x11,0x51,0xa7,0x00, + 0x84,0x84,0x00,0xd1,0x31,0x00,0x00,0x00,0x00,0x50,0xd4,0x80,0xc8,0x04,0x00,0x00, + 0x00,0x04,0xe1,0x40,0x00,0xc9,0x3c,0x00,0x00,0x00,0x00,0xab,0x8e,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa4,0x68,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0xff,0x0d, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x7f,0x00, + 0x9c,0x7d,0x00,0x00,0x00,0x00,0x00,0x7f,0xab,0x00,0x00,0x00,0x00,0xe9,0x30,0x00, + 0x00,0x00,0x8f,0x86,0x52,0xad,0x00,0x00,0x00,0x00,0x00,0xad,0x66,0xa8,0x50,0x00, + 0x2d,0xdc,0x2c,0xcd,0x00,0x00,0x00,0x00,0x16,0xe4,0x2f,0x02,0xc3,0x7d,0x00,0x00, + 0x00,0x00,0x77,0xad,0x1a,0xdd,0x01,0x00,0x00,0x00,0x57,0xda,0x08,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa4,0x64,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0xfc,0x0d, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x00,0x00,0x10,0xe4,0x39,0x00, + 0x9c,0x7d,0x00,0x00,0x00,0x00,0x00,0x27,0xf7,0x3f,0x00,0x00,0x02,0xeb,0x30,0x00, + 0x00,0x00,0x25,0xea,0xc8,0x42,0x00,0x00,0x00,0x00,0x00,0x49,0xd3,0xe2,0x06,0x00, + 0x00,0xce,0xc6,0x6a,0x00,0x00,0x00,0x00,0x9f,0x81,0x00,0x00,0x24,0xef,0x27,0x00, + 0x00,0x00,0x10,0xed,0x92,0x86,0x00,0x00,0x00,0x0c,0xe3,0x45,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x49,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0xe3,0x26, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8a,0x8f,0x00,0x00,0x00,0x00,0x00,0x2d,0xf2,0xd7,0xd5,0xdf,0x8c,0x00,0x00, + 0x9b,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0xeb,0xe6,0xdc,0xf1,0xda,0x22,0x00, + 0x00,0x00,0x00,0xae,0xcf,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe1,0x8d,0x00,0x00, + 0x00,0x68,0xf6,0x10,0x00,0x00,0x00,0x3b,0xdc,0x08,0x00,0x00,0x00,0x7e,0xb3,0x00, + 0x00,0x00,0x00,0x7f,0xff,0x2c,0x00,0x00,0x00,0x58,0xfe,0xee,0xee,0xee,0xee,0xee, + 0x0c,0x00,0x17,0x8c,0xd4,0x09,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0x76,0xc9, + 0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x20,0x21,0x00,0x00,0x00,0x00, + 0x8a,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x1d,0x08,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x53,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x26,0xc3,0xaf,0x02,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0x4e,0xe4, + 0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x5c,0xd5,0x0b,0x00,0x0f,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x17,0xd9,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0xd3,0x3d,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0xd7,0x3b, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0xb5,0xef,0xd9,0xec,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc2,0xc7,0xe5,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa5,0x60,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0xf9,0x0e, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xb1,0x00,0x00, + 0x00,0x00,0x38,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x14,0x24,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x14,0x25,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa4,0x68,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0xff,0x0d, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0xf3,0xd8,0xd8, + 0xd8,0xd8,0xe1,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa4,0x68,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x00,0xff,0x0d, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa1,0x6d,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x05,0xff,0x09, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x87,0x8f,0x00,0x00,0x00,0x4e,0xbe,0x00,0x00,0x2a,0xeb,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x24,0xe1,0xa3,0x26,0x00,0x4e,0xbe,0x00,0x80,0xd9,0x71,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0c,0x3c,0x16,0x00,0x0b,0x1a,0x00,0x3e,0x20,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +]; +
new file mode 100644 --- /dev/null +++ b/gfx/webrender/src/debug_render.rs @@ -0,0 +1,219 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use debug_font_data; +use device::{Device, GpuMarker, ProgramId, VAOId, TextureId, VertexFormat}; +use device::{TextureFilter, VertexUsageHint, TextureTarget}; +use euclid::{Matrix4D, Point2D, Size2D, Rect}; +use internal_types::{ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE, TextureSampler}; +use internal_types::{DebugFontVertex, DebugColorVertex, RenderTargetMode, PackedColor}; +use std::f32; +use webrender_traits::{ColorF, ImageFormat, DeviceUintSize}; + +pub struct DebugRenderer { + font_vertices: Vec<DebugFontVertex>, + font_indices: Vec<u32>, + font_program_id: ProgramId, + font_vao: VAOId, + font_texture_id: TextureId, + + tri_vertices: Vec<DebugColorVertex>, + tri_indices: Vec<u32>, + tri_vao: VAOId, + line_vertices: Vec<DebugColorVertex>, + line_vao: VAOId, + color_program_id: ProgramId, +} + +impl DebugRenderer { + pub fn new(device: &mut Device) -> DebugRenderer { + let font_program_id = device.create_program("debug_font", "shared_other"); + let color_program_id = device.create_program("debug_color", "shared_other"); + + let font_vao = device.create_vao(VertexFormat::DebugFont, 32); + let line_vao = device.create_vao(VertexFormat::DebugColor, 32); + let tri_vao = device.create_vao(VertexFormat::DebugColor, 32); + + let font_texture_id = device.create_texture_ids(1, TextureTarget::Default)[0]; + device.init_texture(font_texture_id, + debug_font_data::BMP_WIDTH, + debug_font_data::BMP_HEIGHT, + ImageFormat::A8, + TextureFilter::Linear, + RenderTargetMode::None, + Some(&debug_font_data::FONT_BITMAP)); + + DebugRenderer { + font_vertices: Vec::new(), + font_indices: Vec::new(), + line_vertices: Vec::new(), + tri_vao: tri_vao, + tri_vertices: Vec::new(), + tri_indices: Vec::new(), + font_program_id: font_program_id, + color_program_id: color_program_id, + font_vao: font_vao, + line_vao: line_vao, + font_texture_id: font_texture_id, + } + } + + pub fn line_height(&self) -> f32 { + debug_font_data::FONT_SIZE as f32 * 1.1 + } + + pub fn add_text(&mut self, + x: f32, + y: f32, + text: &str, + color: &ColorF) -> Rect<f32> { + let mut x_start = x; + let ipw = 1.0 / debug_font_data::BMP_WIDTH as f32; + let iph = 1.0 / debug_font_data::BMP_HEIGHT as f32; + let color = PackedColor::from_color(color); + + let mut min_x = f32::MAX; + let mut max_x = -f32::MAX; + let mut min_y = f32::MAX; + let mut max_y = -f32::MAX; + + for c in text.chars() { + let c = c as usize - debug_font_data::FIRST_GLYPH_INDEX as usize; + if c < debug_font_data::GLYPHS.len() { + let glyph = &debug_font_data::GLYPHS[c]; + + let x0 = (x_start + glyph.xo + 0.5).floor(); + let y0 = (y + glyph.yo + 0.5).floor(); + + let x1 = x0 + glyph.x1 as f32 - glyph.x0 as f32; + let y1 = y0 + glyph.y1 as f32 - glyph.y0 as f32; + + let s0 = glyph.x0 as f32 * ipw; + let t0 = glyph.y0 as f32 * iph; + let s1 = glyph.x1 as f32 * ipw; + let t1 = glyph.y1 as f32 * iph; + + x_start += glyph.xa; + + let vertex_count = self.font_vertices.len() as u32; + + self.font_vertices.push(DebugFontVertex::new(x0, y0, s0, t0, color)); + self.font_vertices.push(DebugFontVertex::new(x1, y0, s1, t0, color)); + self.font_vertices.push(DebugFontVertex::new(x0, y1, s0, t1, color)); + self.font_vertices.push(DebugFontVertex::new(x1, y1, s1, t1, color)); + + self.font_indices.push(vertex_count + 0); + self.font_indices.push(vertex_count + 1); + self.font_indices.push(vertex_count + 2); + self.font_indices.push(vertex_count + 2); + self.font_indices.push(vertex_count + 1); + self.font_indices.push(vertex_count + 3); + + min_x = min_x.min(x0); + max_x = max_x.max(x1); + min_y = min_y.min(y0); + max_y = max_y.max(y1); + } + } + + Rect::new(Point2D::new(min_x, min_y), Size2D::new(max_x-min_x, max_y-min_y)) + } + + pub fn add_quad(&mut self, + x0: f32, + y0: f32, + x1: f32, + y1: f32, + color_top: &ColorF, + color_bottom: &ColorF) { + let color_top = PackedColor::from_color(color_top); + let color_bottom = PackedColor::from_color(color_bottom); + let vertex_count = self.tri_vertices.len() as u32; + + self.tri_vertices.push(DebugColorVertex::new(x0, y0, color_top)); + self.tri_vertices.push(DebugColorVertex::new(x1, y0, color_top)); + self.tri_vertices.push(DebugColorVertex::new(x0, y1, color_bottom)); + self.tri_vertices.push(DebugColorVertex::new(x1, y1, color_bottom)); + + self.tri_indices.push(vertex_count + 0); + self.tri_indices.push(vertex_count + 1); + self.tri_indices.push(vertex_count + 2); + self.tri_indices.push(vertex_count + 2); + self.tri_indices.push(vertex_count + 1); + self.tri_indices.push(vertex_count + 3); + } + + #[allow(dead_code)] + pub fn add_line(&mut self, + x0: i32, + y0: i32, + color0: &ColorF, + x1: i32, + y1: i32, + color1: &ColorF) { + let color0 = PackedColor::from_color(color0); + let color1 = PackedColor::from_color(color1); + self.line_vertices.push(DebugColorVertex::new(x0 as f32, y0 as f32, color0)); + self.line_vertices.push(DebugColorVertex::new(x1 as f32, y1 as f32, color1)); + } + + pub fn render(&mut self, + device: &mut Device, + viewport_size: &DeviceUintSize) { + let _gm = GpuMarker::new("debug"); + device.disable_depth(); + device.set_blend(true); + device.set_blend_mode_alpha(); + + let projection = Matrix4D::ortho(0.0, + viewport_size.width as f32, + viewport_size.height as f32, + 0.0, + ORTHO_NEAR_PLANE, + ORTHO_FAR_PLANE); + + // Triangles + if !self.tri_vertices.is_empty() { + device.bind_program(self.color_program_id, &projection); + device.bind_vao(self.tri_vao); + device.update_vao_indices(self.tri_vao, + &self.tri_indices, + VertexUsageHint::Dynamic); + device.update_vao_main_vertices(self.tri_vao, + &self.tri_vertices, + VertexUsageHint::Dynamic); + device.draw_triangles_u32(0, self.tri_indices.len() as i32); + } + + // Lines + if !self.line_vertices.is_empty() { + device.bind_program(self.color_program_id, &projection); + device.bind_vao(self.line_vao); + device.update_vao_main_vertices(self.line_vao, + &self.line_vertices, + VertexUsageHint::Dynamic); + device.draw_nonindexed_lines(0, self.line_vertices.len() as i32); + } + + // Glyph + if !self.font_indices.is_empty() { + device.bind_program(self.font_program_id, &projection); + device.bind_texture(TextureSampler::Color0, self.font_texture_id); + device.bind_vao(self.font_vao); + device.update_vao_indices(self.font_vao, + &self.font_indices, + VertexUsageHint::Dynamic); + device.update_vao_main_vertices(self.font_vao, + &self.font_vertices, + VertexUsageHint::Dynamic); + device.draw_triangles_u32(0, self.font_indices.len() as i32); + } + + self.font_indices.clear(); + self.font_vertices.clear(); + self.line_vertices.clear(); + self.tri_vertices.clear(); + self.tri_indices.clear(); + } +}
new file mode 100644 --- /dev/null +++ b/gfx/webrender/src/device.rs @@ -0,0 +1,1965 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use euclid::Matrix4D; +use fnv::FnvHasher; +use gleam::gl; +use internal_types::{PackedVertex, RenderTargetMode, TextureSampler, DEFAULT_TEXTURE}; +use internal_types::{BlurAttribute, ClearAttribute, ClipAttribute, VertexAttribute}; +use internal_types::{DebugFontVertex, DebugColorVertex}; +//use notify::{self, Watcher}; +use super::shader_source; +use std::collections::HashMap; +use std::fs::File; +use std::hash::BuildHasherDefault; +use std::io::Read; +use std::mem; +use std::path::PathBuf; +//use std::sync::mpsc::{channel, Sender}; +//use std::thread; +use webrender_traits::{ColorF, ImageFormat}; +use webrender_traits::{DeviceIntPoint, DeviceIntRect, DeviceIntSize}; + +#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] +const GL_FORMAT_A: gl::GLuint = gl::RED; + +#[cfg(any(target_arch = "arm", target_arch = "aarch64"))] +const GL_FORMAT_A: gl::GLuint = gl::ALPHA; + +#[cfg(any(target_os = "windows", all(unix, not(target_os = "android"))))] +const GL_FORMAT_BGRA: gl::GLuint = gl::BGRA; + +#[cfg(target_os = "android")] +const GL_FORMAT_BGRA: gl::GLuint = gl::BGRA_EXT; + +#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] +const SHADER_VERSION: &'static str = "#version 150\n"; + +#[cfg(any(target_arch = "arm", target_arch = "aarch64"))] +const SHADER_VERSION: &'static str = "#version 300 es\n"; + +static SHADER_PREAMBLE: &'static str = "shared"; + +pub type ViewportDimensions = [u32; 2]; + +lazy_static! { + pub static ref MAX_TEXTURE_SIZE: gl::GLint = { + gl::get_integer_v(gl::MAX_TEXTURE_SIZE) + }; +} + +#[repr(u32)] +pub enum DepthFunction { + Less = gl::LESS, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum TextureTarget { + Default, + Array, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum TextureFilter { + Nearest, + Linear, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum VertexFormat { + Triangles, + Rectangles, + DebugFont, + DebugColor, + Clear, + Blur, + Clip, +} + +enum FBOTarget { + Read, + Draw, +} + +fn get_optional_shader_source(shader_name: &str, base_path: &Option<PathBuf>) -> Option<String> { + if let Some(ref base) = *base_path { + let shader_path = base.join(&format!("{}.glsl", shader_name)); + if shader_path.exists() { + let mut source = String::new(); + File::open(&shader_path).unwrap().read_to_string(&mut source).unwrap(); + return Some(source); + } + } + + shader_source::SHADERS.get(shader_name).and_then(|s| Some((*s).to_owned())) +} + +fn get_shader_source(shader_name: &str, base_path: &Option<PathBuf>) -> String { + get_optional_shader_source(shader_name, base_path) + .expect(&format!("Couldn't get required shader: {}", shader_name)) +} + +pub trait FileWatcherHandler : Send { + fn file_changed(&self, path: PathBuf); +} + +impl VertexFormat { + fn bind(&self, main: VBOId, instance: VBOId, offset: gl::GLuint, instance_stride: gl::GLint) { + main.bind(); + + match *self { + VertexFormat::DebugFont => { + gl::enable_vertex_attrib_array(VertexAttribute::Position as gl::GLuint); + gl::enable_vertex_attrib_array(VertexAttribute::Color as gl::GLuint); + gl::enable_vertex_attrib_array(VertexAttribute::ColorTexCoord as gl::GLuint); + + gl::vertex_attrib_divisor(VertexAttribute::Position as gl::GLuint, 0); + gl::vertex_attrib_divisor(VertexAttribute::Color as gl::GLuint, 0); + gl::vertex_attrib_divisor(VertexAttribute::ColorTexCoord as gl::GLuint, 0); + + let vertex_stride = mem::size_of::<DebugFontVertex>() as gl::GLuint; + + gl::vertex_attrib_pointer(VertexAttribute::Position as gl::GLuint, + 2, + gl::FLOAT, + false, + vertex_stride as gl::GLint, + 0 + vertex_stride * offset); + gl::vertex_attrib_pointer(VertexAttribute::Color as gl::GLuint, + 4, + gl::UNSIGNED_BYTE, + true, + vertex_stride as gl::GLint, + 8 + vertex_stride * offset); + gl::vertex_attrib_pointer(VertexAttribute::ColorTexCoord as gl::GLuint, + 2, + gl::FLOAT, + false, + vertex_stride as gl::GLint, + 12 + vertex_stride * offset); + } + VertexFormat::DebugColor => { + gl::enable_vertex_attrib_array(VertexAttribute::Position as gl::GLuint); + gl::enable_vertex_attrib_array(VertexAttribute::Color as gl::GLuint); + + gl::vertex_attrib_divisor(VertexAttribute::Position as gl::GLuint, 0); + gl::vertex_attrib_divisor(VertexAttribute::Color as gl::GLuint, 0); + + let vertex_stride = mem::size_of::<DebugColorVertex>() as gl::GLuint; + + gl::vertex_attrib_pointer(VertexAttribute::Position as gl::GLuint, + 2, + gl::FLOAT, + false, + vertex_stride as gl::GLint, + 0 + vertex_stride * offset); + gl::vertex_attrib_pointer(VertexAttribute::Color as gl::GLuint, + 4, + gl::UNSIGNED_BYTE, + true, + vertex_stride as gl::GLint, + 8 + vertex_stride * offset); + } + VertexFormat::Rectangles | + VertexFormat::Triangles => { + let vertex_stride = mem::size_of::<PackedVertex>() as gl::GLuint; + gl::enable_vertex_attrib_array(VertexAttribute::Position as gl::GLuint); + gl::vertex_attrib_divisor(VertexAttribute::Position as gl::GLuint, 0); + + gl::vertex_attrib_pointer(VertexAttribute::Position as gl::GLuint, + 2, + gl::FLOAT, + false, + vertex_stride as gl::GLint, + 0); + + instance.bind(); + let mut offset = 0; + + for &attrib in [VertexAttribute::GlobalPrimId, + VertexAttribute::PrimitiveAddress, + VertexAttribute::TaskIndex, + VertexAttribute::ClipTaskIndex, + VertexAttribute::LayerIndex, + VertexAttribute::ElementIndex, + VertexAttribute::ZIndex, + ].into_iter() { + gl::enable_vertex_attrib_array(attrib as gl::GLuint); + gl::vertex_attrib_divisor(attrib as gl::GLuint, 1); + gl::vertex_attrib_i_pointer(attrib as gl::GLuint, + 1, + gl::INT, + instance_stride, + offset); + offset += 4; + } + + gl::enable_vertex_attrib_array(VertexAttribute::UserData as gl::GLuint); + gl::vertex_attrib_divisor(VertexAttribute::UserData as gl::GLuint, 1); + gl::vertex_attrib_i_pointer(VertexAttribute::UserData as gl::GLuint, + 2, + gl::INT, + instance_stride, + offset); + } + VertexFormat::Clear => { + let vertex_stride = mem::size_of::<PackedVertex>() as gl::GLuint; + gl::enable_vertex_attrib_array(ClearAttribute::Position as gl::GLuint); + gl::vertex_attrib_divisor(ClearAttribute::Position as gl::GLuint, 0); + + gl::vertex_attrib_pointer(ClearAttribute::Position as gl::GLuint, + 2, + gl::FLOAT, + false, + vertex_stride as gl::GLint, + 0); + + instance.bind(); + + gl::enable_vertex_attrib_array(ClearAttribute::Rectangle as gl::GLuint); + gl::vertex_attrib_divisor(ClearAttribute::Rectangle as gl::GLuint, 1); + gl::vertex_attrib_i_pointer(ClearAttribute::Rectangle as gl::GLuint, + 4, + gl::INT, + instance_stride, + 0); + } + VertexFormat::Blur => { + let vertex_stride = mem::size_of::<PackedVertex>() as gl::GLuint; + gl::enable_vertex_attrib_array(BlurAttribute::Position as gl::GLuint); + gl::vertex_attrib_divisor(BlurAttribute::Position as gl::GLuint, 0); + + gl::vertex_attrib_pointer(BlurAttribute::Position as gl::GLuint, + 2, + gl::FLOAT, + false, + vertex_stride as gl::GLint, + 0); + + instance.bind(); + + for (i, &attrib) in [BlurAttribute::RenderTaskIndex, + BlurAttribute::SourceTaskIndex, + BlurAttribute::Direction, + ].into_iter().enumerate() { + gl::enable_vertex_attrib_array(attrib as gl::GLuint); + gl::vertex_attrib_divisor(attrib as gl::GLuint, 1); + gl::vertex_attrib_i_pointer(attrib as gl::GLuint, + 1, + gl::INT, + instance_stride, + (i * 4) as gl::GLuint); + } + } + VertexFormat::Clip => { + let vertex_stride = mem::size_of::<PackedVertex>() as gl::GLuint; + gl::enable_vertex_attrib_array(ClipAttribute::Position as gl::GLuint); + gl::vertex_attrib_divisor(ClipAttribute::Position as gl::GLuint, 0); + + gl::vertex_attrib_pointer(ClipAttribute::Position as gl::GLuint, + 2, + gl::FLOAT, + false, + vertex_stride as gl::GLint, + 0); + + instance.bind(); + + for (i, &attrib) in [ClipAttribute::RenderTaskIndex, + ClipAttribute::LayerIndex, + ClipAttribute::DataIndex, + ClipAttribute::SegmentIndex, + ].into_iter().enumerate() { + gl::enable_vertex_attrib_array(attrib as gl::GLuint); + gl::vertex_attrib_divisor(attrib as gl::GLuint, 1); + gl::vertex_attrib_i_pointer(attrib as gl::GLuint, + 1, + gl::INT, + instance_stride, + (i * 4) as gl::GLuint); + } + } + } + } +} + +impl TextureId { + pub fn bind(&self) { + gl::bind_texture(self.target, self.name); + } + + pub fn new(name: gl::GLuint) -> TextureId { + TextureId { + name: name, + target: gl::TEXTURE_2D, + } + } + + pub fn invalid() -> TextureId { + TextureId { + name: 0, + target: gl::TEXTURE_2D, + } + } + + pub fn is_valid(&self) -> bool { *self != TextureId::invalid() } +} + +impl ProgramId { + fn bind(&self) { + gl::use_program(self.0); + } +} + +impl VBOId { + fn bind(&self) { + gl::bind_buffer(gl::ARRAY_BUFFER, self.0); + } +} + +impl IBOId { + fn bind(&self) { + gl::bind_buffer(gl::ELEMENT_ARRAY_BUFFER, self.0); + } +} + +impl UBOId { + fn _bind(&self) { + gl::bind_buffer(gl::UNIFORM_BUFFER, self.0); + } +} + +impl FBOId { + fn bind(&self, target: FBOTarget) { + let target = match target { + FBOTarget::Read => gl::READ_FRAMEBUFFER, + FBOTarget::Draw => gl::DRAW_FRAMEBUFFER, + }; + gl::bind_framebuffer(target, self.0); + } +} + +struct Texture { + id: gl::GLuint, + format: ImageFormat, + width: u32, + height: u32, + filter: TextureFilter, + mode: RenderTargetMode, + fbo_ids: Vec<FBOId>, +} + +impl Drop for Texture { + fn drop(&mut self) { + if !self.fbo_ids.is_empty() { + let fbo_ids: Vec<_> = self.fbo_ids.iter().map(|&FBOId(fbo_id)| fbo_id).collect(); + gl::delete_framebuffers(&fbo_ids[..]); + } + gl::delete_textures(&[self.id]); + } +} + +struct Program { + id: gl::GLuint, + u_transform: gl::GLint, + u_device_pixel_ratio: gl::GLint, + name: String, + vs_source: String, + fs_source: String, + prefix: Option<String>, + vs_id: Option<gl::GLuint>, + fs_id: Option<gl::GLuint>,