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
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/
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
15 * The Original Code is the Mozilla SVG project.
17 * The Initial Developer of the Original Code is IBM Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2006
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #include "nsSVGContainerFrame.h"
38 #include "nsSVGUtils.h"
39 #include "nsSVGOuterSVGFrame.h"
41 //----------------------------------------------------------------------
42 // nsISupports methods
44 NS_INTERFACE_MAP_BEGIN(nsSVGDisplayContainerFrame
)
45 NS_INTERFACE_MAP_ENTRY(nsISVGChildFrame
)
46 NS_INTERFACE_MAP_END_INHERITING(nsSVGContainerFrame
)
49 NS_NewSVGContainerFrame(nsIPresShell
* aPresShell
,
51 nsStyleContext
* aContext
)
53 return new (aPresShell
) nsSVGContainerFrame(aContext
);
57 nsSVGContainerFrame::AppendFrames(nsIAtom
* aListName
,
60 return InsertFrames(aListName
, mFrames
.LastChild(), aFrameList
);
64 nsSVGContainerFrame::InsertFrames(nsIAtom
* aListName
,
68 NS_ASSERTION(!aListName
, "unexpected child list");
69 NS_ASSERTION(!aPrevFrame
|| aPrevFrame
->GetParent() == this,
70 "inserting after sibling frame with different parent");
72 mFrames
.InsertFrames(this, aPrevFrame
, aFrameList
);
78 nsSVGContainerFrame::RemoveFrame(nsIAtom
* aListName
,
81 NS_ASSERTION(!aListName
, "unexpected child list");
83 return mFrames
.DestroyFrame(aOldFrame
) ? NS_OK
: NS_ERROR_FAILURE
;
87 nsSVGContainerFrame::Init(nsIContent
* aContent
,
89 nsIFrame
* aPrevInFlow
)
91 AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD
| NS_STATE_SVG_PROPAGATE_TRANSFORM
);
92 nsresult rv
= nsSVGContainerFrameBase::Init(aContent
, aParent
, aPrevInFlow
);
97 nsSVGDisplayContainerFrame::Init(nsIContent
* aContent
,
99 nsIFrame
* aPrevInFlow
)
101 AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM
);
102 if (!(GetStateBits() & NS_STATE_IS_OUTER_SVG
)) {
103 AddStateBits(aParent
->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD
);
105 nsresult rv
= nsSVGContainerFrameBase::Init(aContent
, aParent
, aPrevInFlow
);
110 nsSVGDisplayContainerFrame::InsertFrames(nsIAtom
* aListName
,
111 nsIFrame
* aPrevFrame
,
112 nsIFrame
* aFrameList
)
114 // memorize last new frame
115 nsIFrame
* lastNewFrame
= nsnull
;
117 nsFrameList
tmpList(aFrameList
);
118 lastNewFrame
= tmpList
.LastChild();
121 // Insert the new frames
122 nsSVGContainerFrame::InsertFrames(aListName
, aPrevFrame
, aFrameList
);
124 // Call InitialUpdate on the new frames ONLY if our nsSVGOuterSVGFrame has had
125 // its initial reflow (our NS_FRAME_FIRST_REFLOW bit is clear) - bug 399863.
126 if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW
)) {
127 nsIFrame
* end
= nsnull
;
129 end
= lastNewFrame
->GetNextSibling();
131 for (nsIFrame
* kid
= aFrameList
; kid
!= end
;
132 kid
= kid
->GetNextSibling()) {
133 nsISVGChildFrame
* SVGFrame
= nsnull
;
134 CallQueryInterface(kid
, &SVGFrame
);
136 SVGFrame
->InitialUpdate();
145 nsSVGDisplayContainerFrame::RemoveFrame(nsIAtom
* aListName
,
148 nsSVGUtils::InvalidateCoveredRegion(aOldFrame
);
150 nsresult rv
= nsSVGContainerFrame::RemoveFrame(aListName
, aOldFrame
);
152 if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD
)) {
153 nsSVGUtils::NotifyAncestorsOfFilterRegionChange(this);
159 //----------------------------------------------------------------------
160 // nsISVGChildFrame methods
163 nsSVGDisplayContainerFrame::PaintSVG(nsSVGRenderState
* aContext
,
164 const nsIntRect
*aDirtyRect
)
166 const nsStyleDisplay
*display
= mStyleContext
->GetStyleDisplay();
167 if (display
->mOpacity
== 0.0)
170 for (nsIFrame
* kid
= mFrames
.FirstChild(); kid
;
171 kid
= kid
->GetNextSibling()) {
172 nsSVGUtils::PaintFrameWithEffects(aContext
, aDirtyRect
, kid
);
178 NS_IMETHODIMP_(nsIFrame
*)
179 nsSVGDisplayContainerFrame::GetFrameForPoint(const nsPoint
&aPoint
)
181 return nsSVGUtils::HitTestChildren(this, aPoint
);
184 NS_IMETHODIMP_(nsRect
)
185 nsSVGDisplayContainerFrame::GetCoveredRegion()
187 return nsSVGUtils::GetCoveredRegion(mFrames
);
191 nsSVGDisplayContainerFrame::UpdateCoveredRegion()
193 for (nsIFrame
* kid
= mFrames
.FirstChild(); kid
;
194 kid
= kid
->GetNextSibling()) {
195 nsISVGChildFrame
* SVGFrame
= nsnull
;
196 CallQueryInterface(kid
, &SVGFrame
);
198 SVGFrame
->UpdateCoveredRegion();
205 nsSVGDisplayContainerFrame::InitialUpdate()
207 NS_ASSERTION(GetStateBits() & NS_FRAME_FIRST_REFLOW
,
208 "Yikes! We've been called already! Hopefully we weren't called "
209 "before our nsSVGOuterSVGFrame's initial Reflow()!!!");
211 for (nsIFrame
* kid
= mFrames
.FirstChild(); kid
;
212 kid
= kid
->GetNextSibling()) {
213 nsISVGChildFrame
* SVGFrame
= nsnull
;
214 CallQueryInterface(kid
, &SVGFrame
);
216 SVGFrame
->InitialUpdate();
220 NS_ASSERTION(!(mState
& NS_FRAME_IN_REFLOW
),
221 "We don't actually participate in reflow");
223 // Do unset the various reflow bits, though.
224 mState
&= ~(NS_FRAME_FIRST_REFLOW
| NS_FRAME_IS_DIRTY
|
225 NS_FRAME_HAS_DIRTY_CHILDREN
);
231 nsSVGDisplayContainerFrame::NotifySVGChanged(PRUint32 aFlags
)
233 NS_ASSERTION(aFlags
& (TRANSFORM_CHANGED
| COORD_CONTEXT_CHANGED
),
234 "Invalidation logic may need adjusting");
236 nsSVGUtils::NotifyChildrenOfSVGChange(this, aFlags
);
240 nsSVGDisplayContainerFrame::NotifyRedrawSuspended()
242 for (nsIFrame
* kid
= mFrames
.FirstChild(); kid
;
243 kid
= kid
->GetNextSibling()) {
244 nsISVGChildFrame
* SVGFrame
=nsnull
;
245 CallQueryInterface(kid
, &SVGFrame
);
247 SVGFrame
->NotifyRedrawSuspended();
254 nsSVGDisplayContainerFrame::NotifyRedrawUnsuspended()
256 for (nsIFrame
* kid
= mFrames
.FirstChild(); kid
;
257 kid
= kid
->GetNextSibling()) {
258 nsISVGChildFrame
* SVGFrame
= nsnull
;
259 CallQueryInterface(kid
, &SVGFrame
);
261 SVGFrame
->NotifyRedrawUnsuspended();
268 nsSVGDisplayContainerFrame::GetBBox(nsIDOMSVGRect
**_retval
)
270 return nsSVGUtils::GetBBox(&mFrames
, _retval
);
274 nsSVGDisplayContainerFrame::SetMatrixPropagation(PRBool aPropagate
)
277 AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM
);
279 RemoveStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM
);
285 nsSVGDisplayContainerFrame::GetMatrixPropagation()
287 return (GetStateBits() & NS_STATE_SVG_PROPAGATE_TRANSFORM
) != 0;