Bug 360316 - Avoid group opacity when possible. r=jwatt, sr=roc

This commit is contained in:
tor%cs.brown.edu 2007-01-04 15:05:39 +00:00
Родитель c948ac49d4
Коммит b1e56b1c1b
5 изменённых файлов: 64 добавлений и 13 удалений

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

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