зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. r=merge a=merge CLOSED TREE
This commit is contained in:
Коммит
f24a75f9b7
|
@ -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'
|
||||
|
|
78
client.mk
78
client.mk
|
@ -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"
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче