diff --git a/layout/svg/SVGGeometryFrame.cpp b/layout/svg/SVGGeometryFrame.cpp index daa7526c74b0..e60bf1950271 100644 --- a/layout/svg/SVGGeometryFrame.cpp +++ b/layout/svg/SVGGeometryFrame.cpp @@ -641,34 +641,23 @@ SVGGeometryFrame::GetBBoxContribution(const Matrix &aToBBoxUserspace, // Account for markers: if ((aFlags & nsSVGUtils::eBBoxIncludeMarkers) != 0 && - static_cast(GetContent())->IsMarkable()) { - - float strokeWidth = nsSVGUtils::GetStrokeWidth(this); - MarkerProperties properties = GetMarkerProperties(this); - - if (properties.MarkersExist()) { + element->IsMarkable()) { + nsSVGMarkerFrame* markerFrames[nsSVGMark::eTypeCount]; + if (SVGObserverUtils::GetMarkerFrames(this, &markerFrames)) { nsTArray marks; - static_cast(GetContent())->GetMarkPoints(&marks); - uint32_t num = marks.Length(); - - // These are in the same order as the nsSVGMark::Type constants. - nsSVGMarkerFrame* markerFrames[] = { - properties.GetMarkerStartFrame(), - properties.GetMarkerMidFrame(), - properties.GetMarkerEndFrame(), - }; - static_assert(MOZ_ARRAY_LENGTH(markerFrames) == nsSVGMark::eTypeCount, - "Number of Marker frames should be equal to eTypeCount"); - - for (uint32_t i = 0; i < num; i++) { - const nsSVGMark& mark = marks[i]; - nsSVGMarkerFrame* frame = markerFrames[mark.type]; - if (frame) { - SVGBBox mbbox = - frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this, - mark, strokeWidth); - MOZ_ASSERT(mbbox.IsFinite(), "bbox is about to go bad"); - bbox.UnionEdges(mbbox); + element->GetMarkPoints(&marks); + if (uint32_t num = marks.Length()) { + float strokeWidth = nsSVGUtils::GetStrokeWidth(this); + for (uint32_t i = 0; i < num; i++) { + const nsSVGMark& mark = marks[i]; + nsSVGMarkerFrame* frame = markerFrames[mark.type]; + if (frame) { + SVGBBox mbbox = + frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this, + mark, strokeWidth); + MOZ_ASSERT(mbbox.IsFinite(), "bbox is about to go bad"); + bbox.UnionEdges(mbbox); + } } } } @@ -691,57 +680,6 @@ SVGGeometryFrame::GetCanvasTM() return content->PrependLocalTransformsTo(parent->GetCanvasTM()); } -SVGGeometryFrame::MarkerProperties -SVGGeometryFrame::GetMarkerProperties(SVGGeometryFrame *aFrame) -{ - NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation"); - - MarkerProperties result; - RefPtr markerURL = - SVGObserverUtils::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerStart); - result.mMarkerStart = - SVGObserverUtils::GetMarkerProperty(markerURL, aFrame, - SVGObserverUtils::MarkerStartProperty()); - - markerURL = SVGObserverUtils::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerMid); - result.mMarkerMid = - SVGObserverUtils::GetMarkerProperty(markerURL, aFrame, - SVGObserverUtils::MarkerMidProperty()); - - markerURL = SVGObserverUtils::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerEnd); - result.mMarkerEnd = - SVGObserverUtils::GetMarkerProperty(markerURL, aFrame, - SVGObserverUtils::MarkerEndProperty()); - return result; -} - -nsSVGMarkerFrame * -SVGGeometryFrame::MarkerProperties::GetMarkerStartFrame() -{ - if (!mMarkerStart) - return nullptr; - return static_cast( - mMarkerStart->GetReferencedFrame(LayoutFrameType::SVGMarker, nullptr)); -} - -nsSVGMarkerFrame * -SVGGeometryFrame::MarkerProperties::GetMarkerMidFrame() -{ - if (!mMarkerMid) - return nullptr; - return static_cast( - mMarkerMid->GetReferencedFrame(LayoutFrameType::SVGMarker, nullptr)); -} - -nsSVGMarkerFrame * -SVGGeometryFrame::MarkerProperties::GetMarkerEndFrame() -{ - if (!mMarkerEnd) - return nullptr; - return static_cast( - mMarkerEnd->GetReferencedFrame(LayoutFrameType::SVGMarker, nullptr)); -} - void SVGGeometryFrame::Render(gfxContext* aContext, uint32_t aRenderComponents, @@ -866,28 +804,17 @@ SVGGeometryFrame::PaintMarkers(gfxContext& aContext, const gfxMatrix& aTransform, imgDrawingParams& aImgParams) { - SVGContextPaint* contextPaint = SVGContextPaint::GetContextPaint(GetContent()); - if (static_cast(GetContent())->IsMarkable()) { - MarkerProperties properties = GetMarkerProperties(this); - - if (properties.MarkersExist()) { - float strokeWidth = nsSVGUtils::GetStrokeWidth(this, contextPaint); + auto element = static_cast(GetContent()); + if (element->IsMarkable()) { + nsSVGMarkerFrame* markerFrames[nsSVGMark::eTypeCount]; + if (SVGObserverUtils::GetMarkerFrames(this, &markerFrames)) { nsTArray marks; - static_cast - (GetContent())->GetMarkPoints(&marks); - - uint32_t num = marks.Length(); - if (num) { - // These are in the same order as the nsSVGMark::Type constants. - nsSVGMarkerFrame* markerFrames[] = { - properties.GetMarkerStartFrame(), - properties.GetMarkerMidFrame(), - properties.GetMarkerEndFrame(), - }; - static_assert(MOZ_ARRAY_LENGTH(markerFrames) == nsSVGMark::eTypeCount, - "Number of Marker frames should be equal to eTypeCount"); - + element->GetMarkPoints(&marks); + if (uint32_t num = marks.Length()) { + SVGContextPaint* contextPaint = + SVGContextPaint::GetContextPaint(GetContent()); + float strokeWidth = nsSVGUtils::GetStrokeWidth(this, contextPaint); for (uint32_t i = 0; i < num; i++) { const nsSVGMark& mark = marks[i]; nsSVGMarkerFrame* frame = markerFrames[mark.type]; diff --git a/layout/svg/SVGGeometryFrame.h b/layout/svg/SVGGeometryFrame.h index b7e733f6ce39..f5100dc5c7f7 100644 --- a/layout/svg/SVGGeometryFrame.h +++ b/layout/svg/SVGGeometryFrame.h @@ -129,25 +129,6 @@ private: */ void PaintMarkers(gfxContext& aContext, const gfxMatrix& aMatrix, imgDrawingParams& aImgParams); - - struct MarkerProperties { - SVGMarkerObserver* mMarkerStart; - SVGMarkerObserver* mMarkerMid; - SVGMarkerObserver* mMarkerEnd; - - bool MarkersExist() const { - return mMarkerStart || mMarkerMid || mMarkerEnd; - } - - nsSVGMarkerFrame *GetMarkerStartFrame(); - nsSVGMarkerFrame *GetMarkerMidFrame(); - nsSVGMarkerFrame *GetMarkerEndFrame(); - }; - - /** - * @param aFrame should be the first continuation - */ - static MarkerProperties GetMarkerProperties(SVGGeometryFrame *aFrame); }; } // namespace mozilla diff --git a/layout/svg/SVGObserverUtils.cpp b/layout/svg/SVGObserverUtils.cpp index 9f62aa0ee18d..4ca5f5733614 100644 --- a/layout/svg/SVGObserverUtils.cpp +++ b/layout/svg/SVGObserverUtils.cpp @@ -572,14 +572,37 @@ GetEffectProperty(URLAndReferrerInfo* aURI, nsIFrame* aFrame, return prop; } -SVGMarkerObserver* -SVGObserverUtils::GetMarkerProperty(URLAndReferrerInfo* aURI, nsIFrame* aFrame, - const mozilla::FramePropertyDescriptor* aProperty) +bool +SVGObserverUtils::GetMarkerFrames(nsIFrame* aMarkedFrame, + nsSVGMarkerFrame*(*aFrames)[3]) { - MOZ_ASSERT(aFrame->IsSVGGeometryFrame() && - static_cast(aFrame->GetContent())->IsMarkable(), + MOZ_ASSERT(!aMarkedFrame->GetPrevContinuation() && + aMarkedFrame->IsSVGGeometryFrame() && + static_cast(aMarkedFrame->GetContent())->IsMarkable(), "Bad frame"); - return GetEffectProperty(aURI, aFrame, aProperty); + + bool foundMarker = false; + RefPtr markerURL; + SVGMarkerObserver* observer; + nsIFrame* marker; + +#define GET_MARKER(type) \ + markerURL = GetMarkerURI(aMarkedFrame, &nsStyleSVG::mMarker##type); \ + observer = GetEffectProperty(markerURL, aMarkedFrame, \ + SVGObserverUtils::Marker##type##Property()); \ + marker = observer ? \ + observer->GetReferencedFrame(LayoutFrameType::SVGMarker, nullptr) :\ + nullptr; \ + foundMarker = foundMarker || bool(marker); \ + (*aFrames)[nsSVGMark::e##type] = static_cast(marker); + + GET_MARKER(Start) + GET_MARKER(Mid) + GET_MARKER(End) + +#undef GET_MARKER + + return foundMarker; } SVGGeometryElement* @@ -833,11 +856,11 @@ SVGObserverUtils::UpdateEffects(nsIFrame* aFrame) // Set marker properties here to avoid reference loops RefPtr markerURL = GetMarkerURI(aFrame, &nsStyleSVG::mMarkerStart); - GetMarkerProperty(markerURL, aFrame, MarkerStartProperty()); + GetEffectProperty(markerURL, aFrame, MarkerStartProperty()); markerURL = GetMarkerURI(aFrame, &nsStyleSVG::mMarkerMid); - GetMarkerProperty(markerURL, aFrame, MarkerMidProperty()); + GetEffectProperty(markerURL, aFrame, MarkerMidProperty()); markerURL = GetMarkerURI(aFrame, &nsStyleSVG::mMarkerEnd); - GetMarkerProperty(markerURL, aFrame, MarkerEndProperty()); + GetEffectProperty(markerURL, aFrame, MarkerEndProperty()); } } diff --git a/layout/svg/SVGObserverUtils.h b/layout/svg/SVGObserverUtils.h index f34b95204b91..027a7299f325 100644 --- a/layout/svg/SVGObserverUtils.h +++ b/layout/svg/SVGObserverUtils.h @@ -28,6 +28,7 @@ class nsAtom; class nsIPresShell; class nsIURI; class nsSVGClipPathFrame; +class nsSVGMarkerFrame; class nsSVGPaintServerFrame; class nsSVGFilterFrame; class nsSVGMaskFrame; @@ -688,11 +689,12 @@ public: nsStyleSVGPaint nsStyleSVG::* aPaint); /** - * Get an SVGMarkerObserver for the frame, creating a fresh one if necessary + * Get the start/mid/end-markers for the given frame, and add the frame as + * an observer to those markers. Returns true if at least one marker type is + * found, false otherwise. */ - static SVGMarkerObserver * - GetMarkerProperty(URLAndReferrerInfo* aURI, nsIFrame* aFrame, - const mozilla::FramePropertyDescriptor* aProperty); + static bool + GetMarkerFrames(nsIFrame* aMarkedFrame, nsSVGMarkerFrame*(*aFrames)[3]); /** * Get the SVGGeometryElement that is referenced by aTextPathFrame, and make