Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-05-08 14:32:22 +02:00
commit 5f44ca630c
83 changed files with 1025 additions and 910 deletions

View File

@ -600,6 +600,33 @@ SettingsListener.observe("accessibility.screenreader", false, function(value) {
});
})();
// =================== Telemetry ======================
(function setupTelemetrySettings() {
let gaiaSettingName = 'debug.performance_data.shared';
let geckoPrefName = 'toolkit.telemetry.enabled';
SettingsListener.observe(gaiaSettingName, null, function(value) {
if (value !== null) {
// Gaia setting has been set; update Gecko pref to that.
Services.prefs.setBoolPref(geckoPrefName, value);
return;
}
// Gaia setting has not been set; set the gaia setting to default.
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
let prefValue = true;
#else
let prefValue = false;
#endif
try {
prefValue = Services.prefs.getBoolPref(geckoPrefName);
} catch (e) {
// Pref not set; use default value.
}
let setting = {};
setting[gaiaSettingName] = prefValue;
window.navigator.mozSettings.createLock().set(setting);
});
})();
// =================== Various simple mapping ======================
let settingsToObserve = {
'ril.mms.retrieval_mode': {

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>
@ -128,7 +128,7 @@
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="c3ee0c875393607430086f942950d1b3f496ab0e"/>
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="07f695559cf1834e908fce0ec2a8531582369bac"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="24e0e7016bbc22096b28e8bfdd6362b250ac78b7"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="bc70af75eac79073c4c935bf1f71c0cb10e821b7"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="f620016437dd2f050e044eccef5e70e3f689ccbe"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="65fba428f8d76336b33ddd9e15900357953600ba">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>

View File

@ -18,7 +18,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "e2fad48ac3a632fbd405ff958c9dbf0d821f7b47",
"revision": "2c31857e31048d05f9bb335d8ef2408c612195af",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="3691614d0045f7968addce45d4140fb360c3ceaf"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1e0574b8f6b8a2a8d9d468878ce2b4c283fc9a84"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="68f7b3d4c3734a699b053cc897c1d11b8326fb93"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="f313e6d3aaaefe8c82eaed15912a09b120fb7260"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -922,6 +922,7 @@ let PlacesToolbarHelper = {
if (forceToolbarOverflowCheck) {
viewElt._placesView.updateOverflowStatus();
}
this._shouldWrap = false;
this._setupPlaceholder();
},

View File

@ -785,14 +785,10 @@ StackFrames.prototype = {
if (!isClientEval && !isPopupShown) {
// Move the editor's caret to the proper url and line.
DebuggerView.setEditorLocation(where.url, where.line);
} else {
// Highlight the line where the execution is paused in the editor.
DebuggerView.setEditorLocation(where.url, where.line, { noCaret: true });
// Highlight the breakpoint at the specified url and line if it exists.
DebuggerView.Sources.highlightBreakpoint(where, { noEditorUpdate: true });
}
// Highlight the breakpoint at the line and column if it exists.
DebuggerView.Sources.highlightBreakpointAtCursor();
// Don't display the watch expressions textbox inputs in the pane.
DebuggerView.WatchExpressions.toggleContents(false);

View File

@ -414,17 +414,6 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
}
},
/**
* Highlight the breakpoint on the current currently focused line/column
* if it exists.
*/
highlightBreakpointAtCursor: function() {
let url = DebuggerView.Sources.selectedValue;
let line = DebuggerView.editor.getCursor().line + 1;
let location = { url: url, line: line };
this.highlightBreakpoint(location, { noEditorUpdate: true });
},
/**
* Unhighlights the current breakpoint in this sources container.
*/
@ -2014,21 +2003,21 @@ VariableBubbleView.prototype = {
/**
* The mousemove listener for the source editor.
*/
_onMouseMove: function(e) {
_onMouseMove: function({ clientX: x, clientY: y, buttons: btns }) {
// Prevent the variable inspection popup from showing when the thread client
// is not paused, or while a popup is already visible, or when the user tries
// to select text in the editor.
let isResumed = gThreadClient && gThreadClient.state != "paused";
let isSelecting = DebuggerView.editor.somethingSelected() && e.buttons > 0;
let isPopupVisible = !this._tooltip.isHidden();
if (isResumed || isSelecting || isPopupVisible) {
if (gThreadClient && gThreadClient.state != "paused"
|| !this._tooltip.isHidden()
|| (DebuggerView.editor.somethingSelected()
&& btns > 0)) {
clearNamedTimeout("editor-mouse-move");
return;
}
// Allow events to settle down first. If the mouse hovers over
// a certain point in the editor long enough, try showing a variable bubble.
setNamedTimeout("editor-mouse-move",
EDITOR_VARIABLE_HOVER_DELAY, () => this._findIdentifier(e.clientX, e.clientY));
EDITOR_VARIABLE_HOVER_DELAY, () => this._findIdentifier(x, y));
},
/**

View File

@ -370,7 +370,8 @@ let DebuggerView = {
* The source object coming from the active thread.
* @param object aFlags
* Additional options for setting the source. Supported options:
* - force: boolean forcing all text to be reshown in the editor
* - force: boolean allowing whether we can get the selected url's
* text again.
* @return object
* A promise that is resolved after the source text has been set.
*/
@ -440,7 +441,8 @@ let DebuggerView = {
* - noDebug: don't set the debug location at the specified line
* - align: string specifying whether to align the specified line
* at the "top", "center" or "bottom" of the editor
* - force: boolean forcing all text to be reshown in the editor
* - force: boolean allowing whether we can get the selected url's
* text again
* @return object
* A promise that is resolved after the source text has been set.
*/

View File

@ -285,7 +285,6 @@ skip-if = (os == 'mac' || os == 'win') && (debug == false) # Bug 986166
[browser_dbg_variables-view-popup-13.js]
[browser_dbg_variables-view-popup-14.js]
[browser_dbg_variables-view-popup-15.js]
[browser_dbg_variables-view-popup-16.js]
[browser_dbg_variables-view-reexpand-01.js]
[browser_dbg_variables-view-reexpand-02.js]
[browser_dbg_variables-view-reexpand-03.js]

View File

@ -1,59 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if opening the variables inspection popup preserves the highlighting
* associated with the currently debugged line.
*/
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
function test() {
Task.spawn(function() {
let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
let win = panel.panelWin;
let events = win.EVENTS;
let editor = win.DebuggerView.editor;
let frames = win.DebuggerView.StackFrames;
let variables = win.DebuggerView.Variables;
let bubble = win.DebuggerView.VariableBubble;
let tooltip = bubble._tooltip.panel;
function checkView(selectedFrame, caretLine, debugLine = caretLine) {
is(win.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(frames.itemCount, 25,
"Should have 25 frames.");
is(frames.selectedDepth, selectedFrame,
"The correct frame is selected in the widget.");
ok(isCaretPos(panel, caretLine),
"Editor caret location is correct.");
ok(isDebugPos(panel, debugLine),
"Editor caret location is correct.");
}
function expandGlobalScope() {
let globalScope = variables.getScopeAtIndex(1);
is(globalScope.expanded, false,
"The globalScope should not be expanded yet.");
let finished = waitForDebuggerEvents(panel, events.FETCHED_VARIABLES);
globalScope.expand();
return finished;
}
// Allow this generator function to yield first.
executeSoon(() => debuggee.recurse());
yield waitForSourceAndCaretAndScopes(panel, ".html", 26);
checkView(0, 26);
yield expandGlobalScope();
checkView(0, 26);
// Inspect variable in topmost frame.
yield openVarPopup(panel, { line: 26, ch: 11 });
checkView(0, 26);
yield resumeDebuggerThenCloseAndFinish(panel);
});
}

View File

@ -300,12 +300,6 @@ function isCaretPos(aPanel, aLine, aCol = 1) {
return cursor.line == (aLine - 1) && cursor.ch == (aCol - 1);
}
function isDebugPos(aPanel, aLine) {
let editor = aPanel.panelWin.DebuggerView.editor;
let location = editor.getDebugLocation();
return location != null && editor.hasLineClass(aLine - 1, "debug-line");
}
function isEditorSel(aPanel, [start, end]) {
let editor = aPanel.panelWin.DebuggerView.editor;
let range = {

View File

@ -4,6 +4,9 @@
# Setup for build cache
# Avoid duplication if the file happens to be included twice.
if test -z "$bucket"; then
read branch platform master <<EOF
$(python2.7 -c 'import json; p = json.loads(open("'"$topsrcdir"'/../buildprops.json").read())["properties"]; print p["branch"], p["platform"], p["master"]' 2> /dev/null)
EOF
@ -62,3 +65,5 @@ else
;;
esac
fi
fi

View File

@ -53,6 +53,7 @@ LOCAL_INCLUDES += [
]
DISABLE_STL_WRAPPING = True
NO_VISIBILITY_FLAGS = True
# Suppress warnings in third-party code.
if CONFIG['GNU_CXX']:

View File

@ -2550,8 +2550,13 @@ dnl ===============================================================
if test "$GNU_CC"; then
AC_DEFINE(HAVE_VISIBILITY_HIDDEN_ATTRIBUTE)
AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE)
case "${OS_TARGET}" in
Darwin|Android)
if test -n "$gonkdir"; then
visibility_target=Gonk
else
visibility_target=$OS_TARGET
fi
case "$visibility_target" in
Darwin|Gonk)
VISIBILITY_FLAGS='-fvisibility=hidden'
;;
*)

View File

@ -68,6 +68,7 @@ typedef enum {
GStreamerReader::GStreamerReader(AbstractMediaDecoder* aDecoder)
: MediaDecoderReader(aDecoder),
mMP3FrameParser(aDecoder->GetResource()->GetLength()),
mDataOffset(0),
mUseParserDuration(false),
#if GST_VERSION_MAJOR >= 1
mAllocator(nullptr),
@ -238,7 +239,7 @@ void GStreamerReader::PlayBinSourceSetup(GstAppSrc* aSource)
resource->Seek(SEEK_SET, 0);
/* now we should have a length */
int64_t resourceLength = resource->GetLength();
int64_t resourceLength = GetDataLength();
gst_app_src_set_size(mSource, resourceLength);
if (resource->IsDataCachedToEndOfResource(0) ||
(resourceLength != -1 && resourceLength <= SHORT_FILE_SIZE)) {
@ -287,11 +288,28 @@ nsresult GStreamerReader::ParseMP3Headers()
if (mMP3FrameParser.IsMP3()) {
mLastParserDuration = mMP3FrameParser.GetDuration();
mDataOffset = mMP3FrameParser.GetMP3Offset();
// Update GStreamer's stream length in case we found any ID3 headers to
// ignore.
gst_app_src_set_size(mSource, GetDataLength());
}
return NS_OK;
}
int64_t
GStreamerReader::GetDataLength()
{
int64_t streamLen = mDecoder->GetResource()->GetLength();
if (streamLen < 0) {
return streamLen;
}
return streamLen - mDataOffset;
}
nsresult GStreamerReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags)
{
@ -800,7 +818,7 @@ nsresult GStreamerReader::GetBuffered(dom::TimeRanges* aBuffered,
double end = (double) duration / GST_MSECOND;
LOG(PR_LOG_DEBUG, "complete range [0, %f] for [0, %li]",
end, resource->GetLength());
end, GetDataLength());
aBuffered->Add(0, end);
return NS_OK;
}
@ -829,7 +847,7 @@ nsresult GStreamerReader::GetBuffered(dom::TimeRanges* aBuffered,
double start = (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND;
double end = (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND;
LOG(PR_LOG_DEBUG, "adding range [%f, %f] for [%li %li] size %li",
start, end, startOffset, endOffset, resource->GetLength());
start, end, startOffset, endOffset, GetDataLength());
aBuffered->Add(start, end);
}
@ -933,6 +951,8 @@ gboolean GStreamerReader::SeekDataCb(GstAppSrc* aSrc,
gboolean GStreamerReader::SeekData(GstAppSrc* aSrc, guint64 aOffset)
{
aOffset += mDataOffset;
ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
MediaResource* resource = mDecoder->GetResource();
int64_t resourceLength = resource->GetLength();
@ -941,7 +961,7 @@ gboolean GStreamerReader::SeekData(GstAppSrc* aSrc, guint64 aOffset)
/* It's possible that we didn't know the length when we initialized mSource
* but maybe we do now
*/
gst_app_src_set_size(mSource, resourceLength);
gst_app_src_set_size(mSource, GetDataLength());
}
nsresult rv = NS_ERROR_FAILURE;

View File

@ -178,9 +178,17 @@ private:
// Try to find MP3 headers in this stream using our MP3 frame parser.
nsresult ParseMP3Headers();
// Get the length of the stream, excluding any metadata we have ignored at the
// start of the stream: ID3 headers, for example.
int64_t GetDataLength();
// Use our own MP3 parser here, largely for consistency with other platforms.
MP3FrameParser mMP3FrameParser;
// The byte position in the stream where the actual media (ignoring, for
// example, ID3 tags) starts.
uint64_t mDataOffset;
// We want to be able to decide in |ReadMetadata| whether or not we use the
// duration from the MP3 frame parser, as this backend supports more than just
// MP3. But |NotifyDataArrived| can update the duration and is often called

View File

@ -65,7 +65,7 @@ private:
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
const nsAutoCString mType;
const nsCString mType;
};
} // namespace mozilla

View File

@ -132,6 +132,8 @@ public:
{
return false;
}
static ContainerParser* CreateForMIMEType(const nsACString& aType);
};
class WebMContainerParser : public ContainerParser {
@ -156,6 +158,17 @@ public:
}
};
/*static*/ ContainerParser*
ContainerParser::CreateForMIMEType(const nsACString& aType)
{
if (aType.LowerCaseEqualsLiteral("video/webm") || aType.LowerCaseEqualsLiteral("audio/webm")) {
return new WebMContainerParser();
}
// XXX: Plug in parsers for MPEG4, etc. here.
return new ContainerParser();
}
namespace dom {
void
@ -267,10 +280,7 @@ SourceBuffer::Abort(ErrorResult& aRv)
mAppendWindowEnd = PositiveInfinity<double>();
MSE_DEBUG("%p Abort: Discarding decoder.", this);
if (mDecoder) {
mDecoder->GetResource()->Ended();
mDecoder = nullptr;
}
DiscardDecoder();
}
void
@ -296,7 +306,7 @@ void
SourceBuffer::Detach()
{
Ended();
mDecoder = nullptr;
DiscardDecoder();
mMediaSource = nullptr;
}
@ -317,15 +327,10 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
, mTimestampOffset(0)
, mAppendMode(SourceBufferAppendMode::Segments)
, mUpdating(false)
, mDecoderInit(false)
, mDecoderInitialized(false)
{
MOZ_ASSERT(aMediaSource);
if (mType.EqualsIgnoreCase("video/webm") || mType.EqualsIgnoreCase("audio/webm")) {
mParser = new WebMContainerParser();
} else {
// XXX: Plug in parsers for MPEG4, etc. here.
mParser = new ContainerParser();
}
mParser = ContainerParser::CreateForMIMEType(aType);
MSE_DEBUG("%p SourceBuffer: Creating initial decoder.", this);
InitNewDecoder();
}
@ -339,9 +344,7 @@ SourceBuffer::Create(MediaSource* aMediaSource, const nsACString& aType)
SourceBuffer::~SourceBuffer()
{
if (mDecoder) {
mDecoder->GetResource()->Ended();
}
DiscardDecoder();
}
MediaSource*
@ -374,15 +377,27 @@ SourceBuffer::QueueAsyncSimpleEvent(const char* aName)
bool
SourceBuffer::InitNewDecoder()
{
MOZ_ASSERT(!mDecoder);
MediaSourceDecoder* parentDecoder = mMediaSource->GetDecoder();
nsRefPtr<SubBufferDecoder> decoder = parentDecoder->CreateSubDecoder(mType);
if (!decoder) {
return false;
}
mDecoder = decoder;
mDecoderInitialized = false;
return true;
}
void
SourceBuffer::DiscardDecoder()
{
if (mDecoder) {
mDecoder->GetResource()->Ended();
}
mDecoder = nullptr;
mDecoderInitialized = false;
}
void
SourceBuffer::StartUpdating()
{
@ -424,18 +439,28 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
// TODO: Test buffer full flag.
StartUpdating();
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
if (!mDecoder || mParser->IsInitSegmentPresent(aData, aLength)) {
if (!mDecoder || mDecoderInit) {
MSE_DEBUG("%p AppendBuffer: New initialization segment, creating decoder.", this);
mDecoder->GetResource()->Ended();
if (mParser->IsInitSegmentPresent(aData, aLength)) {
MSE_DEBUG("%p AppendBuffer: New initialization segment.", this);
if (mDecoderInitialized) {
// Existing decoder has been used, time for a new one.
DiscardDecoder();
}
if (!InitNewDecoder()) {
// If we've got a decoder here, it's not initialized, so we can use it
// rather than creating a new one.
if (!mDecoder && !InitNewDecoder()) {
aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
return;
}
}
MSE_DEBUG("%p AppendBuffer: Decoder marked as initialized.", this);
mDecoderInit = true;
mDecoderInitialized = true;
} else if (!mDecoderInitialized) {
MSE_DEBUG("%p AppendBuffer: Non-initialization segment appended during initialization.");
Optional<MediaSourceEndOfStreamError> decodeError(MediaSourceEndOfStreamError::Decode);
ErrorResult dummy;
mMediaSource->EndOfStream(decodeError, dummy);
aRv.Throw(NS_ERROR_FAILURE);
return;
}
// XXX: For future reference: NDA call must run on the main thread.
mDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),

View File

@ -119,9 +119,13 @@ private:
void DispatchSimpleEvent(const char* aName);
void QueueAsyncSimpleEvent(const char* aName);
// Create a new decoder for mType, add it to mDecoders and update mCurrentDecoder.
// Create a new decoder for mType, and store the result in mDecoder.
// Returns true if mDecoder was set.
bool InitNewDecoder();
// Set mDecoder to null and reset mDecoderInitialized.
void DiscardDecoder();
// Update mUpdating and fire the appropriate events.
void StartUpdating();
void StopUpdating();
@ -136,7 +140,7 @@ private:
nsRefPtr<MediaSource> mMediaSource;
const nsAutoCString mType;
const nsCString mType;
nsAutoPtr<ContainerParser> mParser;
@ -150,7 +154,7 @@ private:
SourceBufferAppendMode mAppendMode;
bool mUpdating;
bool mDecoderInit;
bool mDecoderInitialized;
};
} // namespace dom

View File

@ -283,7 +283,7 @@ public:
private:
nsCOMPtr<nsIPrincipal> mPrincipal;
const nsAutoCString mType;
const nsCString mType;
// Provides synchronization between SourceBuffers and InputAdapters.
// Protects all of the member variables below. Read() will await a

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
/*
user_pref("media.mediasource.enabled", true);
*/
function boom()
{
var source = new window.MediaSource();
var videoElement = document.createElementNS('http://www.w3.org/1999/xhtml', 'video');
videoElement.src = URL.createObjectURL(source);
setTimeout(function() {
var buf = source.addSourceBuffer("video/webm");
buf.abort();
buf.appendBuffer(new Float32Array(203));
}, 0);
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -0,0 +1,2 @@
test-pref(media.mediasource.enabled,true) load 926665.html
test-pref(media.mediasource.enabled,true) load 1005366.html

View File

@ -69,4 +69,4 @@ load offline-buffer-source-ended-1.html
skip-if(B2G) HTTP load media-element-source-seek-1.html # intermittent B2G timeouts, bug 994351
skip-if(B2G) load oscillator-ended-1.html # intermittent B2G timeouts, bug 920338
skip-if(B2G) load oscillator-ended-2.html # intermittent B2G timeouts, bug 920338
test-pref(media.mediasource.enabled,true) load 926665.html
include ../../mediasource/test/crashtests/crashtests.list

View File

@ -425,10 +425,10 @@ MediaEngineDefaultAudioSource::Start(SourceMediaStream* aStream, TrackID aID)
#if defined(MOZ_WIDGET_GONK) && defined(DEBUG)
// B2G emulator debug is very, very slow and has problems dealing with realtime audio inputs
mTimer->InitWithCallback(this, MediaEngine::DEFAULT_AUDIO_TIMER_MS*10,
nsITimer::TYPE_REPEATING_PRECISE);
nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP);
#else
mTimer->InitWithCallback(this, MediaEngine::DEFAULT_AUDIO_TIMER_MS,
nsITimer::TYPE_REPEATING_PRECISE);
nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP);
#endif
mState = kStarted;

View File

@ -23,7 +23,7 @@ HASINSTANCE_HOOK_NAME = '_hasInstance'
NEWRESOLVE_HOOK_NAME = '_newResolve'
ENUMERATE_HOOK_NAME = '_enumerate'
ENUM_ENTRY_VARIABLE_NAME = 'strings'
INSTANCE_RESERVED_SLOTS = 3
INSTANCE_RESERVED_SLOTS = 1
def memberReservedSlot(member):
@ -353,6 +353,7 @@ JS_NULL_OBJECT_OPS
if self.descriptor.interface.getExtendedAttribute("Global"):
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS) | JSCLASS_IMPLEMENTS_BARRIERS"
traceHook = "JS_GlobalObjectTraceHook"
reservedSlots = "JSCLASS_GLOBAL_APPLICATION_SLOTS"
if not self.descriptor.workers:
classExtensionAndObjectOps = """\
{
@ -388,6 +389,7 @@ JS_NULL_OBJECT_OPS
"""
else:
classFlags += "JSCLASS_HAS_RESERVED_SLOTS(%d)" % slotCount
reservedSlots = slotCount
if self.descriptor.interface.getExtendedAttribute("NeedNewResolve"):
newResolveHook = "(JSResolveOp)" + NEWRESOLVE_HOOK_NAME
classFlags += " | JSCLASS_NEW_RESOLVE"
@ -423,6 +425,10 @@ JS_NULL_OBJECT_OPS
},
$*{descriptor}
};
static_assert(${instanceReservedSlots} == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(${reservedSlots} >= ${slotCount},
"Must have enough reserved slots.");
""",
name=self.descriptor.interface.identifier.name,
flags=classFlags,
@ -433,7 +439,10 @@ JS_NULL_OBJECT_OPS
call=callHook,
trace=traceHook,
classExtensionAndObjectOps=classExtensionAndObjectOps,
descriptor=DOMClass(self.descriptor))
descriptor=DOMClass(self.descriptor),
instanceReservedSlots=INSTANCE_RESERVED_SLOTS,
reservedSlots=reservedSlots,
slotCount=slotCount)
class CGDOMProxyJSClass(CGThing):
@ -10029,6 +10038,12 @@ class CGDescriptor(CGThing):
not descriptor.workers):
cgThings.append(CGConstructorEnabled(descriptor))
if (descriptor.interface.hasMembersInSlots() and
descriptor.interface.hasChildInterfaces()):
raise TypeError("We don't support members in slots on "
"non-leaf interfaces like %s" %
descriptor.interface.identifier.name)
if descriptor.concrete:
if descriptor.proxy:
if descriptor.interface.totalMembersInSlots != 0:
@ -10056,10 +10071,6 @@ class CGDescriptor(CGThing):
cgThings.append(CGDOMJSClass(descriptor))
cgThings.append(CGGetJSClassMethod(descriptor))
if descriptor.interface.hasMembersInSlots():
if descriptor.interface.hasChildInterfaces():
raise TypeError("We don't support members in slots on "
"non-leaf interfaces like %s" %
descriptor.interface.identifier.name)
cgThings.append(CGUpdateMemberSlotsMethod(descriptor))
if descriptor.interface.getExtendedAttribute("Global"):

View File

@ -1331,6 +1331,23 @@ TabChild::DestroyWindow()
}
mLayersId = 0;
}
for (uint32_t index = 0, count = mCachedFileDescriptorInfos.Length();
index < count;
index++) {
nsAutoPtr<CachedFileDescriptorInfo>& info =
mCachedFileDescriptorInfos[index];
MOZ_ASSERT(!info->mCallback);
if (info->mFileDescriptor.IsValid()) {
MOZ_ASSERT(!info->mCanceled);
nsRefPtr<CloseFileRunnable> runnable =
new CloseFileRunnable(info->mFileDescriptor);
runnable->Dispatch();
}
}
}
bool
@ -1563,6 +1580,9 @@ TabChild::CancelCachedFileDescriptorCallback(
MOZ_ASSERT(info->mCallback == aCallback);
MOZ_ASSERT(!info->mCanceled);
// No need to hold the callback any longer.
info->mCallback = nullptr;
// Set this flag so that we will close the file descriptor when it arrives.
info->mCanceled = true;
}

View File

@ -80,13 +80,18 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::widget;
// Some utilities to handle annoying overloading of "A" tag for link and named anchor
static char hrefText[] = "href";
static char anchorTxt[] = "anchor";
static char namedanchorText[] = "namedanchor";
// Some utilities to handle overloading of "A" tag for link and named anchor.
static bool
IsLinkTag(const nsString& s)
{
return s.EqualsIgnoreCase("href");
}
#define IsLinkTag(s) (s.EqualsIgnoreCase(hrefText))
#define IsNamedAnchorTag(s) (s.EqualsIgnoreCase(anchorTxt) || s.EqualsIgnoreCase(namedanchorText))
static bool
IsNamedAnchorTag(const nsString& s)
{
return s.EqualsIgnoreCase("anchor") || s.EqualsIgnoreCase("namedanchor");
}
nsHTMLEditor::nsHTMLEditor()
: nsPlaintextEditor()
@ -648,7 +653,7 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
}
bool handled = false;
nsresult rv;
nsresult rv = NS_OK;
if (nsHTMLEditUtils::IsTableElement(blockParent)) {
rv = TabInTable(nativeKeyEvent->IsShift(), &handled);
if (handled) {

View File

@ -60,6 +60,7 @@ class FilterNode;
struct NativeSurface {
NativeSurfaceType mType;
SurfaceFormat mFormat;
gfx::IntSize mSize;
void *mSurface;
};
@ -1034,10 +1035,6 @@ public:
static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr);
static TemporaryRef<SourceSurface>
CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
SurfaceFormat aFormat);
static TemporaryRef<DrawTarget>
CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);

View File

@ -81,70 +81,6 @@ private:
} // end anonymous namespace
static bool
GetCairoSurfaceSize(cairo_surface_t* surface, IntSize& size)
{
switch (cairo_surface_get_type(surface))
{
case CAIRO_SURFACE_TYPE_IMAGE:
{
size.width = cairo_image_surface_get_width(surface);
size.height = cairo_image_surface_get_height(surface);
return true;
}
#ifdef CAIRO_HAS_XLIB_SURFACE
case CAIRO_SURFACE_TYPE_XLIB:
{
size.width = cairo_xlib_surface_get_width(surface);
size.height = cairo_xlib_surface_get_height(surface);
return true;
}
#endif
#ifdef CAIRO_HAS_QUARTZ_SURFACE
case CAIRO_SURFACE_TYPE_QUARTZ:
{
CGContextRef cgc = cairo_quartz_surface_get_cg_context(surface);
// It's valid to call these CGBitmapContext functions on non-bitmap
// contexts; they'll just return 0 in that case.
size.width = CGBitmapContextGetWidth(cgc);
size.height = CGBitmapContextGetHeight(cgc);
return true;
}
#endif
#ifdef CAIRO_HAS_WIN32_SURFACE
#ifdef MOZ2D_HAS_MOZ_CAIRO
case CAIRO_SURFACE_TYPE_WIN32:
case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
{
size.width = cairo_win32_surface_get_width(surface);
size.height = cairo_win32_surface_get_height(surface);
return true;
}
#else
case CAIRO_SURFACE_TYPE_WIN32:
{
cairo_surface_t *img = cairo_win32_surface_get_image(surface);
if (!img) {
// XXX - fix me
MOZ_ASSERT(false);
return true;
}
size.width = cairo_image_surface_get_width(img);
size.height = cairo_image_surface_get_height(img);
return true;
}
#endif
#endif
default:
return false;
}
}
static bool
SupportsSelfCopy(cairo_surface_t* surface)
{
@ -1131,26 +1067,14 @@ TemporaryRef<SourceSurface>
DrawTargetCairo::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
{
if (aSurface.mType == NativeSurfaceType::CAIRO_SURFACE) {
IntSize size;
cairo_surface_t* surf = static_cast<cairo_surface_t*>(aSurface.mSurface);
if (GetCairoSurfaceSize(surf, size)) {
RefPtr<SourceSurfaceCairo> source =
new SourceSurfaceCairo(surf, size, aSurface.mFormat);
return source;
}
}
if (aSurface.mSize.width <= 0 ||
aSurface.mSize.height <= 0) {
gfxWarning() << "Can't create a SourceSurface without a valid size";
return nullptr;
}
TemporaryRef<SourceSurface>
DrawTargetCairo::CreateSourceSurfaceForCairoSurface(cairo_surface_t *aSurface,
SurfaceFormat aFormat)
{
IntSize size;
if (GetCairoSurfaceSize(aSurface, size)) {
cairo_surface_t* surf = static_cast<cairo_surface_t*>(aSurface.mSurface);
RefPtr<SourceSurfaceCairo> source =
new SourceSurfaceCairo(aSurface, size, aFormat);
new SourceSurfaceCairo(surf, aSurface.mSize, aSurface.mFormat);
return source;
}

View File

@ -169,10 +169,6 @@ public:
static cairo_surface_t *GetDummySurface();
static TemporaryRef<SourceSurface>
CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
SurfaceFormat aFormat);
private: // methods
// Init cairo surface without doing a cairo_surface_reference() call.
bool InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr);

View File

@ -637,18 +637,6 @@ Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSiz
return retVal;
}
TemporaryRef<SourceSurface>
Factory::CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
SurfaceFormat aFormat)
{
RefPtr<SourceSurface> retVal;
#ifdef USE_CAIRO
retVal = DrawTargetCairo::CreateSourceSurfaceForCairoSurface(aSurface, aFormat);
#endif
return retVal;
}
#ifdef XP_MACOSX
TemporaryRef<DrawTarget>
Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize)

View File

@ -32,7 +32,7 @@ public:
virtual TextureSourceBasic* AsSourceBasic() MOZ_OVERRIDE { return this; }
virtual gfx::SourceSurface* GetSurface() MOZ_OVERRIDE { return mSurface; }
virtual gfx::SourceSurface* GetSurface(DrawTarget* aTarget) MOZ_OVERRIDE { return mSurface; }
SurfaceFormat GetFormat() const MOZ_OVERRIDE
{
@ -293,7 +293,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
Matrix maskTransform;
if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
EffectMask *effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface();
sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(dest);
MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
MOZ_ASSERT(!effectMask->mIs3D);
maskTransform = effectMask->mMaskTransform.As2D();
@ -315,7 +315,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
TextureSourceBasic* source = texturedEffect->mTexture->AsSourceBasic();
DrawSurfaceWithTextureCoords(dest, aRect,
source->GetSurface(),
source->GetSurface(dest),
texturedEffect->mTextureCoords,
texturedEffect->mFilter,
aOpacity, sourceMask, &maskTransform);

View File

@ -46,7 +46,7 @@ MacIOSurfaceTextureHostBasic::MacIOSurfaceTextureHostBasic(
}
gfx::SourceSurface*
MacIOSurfaceTextureSourceBasic::GetSurface()
MacIOSurfaceTextureSourceBasic::GetSurface(gfx::DrawTarget* aTarget)
{
if (!mSourceSurface) {
mSourceSurface = mSurface->GetAsSurface();

View File

@ -34,7 +34,7 @@ public:
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
virtual gfx::SourceSurface* GetSurface() MOZ_OVERRIDE;
virtual gfx::SourceSurface* GetSurface(gfx::DrawTarget* aTarget) MOZ_OVERRIDE;
virtual void DeallocateDeviceData() MOZ_OVERRIDE { }

View File

@ -22,7 +22,7 @@ class TextureSourceBasic
{
public:
virtual ~TextureSourceBasic() {}
virtual gfx::SourceSurface* GetSurface() = 0;
virtual gfx::SourceSurface* GetSurface(gfx::DrawTarget* aTarget) = 0;
};
} // namespace layers

View File

@ -32,11 +32,15 @@ X11TextureSourceBasic::GetFormat() const
}
SourceSurface*
X11TextureSourceBasic::GetSurface()
X11TextureSourceBasic::GetSurface(DrawTarget* aTarget)
{
if (!mSourceSurface) {
mSourceSurface =
Factory::CreateSourceSurfaceForCairoSurface(mSurface->CairoSurface(), GetFormat());
NativeSurface surf;
surf.mFormat = GetFormat();
surf.mType = NativeSurfaceType::CAIRO_SURFACE;
surf.mSurface = mSurface->CairoSurface();
surf.mSize = GetSize();
mSourceSurface = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
}
return mSourceSurface;
}

View File

@ -28,7 +28,7 @@ public:
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
virtual gfx::SourceSurface* GetSurface() MOZ_OVERRIDE;
virtual gfx::SourceSurface* GetSurface(gfx::DrawTarget* aTarget) MOZ_OVERRIDE;
virtual void DeallocateDeviceData() MOZ_OVERRIDE { }

View File

@ -412,6 +412,8 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
destinationSurface = mD2DSurface;
}
aRegion.SimplifyOutwardByArea(100 * 100);
MOZ_ASSERT(mDrawTarget);
nsRefPtr<gfxContext> context = new gfxContext(mDrawTarget);

View File

@ -97,6 +97,290 @@ void nsRegion::SimplifyOutward (uint32_t aMaxRects)
}
}
// compute the covered area difference between two rows.
// by iterating over both rows simultaneously and adding up
// the additional increase in area caused by extending each
// of the rectangles to the combined height of both rows
static uint32_t ComputeMergedAreaIncrease(pixman_box32_t *topRects,
pixman_box32_t *topRectsEnd,
pixman_box32_t *bottomRects,
pixman_box32_t *bottomRectsEnd)
{
uint32_t totalArea = 0;
struct pt {
int32_t x, y;
};
pt *i = (pt*)topRects;
pt *end_i = (pt*)topRectsEnd;
pt *j = (pt*)bottomRects;
pt *end_j = (pt*)bottomRectsEnd;
bool top = false;
bool bottom = false;
int cur_x = i->x;
bool top_next = top;
bool bottom_next = bottom;
//XXX: we could probably simplify this condition and perhaps move it into the loop below
if (j->x < cur_x) {
cur_x = j->x;
j++;
bottom_next = !bottom;
} else if (j->x == cur_x) {
i++;
top_next = !top;
bottom_next = !bottom;
j++;
} else {
top_next = !top;
i++;
}
int topRectsHeight = topRects->y2 - topRects->y1;
int bottomRectsHeight = bottomRects->y2 - bottomRects->y1;
int inbetweenHeight = bottomRects->y1 - topRects->y2;
int width = cur_x;
// top and bottom are the in-status to the left of cur_x
do {
if (top && !bottom) {
totalArea += (inbetweenHeight+bottomRectsHeight)*width;
} else if (bottom && !top) {
totalArea += (inbetweenHeight+topRectsHeight)*width;
} else if (bottom && top) {
totalArea += (inbetweenHeight)*width;
}
top = top_next;
bottom = bottom_next;
// find the next edge
if (i->x < j->x) {
top_next = !top;
width = i->x - cur_x;
cur_x = i->x;
i++;
} else if (j->x < i->x) {
bottom_next = !bottom;
width = j->x - cur_x;
cur_x = j->x;
j++;
} else { // i->x == j->x
top_next = !top;
bottom_next = !bottom;
width = i->x - cur_x;
cur_x = i->x;
i++;
j++;
}
} while (i < end_i && j < end_j);
// handle any remaining rects
while (i < end_i) {
width = i->x - cur_x;
cur_x = i->x;
i++;
if (top)
totalArea += (inbetweenHeight+bottomRectsHeight)*width;
top = !top;
}
while (j < end_j) {
width = j->x - cur_x;
cur_x = j->x;
j++;
if (bottom)
totalArea += (inbetweenHeight+topRectsHeight)*width;
bottom = !bottom;
}
return totalArea;
}
static pixman_box32_t *
CopyRow(pixman_box32_t *dest_it, pixman_box32_t *src_start, pixman_box32_t *src_end)
{
// XXX: std::copy
pixman_box32_t *src_it = src_start;
while (src_it < src_end) {
*dest_it++ = *src_it++;
}
return dest_it;
}
static pixman_box32_t *
MergeRects(pixman_box32_t *topRects, pixman_box32_t *topRectsEnd,
pixman_box32_t *bottomRects, pixman_box32_t *bottomRectsEnd,
pixman_box32_t *tmpRect)
{
struct pt {
int32_t x, y;
};
pixman_box32_t *rect;
// merge the two spans of rects
pt *i = (pt*)topRects;
pt *end_i = (pt*)topRectsEnd;
pt *j = (pt*)bottomRects;
pt *end_j = (pt*)bottomRectsEnd;
bool top;
bool bottom;
int cur_x = i->x;
int32_t y1 = topRects->y1;
int32_t y2 = bottomRects->y2;
if (j->x < cur_x) {
top = false;
bottom = true;
cur_x = j->x;
j++;
} else if (j->x == cur_x) {
top = true;
bottom = true;
i++;
j++;
} else {
top = true;
bottom = false;
i++;
}
rect = tmpRect;
bool started = false;
do {
if (started && !top && !bottom) {
rect->x2 = cur_x;
rect->y2 = y2;
rect++;
started = false;
} else if (!started) {
rect->x1 = cur_x;
rect->y1 = y1;
started = true;
}
if (i >= end_i || j >= end_j)
break;
if (i->x < j->x) {
top = !top;
cur_x = i->x;
i++;
} else if (j->x < i->x) {
bottom = !bottom;
cur_x = j->x;
j++;
} else { // i->x == j->x
top = !top;
bottom = !bottom;
cur_x = i->x;
i++;
j++;
}
} while (true);
// handle any remaining rects
while (i < end_i) {
top = !top;
cur_x = i->x;
i++;
if (!top) {
rect->x2 = cur_x;
rect->y2 = y2;
rect++;
} else {
rect->x1 = cur_x;
rect->y1 = y1;
}
}
while (j < end_j) {
bottom = !bottom;
cur_x = j->x;
j++;
if (!bottom) {
rect->x2 = cur_x;
rect->y2 = y2;
rect++;
} else {
rect->x1 = cur_x;
rect->y1 = y1;
}
}
return rect;
}
void nsRegion::SimplifyOutwardByArea(uint32_t aThreshold)
{
pixman_box32_t *boxes;
int n;
boxes = pixman_region32_rectangles(&mImpl, &n);
pixman_box32_t *end = boxes + n;
pixman_box32_t *topRectsEnd = boxes+1;
pixman_box32_t *topRects = boxes;
// we need some temporary storage for merging both rows of rectangles
nsAutoTArray<pixman_box32_t, 10> tmpStorage;
tmpStorage.SetCapacity(n);
pixman_box32_t *tmpRect = tmpStorage.Elements();
pixman_box32_t *destRect = boxes;
pixman_box32_t *rect = tmpRect;
// find the end of the first span of rectangles
while (topRectsEnd < end && topRectsEnd->y1 == topRects->y1) {
topRectsEnd++;
}
// if we only have one row we are done
if (topRectsEnd == end)
return;
pixman_box32_t *bottomRects = topRectsEnd;
pixman_box32_t *bottomRectsEnd = bottomRects+1;
do {
// find the end of the bottom span of rectangles
while (bottomRectsEnd < end && bottomRectsEnd->y1 == bottomRects->y1) {
bottomRectsEnd++;
}
uint32_t totalArea = ComputeMergedAreaIncrease(topRects, topRectsEnd,
bottomRects, bottomRectsEnd);
if (totalArea <= aThreshold) {
// merge the rects into tmpRect
rect = MergeRects(topRects, topRectsEnd, bottomRects, bottomRectsEnd, tmpRect);
// copy the merged rects back into the destination
topRectsEnd = CopyRow(destRect, tmpRect, rect);
topRects = destRect;
bottomRects = bottomRectsEnd;
destRect = topRects;
} else {
// copy the unmerged rects
destRect = CopyRow(destRect, topRects, topRectsEnd);
topRects = bottomRects;
topRectsEnd = bottomRectsEnd;
bottomRects = bottomRectsEnd;
if (bottomRectsEnd == end) {
// copy the last row when we are done
topRectsEnd = CopyRow(destRect, topRects, topRectsEnd);
}
}
} while (bottomRectsEnd != end);
uint32_t reducedCount = topRectsEnd - pixman_region32_rectangles(&this->mImpl, &n);
// pixman has a special representation for
// regions of 1 rectangle. So just use the
// bounds in that case
if (reducedCount > 1) {
// reach into pixman and lower the number
// of rects stored in data.
this->mImpl.data->numRects = reducedCount;
} else {
*this = GetBounds();
}
}
void nsRegion::SimplifyInward (uint32_t aMaxRects)
{
NS_ASSERTION(aMaxRects >= 1, "Invalid max rect count");

View File

@ -242,6 +242,13 @@ public:
* the same as for the current region.
*/
void SimplifyOutward (uint32_t aMaxRects);
/**
* Simplify the region by adding at most aThreshold area between spans of
* rects. The simplified region will be a superset of the original region.
* The simplified region's bounding box will be the same as for the current
* region.
*/
void SimplifyOutwardByArea(uint32_t aThreshold);
/**
* Make sure the region has at most aMaxRects by removing area from
* it if necessary. The simplified region will be a subset of the
@ -539,6 +546,10 @@ public:
{
mImpl.SimplifyOutward (aMaxRects);
}
void SimplifyOutwardByArea (uint32_t aThreshold)
{
mImpl.SimplifyOutwardByArea (aThreshold);
}
/**
* Make sure the region has at most aMaxRects by removing area from
* it if necessary. The simplified region will be a subset of the

View File

@ -171,3 +171,110 @@ TEST(Gfx, RegionScaleToInside) {
}
}
TEST(Gfx, RegionSimplify) {
{ // ensure simplify works on a single rect
nsRegion r(nsRect(0,100,200,100));
r.SimplifyOutwardByArea(100*100);
nsRegion result(nsRect(0,100,200,100));
EXPECT_TRUE(r.IsEqual(result)) <<
"regions not the same";
}
{ // the rectangles will be merged
nsRegion r(nsRect(0,100,200,100));
r.Or(r, nsRect(0,200,300,200));
r.SimplifyOutwardByArea(100*100);
nsRegion result(nsRect(0,100,300,300));
EXPECT_TRUE(r.IsEqual(result)) <<
"regions not merged";
}
{ // two rectangle on the first span
// one on the second
nsRegion r(nsRect(0,100,200,100));
r.Or(r, nsRect(0,200,300,200));
r.Or(r, nsRect(250,100,50,100));
EXPECT_TRUE(r.GetNumRects() == 3) <<
"wrong number of rects";
r.SimplifyOutwardByArea(100*100);
nsRegion result(nsRect(0,100,300,300));
EXPECT_TRUE(r.IsEqual(result)) <<
"regions not merged";
}
{ // the rectangles will be merged
nsRegion r(nsRect(0,100,200,100));
r.Or(r, nsRect(0,200,300,200));
r.Or(r, nsRect(250,100,50,100));
r.Sub(r, nsRect(200,200,40,200));
EXPECT_TRUE(r.GetNumRects() == 4) <<
"wrong number of rects";
r.SimplifyOutwardByArea(100*100);
nsRegion result(nsRect(0,100,300,300));
result.Sub(result, nsRect(200,100,40,300));
EXPECT_TRUE(r.IsEqual(result)) <<
"regions not merged";
}
{ // three spans of rectangles
nsRegion r(nsRect(0,100,200,100));
r.Or(r, nsRect(0,200,300,200));
r.Or(r, nsRect(250,100,50,50));
r.Sub(r, nsRect(200,200,40,200));
r.SimplifyOutwardByArea(100*100);
nsRegion result(nsRect(0,100,300,300));
result.Sub(result, nsRect(200,100,40,300));
EXPECT_TRUE(r.IsEqual(result)) <<
"regions not merged";
}
{ // three spans of rectangles and an unmerged rectangle
nsRegion r(nsRect(0,100,200,100));
r.Or(r, nsRect(0,200,300,200));
r.Or(r, nsRect(250,100,50,50));
r.Sub(r, nsRect(200,200,40,200));
r.Or(r, nsRect(250,900,150,50));
r.SimplifyOutwardByArea(100*100);
nsRegion result(nsRect(0,100,300,300));
result.Sub(result, nsRect(200,100,40,300));
result.Or(result, nsRect(250,900,150,50));
EXPECT_TRUE(r.IsEqual(result)) <<
"regions not merged";
}
{ // unmerged regions
nsRegion r(nsRect(0,100,200,100));
r.Or(r, nsRect(0,200,300,200));
r.SimplifyOutwardByArea(100);
nsRegion result(nsRect(0,100,200,100));
result.Or(result, nsRect(0,200,300,200));
EXPECT_TRUE(r.IsEqual(result)) <<
"regions not merged";
}
}

View File

@ -12,6 +12,7 @@
#include "mozilla/MemoryReporting.h"
#include "nsISupportsImpl.h"
#include "mozilla/gfx/2D.h"
#include "gfx2DGlue.h"
#include "gfxASurface.h"
#include "gfxContext.h"

View File

@ -39,365 +39,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/gfx/2D.h"
// rounding and truncation functions for a Freetype floating point number
// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
// part and low 6 bits for the fractional part.
#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
#define MOZ_FT_TRUNC(x) ((x) >> 6)
#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
#ifndef ANDROID // not needed on Android, we use the generic gfxFontGroup
/**
* gfxFT2FontGroup
*/
static PRLogModuleInfo *
GetFontLog()
{
static PRLogModuleInfo *sLog;
if (!sLog)
sLog = PR_NewLogModule("ft2fonts");
return sLog;
}
bool
gfxFT2FontGroup::FontCallback(const nsAString& fontName,
const nsACString& genericName,
bool aUseFontSet,
void *closure)
{
nsTArray<nsString> *sa = static_cast<nsTArray<nsString>*>(closure);
if (!fontName.IsEmpty() && !sa->Contains(fontName)) {
sa->AppendElement(fontName);
#ifdef DEBUG_pavlov
printf(" - %s\n", NS_ConvertUTF16toUTF8(fontName).get());
#endif
}
return true;
}
gfxFT2FontGroup::gfxFT2FontGroup(const nsAString& families,
const gfxFontStyle *aStyle,
gfxUserFontSet *aUserFontSet)
: gfxFontGroup(families, aStyle, aUserFontSet)
{
#ifdef DEBUG_pavlov
printf("Looking for %s\n", NS_ConvertUTF16toUTF8(families).get());
#endif
nsTArray<nsString> familyArray;
ForEachFont(FontCallback, &familyArray);
if (familyArray.Length() == 0) {
nsAutoString prefFamilies;
gfxToolkitPlatform::GetPlatform()->GetPrefFonts(aStyle->language, prefFamilies, nullptr);
if (!prefFamilies.IsEmpty()) {
ForEachFont(prefFamilies, aStyle->language, FontCallback, &familyArray);
}
}
if (familyArray.Length() == 0) {
#if defined(MOZ_WIDGET_QT) /* FIXME DFB */
printf("failde to find a font. sadface\n");
// We want to get rid of this entirely at some point, but first we need real lists of fonts.
QFont defaultFont;
QFontInfo fi (defaultFont);
familyArray.AppendElement(nsDependentString(static_cast<const char16_t *>(fi.family().utf16())));
#elif defined(MOZ_WIDGET_GTK)
FcResult result;
FcChar8 *family = nullptr;
FcPattern* pat = FcPatternCreate();
FcPattern *match = FcFontMatch(nullptr, pat, &result);
if (match)
FcPatternGetString(match, FC_FAMILY, 0, &family);
if (family)
familyArray.AppendElement(NS_ConvertUTF8toUTF16((char*)family));
#elif defined(XP_WIN)
HGDIOBJ hGDI = ::GetStockObject(SYSTEM_FONT);
LOGFONTW logFont;
if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont))
familyArray.AppendElement(nsDependentString(logFont.lfFaceName));
#elif defined(ANDROID)
familyArray.AppendElement(NS_LITERAL_STRING("Droid Sans"));
familyArray.AppendElement(NS_LITERAL_STRING("Roboto"));
#else
#error "Platform not supported"
#endif
}
for (uint32_t i = 0; i < familyArray.Length(); i++) {
nsRefPtr<gfxFT2Font> font = gfxFT2Font::GetOrMakeFont(familyArray[i], &mStyle);
if (font) {
mFonts.AppendElement(font);
}
}
NS_ASSERTION(mFonts.Length() > 0, "We need at least one font in a fontgroup");
}
gfxFT2FontGroup::~gfxFT2FontGroup()
{
}
gfxFontGroup *
gfxFT2FontGroup::Copy(const gfxFontStyle *aStyle)
{
return new gfxFT2FontGroup(mFamilies, aStyle, nullptr);
}
// Helper function to return the leading UTF-8 character in a char pointer
// as 32bit number. Also sets the length of the current character (i.e. the
// offset to the next one) in the second argument
uint32_t getUTF8CharAndNext(const uint8_t *aString, uint8_t *aLength)
{
*aLength = 1;
if (aString[0] < 0x80) { // normal 7bit ASCII char
return aString[0];
}
if ((aString[0] >> 5) == 6) { // two leading ones -> two bytes
*aLength = 2;
return ((aString[0] & 0x1F) << 6) + (aString[1] & 0x3F);
}
if ((aString[0] >> 4) == 14) { // three leading ones -> three bytes
*aLength = 3;
return ((aString[0] & 0x0F) << 12) + ((aString[1] & 0x3F) << 6) +
(aString[2] & 0x3F);
}
if ((aString[0] >> 4) == 15) { // four leading ones -> four bytes
*aLength = 4;
return ((aString[0] & 0x07) << 18) + ((aString[1] & 0x3F) << 12) +
((aString[2] & 0x3F) << 6) + (aString[3] & 0x3F);
}
return aString[0];
}
static bool
AddFontNameToArray(const nsAString& aName,
const nsACString& aGenericName,
bool aUseFontSet,
void *aClosure)
{
if (!aName.IsEmpty()) {
nsTArray<nsString> *list = static_cast<nsTArray<nsString> *>(aClosure);
if (list->IndexOf(aName) == list->NoIndex)
list->AppendElement(aName);
}
return true;
}
void
gfxFT2FontGroup::FamilyListToArrayList(const nsString& aFamilies,
nsIAtom *aLangGroup,
nsTArray<nsRefPtr<gfxFontEntry> > *aFontEntryList)
{
nsAutoTArray<nsString, 15> fonts;
ForEachFont(aFamilies, aLangGroup, AddFontNameToArray, &fonts);
uint32_t len = fonts.Length();
for (uint32_t i = 0; i < len; ++i) {
const nsString& str = fonts[i];
nsRefPtr<gfxFontEntry> fe = (gfxToolkitPlatform::GetPlatform()->FindFontEntry(str, mStyle));
aFontEntryList->AppendElement(fe);
}
}
void gfxFT2FontGroup::GetPrefFonts(nsIAtom *aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList)
{
NS_ASSERTION(aLangGroup, "aLangGroup is null");
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
nsAutoCString key;
aLangGroup->ToUTF8String(key);
key.Append("-");
key.AppendInt(GetStyle()->style);
key.Append("-");
key.AppendInt(GetStyle()->weight);
if (!platform->GetPrefFontEntries(key, &fonts)) {
nsString fontString;
platform->GetPrefFonts(aLangGroup, fontString);
if (fontString.IsEmpty())
return;
FamilyListToArrayList(fontString, aLangGroup, &fonts);
platform->SetPrefFontEntries(key, fonts);
}
aFontEntryList.AppendElements(fonts);
}
static int32_t GetCJKLangGroupIndex(const char *aLangGroup) {
int32_t i;
for (i = 0; i < COUNT_OF_CJK_LANG_GROUP; i++) {
if (!PL_strcasecmp(aLangGroup, sCJKLangGroup[i]))
return i;
}
return -1;
}
// this function assigns to the array passed in.
void gfxFT2FontGroup::GetCJKPrefFonts(nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList) {
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
nsAutoCString key("x-internal-cjk-");
key.AppendInt(mStyle.style);
key.Append("-");
key.AppendInt(mStyle.weight);
if (!platform->GetPrefFontEntries(key, &aFontEntryList)) {
NS_ENSURE_TRUE_VOID(Preferences::GetRootBranch());
// Add the CJK pref fonts from accept languages, the order should be same order
nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
if (!list.IsEmpty()) {
const char kComma = ',';
const char *p, *p_end;
list.BeginReading(p);
list.EndReading(p_end);
while (p < p_end) {
while (nsCRT::IsAsciiSpace(*p)) {
if (++p == p_end)
break;
}
if (p == p_end)
break;
const char *start = p;
while (++p != p_end && *p != kComma)
/* nothing */ ;
nsAutoCString lang(Substring(start, p));
lang.CompressWhitespace(false, true);
int32_t index = GetCJKLangGroupIndex(lang.get());
if (index >= 0) {
nsCOMPtr<nsIAtom> atom = do_GetAtom(sCJKLangGroup[index]);
GetPrefFonts(atom, aFontEntryList);
}
p++;
}
}
// Add the system locale
#ifdef XP_WIN
switch (::GetACP()) {
case 932: GetPrefFonts(nsGkAtoms::Japanese, aFontEntryList); break;
case 936: GetPrefFonts(nsGkAtoms::zh_cn, aFontEntryList); break;
case 949: GetPrefFonts(nsGkAtoms::ko, aFontEntryList); break;
// XXX Don't we need to append nsGkAtoms::zh_hk if the codepage is 950?
case 950: GetPrefFonts(nsGkAtoms::zh_tw, aFontEntryList); break;
}
#else
const char *ctype = setlocale(LC_CTYPE, nullptr);
if (ctype) {
if (!PL_strncasecmp(ctype, "ja", 2)) {
GetPrefFonts(nsGkAtoms::Japanese, aFontEntryList);
} else if (!PL_strncasecmp(ctype, "zh_cn", 5)) {
GetPrefFonts(nsGkAtoms::zh_cn, aFontEntryList);
} else if (!PL_strncasecmp(ctype, "zh_hk", 5)) {
GetPrefFonts(nsGkAtoms::zh_hk, aFontEntryList);
} else if (!PL_strncasecmp(ctype, "zh_tw", 5)) {
GetPrefFonts(nsGkAtoms::zh_tw, aFontEntryList);
} else if (!PL_strncasecmp(ctype, "ko", 2)) {
GetPrefFonts(nsGkAtoms::ko, aFontEntryList);
}
}
#endif
// last resort...
GetPrefFonts(nsGkAtoms::Japanese, aFontEntryList);
GetPrefFonts(nsGkAtoms::ko, aFontEntryList);
GetPrefFonts(nsGkAtoms::zh_cn, aFontEntryList);
GetPrefFonts(nsGkAtoms::zh_hk, aFontEntryList);
GetPrefFonts(nsGkAtoms::zh_tw, aFontEntryList);
platform->SetPrefFontEntries(key, aFontEntryList);
}
}
already_AddRefed<gfxFT2Font>
gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList, uint32_t aCh)
{
for (uint32_t i = 0; i < aFontEntryList.Length(); i++) {
gfxFontEntry *fe = aFontEntryList[i].get();
if (fe->HasCharacter(aCh)) {
nsRefPtr<gfxFT2Font> font =
gfxFT2Font::GetOrMakeFont(static_cast<FontEntry*>(fe), &mStyle);
return font.forget();
}
}
return nullptr;
}
already_AddRefed<gfxFont>
gfxFT2FontGroup::WhichPrefFontSupportsChar(uint32_t aCh)
{
if (aCh > 0xFFFF)
return nullptr;
nsRefPtr<gfxFT2Font> selectedFont;
// check out the style's language
nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
GetPrefFonts(mStyle.language, fonts);
selectedFont = WhichFontSupportsChar(fonts, aCh);
// otherwise search prefs
if (!selectedFont) {
uint32_t unicodeRange = FindCharUnicodeRange(aCh);
/* special case CJK */
if (unicodeRange == kRangeSetCJK) {
if (PR_LOG_TEST(GetFontLog(), PR_LOG_DEBUG)) {
PR_LOG(GetFontLog(), PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
}
nsAutoTArray<nsRefPtr<gfxFontEntry>, 15> fonts;
GetCJKPrefFonts(fonts);
selectedFont = WhichFontSupportsChar(fonts, aCh);
} else {
nsIAtom *langGroup = LangGroupFromUnicodeRange(unicodeRange);
if (langGroup) {
PR_LOG(GetFontLog(), PR_LOG_DEBUG, (" - Trying to find fonts for: %s", nsAtomCString(langGroup).get()));
nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
GetPrefFonts(langGroup, fonts);
selectedFont = WhichFontSupportsChar(fonts, aCh);
}
}
}
if (selectedFont) {
nsRefPtr<gfxFont> f = static_cast<gfxFont*>(selectedFont.get());
return f.forget();
}
return nullptr;
}
already_AddRefed<gfxFont>
gfxFT2FontGroup::WhichSystemFontSupportsChar(uint32_t aCh, int32_t aRunScript)
{
#if defined(XP_WIN) || defined(ANDROID)
FontEntry *fe = static_cast<FontEntry*>
(gfxPlatformFontList::PlatformFontList()->
SystemFindFontForChar(aCh, aRunScript, &mStyle));
if (fe) {
nsRefPtr<gfxFT2Font> f = gfxFT2Font::GetOrMakeFont(fe, &mStyle);
nsRefPtr<gfxFont> font = f.get();
return font.forget();
}
#else
nsRefPtr<gfxFont> selectedFont;
nsRefPtr<gfxFont> refFont = GetFontAt(0);
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
selectedFont = platform->FindFontForChar(aCh, refFont);
if (selectedFont)
return selectedFont.forget();
#endif
return nullptr;
}
#endif // !ANDROID
/**
* gfxFT2Font
*/

View File

@ -92,43 +92,5 @@ protected:
CharGlyphMap mCharGlyphCache;
};
#ifndef ANDROID // not needed on Android, uses the standard gfxFontGroup directly
class gfxFT2FontGroup : public gfxFontGroup {
public: // new functions
gfxFT2FontGroup (const nsAString& families,
const gfxFontStyle *aStyle,
gfxUserFontSet *aUserFontSet);
virtual ~gfxFT2FontGroup ();
protected: // from gfxFontGroup
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
protected: // new functions
static bool FontCallback (const nsAString & fontName,
const nsACString & genericName,
bool aUseFontSet,
void *closure);
bool mEnableKerning;
void GetPrefFonts(nsIAtom *aLangGroup,
nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList);
void GetCJKPrefFonts(nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList);
void FamilyListToArrayList(const nsString& aFamilies,
nsIAtom *aLangGroup,
nsTArray<nsRefPtr<gfxFontEntry> > *aFontEntryList);
already_AddRefed<gfxFT2Font> WhichFontSupportsChar(const nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList,
uint32_t aCh);
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh);
already_AddRefed<gfxFont>
WhichSystemFontSupportsChar(uint32_t aCh, int32_t aRunScript);
nsTArray<gfxTextRange> mRanges;
nsString mString;
};
#endif // !ANDROID
#endif /* GFX_FT2FONTS_H */

View File

@ -739,6 +739,7 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
surf.mFormat = format;
surf.mType = NativeSurfaceType::D3D10_TEXTURE;
surf.mSurface = static_cast<gfxD2DSurface*>(aSurface)->GetTexture();
surf.mSize = ToIntSize(aSurface->GetSize());
mozilla::gfx::DrawTarget *dt = static_cast<mozilla::gfx::DrawTarget*>(aSurface->GetData(&kDrawTarget));
if (dt) {
dt->Flush();
@ -753,6 +754,7 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
surf.mFormat = format;
surf.mType = NativeSurfaceType::CAIRO_SURFACE;
surf.mSurface = aSurface->CairoSurface();
surf.mSize = ToIntSize(aSurface->GetSize());
srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
if (srcBuffer) {

View File

@ -205,6 +205,7 @@ private:
DECL_GFX_PREF(Once, "layout.css.touch_action.enabled", TouchActionEnabled, bool, false);
DECL_GFX_PREF(Once, "layout.frame_rate", LayoutFrameRate, int32_t, -1);
DECL_GFX_PREF(Live, "layout.display-list.dump", LayoutDumpDisplayList, bool, false);
DECL_GFX_PREF(Once, "layout.paint_rects_separately", LayoutPaintRectsSeparately, bool, true);
DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false);

View File

@ -581,12 +581,13 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8;
if (method != eAlphaExtraction) {
if (drawTarget) {
// It doesn't matter if moz2DFormat doesn't exactly match the format
// of tempXlibSurface, since this DrawTarget just wraps the cairo
// drawing.
NativeSurface native;
native.mFormat = moz2DFormat;
native.mType = NativeSurfaceType::CAIRO_SURFACE;
native.mSurface = tempXlibSurface;
native.mSize = ToIntSize(size);
RefPtr<SourceSurface> sourceSurface =
Factory::CreateSourceSurfaceForCairoSurface(tempXlibSurface,
moz2DFormat);
drawTarget->CreateSourceSurfaceFromNativeSurface(native);
if (sourceSurface) {
drawTarget->DrawSurface(sourceSurface,
Rect(offset.x, offset.y, size.width, size.height),
@ -622,9 +623,13 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
gfxASurface* paintSurface = blackImage;
if (drawTarget) {
NativeSurface native;
native.mFormat = moz2DFormat;
native.mType = NativeSurfaceType::CAIRO_SURFACE;
native.mSurface = tempXlibSurface;
native.mSize = ToIntSize(size);
RefPtr<SourceSurface> sourceSurface =
Factory::CreateSourceSurfaceForCairoSurface(paintSurface->CairoSurface(),
moz2DFormat);
drawTarget->CreateSourceSurfaceFromNativeSurface(native);
if (sourceSurface) {
drawTarget->DrawSurface(sourceSurface,
Rect(offset.x, offset.y, size.width, size.height),

View File

@ -280,6 +280,11 @@ ProcessOrDeferMessage(HWND hwnd,
case WM_SYNCPAINT:
return 0;
// This message causes QuickTime to make re-entrant calls.
// Simply discarding it doesn't seem to hurt anything.
case WM_APP-1:
return 0;
default: {
if (uMsg && uMsg == mozilla::widget::sAppShellGeckoMsgId) {
// Widget's registered native event callback
@ -390,8 +395,10 @@ WindowIsDeferredWindow(HWND hWnd)
// Plugin windows that can trigger ipc calls in child:
// 'ShockwaveFlashFullScreen' - flash fullscreen window
// 'QTNSHIDDEN' - QuickTime
// 'AGFullScreenWinClass' - silverlight fullscreen window
if (className.EqualsLiteral("ShockwaveFlashFullScreen") ||
className.EqualsLiteral("QTNSHIDDEN") ||
className.EqualsLiteral("AGFullScreenWinClass")) {
return true;
}

View File

@ -421,7 +421,11 @@ struct JSClass {
// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
// previously allowed, but is now an ES5 violation and thus unsupported.
//
#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 31)
// JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
// the beginning of every global object's slots for use by the
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 3
#define JSCLASS_GLOBAL_SLOT_COUNT (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 31)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \

View File

@ -2088,8 +2088,13 @@ dnl ===============================================================
if test "$GNU_CC"; then
AC_DEFINE(HAVE_VISIBILITY_HIDDEN_ATTRIBUTE)
AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE)
case "${OS_TARGET}" in
Darwin|Android)
if test -n "$gonkdir"; then
visibility_target=Gonk
else
visibility_target=$OS_TARGET
fi
case "$visibility_target" in
Darwin|Gonk)
VISIBILITY_FLAGS='-fvisibility=hidden'
;;
*)

View File

@ -38,7 +38,7 @@ class FreeOp;
namespace gc {
struct Arena;
struct ArenaList;
class ArenaList;
struct ArenaHeader;
struct Chunk;

View File

@ -498,20 +498,6 @@ Arena::finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize)
return false;
}
/*
* Insert an arena into the list in appropriate position and update the cursor
* to ensure that any arena before the cursor is full.
*/
void ArenaList::insert(ArenaHeader *a)
{
JS_ASSERT(a);
JS_ASSERT_IF(!head, cursor == &head);
a->next = *cursor;
*cursor = a;
if (!a->hasFreeThings())
cursor = &a->next;
}
template<typename T>
static inline bool
FinalizeTypedArenas(FreeOp *fop,
@ -538,7 +524,7 @@ FinalizeTypedArenas(FreeOp *fop,
*src = aheader->next;
bool allClear = aheader->getArena()->finalize<T>(fop, thingKind, thingSize);
if (!allClear)
dest.insert(aheader);
dest.insertAtCursor(aheader);
else if (releaseArenas)
aheader->chunk()->releaseArena(aheader);
else
@ -548,13 +534,14 @@ FinalizeTypedArenas(FreeOp *fop,
if (budget.isOverBudget())
return false;
}
dest.deepCheck();
return true;
}
/*
* Finalize the list. On return al->cursor points to the first non-empty arena
* after the al->head.
* Finalize the list. On return, |al|'s cursor points to the first non-empty
* arena in the list (which may be null if all arenas are full).
*/
static bool
FinalizeArenas(FreeOp *fop,
@ -935,7 +922,7 @@ void
Chunk::recycleArena(ArenaHeader *aheader, ArenaList &dest, AllocKind thingKind)
{
aheader->getArena()->setAsFullyUnused(thingKind);
dest.insert(aheader);
dest.insertAtCursor(aheader);
}
void
@ -1484,13 +1471,13 @@ ArenaLists::allocateFromArenaInline(Zone *zone, AllocKind thingKind)
volatile uintptr_t *bfs = &backgroundFinalizeState[thingKind];
if (*bfs != BFS_DONE) {
/*
* We cannot search the arena list for free things while the
* background finalization runs and can modify head or cursor at any
* moment. So we always allocate a new arena in that case.
* We cannot search the arena list for free things while background
* finalization runs and can modify it at any moment. So we always
* allocate a new arena in that case.
*/
maybeLock.lock(zone->runtimeFromAnyThread());
if (*bfs == BFS_RUN) {
JS_ASSERT(!*al->cursor);
JS_ASSERT(al->isCursorAtEnd());
chunk = PickChunk(zone);
if (!chunk) {
/*
@ -1509,9 +1496,7 @@ ArenaLists::allocateFromArenaInline(Zone *zone, AllocKind thingKind)
#endif /* JS_THREADSAFE */
if (!chunk) {
if (ArenaHeader *aheader = *al->cursor) {
JS_ASSERT(aheader->hasFreeThings());
if (ArenaHeader *aheader = al->arenaAfterCursor()) {
/*
* Normally, the empty arenas are returned to the chunk
* and should not present on the list. In parallel
@ -1519,7 +1504,8 @@ ArenaLists::allocateFromArenaInline(Zone *zone, AllocKind thingKind)
* list to avoid synchronizing on the chunk.
*/
JS_ASSERT(!aheader->isEmpty() || InParallelSection());
al->cursor = &aheader->next;
al->moveCursorPast(aheader);
/*
* Move the free span stored in the arena to the free list and
@ -1551,11 +1537,11 @@ ArenaLists::allocateFromArenaInline(Zone *zone, AllocKind thingKind)
* as full as its single free span is moved to the free lits, and insert
* it to the list as a fully allocated arena.
*
* We add the arena before the the head, not after the tail pointed by the
* cursor, so after the GC the most recently added arena will be used first
* for allocations improving cache locality.
* We add the arena before the the head, so that after the GC the most
* recently added arena will be used first for allocations. This improves
* cache locality.
*/
JS_ASSERT(!*al->cursor);
JS_ASSERT(al->isCursorAtEnd());
ArenaHeader *aheader = chunk->allocateArena(zone, thingKind);
if (!aheader)
return nullptr;
@ -1568,12 +1554,7 @@ ArenaLists::allocateFromArenaInline(Zone *zone, AllocKind thingKind)
PushArenaAllocatedDuringSweep(zone->runtimeFromMainThread(), aheader);
}
}
aheader->next = al->head;
if (!al->head) {
JS_ASSERT(al->cursor == &al->head);
al->cursor = &aheader->next;
}
al->head = aheader;
al->insertAtStart(aheader);
/* See comments before allocateFromNewArena about this assert. */
JS_ASSERT(!aheader->hasFreeThings());
@ -1604,7 +1585,7 @@ ArenaLists::wipeDuringParallelExecution(JSRuntime *rt)
// that'd be bad.
for (unsigned i = 0; i < FINALIZE_LAST; i++) {
AllocKind thingKind = AllocKind(i);
if (!IsBackgroundFinalized(thingKind) && arenaLists[thingKind].head)
if (!IsBackgroundFinalized(thingKind) && !arenaLists[thingKind].isEmpty())
return;
}
@ -1617,7 +1598,7 @@ ArenaLists::wipeDuringParallelExecution(JSRuntime *rt)
if (!IsBackgroundFinalized(thingKind))
continue;
if (arenaLists[i].head) {
if (!arenaLists[i].isEmpty()) {
purge(thingKind);
forceFinalizeNow(&fop, thingKind);
}
@ -1636,7 +1617,7 @@ ArenaLists::forceFinalizeNow(FreeOp *fop, AllocKind thingKind)
{
JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE);
ArenaHeader *arenas = arenaLists[thingKind].head;
ArenaHeader *arenas = arenaLists[thingKind].head();
arenaLists[thingKind].clear();
SliceBudget budget;
@ -1651,7 +1632,7 @@ ArenaLists::queueForForegroundSweep(FreeOp *fop, AllocKind thingKind)
JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE);
JS_ASSERT(!arenaListsToSweep[thingKind]);
arenaListsToSweep[thingKind] = arenaLists[thingKind].head;
arenaListsToSweep[thingKind] = arenaLists[thingKind].head();
arenaLists[thingKind].clear();
}
@ -1665,9 +1646,8 @@ ArenaLists::queueForBackgroundSweep(FreeOp *fop, AllocKind thingKind)
#endif
ArenaList *al = &arenaLists[thingKind];
if (!al->head) {
if (al->isEmpty()) {
JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE);
JS_ASSERT(al->cursor == &al->head);
return;
}
@ -1678,7 +1658,7 @@ ArenaLists::queueForBackgroundSweep(FreeOp *fop, AllocKind thingKind)
JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE ||
backgroundFinalizeState[thingKind] == BFS_JUST_FINISHED);
arenaListsToSweep[thingKind] = al->head;
arenaListsToSweep[thingKind] = al->head();
al->clear();
backgroundFinalizeState[thingKind] = BFS_RUN;
}
@ -1695,23 +1675,18 @@ ArenaLists::backgroundFinalize(FreeOp *fop, ArenaHeader *listHead, bool onBackgr
FinalizeArenas(fop, &listHead, finalized, thingKind, budget);
JS_ASSERT(!listHead);
/*
* After we finish the finalization al->cursor must point to the end of
* the head list as we emptied the list before the background finalization
* and the allocation adds new arenas before the cursor.
*/
// When arenas are queued for background finalization, all
// arenas are moved to arenaListsToSweep[], leaving the arenaLists[] empty.
// Then, if new arenas are allocated before background finalization
// finishes they are always added to the front of the list. Therefore,
// at this point, |al|'s cursor will always be at the end of its list.
ArenaLists *lists = &zone->allocator.arenas;
ArenaList *al = &lists->arenaLists[thingKind];
AutoLockGC lock(fop->runtime());
JS_ASSERT(lists->backgroundFinalizeState[thingKind] == BFS_RUN);
JS_ASSERT(!*al->cursor);
if (finalized.head) {
*al->cursor = finalized.head;
if (finalized.cursor != &finalized.head)
al->cursor = finalized.cursor;
}
al->appendToListWithCursorAtEnd(finalized);
/*
* We must set the state to BFS_JUST_FINISHED if we are running on the
@ -1722,7 +1697,7 @@ ArenaLists::backgroundFinalize(FreeOp *fop, ArenaHeader *listHead, bool onBackgr
* allocating new arenas from the chunks we can set the state to BFS_DONE if
* we have released all finalized arenas back to their chunks.
*/
if (onBackgroundThread && finalized.head)
if (onBackgroundThread && !finalized.isEmpty())
lists->backgroundFinalizeState[thingKind] = BFS_JUST_FINISHED;
else
lists->backgroundFinalizeState[thingKind] = BFS_DONE;
@ -5335,11 +5310,12 @@ ArenaLists::adoptArenas(JSRuntime *rt, ArenaLists *fromArenaLists)
#endif
ArenaList *fromList = &fromArenaLists->arenaLists[thingKind];
ArenaList *toList = &arenaLists[thingKind];
while (fromList->head != nullptr) {
// Remove entry from |fromList|
ArenaHeader *fromHeader = fromList->head;
fromList->head = fromHeader->next;
fromHeader->next = nullptr;
fromList->deepCheck();
toList->deepCheck();
ArenaHeader *next;
for (ArenaHeader *fromHeader = fromList->head(); fromHeader; fromHeader = next) {
// Copy fromHeader->next before releasing/reinserting.
next = fromHeader->next;
// During parallel execution, we sometimes keep empty arenas
// on the lists rather than sending them back to the chunk.
@ -5348,9 +5324,10 @@ ArenaLists::adoptArenas(JSRuntime *rt, ArenaLists *fromArenaLists)
if (fromHeader->isEmpty())
fromHeader->chunk()->releaseArena(fromHeader);
else
toList->insert(fromHeader);
toList->insertAtCursor(fromHeader);
}
fromList->cursor = &fromList->head;
fromList->clear();
toList->deepCheck();
}
}
@ -5359,10 +5336,7 @@ ArenaLists::containsArena(JSRuntime *rt, ArenaHeader *needle)
{
AutoLockGC lock(rt);
size_t allocKind = needle->getAllocKind();
for (ArenaHeader *aheader = arenaLists[allocKind].head;
aheader != nullptr;
aheader = aheader->next)
{
for (ArenaHeader *aheader = arenaLists[allocKind].head(); aheader; aheader = aheader->next) {
if (aheader == needle)
return true;
}

View File

@ -365,30 +365,165 @@ GetGCKindSlots(AllocKind thingKind, const Class *clasp)
}
/*
* ArenaList::head points to the start of the list. Normally cursor points
* to the first arena in the list with some free things and all arenas
* before cursor are fully allocated. However, as the arena currently being
* allocated from is considered full while its list of free spans is moved
* into the freeList, during the GC or cell enumeration, when an
* unallocated freeList is moved back to the arena, we can see an arena
* with some free cells before the cursor. The cursor is an indirect
* pointer to allow for efficient list insertion at the cursor point and
* other list manipulations.
* Arena lists have a head and a cursor. The cursor conceptually lies on arena
* boundaries, i.e. before the first arena, between two arenas, or after the
* last arena.
*
* Normally the arena following the cursor is the first arena in the list with
* some free things and all arenas before the cursor are fully allocated. (And
* if the cursor is at the end of the list, then all the arenas are full.)
*
* However, the arena currently being allocated from is considered full while
* its list of free spans is moved into the freeList. Therefore, during GC or
* cell enumeration, when an unallocated freeList is moved back to the arena,
* we can see an arena with some free cells before the cursor.
*
* Arenas following the cursor should not be full.
*/
struct ArenaList {
ArenaHeader *head;
ArenaHeader **cursor;
class ArenaList {
// The cursor is implemented via an indirect pointer, |cursorp_|, to allow
// for efficient list insertion at the cursor point and other list
// manipulations.
//
// - If the list is empty: |head| is null, |cursorp_| points to |head|, and
// therefore |*cursorp_| is null.
//
// - If the list is not empty: |head| is non-null, and...
//
// - If the cursor is at the start of the list: |cursorp_| points to
// |head|, and therefore |*cursorp_| points to the first arena.
//
// - If cursor is at the end of the list: |cursorp_| points to the |next|
// field of the last arena, and therefore |*cursorp_| is null.
//
// - If the cursor is at neither the start nor the end of the list:
// |cursorp_| points to the |next| field of the arena preceding the
// cursor, and therefore |*cursorp_| points to the arena following the
// cursor.
//
// |cursorp_| is never null.
//
ArenaHeader *head_;
ArenaHeader **cursorp_;
public:
ArenaList() {
clear();
}
void clear() {
head = nullptr;
cursor = &head;
// This does checking just of |head_| and |cursorp_|.
void check() const {
#ifdef DEBUG
// If the list is empty, it must have this form.
JS_ASSERT_IF(!head_, cursorp_ == &head_);
// If there's an arena following the cursor, it must not be full.
ArenaHeader *cursor = *cursorp_;
JS_ASSERT_IF(cursor, cursor->hasFreeThings());
#endif
}
void insert(ArenaHeader *arena);
// This does checking involving all the arenas in the list.
void deepCheck() const {
#ifdef DEBUG
check();
// All full arenas must precede all non-full arenas.
//
// XXX: this is currently commented out because it fails moderately
// often. I'm not sure if this is because (a) it's not true that all
// full arenas must precede all non-full arenas, or (b) we have some
// defective list-handling code.
//
// bool havePassedFullArenas = false;
// for (ArenaHeader *aheader = head_; aheader; aheader = aheader->next) {
// if (havePassedFullArenas) {
// JS_ASSERT(aheader->hasFreeThings());
// } else if (aheader->hasFreeThings()) {
// havePassedFullArenas = true;
// }
// }
#endif
}
void clear() {
head_ = nullptr;
cursorp_ = &head_;
check();
}
bool isEmpty() const {
check();
return !head_;
}
// This returns nullptr if the list is empty.
ArenaHeader *head() const {
check();
return head_;
}
bool isCursorAtEnd() const {
check();
return !*cursorp_;
}
// This can return nullptr.
ArenaHeader *arenaAfterCursor() const {
check();
return *cursorp_;
}
// This moves the cursor past |aheader|. |aheader| must be an arena within
// this list.
void moveCursorPast(ArenaHeader *aheader) {
cursorp_ = &aheader->next;
check();
}
// This does two things.
// - Inserts |a| at the cursor.
// - Leaves the cursor sitting just before |a|, if |a| is not full, or just
// after |a|, if |a| is full.
//
void insertAtCursor(ArenaHeader *a) {
check();
a->next = *cursorp_;
*cursorp_ = a;
// At this point, the cursor is sitting before |a|. Move it after |a|
// if necessary.
if (!a->hasFreeThings())
cursorp_ = &a->next;
check();
}
// This inserts |a| at the start of the list, and doesn't change the
// cursor.
void insertAtStart(ArenaHeader *a) {
check();
a->next = head_;
if (isEmpty())
cursorp_ = &a->next; // The cursor remains null.
head_ = a;
check();
}
// Appends |list|. |this|'s cursor must be at the end.
void appendToListWithCursorAtEnd(ArenaList &other) {
JS_ASSERT(isCursorAtEnd());
deepCheck();
other.deepCheck();
if (!other.isEmpty()) {
// Because |this|'s cursor is at the end, |cursorp_| points to the
// list-ending null. So this assignment appends |other| to |this|.
*cursorp_ = other.head_;
// If |other|'s cursor isn't at the start of the list, then update
// |this|'s cursor accordingly.
if (other.cursorp_ != &other.head_)
cursorp_ = other.cursorp_;
}
deepCheck();
}
};
class ArenaLists
@ -408,7 +543,7 @@ class ArenaLists
/*
* The background finalization adds the finalized arenas to the list at
* the *cursor position. backgroundFinalizeState controls the interaction
* the cursor position. backgroundFinalizeState controls the interaction
* between the GC lock and the access to the list from the allocation
* thread.
*
@ -420,7 +555,7 @@ class ArenaLists
* lock. The former indicates that the finalization still runs. The latter
* signals that finalization just added to the list finalized arenas. In
* that case the lock effectively serves as a read barrier to ensure that
* the allocation thread see all the writes done during finalization.
* the allocation thread sees all the writes done during finalization.
*/
enum BackgroundFinalizeState {
BFS_DONE,
@ -455,9 +590,10 @@ class ArenaLists
* the background finalization is disabled.
*/
JS_ASSERT(backgroundFinalizeState[i] == BFS_DONE);
ArenaHeader **headp = &arenaLists[i].head;
while (ArenaHeader *aheader = *headp) {
*headp = aheader->next;
ArenaHeader *next;
for (ArenaHeader *aheader = arenaLists[i].head(); aheader; aheader = next) {
// Copy aheader->next before releasing.
next = aheader->next;
aheader->chunk()->releaseArena(aheader);
}
}
@ -473,7 +609,7 @@ class ArenaLists
}
ArenaHeader *getFirstArena(AllocKind thingKind) const {
return arenaLists[thingKind].head;
return arenaLists[thingKind].head();
}
ArenaHeader *getFirstArenaToSweep(AllocKind thingKind) const {
@ -488,22 +624,18 @@ class ArenaLists
*/
if (backgroundFinalizeState[i] != BFS_DONE)
return false;
if (arenaLists[i].head)
if (!arenaLists[i].isEmpty())
return false;
}
return true;
}
bool arenasAreFull(AllocKind thingKind) const {
return !*arenaLists[thingKind].cursor;
}
void unmarkAll() {
for (size_t i = 0; i != FINALIZE_LIMIT; ++i) {
/* The background finalization must have stopped at this point. */
JS_ASSERT(backgroundFinalizeState[i] == BFS_DONE ||
backgroundFinalizeState[i] == BFS_JUST_FINISHED);
for (ArenaHeader *aheader = arenaLists[i].head; aheader; aheader = aheader->next) {
for (ArenaHeader *aheader = arenaLists[i].head(); aheader; aheader = aheader->next) {
uintptr_t *word = aheader->chunk()->bitmap.arenaBits(aheader);
memset(word, 0, ArenaBitmapWords * sizeof(uintptr_t));
}

View File

@ -1802,26 +1802,28 @@ ScriptedDirectProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject prox
cx->names().getOwnPropertyNames);
}
// Proxy.[[Delete]](P, Throw)
// ES6 (5 April 2014) Proxy.[[Delete]](P)
bool
ScriptedDirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
{
// step 1
// step 2
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
// TODO: step 3: Implement revocation semantics
// step 4
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 3
// step 5
RootedValue trap(cx);
if (!JSObject::getProperty(cx, handler, handler, cx->names().deleteProperty, &trap))
return false;
// step 4
// step 7
if (trap.isUndefined())
return DirectProxyHandler::delete_(cx, proxy, id, bp);
// step 5
// step 8
RootedValue value(cx);
if (!IdToExposableValue(cx, id, &value))
return false;
@ -1833,24 +1835,26 @@ ScriptedDirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId
if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult))
return false;
// step 6-7
// step 9
if (ToBoolean(trapResult)) {
// step 12
Rooted<PropertyDescriptor> desc(cx);
if (!GetOwnPropertyDescriptor(cx, target, id, &desc))
return false;
// step 14-15
if (desc.object() && desc.isPermanent()) {
RootedValue v(cx, IdToValue(id));
js_ReportValueError(cx, JSMSG_CANT_DELETE, JSDVG_IGNORE_STACK, v, js::NullPtr());
return false;
}
// step 16
*bp = true;
return true;
}
// step 8
// FIXME: API does not include a Throw parameter
// step 11
*bp = false;
return true;
}

View File

@ -69,7 +69,7 @@ class TypedObjectModuleObject;
class GlobalObject : public JSObject
{
/* Count of slots set aside for application use. */
static const unsigned APPLICATION_SLOTS = 3;
static const unsigned APPLICATION_SLOTS = JSCLASS_GLOBAL_APPLICATION_SLOTS;
/*
* Count of slots to store built-in constructors, prototypes, and initial

View File

@ -26,7 +26,7 @@
#include "GeckoProfiler.h"
#include "mozilla/gfx/Tools.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Preferences.h"
#include "gfxPrefs.h"
#include <algorithm>
@ -3705,14 +3705,7 @@ FrameLayerBuilder::PaintItems(nsTArray<ClippedDisplayItem>& aItems,
*/
static bool ShouldDrawRectsSeparately(gfxContext* aContext, DrawRegionClip aClip)
{
static bool sPaintRectsSeparately;
static bool sPaintRectsSeparatelyPrefCached = false;
if (!sPaintRectsSeparatelyPrefCached) {
mozilla::Preferences::AddBoolVarCache(&sPaintRectsSeparately, "layout.paint_rects_separately", false);
sPaintRectsSeparatelyPrefCached = true;
}
if (!sPaintRectsSeparately ||
if (!gfxPrefs::LayoutPaintRectsSeparately() ||
aContext->IsCairo() ||
aClip == DrawRegionClip::CLIP_NONE) {
return false;

View File

@ -73,7 +73,6 @@ static void AddTransformFunctions(nsCSSValueList* aList,
nsStyleContext* aContext,
nsPresContext* aPresContext,
nsRect& aBounds,
float aAppUnitsPerPixel,
InfallibleTArray<TransformFunction>& aFunctions)
{
if (aList->mValue.GetUnit() == eCSSUnit_None) {
@ -158,7 +157,7 @@ static void AddTransformFunctions(nsCSSValueList* aList,
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
aBounds.Width(), aAppUnitsPerPixel);
aBounds.Width());
aFunctions.AppendElement(Translation(x, 0, 0));
break;
}
@ -166,7 +165,7 @@ static void AddTransformFunctions(nsCSSValueList* aList,
{
double y = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
aBounds.Height(), aAppUnitsPerPixel);
aBounds.Height());
aFunctions.AppendElement(Translation(0, y, 0));
break;
}
@ -174,7 +173,7 @@ static void AddTransformFunctions(nsCSSValueList* aList,
{
double z = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
0, aAppUnitsPerPixel);
0);
aFunctions.AppendElement(Translation(0, 0, z));
break;
}
@ -182,13 +181,13 @@ static void AddTransformFunctions(nsCSSValueList* aList,
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
aBounds.Width(), aAppUnitsPerPixel);
aBounds.Width());
// translate(x) is shorthand for translate(x, 0)
double y = 0;
if (array->Count() == 3) {
y = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(2), aContext, aPresContext, canStoreInRuleTree,
aBounds.Height(), aAppUnitsPerPixel);
aBounds.Height());
}
aFunctions.AppendElement(Translation(x, y, 0));
break;
@ -197,13 +196,13 @@ static void AddTransformFunctions(nsCSSValueList* aList,
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
aBounds.Width(), aAppUnitsPerPixel);
aBounds.Width());
double y = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(2), aContext, aPresContext, canStoreInRuleTree,
aBounds.Height(), aAppUnitsPerPixel);
aBounds.Height());
double z = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(3), aContext, aPresContext, canStoreInRuleTree,
0, aAppUnitsPerPixel);
0);
aFunctions.AppendElement(Translation(x, y, z));
break;
@ -282,8 +281,7 @@ static void AddTransformFunctions(nsCSSValueList* aList,
aContext,
aPresContext,
canStoreInRuleTree,
aBounds,
aAppUnitsPerPixel);
aBounds);
gfx::Matrix4x4 transform;
gfx::ToMatrix4x4(matrix, transform);
aFunctions.AppendElement(TransformMatrix(transform));
@ -322,8 +320,6 @@ AddAnimationForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
nsStyleContext* styleContext = aFrame->StyleContext();
nsPresContext* presContext = aFrame->PresContext();
nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(aFrame);
// all data passed directly to the compositor should be in css pixels
float scale = nsDeviceContext::AppUnitsPerCSSPixel();
mozilla::layers::Animation* animation =
aPending ?
@ -354,11 +350,11 @@ AddAnimationForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
animSegment->endState() = InfallibleTArray<TransformFunction>();
nsCSSValueSharedList* list = segment->mFromValue.GetCSSValueSharedListValue();
AddTransformFunctions(list->mHead, styleContext, presContext, bounds, scale,
AddTransformFunctions(list->mHead, styleContext, presContext, bounds,
animSegment->startState().get_ArrayOfTransformFunction());
list = segment->mToValue.GetCSSValueSharedListValue();
AddTransformFunctions(list->mHead, styleContext, presContext, bounds, scale,
AddTransformFunctions(list->mHead, styleContext, presContext, bounds,
animSegment->endState().get_ArrayOfTransformFunction());
} else if (aProperty == eCSSProperty_opacity) {
animSegment->startState() = segment->mFromValue.GetFloatValue();

View File

@ -41,8 +41,7 @@ ProcessTranslatePart(const nsCSSValue& aValue,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nscoord aSize,
float aAppUnitsPerMatrixUnit)
nscoord aSize)
{
nscoord offset = 0;
float percent = 0.0f;
@ -60,8 +59,7 @@ ProcessTranslatePart(const nsCSSValue& aValue,
// Raw numbers are treated as being pixels.
//
// Don't convert to aValue to AppUnits here to avoid precision issues.
return aValue.GetFloatValue() *
(float(nsPresContext::AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit);
return aValue.GetFloatValue();
} else if (aValue.IsCalcUnit()) {
nsRuleNode::ComputedCalc result =
nsRuleNode::SpecifiedCalcToComputedCalc(aValue, aContext, aPresContext,
@ -73,8 +71,8 @@ ProcessTranslatePart(const nsCSSValue& aValue,
aCanStoreInRuleTree);
}
return (percent * NSAppUnitsToFloatPixels(aSize, aAppUnitsPerMatrixUnit)) +
NSAppUnitsToFloatPixels(offset, aAppUnitsPerMatrixUnit);
return (percent * NSAppUnitsToFloatPixels(aSize, nsPresContext::AppUnitsPerCSSPixel())) +
NSAppUnitsToFloatPixels(offset, nsPresContext::AppUnitsPerCSSPixel());
}
/**
@ -90,7 +88,7 @@ ProcessMatrix(gfx3DMatrix& aMatrix,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
nsRect& aBounds)
{
NS_PRECONDITION(aData->Count() == 7, "Invalid array!");
@ -109,10 +107,10 @@ ProcessMatrix(gfx3DMatrix& aMatrix,
*/
result.x0 = ProcessTranslatePart(aData->Item(5),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Width(), aAppUnitsPerMatrixUnit);
aBounds.Width());
result.y0 = ProcessTranslatePart(aData->Item(6),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Height(), aAppUnitsPerMatrixUnit);
aBounds.Height());
aMatrix.PreMultiply(result);
}
@ -123,7 +121,7 @@ ProcessMatrix3D(gfx3DMatrix& aMatrix,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
nsRect& aBounds)
{
NS_PRECONDITION(aData->Count() == 17, "Invalid array!");
@ -145,13 +143,13 @@ ProcessMatrix3D(gfx3DMatrix& aMatrix,
temp._41 = ProcessTranslatePart(aData->Item(13),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Width(), aAppUnitsPerMatrixUnit);
aBounds.Width());
temp._42 = ProcessTranslatePart(aData->Item(14),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Height(), aAppUnitsPerMatrixUnit);
aBounds.Height());
temp._43 = ProcessTranslatePart(aData->Item(15),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Height(), aAppUnitsPerMatrixUnit);
aBounds.Height());
aMatrix.PreMultiply(temp);
}
@ -163,7 +161,7 @@ ProcessInterpolateMatrix(gfx3DMatrix& aMatrix,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
nsRect& aBounds)
{
NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
@ -172,13 +170,13 @@ ProcessInterpolateMatrix(gfx3DMatrix& aMatrix,
matrix1 = nsStyleTransformMatrix::ReadTransforms(aData->Item(1).GetListValue(),
aContext, aPresContext,
aCanStoreInRuleTree,
aBounds, aAppUnitsPerMatrixUnit);
aBounds, nsPresContext::AppUnitsPerCSSPixel());
}
if (aData->Item(2).GetUnit() == eCSSUnit_List) {
matrix2 = ReadTransforms(aData->Item(2).GetListValue(),
aContext, aPresContext,
aCanStoreInRuleTree,
aBounds, aAppUnitsPerMatrixUnit);
aBounds, nsPresContext::AppUnitsPerCSSPixel());
}
double progress = aData->Item(3).GetPercentValue();
@ -192,7 +190,7 @@ ProcessTranslateX(gfx3DMatrix& aMatrix,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
nsRect& aBounds)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
@ -200,7 +198,7 @@ ProcessTranslateX(gfx3DMatrix& aMatrix,
temp.x = ProcessTranslatePart(aData->Item(1),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Width(), aAppUnitsPerMatrixUnit);
aBounds.Width());
aMatrix.Translate(temp);
}
@ -211,7 +209,7 @@ ProcessTranslateY(gfx3DMatrix& aMatrix,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
nsRect& aBounds)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
@ -219,7 +217,7 @@ ProcessTranslateY(gfx3DMatrix& aMatrix,
temp.y = ProcessTranslatePart(aData->Item(1),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Height(), aAppUnitsPerMatrixUnit);
aBounds.Height());
aMatrix.Translate(temp);
}
@ -228,16 +226,14 @@ ProcessTranslateZ(gfx3DMatrix& aMatrix,
const nsCSSValue::Array* aData,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
float aAppUnitsPerMatrixUnit)
bool& aCanStoreInRuleTree)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
gfxPoint3D temp;
temp.z = ProcessTranslatePart(aData->Item(1),
aContext, aPresContext, aCanStoreInRuleTree,
0, aAppUnitsPerMatrixUnit);
temp.z = ProcessTranslatePart(aData->Item(1), aContext,
aPresContext, aCanStoreInRuleTree, 0);
aMatrix.Translate(temp);
}
@ -248,7 +244,7 @@ ProcessTranslate(gfx3DMatrix& aMatrix,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
nsRect& aBounds)
{
NS_PRECONDITION(aData->Count() == 2 || aData->Count() == 3, "Invalid array!");
@ -256,13 +252,13 @@ ProcessTranslate(gfx3DMatrix& aMatrix,
temp.x = ProcessTranslatePart(aData->Item(1),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Width(), aAppUnitsPerMatrixUnit);
aBounds.Width());
/* If we read in a Y component, set it appropriately */
if (aData->Count() == 3) {
temp.y = ProcessTranslatePart(aData->Item(2),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Height(), aAppUnitsPerMatrixUnit);
aBounds.Height());
}
aMatrix.Translate(temp);
}
@ -273,7 +269,7 @@ ProcessTranslate3D(gfx3DMatrix& aMatrix,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
nsRect& aBounds)
{
NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
@ -281,15 +277,15 @@ ProcessTranslate3D(gfx3DMatrix& aMatrix,
temp.x = ProcessTranslatePart(aData->Item(1),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Width(), aAppUnitsPerMatrixUnit);
aBounds.Width());
temp.y = ProcessTranslatePart(aData->Item(2),
aContext, aPresContext, aCanStoreInRuleTree,
aBounds.Height(), aAppUnitsPerMatrixUnit);
aBounds.Height());
temp.z = ProcessTranslatePart(aData->Item(3),
aContext, aPresContext, aCanStoreInRuleTree,
0, aAppUnitsPerMatrixUnit);
0);
aMatrix.Translate(temp);
}
@ -480,14 +476,13 @@ ProcessPerspective(gfx3DMatrix& aMatrix,
const nsCSSValue::Array* aData,
nsStyleContext *aContext,
nsPresContext *aPresContext,
bool &aCanStoreInRuleTree,
float aAppUnitsPerMatrixUnit)
bool &aCanStoreInRuleTree)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
float depth = ProcessTranslatePart(aData->Item(1), aContext,
aPresContext, aCanStoreInRuleTree,
0, aAppUnitsPerMatrixUnit);
0);
aMatrix.Perspective(depth);
}
@ -502,8 +497,7 @@ MatrixForTransformFunction(gfx3DMatrix& aMatrix,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds,
float aAppUnitsPerMatrixUnit)
nsRect& aBounds)
{
NS_PRECONDITION(aData, "Why did you want to get data from a null array?");
// It's OK if aContext and aPresContext are null if the caller already
@ -515,23 +509,23 @@ MatrixForTransformFunction(gfx3DMatrix& aMatrix,
switch (TransformFunctionOf(aData)) {
case eCSSKeyword_translatex:
ProcessTranslateX(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree, aBounds);
break;
case eCSSKeyword_translatey:
ProcessTranslateY(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree, aBounds);
break;
case eCSSKeyword_translatez:
ProcessTranslateZ(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree);
break;
case eCSSKeyword_translate:
ProcessTranslate(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree, aBounds);
break;
case eCSSKeyword_translate3d:
ProcessTranslate3D(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree, aBounds);
break;
case eCSSKeyword_scalex:
ProcessScaleX(aMatrix, aData);
@ -572,19 +566,19 @@ MatrixForTransformFunction(gfx3DMatrix& aMatrix,
break;
case eCSSKeyword_matrix:
ProcessMatrix(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree, aBounds);
break;
case eCSSKeyword_matrix3d:
ProcessMatrix3D(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree, aBounds);
break;
case eCSSKeyword_interpolatematrix:
ProcessInterpolateMatrix(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree, aBounds);
break;
case eCSSKeyword_perspective:
ProcessPerspective(aMatrix, aData, aContext, aPresContext,
aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
aCanStoreInRuleTree);
break;
default:
NS_NOTREACHED("Unknown transform function!");
@ -621,10 +615,13 @@ ReadTransforms(const nsCSSValueList* aList,
/* Read in a single transform matrix. */
MatrixForTransformFunction(result, currElem.GetArrayValue(), aContext,
aPresContext, aCanStoreInRuleTree,
aBounds, aAppUnitsPerMatrixUnit);
aPresContext, aCanStoreInRuleTree, aBounds);
}
float scale = float(nsPresContext::AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit;
result.Scale(1/scale, 1/scale, 1/scale);
result.ScalePost(scale, scale, scale);
return result;
}

View File

@ -32,8 +32,7 @@ namespace nsStyleTransformMatrix {
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nscoord aSize,
float aAppUnitsPerMatrixUnit);
nscoord aSize);
void
ProcessInterpolateMatrix(gfx3DMatrix& aMatrix,
@ -41,7 +40,7 @@ namespace nsStyleTransformMatrix {
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nsRect& aBounds, float aAppUnitsPerMatrixUnit);
nsRect& aBounds);
/**
* Given an nsCSSValueList containing -moz-transform functions,

View File

@ -2369,18 +2369,16 @@ bool AudioDeviceLinuxALSA::RecThreadProcess()
bool AudioDeviceLinuxALSA::KeyPressed() const{
#ifdef USE_X11
char szKey[32];
unsigned int i = 0;
char state = 0;
#ifdef USE_X11
if (!_XDisplay)
return false;
// Check key map status
XQueryKeymap(_XDisplay, szKey);
#endif
// A bit change in keymap means a key is pressed
for (i = 0; i < sizeof(szKey); i++)
@ -2389,5 +2387,8 @@ bool AudioDeviceLinuxALSA::KeyPressed() const{
// Save old state
memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState));
return (state != 0);
#else
return false;
#endif
}
} // namespace webrtc

View File

@ -3114,18 +3114,16 @@ bool AudioDeviceLinuxPulse::RecThreadProcess()
}
bool AudioDeviceLinuxPulse::KeyPressed() const{
#ifdef USE_X11
char szKey[32];
unsigned int i = 0;
char state = 0;
#ifdef USE_X11
if (!_XDisplay)
return false;
// Check key map status
XQueryKeymap(_XDisplay, szKey);
#endif
// A bit change in keymap means a key is pressed
for (i = 0; i < sizeof(szKey); i++)
@ -3134,5 +3132,8 @@ bool AudioDeviceLinuxPulse::KeyPressed() const{
// Save old state
memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState));
return (state != 0);
#else
return false;
#endif
}
}

View File

@ -17,7 +17,4 @@ ac_add_options --with-branding=mobile/android/branding/nightly
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Use ccache
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/mobile/android/config/mozconfigs/common.override"

View File

@ -15,7 +15,4 @@ ac_add_options --with-branding=mobile/android/branding/nightly
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Use ccache
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/mobile/android/config/mozconfigs/common.override"

View File

@ -14,7 +14,4 @@ ac_add_options --with-branding=mobile/android/branding/nightly
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Use ccache
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/mobile/android/config/mozconfigs/common.override"

View File

@ -147,6 +147,9 @@ static DllBlockInfo sWindowsDllBlocklist[] = {
// Topcrash with V-bates, bug 1002748
{ "libinject.dll", UNVERSIONED },
// Crashes with RoboForm2Go written against old SDK, bug 988311
{ "rf-firefox-22.dll", ALL_VERSIONS },
{ nullptr, 0 }
};

View File

@ -90,8 +90,12 @@ TEST_F(pkixder_input_tests, InputInitWithNullPointerOrZeroLength)
ASSERT_EQ(Failure, input.Init(nullptr, 100));
ASSERT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
// Is this a bug?
// Though it seems odd to initialize with zero-length and non-null ptr, this
// is working as intended. The Input class was intended to protect against
// buffer overflows, and there's no risk with the current behavior. See bug
// 1000354.
ASSERT_EQ(Success, input.Init((const uint8_t*) "hello", 0));
ASSERT_TRUE(input.AtEnd());
}
TEST_F(pkixder_input_tests, InputInitWithLargeData)

View File

@ -5026,23 +5026,12 @@ static int32_t RoundUp(double aDouble)
NPCocoaEventScrollWheel,
&cocoaEvent);
#ifdef __LP64__
// Only dispatch this event if we're not currently tracking a scroll event as
// swipe.
if (!mCancelSwipeAnimation || *mCancelSwipeAnimation == YES) {
#endif // #ifdef __LP64__
mGeckoChild->DispatchWindowEvent(wheelEvent);
if (!mGeckoChild) {
return;
}
#ifdef __LP64__
} else {
// Manually set these members here since we didn't dispatch the event.
wheelEvent.overflowDeltaX = wheelEvent.deltaX;
wheelEvent.overflowDeltaY = wheelEvent.deltaY;
wheelEvent.mViewPortIsOverscrolled = true;
}
#ifdef __LP64__
// overflowDeltaX and overflowDeltaY tell us when the user has tried to
// scroll past the edge of a page (in those cases it's non-zero).
if ((wheelEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) &&

View File

@ -216,6 +216,8 @@ inline void PadDriverDecimal(char *aString)
inline bool
ParseDriverVersion(const nsAString& aVersion, uint64_t *aNumericVersion)
{
*aNumericVersion = 0;
#if defined(XP_WIN)
int a, b, c, d;
char aStr[8], bStr[8], cStr[8], dStr[8];
@ -238,12 +240,15 @@ ParseDriverVersion(const nsAString& aVersion, uint64_t *aNumericVersion)
if (d < 0 || d > 0xffff) return false;
*aNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
return true;
#elif defined(ANDROID)
// Can't use aVersion.ToInteger() because that's not compiled into our code
// unless we have XPCOM_GLUE_AVOID_NSPR disabled.
*aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
#endif
return true;
#else
return false;
#endif
}
}

View File

@ -595,8 +595,10 @@ GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
return 0;
}
#if defined(XP_WIN) || defined(ANDROID)
uint64_t driverVersion;
ParseDriverVersion(adapterDriverVersionString, &driverVersion);
#endif
uint32_t i = 0;
for (; i < info.Length(); i++) {
@ -747,9 +749,6 @@ GfxInfoBase::GetFeatureStatusImpl(int32_t aFeature,
return NS_OK;
}
uint64_t driverVersion;
ParseDriverVersion(adapterDriverVersionString, &driverVersion);
// Check if the device is blocked from the downloaded blocklist. If not, check
// the static list after that. This order is used so that we can later escape
// out of static blocks (i.e. if we were wrong or something was patched, we

View File

@ -194,7 +194,8 @@ struct XPTInterfaceDirectoryEntry {
extern XPT_PUBLIC_API(PRBool)
XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
XPTInterfaceDirectoryEntry *ide,
nsID *iid, char *name, char *name_space,
nsID *iid, const char *name,
const char *name_space,
XPTInterfaceDescriptor *descriptor);
extern XPT_PUBLIC_API(void)
@ -250,7 +251,7 @@ struct XPTInterfaceDescriptor {
extern XPT_PUBLIC_API(PRBool)
XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
uint16_t num_interfaces, char *name,
uint16_t num_interfaces, const char *name,
uint16_t *indexp);
extern XPT_PUBLIC_API(XPTInterfaceDescriptor *)
@ -283,10 +284,10 @@ struct XPTString {
};
extern XPT_PUBLIC_API(XPTString *)
XPT_NewString(XPTArena *arena, uint16_t length, char *bytes);
XPT_NewString(XPTArena *arena, uint16_t length, const char *bytes);
extern XPT_PUBLIC_API(XPTString *)
XPT_NewStringZ(XPTArena *arena, char *bytes);
XPT_NewStringZ(XPTArena *arena, const char *bytes);
/*
* A TypeDescriptor is a variable-size record used to identify the type of a
@ -478,8 +479,8 @@ struct XPTMethodDescriptor {
extern XPT_PUBLIC_API(PRBool)
XPT_FillMethodDescriptor(XPTArena *arena,
XPTMethodDescriptor *meth, uint8_t flags, char *name,
uint8_t num_args);
XPTMethodDescriptor *meth, uint8_t flags,
const char *name, uint8_t num_args);
/*
* Annotation records are variable-size records used to store secondary

View File

@ -283,7 +283,8 @@ XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
XPT_PUBLIC_API(PRBool)
XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
XPTInterfaceDirectoryEntry *ide,
nsID *iid, char *name, char *name_space,
nsID *iid, const char *name,
const char *name_space,
XPTInterfaceDescriptor *descriptor)
{
XPT_COPY_IID(ide->iid, *iid);
@ -695,7 +696,7 @@ DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
XPT_PUBLIC_API(PRBool)
XPT_FillMethodDescriptor(XPTArena *arena, XPTMethodDescriptor *meth,
uint8_t flags, char *name, uint8_t num_args)
uint8_t flags, const char *name, uint8_t num_args)
{
meth->flags = flags & XPT_MD_FLAGMASK;
meth->name = XPT_STRDUP(arena, name);
@ -874,7 +875,7 @@ DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp)
PRBool
XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
uint16_t num_interfaces, char *name,
uint16_t num_interfaces, const char *name,
uint16_t *indexp)
{
int i;

View File

@ -305,7 +305,7 @@ XPT_SeekTo(XPTCursor *cursor, uint32_t offset)
}
XPT_PUBLIC_API(XPTString *)
XPT_NewString(XPTArena *arena, uint16_t length, char *bytes)
XPT_NewString(XPTArena *arena, uint16_t length, const char *bytes)
{
XPTString *str = XPT_NEW(arena, XPTString);
if (!str)
@ -324,7 +324,7 @@ XPT_NewString(XPTArena *arena, uint16_t length, char *bytes)
}
XPT_PUBLIC_API(XPTString *)
XPT_NewStringZ(XPTArena *arena, char *bytes)
XPT_NewStringZ(XPTArena *arena, const char *bytes)
{
uint32_t length = strlen(bytes);
if (length > 0xffff)

View File

@ -26,15 +26,17 @@
#define TRY(msg, cond) TRY_(msg, cond, 0)
#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
XPTString in_str = { 4, "bazz" };
static char bazz[] = "bazz";
XPTString in_str = { 4, bazz };
static char foobar[] = "foobar";
struct TestData {
uint32_t bit32;
uint16_t bit16;
uint8_t bit8[2];
char *cstr;
XPTString *str;
} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe}, "foobar", &in_str},
} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe}, foobar, &in_str},
output = {0, 0, {0, 0}, NULL, NULL };
void