Backout 013743bb609e (bug 591358) for Windows orange.

This commit is contained in:
Ryan VanderMeulen 2012-09-05 19:53:43 -04:00
parent 01eb6774e4
commit f7c91e83b4
2 changed files with 163 additions and 175 deletions

View File

@ -546,7 +546,6 @@ NS_INTERFACE_MAP_END
uint32_t nsCanvasRenderingContext2DAzure::sNumLivingContexts = 0; uint32_t nsCanvasRenderingContext2DAzure::sNumLivingContexts = 0;
uint8_t (*nsCanvasRenderingContext2DAzure::sUnpremultiplyTable)[256] = nullptr; uint8_t (*nsCanvasRenderingContext2DAzure::sUnpremultiplyTable)[256] = nullptr;
uint8_t (*nsCanvasRenderingContext2DAzure::sPremultiplyTable)[256] = nullptr; uint8_t (*nsCanvasRenderingContext2DAzure::sPremultiplyTable)[256] = nullptr;
RefPtr<DrawTarget> nsCanvasRenderingContext2DAzure::sErrorTarget = nullptr;
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -578,7 +577,7 @@ NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult)
} }
nsCanvasRenderingContext2DAzure::nsCanvasRenderingContext2DAzure() nsCanvasRenderingContext2DAzure::nsCanvasRenderingContext2DAzure()
: mZero(false), mOpaque(false), mResetLayer(true) : mValid(false), mZero(false), mOpaque(false), mResetLayer(true)
, mIPC(false) , mIPC(false)
, mIsEntireFrameInvalid(false) , mIsEntireFrameInvalid(false)
, mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false) , mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
@ -601,7 +600,6 @@ nsCanvasRenderingContext2DAzure::~nsCanvasRenderingContext2DAzure()
delete[] sPremultiplyTable; delete[] sPremultiplyTable;
sUnpremultiplyTable = nullptr; sUnpremultiplyTable = nullptr;
sPremultiplyTable = nullptr; sPremultiplyTable = nullptr;
NS_IF_RELEASE(sErrorTarget);
} }
} }
@ -651,7 +649,7 @@ nsCanvasRenderingContext2DAzure::Reset()
// only do this for non-docshell created contexts, // only do this for non-docshell created contexts,
// since those are the ones that we created a surface for // since those are the ones that we created a surface for
if (mTarget && IsTargetValid() && !mDocShell) { if (mValid && !mDocShell) {
gCanvasAzureMemoryUsed -= mWidth * mHeight * 4; gCanvasAzureMemoryUsed -= mWidth * mHeight * 4;
} }
@ -660,6 +658,7 @@ nsCanvasRenderingContext2DAzure::Reset()
// Since the target changes the backing texture will change, and this will // Since the target changes the backing texture will change, and this will
// no longer be valid. // no longer be valid.
mThebesSurface = nullptr; mThebesSurface = nullptr;
mValid = false;
mIsEntireFrameInvalid = false; mIsEntireFrameInvalid = false;
mPredictManyRedrawCalls = false; mPredictManyRedrawCalls = false;
@ -836,15 +835,22 @@ nsCanvasRenderingContext2DAzure::RedrawUser(const gfxRect& r)
Redraw(newr); Redraw(newr);
} }
void NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::EnsureTarget() nsCanvasRenderingContext2DAzure::SetDimensions(int32_t width, int32_t height)
{ {
if (mTarget) { RefPtr<DrawTarget> target;
return;
// Zero sized surfaces cause issues, so just go with 1x1.
if (height == 0 || width == 0) {
mZero = true;
height = 1;
width = 1;
} else {
mZero = false;
} }
// Check that the dimensions are sane // Check that the dimensions are sane
IntSize size(mWidth, mHeight); IntSize size(width, height);
if (size.width <= 0xFFFF && size.height <= 0xFFFF && if (size.width <= 0xFFFF && size.height <= 0xFFFF &&
size.width >= 0 && size.height >= 0) { size.width >= 0 && size.height >= 0) {
SurfaceFormat format = GetSurfaceFormat(); SurfaceFormat format = GetSurfaceFormat();
@ -860,53 +866,41 @@ nsCanvasRenderingContext2DAzure::EnsureTarget()
nsContentUtils::PersistentLayerManagerForDocument(ownerDoc); nsContentUtils::PersistentLayerManagerForDocument(ownerDoc);
} }
if (layerManager) { if (layerManager) {
mTarget = layerManager->CreateDrawTarget(size, format); target = layerManager->CreateDrawTarget(size, format);
} else { } else {
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(size, format); target = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(size, format);
} }
} }
if (mTarget) { if (target) {
if (gCanvasAzureMemoryReporter == nullptr) { if (gCanvasAzureMemoryReporter == nullptr) {
gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory); gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory);
NS_RegisterMemoryReporter(gCanvasAzureMemoryReporter); NS_RegisterMemoryReporter(gCanvasAzureMemoryReporter);
} }
gCanvasAzureMemoryUsed += mWidth * mHeight * 4; gCanvasAzureMemoryUsed += width * height * 4;
JSContext* context = nsContentUtils::GetCurrentJSContext(); JSContext* context = nsContentUtils::GetCurrentJSContext();
if (context) { if (context) {
JS_updateMallocCounter(context, mWidth * mHeight * 4); JS_updateMallocCounter(context, width * height * 4);
} }
} else {
EnsureErrorTarget();
mTarget = sErrorTarget;
}
}
NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::SetDimensions(int32_t width, int32_t height)
{
ClearTarget();
// Zero sized surfaces cause issues, so just go with 1x1.
if (height == 0 || width == 0) {
mZero = true;
mWidth = 1;
mHeight = 1;
} else {
mZero = false;
mWidth = width;
mHeight = height;
} }
return NS_OK; return InitializeWithTarget(target, width, height);
} }
void nsresult
nsCanvasRenderingContext2DAzure::ClearTarget() nsCanvasRenderingContext2DAzure::Initialize(int32_t width, int32_t height)
{ {
Reset(); mWidth = width;
mHeight = height;
if (!mValid) {
// Create a dummy target in the hopes that it will help us deal with users
// calling into us after having changed the size where the size resulted
// in an inability to create a correct DrawTarget.
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
}
mResetLayer = true; mResetLayer = true;
@ -922,6 +916,42 @@ nsCanvasRenderingContext2DAzure::ClearTarget()
state->colorStyles[STYLE_FILL] = NS_RGB(0,0,0); state->colorStyles[STYLE_FILL] = NS_RGB(0,0,0);
state->colorStyles[STYLE_STROKE] = NS_RGB(0,0,0); state->colorStyles[STYLE_STROKE] = NS_RGB(0,0,0);
state->shadowColor = NS_RGBA(0,0,0,0); state->shadowColor = NS_RGBA(0,0,0,0);
if (mTarget) {
mTarget->ClearRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
// always force a redraw, because if the surface dimensions were reset
// then the surface became cleared, and we need to redraw everything.
Redraw();
}
return mValid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
nsresult
nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, int32_t width, int32_t height)
{
Reset();
NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
mDocShell = nullptr;
// This first time this is called on this object is via
// nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
// non-null, otherwise we'll return an error here and GetContext won't
// return this context object and we'll never enter this code again.
// All other times this method is called, if target is null then
// mTarget won't be changed, i.e. it will remain non-null, or else it
// will be set to non-null.
// In all cases, any usable canvas context will have non-null mTarget.
if (target) {
mValid = true;
mTarget = target;
} else {
mValid = false;
}
return Initialize(width, height);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -930,22 +960,25 @@ nsCanvasRenderingContext2DAzure::InitializeWithSurface(nsIDocShell *shell, gfxAS
mDocShell = shell; mDocShell = shell;
mThebesSurface = surface; mThebesSurface = surface;
SetDimensions(width, height);
mTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, IntSize(width, height)); mTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, IntSize(width, height));
if (!mTarget) { mValid = mTarget != nullptr;
EnsureErrorTarget();
mTarget = sErrorTarget;
}
return NS_OK; return Initialize(width, height);
} }
NS_IMETHODIMP NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque) nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque)
{ {
if (isOpaque != mOpaque) { if (isOpaque == mOpaque)
mOpaque = isOpaque; return NS_OK;
ClearTarget();
mOpaque = isOpaque;
if (mValid) {
/* If we've already been created, let SetDimensions take care of
* recreating our surface
*/
return SetDimensions(mWidth, mHeight);
} }
return NS_OK; return NS_OK;
@ -954,9 +987,16 @@ nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque)
NS_IMETHODIMP NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::SetIsIPC(bool isIPC) nsCanvasRenderingContext2DAzure::SetIsIPC(bool isIPC)
{ {
if (isIPC != mIPC) { if (isIPC == mIPC)
mIPC = isIPC; return NS_OK;
ClearTarget();
mIPC = isIPC;
if (mValid) {
/* If we've already been created, let SetDimensions take care of
* recreating our surface
*/
return SetDimensions(mWidth, mHeight);
} }
return NS_OK; return NS_OK;
@ -967,8 +1007,7 @@ nsCanvasRenderingContext2DAzure::Render(gfxContext *ctx, gfxPattern::GraphicsFil
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
EnsureTarget(); if (!mValid || !mTarget) {
if (!IsTargetValid()) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -1012,8 +1051,7 @@ nsCanvasRenderingContext2DAzure::GetInputStream(const char *aMimeType,
const PRUnichar *aEncoderOptions, const PRUnichar *aEncoderOptions,
nsIInputStream **aStream) nsIInputStream **aStream)
{ {
EnsureTarget(); if (!mValid || !mTarget) {
if (!IsTargetValid()) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -1100,7 +1138,6 @@ nsCanvasRenderingContext2DAzure::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
void void
nsCanvasRenderingContext2DAzure::Save() nsCanvasRenderingContext2DAzure::Save()
{ {
EnsureTarget();
mStyleStack[mStyleStack.Length() - 1].transform = mTarget->GetTransform(); mStyleStack[mStyleStack.Length() - 1].transform = mTarget->GetTransform();
mStyleStack.SetCapacity(mStyleStack.Length() + 1); mStyleStack.SetCapacity(mStyleStack.Length() + 1);
mStyleStack.AppendElement(CurrentState()); mStyleStack.AppendElement(CurrentState());
@ -1119,14 +1156,14 @@ nsCanvasRenderingContext2DAzure::Restore()
if (mStyleStack.Length() - 1 == 0) if (mStyleStack.Length() - 1 == 0)
return; return;
TransformWillUpdate();
for (uint32_t i = 0; i < CurrentState().clipsPushed.size(); i++) { for (uint32_t i = 0; i < CurrentState().clipsPushed.size(); i++) {
mTarget->PopClip(); mTarget->PopClip();
} }
mStyleStack.RemoveElementAt(mStyleStack.Length() - 1); mStyleStack.RemoveElementAt(mStyleStack.Length() - 1);
TransformWillUpdate();
mTarget->SetTransform(CurrentState().transform); mTarget->SetTransform(CurrentState().transform);
} }
@ -1144,15 +1181,16 @@ nsCanvasRenderingContext2DAzure::MozRestore()
void void
nsCanvasRenderingContext2DAzure::Scale(double x, double y, ErrorResult& error) nsCanvasRenderingContext2DAzure::Scale(double x, double y, ErrorResult& error)
{ {
if (!mTarget) {
error.Throw(NS_ERROR_FAILURE);
return;
}
if (!FloatValidate(x,y)) { if (!FloatValidate(x,y)) {
return; return;
} }
TransformWillUpdate(); TransformWillUpdate();
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE);
return;
}
Matrix newMatrix = mTarget->GetTransform(); Matrix newMatrix = mTarget->GetTransform();
mTarget->SetTransform(newMatrix.Scale(x, y)); mTarget->SetTransform(newMatrix.Scale(x, y));
@ -1169,16 +1207,16 @@ nsCanvasRenderingContext2DAzure::Scale(float x, float y)
void void
nsCanvasRenderingContext2DAzure::Rotate(double angle, ErrorResult& error) nsCanvasRenderingContext2DAzure::Rotate(double angle, ErrorResult& error)
{ {
if (!mTarget) {
error.Throw(NS_ERROR_FAILURE);
return;
}
if (!FloatValidate(angle)) { if (!FloatValidate(angle)) {
return; return;
} }
TransformWillUpdate(); TransformWillUpdate();
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE);
return;
}
Matrix rotation = Matrix::Rotation(angle); Matrix rotation = Matrix::Rotation(angle);
mTarget->SetTransform(rotation * mTarget->GetTransform()); mTarget->SetTransform(rotation * mTarget->GetTransform());
@ -1195,15 +1233,16 @@ nsCanvasRenderingContext2DAzure::Rotate(float angle)
void void
nsCanvasRenderingContext2DAzure::Translate(double x, double y, ErrorResult& error) nsCanvasRenderingContext2DAzure::Translate(double x, double y, ErrorResult& error)
{ {
if (!mTarget) {
error.Throw(NS_ERROR_FAILURE);
return;
}
if (!FloatValidate(x,y)) { if (!FloatValidate(x,y)) {
return; return;
} }
TransformWillUpdate(); TransformWillUpdate();
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE);
return;
}
Matrix newMatrix = mTarget->GetTransform(); Matrix newMatrix = mTarget->GetTransform();
mTarget->SetTransform(newMatrix.Translate(x, y)); mTarget->SetTransform(newMatrix.Translate(x, y));
@ -1222,15 +1261,16 @@ nsCanvasRenderingContext2DAzure::Transform(double m11, double m12, double m21,
double m22, double dx, double dy, double m22, double dx, double dy,
ErrorResult& error) ErrorResult& error)
{ {
if (!mTarget) {
error.Throw(NS_ERROR_FAILURE);
return;
}
if (!FloatValidate(m11,m12,m21,m22,dx,dy)) { if (!FloatValidate(m11,m12,m21,m22,dx,dy)) {
return; return;
} }
TransformWillUpdate(); TransformWillUpdate();
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE);
return;
}
Matrix matrix(m11, m12, m21, m22, dx, dy); Matrix matrix(m11, m12, m21, m22, dx, dy);
mTarget->SetTransform(matrix * mTarget->GetTransform()); mTarget->SetTransform(matrix * mTarget->GetTransform());
@ -1251,15 +1291,16 @@ nsCanvasRenderingContext2DAzure::SetTransform(double m11, double m12,
double dx, double dy, double dx, double dy,
ErrorResult& error) ErrorResult& error)
{ {
if (!mTarget) {
error.Throw(NS_ERROR_FAILURE);
return;
}
if (!FloatValidate(m11,m12,m21,m22,dx,dy)) { if (!FloatValidate(m11,m12,m21,m22,dx,dy)) {
return; return;
} }
TransformWillUpdate(); TransformWillUpdate();
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE);
return;
}
Matrix matrix(m11, m12, m21, m22, dx, dy); Matrix matrix(m11, m12, m21, m22, dx, dy);
mTarget->SetTransform(matrix); mTarget->SetTransform(matrix);
@ -1328,8 +1369,7 @@ nsCanvasRenderingContext2DAzure::SetMozCurrentTransform(JSContext* cx,
JSObject& currentTransform, JSObject& currentTransform,
ErrorResult& error) ErrorResult& error)
{ {
EnsureTarget(); if (!mTarget) {
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE); error.Throw(NS_ERROR_FAILURE);
return; return;
} }
@ -1357,7 +1397,12 @@ JSObject*
nsCanvasRenderingContext2DAzure::GetMozCurrentTransform(JSContext* cx, nsCanvasRenderingContext2DAzure::GetMozCurrentTransform(JSContext* cx,
ErrorResult& error) const ErrorResult& error) const
{ {
return MatrixToJSObject(cx, mTarget ? mTarget->GetTransform() : Matrix(), error); if (!mTarget) {
error.Throw(NS_ERROR_FAILURE);
return NULL;
}
return MatrixToJSObject(cx, mTarget->GetTransform(), error);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -1377,8 +1422,7 @@ nsCanvasRenderingContext2DAzure::SetMozCurrentTransformInverse(JSContext* cx,
JSObject& currentTransform, JSObject& currentTransform,
ErrorResult& error) ErrorResult& error)
{ {
EnsureTarget(); if (!mTarget) {
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE); error.Throw(NS_ERROR_FAILURE);
return; return;
} }
@ -1410,7 +1454,8 @@ nsCanvasRenderingContext2DAzure::GetMozCurrentTransformInverse(JSContext* cx,
ErrorResult& error) const ErrorResult& error) const
{ {
if (!mTarget) { if (!mTarget) {
return MatrixToJSObject(cx, Matrix(), error); error.Throw(NS_ERROR_FAILURE);
return NULL;
} }
Matrix ctm = mTarget->GetTransform(); Matrix ctm = mTarget->GetTransform();
@ -1857,7 +1902,6 @@ nsCanvasRenderingContext2DAzure::CreatePattern(const HTMLImageOrCanvasOrVideoEle
return NULL; return NULL;
} }
EnsureTarget();
RefPtr<SourceSurface> srcSurf = RefPtr<SourceSurface> srcSurf =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface); gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
@ -1961,7 +2005,7 @@ void
nsCanvasRenderingContext2DAzure::ClearRect(double x, double y, double w, nsCanvasRenderingContext2DAzure::ClearRect(double x, double y, double w,
double h) double h)
{ {
if (!FloatValidate(x,y,w,h) || !mTarget) { if (!FloatValidate(x,y,w,h)) {
return; return;
} }
@ -2035,7 +2079,6 @@ nsCanvasRenderingContext2DAzure::FillRect(double x, double y, double w,
mgfx::Rect bounds; mgfx::Rect bounds;
EnsureTarget();
if (NeedToDrawShadow()) { if (NeedToDrawShadow()) {
bounds = mgfx::Rect(x, y, w, h); bounds = mgfx::Rect(x, y, w, h);
bounds = mTarget->GetTransform().TransformBounds(bounds); bounds = mTarget->GetTransform().TransformBounds(bounds);
@ -2067,22 +2110,17 @@ nsCanvasRenderingContext2DAzure::StrokeRect(double x, double y, double w,
const ContextState &state = CurrentState(); const ContextState &state = CurrentState();
mgfx::Rect bounds; mgfx::Rect bounds;
if (!w && !h) {
return;
}
EnsureTarget();
if (!IsTargetValid()) {
return;
}
if (NeedToDrawShadow()) { if (NeedToDrawShadow()) {
bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f, bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
w + state.lineWidth, h + state.lineWidth); w + state.lineWidth, h + state.lineWidth);
bounds = mTarget->GetTransform().TransformBounds(bounds); bounds = mTarget->GetTransform().TransformBounds(bounds);
} }
if (!w && !h) {
return;
}
if (!h) { if (!h) {
CapStyle cap = CAP_BUTT; CapStyle cap = CAP_BUTT;
if (state.lineJoin == JOIN_ROUND) { if (state.lineJoin == JOIN_ROUND) {
@ -2453,7 +2491,6 @@ nsCanvasRenderingContext2DAzure::EnsureWritablePath()
return; return;
} }
EnsureTarget();
if (!mPath) { if (!mPath) {
NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null"); NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null");
mPathBuilder = mTarget->CreatePathBuilder(fillRule); mPathBuilder = mTarget->CreatePathBuilder(fillRule);
@ -2472,7 +2509,6 @@ nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* =
FillRule fillRule = CurrentState().fillRule; FillRule fillRule = CurrentState().fillRule;
if (!mPath && !mPathBuilder && !mDSPathBuilder) { if (!mPath && !mPathBuilder && !mDSPathBuilder) {
EnsureTarget();
mPathBuilder = mTarget->CreatePathBuilder(fillRule); mPathBuilder = mTarget->CreatePathBuilder(fillRule);
} }
@ -2518,8 +2554,6 @@ nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* =
void void
nsCanvasRenderingContext2DAzure::TransformWillUpdate() nsCanvasRenderingContext2DAzure::TransformWillUpdate()
{ {
EnsureTarget();
// Store the matrix that would transform the current path to device // Store the matrix that would transform the current path to device
// space. // space.
if (mPath || mPathBuilder) { if (mPath || mPathBuilder) {
@ -3003,7 +3037,6 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
float advanceSum = 0; float advanceSum = 0;
mCtx->EnsureTarget();
for (uint32_t c = 0; c < numRuns; c++) { for (uint32_t c = 0; c < numRuns; c++) {
gfxFont *font = runs[c].mFont; gfxFont *font = runs[c].mFont;
uint32_t endRun = 0; uint32_t endRun = 0;
@ -3204,14 +3237,8 @@ nsCanvasRenderingContext2DAzure::DrawOrMeasureText(const nsAString& aRawText,
processor.mPt = gfxPoint(aX, aY); processor.mPt = gfxPoint(aX, aY);
processor.mThebes = processor.mThebes =
new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface()); new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
Matrix matrix = mTarget->GetTransform();
// If we don't have a target then we don't have a transform. A target won't processor.mThebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32));
// be needed in the case where we're measuring the text size. This allows
// to avoid creating a target if it's only being used to measure text sizes.
if (mTarget) {
Matrix matrix = mTarget->GetTransform();
processor.mThebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32));
}
processor.mCtx = this; processor.mCtx = this;
processor.mOp = aOp; processor.mOp = aOp;
processor.mBoundingBox = gfxRect(0, 0, 0, 0); processor.mBoundingBox = gfxRect(0, 0, 0, 0);
@ -3301,7 +3328,6 @@ nsCanvasRenderingContext2DAzure::DrawOrMeasureText(const nsAString& aRawText,
processor.mPt.x *= processor.mAppUnitsPerDevPixel; processor.mPt.x *= processor.mAppUnitsPerDevPixel;
processor.mPt.y *= processor.mAppUnitsPerDevPixel; processor.mPt.y *= processor.mAppUnitsPerDevPixel;
EnsureTarget();
Matrix oldTransform = mTarget->GetTransform(); Matrix oldTransform = mTarget->GetTransform();
// if text is over aMaxWidth, then scale the text horizontally such that its // if text is over aMaxWidth, then scale the text horizontally such that its
// width is precisely aMaxWidth // width is precisely aMaxWidth
@ -3641,8 +3667,6 @@ nsCanvasRenderingContext2DAzure::DrawImage(const HTMLImageOrCanvasOrVideoElement
gfxIntSize imgSize; gfxIntSize imgSize;
Element* element; Element* element;
EnsureTarget();
if (image.IsHTMLCanvasElement()) { if (image.IsHTMLCanvasElement()) {
nsHTMLCanvasElement* canvas = image.GetAsHTMLCanvasElement(); nsHTMLCanvasElement* canvas = image.GetAsHTMLCanvasElement();
element = canvas; element = canvas;
@ -3904,7 +3928,6 @@ nsCanvasRenderingContext2DAzure::DrawWindow(nsIDOMWindow* window, double x,
nsRefPtr<gfxContext> thebes = new gfxContext(drawSurf); nsRefPtr<gfxContext> thebes = new gfxContext(drawSurf);
EnsureTarget();
Matrix matrix = mTarget->GetTransform(); Matrix matrix = mTarget->GetTransform();
thebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21, thebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21,
matrix._22, matrix._31, matrix._32)); matrix._22, matrix._31, matrix._32));
@ -4123,8 +4146,7 @@ nsCanvasRenderingContext2DAzure::GetImageData(JSContext* aCx, double aSx,
double aSy, double aSw, double aSy, double aSw,
double aSh, ErrorResult& error) double aSh, ErrorResult& error)
{ {
EnsureTarget(); if (!mValid) {
if (!IsTargetValid()) {
error.Throw(NS_ERROR_FAILURE); error.Throw(NS_ERROR_FAILURE);
return NULL; return NULL;
} }
@ -4317,19 +4339,6 @@ nsCanvasRenderingContext2DAzure::EnsurePremultiplyTable() {
} }
} }
void
nsCanvasRenderingContext2DAzure::EnsureErrorTarget()
{
if (sErrorTarget) {
return;
}
sErrorTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
NS_ABORT_IF_FALSE(sErrorTarget, "Failed to allocate the error target!");
NS_ADDREF(sErrorTarget);
}
void void
nsCanvasRenderingContext2DAzure::FillRuleChanged() nsCanvasRenderingContext2DAzure::FillRuleChanged()
{ {
@ -4398,6 +4407,10 @@ nsCanvasRenderingContext2DAzure::PutImageData_explicit(int32_t x, int32_t y, uin
bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY, bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
int32_t dirtyWidth, int32_t dirtyHeight) int32_t dirtyWidth, int32_t dirtyHeight)
{ {
if (!mValid) {
return NS_ERROR_FAILURE;
}
if (w == 0 || h == 0) { if (w == 0 || h == 0) {
return NS_ERROR_DOM_SYNTAX_ERR; return NS_ERROR_DOM_SYNTAX_ERR;
} }
@ -4486,11 +4499,6 @@ nsCanvasRenderingContext2DAzure::PutImageData_explicit(int32_t x, int32_t y, uin
} }
} }
EnsureTarget();
if (!IsTargetValid()) {
return NS_ERROR_FAILURE;
}
RefPtr<SourceSurface> sourceSurface = RefPtr<SourceSurface> sourceSurface =
mTarget->CreateSourceSurfaceFromData(imgsurf->Data(), IntSize(w, h), imgsurf->Stride(), FORMAT_B8G8R8A8); mTarget->CreateSourceSurfaceFromData(imgsurf->Data(), IntSize(w, h), imgsurf->Stride(), FORMAT_B8G8R8A8);
@ -4508,7 +4516,13 @@ nsCanvasRenderingContext2DAzure::PutImageData_explicit(int32_t x, int32_t y, uin
NS_IMETHODIMP NS_IMETHODIMP
nsCanvasRenderingContext2DAzure::GetThebesSurface(gfxASurface **surface) nsCanvasRenderingContext2DAzure::GetThebesSurface(gfxASurface **surface)
{ {
EnsureTarget(); if (!mTarget) {
nsRefPtr<gfxASurface> tmpSurf =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR_ALPHA);
*surface = tmpSurf.forget().get();
return NS_OK;
}
if (!mThebesSurface) { if (!mThebesSurface) {
mThebesSurface = mThebesSurface =
gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget); gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
@ -4618,15 +4632,16 @@ nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer, CanvasLayer *aOldLayer,
LayerManager *aManager) LayerManager *aManager)
{ {
EnsureTarget(); if (!mValid) {
if (!IsTargetValid()) {
// No DidTransactionCallback will be received, so mark the context clean // No DidTransactionCallback will be received, so mark the context clean
// now so future invalidations will be dispatched. // now so future invalidations will be dispatched.
MarkContextClean(); MarkContextClean();
return nullptr; return nullptr;
} }
mTarget->Flush(); if (mTarget) {
mTarget->Flush();
}
if (!mResetLayer && aOldLayer) { if (!mResetLayer && aOldLayer) {
CanvasRenderingContext2DUserDataAzure* userData = CanvasRenderingContext2DUserDataAzure* userData =
@ -4692,5 +4707,5 @@ nsCanvasRenderingContext2DAzure::MarkContextClean()
bool bool
nsCanvasRenderingContext2DAzure::ShouldForceInactiveLayer(LayerManager *aManager) nsCanvasRenderingContext2DAzure::ShouldForceInactiveLayer(LayerManager *aManager)
{ {
return !aManager->CanUseCanvasLayerForSize(gfxIntSize(mWidth, mHeight)); return !aManager->CanUseCanvasLayerForSize(gfxIntSize(mWidth, mHeight));
} }

View File

@ -566,8 +566,6 @@ protected:
*/ */
static uint8_t (*sPremultiplyTable)[256]; static uint8_t (*sPremultiplyTable)[256];
static mozilla::RefPtr<mozilla::gfx::DrawTarget> sErrorTarget;
// Some helpers. Doesn't modify a color on failure. // Some helpers. Doesn't modify a color on failure.
void SetStyleFromJSValue(JSContext* cx, JS::Value& value, Style whichStyle); void SetStyleFromJSValue(JSContext* cx, JS::Value& value, Style whichStyle);
void SetStyleFromString(const nsAString& str, Style whichStyle); void SetStyleFromString(const nsAString& str, Style whichStyle);
@ -600,11 +598,6 @@ protected:
*/ */
void EnsurePremultiplyTable(); void EnsurePremultiplyTable();
/**
* Creates the error target, if it doesn't exist
*/
static void EnsureErrorTarget();
/* This function ensures there is a writable pathbuilder available, this /* This function ensures there is a writable pathbuilder available, this
* pathbuilder may be working in user space or in device space or * pathbuilder may be working in user space or in device space or
* device space. * device space.
@ -617,33 +610,11 @@ protected:
// used for the path. // used for the path.
void EnsureUserSpacePath(bool aCommitTransform = true); void EnsureUserSpacePath(bool aCommitTransform = true);
/**
* Needs to be called before updating the transform. This makes a call to
* EnsureTarget() so you don't have to.
*/
void TransformWillUpdate(); void TransformWillUpdate();
// Report the fillRule has changed. // Report the fillRule has changed.
void FillRuleChanged(); void FillRuleChanged();
/**
* Create the backing surfacing, if it doesn't exist. If there is an error
* in creating the target then it will put sErrorTarget in place. If there
* is in turn an error in creating the sErrorTarget then they would both
* be null so IsTargetValid() would still return null.
*/
void EnsureTarget();
/*
* Disposes an old target and prepares to lazily create a new target.
*/
void ClearTarget();
/**
* Check if the target is valid after calling EnsureTarget.
*/
bool IsTargetValid() { return mTarget != sErrorTarget; }
/** /**
* Returns the surface format this canvas should be allocated using. Takes * Returns the surface format this canvas should be allocated using. Takes
* into account mOpaque, platform requirements, etc. * into account mOpaque, platform requirements, etc.
@ -692,6 +663,10 @@ protected:
// Member vars // Member vars
int32_t mWidth, mHeight; int32_t mWidth, mHeight;
// This is true when the canvas is valid, false otherwise, this occurs when
// for some reason initialization of the drawtarget fails. If the canvas
// is invalid certain behavior is expected.
bool mValid;
// This is true when the canvas is valid, but of zero size, this requires // This is true when the canvas is valid, but of zero size, this requires
// specific behavior on some operations. // specific behavior on some operations.
bool mZero; bool mZero;
@ -709,9 +684,7 @@ protected:
// If mCanvasElement is not provided, then a docshell is // If mCanvasElement is not provided, then a docshell is
nsCOMPtr<nsIDocShell> mDocShell; nsCOMPtr<nsIDocShell> mDocShell;
// This is created lazily so it is necessary to call EnsureTarget before // our drawing surfaces, contexts, and layers
// accessing it. In the event of an error it will be equal to
// sErrorTarget.
mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget; mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
/** /**