--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -4746,17 +4746,21 @@ CanvasRenderingContext2D::DrawDirectlyTo
nsIntSize scaledImageSize(std::ceil(aImgSize.width * scale.width),
std::ceil(aImgSize.height * scale.height));
aSrc.Scale(scale.width, scale.height);
// We're wrapping tempTarget's (our) DrawTarget here, so we need to restore
// the matrix even though this is a temp gfxContext.
AutoRestoreTransform autoRestoreTransform(mTarget);
- RefPtr<gfxContext> context = new gfxContext(tempTarget);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(tempTarget);
+ if (!context) {
+ gfxDevCrash(LogReason::InvalidContext) << "Canvas context problem";
+ return;
+ }
context->SetMatrix(contextMatrix.
Scale(1.0 / contextScale.width,
1.0 / contextScale.height).
Translate(aDest.x - aSrc.x, aDest.y - aSrc.y));
// FLAG_CLAMP is added for increased performance, since we never tile here.
uint32_t modifiedFlags = aImage.mDrawingFlags | imgIContainer::FLAG_CLAMP;
@@ -4945,29 +4949,31 @@ CanvasRenderingContext2D::DrawWindow(nsG
RefPtr<gfxContext> thebes;
RefPtr<DrawTarget> drawDT;
// Rendering directly is faster and can be done if mTarget supports Azure
// and does not need alpha blending.
if (gfxPlatform::GetPlatform()->SupportsAzureContentForDrawTarget(mTarget) &&
GlobalAlpha() == 1.0f &&
UsedOperation() == CompositionOp::OP_OVER)
{
- thebes = new gfxContext(mTarget);
+ thebes = gfxContext::ForDrawTarget(mTarget);
+ MOZ_ASSERT(thebes); // alrady checked the draw target above
thebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21,
matrix._22, matrix._31, matrix._32));
} else {
drawDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(ceil(sw), ceil(sh)),
SurfaceFormat::B8G8R8A8);
- if (!drawDT) {
+ if (!drawDT || !drawDT->IsValid()) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
- thebes = new gfxContext(drawDT);
+ thebes = gfxContext::ForDrawTarget(drawDT);
+ MOZ_ASSERT(thebes); // alrady checked the draw target above
thebes->SetMatrix(gfxMatrix::Scaling(matrix._11, matrix._22));
}
nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
Unused << shell->RenderDocument(r, renderDocFlags, backgroundColor, thebes);
// If this canvas was contained in the drawn window, the pre-transaction callback
// may have returned its DT. If so, we must reacquire it here.
EnsureTarget();
--- a/dom/canvas/DocumentRendererChild.cpp
+++ b/dom/canvas/DocumentRendererChild.cpp
@@ -74,20 +74,21 @@ DocumentRendererChild::RenderDocument(ns
data.SetLength(renderSize.width * renderSize.height * 4);
RefPtr<DrawTarget> dt =
Factory::CreateDrawTargetForData(BackendType::CAIRO,
reinterpret_cast<uint8_t*>(data.BeginWriting()),
IntSize(renderSize.width, renderSize.height),
4 * renderSize.width,
SurfaceFormat::B8G8R8A8);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
gfxWarning() << "DocumentRendererChild::RenderDocument failed to Factory::CreateDrawTargetForData";
return false;
}
- RefPtr<gfxContext> ctx = new gfxContext(dt);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(ctx); // already checked the draw target above
ctx->SetMatrix(mozilla::gfx::ThebesMatrix(transform));
nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
shell->RenderDocument(documentRect, renderFlags, bgColor, ctx);
return true;
}
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -290,20 +290,21 @@ MediaEngineTabVideoSource::Draw() {
RefPtr<layers::ImageContainer> container = layers::LayerManager::CreateImageContainer();
RefPtr<DrawTarget> dt =
Factory::CreateDrawTargetForData(BackendType::CAIRO,
mData.get(),
size,
stride,
SurfaceFormat::B8G8R8X8);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
return;
}
- RefPtr<gfxContext> context = new gfxContext(dt);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(context); // already checked the draw target above
context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/mViewportWidth),
(((float) size.height)/mViewportHeight)));
if (mWindow) {
nscolor bgColor = NS_RGB(255, 255, 255);
uint32_t renderDocFlags = mScrollWithPage? 0 :
(nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
nsIPresShell::RENDER_DOCUMENT_RELATIVE);
--- a/gfx/2d/Logging.h
+++ b/gfx/2d/Logging.h
@@ -131,16 +131,17 @@ enum class LogReason : int {
InvalidRect,
CannotDraw3D, // 20
IncompatibleBasicTexturedEffect,
InvalidFont,
PAllocTextureBackendMismatch,
GetFontFileDataFailed,
MessageChannelCloseFailure,
TextureAliveAfterShutdown,
+ InvalidContext,
// End
MustBeLessThanThis = 101,
};
struct BasicLogger
{
// For efficiency, this method exists and copies the logic of the
// OutputMessage below. If making any changes here, also make it
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -102,17 +102,21 @@ BasicLayerManager::PushGroupForLayer(gfx
aContext->SetMatrix(oldMat);
rect.RoundOut();
IntRect surfRect;
ToRect(rect).ToIntRect(&surfRect);
if (!surfRect.IsEmpty()) {
RefPtr<DrawTarget> dt = aContext->GetDrawTarget()->CreateSimilarDrawTarget(surfRect.Size(), SurfaceFormat::B8G8R8A8);
- RefPtr<gfxContext> ctx = new gfxContext(dt, ToRect(rect).TopLeft());
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(dt, ToRect(rect).TopLeft());
+ if (!ctx) {
+ gfxDevCrash(LogReason::InvalidContext) << "BasicLayerManager context problem " << gfx::hexa(dt);
+ return group;
+ }
ctx->SetMatrix(oldMat);
group.mGroupOffset = surfRect.TopLeft();
group.mGroupTarget = ctx;
group.mMaskSurface = GetMaskForLayer(aLayer, &group.mMaskTransform);
return group;
}
@@ -892,36 +896,39 @@ BasicLayerManager::PaintLayer(gfxContext
PaintSelfOrChildren(paintLayerContext, aTarget);
return;
}
const IntRect& bounds = visibleRegion.GetBounds();
RefPtr<DrawTarget> untransformedDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(bounds.width, bounds.height),
SurfaceFormat::B8G8R8A8);
- if (!untransformedDT) {
+ if (!untransformedDT || !untransformedDT->IsValid()) {
return;
}
- RefPtr<gfxContext> groupTarget = new gfxContext(untransformedDT,
- Point(bounds.x, bounds.y));
+ RefPtr<gfxContext> groupTarget = gfxContext::ForDrawTarget(untransformedDT,
+ Point(bounds.x, bounds.y));
+ MOZ_ASSERT(groupTarget); // already checked the target above
PaintSelfOrChildren(paintLayerContext, groupTarget);
// Temporary fast fix for bug 725886
// Revert these changes when 725886 is ready
- MOZ_ASSERT(untransformedDT,
+ MOZ_ASSERT(untransformedDT && untransformedDT->IsValid(),
"We should always allocate an untransformed surface with 3d transforms!");
#ifdef DEBUG
if (aLayer->GetDebugColorIndex() != 0) {
Color color((aLayer->GetDebugColorIndex() & 1) ? 1.f : 0.f,
(aLayer->GetDebugColorIndex() & 2) ? 1.f : 0.f,
(aLayer->GetDebugColorIndex() & 4) ? 1.f : 0.f);
- RefPtr<gfxContext> temp = new gfxContext(untransformedDT, Point(bounds.x, bounds.y));
+ RefPtr<gfxContext> temp = gfxContext::ForDrawTarget(untransformedDT,
+ Point(bounds.x, bounds.y));
+ MOZ_ASSERT(temp); // already checked for target above
temp->SetColor(color);
temp->Paint();
}
#endif
Matrix4x4 effectiveTransform = aLayer->GetEffectiveTransform();
Rect xformBounds =
effectiveTransform.TransformAndClipBounds(Rect(bounds),
ToRect(aTarget->GetClipExtents()));
--- a/gfx/layers/basic/BasicPaintedLayer.cpp
+++ b/gfx/layers/basic/BasicPaintedLayer.cpp
@@ -169,17 +169,19 @@ BasicPaintedLayer::Validate(LayerManager
// from RGB to RGBA, because we might need to repaint with
// subpixel AA)
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
GetLocalVisibleRegion().ToUnknownRegion());
SetAntialiasingFlags(this, target);
RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
- RefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(target);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTargetWithTransform(target);
+ MOZ_ASSERT(ctx); // already checked the target above
+
PaintBuffer(ctx,
state.mRegionToDraw, state.mRegionToDraw, state.mRegionToInvalidate,
state.mDidSelfCopy,
state.mClip,
aCallback, aCallbackData);
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
Mutated();
ctx = nullptr;
--- a/gfx/layers/client/ClientPaintedLayer.cpp
+++ b/gfx/layers/client/ClientPaintedLayer.cpp
@@ -84,17 +84,18 @@ ClientPaintedLayer::PaintThebes()
if (target) {
mContentClient->ReturnDrawTargetToBuffer(target);
}
continue;
}
SetAntialiasingFlags(this, target);
- RefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(target);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTargetWithTransform(target);
+ MOZ_ASSERT(ctx); // already checked the target above
ClientManager()->GetPaintedLayerCallback()(this,
ctx,
iter.mDrawRegion,
iter.mDrawRegion,
state.mClip,
state.mRegionToInvalidate,
ClientManager()->GetPaintedLayerCallbackData());
--- a/gfx/layers/client/SingleTiledContentClient.cpp
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -180,17 +180,21 @@ ClientSingleTiledLayerBuffer::PaintThebe
}
if (dtOnWhite) {
dt = gfx::Factory::CreateDualDrawTarget(dt, dtOnWhite);
dtOnWhite = nullptr;
}
{
- RefPtr<gfxContext> ctx = new gfxContext(dt);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(dt);
+ if (!ctx) {
+ gfxDevCrash(LogReason::InvalidContext) << "SingleTiledContextClient context problem " << gfx::hexa(dt);
+ return;
+ }
ctx->SetMatrix(ctx->CurrentMatrix().Translate(-mTilingOrigin.x, -mTilingOrigin.y));
aCallback(mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
}
// Mark the area we just drew into the back buffer as invalid in the front buffer as they're
// now out of sync.
mTile.mInvalidFront.OrWith(tileDirtyRegion);
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -928,21 +928,22 @@ ClientMultiTiledLayerBuffer::PaintThebes
mSinglePaintDrawTarget =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
gfx::IntSize(ceilf(bounds.width * mResolution),
ceilf(bounds.height * mResolution)),
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(
GetContentType()));
- if (!mSinglePaintDrawTarget) {
+ if (!mSinglePaintDrawTarget || !mSinglePaintDrawTarget->IsValid()) {
return;
}
- ctxt = new gfxContext(mSinglePaintDrawTarget);
+ ctxt = gfxContext::ForDrawTarget(mSinglePaintDrawTarget);
+ MOZ_ASSERT(ctxt); // already checked draw target above
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
}
ctxt->NewPath();
ctxt->SetMatrix(
ctxt->CurrentMatrix().Scale(mResolution, mResolution).
Translate(-bounds.x, -bounds.y));
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
@@ -1153,19 +1154,24 @@ void ClientMultiTiledLayerBuffer::Update
if (gfxPrefs::TiledDrawTargetEnabled() && mMoz2DTiles.size() > 0) {
gfx::TileSet tileset;
for (size_t i = 0; i < mMoz2DTiles.size(); ++i) {
mMoz2DTiles[i].mTileOrigin -= mTilingOrigin;
}
tileset.mTiles = &mMoz2DTiles[0];
tileset.mTileCount = mMoz2DTiles.size();
RefPtr<DrawTarget> drawTarget = gfx::Factory::CreateTiledDrawTarget(tileset);
+ if (!drawTarget || !drawTarget->IsValid()) {
+ gfxDevCrash(LogReason::InvalidContext) << "Invalid tiled draw target";
+ return;
+ }
drawTarget->SetTransform(Matrix());
- RefPtr<gfxContext> ctx = new gfxContext(drawTarget);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(drawTarget);
+ MOZ_ASSERT(ctx); // already checked the draw target above
ctx->SetMatrix(
ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin)));
mCallback(mPaintedLayer, ctx, aPaintRegion, aDirtyRegion,
DrawRegionClip::DRAW, nsIntRegion(), mCallbackData);
mMoz2DTiles.clear();
// Reset:
mTilingOrigin = IntPoint(std::numeric_limits<int32_t>::max(),
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -343,33 +343,38 @@ nsDeviceContext::CreateRenderingContext(
#endif
RefPtr<gfx::DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(printingSurface,
gfx::IntSize(mWidth, mHeight));
// This can legitimately happen - CreateDrawTargetForSurface will fail
// to create a draw target if the size is too large, for instance.
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
gfxCriticalNote << "Failed to create draw target in device context sized " << mWidth << "x" << mHeight << " and pointers " << hexa(mPrintingSurface) << " and " << hexa(printingSurface);
return nullptr;
}
RefPtr<DrawEventRecorder> recorder;
nsresult rv = mDeviceContextSpec->GetDrawEventRecorder(getter_AddRefs(recorder));
if (NS_SUCCEEDED(rv) && recorder) {
dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dt);
+ if (!dt || !dt->IsValid()) {
+ gfxCriticalNote << "Failed to create a recording draw target";
+ return nullptr;
+ }
}
#ifdef XP_MACOSX
dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr);
#endif
dt->AddUserData(&sDisablePixelSnapping, (void*)0x1, nullptr);
- RefPtr<gfxContext> pContext = new gfxContext(dt);
+ RefPtr<gfxContext> pContext = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(pContext); // already checked draw target above
gfxMatrix transform;
if (printingSurface->GetRotateForLandscape()) {
// Rotate page 90 degrees to draw landscape page on portrait paper
IntSize size = printingSurface->GetSize();
transform.Translate(gfxPoint(0, size.width));
gfxMatrix rotate(0, -1,
1, 0,
--- a/gfx/tests/gtest/gfxFontSelectionTest.cpp
+++ b/gfx/tests/gtest/gfxFontSelectionTest.cpp
@@ -186,17 +186,17 @@ struct TestEntry {
static already_AddRefed<gfxContext>
MakeContext ()
{
const int size = 200;
RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(IntSize(size, size),
SurfaceFormat::B8G8R8X8);
- RefPtr<gfxContext> ctx = new gfxContext(drawTarget);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(drawTarget);
return ctx.forget();
}
TestEntry*
AddTest (nsTArray<TestEntry>& testList,
const char *utf8FamilyString,
const gfxFontStyle& fontStyle,
--- a/gfx/tests/gtest/gfxTextRunPerfTest.cpp
+++ b/gfx/tests/gtest/gfxTextRunPerfTest.cpp
@@ -38,17 +38,17 @@ TestEntry testList[] = {
static already_AddRefed<gfxContext>
MakeContext ()
{
const int size = 200;
RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(IntSize(size, size),
SurfaceFormat::B8G8R8X8);
- RefPtr<gfxContext> ctx = new gfxContext(drawTarget);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(drawTarget);
return ctx.forget();
}
const char* lastFamilies = nullptr;
static void
RunTest (TestEntry *test, gfxContext *ctx) {
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -69,24 +69,25 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRe
return nullptr;
}
memset(mData.get(), 0, blurDataSize);
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForData(mData.get(), size,
mBlur->GetStride(),
SurfaceFormat::A8);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
return nullptr;
}
IntRect irect = mBlur->GetRect();
gfxPoint topleft(irect.TopLeft().x, irect.TopLeft().y);
- mContext = new gfxContext(dt);
+ mContext = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(mContext); // already checked for target above
mContext->SetMatrix(gfxMatrix::Translation(-topleft));
return mContext;
}
void
DrawBlur(gfxContext* aDestinationCtx,
SourceSurface* aBlur,
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -67,31 +67,46 @@ PatternFromState::operator mozilla::gfx:
}
gfxContext::gfxContext(DrawTarget *aTarget, const Point& aDeviceOffset)
: mPathIsRect(false)
, mTransformChanged(false)
, mDT(aTarget)
{
- MOZ_ASSERT(aTarget, "Don't create a gfxContext without a DrawTarget");
+ if (!aTarget) {
+ gfxCriticalError() << "Don't create a gfxContext without a DrawTarget";
+ }
MOZ_COUNT_CTOR(gfxContext);
mStateStack.SetLength(1);
CurrentState().drawTarget = mDT;
CurrentState().deviceOffset = aDeviceOffset;
mDT->SetTransform(GetDTTransform());
}
/* static */ already_AddRefed<gfxContext>
-gfxContext::ContextForDrawTarget(DrawTarget* aTarget)
+gfxContext::ForDrawTarget(DrawTarget* aTarget,
+ const mozilla::gfx::Point& aDeviceOffset)
{
if (!aTarget || !aTarget->IsValid()) {
- gfxWarning() << "Invalid target in gfxContext::ContextForDrawTarget";
+ gfxCriticalNote << "Invalid target in gfxContext::ForDrawTarget " << hexa(aTarget);
+ return nullptr;
+ }
+
+ RefPtr<gfxContext> result = new gfxContext(aTarget, aDeviceOffset);
+ return result.forget();
+}
+
+/* static */ already_AddRefed<gfxContext>
+gfxContext::ForDrawTargetWithTransform(DrawTarget* aTarget)
+{
+ if (!aTarget || !aTarget->IsValid()) {
+ gfxCriticalNote << "Invalid target in gfxContext::ForDrawTargetWithTransform " << hexa(aTarget);
return nullptr;
}
Matrix transform = aTarget->GetTransform();
RefPtr<gfxContext> result = new gfxContext(aTarget);
result->SetMatrix(ThebesMatrix(transform));
return result.forget();
}
--- a/gfx/thebes/gfxContext.h
+++ b/gfx/thebes/gfxContext.h
@@ -53,31 +53,36 @@ class gfxContext final {
typedef mozilla::gfx::Pattern Pattern;
typedef mozilla::gfx::Rect Rect;
typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
typedef mozilla::gfx::Size Size;
NS_INLINE_DECL_REFCOUNTING(gfxContext)
public:
-
/**
* Initialize this context from a DrawTarget.
* Strips any transform from aTarget.
* aTarget will be flushed in the gfxContext's destructor.
+ * If aTarget is null or invalid, nullptr is returned. The caller
+ * is responsible for handling this scenario as appropriate.
*/
- explicit gfxContext(mozilla::gfx::DrawTarget *aTarget,
- const mozilla::gfx::Point& aDeviceOffset = mozilla::gfx::Point());
-
+ static already_AddRefed<gfxContext>
+ ForDrawTarget(mozilla::gfx::DrawTarget* aTarget,
+ const mozilla::gfx::Point& aDeviceOffset = mozilla::gfx::Point());
+
/**
* Create a new gfxContext wrapping aTarget and preserving aTarget's
* transform. Note that the transform is moved from aTarget to the resulting
* gfxContext, aTarget will no longer have its transform.
+ * If aTarget is null or invalid, nullptr is returned. The caller
+ * is responsible for handling this scenario as appropriate.
*/
- static already_AddRefed<gfxContext> ContextForDrawTarget(mozilla::gfx::DrawTarget* aTarget);
+ static already_AddRefed<gfxContext>
+ ForDrawTargetWithTransform(mozilla::gfx::DrawTarget* aTarget);
/**
* Return the current transparency group target, if any. If no group is
* active, returns the surface the gfxContext was created with.
*/
already_AddRefed<gfxASurface> CurrentSurface();
mozilla::gfx::DrawTarget *GetDrawTarget() { return mDT; }
@@ -453,16 +458,26 @@ public:
* Copy a PNG encoded Data URL to the clipboard.
*/
void CopyAsDataURI();
#endif
static mozilla::gfx::UserDataKey sDontUseAsSourceKey;
private:
+
+ /**
+ * Initialize this context from a DrawTarget.
+ * Strips any transform from aTarget.
+ * aTarget will be flushed in the gfxContext's destructor. Use the static
+ * ContextForDrawTargetNoTransform() when you want this behavior, as that
+ * version deals with null DrawTarget better.
+ */
+ explicit gfxContext(mozilla::gfx::DrawTarget *aTarget,
+ const mozilla::gfx::Point& aDeviceOffset = mozilla::gfx::Point());
~gfxContext();
friend class PatternFromState;
friend class GlyphBufferAzure;
typedef mozilla::gfx::Matrix Matrix;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::Color Color;
--- a/gfx/thebes/gfxDrawable.cpp
+++ b/gfx/thebes/gfxDrawable.cpp
@@ -117,20 +117,21 @@ gfxCallbackDrawable::gfxCallbackDrawable
already_AddRefed<gfxSurfaceDrawable>
gfxCallbackDrawable::MakeSurfaceDrawable(const Filter aFilter)
{
SurfaceFormat format =
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(gfxContentType::COLOR_ALPHA);
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(mSize,
format);
- if (!dt)
+ if (!dt || !dt->IsValid())
return nullptr;
- RefPtr<gfxContext> ctx = new gfxContext(dt);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(ctx); // already checked for target above
Draw(ctx, gfxRect(0, 0, mSize.width, mSize.height), ExtendMode::CLAMP, aFilter);
RefPtr<SourceSurface> surface = dt->Snapshot();
if (surface) {
RefPtr<gfxSurfaceDrawable> drawable = new gfxSurfaceDrawable(surface, mSize);
return drawable.forget();
}
return nullptr;
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -441,21 +441,23 @@ CreateSamplingRestrictedDrawable(gfxDraw
// create a zero-size surface.
if (needed.IsEmpty())
return nullptr;
IntSize size(int32_t(needed.Width()), int32_t(needed.Height()));
RefPtr<DrawTarget> target =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(size, aFormat);
- if (!target) {
+ if (!target || !target->IsValid()) {
return nullptr;
}
- RefPtr<gfxContext> tmpCtx = new gfxContext(target);
+ RefPtr<gfxContext> tmpCtx = gfxContext::ForDrawTarget(target);
+ MOZ_ASSERT(tmpCtx); // already checked the target above
+
tmpCtx->SetOp(OptimalFillOp());
aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), ExtendMode::REPEAT, Filter::LINEAR,
1.0, gfxMatrix::Translation(needed.TopLeft()));
RefPtr<SourceSurface> surface = target->Snapshot();
RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(surface, size, gfxMatrix::Translation(-needed.TopLeft()));
return drawable.forget();
}
@@ -587,21 +589,23 @@ PrescaleAndTileDrawable(gfxDrawable* aDr
scaledImageSize.height != scaledImageRect.height) {
// If the scaled image isn't pixel aligned, we'll get artifacts
// so we have to take the slow path.
return false;
}
RefPtr<DrawTarget> scaledDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(scaledImageSize, aFormat);
- if (!scaledDT) {
+ if (!scaledDT || !scaledDT->IsValid()) {
return false;
}
- RefPtr<gfxContext> tmpCtx = new gfxContext(scaledDT);
+ RefPtr<gfxContext> tmpCtx = gfxContext::ForDrawTarget(scaledDT);
+ MOZ_ASSERT(tmpCtx); // already checked the target above
+
scaledDT->SetTransform(ToMatrix(scaleMatrix));
gfxRect gfxImageRect(aImageRect.x, aImageRect.y, aImageRect.width, aImageRect.height);
aDrawable->Draw(tmpCtx, gfxImageRect, ExtendMode::REPEAT, aFilter, 1.0, gfxMatrix());
RefPtr<SourceSurface> scaledImage = scaledDT->Snapshot();
{
gfxContextMatrixAutoSaveRestore autoSR(aContext);
@@ -1337,19 +1341,20 @@ gfxUtils::WriteAsPNG(nsIPresShell* aShel
{
int32_t width = 1000, height = 1000;
nsRect r(0, 0, aShell->GetPresContext()->DevPixelsToAppUnits(width),
aShell->GetPresContext()->DevPixelsToAppUnits(height));
RefPtr<mozilla::gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(IntSize(width, height),
SurfaceFormat::B8G8R8A8);
- NS_ENSURE_TRUE(dt, /*void*/);
+ NS_ENSURE_TRUE(dt && dt->IsValid(), /*void*/);
- RefPtr<gfxContext> context = new gfxContext(dt);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(context); // already checked the draw target above
aShell->RenderDocument(r, 0, NS_RGB(255, 255, 0), context);
WriteAsPNG(dt.get(), aFile);
}
/* static */ void
gfxUtils::DumpAsDataURI(SourceSurface* aSurface, FILE* aFile)
{
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
--- a/image/ClippedImage.cpp
+++ b/image/ClippedImage.cpp
@@ -285,22 +285,23 @@ ClippedImage::GetFrameInternal(const nsI
float frameToDraw = InnerImage()->GetFrameIndex(aWhichFrame);
if (!mCachedSurface ||
!mCachedSurface->Matches(aSize, aSVGContext, frameToDraw, aFlags) ||
mCachedSurface->NeedsRedraw()) {
// Create a surface to draw into.
RefPtr<DrawTarget> target = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(IntSize(aSize.width, aSize.height),
SurfaceFormat::B8G8R8A8);
- if (!target) {
+ if (!target || !target->IsValid()) {
NS_ERROR("Could not create a DrawTarget");
return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
}
- RefPtr<gfxContext> ctx = new gfxContext(target);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(target);
+ MOZ_ASSERT(ctx); // already checked the draw target above
// Create our callback.
RefPtr<DrawSingleTileCallback> drawTileCallback =
new DrawSingleTileCallback(this, aSize, aSVGContext, aWhichFrame, aFlags);
RefPtr<gfxDrawable> drawable =
new gfxCallbackDrawable(drawTileCallback, aSize);
// Actually draw. The callback will end up invoking DrawSingleTile.
--- a/image/DynamicImage.cpp
+++ b/image/DynamicImage.cpp
@@ -175,22 +175,23 @@ DynamicImage::GetFrame(uint32_t aWhichFr
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
DynamicImage::GetFrameAtSize(const IntSize& aSize,
uint32_t aWhichFrame,
uint32_t aFlags)
{
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(aSize, SurfaceFormat::B8G8R8A8);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
gfxWarning() <<
"DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget";
return nullptr;
}
- RefPtr<gfxContext> context = new gfxContext(dt);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(context); // already checked the draw target above
auto result = Draw(context, aSize, ImageRegion::Create(aSize),
aWhichFrame, Filter::POINT, Nothing(), aFlags);
return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
}
NS_IMETHODIMP_(bool)
--- a/image/OrientedImage.cpp
+++ b/image/OrientedImage.cpp
@@ -94,31 +94,32 @@ OrientedImage::GetFrame(uint32_t aWhichF
} else {
surfaceFormat = gfx::SurfaceFormat::B8G8R8A8;
}
// Create a surface to draw into.
RefPtr<DrawTarget> target =
gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(size, surfaceFormat);
- if (!target) {
+ if (!target || !target->IsValid()) {
NS_ERROR("Could not create a DrawTarget");
return nullptr;
}
// Create our drawable.
RefPtr<SourceSurface> innerSurface =
InnerImage()->GetFrame(aWhichFrame, aFlags);
NS_ENSURE_TRUE(innerSurface, nullptr);
RefPtr<gfxDrawable> drawable =
new gfxSurfaceDrawable(innerSurface, size);
// Draw.
- RefPtr<gfxContext> ctx = new gfxContext(target);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(target);
+ MOZ_ASSERT(ctx); // already checked the draw target above
ctx->Multiply(OrientationMatrix(size));
gfxUtils::DrawPixelSnapped(ctx, drawable, size, ImageRegion::Create(size),
surfaceFormat, Filter::LINEAR);
return target->Snapshot();
}
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -721,22 +721,23 @@ VectorImage::GetFrameAtSize(const IntSiz
if (mError || !mIsFullyLoaded) {
return nullptr;
}
// Make our surface the size of what will ultimately be drawn to it.
// (either the full image size, or the restricted region)
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(aSize, SurfaceFormat::B8G8R8A8);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
NS_ERROR("Could not create a DrawTarget");
return nullptr;
}
- RefPtr<gfxContext> context = new gfxContext(dt);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(context); // already checked the draw target above
auto result = Draw(context, aSize, ImageRegion::Create(aSize),
aWhichFrame, Filter::POINT, Nothing(), aFlags);
return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
}
NS_IMETHODIMP_(bool)
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -292,24 +292,25 @@ imgFrame::InitWithDrawable(gfxDrawable*
// may have to do an expensive readback, but we warned callers about that in
// the documentation for this method.
MOZ_ASSERT(!mOptSurface, "Called imgFrame::InitWithDrawable() twice?");
target = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(mSize, mFormat);
}
- if (!target) {
+ if (!target || !target->IsValid()) {
mAborted = true;
return NS_ERROR_OUT_OF_MEMORY;
}
// Draw using the drawable the caller provided.
nsIntRect imageRect(0, 0, mSize.width, mSize.height);
- RefPtr<gfxContext> ctx = new gfxContext(target);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(target);
+ MOZ_ASSERT(ctx); // already checked the draw target above
gfxUtils::DrawPixelSnapped(ctx, aDrawable, mSize,
ImageRegion::Create(ThebesRect(imageRect)),
mFormat, aFilter, aImageFlags);
if (canUseDataSurface && !mImageSurface) {
NS_WARNING("Failed to create VolatileDataSourceSurface");
mAborted = true;
return NS_ERROR_OUT_OF_MEMORY;
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3576,17 +3576,22 @@ PaintInactiveLayer(nsDisplayListBuilder*
aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
RefPtr<DrawTarget> tempDT;
if (gfxEnv::DumpPaint()) {
tempDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
itemVisibleRect.Size(),
SurfaceFormat::B8G8R8A8);
if (tempDT) {
- context = new gfxContext(tempDT);
+ context = gfxContext::ForDrawTarget(tempDT);
+ if (!context) {
+ // Leave this as crash, it's in the debugging code, we want to know
+ gfxDevCrash(LogReason::InvalidContext) << "PaintInactive context problem " << gfx::hexa(tempDT);
+ return;
+ }
context->SetMatrix(gfxMatrix::Translation(-itemVisibleRect.x,
-itemVisibleRect.y));
}
}
#endif
basic->BeginTransaction();
basic->SetTarget(context);
@@ -5543,17 +5548,22 @@ static void DebugPaintItem(DrawTarget& a
{
bool snap;
Rect bounds = NSRectToRect(aItem->GetBounds(aBuilder, &snap),
aPresContext->AppUnitsPerDevPixel());
RefPtr<DrawTarget> tempDT =
aDrawTarget.CreateSimilarDrawTarget(IntSize(bounds.width, bounds.height),
SurfaceFormat::B8G8R8A8);
- RefPtr<gfxContext> context = new gfxContext(tempDT);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(tempDT);
+ if (!context) {
+ // Leave this as crash, it's in the debugging code, we want to know
+ gfxDevCrash(LogReason::InvalidContext) << "DebugPaintItem context problem " << gfx::hexa(tempDT);
+ return;
+ }
context->SetMatrix(gfxMatrix::Translation(-bounds.x, -bounds.y));
nsRenderingContext ctx(context);
aItem->Paint(aBuilder, &ctx);
RefPtr<SourceSurface> surface = tempDT->Snapshot();
DumpPaintedImage(aItem, surface);
aDrawTarget.DrawSurface(surface, bounds, Rect(Point(0,0), bounds.Size()));
@@ -6072,22 +6082,23 @@ ContainerState::CreateMaskLayer(Layer *a
// Make mask image width aligned to 4. See Bug 1245552.
IntSize surfaceSizeInt(GetAlignedStride<4>(NSToIntCeil(surfaceSize.width)),
NSToIntCeil(surfaceSize.height));
// no existing mask image, so build a new one
RefPtr<DrawTarget> dt =
aLayer->Manager()->CreateOptimalMaskDrawTarget(surfaceSizeInt);
// fail if we can't get the right surface
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
NS_WARNING("Could not create DrawTarget for mask layer.");
return nullptr;
}
- RefPtr<gfxContext> context = new gfxContext(dt);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(context); // already checked the draw target above
context->Multiply(ThebesMatrix(imageTransform));
// paint the clipping rects with alpha to create the mask
aClip.FillIntersectionOfRoundedRectClips(context,
Color(1.f, 1.f, 1.f, 1.f),
newData.mAppUnitsPerDevPixel,
0,
aRoundedRectClipCount);
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -5089,17 +5089,21 @@ nsImageRenderer::Draw(nsPresContext*
DrawResult result = DrawResult::SUCCESS;
RefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
IntRect tmpDTRect;
if (ctx->CurrentOp() != CompositionOp::OP_OVER || mMaskOp == NS_STYLE_MASK_MODE_LUMINANCE) {
gfxRect clipRect = ctx->GetClipExtents();
tmpDTRect = RoundedOut(ToRect(clipRect));
RefPtr<DrawTarget> tempDT = ctx->GetDrawTarget()->CreateSimilarDrawTarget(tmpDTRect.Size(), SurfaceFormat::B8G8R8A8);
- ctx = new gfxContext(tempDT, tmpDTRect.TopLeft());
+ ctx = gfxContext::ForDrawTarget(tempDT, tmpDTRect.TopLeft());
+ if (!ctx) {
+ gfxDevCrash(LogReason::InvalidContext) << "ImageRenderer::Draw problem " << gfx::hexa(tempDT);
+ return DrawResult::TEMPORARY_ERROR;
+ }
}
switch (mType) {
case eStyleImageType_Image:
{
CSSIntSize imageSize(nsPresContext::AppUnitsToIntCSSPixels(mSize.width),
nsPresContext::AppUnitsToIntCSSPixels(mSize.height));
result =
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6543,17 +6543,21 @@ DrawImageInternal(gfxContext&
IntRect tmpDTRect;
if (destCtx->CurrentOp() != CompositionOp::OP_OVER) {
Rect imageRect = ToRect(params.imageSpaceToDeviceSpace.TransformBounds(params.region.Rect()));
imageRect.ToIntRect(&tmpDTRect);
RefPtr<DrawTarget> tempDT = destCtx->GetDrawTarget()->CreateSimilarDrawTarget(tmpDTRect.Size(), SurfaceFormat::B8G8R8A8);
- destCtx = new gfxContext(tempDT, imageRect.TopLeft());
+ destCtx = gfxContext::ForDrawTarget(tempDT, imageRect.TopLeft());
+ if (!destCtx) {
+ gfxDevCrash(LogReason::InvalidContext) << "NonOP_OVER context problem " << gfx::hexa(tempDT);
+ return result;
+ }
}
destCtx->SetMatrix(params.imageSpaceToDeviceSpace);
Maybe<SVGImageContext> svgContext = ToMaybe(aSVGContext);
if (!svgContext) {
// Use the default viewport.
svgContext = Some(SVGImageContext(params.svgViewportSize, Nothing()));
}
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2902,17 +2902,20 @@ PresShell::ClearFrameRefs(nsIFrame* aFra
}
already_AddRefed<gfxContext>
PresShell::CreateReferenceRenderingContext()
{
nsDeviceContext* devCtx = mPresContext->DeviceContext();
RefPtr<gfxContext> rc;
if (mPresContext->IsScreen()) {
- rc = new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
+ rc = gfxContext::ForDrawTarget(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
+ if (!rc) {
+ return nullptr;
+ }
} else {
// We assume the devCtx has positive width and height for this call.
// However, width and height, may be outside of the reasonable range
// so rc may still be null.
rc = devCtx->CreateRenderingContext();
if (!rc) {
return nullptr;
}
@@ -4929,21 +4932,22 @@ PresShell::PaintRangePaintInfo(const nsT
}
aScreenRect->width = pixelArea.width;
aScreenRect->height = pixelArea.height;
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
IntSize(pixelArea.width, pixelArea.height),
SurfaceFormat::B8G8R8A8);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
return nullptr;
}
- RefPtr<gfxContext> ctx = new gfxContext(dt);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(ctx); // already checked the draw target above
if (aRegion) {
// Convert aRegion from CSS pixels to dev pixels
nsIntRegion region =
aRegion->ToAppUnits(nsPresContext::AppUnitsPerCSSPixel())
.ToOutsidePixels(pc->AppUnitsPerDevPixel());
for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
const nsIntRect& rect = iter.Get();
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -305,18 +305,19 @@ nsDisplayCanvasBackgroundImage::Paint(ns
if (dt) {
BlitSurface(destDT, destRect, dt);
return;
}
dt = destDT->CreateSimilarDrawTarget(IntSize(ceil(destRect.width),
ceil(destRect.height)),
SurfaceFormat::B8G8R8A8);
- if (dt) {
- RefPtr<gfxContext> ctx = new gfxContext(dt);
+ if (dt && dt->IsValid()) {
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(ctx); // already checked draw target above
ctx->SetMatrix(ctx->CurrentMatrix().Translate(-destRect.x, -destRect.y));
nsRenderingContext context(ctx);
PaintInternal(aBuilder, &context, bgClipRect, &bgClipRect);
BlitSurface(dest->GetDrawTarget(), destRect, dt);
frame->Properties().Set(nsIFrame::CachedBackgroundImageDT(),
dt.forget().take());
return;
}
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -349,27 +349,28 @@ nsFilterInstance::BuildSourcePaint(Sourc
DrawTarget* aTargetDT)
{
MOZ_ASSERT(mTargetFrame);
nsIntRect neededRect = aSource->mNeededBounds;
RefPtr<DrawTarget> offscreenDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
neededRect.Size(), SurfaceFormat::B8G8R8A8);
- if (!offscreenDT) {
+ if (!offscreenDT || !offscreenDT->IsValid()) {
return NS_ERROR_OUT_OF_MEMORY;
}
gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform();
if (!deviceToFilterSpace.Invert()) {
return NS_ERROR_FAILURE;
}
if (!mPaintTransform.IsSingular()) {
- RefPtr<gfxContext> gfx = new gfxContext(offscreenDT);
+ RefPtr<gfxContext> gfx = gfxContext::ForDrawTarget(offscreenDT);
+ MOZ_ASSERT(gfx); // already checked the draw target above
gfx->Save();
gfx->Multiply(mPaintTransform *
deviceToFilterSpace *
gfxMatrix::Translation(-neededRect.TopLeft()));
GeneralPattern pattern;
if (aSource == &mFillPaint) {
nsSVGUtils::MakeFillPatternFor(mTargetFrame, gfx, &pattern);
} else if (aSource == &mStrokePaint) {
@@ -413,17 +414,17 @@ nsFilterInstance::BuildSourceImage(DrawT
nsIntRect neededRect = mSourceGraphic.mNeededBounds;
if (neededRect.IsEmpty()) {
return NS_OK;
}
RefPtr<DrawTarget> offscreenDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
neededRect.Size(), SurfaceFormat::B8G8R8A8);
- if (!offscreenDT) {
+ if (!offscreenDT || !offscreenDT->IsValid()) {
return NS_ERROR_OUT_OF_MEMORY;
}
gfxRect r = FilterSpaceToUserSpace(ThebesRect(neededRect));
r.RoundOut();
nsIntRect dirty;
if (!gfxUtils::GfxRectToIntRect(r, &dirty))
return NS_ERROR_FAILURE;
@@ -438,17 +439,18 @@ nsFilterInstance::BuildSourceImage(DrawT
// (since that would eliminate the transform multiplications from user
// space to device space and back again). However, that would make the
// code more complex while being hard to get right without introducing
// subtle bugs, and in practice it probably makes no real difference.)
gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform();
if (!deviceToFilterSpace.Invert()) {
return NS_ERROR_FAILURE;
}
- RefPtr<gfxContext> ctx = new gfxContext(offscreenDT);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(offscreenDT);
+ MOZ_ASSERT(ctx); // already checked the draw target above
ctx->SetMatrix(
ctx->CurrentMatrix().Translate(-neededRect.TopLeft()).
PreMultiply(deviceToFilterSpace));
mPaintCallback->Paint(*ctx, mTargetFrame, mPaintTransform, &dirty);
mSourceGraphic.mSourceSurface = offscreenDT->Snapshot();
mSourceGraphic.mSurfaceRect = neededRect;
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -127,17 +127,21 @@ nsSVGClipPathFrame::GetClipMask(gfxConte
aReferenceDT.CreateSimilarDrawTarget(devSpaceClipExtents.Size(),
SurfaceFormat::A8);
gfxMatrix mat = aReferenceContext.CurrentMatrix() *
gfxMatrix::Translation(-devSpaceClipExtents.TopLeft());
// Paint this clipPath's contents into maskDT:
{
- RefPtr<gfxContext> ctx = new gfxContext(maskDT);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(maskDT);
+ if (!ctx) {
+ gfxCriticalError() << "SVGClipPath context problem " << gfx::hexa(maskDT);
+ return nullptr;
+ }
ctx->SetMatrix(mat);
// We need to set mMatrixForChildren here so that under the PaintSVG calls
// on our children (below) our GetCanvasTM() method will return the correct
// transform.
mMatrixForChildren = GetClipPathTransform(aClippedFrame) * aMatrix;
// Check if this clipPath is itself clipped by another clipPath:
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -563,22 +563,23 @@ nsSVGIntegrationUtils::PaintFramesWithEf
{
gfxContextMatrixAutoSaveRestore matRestore(&aContext);
aContext.SetMatrix(gfxMatrix());
clipRect = aContext.GetClipExtents();
}
IntRect drawRect = RoundedOut(ToRect(clipRect));
RefPtr<DrawTarget> targetDT = aContext.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::A8);
- if (!targetDT) {
+ if (!targetDT || !targetDT->IsValid()) {
aContext.Restore();
return;
}
- RefPtr<gfxContext> target = new gfxContext(targetDT);
+ RefPtr<gfxContext> target = gfxContext::ForDrawTarget(targetDT);
+ MOZ_ASSERT(target); // alrady checked the draw target above
target->SetMatrix(matrixAutoSaveRestore.Matrix() * gfxMatrix::Translation(-drawRect.TopLeft()));
// Compose all mask-images onto maskSurface.
uint32_t flags = aBuilder->GetBackgroundPaintFlags() |
nsCSSRendering::PAINTBG_MASK_IMAGE;
nsRenderingContext rc(target);
// FIXME We should use the return value, see bug 1258510.
Unused << nsCSSRendering::PaintBackgroundWithSC(aFrame->PresContext(),
@@ -612,21 +613,22 @@ nsSVGIntegrationUtils::PaintFramesWithEf
aContext.SetMatrix(gfxMatrix());
clipRect = aContext.GetClipExtents();
}
IntRect drawRect = RoundedOut(ToRect(clipRect));
RefPtr<DrawTarget> targetDT = aContext.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::B8G8R8A8);
- if (!targetDT) {
+ if (!targetDT || !targetDT->IsValid()) {
aContext.Restore();
return;
}
- target = new gfxContext(targetDT);
+ target = gfxContext::ForDrawTarget(targetDT);
+ MOZ_ASSERT(target); // already checked the draw target above
target->SetMatrix(aContext.CurrentMatrix() * gfxMatrix::Translation(-drawRect.TopLeft()));
targetOffset = drawRect.TopLeft();
}
if (clipPathFrame && !isTrivialClip) {
Matrix clippedMaskTransform;
RefPtr<SourceSurface> clipMaskSurface = clipPathFrame->GetClipMask(aContext, aFrame, cssPxToDevPxMatrix,
&clippedMaskTransform, maskSurface, maskTransform);
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -248,24 +248,25 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(gf
if (resultOverflows || maskSurfaceSize.IsEmpty()) {
// XXXjwatt we should return an empty surface so we don't paint aMaskedFrame!
return nullptr;
}
RefPtr<DrawTarget> maskDT =
Factory::CreateDrawTarget(BackendType::CAIRO, maskSurfaceSize,
SurfaceFormat::B8G8R8A8);
- if (!maskDT) {
+ if (!maskDT || !maskDT->IsValid()) {
return nullptr;
}
gfxMatrix maskSurfaceMatrix =
aContext->CurrentMatrix() * gfxMatrix::Translation(-maskSurfaceRect.TopLeft());
- RefPtr<gfxContext> tmpCtx = new gfxContext(maskDT);
+ RefPtr<gfxContext> tmpCtx = gfxContext::ForDrawTarget(maskDT);
+ MOZ_ASSERT(tmpCtx); // already checked the draw target above
tmpCtx->SetMatrix(maskSurfaceMatrix);
mMatrixForChildren = GetMaskTransform(aMaskedFrame) * aMatrix;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
// The CTM of each frame referencing us can be different
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -367,22 +367,23 @@ nsSVGPatternFrame::PaintPattern(const Dr
// and rescale pattern to compensate
patternMatrix->PreScale(patternWidth / surfaceSize.width,
patternHeight / surfaceSize.height);
}
RefPtr<DrawTarget> dt =
aDrawTarget->CreateSimilarDrawTarget(surfaceSize, SurfaceFormat::B8G8R8A8);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
return nullptr;
}
dt->ClearRect(Rect(0, 0, surfaceSize.width, surfaceSize.height));
- RefPtr<gfxContext> gfx = new gfxContext(dt);
+ RefPtr<gfxContext> gfx = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(gfx); // already checked the draw target above
if (aGraphicOpacity != 1.0f) {
gfx->Save();
gfx->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, aGraphicOpacity);
}
// OK, now render -- note that we use "firstKid", which
// we got at the beginning because it takes care of the
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -633,17 +633,21 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
aContext.SetMatrix(gfxMatrix());
clipRect = aContext.GetClipExtents();
}
IntRect drawRect = RoundedOut(ToRect(clipRect));
RefPtr<DrawTarget> targetDT = aContext.GetDrawTarget()->CreateSimilarDrawTarget(drawRect.Size(), SurfaceFormat::B8G8R8A8);
- target = new gfxContext(targetDT);
+ target = gfxContext::ForDrawTarget(targetDT);
+ if (!target) {
+ gfxDevCrash(LogReason::InvalidContext) << "SVGPaintWithEffects context problem " << gfx::hexa(targetDT);
+ return;
+ }
target->SetMatrix(aContext.CurrentMatrix() * gfxMatrix::Translation(-drawRect.TopLeft()));
targetOffset = drawRect.TopLeft();
}
if (clipPathFrame && !isTrivialClip) {
Matrix clippedMaskTransform;
RefPtr<SourceSurface> clipMaskSurface = clipPathFrame->GetClipMask(aContext, aFrame, aTransform,
&clippedMaskTransform, maskSurface, maskTransform);
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -1036,17 +1036,21 @@ PuppetWidget::Paint()
#endif
if (mozilla::layers::LayersBackend::LAYERS_CLIENT == mLayerManager->GetBackendType()) {
// Do nothing, the compositor will handle drawing
if (mTabChild) {
mTabChild->NotifyPainted();
}
} else {
- RefPtr<gfxContext> ctx = new gfxContext(mDrawTarget);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(mDrawTarget);
+ if (!ctx) {
+ gfxDevCrash(LogReason::InvalidContext) << "PuppetWidget context problem " << gfx::hexa(mDrawTarget);
+ return NS_ERROR_FAILURE;
+ }
ctx->Rectangle(gfxRect(0,0,0,0));
ctx->Clip();
AutoLayerManagerSetup setupLayerManager(this, ctx,
BufferMode::BUFFER_NONE);
GetCurrentWidgetListener()->PaintWindow(this, region);
if (mTabChild) {
mTabChild->NotifyPainted();
}
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -1824,21 +1824,22 @@ AndroidBridge::CaptureZoomedView(mozIDOM
return NS_ERROR_FAILURE;
}
MOZ_ASSERT (gfxPlatform::GetPlatform()->SupportsAzureContentForType(BackendType::CAIRO),
"Need BackendType::CAIRO support");
RefPtr < DrawTarget > dt = Factory::CreateDrawTargetForData(
BackendType::CAIRO, data, IntSize(zoomedViewRect.width, zoomedViewRect.height), stride,
format);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
ALOG_BRIDGE("Error creating DrawTarget");
return NS_ERROR_FAILURE;
}
- RefPtr<gfxContext> context = new gfxContext(dt);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(context); // already checked the draw target above
context->SetMatrix(context->CurrentMatrix().Scale(zoomFactor, zoomFactor));
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
if (is24bit) {
gfxUtils::ConvertBGRAtoRGBA(data, stride * zoomedViewRect.height);
}
@@ -1929,21 +1930,23 @@ nsresult AndroidBridge::CaptureThumbnail
"Need BackendType::CAIRO support");
RefPtr<DrawTarget> dt =
Factory::CreateDrawTargetForData(BackendType::CAIRO,
data,
IntSize(bufW, bufH),
stride,
is24bit ? SurfaceFormat::B8G8R8X8 :
SurfaceFormat::R5G6B5_UINT16);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
ALOG_BRIDGE("Error creating DrawTarget");
return NS_ERROR_FAILURE;
}
- RefPtr<gfxContext> context = new gfxContext(dt);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(context); // checked the draw target above
+
context->SetMatrix(
context->CurrentMatrix().Scale(scale * bufW / srcW,
scale * bufH / srcH));
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
if (is24bit) {
gfxUtils::ConvertBGRAtoRGBA(data, stride * bufH);
}
NS_ENSURE_SUCCESS(rv, rv);
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -3729,19 +3729,24 @@ NSEvent* gLastDragMouseDownEvent = nil;
// Create Cairo objects.
RefPtr<gfxQuartzSurface> targetSurface;
RefPtr<gfx::DrawTarget> dt =
gfx::Factory::CreateDrawTargetForCairoCGContext(aContext,
gfx::IntSize(backingSize.width,
backingSize.height));
- MOZ_ASSERT(dt); // see implementation
+ if (!dt || !dt->IsValid()) {
+ // This used to be an assertion, so keep crashing in nightly+aurora
+ gfxDevCrash(mozilla::gfx::LogReason::InvalidContext) << "Cannot create target with CreateDrawTargetForCairoCGContext " << backingSize;
+ return;
+ }
dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr);
- RefPtr<gfxContext> targetContext = new gfxContext(dt);
+ RefPtr<gfxContext> targetContext = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(targetContext); // already checked the draw target above
// Set up the clip region.
targetContext->NewPath();
for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
const LayoutDeviceIntRect& r = iter.Get();
targetContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
}
targetContext->Clip();
--- a/widget/cocoa/nsCocoaUtils.mm
+++ b/widget/cocoa/nsCocoaUtils.mm
@@ -481,17 +481,17 @@ nsresult nsCocoaUtils::CreateNSImageFrom
RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(scaledSize, SurfaceFormat::B8G8R8A8);
if (!drawTarget) {
NS_ERROR("Failed to create DrawTarget");
return NS_ERROR_FAILURE;
}
- RefPtr<gfxContext> context = new gfxContext(drawTarget);
+ RefPtr<gfxContext> context = gfxContext::ForDrawTarget(drawTarget);
if (!context) {
NS_ERROR("Failed to create gfxContext");
return NS_ERROR_FAILURE;
}
mozilla::image::DrawResult res =
aImage->Draw(context, scaledSize, ImageRegion::Create(scaledSize),
aWhichFrame, Filter::POINT, Nothing(),
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -2225,17 +2225,17 @@ nsWindow::OnExposeEvent(cairo_t *cr)
if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
listener->PaintWindow(this, region);
listener->DidPaintWindow();
return TRUE;
}
BufferMode layerBuffering = BufferMode::BUFFERED;
RefPtr<DrawTarget> dt = GetDrawTarget(region, &layerBuffering);
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
return FALSE;
}
RefPtr<gfxContext> ctx;
IntRect boundsRect = region.GetBounds().ToUnknownRect();
IntPoint offset(0, 0);
if (dt->GetSize() == boundsRect.Size()) {
offset = boundsRect.TopLeft();
dt->SetTransform(Matrix::Translation(-offset));
@@ -2249,22 +2249,26 @@ nsWindow::OnExposeEvent(cairo_t *cr)
// our private interface so we can rework things to avoid this.
dt->PushClipRect(Rect(boundsRect));
// The double buffering is done here to extract the shape mask.
// (The shape mask won't be necessary when a visual with an alpha
// channel is used on compositing window managers.)
layerBuffering = BufferMode::BUFFER_NONE;
RefPtr<DrawTarget> destDT = dt->CreateSimilarDrawTarget(boundsRect.Size(), SurfaceFormat::B8G8R8A8);
- ctx = new gfxContext(destDT, boundsRect.TopLeft());
+ if (!destDT || !destDT->IsValid()) {
+ return FALSE;
+ }
+ ctx = gfxContext::ForDrawTarget(destDT, boundsRect.TopLeft());
} else {
gfxUtils::ClipToRegion(dt, region.ToUnknownRegion());
- ctx = new gfxContext(dt, offset);
- }
+ ctx = gfxContext::ForDrawTarget(dt, offset);
+ }
+ MOZ_ASSERT(ctx); // checked both dt and destDT valid draw target above
#if 0
// NOTE: Paint flashing region would be wrong for cairo, since
// cairo inflates the update region, etc. So don't paint flash
// for cairo.
#ifdef DEBUG
// XXX aEvent->region may refer to a newly-invalid area. FIXME
if (0 && WANT_PAINT_FLASHING && gtk_widget_get_window(aEvent))
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -682,20 +682,20 @@ nsBaseDragService::DrawDragForImage(nsII
return NS_ERROR_FAILURE;
nsresult result = NS_OK;
if (aImageLoader) {
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(destSize,
SurfaceFormat::B8G8R8A8);
- if (!dt)
+ if (!dt || !dt->IsValid())
return NS_ERROR_FAILURE;
- RefPtr<gfxContext> ctx = new gfxContext(dt);
+ RefPtr<gfxContext> ctx = gfxContext::ForDrawTarget(dt);
if (!ctx)
return NS_ERROR_FAILURE;
DrawResult res =
imgContainer->Draw(ctx, destSize, ImageRegion::Create(destSize),
imgIContainer::FRAME_CURRENT,
Filter::GOOD, Nothing(),
imgIContainer::FLAG_SYNC_DECODE);
--- a/widget/uikit/nsWindow.mm
+++ b/widget/uikit/nsWindow.mm
@@ -354,32 +354,41 @@ private:
RefPtr<gfxQuartzSurface> targetSurface;
RefPtr<gfxContext> targetContext;
if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(gfx::BackendType::COREGRAPHICS)) {
RefPtr<gfx::DrawTarget> dt =
gfx::Factory::CreateDrawTargetForCairoCGContext(aContext,
gfx::IntSize(backingSize.width,
backingSize.height));
+ if (!dt || !dt->IsValid()) {
+ gfxDevCrash(mozilla::gfx::LogReason::InvalidContext) << "Window context problem 1 " << backingSize;
+ return;
+ }
dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr);
- targetContext = new gfxContext(dt);
+ targetContext = gfxContext::ForDrawTarget(dt);
} else if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(gfx::BackendType::CAIRO)) {
// This is dead code unless you mess with prefs, but keep it around for
// debugging.
targetSurface = new gfxQuartzSurface(aContext, backingSize);
targetSurface->SetAllowUseAsSource(false);
RefPtr<gfx::DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(targetSurface,
gfx::IntSize(backingSize.width,
backingSize.height));
+ if (!dt || !dt->IsValid()) {
+ gfxDevCrash(mozilla::gfx::LogReason::InvalidContext) << "Window context problem 2 " << backingSize;
+ return;
+ }
dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr);
- targetContext = new gfxContext(dt);
+ targetContext = gfxContext::ForDrawTarget(dt);
} else {
- MOZ_ASSERT_UNREACHABLE("COREGRAPHICS is the only supported backed");
+ MOZ_ASSERT_UNREACHABLE("COREGRAPHICS is the only supported backend");
}
+ MOZ_ASSERT(targetContext); // already checked for valid draw targets above
// Set up the clip region.
targetContext->NewPath();
for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
const LayoutDeviceIntRect& r = iter.Get();
targetContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
}
targetContext->Clip();
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -377,17 +377,17 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
}
RECT paintRect;
::GetClientRect(mWnd, &paintRect);
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(targetSurface,
IntSize(paintRect.right - paintRect.left,
paintRect.bottom - paintRect.top));
- if (!dt) {
+ if (!dt || !dt->IsValid()) {
gfxWarning() << "nsWindow::OnPaint failed in CreateDrawTargetForSurface";
return false;
}
// don't need to double buffer with anything but GDI
BufferMode doubleBuffering = mozilla::layers::BufferMode::BUFFER_NONE;
if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) ||
IsRenderMode(gfxWindowsPlatform::RENDER_DIRECT2D)) {
@@ -406,17 +406,18 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
dt->GetSize().width, dt->GetSize().height));
break;
}
#else
doubleBuffering = mozilla::layers::BufferMode::BUFFERED;
#endif
}
- RefPtr<gfxContext> thebesContext = new gfxContext(dt);
+ RefPtr<gfxContext> thebesContext = gfxContext::ForDrawTarget(dt);
+ MOZ_ASSERT(thebesContext); // already checked draw target above
{
AutoLayerManagerSetup
setupLayerManager(this, thebesContext, doubleBuffering);
result = listener->PaintWindow(
this, LayoutDeviceIntRegion::FromUnknownRegion(region));
}