Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-05-08 14:39:43 +02:00
commit 4996440761
80 changed files with 1092 additions and 949 deletions

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()) {
aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
return;
}
// 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

@ -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;
}
}
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;
}
@ -62,4 +66,4 @@ X11TextureSourceBasic::ContentTypeToSurfaceFormat(gfxContentType aType)
default:
return SurfaceFormat::UNKNOWN;
}
}
}

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

@ -575,18 +575,19 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
cairo_surface_destroy(tempXlibSurface);
return;
}
SurfaceFormat moz2DFormat =
cairo_surface_get_content(tempXlibSurface) == CAIRO_CONTENT_COLOR ?
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,
@ -563,7 +550,7 @@ FinalizeArenas(FreeOp *fop,
AllocKind thingKind,
SliceBudget &budget)
{
switch(thingKind) {
switch (thingKind) {
case FINALIZE_OBJECT0:
case FINALIZE_OBJECT0_BACKGROUND:
case FINALIZE_OBJECT2:
@ -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);
}
@ -227,17 +225,15 @@ static void
ProcessTranslateZ(gfx3DMatrix& aMatrix,
const nsCSSValue::Array* aData,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
float aAppUnitsPerMatrixUnit)
nsPresContext* aPresContext,
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,9 +615,12 @@ 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

@ -7,7 +7,6 @@ package org.mozilla.gecko;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UiAsyncTask;
import org.json.JSONArray;
import org.json.JSONException;
@ -34,7 +33,8 @@ public final class TabsAccessor {
BrowserContract.Tabs.TITLE,
BrowserContract.Tabs.URL,
BrowserContract.Clients.GUID,
BrowserContract.Clients.NAME
BrowserContract.Clients.NAME,
BrowserContract.Clients.LAST_MODIFIED,
};
// Projection column numbers
@ -42,7 +42,8 @@ public final class TabsAccessor {
TITLE,
URL,
GUID,
NAME
NAME,
LAST_MODIFIED,
};
private static final String CLIENTS_SELECTION = BrowserContract.Clients.GUID + " IS NOT NULL";
@ -57,6 +58,11 @@ public final class TabsAccessor {
public String url;
public String guid;
public String name;
/**
* This is the last time the remote client uploaded a tabs record; that
* is, it is not per tab, but per remote client.
*/
public long lastModified;
}
public interface OnQueryTabsCompleteListener {
@ -105,7 +111,8 @@ public final class TabsAccessor {
tab.url = cursor.getString(TABS_COLUMN.URL.ordinal());
tab.guid = cursor.getString(TABS_COLUMN.GUID.ordinal());
tab.name = cursor.getString(TABS_COLUMN.NAME.ordinal());
tab.lastModified = cursor.getLong(TABS_COLUMN.LAST_MODIFIED.ordinal());
tabs.add(tab);
}
} finally {

View File

@ -49,6 +49,10 @@ public interface TelemetryContract {
// Generic action, usually for tracking menu and toolbar actions.
public static final String ACTION = "action.1";
// Launching (opening) an external application
// Note: Only used in JavaScript for now, but here for completeness.
public static final String LAUNCH = "launch.1";
}
/**
@ -82,6 +86,10 @@ public interface TelemetryContract {
// Action triggered from a suggestion provided to the user.
public static final String SUGGESTION = "suggestion";
// Action triggered from a pageaction in the URLBar.
// Note: Only used in JavaScript for now, but here for completeness.
public static final String PAGEACTION = "pageaction";
}
/**
@ -101,10 +109,10 @@ public interface TelemetryContract {
public static final String READER = "reader.1";
// URL bar focused.
public static final String URLBAR_FOCUSED = "urlbar.1:";
public static final String URLBAR_FOCUSED = "urlbar.1";
// Awesomescreen frecency search is active.
public static final String FRECENCY = "frecency.1:";
public static final String FRECENCY = "frecency.1";
}
/**

View File

@ -434,3 +434,11 @@ just addresses the organization to follow, e.g. "This site is run by " -->
They are never shown to users -->
<!ENTITY actionbar_menu "Menu">
<!ENTITY actionbar_done "Done">
<!-- Localization note (remote_tabs_last_synced): the variable is replaced by a
"relative time span string" produced by Android. This string describes the
time the tabs were last synced relative to the current time; examples
include "42 minutes ago", "4 days ago", "last week", etc. The subject of
"Last synced" is one of the user's other Sync clients, typically Firefox on
their desktop or laptop.-->
<!ENTITY remote_tabs_last_synced "Last synced: &formatS;">

View File

@ -4,24 +4,24 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/action_bar_button_inverse"
android:gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="@dimen/remote_tab_child_row_height"
android:gravity="center_vertical"
android:orientation="vertical"
android:background="@drawable/action_bar_button_inverse"
android:paddingLeft="2dp"
android:paddingRight="2dp">
<TextView android:id="@+id/tab"
style="@style/TabRowTextAppearance"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@style/TabRowTextAppearance"
android:textSize="14sp"/>
<TextView android:id="@+id/url"
style="@style/TabRowTextAppearance.Url"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@style/TabRowTextAppearance.Url"
android:textSize="12sp"/>
</LinearLayout>

View File

@ -3,16 +3,28 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<org.mozilla.gecko.widget.AllCapsTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/client"
android:layout_width="fill_parent"
android:layout_height="@dimen/remote_tab_group_row_height"
style="@style/TabRowTextAppearance.Url"
android:background="@android:color/transparent"
android:paddingLeft="2dip"
android:paddingRight="2dip"
android:textStyle="bold"
android:textSize="12sp"
android:singleLine="false"
android:maxLines="2"
android:gravity="center_vertical"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/transparent"
android:layout_width="fill_parent"
android:layout_height="@dimen/remote_tab_child_row_height"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="2dp"
android:paddingRight="2dp">
<org.mozilla.gecko.widget.AllCapsTextView android:id="@+id/client"
style="@style/TabRowTextAppearance"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:singleLine="false"
android:textSize="14sp"
android:textStyle="bold" />
<TextView android:id="@+id/last_synced"
style="@style/TabRowTextAppearance.Url"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="12sp"/>
</LinearLayout>

View File

@ -4,25 +4,25 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/transparent"
android:gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="@dimen/remote_tab_child_row_height"
android:gravity="center_vertical"
android:orientation="vertical"
android:background="@drawable/action_bar_button_inverse"
android:paddingLeft="4dp"
android:paddingRight="4dp">
<TextView android:id="@+id/tab"
style="@style/TabRowTextAppearance"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@style/TabRowTextAppearance"
android:textSize="18sp"/>
android:textSize="18sp" />
<TextView android:id="@+id/url"
style="@style/TabRowTextAppearance.Url"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="@style/TabRowTextAppearance.Url"
android:textSize="14sp"
android:maxLength="1024"/>
android:maxLength="1024"
android:textSize="14sp" />
</LinearLayout>

View File

@ -3,14 +3,27 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<org.mozilla.gecko.widget.AllCapsTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/client"
android:layout_width="fill_parent"
android:layout_height="@dimen/remote_tab_group_row_height"
style="@style/TabRowTextAppearance.Url"
android:background="@android:color/transparent"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:textStyle="bold"
android:textSize="14sp"
android:gravity="center_vertical"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/transparent"
android:layout_width="fill_parent"
android:layout_height="@dimen/remote_tab_child_row_height"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="4dp"
android:paddingRight="4dp" >
<org.mozilla.gecko.widget.AllCapsTextView android:id="@+id/client"
style="@style/TabRowTextAppearance"
android:layout_width="fill_parent"
android:layout_height="@dimen/remote_tab_group_row_height"
android:textSize="18sp"
android:textStyle="bold" />
<TextView android:id="@+id/last_synced"
style="@style/TabRowTextAppearance.Url"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:maxLength="1024"
android:textSize="14sp" />
</LinearLayout>

View File

@ -404,4 +404,5 @@
<!-- Miscellaneous -->
<string name="ellipsis">&ellipsis;</string>
<string name="remote_tabs_last_synced">&remote_tabs_last_synced;</string>
</resources>

View File

@ -4,14 +4,6 @@
package org.mozilla.gecko.tabspanel;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -22,6 +14,14 @@ import org.mozilla.gecko.TabsAccessor;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import android.content.Context;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
/**
* The actual list of synced tabs. This serves as the only child view of {@link RemoteTabsContainer}
* so it can be refreshed using a swipe-to-refresh gesture.
@ -30,9 +30,9 @@ class RemoteTabsList extends ExpandableListView
implements ExpandableListView.OnGroupClickListener,
ExpandableListView.OnChildClickListener,
TabsAccessor.OnQueryTabsCompleteListener {
private static final String[] CLIENT_KEY = new String[] { "name" };
private static final String[] CLIENT_KEY = new String[] { "name", "last_synced" };
private static final String[] TAB_KEY = new String[] { "title", "url" };
private static final int[] CLIENT_RESOURCE = new int[] { R.id.client };
private static final int[] CLIENT_RESOURCE = new int[] { R.id.client, R.id.last_synced };
private static final int[] TAB_RESOURCE = new int[] { R.id.tab, R.id.url };
private final Context context;
@ -92,10 +92,13 @@ class RemoteTabsList extends ExpandableListView
HashMap <String, String> client;
HashMap <String, String> tab;
final long now = System.currentTimeMillis();
for (TabsAccessor.RemoteTab remoteTab : remoteTabs) {
if (oldGuid == null || !TextUtils.equals(oldGuid, remoteTab.guid)) {
client = new HashMap <String, String>();
client.put("name", remoteTab.name);
client.put("last_synced", getLastSyncedString(now, remoteTab.lastModified));
clients.add(client);
tabsForClient = new ArrayList <HashMap <String, String>>();
@ -124,4 +127,16 @@ class RemoteTabsList extends ExpandableListView
expandGroup(i);
}
}
/**
* Return a relative "Last synced" time span for the given tab record.
*
* @param now local time.
* @param time to format string for.
* @return string describing time span
*/
protected String getLastSyncedString(long now, long time) {
CharSequence relativeTimeSpanString = DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
return getResources().getString(R.string.remote_tabs_last_synced, relativeTimeSpanString);
}
}

View File

@ -8101,6 +8101,10 @@ var ExternalApps = {
icon: "drawable://icon_openinapp",
clickCallback: () => {
// Create a relative timestamp for telemetry
let uptime = Date.now() - Services.startup.getStartupInfo().linkerInitialized;
UITelemetry.addEvent("launch.1", "pageaction", uptime, "helper");
if (apps.length > 1) {
// Use the HelperApps prompt here to filter out any Http handlers
HelperApps.prompt(apps, {

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

@ -46,15 +46,22 @@ DEFINES += -DENABLE_MARIONETTE=1
endif
ifdef MOZ_PKG_MANIFEST_P
$(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P) $(GLOBAL_DEPS)
# When MOZ_CHROME_MULTILOCALE is defined, we write multilocale.json like:
# {"locales": ["en-US", "de", "ar", ...]}
$(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P) $(GLOBAL_DEPS) FORCE
$(call py_action,preprocessor,$(DEFINES) $(ACDEFINES) $< -o $@)
ifdef MOZ_CHROME_MULTILOCALE
printf '\n[multilocale]\n' >> $@
printf '@BINPATH@/res/multilocale.json\n' >> $@
for LOCALE in en-US $(MOZ_CHROME_MULTILOCALE) ;\
do \
printf '$(BINPATH)/chrome/'"$$LOCALE"'$(JAREXT)\n' >> $@; \
printf '$(BINPATH)/chrome/'"$$LOCALE"'.manifest\n' >> $@; \
done
COMMA=,
echo '{"locales": [$(foreach l,$(MOZ_CHROME_MULTILOCALE),"$(l)"$(COMMA)) "en-US"]}' \
> $(FINAL_TARGET)/res/multilocale.json
endif
GARBAGE += $(MOZ_PKG_MANIFEST)

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;
mGeckoChild->DispatchWindowEvent(wheelEvent);
if (!mGeckoChild) {
return;
}
#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
@ -477,9 +478,9 @@ struct XPTMethodDescriptor {
#define XPT_MD_WANTS_CONTEXT(flags) (flags & XPT_MD_CONTEXT)
extern XPT_PUBLIC_API(PRBool)
XPT_FillMethodDescriptor(XPTArena *arena,
XPTMethodDescriptor *meth, uint8_t flags, char *name,
uint8_t num_args);
XPT_FillMethodDescriptor(XPTArena *arena,
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);
@ -694,8 +695,8 @@ 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)
XPT_FillMethodDescriptor(XPTArena *arena, XPTMethodDescriptor *meth,
uint8_t flags, const char *name, uint8_t num_args)
{
meth->flags = flags & XPT_MD_FLAGMASK;
meth->name = XPT_STRDUP(arena, name);
@ -874,11 +875,11 @@ DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp)
PRBool
XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
uint16_t num_interfaces, char *name,
uint16_t *indexp)
uint16_t num_interfaces, const char *name,
uint16_t *indexp)
{
int i;
for (i=1; i<=num_interfaces; i++) {
fprintf(stderr, "%s == %s ?\n", ide_block[i].name, name);
if (strcmp(ide_block[i].name, name) == 0) {

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