зеркало из https://github.com/mozilla/pjs.git
Bug 360316 - Avoid group opacity when possible. r=jwatt, sr=roc
This commit is contained in:
Родитель
c948ac49d4
Коммит
b1e56b1c1b
|
@ -333,6 +333,15 @@ SetupCairoColor(cairo_t *aCtx, nscolor aRGB, float aOpacity)
|
|||
aOpacity);
|
||||
}
|
||||
|
||||
float
|
||||
nsSVGGeometryFrame::MaybeOptimizeOpacity(float aOpacity)
|
||||
{
|
||||
if (nsSVGUtils::CanOptimizeOpacity(this)) {
|
||||
aOpacity *= GetStyleDisplay()->mOpacity;
|
||||
}
|
||||
return aOpacity;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGGeometryFrame::SetupCairoFill(gfxContext *aContext,
|
||||
void **aClosure)
|
||||
|
@ -345,21 +354,19 @@ nsSVGGeometryFrame::SetupCairoFill(gfxContext *aContext,
|
|||
else
|
||||
cairo_set_fill_rule(ctx, CAIRO_FILL_RULE_WINDING);
|
||||
|
||||
float opacity = MaybeOptimizeOpacity(GetStyleSVG()->mFillOpacity);
|
||||
|
||||
if (GetStateBits() & NS_STATE_SVG_FILL_PSERVER) {
|
||||
nsSVGPaintServerFrame *ps = NS_STATIC_CAST(nsSVGPaintServerFrame*,
|
||||
GetProperty(nsGkAtoms::fill));
|
||||
return ps->SetupPaintServer(ctx, this,
|
||||
GetStyleSVG()->mFillOpacity,
|
||||
aClosure);
|
||||
return ps->SetupPaintServer(ctx, this, opacity, aClosure);
|
||||
} else if (GetStyleSVG()->mFill.mType == eStyleSVGPaintType_Server) {
|
||||
// should have a paint server but something has gone wrong configuring it.
|
||||
SetupCairoColor(ctx,
|
||||
sInvalidPaintColour,
|
||||
GetStyleSVG()->mFillOpacity);
|
||||
SetupCairoColor(ctx, sInvalidPaintColour, opacity);
|
||||
} else
|
||||
SetupCairoColor(ctx,
|
||||
GetStyleSVG()->mFill.mPaint.mColor,
|
||||
GetStyleSVG()->mFillOpacity);
|
||||
opacity);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -428,16 +435,16 @@ nsSVGGeometryFrame::SetupCairoStroke(gfxContext *aContext,
|
|||
|
||||
SetupCairoStrokeHitGeometry(aCtx);
|
||||
|
||||
float opacity = MaybeOptimizeOpacity(GetStyleSVG()->mStrokeOpacity);
|
||||
|
||||
if (GetStateBits() & NS_STATE_SVG_STROKE_PSERVER) {
|
||||
nsSVGPaintServerFrame *ps = NS_STATIC_CAST(nsSVGPaintServerFrame*,
|
||||
GetProperty(nsGkAtoms::stroke));
|
||||
return ps->SetupPaintServer(aCtx, this,
|
||||
GetStyleSVG()->mStrokeOpacity,
|
||||
aClosure);
|
||||
return ps->SetupPaintServer(aCtx, this, opacity, aClosure);
|
||||
} else
|
||||
SetupCairoColor(aCtx,
|
||||
GetStyleSVG()->mStroke.mPaint.mColor,
|
||||
GetStyleSVG()->mStrokeOpacity);
|
||||
opacity);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,14 @@ private:
|
|||
nsresult GetStrokeDashArray(double **arr, PRUint32 *count);
|
||||
float GetStrokeDashoffset();
|
||||
void RemovePaintServerProperties();
|
||||
|
||||
// Returns opacity that should be used in rendering this primitive.
|
||||
// In the general case the return value is just the passed opacity.
|
||||
// If we can avoid the expense of a specified group opacity, we
|
||||
// multiply the passed opacity by the value of the 'opacity'
|
||||
// property, and elsewhere pretend the 'opacity' property has a
|
||||
// value of 1.
|
||||
float MaybeOptimizeOpacity(float aOpacity);
|
||||
};
|
||||
|
||||
#endif // __NS_SVGGEOMETRYFRAME_H__
|
||||
|
|
|
@ -291,8 +291,15 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect)
|
|||
nsSVGUtils::SetClipRect(gfx, ctm, x, y, width, height);
|
||||
}
|
||||
|
||||
nsSVGUtils::CompositeSurfaceMatrix(gfx, thebesSurface, fini,
|
||||
mStyleContext->GetStyleDisplay()->mOpacity);
|
||||
// fill-opacity doesn't affect <image>, so if we're allowed to
|
||||
// optimize group opacity, the opacity used for compositing the
|
||||
// image into the current canvas is just the group opacity.
|
||||
float opacity = 1.0f;
|
||||
if (nsSVGUtils::CanOptimizeOpacity(this)) {
|
||||
opacity = GetStyleDisplay()->mOpacity;
|
||||
}
|
||||
|
||||
nsSVGUtils::CompositeSurfaceMatrix(gfx, thebesSurface, fini, opacity);
|
||||
|
||||
if (GetStyleDisplay()->IsScrollableOverflow())
|
||||
gfx->Restore();
|
||||
|
|
|
@ -626,6 +626,8 @@ nsSVGUtils::PaintChildWithEffects(nsSVGRenderState *aContext,
|
|||
return;
|
||||
|
||||
float opacity = aFrame->GetStyleDisplay()->mOpacity;
|
||||
if (opacity == 0.0f)
|
||||
return;
|
||||
|
||||
/* Properties are added lazily and may have been removed by a restyle,
|
||||
so make sure all applicable ones are set again. */
|
||||
|
@ -658,6 +660,9 @@ nsSVGUtils::PaintChildWithEffects(nsSVGRenderState *aContext,
|
|||
* + Merge opacity and masking if both used together.
|
||||
*/
|
||||
|
||||
if (opacity != 1.0 && nsSVGUtils::CanOptimizeOpacity(aFrame))
|
||||
opacity = 1.0;
|
||||
|
||||
gfxContext *gfx = aContext->GetGfxContext();
|
||||
cairo_t *ctx = nsnull;
|
||||
|
||||
|
@ -1039,6 +1044,22 @@ nsSVGUtils::SetClipRect(gfxContext *aContext,
|
|||
aContext->SetMatrix(oldMatrix);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSVGUtils::CanOptimizeOpacity(nsIFrame *aFrame)
|
||||
{
|
||||
if (!(aFrame->GetStateBits() & NS_STATE_SVG_FILTERED)) {
|
||||
nsIAtom *type = aFrame->GetType();
|
||||
if (type == nsGkAtoms::svgImageFrame)
|
||||
return PR_TRUE;
|
||||
if (type == nsGkAtoms::svgPathGeometryFrame) {
|
||||
nsSVGGeometryFrame *geom = NS_STATIC_CAST(nsSVGGeometryFrame*, aFrame);
|
||||
if (!(geom->HasFill() && geom->HasStroke()))
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
nsSVGRenderState::nsSVGRenderState(nsIRenderingContext *aContext) :
|
||||
|
|
|
@ -323,6 +323,14 @@ public:
|
|||
nsIDOMSVGMatrix *aCTM, float aX, float aY,
|
||||
float aWidth, float aHeight);
|
||||
|
||||
/* Using group opacity instead of fill or stroke opacity on a
|
||||
* geometry object seems to be a common authoring mistake. If we're
|
||||
* not applying filters and not both stroking and filling, we can
|
||||
* generate the same result without going through the overhead of a
|
||||
* push/pop group. */
|
||||
static PRBool
|
||||
CanOptimizeOpacity(nsIFrame *aFrame);
|
||||
|
||||
private:
|
||||
/* Computational (nil) surfaces */
|
||||
static cairo_surface_t *mCairoComputationalSurface;
|
||||
|
|
Загрузка…
Ссылка в новой задаче