From 7c2f3f1ed010f6a297a7e55b540907e30a7dd2c7 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 29 Sep 2014 14:12:06 +0100 Subject: [PATCH] Bug 1073012 , part 2 - Replace nsSVGUtils::SetupCairoStrokePaint with a helper that returns a gfxPattern. r=longsonr --- layout/svg/nsFilterInstance.cpp | 10 +- layout/svg/nsSVGPathGeometryFrame.cpp | 1 - layout/svg/nsSVGUtils.cpp | 196 ++++++++++++-------------- layout/svg/nsSVGUtils.h | 25 +--- 4 files changed, 98 insertions(+), 134 deletions(-) diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp index c8ea52d4e369..1b9659278e0c 100644 --- a/layout/svg/nsFilterInstance.cpp +++ b/layout/svg/nsFilterInstance.cpp @@ -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 strokePattern = + nsSVGUtils::MakeStrokePatternFor(mTargetFrame, gfx); + if (strokePattern) { + gfx->SetPattern(strokePattern); + gfx->Fill(); // yes, filling a primitive subregion with _stroke_ paint + } } gfx->Restore(); } diff --git a/layout/svg/nsSVGPathGeometryFrame.cpp b/layout/svg/nsSVGPathGeometryFrame.cpp index 4f6102563f13..71a6758a138a 100644 --- a/layout/svg/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/nsSVGPathGeometryFrame.cpp @@ -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); } diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index bf7327fca192..b4f57b505777 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -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 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 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 +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 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& 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 dashes; gfxFloat dashOffset; @@ -1618,7 +1590,13 @@ nsSVGUtils::SetupCairoStroke(nsIFrame* aFrame, gfxContext* aContext, } SetupCairoStrokeGeometry(aFrame, aContext, aContextPaint); - return SetupCairoStrokePaint(aFrame, aContext, aContextPaint); + nsRefPtr pattern = + MakeStrokePatternFor(aFrame, aContext, aContextPaint); + if (pattern) { + aContext->SetPattern(pattern); + return true; + } + return false; } bool diff --git a/layout/svg/nsSVGUtils.h b/layout/svg/nsSVGUtils.h index d21eefb5f004..4d0d53274d23 100644 --- a/layout/svg/nsSVGUtils.h +++ b/layout/svg/nsSVGUtils.h @@ -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 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 + 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).