author | Jonathan Watt <jwatt@jwatt.org> |
Tue, 22 Oct 2013 23:45:51 +0200 | |
changeset 151673 | b011488de9e6e3c4fbf4acfd1fd582addcb7a9d1 |
parent 151672 | ce0759a746fb526db7044b7ab1096e2c08823200 |
child 151674 | a8680e083efa3aff99342f19b6bfbcf62c6ae0fb |
push id | 35280 |
push user | jwatt@jwatt.org |
push date | Tue, 22 Oct 2013 21:46:30 +0000 |
treeherder | mozilla-inbound@39f4bb8c55d8 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | heycam |
bugs | 929364 |
milestone | 27.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/svg/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/nsSVGPathGeometryFrame.cpp @@ -580,57 +580,83 @@ nsSVGPathGeometryFrame::Render(nsRenderi case NS_STYLE_SHAPE_RENDERING_CRISPEDGES: gfx->SetAntialiasMode(gfxContext::MODE_ALIASED); break; default: gfx->SetAntialiasMode(gfxContext::MODE_COVERAGE); 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); else gfx->SetFillRule(gfxContext::FILL_RULE_WINDING); 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); if ((aRenderComponents & eRenderFill) && nsSVGUtils::SetupCairoFillPaint(this, gfx, contextPaint)) { gfx->Fill(); } if ((aRenderComponents & eRenderStroke) && nsSVGUtils::SetupCairoStroke(this, gfx, contextPaint)) { gfx->Stroke(); } gfx->NewPath(); - - gfx->Restore(); } void nsSVGPathGeometryFrame::GeneratePath(gfxContext* aContext, const gfxMatrix &aTransform) { if (aTransform.IsSingular()) { aContext->IdentityMatrix();