1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is the Mozilla SVG project.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Robert Longson
19 : * Portions created by the Initial Developer are Copyright (C) 2007
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Robert Longson <longsonr@gmail.com> (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsSVGGFrame.h"
40 : #include "nsSVGSwitchElement.h"
41 : #include "gfxRect.h"
42 : #include "gfxMatrix.h"
43 :
44 : class nsRenderingContext;
45 :
46 : typedef nsSVGGFrame nsSVGSwitchFrameBase;
47 :
48 : class nsSVGSwitchFrame : public nsSVGSwitchFrameBase
49 0 : {
50 : friend nsIFrame*
51 : NS_NewSVGSwitchFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
52 : protected:
53 0 : nsSVGSwitchFrame(nsStyleContext* aContext) :
54 0 : nsSVGSwitchFrameBase(aContext) {}
55 :
56 : public:
57 : NS_DECL_FRAMEARENA_HELPERS
58 :
59 : #ifdef DEBUG
60 : NS_IMETHOD Init(nsIContent* aContent,
61 : nsIFrame* aParent,
62 : nsIFrame* aPrevInFlow);
63 : #endif
64 :
65 : /**
66 : * Get the "type" of the frame
67 : *
68 : * @see nsGkAtoms::svgSwitchFrame
69 : */
70 : virtual nsIAtom* GetType() const;
71 :
72 : #ifdef DEBUG
73 0 : NS_IMETHOD GetFrameName(nsAString& aResult) const
74 : {
75 0 : return MakeFrameName(NS_LITERAL_STRING("SVGSwitch"), aResult);
76 : }
77 : #endif
78 :
79 : // nsISVGChildFrame interface:
80 : NS_IMETHOD PaintSVG(nsRenderingContext* aContext, const nsIntRect *aDirtyRect);
81 : NS_IMETHODIMP_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
82 : NS_IMETHODIMP_(nsRect) GetCoveredRegion();
83 : NS_IMETHOD UpdateCoveredRegion();
84 : NS_IMETHOD InitialUpdate();
85 : virtual void NotifyRedrawUnsuspended();
86 : virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
87 : PRUint32 aFlags);
88 :
89 : private:
90 : nsIFrame *GetActiveChildFrame();
91 : };
92 :
93 : //----------------------------------------------------------------------
94 : // Implementation
95 :
96 : nsIFrame*
97 0 : NS_NewSVGSwitchFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
98 : {
99 0 : return new (aPresShell) nsSVGSwitchFrame(aContext);
100 : }
101 :
102 0 : NS_IMPL_FRAMEARENA_HELPERS(nsSVGSwitchFrame)
103 :
104 : #ifdef DEBUG
105 : NS_IMETHODIMP
106 0 : nsSVGSwitchFrame::Init(nsIContent* aContent,
107 : nsIFrame* aParent,
108 : nsIFrame* aPrevInFlow)
109 : {
110 0 : nsCOMPtr<nsIDOMSVGSwitchElement> svgSwitch = do_QueryInterface(aContent);
111 0 : NS_ASSERTION(svgSwitch, "Content is not an SVG switch\n");
112 :
113 0 : return nsSVGSwitchFrameBase::Init(aContent, aParent, aPrevInFlow);
114 : }
115 : #endif /* DEBUG */
116 :
117 : nsIAtom *
118 0 : nsSVGSwitchFrame::GetType() const
119 : {
120 0 : return nsGkAtoms::svgSwitchFrame;
121 : }
122 :
123 : NS_IMETHODIMP
124 0 : nsSVGSwitchFrame::PaintSVG(nsRenderingContext* aContext,
125 : const nsIntRect *aDirtyRect)
126 : {
127 0 : const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
128 0 : if (display->mOpacity == 0.0)
129 0 : return NS_OK;
130 :
131 0 : nsIFrame *kid = GetActiveChildFrame();
132 0 : if (kid) {
133 0 : nsSVGUtils::PaintFrameWithEffects(aContext, aDirtyRect, kid);
134 : }
135 0 : return NS_OK;
136 : }
137 :
138 :
139 : NS_IMETHODIMP_(nsIFrame*)
140 0 : nsSVGSwitchFrame::GetFrameForPoint(const nsPoint &aPoint)
141 : {
142 0 : nsIFrame *kid = GetActiveChildFrame();
143 0 : if (kid) {
144 0 : nsISVGChildFrame* svgFrame = do_QueryFrame(kid);
145 0 : if (svgFrame) {
146 0 : return svgFrame->GetFrameForPoint(aPoint);
147 : }
148 : }
149 :
150 0 : return nsnull;
151 : }
152 :
153 : NS_IMETHODIMP_(nsRect)
154 0 : nsSVGSwitchFrame::GetCoveredRegion()
155 : {
156 0 : nsRect rect;
157 :
158 0 : nsIFrame *kid = GetActiveChildFrame();
159 0 : if (kid) {
160 0 : nsISVGChildFrame* child = do_QueryFrame(kid);
161 0 : if (child) {
162 0 : rect = child->GetCoveredRegion();
163 : }
164 : }
165 : return rect;
166 : }
167 :
168 : NS_IMETHODIMP
169 0 : nsSVGSwitchFrame::UpdateCoveredRegion()
170 : {
171 0 : static_cast<nsSVGSwitchElement*>(mContent)->UpdateActiveChild();
172 :
173 0 : nsIFrame *kid = GetActiveChildFrame();
174 0 : if (kid) {
175 0 : nsISVGChildFrame* child = do_QueryFrame(kid);
176 0 : if (child) {
177 0 : child->UpdateCoveredRegion();
178 : }
179 : }
180 0 : return NS_OK;
181 : }
182 :
183 : NS_IMETHODIMP
184 0 : nsSVGSwitchFrame::InitialUpdate()
185 : {
186 0 : nsSVGUtils::UpdateGraphic(this);
187 :
188 0 : return nsSVGSwitchFrameBase::InitialUpdate();
189 : }
190 :
191 : void
192 0 : nsSVGSwitchFrame::NotifyRedrawUnsuspended()
193 : {
194 0 : RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
195 :
196 0 : if (GetStateBits() & NS_STATE_SVG_DIRTY)
197 0 : nsSVGUtils::UpdateGraphic(this);
198 :
199 0 : nsSVGSwitchFrameBase::NotifyRedrawUnsuspended();
200 0 : }
201 :
202 : gfxRect
203 0 : nsSVGSwitchFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
204 : PRUint32 aFlags)
205 : {
206 0 : nsIFrame* kid = GetActiveChildFrame();
207 0 : nsISVGChildFrame* svgKid = do_QueryFrame(kid);
208 0 : if (svgKid) {
209 0 : nsIContent *content = kid->GetContent();
210 0 : gfxMatrix transform = aToBBoxUserspace;
211 0 : if (content->IsSVG()) {
212 : transform = static_cast<nsSVGElement*>(content)->
213 0 : PrependLocalTransformsTo(aToBBoxUserspace);
214 : }
215 0 : return svgKid->GetBBoxContribution(transform, aFlags);
216 : }
217 0 : return gfxRect(0.0, 0.0, 0.0, 0.0);
218 : }
219 :
220 : nsIFrame *
221 0 : nsSVGSwitchFrame::GetActiveChildFrame()
222 : {
223 : nsIContent *activeChild =
224 0 : static_cast<nsSVGSwitchElement*>(mContent)->GetActiveChild();
225 :
226 0 : if (activeChild) {
227 0 : for (nsIFrame* kid = mFrames.FirstChild(); kid;
228 : kid = kid->GetNextSibling()) {
229 :
230 0 : if (activeChild == kid->GetContent()) {
231 0 : return kid;
232 : }
233 : }
234 : }
235 0 : return nsnull;
236 : }
|