Line data Source code
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 "gfxMatrix.h"
8 : #include "mozilla/dom/SVGAElement.h"
9 : #include "nsAutoPtr.h"
10 : #include "nsIDOMMutationEvent.h"
11 : #include "nsSVGContainerFrame.h"
12 : #include "nsSVGIntegrationUtils.h"
13 : #include "nsSVGUtils.h"
14 : #include "SVGLengthList.h"
15 :
16 : using namespace mozilla;
17 :
18 0 : class nsSVGAFrame : public nsSVGDisplayContainerFrame
19 : {
20 : friend nsIFrame*
21 : NS_NewSVGAFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
22 : protected:
23 0 : explicit nsSVGAFrame(nsStyleContext* aContext)
24 0 : : nsSVGDisplayContainerFrame(aContext, kClassID)
25 0 : {}
26 :
27 : public:
28 0 : NS_DECL_FRAMEARENA_HELPERS(nsSVGAFrame)
29 :
30 : #ifdef DEBUG
31 : virtual void Init(nsIContent* aContent,
32 : nsContainerFrame* aParent,
33 : nsIFrame* aPrevInFlow) override;
34 : #endif
35 :
36 : // nsIFrame:
37 : virtual nsresult AttributeChanged(int32_t aNameSpaceID,
38 : nsIAtom* aAttribute,
39 : int32_t aModType) override;
40 :
41 : #ifdef DEBUG_FRAME_DUMP
42 0 : virtual nsresult GetFrameName(nsAString& aResult) const override
43 : {
44 0 : return MakeFrameName(NS_LITERAL_STRING("SVGA"), aResult);
45 : }
46 : #endif
47 : // nsSVGDisplayableFrame interface:
48 : virtual void NotifySVGChanged(uint32_t aFlags) override;
49 :
50 : // nsSVGContainerFrame methods:
51 : virtual gfxMatrix GetCanvasTM() override;
52 :
53 : private:
54 : nsAutoPtr<gfxMatrix> mCanvasTM;
55 : };
56 :
57 : //----------------------------------------------------------------------
58 : // Implementation
59 :
60 : nsIFrame*
61 0 : NS_NewSVGAFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
62 : {
63 0 : return new (aPresShell) nsSVGAFrame(aContext);
64 : }
65 :
66 0 : NS_IMPL_FRAMEARENA_HELPERS(nsSVGAFrame)
67 :
68 : //----------------------------------------------------------------------
69 : // nsIFrame methods
70 : #ifdef DEBUG
71 : void
72 0 : nsSVGAFrame::Init(nsIContent* aContent,
73 : nsContainerFrame* aParent,
74 : nsIFrame* aPrevInFlow)
75 : {
76 0 : NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::a),
77 : "Trying to construct an SVGAFrame for a "
78 : "content element that doesn't support the right interfaces");
79 :
80 0 : nsSVGDisplayContainerFrame::Init(aContent, aParent, aPrevInFlow);
81 0 : }
82 : #endif /* DEBUG */
83 :
84 : nsresult
85 0 : nsSVGAFrame::AttributeChanged(int32_t aNameSpaceID,
86 : nsIAtom* aAttribute,
87 : int32_t aModType)
88 : {
89 0 : if (aNameSpaceID == kNameSpaceID_None &&
90 0 : aAttribute == nsGkAtoms::transform) {
91 : // We don't invalidate for transform changes (the layers code does that).
92 : // Also note that SVGTransformableElement::GetAttributeChangeHint will
93 : // return nsChangeHint_UpdateOverflow for "transform" attribute changes
94 : // and cause DoApplyRenderingChangeToTree to make the SchedulePaint call.
95 0 : NotifySVGChanged(TRANSFORM_CHANGED);
96 : }
97 :
98 : // Currently our SMIL implementation does not modify the DOM attributes. Once
99 : // we implement the SVG 2 SMIL behaviour this can be removed
100 : // SVGAElement::SetAttr/UnsetAttr's ResetLinkState() call will be sufficient.
101 0 : if (aModType == nsIDOMMutationEvent::SMIL &&
102 0 : aAttribute == nsGkAtoms::href &&
103 0 : (aNameSpaceID == kNameSpaceID_None ||
104 : aNameSpaceID == kNameSpaceID_XLink)) {
105 :
106 0 : dom::SVGAElement* content = static_cast<dom::SVGAElement*>(mContent);
107 :
108 : // SMIL may change whether an <a> element is a link, in which case we will
109 : // need to update the link state.
110 0 : content->ResetLinkState(true, content->ElementHasHref());
111 : }
112 :
113 0 : return NS_OK;
114 : }
115 :
116 : //----------------------------------------------------------------------
117 : // nsSVGDisplayableFrame methods
118 :
119 : void
120 0 : nsSVGAFrame::NotifySVGChanged(uint32_t aFlags)
121 : {
122 0 : MOZ_ASSERT(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED),
123 : "Invalidation logic may need adjusting");
124 :
125 0 : if (aFlags & TRANSFORM_CHANGED) {
126 : // make sure our cached transform matrix gets (lazily) updated
127 0 : mCanvasTM = nullptr;
128 : }
129 :
130 0 : nsSVGDisplayContainerFrame::NotifySVGChanged(aFlags);
131 0 : }
132 :
133 : //----------------------------------------------------------------------
134 : // nsSVGContainerFrame methods:
135 :
136 : gfxMatrix
137 0 : nsSVGAFrame::GetCanvasTM()
138 : {
139 0 : if (!mCanvasTM) {
140 0 : NS_ASSERTION(GetParent(), "null parent");
141 :
142 0 : nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(GetParent());
143 0 : dom::SVGAElement *content = static_cast<dom::SVGAElement*>(mContent);
144 :
145 0 : gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM());
146 :
147 0 : mCanvasTM = new gfxMatrix(tm);
148 : }
149 :
150 0 : return *mCanvasTM;
151 : }
|