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