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 // Keep in (case-insensitive) order:
7 #include "nsFrame.h"
8 #include "nsGkAtoms.h"
9 #include "nsSVGOuterSVGFrame.h"
10 #include "mozilla/dom/SVGSVGElement.h"
11 #include "mozilla/dom/SVGViewElement.h"
12
13 using namespace mozilla::dom;
14
15 /**
16 * While views are not directly rendered in SVG they can be linked to
17 * and thereby override attributes of an <svg> element via a fragment
18 * identifier. The SVGViewFrame class passes on any attribute changes
19 * the view receives to the overridden <svg> element (if there is one).
20 **/
21 class SVGViewFrame : public nsFrame
22 {
23 friend nsIFrame*
24 NS_NewSVGViewFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
25 protected:
SVGViewFrame(nsStyleContext * aContext)26 explicit SVGViewFrame(nsStyleContext* aContext)
27 : nsFrame(aContext)
28 {
29 AddStateBits(NS_FRAME_IS_NONDISPLAY);
30 }
31
32 public:
33 NS_DECL_FRAMEARENA_HELPERS
34
35 #ifdef DEBUG
36 virtual void Init(nsIContent* aContent,
37 nsContainerFrame* aParent,
38 nsIFrame* aPrevInFlow) override;
39 #endif
40
IsFrameOfType(uint32_t aFlags) const41 virtual bool IsFrameOfType(uint32_t aFlags) const override
42 {
43 return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
44 }
45
46 #ifdef DEBUG_FRAME_DUMP
GetFrameName(nsAString & aResult) const47 virtual nsresult GetFrameName(nsAString& aResult) const override
48 {
49 return MakeFrameName(NS_LITERAL_STRING("SVGView"), aResult);
50 }
51 #endif
52
53 /**
54 * Get the "type" of the frame
55 *
56 * @see nsGkAtoms::svgFELeafFrame
57 */
58 virtual nsIAtom* GetType() const override;
59
60 virtual nsresult AttributeChanged(int32_t aNameSpaceID,
61 nsIAtom* aAttribute,
62 int32_t aModType) override;
63
ComputeCustomOverflow(nsOverflowAreas & aOverflowAreas)64 virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override {
65 // We don't maintain a visual overflow rect
66 return false;
67 }
68 };
69
70 nsIFrame*
NS_NewSVGViewFrame(nsIPresShell * aPresShell,nsStyleContext * aContext)71 NS_NewSVGViewFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
72 {
73 return new (aPresShell) SVGViewFrame(aContext);
74 }
75
NS_IMPL_FRAMEARENA_HELPERS(SVGViewFrame)76 NS_IMPL_FRAMEARENA_HELPERS(SVGViewFrame)
77
78 #ifdef DEBUG
79 void
80 SVGViewFrame::Init(nsIContent* aContent,
81 nsContainerFrame* aParent,
82 nsIFrame* aPrevInFlow)
83 {
84 NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::view),
85 "Content is not an SVG view");
86
87 nsFrame::Init(aContent, aParent, aPrevInFlow);
88 }
89 #endif /* DEBUG */
90
91 nsIAtom *
GetType() const92 SVGViewFrame::GetType() const
93 {
94 return nsGkAtoms::svgViewFrame;
95 }
96
97 nsresult
AttributeChanged(int32_t aNameSpaceID,nsIAtom * aAttribute,int32_t aModType)98 SVGViewFrame::AttributeChanged(int32_t aNameSpaceID,
99 nsIAtom* aAttribute,
100 int32_t aModType)
101 {
102 // Ignore zoomAndPan as it does not cause the <svg> element to re-render
103
104 if (aNameSpaceID == kNameSpaceID_None &&
105 (aAttribute == nsGkAtoms::preserveAspectRatio ||
106 aAttribute == nsGkAtoms::viewBox ||
107 aAttribute == nsGkAtoms::viewTarget)) {
108
109 nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
110 NS_ASSERTION(outerSVGFrame->GetContent()->IsSVGElement(nsGkAtoms::svg),
111 "Expecting an <svg> element");
112
113 SVGSVGElement* svgElement =
114 static_cast<SVGSVGElement*>(outerSVGFrame->GetContent());
115
116 nsAutoString viewID;
117 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, viewID);
118
119 if (svgElement->IsOverriddenBy(viewID)) {
120 // We're the view that's providing overrides, so pretend that the frame
121 // we're overriding was updated.
122 outerSVGFrame->AttributeChanged(aNameSpaceID, aAttribute, aModType);
123 }
124 }
125
126 return nsFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
127 }
128