mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1187401 (Part 1) - Simplify the condition that determines whether we set RasterImage::mHasBeenDecoded. r=tn (69be36e7ef) - Bug 1187401 (Part 2) - Eliminate the nsresult return value from RasterImage::SetMetadata, since it's not used anymore. r=tn (dc521c4b9f) - Bug 1187401 (Part 3) - For consistency, call DoError if SetMetadata sees a negative size. r=tn (d9ca8ec91b) - Bug 1207183 - micro-optimize removing work items from DecodePool's queues; r=seth (6bd2717e3a) - No bug - Fix out-of-date comment in Decoder.cpp. r=me (54fdbbd444) - Bug 1181324 - Eliminate the duplicate mRefCnt member in MultipartImage. r=seth (c4512a443e) - Bug 1180105 - Do not leak the SourceSurface returned from imgIContainer::GetFrame in BlockUntilDecodedAndFinishObserving; r=seth (1cadbffc53) - Bug 1181909 - Fix potential null dereference in NextPartObserver. r=tn (cfd8ad0119) - Bug 108603 - Remove NS_IMPL_QUERY_INTERFACE_INHERITED0. r=mccr8, r=froydnj (4bfa6771fc) - Bug 1159502 - Don't block onload for multipart images. r=tn (8b50eadf39) - Bug 1200413 - Part 1: Re-write RefCountedInsideLambdaChecker to use captures instead of checking for DeclRef instances, r=ehsan (80ef99efe2) - Bug 1200413 - Part 2: Make lambdas in ProgressTracker.cpp capture strong references, r=seth (9e4d96dffa) - Bug 1194557 - Ensure that if the image was locked before RecoverFromLossOfFrames() was called, it's still locked afterwards. r=tn (ea4dc6ea9f) - code style (ad3773ba42) - Bug 1167590 - Mark imgRequestProxy::mListener as MOZ_UNSAFE_REF. r=seth (946ffaed8a) - Bug 1148397 - Fix data race on imgRequest::mHadInsecureRedirect. r=tanvi (e73d0664f3) - No bug - Tweak formatting of logging statement in imgRequest. r=me (cab2bcb014) - Bug 1180126 - Read content disposition regardless of content type in imgRequest::PrepareForNewPart. r=tn (2934597743) - Bug 1139225 - Followup - Remove duplicate multiPartChannel variable. (7f7f555a0b) - Bug 1141398 - Do not always revalidate image cache entries for file URIs. r=tn (31d73cb508) - Bug 1183563 - Fix incorrect mixed content warning after internal redirects. r=tanvi, r=seth (12a6c8a15f) - Bug 1150127 - Stop leaking windows via imgCacheValidator. r=baku (a7809c5fa7) - bits of Bug 1102048 (Part 20, imgLoader) (b2098c8a5a) - (No bug) - Correct blatantly lying comment in imgLoader.cpp. r=me DONTBUILD (64c42a5b09) - Bug 1160592 - Report image source size again in about:memory. r=dholbert (4e04cf3c3e) - Add an assertion for the first argument of NewImageChannel, no bug (4c8f087a8f) - Bug 1127534 - Remove assertion before creating a channel (r=sicking) (988692dc91) - Bug 1175371 - Make VectorImage wait to deliver LOAD_COMPLETE until its size is available. r=dholbert (3c81e0daff) - Bug 1181323 - Move nsSVGRenderingObserver's isupports/refcounting decl to subclasses, since one subclass (nsSVGFilterReference) already has its own redundant copy of the decl. r=dholbert (6171171c2c) - Bug 1161722 - If we're shutting down, don't warn about untracked unlocked surfaces. r=dholbert (f7e18ce481) - Bug 1170877 - Track how many times the SurfaceCache has overflowed and report it in about:memory. r=dholbert (884176cb1d) - Bug 1161743 - Upgrade 'WARNING: Not expiration-tracking an unlocked surface' to an assertion. r=dholbert (9900169e7b) - Bug 1167557 - Crash when a null surface is passed to SurfaceCache::Insert. r=dholbert (b3c4cf60aa) - remove bypass cache not fonud either in FF nor TF (3ed4056a27) - Missing bit Bug 1102048 (Part 25, header guards) - Make image/src files comply (cb8ed2428f) - No bug - Remove obsolete comment in SourceBuffer.h. r=me (6e9c233448) - coding style (94b7269690) - Bug 1157065 - GFX: 2D: Add Loongson3 MMI helpers. r=jrmuizel (ebce946c91) - reverto to FF52 and TFF settings (e147a8c7b5) - Bug 1134599 - Fix rpi build target. r=jrmuizel, r=shuang (b9722f860c) - Bug 1129147 - Part 1. Take CanvasPath into a separate file, to avoid circular dependency. r=roc (859bcad807) - Bug 1129147 - Part 2. Path option to addHitRegion. r=ehsan r=gw280 (b2ab08a8a1) - Bug 1206076: Use a specialized PersistentBufferProvider for Canvas2D when using a SkiaGL DrawTarget. r=jrmuizel (859589caf8) - Bug 1188752 - Addendum: Make PersistentBufferProviderBasic constructor explicit. r=bustage on a CLOSED TREE (a27a4dc974) - style (72a65dcb26) - Bug 1198574 - Remove unnecessary argument for PersistentBufferProvider. r=bas (dca718bba8) - Bug 1163124 - The initial value of the canvas filter property should be "none". r=roc (59df6a01d8)
This commit is contained in:
+1
-1
@@ -904,7 +904,7 @@ pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
|
||||
// falling back to Skia/software for smaller canvases
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
pref("gfx.canvas.azure.backends", "skia");
|
||||
pref("gfx.canvas.azure.accelerated", true);
|
||||
pref("gfx.canvas.azure.accelerated", false);
|
||||
#endif
|
||||
|
||||
// Turn on dynamic cache size for Skia
|
||||
|
||||
@@ -951,13 +951,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() {
|
||||
// lambda, where the declaration they reference is not inside the lambda.
|
||||
// This excludes arguments and local variables, leaving only captured
|
||||
// variables.
|
||||
astMatcher.addMatcher(
|
||||
lambdaExpr(hasDescendant(
|
||||
declRefExpr(hasType(pointerType(pointee(isRefCounted()))),
|
||||
to(decl().bind("decl")))
|
||||
.bind("declref")),
|
||||
unless(hasDescendant(decl(equalsBoundNode("decl"))))),
|
||||
&refCountedInsideLambdaChecker);
|
||||
astMatcher.addMatcher(lambdaExpr().bind("lambda"), &refCountedInsideLambdaChecker);
|
||||
|
||||
// Older clang versions such as the ones used on the infra recognize these
|
||||
// conversions as 'operator _Bool', but newer clang versions recognize these
|
||||
@@ -1241,11 +1235,19 @@ void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run(
|
||||
"Refcounted variable %0 of type %1 cannot be captured by a lambda");
|
||||
unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Note, "Please consider using a smart pointer");
|
||||
const DeclRefExpr *declref = Result.Nodes.getNodeAs<DeclRefExpr>("declref");
|
||||
const LambdaExpr *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
|
||||
|
||||
Diag.Report(declref->getLocStart(), errorID)
|
||||
<< declref->getFoundDecl() << declref->getType()->getPointeeType();
|
||||
Diag.Report(declref->getLocStart(), noteID);
|
||||
for (const LambdaCapture Capture : Lambda->captures()) {
|
||||
if (Capture.capturesVariable()) {
|
||||
QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType();
|
||||
|
||||
if (!Pointee.isNull() && isClassRefCounted(Pointee)) {
|
||||
Diag.Report(Capture.getLocation(), errorID)
|
||||
<< Capture.getCapturedVar() << Pointee;
|
||||
Diag.Report(Capture.getLocation(), noteID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiagnosticsMatcher::ExplicitOperatorBoolChecker::run(
|
||||
|
||||
@@ -67,9 +67,9 @@ void foo() {
|
||||
take(argsp);
|
||||
take(localsp);
|
||||
});
|
||||
take([ptr](R* argptr) {
|
||||
take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
R* localptr;
|
||||
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
ptr->method();
|
||||
argptr->method();
|
||||
localptr->method();
|
||||
});
|
||||
@@ -79,9 +79,9 @@ void foo() {
|
||||
argsp->method();
|
||||
localsp->method();
|
||||
});
|
||||
take([ptr](R* argptr) {
|
||||
take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
R* localptr;
|
||||
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
|
||||
take(ptr);
|
||||
take(argptr);
|
||||
take(localptr);
|
||||
});
|
||||
|
||||
@@ -900,7 +900,7 @@ DOMInterfaces = {
|
||||
|
||||
'Path2D': {
|
||||
'nativeType': 'mozilla::dom::CanvasPath',
|
||||
'headerFile': 'CanvasRenderingContext2D.h'
|
||||
'headerFile': 'CanvasPath.h'
|
||||
},
|
||||
|
||||
'PeerConnectionImpl': {
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/* 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 CanvasPath_h
|
||||
#define CanvasPath_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
enum class CanvasWindingRule : uint32_t;
|
||||
class SVGMatrix;
|
||||
|
||||
class CanvasPath final :
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
|
||||
|
||||
nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& rv);
|
||||
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
|
||||
CanvasPath& aCanvasPath,
|
||||
ErrorResult& rv);
|
||||
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aPathString,
|
||||
ErrorResult& rv);
|
||||
|
||||
void ClosePath();
|
||||
void MoveTo(double x, double y);
|
||||
void LineTo(double x, double y);
|
||||
void QuadraticCurveTo(double cpx, double cpy, double x, double y);
|
||||
void BezierCurveTo(double cp1x, double cp1y,
|
||||
double cp2x, double cp2y,
|
||||
double x, double y);
|
||||
void ArcTo(double x1, double y1, double x2, double y2, double radius,
|
||||
ErrorResult& error);
|
||||
void Rect(double x, double y, double w, double h);
|
||||
void Arc(double x, double y, double radius,
|
||||
double startAngle, double endAngle, bool anticlockwise,
|
||||
ErrorResult& error);
|
||||
void Ellipse(double x, double y, double radiusX, double radiusY,
|
||||
double rotation, double startAngle, double endAngle,
|
||||
bool anticlockwise, ErrorResult& error);
|
||||
|
||||
void LineTo(const gfx::Point& aPoint);
|
||||
void BezierTo(const gfx::Point& aCP1,
|
||||
const gfx::Point& aCP2,
|
||||
const gfx::Point& aCP3);
|
||||
|
||||
already_AddRefed<gfx::Path> GetPath(const CanvasWindingRule& aWinding,
|
||||
const gfx::DrawTarget* aTarget) const;
|
||||
|
||||
explicit CanvasPath(nsISupports* aParent);
|
||||
// already_AddRefed arg because the return value from Path::CopyToBuilder()
|
||||
// is passed directly and we can't drop the only ref to have a raw pointer.
|
||||
CanvasPath(nsISupports* aParent,
|
||||
already_AddRefed<gfx::PathBuilder> aPathBuilder);
|
||||
|
||||
void AddPath(CanvasPath& aCanvasPath,
|
||||
const Optional<NonNull<SVGMatrix>>& aMatrix);
|
||||
|
||||
private:
|
||||
virtual ~CanvasPath() {}
|
||||
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
|
||||
|
||||
mutable RefPtr<gfx::Path> mPath;
|
||||
mutable RefPtr<gfx::PathBuilder> mPathBuilder;
|
||||
|
||||
void EnsurePathBuilder() const;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* CanvasPath_h */
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
|
||||
#include "mozilla/dom/CanvasPath.h"
|
||||
#include "mozilla/dom/HTMLImageElement.h"
|
||||
#include "mozilla/dom/HTMLVideoElement.h"
|
||||
#include "mozilla/dom/SVGMatrix.h"
|
||||
@@ -1402,13 +1403,14 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||
DemoteOldestContextIfNecessary();
|
||||
mBufferProvider = nullptr;
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
|
||||
|
||||
#if USE_SKIA_GPU
|
||||
if (glue && glue->GetGrContext() && glue->GetGLContext()) {
|
||||
mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
|
||||
if (mTarget) {
|
||||
AddDemotableContext(this);
|
||||
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
|
||||
} else {
|
||||
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
|
||||
mode = RenderingMode::SoftwareBackendMode;
|
||||
@@ -3360,15 +3362,24 @@ CanvasRenderingContext2D::MeasureText(const nsAString& rawText,
|
||||
void
|
||||
CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorResult& error)
|
||||
{
|
||||
// check if the path is valid
|
||||
EnsureUserSpacePath(CanvasWindingRule::Nonzero);
|
||||
if(!mPath) {
|
||||
RefPtr<gfx::Path> path;
|
||||
if (options.mPath) {
|
||||
path = options.mPath->GetPath(CanvasWindingRule::Nonzero, mTarget);
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
// check if the path is valid
|
||||
EnsureUserSpacePath(CanvasWindingRule::Nonzero);
|
||||
path = mPath;
|
||||
}
|
||||
|
||||
if(!path) {
|
||||
error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the bounds of the current path. They are relative to the canvas
|
||||
mgfx::Rect bounds(mPath->GetBounds(mTarget->GetTransform()));
|
||||
mgfx::Rect bounds(path->GetBounds(mTarget->GetTransform()));
|
||||
if ((bounds.width == 0) || (bounds.height == 0) || !bounds.IsFinite()) {
|
||||
// The specified region has no pixels.
|
||||
error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
@@ -3397,7 +3408,7 @@ CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorRes
|
||||
RegionInfo info;
|
||||
info.mId = options.mId;
|
||||
info.mElement = options.mControl;
|
||||
RefPtr<PathBuilder> pathBuilder = mPath->TransformedCopyToBuilder(mTarget->GetTransform());
|
||||
RefPtr<PathBuilder> pathBuilder = path->TransformedCopyToBuilder(mTarget->GetTransform());
|
||||
info.mPath = pathBuilder->Finish();
|
||||
|
||||
mHitRegionsOptions.InsertElementAt(0, info);
|
||||
@@ -5598,12 +5609,7 @@ CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mBufferProvider = aManager->CreatePersistentBufferProvider(mTarget->GetSize(), mTarget->GetFormat());
|
||||
|
||||
RefPtr<SourceSurface> surf = mTarget->Snapshot();
|
||||
|
||||
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), mTarget->GetSize()));
|
||||
mTarget->CopySurface(surf, IntRect(IntPoint(), mTarget->GetSize()), IntPoint());
|
||||
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
|
||||
|
||||
return mBufferProvider;
|
||||
}
|
||||
|
||||
@@ -44,77 +44,12 @@ class StringOrCanvasGradientOrCanvasPattern;
|
||||
class OwningStringOrCanvasGradientOrCanvasPattern;
|
||||
class TextMetrics;
|
||||
class CanvasFilterChainObserver;
|
||||
class CanvasPath;
|
||||
|
||||
extern const mozilla::gfx::Float SIGMA_MAX;
|
||||
|
||||
template<typename T> class Optional;
|
||||
|
||||
class CanvasPath final :
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
|
||||
|
||||
nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto);
|
||||
|
||||
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& rv);
|
||||
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
|
||||
CanvasPath& aCanvasPath,
|
||||
ErrorResult& rv);
|
||||
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aPathString,
|
||||
ErrorResult& rv);
|
||||
|
||||
void ClosePath();
|
||||
void MoveTo(double x, double y);
|
||||
void LineTo(double x, double y);
|
||||
void QuadraticCurveTo(double cpx, double cpy, double x, double y);
|
||||
void BezierCurveTo(double cp1x, double cp1y,
|
||||
double cp2x, double cp2y,
|
||||
double x, double y);
|
||||
void ArcTo(double x1, double y1, double x2, double y2, double radius,
|
||||
ErrorResult& error);
|
||||
void Rect(double x, double y, double w, double h);
|
||||
void Arc(double x, double y, double radius,
|
||||
double startAngle, double endAngle, bool anticlockwise,
|
||||
ErrorResult& error);
|
||||
void Ellipse(double x, double y, double radiusX, double radiusY,
|
||||
double rotation, double startAngle, double endAngle,
|
||||
bool anticlockwise, ErrorResult& error);
|
||||
|
||||
void LineTo(const gfx::Point& aPoint);
|
||||
void BezierTo(const gfx::Point& aCP1,
|
||||
const gfx::Point& aCP2,
|
||||
const gfx::Point& aCP3);
|
||||
|
||||
already_AddRefed<gfx::Path> GetPath(const CanvasWindingRule& aWinding,
|
||||
const gfx::DrawTarget* aTarget) const;
|
||||
|
||||
explicit CanvasPath(nsISupports* aParent);
|
||||
// already_AddRefed arg because the return value from Path::CopyToBuilder()
|
||||
// is passed directly and we can't drop the only ref to have a raw pointer.
|
||||
CanvasPath(nsISupports* aParent,
|
||||
already_AddRefed<gfx::PathBuilder> aPathBuilder);
|
||||
|
||||
void AddPath(CanvasPath& aCanvasPath,
|
||||
const Optional<NonNull<SVGMatrix>>& aMatrix);
|
||||
|
||||
private:
|
||||
virtual ~CanvasPath() {}
|
||||
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
|
||||
|
||||
mutable RefPtr<gfx::Path> mPath;
|
||||
mutable RefPtr<gfx::PathBuilder> mPathBuilder;
|
||||
|
||||
void EnsurePathBuilder() const;
|
||||
};
|
||||
|
||||
struct CanvasBidiProcessor;
|
||||
class CanvasRenderingContext2DUserData;
|
||||
class CanvasDrawObserver;
|
||||
@@ -977,6 +912,7 @@ protected:
|
||||
fillRule(mozilla::gfx::FillRule::FILL_WINDING),
|
||||
lineCap(mozilla::gfx::CapStyle::BUTT),
|
||||
lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
|
||||
filterString(MOZ_UTF16("none")),
|
||||
imageSmoothingEnabled(true),
|
||||
fontExplicitLanguage(false)
|
||||
{ }
|
||||
|
||||
@@ -28,6 +28,7 @@ EXPORTS.mozilla.ipc += [
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'CanvasGradient.h',
|
||||
'CanvasPath.h',
|
||||
'CanvasPattern.h',
|
||||
'CanvasRenderingContext2D.h',
|
||||
'CanvasUtils.h',
|
||||
|
||||
@@ -32,16 +32,29 @@ SpecialPowers.pushPrefEnv({"set": [["canvas.hitregions.enabled", true]]}, functi
|
||||
ctx.rect(20, 20, 100, 75);
|
||||
ctx.fill();
|
||||
ctx.addHitRegion({id: "a"});
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = "red";
|
||||
ctx.rect(60, 40, 100, 75);
|
||||
ctx.fill();
|
||||
ctx.addHitRegion({id: "b"});
|
||||
|
||||
var mypath = new Path2D();
|
||||
mypath.rect(80, 60, 10, 10);
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = "yellow";
|
||||
ctx.rect(80, 60, 10, 10);
|
||||
ctx.fill();
|
||||
ctx.addHitRegion({id: "c"});
|
||||
ctx.addHitRegion({id: "c", path: mypath});
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = "green";
|
||||
ctx.rect(60, 60, 10, 10); // This region is on purpose not the hit region
|
||||
ctx.fill();
|
||||
var mypath = new Path2D();
|
||||
mypath.rect(70, 30, 10, 10);
|
||||
ctx.addHitRegion({id: "d", path: mypath});
|
||||
|
||||
synthesizeMouse(input, 25,25, {type: "mousedown"});
|
||||
is(regionId, "a", "Hit region a", ". Found: " + regionId);
|
||||
@@ -55,6 +68,9 @@ SpecialPowers.pushPrefEnv({"set": [["canvas.hitregions.enabled", true]]}, functi
|
||||
synthesizeMouse(input, 85,65, {type: "mousedown"});
|
||||
is(regionId, "c", "Hit region c", ". Found: " + regionId);
|
||||
|
||||
synthesizeMouse(input, 75,35, {type: "mousedown"});
|
||||
is(regionId, "d", "Hit region d", ". Found: " + regionId);
|
||||
|
||||
ctx.removeHitRegion("c");
|
||||
synthesizeMouse(input, 85,65, {type: "mousedown"});
|
||||
is(regionId, "b", "Hit region b", ". Found: " + regionId);
|
||||
|
||||
@@ -81,10 +81,14 @@ static int sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
|
||||
};
|
||||
// A bitwise variable for recording what kind of headset is attached.
|
||||
static int sHeadsetState;
|
||||
#if defined(MOZ_B2G_BT) || ANDROID_VERSION >= 17
|
||||
static bool sBluetoothA2dpEnabled;
|
||||
#endif
|
||||
static const int kBtSampleRate = 8000;
|
||||
static bool sSwitchDone = true;
|
||||
#ifdef MOZ_B2G_BT
|
||||
static bool sA2dpSwitchDone = true;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@@ -216,6 +220,7 @@ static void ProcessDelayedAudioRoute(SwitchState aState)
|
||||
sSwitchDone = true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
static void ProcessDelayedA2dpRoute(audio_policy_dev_state_t aState, const nsCString aAddress)
|
||||
{
|
||||
if (sA2dpSwitchDone)
|
||||
@@ -228,6 +233,7 @@ static void ProcessDelayedA2dpRoute(audio_policy_dev_state_t aState, const nsCSt
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
sA2dpSwitchDone = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMPL_ISUPPORTS(AudioManager, nsIAudioManager, nsIObserver)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ dictionary ContextAttributes2D {
|
||||
};
|
||||
|
||||
dictionary HitRegionOptions {
|
||||
Path2D? path = null;
|
||||
DOMString id = "";
|
||||
Element? control = null;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
============================================================================
|
||||
Name : MMIHelpers.h
|
||||
Author : Heiher <r@hev.cc>
|
||||
Version : 0.0.1
|
||||
Copyright : Copyright (c) 2015 everyone.
|
||||
Description : The helpers for x86 SSE to Loongson MMI.
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __MMI_HELPERS_H__
|
||||
#define __MMI_HELPERS_H__
|
||||
|
||||
#define __mm_packxxxx(_f, _D, _d, _s, _t) \
|
||||
#_f" %["#_t"], %["#_d"h], %["#_s"h] \n\t" \
|
||||
#_f" %["#_D"l], %["#_d"l], %["#_s"l] \n\t" \
|
||||
"punpckhwd %["#_D"h], %["#_D"l], %["#_t"] \n\t" \
|
||||
"punpcklwd %["#_D"l], %["#_D"l], %["#_t"] \n\t"
|
||||
|
||||
#define _mm_or(_D, _d, _s) \
|
||||
"or %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"or %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
#define _mm_xor(_D, _d, _s) \
|
||||
"xor %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"xor %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
#define _mm_and(_D, _d, _s) \
|
||||
"and %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"and %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: pandn */
|
||||
#define _mm_pandn(_D, _d, _s) \
|
||||
"pandn %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"pandn %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: pshuflw */
|
||||
#define _mm_pshuflh(_D, _d, _s) \
|
||||
"mov.d %["#_D"h], %["#_d"h] \n\t" \
|
||||
"pshufh %["#_D"l], %["#_d"l], %["#_s"] \n\t"
|
||||
|
||||
/* SSE: psllw (bits) */
|
||||
#define _mm_psllh(_D, _d, _s) \
|
||||
"psllh %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"psllh %["#_D"l], %["#_d"l], %["#_s"] \n\t"
|
||||
|
||||
/* SSE: pslld (bits) */
|
||||
#define _mm_psllw(_D, _d, _s) \
|
||||
"psllw %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"psllw %["#_D"l], %["#_d"l], %["#_s"] \n\t"
|
||||
|
||||
/* SSE: psllq (bits) */
|
||||
#define _mm_pslld(_D, _d, _s) \
|
||||
"dsll %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"dsll %["#_D"l], %["#_d"l], %["#_s"] \n\t"
|
||||
|
||||
/* SSE: pslldq (bytes) */
|
||||
#define _mm_psllq(_D, _d, _s, _s64, _tf) \
|
||||
"subu %["#_tf"], %["#_s64"], %["#_s"] \n\t" \
|
||||
"dsrl %["#_tf"], %["#_d"l], %["#_tf"] \n\t" \
|
||||
"dsll %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"dsll %["#_D"l], %["#_d"l], %["#_s"] \n\t" \
|
||||
"or %["#_D"h], %["#_D"h], %["#_tf"] \n\t"
|
||||
|
||||
/* SSE: psrlw (bits) */
|
||||
#define _mm_psrlh(_D, _d, _s) \
|
||||
"psrlh %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"psrlh %["#_D"l], %["#_d"l], %["#_s"] \n\t"
|
||||
|
||||
/* SSE: psrld (bits) */
|
||||
#define _mm_psrlw(_D, _d, _s) \
|
||||
"psrlw %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"psrlw %["#_D"l], %["#_d"l], %["#_s"] \n\t"
|
||||
|
||||
/* SSE: psrlq (bits) */
|
||||
#define _mm_psrld(_D, _d, _s) \
|
||||
"dsrl %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"dsrl %["#_D"l], %["#_d"l], %["#_s"] \n\t"
|
||||
|
||||
/* SSE: psrldq (bytes) */
|
||||
#define _mm_psrlq(_D, _d, _s, _s64, _tf) \
|
||||
"subu %["#_tf"], %["#_s64"], %["#_s"] \n\t" \
|
||||
"dsll %["#_tf"], %["#_d"h], %["#_tf"] \n\t" \
|
||||
"dsrl %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"dsrl %["#_D"l], %["#_d"l], %["#_s"] \n\t" \
|
||||
"or %["#_D"l], %["#_D"l], %["#_tf"] \n\t"
|
||||
|
||||
/* SSE: psrad */
|
||||
#define _mm_psraw(_D, _d, _s) \
|
||||
"psraw %["#_D"h], %["#_d"h], %["#_s"] \n\t" \
|
||||
"psraw %["#_D"l], %["#_d"l], %["#_s"] \n\t"
|
||||
|
||||
/* SSE: paddb */
|
||||
#define _mm_paddb(_D, _d, _s) \
|
||||
"paddb %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"paddb %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: paddw */
|
||||
#define _mm_paddh(_D, _d, _s) \
|
||||
"paddh %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"paddh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: paddd */
|
||||
#define _mm_paddw(_D, _d, _s) \
|
||||
"paddw %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"paddw %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: paddq */
|
||||
#define _mm_paddd(_D, _d, _s) \
|
||||
"dadd %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"dadd %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: psubw */
|
||||
#define _mm_psubh(_D, _d, _s) \
|
||||
"psubh %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"psubh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: psubd */
|
||||
#define _mm_psubw(_D, _d, _s) \
|
||||
"psubw %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"psubw %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: pmaxub */
|
||||
#define _mm_pmaxub(_D, _d, _s) \
|
||||
"pmaxub %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"pmaxub %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: pmullw */
|
||||
#define _mm_pmullh(_D, _d, _s) \
|
||||
"pmullh %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"pmullh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: pmulhw */
|
||||
#define _mm_pmulhh(_D, _d, _s) \
|
||||
"pmulhh %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"pmulhh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: pmuludq */
|
||||
#define _mm_pmuluw(_D, _d, _s) \
|
||||
"pmuluw %["#_D"h], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"pmuluw %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: packsswb */
|
||||
#define _mm_packsshb(_D, _d, _s, _t) \
|
||||
__mm_packxxxx(packsshb, _D, _d, _s, _t)
|
||||
|
||||
/* SSE: packssdw */
|
||||
#define _mm_packsswh(_D, _d, _s, _t) \
|
||||
__mm_packxxxx(packsswh, _D, _d, _s, _t)
|
||||
|
||||
/* SSE: packuswb */
|
||||
#define _mm_packushb(_D, _d, _s, _t) \
|
||||
__mm_packxxxx(packushb, _D, _d, _s, _t)
|
||||
|
||||
/* SSE: punpcklbw */
|
||||
#define _mm_punpcklbh(_D, _d, _s) \
|
||||
"punpckhbh %["#_D"h], %["#_d"l], %["#_s"l] \n\t" \
|
||||
"punpcklbh %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: punpcklwd */
|
||||
#define _mm_punpcklhw(_D, _d, _s) \
|
||||
"punpckhhw %["#_D"h], %["#_d"l], %["#_s"l] \n\t" \
|
||||
"punpcklhw %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: punpckldq */
|
||||
#define _mm_punpcklwd(_D, _d, _s) \
|
||||
"punpckhwd %["#_D"h], %["#_d"l], %["#_s"l] \n\t" \
|
||||
"punpcklwd %["#_D"l], %["#_d"l], %["#_s"l] \n\t"
|
||||
|
||||
/* SSE: punpcklqdq */
|
||||
#define _mm_punpckldq(_D, _d, _s) \
|
||||
"mov.d %["#_D"h], %["#_s"l] \n\t" \
|
||||
"mov.d %["#_D"l], %["#_d"l] \n\t"
|
||||
|
||||
/* SSE: punpckhbw */
|
||||
#define _mm_punpckhbh(_D, _d, _s) \
|
||||
"punpcklbh %["#_D"l], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"punpckhbh %["#_D"h], %["#_d"h], %["#_s"h] \n\t"
|
||||
|
||||
/* SSE: punpckhwd */
|
||||
#define _mm_punpckhhw(_D, _d, _s) \
|
||||
"punpcklhw %["#_D"l], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"punpckhhw %["#_D"h], %["#_d"h], %["#_s"h] \n\t"
|
||||
|
||||
/* SSE: punpckhdq */
|
||||
#define _mm_punpckhwd(_D, _d, _s) \
|
||||
"punpcklwd %["#_D"l], %["#_d"h], %["#_s"h] \n\t" \
|
||||
"punpckhwd %["#_D"h], %["#_d"h], %["#_s"h] \n\t"
|
||||
|
||||
/* SSE: punpckhqdq */
|
||||
#define _mm_punpckhdq(_D, _d, _s) \
|
||||
"mov.d %["#_D"l], %["#_d"h] \n\t" \
|
||||
"mov.d %["#_D"h], %["#_s"h] \n\t"
|
||||
|
||||
#endif /* __MMI_HELPERS_H__ */
|
||||
|
||||
@@ -101,6 +101,7 @@ SourceSurfaceSkia::InitFromTexture(DrawTargetSkia* aOwner,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
MOZ_ASSERT(aOwner, "null GrContext");
|
||||
#ifdef USE_SKIA_GPU
|
||||
GrBackendTextureDesc skiaTexGlue;
|
||||
mSize.width = skiaTexGlue.fWidth = aSize.width;
|
||||
mSize.height = skiaTexGlue.fHeight = aSize.height;
|
||||
@@ -117,6 +118,7 @@ SourceSurfaceSkia::InitFromTexture(DrawTargetSkia* aOwner,
|
||||
mBitmap.setPixelRef(texRef);
|
||||
mFormat = aFormat;
|
||||
mStride = mBitmap.rowBytes();
|
||||
#endif
|
||||
|
||||
mDrawTarget = aOwner;
|
||||
return true;
|
||||
|
||||
@@ -168,15 +168,19 @@ ImageOperations::ResizeMethod ResizeMethodToAlgorithmMethod(
|
||||
// GPU-acceleration in the cases where it is possible. So now we just
|
||||
// pick the appropriate software method for each resize quality.
|
||||
switch (method) {
|
||||
// Users of RESIZE_GOOD are willing to trade a lot of quality to
|
||||
// get speed, allowing the use of linear resampling to get hardware
|
||||
// acceleration (SRB). Hence any of our "good" software filters
|
||||
// will be acceptable, and we use the fastest one, Hamming-1.
|
||||
case ImageOperations::RESIZE_GOOD:
|
||||
// In visual tests we see that Hamming-1 is not as good as
|
||||
// Lanczos-2, however it is about 40% faster, and Lanczos-2 itself is
|
||||
// Users of RESIZE_BETTER are willing to trade some quality in order
|
||||
// to improve performance, but are guaranteed not to devolve to a linear
|
||||
// resampling. In visual tests we see that Hamming-1 is not as good as
|
||||
// Lanczos-2, however it is about 40% faster and Lanczos-2 itself is
|
||||
// about 30% faster than Lanczos-3. The use of Hamming-1 has been deemed
|
||||
// an unacceptable trade-off between quality and speed due to the limited
|
||||
// pixel space it operates in (<50%) before switching to HQ scaling
|
||||
// becomes necessary to retain the fidelity of images.
|
||||
// an acceptable trade-off between quality and speed.
|
||||
case ImageOperations::RESIZE_BETTER:
|
||||
return ImageOperations::RESIZE_LANCZOS2;
|
||||
return ImageOperations::RESIZE_HAMMING1;
|
||||
default:
|
||||
return ImageOperations::RESIZE_LANCZOS3;
|
||||
}
|
||||
|
||||
@@ -165,12 +165,12 @@ LayerManager::CreatePersistentBufferProvider(const mozilla::gfx::IntSize &aSize,
|
||||
mozilla::gfx::SurfaceFormat aFormat)
|
||||
{
|
||||
RefPtr<PersistentBufferProviderBasic> bufferProvider =
|
||||
new PersistentBufferProviderBasic(this, aSize, aFormat,
|
||||
new PersistentBufferProviderBasic(aSize, aFormat,
|
||||
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
|
||||
|
||||
if (!bufferProvider->IsValid()) {
|
||||
bufferProvider =
|
||||
new PersistentBufferProviderBasic(this, aSize, aFormat,
|
||||
new PersistentBufferProviderBasic(aSize, aFormat,
|
||||
gfxPlatform::GetPlatform()->GetFallbackCanvasBackend());
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ using namespace gfx;
|
||||
|
||||
namespace layers {
|
||||
|
||||
PersistentBufferProviderBasic::PersistentBufferProviderBasic(LayerManager* aManager, gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat, gfx::BackendType aBackend)
|
||||
PersistentBufferProviderBasic::PersistentBufferProviderBasic(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend)
|
||||
{
|
||||
mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForBackend(aBackend, aSize, aFormat);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define MOZILLA_GFX_PersistentBUFFERPROVIDER_H
|
||||
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef, etc
|
||||
#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/CompositableForwarder.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
@@ -57,8 +57,9 @@ class PersistentBufferProviderBasic : public PersistentBufferProvider
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic)
|
||||
|
||||
PersistentBufferProviderBasic(LayerManager* aManager, gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat, gfx::BackendType aBackend);
|
||||
PersistentBufferProviderBasic(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend);
|
||||
explicit PersistentBufferProviderBasic(gfx::DrawTarget* aTarget) : mDrawTarget(aTarget) {}
|
||||
|
||||
bool IsValid() { return !!mDrawTarget; }
|
||||
virtual LayersBackend GetType() { return LayersBackend::LAYERS_BASIC; }
|
||||
@@ -69,6 +70,7 @@ private:
|
||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1104,6 +1104,7 @@ void
|
||||
gfxPlatform::InitializeSkiaCacheLimits()
|
||||
{
|
||||
if (UseAcceleratedSkiaCanvas()) {
|
||||
#ifdef USE_SKIA_GPU
|
||||
bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
|
||||
int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
|
||||
int cacheSizeLimit = gfxPrefs::CanvasSkiaGLCacheSize();
|
||||
@@ -1125,7 +1126,6 @@ gfxPlatform::InitializeSkiaCacheLimits()
|
||||
printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
mSkiaGlue->GetGrContext()->setResourceCacheLimits(cacheItemLimit, cacheSizeLimit);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ private:
|
||||
{
|
||||
Work work;
|
||||
work.mType = Work::Type::DECODE;
|
||||
work.mDecoder = aQueue.LastElement();
|
||||
work.mDecoder = aQueue.LastElement().forget();
|
||||
aQueue.RemoveElementAt(aQueue.Length() - 1);
|
||||
|
||||
return work;
|
||||
|
||||
+3
-2
@@ -431,9 +431,10 @@ Decoder::PostIsAnimated(int32_t aFirstFrameTimeout)
|
||||
}
|
||||
|
||||
void
|
||||
Decoder::PostFrameStop(Opacity aFrameOpacity /* = Opacity::TRANSPARENT */,
|
||||
Decoder::PostFrameStop(Opacity aFrameOpacity
|
||||
/* = Opacity::SOME_TRANSPARENCY */,
|
||||
DisposalMethod aDisposalMethod
|
||||
/* = DisposalMethod::KEEP */,
|
||||
/* = DisposalMethod::KEEP */,
|
||||
int32_t aTimeout /* = 0 */,
|
||||
BlendMethod aBlendMethod /* = BlendMethod::OVER */)
|
||||
{
|
||||
|
||||
@@ -196,7 +196,6 @@ public:
|
||||
bool HasDecoderError() const { return NS_FAILED(mFailCode); }
|
||||
bool ShouldReportError() const { return mShouldReportError; }
|
||||
nsresult GetDecoderError() const { return mFailCode; }
|
||||
void PostResizeError() { PostDataError(); }
|
||||
|
||||
/// Did we finish decoding enough that calling Decode() again would be useless?
|
||||
bool GetDecodeDone() const
|
||||
@@ -205,10 +204,6 @@ public:
|
||||
HasError() || mDataDone;
|
||||
}
|
||||
|
||||
/// Did we finish decoding enough to set |RasterImage::mHasBeenDecoded|?
|
||||
// XXX(seth): This will be removed in bug 1187401.
|
||||
bool GetDecodeTotallyDone() const { return mDecodeDone && !IsMetadataDecode(); }
|
||||
|
||||
/// Are we in the middle of a frame right now? Used for assertions only.
|
||||
bool InFrame() const { return mInFrame; }
|
||||
|
||||
|
||||
+25
-10
@@ -38,10 +38,16 @@ public:
|
||||
void BlockUntilDecodedAndFinishObserving()
|
||||
{
|
||||
// Use GetFrame() to block until our image finishes decoding.
|
||||
mImage->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_SYNC_DECODE);
|
||||
nsRefPtr<SourceSurface> surface =
|
||||
mImage->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_SYNC_DECODE);
|
||||
|
||||
FinishObserving();
|
||||
// GetFrame() should've sent synchronous notifications that would have
|
||||
// caused us to call FinishObserving() (and null out mImage) already. If for
|
||||
// some reason it didn't, we should do so here.
|
||||
if (mImage) {
|
||||
FinishObserving();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Notify(int32_t aType,
|
||||
@@ -129,9 +135,7 @@ MultipartImage::~MultipartImage()
|
||||
mTracker->ResetImage();
|
||||
}
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE_INHERITED0(MultipartImage, ImageWrapper)
|
||||
NS_IMPL_ADDREF(MultipartImage)
|
||||
NS_IMPL_RELEASE(MultipartImage)
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(MultipartImage, ImageWrapper)
|
||||
|
||||
void
|
||||
MultipartImage::BeginTransitionToPart(Image* aNextPart)
|
||||
@@ -154,7 +158,16 @@ MultipartImage::BeginTransitionToPart(Image* aNextPart)
|
||||
mNextPart->IncrementAnimationConsumers();
|
||||
}
|
||||
|
||||
void MultipartImage::FinishTransition()
|
||||
static Progress
|
||||
FilterProgress(Progress aProgress)
|
||||
{
|
||||
// Filter out onload blocking notifications, since we don't want to block
|
||||
// onload for multipart images.
|
||||
return aProgress & ~(FLAG_ONLOAD_BLOCKED | FLAG_ONLOAD_UNBLOCKED);
|
||||
}
|
||||
|
||||
void
|
||||
MultipartImage::FinishTransition()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mNextPart, "Should have a next part here");
|
||||
@@ -169,7 +182,8 @@ void MultipartImage::FinishTransition()
|
||||
mTracker->ResetForNewRequest();
|
||||
nsRefPtr<ProgressTracker> currentPartTracker =
|
||||
InnerImage()->GetProgressTracker();
|
||||
mTracker->SyncNotifyProgress(currentPartTracker->GetProgress());
|
||||
mTracker
|
||||
->SyncNotifyProgress(FilterProgress(currentPartTracker->GetProgress()));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -189,8 +203,9 @@ void MultipartImage::FinishTransition()
|
||||
|
||||
// Finally, send all the notifications for the new current part and send a
|
||||
// FRAME_UPDATE notification so that observers know to redraw.
|
||||
mTracker->SyncNotifyProgress(newCurrentPartTracker->GetProgress(),
|
||||
GetMaxSizedIntRect());
|
||||
mTracker
|
||||
->SyncNotifyProgress(FilterProgress(newCurrentPartTracker->GetProgress()),
|
||||
GetMaxSizedIntRect());
|
||||
}
|
||||
|
||||
already_AddRefed<imgIContainer>
|
||||
|
||||
@@ -25,7 +25,7 @@ class MultipartImage
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(MultipartImage)
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
void BeginTransitionToPart(Image* aNextPart);
|
||||
|
||||
|
||||
+2
-2
@@ -56,7 +56,7 @@ struct Orientation
|
||||
Flip flip;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_image_Orientation_h
|
||||
|
||||
@@ -441,13 +441,14 @@ void
|
||||
ProgressTracker::AddObserver(IProgressObserver* aObserver)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsRefPtr<IProgressObserver> observer = aObserver;
|
||||
|
||||
mObservers.Write([=](ObserverTable* aTable) {
|
||||
MOZ_ASSERT(!aTable->Get(aObserver, nullptr),
|
||||
MOZ_ASSERT(!aTable->Get(observer, nullptr),
|
||||
"Adding duplicate entry for image observer");
|
||||
|
||||
WeakPtr<IProgressObserver> weakPtr = aObserver;
|
||||
aTable->Put(aObserver, weakPtr);
|
||||
WeakPtr<IProgressObserver> weakPtr = observer.get();
|
||||
aTable->Put(observer, weakPtr);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -455,11 +456,12 @@ bool
|
||||
ProgressTracker::RemoveObserver(IProgressObserver* aObserver)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsRefPtr<IProgressObserver> observer = aObserver;
|
||||
|
||||
// Remove the observer from the list.
|
||||
bool removed = mObservers.Write([=](ObserverTable* aTable) {
|
||||
bool removed = aTable->Get(aObserver, nullptr);
|
||||
aTable->Remove(aObserver);
|
||||
bool removed = aTable->Get(observer, nullptr);
|
||||
aTable->Remove(observer);
|
||||
return removed;
|
||||
});
|
||||
|
||||
|
||||
+18
-18
@@ -819,20 +819,22 @@ RasterImage::OnAddedFrame(uint32_t aNewFrameCount,
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
bool aFromMetadataDecode)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mError) {
|
||||
return NS_ERROR_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (aMetadata.HasSize()) {
|
||||
IntSize size = aMetadata.GetSize();
|
||||
if (size.width < 0 || size.height < 0) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
NS_WARNING("Image has negative intrinsic size");
|
||||
DoError();
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aMetadata.HasOrientation());
|
||||
@@ -843,7 +845,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
NS_WARNING("Image changed size or orientation on redecode! "
|
||||
"This should not happen!");
|
||||
DoError();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the size and flag that we have it.
|
||||
@@ -887,8 +889,6 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
Set("hotspotX", intwrapx);
|
||||
Set("hotspotY", intwrapy);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -1074,7 +1074,7 @@ RasterImage::NotifyForLoadEvent(Progress aProgress)
|
||||
if (mError) {
|
||||
aProgress |= FLAG_HAS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// Notify our listeners, which will fire this image's load event.
|
||||
NotifyProgress(aProgress);
|
||||
}
|
||||
@@ -1374,6 +1374,11 @@ RasterImage::RecoverFromInvalidFrames(const IntSize& aSize, uint32_t aFlags)
|
||||
// Discard all existing frames, since they're probably all now invalid.
|
||||
SurfaceCache::RemoveImage(ImageKey(this));
|
||||
|
||||
// Relock the image if it's supposed to be locked.
|
||||
if (mLockCount > 0) {
|
||||
SurfaceCache::LockImage(ImageKey(this));
|
||||
}
|
||||
|
||||
// Animated images require some special handling, because we normally require
|
||||
// that they never be discarded.
|
||||
if (mAnim) {
|
||||
@@ -1707,22 +1712,20 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
|
||||
MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(),
|
||||
"Finalizing a decoder in the middle of a frame");
|
||||
|
||||
bool wasMetadata = aDecoder->IsMetadataDecode();
|
||||
bool done = aDecoder->GetDecodeDone();
|
||||
|
||||
// If the decoder detected an error, log it to the error console.
|
||||
if (aDecoder->ShouldReportError() && !aDecoder->WasAborted()) {
|
||||
ReportDecoderError(aDecoder);
|
||||
}
|
||||
|
||||
// Record all the metadata the decoder gathered about this image.
|
||||
nsresult rv = SetMetadata(aDecoder->GetImageMetadata(),
|
||||
aDecoder->IsMetadataDecode());
|
||||
if (NS_FAILED(rv)) {
|
||||
aDecoder->PostResizeError();
|
||||
}
|
||||
|
||||
SetMetadata(aDecoder->GetImageMetadata(), wasMetadata);
|
||||
MOZ_ASSERT(mError || mHasSize || !aDecoder->HasSize(),
|
||||
"Should have handed off size by now");
|
||||
"SetMetadata should've gotten a size");
|
||||
|
||||
if (aDecoder->GetDecodeTotallyDone() && !mError) {
|
||||
if (!wasMetadata && aDecoder->GetDecodeDone() && !aDecoder->WasAborted()) {
|
||||
// Flag that we've been decoded before.
|
||||
mHasBeenDecoded = true;
|
||||
if (mAnim) {
|
||||
@@ -1735,9 +1738,6 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
|
||||
aDecoder->TakeInvalidRect(),
|
||||
aDecoder->GetSurfaceFlags());
|
||||
|
||||
bool wasMetadata = aDecoder->IsMetadataDecode();
|
||||
bool done = aDecoder->GetDecodeDone();
|
||||
|
||||
if (!wasMetadata && aDecoder->ChunkCount()) {
|
||||
/*Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS,
|
||||
aDecoder->ChunkCount());*/
|
||||
|
||||
+5
-5
@@ -325,7 +325,7 @@ private:
|
||||
* @param aFromMetadataDecode True if this metadata came from a metadata
|
||||
* decode; false if it came from a full decode.
|
||||
*/
|
||||
nsresult SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode);
|
||||
void SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode);
|
||||
|
||||
/**
|
||||
* In catastrophic circumstances like a GPU driver crash, the contents of our
|
||||
@@ -347,10 +347,10 @@ private: // data
|
||||
/// If this has a value, we're waiting for SetSize() to send the load event.
|
||||
Maybe<Progress> mLoadProgress;
|
||||
|
||||
nsCOMPtr<nsIProperties> mProperties;
|
||||
nsCOMPtr<nsIProperties> mProperties;
|
||||
|
||||
/// If this image is animated, a FrameAnimator which manages its animation.
|
||||
UniquePtr<FrameAnimator> mAnim;
|
||||
UniquePtr<FrameAnimator> mAnim;
|
||||
|
||||
// Image locking.
|
||||
uint32_t mLockCount;
|
||||
@@ -360,7 +360,7 @@ private: // data
|
||||
|
||||
// How many times we've decoded this image.
|
||||
// This is currently only used for statistics
|
||||
int32_t mDecodeCount;
|
||||
int32_t mDecodeCount;
|
||||
|
||||
// If the image contains multiple resolutions, a hint as to which one
|
||||
// should be used
|
||||
@@ -378,7 +378,7 @@ private: // data
|
||||
DrawResult mLastImageContainerDrawResult;
|
||||
|
||||
#ifdef DEBUG
|
||||
uint32_t mFramesNotified;
|
||||
uint32_t mFramesNotified;
|
||||
#endif
|
||||
|
||||
// The source data for this image.
|
||||
|
||||
@@ -35,8 +35,8 @@ class SVGSVGElement;
|
||||
namespace image {
|
||||
|
||||
class SVGDocumentWrapper final : public nsIStreamListener,
|
||||
public nsIObserver,
|
||||
nsSupportsWeakReference
|
||||
public nsIObserver,
|
||||
nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
SVGDocumentWrapper();
|
||||
|
||||
@@ -120,7 +120,8 @@ public:
|
||||
/// If at the end, returns the status passed to SourceBuffer::Complete().
|
||||
nsresult CompletionStatus() const
|
||||
{
|
||||
MOZ_ASSERT(mState == COMPLETE, "Calling CompletionStatus() in the wrong state");
|
||||
MOZ_ASSERT(mState == COMPLETE,
|
||||
"Calling CompletionStatus() in the wrong state");
|
||||
return mState == COMPLETE ? mData.mAtEnd.mStatus : NS_OK;
|
||||
}
|
||||
|
||||
@@ -209,12 +210,6 @@ private:
|
||||
* keep a list of consumers which are waiting for new data, and to resume them
|
||||
* when the producer appends more. All consumers must implement the IResumable
|
||||
* interface to make this possible.
|
||||
*
|
||||
* XXX(seth): We should add support for compacting a SourceBuffer. To do this,
|
||||
* we need to have SourceBuffer keep track of how many live
|
||||
* SourceBufferIterator's point to it. When the SourceBuffer is complete and no
|
||||
* live SourceBufferIterator's for it remain, we can compact its contents into a
|
||||
* single chunk.
|
||||
*/
|
||||
class SourceBuffer final
|
||||
{
|
||||
|
||||
+19
-1
@@ -35,6 +35,7 @@
|
||||
#include "nsSize.h"
|
||||
#include "nsTArray.h"
|
||||
#include "prsystem.h"
|
||||
#include "ShutdownTracker.h"
|
||||
#include "SVGImageContext.h"
|
||||
|
||||
using std::max;
|
||||
@@ -436,6 +437,7 @@ public:
|
||||
, mMaxCost(aSurfaceCacheSize)
|
||||
, mAvailableCost(aSurfaceCacheSize)
|
||||
, mLockedCost(0)
|
||||
, mOverflowCount(0)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
@@ -483,6 +485,7 @@ public:
|
||||
// If this is bigger than we can hold after discarding everything we can,
|
||||
// refuse to cache it.
|
||||
if (MOZ_UNLIKELY(!CanHoldAfterDiscarding(aCost))) {
|
||||
mOverflowCount++;
|
||||
return InsertOutcome::FAILURE;
|
||||
}
|
||||
|
||||
@@ -582,7 +585,8 @@ public:
|
||||
} else {
|
||||
// Our call to AddObject must have failed in StartTracking; most likely
|
||||
// we're in XPCOM shutdown right now.
|
||||
NS_WARNING("Not expiration-tracking an unlocked surface!");
|
||||
NS_ASSERTION(ShutdownTracker::ShutdownHasStarted(),
|
||||
"Not expiration-tracking an unlocked surface!");
|
||||
}
|
||||
|
||||
DebugOnly<bool> foundInCosts = mCosts.RemoveElementSorted(costEntry);
|
||||
@@ -863,6 +867,14 @@ public:
|
||||
"imagelib surface cache.");
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-overflow-count",
|
||||
KIND_OTHER, UNITS_COUNT,
|
||||
mOverflowCount,
|
||||
"Count of how many times the surface cache has hit "
|
||||
"its capacity and been unable to insert a new "
|
||||
"surface.");
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -962,6 +974,7 @@ private:
|
||||
const Cost mMaxCost;
|
||||
Cost mAvailableCost;
|
||||
Cost mLockedCost;
|
||||
size_t mOverflowCount;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(SurfaceCacheImpl, nsIMemoryReporter)
|
||||
@@ -1079,6 +1092,11 @@ SurfaceCache::Insert(imgFrame* aSurface,
|
||||
return InsertOutcome::FAILURE;
|
||||
}
|
||||
|
||||
// Refuse null surfaces.
|
||||
if (!aSurface) {
|
||||
MOZ_CRASH("Don't pass null surfaces to SurfaceCache::Insert");
|
||||
}
|
||||
|
||||
MutexAutoLock lock(sInstance->GetMutex());
|
||||
Cost cost = ComputeCost(aSurface->GetSize(), aSurface->GetBytesPerPixel());
|
||||
return sInstance->Insert(aSurface, cost, aImageKey, aSurfaceKey);
|
||||
|
||||
+45
-41
@@ -9,7 +9,6 @@
|
||||
#include "gfxContext.h"
|
||||
#include "gfxDrawable.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxPrefs.h" // for surface cache size
|
||||
#include "gfxUtils.h"
|
||||
#include "imgFrame.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
@@ -49,6 +48,8 @@ namespace image {
|
||||
// Helper-class: SVGRootRenderingObserver
|
||||
class SVGRootRenderingObserver final : public nsSVGRenderingObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
SVGRootRenderingObserver(SVGDocumentWrapper* aDocWrapper,
|
||||
VectorImage* aVectorImage)
|
||||
: nsSVGRenderingObserver()
|
||||
@@ -67,10 +68,6 @@ public:
|
||||
mInObserverList = true;
|
||||
}
|
||||
|
||||
virtual ~SVGRootRenderingObserver()
|
||||
{
|
||||
StopListening();
|
||||
}
|
||||
|
||||
void ResumeHonoringInvalidations()
|
||||
{
|
||||
@@ -78,6 +75,11 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~SVGRootRenderingObserver()
|
||||
{
|
||||
StopListening();
|
||||
}
|
||||
|
||||
virtual Element* GetTarget() override
|
||||
{
|
||||
return mDocWrapper->GetRootSVGElem();
|
||||
@@ -115,6 +117,8 @@ protected:
|
||||
bool mHonoringInvalidations;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(SVGRootRenderingObserver, nsIMutationObserver)
|
||||
|
||||
class SVGParseCompleteListener final : public nsStubDocumentObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@@ -418,13 +422,18 @@ VectorImage::OnImageDataComplete(nsIRequest* aRequest,
|
||||
if (NS_FAILED(aStatus)) {
|
||||
finalStatus = aStatus;
|
||||
}
|
||||
|
||||
Progress loadProgress = LoadCompleteProgress(aLastPart, mError, finalStatus);
|
||||
|
||||
// Actually fire OnStopRequest.
|
||||
if (mProgressTracker) {
|
||||
mProgressTracker->SyncNotifyProgress(LoadCompleteProgress(aLastPart,
|
||||
mError,
|
||||
finalStatus));
|
||||
if (mIsFullyLoaded || mError) {
|
||||
// Our document is loaded, so we're ready to notify now.
|
||||
mProgressTracker->SyncNotifyProgress(loadProgress);
|
||||
} else {
|
||||
// Record our progress so far; we'll actually send the notifications in
|
||||
// OnSVGDocumentLoaded or OnSVGDocumentError.
|
||||
mLoadProgress = Some(loadProgress);
|
||||
}
|
||||
|
||||
return finalStatus;
|
||||
}
|
||||
|
||||
@@ -867,32 +876,12 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams)
|
||||
nsRefPtr<gfxDrawable> svgDrawable =
|
||||
new gfxCallbackDrawable(cb, aParams.size);
|
||||
|
||||
// We take an early exit without using the surface cache if too large,
|
||||
// because for vector images this can cause bad perf issues if large sizes
|
||||
// are scaled repeatedly (a rather common scenario) that can quickly exhaust
|
||||
// the cache.
|
||||
// Similar to max image size calculations, this has a max cap and size check.
|
||||
// max cap = 8000 (pixels); size check = 5% of cache
|
||||
int32_t maxDimension = 8000;
|
||||
int32_t maxCacheElemSize = (gfxPrefs::ImageMemSurfaceCacheMaxSizeKB() * 1024) / 20;
|
||||
|
||||
bool bypassCache = bool(aParams.flags & FLAG_BYPASS_SURFACE_CACHE) ||
|
||||
// Refuse to cache animated images:
|
||||
// XXX(seth): We may remove this restriction in bug 922893.
|
||||
mHaveAnimations ||
|
||||
// The image is too big to fit in the cache:
|
||||
!SurfaceCache::CanHold(aParams.size) ||
|
||||
// Image x or y is larger than our cache cap:
|
||||
aParams.size.width > maxDimension ||
|
||||
aParams.size.height > maxDimension;
|
||||
if (!bypassCache) {
|
||||
// This is separated out to make sure width and height are sane at this point
|
||||
// and the result can't overflow. Note: keep maxDimension low enough so that
|
||||
// (maxDimension)^2 x 4 < INT32_MAX.
|
||||
// Assuming surface size for any rendered vector image is RGBA, so 4Bpp.
|
||||
bypassCache = (aParams.size.width * aParams.size.height * 4) > maxCacheElemSize;
|
||||
}
|
||||
|
||||
!SurfaceCache::CanHold(aParams.size);
|
||||
if (bypassCache) {
|
||||
return Show(svgDrawable, aParams);
|
||||
}
|
||||
@@ -1193,12 +1182,19 @@ VectorImage::OnSVGDocumentLoaded()
|
||||
|
||||
// Tell *our* observers that we're done loading.
|
||||
if (mProgressTracker) {
|
||||
mProgressTracker->SyncNotifyProgress(FLAG_SIZE_AVAILABLE |
|
||||
FLAG_HAS_TRANSPARENCY |
|
||||
FLAG_FRAME_COMPLETE |
|
||||
FLAG_DECODE_COMPLETE |
|
||||
FLAG_ONLOAD_UNBLOCKED,
|
||||
GetMaxSizedIntRect());
|
||||
Progress progress = FLAG_SIZE_AVAILABLE |
|
||||
FLAG_HAS_TRANSPARENCY |
|
||||
FLAG_FRAME_COMPLETE |
|
||||
FLAG_DECODE_COMPLETE |
|
||||
FLAG_ONLOAD_UNBLOCKED;
|
||||
|
||||
// Merge in any saved progress from OnImageDataComplete.
|
||||
if (mLoadProgress) {
|
||||
progress |= *mLoadProgress;
|
||||
mLoadProgress = Nothing();
|
||||
}
|
||||
|
||||
mProgressTracker->SyncNotifyProgress(progress, GetMaxSizedIntRect());
|
||||
}
|
||||
|
||||
EvaluateAnimation();
|
||||
@@ -1215,10 +1211,18 @@ VectorImage::OnSVGDocumentError()
|
||||
mError = true;
|
||||
|
||||
if (mProgressTracker) {
|
||||
// Unblock page load.
|
||||
mProgressTracker->SyncNotifyProgress(FLAG_DECODE_COMPLETE |
|
||||
FLAG_ONLOAD_UNBLOCKED |
|
||||
FLAG_HAS_ERROR);
|
||||
// Notify observers about the error and unblock page load.
|
||||
Progress progress = FLAG_DECODE_COMPLETE |
|
||||
FLAG_ONLOAD_UNBLOCKED |
|
||||
FLAG_HAS_ERROR;
|
||||
|
||||
// Merge in any saved progress from OnImageDataComplete.
|
||||
if (mLoadProgress) {
|
||||
progress |= *mLoadProgress;
|
||||
mLoadProgress = Nothing();
|
||||
}
|
||||
|
||||
mProgressTracker->SyncNotifyProgress(progress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -23,7 +23,7 @@ class SVGLoadEventListener;
|
||||
class SVGParseCompleteListener;
|
||||
|
||||
class VectorImage final : public ImageResource,
|
||||
public nsIStreamListener
|
||||
public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@@ -102,6 +102,12 @@ private:
|
||||
/// Count of locks on this image (roughly correlated to visible instances).
|
||||
uint32_t mLockCount;
|
||||
|
||||
// Stored result from the Necko load of the image, which we save in
|
||||
// OnImageDataComplete if the underlying SVG document isn't loaded. If we save
|
||||
// this, we actually notify this progress (and clear this value) in
|
||||
// OnSVGDocumentLoaded or OnSVGDocumentError.
|
||||
Maybe<Progress> mLoadProgress;
|
||||
|
||||
bool mIsInitialized; // Have we been initialized?
|
||||
bool mDiscardable; // Are we discardable?
|
||||
bool mIsFullyLoaded; // Has the SVG document finished
|
||||
|
||||
+52
-16
@@ -219,6 +219,8 @@ private:
|
||||
const char* aPathPrefix,
|
||||
const ImageMemoryCounter& aCounter)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/"));
|
||||
pathPrefix.Append(aPathPrefix);
|
||||
pathPrefix.Append(aCounter.Type() == imgIContainer::TYPE_RASTER
|
||||
@@ -239,7 +241,13 @@ private:
|
||||
|
||||
pathPrefix.Append(")/");
|
||||
|
||||
return ReportSurfaces(aHandleReport, aData, pathPrefix, aCounter);
|
||||
rv = ReportSurfaces(aHandleReport, aData, pathPrefix, aCounter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ReportSourceValue(aHandleReport, aData, pathPrefix, aCounter.Values());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult ReportSurfaces(nsIHandleReportCallback* aHandleReport,
|
||||
@@ -344,10 +352,7 @@ private:
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
|
||||
"source",
|
||||
"Raster image source data and vector image documents.",
|
||||
aCounter.Source());
|
||||
rv = ReportSourceValue(aHandleReport, aData, aPathPrefix, aCounter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
|
||||
@@ -365,6 +370,21 @@ private:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult ReportSourceValue(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData,
|
||||
const nsACString& aPathPrefix,
|
||||
const MemoryCounter& aCounter)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix,
|
||||
"source",
|
||||
"Raster image source data and vector image documents.",
|
||||
aCounter.Source());
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static nsresult ReportValue(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData,
|
||||
int32_t aKind,
|
||||
@@ -706,6 +726,8 @@ NewImageChannel(nsIChannel** aResult,
|
||||
nsIPrincipal* aLoadingPrincipal,
|
||||
nsISupports* aRequestingContext)
|
||||
{
|
||||
MOZ_ASSERT(aResult);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHttpChannel> newHttpChannel;
|
||||
|
||||
@@ -768,7 +790,9 @@ NewImageChannel(nsIChannel** aResult,
|
||||
// we should always have a requestingNode, or we are loading something
|
||||
// outside a document, in which case the triggeringPrincipal
|
||||
// should always be the systemPrincipal.
|
||||
MOZ_ASSERT(nsContentUtils::IsSystemPrincipal(triggeringPrincipal));
|
||||
// However, there are two exceptions: one is Notifications and the
|
||||
// other one is Favicons which create a channel in the parent prcoess
|
||||
// in which case we can't get a requestingNode.
|
||||
rv = NS_NewChannel(aResult,
|
||||
aURI,
|
||||
triggeringPrincipal,
|
||||
@@ -1446,9 +1470,8 @@ imgLoader::PutIntoCache(const ImageCacheKey& aKey, imgCacheEntry* entry)
|
||||
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(),
|
||||
"imgLoader::PutIntoCache", "uri", aKey.Spec());
|
||||
|
||||
// Check to see if this request already exists in the cache and is being
|
||||
// loaded on a different thread. If so, don't allow this entry to be added to
|
||||
// the cache.
|
||||
// Check to see if this request already exists in the cache. If so, we'll
|
||||
// replace the old version.
|
||||
nsRefPtr<imgCacheEntry> tmpCacheEntry;
|
||||
if (cache.Get(aKey, getter_AddRefs(tmpCacheEntry)) && tmpCacheEntry) {
|
||||
MOZ_LOG(GetImgLog(), LogLevel::Debug,
|
||||
@@ -1813,7 +1836,7 @@ imgLoader::ValidateEntry(imgCacheEntry* aEntry,
|
||||
// XXX: nullptr seems to be a 'special' key value that indicates that NO
|
||||
// validation is required.
|
||||
//
|
||||
void *key = (void*)aCX;
|
||||
void *key = (void*) aCX;
|
||||
if (request->LoadId() != key) {
|
||||
// If we would need to revalidate this entry, but we're being told to
|
||||
// bypass the cache, we don't allow this entry to be used.
|
||||
@@ -2976,6 +2999,9 @@ imgCacheValidator::RemoveProxy(imgRequestProxy* aProxy)
|
||||
NS_IMETHODIMP
|
||||
imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
{
|
||||
// We may be holding on to a document, so ensure that it's released.
|
||||
nsCOMPtr<nsISupports> context = mContext.forget();
|
||||
|
||||
// If for some reason we don't still have an existing request (probably
|
||||
// because OnStartRequest got delivered more than once), just bail.
|
||||
if (!mRequest) {
|
||||
@@ -3024,7 +3050,7 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
// We don't need to load this any more.
|
||||
aRequest->Cancel(NS_BINDING_ABORTED);
|
||||
|
||||
mRequest->SetLoadId(mContext);
|
||||
mRequest->SetLoadId(context);
|
||||
mRequest->SetValidator(nullptr);
|
||||
|
||||
mRequest = nullptr;
|
||||
@@ -3067,7 +3093,7 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
channel->GetOriginalURI(getter_AddRefs(originalURI));
|
||||
mNewRequest->Init(originalURI, uri, mHadInsecureRedirect, aRequest, channel,
|
||||
mNewEntry, mContext, loadingPrincipal, corsmode, refpol);
|
||||
mNewEntry, context, loadingPrincipal, corsmode, refpol);
|
||||
|
||||
mDestListener = new ProxyListener(mNewRequest);
|
||||
|
||||
@@ -3093,11 +3119,19 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
return mDestListener->OnStartRequest(aRequest, ctxt);
|
||||
}
|
||||
|
||||
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */
|
||||
NS_IMETHODIMP imgCacheValidator::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status)
|
||||
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt,
|
||||
in nsresult status); */
|
||||
NS_IMETHODIMP
|
||||
imgCacheValidator::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* ctxt,
|
||||
nsresult status)
|
||||
{
|
||||
if (!mDestListener)
|
||||
// Be sure we've released the document that we may have been holding on to.
|
||||
mContext = nullptr;
|
||||
|
||||
if (!mDestListener) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mDestListener->OnStopRequest(aRequest, ctxt, status);
|
||||
}
|
||||
@@ -3180,7 +3214,9 @@ imgCacheValidator::
|
||||
if (NS_FAILED(oldChannel->GetURI(getter_AddRefs(oldURI))) ||
|
||||
NS_FAILED(oldURI->SchemeIs("https", &isHttps)) ||
|
||||
NS_FAILED(oldURI->SchemeIs("chrome", &isChrome)) ||
|
||||
NS_FAILED(NS_URIChainHasFlags(oldURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE , &schemeLocal)) ||
|
||||
NS_FAILED(NS_URIChainHasFlags(oldURI,
|
||||
nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
|
||||
&schemeLocal)) ||
|
||||
(!isHttps && !isChrome && !schemeLocal)) {
|
||||
mHadInsecureRedirect = true;
|
||||
}
|
||||
|
||||
+28
-22
@@ -634,17 +634,6 @@ imgRequest::SetCacheValidation(imgCacheEntry* aCacheEntry, nsIRequest* aRequest)
|
||||
aCacheEntry->SetMustValidate(bMustRevalidate);
|
||||
}
|
||||
}
|
||||
|
||||
// We always need to validate file URIs.
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if (channel) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
bool isfile = false;
|
||||
uri->SchemeIs("file", &isfile);
|
||||
if (isfile)
|
||||
aCacheEntry->SetMustValidate(isfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -718,6 +707,13 @@ imgRequest::GetMultipart() const
|
||||
return mIsMultiPartChannel;
|
||||
}
|
||||
|
||||
bool
|
||||
imgRequest::HadInsecureRedirect() const
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
return mHadInsecureRedirect;
|
||||
}
|
||||
|
||||
/** nsIRequestObserver methods **/
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -737,7 +733,7 @@ imgRequest::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
mIsMultiPartChannel = bool(multiPartChannel);
|
||||
}
|
||||
|
||||
// If we're not multipart, we shouldn't have an image yet
|
||||
// If we're not multipart, we shouldn't have an image yet.
|
||||
if (image && !multiPartChannel) {
|
||||
MOZ_ASSERT_UNREACHABLE("Already have an image for a non-multipart request");
|
||||
Cancel(NS_IMAGELIB_ERROR_FAILURE);
|
||||
@@ -752,7 +748,6 @@ imgRequest::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=339610
|
||||
*/
|
||||
if (!mRequest) {
|
||||
nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
|
||||
MOZ_ASSERT(multiPartChannel, "Should have mRequest unless we're multipart");
|
||||
nsCOMPtr<nsIChannel> baseChannel;
|
||||
multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
|
||||
@@ -950,20 +945,20 @@ PrepareForNewPart(nsIRequest* aRequest, nsIInputStream* aInStr, uint32_t aCount,
|
||||
|
||||
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
|
||||
if (result.mContentType.IsEmpty()) {
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (chan) {
|
||||
rv = chan->GetContentType(result.mContentType);
|
||||
chan->GetContentDispositionHeader(result.mContentDisposition);
|
||||
}
|
||||
|
||||
nsresult rv = chan ? chan->GetContentType(result.mContentType)
|
||||
: NS_ERROR_FAILURE;
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(GetImgLog(),
|
||||
LogLevel::Error, ("imgRequest::PrepareForNewPart "
|
||||
"-- Content type unavailable from the channel\n"));
|
||||
LogLevel::Error, ("imgRequest::PrepareForNewPart -- "
|
||||
"Content type unavailable from the channel\n"));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan) {
|
||||
chan->GetContentDispositionHeader(result.mContentDisposition);
|
||||
}
|
||||
|
||||
MOZ_LOG(GetImgLog(), LogLevel::Debug,
|
||||
("imgRequest::PrepareForNewPart -- Got content type %s\n",
|
||||
result.mContentType.get()));
|
||||
@@ -1269,7 +1264,18 @@ imgRequest::OnRedirectVerifyCallback(nsresult result)
|
||||
nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
|
||||
&schemeLocal)) ||
|
||||
(!isHttps && !isChrome && !schemeLocal)) {
|
||||
mHadInsecureRedirect = true;
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
// The csp directive upgrade-insecure-requests performs an internal redirect
|
||||
// to upgrade all requests from http to https before any data is fetched from
|
||||
// the network. Do not pollute mHadInsecureRedirect in case of such an internal
|
||||
// redirect.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
|
||||
bool upgradeInsecureRequests = loadInfo ? loadInfo->GetUpgradeInsecureRequests()
|
||||
: false;
|
||||
if (!upgradeInsecureRequests) {
|
||||
mHadInsecureRedirect = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the current URI.
|
||||
|
||||
+5
-5
@@ -44,10 +44,10 @@ class ProgressTracker;
|
||||
struct NewPartResult;
|
||||
|
||||
class imgRequest final : public nsIStreamListener,
|
||||
public nsIThreadRetargetableStreamListener,
|
||||
public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIAsyncVerifyRedirectCallback
|
||||
public nsIThreadRetargetableStreamListener,
|
||||
public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIAsyncVerifyRedirectCallback
|
||||
{
|
||||
typedef mozilla::image::Image Image;
|
||||
typedef mozilla::image::ImageCacheKey ImageCacheKey;
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
|
||||
// Returns whether we went through an insecure (non-HTTPS) redirect at some
|
||||
// point during loading. This does not consider the current URI.
|
||||
bool HadInsecureRedirect() const { return mHadInsecureRedirect; }
|
||||
bool HadInsecureRedirect() const;
|
||||
|
||||
// The CORS mode for which we loaded this image.
|
||||
int32_t GetCORSMode() const { return mCORSMode; }
|
||||
|
||||
@@ -203,7 +203,10 @@ private:
|
||||
// mListener is only promised to be a weak ref (see imgILoader.idl),
|
||||
// but we actually keep a strong ref to it until we've seen our
|
||||
// first OnStopRequest.
|
||||
imgINotificationObserver* mListener;
|
||||
imgINotificationObserver* MOZ_UNSAFE_REF("Observers must call Cancel() or "
|
||||
"CancelAndForgetObserver() before "
|
||||
"they are destroyed") mListener;
|
||||
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
|
||||
nsLoadFlags mLoadFlags;
|
||||
|
||||
@@ -19,7 +19,6 @@ MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
|
||||
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'imgICache.idl',
|
||||
'imgIContainer.idl',
|
||||
@@ -36,7 +35,6 @@ XPIDL_SOURCES += [
|
||||
|
||||
XPIDL_MODULE = 'imglib2'
|
||||
|
||||
|
||||
EXPORTS += [
|
||||
'ImageCacheKey.h',
|
||||
'ImageLogging.h',
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var timer = Components.classes["@mozilla.org/timer;1"];
|
||||
var waitTimer = timer.createInstance(Components.interfaces.nsITimer);
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.processAsync();
|
||||
waitForFinish(response);
|
||||
}
|
||||
|
||||
function waitForFinish(response) {
|
||||
if (getSharedState("all-parts-done") === "1") {
|
||||
response.write("done");
|
||||
response.finish();
|
||||
} else {
|
||||
waitTimer.initWithCallback(function() {waitForFinish(response);}, 10,
|
||||
Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var counter = 100;
|
||||
var timer = Components.classes["@mozilla.org/timer;1"];
|
||||
var partTimer = timer.createInstance(Components.interfaces.nsITimer);
|
||||
|
||||
function getFileAsInputStream(aFilename) {
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties)
|
||||
.get("CurWorkD", Components.interfaces.nsIFile);
|
||||
|
||||
file.append("tests");
|
||||
file.append("image");
|
||||
file.append("test");
|
||||
file.append("mochitest");
|
||||
file.append(aFilename);
|
||||
|
||||
var fileStream = Components.classes['@mozilla.org/network/file-input-stream;1']
|
||||
.createInstance(Components.interfaces.nsIFileInputStream);
|
||||
fileStream.init(file, 1, 0, false);
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
response.setHeader("Content-Type",
|
||||
"multipart/x-mixed-replace;boundary=BOUNDARYOMG", false);
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
// We're sending parts off in a delayed fashion, to let the tests occur.
|
||||
response.processAsync();
|
||||
response.write("--BOUNDARYOMG\r\n");
|
||||
sendParts(response);
|
||||
}
|
||||
|
||||
function sendParts(response) {
|
||||
if (counter-- == 0) {
|
||||
sendClose(response);
|
||||
setSharedState("all-parts-done", "1");
|
||||
return;
|
||||
}
|
||||
sendNextPart(response);
|
||||
partTimer.initWithCallback(function() {sendParts(response);}, 1,
|
||||
Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
function sendClose(response) {
|
||||
response.write("--BOUNDARYOMG--\r\n");
|
||||
response.finish();
|
||||
}
|
||||
|
||||
function sendNextPart(response) {
|
||||
var nextPartHead = "Content-Type: image/jpeg\r\n\r\n";
|
||||
var inputStream = getFileAsInputStream("damon.jpg");
|
||||
response.bodyOutputStream.write(nextPartHead, nextPartHead.length);
|
||||
response.bodyOutputStream.writeFrom(inputStream, inputStream.available());
|
||||
inputStream.close();
|
||||
// Toss in the boundary, so the browser can know this part is complete
|
||||
response.write("--BOUNDARYOMG\r\n");
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ support-files =
|
||||
bug89419.sjs
|
||||
bug900200.png
|
||||
bug900200-ref.png
|
||||
bug1180105.sjs
|
||||
bug1180105-waiter.sjs
|
||||
clear.gif
|
||||
clear.png
|
||||
clear2.gif
|
||||
@@ -86,6 +88,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
|
||||
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
|
||||
[test_bug89419-2.html]
|
||||
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
|
||||
[test_bug1180105.html]
|
||||
[test_animation_operators.html]
|
||||
[test_drawDiscardedImage.html]
|
||||
skip-if = toolkit == "gonk" #Bug 997034 - canvas.toDataURL() often causes lost connection to device.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1180105
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1180105</title>
|
||||
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload="initializeOnload()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1180105">Mozilla Bug 1180105</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const WAITER_URL = "bug1180105-waiter.sjs";
|
||||
|
||||
function initializeOnload() {
|
||||
var firstimg = document.createElement('img');
|
||||
firstimg.src = "bug1180105.sjs";
|
||||
document.getElementById('content').appendChild(firstimg);
|
||||
|
||||
waitForFinish();
|
||||
}
|
||||
|
||||
function waitForFinish() {
|
||||
var loader = document.getElementById("loader");
|
||||
loader.src = WAITER_URL;
|
||||
loader.onload = function() {
|
||||
var img = document.getElementsByTagName('img')[0];
|
||||
ok(img.width > 0, "Image should be loaded by now");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<div id="content">>
|
||||
<iframe id="loader"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -21,9 +21,6 @@
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
// nsSVGRenderingObserver impl
|
||||
NS_IMPL_ISUPPORTS(nsSVGRenderingObserver, nsIMutationObserver)
|
||||
|
||||
void
|
||||
nsSVGRenderingObserver::StartListening()
|
||||
{
|
||||
@@ -220,6 +217,8 @@ nsSVGFrameReferenceFromProperty::Get()
|
||||
return mFrame;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsSVGRenderingObserverProperty, nsIMutationObserver)
|
||||
|
||||
void
|
||||
nsSVGRenderingObserverProperty::DoUpdate()
|
||||
{
|
||||
|
||||
@@ -55,9 +55,6 @@ public:
|
||||
: mInObserverList(false)
|
||||
{}
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
@@ -174,6 +171,8 @@ private:
|
||||
|
||||
class nsSVGRenderingObserverProperty : public nsSVGIDRenderingObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsSVGRenderingObserverProperty(nsIURI* aURI, nsIFrame *aFrame,
|
||||
bool aReferenceImage)
|
||||
: nsSVGIDRenderingObserver(aURI, aFrame->GetContent(), aReferenceImage)
|
||||
@@ -181,6 +180,8 @@ public:
|
||||
{}
|
||||
|
||||
protected:
|
||||
virtual ~nsSVGRenderingObserverProperty() {}
|
||||
|
||||
virtual void DoUpdate() override;
|
||||
|
||||
nsSVGFrameReferenceFromProperty mFrameReference;
|
||||
|
||||
@@ -698,10 +698,10 @@ pref("gfx.canvas.azure.backends", "direct2d1.1,direct2d,skia,cairo");
|
||||
pref("gfx.content.azure.backends", "direct2d1.1,direct2d,cairo");
|
||||
#else
|
||||
#ifdef XP_MACOSX
|
||||
pref("gfx.content.azure.backends", "cg");
|
||||
pref("gfx.canvas.azure.backends", "skia,cg");
|
||||
// Accelerated cg canvas where available (10.7+)
|
||||
pref("gfx.canvas.azure.accelerated", true);
|
||||
pref("gfx.content.azure.backends", "cg");
|
||||
pref("gfx.canvas.azure.accelerated", false);
|
||||
#else
|
||||
pref("gfx.canvas.azure.backends", "skia,cairo");
|
||||
pref("gfx.content.azure.backends", "cairo");
|
||||
|
||||
@@ -1014,11 +1014,6 @@ NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
|
||||
MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \
|
||||
NS_INTERFACE_TABLE_END
|
||||
|
||||
#define NS_IMPL_QUERY_INTERFACE_INHERITED0(aClass, aSuper) \
|
||||
NS_INTERFACE_TABLE_HEAD(aClass) \
|
||||
NS_INTERFACE_TABLE_INHERITED0(aClass) \
|
||||
NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)
|
||||
|
||||
#define NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, ...) \
|
||||
NS_INTERFACE_TABLE_HEAD(aClass) \
|
||||
NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__) \
|
||||
@@ -1043,7 +1038,8 @@ NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
|
||||
NS_IMPL_QUERY_INTERFACE(aClass, __VA_ARGS__)
|
||||
|
||||
#define NS_IMPL_ISUPPORTS_INHERITED0(aClass, aSuper) \
|
||||
NS_IMPL_QUERY_INTERFACE_INHERITED0(aClass, aSuper) \
|
||||
NS_INTERFACE_TABLE_HEAD(aClass) \
|
||||
NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper) \
|
||||
NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \
|
||||
NS_IMPL_RELEASE_INHERITED(aClass, aSuper) \
|
||||
|
||||
|
||||
Reference in New Issue
Block a user