зеркало из https://github.com/mozilla/gecko-dev.git
Bug 356400 - fix crash when scale(0) set in transform. r=jwatt,sr=tor
This commit is contained in:
Родитель
269274f893
Коммит
46a662c3da
|
@ -433,13 +433,13 @@ nsSVGFilterFrame::FilterPaint(nsISVGRendererCanvas *aCanvas,
|
|||
|
||||
ctm->Multiply(scale, getter_AddRefs(fini));
|
||||
|
||||
aCanvas->CompositeSurfaceMatrix(filterResult, fini, 1.0);
|
||||
nsresult rv = aCanvas->CompositeSurfaceMatrix(filterResult, fini, 1.0);
|
||||
|
||||
aTarget->SetOverrideCTM(nsnull);
|
||||
aTarget->SetMatrixPropagation(PR_TRUE);
|
||||
aTarget->NotifyCanvasTMChanged(PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsRect)
|
||||
|
|
|
@ -1466,8 +1466,7 @@ nsSVGGlyphFrame::GetGlobalTransform(cairo_t *ctx,
|
|||
aCanvas->AdjustMatrixForInitialTransform(&matrix);
|
||||
}
|
||||
|
||||
cairo_matrix_t inverse = matrix;
|
||||
if (cairo_matrix_invert(&inverse)) {
|
||||
if (nsSVGUtils::IsSingular(&matrix)) {
|
||||
cairo_identity_matrix(ctx);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -254,6 +254,8 @@ nsSVGImageFrame::GetImageTransform()
|
|||
NS_IMETHODIMP
|
||||
nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!GetStyleVisibility()->IsVisible())
|
||||
return NS_OK;
|
||||
|
||||
|
@ -292,17 +294,19 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
|
|||
|
||||
if (GetStyleDisplay()->IsScrollableOverflow()) {
|
||||
canvas->PushClip();
|
||||
canvas->SetClipRect(ctm, x, y, width, height);
|
||||
rv = canvas->SetClipRect(ctm, x, y, width, height);
|
||||
}
|
||||
|
||||
canvas->CompositeSurfaceMatrix(mSurface, fini,
|
||||
mStyleContext->GetStyleDisplay()->mOpacity);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = canvas->CompositeSurfaceMatrix(mSurface, fini,
|
||||
mStyleContext->GetStyleDisplay()->mOpacity);
|
||||
}
|
||||
|
||||
if (GetStyleDisplay()->IsScrollableOverflow())
|
||||
canvas->PopClip();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -173,9 +173,7 @@ nsSVGInnerSVGFrame::GetType() const
|
|||
NS_IMETHODIMP
|
||||
nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// printf("nsSVGInnerSVG(%p)::Paint\n", this);
|
||||
#endif
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
canvas->PushClip();
|
||||
|
||||
|
@ -194,15 +192,18 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
|
|||
clipTransform = parent->GetCanvasTM();
|
||||
}
|
||||
|
||||
if (clipTransform)
|
||||
canvas->SetClipRect(clipTransform, x, y, width, height);
|
||||
if (clipTransform) {
|
||||
rv = canvas->SetClipRect(clipTransform, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
nsSVGInnerSVGFrameBase::PaintSVG(canvas, aDirtyRect);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = nsSVGInnerSVGFrameBase::PaintSVG(canvas, aDirtyRect);
|
||||
}
|
||||
|
||||
canvas->PopClip();
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -143,6 +143,7 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsISVGRendererCanvas* aCanvas,
|
|||
{
|
||||
nsCOMPtr<nsISVGCairoCanvas> cairoCanvas = do_QueryInterface(aCanvas);
|
||||
cairo_t *ctx = cairoCanvas->GetContext();
|
||||
cairo_pattern_t *pattern = nsnull;
|
||||
|
||||
cairo_push_group(ctx);
|
||||
|
||||
|
@ -202,7 +203,12 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsISVGRendererCanvas* aCanvas,
|
|||
fprintf(stderr, "mask clip: %f,%f %fx%f\n", x, y, width, height);
|
||||
#endif
|
||||
|
||||
aCanvas->SetClipRect(aMatrix, x, y, width, height);
|
||||
if (NS_FAILED(aCanvas->SetClipRect(aMatrix, x, y, width, height))) {
|
||||
pattern = cairo_pop_group(ctx);
|
||||
if (pattern)
|
||||
cairo_pattern_destroy(pattern);
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
mMaskParent = aParent,
|
||||
|
@ -213,7 +219,7 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsISVGRendererCanvas* aCanvas,
|
|||
nsSVGUtils::PaintChildWithEffects(aCanvas, nsnull, kid);
|
||||
}
|
||||
|
||||
cairo_pattern_t *pattern = cairo_pop_group(ctx);
|
||||
pattern = cairo_pop_group(ctx);
|
||||
if (!pattern)
|
||||
return nsnull;
|
||||
|
||||
|
|
|
@ -647,8 +647,7 @@ nsSVGPathGeometryFrame::GeneratePath(cairo_t *ctx, nsISVGCairoCanvas* aCanvas)
|
|||
aCanvas->AdjustMatrixForInitialTransform(&matrix);
|
||||
}
|
||||
|
||||
cairo_matrix_t inverse = matrix;
|
||||
if (cairo_matrix_invert(&inverse)) {
|
||||
if (nsSVGUtils::IsSingular(&matrix)) {
|
||||
cairo_identity_matrix(ctx);
|
||||
cairo_new_path(ctx);
|
||||
return;
|
||||
|
|
|
@ -918,6 +918,18 @@ nsSVGUtils::GetCairoComputationalSurface()
|
|||
return mCairoComputationalSurface;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSVGUtils::IsSingular(const cairo_matrix_t *aMatrix)
|
||||
{
|
||||
double a, b, c, d;
|
||||
|
||||
a = aMatrix->xx; b = aMatrix->yx;
|
||||
c = aMatrix->xy; d = aMatrix->yy;
|
||||
|
||||
// if the determinant (ad - bc) is zero it's singular
|
||||
return a * d == b * c;
|
||||
}
|
||||
|
||||
cairo_matrix_t
|
||||
nsSVGUtils::ConvertSVGMatrixToCairo(nsIDOMSVGMatrix *aMatrix)
|
||||
{
|
||||
|
|
|
@ -248,6 +248,12 @@ public:
|
|||
static cairo_surface_t *
|
||||
GetCairoComputationalSurface();
|
||||
|
||||
/*
|
||||
* A singular matrix is a non invertible square matrix.
|
||||
*/
|
||||
static PRBool
|
||||
IsSingular(const cairo_matrix_t *aMatrix);
|
||||
|
||||
/*
|
||||
* Convert a nsIDOMSVGMatrix to a cairo_matrix_t.
|
||||
*/
|
||||
|
|
|
@ -133,7 +133,7 @@ public:
|
|||
NS_IMETHOD AdjustMatrixForInitialTransform(cairo_matrix_t* aMatrix);
|
||||
|
||||
protected:
|
||||
void SetupCairoMatrix(nsIDOMSVGMatrix *aCTM);
|
||||
nsresult SetupCairoMatrix(nsIDOMSVGMatrix *aCTM);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIRenderingContext> mMozContext;
|
||||
|
@ -451,11 +451,17 @@ NS_INTERFACE_MAP_END
|
|||
//----------------------------------------------------------------------
|
||||
// nsISVGRendererCanvas methods:
|
||||
|
||||
void nsSVGCairoCanvas::SetupCairoMatrix(nsIDOMSVGMatrix *aCTM)
|
||||
nsresult
|
||||
nsSVGCairoCanvas::SetupCairoMatrix(nsIDOMSVGMatrix *aCTM)
|
||||
{
|
||||
cairo_matrix_t matrix = nsSVGUtils::ConvertSVGMatrixToCairo(aCTM);
|
||||
AdjustMatrixForInitialTransform(&matrix);
|
||||
|
||||
if (nsSVGUtils::IsSingular(&matrix)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
cairo_set_matrix(mCR, &matrix);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** Implements [noscript] nsIRenderingContext lockRenderingContext(const in nsRectRef rect); */
|
||||
|
@ -463,7 +469,11 @@ NS_IMETHODIMP
|
|||
nsSVGCairoCanvas::LockRenderingContext(nsIDOMSVGMatrix* aCTM,
|
||||
nsIRenderingContext **_retval)
|
||||
{
|
||||
SetupCairoMatrix(aCTM);
|
||||
nsresult rv = SetupCairoMatrix(aCTM);
|
||||
if (NS_FAILED(rv)) {
|
||||
*_retval = nsnull;
|
||||
return rv;
|
||||
}
|
||||
*_retval = mMozContext;
|
||||
NS_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
|
@ -701,7 +711,10 @@ nsSVGCairoCanvas::SetClipRect(nsIDOMSVGMatrix *aCTM, float aX, float aY,
|
|||
cairo_matrix_t oldMatrix;
|
||||
cairo_get_matrix(mCR, &oldMatrix);
|
||||
|
||||
SetupCairoMatrix(aCTM);
|
||||
nsresult rv = SetupCairoMatrix(aCTM);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
cairo_new_path(mCR);
|
||||
cairo_rectangle(mCR, aX, aY, aWidth, aHeight);
|
||||
|
@ -775,7 +788,11 @@ nsSVGCairoCanvas::CompositeSurfaceMatrix(cairo_surface_t *aSurface,
|
|||
{
|
||||
cairo_save(mCR);
|
||||
|
||||
SetupCairoMatrix(aCTM);
|
||||
nsresult rv = SetupCairoMatrix(aCTM);
|
||||
if (NS_FAILED(rv)) {
|
||||
cairo_restore(mCR);
|
||||
return rv;
|
||||
}
|
||||
|
||||
cairo_set_source_surface(mCR, aSurface, 0.0, 0.0);
|
||||
cairo_paint_with_alpha(mCR, aOpacity);
|
||||
|
|
Загрузка…
Ссылка в новой задаче