diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index aef962a31bdb..9e8f16e9be95 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -3671,10 +3671,16 @@ SVGTextFrame::PaintSVG(nsRenderingContext* aContext, gfxTextContextPaint *outerContextPaint = (gfxTextContextPaint*)aContext->GetDrawTarget()->GetUserData(&gfxTextContextPaint::sUserDataKey); - nsAutoPtr contextPaint; + SVGTextContextPaint contextPaint; DrawMode drawMode = - SetupCairoState(gfx, frame, outerContextPaint, - getter_Transfers(contextPaint)); + SetupContextPaint(gfx->CurrentMatrix(), frame, outerContextPaint, + &contextPaint); + + if (int(drawMode) & int(DrawMode::GLYPH_STROKE)) { + // This may change the gfxContext's transform (for non-scaling stroke), + // in which case this needs to happen before we call SetMatrix() below. + nsSVGUtils::SetupCairoStrokeGeometry(frame, gfx, outerContextPaint); + } // Set up the transform for painting the text frame for the substring // indicated by the run. @@ -3691,10 +3697,10 @@ SVGTextFrame::PaintSVG(nsRenderingContext* aContext, matrixForPaintServers, paintSVGGlyphs); frame->PaintText(aContext, nsPoint(), frameRect, item, - contextPaint, &callbacks); + &contextPaint, &callbacks); } else { frame->PaintText(aContext, nsPoint(), frameRect, item, - contextPaint, nullptr); + &contextPaint, nullptr); } } @@ -5566,109 +5572,102 @@ SVGTextFrame::TransformFrameRectFromTextChild(const nsRect& aRect, return result - framePosition; } -DrawMode -SVGTextFrame::SetupCairoState(gfxContext* aContext, - nsIFrame* aFrame, - gfxTextContextPaint* aOuterContextPaint, - gfxTextContextPaint** aThisContextPaint) -{ - DrawMode toDraw = DrawMode(0); - SVGTextContextPaint *thisContextPaint = new SVGTextContextPaint(); - - if (SetupCairoStroke(aContext, aFrame, aOuterContextPaint, thisContextPaint)) { - toDraw = DrawMode(int(toDraw) | int(DrawMode::GLYPH_STROKE)); - } - - if (SetupCairoFill(aContext, aFrame, aOuterContextPaint, thisContextPaint)) { - toDraw = DrawMode(int(toDraw) | int(DrawMode::GLYPH_FILL)); - } - - *aThisContextPaint = thisContextPaint; - - return toDraw; -} - -bool -SVGTextFrame::SetupCairoStroke(gfxContext* aContext, - nsIFrame* aFrame, - gfxTextContextPaint* aOuterContextPaint, - SVGTextContextPaint* aThisContextPaint) -{ - const nsStyleSVG *style = aFrame->StyleSVG(); - if (style->mStroke.mType == eStyleSVGPaintType_None) { - aThisContextPaint->SetStrokeOpacity(0.0f); - return false; - } - - nsSVGUtils::SetupCairoStrokeGeometry(aFrame, aContext, aOuterContextPaint); - float opacity = nsSVGUtils::GetOpacity(style->mStrokeOpacitySource, - style->mStrokeOpacity, - aOuterContextPaint); - - SetupInheritablePaint(aContext, aFrame, opacity, aOuterContextPaint, - aThisContextPaint->mStrokePaint, &nsStyleSVG::mStroke, - nsSVGEffects::StrokeProperty()); - - aThisContextPaint->SetStrokeOpacity(opacity); - - return opacity != 0.0f; -} - -bool -SVGTextFrame::SetupCairoFill(gfxContext* aContext, - nsIFrame* aFrame, - gfxTextContextPaint* aOuterContextPaint, - SVGTextContextPaint* aThisContextPaint) -{ - const nsStyleSVG *style = aFrame->StyleSVG(); - if (style->mFill.mType == eStyleSVGPaintType_None) { - aThisContextPaint->SetFillOpacity(0.0f); - return false; - } - - float opacity = nsSVGUtils::GetOpacity(style->mFillOpacitySource, - style->mFillOpacity, - aOuterContextPaint); - - SetupInheritablePaint(aContext, aFrame, opacity, aOuterContextPaint, - aThisContextPaint->mFillPaint, &nsStyleSVG::mFill, - nsSVGEffects::FillProperty()); - - aThisContextPaint->SetFillOpacity(opacity); - - return true; -} - -void -SVGTextFrame::SetupInheritablePaint(gfxContext* aContext, - nsIFrame* aFrame, - float& aOpacity, - gfxTextContextPaint* aOuterContextPaint, - SVGTextContextPaint::Paint& aTargetPaint, - nsStyleSVGPaint nsStyleSVG::*aFillOrStroke, - const FramePropertyDescriptor* aProperty) +/** + * Stores in |aTargetPaint| information on how to reconstruct the current + * fill or stroke pattern. Will also set the paint opacity to transparent if + * the paint is set to "none". + * @param aOuterContextPaint pattern information from the outer text context + * @param aTargetPaint where to store the current pattern information + * @param aFillOrStroke member pointer to the paint we are setting up + * @param aProperty the frame property descriptor of the fill or stroke paint + * server frame + */ +static void +SetupInheritablePaint(const gfxMatrix& aContextMatrix, + nsIFrame* aFrame, + float& aOpacity, + gfxTextContextPaint* aOuterContextPaint, + SVGTextContextPaint::Paint& aTargetPaint, + nsStyleSVGPaint nsStyleSVG::*aFillOrStroke, + const FramePropertyDescriptor* aProperty) { const nsStyleSVG *style = aFrame->StyleSVG(); nsSVGPaintServerFrame *ps = nsSVGEffects::GetPaintServer(aFrame, &(style->*aFillOrStroke), aProperty); - if (ps && ps->SetupPaintServer(aContext, aFrame, aFillOrStroke, aOpacity)) { - aTargetPaint.SetPaintServer(aFrame, aContext->CurrentMatrix(), ps); - } else if (nsSVGUtils::SetupContextPaint(aContext, aOuterContextPaint, - style->*aFillOrStroke, - aOpacity)) { - aTargetPaint.SetContextPaint(aOuterContextPaint, (style->*aFillOrStroke).mType); - } else { - nscolor color = nsSVGUtils::GetFallbackOrPaintColor(aContext, - aFrame->StyleContext(), - aFillOrStroke); - aTargetPaint.SetColor(color); - + if (ps) { nsRefPtr 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 * aOpacity)); - aContext->SetPattern(pattern); + ps->GetPaintServerPattern(aFrame, aContextMatrix, aFillOrStroke, aOpacity); + if (pattern) { + aTargetPaint.SetPaintServer(aFrame, aContextMatrix, ps); + return; + } } + if (aOuterContextPaint) { + nsRefPtr pattern; + switch ((style->*aFillOrStroke).mType) { + case eStyleSVGPaintType_ContextFill: + pattern = aOuterContextPaint->GetFillPattern(aOpacity, aContextMatrix); + break; + case eStyleSVGPaintType_ContextStroke: + pattern = aOuterContextPaint->GetStrokePattern(aOpacity, aContextMatrix); + break; + default: + ; + } + if (pattern) { + aTargetPaint.SetContextPaint(aOuterContextPaint, (style->*aFillOrStroke).mType); + return; + } + } + nscolor color = + nsSVGUtils::GetFallbackOrPaintColor(aFrame->StyleContext(), aFillOrStroke); + aTargetPaint.SetColor(color); +} + +DrawMode +SVGTextFrame::SetupContextPaint(const gfxMatrix& aContextMatrix, + nsIFrame* aFrame, + gfxTextContextPaint* aOuterContextPaint, + SVGTextContextPaint* aThisContextPaint) +{ + DrawMode toDraw = DrawMode(0); + + const nsStyleSVG *style = aFrame->StyleSVG(); + + // fill: + if (style->mFill.mType == eStyleSVGPaintType_None) { + aThisContextPaint->SetFillOpacity(0.0f); + } else { + float opacity = nsSVGUtils::GetOpacity(style->mFillOpacitySource, + style->mFillOpacity, + aOuterContextPaint); + + SetupInheritablePaint(aContextMatrix, aFrame, opacity, aOuterContextPaint, + aThisContextPaint->mFillPaint, &nsStyleSVG::mFill, + nsSVGEffects::FillProperty()); + + aThisContextPaint->SetFillOpacity(opacity); + + toDraw = DrawMode(int(toDraw) | int(DrawMode::GLYPH_FILL)); + } + + // stroke: + if (style->mStroke.mType == eStyleSVGPaintType_None) { + aThisContextPaint->SetStrokeOpacity(0.0f); + } else { + float opacity = nsSVGUtils::GetOpacity(style->mStrokeOpacitySource, + style->mStrokeOpacity, + aOuterContextPaint); + + SetupInheritablePaint(aContextMatrix, aFrame, opacity, aOuterContextPaint, + aThisContextPaint->mStrokePaint, &nsStyleSVG::mStroke, + nsSVGEffects::StrokeProperty()); + + aThisContextPaint->SetStrokeOpacity(opacity); + + toDraw = DrawMode(int(toDraw) | int(DrawMode::GLYPH_STROKE)); + } + + return toDraw; } diff --git a/layout/svg/SVGTextFrame.h b/layout/svg/SVGTextFrame.h index d90a5960f344..76ce11854a9a 100644 --- a/layout/svg/SVGTextFrame.h +++ b/layout/svg/SVGTextFrame.h @@ -594,46 +594,10 @@ private: gfxFloat GetOffsetScale(nsIFrame* aTextPathFrame); gfxFloat GetStartOffset(nsIFrame* aTextPathFrame); - DrawMode SetupCairoState(gfxContext* aContext, - nsIFrame* aFrame, - gfxTextContextPaint* aOuterContextPaint, - gfxTextContextPaint** aThisContextPaint); - - /** - * Sets up the stroke style for |aFrame| in |aContext| and stores stroke - * pattern information in |aThisContextPaint|. - */ - bool SetupCairoStroke(gfxContext* aContext, - nsIFrame* aFrame, - gfxTextContextPaint* aOuterContextPaint, - SVGTextContextPaint* aThisContextPaint); - - /** - * Sets up the fill style for |aFrame| in |aContext| and stores fill pattern - * information in |aThisContextPaint|. - */ - bool SetupCairoFill(gfxContext* aContext, - nsIFrame* aFrame, - gfxTextContextPaint* aOuterContextPaint, - SVGTextContextPaint* aThisContextPaint); - - /** - * Stores in |aTargetPaint| information on how to reconstruct the current - * fill or stroke pattern. Will also set the paint opacity to transparent if - * the paint is set to "none". - * @param aOuterContextPaint pattern information from the outer text context - * @param aTargetPaint where to store the current pattern information - * @param aFillOrStroke member pointer to the paint we are setting up - * @param aProperty the frame property descriptor of the fill or stroke paint - * server frame - */ - void SetupInheritablePaint(gfxContext* aContext, + DrawMode SetupContextPaint(const gfxMatrix& aContextMatrix, nsIFrame* aFrame, - float& aOpacity, gfxTextContextPaint* aOuterContextPaint, - SVGTextContextPaint::Paint& aTargetPaint, - nsStyleSVGPaint nsStyleSVG::*aFillOrStroke, - const FramePropertyDescriptor* aProperty); + SVGTextContextPaint* aThisContextPaint); /** * The MutationObserver we have registered for the element subtree. diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index e81272819957..53a705bae7f6 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -1204,7 +1204,7 @@ nsSVGUtils::PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents, // ---------------------------------------------------------------------- /* static */ nscolor -nsSVGUtils::GetFallbackOrPaintColor(gfxContext *aContext, nsStyleContext *aStyleContext, +nsSVGUtils::GetFallbackOrPaintColor(nsStyleContext *aStyleContext, nsStyleSVGPaint nsStyleSVG::*aFillOrStroke) { const nsStyleSVGPaint &paint = aStyleContext->StyleSVG()->*aFillOrStroke; @@ -1238,8 +1238,8 @@ SetupFallbackOrPaintColor(gfxContext *aContext, nsStyleContext *aStyleContext, nsStyleSVGPaint nsStyleSVG::*aFillOrStroke, float aOpacity) { - nscolor color = nsSVGUtils::GetFallbackOrPaintColor( - aContext, aStyleContext, aFillOrStroke); + nscolor color = + nsSVGUtils::GetFallbackOrPaintColor(aStyleContext, aFillOrStroke); aContext->SetColor(gfxRGBA(NS_GET_R(color)/255.0, NS_GET_G(color)/255.0, diff --git a/layout/svg/nsSVGUtils.h b/layout/svg/nsSVGUtils.h index 05ff202624bf..28fc651acd7b 100644 --- a/layout/svg/nsSVGUtils.h +++ b/layout/svg/nsSVGUtils.h @@ -503,8 +503,7 @@ public: std::min(double(INT32_MAX), aVal))); } - static nscolor GetFallbackOrPaintColor(gfxContext *aContext, - nsStyleContext *aStyleContext, + static nscolor GetFallbackOrPaintColor(nsStyleContext *aStyleContext, nsStyleSVGPaint nsStyleSVG::*aFillOrStroke); /**