author | Tiberius Oros <toros@mozilla.com> |
Fri, 16 Mar 2018 11:53:43 +0200 | |
changeset 408470 | 9cd8e03d9e472f07041be3cd80cc95a8194f91a5 |
parent 408469 | d8e8ec54ed9db4d2e280407a89d8aa8bf747f769 (current diff) |
parent 408385 | 0dd45961fab3a7f4804f3c1ec4ee42a6175e39da (diff) |
child 408471 | 274883cfcd32d97bb460c2a58b0034bdc80e712f |
child 408472 | 943930f3737f3b0850cc7e14c2fe23e4f5f5518b |
child 408537 | 64a49ffcb54bab18717501decd1e094de878227b |
push id | 100948 |
push user | toros@mozilla.com |
push date | Fri, 16 Mar 2018 10:00:55 +0000 |
treeherder | mozilla-inbound@274883cfcd32 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 61.0a1 |
first release with | nightly linux32
9cd8e03d9e47
/
61.0a1
/
20180316100132
/
files
nightly linux64
9cd8e03d9e47
/
61.0a1
/
20180316100132
/
files
nightly mac
9cd8e03d9e47
/
61.0a1
/
20180316100132
/
files
nightly win32
9cd8e03d9e47
/
61.0a1
/
20180316100132
/
files
nightly win64
9cd8e03d9e47
/
61.0a1
/
20180316100132
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
61.0a1
/
20180316100132
/
pushlog to previous
nightly linux64
61.0a1
/
20180316100132
/
pushlog to previous
nightly mac
61.0a1
/
20180316100132
/
pushlog to previous
nightly win32
61.0a1
/
20180316100132
/
pushlog to previous
nightly win64
61.0a1
/
20180316100132
/
pushlog to previous
|
--- a/browser/base/content/browser-safebrowsing.js +++ b/browser/base/content/browser-safebrowsing.js @@ -18,31 +18,26 @@ var gSafeBrowsing = { docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked"); // Show/hide the appropriate menu item. document.getElementById("menu_HelpPopup_reportPhishingtoolmenu") .hidden = isPhishingPage; document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu") .hidden = !isPhishingPage; - var broadcasterId = isPhishingPage - ? "reportPhishingErrorBroadcaster" - : "reportPhishingBroadcaster"; - - var broadcaster = document.getElementById(broadcasterId); - if (!broadcaster) - return; - // Now look at the currentURI to learn which page we were trying // to browse to. - let uri = gBrowser.currentURI; - if (uri && (uri.schemeIs("http") || uri.schemeIs("https"))) - broadcaster.removeAttribute("disabled"); - else - broadcaster.setAttribute("disabled", true); + const uri = gBrowser.currentURI; + const isReportablePage = uri && (uri.schemeIs("http") || uri.schemeIs("https")); + + const disabledByPolicy = !Services.policies.isAllowed("feedbackCommands"); + document.getElementById("reportPhishingBroadcaster") + .disabled = disabledByPolicy || isPhishingPage || !isReportablePage; + document.getElementById("reportPhishingErrorBroadcaster") + .disabled = disabledByPolicy || !isPhishingPage || !isReportablePage; }, /** * Used to report a phishing page or a false positive * * @param name * String One of "PhishMistake", "MalwareMistake", or "Phish" * @param info
--- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -826,16 +826,22 @@ function openFeedbackPage() { function openTourPage() { let scope = {}; ChromeUtils.import("resource:///modules/UITour.jsm", scope); openUILinkIn(scope.UITour.url, "tab"); } function buildHelpMenu() { + document.getElementById("feedbackPage") + .disabled = !Services.policies.isAllowed("feedbackCommands"); + + document.getElementById("helpSafeMode") + .disabled = !Services.policies.isAllowed("safeMode"); + // Enable/disable the "Report Web Forgery" menu item. if (typeof gSafeBrowsing != "undefined") { gSafeBrowsing.setReportPhishingMenu(); } } function isElementVisible(aElement) { if (!aElement)
--- a/browser/components/enterprisepolicies/Policies.jsm +++ b/browser/components/enterprisepolicies/Policies.jsm @@ -130,30 +130,46 @@ var Policies = { "DisableAppUpdate": { onBeforeAddons(manager, param) { if (param) { manager.disallowFeature("appUpdate"); } } }, + "DisableBuiltinPDFViewer": { + onBeforeUIStartup(manager, param) { + if (param) { + manager.disallowFeature("PDF.js"); + } + } + }, + "DisableDeveloperTools": { onBeforeAddons(manager, param) { if (param) { setAndLockPref("devtools.policy.disabled", true); setAndLockPref("devtools.chrome.enabled", false); manager.disallowFeature("devtools"); manager.disallowFeature("about:devtools"); manager.disallowFeature("about:debugging"); manager.disallowFeature("about:devtools-toolbox"); } } }, + "DisableFeedbackCommands": { + onBeforeUIStartup(manager, param) { + if (param) { + manager.disallowFeature("feedbackCommands"); + } + } + }, + "DisableFirefoxAccounts": { onBeforeAddons(manager, param) { if (param) { setAndLockPref("identity.fxaccounts.enabled", false); } } }, @@ -194,16 +210,24 @@ var Policies = { if (param) { manager.disallowFeature("privatebrowsing"); manager.disallowFeature("about:privatebrowsing", true); setAndLockPref("browser.privatebrowsing.autostart", false); } } }, + "DisableSafeMode": { + onBeforeUIStartup(manager, param) { + if (param) { + manager.disallowFeature("safeMode"); + } + } + }, + "DisableSysAddonUpdate": { onBeforeAddons(manager, param) { if (param) { manager.disallowFeature("SysAddonUpdate"); } } },
--- a/browser/components/enterprisepolicies/schemas/policies-schema.json +++ b/browser/components/enterprisepolicies/schemas/policies-schema.json @@ -102,23 +102,37 @@ "DisableAppUpdate": { "description": "Prevent the browser from updating.", "first_available": "60.0", "enterprise_only": true, "type": "boolean" }, + "DisableBuiltinPDFViewer": { + "description": "Disables PDF.js, which displays PDFs within Firefox.", + "first_available": "60.0", + + "type": "boolean" + }, + "DisableDeveloperTools": { "description": "Prevents access to developer tools.", "first_available": "60.0", "type": "boolean" }, + "DisableFeedbackCommands": { + "description": "Prevents ability to send feedback from the help menu (\"Submit Feedback\" and \"Report Deceptive Site\").", + "first_available": "60.0", + + "type": "boolean" + }, + "DisableFirefoxAccounts": { "description": "Disables Firefox Account based services, including Sync.", "first_available": "60.0", "type": "boolean" }, "DisableFirefoxScreenshots": { @@ -151,16 +165,23 @@ "DisablePrivateBrowsing": { "description": "Disables private browsing.", "first_available": "60.0", "type": "boolean" }, + "DisableSafeMode": { + "description": "Prevents ability to restart in safe mode.", + "first_available": "60.0", + + "type": "boolean" + }, + "DisableSysAddonUpdate": { "description": "Prevent the browser from installing and updating system addons.", "first_available": "60.0", "enterprise_only": true, "type": "boolean", "enum": [true] },
--- a/browser/components/enterprisepolicies/tests/browser/browser.ini +++ b/browser/components/enterprisepolicies/tests/browser/browser.ini @@ -19,19 +19,22 @@ support-files = [browser_policy_block_about_addons.js] [browser_policy_block_about_config.js] [browser_policy_block_about_profiles.js] [browser_policy_block_about_support.js] [browser_policy_block_set_desktop_background.js] [browser_policy_bookmarks.js] [browser_policy_clear_blocked_cookies.js] [browser_policy_default_browser_check.js] +[browser_policy_disable_feedback_commands.js] [browser_policy_disable_formhistory.js] [browser_policy_disable_fxaccounts.js] [browser_policy_disable_fxscreenshots.js] [browser_policy_disable_masterpassword.js] +[browser_policy_disable_pdfjs.js] [browser_policy_disable_pocket.js] [browser_policy_disable_privatebrowsing.js] +[browser_policy_disable_safemode.js] [browser_policy_disable_shield.js] [browser_policy_display_bookmarks.js] [browser_policy_display_menu.js] [browser_policy_remember_passwords.js] [browser_policy_set_homepage.js]
new file mode 100644 --- /dev/null +++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_feedback_commands.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* the buidHelpMenu() function comes from browser/base/content/utilityOverlay.js */ + +const NORMAL_PAGE = "http://example.com"; +const PHISH_PAGE = "http://www.itisatrap.org/firefox/its-a-trap.html"; + +async function checkItemsAreDisabled(url) { + await BrowserTestUtils.withNewTab({ + gBrowser, + url, + // The phishing page doesn't send a load notification + waitForLoad: false, + waitForStateStop: true, + }, async function checkItems() { + buildHelpMenu(); + + let reportMenu = document.getElementById("menu_HelpPopup_reportPhishingtoolmenu"); + is(reportMenu.getAttribute("disabled"), "true", + "The `Report Deceptive Site` item should be disabled"); + + let errorMenu = document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu"); + is(errorMenu.getAttribute("disabled"), "true", + "The `This isn’t a deceptive site` item should be disabled"); + }); +} + +add_task(async function test_policy_feedback_commands() { + await setupPolicyEngineWithJson({ + "policies": { + "DisableFeedbackCommands": true + } + }); + + /* from browser/base/content/utilityOverlay.js */ + buildHelpMenu(); + + let feedbackPageMenu = document.getElementById("feedbackPage"); + is(feedbackPageMenu.getAttribute("disabled"), "true", + "The `Submit Feedback...` item should be disabled"); + + await checkItemsAreDisabled(NORMAL_PAGE); + await checkItemsAreDisabled(PHISH_PAGE); + +}); +
new file mode 100644 --- /dev/null +++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_pdfjs.js @@ -0,0 +1,17 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const {PdfJs} = ChromeUtils.import("resource://pdf.js/PdfJs.jsm", {}); + +add_task(async function test_disable_pdfjs() { + is(PdfJs.enabled, true, "PDFjs should be enabled before policy runs"); + + await setupPolicyEngineWithJson({ + "policies": { + "DisableBuiltinPDFViewer": true + } + }); + + is(PdfJs.enabled, false, "PDFjs should be disabled after policy runs"); +});
new file mode 100644 --- /dev/null +++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_safemode.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +add_task(async function setup() { + await setupPolicyEngineWithJson({ + "policies": { + "DisableSafeMode": true + } + }); +}); + +add_task(async function test_help_menu() { + buildHelpMenu(); + let safeModeMenu = document.getElementById("helpSafeMode"); + is(safeModeMenu.getAttribute("disabled"), "true", + "The `Restart with Add-ons Disabled...` item should be disabled"); +}); + +add_task(async function test_safemode_from_about_support() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:support"); + + await ContentTask.spawn(tab.linkedBrowser, null, async function() { + let button = content.document.getElementById("restart-in-safe-mode-button"); + is(button.getAttribute("disabled"), "true", + "The `Restart with Add-ons Disabled...` button should be disabled"); + }); + + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_safemode_from_about_profiles() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:profiles"); + + await ContentTask.spawn(tab.linkedBrowser, null, async function() { + let button = content.document.getElementById("restart-in-safe-mode-button"); + is(button.getAttribute("disabled"), "true", + "The `Restart with Add-ons Disabled...` button should be disabled"); + }); + + await BrowserTestUtils.removeTab(tab); +});
--- a/browser/components/extensions/test/browser/browser-common.ini +++ b/browser/components/extensions/test/browser/browser-common.ini @@ -46,16 +46,17 @@ skip-if = os == 'win' || os == 'mac' # B [browser_ext_browserAction_contextMenu.js] # bug 1369197 skip-if = os == 'linux' [browser_ext_browserAction_disabled.js] [browser_ext_browserAction_pageAction_icon.js] [browser_ext_browserAction_pageAction_icon_permissions.js] [browser_ext_browserAction_popup.js] skip-if = (debug && os == 'linux' && bits == 32) || (os == 'win' && !debug) # Bug 1313372, win: Bug 1285500 +[browser_ext_browserAction_popup_port.js] [browser_ext_browserAction_popup_preload.js] skip-if = (os == 'win' && !debug) # bug 1352668 [browser_ext_browserAction_popup_resize.js] [browser_ext_browserAction_simple.js] [browser_ext_browserAction_telemetry.js] [browser_ext_browserAction_theme_icons.js] [browser_ext_browsingData_formData.js] [browser_ext_browsingData_history.js]
new file mode 100644 --- /dev/null +++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup_port.js @@ -0,0 +1,52 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; + +let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`; + +// Tests that message ports still function correctly after a browserAction popup +// <browser> has been reparented. +add_task(async function test_browserActionPort() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + "browser_action": { + "default_popup": "popup.html", + "browser_style": true, + }, + }, + + background() { + new Promise(resolve => { + browser.runtime.onConnect.addListener(port => { + resolve(Promise.all([ + new Promise(r => port.onMessage.addListener(r)), + new Promise(r => port.onDisconnect.addListener(r)), + ])); + }); + }).then(([msg]) => { + browser.test.assertEq("Hallo.", msg, "Got expected message"); + browser.test.notifyPass("browserAction-popup-port"); + }); + }, + + files: { + "popup.html": scriptPage("popup.js"), + "popup.js"() { + let port = browser.runtime.connect(); + window.onload = () => { + setTimeout(() => { + port.postMessage("Hallo."); + window.close(); + }, 0); + }; + }, + }, + }); + + await extension.startup(); + + await clickBrowserAction(extension); + + await extension.awaitFinish("browserAction-popup-port"); + await extension.unload(); +});
new file mode 100644 --- /dev/null +++ b/browser/docs/BrowserErrorReporter.rst @@ -0,0 +1,48 @@ +.. _browsererrorreporter: + +======================= +Browser Error Reporter +======================= + +The `BrowserErrorReporter.jsm <https://dxr.mozilla.org/mozilla-central/source/browser/modules/BrowserErrorReporter.jsm>`_ module collects errors logged to the Browser Console and sends them to a remote error aggregation service. + +.. note:: + This module and the related service is a prototype and will be removed from Firefox in later 2018. + +Opt-out +======= +Collection is enabled by default in the Nightly channel, except for local builds, where it is disabled. It is not available outside of the Nightly channel. + +To opt-out of collection: + +1. Open ``about:preferences``. +2. Select the Privacy and Security panel and go to the Nightly Data Collection and Use section. +3. Uncheck "Allow Nightly to send browser error reports (including error messages) to Mozilla". + +Collected Error Data +==================== +Errors are first sampled at the rate specified by the ``browser.chrome.errorReporter.sampleRate`` preference. + +The payload sent to the remote collection service contains the following info: + +- Firefox version number +- Firefox update channel (usually "Nightly") +- Firefox build ID +- Revision used to build Firefox +- Timestamp when the error occurred +- A project ID specified by the ``browser.chrome.errorReporter.projectId`` preference +- The error message +- The filename that the error was thrown from +- A stacktrace, if available, of the code being executed when the error was thrown + +Privacy-sensitive info +====================== +Error reports may contain sensitive information about the user: + +- Error messages may inadvertently contain personal info depending on the code that generated the error. +- Filenames in the stack trace may contain add-on IDs of currently-installed add-ons. They may also contain local filesystem paths. + +.. seealso:: + + `Browser Error Collection wiki page <https://wiki.mozilla.org/Firefox/BrowserErrorCollection>`_ + Wiki page with up-to-date information on error collection and how we restrict access to the collected data.
--- a/browser/docs/index.rst +++ b/browser/docs/index.rst @@ -4,8 +4,9 @@ Firefox This is the nascent documentation of the Firefox front-end code. .. toctree:: :maxdepth: 1 UITelemetry BrowserUsageTelemetry + BrowserErrorReporter
--- a/browser/extensions/pdfjs/content/PdfJs.jsm +++ b/browser/extensions/pdfjs/content/PdfJs.jsm @@ -332,16 +332,20 @@ var PdfJs = { }, /** * pdf.js is only enabled if it is both selected as the pdf viewer and if the * global switch enabling it is true. * @return {boolean} Whether or not it's enabled. */ get enabled() { + if (!Services.policies.isAllowed("PDF.js")) { + return false; + } + if (!Services.prefs.getBoolPref(PREF_ENABLED_CACHE_INITIALIZED, false)) { // If we just updated, and the cache hasn't been initialized, then we // can't assume a default state, and need to synchronously initialize // PdfJs if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_POSTUPDATE)) { this.checkEnabled(); }
--- a/browser/modules/BrowserErrorReporter.jsm +++ b/browser/modules/BrowserErrorReporter.jsm @@ -50,19 +50,20 @@ const REPORTED_CATEGORIES = new Set([ * The outgoing requests are designed to be compatible with Sentry. See * https://docs.sentry.io/clientdev/ for details on the data format that Sentry * expects. * * Errors may contain PII, such as in messages or local file paths in stack * traces; see bug 1426482 for privacy review and server-side mitigation. */ class BrowserErrorReporter { - constructor(fetchMethod = this._defaultFetch) { - // A fake fetch is passed by the tests to avoid network connections + constructor(fetchMethod = this._defaultFetch, chromeOnly = true) { + // Test arguments for mocks and changing behavior this.fetch = fetchMethod; + this.chromeOnly = chromeOnly; // Values that don't change between error reports. this.requestBodyTemplate = { logger: "javascript", platform: "javascript", release: Services.appinfo.version, environment: UpdateUtils.getUpdateChannel(false), tags: { @@ -128,53 +129,71 @@ class BrowserErrorReporter { try { message.QueryInterface(Ci.nsIScriptError); } catch (err) { return; // Not an error } const isWarning = message.flags & message.warningFlag; const isFromChrome = REPORTED_CATEGORIES.has(message.category); - if (!isFromChrome || isWarning) { + if ((this.chromeOnly && !isFromChrome) || isWarning) { return; } // Sample the amount of errors we send out const sampleRate = Number.parseFloat(Services.prefs.getCharPref(PREF_SAMPLE_RATE)); if (!Number.isFinite(sampleRate) || (Math.random() >= sampleRate)) { return; } + const extensions = new Map(); + for (let extension of WebExtensionPolicy.getActiveExtensions()) { + extensions.set(extension.mozExtensionHostname, extension); + } + + // Replaces any instances of moz-extension:// URLs with internal UUIDs to use + // the add-on ID instead. + function mangleExtURL(string, anchored = true) { + let re = new RegExp(`${anchored ? "^" : ""}moz-extension://([^/]+)/`, "g"); + + return string.replace(re, (m0, m1) => { + let id = extensions.has(m1) ? extensions.get(m1).id : m1; + return `moz-extension://${id}/`; + }); + } + // Parse the error type from the message if present (e.g. "TypeError: Whoops"). let errorMessage = message.errorMessage; let errorName = "Error"; if (message.errorMessage.match(ERROR_PREFIX_RE)) { const parts = message.errorMessage.split(":"); errorName = parts[0]; errorMessage = parts.slice(1).join(":").trim(); } const frames = []; let frame = message.stack; // Avoid an infinite loop by limiting traces to 100 frames. while (frame && frames.length < 100) { - frames.push(await this.normalizeStackFrame(frame)); + const normalizedFrame = await this.normalizeStackFrame(frame); + normalizedFrame.module = mangleExtURL(normalizedFrame.module, false); + frames.push(normalizedFrame); frame = frame.parent; } // Frames are sent in order from oldest to newest. frames.reverse(); const requestBody = Object.assign({}, this.requestBodyTemplate, { timestamp: new Date().toISOString().slice(0, -1), // Remove trailing "Z" project: Services.prefs.getCharPref(PREF_PROJECT_ID), exception: { values: [ { type: errorName, - value: errorMessage, + value: mangleExtURL(errorMessage), module: message.sourceName, stacktrace: { frames, } }, ], }, culprit: message.sourceName,
--- a/browser/modules/test/browser/browser_BrowserErrorReporter.js +++ b/browser/modules/test/browser/browser_BrowserErrorReporter.js @@ -1,12 +1,13 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; +ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm", this); ChromeUtils.import("resource:///modules/BrowserErrorReporter.jsm", this); /* global sinon */ Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js"); registerCleanupFunction(function() { delete window.sinon; }); @@ -401,8 +402,50 @@ add_task(async function testFetchArgumen }, "Reporter builds stack trace from scriptError correctly.", ); }); reporter.uninit(); resetConsole(); }); + +add_task(async function testAddonIDMangle() { + const fetchSpy = sinon.spy(); + // Passing false here disables category checks on errors, which would + // otherwise block errors directly from extensions. + const reporter = new BrowserErrorReporter(fetchSpy, false); + await SpecialPowers.pushPrefEnv({set: [ + [PREF_ENABLED, true], + [PREF_SAMPLE_RATE, "1.0"], + ]}); + reporter.init(); + + // Create and install test add-on + const id = "browsererrorcollection@example.com"; + const extension = ExtensionTestUtils.loadExtension({ + manifest: { + applications: { + gecko: { id }, + }, + }, + background() { + throw new Error("testAddonIDMangle error"); + }, + }); + await extension.startup(); + + // Just in case the error hasn't been thrown before add-on startup. + const call = await TestUtils.waitForCondition( + () => fetchCallForMessage(fetchSpy, "testAddonIDMangle error"), + `Wait for error from ${id} to be logged`, + ); + const body = JSON.parse(call.args[1].body); + const stackFrame = body.exception.values[0].stacktrace.frames[0]; + ok( + stackFrame.module.startsWith(`moz-extension://${id}/`), + "Stack frame filenames use the proper add-on ID instead of internal UUIDs.", + ); + + await extension.unload(); + reporter.uninit(); + resetConsole(); +});
--- a/devtools/server/actors/addon.js +++ b/devtools/server/actors/addon.js @@ -212,17 +212,17 @@ BrowserAddonActor.prototype = { if (metadata) { return metadata.addonID === this.id; } } catch (e) { // ignore } if (global instanceof Ci.nsIDOMWindow) { - return global.document.nodePrincipal.addonId; + return global.document.nodePrincipal.addonId == this.id; } return false; }, /** * Override the eligibility check for scripts and sources to make * sure every script and source with a URL is stored when debugging
--- a/dom/base/EventSource.cpp +++ b/dom/base/EventSource.cpp @@ -10,16 +10,17 @@ #include "mozilla/DebugOnly.h" #include "mozilla/LoadInfo.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/dom/EventSourceBinding.h" #include "mozilla/dom/MessageEvent.h" #include "mozilla/dom/MessageEventBinding.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/WorkerPrivate.h" +#include "mozilla/dom/WorkerRef.h" #include "mozilla/dom/WorkerRunnable.h" #include "mozilla/dom/WorkerScope.h" #include "mozilla/UniquePtrExtensions.h" #include "nsAutoPtr.h" #include "nsIThreadRetargetableStreamListener.h" #include "nsNetUtil.h" #include "nsIAuthPrompt.h" #include "nsIAuthPrompt2.h" @@ -138,18 +139,18 @@ public: nsresult AddWindowObservers(); void RemoveWindowObservers(); void CloseInternal(); void CleanupOnMainThread(); void AddRefObject(); void ReleaseObject(); - bool RegisterWorkerHolder(); - void UnregisterWorkerHolder(); + bool CreateWorkerRef(WorkerPrivate* aWorkerPrivate); + void ReleaseWorkerRef(); void AssertIsOnTargetThread() const { MOZ_ASSERT(IsTargetThread()); } bool IsTargetThread() const { @@ -277,21 +278,18 @@ public: UniquePtr<Message> mCurrentMessage; nsDeque mMessagesToDispatch; ParserStatus mStatus; mozilla::UniquePtr<mozilla::Decoder> mUnicodeDecoder; nsString mLastFieldName; nsString mLastFieldValue; // EventSourceImpl internal states. - // The worker private where the EventSource is created. nullptr if created on - // main thread. (accessed on worker thread only) - WorkerPrivate* mWorkerPrivate; - // Holder to worker to keep worker alive. (accessed on worker thread only) - nsAutoPtr<WorkerHolder> mWorkerHolder; + // WorkerRef to keep the worker alive. (accessed on worker thread only) + RefPtr<ThreadSafeWorkerRef> mWorkerRef; // This mutex protects mFrozen and mEventSource->mReadyState that are used in // different threads. mozilla::Mutex mMutex; // Whether the window is frozen. May be set on main thread and read on target // thread. Use mMutex to protect it before accessing it. bool mFrozen; // There are some messages are going to be dispatched when thaw. bool mGoingToDispatchAllMessages; @@ -348,32 +346,30 @@ EventSourceImpl::EventSourceImpl(EventSo , mIsMainThread(NS_IsMainThread()) , mIsShutDown(false) , mScriptLine(0) , mScriptColumn(0) , mInnerWindowID(0) { MOZ_ASSERT(mEventSource); if (!mIsMainThread) { - mWorkerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(mWorkerPrivate); mEventSource->mIsMainThread = false; } SetReadyState(CONNECTING); } class CleanupRunnable final : public WorkerMainThreadRunnable { public: explicit CleanupRunnable(EventSourceImpl* aEventSourceImpl) - : WorkerMainThreadRunnable(aEventSourceImpl->mWorkerPrivate, + : WorkerMainThreadRunnable(GetCurrentThreadWorkerPrivate(), NS_LITERAL_CSTRING("EventSource :: Cleanup")) , mImpl(aEventSourceImpl) { - mImpl->mWorkerPrivate->AssertIsOnWorkerThread(); + mWorkerPrivate->AssertIsOnWorkerThread(); } bool MainThreadRun() override { mImpl->CleanupOnMainThread(); return true; } @@ -408,17 +404,17 @@ EventSourceImpl::CloseInternal() CleanupOnMainThread(); } else { ErrorResult rv; // run CleanupOnMainThread synchronously on main thread since it touches // observers and members only can be accessed on main thread. RefPtr<CleanupRunnable> runnable = new CleanupRunnable(this); runnable->Dispatch(Killing, rv); MOZ_ASSERT(!rv.Failed()); - UnregisterWorkerHolder(); + ReleaseWorkerRef(); } while (mMessagesToDispatch.GetSize() != 0) { delete static_cast<Message*>(mMessagesToDispatch.PopFront()); } SetFrozen(false); ResetDecoder(); mUnicodeDecoder = nullptr; @@ -447,30 +443,32 @@ void EventSourceImpl::CleanupOnMainThrea ResetConnection(); mPrincipal = nullptr; mSrc = nullptr; } class InitRunnable final : public WorkerMainThreadRunnable { public: - explicit InitRunnable(EventSourceImpl* aEventSourceImpl, - const nsAString& aURL) - : WorkerMainThreadRunnable(aEventSourceImpl->mWorkerPrivate, + InitRunnable(WorkerPrivate* aWorkerPrivate, + EventSourceImpl* aEventSourceImpl, + const nsAString& aURL) + : WorkerMainThreadRunnable(aWorkerPrivate, NS_LITERAL_CSTRING("EventSource :: Init")) , mImpl(aEventSourceImpl) , mURL(aURL) { - mImpl->mWorkerPrivate->AssertIsOnWorkerThread(); + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); } bool MainThreadRun() override { // Get principal from worker's owner document or from worker. - WorkerPrivate* wp = mImpl->mWorkerPrivate; + WorkerPrivate* wp = mWorkerPrivate; while (wp->GetParent()) { wp = wp->GetParent(); } nsPIDOMWindowInner* window = wp->GetWindow(); nsIDocument* doc = window ? window->GetExtantDoc() : nullptr; nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : wp->GetPrincipal(); if (!principal) { @@ -480,23 +478,46 @@ public: ErrorResult rv; mImpl->Init(principal, mURL, rv); mRv = rv.StealNSResult(); return true; } nsresult ErrorCode() const { return mRv; } -protected: +private: // Raw pointer because this runnable is sync. EventSourceImpl* mImpl; const nsAString& mURL; nsresult mRv; }; +class ConnectRunnable final : public WorkerMainThreadRunnable +{ +public: + explicit ConnectRunnable(WorkerPrivate* aWorkerPrivate, + EventSourceImpl* aEventSourceImpl) + : WorkerMainThreadRunnable(aWorkerPrivate, + NS_LITERAL_CSTRING("EventSource :: Connect")) + , mImpl(aEventSourceImpl) + { + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + } + + bool MainThreadRun() override + { + mImpl->InitChannelAndRequestEventSource(); + return true; + } + +private: + RefPtr<EventSourceImpl> mImpl; +}; + nsresult EventSourceImpl::ParseURL(const nsAString& aURL) { AssertIsOnMainThread(); MOZ_ASSERT(!IsShutDown()); // get the src nsCOMPtr<nsIURI> baseURI; nsresult rv = GetBaseURI(getter_AddRefs(baseURI)); @@ -580,21 +601,16 @@ EventSourceImpl::Init(nsIPrincipal* aPri } } mReconnectionTime = Preferences::GetInt("dom.server-events.default-reconnection-time", DEFAULT_RECONNECTION_TIME_VALUE); mUnicodeDecoder = UTF_8_ENCODING->NewDecoderWithBOMRemoval(); - - // the constructor should throw a SYNTAX_ERROR only if it fails resolving the - // url parameter, so we don't care about the InitChannelAndRequestEventSource - // result. - InitChannelAndRequestEventSource(); } //----------------------------------------------------------------------------- // EventSourceImpl::nsIObserver //----------------------------------------------------------------------------- NS_IMETHODIMP EventSourceImpl::Observe(nsISupports* aSubject, @@ -1126,21 +1142,21 @@ EventSourceImpl::ResetDecoder() ClearFields(); } class CallRestartConnection final : public WorkerMainThreadRunnable { public: explicit CallRestartConnection(EventSourceImpl* aEventSourceImpl) : WorkerMainThreadRunnable( - aEventSourceImpl->mWorkerPrivate, + aEventSourceImpl->mWorkerRef->Private(), NS_LITERAL_CSTRING("EventSource :: RestartConnection")) , mImpl(aEventSourceImpl) { - mImpl->mWorkerPrivate->AssertIsOnWorkerThread(); + mWorkerPrivate->AssertIsOnWorkerThread(); } bool MainThreadRun() override { mImpl->RestartConnection(); return true; } @@ -1471,18 +1487,18 @@ EventSourceImpl::DispatchAllMessageEvent } AutoJSAPI jsapi; if (mIsMainThread) { if (NS_WARN_IF(!jsapi.Init(mEventSource->GetOwner()))) { return; } } else { - MOZ_ASSERT(mWorkerPrivate); - if (NS_WARN_IF(!jsapi.Init(mWorkerPrivate->GlobalScope()))) { + MOZ_ASSERT(mWorkerRef); + if (NS_WARN_IF(!jsapi.Init(mWorkerRef->Private()->GlobalScope()))) { return; } } JSContext* cx = jsapi.cx(); while (mMessagesToDispatch.GetSize() > 0) { UniquePtr<Message> message(static_cast<Message*>(mMessagesToDispatch.PopFront())); // Now we can turn our string into a jsval @@ -1772,38 +1788,16 @@ EventSourceImpl::AddRefObject() void EventSourceImpl::ReleaseObject() { Release(); } namespace { -class EventSourceWorkerHolder final : public WorkerHolder -{ -public: - explicit EventSourceWorkerHolder(EventSourceImpl* aEventSourceImpl) - : WorkerHolder("EventSourceWorkerHolder") - , mEventSourceImpl(aEventSourceImpl) - { - } - - bool Notify(WorkerStatus aStatus) override - { - MOZ_ASSERT(aStatus > Running); - if (aStatus >= Canceling) { - mEventSourceImpl->Close(); - } - return true; - } - -private: - // Raw pointer because the EventSourceImpl object keeps alive the holder. - EventSourceImpl* mEventSourceImpl; -}; class WorkerRunnableDispatcher final : public WorkerRunnable { RefPtr<EventSourceImpl> mEventSourceImpl; public: WorkerRunnableDispatcher(EventSourceImpl* aImpl, WorkerPrivate* aWorkerPrivate, @@ -1844,40 +1838,42 @@ public: } private: nsCOMPtr<nsIRunnable> mEvent; }; } // namespace -bool EventSourceImpl::RegisterWorkerHolder() +bool EventSourceImpl::CreateWorkerRef(WorkerPrivate* aWorkerPrivate) { MOZ_ASSERT(!IsShutDown()); - MOZ_ASSERT(mWorkerPrivate); - mWorkerPrivate->AssertIsOnWorkerThread(); - MOZ_ASSERT(!mWorkerHolder); - mWorkerHolder = new EventSourceWorkerHolder(this); - if (NS_WARN_IF(!mWorkerHolder->HoldWorker(mWorkerPrivate, Canceling))) { - mWorkerHolder = nullptr; + MOZ_ASSERT(!mWorkerRef); + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + + RefPtr<EventSourceImpl> self = this; + RefPtr<StrongWorkerRef> workerRef = + StrongWorkerRef::Create(aWorkerPrivate, "EventSource", [self]() { + self->Close(); + }); + + if (NS_WARN_IF(!workerRef)) { return false; } + + mWorkerRef = new ThreadSafeWorkerRef(workerRef); return true; } -void EventSourceImpl::UnregisterWorkerHolder() +void EventSourceImpl::ReleaseWorkerRef() { - // RegisterWorkerHolder fail will destroy EventSourceImpl and invoke - // UnregisterWorkerHolder. MOZ_ASSERT(IsClosed()); - MOZ_ASSERT(mWorkerPrivate); - mWorkerPrivate->AssertIsOnWorkerThread(); - // The DTOR of this WorkerHolder will release the worker for us. - mWorkerHolder = nullptr; - mWorkerPrivate = nullptr; + MOZ_ASSERT(IsCurrentThreadRunningWorker()); + mWorkerRef = nullptr; } //----------------------------------------------------------------------------- // EventSourceImpl::nsIEventTarget //----------------------------------------------------------------------------- NS_IMETHODIMP EventSourceImpl::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags) { @@ -1891,21 +1887,21 @@ EventSourceImpl::Dispatch(already_AddRef nsCOMPtr<nsIRunnable> event_ref(aEvent); if (mIsMainThread) { return NS_DispatchToMainThread(event_ref.forget()); } if (IsShutDown()) { return NS_OK; } - MOZ_ASSERT(mWorkerPrivate); + // If the target is a worker, we have to use a custom WorkerRunnableDispatcher // runnable. RefPtr<WorkerRunnableDispatcher> event = - new WorkerRunnableDispatcher(this, mWorkerPrivate, event_ref.forget()); + new WorkerRunnableDispatcher(this, mWorkerRef->Private(), event_ref.forget()); if (!event->Dispatch()) { return NS_ERROR_FAILURE; } return NS_OK; } @@ -1977,33 +1973,63 @@ EventSource::Constructor(const GlobalObj return nullptr; } nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal(); if (!principal) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } eventSourceImp->Init(principal, aURL, aRv); - } else { - // In workers we have to keep the worker alive using a WorkerHolder in order - // to dispatch messages correctly. - if (!eventSourceImp->RegisterWorkerHolder()) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - RefPtr<InitRunnable> runnable = new InitRunnable(eventSourceImp, aURL); - runnable->Dispatch(Terminating, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } - aRv = runnable->ErrorCode(); + + eventSourceImp->InitChannelAndRequestEventSource(); + return eventSource.forget(); } + + // Worker side. + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + + RefPtr<InitRunnable> initRunnable = + new InitRunnable(workerPrivate, eventSourceImp, aURL); + initRunnable->Dispatch(Terminating, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + aRv = initRunnable->ErrorCode(); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } + + // In workers we have to keep the worker alive using a WorkerRef in order + // to dispatch messages correctly. + if (!eventSourceImp->CreateWorkerRef(workerPrivate)) { + // The worker is already shutting down. Let's return an already closed + // object, but marked as Connecting. + eventSource->Close(); + + // EventSourceImpl must be released before returning the object, otherwise + // it will set EventSource to a CLOSED state in its DTOR. + eventSourceImp = nullptr; + + eventSource->mReadyState = EventSourceImpl::CONNECTING; + return eventSource.forget(); + } + + // Let's connect to the server. + RefPtr<ConnectRunnable> connectRunnable = + new ConnectRunnable(workerPrivate, eventSourceImp); + connectRunnable->Dispatch(Terminating, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + return eventSource.forget(); } // nsWrapperCache JSObject* EventSource::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
--- a/dom/canvas/WebGLProgram.h +++ b/dom/canvas/WebGLProgram.h @@ -80,17 +80,17 @@ struct CachedDrawFetchLimits final { uint64_t maxVerts; uint64_t maxInstances; }; struct LinkedProgramInfo final : public RefCounted<LinkedProgramInfo> , public SupportsWeakPtr<LinkedProgramInfo> { - friend class WebGLProgram; + friend class mozilla::WebGLProgram; MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo) MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo) ////// WebGLProgram* const prog; const GLenum transformFeedbackBufferMode;
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic +++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic @@ -1,9 +1,9 @@ -52547 +52568 0/nm 0th/pt 1/n1 1st/p 1th/tc 2/nm 2nd/p 2th/tc @@ -14708,16 +14708,17 @@ anticlockwise anticoagulant/MS anticommunism/M anticommunist/SM anticyclone/SM anticyclonic antidemocratic antidepressant/MS antidote/MS +antifa antifascist/MS antifreeze/M antigen/SM antigenic antigenicity/M antihero/M antiheroes antihistamine/SM @@ -16931,16 +16932,17 @@ blobbing bloc/SM block's block/UGDS blockade/MZGDRS blockader/M blockage/MS blockbuster/SM blockbusting/M +blockchain/S blocker/MS blockhead/SM blockhouse/MS blog/SM blogged blogger/MS blogging blogroll/SM @@ -22423,16 +22425,17 @@ demonology/SM demonstrability demonstrable/I demonstrably demonstrate/XGNVDS demonstration/M demonstrative/MYSP demonstrativeness/M demonstrator/MS +demonym/S demote/GD demotic demount demulcent/SM demur/TMRS demure/PY demureness/M demurral/SM @@ -24428,16 +24431,17 @@ embed/S embedded embedding embellish/LGDS embellishment/SM ember/SM embezzle/ZGLDRS embezzlement/M embezzler/M +embiggen embitter/GLDS embitterment/M emblazon/GDLS emblazonment/M emblem/SM emblematic emblematically embodiment/EM @@ -27916,16 +27920,17 @@ gladiolus/M gladness/M gladsome glam glamor/SGMD glamorization/M glamorize/DSG glamorous/Y glamour/GMDS +glamping glance/DSMG gland/SM glandes glandular glans/M glare/DSMG glaring/Y glasnost/M @@ -28756,16 +28761,17 @@ hacking/M hackish hackle/MS hackney/SMDG hacksaw/SM hacktivist/MS hackwork/M had haddock/SM +hadith/S hadn't hadst hafnium/M haft/MS hag/SM haggard/YP haggardness/M haggis/MS @@ -28991,16 +28997,17 @@ hardworking hardy/PTR hare/MGDS harebell/MS harebrained harelip/SM harelipped harem/SM haricot/S +harissa hark/DGS harlequin/SM harlot/SM harlotry/M harm/MDGS harmed/U harmful/YP harmfulness/M @@ -29629,16 +29636,17 @@ hobbyhorse/MS hobbyist/SM hobgoblin/MS hobnail/SGMD hobnob/S hobnobbed hobnobbing hobo/MS hoboes +hoc hock/MDSG hockey/M hockshop/MS hod/SM hodgepodge/SM hoe/SM hoecake/SM hoedown/SM @@ -32133,16 +32141,17 @@ juxtapose/DSG juxtaposition/SM k/IFGS kHz kW kWh kabbala kabbalah kabob/SM +kabocha kaboom kabuki/M kaddish/MS kaffeeklatch/MS kaffeeklatsch/MS kahuna/S kaiser/MS kale/M @@ -32417,16 +32426,17 @@ knuckleduster/S knucklehead/MS knurl/SGMD koala/SM koan/S kohl kohlrabi/M kohlrabies kola/MS +kombucha kook/MS kookaburra/SM kookiness/M kooky/TPR kopeck/MS kopek/SM korma kosher/DSG @@ -34722,23 +34732,25 @@ microbiologist/MS microbiology/M microbrewery/SM microchip/MS microcircuit/SM microcode microcomputer/MS microcosm/MS microcosmic +microcredit microdot/SM microeconomics/M microelectronic/S microelectronics/M microfiber/MS microfiche/M microfilm/GMDS +microfinance microfloppies microgroove/SM microlight/MS microloan/MS micromanage/GDSL micromanagement/M micrometeorite/SM micrometer/MS @@ -35253,16 +35265,17 @@ moil/MDSG moire/SM moist/XTPNRY moisten/DRZG moistener/M moistness/M moisture/M moisturize/ZGDRS moisturizer/M +mojo/S molar/SM molasses/M mold/MDRJSZG moldboard/SM molder/GMD moldiness/M molding/M moldy/TPR @@ -36138,16 +36151,17 @@ neighbor/SMDYG neighborhood/SM neighborliness/M neighs neither nelson/SM nematode/SM nemeses nemesis/M +neoadjuvant neoclassic neoclassical neoclassicism/M neocolonialism/M neocolonialist/MS neocon/SM neoconservative/SM neodymium/M @@ -37990,16 +38004,17 @@ oxidize/ZGDRS oxidizer/M oxtail/S oxyacetylene/M oxygen/M oxygenate/DSGN oxygenation/M oxymora oxymoron/M +oy oyes oyez oyster/SM oz ozone/M p/NRXTGJ pH pa/SMH @@ -42407,16 +42422,17 @@ resp respect/ESGVMD respectability/M respectable respectably respectful/EY respectfulness/M respective/Y respell/SGD +respellings respiration/M respirator/SM respiratory respire/DG resplendence/M resplendent/Y respond/SGD respondent/SM @@ -44941,16 +44957,17 @@ sisterly/P sit/S sitar/SM sitarist/MS sitcom/SM site/MGDS sitemap/SM sitter/SM sitting/SM +situ situate/DSXGN situation/M situational six/MSH sixfold sixpence/MS sixshooter/M sixteen/SMH @@ -45399,17 +45416,17 @@ snarkily snarky/TR snarl's snarl/USDG snarling/Y snarly/TR snatch/ZGMDRS snatcher/M snazzily -snazzy/TR +snazzy/TRP sneak/SMDRZG sneaker/M sneakily sneakiness/M sneaking/Y sneaky/TRP sneer/SJMDG sneering/Y @@ -47112,16 +47129,17 @@ subtly subtopic/SM subtotal/SGMD subtract/GSD subtraction/SM subtrahend/SM subtropic/S subtropical subtropics/M +subtweet/S suburb/MS suburban/SM suburbanite/SM suburbia/M subvention/SM subversion/M subversive/SPMY subversiveness/M @@ -49870,16 +49888,17 @@ tyrannic tyrannical/Y tyrannize/GDS tyrannosaur/MS tyrannosaurus/MS tyrannous tyranny/SM tyrant/SM tyro/MS +tzatziki u/S ubiquitous/Y ubiquity/M udder/SM ufologist/SM ufology/M ugh ugliness/M @@ -51560,16 +51579,17 @@ welfare/M welkin/M well/MDPSG wellhead/SM wellie wellington/MS wellness/M wellspring/MS welly/S +welp welsh/ZGDRS welsher/M welt/MDRSZG welter/GMD welterweight/SM wen/M wench/MS wend/DSG @@ -52099,16 +52119,17 @@ woolly/RSMPT woozily wooziness/M woozy/TRP wop/MS! word's word/ADSG wordage/M wordbook/SM +wordie/S wordily wordiness/M wording/SM wordless/Y wordplay/M wordsmith wordsmiths wordy/TPR
--- a/layout/generic/nsGridContainerFrame.cpp +++ b/layout/generic/nsGridContainerFrame.cpp @@ -190,29 +190,30 @@ enum class GridLineSide struct nsGridContainerFrame::TrackSize { enum StateBits : uint16_t { eAutoMinSizing = 0x1, eMinContentMinSizing = 0x2, eMaxContentMinSizing = 0x4, eMinOrMaxContentMinSizing = eMinContentMinSizing | eMaxContentMinSizing, eIntrinsicMinSizing = eMinOrMaxContentMinSizing | eAutoMinSizing, - // 0x8 is unused, feel free to take it! + eModified = 0x8, eAutoMaxSizing = 0x10, eMinContentMaxSizing = 0x20, eMaxContentMaxSizing = 0x40, eAutoOrMaxContentMaxSizing = eAutoMaxSizing | eMaxContentMaxSizing, eIntrinsicMaxSizing = eAutoOrMaxContentMaxSizing | eMinContentMaxSizing, eFlexMaxSizing = 0x80, eFrozen = 0x100, eSkipGrowUnlimited1 = 0x200, eSkipGrowUnlimited2 = 0x400, eSkipGrowUnlimited = eSkipGrowUnlimited1 | eSkipGrowUnlimited2, eBreakBefore = 0x800, eFitContent = 0x1000, + eInfinitelyGrowable = 0x2000, }; StateBits Initialize(nscoord aPercentageBasis, const nsStyleCoord& aMinCoord, const nsStyleCoord& aMaxCoord); bool IsFrozen() const { return mState & eFrozen; } #ifdef DEBUG void Dump() const; @@ -1134,16 +1135,71 @@ struct nsGridContainerFrame::Tracks nsTArray<GridItemInfo>& aGridItems); /** * Apply the additional alignment needed to align the baseline-aligned subtree * the item belongs to within its baseline track. */ void AlignBaselineSubtree(const GridItemInfo& aGridItem) const; + enum class TrackSizingPhase + { + eIntrinsicMinimums, + eContentBasedMinimums, + eMaxContentMinimums, + eIntrinsicMaximums, + eMaxContentMaximums, + }; + + // Some data we collect on each item for Step 2 of the Track Sizing Algorithm + // in ResolveIntrinsicSize below. + struct Step2ItemData final + { + uint32_t mSpan; + TrackSize::StateBits mState; + LineRange mLineRange; + nscoord mMinSize; + nscoord mMinContentContribution; + nscoord mMaxContentContribution; + nsIFrame* mFrame; + static bool IsSpanLessThan(const Step2ItemData& a, const Step2ItemData& b) + { + return a.mSpan < b.mSpan; + } + + template<TrackSizingPhase phase> + nscoord SizeContributionForPhase() const + { + switch (phase) { + case TrackSizingPhase::eIntrinsicMinimums: + case TrackSizingPhase::eIntrinsicMaximums: + return mMinSize; + case TrackSizingPhase::eContentBasedMinimums: + return mMinContentContribution; + case TrackSizingPhase::eMaxContentMinimums: + case TrackSizingPhase::eMaxContentMaximums: + return mMaxContentContribution; + } + MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected phase"); + } + }; + + using FitContentClamper = + std::function<bool(uint32_t aTrack, nscoord aMinSize, nscoord* aSize)>; + + // Helper method for ResolveIntrinsicSize. + template<TrackSizingPhase phase> + bool GrowSizeForSpanningItems(nsTArray<Step2ItemData>::iterator aIter, + const nsTArray<Step2ItemData>::iterator aEnd, + nsTArray<uint32_t>& aTracks, + nsTArray<TrackSize>& aPlan, + nsTArray<TrackSize>& aItemPlan, + TrackSize::StateBits aSelector, + const FitContentClamper& aClamper = nullptr, + bool aNeedInfinitelyGrowableFlag = false); /** * Resolve Intrinsic Track Sizes. * http://dev.w3.org/csswg/css-grid/#algo-content */ void ResolveIntrinsicSize(GridReflowInput& aState, nsTArray<GridItemInfo>& aGridItems, const TrackSizingFunctions& aFunctions, LineRange GridArea::* aRange, @@ -1156,76 +1212,127 @@ struct nsGridContainerFrame::Tracks * max-sizing function, false otherwise. */ bool ResolveIntrinsicSizeStep1(GridReflowInput& aState, const TrackSizingFunctions& aFunctions, nscoord aPercentageBasis, SizingConstraint aConstraint, const LineRange& aRange, const GridItemInfo& aGridItem); + + // Helper method that returns the track size to use in §11.5.1.2 + // https://drafts.csswg.org/css-grid/#extra-space + template<TrackSizingPhase phase> static + nscoord StartSizeInDistribution(const TrackSize& aSize) + { + switch (phase) { + case TrackSizingPhase::eIntrinsicMinimums: + case TrackSizingPhase::eContentBasedMinimums: + case TrackSizingPhase::eMaxContentMinimums: + return aSize.mBase; + case TrackSizingPhase::eIntrinsicMaximums: + case TrackSizingPhase::eMaxContentMaximums: + if (aSize.mLimit == NS_UNCONSTRAINEDSIZE) { + return aSize.mBase; + } + return aSize.mLimit; + } + MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected phase"); + } + /** * Collect the tracks which are growable (matching aSelector) into * aGrowableTracks, and return the amount of space that can be used - * to grow those tracks. Specifically, we return aAvailableSpace minus - * the sum of mBase's (and corresponding grid gaps) in aPlan (clamped to 0) - * for the tracks in aRange, or zero when there are no growable tracks. - * @note aPlan[*].mBase represents a planned new base or limit. + * to grow those tracks. This method implements CSS Grid §11.5.1.2. + * https://drafts.csswg.org/css-grid/#extra-space */ - nscoord CollectGrowable(nscoord aAvailableSpace, - const nsTArray<TrackSize>& aPlan, - const LineRange& aRange, - TrackSize::StateBits aSelector, - nsTArray<uint32_t>& aGrowableTracks) const + template<TrackSizingPhase phase> + nscoord CollectGrowable(nscoord aAvailableSpace, + const LineRange& aRange, + TrackSize::StateBits aSelector, + nsTArray<uint32_t>& aGrowableTracks) const { MOZ_ASSERT(aAvailableSpace > 0, "why call me?"); nscoord space = aAvailableSpace - mGridGap * (aRange.Extent() - 1); const uint32_t start = aRange.mStart; const uint32_t end = aRange.mEnd; for (uint32_t i = start; i < end; ++i) { - const TrackSize& sz = aPlan[i]; - space -= sz.mBase; + const TrackSize& sz = mSizes[i]; + space -= StartSizeInDistribution<phase>(sz); if (space <= 0) { return 0; } - if ((sz.mState & aSelector) && !sz.IsFrozen()) { + if (sz.mState & aSelector) { aGrowableTracks.AppendElement(i); } } return aGrowableTracks.IsEmpty() ? 0 : space; } - void SetupGrowthPlan(nsTArray<TrackSize>& aPlan, - const nsTArray<uint32_t>& aTracks) const - { - for (uint32_t track : aTracks) { - aPlan[track] = mSizes[track]; - } - } - - void CopyPlanToBase(const nsTArray<TrackSize>& aPlan, - const nsTArray<uint32_t>& aTracks) + template<TrackSizingPhase phase> + void InitializeItemPlan(nsTArray<TrackSize>& aItemPlan, + const nsTArray<uint32_t>& aTracks) const { for (uint32_t track : aTracks) { - MOZ_ASSERT(mSizes[track].mBase <= aPlan[track].mBase); - mSizes[track].mBase = aPlan[track].mBase; - } - } - - void CopyPlanToLimit(const nsTArray<TrackSize>& aPlan, - const nsTArray<uint32_t>& aTracks) + auto& plan = aItemPlan[track]; + const TrackSize& sz = mSizes[track]; + plan.mBase = StartSizeInDistribution<phase>(sz); + bool unlimited = sz.mState & TrackSize::eInfinitelyGrowable; + plan.mLimit = unlimited ? NS_UNCONSTRAINEDSIZE : sz.mLimit; + plan.mState = sz.mState; + } + } + + template<TrackSizingPhase phase> + void InitializePlan(nsTArray<TrackSize>& aPlan) const + { + for (size_t i = 0, len = aPlan.Length(); i < len; ++i) { + auto& plan = aPlan[i]; + const auto& sz = mSizes[i]; + plan.mBase = StartSizeInDistribution<phase>(sz); + MOZ_ASSERT(phase == TrackSizingPhase::eMaxContentMaximums || + !(sz.mState & TrackSize::eInfinitelyGrowable), + "forgot to reset the eInfinitelyGrowable bit?"); + plan.mState = sz.mState; + } + } + + template<TrackSizingPhase phase> + void CopyPlanToSize(const nsTArray<TrackSize>& aPlan, + bool aNeedInfinitelyGrowableFlag = false) { - for (uint32_t track : aTracks) { - MOZ_ASSERT(mSizes[track].mLimit == NS_UNCONSTRAINEDSIZE || - mSizes[track].mLimit <= aPlan[track].mBase); - mSizes[track].mLimit = aPlan[track].mBase; - } - } - - using FitContentClamper = - std::function<bool(uint32_t aTrack, nscoord aMinSize, nscoord* aSize)>; + for (size_t i = 0, len = mSizes.Length(); i < len; ++i) { + const auto& plan = aPlan[i]; + MOZ_ASSERT(plan.mBase >= 0); + auto& sz = mSizes[i]; + switch (phase) { + case TrackSizingPhase::eIntrinsicMinimums: + case TrackSizingPhase::eContentBasedMinimums: + case TrackSizingPhase::eMaxContentMinimums: + sz.mBase = plan.mBase; + break; + case TrackSizingPhase::eIntrinsicMaximums: + if (plan.mState & TrackSize::eModified) { + if (sz.mLimit == NS_UNCONSTRAINEDSIZE && + aNeedInfinitelyGrowableFlag) { + sz.mState |= TrackSize::eInfinitelyGrowable; + } + sz.mLimit = plan.mBase; + } + break; + case TrackSizingPhase::eMaxContentMaximums: + if (plan.mState & TrackSize::eModified) { + sz.mLimit = plan.mBase; + } + sz.mState &= ~TrackSize::eInfinitelyGrowable; + break; + } + } + } + /** * Grow the planned size for tracks in aGrowableTracks up to their limit * and then freeze them (all aGrowableTracks must be unfrozen on entry). * Subtract the space added from aAvailableSpace and return that. */ nscoord GrowTracksToLimit(nscoord aAvailableSpace, nsTArray<TrackSize>& aPlan, const nsTArray<uint32_t>& aGrowableTracks, @@ -1275,22 +1382,23 @@ struct nsGridContainerFrame::Tracks /** * Helper for GrowSelectedTracksUnlimited. For the set of tracks (S) that * match aMinSizingSelector: if a track in S doesn't match aMaxSizingSelector * then mark it with aSkipFlag. If all tracks in S were marked then unmark * them. Return aNumGrowable minus the number of tracks marked. It is * assumed that aPlan have no aSkipFlag set for tracks in aGrowableTracks * on entry to this method. */ - uint32_t MarkExcludedTracks(nsTArray<TrackSize>& aPlan, - uint32_t aNumGrowable, - const nsTArray<uint32_t>& aGrowableTracks, - TrackSize::StateBits aMinSizingSelector, - TrackSize::StateBits aMaxSizingSelector, - TrackSize::StateBits aSkipFlag) const + static uint32_t + MarkExcludedTracks(nsTArray<TrackSize>& aPlan, + uint32_t aNumGrowable, + const nsTArray<uint32_t>& aGrowableTracks, + TrackSize::StateBits aMinSizingSelector, + TrackSize::StateBits aMaxSizingSelector, + TrackSize::StateBits aSkipFlag) { bool foundOneSelected = false; bool foundOneGrowable = false; uint32_t numGrowable = aNumGrowable; for (uint32_t track : aGrowableTracks) { TrackSize& sz = aPlan[track]; const auto state = sz.mState; if (state & aMinSizingSelector) { @@ -1310,67 +1418,86 @@ struct nsGridContainerFrame::Tracks aPlan[track].mState &= ~aSkipFlag; } numGrowable = aNumGrowable; } return numGrowable; } /** - * Increase the planned size for tracks in aGrowableTracks that match - * aSelector (or all tracks if aSelector is zero) beyond their limit. + * Mark all tracks in aGrowableTracks with an eSkipGrowUnlimited bit if + * they *shouldn't* grow unlimited in §11.5.1.2.3 "Distribute space beyond + * growth limits" https://drafts.csswg.org/css-grid/#extra-space + * Return the number of tracks that are still growable. + */ + template<TrackSizingPhase phase> + static uint32_t + MarkExcludedTracks(nsTArray<TrackSize>& aPlan, + const nsTArray<uint32_t>& aGrowableTracks, + TrackSize::StateBits aSelector) + { + uint32_t numGrowable = aGrowableTracks.Length(); + if (phase == TrackSizingPhase::eIntrinsicMaximums || + phase == TrackSizingPhase::eMaxContentMaximums) { + // "when handling any intrinsic growth limit: all affected tracks" + return numGrowable; + } + MOZ_ASSERT(aSelector == (aSelector & TrackSize::eIntrinsicMinSizing) && + (aSelector & TrackSize::eMaxContentMinSizing), + "Should only get here for track sizing steps 2.1 to 2.3"); + // Note that eMaxContentMinSizing is always included. We do those first: + numGrowable = MarkExcludedTracks(aPlan, numGrowable, aGrowableTracks, + TrackSize::eMaxContentMinSizing, + TrackSize::eMaxContentMaxSizing, + TrackSize::eSkipGrowUnlimited1); + // Now mark min-content/auto min-sizing tracks if requested. + auto minOrAutoSelector = aSelector & ~TrackSize::eMaxContentMinSizing; + if (minOrAutoSelector) { + numGrowable = MarkExcludedTracks(aPlan, numGrowable, aGrowableTracks, + minOrAutoSelector, + TrackSize::eIntrinsicMaxSizing, + TrackSize::eSkipGrowUnlimited2); + } + return numGrowable; + } + + /** + * Increase the planned size for tracks in aGrowableTracks that aren't + * marked with a eSkipGrowUnlimited flag beyond their limit. * This implements the "Distribute space beyond growth limits" step in * https://drafts.csswg.org/css-grid/#distribute-extra-space */ void GrowSelectedTracksUnlimited(nscoord aAvailableSpace, nsTArray<TrackSize>& aPlan, const nsTArray<uint32_t>& aGrowableTracks, - TrackSize::StateBits aSelector, + uint32_t aNumGrowable, const FitContentClamper& aFitContentClamper) const { - MOZ_ASSERT(aAvailableSpace > 0 && aGrowableTracks.Length() > 0); - uint32_t numGrowable = aGrowableTracks.Length(); - if (aSelector) { - MOZ_ASSERT(aSelector == (aSelector & TrackSize::eIntrinsicMinSizing) && - (aSelector & TrackSize::eMaxContentMinSizing), - "Should only get here for track sizing steps 2.1 to 2.3"); - // Note that eMaxContentMinSizing is always included. We do those first: - numGrowable = MarkExcludedTracks(aPlan, numGrowable, aGrowableTracks, - TrackSize::eMaxContentMinSizing, - TrackSize::eMaxContentMaxSizing, - TrackSize::eSkipGrowUnlimited1); - // Now mark min-content/auto min-sizing tracks if requested. - auto minOrAutoSelector = aSelector & ~TrackSize::eMaxContentMinSizing; - if (minOrAutoSelector) { - numGrowable = MarkExcludedTracks(aPlan, numGrowable, aGrowableTracks, - minOrAutoSelector, - TrackSize::eIntrinsicMaxSizing, - TrackSize::eSkipGrowUnlimited2); - } - } + MOZ_ASSERT(aAvailableSpace > 0 && aGrowableTracks.Length() > 0 && + aNumGrowable <= aGrowableTracks.Length()); nscoord space = aAvailableSpace; DebugOnly<bool> didClamp = false; - while (numGrowable) { - nscoord spacePerTrack = std::max<nscoord>(space / numGrowable, 1); + while (aNumGrowable) { + nscoord spacePerTrack = std::max<nscoord>(space / aNumGrowable, 1); for (uint32_t track : aGrowableTracks) { TrackSize& sz = aPlan[track]; if (sz.mState & TrackSize::eSkipGrowUnlimited) { continue; // an excluded track } nscoord delta = spacePerTrack; nscoord newBase = sz.mBase + delta; if (MOZ_UNLIKELY((sz.mState & TrackSize::eFitContent) && aFitContentClamper)) { // Clamp newBase to the fit-content() size, for §12.5.2 step 5/6. if (aFitContentClamper(track, sz.mBase, &newBase)) { didClamp = true; delta = newBase - sz.mBase; MOZ_ASSERT(delta >= 0, "track size shouldn't shrink"); sz.mState |= TrackSize::eSkipGrowUnlimited1; - --numGrowable; + --aNumGrowable; } } sz.mBase = newBase; space -= delta; MOZ_ASSERT(space >= 0); if (space == 0) { return; } @@ -1379,56 +1506,40 @@ struct nsGridContainerFrame::Tracks MOZ_ASSERT(didClamp, "we don't exit the loop above except by return, " "unless we clamped some track's size"); } /** * Distribute aAvailableSpace to the planned base size for aGrowableTracks * up to their limits, then distribute the remaining space beyond the limits. */ - void DistributeToTrackBases(nscoord aAvailableSpace, + template<TrackSizingPhase phase> + void DistributeToTrackSizes(nscoord aAvailableSpace, nsTArray<TrackSize>& aPlan, + nsTArray<TrackSize>& aItemPlan, nsTArray<uint32_t>& aGrowableTracks, - TrackSize::StateBits aSelector) + TrackSize::StateBits aSelector, + const FitContentClamper& aFitContentClamper) { - SetupGrowthPlan(aPlan, aGrowableTracks); - nscoord space = GrowTracksToLimit(aAvailableSpace, aPlan, aGrowableTracks, nullptr); + InitializeItemPlan<phase>(aItemPlan, aGrowableTracks); + nscoord space = GrowTracksToLimit(aAvailableSpace, aItemPlan, aGrowableTracks, + aFitContentClamper); if (space > 0) { - GrowSelectedTracksUnlimited(space, aPlan, aGrowableTracks, aSelector, nullptr); - } - CopyPlanToBase(aPlan, aGrowableTracks); - } - - /** - * Distribute aAvailableSpace to the planned limits for aGrowableTracks. - */ - void DistributeToTrackLimits(nscoord aAvailableSpace, - nsTArray<TrackSize>& aPlan, - nsTArray<uint32_t>& aGrowableTracks, - const TrackSizingFunctions& aFunctions, - nscoord aPercentageBasis) - { - auto fitContentClamper = [&aFunctions, aPercentageBasis] (uint32_t aTrack, - nscoord aMinSize, - nscoord* aSize) { - nscoord fitContentLimit = - ::ResolveToDefiniteSize(aFunctions.MaxSizingFor(aTrack), aPercentageBasis); - if (*aSize > fitContentLimit) { - *aSize = std::max(aMinSize, fitContentLimit); - return true; - } - return false; - }; - nscoord space = GrowTracksToLimit(aAvailableSpace, aPlan, aGrowableTracks, - fitContentClamper); - if (space > 0) { - GrowSelectedTracksUnlimited(aAvailableSpace, aPlan, aGrowableTracks, - TrackSize::StateBits(0), fitContentClamper); - } - CopyPlanToLimit(aPlan, aGrowableTracks); + uint32_t numGrowable = + MarkExcludedTracks<phase>(aItemPlan, aGrowableTracks, aSelector); + GrowSelectedTracksUnlimited(space, aItemPlan, aGrowableTracks, + numGrowable, aFitContentClamper); + } + for (uint32_t track : aGrowableTracks) { + nscoord& plannedSize = aPlan[track].mBase; + nscoord itemIncurredSize = aItemPlan[track].mBase; + if (plannedSize < itemIncurredSize) { + plannedSize = itemIncurredSize; + } + } } /** * Distribute aAvailableSize to the tracks. This implements 12.6 at: * http://dev.w3.org/csswg/css-grid/#algo-grow-tracks */ void DistributeFreeSpace(nscoord aAvailableSize) { @@ -4131,41 +4242,74 @@ nsGridContainerFrame::Tracks::AlignBasel case NS_STYLE_ALIGN_CENTER: aGridItem.mBaselineOffset[mAxis] += delta / 2; break; default: MOZ_ASSERT_UNREACHABLE("unexpected baseline subtree alignment"); } } +template<nsGridContainerFrame::Tracks::TrackSizingPhase phase> +bool +nsGridContainerFrame::Tracks::GrowSizeForSpanningItems( + nsTArray<Step2ItemData>::iterator aIter, + const nsTArray<Step2ItemData>::iterator aIterEnd, + nsTArray<uint32_t>& aTracks, + nsTArray<TrackSize>& aPlan, + nsTArray<TrackSize>& aItemPlan, + TrackSize::StateBits aSelector, + const FitContentClamper& aFitContentClamper, + bool aNeedInfinitelyGrowableFlag) +{ + constexpr bool isMaxSizingPhase = + phase == TrackSizingPhase::eIntrinsicMaximums || + phase == TrackSizingPhase::eMaxContentMaximums; + bool needToUpdateSizes = false; + InitializePlan<phase>(aPlan); + for (; aIter != aIterEnd; ++aIter) { + const Step2ItemData& item = *aIter; + if (!(item.mState & aSelector)) { + continue; + } + if (isMaxSizingPhase) { + for (auto j = item.mLineRange.mStart, end = item.mLineRange.mEnd; j < end; ++j) { + aPlan[j].mState |= TrackSize::eModified; + } + } + nscoord space = item.SizeContributionForPhase<phase>(); + if (space <= 0) { + continue; + } + aTracks.ClearAndRetainStorage(); + space = CollectGrowable<phase>(space, item.mLineRange, aSelector, + aTracks); + if (space > 0) { + DistributeToTrackSizes<phase>(space, aPlan, aItemPlan, aTracks, aSelector, + aFitContentClamper); + needToUpdateSizes = true; + } + } + if (isMaxSizingPhase) { + needToUpdateSizes = true; + } + if (needToUpdateSizes) { + CopyPlanToSize<phase>(aPlan, aNeedInfinitelyGrowableFlag); + } + return needToUpdateSizes; +} + void nsGridContainerFrame::Tracks::ResolveIntrinsicSize( GridReflowInput& aState, nsTArray<GridItemInfo>& aGridItems, const TrackSizingFunctions& aFunctions, LineRange GridArea::* aRange, nscoord aPercentageBasis, SizingConstraint aConstraint) { - // Some data we collect on each item for Step 2 of the algorithm below. - struct Step2ItemData - { - uint32_t mSpan; - TrackSize::StateBits mState; - LineRange mLineRange; - nscoord mMinSize; - nscoord mMinContentContribution; - nscoord mMaxContentContribution; - nsIFrame* mFrame; - static bool IsSpanLessThan(const Step2ItemData& a, const Step2ItemData& b) - { - return a.mSpan < b.mSpan; - } - }; - // Resolve Intrinsic Track Sizes // http://dev.w3.org/csswg/css-grid/#algo-content // We're also setting eIsFlexing on the item state here to speed up // FindUsedFlexFraction later. AutoTArray<TrackSize::StateBits, 16> stateBitsPerSpan; nsTArray<Step2ItemData> step2Items; CSSOrderAwareFrameIterator& iter = aState.mIter; gfxContext* rc = &aState.mRenderingContext; @@ -4265,169 +4409,100 @@ nsGridContainerFrame::Tracks::ResolveInt } MOZ_ASSERT(!(gridItem.mState[mAxis] & ItemState::eClampMarginBoxMinSize) || (gridItem.mState[mAxis] & ItemState::eApplyAutoMinSize), "clamping only applies to Automatic Minimum Size"); } // Step 2. if (maxSpan) { + auto fitContentClamper = [&aFunctions, aPercentageBasis] (uint32_t aTrack, + nscoord aMinSize, + nscoord* aSize) + { + nscoord fitContentLimit = + ::ResolveToDefiniteSize(aFunctions.MaxSizingFor(aTrack), aPercentageBasis); + if (*aSize > fitContentLimit) { + *aSize = std::max(aMinSize, fitContentLimit); + return true; + } + return false; + }; + // Sort the collected items on span length, shortest first. std::stable_sort(step2Items.begin(), step2Items.end(), Step2ItemData::IsSpanLessThan); nsTArray<uint32_t> tracks(maxSpan); nsTArray<TrackSize> plan(mSizes.Length()); plan.SetLength(mSizes.Length()); - for (uint32_t i = 0, len = step2Items.Length(); i < len; ) { - // Start / end index for items of the same span length: - const uint32_t spanGroupStartIndex = i; - uint32_t spanGroupEndIndex = len; - const uint32_t span = step2Items[i].mSpan; - for (++i; i < len; ++i) { - if (step2Items[i].mSpan != span) { - spanGroupEndIndex = i; - break; - } - } - + nsTArray<TrackSize> itemPlan(mSizes.Length()); + itemPlan.SetLength(mSizes.Length()); + // Start / end iterator for items of the same span length: + auto spanGroupStart = step2Items.begin(); + auto spanGroupEnd = spanGroupStart; + const auto end = step2Items.end(); + for (; spanGroupStart != end; spanGroupStart = spanGroupEnd) { + while (spanGroupEnd != end && + !Step2ItemData::IsSpanLessThan(*spanGroupStart, *spanGroupEnd)) { + ++spanGroupEnd; + } + + const uint32_t span = spanGroupStart->mSpan; bool updatedBase = false; // Did we update any mBase in step 2.1 - 2.3? TrackSize::StateBits selector(TrackSize::eIntrinsicMinSizing); if (stateBitsPerSpan[span] & selector) { // Step 2.1 MinSize to intrinsic min-sizing. - for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) { - Step2ItemData& item = step2Items[i]; - if (!(item.mState & selector)) { - continue; - } - nscoord space = item.mMinSize; - if (space <= 0) { - continue; - } - tracks.ClearAndRetainStorage(); - space = CollectGrowable(space, mSizes, item.mLineRange, selector, - tracks); - if (space > 0) { - DistributeToTrackBases(space, plan, tracks, selector); - updatedBase = true; - } - } + updatedBase = + GrowSizeForSpanningItems<TrackSizingPhase::eIntrinsicMinimums>( + spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector); } selector = contentBasedMinSelector; if (stateBitsPerSpan[span] & selector) { // Step 2.2 MinContentContribution to min-/max-content (and 'auto' when // sizing under a min-content constraint) min-sizing. - for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) { - Step2ItemData& item = step2Items[i]; - if (!(item.mState & selector)) { - continue; - } - nscoord space = item.mMinContentContribution; - if (space <= 0) { - continue; - } - tracks.ClearAndRetainStorage(); - space = CollectGrowable(space, mSizes, item.mLineRange, selector, - tracks); - if (space > 0) { - DistributeToTrackBases(space, plan, tracks, selector); - updatedBase = true; - } - } + updatedBase |= + GrowSizeForSpanningItems<TrackSizingPhase::eContentBasedMinimums>( + spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector); } selector = maxContentMinSelector; if (stateBitsPerSpan[span] & selector) { // Step 2.3 MaxContentContribution to max-content (and 'auto' when // sizing under a max-content constraint) min-sizing. - for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) { - Step2ItemData& item = step2Items[i]; - if (!(item.mState & selector)) { - continue; - } - nscoord space = item.mMaxContentContribution; - if (space <= 0) { - continue; - } - tracks.ClearAndRetainStorage(); - space = CollectGrowable(space, mSizes, item.mLineRange, selector, - tracks); - if (space > 0) { - DistributeToTrackBases(space, plan, tracks, selector); - updatedBase = true; - } - } + updatedBase |= + GrowSizeForSpanningItems<TrackSizingPhase::eMaxContentMinimums>( + spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector); } if (updatedBase) { // Step 2.4 for (TrackSize& sz : mSizes) { if (sz.mBase > sz.mLimit) { sz.mLimit = sz.mBase; } } } - if (stateBitsPerSpan[span] & TrackSize::eIntrinsicMaxSizing) { - plan = mSizes; - for (TrackSize& sz : plan) { - if (sz.mLimit == NS_UNCONSTRAINEDSIZE) { - // use mBase as the planned limit - } else { - sz.mBase = sz.mLimit; - } - } - + + selector = TrackSize::eIntrinsicMaxSizing; + if (stateBitsPerSpan[span] & selector) { + const bool willRunStep2_6 = + stateBitsPerSpan[span] & TrackSize::eAutoOrMaxContentMaxSizing; // Step 2.5 MinSize to intrinsic max-sizing. - for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) { - Step2ItemData& item = step2Items[i]; - if (!(item.mState & TrackSize::eIntrinsicMaxSizing)) { - continue; - } - nscoord space = item.mMinSize; - if (space <= 0) { - continue; - } - tracks.ClearAndRetainStorage(); - space = CollectGrowable(space, plan, item.mLineRange, - TrackSize::eIntrinsicMaxSizing, - tracks); - if (space > 0) { - DistributeToTrackLimits(space, plan, tracks, aFunctions, - aPercentageBasis); - } - } - for (size_t j = 0, len = mSizes.Length(); j < len; ++j) { - TrackSize& sz = plan[j]; - sz.mState &= ~(TrackSize::eFrozen | TrackSize::eSkipGrowUnlimited); - if (sz.mLimit != NS_UNCONSTRAINEDSIZE) { - sz.mLimit = sz.mBase; // collect the results from 2.5 - } - } - - if (stateBitsPerSpan[span] & TrackSize::eAutoOrMaxContentMaxSizing) { + GrowSizeForSpanningItems<TrackSizingPhase::eIntrinsicMaximums>( + spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector, + fitContentClamper, willRunStep2_6); + + if (willRunStep2_6) { // Step 2.6 MaxContentContribution to max-content max-sizing. - for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) { - Step2ItemData& item = step2Items[i]; - if (!(item.mState & TrackSize::eAutoOrMaxContentMaxSizing)) { - continue; - } - nscoord space = item.mMaxContentContribution; - if (space <= 0) { - continue; - } - tracks.ClearAndRetainStorage(); - space = CollectGrowable(space, plan, item.mLineRange, - TrackSize::eAutoOrMaxContentMaxSizing, - tracks); - if (space > 0) { - DistributeToTrackLimits(space, plan, tracks, aFunctions, - aPercentageBasis); - } - } + selector = TrackSize::eAutoOrMaxContentMaxSizing; + GrowSizeForSpanningItems<TrackSizingPhase::eMaxContentMaximums>( + spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector, + fitContentClamper); } } } } // Step 3. for (TrackSize& sz : mSizes) { if (sz.mLimit == NS_UNCONSTRAINEDSIZE) { @@ -6939,16 +7014,19 @@ nsGridContainerFrame::TrackSize::Dump() printf("max-content "); } else if (mState & eFlexMaxSizing) { printf("flex "); } if (mState & eFrozen) { printf("frozen "); } + if (mState & eModified) { + printf("modified "); + } if (mState & eBreakBefore) { printf("break-before "); } } #endif // DEBUG nsGridContainerFrame*
--- a/layout/generic/test/mochitest.ini +++ b/layout/generic/test/mochitest.ini @@ -137,8 +137,12 @@ support-files = selection_expanding_xbl. [test_selection_touchevents.html] [test_taintedfilters.html] support-files = file_taintedfilters_feDisplacementMap-tainted-1.svg file_taintedfilters_feDisplacementMap-tainted-2.svg file_taintedfilters_feDisplacementMap-tainted-3.svg file_taintedfilters_feDisplacementMap-tainted-ref.svg file_taintedfilters_feDisplacementMap-untainted-ref.svg file_taintedfilters_feDisplacementMap-untainted-1.svg file_taintedfilters_feDisplacementMap-untainted-2.svg file_taintedfilters_red-flood-for-feImage-cors.svg file_taintedfilters_red-flood-for-feImage-cors.svg^headers^ file_taintedfilters_red-flood-for-feImage.svg [test_scroll_position_restore.html] support-files = file_scroll_position_restore.html [test_scroll_position_restore_after_stop.html] [test_scroll_animation_restore.html] [test_scroll_position_iframe.html] +[test_grid_track_sizing_algo_001.html] +skip-if = debug == true # the test is slow +[test_grid_track_sizing_algo_002.html] +skip-if = debug == true # the test is slow
new file mode 100644 --- /dev/null +++ b/layout/generic/test/test_grid_track_sizing_algo_001.html @@ -0,0 +1,1641 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: intrinsic track sizing with spanning items</title> + <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1425599"> + <link rel="help" href="https://drafts.csswg.org/css-grid/#algo-content"> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <style type="text/css"> +body,html { color:black; background:white; font-family:monospace; font-size:16px; padding:0; margin:0; } +* { vertical-align: top; line-height: 1px; } + +.grid { + display: inline-grid; + grid-template-rows: 1px; + grid-auto-rows: 10px; + border: 1px solid; + place-content: start; + place-items: start; +} + +x { + grid-row: 1; + height: 1px; + background: grey; +} + +x:nth-child(1) { background: lime; width: 3px; grid-column: 1/span 2; } +x:nth-child(2) { background: silver; width: 6px; grid-column: 2/span 4; } +x:nth-child(3) { background: blue; width: 12px; grid-column: 2/span 2; } + </style> +</head> +<body> + +<script> +let min1 = [ + "0", "4px" +]; +let min2 = [ + "auto", "min-content", "max-content" +]; +let max1 = [ + "8px" +]; +let max2 = [ + "auto", "min-content", "max-content" +]; + +var track = []; +min1.forEach((min) => { max2.forEach((max) => { + track.push("minmax(" + min + "," + max + ")"); +})}); +min2.forEach((min) => { max2.forEach((max) => { + track.push("minmax(" + min + "," + max + ")"); +})}); +min2.forEach((min) => { max1.forEach((max) => { + track.push("minmax(" + min + "," + max + ")"); +})}); +min2.forEach((min) => { max2.forEach((max) => { + track.push("minmax(" + min + "," + max + ")"); +})}); +track.push("fit-content(8px)"); + +var cols = []; +track.forEach((c1) => { + cols.push(c1 + " " + c1 + " " + c1 + " " + c1 + " " + c1); + track.forEach((c2) => { + if (c1 != c2) { + cols.push(c1 + " " + c2 + " " + c2 + " " + c2 + " " + c2); + cols.push(c2 + " " + c1 + " " + c1 + " " + c2 + " " + c2); + } +})}); + +document.body.style.display = 'none'; +cols.forEach((col) => { + let grid = document.createElement('div'); + grid.className = "grid"; + grid.style.gridTemplateColumns = col; + grid.appendChild(document.createElement('x')) + grid.appendChild(document.createElement('x')) + grid.appendChild(document.createElement('x')) + document.body.appendChild(grid); +}); +document.body.style.display = ''; +</script> + +<script> +var actual = []; +[...document.querySelectorAll('.grid')].forEach(function(e) { + let cs = window.getComputedStyle(e); + actual.push([cs.gridTemplateColumns, cs.width]); +}); + +function dumpResult() { + var s = ""; + actual.forEach(v => { + s += '["' + v[0] + '","' + v[1] + '"],\n'; + }); + let pre = document.createElement("pre"); + pre.innerHTML = s; + document.body.appendChild(pre); +} + +let expected = [ +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 8px 8px 8px 8px","32px"], +["8px 6px 6px 8px 8px","36px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 3px 3px","21px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 4px 4px","24px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 8px 8px 8px 8px","36px"], +["8px 6px 6px 8px 8px","36px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["4px 6px 6px 0px 0px","16px"], +["0px 6px 6px 0px 0px","12px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 0px 0px","20px"], +["0px 8px 8px 0px 0px","16px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 4px 4px","28px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["8px 6px 6px 0px 0px","20px"], +["1.5px 8px 8px 0px 0px","17.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["3px 6px 6px 0px 0px","15px"], +["0px 6px 6px 0px 0px","12px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["0px 6px 6px 4px 4px","20px"], +["4px 6px 6px 4px 4px","24px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 8px 8px 8px 8px","33.5px"], +["8px 6px 6px 8px 8px","36px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +["1.5px 6px 6px 0px 0px","13.5px"], +]; + +function test() { + ok(expected.length > 0, "sanity check"); + for (i = 0; i < expected.length; ++i) { + var msg = ""; + if (actual[i][0] != expected[i][0]) { + msg = "'grid-template-columns' for grid index " + i + ":\n" + [...document.querySelectorAll('.grid')][i].outerHTML; + is(actual[i][0], expected[i][0], msg); + } + if (actual[i][1] != expected[i][1]) { + msg = "'width' for grid index " + i + ":\n" + [...document.querySelectorAll('.grid')][i].outerHTML; + is(actual[i][1], expected[i][1], msg); + } + if (msg != "") { + i = expected.length; // stop after first failed grid by default + } + } + SimpleTest.finish(); +} + +</script> + +<script> +window.onload = function() { setTimeout(test, 0); }; +SimpleTest.waitForExplicitFinish(); +</script> + +</body> +</html>
new file mode 100644 --- /dev/null +++ b/layout/generic/test/test_grid_track_sizing_algo_002.html @@ -0,0 +1,1641 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: intrinsic track sizing with spanning items</title> + <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1425599"> + <link rel="help" href="https://drafts.csswg.org/css-grid/#algo-content"> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <style type="text/css"> +body,html { color:black; background:white; font-family:monospace; font-size:16px; padding:0; margin:0; } +* { vertical-align: top; line-height: 1px; } + +.grid { + display: inline-grid; + grid-template-rows: 1px; + grid-auto-rows: 10px; + border: 1px solid; + place-content: start; + place-items: start; +} + +x { + grid-row: 1; + height: 1px; + background: grey; +} + +x:nth-child(1) { background: lime; width: 3px; grid-column: 1/span 2; } +x:nth-child(2) { background: silver; width: 6px; grid-column: 2/span 3; } +x:nth-child(3) { background: blue; width: 12px; grid-column: 1/span 2; } + </style> +</head> +<body> + +<script> +let min1 = [ + "0", "4px" +]; +let min2 = [ + "auto", "min-content", "max-content" +]; +let max1 = [ + "8px" +]; +let max2 = [ + "auto", "min-content", "max-content" +]; + +var track = []; +min1.forEach((min) => { max2.forEach((max) => { + track.push("minmax(" + min + "," + max + ")"); +})}); +min2.forEach((min) => { max2.forEach((max) => { + track.push("minmax(" + min + "," + max + ")"); +})}); +min2.forEach((min) => { max1.forEach((max) => { + track.push("minmax(" + min + "," + max + ")"); +})}); +min2.forEach((min) => { max2.forEach((max) => { + track.push("minmax(" + min + "," + max + ")"); +})}); +track.push("fit-content(8px)"); + +var cols = []; +track.forEach((c1) => { + cols.push(c1 + " " + c1 + " " + c1 + " " + c1 + " " + c1); + track.forEach((c2) => { + if (c1 != c2) { + cols.push(c1 + " " + c2 + " " + c2 + " " + c2 + " " + c2); + cols.push(c2 + " " + c1 + " " + c1 + " " + c2 + " " + c2); + } +})}); + +document.body.style.display = 'none'; +cols.forEach((col) => { + let grid = document.createElement('div'); + grid.className = "grid"; + grid.style.gridTemplateColumns = col; + grid.appendChild(document.createElement('x')) + grid.appendChild(document.createElement('x')) + grid.appendChild(document.createElement('x')) + document.body.appendChild(grid); +}); +document.body.style.display = ''; +</script> + +<script> +var actual = []; +[...document.querySelectorAll('.grid')].forEach(function(e) { + let cs = window.getComputedStyle(e); + actual.push([cs.gridTemplateColumns, cs.width]); +}); + +function dumpResult() { + var s = ""; + actual.forEach(v => { + s += '["' + v[0] + '","' + v[1] + '"],\n'; + }); + let pre = document.createElement("pre"); + pre.innerHTML = s; + document.body.appendChild(pre); +} + +let expected = [ +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["4px 8px 4px 4px 4px","24px"], +["8px 4px 0px 4px 4px","20px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 8px 8px 8px","36px"], +["12px 0px 0px 8px 8px","28px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 0px 6px 0px","18px"], +["6px 6px 4px 4px 4px","24px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["6px 6px 4px 4px 4px","24px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["6px 6px 4px 4px 4px","24px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["8px 4px 1px 1px 0px","14px"], +["4px 8px 4px 0px 0px","16px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["6px 6px 4px 4px 4px","24px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 8px 8px 8px","36px"], +["8px 4px 4px 8px 8px","32px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["4px 8px 0px 0px 0px","12px"], +["8px 4px 4px 0px 0px","16px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["8px 8px 8px 8px 8px","40px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 8px 8px 8px 8px","40px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 8px 8px 8px 8px","40px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 8px 0px 0px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 8px 4px 4px","28px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 8px 8px 8px 8px","40px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["8px 6px 0px 0px 0px","14px"], +["6px 8px 8px 0px 0px","22px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["12px 0px 3px 3px 0px","18px"], +["0px 12px 0px 0px 0px","12px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["8px 4px 4px 4px 4px","24px"], +["4px 8px 0px 4px 4px","20px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 8px 8px 8px 8px","38px"], +["8px 6px 0px 8px 8px","30px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +["6px 6px 0px 0px 0px","12px"], +]; + +function test() { + ok(expected.length > 0, "sanity check"); + for (i = 0; i < expected.length; ++i) { + var msg = ""; + if (actual[i][0] != expected[i][0]) { + msg = "'grid-template-columns' for grid index " + i + ":\n" + [...document.querySelectorAll('.grid')][i].outerHTML; + is(actual[i][0], expected[i][0], msg); + } + if (actual[i][1] != expected[i][1]) { + msg = "'width' for grid index " + i + ":\n" + [...document.querySelectorAll('.grid')][i].outerHTML; + is(actual[i][1], expected[i][1], msg); + } + if (msg != "") { + i = expected.length; // stop after first failed grid by default + } + } + SimpleTest.finish(); +} + +</script> + +<script> +window.onload = function() { setTimeout(test, 0); }; +SimpleTest.waitForExplicitFinish(); +</script> + +</body> +</html>
--- a/layout/reftests/css-grid/grid-col-max-sizing-max-content-001-ref.html +++ b/layout/reftests/css-grid/grid-col-max-sizing-max-content-001-ref.html @@ -12,19 +12,19 @@ body,html { color:black; background:whit .grid { display: block; border: dashed blue; float:left; clear:left; } -.c1 { min-width:40px; margin-bottom: 2px; margin-right: 47px; } +.c1 { width:40px; margin-bottom: 2px; margin-right: 47px; } .r1 { min-width:70px; margin-left: 38px; margin-top: 2px; } -.c3 { min-width:0; margin: 2px 18px 1px 85px; } +.c3 { width:10px; margin: 2px 18px 1px 71px; } span { display: block; background: gray; border-style: solid; border-width: 1px 3px 5px 7px; padding: 1px 3px; margin: 1px 5px; @@ -47,42 +47,43 @@ x { display:inline-block; width:10px; he </div> <div class="grid"> <span class="c1"><x> </x></span> <span class="r1"><x> </x></span> <span class="r1"><x> </x></span> <span class="r1"><x> </x></span> </div> + <div class="grid" style="width:436px"> -<span class="c1" style="margin-right:41px"><x> </x></span> +<span class="c1" style="width:374px; margin-right:41px"><x> </x></span> <span class="r1" style="margin-left:5px"><x> </x></span> <span class="c3" style="margin-left:405px; float:left;margin-top:1px;"><x> </x></span> </div> <div class="grid" style="width:500px;"> -<span class="c1" style="min-width:20px;margin-right:448px"><x> </x></span> +<span class="c1" style="width:20px;margin-right:448px"><x> </x></span> <span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span> <span class="r1" style="min-width:30px;margin-left:28px; margin-right:426px"><x> </x></span> <span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span> </div> <div class="grid" style="width:583px;"> -<span class="c1" style="margin-right:55px"><x> </x></span> +<span class="c1" style="width:507px; margin-right:55px"><x> </x></span> <span class="r1"><x> </x></span> <span class="c3" style="margin-left:538px; float:left;margin-top:1px;"><x> </x></span> </div> <div class="grid" style="width:389px;"> <span class="c1" style="width:100px"><x> </x></span> <span class="r1" style="width:300px;margin-left:68px;"><x> </x></span> -<span class="c3" style="margin-left:245px;float:left;margin-top:1px;"><x> </x></span> +<span class="c3" style="margin-left:131px;float:left;margin-top:1px;"><x> </x></span> </div> <div class="grid" style="width:389px;"> <span class="c1" style="width:100px"><x> </x></span> <span class="r1" style="width:300px;margin-left:68px;"><x> </x></span> -<span class="c3" style="margin-left:245px;float:left;margin-top:1px;"><x> </x></span> +<span class="c3" style="margin-left:131px;float:left;margin-top:1px;"><x> </x></span> </div> </body> </html>
--- a/layout/reftests/css-grid/grid-col-max-sizing-max-content-002-ref.html +++ b/layout/reftests/css-grid/grid-col-max-sizing-max-content-002-ref.html @@ -16,19 +16,19 @@ body,html { color:black; background:whit clear:left; } .wrap { border: dashed blue; overflow:hidden; clear:left; } -.c1 { min-width:40px; margin-bottom: 2px; margin-right: 47px; } +.c1 { width:40px; margin-bottom: 2px; margin-right: 47px; } .r1 { min-width:70px; margin-left: 38px; margin-top: 2px; } -.c3 { min-width:0; margin: 2px 18px 1px 85px; } +.c3 { width:10px; margin: 2px 18px 1px 71px; } span { display: block; background: gray; border-style: solid; border-width: 1px 3px 5px 7px; padding: 1px 3px; margin: 1px 5px; @@ -51,42 +51,43 @@ x { display:inline-block; width:10px; he </div></div> <div class="wrap"><div class="grid"> <span class="c1"><x> </x></span> <span class="r1"><x> </x></span> <span class="r1"><x> </x></span> <span class="r1"><x> </x></span> </div></div> + <div class="wrap"><div class="grid" style="width:436px"> -<span class="c1" style="margin-right:41px"><x> </x></span> +<span class="c1" style="width:374px; margin-right:41px"><x> </x></span> <span class="r1" style="margin-left:5px"><x> </x></span> <span class="c3" style="margin-left:405px; float:left;margin-top:1px;"><x> </x></span> </div></div> <div class="wrap" style="float:left;"><div class="grid" style="width:500px;"> -<span class="c1" style="min-width:20px;margin-right:448px"><x> </x></span> +<span class="c1" style="width:20px;margin-right:448px"><x> </x></span> <span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span> <span class="r1" style="min-width:30px;margin-left:28px; margin-right:426px"><x> </x></span> <span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span> </div></div> <div class="wrap"><div class="grid" style="width:583px;"> -<span class="c1" style="margin-right:55px"><x> </x></span> +<span class="c1" style="width:507px; margin-right:55px"><x> </x></span> <span class="r1"><x> </x></span> <span class="c3" style="margin-left:538px; float:left;margin-top:1px;"><x> </x></span> </div></div> <div class="wrap"><div class="grid" style="width:389px;"> <span class="c1" style="width:100px"><x> </x></span> <span class="r1" style="width:300px;margin-left:68px;"><x> </x></span> -<span class="c3" style="margin-left:245px;float:left;margin-top:1px;"><x> </x></span> +<span class="c3" style="margin-left:131px;float:left;margin-top:1px;"><x> </x></span> </div></div> <div class="wrap"><div class="grid" style="width:389px;"> <span class="c1" style="width:100px"><x> </x></span> <span class="r1" style="width:300px;margin-left:68px;"><x> </x></span> -<span class="c3" style="margin-left:245px;float:left;margin-top:1px;"><x> </x></span> +<span class="c3" style="margin-left:131px;float:left;margin-top:1px;"><x> </x></span> </div></div> </body> </html>
--- a/layout/reftests/css-grid/grid-flex-min-sizing-002-ref.html +++ b/layout/reftests/css-grid/grid-flex-min-sizing-002-ref.html @@ -122,20 +122,20 @@ body,html { color:black; background:whit .gE { grid-template-columns: minmax(8px,0) minmax(8px,0) minmax(8px,0) 0px; } .gF { - grid-template-columns: 22px - 1px - 1px - auto; + grid-template-columns: 2px + 20px + 2px + 0; } .t { grid-column: span 3; border:2px solid; } .d1 { grid-column: 1 / span 2; background: grey; } .d3 { grid-column: 3 / span 2; background: blue; } div { min-width:0; min-height:10px; } t { display:inline-block; width:20px; }
--- a/layout/reftests/css-grid/grid-max-sizing-flex-004-ref.html +++ b/layout/reftests/css-grid/grid-max-sizing-flex-004-ref.html @@ -46,18 +46,18 @@ x { display:inline-block; height:10px; w <div class="grid zero" style="width:0;height:0;"></div> <div class="grid zero" style="width:1px;height:1px;"></div> <!-- TODO: fails due to broken align:stretch <div class="grid flex" style="width:0;height:0;"><span class="c1"><x></x></span><span class="c2" style="position:relative;top:0px;width:0;min-height:0;height:1px;min-width:0;border-width:0 0 0 10px;z-index:1;"><x></x></span></div> <div class="grid flex" style="width:1px;height:1px;"><span class="c1" style="margin-top:1px"><x></x></span></div> --> -<div class="grid mm" style="width:0;height:0;"><span class="c1" style="min-width:23px;min-height:10px"><x></x></span><span class="c2" style="position:relative;left:14px;width:18px;min-width:0;z-index:-1"><x></x></span></div> -<div class="grid mm" style="width:1px;height:1px;"><span class="c1" style="min-width:23px;min-height:10px"><x></x></span><span class="c2" style="position:relative;left:14px;width:18px;min-width:0;z-index:-1"><x></x></span></div> +<div class="grid mm" style="width:0;height:0;"><span class="c1" style="min-width:18px;min-height:10px"><x></x></span><span class="c2" style="position:relative;left:14px;width:18px;min-width:0;z-index:-1"><x></x></span></div> +<div class="grid mm" style="width:1px;height:1px;"><span class="c1" style="min-width:18px;min-height:10px"><x></x></span><span class="c2" style="position:relative;left:14px;width:18px;min-width:0;z-index:-1"><x></x></span></div> <!-- TODO: fails due to broken align:stretch <div class="grid zero" style="width:0;height:0;"><span class="c1"><x></x></span></div> <div class="grid zero" style="width:1px;height:1px;"><span class="c1"><x></x></span></div> --> <div class="grid flex"> <span class="c1 r1"><x></x></span> </div>
--- a/layout/reftests/css-grid/grid-track-intrinsic-sizing-002-ref.html +++ b/layout/reftests/css-grid/grid-track-intrinsic-sizing-002-ref.html @@ -22,65 +22,65 @@ body,html { color:black; background:whit } .d1 { position: absolute; bottom: 0; background: grey; } .g1 .d1 { - width: 52px; + width: 0px; } .g2 .d1 { - width: 56px; + width: 0px; } .g2f .d1 { - width: 69px; + width: 0px; } .g3 .d1 { - width: 56px; + width: 0px; } .g4 .d1 { - width: 96px; + width: 80px; } .g4f .d1 { - width: 69px; + width: 0px; } .g5 .d1 { - width: 96px; + width: 80px; } .g6 .d1 { - width: 69px; + width: 0px; } .g6f .d1 { - width: 69px; + width: 0px; } .g7 .d1 { - width: 69px; + width: 0px; } .g8 .t { width: 196px; } .g8 .d1 { width: 200px; } .g9 .d1 { - width: 69px; + width: 0px; } .gA .d1 { - width: 93px; + width: 80px; } .gB .d1 { - width: 93px; + width: 80px; } .gC .d1 { - width: 93px; + width: 80px; } .gD .d1 { - width: 93px; + width: 80px; } .t { grid-column: span 1; border:2px solid; } div { min-width:0; min-height:10px; } t { display:inline-block; width:20px; } </style> </head>
--- a/layout/reftests/css-grid/grid-track-intrinsic-sizing-003-ref.html +++ b/layout/reftests/css-grid/grid-track-intrinsic-sizing-003-ref.html @@ -22,125 +22,125 @@ body,html { color:black; background:whit } .d1 { position: absolute; bottom: 0; background: grey; } .g1 .d1 { - width: 52px; + width: 0px; } .g2 .d1 { - width: 56px; + width: 0px; } .g2f .d1 { width: 69px; } .g3 .d1 { - width: 56px; + width: 0px; } .g4 .d1 { - width: 96px; + width: 80px; } .g4f .d1 { width: 104px; } .g5 .d1 { - width: 96px; + width: 80px; } .g6 .d1 { - width: 69px; + width: 0px; } .g6f .d1 { width: 89px; } .g7 .d1 { - width: 69px; + width: 0px; } .g8 .t { width: 196px; } .g8 .d1 { width: 200px; } .g9 .d1 { - width: 69px; + width: 0px; } .gA .d1 { - width: 93px; + width: 80px; } .gB .d1 { - width: 93px; + width: 80px; } .gC .d1 { - width: 93px; + width: 80px; } .gD .d1 { - width: 93px; + width: 80px; } .d2 { position: absolute; bottom: 0; right: 0; background: blue; } .g1 .d2 { - width: 448px; + width: 500px; } .g2 .d2 { - width: 444px; + width: 500px; } .g2f .d2 { right: auto; left: 69px; width: 35px; } .g3 .d2 { - width: 444px; + width: 500px; } .g4 .d2 { - width: 404px; + width: 420px; } .g4f .d2 { right: auto; left: 69px; width: 35px; } .g5 .d2 { - width: 404px; + width: 420px; } .g6 .d2 { - width: 431px; + width: 500px; } .g6f .d2 { right: auto; left: 69px; width: 35px; } .g7 .d2 { - width: 431px; + width: 500px; } .g8 .d2 { width: 300px; } .g9 .d2 { - width: 431px; + width: 500px; } .gA .d2 { - width: 407px; + width: 420px; } .gB .d2 { - width: 407px; + width: 420px; } .gC .d2 { - width: 407px; + width: 420px; } .gD .d2 { - width: 407px; + width: 420px; } .t { grid-column: span 1; border:2px solid; } div { min-width:0; min-height:10px; } t { display:inline-block; width:20px; } </style> </head>
--- a/mfbt/HashFunctions.h +++ b/mfbt/HashFunctions.h @@ -60,17 +60,24 @@ namespace mozilla { /** * The golden ratio as a 32-bit fixed-point value. */ static const uint32_t kGoldenRatioU32 = 0x9E3779B9U; namespace detail { -inline uint32_t +MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW +constexpr uint32_t +RotateLeft5(uint32_t aValue) +{ + return (aValue << 5) | (aValue >> 27); +} + +constexpr uint32_t AddU32ToHash(uint32_t aHash, uint32_t aValue) { /* * This is the meat of all our hash routines. This hash function is not * particularly sophisticated, but it seems to work well for our mostly * plain-text inputs. Implementation notes follow. * * Our use of the golden ratio here is arbitrary; we could pick almost any @@ -84,17 +91,17 @@ AddU32ToHash(uint32_t aHash, uint32_t aV * * The rotation length of 5 is also arbitrary, although an odd number is again * preferable so our hash explores the whole universe of possible rotations. * * Finally, we multiply by the golden ratio *after* xor'ing, not before. * Otherwise, if |aHash| is 0 (as it often is for the beginning of a * message), the expression * - * mozilla::WrappingMultiply(kGoldenRatioU32, RotateBitsLeft(aHash, 5)) + * mozilla::WrappingMultiply(kGoldenRatioU32, RotateLeft5(aHash)) * |xor| * aValue * * evaluates to |aValue|. * * (Number-theoretic aside: Because any odd number |m| is relatively prime to * our modulus (2**32), the list * @@ -105,24 +112,24 @@ AddU32ToHash(uint32_t aHash, uint32_t aV * * It's also nice if |m| has large-ish order mod 2**32 -- that is, if the * smallest k such that m**k == 1 (mod 2**32) is large -- so we can safely * multiply our hash value by |m| a few times without negating the * multiplicative effect. Our golden ratio constant has order 2**29, which is * more than enough for our purposes.) */ return mozilla::WrappingMultiply(kGoldenRatioU32, - RotateLeft(aHash, 5) ^ aValue); + RotateLeft5(aHash) ^ aValue); } /** * AddUintptrToHash takes sizeof(uintptr_t) as a template parameter. */ template<size_t PtrSize> -inline uint32_t +constexpr uint32_t AddUintptrToHash(uint32_t aHash, uintptr_t aValue) { return AddU32ToHash(aHash, static_cast<uint32_t>(aValue)); } template<> inline uint32_t AddUintptrToHash<8>(uint32_t aHash, uintptr_t aValue) @@ -168,17 +175,17 @@ AddToHash(uint32_t aHash, A* aA) return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, uintptr_t(aA)); } // We use AddUintptrToHash() for hashing all integral types. 8-byte integral types // are treated the same as 64-bit pointers, and smaller integral types are first // implicitly converted to 32 bits and then passed to AddUintptrToHash() to be hashed. template<typename T, typename U = typename mozilla::EnableIf<mozilla::IsIntegral<T>::value>::Type> -MOZ_MUST_USE inline uint32_t +MOZ_MUST_USE constexpr uint32_t AddToHash(uint32_t aHash, T aA) { return detail::AddUintptrToHash<sizeof(T)>(aHash, aA); } template<typename A, typename... Args> MOZ_MUST_USE uint32_t AddToHash(uint32_t aHash, A aArg, Args... aArgs) @@ -208,16 +215,29 @@ HashUntilZero(const T* aStr) { uint32_t hash = 0; for (T c; (c = *aStr); aStr++) { hash = AddToHash(hash, c); } return hash; } +// This is a `constexpr` alternative to HashUntilZero(const T*). It should +// only be used for compile-time computation because it uses recursion. +// XXX: once support for GCC 4.9 is dropped, this function should be removed +// and HashUntilZero(const T*) should be made `constexpr`. +template<typename T> +constexpr uint32_t +ConstExprHashUntilZero(const T* aStr, uint32_t aHash) +{ + return !*aStr + ? aHash + : ConstExprHashUntilZero(aStr + 1, AddToHash(aHash, *aStr)); +} + template<typename T> uint32_t HashKnownLength(const T* aStr, size_t aLength) { uint32_t hash = 0; for (size_t i = 0; i < aLength; i++) { hash = AddToHash(hash, aStr[i]); } @@ -252,16 +272,31 @@ HashString(const unsigned char* aStr, si } MOZ_MUST_USE inline uint32_t HashString(const char16_t* aStr) { return detail::HashUntilZero(aStr); } +// This is a `constexpr` alternative to HashString(const char16_t*). It should +// only be used for compile-time computation because it uses recursion. +// +// You may need to use the +// MOZ_{PUSH,POP}_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING macros if you use +// this function. See the comment on those macros' definitions for more detail. +// +// XXX: once support for GCC 4.9 is dropped, this function should be removed +// and HashString(const char16_t*) should be made `constexpr`. +MOZ_MUST_USE constexpr uint32_t +ConstExprHashString(const char16_t* aStr) +{ + return detail::ConstExprHashUntilZero(aStr, 0); +} + MOZ_MUST_USE inline uint32_t HashString(const char16_t* aStr, size_t aLength) { return detail::HashKnownLength(aStr, aLength); } /* * On Windows, wchar_t is not the same as char16_t, even though it's
--- a/mfbt/WrappingOperations.h +++ b/mfbt/WrappingOperations.h @@ -89,55 +89,42 @@ struct WrapToSignedHelper /** * Convert an unsigned value to signed, if necessary wrapping around. * * This is the behavior normal C++ casting will perform in most implementations * these days -- but this function makes explicit that such conversion is * happening. */ template<typename UnsignedType> -inline constexpr typename detail::WrapToSignedHelper<UnsignedType>::SignedType +constexpr typename detail::WrapToSignedHelper<UnsignedType>::SignedType WrapToSigned(UnsignedType aValue) { return detail::WrapToSignedHelper<UnsignedType>::compute(aValue); } -// The |mozilla::Wrapping*| functions aren't constexpr because MSVC warns about -// well-defined unsigned integer overflows that may occur within the constexpr -// math. If/when MSVC fix this bug, we should make them all constexpr. -// -// https://msdn.microsoft.com/en-us/library/4kze989h.aspx (C4307) -// https://developercommunity.visualstudio.com/content/problem/211134/unsigned-integer-overflows-in-constexpr-functionsa.html (bug report) -// -// For now there's no practical, readable way to avoid such overflows in pure -// C++. And we can't add narrow #pragmas where overflow can occur to disable -// the warnings, because constexpr apparently causes the warning to be emitted -// at the outermost call *sites* (so every user of |mozilla::Wrapping*| would -// have to add them). - namespace detail { template<typename T> -inline constexpr T +constexpr T ToResult(typename MakeUnsigned<T>::Type aUnsigned) { // We could *always* return WrapToSigned and rely on unsigned conversion to // undo the wrapping when |T| is unsigned, but this seems clearer. return IsSigned<T>::value ? WrapToSigned(aUnsigned) : aUnsigned; } template<typename T> struct WrappingAddHelper { private: using UnsignedT = typename MakeUnsigned<T>::Type; public: MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW - static T compute(T aX, T aY) + static constexpr T compute(T aX, T aY) { return ToResult<T>(static_cast<UnsignedT>(aX) + static_cast<UnsignedT>(aY)); } }; } // namespace detail /** @@ -160,33 +147,33 @@ public: * WrappingAdd(int32_t(-42), int32_t(-17)) is -59 ((8589934533 mod 2**32) - 2**32). * * There's no equivalent to this operation in C++, as C++ signed addition that * overflows has undefined behavior. But it's how such addition *tends* to * behave with most compilers, unless an optimization or similar -- quite * permissibly -- triggers different behavior. */ template<typename T> -inline T +constexpr T WrappingAdd(T aX, T aY) { return detail::WrappingAddHelper<T>::compute(aX, aY); } namespace detail { template<typename T> struct WrappingSubtractHelper { private: using UnsignedT = typename MakeUnsigned<T>::Type; public: MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW - static T compute(T aX, T aY) + static constexpr T compute(T aX, T aY) { return ToResult<T>(static_cast<UnsignedT>(aX) - static_cast<UnsignedT>(aY)); } }; } // namespace detail /** @@ -210,33 +197,33 @@ public: * WrappingSubtract(int32_t(-17), int32_t(-42)) is 25 (25 mod 2**32). * * There's no equivalent to this operation in C++, as C++ signed subtraction * that overflows has undefined behavior. But it's how such subtraction *tends* * to behave with most compilers, unless an optimization or similar -- quite * permissibly -- triggers different behavior. */ template<typename T> -inline T +constexpr T WrappingSubtract(T aX, T aY) { return detail::WrappingSubtractHelper<T>::compute(aX, aY); } namespace detail { template<typename T> struct WrappingMultiplyHelper { private: using UnsignedT = typename MakeUnsigned<T>::Type; public: MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW - static T compute(T aX, T aY) + static constexpr T compute(T aX, T aY) { // Begin with |1U| to ensure the overall operation chain is never promoted // to signed integer operations that might have *signed* integer overflow. return ToResult<T>(static_cast<UnsignedT>(1U * static_cast<UnsignedT>(aX) * static_cast<UnsignedT>(aY))); } }; @@ -272,17 +259,41 @@ public: * WrappingMultiply(int8_t(16), int8_t(255)) is -16 ((4080 mod 2**8) - 2**8). * * There's no equivalent to this operation in C++, as C++ signed * multiplication that overflows has undefined behavior. But it's how such * multiplication *tends* to behave with most compilers, unless an optimization * or similar -- quite permissibly -- triggers different behavior. */ template<typename T> -inline T +constexpr T WrappingMultiply(T aX, T aY) { return detail::WrappingMultiplyHelper<T>::compute(aX, aY); } +// The |mozilla::Wrapping*| functions are constexpr. Unfortunately, MSVC warns +// about well-defined unsigned integer overflows that may occur within the +// constexpr math. +// +// https://msdn.microsoft.com/en-us/library/4kze989h.aspx (C4307) +// https://developercommunity.visualstudio.com/content/problem/211134/unsigned-integer-overflows-in-constexpr-functionsa.html (bug report) +// +// So we need a way to suppress these warnings. Unfortunately, the warnings are +// issued at the very top of the `constexpr` chain, which is often some +// distance from the triggering Wrapping*() operation. So we can't suppress +// them within this file. Instead, callers have to do it with these macros. +// +// If/when MSVC fix this bug, we should remove these macros. +#ifdef _MSC_VER +#define MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING \ + __pragma(warning(push)) \ + __pragma(warning(disable:4307)) +#define MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING \ + __pragma(warning(pop)) +#else +#define MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING +#define MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING +#endif + } /* namespace mozilla */ #endif /* mozilla_WrappingOperations_h */
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_cli_arguments.py +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_cli_arguments.py @@ -1,15 +1,23 @@ # 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/. from __future__ import absolute_import import copy +import platform +try: + import winreg +except ImportError: + try: + import _winreg as winreg + except ImportError: + pass from marionette_harness import MarionetteTestCase class TestCommandLineArguments(MarionetteTestCase): def setUp(self): super(TestCommandLineArguments, self).setUp() @@ -29,18 +37,45 @@ class TestCommandLineArguments(Marionett self.marionette.start_session() with self.marionette.using_context("chrome"): safe_mode = self.marionette.execute_script(""" Cu.import("resource://gre/modules/Services.jsm"); return Services.appinfo.inSafeMode; """) + self.assertTrue(safe_mode, "Safe Mode has not been enabled") - self.assertTrue(safe_mode, "Safe Mode has not been enabled") + def test_safe_mode_blocked_by_policy(self): + if platform.system() != 'Windows': + return + + reg_policies = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, "SOFTWARE\\Policies", 0, winreg.KEY_WRITE) + reg_mozilla = winreg.CreateKeyEx(reg_policies, "Mozilla", 0, winreg.KEY_WRITE) + reg_firefox = winreg.CreateKeyEx(reg_mozilla, "Firefox", 0, winreg.KEY_WRITE) + winreg.SetValueEx(reg_firefox, "DisableSafeMode", 0, winreg.REG_DWORD, 1) + + self.marionette.instance.app_args.append("-safe-mode") + + self.marionette.quit() + self.marionette.start_session() + + with self.marionette.using_context("chrome"): + safe_mode = self.marionette.execute_script(""" + Cu.import("resource://gre/modules/Services.jsm"); + + return Services.appinfo.inSafeMode; + """) + self.assertFalse(safe_mode, "Safe Mode has been enabled") + + winreg.CloseKey(reg_firefox) + winreg.DeleteKey(reg_mozilla, "Firefox") + winreg.CloseKey(reg_mozilla) + winreg.DeleteKey(reg_policies, "Mozilla") + winreg.CloseKey(reg_policies) def test_startup_timeout(self): startup_timeout = self.marionette.startup_timeout # Use a timeout which always cause an IOError self.marionette.startup_timeout = .1 msg = "Process killed after {}s".format(self.marionette.startup_timeout)
--- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -319479,16 +319479,22 @@ ] ], "eventsource/dedicated-worker/eventsource-close.htm": [ [ "/eventsource/dedicated-worker/eventsource-close.htm", {} ] ], + "eventsource/dedicated-worker/eventsource-close2.htm": [ + [ + "/eventsource/dedicated-worker/eventsource-close2.htm", + {} + ] + ], "eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm": [ [ "/eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm", { "timeout": "long" } ] ], @@ -390173,17 +390179,17 @@ "3beee687d73a0e5c987b1e697c51230f405ff7a7", "manual" ], "FileAPI/FileReader/test_securityerrors-manual.html": [ "d352d5c6b5d1f2ada419d51bcfd9ecd9100bf892", "manual" ], "FileAPI/FileReader/workers.html": [ - "7e9f00c9af5bb982a1b549ebc9f5a3d0b5cf4387", + "d7894a0abb064411d4811d8cfb9c3ce65f99babd", "testharness" ], "FileAPI/FileReaderSync.worker.js": [ "19741fbd0498bf9135408ceb6128221cbeb4e2f3", "testharness" ], "FileAPI/OWNERS": [ "f1d0cf569f445712d986e9a85f3cbc717137d7fe", @@ -542312,16 +542318,20 @@ "eventsource/README.md": [ "f450de54700a6057f2acb57d2c52257684b337f8", "support" ], "eventsource/dedicated-worker/eventsource-close.htm": [ "700107771158b22fa280f30a5a52d1aac617ff6e", "testharness" ], + "eventsource/dedicated-worker/eventsource-close2.htm": [ + "a3d13b0261b05eba56effb9ca3f6c31e312e777a", + "testharness" + ], "eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm": [ "9614ac5ce1967bbbcae6a1cc8d64465579f6410d", "testharness" ], "eventsource/dedicated-worker/eventsource-constructor-url-bogus.htm": [ "d97370612a324674cc3c9db744656efc2c517573", "testharness" ], @@ -546821,17 +546831,17 @@ "049dd60f6397e87da17edf9ddb96c10fc08e57d4", "testharness" ], "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-negative-width-height.html": [ "3fddee5842259433e1158eb326e51d037dd42774", "testharness" ], "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html": [ - "caaede75e5c16cc78023ce410f48e37e612cffbb", + "6da68164fdba8986d4dd217ad48198f675e83165", "testharness" ], "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html": [ "94c1f2f19317d039e4c30e30fcdc41da20fe402f", "testharness" ], "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerwidth.html": [ "30ef1e2913e78f0fde1794bdf5bceef435a7101a", @@ -594601,17 +594611,17 @@ "f3255ca1da5c8e81c37e658cb2dc83e1a7dc2e63", "testharness" ], "websockets/Create-nonAscii-protocol-string.htm": [ "f556c52a5ba7370dfd94f57331d606b147b0932f", "testharness" ], "websockets/Create-on-worker-shutdown.html": [ - "6c1e57e92b617fdb3d8dd86528af7073d21ece03", + "e710493c0cd84630a1c853ada23c37908bece9cb", "testharness" ], "websockets/Create-protocol-with-space.htm": [ "923fd2681d86812d63347f995f91747ebec18a44", "testharness" ], "websockets/Create-protocols-repeated-case-insensitive.htm": [ "55a3dbf713cf45900f8af2e9c9bc2f41bb447141",
new file mode 100644 --- /dev/null +++ b/testing/web-platform/tests/eventsource/dedicated-worker/eventsource-close2.htm @@ -0,0 +1,29 @@ +<!-- +self.close() +var source = new EventSource("../resources/message.py") +postMessage(source.readyState) +/*--> +<!DOCTYPE html> +<html> + <head> + <title>dedicated worker - EventSource created after: worker.close()</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var test = async_test(); + test.step(function() { + var worker = new Worker('#') + worker.onmessage = function(e) { + test.step(function() { + assert_equals(e.data, EventSource.CONNECTING, 'this.readyState') + }) + test.done() + } + }) + </script> + </body> +</html> +<!--*/ //-->
--- a/toolkit/content/aboutProfiles.js +++ b/toolkit/content/aboutProfiles.js @@ -80,17 +80,21 @@ function refreshUI() { isInUse, }); } let createButton = document.getElementById("create-button"); createButton.onclick = createProfileWizard; let restartSafeModeButton = document.getElementById("restart-in-safe-mode-button"); - restartSafeModeButton.onclick = function() { restart(true); }; + if (!Services.policies || Services.policies.isAllowed("safeMode")) { + restartSafeModeButton.onclick = function() { restart(true); }; + } else { + restartSafeModeButton.setAttribute("disabled", "true"); + } let restartNormalModeButton = document.getElementById("restart-button"); restartNormalModeButton.onclick = function() { restart(false); }; } function openDirectory(dir) { let nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile", "initWithPath");
--- a/toolkit/content/aboutSupport.js +++ b/toolkit/content/aboutSupport.js @@ -1201,16 +1201,20 @@ function openProfileDirectory() { function populateActionBox() { if (ResetProfile.resetSupported()) { $("reset-box").style.display = "block"; $("action-box").style.display = "block"; } if (!Services.appinfo.inSafeMode && AppConstants.platform !== "android") { $("safe-mode-box").style.display = "block"; $("action-box").style.display = "block"; + + if (Services.policies && !Services.policies.isAllowed("safeMode")) { + $("restart-in-safe-mode-button").setAttribute("disabled", "true"); + } } } // Prompt user to restart the browser in safe mode function safeModeRestart() { let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"] .createInstance(Ci.nsISupportsPRBool); Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
--- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -2773,27 +2773,22 @@ var gDetailView = { } else { screenshotbox.hidden = true; } var desc = document.getElementById("detail-desc"); desc.textContent = aAddon.description; var fullDesc = document.getElementById("detail-fulldesc"); - if (aAddon.fullDescription) { - // The following is part of an awful hack to include the licenses for GMP - // plugins without having bug 624602 fixed yet, and intentionally ignores - // localisation. - if (aAddon.isGMPlugin) { - // eslint-disable-next-line no-unsanitized/property - fullDesc.unsafeSetInnerHTML(aAddon.fullDescription); - } else { - fullDesc.textContent = aAddon.fullDescription; - } - + if (aAddon.getFullDescription) { + fullDesc.textContent = ""; + fullDesc.append(aAddon.getFullDescription(document)); + fullDesc.hidden = false; + } else if (aAddon.fullDescription) { + fullDesc.textContent = aAddon.fullDescription; fullDesc.hidden = false; } else { fullDesc.hidden = true; } var contributions = document.getElementById("detail-contributions"); if ("contributionURL" in aAddon && aAddon.contributionURL) { contributions.hidden = false;
--- a/toolkit/mozapps/extensions/internal/GMPProvider.jsm +++ b/toolkit/mozapps/extensions/internal/GMPProvider.jsm @@ -24,16 +24,18 @@ ChromeUtils.defineModuleGetter( this, "setTimeout", "resource://gre/modules/Timer.jsm"); const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties"; const SEC_IN_A_DAY = 24 * 60 * 60; // How long to wait after a user enabled EME before attempting to download CDMs. const GMP_CHECK_DELAY = 10 * 1000; // milliseconds +const XHTML = "http://www.w3.org/1999/xhtml"; + const NS_GRE_DIR = "GreD"; const CLEARKEY_PLUGIN_ID = "gmp-clearkey"; const CLEARKEY_VERSION = "0.1"; const GMP_LICENSE_INFO = "gmp_license_info"; const GMP_PRIVACY_INFO = "gmp_privacy_info"; const GMP_LEARN_MORE = "learn_more_label"; @@ -90,18 +92,19 @@ function configureLogging() { } /** * The GMPWrapper provides the info for the various GMP plugins to public * callers through the API. */ -function GMPWrapper(aPluginInfo) { +function GMPWrapper(aPluginInfo, aRawPluginInfo) { this._plugin = aPluginInfo; + this._rawPlugin = aRawPluginInfo; this._log = Log.repository.getLoggerWithMessagePrefix("Toolkit.GMP", "GMPWrapper(" + this._plugin.id + ") "); Services.prefs.addObserver(GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_ENABLED, this._plugin.id), this, true); Services.prefs.addObserver(GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_VERSION, @@ -135,17 +138,41 @@ GMPWrapper.prototype = { get id() { return this._plugin.id; }, get type() { return "plugin"; }, get isGMPlugin() { return true; }, get name() { return this._plugin.name; }, get creator() { return null; }, get homepageURL() { return this._plugin.homepageURL; }, get description() { return this._plugin.description; }, - get fullDescription() { return this._plugin.fullDescription; }, + get fullDescription() { return null; }, + + getFullDescription(doc) { + let plugin = this._rawPlugin; + + let frag = doc.createDocumentFragment(); + for (let [urlProp, labelId] of [["learnMoreURL", GMP_LEARN_MORE], + ["licenseURL", this.id == WIDEVINE_ID ? + GMP_PRIVACY_INFO : GMP_LICENSE_INFO]]) { + if (plugin[urlProp]) { + let a = doc.createElementNS(XHTML, "a"); + a.href = plugin[urlProp]; + a.target = "_blank"; + a.textContent = pluginsBundle.GetStringFromName(labelId); + + if (frag.childElementCount) { + frag.append(doc.createElementNS(XHTML, "br"), + doc.createElementNS(XHTML, "br")); + } + frag.append(a); + } + } + + return frag; + }, get version() { return GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_VERSION, null, this._plugin.id); }, get isActive() { return !this.appDisabled && !this.userDisabled && @@ -628,43 +655,29 @@ var GMPProvider = { aCallback(results); }, get isEnabled() { return GMPPrefs.getBool(GMPPrefs.KEY_PROVIDER_ENABLED, false); }, - generateFullDescription(aPlugin) { - let rv = []; - for (let [urlProp, labelId] of [["learnMoreURL", GMP_LEARN_MORE], - ["licenseURL", aPlugin.id == WIDEVINE_ID ? - GMP_PRIVACY_INFO : GMP_LICENSE_INFO]]) { - if (aPlugin[urlProp]) { - let label = pluginsBundle.GetStringFromName(labelId); - rv.push(`<xhtml:a href="${aPlugin[urlProp]}" target="_blank">${label}</xhtml:a>.`); - } - } - return rv.length ? rv.join("<xhtml:br /><xhtml:br />") : undefined; - }, - buildPluginList() { this._plugins = new Map(); for (let aPlugin of GMP_PLUGINS) { let plugin = { id: aPlugin.id, name: pluginsBundle.GetStringFromName(aPlugin.name), description: pluginsBundle.GetStringFromName(aPlugin.description), homepageURL: aPlugin.homepageURL, optionsURL: aPlugin.optionsURL, wrapper: null, isEME: aPlugin.isEME, }; - plugin.fullDescription = this.generateFullDescription(aPlugin); - plugin.wrapper = new GMPWrapper(plugin); + plugin.wrapper = new GMPWrapper(plugin, aPlugin); this._plugins.set(plugin.id, plugin); } }, ensureProperCDMInstallState() { if (!GMPPrefs.getBool(GMPPrefs.KEY_EME_ENABLED, true)) { for (let plugin of this._plugins.values()) { if (plugin.isEME && plugin.wrapper.isInstalled) {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js @@ -506,17 +506,20 @@ add_task(async function test_permissions let install = await AddonManager.getInstallForFile(xpi); let perminfo; install.promptHandler = info => { perminfo = info; return Promise.resolve(); }; - await promiseCompleteInstall(install); + await Promise.all([ + promiseCompleteInstall(install), + promiseWebExtensionStartup(), + ]); notEqual(perminfo, undefined, "Permission handler was invoked"); equal(perminfo.existingAddon, null, "Permission info does not include an existing addon"); notEqual(perminfo.addon, null, "Permission info includes the new addon"); let perms = perminfo.addon.userPermissions; deepEqual(perms.permissions, ["tabs", "storage"], "API permissions are correct"); deepEqual(perms.origins, ["https://*.example.com/*", "<all_urls>"], "Host permissions are correct");
--- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -3149,16 +3149,50 @@ public: bool mDisableRemote; #endif #if defined(MOZ_WIDGET_GTK) GdkDisplay* mGdkDisplay; #endif }; +#ifdef XP_WIN +namespace { + +bool PolicyHasRegValue(HKEY aKey, LPCTSTR aName, DWORD* aValue) +{ + HKEY hkey = NULL; + LONG ret = RegOpenKeyExW(aKey, + L"SOFTWARE\\Policies\\Mozilla\\Firefox", 0, KEY_READ, &hkey); + if (ret != ERROR_SUCCESS) { + return false; + } + nsAutoRegKey key(hkey); + DWORD len = sizeof(aValue); + ret = RegQueryValueExW(hkey, aName, 0, NULL, (LPBYTE)aValue, &len); + RegCloseKey(key); + return ret == ERROR_SUCCESS; +} + +bool SafeModeBlockedByPolicy() +{ + LPCTSTR policyName = L"DisableSafeMode"; + DWORD value; + if (PolicyHasRegValue(HKEY_LOCAL_MACHINE, policyName, &value)) { + return value == 1; + } + if (PolicyHasRegValue(HKEY_CURRENT_USER, policyName, &value)) { + return value == 1; + } + return false; +} + +} // anonymous namespace +#endif // XP_WIN + /* * XRE_mainInit - Initial setup and command line parameter processing. * Main() will exit early if either return value != 0 or if aExitFlag is * true. */ int XREMain::XRE_mainInit(bool* aExitFlag) { @@ -3485,22 +3519,16 @@ XREMain::XRE_mainInit(bool* aExitFlag) if (override) { gRestartArgv[gRestartArgc++] = const_cast<char*>("-override"); gRestartArgv[gRestartArgc++] = const_cast<char*>(override); } gRestartArgv[gRestartArgc] = nullptr; - if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) { - gSafeMode = true; - // unset the env variable - SaveToEnv("MOZ_SAFE_MODE_RESTART="); - } - ar = CheckArg("safe-mode", true); if (ar == ARG_BAD) { PR_fprintf(PR_STDERR, "Error: argument --safe-mode is invalid when argument --osint is specified\n"); return 1; } if (ar == ARG_FOUND) { gSafeMode = true; } @@ -3521,16 +3549,30 @@ XREMain::XRE_mainInit(bool* aExitFlag) #ifdef XP_MACOSX if ((GetCurrentEventKeyModifiers() & optionKey) && !EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) gSafeMode = true; #endif #ifdef XP_WIN +if (gSafeMode && SafeModeBlockedByPolicy()) { + gSafeMode = false; + } +#endif + + // The Safe Mode Policy should not be enforced for the env var case + // (used by updater and crash-recovery). + if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) { + gSafeMode = true; + // unset the env variable + SaveToEnv("MOZ_SAFE_MODE_RESTART="); + } + +#ifdef XP_WIN { // Add CPU microcode version to the crash report as "CPUMicrocodeVersion". // It feels like this code may belong in nsSystemInfo instead. int cpuUpdateRevision = -1; HKEY key; static const WCHAR keyName[] = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";