Merge mozilla-central to mozilla-inbound. r=merge a=merge CLOSED TREE

This commit is contained in:
Noemi Erli 2017-11-15 12:15:40 +02:00
Родитель e225e00cb0 550148ab69
Коммит f24a75f9b7
326 изменённых файлов: 4325 добавлений и 7041 удалений

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

@ -49,7 +49,7 @@
// 'labelled by'/'label for' relations for xul:tab and xul:tabpanel
var tabs = tabBrowser().tabContainer.childNodes;
var panels = tabBrowser().mTabBox.tabpanels.childNodes;
var panels = tabBrowser().tabbox.tabpanels.childNodes;
testRelation(panels[0], RELATION_LABELLED_BY, tabs[0]);
testRelation(tabs[0], RELATION_LABEL_FOR, panels[0]);

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

@ -213,7 +213,7 @@
]
};
testAccessibleTree(tabBrowser().mTabBox.tabpanels, tabboxAccTree);
testAccessibleTree(tabBrowser().tabbox.tabpanels, tabboxAccTree);
}
this.getID = function testTabHierarchy_getID()

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

@ -183,7 +183,7 @@ Compatibility::Init()
if (::GetModuleHandleW(L"nvdaHelperRemote"))
sConsumers |= NVDA;
if (::GetModuleHandleW(L"OsmHooks"))
if (::GetModuleHandleW(L"OsmHooks") || ::GetModuleHandleW(L"OsmHks64"))
sConsumers |= COBRA;
if (::GetModuleHandleW(L"WebFinderRemote"))

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

@ -1464,6 +1464,8 @@ pref("media.eme.vp9-in-mp4.enabled", true);
pref("media.eme.vp9-in-mp4.enabled", false);
#endif
pref("media.eme.hdcp-policy-check.enabled", false);
// Whether we should run a test-pattern through EME GMPs before assuming they'll
// decode H.264.
pref("media.gmp.trial-create.enabled", true);

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

@ -547,7 +547,7 @@ var ctrlTab = {
tabContainer[toggleEventListener]("TabClose", this);
document[toggleEventListener]("keypress", this);
gBrowser.mTabBox.handleCtrlTab = !enable;
gBrowser.tabbox.handleCtrlTab = !enable;
if (enable)
PageThumbs.addExpirationFilter(this);

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

@ -69,7 +69,7 @@
Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
.getService(Components.interfaces.mozIPlacesAutoComplete);
</field>
<field name="mTabBox" readonly="true">
<field name="tabbox" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "tabbox");
</field>
<field name="mPanelContainer" readonly="true">
@ -1422,6 +1422,12 @@
this.tabContainer._setPositionalAttributes();
// Enable touch events to start a native dragging
// session to allow the user to easily drag the selected tab.
// This is currently only supported on Windows.
oldTab.removeAttribute("touchdownstartsdrag");
this.mCurrentTab.setAttribute("touchdownstartsdrag", "true");
if (!gMultiProcessBrowser) {
document.commandDispatcher.unlock();
@ -3931,10 +3937,10 @@
<setter>
<![CDATA[
if (gNavToolbox.collapsed && !this._allowTabChange) {
return this.mTabBox.selectedTab;
return this.tabbox.selectedTab;
}
// Update the tab
this.mTabBox.selectedTab = val;
this.tabbox.selectedTab = val;
return val;
]]>
</setter>
@ -4621,7 +4627,7 @@
this.maybeVisibleTabs.add(showTab);
let tabs = this.tabbrowser.mTabBox.tabs;
let tabs = this.tabbrowser.tabbox.tabs;
let tabPanel = this.tabbrowser.mPanelContainer;
let showPanel = tabs.getRelatedElement(showTab);
let index = Array.indexOf(tabPanel.childNodes, showPanel);
@ -6425,7 +6431,7 @@
</field>
<field name="tabbox" readonly="true">
this.tabbrowser.mTabBox;
this.tabbrowser.tabbox;
</field>
<field name="contextMenu" readonly="true">

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

@ -29,7 +29,7 @@ add_task(async function() {
is(win.gBrowser.browsers.length, 1, "Window has one browser");
is(win.gBrowser.selectedTab, newTab, "Remaining tab is selected");
is(win.gBrowser.selectedBrowser, newBrowser, "Browser for remaining tab is selected");
is(win.gBrowser.mTabBox.selectedPanel, newBrowser.parentNode.parentNode.parentNode.parentNode, "Panel for remaining tab is selected");
is(win.gBrowser.tabbox.selectedPanel, newBrowser.parentNode.parentNode.parentNode.parentNode, "Panel for remaining tab is selected");
}
await promiseWindowClosed(win);

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

@ -57,11 +57,11 @@ add_task(async function test() {
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+PageUp on Tab2");
if (gBrowser.mTabBox._handleMetaAltArrows) {
if (gBrowser.tabbox._handleMetaAltArrows) {
gBrowser.selectedTab = tab1;
browser1.focus();
let ltr = window.getComputedStyle(gBrowser.mTabBox).direction == "ltr";
let ltr = window.getComputedStyle(gBrowser.tabbox).direction == "ltr";
let advanceKey = ltr ? "VK_RIGHT" : "VK_LEFT";
let reverseKey = ltr ? "VK_LEFT" : "VK_RIGHT";
@ -109,7 +109,7 @@ add_task(async function test() {
// XXX Currently, Command + "{" and "}" don't work if keydown event is
// consumed because following keypress event isn't fired.
let ltr = window.getComputedStyle(gBrowser.mTabBox).direction == "ltr";
let ltr = window.getComputedStyle(gBrowser.tabbox).direction == "ltr";
let advanceKey = ltr ? "}" : "{";
let reverseKey = ltr ? "{" : "}";

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

@ -896,11 +896,9 @@ CustomizeMode.prototype = {
let removable = aPlace == "palette" || CustomizableUI.isWidgetRemovable(aNode);
wrapper.setAttribute("removable", removable);
if (AppConstants.platform == "win") {
// Allow touch events to initiate dragging in customize mode.
// This is only supported on Windows for now.
wrapper.setAttribute("touchdownstartsdrag", "true");
}
// Allow touch events to initiate dragging in customize mode.
// This is only supported on Windows for now.
wrapper.setAttribute("touchdownstartsdrag", "true");
let contextMenuAttrName = "";
if (aNode.getAttribute("context")) {

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

@ -3279,7 +3279,7 @@ var SessionStoreInternal = {
tabMap.set(tab, tabData);
tabsData.push(tabData);
}
winData.selected = tabbrowser.mTabBox.selectedIndex + 1;
winData.selected = tabbrowser.tabbox.selectedIndex + 1;
this._updateWindowFeatures(aWindow);

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

@ -10,32 +10,34 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/TelemetryController.jsm");
Cu.import("resource://gre/modules/Timer.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.importGlobalProperties(["URL"]);
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
"resource://gre/modules/LightweightThemeManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ResetProfile",
"resource://gre/modules/ResetProfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
"resource://gre/modules/UITelemetry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
"resource:///modules/BrowserUITelemetry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
"resource://gre/modules/FxAccounts.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
"resource://gre/modules/LightweightThemeManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PageActions",
"resource:///modules/PageActions.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
"resource://gre/modules/ProfileAge.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
"resource:///modules/ReaderParent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PageActions",
"resource:///modules/PageActions.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
"resource://gre/modules/FxAccounts.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ResetProfile",
"resource://gre/modules/ResetProfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
"resource://gre/modules/UITelemetry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm");
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
const PREF_LOG_LEVEL = "browser.uitour.loglevel";
@ -1620,9 +1622,7 @@ this.UITour = {
getAppInfo(aMessageManager, aWindow, aCallbackID) {
(async () => {
let props = ["defaultUpdateChannel", "version"];
let appinfo = {};
props.forEach(property => appinfo[property] = Services.appinfo[property]);
let appinfo = {version: Services.appinfo.version};
// Identifier of the partner repack, as stored in preference "distribution.id"
// and included in Firefox and other update pings. Note this is not the same as
@ -1631,6 +1631,9 @@ this.UITour = {
Services.prefs.getDefaultBranch("distribution.").getCharPref("id", "default");
appinfo.distribution = distribution;
// Update channel, in a way that preserves 'beta' for RC beta builds:
appinfo.defaultUpdateChannel = UpdateUtils.getUpdateChannel(false /* no partner ID */);
let isDefaultBrowser = null;
try {
let shell = aWindow.getShellService();

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

@ -9,6 +9,7 @@ var gContentWindow;
Components.utils.import("resource://testing-common/TelemetryArchiveTesting.jsm", this);
Components.utils.import("resource://gre/modules/ProfileAge.jsm", this);
Components.utils.import("resource://gre/modules/UpdateUtils.jsm", this);
function test() {
@ -291,11 +292,9 @@ var tests = [
}),
function test_getConfigurationVersion(done) {
function callback(result) {
let props = ["defaultUpdateChannel", "version"];
for (let property of props) {
ok(typeof(result[property]) !== "undefined", "Check " + property + " isn't undefined.");
is(result[property], Services.appinfo[property], "Should have the same " + property + " property.");
}
ok(typeof result.version !== "undefined", "Check version isn't undefined.");
is(result.version, Services.appinfo.version, "Should have the same version property.");
is(result.defaultUpdateChannel, UpdateUtils.getUpdateChannel(false), "Should have the correct update channel.");
done();
}

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

@ -155,6 +155,7 @@ xul|richlistitem[originaltype="autofill-insecureWarning"] {
background-color: #EDEDED;
font-size: calc(var(--option-btn-font-size) / var(--default-font-size) * 1em);
color: var(--option-btn-text-color);
text-align: center;
}
.autofill-footer[no-warning="true"] > .autofill-warning {

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

@ -86,7 +86,7 @@
* doesn't reverse the order of the items in the titlebar in RTL mode. */
.titlebar-placeholder[type="caption-buttons"],
#titlebar-buttonbox {
margin-left: 7px;
margin-left: 12px;
}
/* The fullscreen button doesnt show on Yosemite(10.10) or above so dont give it a

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

@ -165,9 +165,9 @@ class RemoteAutomation(Automation):
def deleteTombstones(self):
# delete any existing tombstone files from device
remoteDir = "/data/tombstones"
tombstones = "/data/tombstones/*"
try:
self._devicemanager.shellCheckOutput(['rm', '-r', remoteDir], root=True,
self._devicemanager.shellCheckOutput(['rm', '-r', tombstones], root=True,
timeout=DeviceManager.short_timeout)
except DMError:
# This may just indicate that the tombstone directory is missing

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

@ -306,6 +306,7 @@ def old_configure_options(*options):
@imports('sys')
@imports(_from='mozbuild.shellutil', _import='quote')
@imports(_from='mozbuild.shellutil', _import='split')
@imports(_from='mozbuild.util', _import='encode')
def old_configure(prepare_configure, extra_old_configure_args, all_options,
*options):
cmd = prepare_configure
@ -319,7 +320,7 @@ def old_configure(prepare_configure, extra_old_configure_args, all_options,
if value.origin != 'default'
]
env = os.environ
env = dict(os.environ)
extra_env = {}
# We also pass it the options from js/moz.configure so that it can pass
@ -335,7 +336,6 @@ def old_configure(prepare_configure, extra_old_configure_args, all_options,
extra_env[k] = v
if extra_env:
env = dict(env)
env.update(extra_env)
# For debugging purpose, in case it's not what we'd expect.
@ -356,7 +356,7 @@ def old_configure(prepare_configure, extra_old_configure_args, all_options,
log_size = os.path.getsize('config.log')
ret = subprocess.call(cmd)
ret = subprocess.call(cmd, env=encode(env))
if ret:
with log.queue_debug():
with encoded_open('config.log', 'r') as fh:

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

@ -81,20 +81,20 @@ add_old_configure_assignment('_YASM_MINOR_VERSION',
def yasm_asflags(yasm, target):
if yasm:
asflags = {
('OSX', 'x86'): '-f macho32',
('OSX', 'x86_64'): '-f macho64',
('WINNT', 'x86'): '-f win32',
('WINNT', 'x86_64'): '-f x64',
('OSX', 'x86'): ['-f', 'macho32'],
('OSX', 'x86_64'): ['-f', 'macho64'],
('WINNT', 'x86'): ['-f', 'win32'],
('WINNT', 'x86_64'): ['-f', 'x64'],
}.get((target.os, target.cpu), None)
if asflags is None:
# We're assuming every x86 platform we support that's
# not Windows or Mac is ELF.
if target.cpu == 'x86':
asflags = '-f elf32'
asflags = ['-f', 'elf32']
elif target.cpu == 'x86_64':
asflags = '-f elf64'
asflags = ['-f', 'elf64']
if asflags:
asflags += ' -rnasm -pnasm'
asflags += ['-rnasm', '-pnasm']
return asflags
@ -1351,7 +1351,7 @@ def rust_compiler_flags(opt_level_option, debug_rust, debug_symbols,
debug_assertions = None
debug_info = None
if opt_level_option.origin != 'default':
if opt_level_option:
opt_level = opt_level_option[0]
else:
opt_level = '1' if optimize else '0'

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

@ -32,28 +32,8 @@ ifeq "$(CWD)" "/"
CWD := /.
endif
ifndef TOPSRCDIR
ifeq (,$(wildcard client.mk))
TOPSRCDIR := $(patsubst %/,%,$(dir $(MAKEFILE_LIST)))
else
TOPSRCDIR := $(CWD)
endif
endif
PYTHON ?= $(shell which python2.7 > /dev/null 2>&1 && echo python2.7 || echo python)
CONFIG_GUESS := $(shell $(TOPSRCDIR)/build/autoconf/config.guess)
####################################
# Sanity checks
# Windows checks.
ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
# Set this for baseconfig.mk
HOST_OS_ARCH=WINNT
endif
####################################
# Load mozconfig Options
@ -69,23 +49,14 @@ endef
# before evaluation. $(shell) replacing newlines with spaces, || is always
# followed by a space (since sed doesn't remove newlines), except on the
# last line, so replace both '|| ' and '||'.
MOZCONFIG_CONTENT := $(subst ||,$(CR),$(subst || ,$(CR),$(shell $(TOPSRCDIR)/mach environment --format=client.mk | sed 's/$$/||/')))
$(eval $(MOZCONFIG_CONTENT))
export FOUND_MOZCONFIG
MOZCONFIG_CONTENT := $(subst ||,$(CR),$(subst || ,$(CR),$(shell cat $(OBJDIR)/.mozconfig-client-mk | sed 's/$$/||/')))
include $(OBJDIR)/.mozconfig-client-mk
# As '||' was used as a newline separator, it means it's not occurring in
# lines themselves. It can thus safely be used to replaces normal spaces,
# to then replace newlines with normal spaces. This allows to get a list
# of mozconfig output lines.
MOZCONFIG_OUT_LINES := $(subst $(CR), ,$(subst $(NULL) $(NULL),||,$(MOZCONFIG_CONTENT)))
# Filter-out comments from those lines.
START_COMMENT = \#
MOZCONFIG_OUT_FILTERED := $(filter-out $(START_COMMENT)%,$(MOZCONFIG_OUT_LINES))
ifdef AUTOCLOBBER
export AUTOCLOBBER=1
endif
ifdef MOZ_PARALLEL_BUILD
MOZ_MAKE_FLAGS := $(filter-out -j%,$(MOZ_MAKE_FLAGS))
@ -110,9 +81,6 @@ MOZ_MAKE = $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
CONFIGURES := $(TOPSRCDIR)/configure
CONFIGURES += $(TOPSRCDIR)/js/src/configure
# Make targets that are going to be passed to the real build system
OBJDIR_TARGETS = install export libs clean realclean distclean upload sdk installer package package-compare stage-package source-package l10n-check automation/build
#######################################################################
# Rules
@ -124,17 +92,9 @@ $(error client.mk must be used via `mach`. Try running \
`./mach $(firstword $(MAKECMDGOALS) $(.DEFAULT_GOAL))`)
endif
# Include baseconfig.mk for its $(MAKE) validation.
include $(TOPSRCDIR)/config/baseconfig.mk
# Define mkdir
include $(TOPSRCDIR)/config/makefiles/makeutils.mk
include $(TOPSRCDIR)/config/makefiles/autotargets.mk
# For now, only output "export" lines and lines containing UPLOAD_EXTRA_FILES
# from mach environment --format=client.mk output.
# For now, only output "export" lines and lines containing UPLOAD_EXTRA_FILES.
MOZCONFIG_MK_LINES := $(filter export||% UPLOAD_EXTRA_FILES% %UPLOAD_EXTRA_FILES%,$(MOZCONFIG_OUT_LINES))
$(OBJDIR)/.mozconfig.mk: $(TOPSRCDIR)/client.mk $(FOUND_MOZCONFIG) $(call mkdir_deps,$(OBJDIR)) $(OBJDIR)/CLOBBER
$(OBJDIR)/.mozconfig.mk: $(TOPSRCDIR)/client.mk $(FOUND_MOZCONFIG)
$(if $(MOZCONFIG_MK_LINES),( $(foreach line,$(MOZCONFIG_MK_LINES), echo '$(subst ||, ,$(line))';) )) > $@
# Include that makefile so that it is created. This should not actually change
@ -144,14 +104,11 @@ include $(OBJDIR)/.mozconfig.mk
# Print out any options loaded from mozconfig.
all build clean distclean export libs install realclean::
ifneq (,$(strip $(MOZCONFIG_OUT_FILTERED)))
ifneq (,$(strip $(MOZCONFIG_OUT_LINES)))
$(info Adding client.mk options from $(FOUND_MOZCONFIG):)
$(foreach line,$(MOZCONFIG_OUT_FILTERED),$(info $(NULL) $(NULL) $(NULL) $(NULL) $(subst ||, ,$(line))))
$(foreach line,$(MOZCONFIG_OUT_LINES),$(info $(NULL) $(NULL) $(NULL) $(NULL) $(subst ||, ,$(line))))
endif
# helper target for mobile
build_and_deploy: build package install
# In automation, manage an sccache daemon. The starting of the server
# needs to be in a make file so sccache inherits the jobserver.
ifdef MOZBUILD_MANAGE_SCCACHE_DAEMON
@ -186,7 +143,6 @@ $(CONFIGURES): %: %.in $(EXTRA_CONFIG_DEPS)
CONFIG_STATUS_DEPS := \
$(wildcard $(TOPSRCDIR)/*/confvars.sh) \
$(CONFIGURES) \
$(TOPSRCDIR)/CLOBBER \
$(TOPSRCDIR)/nsprpub/configure \
$(TOPSRCDIR)/config/milestone.txt \
$(TOPSRCDIR)/browser/config/version.txt \
@ -214,16 +170,10 @@ else
CONFIGURE = $(TOPSRCDIR)/configure
endif
$(OBJDIR)/CLOBBER: $(TOPSRCDIR)/CLOBBER
$(PYTHON) $(TOPSRCDIR)/config/pythonpath.py -I $(TOPSRCDIR)/testing/mozbase/mozfile \
$(TOPSRCDIR)/python/mozbuild/mozbuild/controller/clobber.py $(TOPSRCDIR) $(OBJDIR)
configure-files: $(CONFIGURES)
configure-preqs = \
$(OBJDIR)/CLOBBER \
configure-files \
$(call mkdir_deps,$(OBJDIR)) \
save-mozconfig \
$(OBJDIR)/.mozconfig.json \
$(NULL)
@ -235,7 +185,7 @@ CREATE_MOZCONFIG_JSON = $(shell $(TOPSRCDIR)/mach environment --format=json -o $
ifneq (,$(CREATE_MOZCONFIG_JSON))
endif
$(OBJDIR)/.mozconfig.json: $(call mkdir_deps,$(OBJDIR)) ;
$(OBJDIR)/.mozconfig.json: ;
save-mozconfig: $(FOUND_MOZCONFIG)
ifdef FOUND_MOZCONFIG
@ -247,7 +197,7 @@ configure:: $(configure-preqs)
$(call BUILDSTATUS,TIER_START configure)
@echo cd $(OBJDIR);
@echo $(CONFIGURE) $(CONFIGURE_ARGS)
@cd $(OBJDIR) && $(BUILD_PROJECT_ARG) $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
@cd $(OBJDIR) && $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
|| ( echo '*** Fix above errors and then restart with\
"$(MAKE) -f client.mk build"' && exit 1 )
@touch $(OBJDIR)/Makefile
@ -273,16 +223,9 @@ endif
build:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
+$(MOZ_MAKE)
####################################
# Other targets
# Pass these target onto the real build system
$(OBJDIR_TARGETS):: $(OBJDIR)/Makefile $(OBJDIR)/config.status
+$(MOZ_MAKE) $@
ifdef MOZ_AUTOMATION
build::
$(MAKE) -f $(TOPSRCDIR)/client.mk automation/build
+$(MOZ_MAKE) automation/build
endif
ifdef MOZBUILD_MANAGE_SCCACHE_DAEMON
@ -298,5 +241,4 @@ endif
.PHONY: \
build \
configure \
$(OBJDIR_TARGETS)
configure

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

@ -132,25 +132,6 @@ TOUCH ?= touch
PYTHON_PATH = $(PYTHON) $(topsrcdir)/config/pythonpath.py
# determine debug-related options
_DEBUG_ASFLAGS :=
ifneq (,$(MOZ_DEBUG)$(MOZ_DEBUG_SYMBOLS))
ifeq ($(AS),$(YASM))
ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
_DEBUG_ASFLAGS += -g cv8
else
ifneq ($(OS_ARCH),Darwin)
_DEBUG_ASFLAGS += -g dwarf2
endif
endif
else
_DEBUG_ASFLAGS += $(MOZ_DEBUG_FLAGS)
endif
endif
ASFLAGS += $(_DEBUG_ASFLAGS)
#
# Build using PIC by default
#
@ -223,7 +204,7 @@ COMPILE_CFLAGS = $(COMPUTED_CFLAGS) $(PGO_CFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE
COMPILE_CXXFLAGS = $(COMPUTED_CXXFLAGS) $(PGO_CFLAGS) $(_DEPEND_CFLAGS) $(MK_COMPILE_DEFINES)
COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS)
COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS)
ASFLAGS += $(MOZBUILD_ASFLAGS)
ASFLAGS = $(COMPUTED_ASFLAGS)
HOST_CFLAGS = $(COMPUTED_HOST_CFLAGS) $(_DEPEND_CFLAGS)
HOST_CXXFLAGS = $(COMPUTED_HOST_CXXFLAGS) $(_DEPEND_CFLAGS)

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

@ -84,6 +84,7 @@ skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keybo
[browser_inspector_highlighter-cssshape_04.js]
[browser_inspector_highlighter-cssshape_05.js]
[browser_inspector_highlighter-cssshape_06.js]
[browser_inspector_highlighter-cssshape_07.js]
[browser_inspector_highlighter-cssshape_iframe_01.js]
[browser_inspector_highlighter-csstransform_01.js]
[browser_inspector_highlighter-csstransform_02.js]

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

@ -0,0 +1,117 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Test that shapes are updated correctly for scaling on one axis in transform mode.
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_cssshapes.html";
const HIGHLIGHTER_TYPE = "ShapesHighlighter";
const SHAPE_IDS = ["#polygon-transform", "#ellipse"];
add_task(function* () {
let inspector = yield openInspectorForURL(TEST_URL);
let helper = yield getHighlighterHelperFor(HIGHLIGHTER_TYPE)(inspector);
let {testActor} = inspector;
yield testOneDimScale(testActor, helper);
helper.finalize();
});
function* testOneDimScale(testActor, helper) {
for (let shape of SHAPE_IDS) {
info(`Displaying ${shape}`);
yield helper.show(shape, {mode: "cssClipPath", transformMode: true});
let { mouse } = helper;
let { top, left, width, height } = yield getBoundingBoxInPx(testActor, helper, shape);
// if the top or left edges are not visible, move the shape so it is.
if (top < 0 || left < 0) {
let x = left + width / 2;
let y = top + height / 2;
let dx = Math.max(0, -left);
let dy = Math.max(0, -top);
yield mouse.down(x, y, shape);
yield mouse.move(x + dx, y + dy, shape);
yield mouse.up(x + dx, y + dy, shape);
yield testActor.reflow();
left += dx;
top += dy;
}
let dx = width / 10;
let dy = height / 10;
info("Scaling from w");
yield mouse.down(left, top + height / 2, shape);
yield mouse.move(left + dx, top + height / 2, shape);
yield mouse.up(left + dx, top + height / 2, shape);
yield testActor.reflow();
let wBB = yield getBoundingBoxInPx(testActor, helper, shape);
is(wBB.top, top, `${shape} top not moved down after w scale`);
isnot(wBB.left, left, `${shape} left moved right after w scale`);
isnot(wBB.width, width, `${shape} width reduced after w scale`);
is(wBB.height, height, `${shape} height not reduced after w scale`);
info("Scaling from e");
yield mouse.down(wBB.left + wBB.width, wBB.top + wBB.height / 2, shape);
yield mouse.move(wBB.left + wBB.width - dx, wBB.top + wBB.height / 2, shape);
yield mouse.up(wBB.left + wBB.width - dx, wBB.top + wBB.height / 2, shape);
yield testActor.reflow();
let eBB = yield getBoundingBoxInPx(testActor, helper, shape);
is(eBB.top, wBB.top, `${shape} top not moved down after e scale`);
is(eBB.left, wBB.left, `${shape} left not moved right after e scale`);
isnot(eBB.width, wBB.width, `${shape} width reduced after e scale`);
is(eBB.height, wBB.height, `${shape} height not reduced after e scale`);
info("Scaling from s");
yield mouse.down(eBB.left + eBB.width / 2, eBB.top + eBB.height, shape);
yield mouse.move(eBB.left + eBB.width / 2, eBB.top + eBB.height - dy, shape);
yield mouse.up(eBB.left + eBB.width / 2, eBB.top + eBB.height - dy, shape);
yield testActor.reflow();
let sBB = yield getBoundingBoxInPx(testActor, helper, shape);
is(sBB.top, eBB.top, `${shape} top not moved down after w scale`);
is(sBB.left, eBB.left, `${shape} left not moved right after w scale`);
is(sBB.width, eBB.width, `${shape} width not reduced after w scale`);
isnot(sBB.height, eBB.height, `${shape} height reduced after w scale`);
info("Scaling from n");
yield mouse.down(sBB.left + sBB.width / 2, sBB.top, shape);
yield mouse.move(sBB.left + sBB.width / 2, sBB.top + dy, shape);
yield mouse.up(sBB.left + sBB.width / 2, sBB.top + dy, shape);
yield testActor.reflow();
let nBB = yield getBoundingBoxInPx(testActor, helper, shape);
isnot(nBB.top, sBB.top, `${shape} top moved down after n scale`);
is(nBB.left, sBB.left, `${shape} left not moved right after n scale`);
is(nBB.width, sBB.width, `${shape} width reduced after n scale`);
isnot(nBB.height, sBB.height, `${shape} height not reduced after n scale`);
}
}
function* getBoundingBoxInPx(testActor, helper, shape = "#polygon") {
let bbTop = parseFloat(yield helper.getElementAttribute("shapes-bounding-box", "y"));
let bbLeft = parseFloat(yield helper.getElementAttribute("shapes-bounding-box", "x"));
let bbWidth = parseFloat(yield helper.getElementAttribute("shapes-bounding-box",
"width"));
let bbHeight = parseFloat(yield helper.getElementAttribute("shapes-bounding-box",
"height"));
let quads = yield testActor.getAllAdjustedQuads(shape);
let { width, height } = quads.content[0].bounds;
let computedStyle = yield helper.highlightedNode.getComputedStyle();
let paddingTop = parseFloat(computedStyle["padding-top"].value);
let paddingLeft = parseFloat(computedStyle["padding-left"].value);
return {
top: paddingTop + height * bbTop / 100,
left: paddingLeft + width * bbLeft / 100,
width: width * bbWidth / 100,
height: height * bbHeight / 100
};
}

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

@ -526,31 +526,39 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
let { width, height } = this.zoomAdjustedDimensions;
// How much points on each axis should be translated before scaling
let transX = (type === "scale-se" || type === "scale-ne") ?
let transX = (type === "scale-se" || type === "scale-ne" || type === "scale-e") ?
minX / 100 * width : maxX / 100 * width;
let transY = (type === "scale-se" || type === "scale-sw") ?
let transY = (type === "scale-se" || type === "scale-sw" || type === "scale-s") ?
minY / 100 * height : maxY / 100 * height;
let { percentX, percentY } = this.convertPageCoordsToPercent(x, y);
let { percentX: percentPageX,
percentY: percentPageY } = this.convertPageCoordsToPercent(pageX, pageY);
// distance from original click to current mouse position, in %
let distanceX = (type === "scale-se" || type === "scale-ne") ?
let distanceX = (type === "scale-se" || type === "scale-ne" || type === "scale-e") ?
percentPageX - percentX : percentX - percentPageX;
let distanceY = (type === "scale-se" || type === "scale-sw") ?
let distanceY = (type === "scale-se" || type === "scale-sw" || type === "scale-s") ?
percentPageY - percentY : percentY - percentPageY;
// scale = 1 + proportion of distance to bounding box width/height of shape
let scaleX = 1 + distanceX / (maxX - minX);
let scaleY = 1 + distanceY / (maxY - minY);
let scale = (scaleX + scaleY) / 2;
let axis = "xy";
if (type === "scale-e" || type === "scale-w") {
scale = scaleX;
axis = "x";
} else if (type === "scale-n" || type === "scale-s") {
scale = scaleY;
axis = "y";
}
if (this.shapeType === "polygon") {
this._scalePolygon(pageX, pageY, transX, transY, scale);
this._scalePolygon(pageX, pageY, transX, transY, scale, axis);
} else if (this.shapeType === "circle") {
this._scaleCircle(pageX, pageY, transX, transY, scale);
} else if (this.shapeType === "ellipse") {
this._scaleEllipse(pageX, pageY, transX, transY, scale);
this._scaleEllipse(pageX, pageY, transX, transY, scale, axis);
} else if (this.shapeType === "inset") {
this._scaleInset(pageX, pageY, transX, transY, scale);
}
@ -564,15 +572,16 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
* @param {Number} transX the number of pixels to translate on the x axis before scaling
* @param {Number} transY the number of pixels to translate on the y axis before scaling
* @param {Number} scale the proportion to scale by
* @param {String} axis the axis to scale on. "x", "y", or "xy" for both.
*/
_scalePolygon(pageX, pageY, transX, transY, scale) {
_scalePolygon(pageX, pageY, transX, transY, scale, axis) {
let { pointsInfo } = this[_dragging];
let polygonDef = (this.fillRule) ? `${this.fillRule}, ` : "";
polygonDef += pointsInfo.map(point => {
let { unitX, unitY, valueX, valueY, ratioX, ratioY } = point;
let [newX, newY] = scalePoint(valueX, valueY, transX * ratioX,
transY * ratioY, scale);
transY * ratioY, scale, axis);
return `${newX}${unitX} ${newY}${unitY}`;
}).join(", ");
polygonDef = (this.geometryBox) ? `polygon(${polygonDef}) ${this.geometryBox}` :
@ -613,13 +622,14 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
* @param {Number} transX the number of pixels to translate on the x axis before scaling
* @param {Number} transY the number of pixels to translate on the y axis before scaling
* @param {Number} scale the proportion to scale by
* @param {String} axis the axis to scale on. "x", "y", or "xy" for both.
*/
_scaleEllipse(pageX, pageY, transX, transY, scale) {
_scaleEllipse(pageX, pageY, transX, transY, scale, axis) {
let { unitX, unitY, unitRX, unitRY, valueX, valueY,
ratioX, ratioY, ratioRX, ratioRY } = this[_dragging];
let [newCx, newCy] = scalePoint(valueX, valueY, transX * ratioX,
transY * ratioY, scale);
transY * ratioY, scale, axis);
// As part of scaling, the center is translated to be tangent to the lines y=0 & x=0.
// To get the new radii, we scale the new center back to that point and get the
// distances to the line x=0 and y=0.
@ -1082,6 +1092,10 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
{ pointName: "scale-ne", x: maxX, y: minY, cursor: "nesw-resize" },
{ pointName: "scale-sw", x: minX, y: maxY, cursor: "nesw-resize" },
{ pointName: "scale-nw", x: minX, y: minY, cursor: "nwse-resize" },
{ pointName: "scale-n", x: centerX, y: minY, cursor: "ns-resize" },
{ pointName: "scale-s", x: centerX, y: maxY, cursor: "ns-resize" },
{ pointName: "scale-e", x: maxX, y: centerY, cursor: "ew-resize" },
{ pointName: "scale-w", x: minX, y: centerY, cursor: "ew-resize" }
];
for (let { pointName, x, y, cursor } of points) {
@ -1226,7 +1240,7 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
let centerX = (minX + maxX) / 2;
let centerY = (minY + maxY) / 2;
const points = [
let points = [
{ point: "translate", x: centerX, y: centerY },
{ point: "scale-se", x: maxX, y: maxY },
{ point: "scale-ne", x: maxX, y: minY },
@ -1234,6 +1248,13 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
{ point: "scale-nw", x: minX, y: minY },
];
if (this.shapeType === "polygon" || this.shapeType === "ellipse") {
points.push({ point: "scale-n", x: centerX, y: minY },
{ point: "scale-s", x: centerX, y: maxY },
{ point: "scale-e", x: maxX, y: centerY },
{ point: "scale-w", x: minX, y: centerY });
}
for (let { point, x, y } of points) {
if (pageX >= x - clickRadiusX && pageX <= x + clickRadiusX &&
pageY >= y - clickRadiusY && pageY <= y + clickRadiusY) {
@ -1879,6 +1900,10 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
let centerY = (minY + maxY) / 2;
let markerPoints = [[centerX, centerY], [minX, minY],
[maxX, minY], [minX, maxY], [maxX, maxY]];
if (this.shapeType === "polygon" || this.shapeType === "ellipse") {
markerPoints.push([minX, centerY], [maxX, centerY],
[centerX, minY], [centerX, maxY]);
}
this._drawMarkers(markerPoints, width, height, zoom);
if (this.shapeType === "polygon") {

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

@ -130,11 +130,12 @@ const roundTo = (value, exp) => {
* @param {Number} transX the amount to translate the x coord by
* @param {Number} transY the amount ot translate the y coord by
* @param {Number} scale the scaling factor
* @param {String} axis the axis to scale on. "x", "y", or "xy" for both.
* @returns {Array} of the form [newX, newY], containing the coord pair after scaling.
*/
const scalePoint = (x, y, transX, transY, scale) => {
let newX = (x - transX) * scale + transX;
let newY = (y - transY) * scale + transY;
const scalePoint = (x, y, transX, transY, scale, axis = "xy") => {
let newX = (axis === "y") ? x : (x - transX) * scale + transX;
let newY = (axis === "x") ? y : (y - transY) * scale + transY;
return [newX, newY];
};

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

@ -55,11 +55,11 @@ function observeStyling(frameCount, onFrame) {
docShell.recordProfileTimelineMarkers = true;
docShell.popProfileTimelineMarkers();
return new Promise(function(resolve) {
return waitForAnimationFrames(frameCount, onFrame).then(function() {
return new Promise(resolve => {
return waitForAnimationFrames(frameCount, onFrame).then(() => {
var markers = docShell.popProfileTimelineMarkers();
docShell.recordProfileTimelineMarkers = false;
var stylingMarkers = markers.filter(function(marker, index) {
var stylingMarkers = markers.filter((marker, index) => {
return marker.name == 'Styles' && marker.isAnimationOnly;
});
resolve(stylingMarkers);
@ -68,14 +68,14 @@ function observeStyling(frameCount, onFrame) {
}
function ensureElementRemoval(aElement) {
return new Promise(function(resolve) {
return new Promise(resolve => {
aElement.remove();
waitForAllPaintsFlushed(resolve);
});
}
function waitForWheelEvent(aTarget) {
return new Promise(function(resolve, reject) {
return new Promise(resolve => {
// Get the scrollable target element position in this window coordinate
// system to send a wheel event to the element.
var targetRect = aTarget.getBoundingClientRect();
@ -106,7 +106,7 @@ function add_task_if_omta_enabled(test) {
// We need to wait for all paints before running tests to avoid contaminations
// from styling of this document itself.
waitForAllPaints(function() {
waitForAllPaints(() => {
add_task(async function restyling_for_main_thread_animations() {
var div = addDiv(null, { style: 'animation: background-color 100s' });
var animation = div.getAnimations()[0];
@ -196,7 +196,7 @@ waitForAllPaints(function() {
var mouseX = initialRect.left + initialRect.width / 2;
var mouseY = initialRect.top + initialRect.height / 2;
var markers = await observeStyling(5, function() {
var markers = await observeStyling(5, () => {
// We can't use synthesizeMouse here since synthesizeMouse causes
// layout flush.
synthesizeMouseAtPoint(mouseX++, mouseY++,
@ -219,7 +219,7 @@ waitForAllPaints(function() {
var mouseX = initialRect.left + initialRect.width / 2;
var mouseY = initialRect.top + initialRect.height / 2;
var markers = await observeStyling(5, function() {
var markers = await observeStyling(5, () => {
// We can't use synthesizeMouse here since synthesizeMouse causes
// layout flush.
synthesizeMouseAtPoint(mouseX++, mouseY++,
@ -492,7 +492,7 @@ waitForAllPaints(function() {
await animation.ready;
var markers = await observeStyling(1, function() {
var markers = await observeStyling(1, () => {
parentElement.style.height = '100px';
});
@ -712,11 +712,25 @@ waitForAllPaints(function() {
await waitForAnimationFrames(5);
// Apply another animation style
div.style.animation = 'background-color 110s';
var animation = div.getAnimations()[0];
var markers = await observeStyling(5);
is(markers.length, 5,
'Applying animation style with different duration ' +
'should cause restyles on every frame.');
var markers = await observeStyling(1);
if (isServo) {
// There should be two restyles.
// 1) Animation-only restyle for before applying the new animation style
// 2) Animation-only restyle for after applying the new animation style
is(markers.length, 2,
'Applying animation style with different duration ' +
'should restyle twice');
} else {
// There should be three restyles.
// 1) Animation-only restyle for before applying the new animation style
// 2) Restyle for applying the new animation style
// Note: In gecko styling for animations is not separated.
// 3) Restyle triggered by updating an existing animation (specifically
// the animation-duration)
is(markers.length, 3,
'Applying animation style with different duration ' +
'should restyles three times');
}
await ensureElementRemoval(div);
});

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

@ -323,6 +323,19 @@ nsDOMWindowUtils::GetDocCharsetIsForced(bool *aIsForced)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetPhysicalMillimeterInCSSPixels(float* aPhysicalMillimeter)
{
nsPresContext* presContext = GetPresContext();
if (!presContext) {
return NS_ERROR_NOT_AVAILABLE;
}
*aPhysicalMillimeter = presContext->AppUnitsToFloatCSSPixels(
presContext->PhysicalMillimetersToAppUnits(1));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetDocumentMetadata(const nsAString& aName,
nsAString& aValue)

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

@ -412,8 +412,6 @@ ImageDocument::DOMRestoreImageTo(int32_t aX, int32_t aY)
void
ImageDocument::ScrollImageTo(int32_t aX, int32_t aY, bool restoreImage)
{
float ratio = GetRatio();
if (restoreImage) {
RestoreImage();
FlushPendingNotifications(FlushType::Layout);
@ -429,6 +427,12 @@ ImageDocument::ScrollImageTo(int32_t aX, int32_t aY, bool restoreImage)
return;
}
float ratio = GetRatio();
// Don't try to scroll image if the document is not visible (mVisibleWidth or
// mVisibleHeight is zero).
if (ratio <= 0.0) {
return;
}
nsRect portRect = sf->GetScrollPortRect();
sf->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(aX/ratio) - portRect.width/2,
nsPresContext::CSSPixelsToAppUnits(aY/ratio) - portRect.height/2),

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

@ -1,6 +1,8 @@
[DEFAULT]
support-files =
file_anchor_ping.html
image.png
[test_anchor_ping.html]
skip-if = os == 'android'
[test_bug1414077.html]

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

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1414077
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1414077</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1414077 **/
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set":[["browser.enable_automatic_image_resizing", true]]}, function() {
var testWin = document.querySelector("iframe");
testWin.height = 0;
testWin.width = 0;
testWin.src = "image.png";
testWin.onload = function() {
var testDoc = testWin.contentDocument;
// testDoc should be a image document.
ok(testDoc.imageIsOverflowing, "image is overflowing");
ok(testDoc.imageIsResized, "image is resized to fit visible area by default");
// Restore image to original size.
testDoc.restoreImage();
ok(testDoc.imageIsOverflowing, "image is overflowing");
ok(!testDoc.imageIsResized, "image is restored to original size");
// Resize the image to fit visible area
testDoc.shrinkToFit();
ok(testDoc.imageIsOverflowing, "image is overflowing");
ok(testDoc.imageIsResized, "image is resized to fit visible area");
SimpleTest.finish();
};
});
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1414077">Mozilla Bug 1414077</a>
<iframe></iframe>
</body>
</html>

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

@ -79,6 +79,11 @@ interface nsIDOMWindowUtils : nsISupports {
*/
readonly attribute boolean docCharsetIsForced;
/**
* Return the conversion of a physical millimeter in CSS pixels.
*/
readonly attribute float physicalMillimeterInCSSPixels;
/**
* Function to get metadata associated with the window's current document
* @param aName the name of the metadata. This should be all lowercase.

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

@ -3344,17 +3344,6 @@ TabChild::ReinitRenderingForDeviceReset()
ReinitRendering();
}
void
TabChild::CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo)
{
RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
mTextureFactoryIdentifier = aNewIdentifier;
lm->UpdateTextureFactoryIdentifier(aNewIdentifier, aDeviceResetSeqNo);
FrameLayerBuilder::InvalidateAllLayers(lm);
}
NS_IMETHODIMP
TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText,
const char16_t *aTipDir)

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

@ -628,8 +628,6 @@ public:
void InvalidateLayers();
void ReinitRendering();
void ReinitRenderingForDeviceReset();
void CompositorUpdated(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo);
static inline TabChild* GetFrom(nsIDOMWindow* aWindow)
{

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

@ -225,6 +225,12 @@ public:
virtual void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
nsTArray<nsCString>& aSessionIds) = 0;
// Main thread only.
// Calls MediaKeys->ResolvePromiseWithKeyStatus(aPromiseId, aKeyStatus) after
// the CDM has processed the request.
virtual void GetStatusForPolicy(PromiseId aPromiseId,
const nsAString& aMinHdcpVersion) = 0;
#ifdef DEBUG
virtual bool IsOnOwnerThread() = 0;
#endif

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

@ -597,5 +597,51 @@ MediaKeys::GetSessionsInfo(nsString& sessionsInfo)
}
}
already_AddRefed<Promise>
MediaKeys::GetStatusForPolicy(const MediaKeysPolicy& aPolicy,
ErrorResult& aRv)
{
RefPtr<DetailedPromise> promise(MakePromise(aRv,
NS_LITERAL_CSTRING("MediaKeys::GetStatusForPolicy()")));
if (aRv.Failed()) {
return nullptr;
}
// Currently, only widevine CDM supports for this API.
if (!IsWidevineKeySystem(mKeySystem)) {
EME_LOG("MediaKeys[%p]::GetStatusForPolicy() HDCP policy check on unsupported keysystem ", this);
NS_WARNING("Tried to query without a CDM");
promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
NS_LITERAL_CSTRING("HDCP policy check on unsupported keysystem"));
return promise.forget();
}
if (!mProxy) {
NS_WARNING("Tried to use a MediaKeys without a CDM");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Null CDM in MediaKeys.GetStatusForPolicy()"));
return promise.forget();
}
EME_LOG("GetStatusForPolicy minHdcpVersion = %s.", NS_ConvertUTF16toUTF8(aPolicy.mMinHdcpVersion).get());
mProxy->GetStatusForPolicy(StorePromise(promise), aPolicy.mMinHdcpVersion);
return promise.forget();
}
void
MediaKeys::ResolvePromiseWithKeyStatus(PromiseId aId, MediaKeyStatus aMediaKeyStatus)
{
RefPtr<DetailedPromise> promise(RetrievePromise(aId));
if (!promise) {
return;
}
RefPtr<MediaKeys> keys(this);
EME_LOG("MediaKeys[%p]::ResolvePromiseWithKeyStatus() resolve promise id=%d, keystatus=%" PRIu8,
this,
aId,
static_cast<uint8_t>(aMediaKeyStatus));
promise->MaybeResolve(aMediaKeyStatus);
}
} // namespace dom
} // namespace mozilla

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

@ -16,6 +16,7 @@
#include "nsRefPtrHashtable.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/MediaKeysBinding.h"
#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus
#include "mozilla/dom/MediaKeySystemAccessBinding.h"
#include "mozIGeckoMediaPluginService.h"
#include "mozilla/DetailedPromise.h"
@ -29,6 +30,7 @@ namespace dom {
class ArrayBufferViewOrArrayBuffer;
class MediaKeySession;
struct MediaKeysPolicy;
class HTMLMediaElement;
typedef nsRefPtrHashtable<nsStringHashKey, MediaKeySession> KeySessionHashMap;
@ -130,6 +132,12 @@ public:
void GetSessionsInfo(nsString& sessionsInfo);
// JavaScript: MediaKeys.GetStatusForPolicy()
already_AddRefed<Promise> GetStatusForPolicy(const MediaKeysPolicy& aPolicy,
ErrorResult& aR);
// Called by CDMProxy when CDM successfully GetStatusForPolicy.
void ResolvePromiseWithKeyStatus(PromiseId aId, dom::MediaKeyStatus aMediaKeyStatus);
private:
// Instantiate CDMProxy instance.

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

@ -108,7 +108,7 @@ MediaDrmCDMProxy::LoadSession(PromiseId aPromiseId,
{
// TODO: Implement LoadSession.
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Currently Fennec did not support LoadSession"));
NS_LITERAL_CSTRING("Currently Fennec does not support LoadSession"));
}
void
@ -117,7 +117,7 @@ MediaDrmCDMProxy::SetServerCertificate(PromiseId aPromiseId,
{
// TODO: Implement SetServerCertificate.
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Currently Fennec did not support SetServerCertificate"));
NS_LITERAL_CSTRING("Currently Fennec does not support SetServerCertificate"));
}
void
@ -168,7 +168,7 @@ MediaDrmCDMProxy::RemoveSession(const nsAString& aSessionId,
{
// TODO: Implement RemoveSession.
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Currently Fennec did not support RemoveSession"));
NS_LITERAL_CSTRING("Currently Fennec does not support RemoveSession"));
}
void
@ -372,6 +372,15 @@ MediaDrmCDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
caps.GetSessionIdsForKeyId(aKeyId, aSessionIds);
}
void
MediaDrmCDMProxy::GetStatusForPolicy(PromiseId aPromiseId,
const nsAString& aMinHdcpVersion)
{
// TODO: Implement GetStatusForPolicy.
RejectPromise(aPromiseId, NS_ERROR_DOM_NOT_SUPPORTED_ERR,
NS_LITERAL_CSTRING("Currently Fennec does not support GetStatusForPolicy"));
}
#ifdef DEBUG
bool
MediaDrmCDMProxy::IsOnOwnerThread()

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

@ -115,6 +115,9 @@ public:
void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
nsTArray<nsCString>& aSessionIds) override;
void GetStatusForPolicy(PromiseId aPromiseId,
const nsAString& aMinHdcpVersion) override;
#ifdef DEBUG
bool IsOnOwnerThread() override;
#endif

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

@ -22,6 +22,9 @@ public:
virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccessful) = 0;
virtual void ResolvePromiseWithKeyStatus(uint32_t aPromiseId,
uint32_t aKeyStatus) = 0;
virtual void ResolvePromise(uint32_t aPromiseId) = 0;
virtual void RejectPromise(uint32_t aPromiseId,

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

@ -116,6 +116,16 @@ ToDOMMediaKeyStatus(uint32_t aStatus)
return dom::MediaKeyStatus::Internal_error;
}
void
ChromiumCDMCallbackProxy::ResolvePromiseWithKeyStatus(uint32_t aPromiseId,
uint32_t aKeyStatus)
{
DispatchToMainThread("ChromiumCDMProxy::OnResolvePromiseWithKeyStatus",
&ChromiumCDMProxy::OnResolvePromiseWithKeyStatus,
aPromiseId,
ToDOMMediaKeyStatus(aKeyStatus));
}
void
ChromiumCDMCallbackProxy::SessionKeysChange(const nsCString& aSessionId,
nsTArray<mozilla::gmp::CDMKeyInformation> && aKeysInfo)

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

@ -27,6 +27,9 @@ public:
void ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccessful) override;
void ResolvePromiseWithKeyStatus(uint32_t aPromiseId,
uint32_t aKeyStatus) override;
void ResolvePromise(uint32_t aPromiseId) override;
void RejectPromise(uint32_t aPromiseId,

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

@ -226,7 +226,13 @@ ChromiumCDMChild::CallOnMessageLoopThread(const char* const aName,
void
ChromiumCDMChild::OnResolveKeyStatusPromise(uint32_t aPromiseId,
cdm::KeyStatus aKeyStatus) {
//TODO: The callback of GetStatusForPolicy, will implement it in Bug 1404230.
GMP_LOG("ChromiumCDMChild::OnResolveKeyStatusPromise(pid=%" PRIu32 "keystatus=%d)",
aPromiseId,
aKeyStatus);
CallOnMessageLoopThread("gmp::ChromiumCDMChild::OnResolveKeyStatusPromise",
&ChromiumCDMChild::SendOnResolvePromiseWithKeyStatus,
aPromiseId,
static_cast<uint32_t>(aKeyStatus));
}
bool
@ -624,6 +630,64 @@ ChromiumCDMChild::RecvRemoveSession(const uint32_t& aPromiseId,
return IPC_OK();
}
// See https://cs.chromium.org/chromium/src/media/blink/webcontentdecryptionmodule_impl.cc?rcl=9d4e17194fbae2839d269e0b625520eac09efa9b&l=40
static cdm::HdcpVersion
ToCDMHdcpVersion(const nsCString& aMinHdcpVersion)
{
// String compare with ignoring case.
if (aMinHdcpVersion.IsEmpty()) {
return cdm::HdcpVersion::kHdcpVersionNone;
}
if (aMinHdcpVersion.EqualsIgnoreCase("hdcp-1.0")) {
return cdm::HdcpVersion::kHdcpVersion1_0;
}
if (aMinHdcpVersion.EqualsIgnoreCase("hdcp-1.1")) {
return cdm::HdcpVersion::kHdcpVersion1_1;
}
if (aMinHdcpVersion.EqualsIgnoreCase("hdcp-1.2")) {
return cdm::HdcpVersion::kHdcpVersion1_2;
}
if (aMinHdcpVersion.EqualsIgnoreCase("hdcp-1.3")) {
return cdm::HdcpVersion::kHdcpVersion1_3;
}
if (aMinHdcpVersion.EqualsIgnoreCase("hdcp-1.4")) {
return cdm::HdcpVersion::kHdcpVersion1_4;
}
if (aMinHdcpVersion.EqualsIgnoreCase("hdcp-2.0")) {
return cdm::HdcpVersion::kHdcpVersion2_0;
}
if (aMinHdcpVersion.EqualsIgnoreCase("hdcp-2.1")) {
return cdm::HdcpVersion::kHdcpVersion2_1;
}
if (aMinHdcpVersion.EqualsIgnoreCase("hdcp-2.2")) {
return cdm::HdcpVersion::kHdcpVersion2_2;
}
// Invalid hdcp version string.
return cdm::HdcpVersion::kHdcpVersionNone;
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvGetStatusForPolicy(const uint32_t& aPromiseId,
const nsCString& aMinHdcpVersion)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvGetStatusForPolicy(pid=%" PRIu32 ", MinHdcpVersion=%s)",
aPromiseId,
aMinHdcpVersion.get());
if (mCDM) {
cdm::Policy policy;
// We didn't check the return value of ToCDMHdcpVersion.
// Let CDM to handle the cdm::HdcpVersion::kHdcpVersionNone case.
// ChromiumCDM8BackwardsCompat::GetStatusForPolicy will reject the promise
// since this API is only supported by CDM version 9.
// CDM will callback by OnResolveKeyStatusPromise when it successfully executes.
policy.min_hdcp_version = ToCDMHdcpVersion(aMinHdcpVersion);
mCDM->GetStatusForPolicy(aPromiseId, policy);
}
return IPC_OK();
}
static void
InitInputBuffer(const CDMInputBuffer& aBuffer,
nsTArray<cdm::SubsampleEntry>& aSubSamples,

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

@ -128,6 +128,8 @@ protected:
const nsCString& aSessionId) override;
ipc::IPCResult RecvRemoveSession(const uint32_t& aPromiseId,
const nsCString& aSessionId) override;
ipc::IPCResult RecvGetStatusForPolicy(const uint32_t& aPromiseId,
const nsCString& aMinHdcpVersion) override;
ipc::IPCResult RecvDecrypt(const uint32_t& aId,
const CDMInputBuffer& aBuffer) override;
ipc::IPCResult RecvInitializeVideoDecoder(

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

@ -186,6 +186,25 @@ ChromiumCDMParent::RemoveSession(const nsCString& aSessionId,
}
}
void
ChromiumCDMParent::GetStatusForPolicy(uint32_t aPromiseId,
const nsCString& aMinHdcpVersion)
{
GMP_LOG("ChromiumCDMParent::GetStatusForPolicy(this=%p)", this);
if (mIsShutdown) {
RejectPromise(aPromiseId,
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("CDM is shutdown."));
return;
}
if (!SendGetStatusForPolicy(aPromiseId, aMinHdcpVersion)) {
RejectPromise(
aPromiseId,
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Failed to send getStatusForPolicy to CDM process"));
}
}
bool
ChromiumCDMParent::InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer,
MediaRawData* aSample)
@ -274,6 +293,24 @@ ChromiumCDMParent::Recv__delete__()
return IPC_OK();
}
ipc::IPCResult
ChromiumCDMParent::RecvOnResolvePromiseWithKeyStatus(const uint32_t& aPromiseId,
const uint32_t& aKeyStatus)
{
GMP_LOG("ChromiumCDMParent::RecvOnResolvePromiseWithKeyStatus(this=%p, pid=%u, "
"keystatus=%u)",
this,
aPromiseId,
aKeyStatus);
if (!mCDMCallback || mIsShutdown) {
return IPC_OK();
}
mCDMCallback->ResolvePromiseWithKeyStatus(aPromiseId, aKeyStatus);
return IPC_OK();
}
ipc::IPCResult
ChromiumCDMParent::RecvOnResolveNewSessionPromise(const uint32_t& aPromiseId,
const nsCString& aSessionId)

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

@ -66,6 +66,9 @@ public:
void RemoveSession(const nsCString& aSessionId, uint32_t aPromiseId);
void GetStatusForPolicy(uint32_t aPromiseId,
const nsCString& aMinHdcpVersion);
RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample);
// TODO: Add functions for clients to send data to CDM, and
@ -90,6 +93,9 @@ protected:
~ChromiumCDMParent() {}
ipc::IPCResult Recv__delete__() override;
ipc::IPCResult RecvOnResolvePromiseWithKeyStatus(
const uint32_t& aPromiseId,
const uint32_t& aKeyStatus) override;
ipc::IPCResult RecvOnResolveNewSessionPromise(
const uint32_t& aPromiseId,
const nsCString& aSessionId) override;

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

@ -465,6 +465,17 @@ ChromiumCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId,
mKeys->OnSessionLoaded(aPromiseId, aSuccess);
}
void
ChromiumCDMProxy::OnResolvePromiseWithKeyStatus(uint32_t aPromiseId,
dom::MediaKeyStatus aKeyStatus)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
return;
}
mKeys->ResolvePromiseWithKeyStatus(aPromiseId, aKeyStatus);
}
void
ChromiumCDMProxy::OnSessionMessage(const nsAString& aSessionId,
dom::MediaKeyMessageType aMessageType,
@ -598,6 +609,31 @@ ChromiumCDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
caps.GetSessionIdsForKeyId(aKeyId, aSessionIds);
}
void
ChromiumCDMProxy::GetStatusForPolicy(PromiseId aPromiseId,
const nsAString& aMinHdcpVersion)
{
MOZ_ASSERT(NS_IsMainThread());
EME_LOG("ChromiumCDMProxy::GetStatusForPolicy(pid=%u) minHdcpVersion=%s",
aPromiseId,
NS_ConvertUTF16toUTF8(aMinHdcpVersion).get());
RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent();
if (!cdm) {
RejectPromise(aPromiseId,
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Null CDM in GetStatusForPolicy"));
return;
}
mGMPThread->Dispatch(NewRunnableMethod<uint32_t, nsCString>(
"gmp::ChromiumCDMParent::GetStatusForPolicy",
cdm,
&gmp::ChromiumCDMParent::GetStatusForPolicy,
aPromiseId,
NS_ConvertUTF16toUTF8(aMinHdcpVersion)));
}
void
ChromiumCDMProxy::Terminated()
{

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

@ -105,6 +105,9 @@ public:
void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId,
nsTArray<nsCString>& aSessionIds) override;
void GetStatusForPolicy(PromiseId aPromiseId,
const nsAString& aMinHdcpVersion) override;
#ifdef DEBUG
bool IsOnOwnerThread() override;
#endif
@ -115,6 +118,9 @@ public:
// CDM, which will fail on all operations.
already_AddRefed<gmp::ChromiumCDMParent> GetCDMParent();
void OnResolvePromiseWithKeyStatus(uint32_t aPromiseId,
dom::MediaKeyStatus aKeyStatus);
private:
void OnCDMCreated(uint32_t aPromiseId);

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

@ -58,9 +58,16 @@ child:
async PurgeShmems();
// cdm::ContentDecryptionModule9
async GetStatusForPolicy(uint32_t aPromiseId,
nsCString aMinHdcpVersion);
parent:
async __delete__();
// cdm::Host9
async OnResolvePromiseWithKeyStatus(uint32_t aPromiseId, uint32_t aKeyStatus);
// cdm::Host8
async OnResolveNewSessionPromise(uint32_t aPromiseId, nsCString aSessionId);

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

@ -1072,6 +1072,9 @@ private:
void ResolveLoadSessionPromise(uint32_t aPromiseId,
bool aSuccessful) override { }
void ResolvePromiseWithKeyStatus(uint32_t aPromiseId,
uint32_t aKeyStatus) override { }
void ResolvePromise(uint32_t aPromiseId) override { }
void RejectPromise(uint32_t aPromiseId,

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

@ -810,6 +810,9 @@ scheme=https
[test_eme_waitingforkey.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_eme_getstatusforpolicy.html]
skip-if = toolkit == 'android' # bug 1149374
scheme=https
[test_empty_resource.html]
[test_error_in_video_document.html]
[test_error_on_404.html]

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

@ -0,0 +1,57 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test Encrypted Media Extensions</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="eme.js"></script>
</head>
<body>
<pre id="test">
<video id="v" controls></video>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function createMediaKeysAndSet() {
return navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, gCencMediaKeySystemConfig)
.then(function (access) {
return access.createMediaKeys();
})
.then(function (mediaKeys) {
document.getElementById("v").setMediaKeys(mediaKeys);
return mediaKeys;
});
}
function test() {
SetupEMEPref(() => {
createMediaKeysAndSet()
.then((m) => {
let video = document.getElementById("v");
is(video.mediaKeys, m, "Should have set MediaKeys on media element");
// getStatusForPolicy() is not suppored by ClearKey key system.
// The promise will always be rejected with NotSupportedError.
return video.mediaKeys.getStatusForPolicy({minHdcpVersion: "hdcp-2.0"});
})
.then((mediaKeyStatus) => {
ok(false, "Promise of getStatusForPolicy should not be resolved with clearkey key system");
})
// Promise rejected with NotSupportedError as expected.
.catch(reason => is("NotSupportedError", reason.name,
"Promise should be rejected with NotSupportedError."))
.then(() => SimpleTest.finish());
});
}
SpecialPowers.pushPrefEnv({"set":
[
["media.eme.hdcp-policy-check.enabled", true],
]
}, test);
</script>
</pre>
</body>
</html>

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

@ -18,6 +18,11 @@ enum MediaKeySessionType {
// persistent-usage-record,
};
// https://github.com/WICG/media-capabilities/blob/master/eme-extension-policy-check.md
dictionary MediaKeysPolicy {
DOMString minHdcpVersion = "";
};
interface MediaKeys {
readonly attribute DOMString keySystem;
@ -26,4 +31,7 @@ interface MediaKeys {
[NewObject]
Promise<void> setServerCertificate(BufferSource serverCertificate);
[Pref="media.eme.hdcp-policy-check.enabled", NewObject]
Promise<MediaKeyStatus> getStatusForPolicy(optional MediaKeysPolicy policy);
};

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

@ -175,4 +175,4 @@ Troubleshooting tips:
-------------------------------------------------------------------------------
The version of WebRender currently in the tree is:
f58ed651b47f47382b63dd2bce6e4ed10ee18c78
8a39cf24f493e894a66c2465dd310a2b2923e558

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

@ -732,8 +732,7 @@ public:
virtual void AddDidCompositeObserver(DidCompositeObserver* aObserver) { MOZ_CRASH("GFX: LayerManager"); }
virtual void RemoveDidCompositeObserver(DidCompositeObserver* aObserver) { MOZ_CRASH("GFX: LayerManager"); }
virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo) {}
virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier) {}
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier()
{

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

@ -103,15 +103,10 @@ ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
, mNeedsComposite(false)
, mQueuedAsyncPaints(false)
, mPaintSequenceNumber(0)
, mDeviceResetSequenceNumber(0)
, mForwarder(new ShadowLayerForwarder(this))
{
MOZ_COUNT_CTOR(ClientLayerManager);
mMemoryPressureObserver = new MemoryPressureObserver(this);
if (XRE_IsContentProcess()) {
mDeviceResetSequenceNumber = CompositorBridgeChild::Get()->DeviceResetSequenceNumber();
}
}
@ -241,23 +236,6 @@ ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
return false;
}
if (XRE_IsContentProcess() &&
mForwarder->DeviceCanReset() &&
mDeviceResetSequenceNumber != CompositorBridgeChild::Get()->DeviceResetSequenceNumber())
{
// The compositor has informed this process that a device reset occurred,
// but it has not finished informing each TabChild of its new
// TextureFactoryIdentifier. Until then, it's illegal to paint. Note that
// it is also illegal to request a new TIF synchronously, because we're
// not guaranteed the UI process has finished acquiring new compositors
// for each widget.
//
// Note that we only do this for accelerated backends, since we do not
// perform resets on basic compositors.
gfxCriticalNote << "Discarding a paint since a device reset has not yet been acknowledged.";
return false;
}
mInTransaction = true;
mTransactionStart = TimeStamp::Now();
@ -691,14 +669,9 @@ ClientLayerManager::WaitOnTransactionProcessed()
}
}
void
ClientLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo)
ClientLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier)
{
MOZ_ASSERT_IF(XRE_IsContentProcess(),
aDeviceResetSeqNo == CompositorBridgeChild::Get()->DeviceResetSequenceNumber());
mForwarder->IdentifyTextureHost(aNewIdentifier);
mDeviceResetSequenceNumber = aDeviceResetSeqNo;
}
void

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

@ -110,8 +110,7 @@ public:
virtual already_AddRefed<BorderLayer> CreateBorderLayer() override;
virtual already_AddRefed<RefLayer> CreateRefLayer() override;
virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo) override;
virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier) override;
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override
{
return AsShadowForwarder()->GetTextureFactoryIdentifier();
@ -357,10 +356,6 @@ private:
// Incremented in BeginTransaction(), but not for repeat transactions.
uint32_t mPaintSequenceNumber;
// A sequence number for checking whether we have not yet acknowledged
// a device reset.
uint64_t mDeviceResetSequenceNumber;
APZTestData mApzTestData;
RefPtr<ShadowLayerForwarder> mForwarder;

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

@ -87,7 +87,6 @@ CompositorBridgeChild::CompositorBridgeChild(CompositorManagerChild *aManager)
, mCanSend(false)
, mActorDestroyed(false)
, mFwdTransactionId(0)
, mDeviceResetSequenceNumber(0)
, mMessageLoop(MessageLoop::current())
, mProcessToken(0)
, mSectionAllocator(nullptr)

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

@ -215,10 +215,6 @@ public:
wr::IdNamespace*) override;
bool DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor) override;
uint64_t DeviceResetSequenceNumber() const {
return mDeviceResetSequenceNumber;
}
wr::MaybeExternalImageId GetNextExternalImageId() override;
wr::PipelineId GetNextPipelineId();
@ -358,11 +354,6 @@ private:
*/
uint64_t mFwdTransactionId;
/**
* Last sequence number recognized for a device reset.
*/
uint64_t mDeviceResetSequenceNumber;
/**
* Hold TextureClients refs until end of their usages on host side.
* It defer calling of TextureClient recycle callback.

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

@ -81,7 +81,7 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder
mLayerScrollData.emplace_back();
mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1);
auto callback = [&aScrollData](FrameMetrics::ViewID aScrollId) -> bool {
return aScrollData.HasMetadataFor(aScrollId);
return aScrollData.HasMetadataFor(aScrollId).isSome();
};
if (Maybe<ScrollMetadata> rootMetadata = nsLayoutUtils::GetRootMetadata(
aDisplayListBuilder, mManager, ContainerLayerParameters(), callback)) {
@ -485,21 +485,20 @@ WebRenderCommandBuilder::GenerateFallbackData(nsDisplayItem* aItem,
// Blob images will only draw the visible area of the blob so we don't need to clip
// them here and can just rely on the webrender clipping.
bool useClipBounds = true;
nsRect paintBounds = itemBounds;
if (useBlobImage) {
paintBounds = itemBounds;
useClipBounds = false;
} else {
paintBounds = aItem->GetClippedBounds(aDisplayListBuilder);
}
// nsDisplayItem::Paint() may refer the variables that come from ComputeVisibility().
// So we should call RecomputeVisibility() before painting. e.g.: nsDisplayBoxShadowInner
// So we should call ComputeVisibility() before painting. e.g.: nsDisplayBoxShadowInner
// uses mVisibleRegion in Paint() and mVisibleRegion is computed in
// nsDisplayBoxShadowInner::ComputeVisibility().
nsRegion visibleRegion(itemBounds);
aItem->RecomputeVisibility(aDisplayListBuilder, &visibleRegion, useClipBounds);
nsRegion visibleRegion(paintBounds);
aItem->SetVisibleRect(paintBounds, false);
aItem->ComputeVisibility(aDisplayListBuilder, &visibleRegion);
const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(paintBounds, appUnitsPerDevPixel);

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

@ -530,8 +530,7 @@ WebRenderLayerManager::WrUpdated()
}
void
WebRenderLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo)
WebRenderLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier)
{
WrBridge()->IdentifyTextureHost(aNewIdentifier);
}

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

@ -94,8 +94,7 @@ public:
const mozilla::TimeStamp& aCompositeEnd) override;
virtual void ClearCachedResources(Layer* aSubtree = nullptr) override;
virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo) override;
virtual void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier) override;
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override;
virtual void SetTransactionIdAllocator(TransactionIdAllocator* aAllocator) override

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

@ -54,11 +54,17 @@ WebRenderLayerScrollData::Initialize(WebRenderScrollData& aOwner,
asr && asr != aStopAtAsr;
asr = asr->mParent) {
MOZ_ASSERT(aOwner.GetManager());
Maybe<ScrollMetadata> metadata = asr->mScrollableFrame->ComputeScrollMetadata(
nullptr, aOwner.GetManager(), aItem->ReferenceFrame(),
ContainerLayerParameters(), nullptr);
MOZ_ASSERT(metadata);
mScrollIds.AppendElement(aOwner.AddMetadata(metadata.ref()));
FrameMetrics::ViewID scrollId = nsLayoutUtils::ViewIDForASR(asr);
if (Maybe<size_t> index = aOwner.HasMetadataFor(scrollId)) {
mScrollIds.AppendElement(index.ref());
} else {
Maybe<ScrollMetadata> metadata = asr->mScrollableFrame->ComputeScrollMetadata(
nullptr, aOwner.GetManager(), aItem->ReferenceFrame(),
ContainerLayerParameters(), nullptr);
MOZ_ASSERT(metadata);
MOZ_ASSERT(metadata->GetMetrics().GetScrollId() == scrollId);
mScrollIds.AppendElement(aOwner.AddMetadata(metadata.ref()));
}
}
}
@ -200,10 +206,11 @@ WebRenderScrollData::GetScrollMetadata(size_t aIndex) const
return mScrollMetadatas[aIndex];
}
bool
Maybe<size_t>
WebRenderScrollData::HasMetadataFor(const FrameMetrics::ViewID& aScrollId) const
{
return mScrollIdMap.find(aScrollId) != mScrollIdMap.end();
auto it = mScrollIdMap.find(aScrollId);
return (it == mScrollIdMap.end() ? Nothing() : Some(it->second));
}
void

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

@ -151,7 +151,7 @@ public:
const WebRenderLayerScrollData* GetLayerData(size_t aIndex) const;
const ScrollMetadata& GetScrollMetadata(size_t aIndex) const;
bool HasMetadataFor(const FrameMetrics::ViewID& aScrollId) const;
Maybe<size_t> HasMetadataFor(const FrameMetrics::ViewID& aScrollId) const;
const FocusTarget& GetFocusTarget() const { return mFocusTarget; }
void SetFocusTarget(const FocusTarget& aFocusTarget);

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

@ -23,6 +23,17 @@ class nsIFrame;
class nsAtom;
class nsIWidget;
namespace mozilla {
namespace layers {
class StackingContextHelper;
class WebRenderLayerManager;
}
namespace wr {
class DisplayListBuilder;
class IpcResourceUpdateQueue;
}
}
// IID for the nsITheme interface
// {7329f760-08cb-450f-8225-dae729096dec}
#define NS_ITHEME_IID \
@ -61,6 +72,20 @@ public:
const nsRect& aRect,
const nsRect& aDirtyRect) = 0;
/**
* Create WebRender commands for the theme background.
* @return true if the theme knows how to create WebRender commands for the
* given widget type, false if DrawWidgetBackground need sto be called
* instead.
*/
virtual bool CreateWebRenderCommandsForWidget(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsIFrame* aFrame,
uint8_t aWidgetType,
const nsRect& aRect) { return false; }
/**
* Get the computed CSS border for the widget, in pixels.
*/

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

@ -1,6 +1,6 @@
[package]
name = "webrender"
version = "0.53.1"
version = "0.53.2"
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/webrender"

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

@ -54,6 +54,6 @@ void main(void) {
#ifdef WR_FRAGMENT_SHADER
void main(void) {
float a = texture(sColor0, vUv).a;
oFragColor = vec4(vColor.rgb, vColor.a * a);
oFragColor = vColor * a;
}
#endif

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

@ -10,7 +10,7 @@ varying vec4 vColor;
in vec4 aColor;
void main(void) {
vColor = aColor;
vColor = vec4(aColor.rgb * aColor.a, aColor.a);
vec4 pos = vec4(aPosition, 1.0);
pos.xy = floor(pos.xy * uDevicePixelRatio + 0.5) / uDevicePixelRatio;
gl_Position = uTransform * pos;

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

@ -23,6 +23,6 @@ void main(void) {
#ifdef WR_FRAGMENT_SHADER
void main(void) {
float alpha = texture(sColor0, vec3(vColorTexCoord.xy, 0.0)).r;
oFragColor = vec4(vColor.xyz, vColor.w * alpha);
oFragColor = vColor * alpha;
}
#endif

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

@ -8,6 +8,7 @@ varying vec3 vUv;
flat varying vec4 vUvBounds;
flat varying float vAmount;
flat varying int vOp;
flat varying mat4 vColorMat;
#ifdef WR_VERTEX_SHADER
void main(void) {
@ -34,6 +35,52 @@ void main(void) {
vOp = ci.user_data0;
vAmount = float(ci.user_data1) / 65535.0;
float lumR = 0.2126;
float lumG = 0.7152;
float lumB = 0.0722;
float oneMinusLumR = 1.0 - lumR;
float oneMinusLumG = 1.0 - lumG;
float oneMinusLumB = 1.0 - lumB;
float oneMinusAmount = 1.0 - vAmount;
switch (vOp) {
case 2: {
// Grayscale
vColorMat = mat4(vec4(lumR + oneMinusLumR * oneMinusAmount, lumR - lumR * oneMinusAmount, lumR - lumR * oneMinusAmount, 0.0),
vec4(lumG - lumG * oneMinusAmount, lumG + oneMinusLumG * oneMinusAmount, lumG - lumG * oneMinusAmount, 0.0),
vec4(lumB - lumB * oneMinusAmount, lumB - lumB * oneMinusAmount, lumB + oneMinusLumB * oneMinusAmount, 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
break;
}
case 3: {
// HueRotate
float c = cos(vAmount * 0.01745329251);
float s = sin(vAmount * 0.01745329251);
vColorMat = mat4(vec4(lumR + oneMinusLumR * c - lumR * s, lumR - lumR * c + 0.143 * s, lumR - lumR * c - oneMinusLumR * s, 0.0),
vec4(lumG - lumG * c - lumG * s, lumG + oneMinusLumG * c + 0.140 * s, lumG - lumG * c + lumG * s, 0.0),
vec4(lumB - lumB * c + oneMinusLumB * s, lumB - lumB * c - 0.283 * s, lumB + oneMinusLumB * c + lumB * s, 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
break;
}
case 5: {
// Saturate
vColorMat = mat4(vec4(oneMinusAmount * lumR + vAmount, oneMinusAmount * lumR, oneMinusAmount * lumR, 0.0),
vec4(oneMinusAmount * lumG, oneMinusAmount * lumG + vAmount, oneMinusAmount * lumG, 0.0),
vec4(oneMinusAmount * lumB, oneMinusAmount * lumB, oneMinusAmount * lumB + vAmount, 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
break;
}
case 6: {
// Sepia
vColorMat = mat4(vec4(0.393 + 0.607 * oneMinusAmount, 0.349 - 0.349 * oneMinusAmount, 0.272 - 0.272 * oneMinusAmount, 0.0),
vec4(0.769 - 0.769 * oneMinusAmount, 0.686 + 0.314 * oneMinusAmount, 0.534 - 0.534 * oneMinusAmount, 0.0),
vec4(0.189 - 0.189 * oneMinusAmount, 0.168 - 0.168 * oneMinusAmount, 0.131 + 0.869 * oneMinusAmount, 0.0),
vec4(0.0, 0.0, 0.0, 1.0));
break;
}
}
gl_Position = uTransform * vec4(local_pos, ci.z, 1.0);
}
#endif
@ -43,55 +90,6 @@ void main(void) {
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
vec3 rgbToHsv(vec3 c) {
float value = max(max(c.r, c.g), c.b);
float chroma = value - min(min(c.r, c.g), c.b);
if (chroma == 0.0) {
return vec3(0.0);
}
float saturation = chroma / value;
float hue;
if (c.r == value)
hue = (c.g - c.b) / chroma;
else if (c.g == value)
hue = 2.0 + (c.b - c.r) / chroma;
else // if (c.b == value)
hue = 4.0 + (c.r - c.g) / chroma;
hue *= 1.0/6.0;
if (hue < 0.0)
hue += 1.0;
return vec3(hue, saturation, value);
}
vec3 hsvToRgb(vec3 c) {
if (c.s == 0.0) {
return vec3(c.z);
}
float hue = c.x * 6.0;
int sector = int(hue);
float residualHue = hue - float(sector);
vec3 pqt = c.z * vec3(1.0 - c.y, 1.0 - c.y * residualHue, 1.0 - c.y * (1.0 - residualHue));
switch (sector) {
case 0:
return vec3(c.z, pqt.z, pqt.x);
case 1:
return vec3(pqt.y, c.z, pqt.x);
case 2:
return vec3(pqt.x, c.z, pqt.z);
case 3:
return vec3(pqt.x, pqt.y, c.z);
case 4:
return vec3(pqt.z, pqt.x, c.z);
default:
return vec3(c.z, pqt.x, pqt.y);
}
}
vec4 Blur(float radius, vec2 direction) {
// TODO(gw): Support blur in WR2!
return vec4(1.0);
@ -101,20 +99,6 @@ vec4 Contrast(vec4 Cs, float amount) {
return vec4(Cs.rgb * amount - 0.5 * amount + 0.5, 1.0);
}
vec4 Grayscale(vec4 Cs, float amount) {
float ia = 1.0 - amount;
return mat4(vec4(0.2126 + 0.7874 * ia, 0.2126 - 0.2126 * ia, 0.2126 - 0.2126 * ia, 0.0),
vec4(0.7152 - 0.7152 * ia, 0.7152 + 0.2848 * ia, 0.7152 - 0.7152 * ia, 0.0),
vec4(0.0722 - 0.0722 * ia, 0.0722 - 0.0722 * ia, 0.0722 + 0.9278 * ia, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)) * Cs;
}
vec4 HueRotate(vec4 Cs, float amount) {
vec3 CsHsv = rgbToHsv(Cs.rgb);
CsHsv.x = mod(CsHsv.x + amount / 6.283185307179586, 1.0);
return vec4(hsvToRgb(CsHsv), Cs.a);
}
vec4 Invert(vec4 Cs, float amount) {
Cs.rgb /= Cs.a;
@ -124,18 +108,6 @@ vec4 Invert(vec4 Cs, float amount) {
return vec4(color.rgb * Cs.a, Cs.a);
}
vec4 Saturate(vec4 Cs, float amount) {
return vec4(hsvToRgb(min(vec3(1.0, amount, 1.0) * rgbToHsv(Cs.rgb), vec3(1.0))), Cs.a);
}
vec4 Sepia(vec4 Cs, float amount) {
float ia = 1.0 - amount;
return mat4(vec4(0.393 + 0.607 * ia, 0.349 - 0.349 * ia, 0.272 - 0.272 * ia, 0.0),
vec4(0.769 - 0.769 * ia, 0.686 + 0.314 * ia, 0.534 - 0.534 * ia, 0.0),
vec4(0.189 - 0.189 * ia, 0.168 - 0.168 * ia, 0.131 + 0.869 * ia, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)) * Cs;
}
vec4 Brightness(vec4 Cs, float amount) {
// Un-premultiply the input.
Cs.rgb /= Cs.a;
@ -169,27 +141,17 @@ void main(void) {
case 1:
oFragColor = Contrast(Cs, vAmount);
break;
case 2:
oFragColor = Grayscale(Cs, vAmount);
break;
case 3:
oFragColor = HueRotate(Cs, vAmount);
break;
case 4:
oFragColor = Invert(Cs, vAmount);
break;
case 5:
oFragColor = Saturate(Cs, vAmount);
break;
case 6:
oFragColor = Sepia(Cs, vAmount);
break;
case 7:
oFragColor = Brightness(Cs, vAmount);
break;
case 8:
oFragColor = Opacity(Cs, vAmount);
break;
default:
oFragColor = vColorMat * Cs;
}
}
#endif

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

@ -298,6 +298,8 @@ void main(void) {
result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
result.a = Cs.a;
result.rgb *= result.a;
oFragColor = result;
}
#endif

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

@ -181,7 +181,7 @@ void main(void) {
vec2 local_pos = vLocalPos;
#endif
alpha = min(alpha, do_clip());
alpha *= do_clip();
#endif
// Find the appropriate distance to apply the step over.
@ -259,6 +259,6 @@ void main(void) {
}
}
oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha);
oFragColor = vColor * alpha;
}
#endif

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

@ -194,6 +194,6 @@ void main(void) {
// See the YuvColorMatrix definition for an explanation of where the constants come from.
vec3 rgb = YuvColorMatrix * (yuv_value - vec3(0.06275, 0.50196, 0.50196));
oFragColor = vec4(rgb, alpha);
oFragColor = vec4(rgb * alpha, alpha);
}
#endif

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

@ -10,7 +10,6 @@ use ellipse::Ellipse;
use frame_builder::FrameBuilder;
use gpu_cache::GpuDataRequest;
use prim_store::{BorderPrimitiveCpu, RectangleContent, PrimitiveContainer, TexelRect};
use tiling::PrimitiveFlags;
use util::{lerp, pack_as_float};
#[repr(u8)]
@ -388,7 +387,7 @@ impl FrameBuilder {
clip_and_scroll,
&info,
RectangleContent::Fill(border.top.color),
PrimitiveFlags::None,
None,
);
}
if left_edge == BorderEdgeKind::Solid {
@ -401,7 +400,7 @@ impl FrameBuilder {
clip_and_scroll,
&info,
RectangleContent::Fill(border.left.color),
PrimitiveFlags::None,
None,
);
}
if right_edge == BorderEdgeKind::Solid {
@ -414,7 +413,7 @@ impl FrameBuilder {
clip_and_scroll,
&info,
RectangleContent::Fill(border.right.color),
PrimitiveFlags::None,
None,
);
}
if bottom_edge == BorderEdgeKind::Solid {
@ -427,7 +426,7 @@ impl FrameBuilder {
clip_and_scroll,
&info,
RectangleContent::Fill(border.bottom.color),
PrimitiveFlags::None,
None,
);
}
} else {

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

@ -245,7 +245,8 @@ impl ClipSources {
}
}
pub fn is_masking(&self) -> bool {
/// Whether or not this ClipSources has any clips (does any clipping).
pub fn has_clips(&self) -> bool {
!self.clips.is_empty()
}
}

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

@ -6,7 +6,7 @@ use api::{ClipId, DeviceIntRect, LayerPixel, LayerPoint, LayerRect, LayerSize};
use api::{LayerToScrollTransform, LayerToWorldTransform, LayerVector2D, LayoutVector2D, PipelineId};
use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity};
use api::{StickyOffsetBounds, WorldPoint};
use clip::{ClipRegion, ClipSources, ClipSourcesHandle, ClipStore};
use clip::{ClipSourcesHandle, ClipStore};
use clip_scroll_tree::{CoordinateSystemId, TransformUpdateState};
use euclid::SideOffsets2D;
use geometry::ray_intersects_rect;
@ -26,30 +26,6 @@ const CAN_OVERSCROLL: bool = false;
const MAX_LOCAL_VIEWPORT: f32 = 1000000.0;
#[derive(Debug)]
pub struct ClipInfo {
/// The clips for this node.
pub clip_sources: ClipSourcesHandle,
/// Whether or not this clip node automatically creates a mask.
pub is_masking: bool,
}
impl ClipInfo {
pub fn new(
clip_region: ClipRegion,
clip_store: &mut ClipStore,
) -> ClipInfo {
let clip_sources = ClipSources::from(clip_region);
let is_masking = clip_sources.is_masking();
ClipInfo {
clip_sources: clip_store.insert(clip_sources),
is_masking,
}
}
}
#[derive(Debug)]
pub struct StickyFrameInfo {
pub margins: SideOffsets2D<Option<f32>>,
@ -82,7 +58,7 @@ pub enum NodeType {
ReferenceFrame(ReferenceFrameInfo),
/// Other nodes just do clipping, but no transformation.
Clip(ClipInfo),
Clip(ClipSourcesHandle),
/// Transforms it's content, but doesn't clip it. Can also be adjusted
/// by scroll events or setting scroll offsets.
@ -151,7 +127,7 @@ pub struct ClipScrollNode {
/// A linear ID / index of this clip-scroll node. Used as a reference to
/// pass to shaders, to allow them to fetch a given clip-scroll node.
pub id: ClipScrollNodeIndex,
pub node_data_index: ClipScrollNodeIndex,
}
impl ClipScrollNode {
@ -175,7 +151,7 @@ impl ClipScrollNode {
clip_chain_node: None,
combined_clip_outer_bounds: DeviceIntRect::max_rect(),
coordinate_system_id: CoordinateSystemId(0),
id: ClipScrollNodeIndex(0),
node_data_index: ClipScrollNodeIndex(0),
}
}
@ -200,10 +176,10 @@ impl ClipScrollNode {
pub fn new_clip_node(
pipeline_id: PipelineId,
parent_id: ClipId,
clip_info: ClipInfo,
handle: ClipSourcesHandle,
clip_rect: LayerRect,
) -> Self {
Self::new(pipeline_id, Some(parent_id), &clip_rect, NodeType::Clip(clip_info))
Self::new(pipeline_id, Some(parent_id), &clip_rect, NodeType::Clip(handle))
}
pub fn new_reference_frame(
@ -289,6 +265,58 @@ impl ClipScrollNode {
true
}
pub fn update(
&mut self,
state: &mut TransformUpdateState,
node_data: &mut Vec<ClipScrollNodeData>,
device_pixel_ratio: f32,
clip_store: &mut ClipStore,
resource_cache: &mut ResourceCache,
gpu_cache: &mut GpuCache,
) {
// We set this earlier so that we can use it before we have all the data necessary
// to populate the ClipScrollNodeData.
self.node_data_index = ClipScrollNodeIndex(node_data.len() as u32);
self.update_transform(state);
self.update_clip_work_item(
state,
device_pixel_ratio,
clip_store,
resource_cache,
gpu_cache,
);
let local_clip_rect = if self.world_content_transform.has_perspective_component() {
LayerRect::new(
LayerPoint::new(-MAX_LOCAL_VIEWPORT, -MAX_LOCAL_VIEWPORT),
LayerSize::new(2.0 * MAX_LOCAL_VIEWPORT, 2.0 * MAX_LOCAL_VIEWPORT)
)
} else {
self.combined_local_viewport_rect
};
let data = match self.world_content_transform.inverse() {
Some(inverse) => {
ClipScrollNodeData {
transform: self.world_content_transform,
inv_transform: inverse,
local_clip_rect,
reference_frame_relative_scroll_offset:
self.reference_frame_relative_scroll_offset,
scroll_offset: self.scroll_offset(),
}
}
None => {
state.combined_outer_clip_bounds = DeviceIntRect::zero();
ClipScrollNodeData::invalid()
}
};
// Write the data that will be made available to the GPU for this node.
node_data.push(data);
}
pub fn update_clip_work_item(
&mut self,
state: &mut TransformUpdateState,
@ -298,8 +326,8 @@ impl ClipScrollNode {
gpu_cache: &mut GpuCache,
) {
let current_clip_chain = state.parent_clip_chain.clone();
let clip_info = match self.node_type {
NodeType::Clip(ref mut info) if info.is_masking => info,
let clip_sources_handle = match self.node_type {
NodeType::Clip(ref handle) => handle,
_ => {
self.clip_chain_node = current_clip_chain;
self.combined_clip_outer_bounds = state.combined_outer_clip_bounds;
@ -307,7 +335,7 @@ impl ClipScrollNode {
}
};
let clip_sources = clip_store.get_mut(&clip_info.clip_sources);
let clip_sources = clip_store.get_mut(clip_sources_handle);
clip_sources.update(
&self.world_viewport_transform,
gpu_cache,
@ -326,8 +354,8 @@ impl ClipScrollNode {
// TODO: Combine rectangles in the same axis-aligned clip space here?
self.clip_chain_node = Some(Rc::new(ClipChainNode {
work_item: ClipWorkItem {
scroll_node_id: self.id,
clip_sources: clip_info.clip_sources.weak(),
scroll_node_data_index: self.node_data_index,
clip_sources: clip_sources_handle.weak(),
coordinate_system_id: state.current_coordinate_system_id,
},
prev: current_clip_chain,
@ -337,11 +365,7 @@ impl ClipScrollNode {
state.parent_clip_chain = self.clip_chain_node.clone();
}
pub fn update_transform(
&mut self,
state: &mut TransformUpdateState,
node_data: &mut Vec<ClipScrollNodeData>,
) {
pub fn update_transform(&mut self, state: &mut TransformUpdateState) {
// We calculate this here to avoid a double-borrow later.
let sticky_offset = self.calculate_sticky_offset(
&state.nearest_scrolling_ancestor_offset,
@ -440,36 +464,6 @@ impl ClipScrollNode {
// Store coord system ID, and also the ID used for shaders to reference this node.
self.coordinate_system_id = state.current_coordinate_system_id;
self.id = ClipScrollNodeIndex(node_data.len() as u32);
let local_clip_rect = if self.world_content_transform.has_perspective_component() {
LayerRect::new(
LayerPoint::new(-MAX_LOCAL_VIEWPORT, -MAX_LOCAL_VIEWPORT),
LayerSize::new(2.0 * MAX_LOCAL_VIEWPORT, 2.0 * MAX_LOCAL_VIEWPORT)
)
} else {
self.combined_local_viewport_rect
};
let data = match self.world_content_transform.inverse() {
Some(inverse) => {
ClipScrollNodeData {
transform: self.world_content_transform,
inv_transform: inverse,
local_clip_rect,
reference_frame_relative_scroll_offset: self.reference_frame_relative_scroll_offset,
scroll_offset: self.scroll_offset(),
}
}
None => {
state.combined_outer_clip_bounds = DeviceIntRect::zero();
ClipScrollNodeData::invalid()
}
};
// Write the data that will be made available to the GPU for this node.
node_data.push(data);
}
fn calculate_sticky_offset(

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

@ -180,8 +180,8 @@ impl ClipScrollTree {
};
let point_in_layer = transformed_point - node.local_viewport_rect.origin.to_vector();
let clip_info = match node.node_type {
NodeType::Clip(ref info) => info,
let clip_sources_handle = match node.node_type {
NodeType::Clip(ref clip_sources_handle) => clip_sources_handle,
_ => {
cache.insert(*node_id, Some(point_in_layer));
return true;
@ -194,7 +194,7 @@ impl ClipScrollTree {
}
let point_in_clips = transformed_point - node.local_clip_rect.origin.to_vector();
for &(ref clip, _) in clip_store.get(&clip_info.clip_sources).clips() {
for &(ref clip, _) in clip_store.get(&clip_sources_handle).clips() {
if !clip.contains(&point_in_clips) {
cache.insert(*node_id, None);
return false;
@ -325,7 +325,7 @@ impl ClipScrollTree {
.scroll(scroll_location, phase)
}
pub fn update_all_node_transforms(
pub fn update_tree(
&mut self,
screen_rect: &DeviceIntRect,
device_pixel_ratio: f32,
@ -357,7 +357,7 @@ impl ClipScrollTree {
current_coordinate_system_id: CoordinateSystemId(0),
next_coordinate_system_id: CoordinateSystemId(0).next(),
};
self.update_node_transform(
self.update_node(
root_reference_frame_id,
&mut state,
device_pixel_ratio,
@ -368,7 +368,7 @@ impl ClipScrollTree {
);
}
fn update_node_transform(
fn update_node(
&mut self,
layer_id: ClipId,
state: &mut TransformUpdateState,
@ -387,12 +387,9 @@ impl ClipScrollTree {
None => return,
};
node.update_transform(
&mut state,
node_data
);
node.update_clip_work_item(
node.update(
&mut state,
node_data,
device_pixel_ratio,
clip_store,
resource_cache,
@ -403,7 +400,7 @@ impl ClipScrollTree {
};
for child_layer_id in node_children {
self.update_node_transform(
self.update_node(
child_layer_id,
&mut state,
device_pixel_ratio,
@ -507,11 +504,11 @@ impl ClipScrollTree {
let node = self.nodes.get(id).unwrap();
match node.node_type {
NodeType::Clip(ref info) => {
NodeType::Clip(ref clip_sources_handle) => {
pt.new_level("Clip".to_owned());
pt.add_item(format!("id: {:?}", id));
let clips = clip_store.get(&info.clip_sources).clips();
let clips = clip_store.get(&clip_sources_handle).clips();
pt.new_level(format!("Clip Sources [{}]", clips.len()));
for source in clips {
pt.add_item(format!("{:?}", source));

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

@ -266,7 +266,7 @@ impl DebugRenderer {
let _gm = GpuMarker::new(device.rc_gl(), "debug");
device.disable_depth();
device.set_blend(true);
device.set_blend_mode_alpha();
device.set_blend_mode_premultiplied_alpha();
let projection = Transform3D::ortho(
0.0,

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

@ -1882,16 +1882,6 @@ impl Device {
self.gl.blend_equation(gl::FUNC_ADD);
}
pub fn set_blend_mode_alpha(&self) {
self.gl.blend_func_separate(
gl::SRC_ALPHA,
gl::ONE_MINUS_SRC_ALPHA,
gl::ONE,
gl::ONE_MINUS_SRC_ALPHA,
);
self.gl.blend_equation(gl::FUNC_ADD);
}
pub fn set_blend_mode_multiply(&self) {
self.gl
.blend_func_separate(gl::ZERO, gl::SRC_COLOR, gl::ZERO, gl::SRC_ALPHA);

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

@ -15,14 +15,14 @@ use clip::ClipRegion;
use clip_scroll_node::StickyFrameInfo;
use clip_scroll_tree::{ClipScrollTree, ScrollStates};
use euclid::rect;
use frame_builder::{FrameBuilder, FrameBuilderConfig};
use frame_builder::{FrameBuilder, FrameBuilderConfig, ScrollbarInfo};
use gpu_cache::GpuCache;
use internal_types::{FastHashMap, FastHashSet, RendererFrame};
use prim_store::RectangleContent;
use profiler::{GpuCacheProfileCounters, TextureCacheProfileCounters};
use resource_cache::{FontInstanceMap,ResourceCache, TiledImageMap};
use scene::{Scene, StackingContextHelpers, ScenePipeline};
use tiling::{CompositeOps, Frame, PrimitiveFlags};
use tiling::{CompositeOps, Frame};
use util::ComplexClipRegionHelpers;
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Eq, Ord)]
@ -84,7 +84,9 @@ impl<'a> FlattenContext<'a> {
&mut self,
traversal: &mut BuiltDisplayListIter<'a>,
pipeline_id: PipelineId,
content_size: &LayoutSize,
frame_size: &LayoutSize,
root_reference_frame_id: ClipId,
root_scroll_frame_id: ClipId,
) {
self.builder.push_stacking_context(
&LayerVector2D::zero(),
@ -103,17 +105,16 @@ impl<'a> FlattenContext<'a> {
// For the root pipeline, there's no need to add a full screen rectangle
// here, as it's handled by the framebuffer clear.
let clip_id = ClipId::root_scroll_node(pipeline_id);
if self.scene.root_pipeline_id != Some(pipeline_id) {
if let Some(pipeline) = self.scene.pipelines.get(&pipeline_id) {
if let Some(bg_color) = pipeline.background_color {
let root_bounds = LayerRect::new(LayerPoint::zero(), *content_size);
let root_bounds = LayerRect::new(LayerPoint::zero(), *frame_size);
let info = LayerPrimitiveInfo::new(root_bounds);
self.builder.add_solid_rectangle(
ClipAndScrollInfo::simple(clip_id),
ClipAndScrollInfo::simple(root_reference_frame_id),
&info,
RectangleContent::Fill(bg_color),
PrimitiveFlags::None,
None,
);
}
}
@ -124,13 +125,12 @@ impl<'a> FlattenContext<'a> {
if self.builder.config.enable_scrollbars {
let scrollbar_rect = LayerRect::new(LayerPoint::zero(), LayerSize::new(10.0, 70.0));
let info = LayerPrimitiveInfo::new(scrollbar_rect);
let container_rect = LayerRect::new(LayerPoint::zero(), *frame_size);
self.builder.add_solid_rectangle(
ClipAndScrollInfo::simple(clip_id),
&info,
ClipAndScrollInfo::simple(root_reference_frame_id),
&LayerPrimitiveInfo::new(scrollbar_rect),
RectangleContent::Fill(DEFAULT_SCROLLBAR_COLOR),
PrimitiveFlags::Scrollbar(self.clip_scroll_tree.topmost_scrolling_node_id(), 4.0),
Some(ScrollbarInfo(root_scroll_frame_id, container_rect)),
);
}
@ -371,7 +371,9 @@ impl<'a> FlattenContext<'a> {
self.flatten_root(
&mut pipeline.display_list.iter(),
pipeline_id,
&pipeline.content_size,
&iframe_rect.size,
iframe_reference_frame_id,
ClipId::root_scroll_node(pipeline_id),
);
self.builder.pop_reference_frame();
@ -459,7 +461,7 @@ impl<'a> FlattenContext<'a> {
clip_and_scroll,
&prim_info,
RectangleContent::Fill(info.color),
PrimitiveFlags::None,
None,
);
}
}
@ -468,7 +470,7 @@ impl<'a> FlattenContext<'a> {
clip_and_scroll,
&prim_info,
RectangleContent::Clear,
PrimitiveFlags::None,
None,
);
}
SpecificDisplayItem::Line(ref info) => {
@ -689,7 +691,7 @@ impl<'a> FlattenContext<'a> {
*clip_and_scroll,
&prim_info,
content,
PrimitiveFlags::None,
None,
);
has_opaque = true;
}
@ -710,7 +712,7 @@ impl<'a> FlattenContext<'a> {
*clip_and_scroll,
&prim_info,
content,
PrimitiveFlags::None,
None,
);
}
true
@ -1142,10 +1144,14 @@ impl FrameContext {
roller.clip_scroll_tree,
);
let reference_frame_id = roller.clip_scroll_tree.root_reference_frame_id;
let scroll_frame_id = roller.clip_scroll_tree.topmost_scrolling_node_id;
roller.flatten_root(
&mut root_pipeline.display_list.iter(),
root_pipeline_id,
&root_pipeline.content_size,
&root_pipeline.viewport_size,
reference_frame_id,
scroll_frame_id,
);
self.pipeline_epoch_map.extend(roller.pipeline_epochs.drain(..));

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

@ -3,9 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderDetails, BorderDisplayItem, BuiltDisplayList};
use api::{ClipAndScrollInfo, ClipId, ColorF};
use api::{ClipAndScrollInfo, ClipId, ColorF, PremultipliedColorF};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
use api::{ExtendMode, FilterOp, FontInstance, FontRenderMode};
use api::{ExtendMode, FilterOp, FontRenderMode};
use api::{GlyphInstance, GlyphOptions, GradientStop, HitTestFlags, HitTestItem, HitTestResult};
use api::{ImageKey, ImageRendering, ItemRange, ItemTag, LayerPoint, LayerPrimitiveInfo, LayerRect};
use api::{LayerPixel, LayerSize, LayerToScrollTransform, LayerVector2D, LayoutVector2D, LineOrientation};
@ -15,13 +15,14 @@ use api::{WorldPixel, WorldPoint, YuvColorSpace, YuvData, device_length};
use app_units::Au;
use border::ImageBorderSegment;
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore, Contains};
use clip_scroll_node::{ClipInfo, ClipScrollNode, NodeType};
use clip_scroll_tree::{ClipScrollTree};
use clip_scroll_node::{ClipScrollNode, NodeType};
use clip_scroll_tree::ClipScrollTree;
use euclid::{SideOffsets2D, TypedTransform3D, vec2, vec3};
use frame::FrameId;
use glyph_rasterizer::FontInstance;
use gpu_cache::GpuCache;
use internal_types::{FastHashMap, FastHashSet, HardwareCompositeOp};
use picture::{PicturePrimitive};
use picture::{PictureKind, PicturePrimitive};
use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{TexelRect, YuvImagePrimitiveCpu};
use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu, LinePrimitive, PrimitiveKind};
@ -34,13 +35,15 @@ use render_task::RenderTaskTree;
use resource_cache::ResourceCache;
use scene::ScenePipeline;
use std::{mem, usize, f32, i32};
use tiling::{CompositeOps, Frame};
use tiling::{ContextIsolation, RenderTargetKind, StackingContextIndex};
use tiling::{PrimitiveFlags, PrimitiveRunCmd, RenderPass};
use tiling::{RenderTargetContext, ScrollbarPrimitive, StackingContext};
use tiling::{CompositeOps, ContextIsolation, Frame, PrimitiveRunCmd, RenderPass};
use tiling::{RenderTargetContext, RenderTargetKind, ScrollbarPrimitive, StackingContext};
use tiling::StackingContextIndex;
use util::{self, pack_as_float, RectHelpers, recycle_vec};
use box_shadow::BLUR_SAMPLE_SCALE;
#[derive(Debug)]
pub struct ScrollbarInfo(pub ClipId, pub LayerRect);
/// Construct a polygon from stacking context boundaries.
/// `anchor` here is an index that's going to be preserved in all the
/// splits of the polygon.
@ -473,11 +476,12 @@ impl FrameBuilder {
clip_scroll_tree: &mut ClipScrollTree,
) {
let clip_rect = clip_region.main;
let clip_info = ClipInfo::new(
clip_region,
&mut self.clip_store,
);
let node = ClipScrollNode::new_clip_node(pipeline_id, parent_id, clip_info, clip_rect);
let clip_sources = ClipSources::from(clip_region);
debug_assert!(clip_sources.has_clips());
let handle = self.clip_store.insert(clip_sources);
let node = ClipScrollNode::new_clip_node(pipeline_id, parent_id, handle, clip_rect);
clip_scroll_tree.add_node(node, new_node_id);
}
@ -565,7 +569,7 @@ impl FrameBuilder {
clip_and_scroll: ClipAndScrollInfo,
info: &LayerPrimitiveInfo,
content: RectangleContent,
flags: PrimitiveFlags,
scrollbar_info: Option<ScrollbarInfo>,
) {
if let RectangleContent::Fill(ColorF{a, ..}) = content {
if a == 0.0 {
@ -587,15 +591,12 @@ impl FrameBuilder {
PrimitiveContainer::Rectangle(prim),
);
match flags {
PrimitiveFlags::None => {}
PrimitiveFlags::Scrollbar(clip_id, border_radius) => {
self.scrollbar_prims.push(ScrollbarPrimitive {
prim_index,
clip_id,
border_radius,
});
}
if let Some(ScrollbarInfo(clip_id, frame_rect)) = scrollbar_info {
self.scrollbar_prims.push(ScrollbarPrimitive {
prim_index,
clip_id,
frame_rect,
});
}
}
@ -605,31 +606,33 @@ impl FrameBuilder {
info: &LayerPrimitiveInfo,
wavy_line_thickness: f32,
orientation: LineOrientation,
color: &ColorF,
line_color: &ColorF,
style: LineStyle,
) {
let line = LinePrimitive {
wavy_line_thickness,
color: *color,
style: style,
orientation: orientation,
color: line_color.premultiplied(),
style,
orientation,
};
let mut fast_shadow_prims = Vec::new();
for (idx, &(shadow_prim_index, _)) in self.shadow_prim_stack.iter().enumerate() {
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
let picture = &self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
let shadow = picture.as_text_shadow();
if shadow.blur_radius == 0.0 {
fast_shadow_prims.push((idx, shadow.clone()));
match picture.kind {
PictureKind::TextShadow { offset, color, blur_radius } if blur_radius == 0.0 => {
fast_shadow_prims.push((idx, offset, color));
}
_ => {}
}
}
for (idx, shadow) in fast_shadow_prims {
for (idx, shadow_offset, shadow_color) in fast_shadow_prims {
let mut line = line.clone();
line.color = shadow.color;
line.color = shadow_color.premultiplied();
let mut info = info.clone();
info.rect = info.rect.translate(&shadow.offset);
info.rect = info.rect.translate(&shadow_offset);
let prim_index = self.create_primitive(
&info,
Vec::new(),
@ -644,7 +647,7 @@ impl FrameBuilder {
PrimitiveContainer::Line(line),
);
if color.a > 0.0 {
if line_color.a > 0.0 {
if self.shadow_prim_stack.is_empty() {
self.add_primitive_to_hit_testing_list(&info, clip_and_scroll);
self.add_primitive_to_draw_list(prim_index, clip_and_scroll);
@ -658,15 +661,17 @@ impl FrameBuilder {
debug_assert_eq!(shadow_metadata.prim_kind, PrimitiveKind::Picture);
let picture =
&mut self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
let blur_radius = picture.as_text_shadow().blur_radius;
// Only run real blurs here (fast path zero blurs are handled above).
if blur_radius > 0.0 {
picture.add_primitive(
prim_index,
&info.rect,
clip_and_scroll,
);
match picture.kind {
// Only run real blurs here (fast path zero blurs are handled above).
PictureKind::TextShadow { blur_radius, .. } if blur_radius > 0.0 => {
picture.add_primitive(
prim_index,
&info.rect,
clip_and_scroll,
);
}
_ => {}
}
}
}
@ -1043,12 +1048,12 @@ impl FrameBuilder {
run_offset: LayoutVector2D,
info: &LayerPrimitiveInfo,
font: &FontInstance,
color: &ColorF,
text_color: &ColorF,
glyph_range: ItemRange<GlyphInstance>,
glyph_count: usize,
glyph_options: Option<GlyphOptions>,
) {
let rect = info.rect;
let original_rect = info.rect;
// Trivial early out checks
if font.size.0 <= 0 {
return;
@ -1093,7 +1098,7 @@ impl FrameBuilder {
let prim_font = FontInstance::new(
font.font_key,
font.size,
*color,
*text_color,
font.bg_color,
render_mode,
font.subpx_dir,
@ -1122,12 +1127,14 @@ impl FrameBuilder {
for (idx, &(shadow_prim_index, _)) in self.shadow_prim_stack.iter().enumerate() {
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
let picture_prim = &self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
let shadow = picture_prim.as_text_shadow();
if shadow.blur_radius == 0.0 {
let mut text_prim = prim.clone();
text_prim.font.color = shadow.color.into();
text_prim.offset += shadow.offset;
fast_shadow_prims.push((idx, text_prim));
match picture_prim.kind {
PictureKind::TextShadow { offset, color, blur_radius } if blur_radius == 0.0 => {
let mut text_prim = prim.clone();
text_prim.font.color = color.into();
text_prim.offset += offset;
fast_shadow_prims.push((idx, text_prim));
}
_ => {}
}
}
@ -1152,7 +1159,7 @@ impl FrameBuilder {
);
// Only add a visual element if it can contribute to the scene.
if color.a > 0.0 {
if text_color.a > 0.0 {
if self.shadow_prim_stack.is_empty() {
self.add_primitive_to_hit_testing_list(info, clip_and_scroll);
self.add_primitive_to_draw_list(prim_index, clip_and_scroll);
@ -1171,17 +1178,19 @@ impl FrameBuilder {
for &(shadow_prim_index, _) in &self.shadow_prim_stack {
let shadow_metadata = &mut self.prim_store.cpu_metadata[shadow_prim_index.0];
debug_assert_eq!(shadow_metadata.prim_kind, PrimitiveKind::Picture);
let picture_prim =
let picture =
&mut self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
// Only run real blurs here (fast path zero blurs are handled above).
let blur_radius = picture_prim.as_text_shadow().blur_radius;
if blur_radius > 0.0 {
picture_prim.add_primitive(
prim_index,
&rect,
clip_and_scroll,
);
match picture.kind {
// Only run real blurs here (fast path zero blurs are handled above).
PictureKind::TextShadow { blur_radius, .. } if blur_radius > 0.0 => {
picture.add_primitive(
prim_index,
&original_rect,
clip_and_scroll,
);
}
_ => {}
}
}
}
@ -1515,45 +1524,31 @@ impl FrameBuilder {
}
fn update_scroll_bars(&mut self, clip_scroll_tree: &ClipScrollTree, gpu_cache: &mut GpuCache) {
let distance_from_edge = 8.0;
static SCROLLBAR_PADDING: f32 = 8.0;
for scrollbar_prim in &self.scrollbar_prims {
let metadata = &mut self.prim_store.cpu_metadata[scrollbar_prim.prim_index.0];
let clip_scroll_node = &clip_scroll_tree.nodes[&scrollbar_prim.clip_id];
let scroll_frame = &clip_scroll_tree.nodes[&scrollbar_prim.clip_id];
// Invalidate what's in the cache so it will get rebuilt.
gpu_cache.invalidate(&metadata.gpu_location);
let scrollable_distance = clip_scroll_node.scrollable_size().height;
let scrollable_distance = scroll_frame.scrollable_size().height;
if scrollable_distance <= 0.0 {
metadata.local_clip_rect.size = LayerSize::zero();
continue;
}
let amount_scrolled = -scroll_frame.scroll_offset().y / scrollable_distance;
let scroll_offset = clip_scroll_node.scroll_offset();
let f = -scroll_offset.y / scrollable_distance;
let frame_rect = scrollbar_prim.frame_rect;
let min_y = frame_rect.origin.y + SCROLLBAR_PADDING;
let max_y = frame_rect.origin.y + frame_rect.size.height -
(SCROLLBAR_PADDING + metadata.local_rect.size.height);
let min_y = clip_scroll_node.local_viewport_rect.origin.y - scroll_offset.y +
distance_from_edge;
let max_y = clip_scroll_node.local_viewport_rect.origin.y +
clip_scroll_node.local_viewport_rect.size.height -
scroll_offset.y - metadata.local_rect.size.height -
distance_from_edge;
metadata.local_rect.origin.x = clip_scroll_node.local_viewport_rect.origin.x +
clip_scroll_node.local_viewport_rect.size.width -
metadata.local_rect.size.width -
distance_from_edge;
metadata.local_rect.origin.y = util::lerp(min_y, max_y, f);
metadata.local_rect.origin.x = frame_rect.origin.x + frame_rect.size.width -
(metadata.local_rect.size.width + SCROLLBAR_PADDING);
metadata.local_rect.origin.y = util::lerp(min_y, max_y, amount_scrolled);
metadata.local_clip_rect = metadata.local_rect;
// TODO(gw): The code to set / update border clips on scroll bars
// has been broken for a long time, so I've removed it
// for now. We can re-add that code once the clips
// data is moved over to the GPU cache!
}
}
@ -1716,7 +1711,7 @@ impl FrameBuilder {
RenderTargetKind::Color,
&[],
ClearMode::Transparent,
ColorF::new(0.0, 0.0, 0.0, 0.0),
PremultipliedColorF::TRANSPARENT,
);
let blur_render_task_id = render_tasks.add(blur_render_task);
let item = AlphaRenderItem::HardwareComposite(
@ -1856,7 +1851,12 @@ impl FrameBuilder {
self.prim_store
.add_render_tasks_for_prim(prim_index, &mut current_task);
let item =
AlphaRenderItem::Primitive(clip_node.id, scroll_node.id, prim_index, next_z);
AlphaRenderItem::Primitive(
clip_node.node_data_index,
scroll_node.node_data_index,
prim_index,
next_z
);
current_task.as_alpha_batch_mut().items.push(item);
next_z += 1;
}
@ -1903,7 +1903,7 @@ impl FrameBuilder {
let mut node_data = Vec::new();
clip_scroll_tree.update_all_node_transforms(
clip_scroll_tree.update_tree(
&screen_rect,
device_pixel_ratio,
&mut self.clip_store,

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

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{DevicePoint, DeviceUintSize, FontInstance, GlyphKey};
use glyph_rasterizer::GlyphFormat;
use api::{DevicePoint, DeviceUintSize, GlyphKey};
use glyph_rasterizer::{FontInstance, GlyphFormat};
use internal_types::FastHashMap;
use resource_cache::ResourceClassCache;
use std::sync::Arc;

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

@ -3,11 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#[cfg(test)]
use api::{ColorF, ColorU, IdNamespace, LayoutPoint, SubpixelDirection};
use api::{DevicePoint, DeviceUintSize, FontInstance, FontRenderMode};
use api::{FontKey, FontTemplate, GlyphDimensions, GlyphKey};
use api::{IdNamespace, LayoutPoint};
use api::{ColorF, ColorU, DevicePoint, DeviceUintSize};
use api::{FontInstancePlatformOptions, FontRenderMode, FontVariation};
use api::{FontKey, FontTemplate, GlyphDimensions, GlyphKey, SubpixelDirection};
use api::{ImageData, ImageDescriptor, ImageFormat};
#[cfg(test)]
use app_units::Au;
use device::TextureFilter;
use glyph_cache::{CachedGlyphInfo, GlyphCache};
@ -23,6 +23,58 @@ use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::mpsc::{channel, Receiver, Sender};
use texture_cache::{TextureCache, TextureCacheHandle};
#[derive(Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
pub struct FontInstance {
pub font_key: FontKey,
// The font size is in *device* pixels, not logical pixels.
// It is stored as an Au since we need sub-pixel sizes, but
// can't store as a f32 due to use of this type as a hash key.
// TODO(gw): Perhaps consider having LogicalAu and DeviceAu
// or something similar to that.
pub size: Au,
pub color: ColorU,
pub bg_color: ColorU,
pub render_mode: FontRenderMode,
pub subpx_dir: SubpixelDirection,
pub platform_options: Option<FontInstancePlatformOptions>,
pub variations: Vec<FontVariation>,
pub synthetic_italics: bool,
}
impl FontInstance {
pub fn new(
font_key: FontKey,
size: Au,
color: ColorF,
bg_color: ColorU,
render_mode: FontRenderMode,
subpx_dir: SubpixelDirection,
platform_options: Option<FontInstancePlatformOptions>,
variations: Vec<FontVariation>,
synthetic_italics: bool,
) -> Self {
FontInstance {
font_key,
size,
color: color.into(),
bg_color,
render_mode,
subpx_dir,
platform_options,
variations,
synthetic_italics,
}
}
pub fn get_subpx_offset(&self, glyph: &GlyphKey) -> (f64, f64) {
match self.subpx_dir {
SubpixelDirection::None => (0.0, 0.0),
SubpixelDirection::Horizontal => (glyph.subpixel_offset.into(), 0.0),
SubpixelDirection::Vertical => (0.0, glyph.subpixel_offset.into()),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum GlyphFormat {
Mono,

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

@ -24,7 +24,7 @@
//! address in the GPU cache of a given resource slot
//! for this frame.
use api::{ColorF, LayerRect};
use api::{LayerRect, PremultipliedColorF};
use device::FrameId;
use internal_types::UvRect;
use profiler::GpuCacheProfileCounters;
@ -64,7 +64,7 @@ impl GpuBlockData {
}
/// Conversion helpers for GpuBlockData
impl Into<GpuBlockData> for ColorF {
impl Into<GpuBlockData> for PremultipliedColorF {
fn into(self) -> GpuBlockData {
GpuBlockData {
data: [self.r, self.g, self.b, self.a],

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

@ -31,7 +31,7 @@ pub struct BlurInstance {
#[repr(C)]
pub struct ClipMaskInstance {
pub render_task_address: RenderTaskAddress,
pub scroll_node_id: ClipScrollNodeIndex,
pub scroll_node_data_index: ClipScrollNodeIndex,
pub segment: i32,
pub clip_data_address: GpuCacheAddress,
pub resource_address: GpuCacheAddress,

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

@ -2,8 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderRadiusKind, ColorF, ClipAndScrollInfo, device_length, DeviceIntSize};
use api::{BoxShadowClipMode, LayerPoint, LayerRect, LayerSize, Shadow};
use api::{BorderRadiusKind, ColorF, ClipAndScrollInfo};
use api::{device_length, DeviceIntSize};
use api::{BoxShadowClipMode, LayerPoint, LayerRect, LayerSize, LayerVector2D, Shadow};
use box_shadow::BLUR_SAMPLE_SCALE;
use frame_builder::PrimitiveContext;
use gpu_cache::GpuDataRequest;
@ -24,7 +25,9 @@ use tiling::RenderTargetKind;
#[derive(Debug)]
pub enum PictureKind {
TextShadow {
shadow: Shadow,
offset: LayerVector2D,
color: ColorF,
blur_radius: f32,
},
BoxShadow {
blur_radius: f32,
@ -48,13 +51,15 @@ pub struct PicturePrimitive {
}
impl PicturePrimitive {
pub fn new_text_shadow(shadow: Shadow) -> PicturePrimitive {
pub fn new_text_shadow(shadow: Shadow) -> Self {
PicturePrimitive {
prim_runs: Vec::new(),
render_task_id: None,
content_rect: LayerRect::zero(),
kind: PictureKind::TextShadow {
shadow,
offset: shadow.offset,
color: shadow.color,
blur_radius: shadow.blur_radius,
},
}
}
@ -65,14 +70,14 @@ impl PicturePrimitive {
blur_regions: Vec<LayerRect>,
clip_mode: BoxShadowClipMode,
radii_kind: BorderRadiusKind,
) -> PicturePrimitive {
) -> Self {
PicturePrimitive {
prim_runs: Vec::new(),
render_task_id: None,
content_rect: LayerRect::zero(),
kind: PictureKind::BoxShadow {
blur_radius,
color: color.premultiplied(),
color,
blur_regions,
clip_mode,
radii_kind,
@ -80,13 +85,6 @@ impl PicturePrimitive {
}
}
pub fn as_text_shadow(&self) -> &Shadow {
match self.kind {
PictureKind::TextShadow { ref shadow } => shadow,
PictureKind::BoxShadow { .. } => panic!("bug: not a text shadow")
}
}
pub fn add_primitive(
&mut self,
prim_index: PrimitiveIndex,
@ -120,15 +118,15 @@ impl PicturePrimitive {
pub fn build(&mut self) -> LayerRect {
match self.kind {
PictureKind::TextShadow { ref shadow } => {
let blur_offset = shadow.blur_radius * BLUR_SAMPLE_SCALE;
PictureKind::TextShadow { offset, blur_radius, .. } => {
let blur_offset = blur_radius * BLUR_SAMPLE_SCALE;
self.content_rect = self.content_rect.inflate(
blur_offset,
blur_offset,
);
self.content_rect.translate(&shadow.offset)
self.content_rect.translate(&offset)
}
PictureKind::BoxShadow { blur_radius, clip_mode, radii_kind, .. } => {
// We need to inflate the content rect if outset.
@ -193,8 +191,8 @@ impl PicturePrimitive {
let cache_size = DeviceIntSize::new(cache_width, cache_height);
match self.kind {
PictureKind::TextShadow { ref shadow } => {
let blur_radius = device_length(shadow.blur_radius, prim_context.device_pixel_ratio);
PictureKind::TextShadow { blur_radius, color, .. } => {
let blur_radius = device_length(blur_radius, prim_context.device_pixel_ratio);
// Quote from https://drafts.csswg.org/css-backgrounds-3/#shadow-blur
// "the image that would be generated by applying to the shadow a
@ -206,7 +204,7 @@ impl PicturePrimitive {
prim_index,
RenderTargetKind::Color,
self.content_rect.origin,
shadow.color,
color.premultiplied(),
ClearMode::Transparent,
);
@ -219,7 +217,7 @@ impl PicturePrimitive {
RenderTargetKind::Color,
&[],
ClearMode::Transparent,
shadow.color,
color.premultiplied(),
);
self.render_task_id = Some(render_tasks.add(render_task));
@ -246,7 +244,7 @@ impl PicturePrimitive {
prim_index,
RenderTargetKind::Alpha,
self.content_rect.origin,
color,
color.premultiplied(),
ClearMode::Zero,
);
@ -259,7 +257,7 @@ impl PicturePrimitive {
RenderTargetKind::Alpha,
blur_regions,
blur_clear_mode,
color,
color.premultiplied(),
);
self.render_task_id = Some(render_tasks.add(render_task));

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

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ColorU, FontKey, FontRenderMode, GlyphDimensions};
use api::{FontInstance, FontVariation, NativeFontHandle};
use api::{FontVariation, NativeFontHandle};
use api::{GlyphKey, SubpixelDirection};
use app_units::Au;
use core_foundation::array::{CFArray, CFArrayRef};
@ -22,7 +22,7 @@ use core_text;
use core_text::font::{CTFont, CTFontRef};
use core_text::font_descriptor::{kCTFontDefaultOrientation, kCTFontColorGlyphsTrait};
use gamma_lut::{ColorLut, GammaLut};
use glyph_rasterizer::{GlyphFormat, RasterizedGlyph};
use glyph_rasterizer::{FontInstance, GlyphFormat, RasterizedGlyph};
use internal_types::FastHashMap;
use std::collections::hash_map::Entry;
use std::ptr;

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

@ -2,9 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{FontInstance, FontKey, FontRenderMode, GlyphDimensions};
use api::{ColorU, GlyphDimensions, GlyphKey, FontKey, FontRenderMode};
use api::{FontInstancePlatformOptions, FontLCDFilter, FontHinting};
use api::{NativeFontHandle, SubpixelDirection, GlyphKey, ColorU};
use api::{NativeFontHandle, SubpixelDirection};
use api::{FONT_FORCE_AUTOHINT, FONT_NO_AUTOHINT, FONT_EMBEDDED_BITMAP};
use api::{FONT_EMBOLDEN, FONT_VERTICAL_LAYOUT, FONT_SUBPIXEL_BGR};
use freetype::freetype::{FT_BBox, FT_Outline_Translate, FT_Pixel_Mode, FT_Render_Mode};
@ -18,7 +18,7 @@ use freetype::freetype::{FT_LOAD_COLOR, FT_LOAD_DEFAULT, FT_LOAD_FORCE_AUTOHINT}
use freetype::freetype::{FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH, FT_LOAD_NO_AUTOHINT};
use freetype::freetype::{FT_LOAD_NO_BITMAP, FT_LOAD_NO_HINTING, FT_LOAD_VERTICAL_LAYOUT};
use freetype::freetype::{FT_FACE_FLAG_SCALABLE, FT_FACE_FLAG_FIXED_SIZES, FT_Err_Cannot_Render_Glyph};
use glyph_rasterizer::{GlyphFormat, RasterizedGlyph};
use glyph_rasterizer::{FontInstance, GlyphFormat, RasterizedGlyph};
use internal_types::FastHashMap;
use std::{cmp, mem, ptr, slice};
use std::cmp::max;
@ -398,13 +398,13 @@ impl FontContext {
match font.render_mode {
FontRenderMode::Mono | FontRenderMode::Bitmap => {
// In mono/bitmap modes the color of the font is irrelevant.
font.color = ColorU::new(255, 255, 255, 255);
font.color = ColorU::new(0xFF, 0xFF, 0xFF, 0xFF);
// Subpixel positioning is disabled in mono and bitmap modes.
font.subpx_dir = SubpixelDirection::None;
}
FontRenderMode::Alpha | FontRenderMode::Subpixel => {
// We don't do any preblending with FreeType currently, so the color is not used.
font.color = ColorU::new(255, 255, 255, 255);
font.color = ColorU::new(0xFF, 0xFF, 0xFF, 0xFF);
}
}
}

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

@ -2,11 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{FontInstance, FontInstancePlatformOptions, FontKey, FontRenderMode};
use api::{FontInstancePlatformOptions, FontKey, FontRenderMode};
use api::{ColorU, GlyphDimensions, GlyphKey, SubpixelDirection};
use dwrote;
use gamma_lut::{ColorLut, GammaLut};
use glyph_rasterizer::{GlyphFormat, RasterizedGlyph};
use glyph_rasterizer::{FontInstance, GlyphFormat, RasterizedGlyph};
use internal_types::FastHashMap;
use std::sync::Arc;

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

@ -3,13 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderRadius, BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect};
use api::{DevicePoint, ExtendMode, FontInstance, GlyphInstance, GlyphKey};
use api::{DevicePoint, ExtendMode, GlyphInstance, GlyphKey};
use api::{GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag, LayerPoint, LayerRect};
use api::{ClipMode, LayerSize, LayerVector2D, LineOrientation, LineStyle};
use api::{ClipAndScrollInfo, EdgeAaSegmentMask, TileOffset, YuvColorSpace, YuvFormat};
use api::{ClipAndScrollInfo, EdgeAaSegmentMask, PremultipliedColorF, TileOffset};
use api::{YuvColorSpace, YuvFormat};
use border::BorderCornerInstance;
use clip::{ClipSourcesHandle, ClipStore, Geometry};
use frame_builder::PrimitiveContext;
use glyph_rasterizer::FontInstance;
use gpu_cache::{GpuBlockData, GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest,
ToGpuBlocks};
use picture::PicturePrimitive;
@ -180,15 +182,11 @@ pub struct RectanglePrimitive {
impl ToGpuBlocks for RectanglePrimitive {
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
match &self.content {
&RectangleContent::Fill(ref color) => {
request.push(color.premultiplied());
}
&RectangleContent::Clear => {
// Opaque black with operator dest out
request.push(ColorF::new(0.0, 0.0, 0.0, 1.0));
}
}
request.push(match self.content {
RectangleContent::Fill(color) => color.premultiplied(),
// Opaque black with operator dest out
RectangleContent::Clear => PremultipliedColorF::BLACK,
});
request.extend_from_slice(&[GpuBlockData {
data: [self.edge_aa_segment_mask.bits() as f32, 0.0, 0.0, 0.0],
}]);
@ -254,7 +252,7 @@ impl ToGpuBlocks for BrushPrimitive {
#[derive(Debug, Clone)]
#[repr(C)]
pub struct LinePrimitive {
pub color: ColorF,
pub color: PremultipliedColorF,
pub wavy_line_thickness: f32,
pub style: LineStyle,
pub orientation: LineOrientation,
@ -377,8 +375,8 @@ pub const GRADIENT_DATA_SIZE: usize = GRADIENT_DATA_TABLE_SIZE + 2;
#[repr(C)]
// An entry in a gradient data table representing a segment of the gradient color space.
pub struct GradientDataEntry {
pub start_color: ColorF,
pub end_color: ColorF,
pub start_color: PremultipliedColorF,
pub end_color: PremultipliedColorF,
}
struct GradientGpuBlockBuilder<'a> {
@ -390,7 +388,7 @@ impl<'a> GradientGpuBlockBuilder<'a> {
fn new(
stops_range: ItemRange<GradientStop>,
display_list: &'a BuiltDisplayList,
) -> GradientGpuBlockBuilder<'a> {
) -> Self {
GradientGpuBlockBuilder {
stops_range,
display_list,
@ -403,8 +401,8 @@ impl<'a> GradientGpuBlockBuilder<'a> {
&self,
start_idx: usize,
end_idx: usize,
start_color: &ColorF,
end_color: &ColorF,
start_color: &PremultipliedColorF,
end_color: &PremultipliedColorF,
entries: &mut [GradientDataEntry; GRADIENT_DATA_SIZE],
) {
// Calculate the color difference for individual steps in the ramp.
@ -628,8 +626,12 @@ impl TextRunPrimitiveCpu {
}
fn write_gpu_blocks(&self, request: &mut GpuDataRequest) {
let bg_color = ColorF::from(self.font.bg_color);
request.push(ColorF::from(self.font.color).premultiplied());
request.push(ColorF::from(self.font.bg_color));
// this is the only case where we need to provide plain color to GPU
request.extend_from_slice(&[
GpuBlockData { data: [bg_color.r, bg_color.g, bg_color.b, 1.0] }
]);
request.push([
self.offset.x,
self.offset.y,
@ -1239,7 +1241,8 @@ impl PrimitiveStore {
let prim_clips = clip_store.get(&metadata.clip_sources);
let is_axis_aligned = transform.transform_kind() == TransformedRectKind::AxisAligned;
let clip_task = if prim_context.clip_node.clip_chain_node.is_some() || prim_clips.is_masking() {
let has_clips = prim_context.clip_node.clip_chain_node.is_some() || prim_clips.has_clips();
let clip_task = if has_clips {
// Take into account the actual clip info of the primitive, and
// mutate the current bounds accordingly.
let mask_rect = match prim_clips.bounds.outer {
@ -1253,10 +1256,10 @@ impl PrimitiveStore {
_ => prim_screen_rect,
};
let extra_clip = if prim_clips.is_masking() {
let extra_clip = if prim_clips.has_clips() {
Some(Rc::new(ClipChainNode {
work_item: ClipWorkItem {
scroll_node_id: prim_context.scroll_node.id,
scroll_node_data_index: prim_context.scroll_node.node_data_index,
clip_sources: metadata.clip_sources.weak(),
coordinate_system_id: prim_context.scroll_node.coordinate_system_id,
},

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

@ -568,8 +568,8 @@ impl ProfileGraph {
rect.origin.y,
rect.origin.x + rect.size.width + 10.0,
rect.origin.y + rect.size.height,
ColorF::new(0.1, 0.1, 0.1, 0.8).into(),
ColorF::new(0.2, 0.2, 0.2, 0.8).into(),
ColorU::new(25, 25, 25, 200),
ColorU::new(51, 51, 51, 200),
);
let bx0 = x + 10.0;
@ -655,8 +655,8 @@ impl GpuFrameCollection {
bounding_rect.origin.y,
bounding_rect.origin.x + bounding_rect.size.width,
bounding_rect.origin.y + bounding_rect.size.height,
ColorF::new(0.1, 0.1, 0.1, 0.8).into(),
ColorF::new(0.2, 0.2, 0.2, 0.8).into(),
ColorU::new(25, 25, 25, 200),
ColorU::new(51, 51, 51, 200),
);
let w = graph_rect.size.width;

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

@ -471,11 +471,13 @@ impl RenderBackend {
self.resource_cache
.update_resources(updates, &mut profile_counters.resources);
}
ApiMsg::GetGlyphDimensions(font, glyph_keys, tx) => {
ApiMsg::GetGlyphDimensions(instance_key, glyph_keys, tx) => {
let mut glyph_dimensions = Vec::with_capacity(glyph_keys.len());
for glyph_key in &glyph_keys {
let glyph_dim = self.resource_cache.get_glyph_dimensions(&font, glyph_key);
glyph_dimensions.push(glyph_dim);
if let Some(font) = self.resource_cache.get_font_instance(instance_key) {
for glyph_key in &glyph_keys {
let glyph_dim = self.resource_cache.get_glyph_dimensions(&font, glyph_key);
glyph_dimensions.push(glyph_dim);
}
}
tx.send(glyph_dimensions).unwrap();
}

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

@ -3,8 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ClipId, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{ColorF, FilterOp, LayerPoint, MixBlendMode};
use api::{LayerRect, PipelineId};
use api::{FilterOp, LayerPoint, LayerRect, MixBlendMode};
use api::{PipelineId, PremultipliedColorF};
use clip::{ClipSource, ClipSourcesWeakHandle, ClipStore};
use clip_scroll_tree::CoordinateSystemId;
use gpu_cache::GpuCacheHandle;
@ -204,7 +204,7 @@ pub enum MaskGeometryKind {
#[derive(Debug, Clone)]
pub struct ClipWorkItem {
pub scroll_node_id: ClipScrollNodeIndex,
pub scroll_node_data_index: ClipScrollNodeIndex,
pub clip_sources: ClipSourcesWeakHandle,
pub coordinate_system_id: CoordinateSystemId,
}
@ -263,7 +263,7 @@ pub struct PictureTask {
pub prim_index: PrimitiveIndex,
pub target_kind: RenderTargetKind,
pub content_origin: LayerPoint,
pub color: ColorF,
pub color: PremultipliedColorF,
}
#[derive(Debug)]
@ -271,7 +271,7 @@ pub struct BlurTask {
pub blur_std_deviation: f32,
pub target_kind: RenderTargetKind,
pub regions: Vec<LayerRect>,
pub color: ColorF,
pub color: PremultipliedColorF,
pub scale_factor: f32,
}
@ -316,7 +316,7 @@ impl RenderTask {
screen_origin: DeviceIntPoint,
location: RenderTaskLocation,
frame_output_pipeline_id: Option<PipelineId>,
) -> RenderTask {
) -> Self {
RenderTask {
cache_key: None,
children: Vec::new(),
@ -333,7 +333,7 @@ impl RenderTask {
pub fn new_dynamic_alpha_batch(
rect: &DeviceIntRect,
frame_output_pipeline_id: Option<PipelineId>,
) -> RenderTask {
) -> Self {
let location = RenderTaskLocation::Dynamic(None, rect.size);
Self::new_alpha_batch(rect.origin, location, frame_output_pipeline_id)
}
@ -343,9 +343,9 @@ impl RenderTask {
prim_index: PrimitiveIndex,
target_kind: RenderTargetKind,
content_origin: LayerPoint,
color: ColorF,
color: PremultipliedColorF,
clear_mode: ClearMode,
) -> RenderTask {
) -> Self {
RenderTask {
cache_key: None,
children: Vec::new(),
@ -360,7 +360,7 @@ impl RenderTask {
}
}
pub fn new_readback(screen_rect: DeviceIntRect) -> RenderTask {
pub fn new_readback(screen_rect: DeviceIntRect) -> Self {
RenderTask {
cache_key: None,
children: Vec::new(),
@ -379,7 +379,7 @@ impl RenderTask {
clip_store: &ClipStore,
is_axis_aligned: bool,
prim_coordinate_system_id: CoordinateSystemId,
) -> Option<RenderTask> {
) -> Option<Self> {
// Filter out all the clip instances that don't contribute to the result
let mut current_coordinate_system_id = prim_coordinate_system_id;
let mut inner_rect = Some(task_rect);
@ -399,7 +399,7 @@ impl RenderTask {
let clip_info = clip_store
.get_opt(&node.work_item.clip_sources)
.expect("bug: clip item should exist");
debug_assert!(clip_info.is_masking());
debug_assert!(clip_info.has_clips());
match clip_info.bounds.inner {
Some(ref inner) if !inner.device_rect.is_empty() => {
@ -453,7 +453,7 @@ impl RenderTask {
})
}
// Construct a render task to apply a blur to a primitive.
// Construct a render task to apply a blur to a primitive.
// The render task chain that is constructed looks like:
//
// PrimitiveCacheTask: Draw the primitives.
@ -478,8 +478,8 @@ impl RenderTask {
target_kind: RenderTargetKind,
regions: &[LayerRect],
clear_mode: ClearMode,
color: ColorF,
) -> RenderTask {
color: PremultipliedColorF,
) -> Self {
// Adjust large std deviation value.
let mut adjusted_blur_std_deviation = blur_std_deviation;
let blur_target_size = render_tasks.get(src_task_id).get_dynamic_size();
@ -540,7 +540,7 @@ impl RenderTask {
target_kind: RenderTargetKind,
src_task_id: RenderTaskId,
target_size: DeviceIntSize,
) -> RenderTask {
) -> Self {
RenderTask {
cache_key: None,
children: vec![src_task_id],
@ -649,8 +649,8 @@ impl RenderTask {
],
}
}
RenderTaskKind::VerticalBlur(ref task_info) |
RenderTaskKind::HorizontalBlur(ref task_info) => {
RenderTaskKind::VerticalBlur(ref task) |
RenderTaskKind::HorizontalBlur(ref task) => {
let (target_rect, target_index) = self.get_target_rect();
RenderTaskData {
data: [
@ -659,13 +659,13 @@ impl RenderTask {
target_rect.size.width as f32,
target_rect.size.height as f32,
target_index.0 as f32,
task_info.blur_std_deviation,
task_info.scale_factor,
task.blur_std_deviation,
task.scale_factor,
0.0,
task_info.color.r,
task_info.color.g,
task_info.color.b,
task_info.color.a,
task.color.r,
task.color.g,
task.color.b,
task.color.a,
],
}
}

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

@ -10,7 +10,7 @@
//! [renderer]: struct.Renderer.html
use api::{channel, BlobImageRenderer, FontRenderMode};
use api::{ColorF, ColorU, Epoch, PipelineId, RenderApiSender, RenderNotifier};
use api::{ColorF, Epoch, PipelineId, RenderApiSender, RenderNotifier};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
use api::{ExternalImageId, ExternalImageType, ImageFormat};
use api::{YUV_COLOR_SPACES, YUV_FORMATS};
@ -639,10 +639,9 @@ impl SourceTextureResolver {
#[allow(dead_code)] // SubpixelVariableTextColor is not used at the moment.
pub enum BlendMode {
None,
Alpha,
PremultipliedAlpha,
PremultipliedDestOut,
SubpixelConstantTextColor(ColorU),
SubpixelConstantTextColor(ColorF),
SubpixelWithBgColor,
SubpixelVariableTextColor,
}
@ -1013,7 +1012,6 @@ impl BrushShader {
BlendMode::None => {
self.opaque.bind(device, projection, mode, renderer_errors)
}
BlendMode::Alpha |
BlendMode::PremultipliedAlpha |
BlendMode::PremultipliedDestOut |
BlendMode::SubpixelConstantTextColor(..) |
@ -2517,7 +2515,6 @@ impl Renderer {
TransformBatchKind::Rectangle(needs_clipping) => {
debug_assert!(
!needs_clipping || match key.blend_mode {
BlendMode::Alpha |
BlendMode::PremultipliedAlpha |
BlendMode::PremultipliedDestOut |
BlendMode::SubpixelConstantTextColor(..) |
@ -2759,7 +2756,6 @@ impl Renderer {
self.device.disable_depth();
self.device.enable_depth_write();
self.device.set_blend(false);
self.device.set_blend_mode_alpha();
match render_target {
Some(..) if self.enable_clear_scissor => {
// TODO(gw): Applying a scissor rect and minimal clear here
@ -2818,7 +2814,7 @@ impl Renderer {
// to multiple tiles in the normal text run case.
if !target.text_run_cache_prims.is_empty() {
self.device.set_blend(true);
self.device.set_blend_mode_alpha();
self.device.set_blend_mode_premultiplied_alpha();
let _gm = self.gpu_profile.add_marker(GPU_TAG_CACHE_TEXT_RUN);
self.cs_text_run
@ -2835,7 +2831,7 @@ impl Renderer {
// TODO(gw): Technically, we don't need blend for solid
// lines. We could check that here?
self.device.set_blend(true);
self.device.set_blend_mode_alpha();
self.device.set_blend_mode_premultiplied_alpha();
let _gm = self.gpu_profile.add_marker(GPU_TAG_CACHE_LINE);
self.cs_line
@ -2888,7 +2884,6 @@ impl Renderer {
if self.debug_flags.contains(DebugFlags::ALPHA_PRIM_DBG) {
let color = match batch.key.blend_mode {
BlendMode::None => debug_colors::BLACK,
BlendMode::Alpha => debug_colors::YELLOW,
BlendMode::PremultipliedAlpha => debug_colors::GREY,
BlendMode::PremultipliedDestOut => debug_colors::SALMON,
BlendMode::SubpixelConstantTextColor(..) => debug_colors::GREEN,
@ -2932,7 +2927,7 @@ impl Renderer {
);
}
BlendMode::SubpixelConstantTextColor(color) => {
self.device.set_blend_mode_subpixel_constant_text_color(color.into());
self.device.set_blend_mode_subpixel_constant_text_color(color);
self.ps_text_run.bind(
&mut self.device,
@ -3038,7 +3033,7 @@ impl Renderer {
self.device
.draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
}
BlendMode::Alpha | BlendMode::PremultipliedDestOut | BlendMode::None => {
BlendMode::PremultipliedDestOut | BlendMode::None => {
unreachable!("bug: bad blend mode for text");
}
}
@ -3052,10 +3047,6 @@ impl Renderer {
BlendMode::None => {
self.device.set_blend(false);
}
BlendMode::Alpha => {
self.device.set_blend(true);
self.device.set_blend_mode_alpha();
}
BlendMode::PremultipliedAlpha => {
self.device.set_blend(true);
self.device.set_blend_mode_premultiplied_alpha();

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

@ -6,7 +6,7 @@ use api::{AddFont, BlobImageData, BlobImageResources, ResourceUpdate, ResourceUp
use api::{BlobImageDescriptor, BlobImageError, BlobImageRenderer, BlobImageRequest};
use api::{ColorF, FontRenderMode};
use api::{DevicePoint, DeviceUintRect, DeviceUintSize};
use api::{Epoch, FontInstance, FontInstanceKey, FontKey, FontTemplate};
use api::{Epoch, FontInstanceKey, FontKey, FontTemplate};
use api::{ExternalImageData, ExternalImageType};
use api::{FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
use api::{GlyphDimensions, GlyphKey, IdNamespace};
@ -16,7 +16,7 @@ use app_units::Au;
use device::TextureFilter;
use frame::FrameId;
use glyph_cache::GlyphCache;
use glyph_rasterizer::{GlyphFormat, GlyphRasterizer, GlyphRequest};
use glyph_rasterizer::{FontInstance, GlyphFormat, GlyphRasterizer, GlyphRequest};
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
use internal_types::{FastHashMap, FastHashSet, SourceTexture, TextureUpdateList};
use profiler::{ResourceProfileCounters, TextureCacheProfileCounters};
@ -389,6 +389,11 @@ impl ResourceCache {
self.resources.font_instances.clone()
}
pub fn get_font_instance(&self, instance_key: FontInstanceKey) -> Option<FontInstance> {
let instance_map = self.resources.font_instances.read().unwrap();
instance_map.get(&instance_key).cloned()
}
pub fn add_image_template(
&mut self,
image_key: ImageKey,

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

@ -62,7 +62,7 @@ impl AlphaBatchHelpers for PrimitiveStore {
if font.bg_color.a != 0 {
BlendMode::SubpixelWithBgColor
} else {
BlendMode::SubpixelConstantTextColor(font.color)
BlendMode::SubpixelConstantTextColor(font.color.into())
}
}
FontRenderMode::Alpha |
@ -89,21 +89,17 @@ impl AlphaBatchHelpers for PrimitiveStore {
},
PrimitiveKind::Border |
PrimitiveKind::Image |
PrimitiveKind::YuvImage |
PrimitiveKind::AlignedGradient |
PrimitiveKind::AngleGradient |
PrimitiveKind::RadialGradient |
PrimitiveKind::Line |
PrimitiveKind::Brush |
PrimitiveKind::Picture => if needs_blending {
BlendMode::PremultipliedAlpha
} else {
BlendMode::None
},
PrimitiveKind::YuvImage |
PrimitiveKind::Line |
PrimitiveKind::Brush => if needs_blending {
BlendMode::Alpha
} else {
BlendMode::None
},
}
}
}
@ -112,7 +108,7 @@ impl AlphaBatchHelpers for PrimitiveStore {
pub struct ScrollbarPrimitive {
pub clip_id: ClipId,
pub prim_index: PrimitiveIndex,
pub border_radius: f32,
pub frame_rect: LayerRect,
}
#[derive(Debug)]
@ -122,12 +118,6 @@ pub enum PrimitiveRunCmd {
PrimitiveRun(PrimitiveRun),
}
#[derive(Debug, Copy, Clone)]
pub enum PrimitiveFlags {
None,
Scrollbar(ClipId, f32),
}
#[derive(Debug, Copy, Clone)]
pub struct RenderTargetIndex(pub usize);
@ -282,7 +272,7 @@ impl BatchList {
) -> &mut Vec<PrimitiveInstance> {
match key.blend_mode {
BlendMode::None => self.opaque_batch_list.get_suitable_batch(key),
BlendMode::Alpha | BlendMode::PremultipliedAlpha |
BlendMode::PremultipliedAlpha |
BlendMode::PremultipliedDestOut |
BlendMode::SubpixelConstantTextColor(..) |
BlendMode::SubpixelVariableTextColor |
@ -399,7 +389,7 @@ impl AlphaRenderItem {
source_id,
backdrop_id,
},
BlendMode::Alpha,
BlendMode::PremultipliedAlpha,
BatchTextures::no_texture(),
);
let batch = batch_list.get_suitable_batch(key, &stacking_context.screen_bounds);
@ -881,7 +871,7 @@ impl ClipBatcher {
for work_item in clips.iter() {
let instance = ClipMaskInstance {
render_task_address: task_address,
scroll_node_id: work_item.scroll_node_id,
scroll_node_data_index: work_item.scroll_node_data_index,
segment: 0,
clip_data_address: GpuCacheAddress::invalid(),
resource_address: GpuCacheAddress::invalid(),

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

@ -1,6 +1,6 @@
[package]
name = "webrender_api"
version = "0.53.1"
version = "0.53.2"
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/webrender"

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

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use {BuiltDisplayList, BuiltDisplayListDescriptor, ClipId, ColorF, DeviceIntPoint, DeviceUintRect};
use {DeviceUintSize, FontInstance, FontInstanceKey, FontInstanceOptions};
use {DeviceUintSize, FontInstanceKey, FontInstanceOptions};
use {FontInstancePlatformOptions, FontKey, FontVariation, GlyphDimensions, GlyphKey, ImageData};
use {ImageDescriptor, ImageKey, ItemTag, LayoutPoint, LayoutSize, LayoutTransform, LayoutVector2D};
use {NativeFontHandle, WorldPoint};
@ -265,7 +265,7 @@ pub enum ApiMsg {
UpdateResources(ResourceUpdates),
/// Gets the glyph dimensions
GetGlyphDimensions(
FontInstance,
FontInstanceKey,
Vec<GlyphKey>,
MsgSender<Vec<Option<GlyphDimensions>>>,
),
@ -387,13 +387,14 @@ impl RenderApiSender {
/// Creates a new resource API object with a dedicated namespace.
pub fn create_api(&self) -> RenderApi {
let (sync_tx, sync_rx) = channel::msg_channel().unwrap();
let (sync_tx, sync_rx) =
channel::msg_channel().expect("Failed to create channel");
let msg = ApiMsg::CloneApi(sync_tx);
self.api_sender.send(msg).unwrap();
self.api_sender.send(msg).expect("Failed to send CloneApi message");
RenderApi {
api_sender: self.api_sender.clone(),
payload_sender: self.payload_sender.clone(),
namespace_id: sync_rx.recv().unwrap(),
namespace_id: sync_rx.recv().expect("Failed to receive API response"),
next_id: Cell::new(ResourceId(0)),
}
}
@ -447,7 +448,7 @@ impl RenderApi {
/// This means that glyph dimensions e.g. for spaces (' ') will mostly be None.
pub fn get_glyph_dimensions(
&self,
font: FontInstance,
font: FontInstanceKey,
glyph_keys: Vec<GlyphKey>,
) -> Vec<Option<GlyphDimensions>> {
let (tx, rx) = channel::msg_channel().unwrap();

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

@ -2,8 +2,32 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::cmp;
use std::hash::{Hash, Hasher};
/// Represents pre-multiplied RGBA colors with floating point numbers.
///
/// All components must be between 0.0 and 1.0.
/// An alpha value of 1.0 is opaque while 0.0 is fully transparent.
///
/// In premultiplied colors transitions to transparent always look "nice"
/// therefore they are used in CSS gradients.
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct PremultipliedColorF {
pub r: f32,
pub g: f32,
pub b: f32,
pub a: f32,
}
impl PremultipliedColorF {
///
pub const BLACK: Self = PremultipliedColorF { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
///
pub const TRANSPARENT: Self = PremultipliedColorF { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
}
/// Represents RGBA screen colors with floating point numbers.
///
/// All components must be between 0.0 and 1.0.
@ -38,33 +62,26 @@ impl ColorF {
}
/// Multiply the RGB components with the alpha channel.
///
/// In premultiplied colors transistions to transparent always look "nice"
/// therefore they are used in CSS gradients.
pub fn premultiplied(&self) -> ColorF {
self.scale_rgb(self.a)
pub fn premultiplied(&self) -> PremultipliedColorF {
let c = self.scale_rgb(self.a);
PremultipliedColorF { r: c.r, g: c.g, b: c.b, a: c.a }
}
}
// Floats don't impl Hash/Eq...
impl Eq for ColorF {}
impl Hash for ColorF {
// Floats don't impl Hash/Eq/Ord...
impl Eq for PremultipliedColorF {}
impl Ord for PremultipliedColorF {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.partial_cmp(other).unwrap_or(cmp::Ordering::Equal)
}
}
impl Hash for PremultipliedColorF {
fn hash<H: Hasher>(&self, state: &mut H) {
// Note: this is inconsistent with the Eq impl for -0.0 (don't care).
self.r._to_bits().hash(state);
self.g._to_bits().hash(state);
self.b._to_bits().hash(state);
self.a._to_bits().hash(state);
}
}
// FIXME: remove this when Rust 1.21 is stable (float_bits_conv)
pub trait ToBits {
fn _to_bits(self) -> u32;
}
impl ToBits for f32 {
fn _to_bits(self) -> u32 {
unsafe { ::std::mem::transmute(self) }
self.r.to_bits().hash(state);
self.g.to_bits().hash(state);
self.b.to_bits().hash(state);
self.a.to_bits().hash(state);
}
}
@ -95,8 +112,11 @@ fn round_to_int(x: f32) -> u8 {
val as u8
}
// TODO: We shouldn't really convert back to `ColorU` ever,
// since it's lossy. One of the blockers is that all of our debug colors
// are specified in `ColorF`. Changing it to `ColorU` would be nice.
impl From<ColorF> for ColorU {
fn from(color: ColorF) -> ColorU {
fn from(color: ColorF) -> Self {
ColorU {
r: round_to_int(color.r),
g: round_to_int(color.g),
@ -107,7 +127,7 @@ impl From<ColorF> for ColorU {
}
impl From<ColorU> for ColorF {
fn from(color: ColorU) -> ColorF {
fn from(color: ColorU) -> Self {
ColorF {
r: color.r as f32 / 255.0,
g: color.g as f32 / 255.0,

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

@ -533,6 +533,12 @@ impl<'a> Write for SizeCounter {
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
/// Serializes a value assuming the Serialize impl has a stable size across two
/// invocations.
///
/// If this assumption is incorrect, the result will be Undefined Behaviour. This
/// assumption should hold for all derived Serialize impls, which is all we currently
/// use.
fn serialize_fast<T: Serialize>(vec: &mut Vec<u8>, e: &T) {
// manually counting the size is faster than vec.reserve(bincode::serialized_size(&e) as usize) for some reason
let mut size = SizeCounter(0);
@ -548,7 +554,55 @@ fn serialize_fast<T: Serialize>(vec: &mut Vec<u8>, e: &T) {
unsafe { vec.set_len(old_len + size.0); }
// make sure we wrote the right amount
debug_assert!(((w.0 as usize) - (vec.as_ptr() as usize)) == vec.len());
debug_assert_eq!(((w.0 as usize) - (vec.as_ptr() as usize)), vec.len());
}
/// Serializes an iterator, assuming:
///
/// * The Clone impl is trivial (e.g. we're just memcopying a slice iterator)
/// * The ExactSizeIterator impl is stable and correct across a Clone
/// * The Serialize impl has a stable size across two invocations
///
/// If the first is incorrect, webrender will be very slow. If the other two are
/// incorrect, the result will be Undefined Behaviour! The ExactSizeIterator
/// bound would ideally be replaced with a TrustedLen bound to protect us a bit
/// better, but that trait isn't stable (and won't be for a good while, if ever).
///
/// Debug asserts are included that should catch all Undefined Behaviour, but
/// we can't afford to include these in release builds.
fn serialize_iter_fast<I>(vec: &mut Vec<u8>, iter: I) -> usize
where I: ExactSizeIterator + Clone,
I::Item: Serialize,
{
// manually counting the size is faster than vec.reserve(bincode::serialized_size(&e) as usize) for some reason
let mut size = SizeCounter(0);
let mut count1 = 0;
for e in iter.clone() {
bincode::serialize_into(&mut size, &e, bincode::Infinite).unwrap();
count1 += 1;
}
vec.reserve(size.0);
let old_len = vec.len();
let ptr = unsafe { vec.as_mut_ptr().offset(old_len as isize) };
let mut w = UnsafeVecWriter(ptr);
let mut count2 = 0;
for e in iter {
bincode::serialize_into(&mut w, &e, bincode::Infinite).unwrap();
count2 += 1;
}
// fix up the length
unsafe { vec.set_len(old_len + size.0); }
// make sure we wrote the right amount
debug_assert_eq!(((w.0 as usize) - (vec.as_ptr() as usize)), vec.len());
debug_assert_eq!(count1, count2);
count1
}
// This uses a (start, end) representation instead of (start, len) so that
@ -754,12 +808,11 @@ impl DisplayListBuilder {
fn push_iter<I>(&mut self, iter: I)
where
I: IntoIterator,
I::IntoIter: ExactSizeIterator,
I::IntoIter: ExactSizeIterator + Clone,
I::Item: Serialize,
{
let iter = iter.into_iter();
let len = iter.len();
let mut count = 0;
// Format:
// payload_byte_size: usize, item_count: usize, [I; item_count]
@ -770,10 +823,7 @@ impl DisplayListBuilder {
serialize_fast(&mut self.data, &len);
let payload_offset = self.data.len();
for elem in iter {
count += 1;
serialize_fast(&mut self.data, &elem);
}
let count = serialize_iter_fast(&mut self.data, iter.into_iter());
// Now write the actual byte_size
let final_offset = self.data.len();
@ -1165,7 +1215,7 @@ impl DisplayListBuilder {
) -> ClipId
where
I: IntoIterator<Item = ComplexClipRegion>,
I::IntoIter: ExactSizeIterator,
I::IntoIter: ExactSizeIterator + Clone,
{
let parent = self.clip_stack.last().unwrap().scroll_node_id;
self.define_scroll_frame_with_parent(
@ -1190,7 +1240,7 @@ impl DisplayListBuilder {
) -> ClipId
where
I: IntoIterator<Item = ComplexClipRegion>,
I::IntoIter: ExactSizeIterator,
I::IntoIter: ExactSizeIterator + Clone,
{
let id = self.generate_clip_id(id);
let item = SpecificDisplayItem::ScrollFrame(ScrollFrameDisplayItem {
@ -1215,7 +1265,7 @@ impl DisplayListBuilder {
) -> ClipId
where
I: IntoIterator<Item = ComplexClipRegion>,
I::IntoIter: ExactSizeIterator,
I::IntoIter: ExactSizeIterator + Clone,
{
let parent = self.clip_stack.last().unwrap().scroll_node_id;
self.define_clip_with_parent(
@ -1236,7 +1286,7 @@ impl DisplayListBuilder {
) -> ClipId
where
I: IntoIterator<Item = ComplexClipRegion>,
I::IntoIter: ExactSizeIterator,
I::IntoIter: ExactSizeIterator + Clone,
{
let id = self.generate_clip_id(id);
let item = SpecificDisplayItem::Clip(ClipDisplayItem {

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

@ -2,8 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use {ColorF, ColorU, IdNamespace, LayoutPoint, ToBits};
use app_units::Au;
use {ColorU, IdNamespace, LayoutPoint};
#[cfg(target_os = "macos")]
use core_foundation::string::CFString;
#[cfg(target_os = "macos")]
@ -178,14 +177,14 @@ pub struct FontVariation {
impl Ord for FontVariation {
fn cmp(&self, other: &FontVariation) -> Ordering {
self.tag.cmp(&other.tag)
.then(self.value._to_bits().cmp(&other.value._to_bits()))
.then(self.value.to_bits().cmp(&other.value.to_bits()))
}
}
impl PartialEq for FontVariation {
fn eq(&self, other: &FontVariation) -> bool {
self.tag == other.tag &&
self.value._to_bits() == other.value._to_bits()
self.value.to_bits() == other.value.to_bits()
}
}
@ -194,7 +193,7 @@ impl Eq for FontVariation {}
impl Hash for FontVariation {
fn hash<H: Hasher>(&self, state: &mut H) {
self.tag.hash(state);
self.value._to_bits().hash(state);
self.value.to_bits().hash(state);
}
}
@ -309,58 +308,6 @@ impl Default for FontInstancePlatformOptions {
}
}
#[derive(Clone, Hash, PartialEq, Eq, Debug, Deserialize, Serialize, Ord, PartialOrd)]
pub struct FontInstance {
pub font_key: FontKey,
// The font size is in *device* pixels, not logical pixels.
// It is stored as an Au since we need sub-pixel sizes, but
// can't store as a f32 due to use of this type as a hash key.
// TODO(gw): Perhaps consider having LogicalAu and DeviceAu
// or something similar to that.
pub size: Au,
pub color: ColorU,
pub bg_color: ColorU,
pub render_mode: FontRenderMode,
pub subpx_dir: SubpixelDirection,
pub platform_options: Option<FontInstancePlatformOptions>,
pub variations: Vec<FontVariation>,
pub synthetic_italics: bool,
}
impl FontInstance {
pub fn new(
font_key: FontKey,
size: Au,
color: ColorF,
bg_color: ColorU,
render_mode: FontRenderMode,
subpx_dir: SubpixelDirection,
platform_options: Option<FontInstancePlatformOptions>,
variations: Vec<FontVariation>,
synthetic_italics: bool,
) -> FontInstance {
FontInstance {
font_key,
size,
color: color.into(),
bg_color,
render_mode,
subpx_dir,
platform_options,
variations,
synthetic_italics,
}
}
pub fn get_subpx_offset(&self, glyph: &GlyphKey) -> (f64, f64) {
match self.subpx_dir {
SubpixelDirection::None => (0.0, 0.0),
SubpixelDirection::Horizontal => (glyph.subpixel_offset.into(), 0.0),
SubpixelDirection::Vertical => (0.0, glyph.subpixel_offset.into()),
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Ord, PartialOrd)]
pub struct FontInstanceKey(pub IdNamespace, pub u32);

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

@ -5,7 +5,7 @@ authors = ["The Mozilla Project Developers"]
license = "MPL-2.0"
[dependencies]
webrender_api = {path = "../webrender_api", version = "0.53.1"}
webrender_api = {path = "../webrender_api", version = "0.53.2"}
rayon = "0.8"
thread_profiler = "0.1.1"
euclid = "0.15"
@ -15,7 +15,7 @@ log = "0.3"
[dependencies.webrender]
path = "../webrender"
version = "0.53.1"
version = "0.53.2"
default-features = false
[target.'cfg(target_os = "windows")'.dependencies]

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

@ -176,8 +176,11 @@ OSPreferences::ReadDateTimePattern(DateTimeFormatStyle aDateStyle,
str->EndReading(end);
if (FindInReadable(NS_LITERAL_STRING("dddd"), pos, end)) {
str->ReplaceLiteral(pos - start, 4, u"EEEE");
} else if (FindInReadable(NS_LITERAL_STRING("ddd"), pos, end)) {
str->ReplaceLiteral(pos - start, 3, u"EEE");
} else {
pos = start;
if (FindInReadable(NS_LITERAL_STRING("ddd"), pos, end)) {
str->ReplaceLiteral(pos - start, 3, u"EEE");
}
}
// Also, Windows uses lowercase "g" or "gg" for era, but ICU wants uppercase "G"

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше