1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef __NS_SVGMARKERFRAME_H__
8 #define __NS_SVGMARKERFRAME_H__
9 
10 #include "mozilla/Attributes.h"
11 #include "gfxMatrix.h"
12 #include "gfxRect.h"
13 #include "nsFrame.h"
14 #include "nsLiteralString.h"
15 #include "nsQueryFrame.h"
16 #include "nsSVGContainerFrame.h"
17 #include "nsSVGUtils.h"
18 
19 class gfxContext;
20 
21 namespace mozilla {
22 
23 class PresShell;
24 class SVGGeometryFrame;
25 
26 struct SVGMark;
27 
28 namespace dom {
29 class SVGViewportElement;
30 }  // namespace dom
31 }  // namespace mozilla
32 
33 class nsSVGMarkerFrame final : public nsSVGContainerFrame {
34   typedef mozilla::SVGMark SVGMark;
35   typedef mozilla::image::imgDrawingParams imgDrawingParams;
36 
37   friend class nsSVGMarkerAnonChildFrame;
38   friend nsContainerFrame* NS_NewSVGMarkerFrame(mozilla::PresShell* aPresShell,
39                                                 ComputedStyle* aStyle);
40 
41  protected:
nsSVGMarkerFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)42   explicit nsSVGMarkerFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
43       : nsSVGContainerFrame(aStyle, aPresContext, kClassID),
44         mMarkedFrame(nullptr),
45         mInUse(false),
46         mInUse2(false) {
47     AddStateBits(NS_FRAME_IS_NONDISPLAY);
48   }
49 
50  public:
51   NS_DECL_FRAMEARENA_HELPERS(nsSVGMarkerFrame)
52 
53   // nsIFrame interface:
54 #ifdef DEBUG
55   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
56                     nsIFrame* aPrevInFlow) override;
57 #endif
58 
BuildDisplayList(nsDisplayListBuilder * aBuilder,const nsDisplayListSet & aLists)59   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
60                                 const nsDisplayListSet& aLists) override {}
61 
62   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
63                                     int32_t aModType) override;
64 
65 #ifdef DEBUG_FRAME_DUMP
GetFrameName(nsAString & aResult)66   virtual nsresult GetFrameName(nsAString& aResult) const override {
67     return MakeFrameName(NS_LITERAL_STRING("SVGMarker"), aResult);
68   }
69 #endif
70 
GetContentInsertionFrame()71   virtual nsContainerFrame* GetContentInsertionFrame() override {
72     // Any children must be added to our single anonymous inner frame kid.
73     MOZ_ASSERT(
74         PrincipalChildList().FirstChild() &&
75             PrincipalChildList().FirstChild()->IsSVGMarkerAnonChildFrame(),
76         "Where is our anonymous child?");
77     return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
78   }
79 
80   // nsSVGMarkerFrame methods:
81   void PaintMark(gfxContext& aContext, const gfxMatrix& aToMarkedFrameUserSpace,
82                  mozilla::SVGGeometryFrame* aMarkedFrame, const SVGMark& aMark,
83                  float aStrokeWidth, imgDrawingParams& aImgParams);
84 
85   SVGBBox GetMarkBBoxContribution(const Matrix& aToBBoxUserspace,
86                                   uint32_t aFlags,
87                                   mozilla::SVGGeometryFrame* aMarkedFrame,
88                                   const SVGMark& aMark, float aStrokeWidth);
89 
90   // Return our anonymous box child.
91   void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
92 
93  private:
94   // stuff needed for callback
95   mozilla::SVGGeometryFrame* mMarkedFrame;
96   Matrix mMarkerTM;
97 
98   // nsSVGContainerFrame methods:
99   virtual gfxMatrix GetCanvasTM() override;
100 
101   // A helper class to allow us to paint markers safely. The helper
102   // automatically sets and clears the mInUse flag on the marker frame (to
103   // prevent nasty reference loops) as well as the reference to the marked
104   // frame and its coordinate context. It's easy to mess this up
105   // and break things, so this helper makes the code far more robust.
106   class MOZ_RAII AutoMarkerReferencer {
107    public:
108     AutoMarkerReferencer(nsSVGMarkerFrame* aFrame,
109                          mozilla::SVGGeometryFrame* aMarkedFrame
110                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
111     ~AutoMarkerReferencer();
112 
113    private:
114     nsSVGMarkerFrame* mFrame;
115     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
116   };
117 
118   // nsSVGMarkerFrame methods:
119   void SetParentCoordCtxProvider(mozilla::dom::SVGViewportElement* aContext);
120 
121   // recursion prevention flag
122   bool mInUse;
123 
124   // second recursion prevention flag, for GetCanvasTM()
125   bool mInUse2;
126 };
127 
128 ////////////////////////////////////////////////////////////////////////
129 // nsMarkerAnonChildFrame class
130 
131 class nsSVGMarkerAnonChildFrame final : public nsSVGDisplayContainerFrame {
132   friend nsContainerFrame* NS_NewSVGMarkerAnonChildFrame(
133       mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
134 
nsSVGMarkerAnonChildFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)135   explicit nsSVGMarkerAnonChildFrame(ComputedStyle* aStyle,
136                                      nsPresContext* aPresContext)
137       : nsSVGDisplayContainerFrame(aStyle, aPresContext, kClassID) {}
138 
139  public:
140   NS_DECL_FRAMEARENA_HELPERS(nsSVGMarkerAnonChildFrame)
141 
142 #ifdef DEBUG
143   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
144                     nsIFrame* aPrevInFlow) override;
145 #endif
146 
147 #ifdef DEBUG_FRAME_DUMP
GetFrameName(nsAString & aResult)148   virtual nsresult GetFrameName(nsAString& aResult) const override {
149     return MakeFrameName(NS_LITERAL_STRING("SVGMarkerAnonChild"), aResult);
150   }
151 #endif
152 
153   // nsSVGContainerFrame methods:
GetCanvasTM()154   virtual gfxMatrix GetCanvasTM() override {
155     return static_cast<nsSVGMarkerFrame*>(GetParent())->GetCanvasTM();
156   }
157 };
158 #endif
159