Bug 929364 - Avoid changing the current transform between emitting the path and clipping using that path in the SVGAutoRenderState::CLIP case. r=heycam

This commit is contained in:
Jonathan Watt 2013-10-22 23:45:51 +02:00
parent bbee419bc7
commit 927534b8bb

View File

@ -585,16 +585,39 @@ nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext,
break;
}
/* save/restore the state so we don't screw up the xform */
gfx->Save();
GeneratePath(gfx, GetCanvasTM(FOR_PAINTING, aTransformRoot));
if (renderMode != SVGAutoRenderState::NORMAL) {
NS_ABORT_IF_FALSE(renderMode == SVGAutoRenderState::CLIP ||
renderMode == SVGAutoRenderState::CLIP_MASK,
"Unknown render mode");
gfx->Restore();
// In the case that |renderMode == SVGAutoRenderState::CLIP| then we don't
// use the path we generate here until further up the call stack when
// nsSVGClipPathFrame::Clip calls gfxContext::Clip. That's a problem for
// Moz2D which emits paths in user space (unlike cairo which emits paths in
// device space). gfxContext has hacks to deal with code changing the
// transform then using the current path when it is backed by Moz2D, but
// Moz2D itself does not since that would fundamentally go against its API.
// Therefore we do not want to Save()/Restore() the gfxContext here in the
// SVGAutoRenderState::CLIP case since that would block us from killing off
// gfxContext and using Moz2D directly. Not bothering to Save()/Restore()
// is actually okay, since we know that doesn't matter in the
// SVGAutoRenderState::CLIP case (at least for the current implementation).
gfxContextMatrixAutoSaveRestore autoSaveRestore;
if (renderMode != SVGAutoRenderState::CLIP) {
autoSaveRestore.SetContext(gfx);
}
GeneratePath(gfx, GetCanvasTM(FOR_PAINTING, aTransformRoot));
// We used to call gfx->Restore() here, since for the
// SVGAutoRenderState::CLIP case it is important to leave the fill rule
// that we set below untouched so that the value is still set when return
// to gfxContext::Clip() further up the call stack. Since we no longer
// call gfx->Save() in the SVGAutoRenderState::CLIP case we don't need to
// worry that autoSaveRestore will delay the Restore() call for the
// CLIP_MASK case until we exit this function.
gfxContext::FillRule oldFillRull = gfx->CurrentFillRule();
if (GetClipRule() == NS_STYLE_FILL_RULE_EVENODD)
gfx->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
@ -604,12 +627,17 @@ nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext,
if (renderMode == SVGAutoRenderState::CLIP_MASK) {
gfx->SetColor(gfxRGBA(1.0f, 1.0f, 1.0f, 1.0f));
gfx->Fill();
gfx->SetFillRule(oldFillRull); // restore, but only for CLIP_MASK
gfx->NewPath();
}
return;
}
gfxContextAutoSaveRestore autoSaveRestore(gfx);
GeneratePath(gfx, GetCanvasTM(FOR_PAINTING, aTransformRoot));
gfxTextContextPaint *contextPaint =
(gfxTextContextPaint*)aContext->GetUserData(&gfxTextContextPaint::sUserDataKey);
@ -624,8 +652,6 @@ nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext,
}
gfx->NewPath();
gfx->Restore();
}
void