Merge mozilla-beta to b2g37. a=merge
Merge mozilla-beta to b2g37. a=merge
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -35,16 +35,28 @@ loop.panel = (function(_, mozL10n) {
};
},
shouldComponentUpdate: function(nextProps, nextState) {
var tabChange = this.state.selectedTab !== nextState.selectedTab;
if (tabChange) {
this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab);
}
+
+ if (!tabChange && nextProps.buttonsHidden) {
+ if (nextProps.buttonsHidden.length !== this.props.buttonsHidden.length) {
+ tabChange = true;
+ } else {
+ for (var i = 0, l = nextProps.buttonsHidden.length; i < l && !tabChange; ++i) {
+ if (this.props.buttonsHidden.indexOf(nextProps.buttonsHidden[i]) === -1) {
+ tabChange = true;
+ }
+ }
+ }
+ }
return tabChange;
},
getInitialState: function() {
// XXX Work around props.selectedTab being undefined initially.
// When we don't need to rely on the pref, this can move back to
// getDefaultProps (bug 1100258).
return {
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -35,16 +35,28 @@ loop.panel = (function(_, mozL10n) {
};
},
shouldComponentUpdate: function(nextProps, nextState) {
var tabChange = this.state.selectedTab !== nextState.selectedTab;
if (tabChange) {
this.props.mozLoop.notifyUITour("Loop:PanelTabChanged", nextState.selectedTab);
}
+
+ if (!tabChange && nextProps.buttonsHidden) {
+ if (nextProps.buttonsHidden.length !== this.props.buttonsHidden.length) {
+ tabChange = true;
+ } else {
+ for (var i = 0, l = nextProps.buttonsHidden.length; i < l && !tabChange; ++i) {
+ if (this.props.buttonsHidden.indexOf(nextProps.buttonsHidden[i]) === -1) {
+ tabChange = true;
+ }
+ }
+ }
+ }
return tabChange;
},
getInitialState: function() {
// XXX Work around props.selectedTab being undefined initially.
// When we don't need to rely on the pref, this can move back to
// getDefaultProps (bug 1100258).
return {
--- a/browser/components/loop/test/mochitest/browser_toolbarbutton.js
+++ b/browser/components/loop/test/mochitest/browser_toolbarbutton.js
@@ -33,26 +33,34 @@ add_task(function* test_LoopUI_getters()
Assert.ok(LoopUI.panel, "LoopUI panel element should be set");
Assert.strictEqual(LoopUI.browser, null, "Browser element should not be there yet");
Assert.strictEqual(LoopUI.selectedTab, null, "No tab should be selected yet");
// Load and show the Loop panel for the very first time this session.
yield loadLoopPanel();
Assert.ok(LoopUI.browser, "Browser element should be there");
Assert.strictEqual(LoopUI.selectedTab, "rooms", "Initially the rooms tab should be selected");
+ let panelTabs = LoopUI.browser.contentDocument.querySelectorAll(".tab-view > li");
+ Assert.strictEqual(panelTabs.length, 1, "Only one tab, 'rooms', should be visible");
// Hide the panel.
yield LoopUI.togglePanel();
Assert.strictEqual(LoopUI.selectedTab, "rooms", "Rooms tab should still be selected");
// Make sure the contacts tab shows up by simulating a login.
MozLoopServiceInternal.fxAOAuthTokenData = fxASampleToken;
MozLoopServiceInternal.fxAOAuthProfile = fxASampleProfile;
yield MozLoopServiceInternal.notifyStatusChanged("login");
+ yield LoopUI.togglePanel();
+ Assert.strictEqual(LoopUI.selectedTab, "rooms", "Rooms tab should still be selected");
+ panelTabs = LoopUI.browser.contentDocument.querySelectorAll(".tab-view > li");
+ Assert.strictEqual(panelTabs.length, 2, "Two tabs should be visible");
+ yield LoopUI.togglePanel();
+
// Programmatically select the contacts tab.
yield LoopUI.togglePanel(null, "contacts");
Assert.strictEqual(LoopUI.selectedTab, "contacts", "Contacts tab should be selected now");
// Switch back to the rooms tab.
yield LoopUI.openCallPanel(null, "rooms");
Assert.strictEqual(LoopUI.selectedTab, "rooms", "Rooms tab should be selected now");
--- a/dom/canvas/test/_webgl-conformance.ini
+++ b/dom/canvas/test/_webgl-conformance.ini
@@ -765,16 +765,17 @@ skip-if = (os == 'android') || (os == 'b
[webgl-conformance/_wrappers/test_conformance__textures__texture-active-bind-2.html]
[webgl-conformance/_wrappers/test_conformance__textures__texture-active-bind.html]
[webgl-conformance/_wrappers/test_conformance__textures__texture-complete.html]
[webgl-conformance/_wrappers/test_conformance__textures__texture-formats-test.html]
[webgl-conformance/_wrappers/test_conformance__textures__texture-mips.html]
[webgl-conformance/_wrappers/test_conformance__textures__texture-npot-video.html]
skip-if = os == 'win'
[webgl-conformance/_wrappers/test_conformance__textures__texture-npot.html]
+skip-if = os == 'android'
[webgl-conformance/_wrappers/test_conformance__textures__texture-size.html]
skip-if = os == 'android'
[webgl-conformance/_wrappers/test_conformance__textures__texture-size-cube-maps.html]
skip-if = os == 'android'
[webgl-conformance/_wrappers/test_conformance__textures__texture-transparent-pixels-initialized.html]
[webgl-conformance/_wrappers/test_conformance__typedarrays__array-buffer-crash.html]
[webgl-conformance/_wrappers/test_conformance__typedarrays__array-buffer-view-crash.html]
[webgl-conformance/_wrappers/test_conformance__typedarrays__array-unit-tests.html]
--- a/dom/canvas/test/webgl-conformance/mochi-single.html
+++ b/dom/canvas/test/webgl-conformance/mochi-single.html
@@ -117,17 +117,16 @@ function GetExpectedTestFailSet() {
failSet['conformance/glsl/functions/glsl-function-step-gentype.html'] = true;
failSet['conformance/limits/gl-max-texture-dimensions.html'] = true;
failSet['conformance/limits/gl-min-textures.html'] = true;
failSet['conformance/rendering/draw-elements-out-of-bounds.html'] = true;
failSet['conformance/state/gl-get-calls.html'] = true;
failSet['conformance/textures/tex-image-with-format-and-type.html'] = true;
failSet['conformance/textures/tex-sub-image-2d.html'] = true;
failSet['conformance/textures/texture-mips.html'] = true;
- failSet['conformance/textures/texture-npot.html'] = true;
failSet['conformance/textures/texture-size-cube-maps.html'] = true;
} else {
// Android 2.3 slaves.
failSet['conformance/extensions/oes-texture-float.html'] = true;
failSet['conformance/glsl/functions/glsl-function-sin.html'] = true;
failSet['conformance/misc/object-deletion-behaviour.html'] = true;
failSet['conformance/textures/tex-image-and-sub-image-2d-with-video.html'] = true;
failSet['conformance/textures/texture-mips.html'] = true;
--- a/dom/canvas/test/webgl-conformance/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conformance/mochitest-errata.ini
@@ -62,16 +62,19 @@ skip-if = os == 'android'
# Crashes on Android.
skip-if = os == 'android'
[_wrappers/test_conformance__textures__texture-size.html]
# Crashes on Android 4.0.
skip-if = os == 'android'
[_wrappers/test_conformance__textures__texture-size-cube-maps.html]
# Crashes on Android 4.0.
skip-if = os == 'android'
+[_wrappers/test_conformance__textures__texture-npot.html]
+# Intermittent fail on Android 4.0.
+skip-if = os == 'android'
########################################################################
# B2G
[_wrappers/test_conformance__context__context-attributes-alpha-depth-stencil-antialias.html]
# Asserts on 'B2G ICS Emulator Debug'.
skip-if = (os == 'b2g')
[_wrappers/test_conformance__textures__tex-image-and-uniform-binding-bugs.html]
# Intermittently asserts on 'B2G ICS Emulator Debug'.
--- a/dom/media/fmp4/SharedDecoderManager.cpp
+++ b/dom/media/fmp4/SharedDecoderManager.cpp
@@ -191,18 +191,20 @@ SharedDecoderProxy::Flush()
return NS_OK;
}
nsresult
SharedDecoderProxy::Drain()
{
if (mManager->mActiveProxy == this) {
return mManager->mDecoder->Drain();
+ } else {
+ mCallback->DrainComplete();
+ return NS_OK;
}
- return NS_OK;
}
nsresult
SharedDecoderProxy::Shutdown()
{
mManager->SetIdle(this);
return NS_OK;
}
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -1000,17 +1000,17 @@ TrackBuffer::RangeRemoval(int64_t aStart
nsTArray<SourceBufferDecoder*> decoders;
decoders.AppendElements(mInitializedDecoders);
if (aStart <= bufferedStart && aEnd < bufferedEnd) {
// Evict data from beginning.
for (size_t i = 0; i < decoders.Length(); ++i) {
nsRefPtr<dom::TimeRanges> buffered = new dom::TimeRanges();
decoders[i]->GetBuffered(buffered);
- if (buffered->GetEndTime() < aEnd) {
+ if (int64_t(buffered->GetEndTime() * USECS_PER_S) < aEnd) {
// Can be fully removed.
MSE_DEBUG("remove all bufferedEnd=%f time=%f, size=%lld",
buffered->GetEndTime(), time,
decoders[i]->GetResource()->GetSize());
decoders[i]->GetResource()->EvictAll();
} else {
int64_t offset = decoders[i]->ConvertToByteOffset(aEnd);
MSE_DEBUG("removing some bufferedEnd=%f offset=%lld size=%lld",
@@ -1019,17 +1019,17 @@ TrackBuffer::RangeRemoval(int64_t aStart
if (offset > 0) {
decoders[i]->GetResource()->EvictData(offset, offset);
}
}
}
} else {
// Only trimming existing buffers.
for (size_t i = 0; i < decoders.Length(); ++i) {
- if (aStart <= buffered->GetStartTime()) {
+ if (aStart <= int64_t(buffered->GetStartTime() * USECS_PER_S)) {
// It will be entirely emptied, can clear all data.
decoders[i]->GetResource()->EvictAll();
} else {
decoders[i]->Trim(aStart);
}
}
}
--- a/image/public/imgIContainer.idl
+++ b/image/public/imgIContainer.idl
@@ -111,17 +111,17 @@ native nsIntSizeByVal(nsIntSize);
/**
* imgIContainer is the interface that represents an image. It allows
* access to frames as Thebes surfaces. It also allows drawing of images
* onto Thebes contexts.
*
* Internally, imgIContainer also manages animation of images.
*/
-[scriptable, builtinclass, uuid(4e7d0b17-cb57-4d68-860f-59b303a86dbd)]
+[scriptable, builtinclass, uuid(9a43298b-bf49-44fc-9abe-9ff702f1bd25)]
interface imgIContainer : nsISupports
{
/**
* The width of the container rectangle. In the case of any error,
* zero is returned, and an exception will be thrown.
*/
readonly attribute int32_t width;
@@ -420,24 +420,16 @@ interface imgIContainer : nsISupports
* (FLAG_DECODE_*) and FLAG_SYNC_DECODE (which will
* synchronously decode images that can be decoded "quickly",
* just like startDecoding() does) are accepted; others will be
* ignored.
*/
[noscript] void requestDecodeForSize([const] in nsIntSize aSize,
in uint32_t aFlags);
- /*
- * Returns true if no more decoding can be performed on this image. Images
- * with errors return true since they cannot be decoded any further. Note that
- * because decoded images may be discarded, isDecoded() may return false even
- * if it has returned true in the past.
- */
- [noscript, notxpcom, nostdcall] bool isDecoded();
-
/**
* Increments the lock count on the image. An image will not be discarded
* as long as the lock count is nonzero. Note that it is still possible for
* the image to be undecoded if decode-on-draw is enabled and the image
* was never drawn.
*
* Upon instantiation images have a lock count of zero.
*/
--- a/image/src/DynamicImage.cpp
+++ b/image/src/DynamicImage.cpp
@@ -255,22 +255,16 @@ DynamicImage::StartDecoding()
}
NS_IMETHODIMP
DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags)
{
return NS_OK;
}
-bool
-DynamicImage::IsDecoded()
-{
- return true;
-}
-
NS_IMETHODIMP
DynamicImage::LockImage()
{
return NS_OK;
}
NS_IMETHODIMP
DynamicImage::UnlockImage()
--- a/image/src/ImageWrapper.cpp
+++ b/image/src/ImageWrapper.cpp
@@ -225,22 +225,16 @@ ImageWrapper::StartDecoding()
}
NS_IMETHODIMP
ImageWrapper::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags)
{
return mInnerImage->RequestDecodeForSize(aSize, aFlags);
}
-bool
-ImageWrapper::IsDecoded()
-{
- return mInnerImage->IsDecoded();
-}
-
NS_IMETHODIMP
ImageWrapper::LockImage()
{
MOZ_ASSERT(NS_IsMainThread(),
"Main thread to encourage serialization with UnlockImage");
return mInnerImage->LockImage();
}
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -1464,23 +1464,16 @@ RasterImage::RequestDecodeForSize(const
// Look up the first frame of the image, which will implicitly start decoding
// if it's not available right now.
LookupFrame(0, targetSize, flags);
return NS_OK;
}
-bool
-RasterImage::IsDecoded()
-{
- // XXX(seth): We need to get rid of this; it's not reliable.
- return mHasBeenDecoded || mError || (mDecodeOnDraw && mHasSourceData);
-}
-
NS_IMETHODIMP
RasterImage::Decode(const Maybe<nsIntSize>& aSize, uint32_t aFlags)
{
MOZ_ASSERT(!aSize || NS_IsMainThread());
if (mError) {
return NS_ERROR_FAILURE;
}
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -926,22 +926,16 @@ NS_IMETHODIMP
VectorImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags)
{
// Nothing to do for SVG images, though in theory we could rasterize to the
// provided size ahead of time if we supported off-main-thread SVG
// rasterization...
return NS_OK;
}
-bool
-VectorImage::IsDecoded()
-{
- return mIsFullyLoaded || mError;
-}
-
//******************************************************************************
/* void lockImage() */
NS_IMETHODIMP
VectorImage::LockImage()
{
// This method is for image-discarding, which only applies to RasterImages.
return NS_OK;
}
--- a/js/src/asmjs/AsmJSSignalHandlers.cpp
+++ b/js/src/asmjs/AsmJSSignalHandlers.cpp
@@ -937,17 +937,17 @@ RedirectIonBackedgesToInterruptCheck(JSR
// thus not in a JIT iloop. We assume that the interrupt flag will be
// checked at least once before entering JIT code (if not, no big deal;
// the browser will just request another interrupt in a second).
if (!jitRuntime->mutatingBackedgeList())
jitRuntime->patchIonBackedges(rt, jit::JitRuntime::BackedgeInterruptCheck);
}
}
-static void
+static bool
RedirectJitCodeToInterruptCheck(JSRuntime *rt, CONTEXT *context)
{
RedirectIonBackedgesToInterruptCheck(rt);
if (AsmJSActivation *activation = rt->mainThread.asmJSActivationStack()) {
const AsmJSModule &module = activation->module();
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
@@ -955,18 +955,21 @@ RedirectJitCodeToInterruptCheck(JSRuntim
rt->mainThread.simulator()->set_resume_pc(int32_t(module.interruptExit()));
#endif
uint8_t **ppc = ContextToPC(context);
uint8_t *pc = *ppc;
if (module.containsFunctionPC(pc)) {
activation->setResumePC(pc);
*ppc = module.interruptExit();
+ return true;
}
}
+
+ return false;
}
#if !defined(XP_WIN)
// For the interrupt signal, pick a signal number that:
// - is not otherwise used by mozilla or standard libraries
// - defaults to nostop and noprint on gdb/lldb so that noone is bothered
// SIGVTALRM a relative of SIGALRM, so intended for user code, but, unlike
// SIGALRM, not used anywhere else in Mozilla.
@@ -1094,18 +1097,18 @@ js::InterruptRunningJitCode(JSRuntime *r
// its context from this thread. SuspendThread can sporadically fail if the
// thread is in the middle of a syscall. Rather than retrying in a loop,
// just wait for the next request for interrupt.
HANDLE thread = (HANDLE)rt->ownerThreadNative();
if (SuspendThread(thread) != -1) {
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL;
if (GetThreadContext(thread, &context)) {
- RedirectJitCodeToInterruptCheck(rt, &context);
- SetThreadContext(thread, &context);
+ if (RedirectJitCodeToInterruptCheck(rt, &context))
+ SetThreadContext(thread, &context);
}
ResumeThread(thread);
}
#else
// On Unix, we instead deliver an async signal to the main thread which
// halts the thread and callers our JitInterruptHandler (which has already
// been installed by EnsureSignalHandlersInstalled).
pthread_t thread = (pthread_t)rt->ownerThreadNative();
--- a/js/src/builtin/SymbolObject.cpp
+++ b/js/src/builtin/SymbolObject.cpp
@@ -24,17 +24,17 @@ const Class SymbolObject::class_ = {
nullptr, /* getProperty */
nullptr, /* setProperty */
nullptr, /* enumerate */
nullptr, /* resolve */
convert
};
SymbolObject *
-SymbolObject::create(JSContext *cx, JS::Symbol *symbol)
+SymbolObject::create(JSContext *cx, JS::HandleSymbol symbol)
{
JSObject *obj = NewBuiltinClassInstance(cx, &class_);
if (!obj)
return nullptr;
SymbolObject &symobj = obj->as<SymbolObject>();
symobj.setPrimitiveValue(symbol);
return &symobj;
}
--- a/js/src/builtin/SymbolObject.h
+++ b/js/src/builtin/SymbolObject.h
@@ -23,17 +23,17 @@ class SymbolObject : public NativeObject
static const Class class_;
static JSObject *initClass(JSContext *cx, js::HandleObject obj);
/*
* Creates a new Symbol object boxing the given primitive Symbol. The
* object's [[Prototype]] is determined from context.
*/
- static SymbolObject *create(JSContext *cx, JS::Symbol *symbol);
+ static SymbolObject *create(JSContext *cx, JS::HandleSymbol symbol);
JS::Symbol *unbox() const {
return getFixedSlot(PRIMITIVE_VALUE_SLOT).toSymbol();
}
private:
inline void setPrimitiveValue(JS::Symbol *symbol) {
setFixedSlot(PRIMITIVE_VALUE_SLOT, SymbolValue(symbol));
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1607,18 +1607,18 @@ RegExpCompiler::Assemble(JSContext *cx,
while (!work_list_.empty())
work_list_.popCopy()->Emit(this, &new_trace);
RegExpCode code = macro_assembler_->GenerateCode(cx, match_only_);
if (code.empty())
return RegExpCode();
if (reg_exp_too_big_) {
+ code.destroy();
JS_ReportError(cx, "regexp too big");
- code.destroy();
return RegExpCode();
}
return code;
}
template <typename CharT>
static void
--- a/js/src/jit/ExecutableAllocator.h
+++ b/js/src/jit/ExecutableAllocator.h
@@ -28,16 +28,17 @@
#include <limits>
#include <stddef.h> // for ptrdiff_t
#include "jsalloc.h"
#include "jit/arm/Simulator-arm.h"
#include "jit/mips/Simulator-mips.h"
+#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "js/Vector.h"
#ifdef JS_CPU_SPARC
#ifdef __linux__ // bugzilla 502369
static void sync_instruction_memory(caddr_t v, u_int len)
{
caddr_t end = v + len;
@@ -241,18 +242,21 @@ public:
// (found, or created if necessary) a pool that had enough space.
void *result = (*poolp)->alloc(n, type);
MOZ_ASSERT(result);
return result;
}
void releasePoolPages(ExecutablePool *pool) {
MOZ_ASSERT(pool->m_allocation.pages);
- if (destroyCallback)
+ if (destroyCallback) {
+ // Do not allow GC during the page release callback.
+ JS::AutoSuppressGCAnalysis nogc;
destroyCallback(pool->m_allocation.pages, pool->m_allocation.size);
+ }
systemRelease(pool->m_allocation);
MOZ_ASSERT(m_pools.initialized());
m_pools.remove(m_pools.lookup(pool)); // this asserts if |pool| is not in m_pools
}
void addSizeOfCode(JS::CodeSizes *sizes) const;
void setDestroyCallback(DestroyCallback destroyCallback) {
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -2980,16 +2980,19 @@ MClampToUint8::foldsTo(TempAllocator &al
}
}
return this;
}
bool
MCompare::tryFoldEqualOperands(bool *result)
{
+ // Temporarily disabled due to bug 1130679.
+ return false;
+
if (lhs() != rhs())
return false;
// Intuitively somebody would think that if lhs == rhs,
// then we can just return true. (Or false for !==)
// However NaN !== NaN is true! So we spend some time trying
// to eliminate this case.
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3586,17 +3586,18 @@ js::PrimitiveToObject(JSContext *cx, con
Rooted<JSString*> str(cx, v.toString());
return StringObject::create(cx, str);
}
if (v.isNumber())
return NumberObject::create(cx, v.toNumber());
if (v.isBoolean())
return BooleanObject::create(cx, v.toBoolean());
MOZ_ASSERT(v.isSymbol());
- return SymbolObject::create(cx, v.toSymbol());
+ RootedSymbol symbol(cx, v.toSymbol());
+ return SymbolObject::create(cx, symbol);
}
/*
* Invokes the ES5 ToObject algorithm on vp, returning the result. If vp might
* already be an object, use ToObject. reportCantConvert controls how null and
* undefined errors are reported.
*
* Callers must handle the already-object case.
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -4405,19 +4405,18 @@ FrameLayerBuilder::PaintItems(nsTArray<C
gfxContext *aContext,
nsRenderingContext *aRC,
nsDisplayListBuilder* aBuilder,
nsPresContext* aPresContext,
const nsIntPoint& aOffset,
float aXScale, float aYScale,
int32_t aCommonClipCount)
{
-#ifdef MOZ_DUMP_PAINTING
DrawTarget& aDrawTarget = *aRC->GetDrawTarget();
-#endif
+
int32_t appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
nsRect boundRect = aRect.ToAppUnits(appUnitsPerDevPixel);
boundRect.MoveBy(NSIntPixelsToAppUnits(aOffset.x, appUnitsPerDevPixel),
NSIntPixelsToAppUnits(aOffset.y, appUnitsPerDevPixel));
boundRect.ScaleInverseRoundOut(aXScale, aYScale);
DisplayItemClip currentClip;
bool currentClipIsSetInContext = false;
@@ -4457,17 +4456,19 @@ FrameLayerBuilder::PaintItems(nsTArray<C
NS_ASSERTION(aCommonClipCount < 100,
"Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong.");
currentClip.ApplyTo(aContext, aPresContext, aCommonClipCount);
aContext->NewPath();
}
}
if (cdi->mInactiveLayerManager) {
+ bool saved = aDrawTarget.GetPermitSubpixelAA();
PaintInactiveLayer(aBuilder, cdi->mInactiveLayerManager, cdi->mItem, aContext, aRC);
+ aDrawTarget.SetPermitSubpixelAA(saved);
} else {
nsIFrame* frame = cdi->mItem->Frame();
frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::sDumpPainting) {
DebugPaintItem(aDrawTarget, aPresContext, cdi->mItem, aBuilder);
} else {
#else
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -57,17 +57,17 @@
#include "gfxColor.h"
#include "gfxGradientCache.h"
#include "GraphicsFilter.h"
#include <algorithm>
using namespace mozilla;
using namespace mozilla::css;
using namespace mozilla::gfx;
-using mozilla::image::ImageOps;
+using namespace mozilla::image;
using mozilla::CSSSizeOrRatio;
static int gFrameTreeLockCount = 0;
// To avoid storing this data on nsInlineFrame (bloat) and to avoid
// recalculating this for each frame in a continuation (perf), hold
// a cache of various coordinate information that we need in order
// to paint inline backgrounds.
@@ -1613,17 +1613,17 @@ nsCSSRendering::PaintBoxShadowInner(nsPr
shadowContext->Fill();
shadowContext->NewPath();
blurringArea.DoPaint();
renderContext->Restore();
}
}
-void
+DrawResult
nsCSSRendering::PaintBackground(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
uint32_t aFlags,
nsRect* aBGClipRect,
int32_t aLayer)
@@ -1637,31 +1637,31 @@ nsCSSRendering::PaintBackground(nsPresCo
nsStyleContext *sc;
if (!FindBackground(aForFrame, &sc)) {
// We don't want to bail out if moz-appearance is set on a root
// node. If it has a parent content node, bail because it's not
// a root, otherwise keep going in order to let the theme stuff
// draw the background. The canvas really should be drawing the
// bg, but there's no way to hook that up via css.
if (!aForFrame->StyleDisplay()->mAppearance) {
- return;
+ return DrawResult::SUCCESS;
}
nsIContent* content = aForFrame->GetContent();
if (!content || content->GetParent()) {
- return;
+ return DrawResult::SUCCESS;
}
sc = aForFrame->StyleContext();
}
- PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame,
- aDirtyRect, aBorderArea, sc,
- *aForFrame->StyleBorder(), aFlags,
- aBGClipRect, aLayer);
+ return PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame,
+ aDirtyRect, aBorderArea, sc,
+ *aForFrame->StyleBorder(), aFlags,
+ aBGClipRect, aLayer);
}
static bool
IsOpaqueBorderEdge(const nsStyleBorder& aBorder, mozilla::css::Side aSide)
{
if (aBorder.GetComputedBorder().Side(aSide) == 0)
return true;
switch (aBorder.GetBorderStyle(aSide)) {
@@ -2812,47 +2812,52 @@ nsCSSRendering::PaintGradient(nsPresCont
ctx->SetPattern(gradientPattern);
}
ctx->Fill();
ctx->SetMatrix(ctm);
}
}
}
-void
+DrawResult
nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
nsStyleContext* aBackgroundSC,
const nsStyleBorder& aBorder,
uint32_t aFlags,
nsRect* aBGClipRect,
int32_t aLayer)
{
NS_PRECONDITION(aForFrame,
"Frame is expected to be provided to PaintBackground");
+ // Initialize our result to success. We update it only if its value is
+ // currently DrawResult::SUCCESS, which means that as soon as we hit our first
+ // non-successful draw, we stop updating and will return that value.
+ DrawResult result = DrawResult::SUCCESS;
+
// Check to see if we have an appearance defined. If so, we let the theme
// renderer draw the background and bail out.
// XXXzw this ignores aBGClipRect.
const nsStyleDisplay* displayData = aForFrame->StyleDisplay();
if (displayData->mAppearance) {
nsITheme *theme = aPresContext->GetTheme();
if (theme && theme->ThemeSupportsWidget(aPresContext, aForFrame,
displayData->mAppearance)) {
nsRect drawing(aBorderArea);
theme->GetWidgetOverflow(aPresContext->DeviceContext(),
aForFrame, displayData->mAppearance, &drawing);
drawing.IntersectRect(drawing, aDirtyRect);
theme->DrawWidgetBackground(&aRenderingContext, aForFrame,
displayData->mAppearance, aBorderArea,
drawing);
- return;
+ return DrawResult::SUCCESS;
}
}
// For canvas frames (in the CSS sense) we draw the background color using
// a solid color item that gets added in nsLayoutUtils::PaintFrame,
// or nsSubDocumentFrame::BuildDisplayList (bug 488242). (The solid
// color may be moved into nsDisplayCanvasBackground by
// nsPresShell::AddCanvasBackgroundColorItem, and painted by
@@ -2877,17 +2882,17 @@ nsCSSRendering::PaintBackgroundWithSC(ns
if (drawBackgroundColor && aLayer >= 0) {
drawBackgroundColor = false;
}
// At this point, drawBackgroundImage and drawBackgroundColor are
// true if and only if we are actually supposed to paint an image or
// color into aDirtyRect, respectively.
if (!drawBackgroundImage && !drawBackgroundColor)
- return;
+ return DrawResult::SUCCESS;
// Compute the outermost boundary of the area that might be painted.
// Same coordinate space as aBorderArea & aBGClipRect.
Sides skipSides = aForFrame->GetSkipSides();
nsRect paintBorderArea =
::BoxDecorationRectForBackground(aForFrame, aBorderArea, skipSides, &aBorder);
nsRect clipBorderArea =
::BoxDecorationRectForBorder(aForFrame, aBorderArea, skipSides, &aBorder);
@@ -2924,23 +2929,23 @@ nsCSSRendering::PaintBackgroundWithSC(ns
// If there is no background image, draw a color. (If there is
// neither a background image nor a color, we wouldn't have gotten
// this far.)
if (!drawBackgroundImage) {
if (!isCanvasFrame) {
DrawBackgroundColor(clipState, ctx, appUnitsPerPixel);
}
- return;
+ return DrawResult::SUCCESS;
}
if (bg->mImageCount < 1) {
// Return if there are no background layers, all work from this point
// onwards happens iteratively on these.
- return;
+ return DrawResult::SUCCESS;
}
// Validate the layer range before we start iterating.
int32_t startLayer = aLayer;
int32_t nLayers = 1;
if (startLayer < 0) {
startLayer = (int32_t)bg->mImageCount - 1;
nLayers = bg->mImageCount;
@@ -2999,27 +3004,36 @@ nsCSSRendering::PaintBackgroundWithSC(ns
nsBackgroundLayerState state = PrepareBackgroundLayer(aPresContext, aForFrame,
aFlags, paintBorderArea, clipState.mBGClipArea, layer);
if (!state.mFillArea.IsEmpty()) {
if (state.mCompositingOp != gfxContext::OPERATOR_OVER) {
NS_ASSERTION(ctx->CurrentOperator() == gfxContext::OPERATOR_OVER,
"It is assumed the initial operator is OPERATOR_OVER, when it is restored later");
ctx->SetOperator(state.mCompositingOp);
}
- state.mImageRenderer.DrawBackground(aPresContext, aRenderingContext,
- state.mDestArea, state.mFillArea,
- state.mAnchor + paintBorderArea.TopLeft(),
- clipState.mDirtyRect);
+
+ DrawResult resultForLayer =
+ state.mImageRenderer.DrawBackground(aPresContext, aRenderingContext,
+ state.mDestArea, state.mFillArea,
+ state.mAnchor + paintBorderArea.TopLeft(),
+ clipState.mDirtyRect);
+
+ if (result == DrawResult::SUCCESS) {
+ result = resultForLayer;
+ }
+
if (state.mCompositingOp != gfxContext::OPERATOR_OVER) {
ctx->SetOperator(gfxContext::OPERATOR_OVER);
}
}
}
}
}
+
+ return result;
}
static inline bool
IsTransformed(nsIFrame* aForFrame, nsIFrame* aTopFrame)
{
for (nsIFrame* f = aForFrame; f != aTopFrame; f = f->GetParent()) {
if (f->IsTransformed()) {
return true;
@@ -3328,44 +3342,16 @@ nsCSSRendering::GetBackgroundLayerRect(n
nsRect borderArea =
::BoxDecorationRectForBackground(aForFrame, aBorderArea, skipSides);
nsBackgroundLayerState state =
PrepareBackgroundLayer(aPresContext, aForFrame, aFlags, borderArea,
aClipRect, aLayer);
return state.mFillArea;
}
-/* static */ bool
-nsCSSRendering::IsBackgroundImageDecodedForStyleContextAndLayer(
- const nsStyleBackground *aBackground, uint32_t aLayer)
-{
- const nsStyleImage* image = &aBackground->mLayers[aLayer].mImage;
- if (image->GetType() == eStyleImageType_Image) {
- nsCOMPtr<imgIContainer> img;
- if (NS_SUCCEEDED(image->GetImageData()->GetImage(getter_AddRefs(img)))) {
- if (!img->IsDecoded()) {
- return false;
- }
- }
- }
- return true;
-}
-
-/* static */ bool
-nsCSSRendering::AreAllBackgroundImagesDecodedForFrame(nsIFrame* aFrame)
-{
- const nsStyleBackground *bg = aFrame->StyleContext()->StyleBackground();
- NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
- if (!IsBackgroundImageDecodedForStyleContextAndLayer(bg, i)) {
- return false;
- }
- }
- return true;
-}
-
static void
DrawBorderImage(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aBorderArea,
const nsStyleBorder& aStyleBorder,
const nsRect& aDirtyRect,
Sides aSkipSides)
@@ -4904,62 +4890,62 @@ ConvertImageRendererToDrawFlags(uint32_t
drawFlags |= imgIContainer::FLAG_SYNC_DECODE;
}
if (aImageRendererFlags & nsImageRenderer::FLAG_PAINTING_TO_WINDOW) {
drawFlags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}
return drawFlags;
}
-void
+DrawResult
nsImageRenderer::Draw(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const CSSIntRect& aSrc)
{
if (!mIsReady) {
NS_NOTREACHED("Ensure PrepareImage() has returned true before calling me");
- return;
+ return DrawResult::TEMPORARY_ERROR;
}
if (aDest.IsEmpty() || aFill.IsEmpty() ||
mSize.width <= 0 || mSize.height <= 0) {
- return;
+ return DrawResult::SUCCESS;
}
GraphicsFilter filter = nsLayoutUtils::GetGraphicsFilterForFrame(mForFrame);
switch (mType) {
case eStyleImageType_Image:
{
nsIntSize imageSize(nsPresContext::AppUnitsToIntCSSPixels(mSize.width),
nsPresContext::AppUnitsToIntCSSPixels(mSize.height));
- nsLayoutUtils::DrawBackgroundImage(*aRenderingContext.ThebesContext(),
- aPresContext,
- mImageContainer, imageSize, filter,
- aDest, aFill, aAnchor, aDirtyRect,
- ConvertImageRendererToDrawFlags(mFlags));
- return;
+ return
+ nsLayoutUtils::DrawBackgroundImage(*aRenderingContext.ThebesContext(),
+ aPresContext,
+ mImageContainer, imageSize, filter,
+ aDest, aFill, aAnchor, aDirtyRect,
+ ConvertImageRendererToDrawFlags(mFlags));
}
case eStyleImageType_Gradient:
{
nsCSSRendering::PaintGradient(aPresContext, aRenderingContext,
mGradientData, aDirtyRect,
aDest, aFill, aSrc, mSize);
- return;
+ return DrawResult::SUCCESS;
}
case eStyleImageType_Element:
{
nsRefPtr<gfxDrawable> drawable = DrawableForElement(aDest,
aRenderingContext);
if (!drawable) {
NS_WARNING("Could not create drawable for element");
- return;
+ return DrawResult::TEMPORARY_ERROR;
}
gfxContext* ctx = aRenderingContext.ThebesContext();
gfxContext::GraphicsOperator op = ctx->CurrentOperator();
if (op != gfxContext::OPERATOR_OVER) {
ctx->PushGroup(gfxContentType::COLOR_ALPHA);
ctx->SetOperator(gfxContext::OPERATOR_OVER);
}
@@ -4970,21 +4956,21 @@ nsImageRenderer::Draw(nsPresContext*
filter, aDest, aFill, aAnchor, aDirtyRect,
ConvertImageRendererToDrawFlags(mFlags));
if (op != gfxContext::OPERATOR_OVER) {
ctx->PopGroupToSource();
ctx->Paint();
}
- return;
+ return DrawResult::SUCCESS;
}
case eStyleImageType_Null:
default:
- return;
+ return DrawResult::SUCCESS;
}
}
already_AddRefed<gfxDrawable>
nsImageRenderer::DrawableForElement(const nsRect& aImageRect,
nsRenderingContext& aRenderingContext)
{
NS_ASSERTION(mType == eStyleImageType_Element,
@@ -5007,38 +4993,38 @@ nsImageRenderer::DrawableForElement(cons
}
NS_ASSERTION(mImageElementSurface.mSourceSurface, "Surface should be ready.");
nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(
mImageElementSurface.mSourceSurface,
mImageElementSurface.mSize);
return drawable.forget();
}
-void
+DrawResult
nsImageRenderer::DrawBackground(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty)
{
if (!mIsReady) {
NS_NOTREACHED("Ensure PrepareImage() has returned true before calling me");
- return;
+ return DrawResult::TEMPORARY_ERROR;
}
if (aDest.IsEmpty() || aFill.IsEmpty() ||
mSize.width <= 0 || mSize.height <= 0) {
- return;
+ return DrawResult::SUCCESS;
}
- Draw(aPresContext, aRenderingContext,
- aDirty, aDest, aFill, aAnchor,
- CSSIntRect(0, 0,
- nsPresContext::AppUnitsToIntCSSPixels(mSize.width),
- nsPresContext::AppUnitsToIntCSSPixels(mSize.height)));
+ return Draw(aPresContext, aRenderingContext,
+ aDirty, aDest, aFill, aAnchor,
+ CSSIntRect(0, 0,
+ nsPresContext::AppUnitsToIntCSSPixels(mSize.width),
+ nsPresContext::AppUnitsToIntCSSPixels(mSize.height)));
}
/**
* Compute the size and position of the master copy of the image. I.e., a single
* tile used to fill the dest rect.
* aFill The destination rect to be filled
* aHFill and aVFill are the repeat patterns for the component -
* NS_STYLE_BORDER_IMAGE_REPEAT_* - i.e., how a tiling unit is used to fill aFill
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -5,16 +5,17 @@
/* utility functions for drawing borders and backgrounds */
#ifndef nsCSSRendering_h___
#define nsCSSRendering_h___
#include "gfxBlur.h"
#include "gfxContext.h"
+#include "imgIContainer.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/gfx/Rect.h"
#include "nsLayoutUtils.h"
#include "nsStyleStruct.h"
#include "nsIFrame.h"
class gfxDrawable;
class nsStyleContext;
@@ -104,16 +105,17 @@ struct CSSSizeOrRatio
* nsStyleImage image, which may internally be a real image, a sub image, or a
* CSS gradient.
*
* @note Always call the member functions in the order of PrepareImage(),
* SetSize(), and Draw*().
*/
class nsImageRenderer {
public:
+ typedef mozilla::image::DrawResult DrawResult;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::ImageContainer ImageContainer;
enum {
FLAG_SYNC_DECODE_IMAGES = 0x01,
FLAG_PAINTING_TO_WINDOW = 0x02
};
enum FitType
@@ -197,22 +199,22 @@ public:
void SetPreferredSize(const mozilla::CSSSizeOrRatio& aIntrinsicSize,
const nsSize& aDefaultSize);
/**
* Draws the image to the target rendering context using background-specific
* arguments.
* @see nsLayoutUtils::DrawImage() for parameters.
*/
- void DrawBackground(nsPresContext* aPresContext,
- nsRenderingContext& aRenderingContext,
- const nsRect& aDest,
- const nsRect& aFill,
- const nsPoint& aAnchor,
- const nsRect& aDirty);
+ DrawResult DrawBackground(nsPresContext* aPresContext,
+ nsRenderingContext& aRenderingContext,
+ const nsRect& aDest,
+ const nsRect& aFill,
+ const nsPoint& aAnchor,
+ const nsRect& aDirty);
/**
* Draw the image to a single component of a border-image style rendering.
* aFill The destination rect to be drawn into
* aSrc is the part of the image to be rendered into a tile (aUnitSize in
* aFill), if aSrc and the dest tile are different sizes, the image will be
* scaled to map aSrc onto the dest tile.
* aHFill and aVFill are the repeat patterns for the component -
@@ -242,23 +244,23 @@ public:
private:
/**
* Draws the image to the target rendering context.
* aSrc is a rect on the source image which will be mapped to aDest; it's
* currently only used for gradients.
*
* @see nsLayoutUtils::DrawImage() for other parameters.
*/
- void Draw(nsPresContext* aPresContext,
- nsRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- const nsRect& aDest,
- const nsRect& aFill,
- const nsPoint& aAnchor,
- const mozilla::CSSIntRect& aSrc);
+ DrawResult Draw(nsPresContext* aPresContext,
+ nsRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ const nsRect& aDest,
+ const nsRect& aFill,
+ const nsPoint& aAnchor,
+ const mozilla::CSSIntRect& aSrc);
/**
* Helper method for creating a gfxDrawable from mPaintServerFrame or
* mImageElementSurface.
* Requires mType is eStyleImageType_Element.
* Returns null if we cannot create the drawable.
*/
already_AddRefed<gfxDrawable> DrawableForElement(const nsRect& aImageRect,
@@ -316,16 +318,17 @@ struct nsBackgroundLayerState {
gfxContext::GraphicsOperator mCompositingOp;
};
struct nsCSSRendering {
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::Float Float;
typedef mozilla::gfx::Rect Rect;
typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
+ typedef mozilla::image::DrawResult DrawResult;
typedef nsIFrame::Sides Sides;
/**
* Initialize any static variables used by nsCSSRendering.
*/
static void Init();
/**
@@ -549,70 +552,58 @@ struct nsCSSRendering {
*/
PAINTBG_SYNC_DECODE_IMAGES = 0x02,
/**
* When this flag is passed, painting will go to the screen so we can
* take advantage of the fact that it will be clipped to the viewport.
*/
PAINTBG_TO_WINDOW = 0x04
};
- static void PaintBackground(nsPresContext* aPresContext,
- nsRenderingContext& aRenderingContext,
- nsIFrame* aForFrame,
- const nsRect& aDirtyRect,
- const nsRect& aBorderArea,
- uint32_t aFlags,
- nsRect* aBGClipRect = nullptr,
- int32_t aLayer = -1);
+ static DrawResult PaintBackground(nsPresContext* aPresContext,
+ nsRenderingContext& aRenderingContext,
+ nsIFrame* aForFrame,
+ const nsRect& aDirtyRect,
+ const nsRect& aBorderArea,
+ uint32_t aFlags,
+ nsRect* aBGClipRect = nullptr,
+ int32_t aLayer = -1);
/**
* Same as |PaintBackground|, except using the provided style structs.
* This short-circuits the code that ensures that the root element's
* background is drawn on the canvas.
* The aLayer parameter allows you to paint a single layer of the background.
* The default value for aLayer, -1, means that all layers will be painted.
* The background color will only be painted if the back-most layer is also
* being painted.
*/
- static void PaintBackgroundWithSC(nsPresContext* aPresContext,
- nsRenderingContext& aRenderingContext,
- nsIFrame* aForFrame,
- const nsRect& aDirtyRect,
- const nsRect& aBorderArea,
- nsStyleContext *aStyleContext,
- const nsStyleBorder& aBorder,
- uint32_t aFlags,
- nsRect* aBGClipRect = nullptr,
- int32_t aLayer = -1);
+ static DrawResult PaintBackgroundWithSC(nsPresContext* aPresContext,
+ nsRenderingContext& aRenderingContext,
+ nsIFrame* aForFrame,
+ const nsRect& aDirtyRect,
+ const nsRect& aBorderArea,
+ nsStyleContext *aStyleContext,
+ const nsStyleBorder& aBorder,
+ uint32_t aFlags,
+ nsRect* aBGClipRect = nullptr,
+ int32_t aLayer = -1);
/**
* Returns the rectangle covered by the given background layer image, taking
* into account background positioning, sizing, and repetition, but not
* clipping.
*/
static nsRect GetBackgroundLayerRect(nsPresContext* aPresContext,
nsIFrame* aForFrame,
const nsRect& aBorderArea,
const nsRect& aClipRect,
const nsStyleBackground::Layer& aLayer,
uint32_t aFlags);
/**
- * Checks if image in layer aLayer of aBackground is currently decoded.
- */
- static bool IsBackgroundImageDecodedForStyleContextAndLayer(
- const nsStyleBackground *aBackground, uint32_t aLayer);
-
- /**
- * Checks if all images that are part of the background for aFrame are
- * currently decoded.
- */
- static bool AreAllBackgroundImagesDecodedForFrame(nsIFrame* aFrame);
-
- /**
* Called when we start creating a display list. The frame tree will not
* change until a matching EndFrameTreeLocked is called.
*/
static void BeginFrameTreesLocked();
/**
* Called when we've finished using a display list. When all
* BeginFrameTreeLocked calls have been balanced by an EndFrameTreeLocked,
* the frame tree may start changing again.
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -71,16 +71,17 @@
// GetTickCount().
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::dom;
+using namespace mozilla::image;
using namespace mozilla::layout;
using namespace mozilla::gfx;
typedef FrameMetrics::ViewID ViewID;
#ifdef DEBUG
static bool
SpammyLayoutWarningsEnabled()
@@ -1975,30 +1976,16 @@ nsDisplayItem::nsDisplayItem(nsDisplayLi
NS_ASSERTION(aBuilder->GetDirtyRect().width >= 0 ||
!aBuilder->IsForPainting(), "dirty rect not set");
// The dirty rect is for mCurrentFrame, so we have to use
// mCurrentOffsetToReferenceFrame
mVisibleRect = aBuilder->GetDirtyRect() +
aBuilder->GetCurrentFrameOffsetToReferenceFrame();
}
-void
-nsDisplayItem::AddInvalidRegionForSyncDecodeBackgroundImages(
- nsDisplayListBuilder* aBuilder,
- const nsDisplayItemGeometry* aGeometry,
- nsRegion* aInvalidRegion)
-{
- if (aBuilder->ShouldSyncDecodeImages()) {
- if (!nsCSSRendering::AreAllBackgroundImagesDecodedForFrame(mFrame)) {
- bool snap;
- aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
- }
- }
-}
-
/* static */ bool
nsDisplayItem::ForceActiveLayers()
{
static bool sForce = false;
static bool sForceCached = false;
if (!sForceCached) {
Preferences::AddBoolVarCache(&sForce, "layers.force-active", false);
@@ -2511,16 +2498,21 @@ nsDisplayBackgroundImage::BuildLayer(nsD
void
nsDisplayBackgroundImage::ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset)
{
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
mozilla::gfx::IntSize imageSize = mImageContainer->GetCurrentSize();
NS_ASSERTION(imageSize.width != 0 && imageSize.height != 0, "Invalid image size!");
+ if (imageSize.width > 0 && imageSize.height > 0) {
+ // We're actually using the ImageContainer. Let our frame know that it
+ // should consider itself to have painted successfully.
+ nsDisplayBackgroundGeometry::UpdateDrawResult(this, DrawResult::SUCCESS);
+ }
gfxPoint p = mDestRect.TopLeft() + aOffset;
Matrix transform = Matrix::Translation(p.x, p.y);
transform.PreScale(mDestRect.width / imageSize.width,
mDestRect.height / imageSize.height);
aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
}
@@ -2680,21 +2672,23 @@ nsDisplayBackgroundImage::Paint(nsDispla
void
nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx, const nsRect& aBounds,
nsRect* aClipRect) {
nsPoint offset = ToReferenceFrame();
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
CheckForBorderItem(this, flags);
- nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
- aBounds,
- nsRect(offset, mFrame->GetSize()),
- flags, aClipRect, mLayer);
-
+ DrawResult result =
+ nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
+ aBounds,
+ nsRect(offset, mFrame->GetSize()),
+ flags, aClipRect, mLayer);
+
+ nsDisplayBackgroundGeometry::UpdateDrawResult(this, result);
}
void nsDisplayBackgroundImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion)
{
if (!mBackgroundStyle) {
return;
@@ -2713,18 +2707,19 @@ void nsDisplayBackgroundImage::ComputeIn
aInvalidRegion->Or(bounds, geometry->mBounds);
if (positioningArea.Size() != geometry->mPositioningArea.Size()) {
NotifyRenderingChanged();
}
return;
}
if (aBuilder->ShouldSyncDecodeImages()) {
- if (mBackgroundStyle &&
- !nsCSSRendering::IsBackgroundImageDecodedForStyleContextAndLayer(mBackgroundStyle, mLayer)) {
+ const nsStyleImage& image = mBackgroundStyle->mLayers[mLayer].mImage;
+ if (image.GetType() == eStyleImageType_Image &&
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
aInvalidRegion->Or(*aInvalidRegion, bounds);
NotifyRenderingChanged();
}
}
if (!bounds.IsEqualInterior(geometry->mBounds)) {
// Positioning area is unchanged, so invalidate just the change in the
// painting area.
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1143,26 +1143,16 @@ public:
aInvalidRegion->Or(aGeometry->mBounds, bounds);
} else {
aInvalidRegion->Xor(aGeometry->mBounds, bounds);
}
}
}
/**
- * For display items types that just draw a background we use this function
- * to do any invalidation that might be needed if we are asked to sync decode
- * images.
- */
- void AddInvalidRegionForSyncDecodeBackgroundImages(
- nsDisplayListBuilder* aBuilder,
- const nsDisplayItemGeometry* aGeometry,
- nsRegion* aInvalidRegion);
-
- /**
* Called when the area rendered by this display item has changed (been
* invalidated or changed geometry) since the last paint. This includes
* when the display item was not rendered at all in the last paint.
* It does NOT get called when a display item was being rendered and no
* longer is, because generally that means there is no display item to
* call this method on.
*/
virtual void NotifyRenderingChanged() {}
--- a/layout/base/nsDisplayListInvalidation.cpp
+++ b/layout/base/nsDisplayListInvalidation.cpp
@@ -19,16 +19,22 @@ nsDisplayItemGeometry::~nsDisplayItemGeo
MOZ_COUNT_DTOR(nsDisplayItemGeometry);
}
nsDisplayItemGenericGeometry::nsDisplayItemGenericGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
: nsDisplayItemGeometry(aItem, aBuilder)
, mBorderRect(aItem->GetBorderRect())
{}
+bool
+ShouldSyncDecodeImages(nsDisplayListBuilder* aBuilder)
+{
+ return aBuilder->ShouldSyncDecodeImages();
+}
+
void
nsDisplayItemGenericGeometry::MoveBy(const nsPoint& aOffset)
{
nsDisplayItemGeometry::MoveBy(aOffset);
mBorderRect.MoveBy(aOffset);
}
nsDisplayItemBoundsGeometry::nsDisplayItemBoundsGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
@@ -48,16 +54,17 @@ nsDisplayBorderGeometry::MoveBy(const ns
{
nsDisplayItemGeometry::MoveBy(aOffset);
mContentRect.MoveBy(aOffset);
}
nsDisplayBackgroundGeometry::nsDisplayBackgroundGeometry(nsDisplayBackgroundImage* aItem,
nsDisplayListBuilder* aBuilder)
: nsDisplayItemGeometry(aItem, aBuilder)
+ , nsImageGeometryMixin(aItem, aBuilder)
, mPositioningArea(aItem->GetPositioningArea())
{}
void
nsDisplayBackgroundGeometry::MoveBy(const nsPoint& aOffset)
{
nsDisplayItemGeometry::MoveBy(aOffset);
mPositioningArea.MoveBy(aOffset);
--- a/layout/base/nsDisplayListInvalidation.h
+++ b/layout/base/nsDisplayListInvalidation.h
@@ -69,70 +69,101 @@ class nsDisplayItemGenericGeometry : pub
public:
nsDisplayItemGenericGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
virtual void MoveBy(const nsPoint& aOffset) MOZ_OVERRIDE;
nsRect mBorderRect;
};
+bool ShouldSyncDecodeImages(nsDisplayListBuilder* aBuilder);
+
/**
* nsImageGeometryMixin is a mixin for geometry items that draw images. Geometry
* items that include this mixin can track drawing results and use that
* information to inform invalidation decisions.
*
* This mixin uses CRTP; its template parameter should be the type of the class
* that is inheriting from it. See nsDisplayItemGenericImageGeometry for an
* example.
*/
template <typename T>
class nsImageGeometryMixin
{
public:
- explicit nsImageGeometryMixin(nsDisplayItem* aItem)
+ nsImageGeometryMixin(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
: mLastDrawResult(mozilla::image::DrawResult::NOT_READY)
+ , mWaitingForPaint(false)
{
+ // Transfer state from the previous version of this geometry item.
auto lastGeometry =
static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
if (lastGeometry) {
- mLastDrawResult = lastGeometry->LastDrawResult();
+ mLastDrawResult = lastGeometry->mLastDrawResult;
+ mWaitingForPaint = lastGeometry->mWaitingForPaint;
+ }
+
+ // If our display item is going to invalidate to trigger sync decoding of
+ // images, mark ourselves as waiting for a paint. If we actually get
+ // painted, UpdateDrawResult will get called, and we'll clear the flag.
+ if (ShouldSyncDecodeImages(aBuilder) &&
+ ShouldInvalidateToSyncDecodeImages()) {
+ mWaitingForPaint = true;
}
}
static void UpdateDrawResult(nsDisplayItem* aItem,
mozilla::image::DrawResult aResult)
{
auto lastGeometry =
static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
if (lastGeometry) {
lastGeometry->mLastDrawResult = aResult;
+ lastGeometry->mWaitingForPaint = false;
}
}
- mozilla::image::DrawResult LastDrawResult() const { return mLastDrawResult; }
+ bool ShouldInvalidateToSyncDecodeImages() const
+ {
+ if (mWaitingForPaint) {
+ // We previously invalidated for sync decoding and haven't gotten painted
+ // since them. This suggests that our display item is completely occluded
+ // and there's no point in invalidating again - and because the reftest
+ // harness takes a new snapshot every time we invalidate, doing so might
+ // lead to an invalidation loop if we're in a reftest.
+ return false;
+ }
+
+ if (mLastDrawResult == mozilla::image::DrawResult::SUCCESS) {
+ return false;
+ }
+
+ return true;
+ }
private:
mozilla::image::DrawResult mLastDrawResult;
+ bool mWaitingForPaint;
};
/**
* nsDisplayItemGenericImageGeometry is a generic geometry item class that
* includes nsImageGeometryMixin.
*
* This should be sufficient for most display items that draw images.
*/
class nsDisplayItemGenericImageGeometry
: public nsDisplayItemGenericGeometry
, public nsImageGeometryMixin<nsDisplayItemGenericImageGeometry>
{
public:
nsDisplayItemGenericImageGeometry(nsDisplayItem* aItem,
nsDisplayListBuilder* aBuilder)
: nsDisplayItemGenericGeometry(aItem, aBuilder)
- , nsImageGeometryMixin(aItem)
+ , nsImageGeometryMixin(aItem, aBuilder)
{ }
};
class nsDisplayItemBoundsGeometry : public nsDisplayItemGeometry
{
public:
nsDisplayItemBoundsGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
@@ -144,17 +175,19 @@ class nsDisplayBorderGeometry : public n
public:
nsDisplayBorderGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
virtual void MoveBy(const nsPoint& aOffset) MOZ_OVERRIDE;
nsRect mContentRect;
};
-class nsDisplayBackgroundGeometry : public nsDisplayItemGeometry
+class nsDisplayBackgroundGeometry
+ : public nsDisplayItemGeometry
+ , public nsImageGeometryMixin<nsDisplayBackgroundGeometry>
{
public:
nsDisplayBackgroundGeometry(nsDisplayBackgroundImage* aItem, nsDisplayListBuilder* aBuilder);
virtual void MoveBy(const nsPoint& aOffset) MOZ_OVERRIDE;
nsRect mPositioningArea;
};
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -14,16 +14,18 @@
#include "nsFrame.h"
#include "mozilla/EventStates.h"
#include "mozilla/dom/Element.h"
#define ACTIVE "active"
#define HOVER "hover"
#define FOCUS "focus"
+using namespace mozilla::image;
+
nsButtonFrameRenderer::nsButtonFrameRenderer()
{
MOZ_COUNT_CTOR(nsButtonFrameRenderer);
}
nsButtonFrameRenderer::~nsButtonFrameRenderer()
{
MOZ_COUNT_DTOR(nsButtonFrameRenderer);
@@ -125,16 +127,17 @@ public:
HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE {
aOutFrames->AppendElement(mFrame);
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) MOZ_OVERRIDE;
+ virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("ButtonBorderBackground", TYPE_BUTTON_BORDER_BACKGROUND)
private:
nsButtonFrameRenderer* mBFR;
};
@@ -160,36 +163,52 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("ButtonForeground", TYPE_BUTTON_FOREGROUND)
private:
nsButtonFrameRenderer* mBFR;
};
+nsDisplayItemGeometry*
+nsDisplayButtonBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+ return new nsDisplayItemGenericImageGeometry(this, aBuilder);
+}
+
void
nsDisplayButtonBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion)
{
- AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion);
+ auto geometry =
+ static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+ if (aBuilder->ShouldSyncDecodeImages() &&
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
+ bool snap;
+ aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
+ }
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
void nsDisplayButtonBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
NS_ASSERTION(mFrame, "No frame?");
nsPresContext* pc = mFrame->PresContext();
nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
// draw the border and background inside the focus and outline borders
- mBFR->PaintBorderAndBackground(pc, *aCtx, mVisibleRect, r,
- aBuilder->GetBackgroundPaintFlags());
+ DrawResult result =
+ mBFR->PaintBorderAndBackground(pc, *aCtx, mVisibleRect, r,
+ aBuilder->GetBackgroundPaintFlags());
+
+ nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
}
void nsDisplayButtonForeground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
nsPresContext *presContext = mFrame->PresContext();
const nsStyleDisplay *disp = mFrame->StyleDisplay();
if (!mFrame->IsThemed(disp) ||
@@ -255,36 +274,39 @@ nsButtonFrameRenderer::PaintOutlineAndFo
GetButtonInnerFocusRect(aRect, rect);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
aDirtyRect, rect, mInnerFocusStyle);
}
}
-void
+DrawResult
nsButtonFrameRenderer::PaintBorderAndBackground(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aRect,
uint32_t aBGFlags)
{
// get the button rect this is inside the focus and outline rects
nsRect buttonRect;
GetButtonRect(aRect, buttonRect);
nsStyleContext* context = mFrame->StyleContext();
- nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, mFrame,
- aDirtyRect, buttonRect, aBGFlags);
+ DrawResult result =
+ nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, mFrame,
+ aDirtyRect, buttonRect, aBGFlags);
nsCSSRendering::PaintBoxShadowInner(aPresContext, aRenderingContext,
mFrame, buttonRect, aDirtyRect);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
aDirtyRect, buttonRect, context);
+
+ return result;
}
void
nsButtonFrameRenderer::GetButtonOuterFocusRect(const nsRect& aRect, nsRect& focusRect)
{
focusRect = aRect;
}
--- a/layout/forms/nsButtonFrameRenderer.h
+++ b/layout/forms/nsButtonFrameRenderer.h
@@ -1,16 +1,17 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsButtonFrameRenderer_h___
#define nsButtonFrameRenderer_h___
+#include "imgIContainer.h"
#include "nsAutoPtr.h"
#include "nsMargin.h"
class nsIFrame;
class nsFrame;
class nsDisplayList;
class nsDisplayListBuilder;
class nsPresContext;
@@ -19,16 +20,18 @@ struct nsRect;
class nsStyleContext;
#define NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX 0
#define NS_BUTTON_RENDERER_FOCUS_OUTER_CONTEXT_INDEX 1
#define NS_BUTTON_RENDERER_LAST_CONTEXT_INDEX NS_BUTTON_RENDERER_FOCUS_OUTER_CONTEXT_INDEX
class nsButtonFrameRenderer {
+ typedef mozilla::image::DrawResult DrawResult;
+
public:
nsButtonFrameRenderer();
~nsButtonFrameRenderer();
/**
* Create display list items for the button
*/
@@ -36,21 +39,21 @@ public:
nsDisplayList* aBackground, nsDisplayList* aForeground);
void PaintOutlineAndFocusBorders(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aRect);
- void PaintBorderAndBackground(nsPresContext* aPresContext,
- nsRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- const nsRect& aRect,
- uint32_t aBGFlags);
+ DrawResult PaintBorderAndBackground(nsPresContext* aPresContext,
+ nsRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ const nsRect& aRect,
+ uint32_t aBGFlags);
void SetFrame(nsFrame* aFrame, nsPresContext* aPresContext);
void SetDisabled(bool aDisabled, bool notify);
bool isActive();
bool isDisabled();
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -19,16 +19,17 @@
#include "nsDisplayList.h"
#include "nsRenderingContext.h"
#include "nsIScrollableFrame.h"
#include "mozilla/Likely.h"
#include "mozilla/Maybe.h"
using namespace mozilla;
using namespace mozilla::gfx;
+using namespace mozilla::image;
using namespace mozilla::layout;
nsContainerFrame*
NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsFieldSetFrame(aContext);
}
@@ -97,16 +98,17 @@ public:
}
#endif
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
+ virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("FieldSetBorderBackground", TYPE_FIELDSET_BORDER_BACKGROUND)
};
void nsDisplayFieldSetBorderBackground::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
@@ -116,27 +118,42 @@ void nsDisplayFieldSetBorderBackground::
// It's not clear whether this is correct.
aOutFrames->AppendElement(mFrame);
}
void
nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
- static_cast<nsFieldSetFrame*>(mFrame)->
+ DrawResult result = static_cast<nsFieldSetFrame*>(mFrame)->
PaintBorderBackground(*aCtx, ToReferenceFrame(),
mVisibleRect, aBuilder->GetBackgroundPaintFlags());
+
+ nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+}
+
+nsDisplayItemGeometry*
+nsDisplayFieldSetBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+ return new nsDisplayItemGenericImageGeometry(this, aBuilder);
}
void
nsDisplayFieldSetBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion)
{
- AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion);
+ auto geometry =
+ static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+ if (aBuilder->ShouldSyncDecodeImages() &&
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
+ bool snap;
+ aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
+ }
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
void
nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) {
@@ -183,31 +200,32 @@ nsFieldSetFrame::BuildDisplayList(nsDisp
}
// Put the inner frame's display items on the master list. Note that this
// moves its border/background display items to our BorderBackground() list,
// which isn't really correct, but it's OK because the inner frame is
// anonymous and can't have its own border and background.
contentDisplayItems.MoveTo(aLists);
}
-void
+DrawResult
nsFieldSetFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext,
nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags)
{
// if the border is smaller than the legend. Move the border down
// to be centered on the legend.
// FIXME: This means border-radius clamping is incorrect; we should
// override nsIFrame::GetBorderRadii.
nsRect rect = VisualBorderRectRelativeToSelf();
nscoord yoff = rect.y;
rect += aPt;
nsPresContext* presContext = PresContext();
- nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
- aDirtyRect, rect, aBGFlags);
+ DrawResult result =
+ nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
+ aDirtyRect, rect, aBGFlags);
nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext,
this, rect, aDirtyRect);
if (nsIFrame* legend = GetLegend()) {
nscoord topBorder = StyleBorder()->GetComputedBorderWidth(NS_SIDE_TOP);
// Use the rect of the legend frame, not mLegendRect, so we draw our
@@ -258,16 +276,18 @@ nsFieldSetFrame::PaintBorderBackground(n
gfx->Restore();
} else {
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
aDirtyRect,
nsRect(aPt, mRect.Size()),
mStyleContext);
}
+
+ return result;
}
nscoord
nsFieldSetFrame::GetIntrinsicISize(nsRenderingContext* aRenderingContext,
nsLayoutUtils::IntrinsicISizeType aType)
{
nscoord legendWidth = 0;
nscoord contentWidth = 0;
--- a/layout/forms/nsFieldSetFrame.h
+++ b/layout/forms/nsFieldSetFrame.h
@@ -2,20 +2,23 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsFieldSetFrame_h___
#define nsFieldSetFrame_h___
#include "mozilla/Attributes.h"
+#include "imgIContainer.h"
#include "nsContainerFrame.h"
class nsFieldSetFrame MOZ_FINAL : public nsContainerFrame
{
+ typedef mozilla::image::DrawResult DrawResult;
+
public:
NS_DECL_FRAMEARENA_HELPERS
explicit nsFieldSetFrame(nsStyleContext* aContext);
nscoord
GetIntrinsicISize(nsRenderingContext* aRenderingContext,
nsLayoutUtils::IntrinsicISizeType);
@@ -42,18 +45,19 @@ public:
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus) MOZ_OVERRIDE;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
- void PaintBorderBackground(nsRenderingContext& aRenderingContext,
- nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags);
+ DrawResult PaintBorderBackground(nsRenderingContext& aRenderingContext,
+ nsPoint aPt, const nsRect& aDirtyRect,
+ uint32_t aBGFlags);
#ifdef DEBUG
virtual void SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList) MOZ_OVERRIDE;
virtual void AppendFrames(ChildListID aListID,
nsFrameList& aFrameList) MOZ_OVERRIDE;
virtual void InsertFrames(ChildListID aListID,
nsIFrame* aPrevFrame,
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -172,17 +172,17 @@ nsBulletFrame::DidSetStyleContext(nsStyl
class nsDisplayBulletGeometry
: public nsDisplayItemGenericGeometry
, public nsImageGeometryMixin<nsDisplayBulletGeometry>
{
public:
nsDisplayBulletGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
: nsDisplayItemGenericGeometry(aItem, aBuilder)
- , nsImageGeometryMixin(aItem)
+ , nsImageGeometryMixin(aItem, aBuilder)
{
nsBulletFrame* f = static_cast<nsBulletFrame*>(aItem->Frame());
mOrdinal = f->GetOrdinal();
}
int32_t mOrdinal;
};
@@ -234,17 +234,17 @@ public:
if (f->GetOrdinal() != geometry->mOrdinal) {
bool snap;
aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
return;
}
nsCOMPtr<imgIContainer> image = f->GetImage();
if (aBuilder->ShouldSyncDecodeImages() && image &&
- geometry->LastDrawResult() != DrawResult::SUCCESS) {
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
bool snap;
aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
}
return nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
};
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1377,17 +1377,17 @@ void
nsDisplayImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion)
{
auto geometry =
static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
if (aBuilder->ShouldSyncDecodeImages() &&
- geometry->LastDrawResult() != DrawResult::SUCCESS) {
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
bool snap;
aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
}
nsDisplayImageContainer::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
already_AddRefed<ImageContainer>
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -36,16 +36,17 @@
#include "nsMathMLOperators.h"
#include <algorithm>
#include "gfxMathTable.h"
#include "nsUnicodeScriptCodes.h"
using namespace mozilla;
using namespace mozilla::gfx;
+using namespace mozilla::image;
//#define NOISY_SEARCH 1
// BUG 848725 Drawing failure with stretchy horizontal parenthesis when no fonts
// are installed. "kMaxScaleFactor" is required to limit the scale for the
// vertical and horizontal stretchy operators.
static const float kMaxScaleFactor = 20.0;
static const float kLargeOpFactor = float(M_SQRT2);
@@ -1880,46 +1881,64 @@ public:
MOZ_COUNT_CTOR(nsDisplayMathMLCharBackground);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayMathMLCharBackground() {
MOZ_COUNT_DTOR(nsDisplayMathMLCharBackground);
}
#endif
+ virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) MOZ_OVERRIDE;
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("MathMLCharBackground", TYPE_MATHML_CHAR_BACKGROUND)
private:
nsStyleContext* mStyleContext;
nsRect mRect;
};
+nsDisplayItemGeometry*
+nsDisplayMathMLCharBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+ return new nsDisplayItemGenericImageGeometry(this, aBuilder);
+}
+
void
nsDisplayMathMLCharBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion)
{
- AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion);
+ auto geometry =
+ static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+ if (aBuilder->ShouldSyncDecodeImages() &&
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
+ bool snap;
+ aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
+ }
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
void nsDisplayMathMLCharBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
const nsStyleBorder* border = mStyleContext->StyleBorder();
nsRect rect(mRect + ToReferenceFrame());
- nsCSSRendering::PaintBackgroundWithSC(mFrame->PresContext(), *aCtx, mFrame,
- mVisibleRect, rect,
- mStyleContext, *border,
- aBuilder->GetBackgroundPaintFlags());
+
+ DrawResult result =
+ nsCSSRendering::PaintBackgroundWithSC(mFrame->PresContext(), *aCtx, mFrame,
+ mVisibleRect, rect,
+ mStyleContext, *border,
+ aBuilder->GetBackgroundPaintFlags());
+
+ nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
}
class nsDisplayMathMLCharForeground : public nsDisplayItem {
public:
nsDisplayMathMLCharForeground(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsMathMLChar* aChar,
uint32_t aIndex, bool aIsSelected)
: nsDisplayItem(aBuilder, aFrame), mChar(aChar),
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -35,16 +35,17 @@
#include <algorithm>
//TABLECELL SELECTION
#include "nsFrameSelection.h"
#include "mozilla/LookAndFeel.h"
using namespace mozilla;
using namespace mozilla::gfx;
+using namespace mozilla::image;
nsTableCellFrame::nsTableCellFrame(nsStyleContext* aContext) :
nsContainerFrame(aContext)
, mDesiredSize(GetWritingMode())
{
mColIndex = 0;
mPriorAvailWidth = 0;
@@ -358,37 +359,38 @@ nsTableCellFrame::DecorateForSelection(n
StrokeLineWithSnapping(nsPoint(mRect.width - (2*onePixel), 2*onePixel),
nsPoint(mRect.width - (2*onePixel), mRect.height-onePixel),
appUnitsPerDevPixel, *drawTarget, color);
}
}
}
}
-void
+DrawResult
nsTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsPoint aPt,
uint32_t aFlags)
{
nsRect rect(aPt, GetSize());
- nsCSSRendering::PaintBackground(PresContext(), aRenderingContext, this,
- aDirtyRect, rect, aFlags);
+ return nsCSSRendering::PaintBackground(PresContext(), aRenderingContext, this,
+ aDirtyRect, rect, aFlags);
}
// Called by nsTablePainter
-void
+DrawResult
nsTableCellFrame::PaintCellBackground(nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt,
uint32_t aFlags)
{
- if (!StyleVisibility()->IsVisible())
- return;
+ if (!StyleVisibility()->IsVisible()) {
+ return DrawResult::SUCCESS;
+ }
- PaintBackground(aRenderingContext, aDirtyRect, aPt, aFlags);
+ return PaintBackground(aRenderingContext, aDirtyRect, aPt, aFlags);
}
nsresult
nsTableCellFrame::ProcessBorders(nsTableFrame* aFrame,
nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
const nsStyleBorder* borderStyle = StyleBorder();
@@ -421,50 +423,61 @@ public:
HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE {
aOutFrames->AppendElement(mFrame);
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) MOZ_OVERRIDE;
+ virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("TableCellBackground", TYPE_TABLE_CELL_BACKGROUND)
};
void nsDisplayTableCellBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
- static_cast<nsTableCellFrame*>(mFrame)->
+ DrawResult result = static_cast<nsTableCellFrame*>(mFrame)->
PaintBackground(*aCtx, mVisibleRect, ToReferenceFrame(),
aBuilder->GetBackgroundPaintFlags());
+
+ nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
}
nsRect
nsDisplayTableCellBackground::GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap)
{
// revert from nsDisplayTableItem's implementation ... cell backgrounds
// don't overflow the cell
return nsDisplayItem::GetBounds(aBuilder, aSnap);
}
+nsDisplayItemGeometry*
+nsDisplayTableCellBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+ return new nsDisplayItemGenericImageGeometry(this, aBuilder);
+}
+
void
nsDisplayTableCellBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion)
{
- if (aBuilder->ShouldSyncDecodeImages()) {
- if (!nsCSSRendering::AreAllBackgroundImagesDecodedForFrame(mFrame)) {
- bool snap;
- aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
- }
+ auto geometry =
+ static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+ if (aBuilder->ShouldSyncDecodeImages() &&
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
+ bool snap;
+ aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
}
nsDisplayTableItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
void nsTableCellFrame::InvalidateFrame(uint32_t aDisplayItemKey)
{
nsIFrame::InvalidateFrame(aDisplayItemKey);
@@ -1214,17 +1227,17 @@ nsBCTableCellFrame::GetBorderOverflow()
halfBorder.top = BC_BORDER_TOP_HALF_COORD(p2t, mTopBorder);
halfBorder.right = BC_BORDER_RIGHT_HALF_COORD(p2t, mRightBorder);
halfBorder.bottom = BC_BORDER_BOTTOM_HALF_COORD(p2t, mBottomBorder);
halfBorder.left = BC_BORDER_LEFT_HALF_COORD(p2t, mLeftBorder);
return halfBorder;
}
-void
+DrawResult
nsBCTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsPoint aPt,
uint32_t aFlags)
{
// make border-width reflect the half of the border-collapse
// assigned border that's inside the cell
nsMargin borderWidth;
@@ -1234,13 +1247,13 @@ nsBCTableCellFrame::PaintBackground(nsRe
NS_FOR_CSS_SIDES(side) {
myBorder.SetBorderWidth(side, borderWidth.Side(side));
}
nsRect rect(aPt, GetSize());
// bypassing nsCSSRendering::PaintBackground is safe because this kind
// of frame cannot be used for the root element
- nsCSSRendering::PaintBackgroundWithSC(PresContext(), aRenderingContext, this,
- aDirtyRect, rect,
- StyleContext(), myBorder,
- aFlags, nullptr);
+ return nsCSSRendering::PaintBackgroundWithSC(PresContext(), aRenderingContext,
+ this, aDirtyRect, rect,
+ StyleContext(), myBorder,
+ aFlags, nullptr);
}
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -2,16 +2,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsTableCellFrame_h__
#define nsTableCellFrame_h__
#include "mozilla/Attributes.h"
#include "celldata.h"
+#include "imgIContainer.h"
#include "nsITableCellLayout.h"
#include "nscore.h"
#include "nsContainerFrame.h"
#include "nsStyleContext.h"
#include "nsIPercentHeightObserver.h"
#include "nsGkAtoms.h"
#include "nsLayoutUtils.h"
#include "nsTArray.h"
@@ -28,16 +29,18 @@ class nsTableFrame;
* no actual support is under the hood.
*
* @author sclark
*/
class nsTableCellFrame : public nsContainerFrame,
public nsITableCellLayout,
public nsIPercentHeightObserver
{
+ typedef mozilla::image::DrawResult DrawResult;
+
public:
NS_DECL_QUERYFRAME_TARGET(nsTableCellFrame)
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS
// default constructor supplied by the compiler
explicit nsTableCellFrame(nsStyleContext* aContext);
@@ -88,19 +91,19 @@ public:
* @return the frame that was created
*/
friend nsIFrame* NS_NewTableCellFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
- void PaintCellBackground(nsRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect, nsPoint aPt,
- uint32_t aFlags);
+ DrawResult PaintCellBackground(nsRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect, nsPoint aPt,
+ uint32_t aFlags);
virtual nsresult ProcessBorders(nsTableFrame* aFrame,
nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists);
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
@@ -197,20 +200,20 @@ public:
bool HasPctOverHeight();
void SetHasPctOverHeight(bool aValue);
nsTableCellFrame* GetNextCell() const;
virtual nsMargin* GetBorderWidth(nsMargin& aBorder) const;
- virtual void PaintBackground(nsRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- nsPoint aPt,
- uint32_t aFlags);
+ virtual DrawResult PaintBackground(nsRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ nsPoint aPt,
+ uint32_t aFlags);
void DecorateForSelection(nsRenderingContext& aRenderingContext,
nsPoint aPt);
virtual bool UpdateOverflow() MOZ_OVERRIDE;
virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
{
@@ -284,16 +287,17 @@ inline void nsTableCellFrame::SetHasPctO
} else {
mState &= ~NS_TABLE_CELL_HAS_PCT_OVER_HEIGHT;
}
}
// nsBCTableCellFrame
class nsBCTableCellFrame MOZ_FINAL : public nsTableCellFrame
{
+ typedef mozilla::image::DrawResult DrawResult;
public:
NS_DECL_FRAMEARENA_HELPERS
explicit nsBCTableCellFrame(nsStyleContext* aContext);
~nsBCTableCellFrame();
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
@@ -314,20 +318,20 @@ public:
void SetBorderWidth(mozilla::css::Side aSide, BCPixelSize aPixelValue);
virtual nsMargin GetBorderOverflow() MOZ_OVERRIDE;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
#endif
- virtual void PaintBackground(nsRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- nsPoint aPt,
- uint32_t aFlags) MOZ_OVERRIDE;
+ virtual DrawResult PaintBackground(nsRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ nsPoint aPt,
+ uint32_t aFlags) MOZ_OVERRIDE;
private:
// These are the entire width of the border (the cell edge contains only
// the inner half, per the macros in nsTablePainter.h).
BCPixelSize mTopBorder;
BCPixelSize mRightBorder;
BCPixelSize mBottomBorder;
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -42,16 +42,17 @@
#include "nsStyleSet.h"
#include "nsDisplayList.h"
#include "nsIScrollableFrame.h"
#include "nsCSSProps.h"
#include "RestyleTracker.h"
#include <algorithm>
using namespace mozilla;
+using namespace mozilla::image;
using namespace mozilla::layout;
/********************************************************************************
** nsTableReflowState **
********************************************************************************/
struct nsTableReflowState {
@@ -1109,16 +1110,17 @@ public:
MOZ_COUNT_CTOR(nsDisplayTableBorderBackground);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayTableBorderBackground() {
MOZ_COUNT_DTOR(nsDisplayTableBorderBackground);
}
#endif
+ virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) MOZ_OVERRIDE;
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND)
};
@@ -1131,62 +1133,49 @@ IsFrameAllowedInTable(nsIAtom* aType)
nsGkAtoms::tableRowGroupFrame == aType ||
nsGkAtoms::scrollFrame == aType ||
nsGkAtoms::tableFrame == aType ||
nsGkAtoms::tableColFrame == aType ||
nsGkAtoms::tableColGroupFrame == aType;
}
#endif
-/* static */ bool
-nsTableFrame::AnyTablePartHasUndecodedBackgroundImage(nsIFrame* aStart,
- nsIFrame* aEnd)
-{
- for (nsIFrame* f = aStart; f != aEnd; f = f->GetNextSibling()) {
- NS_ASSERTION(IsFrameAllowedInTable(f->GetType()), "unexpected frame type");
-
- if (!nsCSSRendering::AreAllBackgroundImagesDecodedForFrame(f))
- return true;
-
- nsTableCellFrame *cellFrame = do_QueryFrame(f);
- if (cellFrame)
- continue;
-
- if (AnyTablePartHasUndecodedBackgroundImage(f->PrincipalChildList().FirstChild(), nullptr))
- return true;
- }
-
- return false;
+nsDisplayItemGeometry*
+nsDisplayTableBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+ return new nsDisplayItemGenericImageGeometry(this, aBuilder);
}
void
nsDisplayTableBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion)
{
- if (aBuilder->ShouldSyncDecodeImages()) {
- if (nsTableFrame::AnyTablePartHasUndecodedBackgroundImage(mFrame, mFrame->GetNextSibling()) ||
- nsTableFrame::AnyTablePartHasUndecodedBackgroundImage(
- mFrame->GetChildList(nsIFrame::kColGroupList).FirstChild(), nullptr)) {
- bool snap;
- aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
- }
+ auto geometry =
+ static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+ if (aBuilder->ShouldSyncDecodeImages() &&
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
+ bool snap;
+ aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
}
nsDisplayTableItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
void
nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
- static_cast<nsTableFrame*>(mFrame)->
+ DrawResult result = static_cast<nsTableFrame*>(mFrame)->
PaintTableBorderBackground(*aCtx, mVisibleRect,
ToReferenceFrame(),
aBuilder->GetBackgroundPaintFlags());
+
+ nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
}
static int32_t GetTablePartRank(nsDisplayItem* aItem)
{
nsIAtom* type = aItem->Frame()->GetType();
if (type == nsGkAtoms::tableFrame)
return 0;
if (type == nsGkAtoms::tableRowGroupFrame)
@@ -1347,31 +1336,31 @@ nsTableFrame::GetDeflationForBackground(
!IsBorderCollapse())
return nsMargin(0,0,0,0);
return GetOuterBCBorder();
}
// XXX We don't put the borders and backgrounds in tree order like we should.
// That requires some major surgery which we aren't going to do right now.
-void
+DrawResult
nsTableFrame::PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsPoint aPt, uint32_t aBGPaintFlags)
{
nsPresContext* presContext = PresContext();
TableBackgroundPainter painter(this, TableBackgroundPainter::eOrigin_Table,
presContext, aRenderingContext,
aDirtyRect, aPt, aBGPaintFlags);
nsMargin deflate = GetDeflationForBackground(presContext);
// If 'deflate' is (0,0,0,0) then we'll paint the table background
// in a separate display item, so don't do it here.
- nsresult rv = painter.PaintTable(this, deflate, deflate != nsMargin(0, 0, 0, 0));
- if (NS_FAILED(rv)) return;
+ DrawResult result =
+ painter.PaintTable(this, deflate, deflate != nsMargin(0, 0, 0, 0));
if (StyleVisibility()->IsVisible()) {
if (!IsBorderCollapse()) {
Sides skipSides = GetSkipSides();
nsRect rect(aPt, mRect.Size());
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
aDirtyRect, rect, mStyleContext, skipSides);
}
@@ -1385,16 +1374,18 @@ nsTableFrame::PaintTableBorderBackground
// XXX we should probably get rid of this translation at some stage
// But that would mean modifying PaintBCBorders, ugh
gfxContextMatrixAutoSaveRestore autoSR(ctx);
ctx->SetMatrix(ctx->CurrentMatrix().Translate(devPixelOffset));
PaintBCBorders(aRenderingContext, aDirtyRect - aPt);
}
}
+
+ return result;
}
nsIFrame::LogicalSides
nsTableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
{
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
return LogicalSides();
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -2,16 +2,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsTableFrame_h__
#define nsTableFrame_h__
#include "mozilla/Attributes.h"
#include "celldata.h"
+#include "imgIContainer.h"
#include "nscore.h"
#include "nsContainerFrame.h"
#include "nsStyleCoord.h"
#include "nsStyleConsts.h"
#include "nsTableColFrame.h"
#include "nsTableColGroupFrame.h"
#include "nsCellMap.h"
#include "nsGkAtoms.h"
@@ -101,16 +102,18 @@ private:
* Used as a pseudo-frame within nsTableOuterFrame, it may also be used
* stand-alone as the top-level frame.
*
* The principal child list contains row group frames. There is also an
* additional child list, kColGroupList, which contains the col group frames.
*/
class nsTableFrame : public nsContainerFrame
{
+ typedef mozilla::image::DrawResult DrawResult;
+
public:
NS_DECL_FRAMEARENA_HELPERS
static void DestroyPositionedTablePartArray(void* aPropertyValue);
NS_DECLARE_FRAME_PROPERTY(PositionedTablePartArray, DestroyPositionedTablePartArray)
/** nsTableOuterFrame has intimate knowledge of the inner table frame */
friend class nsTableOuterFrame;
@@ -241,26 +244,19 @@ public:
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
/**
* Paint the background of the table and its parts (column groups,
* columns, row groups, rows, and cells), and the table border, and all
* internal borders if border-collapse is on.
*/
- void PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- nsPoint aPt, uint32_t aBGPaintFlags);
-
- /**
- * Determines if any table part has a background image that is currently not
- * decoded. Does not look into cell contents (ie only table parts).
- */
- static bool AnyTablePartHasUndecodedBackgroundImage(nsIFrame* aStart,
- nsIFrame* aEnd);
+ DrawResult PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ nsPoint aPt, uint32_t aBGPaintFlags);
/** Get the outer half (i.e., the part outside the height and width of
* the table) of the largest segment (?) of border-collapsed border on
* the table on each side, or 0 for non border-collapsed tables.
*/
nsMargin GetOuterBCBorder() const;
/** Same as above, but only if it's included from the border-box width
--- a/layout/tables/nsTablePainter.cpp
+++ b/layout/tables/nsTablePainter.cpp
@@ -92,16 +92,18 @@
Elements with stacking contexts set up their own painter to finish the
painting process, since they were skipped. They call the appropriate
sub-part of the loop (e.g. PaintRow) which will paint the frame and
descendants.
XXX views are going
*/
+using namespace mozilla::image;
+
TableBackgroundPainter::TableBackgroundData::TableBackgroundData()
: mFrame(nullptr),
mVisible(false),
mBorder(nullptr),
mSynthBorder(nullptr)
{
MOZ_COUNT_CTOR(TableBackgroundData);
}
@@ -168,33 +170,31 @@ TableBackgroundPainter::TableBackgroundD
const nsStyleBackground *bg = mFrame->StyleBackground();
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
if (!bg->mLayers[i].mImage.IsEmpty())
return true;
}
return false;
}
-nsresult
+void
TableBackgroundPainter::TableBackgroundData::SetBCBorder(nsMargin& aBorder,
TableBackgroundPainter* aPainter)
{
- NS_PRECONDITION(aPainter, "null painter");
+ MOZ_ASSERT(aPainter);
if (!mSynthBorder) {
mSynthBorder = new (aPainter->mPresContext)
nsStyleBorder(aPainter->mZeroBorder);
- if (!mSynthBorder) return NS_ERROR_OUT_OF_MEMORY;
}
NS_FOR_CSS_SIDES(side) {
mSynthBorder->SetBorderWidth(side, aBorder.Side(side));
}
mBorder = mSynthBorder;
- return NS_OK;
}
TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame,
Origin aOrigin,
nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsPoint& aRenderPt,
@@ -240,23 +240,33 @@ TableBackgroundPainter::~TableBackground
}
delete [] mCols;
}
mRowGroup.Destroy(mPresContext);
mRow.Destroy(mPresContext);
MOZ_COUNT_DTOR(TableBackgroundPainter);
}
-nsresult
+static void UpdateDrawResult(DrawResult* aCurrentResult,
+ DrawResult aNewResult)
+{
+ MOZ_ASSERT(aCurrentResult);
+ if (*aCurrentResult == DrawResult::SUCCESS) {
+ *aCurrentResult = aNewResult;
+ }
+}
+
+DrawResult
TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame,
nsTableRowGroupFrame* aFirstRowGroup,
nsTableRowGroupFrame* aLastRowGroup,
const nsMargin& aDeflate)
{
- NS_PRECONDITION(aTableFrame, "null frame");
+ MOZ_ASSERT(aTableFrame);
+
TableBackgroundData tableData;
tableData.SetFull(aTableFrame);
tableData.mRect.MoveTo(0,0); //using table's coords
tableData.mRect.Deflate(aDeflate);
if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) {
if (aFirstRowGroup && aLastRowGroup && mNumCols > 0) {
//only handle non-degenerate tables; we need a more robust BC model
//to make degenerate tables' borders reasonable to deal with
@@ -273,33 +283,35 @@ TableBackgroundPainter::PaintTableFrame(
nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow();
if (rowFrame) {
rowFrame->GetContinuousBCBorderWidth(tempBorder);
border.top = tempBorder.top;
}
border.left = aTableFrame->GetContinuousLeftBCBorderWidth();
- nsresult rv = tableData.SetBCBorder(border, this);
- if (NS_FAILED(rv)) {
- tableData.Destroy(mPresContext);
- return rv;
- }
+ tableData.SetBCBorder(border, this);
}
}
+
+ DrawResult result = DrawResult::SUCCESS;
+
if (tableData.IsVisible()) {
- nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
- tableData.mFrame, mDirtyRect,
- tableData.mRect + mRenderPt,
- tableData.mFrame->StyleContext(),
- *tableData.mBorder,
- mBGPaintFlags);
+ result =
+ nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
+ tableData.mFrame, mDirtyRect,
+ tableData.mRect + mRenderPt,
+ tableData.mFrame->StyleContext(),
+ *tableData.mBorder,
+ mBGPaintFlags);
}
+
tableData.Destroy(mPresContext);
- return NS_OK;
+
+ return result;
}
void
TableBackgroundPainter::TranslateContext(nscoord aDX,
nscoord aDY)
{
mRenderPt += nsPoint(aDX, aDY);
if (mCols) {
@@ -313,46 +325,47 @@ TableBackgroundPainter::TranslateContext
return;
mCols[i].mColGroup->mRect.MoveBy(-aDX, -aDY);
lastColGroup = mCols[i].mColGroup;
}
}
}
}
-nsresult
+DrawResult
TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
const nsMargin& aDeflate,
bool aPaintTableBackground)
{
NS_PRECONDITION(aTableFrame, "null table frame");
nsTableFrame::RowGroupArray rowGroups;
aTableFrame->OrderRowGroups(rowGroups);
+ DrawResult result = DrawResult::SUCCESS;
+
if (rowGroups.Length() < 1) { //degenerate case
if (aPaintTableBackground) {
PaintTableFrame(aTableFrame, nullptr, nullptr, nsMargin(0,0,0,0));
}
/* No cells; nothing else to paint */
- return NS_OK;
+ return result;
}
if (aPaintTableBackground) {
PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1],
aDeflate);
}
/*Set up column background/border data*/
if (mNumCols > 0) {
nsFrameList& colGroupList = aTableFrame->GetColGroups();
NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup");
mCols = new ColData[mNumCols];
- if (!mCols) return NS_ERROR_OUT_OF_MEMORY;
TableBackgroundData* cgData = nullptr;
nsMargin border;
/* BC left borders aren't stored on cols, but the previous column's
right border is the next one's left border.*/
//Start with table's left border.
nscoord lastLeftBorder = aTableFrame->GetContinuousLeftBCBorderWidth();
for (nsTableColGroupFrame* cgFrame = static_cast<nsTableColGroupFrame*>(colGroupList.FirstChild());
@@ -360,27 +373,21 @@ TableBackgroundPainter::PaintTable(nsTab
if (cgFrame->GetColCount() < 1) {
//No columns, no cells, so no need for data
continue;
}
/*Create data struct for column group*/
cgData = new TableBackgroundData;
- if (!cgData) return NS_ERROR_OUT_OF_MEMORY;
cgData->SetFull(cgFrame);
if (mIsBorderCollapse && cgData->ShouldSetBCBorder()) {
border.left = lastLeftBorder;
cgFrame->GetContinuousBCBorderWidth(border);
- nsresult rv = cgData->SetBCBorder(border, this);
- if (NS_FAILED(rv)) {
- cgData->Destroy(mPresContext);
- delete cgData;
- return rv;
- }
+ cgData->SetBCBorder(border, this);
}
// Boolean that indicates whether mCols took ownership of cgData
bool cgDataOwnershipTaken = false;
/*Loop over columns in this colgroup*/
for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col;
col = static_cast<nsTableColFrame*>(col->GetNextSibling())) {
@@ -394,18 +401,17 @@ TableBackgroundPainter::PaintTable(nsTab
mCols[colIndex].mCol.mRect.MoveBy(cgData->mRect.x, cgData->mRect.y);
//link to parent colgroup's data
mCols[colIndex].mColGroup = cgData;
cgDataOwnershipTaken = true;
if (mIsBorderCollapse) {
border.left = lastLeftBorder;
lastLeftBorder = col->GetContinuousBCBorderWidth(border);
if (mCols[colIndex].mCol.ShouldSetBCBorder()) {
- nsresult rv = mCols[colIndex].mCol.SetBCBorder(border, this);
- if (NS_FAILED(rv)) return rv;
+ mCols[colIndex].mCol.SetBCBorder(border, this);
}
}
}
if (!cgDataOwnershipTaken) {
cgData->Destroy(mPresContext);
delete cgData;
}
@@ -422,28 +428,30 @@ TableBackgroundPainter::PaintTable(nsTab
// We have to draw backgrounds not only within the overflow region of this
// row group, but also possibly (in the case of column / column group
// backgrounds) at its pre-relative-positioning location.
nsRect rgVisualOverflow = rg->GetVisualOverflowRectRelativeToSelf();
nsRect rgOverflowRect = rgVisualOverflow + rg->GetPosition();
nsRect rgNormalRect = rgVisualOverflow + rg->GetNormalPosition();
if (rgOverflowRect.Union(rgNormalRect).Intersects(mDirtyRect - mRenderPt)) {
- nsresult rv = PaintRowGroup(rg, rg->IsPseudoStackingContextFromStyle());
- if (NS_FAILED(rv)) return rv;
+ DrawResult rowGroupResult =
+ PaintRowGroup(rg, rg->IsPseudoStackingContextFromStyle());
+ UpdateDrawResult(&result, rowGroupResult);
}
}
- return NS_OK;
+
+ return result;
}
-nsresult
+DrawResult
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
bool aPassThrough)
{
- NS_PRECONDITION(aFrame, "null frame");
+ MOZ_ASSERT(aFrame);
if (!mRowGroup.mFrame) {
mRowGroup.SetFrame(aFrame);
}
nsTableRowFrame* firstRow = aFrame->GetFirstRow();
/* Load row group data */
@@ -453,20 +461,17 @@ TableBackgroundPainter::PaintRowGroup(ns
nsMargin border;
if (firstRow) {
//pick up first row's top border (= rg top border)
firstRow->GetContinuousBCBorderWidth(border);
/* (row group doesn't store its top border) */
}
//overwrite sides+bottom borders with rg's own
aFrame->GetContinuousBCBorderWidth(border);
- nsresult res = mRowGroup.SetBCBorder(border, this);
- if (!NS_SUCCEEDED(res)) {
- return res;
- }
+ mRowGroup.SetBCBorder(border, this);
}
aPassThrough = !mRowGroup.IsVisible();
}
/* translate everything into row group coord system*/
if (eOrigin_TableRowGroup != mOrigin) {
TranslateContext(mRowGroup.mRect.x, mRowGroup.mRect.y);
}
@@ -491,51 +496,55 @@ TableBackgroundPainter::PaintRowGroup(ns
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(cursor);
if (!row) {
// No useful cursor; just start at the top. Don't bother to set up a
// cursor; if we've gotten this far then we've already built the display
// list for the rowgroup, so not having a cursor means that there's some
// good reason we don't have a cursor and we shouldn't create one here.
row = firstRow;
}
+
+ DrawResult result = DrawResult::SUCCESS;
/* Finally paint */
for (; row; row = row->GetNextRow()) {
mRow.SetFrame(row);
// Be sure to consider our positions both pre- and post-relative
// positioning, since we potentially need to paint at both places.
nscoord rowY = std::min(mRow.mRect.y, row->GetNormalPosition().y);
// Intersect wouldn't handle rowspans.
if (cursor &&
(mDirtyRect.YMost() - mRenderPt.y) <= (rowY - overflowAbove)) {
// All done; cells originating in later rows can't intersect mDirtyRect.
break;
}
- nsresult rv = PaintRow(row, aPassThrough || row->IsPseudoStackingContextFromStyle());
- if (NS_FAILED(rv)) return rv;
+ DrawResult rowResult =
+ PaintRow(row, aPassThrough || row->IsPseudoStackingContextFromStyle());
+
+ UpdateDrawResult(&result, rowResult);
}
/* translate back into table coord system */
if (eOrigin_TableRowGroup != mOrigin) {
TranslateContext(-rgRect.x, -rgRect.y);
}
/* unload rg data */
mRowGroup.Clear();
- return NS_OK;
+ return result;
}
-nsresult
+DrawResult
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
bool aPassThrough)
{
- NS_PRECONDITION(aFrame, "null frame");
+ MOZ_ASSERT(aFrame);
if (!mRow.mFrame) {
mRow.SetFrame(aFrame);
}
/* Load row data */
if (!aPassThrough) {
mRow.SetData();
@@ -547,125 +556,138 @@ TableBackgroundPainter::PaintRow(nsTable
}
else { //acquire rg's bottom border
nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame->GetParent());
rowGroup->GetContinuousBCBorderWidth(border);
}
//get the rest of the borders; will overwrite all but bottom
aFrame->GetContinuousBCBorderWidth(border);
- nsresult res = mRow.SetBCBorder(border, this);
- if (!NS_SUCCEEDED(res)) {
- return res;
- }
+ mRow.SetBCBorder(border, this);
}
aPassThrough = !mRow.IsVisible();
}
/* Translate */
if (eOrigin_TableRow == mOrigin) {
/* If we originate from the row, then make the row the origin. */
mRow.mRect.MoveTo(0, 0);
}
//else: Use row group's coord system -> no translation necessary
+ DrawResult result = DrawResult::SUCCESS;
+
for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) {
nsRect cellBGRect, rowBGRect, rowGroupBGRect, colBGRect;
ComputeCellBackgrounds(cell, cellBGRect, rowBGRect,
rowGroupBGRect, colBGRect);
// Find the union of all the cell background layers.
nsRect combinedRect(cellBGRect);
combinedRect.UnionRect(combinedRect, rowBGRect);
combinedRect.UnionRect(combinedRect, rowGroupBGRect);
combinedRect.UnionRect(combinedRect, colBGRect);
if (combinedRect.Intersects(mDirtyRect)) {
bool passCell = aPassThrough || cell->IsPseudoStackingContextFromStyle();
- nsresult rv = PaintCell(cell, cellBGRect, rowBGRect, rowGroupBGRect,
- colBGRect, passCell);
- if (NS_FAILED(rv)) return rv;
+ DrawResult cellResult = PaintCell(cell, cellBGRect, rowBGRect,
+ rowGroupBGRect, colBGRect, passCell);
+ UpdateDrawResult(&result, cellResult);
}
}
/* Unload row data */
mRow.Clear();
- return NS_OK;
+
+ return result;
}
-nsresult
+DrawResult
TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
nsRect& aCellBGRect,
nsRect& aRowBGRect,
nsRect& aRowGroupBGRect,
nsRect& aColBGRect,
bool aPassSelf)
{
- NS_PRECONDITION(aCell, "null frame");
+ MOZ_ASSERT(aCell);
const nsStyleTableBorder* cellTableStyle;
cellTableStyle = aCell->StyleTableBorder();
if (NS_STYLE_TABLE_EMPTY_CELLS_SHOW != cellTableStyle->mEmptyCells &&
aCell->GetContentEmpty() && !mIsBorderCollapse) {
- return NS_OK;
+ return DrawResult::SUCCESS;
}
int32_t colIndex;
aCell->GetColIndex(colIndex);
NS_ASSERTION(colIndex < int32_t(mNumCols), "prevent array boundary violation");
- if (int32_t(mNumCols) <= colIndex)
- return NS_OK;
+ if (int32_t(mNumCols) <= colIndex) {
+ return DrawResult::SUCCESS;
+ }
+
+ DrawResult result = DrawResult::SUCCESS;
//Paint column group background
if (mCols && mCols[colIndex].mColGroup && mCols[colIndex].mColGroup->IsVisible()) {
- nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
- mCols[colIndex].mColGroup->mFrame, mDirtyRect,
- mCols[colIndex].mColGroup->mRect + mRenderPt,
- mCols[colIndex].mColGroup->mFrame->StyleContext(),
- *mCols[colIndex].mColGroup->mBorder,
- mBGPaintFlags, &aColBGRect);
+ DrawResult colGroupResult =
+ nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
+ mCols[colIndex].mColGroup->mFrame, mDirtyRect,
+ mCols[colIndex].mColGroup->mRect + mRenderPt,
+ mCols[colIndex].mColGroup->mFrame->StyleContext(),
+ *mCols[colIndex].mColGroup->mBorder,
+ mBGPaintFlags, &aColBGRect);
+ UpdateDrawResult(&result, colGroupResult);
}
//Paint column background
if (mCols && mCols[colIndex].mCol.IsVisible()) {
- nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
- mCols[colIndex].mCol.mFrame, mDirtyRect,
- mCols[colIndex].mCol.mRect + mRenderPt,
- mCols[colIndex].mCol.mFrame->StyleContext(),
- *mCols[colIndex].mCol.mBorder,
- mBGPaintFlags, &aColBGRect);
+ DrawResult colResult =
+ nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
+ mCols[colIndex].mCol.mFrame, mDirtyRect,
+ mCols[colIndex].mCol.mRect + mRenderPt,
+ mCols[colIndex].mCol.mFrame->StyleContext(),
+ *mCols[colIndex].mCol.mBorder,
+ mBGPaintFlags, &aColBGRect);
+ UpdateDrawResult(&result, colResult);
}
//Paint row group background
if (mRowGroup.IsVisible()) {
- nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
- mRowGroup.mFrame, mDirtyRect,
- mRowGroup.mRect + mRenderPt,
- mRowGroup.mFrame->StyleContext(),
- *mRowGroup.mBorder,
- mBGPaintFlags, &aRowGroupBGRect);
+ DrawResult rowGroupResult =
+ nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
+ mRowGroup.mFrame, mDirtyRect,
+ mRowGroup.mRect + mRenderPt,
+ mRowGroup.mFrame->StyleContext(),
+ *mRowGroup.mBorder,
+ mBGPaintFlags, &aRowGroupBGRect);
+ UpdateDrawResult(&result, rowGroupResult);
}
//Paint row background
if (mRow.IsVisible()) {
- nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
- mRow.mFrame, mDirtyRect,
- mRow.mRect + mRenderPt,
- mRow.mFrame->StyleContext(),
- *mRow.mBorder,
- mBGPaintFlags, &aRowBGRect);
+ DrawResult rowResult =
+ nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
+ mRow.mFrame, mDirtyRect,
+ mRow.mRect + mRenderPt,
+ mRow.mFrame->StyleContext(),
+ *mRow.mBorder,
+ mBGPaintFlags, &aRowBGRect);
+ UpdateDrawResult(&result, rowResult);
}
//Paint cell background in border-collapse unless we're just passing
if (mIsBorderCollapse && !aPassSelf) {
- aCell->PaintCellBackground(mRenderingContext, mDirtyRect,
- aCellBGRect.TopLeft(), mBGPaintFlags);
+ DrawResult cellResult =
+ aCell->PaintCellBackground(mRenderingContext, mDirtyRect,
+ aCellBGRect.TopLeft(), mBGPaintFlags);
+ UpdateDrawResult(&result, cellResult);
}
- return NS_OK;
+ return result;
}
void
TableBackgroundPainter::ComputeCellBackgrounds(nsTableCellFrame* aCell,
nsRect& aCellBGRect,
nsRect& aRowBGRect,
nsRect& aRowGroupBGRect,
nsRect& aColBGRect)
--- a/layout/tables/nsTablePainter.h
+++ b/layout/tables/nsTablePainter.h
@@ -1,16 +1,18 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsTablePainter_h__
#define nsTablePainter_h__
+#include "imgIContainer.h"
+
#include "celldata.h"
// flags for Paint, PaintChild, PaintChildren are currently only used by tables.
//Table-based paint call; not a direct call as with views
#define NS_PAINT_FLAG_TABLE_BG_PAINT 0x00000001
//Cells should paint their backgrounds only, no children
#define NS_PAINT_FLAG_TABLE_CELL_BG_PASS 0x00000002
@@ -22,16 +24,18 @@ class nsTableCellFrame;
class TableBackgroundPainter
{
/*
* Helper class for painting table backgrounds
*
*/
+ typedef mozilla::image::DrawResult DrawResult;
+
public:
enum Origin { eOrigin_Table, eOrigin_TableRowGroup, eOrigin_TableRow };
/** Public constructor
* @param aTableFrame - the table's table frame
* @param aOrigin - what type of table frame is creating this instance
* @param aPresContext - the presentation context
@@ -75,80 +79,89 @@ class TableBackgroundPainter
* (Cells themselves will only be painted in border collapse)
* Table must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aTableFrame - the table frame
* @param aDeflate - deflation needed to bring table's mRect
* to the outer grid lines in border-collapse
* @param aPaintTableBackground - if true, the table background
* is included, otherwise it isn't
+ * @returns DrawResult::SUCCESS if all painting was successful. If some
+ * painting failed or an improved result could be achieved by sync
+ * decoding images, returns another value.
*/
- nsresult PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate,
- bool aPaintTableBackground);
+ DrawResult PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate,
+ bool aPaintTableBackground);
/** Paint background for the row group and its children down through cells
* (Cells themselves will only be painted in border collapse)
* Standards mode only
* Table Row Group must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aFrame - the table row group frame
+ * @returns DrawResult::SUCCESS if all painting was successful. If some
+ * painting failed or an improved result could be achieved by sync
+ * decoding images, returns another value.
*/
- nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame)
+ DrawResult PaintRowGroup(nsTableRowGroupFrame* aFrame)
{ return PaintRowGroup(aFrame, false); }
/** Paint background for the row and its children down through cells
* (Cells themselves will only be painted in border collapse)
* Standards mode only
* Table Row must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aFrame - the table row frame
+ * @returns DrawResult::SUCCESS if all painting was successful. If some
+ * painting failed or an improved result could be achieved by sync
+ * decoding images, returns another value.
*/
- nsresult PaintRow(nsTableRowFrame* aFrame)
+ DrawResult PaintRow(nsTableRowFrame* aFrame)
{ return PaintRow(aFrame, false); }
private:
/** Paint table frame's background
* @param aTableFrame - the table frame
* @param aFirstRowGroup - the first (in layout order) row group
* may be null
* @param aLastRowGroup - the last (in layout order) row group
* may be null
* @param aDeflate - adjustment to frame's rect (used for quirks BC)
* may be null
*/
- nsresult PaintTableFrame(nsTableFrame* aTableFrame,
- nsTableRowGroupFrame* aFirstRowGroup,
- nsTableRowGroupFrame* aLastRowGroup,
- const nsMargin& aDeflate);
+ DrawResult PaintTableFrame(nsTableFrame* aTableFrame,
+ nsTableRowGroupFrame* aFirstRowGroup,
+ nsTableRowGroupFrame* aLastRowGroup,
+ const nsMargin& aDeflate);
/* aPassThrough params indicate whether to paint the element or to just
* pass through and paint underlying layers only
* See Public versions for function descriptions
*/
- nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame,
- bool aPassThrough);
- nsresult PaintRow(nsTableRowFrame* aFrame,
- bool aPassThrough);
+ DrawResult PaintRowGroup(nsTableRowGroupFrame* aFrame,
+ bool aPassThrough);
+ DrawResult PaintRow(nsTableRowFrame* aFrame,
+ bool aPassThrough);
/** Paint table background layers for this cell space
* Also paints cell's own background in border-collapse mode
* @param aCell - the cell
* @param aCellBGRect - background rect for the cell
* @param aRowBGRect - background rect for the row
* @param aRowGroupBGRect - background rect for the row group
* @param aColBGRect - background rect for the column and column group
* @param aPassSelf - pass this cell; i.e. paint only underlying layers
*/
- nsresult PaintCell(nsTableCellFrame* aCell,
- nsRect& aCellBGRect,
- nsRect& aRowBGRect,
- nsRect& aRowGroupBGRect,
- nsRect& aColBGRect,
- bool aPassSelf);
+ DrawResult PaintCell(nsTableCellFrame* aCell,
+ nsRect& aCellBGRect,
+ nsRect& aRowBGRect,
+ nsRect& aRowGroupBGRect,
+ nsRect& aColBGRect,
+ bool aPassSelf);
/** Compute table background layer positions for this cell space
* @param aCell - the cell
* @param aCellBGRectOut - outparam: background rect for the cell
* @param aRowBGRectOut - outparam: background rect for the row
* @param aRowGroupBGRectOut - outparam: background rect for the row group
* @param aColBGRectOut - outparam: background rect for the column
and column group
@@ -200,18 +213,18 @@ class TableBackgroundPainter
/** Calculate the style data for mFrame */
void SetData();
/** True if need to set border-collapse border; must call SetFull beforehand */
bool ShouldSetBCBorder();
/** Set border-collapse border with aBorderWidth as widths */
- nsresult SetBCBorder(nsMargin& aBorderWidth,
- TableBackgroundPainter* aPainter);
+ void SetBCBorder(nsMargin& aBorderWidth,
+ TableBackgroundPainter* aPainter);
private:
nsStyleBorder* mSynthBorder;
};
struct ColData;
friend struct ColData;
struct ColData {
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -20,16 +20,17 @@
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsCOMPtr.h"
#include "nsDisplayList.h"
#include "nsIFrameInlines.h"
#include <algorithm>
using namespace mozilla;
+using namespace mozilla::image;
struct nsTableCellReflowState : public nsHTMLReflowState
{
nsTableCellReflowState(nsPresContext* aPresContext,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aFrame,
const LogicalSize& aAvailableSpace,
uint32_t aFlags = 0)
@@ -530,50 +531,63 @@ public:
MOZ_COUNT_CTOR(nsDisplayTableRowBackground);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayTableRowBackground() {
MOZ_COUNT_DTOR(nsDisplayTableRowBackground);
}
#endif
+ virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) MOZ_OVERRIDE;
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("TableRowBackground", TYPE_TABLE_ROW_BACKGROUND)
};
+nsDisplayItemGeometry*
+nsDisplayTableRowBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+ return new nsDisplayItemGenericImageGeometry(this, aBuilder);
+}
+
void
nsDisplayTableRowBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion)
{
- if (aBuilder->ShouldSyncDecodeImages()) {
- if (nsTableFrame::AnyTablePartHasUndecodedBackgroundImage(mFrame, mFrame->GetNextSibling())) {
- bool snap;
- aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
- }
+ auto geometry =
+ static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+ if (aBuilder->ShouldSyncDecodeImages() &&
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
+ bool snap;
+ aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
}
nsDisplayTableItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
void
nsDisplayTableRowBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(mFrame);
TableBackgroundPainter painter(tableFrame,
TableBackgroundPainter::eOrigin_TableRow,
mFrame->PresContext(), *aCtx,
mVisibleRect, ToReferenceFrame(),
aBuilder->GetBackgroundPaintFlags());
- painter.PaintRow(static_cast<nsTableRowFrame*>(mFrame));
+
+ DrawResult result =
+ painter.PaintRow(static_cast<nsTableRowFrame*>(mFrame));
+
+ nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
}
void
nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsDisplayTableItem* item = nullptr;
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -17,16 +17,17 @@
#include "nsHTMLParts.h"
#include "nsCSSFrameConstructor.h"
#include "nsDisplayList.h"
#include "nsCellMap.h"//table cell navigation
#include <algorithm>
using namespace mozilla;
+using namespace mozilla::image;
using namespace mozilla::layout;
nsTableRowGroupFrame::nsTableRowGroupFrame(nsStyleContext* aContext):
nsContainerFrame(aContext)
{
SetRepeatable(false);
}
@@ -142,51 +143,64 @@ public:
MOZ_COUNT_CTOR(nsDisplayTableRowGroupBackground);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayTableRowGroupBackground() {
MOZ_COUNT_DTOR(nsDisplayTableRowGroupBackground);
}
#endif
+ virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) MOZ_OVERRIDE;
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("TableRowGroupBackground", TYPE_TABLE_ROW_GROUP_BACKGROUND)
};
+nsDisplayItemGeometry*
+nsDisplayTableRowGroupBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+ return new nsDisplayItemGenericImageGeometry(this, aBuilder);
+}
+
void
nsDisplayTableRowGroupBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion)
{
- if (aBuilder->ShouldSyncDecodeImages()) {
- if (nsTableFrame::AnyTablePartHasUndecodedBackgroundImage(mFrame, mFrame->GetNextSibling())) {
- bool snap;
- aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
- }
+ auto geometry =
+ static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+ if (aBuilder->ShouldSyncDecodeImages() &&
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
+ bool snap;
+ aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
}
nsDisplayTableItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
void
nsDisplayTableRowGroupBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(mFrame);
TableBackgroundPainter painter(tableFrame,
TableBackgroundPainter::eOrigin_TableRowGroup,
mFrame->PresContext(), *aCtx,
mVisibleRect, ToReferenceFrame(),
aBuilder->GetBackgroundPaintFlags());
- painter.PaintRowGroup(static_cast<nsTableRowGroupFrame*>(mFrame));
+
+ DrawResult result =
+ painter.PaintRowGroup(static_cast<nsTableRowGroupFrame*>(mFrame));
+
+ nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
}
// Handle the child-traversal part of DisplayGenericTablePart
static void
DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
const nsRect& aDirtyRect, const nsDisplayListSet& aLists)
{
nscoord overflowAbove;
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -383,17 +383,17 @@ nsDisplayXULImage::ComputeInvalidationRe
nsRegion* aInvalidRegion)
{
auto boxFrame = static_cast<nsImageBoxFrame*>(mFrame);
auto geometry =
static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
if (aBuilder->ShouldSyncDecodeImages() &&
boxFrame->mImageRequest &&
- geometry->LastDrawResult() != DrawResult::SUCCESS) {
+ geometry->ShouldInvalidateToSyncDecodeImages()) {
bool snap;
aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
}
nsDisplayImageContainer::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
void
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2768,22 +2768,50 @@ nsTreeBodyFrame::HandleEvent(nsPresConte
CloseCallback, nsITimer::TYPE_ONE_SHOT,
getter_AddRefs(mSlots->mTimer));
}
}
return NS_OK;
}
-static void
-PaintTreeBody(nsIFrame* aFrame, nsRenderingContext* aCtx,
- const nsRect& aDirtyRect, nsPoint aPt)
-{
- static_cast<nsTreeBodyFrame*>(aFrame)->PaintTreeBody(*aCtx, aDirtyRect, aPt);
-}
+class nsDisplayTreeBody MOZ_FINAL : public nsDisplayItem {
+public:
+ nsDisplayTreeBody(nsDisplayListBuilder* aBuilder, nsFrame* aFrame) :
+ nsDisplayItem(aBuilder, aFrame),
+ mDisableSubpixelAA(false) {
+ MOZ_COUNT_CTOR(nsDisplayTreeBody);
+ }
+#ifdef NS_BUILD_REFCNT_LOGGING
+ virtual ~nsDisplayTreeBody() {
+ MOZ_COUNT_DTOR(nsDisplayTreeBody);
+ }
+#endif
+
+ virtual void Paint(nsDisplayListBuilder* aBuilder,
+ nsRenderingContext* aCtx) MOZ_OVERRIDE
+ {
+ gfxContext* ctx = aCtx->ThebesContext();
+ gfxContextAutoDisableSubpixelAntialiasing disable(ctx, mDisableSubpixelAA);
+ static_cast<nsTreeBodyFrame*>(mFrame)->
+ PaintTreeBody(*aCtx, mVisibleRect, ToReferenceFrame());
+ }
+ NS_DISPLAY_DECL_NAME("XULTreeBody", TYPE_XUL_TREE_BODY)
+
+ virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
+ {
+ bool snap;
+ return GetBounds(aBuilder, &snap);
+ }
+ virtual void DisableComponentAlpha() MOZ_OVERRIDE {
+ mDisableSubpixelAA = true;
+ }
+
+ bool mDisableSubpixelAA;
+};
// Painting routines
void
nsTreeBodyFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// REVIEW: why did we paint if we were collapsed? that makes no sense!
@@ -2794,18 +2822,17 @@ nsTreeBodyFrame::BuildDisplayList(nsDisp
nsLeafBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
// Bail out now if there's no view or we can't run script because the
// document is a zombie
if (!mView || !GetContent ()->GetComposedDoc()->GetWindow())
return;
aLists.Content()->AppendNewToTop(new (aBuilder)
- nsDisplayGeneric(aBuilder, this, ::PaintTreeBody, "XULTreeBody",
- nsDisplayItem::TYPE_XUL_TREE_BODY));
+ nsDisplayTreeBody(aBuilder, this));
}
void
nsTreeBodyFrame::PaintTreeBody(nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt)
{
// Update our available height and our page count.
CalcInnerBox();
--- a/mobile/android/base/db/LocalBrowserDB.java
+++ b/mobile/android/base/db/LocalBrowserDB.java
@@ -27,16 +27,17 @@ import org.mozilla.gecko.AboutPages;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.R;
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
import org.mozilla.gecko.db.BrowserContract.Combined;
import org.mozilla.gecko.db.BrowserContract.ExpirePriority;
import org.mozilla.gecko.db.BrowserContract.Favicons;
import org.mozilla.gecko.db.BrowserContract.History;
import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
+import org.mozilla.gecko.db.BrowserContract.SearchHistory;
import org.mozilla.gecko.db.BrowserContract.SyncColumns;
import org.mozilla.gecko.db.BrowserContract.Thumbnails;
import org.mozilla.gecko.db.BrowserDB.FilterFlags;
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.mozglue.RobocopTarget;
@@ -88,16 +89,17 @@ public class LocalBrowserDB {
private final Uri mParentsUriWithProfile;
private final Uri mHistoryUriWithProfile;
private final Uri mHistoryExpireUriWithProfile;
private final Uri mCombinedUriWithProfile;
private final Uri mUpdateHistoryUriWithProfile;
private final Uri mFaviconsUriWithProfile;
private final Uri mThumbnailsUriWithProfile;
private final Uri mReadingListUriWithProfile;
+ private final Uri mSearchHistoryUri;
private static final String[] DEFAULT_BOOKMARK_COLUMNS =
new String[] { Bookmarks._ID,
Bookmarks.GUID,
Bookmarks.URL,
Bookmarks.TITLE,
Bookmarks.TYPE,
Bookmarks.PARENT };
@@ -110,16 +112,18 @@ public class LocalBrowserDB {
mParentsUriWithProfile = appendProfile(Bookmarks.PARENTS_CONTENT_URI);
mHistoryUriWithProfile = appendProfile(History.CONTENT_URI);
mHistoryExpireUriWithProfile = appendProfile(History.CONTENT_OLD_URI);
mCombinedUriWithProfile = appendProfile(Combined.CONTENT_URI);
mFaviconsUriWithProfile = appendProfile(Favicons.CONTENT_URI);
mThumbnailsUriWithProfile = appendProfile(Thumbnails.CONTENT_URI);
mReadingListUriWithProfile = appendProfile(ReadingListItems.CONTENT_URI);
+ mSearchHistoryUri = BrowserContract.SearchHistory.CONTENT_URI;
+
mUpdateHistoryUriWithProfile = mHistoryUriWithProfile.buildUpon().
appendQueryParameter(BrowserContract.PARAM_INCREMENT_VISITS, "true").
appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build();
}
/**
* Not thread safe. A helper to allocate new IDs for arbitrary strings.
*/
@@ -675,16 +679,17 @@ public class LocalBrowserDB {
public void removeHistoryEntry(ContentResolver cr, String url) {
cr.delete(mHistoryUriWithProfile,
History.URL + " = ?",
new String[] { url });
}
public void clearHistory(ContentResolver cr) {
cr.delete(mHistoryUriWithProfile, null, null);
+ cr.delete(mSearchHistoryUri, null, null);
}
@RobocopTarget
public Cursor getBookmarksInFolder(ContentResolver cr, long folderId) {
final boolean addDesktopFolder;
// We always want to show mobile bookmarks in the root view.
if (folderId == Bookmarks.FIXED_ROOT_ID) {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1548,17 +1548,17 @@ pref("network.dns.disableIPv6", false);
// This is the number of dns cache entries allowed
pref("network.dnsCacheEntries", 400);
// In the absence of OS TTLs, the DNS cache TTL value
pref("network.dnsCacheExpiration", 60);
// Get TTL; not supported on all platforms; nop on the unsupported ones.
-pref("network.dns.get-ttl", true);
+pref("network.dns.get-ttl", false);
// The grace period allows the DNS cache to use expired entries, while kicking off
// a revalidation in the background.
pref("network.dnsCacheExpirationGracePeriod", 60);
// This preference can be used to turn off DNS prefetch.
pref("network.dns.disablePrefetch", false);
--- a/toolkit/components/passwordmgr/LoginManagerParent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerParent.jsm
@@ -102,18 +102,19 @@ var LoginManagerParent = {
findLogins: function(showMasterPassword, formOrigin, actionOrigin,
requestId, target) {
if (!showMasterPassword && !Services.logins.isLoggedIn) {
target.sendAsyncMessage("RemoteLogins:loginsFound",
{ requestId: requestId, logins: [] });
return;
}
+ let allLoginsCount = Services.logins.countLogins(formOrigin, "", null);
// If there are no logins for this site, bail out now.
- if (!Services.logins.countLogins(formOrigin, "", null)) {
+ if (!allLoginsCount) {
target.sendAsyncMessage("RemoteLogins:loginsFound",
{ requestId: requestId, logins: [] });
return;
}
// If we're currently displaying a master password prompt, defer
// processing this form until the user handles the prompt.
if (Services.logins.uiBusy) {
@@ -147,16 +148,26 @@ var LoginManagerParent = {
Services.obs.addObserver(observer, "passwordmgr-crypto-login", false);
Services.obs.addObserver(observer, "passwordmgr-crypto-loginCanceled", false);
return;
}
var logins = Services.logins.findLogins({}, formOrigin, actionOrigin, null);
target.sendAsyncMessage("RemoteLogins:loginsFound",
{ requestId: requestId, logins: logins });
+
+ const PWMGR_FORM_ACTION_EFFECT = Services.telemetry.getHistogramById("PWMGR_FORM_ACTION_EFFECT");
+ if (logins.length == 0) {
+ PWMGR_FORM_ACTION_EFFECT.add(2);
+ } else if (logins.length == allLoginsCount) {
+ PWMGR_FORM_ACTION_EFFECT.add(0);
+ } else {
+ // logins.length < allLoginsCount
+ PWMGR_FORM_ACTION_EFFECT.add(1);
+ }
},
doAutocompleteSearch: function({ formOrigin, actionOrigin,
searchString, previousResult,
rect, requestId, remote }, target) {
// Note: previousResult is a regular object, not an
// nsIAutoCompleteResult.
var result;
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -7197,16 +7197,22 @@
"PWMGR_BLOCKLIST_NUM_SITES": {
"expires_in_version": "never",
"kind": "exponential",
"high": 100,
"n_buckets" : 10,
"extended_statistics_ok": true,
"description": "The number of sites for which the user has explicitly rejected saving logins"
},
+ "PWMGR_FORM_ACTION_EFFECT": {
+ "expires_in_version": "never",
+ "kind": "enumerated",
+ "n_values" : 5,
+ "description": "The effect of the form action on signon autofill. (0=No effect, 1=Fewer logins after considering the form action, 2=No logins match form origin and action."
+ },
"PWMGR_FORM_AUTOFILL_RESULT": {
"expires_in_version": "never",
"kind": "enumerated",
"n_values" : 20,
"description": "The result of auto-filling a login form. See http://mzl.la/1Mbs6jL for bucket descriptions."
},
"PWMGR_NUM_PASSWORDS_PER_HOSTNAME": {
"expires_in_version": "never",