Bug 1073012 , part 2 - Replace nsSVGUtils::SetupCairoStrokePaint with a helper that returns a gfxPattern. r=longsonr

This commit is contained in:
Jonathan Watt 2014-09-29 14:12:06 +01:00
parent 071a7f8dad
commit 7c2f3f1ed0
4 changed files with 98 additions and 134 deletions

View File

@ -375,9 +375,13 @@ nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
gfx->SetPattern(fillPattern);
gfx->Fill();
}
} else if (aSource == &mStrokePaint &&
nsSVGUtils::SetupCairoStrokePaint(mTargetFrame, gfx)) {
gfx->Fill();
} else if (aSource == &mStrokePaint) {
nsRefPtr<gfxPattern> strokePattern =
nsSVGUtils::MakeStrokePatternFor(mTargetFrame, gfx);
if (strokePattern) {
gfx->SetPattern(strokePattern);
gfx->Fill(); // yes, filling a primitive subregion with _stroke_ paint
}
}
gfx->Restore();
}

View File

@ -503,7 +503,6 @@ nsSVGPathGeometryFrame::GetBBoxContribution(const Matrix &aToBBoxUserspace,
// though, because if pathExtents is empty, its position will not have
// been set. Happily we can use tmpCtx->GetUserStrokeExtent() to find
// the center point of the extents even though it gets the extents wrong.
nsSVGUtils::SetupCairoStrokeBBoxGeometry(this, tmpCtx);
pathExtents.MoveTo(tmpCtx->GetUserStrokeExtent().Center());
pathExtents.SizeTo(0, 0);
}

View File

@ -1233,20 +1233,6 @@ nsSVGUtils::GetFallbackOrPaintColor(nsStyleContext *aStyleContext,
return color;
}
static void
SetupFallbackOrPaintColor(gfxContext *aContext, nsStyleContext *aStyleContext,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aOpacity)
{
nscolor color =
nsSVGUtils::GetFallbackOrPaintColor(aStyleContext, aFillOrStroke);
aContext->SetColor(gfxRGBA(NS_GET_R(color)/255.0,
NS_GET_G(color)/255.0,
NS_GET_B(color)/255.0,
NS_GET_A(color)/255.0 * aOpacity));
}
static float
MaybeOptimizeOpacity(nsIFrame *aFrame, float aFillOrStrokeOpacity)
{
@ -1257,38 +1243,6 @@ MaybeOptimizeOpacity(nsIFrame *aFrame, float aFillOrStrokeOpacity)
return aFillOrStrokeOpacity;
}
/* static */ bool
nsSVGUtils::SetupContextPaint(gfxContext *aContext,
gfxTextContextPaint *aContextPaint,
const nsStyleSVGPaint &aPaint,
float aOpacity)
{
nsRefPtr<gfxPattern> pattern;
if (!aContextPaint) {
return false;
}
switch (aPaint.mType) {
case eStyleSVGPaintType_ContextFill:
pattern = aContextPaint->GetFillPattern(aOpacity, aContext->CurrentMatrix());
break;
case eStyleSVGPaintType_ContextStroke:
pattern = aContextPaint->GetStrokePattern(aOpacity, aContext->CurrentMatrix());
break;
default:
return false;
}
if (!pattern) {
return false;
}
aContext->SetPattern(pattern);
return true;
}
/* static */ already_AddRefed<gfxPattern>
nsSVGUtils::MakeFillPatternFor(nsIFrame *aFrame,
gfxContext* aContext,
@ -1336,7 +1290,7 @@ nsSVGUtils::MakeFillPatternFor(nsIFrame *aFrame,
// On failure, use the fallback colour in case we have an
// objectBoundingBox where the width or height of the object is zero.
// See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
nscolor color = GetFallbackOrPaintColor(aContext, aFrame->StyleContext(),
nscolor color = GetFallbackOrPaintColor(aFrame->StyleContext(),
&nsStyleSVG::mFill);
pattern = new gfxPattern(gfxRGBA(NS_GET_R(color)/255.0,
NS_GET_G(color)/255.0,
@ -1345,35 +1299,60 @@ nsSVGUtils::MakeFillPatternFor(nsIFrame *aFrame,
return pattern.forget();
}
bool
nsSVGUtils::SetupCairoStrokePaint(nsIFrame *aFrame, gfxContext* aContext,
gfxTextContextPaint *aContextPaint)
/* static */ already_AddRefed<gfxPattern>
nsSVGUtils::MakeStrokePatternFor(nsIFrame *aFrame,
gfxContext* aContext,
gfxTextContextPaint *aContextPaint)
{
const nsStyleSVG* style = aFrame->StyleSVG();
if (style->mStroke.mType == eStyleSVGPaintType_None)
return false;
if (style->mStroke.mType == eStyleSVGPaintType_None) {
return nullptr;
}
float opacity = MaybeOptimizeOpacity(aFrame,
GetOpacity(style->mStrokeOpacitySource,
style->mStrokeOpacity,
aContextPaint));
nsRefPtr<gfxPattern> pattern;
nsSVGPaintServerFrame *ps =
nsSVGEffects::GetPaintServer(aFrame, &style->mStroke, nsSVGEffects::StrokeProperty());
if (ps && ps->SetupPaintServer(aContext, aFrame, &nsStyleSVG::mStroke, opacity))
return true;
nsSVGEffects::GetPaintServer(aFrame, &style->mStroke,
nsSVGEffects::StrokeProperty());
if (ps) {
pattern = ps->GetPaintServerPattern(aFrame, aContext->CurrentMatrix(),
&nsStyleSVG::mStroke, opacity);
if (pattern) {
pattern->CacheColorStops(aContext->GetDrawTarget());
return pattern.forget();
}
}
if (SetupContextPaint(aContext, aContextPaint, style->mStroke, opacity)) {
return true;
if (aContextPaint) {
switch (style->mStroke.mType) {
case eStyleSVGPaintType_ContextFill:
pattern = aContextPaint->GetFillPattern(opacity, aContext->CurrentMatrix());
break;
case eStyleSVGPaintType_ContextStroke:
pattern = aContextPaint->GetStrokePattern(opacity, aContext->CurrentMatrix());
break;
default:
;
}
if (pattern) {
return pattern.forget();
}
}
// On failure, use the fallback colour in case we have an
// objectBoundingBox where the width or height of the object is zero.
// See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
SetupFallbackOrPaintColor(aContext, aFrame->StyleContext(),
&nsStyleSVG::mStroke, opacity);
return true;
nscolor color = GetFallbackOrPaintColor(aFrame->StyleContext(),
&nsStyleSVG::mStroke);
pattern = new gfxPattern(gfxRGBA(NS_GET_R(color)/255.0,
NS_GET_G(color)/255.0,
NS_GET_B(color)/255.0,
NS_GET_A(color)/255.0 * opacity));
return pattern.forget();
}
/* static */ float
@ -1431,51 +1410,6 @@ nsSVGUtils::GetStrokeWidth(nsIFrame* aFrame, gfxTextContextPaint *aContextPaint)
return SVGContentUtils::CoordToFloat(ctx, style->mStrokeWidth);
}
void
nsSVGUtils::SetupCairoStrokeBBoxGeometry(nsIFrame* aFrame,
gfxContext *aContext,
gfxTextContextPaint *aContextPaint)
{
float width = GetStrokeWidth(aFrame, aContextPaint);
if (width <= 0)
return;
aContext->SetLineWidth(width);
// Apply any stroke-specific transform
gfxMatrix strokeTransform = GetStrokeTransform(aFrame);
if (!strokeTransform.IsIdentity()) {
aContext->Multiply(strokeTransform);
}
const nsStyleSVG* style = aFrame->StyleSVG();
switch (style->mStrokeLinecap) {
case NS_STYLE_STROKE_LINECAP_BUTT:
aContext->SetLineCap(gfxContext::LINE_CAP_BUTT);
break;
case NS_STYLE_STROKE_LINECAP_ROUND:
aContext->SetLineCap(gfxContext::LINE_CAP_ROUND);
break;
case NS_STYLE_STROKE_LINECAP_SQUARE:
aContext->SetLineCap(gfxContext::LINE_CAP_SQUARE);
break;
}
aContext->SetMiterLimit(style->mStrokeMiterlimit);
switch (style->mStrokeLinejoin) {
case NS_STYLE_STROKE_LINEJOIN_MITER:
aContext->SetLineJoin(gfxContext::LINE_JOIN_MITER);
break;
case NS_STYLE_STROKE_LINEJOIN_ROUND:
aContext->SetLineJoin(gfxContext::LINE_JOIN_ROUND);
break;
case NS_STYLE_STROKE_LINEJOIN_BEVEL:
aContext->SetLineJoin(gfxContext::LINE_JOIN_BEVEL);
break;
}
}
static bool
GetStrokeDashData(nsIFrame* aFrame,
FallibleTArray<gfxFloat>& aDashes,
@ -1538,10 +1472,48 @@ GetStrokeDashData(nsIFrame* aFrame,
}
void
nsSVGUtils::SetupCairoStrokeGeometry(nsIFrame* aFrame, gfxContext* aContext,
nsSVGUtils::SetupCairoStrokeGeometry(nsIFrame* aFrame,
gfxContext *aContext,
gfxTextContextPaint *aContextPaint)
{
SetupCairoStrokeBBoxGeometry(aFrame, aContext, aContextPaint);
float width = GetStrokeWidth(aFrame, aContextPaint);
if (width <= 0)
return;
aContext->SetLineWidth(width);
// Apply any stroke-specific transform
gfxMatrix strokeTransform = GetStrokeTransform(aFrame);
if (!strokeTransform.IsIdentity()) {
aContext->Multiply(strokeTransform);
}
const nsStyleSVG* style = aFrame->StyleSVG();
switch (style->mStrokeLinecap) {
case NS_STYLE_STROKE_LINECAP_BUTT:
aContext->SetLineCap(gfxContext::LINE_CAP_BUTT);
break;
case NS_STYLE_STROKE_LINECAP_ROUND:
aContext->SetLineCap(gfxContext::LINE_CAP_ROUND);
break;
case NS_STYLE_STROKE_LINECAP_SQUARE:
aContext->SetLineCap(gfxContext::LINE_CAP_SQUARE);
break;
}
aContext->SetMiterLimit(style->mStrokeMiterlimit);
switch (style->mStrokeLinejoin) {
case NS_STYLE_STROKE_LINEJOIN_MITER:
aContext->SetLineJoin(gfxContext::LINE_JOIN_MITER);
break;
case NS_STYLE_STROKE_LINEJOIN_ROUND:
aContext->SetLineJoin(gfxContext::LINE_JOIN_ROUND);
break;
case NS_STYLE_STROKE_LINEJOIN_BEVEL:
aContext->SetLineJoin(gfxContext::LINE_JOIN_BEVEL);
break;
}
AutoFallibleTArray<gfxFloat, 10> dashes;
gfxFloat dashOffset;
@ -1618,7 +1590,13 @@ nsSVGUtils::SetupCairoStroke(nsIFrame* aFrame, gfxContext* aContext,
}
SetupCairoStrokeGeometry(aFrame, aContext, aContextPaint);
return SetupCairoStrokePaint(aFrame, aContext, aContextPaint);
nsRefPtr<gfxPattern> pattern =
MakeStrokePatternFor(aFrame, aContext, aContextPaint);
if (pattern) {
aContext->SetPattern(pattern);
return true;
}
return false;
}
bool

View File

@ -506,25 +506,15 @@ public:
static nscolor GetFallbackOrPaintColor(nsStyleContext *aStyleContext,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke);
/**
* Set up cairo context with an object pattern
*/
static bool SetupContextPaint(gfxContext *aContext,
gfxTextContextPaint *aContextPaint,
const nsStyleSVGPaint& aPaint,
float aOpacity);
static already_AddRefed<gfxPattern>
MakeFillPatternFor(nsIFrame *aFrame,
gfxContext* aContext,
gfxTextContextPaint *aContextPaint = nullptr);
/**
* Sets the current paint on the specified gfxContent to be the SVG 'stroke'
* for the given frame.
*/
static bool SetupCairoStrokePaint(nsIFrame* aFrame, gfxContext* aContext,
gfxTextContextPaint *aContextPaint = nullptr);
static already_AddRefed<gfxPattern>
MakeStrokePatternFor(nsIFrame* aFrame,
gfxContext* aContext,
gfxTextContextPaint *aContextPaint = nullptr);
static float GetOpacity(nsStyleSVGOpacitySource aOpacityType,
const float& aOpacity,
@ -539,13 +529,6 @@ public:
static float GetStrokeWidth(nsIFrame* aFrame,
gfxTextContextPaint *aContextPaint = nullptr);
/*
* Set up a cairo context for measuring the bounding box of a stroked path.
*/
static void SetupCairoStrokeBBoxGeometry(nsIFrame* aFrame,
gfxContext *aContext,
gfxTextContextPaint *aContextPaint = nullptr);
/*
* Set up a cairo context for a stroked path (including any dashing that
* applies).