diff --git a/b2g/config/hamachi/config.json b/b2g/config/hamachi/config.json index 4c1f03751d3..f31cbdc7edb 100644 --- a/b2g/config/hamachi/config.json +++ b/b2g/config/hamachi/config.json @@ -14,7 +14,7 @@ "{objdir}/dist/b2g-*.crashreporter-symbols.zip", "{objdir}/dist/b2g-*.tar.gz", "{workdir}/sources.xml", - "{workdir}/out/target/product/hamachi/fota-update.mar" + "{workdir}/out/target/product/hamachi/*.mar" ], "env": { "VARIANT": "user", diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 88c712ace8a..cf2d50f6fa8 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -388,7 +388,7 @@ #endif @BINPATH@/components/SiteSpecificUserAgent.js @BINPATH@/components/SiteSpecificUserAgent.manifest -@BINPATH@/components/storage-mozStorage.js +@BINPATH@/components/storage-json.js @BINPATH@/components/crypto-SDR.js @BINPATH@/components/jsconsole-clhandler.manifest @BINPATH@/components/jsconsole-clhandler.js diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 2be3b148d22..4dc978ef075 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1129,6 +1129,18 @@ var gBrowserInit = { } }, 10000); + // Load the Login Manager data from disk off the main thread, some time + // after startup. If the data is required before the timeout, for example + // because a restored page contains a password field, it will be loaded on + // the main thread, and this initialization request will be ignored. + setTimeout(function() { + try { + Services.logins; + } catch (ex) { + Cu.reportError(ex); + } + }, 3000); + // The object handling the downloads indicator is also initialized here in the // delayed startup function, but the actual indicator element is not loaded // unless there are downloads to be displayed. diff --git a/browser/components/customizableui/content/panelUI.js b/browser/components/customizableui/content/panelUI.js index c68c32e6ec9..9097db9ba85 100644 --- a/browser/components/customizableui/content/panelUI.js +++ b/browser/components/customizableui/content/panelUI.js @@ -328,6 +328,9 @@ const PanelUI = { tempPanel.setAttribute("type", "arrow"); tempPanel.setAttribute("id", "customizationui-widget-panel"); tempPanel.setAttribute("class", "cui-widget-panel"); + if (this._disableAnimations) { + tempPanel.setAttribute("animate", "false"); + } tempPanel.setAttribute("context", ""); document.getElementById(CustomizableUI.AREA_NAVBAR).appendChild(tempPanel); // If the view has a footer, set a convenience class on the panel. @@ -363,6 +366,19 @@ const PanelUI = { } }, + /** + * NB: The enable- and disableSingleSubviewPanelAnimations methods only + * affect the hiding/showing animations of single-subview panels (tempPanel + * in the showSubView method). + */ + disableSingleSubviewPanelAnimations: function() { + this._disableAnimations = true; + }, + + enableSingleSubviewPanelAnimations: function() { + this._disableAnimations = false; + }, + onWidgetAfterDOMChange: function(aNode, aNextNode, aContainer, aWasRemoval) { if (aContainer != this.contents) { return; diff --git a/browser/components/customizableui/test/browser_988072_sidebar_events.js b/browser/components/customizableui/test/browser_988072_sidebar_events.js index e4fe5510e84..a893bb53b8c 100644 --- a/browser/components/customizableui/test/browser_988072_sidebar_events.js +++ b/browser/components/customizableui/test/browser_988072_sidebar_events.js @@ -41,6 +41,16 @@ function createSidebarItem() { gSidebarMenu.insertBefore(gTestSidebarItem, gSidebarMenu.firstChild); } +function addWidget() { + CustomizableUI.addWidgetToArea("sidebar-button", "nav-bar"); + PanelUI.disableSingleSubviewPanelAnimations(); +} + +function removeWidget() { + CustomizableUI.removeWidgetFromArea("sidebar-button"); + PanelUI.enableSingleSubviewPanelAnimations(); +} + // Filters out the trailing menuseparators from the sidebar list function getSidebarList() { let sidebars = [...gSidebarMenu.children]; @@ -76,7 +86,7 @@ let showSidebarPopup = Task.async(function*() { // Check the sidebar widget shows the default items add_task(function*() { - CustomizableUI.addWidgetToArea("sidebar-button", "nav-bar"); + addWidget(); yield showSidebarPopup(); @@ -89,13 +99,14 @@ add_task(function*() { document.getElementById("customizationui-widget-panel").hidePopup(); yield subviewHiddenPromise; - return resetCustomization(); + removeWidget(); }); function add_sidebar_task(description, setup, teardown) { add_task(function*() { info(description); createSidebarItem(); + addWidget(); yield setup(); CustomizableUI.addWidgetToArea("sidebar-button", "nav-bar"); @@ -114,7 +125,7 @@ function add_sidebar_task(description, setup, teardown) { yield teardown(); gTestSidebarItem.remove(); - return resetCustomization(); + removeWidget(); }); } diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index d935f0a2204..da9fcad6ab8 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -105,13 +105,13 @@ const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser"; const PREF_PLUGINS_UPDATEURL = "plugins.update.url"; // Seconds of idle before trying to create a bookmarks backup. -const BOOKMARKS_BACKUP_IDLE_TIME_SEC = 10 * 60; +const BOOKMARKS_BACKUP_IDLE_TIME_SEC = 8 * 60; // Minimum interval between backups. We try to not create more than one backup // per interval. const BOOKMARKS_BACKUP_MIN_INTERVAL_DAYS = 1; // Maximum interval between backups. If the last backup is older than these // days we will try to create a new one more aggressively. -const BOOKMARKS_BACKUP_MAX_INTERVAL_DAYS = 5; +const BOOKMARKS_BACKUP_MAX_INTERVAL_DAYS = 3; // Factory object const BrowserGlueServiceFactory = { diff --git a/browser/devtools/debugger/test/browser_dbg_addon-panels.js b/browser/devtools/debugger/test/browser_dbg_addon-panels.js index 71f31718866..43dab85bff3 100644 --- a/browser/devtools/debugger/test/browser_dbg_addon-panels.js +++ b/browser/devtools/debugger/test/browser_dbg_addon-panels.js @@ -27,7 +27,7 @@ function test() { // Check only valid tabs are shown let tabs = addonDebugger.frame.contentDocument.getElementById("toolbox-tabs").children; - let expectedTabs = ["options", "webconsole", "jsdebugger", "scratchpad"]; + let expectedTabs = ["webconsole", "jsdebugger", "scratchpad"]; is(tabs.length, expectedTabs.length, "displaying only " + expectedTabs.length + " tabs in addon debugger"); Array.forEach(tabs, (tab, i) => { diff --git a/browser/devtools/framework/test/browser_toolbox_options_disable_buttons.js b/browser/devtools/framework/test/browser_toolbox_options_disable_buttons.js index 6bd0a88a644..d30e2e68c0b 100644 --- a/browser/devtools/framework/test/browser_toolbox_options_disable_buttons.js +++ b/browser/devtools/framework/test/browser_toolbox_options_disable_buttons.js @@ -58,7 +58,7 @@ function testSelectTool(aToolbox) { function testPreferenceAndUIStateIsConsistent() { let checkNodes = [...panelWin.document.querySelectorAll("#enabled-toolbox-buttons-box > checkbox")]; - let toolboxButtonNodes = [...doc.querySelectorAll("#toolbox-buttons > toolbarbutton")]; + let toolboxButtonNodes = [...doc.querySelectorAll(".command-button")]; let toggleableTools = toolbox.toolboxButtons; for (let tool of toggleableTools) { @@ -74,7 +74,7 @@ function testPreferenceAndUIStateIsConsistent() { function testToggleToolboxButtons() { let checkNodes = [...panelWin.document.querySelectorAll("#enabled-toolbox-buttons-box > checkbox")]; - let toolboxButtonNodes = [...doc.querySelectorAll("#toolbox-buttons > toolbarbutton")]; + let toolboxButtonNodes = [...doc.querySelectorAll(".command-button")]; let visibleButtons = toolboxButtonNodes.filter(button=>!button.hasAttribute("hidden")); let toggleableTools = toolbox.toolboxButtons; diff --git a/browser/devtools/framework/toolbox.js b/browser/devtools/framework/toolbox.js index dbfe7239a54..b100081d95e 100644 --- a/browser/devtools/framework/toolbox.js +++ b/browser/devtools/framework/toolbox.js @@ -555,7 +555,7 @@ Toolbox.prototype = { this._pickerButton.className = "command-button command-button-invertable"; this._pickerButton.setAttribute("tooltiptext", toolboxStrings("pickButton.tooltip")); - let container = this.doc.querySelector("#toolbox-buttons"); + let container = this.doc.querySelector("#toolbox-picker-container"); container.appendChild(this._pickerButton); this._togglePicker = this.highlighterUtils.togglePicker.bind(this.highlighterUtils); @@ -690,21 +690,29 @@ Toolbox.prototype = { vbox.id = "toolbox-panel-" + id; } - // If there is no tab yet, or the ordinal to be added is the largest one. - if (tabs.childNodes.length == 0 || - +tabs.lastChild.getAttribute("ordinal") <= toolDefinition.ordinal) { - tabs.appendChild(radio); + if (id === "options") { + // Options panel is special. It doesn't belong in the same container as + // the other tabs. + let optionTabContainer = this.doc.getElementById("toolbox-option-container"); + optionTabContainer.appendChild(radio); deck.appendChild(vbox); } else { - // else, iterate over all the tabs to get the correct location. - Array.some(tabs.childNodes, (node, i) => { - if (+node.getAttribute("ordinal") > toolDefinition.ordinal) { - tabs.insertBefore(radio, node); - deck.insertBefore(vbox, deck.childNodes[i]); - return true; - } - return false; - }); + // If there is no tab yet, or the ordinal to be added is the largest one. + if (tabs.childNodes.length == 0 || + tabs.lastChild.getAttribute("ordinal") <= toolDefinition.ordinal) { + tabs.appendChild(radio); + deck.appendChild(vbox); + } else { + // else, iterate over all the tabs to get the correct location. + Array.some(tabs.childNodes, (node, i) => { + if (+node.getAttribute("ordinal") > toolDefinition.ordinal) { + tabs.insertBefore(radio, node); + deck.insertBefore(vbox, deck.childNodes[i]); + return true; + } + return false; + }); + } } this._addKeysToWindow(); @@ -805,6 +813,15 @@ Toolbox.prototype = { let tab = this.doc.getElementById("toolbox-tab-" + id); tab.setAttribute("selected", "true"); + // If options is selected, the separator between it and the + // command buttons should be hidden. + let sep = this.doc.getElementById("toolbox-controls-separator"); + if (id === "options") { + sep.setAttribute("invisible", "true"); + } else { + sep.removeAttribute("invisible"); + } + if (this.currentToolId == id) { // re-focus tool to get key events again this.focusTool(id); @@ -831,20 +848,13 @@ Toolbox.prototype = { let tabstrip = this.doc.getElementById("toolbox-tabs"); // select the right tab, making 0th index the default tab if right tab not - // found - let index = 0; - let tabs = tabstrip.childNodes; - for (let i = 0; i < tabs.length; i++) { - if (tabs[i] === tab) { - index = i; - break; - } - } - tabstrip.selectedItem = tab; + // found. + tabstrip.selectedItem = tab || tabstrip.childNodes[0]; // and select the right iframe let deck = this.doc.getElementById("toolbox-deck"); - deck.selectedIndex = index; + let panel = this.doc.getElementById("toolbox-panel-" + id); + deck.selectedPanel = panel; this.currentToolId = id; this._refreshConsoleDisplay(); @@ -907,8 +917,10 @@ Toolbox.prototype = { * Loads the tool next to the currently selected tool. */ selectNextTool: function() { + let tools = this.doc.querySelectorAll(".devtools-tab"); let selected = this.doc.querySelector(".devtools-tab[selected]"); - let next = selected.nextSibling || selected.parentNode.firstChild; + let nextIndex = [...tools].indexOf(selected) + 1; + let next = tools[nextIndex] || tools[0]; let tool = next.getAttribute("toolid"); return this.selectTool(tool); }, @@ -917,9 +929,11 @@ Toolbox.prototype = { * Loads the tool just left to the currently selected tool. */ selectPreviousTool: function() { + let tools = this.doc.querySelectorAll(".devtools-tab"); let selected = this.doc.querySelector(".devtools-tab[selected]"); - let previous = selected.previousSibling || selected.parentNode.lastChild; - let tool = previous.getAttribute("toolid"); + let prevIndex = [...tools].indexOf(selected) - 1; + let prev = tools[prevIndex] || tools[tools.length - 1]; + let tool = prev.getAttribute("toolid"); return this.selectTool(tool); }, diff --git a/browser/devtools/framework/toolbox.xul b/browser/devtools/framework/toolbox.xul index 6507a1410cb..a21c9506d1c 100644 --- a/browser/devtools/framework/toolbox.xul +++ b/browser/devtools/framework/toolbox.xul @@ -51,26 +51,17 @@ -#ifdef XP_MACOSX - - - - -#endif - - + + -#ifndef XP_MACOSX + -#endif diff --git a/browser/devtools/main.js b/browser/devtools/main.js index 76b55b9a5e3..41b145ae8c8 100644 --- a/browser/devtools/main.js +++ b/browser/devtools/main.js @@ -86,7 +86,7 @@ Tools.webConsole = { key: l10n("cmd.commandkey", webConsoleStrings), accesskey: l10n("webConsoleCmd.accesskey", webConsoleStrings), modifiers: Services.appinfo.OS == "Darwin" ? "accel,alt" : "accel,shift", - ordinal: 1, + ordinal: 2, icon: "chrome://browser/skin/devtools/tool-webconsole.svg", invertIconForLightTheme: true, url: "chrome://browser/content/devtools/webconsole.xul", @@ -117,7 +117,7 @@ Tools.inspector = { id: "inspector", accesskey: l10n("inspector.accesskey", inspectorStrings), key: l10n("inspector.commandkey", inspectorStrings), - ordinal: 2, + ordinal: 1, modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift", icon: "chrome://browser/skin/devtools/tool-inspector.svg", invertIconForLightTheme: true, diff --git a/browser/devtools/styleeditor/styleeditor.xul b/browser/devtools/styleeditor/styleeditor.xul index 67f3ea067c9..5fea157fd3a 100644 --- a/browser/devtools/styleeditor/styleeditor.xul +++ b/browser/devtools/styleeditor/styleeditor.xul @@ -159,7 +159,7 @@

&csscoverage.unused;

-

&csscoverage.noMatch;

+

&csscoverage.noMatches;

${page.url}

image { @@ -302,10 +302,6 @@ } .devtools-closebutton:hover { - opacity: 0.8; -} - -.devtools-closebutton:hover:active { opacity: 1; } @@ -457,10 +453,6 @@ * Rules that apply to the global toolbox like command buttons, * devtools tabs, docking buttons, etc. */ -#toolbox-controls { - margin: 0 4px; -} - #toolbox-controls > toolbarbutton, #toolbox-dock-buttons > toolbarbutton { -moz-appearance: none; @@ -500,7 +492,7 @@ #toolbox-dock-window, #toolbox-dock-bottom, #toolbox-dock-side { - opacity: 0.6; + opacity: 0.8; } #toolbox-dock-window:hover, @@ -510,14 +502,16 @@ } #toolbox-controls-separator { - width: 3px; + width: 2px; background-image: linear-gradient(hsla(204,45%,98%,0), hsla(204,45%,98%,.1), hsla(204,45%,98%,0)), linear-gradient(hsla(206,37%,4%,0), hsla(206,37%,4%,.6), hsla(206,37%,4%,0)), linear-gradient(hsla(204,45%,98%,0), hsla(204,45%,98%,.1), hsla(204,45%,98%,0)); background-size: 1px 100%; background-repeat: no-repeat; background-position: 0, 1px, 2px; - -moz-margin-start: 8px; +} +#toolbox-controls-separator[invisible] { + visibility: hidden; } /* Command buttons */ @@ -650,7 +644,9 @@ max-width: 127px; margin: 0; padding: 0; - -moz-border-start: 1px solid; + border-style: solid; + border-width: 0; + -moz-border-start-width: 1px; -moz-box-align: center; } @@ -691,18 +687,6 @@ background-color: rgba(44, 187, 15, .2); } -.devtools-tab:first-child { - -moz-border-start-width: 0; -} - -.theme-light .devtools-tab:last-child { - -moz-border-end: 1px solid #aaa; -} - -.theme-dark .devtools-tab:last-child { - -moz-border-end: 1px solid #42484f; -} - .devtools-tab > image { border: none; -moz-margin-end: 0; @@ -712,10 +696,6 @@ width: 16px; /* Prevents collapse during theme switching */ } -#toolbox-tab-options > image { - margin: 0 8px; -} - .devtools-tab > label { white-space: nowrap; } @@ -729,7 +709,7 @@ opacity: 1; } -.theme-dark #toolbox-tabs .devtools-tab[selected] { +.theme-dark .devtools-tab[selected] { color: #f5f7fa; background-color: #1a4666; box-shadow: 0 2px 0 #d7f1ff inset, @@ -737,7 +717,7 @@ 0 -2px 0 rgba(0,0,0,.2) inset; } -.theme-light #toolbox-tabs .devtools-tab[selected] { +.theme-light .devtools-tab[selected] { color: #f5f7fa; background-color: #4c9ed9; box-shadow: 0 2px 0 #d7f1ff inset, @@ -745,29 +725,51 @@ 0 -2px 0 rgba(0,0,0,.06) inset; } -.devtools-tab[selected]:not(:first-child), -.devtools-tab[highlighted]:not(:first-child) { +#toolbox-tabs .devtools-tab[selected]:not(:first-child), +#toolbox-tabs .devtools-tab[highlighted]:not(:first-child) { border-width: 0; -moz-padding-start: 1px; } -.devtools-tab[selected]:last-child, -.devtools-tab[highlighted]:last-child { +#toolbox-tabs .devtools-tab[selected]:last-child, +#toolbox-tabs .devtools-tab[highlighted]:last-child { -moz-padding-end: 1px; } -.devtools-tab[selected] + .devtools-tab, -.devtools-tab[highlighted] + .devtools-tab { +#toolbox-tabs .devtools-tab[selected] + .devtools-tab, +#toolbox-tabs .devtools-tab[highlighted] + .devtools-tab { -moz-border-start-width: 0; -moz-padding-start: 1px; } +#toolbox-tabs .devtools-tab:first-child[selected] { + -moz-border-start-width: 0; +} + +#toolbox-tabs .devtools-tab:last-child { + -moz-border-end-width: 1px; +} + .devtools-tab:not([highlighted]) > .highlighted-icon, .devtools-tab[selected] > .highlighted-icon, .devtools-tab:not([selected])[highlighted] > .default-icon { visibility: collapse; } +/* The options tab is special - it doesn't have the same parent + as the other tabs (toolbox-option-container vs toolbox-tabs) */ +#toolbox-option-container .devtools-tab:not([selected]) { + background-color: transparent; +} +#toolbox-option-container .devtools-tab { + border-color: transparent; + border-width: 0; + -moz-padding-start: 1px; +} +#toolbox-tab-options > image { + margin: 0 8px; +} + /* Invert the colors of certain dark theme images for displaying * inside of the light theme. */ diff --git a/build/valgrind/cross-architecture.sup b/build/valgrind/cross-architecture.sup index 3b2d99e1561..0ad214b49f6 100644 --- a/build/valgrind/cross-architecture.sup +++ b/build/valgrind/cross-architecture.sup @@ -100,3 +100,12 @@ fun:_ZN22nsComponentManagerImpl17ManifestComponentERNS_25ManifestProcessingContextEiPKPc ... } +{ + Bug 1017112 + Memcheck:Leak + fun:malloc + ... + fun:PK11_InitPin + fun:_ZN11nsPK11Token12InitPasswordEPKDs + ... +} diff --git a/content/media/AudioStream.cpp b/content/media/AudioStream.cpp index 9956280adbd..9db5a820582 100644 --- a/content/media/AudioStream.cpp +++ b/content/media/AudioStream.cpp @@ -152,7 +152,10 @@ AudioStream::AudioStream() , mAudioClock(MOZ_THIS_IN_INITIALIZER_LIST()) , mLatencyRequest(HighLatency) , mReadPoint(0) - , mLostFrames(0) + , mWrittenFramesPast(0) + , mLostFramesPast(0) + , mWrittenFramesLast(0) + , mLostFramesLast(0) , mDumpFile(nullptr) , mVolume(1.0) , mBytesPerFrame(0) @@ -780,9 +783,28 @@ AudioStream::GetPositionInFramesUnlocked() // Adjust the reported position by the number of silent frames written // during stream underruns. + // Since frames sent to DataCallback is not consumed by the backend immediately, + // it will be an over adjustment if we return |position - mLostFramesPast - mLostFramesLast|. + // On the other hand, we need to keep the whole history of frames sent to DataCallback + // in order to adjust position correctly which will require more storage. + // We choose a simple way to store the history where |mWrittenFramesPast| and + // |mLostFramesPast| are the sum of frames from 1th to |N-1|th callbacks, and + // |mWrittenFramesLast| and |mLostFramesLast| represent the frames sent in last callback. + // When |position| lies in + // [mWrittenFramesPast+mLostFramesPast, mWrittenFramesPast+mLostFramesPast+mWrittenFramesLast+mLostFramesLast], + // we will be able to adjust position precisely which should be the major case. + // If |position| falls in [0, mWrittenFramesPast+mLostFramesPast), there will be an + // error in the adjustment. However that is fine as long as we can ensure the + // adjusted position is mono-increasing to avoid audio clock going backward. uint64_t adjustedPosition = 0; - if (position >= mLostFrames) { - adjustedPosition = position - mLostFrames; + if (position <= mWrittenFramesPast) { + adjustedPosition = position; + } else if (position <= mWrittenFramesPast + mLostFramesPast) { + adjustedPosition = mWrittenFramesPast; + } else if (position <= mWrittenFramesPast + mLostFramesPast + mWrittenFramesLast) { + adjustedPosition = position - mLostFramesPast; + } else { + adjustedPosition = mWrittenFramesPast + mWrittenFramesLast; } return std::min(adjustedPosition, INT64_MAX); } @@ -929,6 +951,9 @@ AudioStream::DataCallback(void* aBuffer, long aFrames) uint32_t servicedFrames = 0; int64_t insertTime; + mWrittenFramesPast += mWrittenFramesLast; + mLostFramesPast += mLostFramesLast; + // NOTE: wasapi (others?) can call us back *after* stop()/Shutdown() (mState == SHUTDOWN) // Bug 996162 @@ -992,6 +1017,8 @@ AudioStream::DataCallback(void* aBuffer, long aFrames) } underrunFrames = aFrames - servicedFrames; + mWrittenFramesLast = servicedFrames; + mLostFramesLast = underrunFrames; if (mState != DRAINING) { uint8_t* rpos = static_cast(aBuffer) + FramesToBytes(aFrames - underrunFrames); @@ -1000,7 +1027,6 @@ AudioStream::DataCallback(void* aBuffer, long aFrames) PR_LOG(gAudioStreamLog, PR_LOG_WARNING, ("AudioStream %p lost %d frames", this, underrunFrames)); } - mLostFrames += underrunFrames; servicedFrames += underrunFrames; } diff --git a/content/media/AudioStream.h b/content/media/AudioStream.h index fa08f21662a..e995c7e370f 100644 --- a/content/media/AudioStream.h +++ b/content/media/AudioStream.h @@ -65,8 +65,6 @@ public: // Get the current pitch preservation state. // Called on the audio thread. bool GetPreservesPitch(); - // Get the number of frames written to the backend. - int64_t GetWritten(); private: // This AudioStream holds a strong reference to this AudioClock. This // pointer is garanteed to always be valid. @@ -372,9 +370,14 @@ private: }; nsAutoTArray mInserts; - // Sum of silent frames written when DataCallback requests more frames - // than are available in mBuffer. - uint64_t mLostFrames; + // Suppose we have received DataCallback for N times, |mWrittenFramesPast| + // and |mLostFramesPast| are the sum of frames written to the backend from + // 1st to |N-1|th DataCallbacks. + uint64_t mWrittenFramesPast; // non-silent frames + uint64_t mLostFramesPast; // silent frames + // Frames written to the backend in Nth DataCallback. + uint64_t mWrittenFramesLast; // non-silent frames + uint64_t mLostFramesLast; // silent frames // Output file for dumping audio FILE* mDumpFile; diff --git a/content/svg/document/src/SVGDocument.cpp b/content/svg/document/src/SVGDocument.cpp index c5280aef795..bfcb9651cec 100644 --- a/content/svg/document/src/SVGDocument.cpp +++ b/content/svg/document/src/SVGDocument.cpp @@ -140,7 +140,11 @@ SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded() } } - EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::NumberControlSheet()); + nsCSSStyleSheet* sheet = nsLayoutStylesheetCache::NumberControlSheet(); + if (sheet) { + // number-control.css can be behind a pref + EnsureOnDemandBuiltInUASheet(sheet); + } EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::FormsSheet()); EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::HTMLSheet()); EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::UASheet()); diff --git a/gfx/2d/Tools.h b/gfx/2d/Tools.h index 3034d2122cd..8a12edb1989 100644 --- a/gfx/2d/Tools.h +++ b/gfx/2d/Tools.h @@ -138,14 +138,21 @@ struct AlignedArray T *mPtr; }; +/** + * Returns aStride increased, if necessary, so that it divides exactly into + * |alignment|. + * + * Note that currently |alignment| must be a power-of-2. If for some reason we + * want to support NPOT alignment we can revert back to this functions old + * implementation. + */ template int32_t GetAlignedStride(int32_t aStride) { - if (aStride % alignment) { - return aStride + (alignment - (aStride % alignment)); - } - - return aStride; + static_assert(alignment > 0 && (alignment & (alignment-1)) == 0, + "This implementation currently require power-of-two alignment"); + const int32_t mask = alignment - 1; + return (aStride + mask) & ~mask; } } diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index 6eef998b0e4..5ee051e9623 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -106,11 +106,25 @@ ImageHost::Composite(EffectChain& aEffectChain, gfx::Rect pictureRect(0, 0, mPictureRect.width, mPictureRect.height); - //XXX: We might have multiple texture sources here (e.g. 3 YCbCr textures), and we're - // only iterating over the tiles of the first one. Are we assuming that the tiling - // will be identical? Can we ensure that somehow? BigImageIterator* it = source->AsBigImageIterator(); if (it) { + + // This iteration does not work if we have multiple texture sources here + // (e.g. 3 YCbCr textures). There's nothing preventing the different + // planes from having different resolutions or tile sizes. For example, a + // YCbCr frame could have Cb and Cr planes that are half the resolution of + // the Y plane, in such a way that the Y plane overflows the maximum + // texture size and the Cb and Cr planes do not. Then the Y plane would be + // split into multiple tiles and the Cb and Cr planes would just be one + // tile each. + // To handle the general case correctly, we'd have to create a grid of + // intersected tiles over all planes, and then draw each grid tile using + // the corresponding source tiles from all planes, with appropriate + // per-plane per-tile texture coords. + // DrawQuad currently assumes that all planes use the same texture coords. + MOZ_ASSERT(it->GetTileCount() == 1 || !source->GetNextSibling(), + "Can't handle multi-plane BigImages"); + it->BeginBigImageIteration(); do { nsIntRect tileRect = it->GetTileRect(); diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index ffe376801f0..f6b42ca59b4 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -307,11 +307,24 @@ CompositorOGL::Initialize() mGLContext->fGenBuffers(1, &mQuadVBO); mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO); + // 4 quads, with the number of the quad (vertexID) encoded in w. GLfloat vertices[] = { - /* First quad vertices */ - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - /* Then quad texcoords */ - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 0.0f, 2.0f, + 1.0f, 0.0f, 0.0f, 2.0f, + 0.0f, 1.0f, 0.0f, 2.0f, + 1.0f, 1.0f, 0.0f, 2.0f, + 0.0f, 0.0f, 0.0f, 3.0f, + 1.0f, 0.0f, 0.0f, 3.0f, + 0.0f, 1.0f, 0.0f, 3.0f, + 1.0f, 1.0f, 0.0f, 3.0f, }; HeapCopyOfStackArray verticesOnHeap(vertices); mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, @@ -528,9 +541,7 @@ CompositorOGL::BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg, aTexCoordRect, layerRects, textureRects); - for (int n = 0; n < rects; ++n) { - BindAndDrawQuad(aProg, layerRects[n], textureRects[n]); - } + BindAndDrawQuads(aProg, rects, layerRects, textureRects); } void @@ -1499,26 +1510,27 @@ CompositorOGL::BindQuadVBO() { void CompositorOGL::QuadVBOVerticesAttrib(GLuint aAttribIndex) { - mGLContext->fVertexAttribPointer(aAttribIndex, 2, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - (GLvoid*) QuadVBOVertexOffset()); + mGLContext->fVertexAttribPointer(aAttribIndex, 4, + LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, + (GLvoid*) 0); } void CompositorOGL::QuadVBOTexCoordsAttrib(GLuint aAttribIndex) { - mGLContext->fVertexAttribPointer(aAttribIndex, 2, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - (GLvoid*) QuadVBOTexCoordOffset()); + mGLContext->fVertexAttribPointer(aAttribIndex, 4, + LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, + (GLvoid*) 0); } void -CompositorOGL::BindAndDrawQuad(ShaderProgramOGL *aProg, - const Rect& aLayerRect, - const Rect& aTextureRect) +CompositorOGL::BindAndDrawQuads(ShaderProgramOGL *aProg, + int aQuads, + const Rect* aLayerRects, + const Rect* aTextureRects) { NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized"); - aProg->SetLayerRect(aLayerRect); + aProg->SetLayerRects(aLayerRects); GLuint vertAttribIndex = aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib); GLuint texCoordAttribIndex = aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib); @@ -1530,11 +1542,11 @@ CompositorOGL::BindAndDrawQuad(ShaderProgramOGL *aProg, QuadVBOTexCoordsAttrib(texCoordAttribIndex); mGLContext->fEnableVertexAttribArray(texCoordAttribIndex); - aProg->SetTextureRect(aTextureRect); + aProg->SetTextureRects(aTextureRects); } mGLContext->fEnableVertexAttribArray(vertAttribIndex); - mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4 * aQuads); } GLuint diff --git a/gfx/layers/opengl/CompositorOGL.h b/gfx/layers/opengl/CompositorOGL.h index a9f59617533..787aaea8a09 100644 --- a/gfx/layers/opengl/CompositorOGL.h +++ b/gfx/layers/opengl/CompositorOGL.h @@ -352,15 +352,22 @@ private: GLuint aSourceFrameBuffer, GLuint *aFBO, GLuint *aTexture); - GLintptr QuadVBOVertexOffset() { return 0; } - GLintptr QuadVBOTexCoordOffset() { return sizeof(float)*4*2; } - void BindQuadVBO(); void QuadVBOVerticesAttrib(GLuint aAttribIndex); void QuadVBOTexCoordsAttrib(GLuint aAttribIndex); + void BindAndDrawQuads(ShaderProgramOGL *aProg, + int aQuads, + const gfx::Rect* aLayerRect, + const gfx::Rect* aTextureRect); void BindAndDrawQuad(ShaderProgramOGL *aProg, const gfx::Rect& aLayerRect, - const gfx::Rect& aTextureRect = gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f)); + const gfx::Rect& aTextureRect = gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f)) { + gfx::Rect layerRects[4]; + gfx::Rect textureRects[4]; + layerRects[0] = aLayerRect; + textureRects[0] = aTextureRect; + BindAndDrawQuads(aProg, 1, layerRects, textureRects); + } void BindAndDrawQuadWithTextureRect(ShaderProgramOGL *aProg, const gfx::Rect& aRect, const gfx::Rect& aTexCoordRect, diff --git a/gfx/layers/opengl/OGLShaderProgram.cpp b/gfx/layers/opengl/OGLShaderProgram.cpp index 7570cd395eb..59b1a8ba1dc 100644 --- a/gfx/layers/opengl/OGLShaderProgram.cpp +++ b/gfx/layers/opengl/OGLShaderProgram.cpp @@ -32,10 +32,10 @@ AddUniforms(ProgramProfileOGL& aProfile) static const char *sKnownUniformNames[] = { "uLayerTransform", "uMaskTransform", - "uLayerRect", + "uLayerRects", "uMatrixProj", "uTextureTransform", - "uTextureRect", + "uTextureRects", "uRenderTargetOffset", "uLayerOpacity", "uTexture", @@ -146,7 +146,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) AddUniforms(result); vs << "uniform mat4 uMatrixProj;" << endl; - vs << "uniform vec4 uLayerRect;" << endl; + vs << "uniform vec4 uLayerRects[4];" << endl; vs << "uniform mat4 uLayerTransform;" << endl; vs << "uniform vec4 uRenderTargetOffset;" << endl; @@ -154,8 +154,8 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { vs << "uniform mat4 uTextureTransform;" << endl; - vs << "uniform vec4 uTextureRect;" << endl; - vs << "attribute vec2 aTexCoord;" << endl; + vs << "uniform vec4 uTextureRects[4];" << endl; + vs << "attribute vec4 aTexCoord;" << endl; vs << "varying vec2 vTexCoord;" << endl; } @@ -166,7 +166,9 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) } vs << "void main() {" << endl; - vs << " vec4 finalPosition = vec4(aVertexCoord.xy * uLayerRect.zw + uLayerRect.xy, 0.0, 1.0);" << endl; + vs << " int vertexID = int(aVertexCoord.w);" << endl; + vs << " vec4 layerRect = uLayerRects[vertexID];" << endl; + vs << " vec4 finalPosition = vec4(aVertexCoord.xy * layerRect.zw + layerRect.xy, 0.0, 1.0);" << endl; vs << " finalPosition = uLayerTransform * finalPosition;" << endl; vs << " finalPosition.xyz /= finalPosition.w;" << endl; @@ -184,7 +186,8 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) vs << " finalPosition = uMatrixProj * finalPosition;" << endl; if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { - vs << " vec2 texCoord = aTexCoord * uTextureRect.zw + uTextureRect.xy;" << endl; + vs << " vec4 textureRect = uTextureRects[vertexID];" << endl; + vs << " vec2 texCoord = aTexCoord.xy * textureRect.zw + textureRect.xy;" << endl; vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" << endl; } diff --git a/gfx/layers/opengl/OGLShaderProgram.h b/gfx/layers/opengl/OGLShaderProgram.h index 216bf4ca812..b09935c1392 100644 --- a/gfx/layers/opengl/OGLShaderProgram.h +++ b/gfx/layers/opengl/OGLShaderProgram.h @@ -52,10 +52,10 @@ public: LayerTransform = 0, MaskTransform, - LayerRect, + LayerRects, MatrixProj, TextureTransform, - TextureRect, + TextureRects, RenderTargetOffset, LayerOpacity, Texture, @@ -322,9 +322,12 @@ public: SetMatrixUniform(KnownUniform::MaskTransform, aMatrix); } - void SetLayerRect(const gfx::Rect& aRect) { - float vals[4] = { float(aRect.x), float(aRect.y), float(aRect.width), float(aRect.height) }; - SetUniform(KnownUniform::LayerRect, 4, vals); + void SetLayerRects(const gfx::Rect* aRects) { + float vals[16] = { aRects[0].x, aRects[0].y, aRects[0].width, aRects[0].height, + aRects[1].x, aRects[1].y, aRects[1].width, aRects[1].height, + aRects[2].x, aRects[2].y, aRects[2].width, aRects[2].height, + aRects[3].x, aRects[3].y, aRects[3].width, aRects[3].height }; + SetUniform(KnownUniform::LayerRects, 16, vals); } void SetProjectionMatrix(const gfx::Matrix4x4& aMatrix) { @@ -336,9 +339,12 @@ public: SetMatrixUniform(KnownUniform::TextureTransform, aMatrix); } - void SetTextureRect(const gfx::Rect& aRect) { - float vals[4] = { float(aRect.x), float(aRect.y), float(aRect.width), float(aRect.height) }; - SetUniform(KnownUniform::TextureRect, 4, vals); + void SetTextureRects(const gfx::Rect* aRects) { + float vals[16] = { aRects[0].x, aRects[0].y, aRects[0].width, aRects[0].height, + aRects[1].x, aRects[1].y, aRects[1].width, aRects[1].height, + aRects[2].x, aRects[2].y, aRects[2].width, aRects[2].height, + aRects[3].x, aRects[3].y, aRects[3].width, aRects[3].height }; + SetUniform(KnownUniform::TextureRects, 16, vals); } void SetRenderOffset(const nsIntPoint& aOffset) { @@ -471,6 +477,7 @@ protected: case 2: mGL->fUniform2fv(ku.mLocation, 1, ku.mValue.f16v); break; case 3: mGL->fUniform3fv(ku.mLocation, 1, ku.mValue.f16v); break; case 4: mGL->fUniform4fv(ku.mLocation, 1, ku.mValue.f16v); break; + case 16: mGL->fUniform4fv(ku.mLocation, 4, ku.mValue.f16v); break; default: NS_NOTREACHED("Bogus aLength param"); } diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index d2620c47690..7f8e938df21 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -251,6 +251,15 @@ TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface, (mTexImage->GetSize() != size && !aSrcOffset) || mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) { if (mFlags & TextureFlags::DISALLOW_BIGIMAGE) { + GLint maxTextureSize; + mGL->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTextureSize); + if (size.width > maxTextureSize || size.height > maxTextureSize) { + NS_WARNING("Texture exceeds maximum texture size, refusing upload"); + return false; + } + // Explicitly use CreateBasicTextureImage instead of CreateTextureImage, + // because CreateTextureImage might still choose to create a tiled + // texture image. mTexImage = CreateBasicTextureImage(mGL, size, gfx::ContentForFormat(aSurface->GetFormat()), WrapMode(mGL, mFlags), diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 2c602dd20b9..5d61d3c2771 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -123,6 +123,7 @@ gfxFontEntry::gfxFontEntry() : mHasSpaceFeaturesNonKerning(false), mSkipDefaultFeatureSpaceCheck(false), mCheckedForGraphiteTables(false), + mCheckedForGraphiteSmallCaps(false), mHasCmapTable(false), mGrFaceInitialized(false), mCheckedForColorGlyph(false), @@ -156,6 +157,7 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) : mHasSpaceFeaturesNonKerning(false), mSkipDefaultFeatureSpaceCheck(false), mCheckedForGraphiteTables(false), + mCheckedForGraphiteSmallCaps(false), mHasCmapTable(false), mGrFaceInitialized(false), mCheckedForColorGlyph(false), @@ -879,6 +881,89 @@ gfxFontEntry::CheckForGraphiteTables() mHasGraphiteTables = HasFontTable(TRUETYPE_TAG('S','i','l','f')); } +bool +gfxFontEntry::SupportsOpenTypeSmallCaps(int32_t aScript) +{ + if (!mSmallCapsSupport) { + mSmallCapsSupport = new nsDataHashtable(); + } + + bool result; + if (mSmallCapsSupport->Get(uint32_t(aScript), &result)) { + return result; + } + + result = false; + + hb_face_t *face = GetHBFace(); + + if (hb_ot_layout_has_substitution(face)) { + // Decide what harfbuzz script code will be used for shaping + hb_script_t hbScript; + if (aScript <= MOZ_SCRIPT_INHERITED) { + // For unresolved "common" or "inherited" runs, default to Latin + // for now. (Compare gfxHarfBuzzShaper.) + hbScript = HB_SCRIPT_LATIN; + } else { + hbScript = hb_script_t(GetScriptTagForCode(aScript)); + } + + // Get the OpenType tag(s) that match this script code + hb_tag_t scriptTags[4] = { + HB_TAG_NONE, + HB_TAG_NONE, + HB_TAG_NONE, + HB_TAG_NONE + }; + hb_ot_tags_from_script(hbScript, &scriptTags[0], &scriptTags[1]); + + // Replace the first remaining NONE with DEFAULT + hb_tag_t* scriptTag = &scriptTags[0]; + while (*scriptTag != HB_TAG_NONE) { + ++scriptTag; + } + *scriptTag = HB_OT_TAG_DEFAULT_SCRIPT; + + // Now check for 'smcp' under the first of those scripts that is present + const hb_tag_t kGSUB = HB_TAG('G','S','U','B'); + const hb_tag_t kSMCP = HB_TAG('s','m','c','p'); + scriptTag = &scriptTags[0]; + while (*scriptTag != HB_TAG_NONE) { + unsigned int scriptIndex; + if (hb_ot_layout_table_find_script(face, kGSUB, *scriptTag, + &scriptIndex)) { + if (hb_ot_layout_language_find_feature(face, kGSUB, + scriptIndex, + HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, + kSMCP, nullptr)) { + result = true; + } + break; + } + ++scriptTag; + } + } + + hb_face_destroy(face); + + mSmallCapsSupport->Put(uint32_t(aScript), result); + + return result; +} + +bool +gfxFontEntry::SupportsGraphiteSmallCaps() +{ + if (!mCheckedForGraphiteSmallCaps) { + gr_face* face = GetGrFace(); + mHasGraphiteSmallCaps = + gr_face_find_fref(face, TRUETYPE_TAG('s','m','c','p')) != nullptr; + ReleaseGrFace(face); + mCheckedForGraphiteSmallCaps = true; + } + return mHasGraphiteSmallCaps; +} + bool gfxFontEntry::GetColorLayersInfo(uint32_t aGlyphId, nsTArray& aLayerGlyphs, @@ -2011,6 +2096,7 @@ gfxFontShaper::MergeFontFeatures( if (styleRuleFeatures.IsEmpty() && aFontFeatures.IsEmpty() && !aDisableLigatures && + !aStyle->smallCaps && numAlts == 0) { return false; } @@ -2022,6 +2108,10 @@ gfxFontShaper::MergeFontFeatures( aMergedFeatures.Put(HB_TAG('c','l','i','g'), 0); } + if (aStyle->smallCaps) { + aMergedFeatures.Put(HB_TAG('s','m','c','p'), 1); + } + // add feature values from font uint32_t i, count; @@ -2608,6 +2698,16 @@ gfxFont::SpaceMayParticipateInShaping(int32_t aRunScript) return false; } +bool +gfxFont::SupportsSmallCaps(int32_t aScript) +{ + if (mGraphiteShaper && gfxPlatform::GetPlatform()->UseGraphiteShaping()) { + return GetFontEntry()->SupportsGraphiteSmallCaps(); + } + + return GetFontEntry()->SupportsOpenTypeSmallCaps(aScript); +} + bool gfxFont::HasFeatureSet(uint32_t aFeature, bool& aFeatureOn) { @@ -5444,13 +5544,14 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext, // create the glyph run for this range if (matchedFont) { - if (mStyle.smallCaps) { - if (!matchedFont->InitSmallCapsRun(aContext, aTextRun, - aString + runStart, - aOffset + runStart, - matchedLength, - range.matchType, - aRunScript)) { + if (mStyle.smallCaps && + !matchedFont->SupportsSmallCaps(aRunScript)) { + if (!matchedFont->InitFakeSmallCapsRun(aContext, aTextRun, + aString + runStart, + aOffset + runStart, + matchedLength, + range.matchType, + aRunScript)) { matchedFont = nullptr; } } else { @@ -5549,28 +5650,28 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext, } bool -gfxFont::InitSmallCapsRun(gfxContext *aContext, - gfxTextRun *aTextRun, - const uint8_t *aText, - uint32_t aOffset, - uint32_t aLength, - uint8_t aMatchType, - int32_t aScript) +gfxFont::InitFakeSmallCapsRun(gfxContext *aContext, + gfxTextRun *aTextRun, + const uint8_t *aText, + uint32_t aOffset, + uint32_t aLength, + uint8_t aMatchType, + int32_t aScript) { NS_ConvertASCIItoUTF16 unicodeString(reinterpret_cast(aText), aLength); - return InitSmallCapsRun(aContext, aTextRun, unicodeString.get(), - aOffset, aLength, aMatchType, aScript); + return InitFakeSmallCapsRun(aContext, aTextRun, unicodeString.get(), + aOffset, aLength, aMatchType, aScript); } bool -gfxFont::InitSmallCapsRun(gfxContext *aContext, - gfxTextRun *aTextRun, - const char16_t *aText, - uint32_t aOffset, - uint32_t aLength, - uint8_t aMatchType, - int32_t aScript) +gfxFont::InitFakeSmallCapsRun(gfxContext *aContext, + gfxTextRun *aTextRun, + const char16_t *aText, + uint32_t aOffset, + uint32_t aLength, + uint8_t aMatchType, + int32_t aScript) { bool ok = true; diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index c9fde71965a..b860cd1ff22 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -273,6 +273,9 @@ public: bool IgnoreGDEF() const { return mIgnoreGDEF; } bool IgnoreGSUB() const { return mIgnoreGSUB; } + bool SupportsOpenTypeSmallCaps(int32_t aScript); + bool SupportsGraphiteSmallCaps(); + virtual bool IsSymbolFont(); virtual bool HasFontTable(uint32_t aTableTag); @@ -541,6 +544,8 @@ public: bool mSkipDefaultFeatureSpaceCheck : 1; bool mHasGraphiteTables : 1; bool mCheckedForGraphiteTables : 1; + bool mHasGraphiteSmallCaps : 1; + bool mCheckedForGraphiteSmallCaps : 1; bool mHasCmapTable : 1; bool mGrFaceInitialized : 1; bool mCheckedForColorGlyph : 1; @@ -562,6 +567,7 @@ public: nsTArray mFontsUsingSVGGlyphs; nsAutoPtr mMathTable; nsTArray mFeatureSettings; + nsAutoPtr> mSmallCapsSupport; uint32_t mLanguageOverride; // Color Layer font support @@ -1608,6 +1614,9 @@ public: return mFontEntry->HasGraphiteTables(); } + // whether the font supports "real" small caps or should fake them + bool SupportsSmallCaps(int32_t aScript); + // Subclasses may choose to look up glyph ids for characters. // If they do not override this, gfxHarfBuzzShaper will fetch the cmap // table and use that. @@ -1808,21 +1817,21 @@ public: return mFontEntry->GetUVSGlyph(aCh, aVS); } - bool InitSmallCapsRun(gfxContext *aContext, - gfxTextRun *aTextRun, - const uint8_t *aText, - uint32_t aOffset, - uint32_t aLength, - uint8_t aMatchType, - int32_t aScript); + bool InitFakeSmallCapsRun(gfxContext *aContext, + gfxTextRun *aTextRun, + const uint8_t *aText, + uint32_t aOffset, + uint32_t aLength, + uint8_t aMatchType, + int32_t aScript); - bool InitSmallCapsRun(gfxContext *aContext, - gfxTextRun *aTextRun, - const char16_t *aText, - uint32_t aOffset, - uint32_t aLength, - uint8_t aMatchType, - int32_t aScript); + bool InitFakeSmallCapsRun(gfxContext *aContext, + gfxTextRun *aTextRun, + const char16_t *aText, + uint32_t aOffset, + uint32_t aLength, + uint8_t aMatchType, + int32_t aScript); // call the (virtual) InitTextRun method to do glyph generation/shaping, // limiting the length of text passed by processing the run in multiple diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index d847f9e65d2..871d2f35e48 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -412,7 +412,7 @@ VectorImage::HeapSizeOfVectorImageDocument(nsACString* aDocURL) const } nsWindowSizes windowSizes(WindowsMallocSizeOf); - doc->DocAddSizeOfExcludingThis(&windowSizes); + doc->DocAddSizeOfIncludingThis(&windowSizes); return windowSizes.getTotalSize(); } diff --git a/js/src/jit-test/tests/ion/dce-with-rinstructions.js b/js/src/jit-test/tests/ion/dce-with-rinstructions.js index 89bb7858e22..ff5cdec030e 100644 --- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js +++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js @@ -163,6 +163,35 @@ function radd_object(i) { return i; } +var uceFault_sub_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_sub_number')); +function rsub_number(i) { + var x = 1 - i; + if (uceFault_sub_number(i) || uceFault_sub_number(i)) + assertEq(x, -98 /* = 1 - 99 */); + return i; +} + +var uceFault_sub_float = eval(uneval(uceFault).replace('uceFault', 'uceFault_sub_float')); +function rsub_float(i) { + var t = Math.fround(1/3); + var fi = Math.fround(i); + var x = Math.fround(Math.fround(Math.fround(Math.fround(t - fi) - t) - fi) - t); + if (uceFault_sub_float(i) || uceFault_sub_float(i)) + assertEq(x, -198.3333282470703); /* != -198.33333334326744 (when computed with double subtractions) */ + return i; +} + +var uceFault_sub_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_sub_object')); +function rsub_object(i) { + var t = i; + var o = { valueOf: function () { return t; } }; + var x = o - i; /* computed with t == i, not 1000 */ + t = 1000; + if (uceFault_sub_object(i) || uceFault_sub_object(i)) + assertEq(x, 0); + return i; +} + for (i = 0; i < 100; i++) { rbitnot_number(i); rbitnot_object(i); @@ -180,6 +209,9 @@ for (i = 0; i < 100; i++) { radd_float(i); radd_string(i); radd_object(i); + rsub_number(i); + rsub_float(i); + rsub_object(i); } // Test that we can refer multiple time to the same recover instruction, as well diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index fda8f0e4d95..8b4716f8250 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -4300,6 +4300,11 @@ class MSub : public MBinaryArithInstruction void computeRange(TempAllocator &alloc); bool truncate(TruncateKind kind); TruncateKind operandTruncateKind(size_t index) const; + + bool writeRecoverData(CompactBufferWriter &writer) const; + bool canRecoverOnBailout() const { + return specialization_ != MIRType_None; + } }; class MMul : public MBinaryArithInstruction diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index 26455eb3743..48308732dcc 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -330,6 +330,40 @@ RAdd::recover(JSContext *cx, SnapshotIterator &iter) const return true; } +bool +MSub::writeRecoverData(CompactBufferWriter &writer) const +{ + MOZ_ASSERT(canRecoverOnBailout()); + writer.writeUnsigned(uint32_t(RInstruction::Recover_Sub)); + writer.writeByte(specialization_ == MIRType_Float32); + return true; +} + +RSub::RSub(CompactBufferReader &reader) +{ + isFloatOperation_ = reader.readByte(); +} + +bool +RSub::recover(JSContext *cx, SnapshotIterator &iter) const +{ + RootedValue lhs(cx, iter.read()); + RootedValue rhs(cx, iter.read()); + RootedValue result(cx); + + MOZ_ASSERT(!lhs.isObject() && !rhs.isObject()); + if (!js::SubValues(cx, &lhs, &rhs, &result)) + return false; + + // MIRType_Float32 is a specialization embedding the fact that the result is + // rounded to a Float32. + if (isFloatOperation_ && !RoundFloat32(cx, result, &result)) + return false; + + iter.storeInstructionResult(result); + return true; +} + bool MNewObject::writeRecoverData(CompactBufferWriter &writer) const { diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h index 7bdb45ff70d..a291a952198 100644 --- a/js/src/jit/Recover.h +++ b/js/src/jit/Recover.h @@ -25,6 +25,7 @@ namespace jit { _(Rsh) \ _(Ursh) \ _(Add) \ + _(Sub) \ _(NewObject) \ _(NewDerivedTypedObject) @@ -181,6 +182,21 @@ class RAdd MOZ_FINAL : public RInstruction bool recover(JSContext *cx, SnapshotIterator &iter) const; }; +class RSub MOZ_FINAL : public RInstruction +{ + private: + bool isFloatOperation_; + + public: + RINSTRUCTION_HEADER_(Sub) + + virtual uint32_t numOperands() const { + return 2; + } + + bool recover(JSContext *cx, SnapshotIterator &iter) const; +}; + class RNewObject MOZ_FINAL : public RInstruction { private: diff --git a/js/src/tests/browser.js b/js/src/tests/browser.js index e0e178f5f37..50892829c43 100644 --- a/js/src/tests/browser.js +++ b/js/src/tests/browser.js @@ -64,7 +64,7 @@ function DocumentWrite(s) } function print() { - var s = ''; + var s = 'TEST-INFO | '; var a; for (var i = 0; i < arguments.length; i++) { diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 00b87024119..a52a970a1ca 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -1840,6 +1840,9 @@ AddTransformedBoundsToRegion(const nsIntRegion& aRegion, nsIntRegion* aDest) { nsIntRect bounds = aRegion.GetBounds(); + if (bounds.IsEmpty()) { + return; + } gfxRect transformed = aTransform.TransformBounds(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height)); transformed.RoundOut(); diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 7023b6abdc7..79ecb44c8cd 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -2156,6 +2156,68 @@ FindTileStart(nscoord aDirtyCoord, nscoord aTilePos, nscoord aTileDim) return NSToCoordRound(multiples*aTileDim + aTilePos); } +static gfxFloat +LinearGradientStopPositionForPoint(const gfxPoint& aGradientStart, + const gfxPoint& aGradientEnd, + const gfxPoint& aPoint) +{ + gfxPoint d = aGradientEnd - aGradientStart; + gfxPoint p = aPoint - aGradientStart; + /** + * Compute a parameter t such that a line perpendicular to the + * d vector, passing through aGradientStart + d*t, also + * passes through aPoint. + * + * t is given by + * (p.x - d.x*t)*d.x + (p.y - d.y*t)*d.y = 0 + * + * Solving for t we get + * numerator = d.x*p.x + d.y*p.y + * denominator = d.x^2 + d.y^2 + * t = numerator/denominator + * + * In nsCSSRendering::PaintGradient we know the length of d + * is not zero. + */ + double numerator = d.x * p.x + d.y * p.y; + double denominator = d.x * d.x + d.y * d.y; + return numerator / denominator; +} + +static bool +RectIsBeyondLinearGradientEdge(const gfxRect& aRect, + const gfxMatrix& aPatternMatrix, + const nsTArray& aStops, + const gfxPoint& aGradientStart, + const gfxPoint& aGradientEnd, + gfxRGBA* aOutEdgeColor) +{ + gfxFloat topLeft = LinearGradientStopPositionForPoint( + aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.TopLeft())); + gfxFloat topRight = LinearGradientStopPositionForPoint( + aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.TopRight())); + gfxFloat bottomLeft = LinearGradientStopPositionForPoint( + aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.BottomLeft())); + gfxFloat bottomRight = LinearGradientStopPositionForPoint( + aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.BottomRight())); + + const ColorStop& firstStop = aStops[0]; + if (topLeft < firstStop.mPosition && topRight < firstStop.mPosition && + bottomLeft < firstStop.mPosition && bottomRight < firstStop.mPosition) { + *aOutEdgeColor = firstStop.mColor; + return true; + } + + const ColorStop& lastStop = aStops.LastElement(); + if (topLeft >= lastStop.mPosition && topRight >= lastStop.mPosition && + bottomLeft >= lastStop.mPosition && bottomRight >= lastStop.mPosition) { + *aOutEdgeColor = lastStop.mColor; + return true; + } + + return false; +} + void nsCSSRendering::PaintGradient(nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, @@ -2362,11 +2424,13 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext, nsRefPtr gradientPattern; bool forceRepeatToCoverTiles = false; gfxMatrix matrix; + gfxPoint gradientStart; + gfxPoint gradientEnd; if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) { // Compute the actual gradient line ends we need to pass to cairo after // stops have been normalized. - gfxPoint gradientStart = lineStart + (lineEnd - lineStart)*stopOrigin; - gfxPoint gradientEnd = lineStart + (lineEnd - lineStart)*stopEnd; + gradientStart = lineStart + (lineEnd - lineStart)*stopOrigin; + gradientEnd = lineStart + (lineEnd - lineStart)*stopEnd; gfxPoint gradientStopStart = lineStart + (lineEnd - lineStart)*firstStop; gfxPoint gradientStopEnd = lineStart + (lineEnd - lineStart)*lastStop; @@ -2488,6 +2552,9 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext, gfxRect areaToFill = nsLayoutUtils::RectToGfxRect(aFillArea, appUnitsPerDevPixel); + gfxRect dirtyAreaToFill = nsLayoutUtils::RectToGfxRect(dirty, appUnitsPerDevPixel); + dirtyAreaToFill.RoundOut(); + gfxMatrix ctm = ctx->CurrentMatrix(); bool isCTMPreservingAxisAlignedRectangles = ctm.PreservesAxisAlignedRectangles(); @@ -2535,8 +2602,18 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext, } ctx->NewPath(); ctx->Rectangle(fillRect); - ctx->Translate(tileRect.TopLeft()); - ctx->SetPattern(gradientPattern); + + gfxRect dirtyFillRect = fillRect.Intersect(dirtyAreaToFill); + gfxRect fillRectRelativeToTile = dirtyFillRect - tileRect.TopLeft(); + gfxRGBA edgeColor; + if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR && !isRepeat && + RectIsBeyondLinearGradientEdge(fillRectRelativeToTile, matrix, stops, + gradientStart, gradientEnd, &edgeColor)) { + ctx->SetColor(edgeColor); + } else { + ctx->Translate(tileRect.TopLeft()); + ctx->SetPattern(gradientPattern); + } ctx->Fill(); ctx->SetMatrix(ctm); } diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index bbc3233abc9..70a5e3edd2d 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1623,12 +1623,10 @@ GetAnimatedGeometryRootForFrame(nsIFrame* aFrame, if (!parent) break; nsIAtom* parentType = parent->GetType(); -#ifdef ANDROID // Treat the slider thumb as being as an active scrolled root - // on mobile so that it can move without repainting. + // so that it can move without repainting. if (parentType == nsGkAtoms::sliderFrame) break; -#endif // Sticky frames are active if their nearest scrollable frame // is also active, just keep a record of sticky frames that we // encounter for now. diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 067f7a7da78..0354471e170 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -2183,7 +2183,7 @@ void ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists, - bool& aCreateLayer, + bool aCreateLayer, bool aPositioned) { nsITheme* theme = mOuter->PresContext()->GetTheme(); @@ -2438,9 +2438,9 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, } } - // We put scrollbars in their own layers when this is the root scroll - // frame and we are a toplevel content document. In this situation, the - // scrollbar(s) would normally be assigned their own layer anyway, since + // We put non-overlay scrollbars in their own layers when this is the root + // scroll frame and we are a toplevel content document. In this situation, + // the scrollbar(s) would normally be assigned their own layer anyway, since // they're not scrolled with the rest of the document. But when both // scrollbars are visible, the layer's visible rectangle would be the size // of the viewport, so most layer implementations would create a layer buffer @@ -2475,16 +2475,9 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, aDirtyRect, aLists); -#ifdef MOZ_WIDGET_GONK - // TODO: only layerize the overlay scrollbars if this scrollframe can be - // panned asynchronously. For now just always layerize on B2G because. - // that's where we want the layerized scrollbars - createLayersForScrollbars = true; -#endif if (addScrollBars) { // Add overlay scrollbars. - AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, createLayersForScrollbars, - true); + AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, true, true); } return; @@ -2685,14 +2678,9 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, scrolledContent.BorderBackground()->AppendNewToBottom(layerItem); } // Now display overlay scrollbars and the resizer, if we have one. -#ifdef MOZ_WIDGET_GONK - // TODO: only layerize the overlay scrollbars if this scrollframe can be - // panned asynchronously. For now just always layerize on B2G because. - // that's where we want the layerized scrollbars - createLayersForScrollbars = true; -#endif - AppendScrollPartsTo(aBuilder, aDirtyRect, scrolledContent, - createLayersForScrollbars, true); + // Always create layers for these, so that we don't create a giant layer + // covering the whole scrollport if both scrollbars are visible. + AppendScrollPartsTo(aBuilder, aDirtyRect, scrolledContent, true, true); scrolledContent.MoveTo(aLists); } diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 63d8c33e8a8..85b032535d3 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -68,7 +68,7 @@ public: void AppendScrollPartsTo(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists, - bool& aCreateLayer, + bool aCreateLayer, bool aPositioned); bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea, diff --git a/layout/media/symbols.def.in b/layout/media/symbols.def.in index d6754ce9e92..5274bb59641 100644 --- a/layout/media/symbols.def.in +++ b/layout/media/symbols.def.in @@ -592,12 +592,14 @@ hb_ot_layout_collect_lookups hb_ot_layout_feature_get_lookups hb_ot_layout_has_positioning hb_ot_layout_has_substitution +hb_ot_layout_language_find_feature hb_ot_layout_language_get_feature_indexes hb_ot_layout_language_get_feature_tags hb_ot_layout_language_get_required_feature_index hb_ot_layout_lookup_collect_glyphs hb_ot_layout_script_get_language_tags hb_ot_layout_table_choose_script +hb_ot_layout_table_find_script hb_ot_layout_table_get_script_tags hb_ot_tag_to_language hb_ot_tag_to_script diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 3c08f3e926e..c9fc9b1868b 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -845,7 +845,7 @@ skip-if(B2G&&browserIsRemote) == 401946-1.xul about:blank # bug 974780 == 402567-1.html 402567-1-ref.html == 402567-2.html 402567-2-ref.html == 402567-3.html 402567-3-ref.html -skip-if(B2G) == 402567-4.html 402567-4-ref.html +skip-if(B2G) fuzzy-if(gtk2Widget,2,40) == 402567-4.html 402567-4-ref.html random-if(B2G&&browserIsRemote) == 402629-1.html 402629-1-ref.html random-if(B2G&&browserIsRemote) == 402629-2.html 402629-2-ref.html random-if(B2G&&browserIsRemote) == 402629-3.html 402629-3-ref.html diff --git a/layout/reftests/canvas/text-small-caps-1-ref.html b/layout/reftests/canvas/text-small-caps-1-ref.html index 4464352739c..0d5b0793ed4 100644 --- a/layout/reftests/canvas/text-small-caps-1-ref.html +++ b/layout/reftests/canvas/text-small-caps-1-ref.html @@ -9,11 +9,11 @@ diff --git a/layout/reftests/canvas/text-small-caps-1.html b/layout/reftests/canvas/text-small-caps-1.html index 12a343c4bf4..9312a4e8671 100644 --- a/layout/reftests/canvas/text-small-caps-1.html +++ b/layout/reftests/canvas/text-small-caps-1.html @@ -9,11 +9,11 @@ diff --git a/layout/reftests/fonts/sil/Charis-license.txt b/layout/reftests/fonts/sil/Charis-license.txt new file mode 100755 index 00000000000..b3a335dc785 --- /dev/null +++ b/layout/reftests/fonts/sil/Charis-license.txt @@ -0,0 +1,94 @@ +This Font Software is Copyright (c) 1997-2013, SIL International (http://scripts.sil.org/) +with Reserved Font Names "Charis" and "SIL". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/layout/reftests/fonts/sil/CharisSIL-R.ttf b/layout/reftests/fonts/sil/CharisSIL-R.ttf new file mode 100755 index 00000000000..f0abfe0cfcb Binary files /dev/null and b/layout/reftests/fonts/sil/CharisSIL-R.ttf differ diff --git a/layout/reftests/forms/textarea/reftest.list b/layout/reftests/forms/textarea/reftest.list index b17c77a4cea..901b12917db 100644 --- a/layout/reftests/forms/textarea/reftest.list +++ b/layout/reftests/forms/textarea/reftest.list @@ -1,6 +1,6 @@ skip-if(B2G) fails-if(Android) == resize.html resize-ref.html # an offset seems to apply to the native resizer on windows so skip this test for now -skip-if(B2G) fails-if(Android) skip-if(winWidget) == resize-background.html resize-background-ref.html +skip-if(B2G) fails-if(Android) skip-if(winWidget) fuzzy-if(cocoaWidget,1,33) == resize-background.html resize-background-ref.html skip-if(B2G) fails-if(Android) != ltr.html rtl.html skip-if(B2G) fails-if(Android) != ltr-scrollbar.html rtl-scrollbar.html skip-if(B2G) fails-if(Android) != in-ltr-doc-scrollbar.html in-rtl-doc-scrollbar.html diff --git a/layout/reftests/image-element/reftest.list b/layout/reftests/image-element/reftest.list index 79d2d20a619..9844f073394 100644 --- a/layout/reftests/image-element/reftest.list +++ b/layout/reftests/image-element/reftest.list @@ -17,7 +17,7 @@ random-if(d2d) == element-paint-transform-02.html element-paint-transform-02-ref == element-paint-background-size-02.html element-paint-background-size-02-ref.html == element-paint-transform-repeated.html element-paint-transform-repeated-ref.html fuzzy-if(d2d,255,24) == element-paint-transform-03.html element-paint-transform-03-ref.html -== element-paint-native-widget.html element-paint-native-widget-ref.html +fuzzy-if(gtk2Widget,1,32) fuzzy-if(cocoaWidget,1,106) == element-paint-native-widget.html element-paint-native-widget-ref.html == element-paint-subimage-sampling-restriction.html about:blank == element-paint-clippath.html element-paint-clippath-ref.html == element-paint-sharpness-01a.html element-paint-sharpness-01b.html diff --git a/layout/reftests/text-overflow/reftest.list b/layout/reftests/text-overflow/reftest.list index be045ad4cda..f11127bff99 100644 --- a/layout/reftests/text-overflow/reftest.list +++ b/layout/reftests/text-overflow/reftest.list @@ -3,8 +3,8 @@ skip-if(B2G) == ellipsis-font-fallback.html ellipsis-font-fallback-ref.html skip-if(B2G) HTTP(..) == marker-basic.html marker-basic-ref.html skip-if(B2G) HTTP(..) == marker-string.html marker-string-ref.html skip-if(Android||B2G) HTTP(..) == bidi-simple.html bidi-simple-ref.html # Fails on Android due to anti-aliasing -skip-if(!gtk2Widget) HTTP(..) == bidi-simple-scrolled.html bidi-simple-scrolled-ref.html # Fails on Windows and OSX due to anti-aliasing -skip-if(B2G) fuzzy-if(Android&&AndroidVersion<15,9,2545) fuzzy-if(Android&&AndroidVersion>=15,24,4000) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 +skip-if(!gtk2Widget) fuzzy-if(gtk2Widget,1,104) HTTP(..) == bidi-simple-scrolled.html bidi-simple-scrolled-ref.html # Fails on Windows and OSX due to anti-aliasing +skip-if(B2G) fuzzy-if(Android&&AndroidVersion<15,9,2545) fuzzy-if(Android&&AndroidVersion>=15,24,4000) fuzzy-if(cocoaWidget,1,40) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 fuzzy-if(OSX==10.8,1,1) HTTP(..) == anonymous-block.html anonymous-block-ref.html skip-if(B2G) HTTP(..) == false-marker-overlap.html false-marker-overlap-ref.html HTTP(..) == visibility-hidden.html visibility-hidden-ref.html diff --git a/layout/reftests/text-transform/fake-small-caps-1-ref.html b/layout/reftests/text-transform/fake-small-caps-1-ref.html new file mode 100644 index 00000000000..3b14167ad2f --- /dev/null +++ b/layout/reftests/text-transform/fake-small-caps-1-ref.html @@ -0,0 +1,22 @@ + + + + + + + +
SMALL CAPS + + diff --git a/layout/reftests/text-transform/fake-small-caps-1.html b/layout/reftests/text-transform/fake-small-caps-1.html new file mode 100644 index 00000000000..21d83c36368 --- /dev/null +++ b/layout/reftests/text-transform/fake-small-caps-1.html @@ -0,0 +1,19 @@ + + + + + + + +
Small Caps + + diff --git a/layout/reftests/text-transform/graphite-small-caps-1-notref.html b/layout/reftests/text-transform/graphite-small-caps-1-notref.html new file mode 100644 index 00000000000..d56a6694e0a --- /dev/null +++ b/layout/reftests/text-transform/graphite-small-caps-1-notref.html @@ -0,0 +1,22 @@ + + + + + + + +
SMALL CAPS + + diff --git a/layout/reftests/text-transform/graphite-small-caps-1-ref.html b/layout/reftests/text-transform/graphite-small-caps-1-ref.html new file mode 100644 index 00000000000..f479b5edc91 --- /dev/null +++ b/layout/reftests/text-transform/graphite-small-caps-1-ref.html @@ -0,0 +1,23 @@ + + + + + + + +
Small Caps + + diff --git a/layout/reftests/text-transform/graphite-small-caps-1.html b/layout/reftests/text-transform/graphite-small-caps-1.html new file mode 100644 index 00000000000..eb9d35bc880 --- /dev/null +++ b/layout/reftests/text-transform/graphite-small-caps-1.html @@ -0,0 +1,19 @@ + + + + + + + +
Small Caps + + diff --git a/layout/reftests/text-transform/greek-small-caps-1-ref.html b/layout/reftests/text-transform/greek-small-caps-1-ref.html index fa5255fda71..7e30707574f 100644 --- a/layout/reftests/text-transform/greek-small-caps-1-ref.html +++ b/layout/reftests/text-transform/greek-small-caps-1-ref.html @@ -4,8 +4,13 @@ Test for Greek small-caps + + +
SMALL CAPS + + diff --git a/layout/reftests/text-transform/opentype-small-caps-1-ref.html b/layout/reftests/text-transform/opentype-small-caps-1-ref.html new file mode 100644 index 00000000000..466b4efecea --- /dev/null +++ b/layout/reftests/text-transform/opentype-small-caps-1-ref.html @@ -0,0 +1,23 @@ + + + + + + + +
Small Caps + + diff --git a/layout/reftests/text-transform/opentype-small-caps-1.html b/layout/reftests/text-transform/opentype-small-caps-1.html new file mode 100644 index 00000000000..53974db6e9d --- /dev/null +++ b/layout/reftests/text-transform/opentype-small-caps-1.html @@ -0,0 +1,19 @@ + + + + + + + +
Small Caps + + diff --git a/layout/reftests/text-transform/reftest.list b/layout/reftests/text-transform/reftest.list index 8205abc4ba0..f36280e9e01 100644 --- a/layout/reftests/text-transform/reftest.list +++ b/layout/reftests/text-transform/reftest.list @@ -8,7 +8,12 @@ == capitalize-7a.html capitalize-7-ref.html == lowercase-1.html lowercase-ref.html == lowercase-sigma-1.html lowercase-sigma-1-ref.html -== small-caps-1.html small-caps-1-ref.html +fails-if(B2G) random-if(winWidget) == small-caps-1.html small-caps-1-ref.html # fails if default font supports 'smcp' +HTTP(..) == fake-small-caps-1.html fake-small-caps-1-ref.html +HTTP(..) == opentype-small-caps-1.html opentype-small-caps-1-ref.html +HTTP(..) != opentype-small-caps-1.html opentype-small-caps-1-notref.html +HTTP(..) == graphite-small-caps-1.html graphite-small-caps-1-ref.html +HTTP(..) != graphite-small-caps-1.html graphite-small-caps-1-notref.html == uppercase-1.html uppercase-ref.html == uppercase-szlig-1.html uppercase-szlig-ref.html # these use DejaVu Sans via @font-face for consistency of results @@ -22,7 +27,7 @@ skip-if(B2G) HTTP(..) == all-title.html all-title-ref.html # bug 773482 HTTP(..) != small-caps-turkish-1.html small-caps-turkish-1-notref.html == greek-uppercase-1.html greek-uppercase-1-ref.html == greek-uppercase-2.html greek-uppercase-2-ref.html -== greek-small-caps-1.html greek-small-caps-1-ref.html +HTTP(..) == greek-small-caps-1.html greek-small-caps-1-ref.html == fullwidth-1.html fullwidth-1-ref.html == fullwidth-2.html fullwidth-2-ref.html == fullwidth-all.html fullwidth-all-ref.html diff --git a/layout/reftests/xul/text-small-caps-1-ref.xul b/layout/reftests/xul/text-small-caps-1-ref.xul index 12b66928d2f..e3df45e142c 100644 --- a/layout/reftests/xul/text-small-caps-1-ref.xul +++ b/layout/reftests/xul/text-small-caps-1-ref.xul @@ -1,6 +1,6 @@ - +