Merge inbound to mozilla-central. a=merge

This commit is contained in:
Cosmin Sabou 2018-04-04 20:53:53 +03:00
Родитель f9138cc6f4 8dcff1f91e
Коммит 91c9d08e42
93 изменённых файлов: 2517 добавлений и 400 удалений

Просмотреть файл

@ -1250,16 +1250,6 @@ var BookmarkingUI = {
return BrowserPageActions.panelAnchorNodeForAction(action);
},
get notifier() {
delete this.notifier;
return this.notifier = document.getElementById("bookmarked-notification-anchor");
},
get dropmarkerNotifier() {
delete this.dropmarkerNotifier;
return this.dropmarkerNotifier = document.getElementById("bookmarked-notification-dropmarker-anchor");
},
get broadcaster() {
delete this.broadcaster;
let broadcaster = document.getElementById("bookmarkThisPageBroadcaster");

Просмотреть файл

@ -522,15 +522,6 @@
</vbox>
</hbox>
<hbox id="bookmarked-notification-container" mousethrough="always">
<vbox id="bookmarked-notification-anchor">
<vbox id="bookmarked-notification"/>
</vbox>
<vbox id="bookmarked-notification-dropmarker-anchor">
<image id="bookmarked-notification-dropmarker-icon"/>
</vbox>
</hbox>
<tooltip id="dynamic-shortcut-tooltip"
onpopupshowing="UpdateDynamicShortcutTooltipText(this);"/>

Просмотреть файл

@ -1,6 +1,9 @@
"use strict";
/* global PanelUI */
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
let gCUITestUtils = new CustomizableUITestUtils(window);
/**
* WHOA THERE: We should never be adding new things to
* EXPECTED_APPMENU_OPEN_REFLOWS. This is a whitelist that should slowly go
@ -71,13 +74,10 @@ add_task(async function() {
};
// First, open the appmenu.
await withPerfObserver(async function() {
let popupShown =
BrowserTestUtils.waitForEvent(PanelUI.panel, "popupshown");
await PanelUI.show();
await popupShown;
}, {expectedReflows: EXPECTED_APPMENU_OPEN_REFLOWS,
frames: frameExpectations});
await withPerfObserver(() => gCUITestUtils.openMainMenu(), {
expectedReflows: EXPECTED_APPMENU_OPEN_REFLOWS,
frames: frameExpectations,
});
// Now open a series of subviews, and then close the appmenu. We
// should not reflow during any of this.
@ -122,8 +122,6 @@ add_task(async function() {
await openSubViewsRecursively(PanelUI.mainView);
let hidden = BrowserTestUtils.waitForEvent(PanelUI.panel, "popuphidden");
PanelUI.hide();
await hidden;
await gCUITestUtils.hideMainMenu();
}, {expectedReflows: [], frames: frameExpectations});
});

Просмотреть файл

@ -119,7 +119,7 @@ add_task(async function() {
is(menuButton.getAttribute("badge-status"), "addon-alert", "Should have addon alert badge");
// Find the menu entries for sideloaded extensions
await PanelUI.show();
await gCUITestUtils.openMainMenu();
let addons = PanelUI.addonNotificationContainer;
is(addons.children.length, 4, "Have 4 menu entries for sideloaded extensions");
@ -159,7 +159,7 @@ add_task(async function() {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
// Should still have 3 entries in the hamburger menu
await PanelUI.show();
await gCUITestUtils.openMainMenu();
addons = PanelUI.addonNotificationContainer;
is(addons.children.length, 3, "Have 3 menu entries for sideloaded extensions");
@ -189,13 +189,13 @@ add_task(async function() {
is(addon4.userDisabled, true, "Addon 4 should still be disabled");
// Should still have 2 entries in the hamburger menu
await PanelUI.show();
await gCUITestUtils.openMainMenu();
addons = PanelUI.addonNotificationContainer;
is(addons.children.length, 2, "Have 2 menu entries for sideloaded extensions");
// Close the hamburger menu and go directly to the addons manager
await PanelUI.hide();
await gCUITestUtils.hideMainMenu();
win = await BrowserOpenAddonsMgr(VIEW);
@ -225,13 +225,13 @@ add_task(async function() {
is(addon3.userDisabled, false, "Addon 3 should be enabled");
// Should still have 1 entry in the hamburger menu
await PanelUI.show();
await gCUITestUtils.openMainMenu();
addons = PanelUI.addonNotificationContainer;
is(addons.children.length, 1, "Have 1 menu entry for sideloaded extensions");
// Close the hamburger menu and go to the detail page for this addon
await PanelUI.hide();
await gCUITestUtils.hideMainMenu();
win = await BrowserOpenAddonsMgr(`addons://detail/${encodeURIComponent(ID4)}`);
let button = win.document.getElementById("detail-enable-btn");

Просмотреть файл

@ -79,7 +79,7 @@ async function backgroundUpdateTest(url, id, checkIconFn) {
is(getBadgeStatus(), "addon-alert", "Should have addon alert badge");
// Find the menu entry for the update
await PanelUI.show();
await gCUITestUtils.openMainMenu();
let addons = PanelUI.addonNotificationContainer;
is(addons.children.length, 1, "Have a menu entry for the update");
@ -123,10 +123,10 @@ async function backgroundUpdateTest(url, id, checkIconFn) {
// Alert badge and hamburger menu items should be gone
is(getBadgeStatus(), "", "Addon alert badge should be gone");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
addons = PanelUI.addonNotificationContainer;
is(addons.children.length, 0, "Update menu entries should be gone");
await PanelUI.hide();
await gCUITestUtils.hideMainMenu();
// Re-check for an update
updatePromise = promiseInstallEvent(addon, "onDownloadEnded");
@ -136,7 +136,7 @@ async function backgroundUpdateTest(url, id, checkIconFn) {
is(getBadgeStatus(), "addon-alert", "Should have addon alert badge");
// Find the menu entry for the update
await PanelUI.show();
await gCUITestUtils.openMainMenu();
addons = PanelUI.addonNotificationContainer;
is(addons.children.length, 1, "Have a menu entry for the update");

Просмотреть файл

@ -61,10 +61,10 @@ async function testNoPrompt(origUrl, id) {
// There should be no notifications about the update
is(getBadgeStatus(), "", "Should not have addon alert badge");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
let addons = PanelUI.addonNotificationContainer;
is(addons.children.length, 0, "Have 0 updates in the PanelUI menu");
await PanelUI.hide();
await gCUITestUtils.hideMainMenu();
ok(!sawPopup, "Should not have seen permissions notification");

Просмотреть файл

@ -8,6 +8,8 @@ XPCOMUtils.defineLazyGetter(this, "Management", () => {
return Management;
});
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
let gCUITestUtils = new CustomizableUITestUtils(window);
/**
* Wait for the given PopupNotification to display

Просмотреть файл

@ -194,36 +194,24 @@ const PanelUI = {
*/
show(aEvent) {
this._ensureShortcutsShown();
return new Promise(resolve => {
this.ensureReady().then(() => {
if (this.panel.state == "open" ||
document.documentElement.hasAttribute("customizing")) {
resolve();
return;
}
(async () => {
await this.ensureReady();
let anchor;
let domEvent = null;
if (!aEvent ||
aEvent.type == "command") {
anchor = this.menuButton;
} else {
domEvent = aEvent;
anchor = aEvent.target;
}
if (this.panel.state == "open" ||
document.documentElement.hasAttribute("customizing")) {
return;
}
this.panel.addEventListener("popupshown", function() {
resolve();
}, {once: true});
let domEvent = null;
if (aEvent && aEvent.type != "command") {
domEvent = aEvent;
}
anchor = this._getPanelAnchor(anchor);
PanelMultiView.openPopup(this.panel, anchor, {
triggerEvent: domEvent,
}).catch(Cu.reportError);
}, (reason) => {
console.error("Error showing the PanelUI menu", reason);
let anchor = this._getPanelAnchor(this.menuButton);
await PanelMultiView.openPopup(this.panel, anchor, {
triggerEvent: domEvent,
});
});
})().catch(Cu.reportError);
},
/**

Просмотреть файл

@ -10,6 +10,10 @@ DIRS += [
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
TESTING_JS_MODULES += [
'test/CustomizableUITestUtils.jsm',
]
EXTRA_JS_MODULES += [
'CustomizableUI.jsm',
'CustomizableWidgets.jsm',

Просмотреть файл

@ -0,0 +1,86 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Shared functions generally available for tests involving PanelMultiView and
* the CustomizableUI elements in the browser window.
*/
var EXPORTED_SYMBOLS = ["CustomizableUITestUtils"];
ChromeUtils.import("resource://testing-common/Assert.jsm");
ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
class CustomizableUITestUtils {
/**
* Constructs an instance that operates with the specified browser window.
*/
constructor(window) {
this.window = window;
this.document = window.document;
this.PanelUI = window.PanelUI;
}
/**
* Opens a closed PanelMultiView via the specified function while waiting for
* the main view with the specified ID to become fully interactive.
*/
async openPanelMultiView(panel, mainView, openFn) {
if (panel.state == "open") {
// Some tests may intermittently leave the panel open. We report this, but
// don't fail so we don't introduce new intermittent test failures.
Assert.ok(true, "A previous test left the panel open. This should be" +
" fixed, but we can still do a best-effort recovery and" +
" assume that the requested view will be made visible.");
await openFn();
return;
}
if (panel.state == "hiding") {
// There may still be tests that don't wait after invoking a command that
// causes the main menu panel to close. Depending on timing, the panel may
// or may not be fully closed when the following test runs. We handle this
// case gracefully so we don't risk introducing new intermittent test
// failures that may show up at a later time.
Assert.ok(true, "A previous test requested the panel to close but" +
" didn't wait for the operation to complete. While" +
" the test should be fixed, we can still continue.");
} else {
Assert.equal(panel.state, "closed", "The panel is closed to begin with.");
}
let promiseShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
await openFn();
await promiseShown;
}
/**
* Closes an open PanelMultiView via the specified function while waiting for
* the operation to complete.
*/
async hidePanelMultiView(panel, closeFn) {
Assert.ok(panel.state == "open", "The panel is open to begin with.");
let promiseHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
await closeFn();
await promiseHidden;
}
/**
* Opens the main menu and waits for it to become fully interactive.
*/
async openMainMenu() {
await this.openPanelMultiView(this.PanelUI.panel, this.PanelUI.mainView,
() => this.PanelUI.show());
}
/**
* Closes the main menu and waits for the operation to complete.
*/
async hideMainMenu() {
await this.hidePanelMultiView(this.PanelUI.panel,
() => this.PanelUI.hide());
}
}

Просмотреть файл

@ -29,13 +29,15 @@ add_task(async function() {
// test paste button by pasting text to URL bar
gURLBar.focus();
await PanelUI.show();
await gCUITestUtils.openMainMenu();
info("Menu panel was opened");
ok(!pasteButton.hasAttribute("disabled"), "Paste button is enabled");
pasteButton.click();
is(gURLBar.value, text, "Text pasted successfully");
await gCUITestUtils.hideMainMenu();
});
});

Просмотреть файл

@ -33,7 +33,7 @@ add_task(async function() {
newTab = gBrowser.selectedTab;
await promiseTabLoadEvent(newTab, TEST_PAGE);
await PanelUI.show();
await gCUITestUtils.openMainMenu();
await waitForCondition(() => !feedButton.hasAttribute("disabled"));
ok(!feedButton.hasAttribute("disabled"), "The Subscribe button gets enabled");

Просмотреть файл

@ -52,10 +52,8 @@ add_task(async function test_init() {
});
// Open and close the panel first so that it is fully initialized.
await PanelUI.show();
let hiddenPromise = promisePanelHidden(window);
PanelUI.hide();
await hiddenPromise;
await gCUITestUtils.openMainMenu();
await gCUITestUtils.hideMainMenu();
});
// Test updating when the panel is open with the edit-controls on the panel.
@ -64,7 +62,7 @@ add_task(async function test_panelui_opened() {
gURLBar.focus();
gURLBar.value = "test";
await PanelUI.show();
await gCUITestUtils.openMainMenu();
checkState(false, "Update when edit-controls is on panel and visible");
@ -75,9 +73,7 @@ add_task(async function test_panelui_opened() {
checkState(true, "Update when edit-controls is on panel and selection changed");
overridePromise = expectCommandUpdate(0);
let hiddenPromise = promisePanelHidden(window);
PanelUI.hide();
await hiddenPromise;
await gCUITestUtils.hideMainMenu();
await overridePromise;
// Check that updates do not occur after the panel has been closed.

Просмотреть файл

@ -8,7 +8,7 @@
* also while the view is displayed in the main menu.
*/
add_task(async function test_library_after_appMenu() {
await PanelUI.show();
await gCUITestUtils.openMainMenu();
// Show the Library view as a subview of the main menu.
let libraryView = document.getElementById("appMenu-libraryView");

Просмотреть файл

@ -73,16 +73,16 @@ add_task(async function testSecondaryActionWorkflow() {
is(PanelUI.menuButton.getAttribute("badge-status"), "update-manual", "Badge is displaying on PanelUI button.");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
isnot(PanelUI.menuButton.getAttribute("badge-status"), "update-manual", "Badge is hidden on PanelUI button.");
let menuItem = PanelUI.mainView.querySelector(".panel-banner-item");
is(menuItem.label, menuItem.getAttribute("label-update-manual"), "Showing correct label");
is(menuItem.hidden, false, "update-manual menu item is showing.");
await PanelUI.hide();
await gCUITestUtils.hideMainMenu();
is(PanelUI.menuButton.getAttribute("badge-status"), "update-manual", "Badge is shown on PanelUI button.");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
menuItem.click();
ok(mainActionCalled, "Main action callback was called");
@ -124,7 +124,7 @@ add_task(async function testInteractionWithBadges() {
is(PanelUI.menuButton.getAttribute("badge-status"), "update-manual", "Badge is displaying on PanelUI button.");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
isnot(PanelUI.menuButton.getAttribute("badge-status"), "update-manual", "Badge is hidden on PanelUI button.");
let menuItem = PanelUI.mainView.querySelector(".panel-banner-item");
is(menuItem.label, menuItem.getAttribute("label-update-manual"), "Showing correct label");
@ -198,9 +198,9 @@ add_task(async function testMultipleBadges() {
AppMenuNotifications.removeNotification(/^fxa-/);
is(menuButton.hasAttribute("badge-status"), false, "Should not have a badge status");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
is(menuButton.hasAttribute("badge-status"), false, "Should not have a badge status (Hamburger menu opened)");
PanelUI.hide();
await gCUITestUtils.hideMainMenu();
AppMenuNotifications.showBadgeOnlyNotification("fxa-needs-authentication");
AppMenuNotifications.showBadgeOnlyNotification("update-succeeded");
@ -252,7 +252,7 @@ add_task(async function testMultipleNonBadges() {
is(PanelUI.notificationPanel.state, "closed", "update-manual doorhanger is closed.");
is(PanelUI.menuButton.getAttribute("badge-status"), "update-restart", "update-restart badge is displaying on PanelUI button.");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
isnot(PanelUI.menuButton.getAttribute("badge-status"), "update-restart", "update-restart badge is hidden on PanelUI button.");
let menuItem = PanelUI.mainView.querySelector(".panel-banner-item");
is(menuItem.label, menuItem.getAttribute("label-update-restart"), "Showing correct label");
@ -264,7 +264,7 @@ add_task(async function testMultipleNonBadges() {
is(PanelUI.notificationPanel.state, "closed", "update-manual doorhanger is closed.");
is(PanelUI.menuButton.getAttribute("badge-status"), "update-manual", "update-manual badge is displaying on PanelUI button.");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
isnot(PanelUI.menuButton.getAttribute("badge-status"), "update-manual", "update-manual badge is hidden on PanelUI button.");
is(menuItem.label, menuItem.getAttribute("label-update-manual"), "Showing correct label");
is(menuItem.hidden, false, "update-manual menu item is showing.");

Просмотреть файл

@ -8,9 +8,7 @@ const {PanelView} = ChromeUtils.import("resource:///modules/PanelMultiView.jsm",
const kHelpButtonId = "appMenu-help-button";
add_task(async function testUpDownKeys() {
let promise = promisePanelShown(window);
PanelUI.show();
await promise;
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
@ -35,15 +33,11 @@ add_task(async function testUpDownKeys() {
"The first button should be focused after navigating upward");
}
promise = promisePanelHidden(window);
PanelUI.hide();
await promise;
await gCUITestUtils.hideMainMenu();
});
add_task(async function testEnterKeyBehaviors() {
let promise = promisePanelShown(window);
PanelUI.show();
await promise;
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
@ -53,7 +47,7 @@ add_task(async function testEnterKeyBehaviors() {
Assert.equal(focusedElement, buttons[buttons.length - 1],
"The last button should be focused after navigating upward");
promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown");
let promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown");
// Make sure the Help button is in focus.
while (!focusedElement || !focusedElement.id || focusedElement.id != kHelpButtonId) {
EventUtils.synthesizeKey("KEY_ArrowUp");
@ -98,9 +92,8 @@ add_task(async function testEnterKeyBehaviors() {
null : BrowserTestUtils.waitForEvent(gBrowser.selectedTab, "TabFindInitialized");
Assert.equal(focusedElement.id, kFindButtonId, "Find button should be selected");
promise = promisePanelHidden(window);
EventUtils.synthesizeKey("KEY_Enter");
await promise;
await gCUITestUtils.hidePanelMultiView(PanelUI.panel,
() => EventUtils.synthesizeKey("KEY_Enter"));
await findBarPromise;
Assert.ok(!gFindBar.hidden, "Findbar should have opened");
@ -108,9 +101,7 @@ add_task(async function testEnterKeyBehaviors() {
});
add_task(async function testLeftRightKeys() {
let promise = promisePanelShown(window);
PanelUI.show();
await promise;
await gCUITestUtils.openMainMenu();
// Navigate to the 'Help' button, which points to a subview.
let focusedElement = document.commandDispatcher.focusedElement;
@ -122,7 +113,7 @@ add_task(async function testLeftRightKeys() {
// Hitting ArrowRight on a button that points to a subview should navigate us
// there.
promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown");
let promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown");
EventUtils.synthesizeKey("KEY_ArrowRight");
await promise;
@ -135,15 +126,11 @@ add_task(async function testLeftRightKeys() {
Assert.equal(focusedElement.id, kHelpButtonId,
"Help button should be focused again now that we're back in the main view");
promise = promisePanelHidden(window);
PanelUI.hide();
await promise;
await gCUITestUtils.hideMainMenu();
});
add_task(async function testTabKey() {
let promise = promisePanelShown(window);
PanelUI.show();
await promise;
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
@ -172,15 +159,11 @@ add_task(async function testTabKey() {
Assert.equal(document.commandDispatcher.focusedElement, buttons[buttons.length - 1],
"Pressing shift + tab should cycle around and select the last button again");
promise = promisePanelHidden(window);
PanelUI.hide();
await promise;
await gCUITestUtils.hideMainMenu();
});
add_task(async function testInterleavedTabAndArrowKeys() {
let promise = promisePanelShown(window);
PanelUI.show();
await promise;
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
let tab = false;
@ -199,15 +182,11 @@ add_task(async function testInterleavedTabAndArrowKeys() {
Assert.equal(document.commandDispatcher.focusedElement, buttons[buttons.length - 1],
"The last button should be focused after a mix of Tab and ArrowDown");
promise = promisePanelHidden(window);
PanelUI.hide();
await promise;
await gCUITestUtils.hideMainMenu();
});
add_task(async function testSpaceDownAfterTabNavigation() {
let promise = promisePanelShown(window);
PanelUI.show();
await promise;
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements();
let button;
@ -226,11 +205,9 @@ add_task(async function testSpaceDownAfterTabNavigation() {
// Pressing down space on a button that points to a subview should navigate us
// there, before keyup.
promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown");
let promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown");
EventUtils.synthesizeKey(" ", {type: "keydown"});
await promise;
promise = promisePanelHidden(window);
PanelUI.hide();
await promise;
await gCUITestUtils.hideMainMenu();
});

Просмотреть файл

@ -10,16 +10,12 @@
// Show and hide the menu panel programmatically without an event (like UITour.jsm would)
add_task(async function() {
let shownPromise = promisePanelShown(window);
PanelUI.show();
await shownPromise;
await gCUITestUtils.openMainMenu();
is(PanelUI.panel.getAttribute("panelopen"), "true", "Check that panel has panelopen attribute");
is(PanelUI.panel.state, "open", "Check that panel state is 'open'");
let hiddenPromise = promisePanelHidden(window);
PanelUI.hide();
await hiddenPromise;
await gCUITestUtils.hideMainMenu();
ok(!PanelUI.panel.hasAttribute("panelopen"), "Check that panel doesn't have the panelopen attribute");
is(PanelUI.panel.state, "closed", "Check that panel state is 'closed'");
@ -27,16 +23,14 @@ add_task(async function() {
// Toggle the menu panel open and closed
add_task(async function() {
let shownPromise = promisePanelShown(window);
PanelUI.toggle({type: "command"});
await shownPromise;
await gCUITestUtils.openPanelMultiView(PanelUI.panel, PanelUI.mainView,
() => PanelUI.toggle({type: "command"}));
is(PanelUI.panel.getAttribute("panelopen"), "true", "Check that panel has panelopen attribute");
is(PanelUI.panel.state, "open", "Check that panel state is 'open'");
let hiddenPromise = promisePanelHidden(window);
PanelUI.toggle({type: "command"});
await hiddenPromise;
await gCUITestUtils.hidePanelMultiView(PanelUI.panel,
() => PanelUI.toggle({type: "command"}));
ok(!PanelUI.panel.hasAttribute("panelopen"), "Check that panel doesn't have the panelopen attribute");
is(PanelUI.panel.state, "closed", "Check that panel state is 'closed'");

Просмотреть файл

@ -9,11 +9,17 @@ var tmp = {};
ChromeUtils.import("resource://gre/modules/Promise.jsm", tmp);
ChromeUtils.import("resource:///modules/CustomizableUI.jsm", tmp);
ChromeUtils.import("resource://gre/modules/AppConstants.jsm", tmp);
var {Promise, CustomizableUI, AppConstants} = tmp;
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", tmp);
var {Promise, CustomizableUI, AppConstants, CustomizableUITestUtils} = tmp;
var EventUtils = {};
Services.scriptloader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
/**
* Instance of CustomizableUITestUtils for the current browser window.
*/
var gCUITestUtils = new CustomizableUITestUtils(window);
Services.prefs.setBoolPref("browser.uiCustomization.skipSourceNodeCheck", true);
registerCleanupFunction(() => Services.prefs.clearUserPref("browser.uiCustomization.skipSourceNodeCheck"));
@ -254,11 +260,6 @@ function promiseWindowClosed(win) {
});
}
function promisePanelShown(win) {
let panelEl = win.PanelUI.panel;
return promisePanelElementShown(win, panelEl);
}
function promiseOverflowShown(win) {
let panelEl = win.document.getElementById("widget-overflow");
return promisePanelElementShown(win, panelEl);
@ -278,11 +279,6 @@ function promisePanelElementShown(win, aPanel) {
});
}
function promisePanelHidden(win) {
let panelEl = win.PanelUI.panel;
return promisePanelElementHidden(win, panelEl);
}
function promiseOverflowHidden(win) {
let panelEl = win.PanelUI.overflowPanel;
return promisePanelElementHidden(win, panelEl);

Просмотреть файл

@ -3,6 +3,9 @@
"use strict";
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
let gCUITestUtils = new CustomizableUITestUtils(window);
const TEST_URL = "https://www.example.com/";
/**
@ -15,13 +18,10 @@ add_task(async function test_panelview_bookmarks_delete() {
title: TEST_URL,
});
let mainView = document.getElementById("appMenu-mainView");
let promise = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
PanelUI.show();
await promise;
await gCUITestUtils.openMainMenu();
let libraryView = document.getElementById("appMenu-libraryView");
promise = BrowserTestUtils.waitForEvent(libraryView, "ViewShown");
let promise = BrowserTestUtils.waitForEvent(libraryView, "ViewShown");
document.getElementById("appMenu-library-button").click();
await promise;
@ -55,7 +55,5 @@ add_task(async function test_panelview_bookmarks_delete() {
EventUtils.synthesizeMouseAtCenter(placesContextDelete, {});
await promise;
promise = BrowserTestUtils.waitForEvent(PanelUI.panel, "popuphidden");
PanelUI.hide();
await promise;
await gCUITestUtils.hideMainMenu();
});

Просмотреть файл

@ -1,6 +1,9 @@
// Tests that the suggestion popup appears at the right times in response to
// focus and user events (mouse, keyboard, drop).
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
let gCUITestUtils = new CustomizableUITestUtils(window);
// Instead of loading EventUtils.js into the test scope in browser-test.js for all tests,
// we only need EventUtils.js for a few files which is why we are using loadSubScript.
var EventUtils = {};
@ -570,7 +573,7 @@ add_task(async function dont_open_in_customization() {
sawPopup = true;
}
searchPopup.addEventListener("popupshowing", listener);
await PanelUI.show();
await gCUITestUtils.openMainMenu();
promise = promiseEvent(searchPopup, "popuphidden");
await startCustomizing();
await promise;

Просмотреть файл

@ -1,5 +1,8 @@
"use strict";
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
let gCUITestUtils = new CustomizableUITestUtils(window);
var gTestTab;
var gContentAPI;
var gContentWindow;
@ -135,7 +138,7 @@ add_UITour_task(async function test_info_target_callback() {
await showInfoPromise("appMenu", "I want to know when the target is clicked", "*click*", null, null, "makeInfoOptions");
await PanelUI.show();
await gCUITestUtils.openMainMenu();
let returnValue = await waitForCallbackResultPromise();

Просмотреть файл

@ -142,7 +142,6 @@ menuitem.bookmark-item {
opacity: 0.7;
}
%include ../shared/bookmarked-notification.inc.css
%include ../shared/toolbarbuttons.inc.css
%include ../shared/toolbarbutton-icons.inc.css
%include ../shared/menupanel.inc.css

Просмотреть файл

@ -218,8 +218,6 @@
}
}
%include ../shared/bookmarked-notification.inc.css
%include ../shared/toolbarbuttons.inc.css
%include ../shared/toolbarbutton-icons.inc.css
%include ../shared/menupanel.inc.css

Просмотреть файл

@ -1,64 +0,0 @@
/* ----- BOOKMARK STAR ANIMATION ----- */
@keyframes animation-bookmarkAdded {
from { transform: rotate(0deg) translateX(-16px) rotate(0deg) scale(1); opacity: 0; }
60% { transform: rotate(180deg) translateX(-16px) rotate(-180deg) scale(2.2); opacity: 1; }
80% { opacity: 1; }
to { transform: rotate(180deg) translateX(-16px) rotate(-180deg) scale(1); opacity: 0; }
}
@keyframes animation-bookmarkPulse {
from { transform: scale(1); }
50% { transform: scale(1.3); }
to { transform: scale(1); }
}
#bookmarked-notification-container {
min-height: 1px;
min-width: 1px;
height: 1px;
margin-bottom: -1px;
z-index: 5;
position: relative;
}
#bookmarked-notification {
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
width: 16px;
height: 16px;
opacity: 0;
}
#bookmarked-notification-dropmarker-anchor {
z-index: -1;
position: relative;
}
#bookmarked-notification-dropmarker-icon {
-moz-context-properties: fill;
width: 18px;
height: 18px;
visibility: hidden;
}
#bookmarked-notification-anchor[notification="finish"] > #bookmarked-notification {
background-image: url("chrome://browser/skin/places/bookmarks-notification-finish.png");
animation: animation-bookmarkAdded 800ms;
animation-timing-function: ease, ease, ease;
}
@media (min-resolution: 2dppx) {
#bookmarked-notification-anchor[notification="finish"] > #bookmarked-notification {
background-image: url("chrome://browser/skin/places/bookmarks-notification-finish@2x.png");
}
}
#bookmarked-notification-dropmarker-anchor[notification="finish"] > #bookmarked-notification-dropmarker-icon {
visibility: visible;
animation: animation-bookmarkPulse 300ms;
animation-delay: 600ms;
animation-timing-function: ease-out;
}

Просмотреть файл

@ -216,8 +216,6 @@
skin/classic/browser/panic-panel/header@2x.png (../shared/panic-panel/header@2x.png)
skin/classic/browser/panic-panel/icons.png (../shared/panic-panel/icons.png)
skin/classic/browser/panic-panel/icons@2x.png (../shared/panic-panel/icons@2x.png)
skin/classic/browser/places/bookmarks-notification-finish.png (../shared/places/bookmarks-notification-finish.png)
skin/classic/browser/places/bookmarks-notification-finish@2x.png (../shared/places/bookmarks-notification-finish@2x.png)
skin/classic/browser/places/bookmarksMenu.svg (../shared/places/bookmarksMenu.svg)
skin/classic/browser/places/bookmarksToolbar.svg (../shared/places/bookmarksToolbar.svg)
skin/classic/browser/places/folder.svg (../shared/places/folder.svg)

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.3 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 8.4 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 602 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 902 B

Двоичные данные
browser/themes/shared/privatebrowsing/check.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 338 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 370 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 6.7 KiB

Просмотреть файл

@ -374,7 +374,6 @@ menuitem.bookmark-item {
}
%include ../shared/bookmarked-notification.inc.css
%include ../shared/toolbarbuttons.inc.css
%include ../shared/toolbarbutton-icons.inc.css
%include ../shared/menupanel.inc.css

Просмотреть файл

@ -59,7 +59,7 @@ async function reopenAppMenu(browserWindow) {
browserWindow.PanelUI.hide();
let view = browserWindow.document.getElementById("appMenu-mainView");
let promiseViewShown = BrowserTestUtils.waitForEvent(view, "ViewShown");
await browserWindow.PanelUI.show();
browserWindow.PanelUI.show();
await promiseViewShown;
}

Просмотреть файл

@ -83,6 +83,7 @@
#include "mozilla/dom/ServiceWorkerManager.h"
#include "imgLoader.h"
#include "nsAboutProtocolUtils.h"
#include "nsCanvasFrame.h"
#include "nsContentCID.h"
#include "nsError.h"
@ -5313,9 +5314,100 @@ nsIDocument::DispatchContentLoadedEvents()
UnblockOnload(true);
}
#if defined(DEBUG) && !defined(ANDROID)
// We want to get to a point where all about: pages ship with a CSP. This
// assertion ensures that we can not deploy new about: pages without a CSP.
// Initially we will whitelist legacy about: pages which not yet have a CSP
// attached, but ultimately that whitelist should disappear.
// Please note that any about: page should not use inline JS or inline CSS,
// and instead should load JS and CSS from an external file (*.js, *.css)
// which allows us to apply a strong CSP omitting 'unsafe-inline'. Ideally,
// the CSP allows precisely the resources that need to be loaded; but it
// should at least be as strong as:
// <meta http-equiv="Content-Security-Policy" content="default-src chrome:"/>
static void
AssertContentPrivilegedAboutPageHasCSP(nsIURI* aDocumentURI, nsIPrincipal* aPrincipal)
{
// Curently we can't serialize the CSP, hence we only assert if
// running in the content process.
if (!XRE_IsContentProcess()) {
return;
}
// Check if we are loading an about: URI at all
bool isAboutURI =
(NS_SUCCEEDED(aDocumentURI->SchemeIs("about", &isAboutURI)) && isAboutURI);
if (!isAboutURI) {
return;
}
// Check if we are loading a content-privileged about: URI
nsCOMPtr<nsIAboutModule> aboutModule;
nsresult rv = NS_GetAboutModule(aDocumentURI, getter_AddRefs(aboutModule));
NS_ENSURE_SUCCESS_VOID(rv);
uint32_t aboutModuleFlags = 0;
rv = aboutModule->GetURIFlags(aDocumentURI, &aboutModuleFlags);
NS_ENSURE_SUCCESS_VOID(rv);
if (!(aboutModuleFlags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT)) {
return;
}
// Potentially init the legacy whitelist of about URIs without a CSP.
static StaticAutoPtr<nsTArray<nsCString>> sLegacyAboutPagesWithNoCSP;
if (!sLegacyAboutPagesWithNoCSP) {
sLegacyAboutPagesWithNoCSP = new nsTArray<nsCString>();
nsAutoCString legacyAboutPages;
Preferences::GetCString("csp.content_privileged_about_uris_without_csp",
legacyAboutPages);
for (const nsACString& hostString : legacyAboutPages.Split(',')) {
// please note that for the actual whitelist we only store the path of
// about: URI. Let's reassemble the full about URI here so we don't
// have to remove query arguments later.
nsCString aboutURI;
aboutURI.AppendLiteral("about:");
aboutURI.Append(hostString);
sLegacyAboutPagesWithNoCSP->AppendElement(aboutURI);
}
ClearOnShutdown(&sLegacyAboutPagesWithNoCSP);
}
// Check if the about URI is whitelisted
nsAutoCString aboutSpec;
aDocumentURI->GetSpec(aboutSpec);
for (auto& legacyPageEntry : *sLegacyAboutPagesWithNoCSP) {
// please note that we perform a substring match here on purpose,
// so we don't have to deal and parse out all the query arguments
// the various about pages rely on.
if (aboutSpec.Find(legacyPageEntry) == 0) {
return;
}
}
nsCOMPtr<nsIContentSecurityPolicy> csp;
aPrincipal->GetCsp(getter_AddRefs(csp));
nsAutoString parsedPolicyStr;
if (csp) {
uint32_t policyCount = 0;
csp->GetPolicyCount(&policyCount);
if (policyCount > 0) {
csp->GetPolicyString(0, parsedPolicyStr);
}
}
MOZ_ASSERT(parsedPolicyStr.Find("default-src") >= 0,
"about: page must contain a CSP including default-src");
}
#endif
void
nsDocument::EndLoad()
{
#if defined(DEBUG) && !defined(ANDROID)
AssertContentPrivilegedAboutPageHasCSP(mDocumentURI, NodePrincipal());
#endif
// EndLoad may have been called without a matching call to BeginLoad, in the
// case of a failed parse (for example, due to timeout). In such a case, we
// still want to execute part of this code to do appropriate cleanup, but we

Просмотреть файл

@ -179,7 +179,12 @@ WebRenderImageHost::GetAsTextureHostForComposite()
}
SetCurrentTextureHost(img->mTextureHost);
// XXX Add UpdateBias()
mBias = UpdateBias(
mWrBridge->AsyncImageManager()->GetCompositionTime(),
mImages[imageIndex].mTimeStamp,
uint32_t(imageIndex + 1) < mImages.Length() ?
mImages[imageIndex + 1].mTimeStamp : TimeStamp(),
mBias);
return mCurrentTextureHost;
}

Просмотреть файл

@ -2,7 +2,7 @@ This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
Our reference repository is https://github.com/khaledhosny/ots/.
Current revision: f7238234966c466c5e3d11ee822e9760be0c527a (6.1.1)
Current revision: 63ff19f4a887cca099d2e4b3b1b7d6a9a131233b (6.1.1)
Upstream files included: LICENSE, src/, include/, tests/*.cc

109
gfx/ots/src/avar.cc Normal file
Просмотреть файл

@ -0,0 +1,109 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "avar.h"
#include "fvar.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeAVAR
// -----------------------------------------------------------------------------
bool OpenTypeAVAR::Parse(const uint8_t* data, size_t length) {
Buffer table(data, length);
if (!table.ReadU16(&this->majorVersion) ||
!table.ReadU16(&this->minorVersion) ||
!table.ReadU16(&this->reserved) ||
!table.ReadU16(&this->axisCount)) {
return Drop("Failed to read table header");
}
if (this->majorVersion != 1) {
return Drop("Unknown table version");
}
if (this->minorVersion > 0) {
// we only know how to serialize version 1.0
Warning("Downgrading minor version to 0");
this->minorVersion = 0;
}
if (this->reserved != 0) {
Warning("Expected reserved=0");
this->reserved = 0;
}
OpenTypeFVAR* fvar = static_cast<OpenTypeFVAR*>(
GetFont()->GetTypedTable(OTS_TAG_FVAR));
if (!fvar) {
return DropVariations("Required fvar table is missing");
}
if (axisCount != fvar->AxisCount()) {
return Drop("Axis count mismatch");
}
for (size_t i = 0; i < this->axisCount; i++) {
this->axisSegmentMaps.emplace_back();
uint16_t positionMapCount;
if (!table.ReadU16(&positionMapCount)) {
return Drop("Failed to read position map count");
}
int foundRequiredMappings = 0;
for (size_t j = 0; j < positionMapCount; j++) {
AxisValueMap map;
if (!table.ReadS16(&map.fromCoordinate) ||
!table.ReadS16(&map.toCoordinate)) {
return Drop("Failed to read axis value map");
}
if (map.fromCoordinate < -0x4000 ||
map.fromCoordinate > 0x4000 ||
map.toCoordinate < -0x4000 ||
map.toCoordinate > 0x4000) {
return Drop("Axis value map coordinate out of range");
}
if (j > 0) {
if (map.fromCoordinate <= this->axisSegmentMaps[i].back().fromCoordinate ||
map.toCoordinate < this->axisSegmentMaps[i].back().toCoordinate) {
return Drop("Axis value map out of order");
}
}
if ((map.fromCoordinate == -0x4000 && map.toCoordinate == -0x4000) ||
(map.fromCoordinate == 0 && map.toCoordinate == 0) ||
(map.fromCoordinate == 0x4000 && map.toCoordinate == 0x4000)) {
++foundRequiredMappings;
}
this->axisSegmentMaps[i].push_back(map);
}
if (positionMapCount > 0 && foundRequiredMappings != 3) {
return Drop("A required mapping (for -1, 0 or 1) is missing");
}
}
return true;
}
bool OpenTypeAVAR::Serialize(OTSStream* out) {
if (!out->WriteU16(this->majorVersion) ||
!out->WriteU16(this->minorVersion) ||
!out->WriteU16(this->reserved) ||
!out->WriteU16(this->axisCount)) {
return Error("Failed to write table");
}
for (size_t i = 0; i < this->axisCount; i++) {
const auto& axisValueMap = this->axisSegmentMaps[i];
if (!out->WriteU16(axisValueMap.size())) {
return Error("Failed to write table");
}
for (size_t j = 0; j < axisValueMap.size(); j++) {
if (!out->WriteS16(axisValueMap[j].fromCoordinate) ||
!out->WriteS16(axisValueMap[j].toCoordinate)) {
return Error("Failed to write table");
}
}
}
return true;
}
} // namespace ots

42
gfx/ots/src/avar.h Normal file
Просмотреть файл

@ -0,0 +1,42 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_AVAR_H_
#define OTS_AVAR_H_
#include "ots.h"
#include <vector>
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeAVAR Interface
// -----------------------------------------------------------------------------
class OpenTypeAVAR : public Table {
public:
explicit OpenTypeAVAR(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
uint16_t majorVersion;
uint16_t minorVersion;
uint16_t reserved;
uint16_t axisCount;
struct AxisValueMap {
int16_t fromCoordinate;
int16_t toCoordinate;
};
std::vector<std::vector<AxisValueMap>> axisSegmentMaps;
};
} // namespace ots
#endif // OTS_AVAR_H_

56
gfx/ots/src/cvar.cc Normal file
Просмотреть файл

@ -0,0 +1,56 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cvar.h"
#include "fvar.h"
#include "variations.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeCVAR
// -----------------------------------------------------------------------------
bool OpenTypeCVAR::Parse(const uint8_t* data, size_t length) {
Buffer table(data, length);
uint16_t majorVersion;
uint16_t minorVersion;
if (!table.ReadU16(&majorVersion) ||
!table.ReadU16(&minorVersion)) {
return Drop("Failed to read table header");
}
if (majorVersion != 1) {
return Drop("Unknown table version");
}
OpenTypeFVAR* fvar = static_cast<OpenTypeFVAR*>(
GetFont()->GetTypedTable(OTS_TAG_FVAR));
if (!fvar) {
return DropVariations("Required fvar table is missing");
}
if (!ParseVariationData(GetFont(), data + table.offset(), length - table.offset(),
fvar->AxisCount(), 0)) {
return Drop("Failed to parse variation data");
}
this->m_data = data;
this->m_length = length;
return true;
}
bool OpenTypeCVAR::Serialize(OTSStream* out) {
if (!out->Write(this->m_data, this->m_length)) {
return Error("Failed to write cvar table");
}
return true;
}
} // namespace ots

31
gfx/ots/src/cvar.h Normal file
Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_CVAR_H_
#define OTS_CVAR_H_
#include "ots.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeCVAR Interface
// -----------------------------------------------------------------------------
class OpenTypeCVAR : public Table {
public:
explicit OpenTypeCVAR(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
const uint8_t *m_data;
size_t m_length;
};
} // namespace ots
#endif // OTS_CVAR_H_

164
gfx/ots/src/fvar.cc Normal file
Просмотреть файл

@ -0,0 +1,164 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fvar.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeFVAR
// -----------------------------------------------------------------------------
bool OpenTypeFVAR::Parse(const uint8_t* data, size_t length) {
Buffer table(data, length);
if (!table.ReadU16(&this->majorVersion) ||
!table.ReadU16(&this->minorVersion) ||
!table.ReadU16(&this->axesArrayOffset) ||
!table.ReadU16(&this->reserved) ||
!table.ReadU16(&this->axisCount) ||
!table.ReadU16(&this->axisSize) ||
!table.ReadU16(&this->instanceCount) ||
!table.ReadU16(&this->instanceSize)) {
return DropVariations("Failed to read table header");
}
if (this->majorVersion != 1) {
return DropVariations("Unknown table version");
}
if (this->minorVersion > 0) {
Warning("Downgrading minor version to 0");
this->minorVersion = 0;
}
if (this->axesArrayOffset > length || this->axesArrayOffset < table.offset()) {
return DropVariations("Bad axesArrayOffset");
}
if (this->reserved != 2) {
Warning("Expected reserved=2");
this->reserved = 2;
}
if (this->axisCount == 0) {
return DropVariations("No variation axes");
}
if (this->axisSize != 20) {
return DropVariations("Invalid axisSize");
}
// instanceCount is not validated
if (this->instanceSize == this->axisCount * sizeof(Fixed) + 6) {
this->instancesHavePostScriptNameID = true;
} else if (this->instanceSize == this->axisCount * sizeof(Fixed) + 4) {
this->instancesHavePostScriptNameID = false;
} else {
return DropVariations("Invalid instanceSize");
}
// When we serialize, the axes array will go here, even if it was
// originally at a different offset. So we update the axesArrayOffset
// field for the header.
uint32_t origAxesArrayOffset = this->axesArrayOffset;
this->axesArrayOffset = table.offset();
table.set_offset(origAxesArrayOffset);
for (unsigned i = 0; i < this->axisCount; i++) {
this->axes.emplace_back();
auto& axis = this->axes[i];
if (!table.ReadU32(&axis.axisTag) ||
!table.ReadS32(&axis.minValue) ||
!table.ReadS32(&axis.defaultValue) ||
!table.ReadS32(&axis.maxValue) ||
!table.ReadU16(&axis.flags) ||
!table.ReadU16(&axis.axisNameID)) {
return DropVariations("Failed to read axis record");
}
if (!CheckTag(axis.axisTag)) {
return DropVariations("Bad axis tag");
}
if (!(axis.minValue <= axis.defaultValue && axis.defaultValue <= axis.maxValue)) {
return DropVariations("Bad axis value range");
}
if ((axis.flags & 0xFFFEu) != 0) {
Warning("Discarding unknown axis flags");
axis.flags &= ~0xFFFEu;
}
if (axis.axisNameID <= 255 || axis.axisNameID >= 32768) {
Warning("Axis nameID out of range");
// We don't check that the name actually exists -- assume the client can handle
// a missing name when it tries to read the table.
}
}
for (unsigned i = 0; i < this->instanceCount; i++) {
this->instances.emplace_back();
auto& inst = this->instances[i];
if (!table.ReadU16(&inst.subfamilyNameID) ||
!table.ReadU16(&inst.flags)) {
return DropVariations("Failed to read instance record");
}
inst.coordinates.reserve(this->axisCount);
for (unsigned j = 0; j < this->axisCount; j++) {
inst.coordinates.emplace_back();
auto& coord = inst.coordinates[j];
if (!table.ReadS32(&coord)) {
return DropVariations("Failed to read instance coordinates");
}
}
if (this->instancesHavePostScriptNameID) {
if (!table.ReadU16(&inst.postScriptNameID)) {
return DropVariations("Failed to read instance psname ID");
}
}
}
if (table.remaining()) {
return Warning("%zu bytes unparsed", table.remaining());
}
return true;
}
bool OpenTypeFVAR::Serialize(OTSStream* out) {
if (!out->WriteU16(this->majorVersion) ||
!out->WriteU16(this->minorVersion) ||
!out->WriteU16(this->axesArrayOffset) ||
!out->WriteU16(this->reserved) ||
!out->WriteU16(this->axisCount) ||
!out->WriteU16(this->axisSize) ||
!out->WriteU16(this->instanceCount) ||
!out->WriteU16(this->instanceSize)) {
return Error("Failed to write table");
}
for (unsigned i = 0; i < this->axisCount; i++) {
const auto& axis = this->axes[i];
if (!out->WriteU32(axis.axisTag) ||
!out->WriteS32(axis.minValue) ||
!out->WriteS32(axis.defaultValue) ||
!out->WriteS32(axis.maxValue) ||
!out->WriteU16(axis.flags) ||
!out->WriteU16(axis.axisNameID)) {
return Error("Failed to write table");
}
}
for (unsigned i = 0; i < this->instanceCount; i++) {
const auto& inst = this->instances[i];
if (!out->WriteU16(inst.subfamilyNameID) ||
!out->WriteU16(inst.flags)) {
return Error("Failed to write table");
}
for (unsigned j = 0; j < this->axisCount; j++) {
const auto& coord = inst.coordinates[j];
if (!out->WriteS32(coord)) {
return Error("Failed to write table");
}
}
if (this->instancesHavePostScriptNameID) {
if (!out->WriteU16(inst.postScriptNameID)) {
return Error("Failed to write table");
}
}
}
return true;
}
} // namespace ots

63
gfx/ots/src/fvar.h Normal file
Просмотреть файл

@ -0,0 +1,63 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_FVAR_H_
#define OTS_FVAR_H_
#include <vector>
#include "ots.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeFVAR Interface
// -----------------------------------------------------------------------------
class OpenTypeFVAR : public Table {
public:
explicit OpenTypeFVAR(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
const uint16_t AxisCount() const { return axisCount; }
private:
uint16_t majorVersion;
uint16_t minorVersion;
uint16_t axesArrayOffset;
uint16_t reserved;
uint16_t axisCount;
uint16_t axisSize;
uint16_t instanceCount;
uint16_t instanceSize;
typedef int32_t Fixed; /* 16.16 fixed-point value */
struct VariationAxisRecord {
uint32_t axisTag;
Fixed minValue;
Fixed defaultValue;
Fixed maxValue;
uint16_t flags;
uint16_t axisNameID;
};
std::vector<VariationAxisRecord> axes;
struct InstanceRecord {
uint16_t subfamilyNameID;
uint16_t flags;
std::vector<Fixed> coordinates;
uint16_t postScriptNameID; // optional
};
std::vector<InstanceRecord> instances;
bool instancesHavePostScriptNameID;
};
} // namespace ots
#endif // OTS_FVAR_H_

Просмотреть файл

@ -30,8 +30,10 @@ enum GPOS_TYPE {
GPOS_TYPE_RESERVED = 10
};
// The size of gpos header.
const unsigned kGposHeaderSize = 10;
// The size of gpos header, version 1.0.
const unsigned kGposHeaderSize_1_0 = 10;
// The size of gpos header, version 1.1.
const unsigned kGposHeaderSize_1_1 = 14;
// The maximum format number for anchor tables.
const uint16_t kMaxAnchorFormat = 3;
// The maximum number of class value.
@ -749,23 +751,34 @@ bool OpenTypeGPOS::Parse(const uint8_t *data, size_t length) {
Font *font = GetFont();
Buffer table(data, length);
uint32_t version = 0;
uint16_t version_major = 0, version_minor = 0;
uint16_t offset_script_list = 0;
uint16_t offset_feature_list = 0;
uint16_t offset_lookup_list = 0;
if (!table.ReadU32(&version) ||
uint32_t offset_feature_variations = 0;
if (!table.ReadU16(&version_major) ||
!table.ReadU16(&version_minor) ||
!table.ReadU16(&offset_script_list) ||
!table.ReadU16(&offset_feature_list) ||
!table.ReadU16(&offset_lookup_list)) {
return Error("Incomplete table");
}
if (version != 0x00010000) {
if (version_major != 1 || version_minor > 1) {
return Error("Bad version");
}
if (version_minor > 0) {
if (!table.ReadU32(&offset_feature_variations)) {
return Error("Incomplete table");
}
}
const size_t header_size =
(version_minor == 0) ? kGposHeaderSize_1_0 : kGposHeaderSize_1_1;
if (offset_lookup_list) {
if (offset_lookup_list < kGposHeaderSize || offset_lookup_list >= length) {
if (offset_lookup_list < header_size || offset_lookup_list >= length) {
return Error("Bad lookup list offset in table header");
}
@ -779,7 +792,7 @@ bool OpenTypeGPOS::Parse(const uint8_t *data, size_t length) {
uint16_t num_features = 0;
if (offset_feature_list) {
if (offset_feature_list < kGposHeaderSize || offset_feature_list >= length) {
if (offset_feature_list < header_size || offset_feature_list >= length) {
return Error("Bad feature list offset in table header");
}
@ -791,7 +804,7 @@ bool OpenTypeGPOS::Parse(const uint8_t *data, size_t length) {
}
if (offset_script_list) {
if (offset_script_list < kGposHeaderSize || offset_script_list >= length) {
if (offset_script_list < header_size || offset_script_list >= length) {
return Error("Bad script list offset in table header");
}
@ -801,6 +814,18 @@ bool OpenTypeGPOS::Parse(const uint8_t *data, size_t length) {
}
}
if (offset_feature_variations) {
if (offset_feature_variations < header_size || offset_feature_variations >= length) {
return Error("Bad feature variations offset in table header");
}
if (!ParseFeatureVariationsTable(font, data + offset_feature_variations,
length - offset_feature_variations,
this->num_lookups)) {
return Error("Failed to parse feature variations table");
}
}
this->m_data = data;
this->m_length = length;
return true;

Просмотреть файл

@ -17,8 +17,10 @@
namespace {
// The GSUB header size
const size_t kGsubHeaderSize = 4 + 3 * 2;
// The GSUB header size for table version 1.0
const size_t kGsubHeaderSize_1_0 = 4 + 3 * 2;
// GSUB header size v1.1
const size_t kGsubHeaderSize_1_1 = 4 + 3 * 2 + 4;
enum GSUB_TYPE {
GSUB_TYPE_SINGLE = 1,
@ -580,23 +582,34 @@ bool OpenTypeGSUB::Parse(const uint8_t *data, size_t length) {
Font *font = GetFont();
Buffer table(data, length);
uint32_t version = 0;
uint16_t version_major = 0, version_minor = 0;
uint16_t offset_script_list = 0;
uint16_t offset_feature_list = 0;
uint16_t offset_lookup_list = 0;
if (!table.ReadU32(&version) ||
uint32_t offset_feature_variations = 0;
if (!table.ReadU16(&version_major) ||
!table.ReadU16(&version_minor) ||
!table.ReadU16(&offset_script_list) ||
!table.ReadU16(&offset_feature_list) ||
!table.ReadU16(&offset_lookup_list)) {
return Error("Incomplete table");
}
if (version != 0x00010000) {
if (version_major != 1 || version_minor > 1) {
return Error("Bad version");
}
if (version_minor > 0) {
if (!table.ReadU32(&offset_feature_variations)) {
return Error("Incomplete table");
}
}
const size_t header_size =
(version_minor == 0) ? kGsubHeaderSize_1_0 : kGsubHeaderSize_1_1;
if (offset_lookup_list) {
if (offset_lookup_list < kGsubHeaderSize || offset_lookup_list >= length) {
if (offset_lookup_list < header_size || offset_lookup_list >= length) {
return Error("Bad lookup list offset in table header");
}
@ -610,7 +623,7 @@ bool OpenTypeGSUB::Parse(const uint8_t *data, size_t length) {
uint16_t num_features = 0;
if (offset_feature_list) {
if (offset_feature_list < kGsubHeaderSize || offset_feature_list >= length) {
if (offset_feature_list < header_size || offset_feature_list >= length) {
return Error("Bad feature list offset in table header");
}
@ -622,7 +635,7 @@ bool OpenTypeGSUB::Parse(const uint8_t *data, size_t length) {
}
if (offset_script_list) {
if (offset_script_list < kGsubHeaderSize || offset_script_list >= length) {
if (offset_script_list < header_size || offset_script_list >= length) {
return Error("Bad script list offset in table header");
}
@ -632,6 +645,18 @@ bool OpenTypeGSUB::Parse(const uint8_t *data, size_t length) {
}
}
if (offset_feature_variations) {
if (offset_feature_variations < header_size || offset_feature_variations >= length) {
return Error("Bad feature variations offset in table header");
}
if (!ParseFeatureVariationsTable(font, data + offset_feature_variations,
length - offset_feature_variations,
this->num_lookups)) {
return Error("Failed to parse feature variations table");
}
}
this->m_data = data;
this->m_length = length;
return true;

156
gfx/ots/src/gvar.cc Normal file
Просмотреть файл

@ -0,0 +1,156 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gvar.h"
#include "fvar.h"
#include "maxp.h"
#include "variations.h"
#define TABLE_NAME "gvar"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeGVAR
// -----------------------------------------------------------------------------
static bool ParseSharedTuples(const Font* font, const uint8_t* data, size_t length,
size_t sharedTupleCount, size_t axisCount) {
Buffer subtable(data, length);
for (unsigned i = 0; i < sharedTupleCount; i++) {
for (unsigned j = 0; j < axisCount; j++) {
int16_t coordinate;
if (!subtable.ReadS16(&coordinate)) {
return OTS_FAILURE_MSG("Failed to read shared tuple coordinate");
}
}
}
return true;
}
static bool ParseGlyphVariationDataArray(const Font* font, const uint8_t* data, size_t length,
uint16_t flags, size_t glyphCount, size_t axisCount,
size_t sharedTupleCount,
const uint8_t* glyphVariationData,
size_t glyphVariationDataLength) {
Buffer subtable(data, length);
bool glyphVariationDataOffsetsAreLong = (flags & 0x0001u);
uint32_t prevOffset = 0;
for (size_t i = 0; i < glyphCount + 1; i++) {
uint32_t offset;
if (glyphVariationDataOffsetsAreLong) {
if (!subtable.ReadU32(&offset)) {
return OTS_FAILURE_MSG("Failed to read GlyphVariationData offset");
}
} else {
uint16_t halfOffset;
if (!subtable.ReadU16(&halfOffset)) {
return OTS_FAILURE_MSG("Failed to read GlyphVariationData offset");
}
offset = halfOffset * 2;
}
if (i > 0 && offset > prevOffset) {
if (prevOffset > glyphVariationDataLength) {
return OTS_FAILURE_MSG("Invalid GlyphVariationData offset");
}
if (!ParseVariationData(font, glyphVariationData + prevOffset,
glyphVariationDataLength - prevOffset,
axisCount, sharedTupleCount)) {
return OTS_FAILURE_MSG("Failed to parse GlyphVariationData");
}
}
prevOffset = offset;
}
return true;
}
bool OpenTypeGVAR::Parse(const uint8_t* data, size_t length) {
Buffer table(data, length);
uint16_t majorVersion;
uint16_t minorVersion;
uint16_t axisCount;
uint16_t sharedTupleCount;
uint32_t sharedTuplesOffset;
uint16_t glyphCount;
uint16_t flags;
uint32_t glyphVariationDataArrayOffset;
if (!table.ReadU16(&majorVersion) ||
!table.ReadU16(&minorVersion) ||
!table.ReadU16(&axisCount) ||
!table.ReadU16(&sharedTupleCount) ||
!table.ReadU32(&sharedTuplesOffset) ||
!table.ReadU16(&glyphCount) ||
!table.ReadU16(&flags) ||
!table.ReadU32(&glyphVariationDataArrayOffset)) {
return DropVariations("Failed to read table header");
}
if (majorVersion != 1) {
return DropVariations("Unknown table version");
}
// check axisCount == fvar->axisCount
OpenTypeFVAR* fvar = static_cast<OpenTypeFVAR*>(
GetFont()->GetTypedTable(OTS_TAG_FVAR));
if (!fvar) {
return DropVariations("Required fvar table is missing");
}
if (axisCount != fvar->AxisCount()) {
return DropVariations("Axis count mismatch");
}
// check glyphCount == maxp->num_glyphs
OpenTypeMAXP* maxp = static_cast<OpenTypeMAXP*>(
GetFont()->GetTypedTable(OTS_TAG_MAXP));
if (!maxp) {
return DropVariations("Required maxp table is missing");
}
if (glyphCount != maxp->num_glyphs) {
return DropVariations("Glyph count mismatch");
}
if (sharedTupleCount > 0) {
if (sharedTuplesOffset < table.offset() || sharedTuplesOffset > length) {
return DropVariations("Invalid sharedTuplesOffset");
}
if (!ParseSharedTuples(GetFont(),
data + sharedTuplesOffset, length - sharedTuplesOffset,
sharedTupleCount, axisCount)) {
return DropVariations("Failed to parse shared tuples");
}
}
if (glyphVariationDataArrayOffset) {
if (glyphVariationDataArrayOffset > length) {
return DropVariations("Invalid glyphVariationDataArrayOffset");
}
if (!ParseGlyphVariationDataArray(GetFont(),
data + table.offset(), length - table.offset(),
flags, glyphCount, axisCount, sharedTupleCount,
data + glyphVariationDataArrayOffset,
length - glyphVariationDataArrayOffset)) {
return DropVariations("Failed to read glyph variation data array");
}
}
this->m_data = data;
this->m_length = length;
return true;
}
bool OpenTypeGVAR::Serialize(OTSStream* out) {
if (!out->Write(this->m_data, this->m_length)) {
return Error("Failed to write gvar table");
}
return true;
}
} // namespace ots

31
gfx/ots/src/gvar.h Normal file
Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_GVAR_H_
#define OTS_GVAR_H_
#include "ots.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeGVAR Interface
// -----------------------------------------------------------------------------
class OpenTypeGVAR : public Table {
public:
explicit OpenTypeGVAR(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
const uint8_t *m_data;
size_t m_length;
};
} // namespace ots
#endif // OTS_GVAR_H_

87
gfx/ots/src/hvar.cc Normal file
Просмотреть файл

@ -0,0 +1,87 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "hvar.h"
#include "variations.h"
#define TABLE_NAME "HVAR"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeHVAR
// -----------------------------------------------------------------------------
bool OpenTypeHVAR::Parse(const uint8_t* data, size_t length) {
Buffer table(data, length);
uint16_t majorVersion;
uint16_t minorVersion;
uint32_t itemVariationStoreOffset;
uint32_t advanceWidthMappingOffset;
uint32_t lsbMappingOffset;
uint32_t rsbMappingOffset;
if (!table.ReadU16(&majorVersion) ||
!table.ReadU16(&minorVersion) ||
!table.ReadU32(&itemVariationStoreOffset) ||
!table.ReadU32(&advanceWidthMappingOffset) ||
!table.ReadU32(&lsbMappingOffset) ||
!table.ReadU32(&rsbMappingOffset)) {
return DropVariations("Failed to read table header");
}
if (majorVersion != 1) {
return DropVariations("Unknown table version");
}
if (itemVariationStoreOffset > length ||
advanceWidthMappingOffset > length ||
lsbMappingOffset > length ||
rsbMappingOffset > length) {
return DropVariations("Invalid subtable offset");
}
if (!ParseItemVariationStore(GetFont(), data + itemVariationStoreOffset,
length - itemVariationStoreOffset)) {
return DropVariations("Failed to parse item variation store");
}
if (advanceWidthMappingOffset) {
if (!ParseDeltaSetIndexMap(GetFont(), data + advanceWidthMappingOffset,
length - advanceWidthMappingOffset)) {
return DropVariations("Failed to parse advance width mappings");
}
}
if (lsbMappingOffset) {
if (!ParseDeltaSetIndexMap(GetFont(), data + lsbMappingOffset,
length - lsbMappingOffset)) {
return DropVariations("Failed to parse LSB mappings");
}
}
if (rsbMappingOffset) {
if (!ParseDeltaSetIndexMap(GetFont(), data + rsbMappingOffset,
length - rsbMappingOffset)) {
return DropVariations("Failed to parse RSB mappings");
}
}
this->m_data = data;
this->m_length = length;
return true;
}
bool OpenTypeHVAR::Serialize(OTSStream* out) {
if (!out->Write(this->m_data, this->m_length)) {
return Error("Failed to write HVAR table");
}
return true;
}
} // namespace ots

31
gfx/ots/src/hvar.h Normal file
Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_HVAR_H_
#define OTS_HVAR_H_
#include "ots.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeHVAR Interface
// -----------------------------------------------------------------------------
class OpenTypeHVAR : public Table {
public:
explicit OpenTypeHVAR(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
const uint8_t *m_data;
size_t m_length;
};
} // namespace ots
#endif // OTS_HVAR_H_

Просмотреть файл

@ -7,6 +7,9 @@
#include <limits>
#include <vector>
#ifdef OTS_VARIATIONS
#include "fvar.h"
#endif
#include "gdef.h"
// OpenType Layout Common Table Formats
@ -24,6 +27,9 @@ const uint16_t kNoRequiredFeatureIndexDefined = 0xFFFF;
const uint16_t kUseMarkFilteringSetBit = 0x0010;
// The maximum type number of format for device tables.
const uint16_t kMaxDeltaFormatType = 3;
// In variation fonts, Device Tables are replaced by VariationIndex tables,
// indicated by this flag in the deltaFormat field.
const uint16_t kVariationIndex = 0x8000;
// The maximum number of class value.
const uint16_t kMaxClassDefValue = 0xFFFF;
@ -1380,6 +1386,12 @@ bool ParseDeviceTable(const ots::Font *font,
!subtable.ReadU16(&delta_format)) {
return OTS_FAILURE_MSG("Failed to read device table header");
}
if (delta_format == kVariationIndex) {
// start_size and end_size are replaced by deltaSetOuterIndex
// and deltaSetInnerIndex respectively, but we don't attempt to
// check them here, so nothing more to do.
return true;
}
if (start_size > end_size) {
return OTS_FAILURE_MSG("bad size range: %u > %u", start_size, end_size);
}
@ -1496,6 +1508,179 @@ bool ParseExtensionSubtable(const Font *font,
return true;
}
bool ParseConditionTable(const Font *font,
const uint8_t *data, const size_t length,
const uint16_t axis_count) {
Buffer subtable(data, length);
uint16_t format = 0;
if (!subtable.ReadU16(&format)) {
return OTS_FAILURE_MSG("Failed to read condition table format");
}
if (format != 1) {
// An unknown format is not an error, but should be ignored per spec.
return true;
}
uint16_t axis_index = 0;
int16_t filter_range_min_value = 0;
int16_t filter_range_max_value = 0;
if (!subtable.ReadU16(&axis_index) ||
!subtable.ReadS16(&filter_range_min_value) ||
!subtable.ReadS16(&filter_range_max_value)) {
return OTS_FAILURE_MSG("Failed to read condition table (format 1)");
}
#ifdef OTS_VARIATIONS // we can't check this if we're not parsing variation tables
if (axis_index >= axis_count) {
return OTS_FAILURE_MSG("Axis index out of range in condition");
}
#endif
// Check min/max values are within range -1.0 .. 1.0 and properly ordered
if (filter_range_min_value < -0x4000 || // -1.0 in F2DOT14 format
filter_range_max_value > 0x4000 || // +1.0 in F2DOT14 format
filter_range_min_value > filter_range_max_value) {
return OTS_FAILURE_MSG("Invalid filter range in condition");
}
return true;
}
bool ParseConditionSetTable(const Font *font,
const uint8_t *data, const size_t length,
const uint16_t axis_count) {
Buffer subtable(data, length);
uint16_t condition_count = 0;
if (!subtable.ReadU16(&condition_count)) {
return OTS_FAILURE_MSG("Failed to read condition count");
}
for (uint16_t i = 0; i < condition_count; i++) {
uint32_t condition_offset = 0;
if (!subtable.ReadU32(&condition_offset)) {
return OTS_FAILURE_MSG("Failed to read condition offset");
}
if (condition_offset < subtable.offset() || condition_offset >= length) {
return OTS_FAILURE_MSG("Offset out of range");
}
if (!ParseConditionTable(font, data + condition_offset, length - condition_offset,
axis_count)) {
return OTS_FAILURE_MSG("Failed to parse condition table");
}
}
return true;
}
bool ParseFeatureTableSubstitutionTable(const Font *font,
const uint8_t *data, const size_t length,
const uint16_t num_lookups) {
Buffer subtable(data, length);
uint16_t version_major = 0;
uint16_t version_minor = 0;
uint16_t substitution_count = 0;
const size_t kFeatureTableSubstitutionHeaderSize = 3 * sizeof(uint16_t);
if (!subtable.ReadU16(&version_major) ||
!subtable.ReadU16(&version_minor) ||
!subtable.ReadU16(&substitution_count)) {
return OTS_FAILURE_MSG("Failed to read feature table substitution table header");
}
for (uint16_t i = 0; i < substitution_count; i++) {
uint16_t feature_index = 0;
uint32_t alternate_feature_table_offset = 0;
const size_t kFeatureTableSubstitutionRecordSize = sizeof(uint16_t) + sizeof(uint32_t);
if (!subtable.ReadU16(&feature_index) ||
!subtable.ReadU32(&alternate_feature_table_offset)) {
return OTS_FAILURE_MSG("Failed to read feature table substitution record");
}
if (alternate_feature_table_offset < kFeatureTableSubstitutionHeaderSize +
kFeatureTableSubstitutionRecordSize * substitution_count ||
alternate_feature_table_offset >= length) {
return OTS_FAILURE_MSG("Invalid alternate feature table offset");
}
if (!ParseFeatureTable(font, data + alternate_feature_table_offset,
length - alternate_feature_table_offset, num_lookups)) {
return OTS_FAILURE_MSG("Failed to parse alternate feature table");
}
}
return true;
}
bool ParseFeatureVariationsTable(const Font *font,
const uint8_t *data, const size_t length,
const uint16_t num_lookups) {
Buffer subtable(data, length);
uint16_t version_major = 0;
uint16_t version_minor = 0;
uint32_t feature_variation_record_count = 0;
if (!subtable.ReadU16(&version_major) ||
!subtable.ReadU16(&version_minor) ||
!subtable.ReadU32(&feature_variation_record_count)) {
return OTS_FAILURE_MSG("Failed to read feature variations table header");
}
#ifdef OTS_VARIATIONS
OpenTypeFVAR* fvar = static_cast<OpenTypeFVAR*>(font->GetTypedTable(OTS_TAG_FVAR));
if (!fvar) {
return OTS_FAILURE_MSG("Not a variation font");
}
const uint16_t axis_count = fvar->AxisCount();
#else
const uint16_t axis_count = 0;
#endif
const size_t kEndOfFeatureVariationRecords =
2 * sizeof(uint16_t) + sizeof(uint32_t) +
feature_variation_record_count * 2 * sizeof(uint32_t);
for (uint32_t i = 0; i < feature_variation_record_count; i++) {
uint32_t condition_set_offset = 0;
uint32_t feature_table_substitution_offset = 0;
if (!subtable.ReadU32(&condition_set_offset) ||
!subtable.ReadU32(&feature_table_substitution_offset)) {
return OTS_FAILURE_MSG("Failed to read feature variation record");
}
if (condition_set_offset) {
if (condition_set_offset < kEndOfFeatureVariationRecords ||
condition_set_offset >= length) {
return OTS_FAILURE_MSG("Condition set offset out of range");
}
if (!ParseConditionSetTable(font, data + condition_set_offset,
length - condition_set_offset,
axis_count)) {
return OTS_FAILURE_MSG("Failed to parse condition set table");
}
}
if (feature_table_substitution_offset) {
if (feature_table_substitution_offset < kEndOfFeatureVariationRecords ||
feature_table_substitution_offset >= length) {
return OTS_FAILURE_MSG("Feature table substitution offset out of range");
}
if (!ParseFeatureTableSubstitutionTable(font, data + feature_table_substitution_offset,
length - feature_table_substitution_offset,
num_lookups)) {
return OTS_FAILURE_MSG("Failed to parse feature table substitution table");
}
}
}
return true;
}
} // namespace ots
#undef TABLE_NAME

Просмотреть файл

@ -70,6 +70,23 @@ bool ParseExtensionSubtable(const Font *font,
const uint8_t *data, const size_t length,
const LookupSubtableParser* parser);
// For feature variations table (in GSUB/GPOS v1.1)
bool ParseConditionTable(const Font *font,
const uint8_t *data, const size_t length,
const uint16_t axis_count);
bool ParseConditionSetTable(const Font *font,
const uint8_t *data, const size_t length,
const uint16_t axis_count);
bool ParseFeatureTableSubstitutionTable(const Font *font,
const uint8_t *data, const size_t length,
const uint16_t num_lookups);
bool ParseFeatureVariationsTable(const Font *font,
const uint8_t *data, const size_t length,
const uint16_t num_lookups);
} // namespace ots
#endif // OTS_LAYOUT_H_

Просмотреть файл

@ -15,22 +15,27 @@ SOURCES += [
]
UNIFIED_SOURCES += [
'avar.cc',
'cff.cc',
'cff_type2_charstring.cc',
'cmap.cc',
'cvar.cc',
'cvt.cc',
'feat.cc',
'fpgm.cc',
'fvar.cc',
'gasp.cc',
'glat.cc',
'gloc.cc',
'glyf.cc',
'gpos.cc',
'gsub.cc',
'gvar.cc',
'hdmx.cc',
'head.cc',
'hhea.cc',
'hmtx.cc',
'hvar.cc',
'kern.cc',
'layout.cc',
'loca.cc',
@ -38,6 +43,7 @@ UNIFIED_SOURCES += [
'math.cc',
'maxp.cc',
'metrics.cc',
'mvar.cc',
'name.cc',
'os2.cc',
'ots.cc',
@ -46,10 +52,13 @@ UNIFIED_SOURCES += [
'sile.cc',
'silf.cc',
'sill.cc',
'stat.cc',
'variations.cc',
'vdmx.cc',
'vhea.cc',
'vmtx.cc',
'vorg.cc',
'vvar.cc',
]
# We allow warnings for third-party code that can be updated from upstream.
@ -60,6 +69,7 @@ FINAL_LIBRARY = 'gkmedias'
DEFINES['PACKAGE_VERSION'] = '"moz"'
DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
DEFINES['OTS_GRAPHITE'] = 1
DEFINES['OTS_VARIATIONS'] = 1
USE_LIBS += [
'brotli',

91
gfx/ots/src/mvar.cc Normal file
Просмотреть файл

@ -0,0 +1,91 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mvar.h"
#include "variations.h"
#define TABLE_NAME "MVAR"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeMVAR
// -----------------------------------------------------------------------------
bool OpenTypeMVAR::Parse(const uint8_t* data, size_t length) {
Buffer table(data, length);
uint16_t majorVersion;
uint16_t minorVersion;
uint16_t reserved;
uint16_t valueRecordSize;
uint16_t valueRecordCount;
uint16_t itemVariationStoreOffset;
if (!table.ReadU16(&majorVersion) ||
!table.ReadU16(&minorVersion) ||
!table.ReadU16(&reserved) ||
!table.ReadU16(&valueRecordSize) ||
!table.ReadU16(&valueRecordCount) ||
!table.ReadU16(&itemVariationStoreOffset)) {
return DropVariations("Failed to read table header");
}
if (majorVersion != 1) {
return DropVariations("Unknown table version");
}
if (reserved != 0) {
Warning("Expected reserved=0");
}
if (valueRecordSize < 8) {
return DropVariations("Value record size too small");
}
if (valueRecordCount == 0) {
if (itemVariationStoreOffset != 0) {
return DropVariations("Unexpected item variation store");
}
} else {
if (itemVariationStoreOffset < table.offset() || itemVariationStoreOffset > length) {
return DropVariations("Invalid item variation store offset");
}
if (!ParseItemVariationStore(GetFont(), data + itemVariationStoreOffset,
length - itemVariationStoreOffset)) {
return DropVariations("Failed to parse item variation store");
}
}
uint32_t prevTag = 0;
for (unsigned i = 0; i < valueRecordCount; i++) {
uint32_t tag;
uint16_t deltaSetOuterIndex, deltaSetInnerIndex;
if (!table.ReadU32(&tag) ||
!table.ReadU16(&deltaSetOuterIndex) ||
!table.ReadU16(&deltaSetInnerIndex)) {
return DropVariations("Failed to read value record");
}
if (tag <= prevTag) {
return DropVariations("Invalid or out-of-order value tag");
}
prevTag = tag;
}
this->m_data = data;
this->m_length = length;
return true;
}
bool OpenTypeMVAR::Serialize(OTSStream* out) {
if (!out->Write(this->m_data, this->m_length)) {
return Error("Failed to write MVAR table");
}
return true;
}
} // namespace ots

31
gfx/ots/src/mvar.h Normal file
Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_MVAR_H_
#define OTS_MVAR_H_
#include "ots.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeMVAR Interface
// -----------------------------------------------------------------------------
class OpenTypeMVAR : public Table {
public:
explicit OpenTypeMVAR(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
const uint8_t *m_data;
size_t m_length;
};
} // namespace ots
#endif // OTS_MVAR_H_

Просмотреть файл

@ -169,6 +169,14 @@ bool OpenTypeNAME::Parse(const uint8_t* data, size_t length) {
if (tag_end > length) {
return Error("bad end of tag %d > %ld for langTagRecord %d", tag_end, length, i);
}
// Lang tag is BCP 47 tag per the spec, the recommonded BCP 47 max tag
// length is 35:
// https://tools.ietf.org/html/bcp47#section-4.4.1
// We are being too generous and allowing for 100 (multiplied by 2 since
// this is UTF-16 string).
if (tag_length > 100 * 2) {
return Error("Too long language tag for LangTagRecord %d: %d", i, tag_length);
}
std::string tag(string_base + tag_offset, tag_length);
this->lang_tags.push_back(tag);
}

Просмотреть файл

@ -14,7 +14,7 @@
#include <map>
#include <vector>
#include "woff2/decode.h"
#include <woff2/decode.h>
// The OpenType Font File
// http://www.microsoft.com/typography/otspec/otff.htm
@ -57,6 +57,17 @@
#include "sill.h"
#endif
#ifdef OTS_VARIATIONS
#include "avar.h"
#include "cvar.h"
#include "fvar.h"
#include "gvar.h"
#include "hvar.h"
#include "mvar.h"
#include "stat.h"
#include "vvar.h"
#endif
namespace ots {
struct Arena {
@ -78,6 +89,17 @@ struct Arena {
std::vector<uint8_t*> hunks_;
};
bool CheckTag(uint32_t tag_value) {
for (unsigned i = 0; i < 4; ++i) {
const uint32_t check = tag_value & 0xff;
if (check < 32 || check > 126) {
return false; // non-ASCII character found.
}
tag_value >>= 8;
}
return true;
}
}; // namespace ots
namespace {
@ -91,17 +113,6 @@ namespace {
#define OTS_WARNING_MSG_HDR(...) OTS_WARNING_MSG_(header, __VA_ARGS__)
bool CheckTag(uint32_t tag_value) {
for (unsigned i = 0; i < 4; ++i) {
const uint32_t check = tag_value & 0xff;
if (check < 32 || check > 126) {
return false; // non-ASCII character found.
}
tag_value >>= 8;
}
return true;
}
const struct {
uint32_t tag;
bool required;
@ -126,6 +137,18 @@ const struct {
{ OTS_TAG_LTSH, false },
{ OTS_TAG_VORG, false },
{ OTS_TAG_KERN, false },
// We need to parse fvar table before other tables that may need to know
// the number of variation axes (if any)
#ifdef OTS_VARIATIONS
{ OTS_TAG_FVAR, false },
{ OTS_TAG_AVAR, false },
{ OTS_TAG_CVAR, false },
{ OTS_TAG_GVAR, false },
{ OTS_TAG_HVAR, false },
{ OTS_TAG_MVAR, false },
{ OTS_TAG_STAT, false },
{ OTS_TAG_VVAR, false },
#endif
// We need to parse GDEF table in advance of parsing GSUB/GPOS tables
// because they could refer GDEF table.
{ OTS_TAG_GDEF, false },
@ -580,7 +603,7 @@ bool ProcessGeneric(ots::FontFile *header,
}
// all tag names must be built from printable ASCII characters
if (!CheckTag(tables[i].tag)) {
if (!ots::CheckTag(tables[i].tag)) {
OTS_WARNING_MSG_HDR("Invalid table tag: 0x%X", tables[i].tag);
}
@ -896,6 +919,16 @@ bool Font::ParseTable(const TableEntry& table_entry, const uint8_t* data,
case OTS_TAG_SILE: table = new OpenTypeSILE(this, tag); break;
case OTS_TAG_SILF: table = new OpenTypeSILF(this, tag); break;
case OTS_TAG_SILL: table = new OpenTypeSILL(this, tag); break;
#endif
#ifdef OTS_VARIATIONS
case OTS_TAG_AVAR: table = new OpenTypeAVAR(this, tag); break;
case OTS_TAG_CVAR: table = new OpenTypeCVAR(this, tag); break;
case OTS_TAG_FVAR: table = new OpenTypeFVAR(this, tag); break;
case OTS_TAG_GVAR: table = new OpenTypeGVAR(this, tag); break;
case OTS_TAG_HVAR: table = new OpenTypeHVAR(this, tag); break;
case OTS_TAG_MVAR: table = new OpenTypeMVAR(this, tag); break;
case OTS_TAG_STAT: table = new OpenTypeSTAT(this, tag); break;
case OTS_TAG_VVAR: table = new OpenTypeVVAR(this, tag); break;
#endif
default: break;
}
@ -953,6 +986,23 @@ void Font::DropGraphite() {
dropped_graphite = true;
}
void Font::DropVariations() {
file->context->Message(0, "Dropping all Variation tables");
for (const std::pair<uint32_t, Table*> entry : m_tables) {
if (entry.first == OTS_TAG_AVAR ||
entry.first == OTS_TAG_CVAR ||
entry.first == OTS_TAG_FVAR ||
entry.first == OTS_TAG_GVAR ||
entry.first == OTS_TAG_HVAR ||
entry.first == OTS_TAG_MVAR ||
entry.first == OTS_TAG_STAT ||
entry.first == OTS_TAG_VVAR) {
entry.second->Drop("Discarding Variations table");
}
}
dropped_variations = true;
}
bool Table::ShouldSerialize() {
return m_shouldSerialize;
}
@ -1003,6 +1053,16 @@ bool Table::DropGraphite(const char *format, ...) {
return true;
}
bool Table::DropVariations(const char *format, ...) {
va_list va;
va_start(va, format);
Message(0, format, va);
va_end(va);
m_font->DropVariations();
return true;
}
bool TablePassthru::Parse(const uint8_t *data, size_t length) {
m_data = data;
m_length = length;

Просмотреть файл

@ -184,6 +184,9 @@ template<typename T> T Round2(T value) {
return (value + 1) & ~1;
}
// Check that a tag consists entirely of printable ASCII characters
bool CheckTag(uint32_t tag_value);
bool IsValidVersionTag(uint32_t tag);
#define OTS_TAG_CFF OTS_TAG('C','F','F',' ')
@ -219,6 +222,15 @@ bool IsValidVersionTag(uint32_t tag);
#define OTS_TAG_VMTX OTS_TAG('v','m','t','x')
#define OTS_TAG_VORG OTS_TAG('V','O','R','G')
#define OTS_TAG_AVAR OTS_TAG('a','v','a','r')
#define OTS_TAG_CVAR OTS_TAG('c','v','a','r')
#define OTS_TAG_FVAR OTS_TAG('f','v','a','r')
#define OTS_TAG_GVAR OTS_TAG('g','v','a','r')
#define OTS_TAG_HVAR OTS_TAG('H','V','A','R')
#define OTS_TAG_MVAR OTS_TAG('M','V','A','R')
#define OTS_TAG_VVAR OTS_TAG('V','V','A','R')
#define OTS_TAG_STAT OTS_TAG('S','T','A','T')
struct Font;
struct FontFile;
struct TableEntry;
@ -252,6 +264,7 @@ class Table {
bool Warning(const char *format, ...);
bool Drop(const char *format, ...);
bool DropGraphite(const char *format, ...);
bool DropVariations(const char *format, ...);
private:
void Message(int level, const char *format, va_list va);
@ -286,7 +299,8 @@ struct Font {
search_range(0),
entry_selector(0),
range_shift(0),
dropped_graphite(false) {
dropped_graphite(false),
dropped_variations(false) {
}
bool ParseTable(const TableEntry& tableinfo, const uint8_t* data,
@ -301,6 +315,9 @@ struct Font {
// Drop all Graphite tables and don't parse new ones.
void DropGraphite();
// Drop all Variations tables and don't parse new ones.
void DropVariations();
FontFile *file;
uint32_t version;
@ -309,6 +326,7 @@ struct Font {
uint16_t entry_selector;
uint16_t range_shift;
bool dropped_graphite;
bool dropped_variations;
private:
std::map<uint32_t, Table*> m_tables;

326
gfx/ots/src/stat.cc Normal file
Просмотреть файл

@ -0,0 +1,326 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "stat.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeSTAT
// -----------------------------------------------------------------------------
bool OpenTypeSTAT::Parse(const uint8_t* data, size_t length) {
Buffer table(data, length);
if (!table.ReadU16(&this->majorVersion) ||
!table.ReadU16(&this->minorVersion) ||
!table.ReadU16(&this->designAxisSize) ||
!table.ReadU16(&this->designAxisCount) ||
!table.ReadU32(&this->designAxesOffset) ||
!table.ReadU16(&this->axisValueCount) ||
!table.ReadU32(&this->offsetToAxisValueOffsets) ||
!(this->minorVersion < 1 || table.ReadU16(&this->elidedFallbackNameID))) {
return Drop("Failed to read table header");
}
if (this->majorVersion != 1) {
return Drop("Unknown table version");
}
if (this->minorVersion > 2) {
Warning("Unknown minor version, downgrading to 2");
this->minorVersion = 2;
}
if (this->designAxisSize < sizeof(AxisRecord)) {
return Drop("Invalid designAxisSize");
}
size_t headerEnd = table.offset();
if (this->designAxisCount == 0) {
if (this->designAxesOffset != 0) {
Warning("Unexpected non-zero designAxesOffset");
this->designAxesOffset = 0;
}
} else {
if (this->designAxesOffset < headerEnd ||
size_t(this->designAxesOffset) +
size_t(this->designAxisCount) * size_t(this->designAxisSize) > length) {
return Drop("Invalid designAxesOffset");
}
}
for (size_t i = 0; i < this->designAxisCount; i++) {
table.set_offset(this->designAxesOffset + i * this->designAxisSize);
this->designAxes.emplace_back();
auto& axis = this->designAxes[i];
if (!table.ReadU32(&axis.axisTag) ||
!table.ReadU16(&axis.axisNameID) ||
!table.ReadU16(&axis.axisOrdering)) {
return Drop("Failed to read design axis");
}
if (!CheckTag(axis.axisTag)) {
return Drop("Bad design axis tag");
}
if (axis.axisNameID <= 255 || axis.axisNameID >= 32768) {
Warning("Design axis nameID out of range");
// We don't check that the name actually exists -- assume the client can handle
// a missing name when it tries to read the table.
}
}
// TODO
// - check that all axes defined in fvar are covered by STAT
// - check that axisOrdering values are not duplicated (warn only)
if (this->axisValueCount == 0) {
if (this->offsetToAxisValueOffsets != 0) {
Warning("Unexpected non-zero offsetToAxisValueOffsets");
this->offsetToAxisValueOffsets = 0;
}
} else {
if (this->offsetToAxisValueOffsets < headerEnd ||
size_t(this->offsetToAxisValueOffsets) +
size_t(this->axisValueCount) * sizeof(uint16_t) > length) {
return Drop("Invalid offsetToAxisValueOffsets");
}
}
for (size_t i = 0; i < this->axisValueCount; i++) {
table.set_offset(this->offsetToAxisValueOffsets + i * sizeof(uint16_t));
uint16_t axisValueOffset;
if (!table.ReadU16(&axisValueOffset)) {
return Drop("Failed to read axis value offset");
}
if (this->offsetToAxisValueOffsets + axisValueOffset > length) {
return Drop("Invalid axis value offset");
}
table.set_offset(this->offsetToAxisValueOffsets + axisValueOffset);
uint16_t format;
if (!table.ReadU16(&format)) {
return Drop("Failed to read axis value format");
}
this->axisValues.emplace_back(format);
auto& axisValue = axisValues[i];
switch (format) {
case 1:
if (!table.ReadU16(&axisValue.format1.axisIndex) ||
!table.ReadU16(&axisValue.format1.flags) ||
!table.ReadU16(&axisValue.format1.valueNameID) ||
!table.ReadS32(&axisValue.format1.value)) {
return Drop("Failed to read axis value (format 1)");
}
if (axisValue.format1.axisIndex >= this->designAxisCount) {
return Drop("Axis index out of range");
}
if ((axisValue.format1.flags & 0xFFFCu) != 0) {
Warning("Unexpected axis value flags");
axisValue.format1.flags &= ~0xFFFCu;
}
if (axisValue.format1.valueNameID <= 255 || axisValue.format1.valueNameID >= 32768) {
Warning("Axis value nameID out of range");
}
break;
case 2:
if (!table.ReadU16(&axisValue.format2.axisIndex) ||
!table.ReadU16(&axisValue.format2.flags) ||
!table.ReadU16(&axisValue.format2.valueNameID) ||
!table.ReadS32(&axisValue.format2.nominalValue) ||
!table.ReadS32(&axisValue.format2.rangeMinValue) ||
!table.ReadS32(&axisValue.format2.rangeMaxValue)) {
return Drop("Failed to read axis value (format 2)");
}
if (axisValue.format2.axisIndex >= this->designAxisCount) {
return Drop("Axis index out of range");
}
if ((axisValue.format2.flags & 0xFFFCu) != 0) {
Warning("Unexpected axis value flags");
axisValue.format1.flags &= ~0xFFFCu;
}
if (axisValue.format2.valueNameID <= 255 || axisValue.format2.valueNameID >= 32768) {
Warning("Axis value nameID out of range");
}
if (!(axisValue.format2.rangeMinValue <= axisValue.format2.nominalValue &&
axisValue.format2.nominalValue <= axisValue.format2.rangeMaxValue)) {
Warning("Bad axis value range or nominal value");
}
break;
case 3:
if (!table.ReadU16(&axisValue.format3.axisIndex) ||
!table.ReadU16(&axisValue.format3.flags) ||
!table.ReadU16(&axisValue.format3.valueNameID) ||
!table.ReadS32(&axisValue.format3.value) ||
!table.ReadS32(&axisValue.format3.linkedValue)) {
return Drop("Failed to read axis value (format 3)");
}
if (axisValue.format3.axisIndex >= this->designAxisCount) {
return Drop("Axis index out of range");
}
if ((axisValue.format3.flags & 0xFFFCu) != 0) {
Warning("Unexpected axis value flags");
axisValue.format3.flags &= ~0xFFFCu;
}
if (axisValue.format3.valueNameID <= 255 || axisValue.format3.valueNameID >= 32768) {
Warning("Axis value nameID out of range");
}
break;
case 4:
if (this->minorVersion < 2) {
Warning("Invalid table version for format 4 axis values - updating");
this->minorVersion = 2;
}
if (!table.ReadU16(&axisValue.format4.axisCount) ||
!table.ReadU16(&axisValue.format4.flags) ||
!table.ReadU16(&axisValue.format4.valueNameID)) {
return Drop("Failed to read axis value (format 4)");
}
if (axisValue.format4.axisCount > this->designAxisCount) {
return Drop("Axis count out of range");
}
if ((axisValue.format4.flags & 0xFFFCu) != 0) {
Warning("Unexpected axis value flags");
axisValue.format4.flags &= ~0xFFFCu;
}
if (axisValue.format4.valueNameID <= 255 || axisValue.format4.valueNameID >= 32768) {
Warning("Axis value nameID out of range");
}
for (unsigned j = 0; j < axisValue.format4.axisCount; j++) {
axisValue.format4.axisValues.emplace_back();
auto& v = axisValue.format4.axisValues[j];
if (!table.ReadU16(&v.axisIndex) ||
!table.ReadS32(&v.value)) {
return Drop("Failed to read axis value");
}
if (v.axisIndex >= this->designAxisCount) {
return Drop("Axis index out of range");
}
}
break;
default:
return Drop("Unknown axis value format");
}
}
return true;
}
bool OpenTypeSTAT::Serialize(OTSStream* out) {
off_t tableStart = out->Tell();
size_t headerSize = 5 * sizeof(uint16_t) + 2 * sizeof(uint32_t);
if (this->minorVersion >= 1) {
headerSize += sizeof(uint16_t);
}
if (this->designAxisCount == 0) {
this->designAxesOffset = 0;
} else {
this->designAxesOffset = headerSize;
}
this->designAxisSize = sizeof(AxisRecord);
if (this->axisValueCount == 0) {
this->offsetToAxisValueOffsets = 0;
} else {
if (this->designAxesOffset == 0) {
this->offsetToAxisValueOffsets = headerSize;
} else {
this->offsetToAxisValueOffsets = this->designAxesOffset + this->designAxisCount * this->designAxisSize;
}
}
if (!out->WriteU16(this->majorVersion) ||
!out->WriteU16(this->minorVersion) ||
!out->WriteU16(this->designAxisSize) ||
!out->WriteU16(this->designAxisCount) ||
!out->WriteU32(this->designAxesOffset) ||
!out->WriteU16(this->axisValueCount) ||
!out->WriteU32(this->offsetToAxisValueOffsets) ||
!(this->minorVersion < 1 || out->WriteU16(this->elidedFallbackNameID))) {
return Error("Failed to write table header");
}
if (this->designAxisCount > 0) {
if (out->Tell() - tableStart != this->designAxesOffset) {
return Error("Error computing designAxesOffset");
}
}
for (unsigned i = 0; i < this->designAxisCount; i++) {
const auto& axis = this->designAxes[i];
if (!out->WriteU32(axis.axisTag) ||
!out->WriteU16(axis.axisNameID) ||
!out->WriteU16(axis.axisOrdering)) {
return Error("Failed to write design axis");
}
}
if (this->axisValueCount > 0) {
if (out->Tell() - tableStart != this->offsetToAxisValueOffsets) {
return Error("Error computing offsetToAxisValueOffsets");
}
}
uint32_t axisValueOffset = this->axisValueCount * sizeof(uint16_t);
for (unsigned i = 0; i < this->axisValueCount; i++) {
const auto& value = this->axisValues[i];
if (!out->WriteU16(axisValueOffset)) {
return Error("Failed to write axis value offset");
}
axisValueOffset += value.Length();
}
for (unsigned i = 0; i < this->axisValueCount; i++) {
const auto& value = this->axisValues[i];
if (!out->WriteU16(value.format)) {
return Error("Failed to write axis value");
}
switch (value.format) {
case 1:
if (!out->WriteU16(value.format1.axisIndex) ||
!out->WriteU16(value.format1.flags) ||
!out->WriteU16(value.format1.valueNameID) ||
!out->WriteS32(value.format1.value)) {
return Error("Failed to write axis value");
}
break;
case 2:
if (!out->WriteU16(value.format2.axisIndex) ||
!out->WriteU16(value.format2.flags) ||
!out->WriteU16(value.format2.valueNameID) ||
!out->WriteS32(value.format2.nominalValue) ||
!out->WriteS32(value.format2.rangeMinValue) ||
!out->WriteS32(value.format2.rangeMaxValue)) {
return Error("Failed to write axis value");
}
break;
case 3:
if (!out->WriteU16(value.format3.axisIndex) ||
!out->WriteU16(value.format3.flags) ||
!out->WriteU16(value.format3.valueNameID) ||
!out->WriteS32(value.format3.value) ||
!out->WriteS32(value.format3.linkedValue)) {
return Error("Failed to write axis value");
}
break;
case 4:
if (!out->WriteU16(value.format4.axisCount) ||
!out->WriteU16(value.format4.flags) ||
!out->WriteU16(value.format4.valueNameID)) {
return Error("Failed to write axis value");
}
for (unsigned j = 0; j < value.format4.axisValues.size(); j++) {
if (!out->WriteU16(value.format4.axisValues[i].axisIndex) ||
!out->WriteS32(value.format4.axisValues[i].value)) {
return Error("Failed to write axis value");
}
}
break;
default:
return Error("Bad value format");
}
}
return true;
}
} // namespace ots

152
gfx/ots/src/stat.h Normal file
Просмотреть файл

@ -0,0 +1,152 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_STAT_H_
#define OTS_STAT_H_
#include <vector>
#include "ots.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeSTAT Interface
// -----------------------------------------------------------------------------
class OpenTypeSTAT : public Table {
public:
explicit OpenTypeSTAT(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
uint16_t majorVersion;
uint16_t minorVersion;
uint16_t designAxisSize;
uint16_t designAxisCount;
uint32_t designAxesOffset;
uint16_t axisValueCount;
uint32_t offsetToAxisValueOffsets;
uint16_t elidedFallbackNameID;
struct AxisRecord {
uint32_t axisTag;
uint16_t axisNameID;
uint16_t axisOrdering;
};
std::vector<AxisRecord> designAxes;
typedef int32_t Fixed; /* 16.16 fixed-point value */
struct AxisValueFormat1 {
uint16_t axisIndex;
uint16_t flags;
uint16_t valueNameID;
Fixed value;
static const size_t Length() {
return 3 * sizeof(uint16_t) + sizeof(Fixed);
}
};
struct AxisValueFormat2 {
uint16_t axisIndex;
uint16_t flags;
uint16_t valueNameID;
Fixed nominalValue;
Fixed rangeMinValue;
Fixed rangeMaxValue;
static const size_t Length() {
return 3 * sizeof(uint16_t) + 3 * sizeof(Fixed);
}
};
struct AxisValueFormat3 {
uint16_t axisIndex;
uint16_t flags;
uint16_t valueNameID;
Fixed value;
Fixed linkedValue;
static const size_t Length() {
return 3 * sizeof(uint16_t) + 2 * sizeof(Fixed);
}
};
struct AxisValueFormat4 {
uint16_t axisCount;
uint16_t flags;
uint16_t valueNameID;
struct AxisValue {
uint16_t axisIndex;
Fixed value;
};
std::vector<AxisValue> axisValues;
const size_t Length() const {
return 3 * sizeof(uint16_t) + axisValues.size() * (sizeof(uint16_t) + sizeof(Fixed));
}
};
struct AxisValueRecord {
uint16_t format;
union {
AxisValueFormat1 format1;
AxisValueFormat2 format2;
AxisValueFormat3 format3;
AxisValueFormat4 format4;
};
explicit AxisValueRecord(uint16_t format_)
: format(format_)
{
if (format == 4) {
new (&this->format4) AxisValueFormat4();
}
}
AxisValueRecord(const AxisValueRecord& other_)
: format(other_.format)
{
switch (format) {
case 1:
format1 = other_.format1;
break;
case 2:
format2 = other_.format2;
break;
case 3:
format3 = other_.format3;
break;
case 4:
format4 = other_.format4;
break;
}
}
~AxisValueRecord() {
if (format == 4) {
this->format4.~AxisValueFormat4();
}
}
uint32_t Length() const {
switch (format) {
case 1:
return sizeof(uint16_t) + format1.Length();
case 2:
return sizeof(uint16_t) + format2.Length();
case 3:
return sizeof(uint16_t) + format3.Length();
case 4:
return sizeof(uint16_t) + format4.Length();
default:
// can't happen
return 0;
}
}
};
std::vector<AxisValueRecord> axisValues;
};
} // namespace ots
#endif // OTS_STAT_H_

248
gfx/ots/src/variations.cc Normal file
Просмотреть файл

@ -0,0 +1,248 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "layout.h"
#include "fvar.h"
// OpenType Variations Common Table Formats
#define TABLE_NAME "Variations" // XXX: use individual table names
namespace {
bool ParseVariationRegionList(const ots::Font* font, const uint8_t* data, const size_t length,
uint16_t* regionCount) {
ots::Buffer subtable(data, length);
uint16_t axisCount;
if (!subtable.ReadU16(&axisCount) ||
!subtable.ReadU16(regionCount)) {
return OTS_FAILURE_MSG("Failed to read variation region list header");
}
const ots::OpenTypeFVAR* fvar =
static_cast<ots::OpenTypeFVAR*>(font->GetTypedTable(OTS_TAG_FVAR));
if (!fvar) {
return OTS_FAILURE_MSG("Required fvar table is missing");
}
if (axisCount != fvar->AxisCount()) {
return OTS_FAILURE_MSG("Axis count mismatch");
}
for (unsigned i = 0; i < *regionCount; i++) {
for (unsigned j = 0; j < axisCount; j++) {
int16_t startCoord, peakCoord, endCoord;
if (!subtable.ReadS16(&startCoord) ||
!subtable.ReadS16(&peakCoord) ||
!subtable.ReadS16(&endCoord)) {
return OTS_FAILURE_MSG("Failed to read region axis coordinates");
}
if (startCoord > peakCoord || peakCoord > endCoord) {
return OTS_FAILURE_MSG("Region axis coordinates out of order");
}
if (startCoord < -0x4000 || endCoord > 0x4000) {
return OTS_FAILURE_MSG("Region axis coordinate out of range");
}
if ((peakCoord < 0 && endCoord > 0) ||
(peakCoord > 0 && startCoord < 0)) {
return OTS_FAILURE_MSG("Invalid region axis coordinates");
}
}
}
return true;
}
bool
ParseVariationDataSubtable(const ots::Font* font, const uint8_t* data, const size_t length,
const uint16_t regionCount) {
ots::Buffer subtable(data, length);
uint16_t itemCount;
uint16_t shortDeltaCount;
uint16_t regionIndexCount;
if (!subtable.ReadU16(&itemCount) ||
!subtable.ReadU16(&shortDeltaCount) ||
!subtable.ReadU16(&regionIndexCount)) {
return OTS_FAILURE_MSG("Failed to read variation data subtable header");
}
for (unsigned i = 0; i < regionIndexCount; i++) {
uint16_t regionIndex;
if (!subtable.ReadU16(&regionIndex) || regionIndex >= regionCount) {
return OTS_FAILURE_MSG("Bad region index");
}
}
if (!subtable.Skip(size_t(itemCount) * size_t(shortDeltaCount) + size_t(regionIndexCount))) {
return OTS_FAILURE_MSG("Failed to read delta data");
}
return true;
}
} // namespace
namespace ots {
bool
ParseItemVariationStore(const Font* font, const uint8_t* data, const size_t length) {
Buffer subtable(data, length);
uint16_t format;
uint32_t variationRegionListOffset;
uint16_t itemVariationDataCount;
if (!subtable.ReadU16(&format) ||
!subtable.ReadU32(&variationRegionListOffset) ||
!subtable.ReadU16(&itemVariationDataCount)) {
return OTS_FAILURE_MSG("Failed to read item variation store header");
}
if (format != 1) {
return OTS_FAILURE_MSG("Unknown item variation store format");
}
if (variationRegionListOffset < subtable.offset() + 4 * itemVariationDataCount ||
variationRegionListOffset > length) {
return OTS_FAILURE_MSG("Invalid variation region list offset");
}
uint16_t regionCount;
if (!ParseVariationRegionList(font,
data + variationRegionListOffset,
length - variationRegionListOffset,
&regionCount)) {
return OTS_FAILURE_MSG("Failed to parse variation region list");
}
for (unsigned i = 0; i < itemVariationDataCount; i++) {
uint32_t offset;
if (!subtable.ReadU32(&offset)) {
return OTS_FAILURE_MSG("Failed to read variation data subtable offset");
}
if (offset >= length) {
return OTS_FAILURE_MSG("Bad offset to variation data subtable");
}
if (!ParseVariationDataSubtable(font, data + offset, length - offset, regionCount)) {
return OTS_FAILURE_MSG("Failed to parse variation data subtable");
}
}
return true;
}
bool ParseDeltaSetIndexMap(const Font* font, const uint8_t* data, const size_t length) {
Buffer subtable(data, length);
uint16_t entryFormat;
uint16_t mapCount;
if (!subtable.ReadU16(&entryFormat) ||
!subtable.ReadU16(&mapCount)) {
return OTS_FAILURE_MSG("Failed to read delta set index map header");
}
const uint16_t INNER_INDEX_BIT_COUNT_MASK = 0x000F;
const uint16_t MAP_ENTRY_SIZE_MASK = 0x0030;
const uint16_t entrySize = (((entryFormat & MAP_ENTRY_SIZE_MASK) >> 4) + 1);
if (!subtable.Skip(entrySize * mapCount)) {
return OTS_FAILURE_MSG("Failed to read delta set index map data");
}
return true;
}
bool ParseVariationData(const Font* font, const uint8_t* data, size_t length,
size_t axisCount, size_t sharedTupleCount) {
Buffer subtable(data, length);
uint16_t tupleVariationCount;
uint16_t dataOffset;
if (!subtable.ReadU16(&tupleVariationCount) ||
!subtable.ReadU16(&dataOffset)) {
return OTS_FAILURE_MSG("Failed to read variation data header");
}
if (dataOffset > length) {
return OTS_FAILURE_MSG("Invalid serialized data offset");
}
tupleVariationCount &= 0x0FFF; // mask off flags
const uint16_t EMBEDDED_PEAK_TUPLE = 0x8000;
const uint16_t INTERMEDIATE_REGION = 0x4000;
const uint16_t TUPLE_INDEX_MASK = 0x0FFF;
for (unsigned i = 0; i < tupleVariationCount; i++) {
uint16_t variationDataSize;
uint16_t tupleIndex;
if (!subtable.ReadU16(&variationDataSize) ||
!subtable.ReadU16(&tupleIndex)) {
return OTS_FAILURE_MSG("Failed to read tuple variation header");
}
if (tupleIndex & EMBEDDED_PEAK_TUPLE) {
for (unsigned axis = 0; axis < axisCount; axis++) {
int16_t coordinate;
if (!subtable.ReadS16(&coordinate)) {
return OTS_FAILURE_MSG("Failed to read tuple coordinate");
}
if (coordinate < -0x4000 || coordinate > 0x4000) {
return OTS_FAILURE_MSG("Invalid tuple coordinate");
}
}
}
if (tupleIndex & INTERMEDIATE_REGION) {
std::vector<int16_t> startTuple(axisCount);
for (unsigned axis = 0; axis < axisCount; axis++) {
int16_t coordinate;
if (!subtable.ReadS16(&coordinate)) {
return OTS_FAILURE_MSG("Failed to read tuple coordinate");
}
if (coordinate < -0x4000 || coordinate > 0x4000) {
return OTS_FAILURE_MSG("Invalid tuple coordinate");
}
startTuple.push_back(coordinate);
}
std::vector<int16_t> endTuple(axisCount);
for (unsigned axis = 0; axis < axisCount; axis++) {
int16_t coordinate;
if (!subtable.ReadS16(&coordinate)) {
return OTS_FAILURE_MSG("Failed to read tuple coordinate");
}
if (coordinate < -0x4000 || coordinate > 0x4000) {
return OTS_FAILURE_MSG("Invalid tuple coordinate");
}
endTuple.push_back(coordinate);
}
for (unsigned axis = 0; axis < axisCount; axis++) {
if (startTuple[axis] > endTuple[axis]) {
return OTS_FAILURE_MSG("Invalid intermediate range");
}
}
}
if (!(tupleIndex & EMBEDDED_PEAK_TUPLE)) {
tupleIndex &= TUPLE_INDEX_MASK;
if (tupleIndex >= sharedTupleCount) {
return OTS_FAILURE_MSG("Tuple index out of range");
}
}
}
// TODO: we don't attempt to interpret the serialized data block
return true;
}
} // namespace ots

23
gfx/ots/src/variations.h Normal file
Просмотреть файл

@ -0,0 +1,23 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_VARIATIONS_H_
#define OTS_VARIATIONS_H_
#include "ots.h"
// Utility functions for OpenType variations common table formats.
namespace ots {
bool ParseItemVariationStore(const Font* font, const uint8_t* data, const size_t length);
bool ParseDeltaSetIndexMap(const Font* font, const uint8_t* data, const size_t length);
bool ParseVariationData(const Font* font, const uint8_t* data, size_t length,
size_t axisCount, size_t sharedTupleCount);
} // namespace ots
#endif // OTS_VARIATIONS_H_

97
gfx/ots/src/vvar.cc Normal file
Просмотреть файл

@ -0,0 +1,97 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "vvar.h"
#include "variations.h"
#define TABLE_NAME "VVAR"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeVVAR
// -----------------------------------------------------------------------------
bool OpenTypeVVAR::Parse(const uint8_t* data, size_t length) {
Buffer table(data, length);
uint16_t majorVersion;
uint16_t minorVersion;
uint32_t itemVariationStoreOffset;
uint32_t advanceHeightMappingOffset;
uint32_t tsbMappingOffset;
uint32_t bsbMappingOffset;
uint32_t vOrgMappingOffset;
if (!table.ReadU16(&majorVersion) ||
!table.ReadU16(&minorVersion) ||
!table.ReadU32(&itemVariationStoreOffset) ||
!table.ReadU32(&advanceHeightMappingOffset) ||
!table.ReadU32(&tsbMappingOffset) ||
!table.ReadU32(&bsbMappingOffset) ||
!table.ReadU32(&vOrgMappingOffset)) {
return DropVariations("Failed to read table header");
}
if (majorVersion != 1) {
return DropVariations("Unknown table version");
}
if (itemVariationStoreOffset > length ||
advanceHeightMappingOffset > length ||
tsbMappingOffset > length ||
bsbMappingOffset > length ||
vOrgMappingOffset > length) {
return DropVariations("Invalid subtable offset");
}
if (!ParseItemVariationStore(GetFont(), data + itemVariationStoreOffset,
length - itemVariationStoreOffset)) {
return DropVariations("Failed to parse item variation store");
}
if (advanceHeightMappingOffset) {
if (!ParseDeltaSetIndexMap(GetFont(), data + advanceHeightMappingOffset,
length - advanceHeightMappingOffset)) {
return DropVariations("Failed to parse advance height mappings");
}
}
if (tsbMappingOffset) {
if (!ParseDeltaSetIndexMap(GetFont(), data + tsbMappingOffset,
length - tsbMappingOffset)) {
return DropVariations("Failed to parse TSB mappings");
}
}
if (bsbMappingOffset) {
if (!ParseDeltaSetIndexMap(GetFont(), data + bsbMappingOffset,
length - bsbMappingOffset)) {
return DropVariations("Failed to parse BSB mappings");
}
}
if (vOrgMappingOffset) {
if (!ParseDeltaSetIndexMap(GetFont(), data + vOrgMappingOffset,
length - vOrgMappingOffset)) {
return DropVariations("Failed to parse vOrg mappings");
}
}
this->m_data = data;
this->m_length = length;
return true;
}
bool OpenTypeVVAR::Serialize(OTSStream* out) {
if (!out->Write(this->m_data, this->m_length)) {
return Error("Failed to write VVAR table");
}
return true;
}
} // namespace ots

31
gfx/ots/src/vvar.h Normal file
Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) 2018 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef OTS_VVAR_H_
#define OTS_VVAR_H_
#include "ots.h"
namespace ots {
// -----------------------------------------------------------------------------
// OpenTypeVVAR Interface
// -----------------------------------------------------------------------------
class OpenTypeVVAR : public Table {
public:
explicit OpenTypeVVAR(Font* font, uint32_t tag)
: Table(font, tag, tag) { }
bool Parse(const uint8_t* data, size_t length);
bool Serialize(OTSStream* out);
private:
const uint8_t *m_data;
size_t m_length;
};
} // namespace ots
#endif // OTS_VVAR_H_

Просмотреть файл

@ -472,7 +472,7 @@ private:
DECL_GFX_PREF(Once, "gfx.direct3d11.break-on-error", Direct3D11BreakOnError, bool, false);
DECL_GFX_PREF(Once, "gfx.direct3d11.sleep-on-create-device", Direct3D11SleepOnCreateDevice, int32_t, 0);
DECL_GFX_PREF(Live, "gfx.downloadable_fonts.keep_color_bitmaps", KeepColorBitmaps, bool, false);
DECL_GFX_PREF(Live, "gfx.downloadable_fonts.keep_variation_tables", KeepVariationTables, bool, false);
DECL_GFX_PREF(Live, "gfx.downloadable_fonts.validate_variation_tables", ValidateVariationTables, bool, true);
DECL_GFX_PREF(Live, "gfx.downloadable_fonts.otl_validation", ValidateOTLTables, bool, true);
DECL_GFX_PREF(Live, "gfx.draw-color-bars", CompositorDrawColorBars, bool, false);
DECL_GFX_PREF(Once, "gfx.e10s.hide-plugins-for-scroll", HidePluginsForScroll, bool, true);

Просмотреть файл

@ -183,7 +183,7 @@ public:
// Whether to apply OTS validation to OpenType Layout tables
mCheckOTLTables = gfxPrefs::ValidateOTLTables();
// Whether to preserve Variation tables in downloaded fonts
mKeepVariationTables = gfxPrefs::KeepVariationTables();
mCheckVariationTables = gfxPrefs::ValidateVariationTables();
// Whether to preserve color bitmap glyphs
mKeepColorBitmaps = gfxPrefs::KeepColorBitmaps();
}
@ -195,7 +195,7 @@ public:
(aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') ||
aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') ||
aTag == TRUETYPE_TAG('G', 'S', 'U', 'B'))) ||
(mKeepVariationTables &&
(!mCheckVariationTables &&
(aTag == TRUETYPE_TAG('a', 'v', 'a', 'r') ||
aTag == TRUETYPE_TAG('c', 'v', 'a', 'r') ||
aTag == TRUETYPE_TAG('f', 'v', 'a', 'r') ||
@ -242,7 +242,7 @@ private:
gfxUserFontEntry* mUserFontEntry;
nsTHashtable<nsCStringHashKey> mWarningsIssued;
bool mCheckOTLTables;
bool mKeepVariationTables;
bool mCheckVariationTables;
bool mKeepColorBitmaps;
};

Просмотреть файл

@ -348,7 +348,7 @@ diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
} else {
// Specialized scalers and rotation.
-#if USE_MMX && defined(_MSC_VER)
+#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_MSC_VER) && defined(_M_IX86)
+#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_MSC_VER) && defined(_M_IX86) && !defined(__clang__)
+ if(mozilla::supports_sse()) {
if (width == (source_width * 2)) {
- DoubleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,

Просмотреть файл

@ -34,7 +34,7 @@ if CONFIG['INTEL_ARCHITECTURE']:
SOURCES['yuv_convert_mmx.cpp'].flags += CONFIG['MMX_FLAGS']
if CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
if CONFIG['OS_TEST'] == 'x86_64':
if CONFIG['OS_TEST'] == 'x86_64' or CONFIG['CC_TYPE'] == 'clang-cl':
SOURCES += [
'yuv_row_win64.cpp',
]

Просмотреть файл

@ -487,7 +487,7 @@ void ScaleYCbCrToRGB32_deprecated(const uint8* y_buf,
dest_pixel, width, source_dx);
} else {
// Specialized scalers and rotation.
#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_MSC_VER) && defined(_M_IX86)
#if defined(MOZILLA_MAY_SUPPORT_SSE) && defined(_MSC_VER) && defined(_M_IX86) && !defined(__clang__)
if(mozilla::supports_sse()) {
if (width == (source_width * 2)) {
DoubleYUVToRGB32Row_SSE(y_ptr, u_ptr, v_ptr,

Просмотреть файл

@ -183,15 +183,8 @@ static void
WeakCollection_finalize(FreeOp* fop, JSObject* obj)
{
MOZ_ASSERT(fop->maybeOnHelperThread());
if (ObjectValueMap* map = obj->as<WeakCollectionObject>().getMap()) {
#ifdef DEBUG
map->~ObjectValueMap();
memset(static_cast<void*>(map), 0xdc, sizeof(*map));
fop->free_(map);
#else
if (ObjectValueMap* map = obj->as<WeakCollectionObject>().getMap())
fop->delete_(map);
#endif
}
}
JS_PUBLIC_API(JSObject*)

Просмотреть файл

@ -591,6 +591,8 @@ BaselineCacheIRCompiler::emitMegamorphicLoadSlotResult()
masm.adjustStack(sizeof(Value));
masm.branchIfFalseBool(scratch2, failure->label());
if (JitOptions.spectreJitToCxxCalls)
masm.speculationBarrier();
return true;
}

Просмотреть файл

@ -2826,6 +2826,8 @@ CacheIRCompiler::emitMegamorphicLoadSlotByValueResult()
masm.jump(failure->label());
masm.bind(&ok);
if (JitOptions.spectreJitToCxxCalls)
masm.speculationBarrier();
masm.setFramePushed(framePushed);
masm.loadTypedOrValue(Address(masm.getStackPointer(), 0), output);
masm.adjustStack(sizeof(Value));

Просмотреть файл

@ -1016,6 +1016,8 @@ IonCacheIRCompiler::emitMegamorphicLoadSlotResult()
masm.adjustStack(sizeof(Value));
masm.branchIfFalseBool(scratch2, failure->label());
if (JitOptions.spectreJitToCxxCalls)
masm.speculationBarrier();
return true;
}
@ -1209,6 +1211,9 @@ IonCacheIRCompiler::emitCallNativeGetterResult()
Address outparam(masm.getStackPointer(), IonOOLNativeExitFrameLayout::offsetOfResult());
masm.loadValue(outparam, output.valueReg());
if (JitOptions.spectreJitToCxxCalls)
masm.speculationBarrier();
masm.adjustStack(IonOOLNativeExitFrameLayout::Size(0));
return true;
}
@ -1268,6 +1273,10 @@ IonCacheIRCompiler::emitCallProxyGetResult()
Address outparam(masm.getStackPointer(), IonOOLProxyExitFrameLayout::offsetOfResult());
masm.loadValue(outparam, output.valueReg());
// Spectre mitigation in case of speculative execution within C++ code.
if (JitOptions.spectreJitToCxxCalls)
masm.speculationBarrier();
// masm.leaveExitFrame & pop locals
masm.adjustStack(IonOOLProxyExitFrameLayout::Size());
return true;

Просмотреть файл

@ -597,19 +597,6 @@ mozilla::TimeStamp PresShell::sLastInputProcessed;
bool PresShell::sProcessInteractable = false;
#ifdef DEBUG
static void
VerifyStyleTree(nsPresContext* aPresContext, nsFrameManager* aFrameManager)
{
if (nsFrame::GetVerifyStyleTreeEnable()) {
NS_ERROR("stylo: cannot verify style tree with a ServoRestyleManager");
}
}
#define VERIFY_STYLE_TREE ::VerifyStyleTree(mPresContext, mFrameConstructor)
#else
#define VERIFY_STYLE_TREE
#endif
static bool gVerifyReflowEnabled;
bool
@ -1820,7 +1807,6 @@ PresShell::Initialize()
// content object down
mFrameConstructor->ContentInserted(
nullptr, root, nullptr, nsCSSFrameConstructor::InsertionKind::Sync);
VERIFY_STYLE_TREE;
// Something in mFrameConstructor->ContentInserted may have caused
// Destroy() to get called, bug 337586.
@ -4383,7 +4369,6 @@ PresShell::CharacterDataChanged(nsIContent* aContent,
mPresContext->RestyleManager()->CharacterDataChanged(aContent, aInfo);
mFrameConstructor->CharacterDataChanged(aContent, aInfo);
VERIFY_STYLE_TREE;
}
void
@ -4397,7 +4382,6 @@ PresShell::ContentStateChanged(nsIDocument* aDocument,
if (mDidInitialize) {
nsAutoCauseReflowNotifier crNotifier(this);
mPresContext->RestyleManager()->ContentStateChanged(aContent, aStateMask);
VERIFY_STYLE_TREE;
}
}
@ -4437,7 +4421,6 @@ PresShell::AttributeWillChange(Element* aElement,
mPresContext->RestyleManager()->AttributeWillChange(aElement, aNameSpaceID,
aAttribute, aModType,
aNewValue);
VERIFY_STYLE_TREE;
}
}
@ -4459,7 +4442,6 @@ PresShell::AttributeChanged(Element* aElement,
mPresContext->RestyleManager()->AttributeChanged(aElement, aNameSpaceID,
aAttribute, aModType,
aOldValue);
VERIFY_STYLE_TREE;
}
}
@ -4490,8 +4472,6 @@ PresShell::ContentAppended(nsIContent* aFirstNewContent)
container,
aFirstNewContent,
nsCSSFrameConstructor::InsertionKind::Async);
VERIFY_STYLE_TREE;
}
void
@ -4517,8 +4497,6 @@ PresShell::ContentInserted(nsIContent* aChild)
aChild,
nullptr,
nsCSSFrameConstructor::InsertionKind::Async);
VERIFY_STYLE_TREE;
}
void
@ -4560,8 +4538,6 @@ PresShell::ContentRemoved(nsIContent* aChild, nsIContent* aPreviousSibling)
mFrameConstructor->ContentRemoved(
aChild->GetParent(), aChild, oldNextSibling,
nsCSSFrameConstructor::REMOVE_CONTENT);
VERIFY_STYLE_TREE;
}
void
@ -4596,7 +4572,6 @@ PresShell::ReconstructFrames()
nsAutoCauseReflowNotifier crNotifier(this);
mFrameConstructor->ReconstructDocElementHierarchy(nsCSSFrameConstructor::InsertionKind::Sync);
VERIFY_STYLE_TREE;
}
void
@ -9748,12 +9723,6 @@ PresShell::ListStyleSheets(FILE *out, int32_t aIndent)
fputs("\n", out);
}
}
void
PresShell::VerifyStyleTree()
{
VERIFY_STYLE_TREE;
}
#endif
//=============================================================

Просмотреть файл

@ -320,7 +320,6 @@ public:
void ListComputedStyles(FILE *out, int32_t aIndent = 0) override;
void ListStyleSheets(FILE *out, int32_t aIndent = 0) override;
void VerifyStyleTree() override;
#endif
static LazyLogModule gLog;

Просмотреть файл

@ -621,18 +621,6 @@ RestyleManager::ChangeHintToString(nsChangeHint aHint)
static bool gInApplyRenderingChangeToTree = false;
#endif
#ifdef DEBUG
void
RestyleManager::DebugVerifyStyleTree(nsIFrame* aFrame)
{
// XXXheycam For now, we know that we don't use the same inheritance
// hierarchy for certain cases, so just skip these assertions until
// we work out what we want to assert (bug 1322570).
}
#endif // DEBUG
/**
* Sync views on aFrame and all of aFrame's descendants (following placeholders),
* if aChange has nsChangeHint_SyncFrameView.
@ -1709,24 +1697,6 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
}
}
#ifdef DEBUG
// Verify the style tree. Note that this needs to happen once we've
// processed the whole list, since until then the tree is not in fact in a
// consistent state.
for (const nsStyleChangeData& data : aChangeList) {
// reget frame from content since it may have been regenerated...
if (data.mContent) {
nsIFrame* frame = data.mContent->GetPrimaryFrame();
if (frame) {
DebugVerifyStyleTree(frame);
}
} else if (!data.mFrame || !data.mFrame->IsViewportFrame()) {
NS_WARNING("Unable to test style tree integrity -- no content node "
"(and not a viewport frame)");
}
}
#endif
aChangeList.Clear();
}

Просмотреть файл

@ -1069,7 +1069,6 @@ public:
virtual void ListComputedStyles(FILE *out, int32_t aIndent = 0) = 0;
virtual void ListStyleSheets(FILE *out, int32_t aIndent = 0) = 0;
virtual void VerifyStyleTree() = 0;
#endif
#ifdef ACCESSIBILITY

Просмотреть файл

@ -309,25 +309,6 @@ bool nsFrame::GetShowEventTargetFrameBorder()
*/
mozilla::LazyLogModule nsFrame::sFrameLogModule("frame");
static mozilla::LazyLogModule sStyleVerifyTreeLogModuleInfo("styleverifytree");
static uint32_t gStyleVerifyTreeEnable = 0x55;
bool
nsFrame::GetVerifyStyleTreeEnable()
{
if (gStyleVerifyTreeEnable == 0x55) {
gStyleVerifyTreeEnable = 0 != (int)((mozilla::LogModule*)sStyleVerifyTreeLogModuleInfo)->Level();
}
return gStyleVerifyTreeEnable;
}
void
nsFrame::SetVerifyStyleTreeEnable(bool aEnabled)
{
gStyleVerifyTreeEnable = aEnabled;
}
#endif
NS_DECLARE_FRAME_PROPERTY_DELETABLE(AbsoluteContainingBlockProperty,

Просмотреть файл

@ -706,8 +706,9 @@ private:
// Returns true if this frame has any kind of CSS transitions.
bool HasCSSTransitions();
#ifdef DEBUG_FRAME_DUMP
public:
#ifdef DEBUG_FRAME_DUMP
/**
* Get a printable from of the name of the frame type.
* XXX This should be eliminated and we use GetType() instead...
@ -720,20 +721,6 @@ public:
#endif
#ifdef DEBUG
public:
/**
* See if style tree verification is enabled. To enable style tree
* verification add "styleverifytree:1" to your MOZ_LOG
* environment variable (any non-zero debug level will work). Or,
* call SetVerifyStyleTreeEnable with true.
*/
static bool GetVerifyStyleTreeEnable();
/**
* Set the verify-style-tree enable flag.
*/
static void SetVerifyStyleTreeEnable(bool aEnabled);
static mozilla::LazyLogModule sFrameLogModule;
// Show frame borders when rendering
@ -743,11 +730,8 @@ public:
// Show frame border of event target
static void ShowEventTargetFrameBorder(bool aEnable);
static bool GetShowEventTargetFrameBorder();
#endif
public:
static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayList& aList,
bool aDumpHtml = false)

Просмотреть файл

@ -1,5 +1,5 @@
# enable variation font support
default-preferences pref(layout.css.font-variations.enabled,true) pref(gfx.downloadable_fonts.keep_variation_tables,true)
default-preferences pref(layout.css.font-variations.enabled,true)
# Currently, debug Linux builds hit a fatal assertion inside Skia, so skip until that is resolved (bug 1442669).
skip-if(skiaContent&&isDebugBuild) == font-optical-sizing-1.html font-optical-sizing-1-ref.html

Просмотреть файл

@ -838,8 +838,8 @@ pref("gfx.downloadable_fonts.otl_validation", true);
// to render fonts (Linux/Gtk and Android).
pref("gfx.downloadable_fonts.keep_color_bitmaps", false);
// Whether to preserve OpenType variation tables in fonts (bypassing OTS)
pref("gfx.downloadable_fonts.keep_variation_tables", true);
// Whether to validate OpenType variation tables in fonts
pref("gfx.downloadable_fonts.validate_variation_tables", true);
#ifdef ANDROID
pref("gfx.bundled_fonts.enabled", true);
@ -2616,6 +2616,11 @@ pref("security.notification_enable_delay", 500);
pref("security.csp.enable", true);
pref("security.csp.experimentalEnabled", false);
pref("security.csp.enableStrictDynamic", true);
#if defined(DEBUG) && !defined(ANDROID)
pref("csp.content_privileged_about_uris_without_csp", "blank,blocked,cache,certerror,checkerboard,credits,home,logo,neterror,newtab,printpreview,rights,srcdoc,studies");
#endif
#ifdef NIGHTLY_BUILD
pref("security.csp.enable_violation_events", true);
#else

Просмотреть файл

@ -1769,9 +1769,7 @@ if test -n "$_USE_SYSTEM_NSS"; then
AM_PATH_NSS(3.36, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
fi
if test -n "$MOZ_SYSTEM_NSS"; then
NSS_LIBS="$NSS_LIBS -lcrmf"
else
if test -z "$MOZ_SYSTEM_NSS"; then
NSS_CFLAGS="-I${DIST}/include/nss"
case "${OS_ARCH}" in
# Only few platforms have been tested with GYP

Просмотреть файл

@ -1 +1 @@
6ae3ab8a1e7b
954032211d2d

Просмотреть файл

@ -10,3 +10,4 @@
*/
#error "Do not include this header file."

Просмотреть файл

@ -1000,6 +1000,39 @@ TEST_P(HelloRetryRequestAgentTest, HandleNoopHelloRetryRequest) {
SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
}
class ReplaceRandom : public TlsHandshakeFilter {
public:
ReplaceRandom(const std::shared_ptr<TlsAgent>& a, const DataBuffer& r)
: TlsHandshakeFilter(a, {kTlsHandshakeServerHello}), random_(r) {}
PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) override {
output->Assign(input);
output->Write(2, random_);
return CHANGE;
}
private:
DataBuffer random_;
};
// Make sure that the TLS 1.3 special value for the ServerHello.random
// is rejected by earlier versions.
TEST_P(TlsConnectStreamPre13, HrrRandomOnTls10) {
static const uint8_t hrr_random[] = {
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C,
0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB,
0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C};
EnsureTlsSetup();
MakeTlsFilter<ReplaceRandom>(server_,
DataBuffer(hrr_random, sizeof(hrr_random)));
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
INSTANTIATE_TEST_CASE_P(HelloRetryRequestAgentTests, HelloRetryRequestAgentTest,
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
TlsConnectTestBase::kTlsV13));

Просмотреть файл

@ -272,14 +272,9 @@
},
}],
[ 'cc_use_gnu_ld==1 and OS=="win" and target_arch=="x64"', {
# mingw x64
'defines': [
'MP_IS_LITTLE_ENDIAN',
'NSS_BEVAND_ARCFOUR',
'MPI_AMD64',
'MP_ASSEMBLY_MULTIPLY',
'NSS_USE_COMBA',
'USE_HW_AES',
'INTEL_GCM',
],
}],
[ 'OS!="win"', {

Просмотреть файл

@ -123,6 +123,11 @@
'intel-gcm-x86-masm.asm',
],
}],
[ 'cc_use_gnu_ld==1', {
# mingw
'sources': [
],
}],
[ 'cc_is_clang!=1', {
# MSVC
'sources': [

Просмотреть файл

@ -6288,7 +6288,7 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
/* The server didn't pick 1.3 although we either received a
* HelloRetryRequest, or we prepared to send early app data. */
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
if (ss->ssl3.hs.helloRetry) {
if (isHelloRetry || ss->ssl3.hs.helloRetry) {
/* SSL3_SendAlert() will uncache the SID. */
desc = illegal_parameter;
errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;

Просмотреть файл

@ -112,6 +112,7 @@ reftest:
macosx64.*/debug: 3
windows.*/opt: 2
windows.*/debug: 4
windows10-64-ccov/debug: 6
default: 8
e10s:
by-test-platform:
@ -120,6 +121,7 @@ reftest:
max-run-time:
by-test-platform:
android.*: 7200
windows10-64-ccov/debug: 5400
default: 3600
mozharness:
chunked:

Просмотреть файл

@ -18,8 +18,8 @@ toolkit.jar:
res/payments/debugging.css (res/debugging.css)
res/payments/debugging.html (res/debugging.html)
res/payments/debugging.js (res/debugging.js)
res/payments/formautofill/autofillEditForms.js (../../../../browser/extensions/formautofill/content/autofillEditForms.js)
res/payments/formautofill/editCreditCard.xhtml (../../../../browser/extensions/formautofill/content/editCreditCard.xhtml)
res/payments/formautofill/autofillEditForms.js (../../../browser/extensions/formautofill/content/autofillEditForms.js)
res/payments/formautofill/editCreditCard.xhtml (../../../browser/extensions/formautofill/content/editCreditCard.xhtml)
res/payments/unprivileged-fallbacks.js (res/unprivileged-fallbacks.js)
res/payments/mixins/ (res/mixins/*.js)
res/payments/PaymentsStore.js (res/PaymentsStore.js)

Просмотреть файл

@ -758,7 +758,6 @@ var Impl = {
if (!Utils.isContentProcess && Telemetry.canRecordExtended) {
try {
ret.addonManager = AddonManagerPrivate.getSimpleMeasures();
ret.UITelemetry = UITelemetry.getSimpleMeasures();
} catch (ex) {}
}

Просмотреть файл

@ -164,6 +164,8 @@ Only available in the extended set of measures, it contains a set of counters re
UITelemetry
~~~~~~~~~~~
As of Firefox 61 this section is no longer present.
Only available in the extended set of measures. For more see :ref:`uitelemetry`.
startupInterrupted
@ -632,10 +634,6 @@ Structure:
...
}
UITelemetry
-----------
See the ``UITelemetry data format`` documentation.
slowSQL
-------
This section contains the information about the slow SQL queries for both the main and other threads. The execution of an SQL statement is considered slow if it takes 50ms or more on the main thread or 100ms or more on other threads. Slow SQL statements will be automatically trimmed to 1000 characters. This limit doesn't include the ellipsis and database name, that are appended at the end of the stored statement.
@ -699,3 +697,4 @@ Version History
- Stopped reporting ``childPayloads`` (`bug 1443599 <https://bugzilla.mozilla.org/show_bug.cgi?id=1443599>`_).
- Stopped reporting ``saved-session`` pings on Firefox Desktop (`bug 1443603 <https://bugzilla.mozilla.org/show_bug.cgi?id=1443603>`_).
- Stopped reporting ``UITelemetry`` (`bug 1443605 <https://bugzilla.mozilla.org/show_bug.cgi?id=1443605>`_)

Просмотреть файл

@ -2103,7 +2103,7 @@ add_task(async function test_pingExtendedStats() {
Assert.ok(!("addonManager" in ping.payload.simpleMeasurements),
"addonManager must not be sent if the extended set is off.");
Assert.ok(!("UITelemetry" in ping.payload.simpleMeasurements),
"UITelemetry must not be sent if the extended set is off.");
"UITelemetry must not be sent.");
// Restore the preference.
Telemetry.canRecordExtended = true;
@ -2121,8 +2121,8 @@ add_task(async function test_pingExtendedStats() {
Assert.ok("addonManager" in ping.payload.simpleMeasurements,
"addonManager must be sent if the extended set is on.");
Assert.ok("UITelemetry" in ping.payload.simpleMeasurements,
"UITelemetry must be sent if the extended set is on.");
Assert.ok(!("UITelemetry" in ping.payload.simpleMeasurements),
"UITelemetry must not be sent.");
await TelemetryController.testShutdown();
});