Bug 356400 - fix crash when scale(0) set in transform. r=jwatt,sr=tor

This commit is contained in:
longsonr%gmail.com 2006-10-27 10:34:23 +00:00
Родитель 269274f893
Коммит 46a662c3da
9 изменённых файлов: 68 добавлений и 24 удалений

Просмотреть файл

@ -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);