Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / svg / base / src / nsSVGContainerFrame.cpp
blobb7b9c6e3d4765e918d860596c33b9eda93d40df6
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
13 * License.
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.
21 * Contributor(s):
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)
48 nsIFrame*
49 NS_NewSVGContainerFrame(nsIPresShell* aPresShell,
50 nsIContent* aContent,
51 nsStyleContext* aContext)
53 return new (aPresShell) nsSVGContainerFrame(aContext);
56 NS_IMETHODIMP
57 nsSVGContainerFrame::AppendFrames(nsIAtom* aListName,
58 nsIFrame* aFrameList)
60 return InsertFrames(aListName, mFrames.LastChild(), aFrameList);
63 NS_IMETHODIMP
64 nsSVGContainerFrame::InsertFrames(nsIAtom* aListName,
65 nsIFrame* aPrevFrame,
66 nsIFrame* aFrameList)
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);
74 return NS_OK;
77 NS_IMETHODIMP
78 nsSVGContainerFrame::RemoveFrame(nsIAtom* aListName,
79 nsIFrame* aOldFrame)
81 NS_ASSERTION(!aListName, "unexpected child list");
83 return mFrames.DestroyFrame(aOldFrame) ? NS_OK : NS_ERROR_FAILURE;
86 NS_IMETHODIMP
87 nsSVGContainerFrame::Init(nsIContent* aContent,
88 nsIFrame* aParent,
89 nsIFrame* aPrevInFlow)
91 AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_PROPAGATE_TRANSFORM);
92 nsresult rv = nsSVGContainerFrameBase::Init(aContent, aParent, aPrevInFlow);
93 return rv;
96 NS_IMETHODIMP
97 nsSVGDisplayContainerFrame::Init(nsIContent* aContent,
98 nsIFrame* aParent,
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);
106 return rv;
109 NS_IMETHODIMP
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;
128 if (lastNewFrame)
129 end = lastNewFrame->GetNextSibling();
131 for (nsIFrame* kid = aFrameList; kid != end;
132 kid = kid->GetNextSibling()) {
133 nsISVGChildFrame* SVGFrame = nsnull;
134 CallQueryInterface(kid, &SVGFrame);
135 if (SVGFrame) {
136 SVGFrame->InitialUpdate();
141 return NS_OK;
144 NS_IMETHODIMP
145 nsSVGDisplayContainerFrame::RemoveFrame(nsIAtom* aListName,
146 nsIFrame* aOldFrame)
148 nsSVGUtils::InvalidateCoveredRegion(aOldFrame);
150 nsresult rv = nsSVGContainerFrame::RemoveFrame(aListName, aOldFrame);
152 if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
153 nsSVGUtils::NotifyAncestorsOfFilterRegionChange(this);
156 return rv;
159 //----------------------------------------------------------------------
160 // nsISVGChildFrame methods
162 NS_IMETHODIMP
163 nsSVGDisplayContainerFrame::PaintSVG(nsSVGRenderState* aContext,
164 const nsIntRect *aDirtyRect)
166 const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
167 if (display->mOpacity == 0.0)
168 return NS_OK;
170 for (nsIFrame* kid = mFrames.FirstChild(); kid;
171 kid = kid->GetNextSibling()) {
172 nsSVGUtils::PaintFrameWithEffects(aContext, aDirtyRect, kid);
175 return NS_OK;
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);
190 NS_IMETHODIMP
191 nsSVGDisplayContainerFrame::UpdateCoveredRegion()
193 for (nsIFrame* kid = mFrames.FirstChild(); kid;
194 kid = kid->GetNextSibling()) {
195 nsISVGChildFrame* SVGFrame = nsnull;
196 CallQueryInterface(kid, &SVGFrame);
197 if (SVGFrame) {
198 SVGFrame->UpdateCoveredRegion();
201 return NS_OK;
204 NS_IMETHODIMP
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);
215 if (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);
227 return NS_OK;
230 void
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);
239 NS_IMETHODIMP
240 nsSVGDisplayContainerFrame::NotifyRedrawSuspended()
242 for (nsIFrame* kid = mFrames.FirstChild(); kid;
243 kid = kid->GetNextSibling()) {
244 nsISVGChildFrame* SVGFrame=nsnull;
245 CallQueryInterface(kid, &SVGFrame);
246 if (SVGFrame) {
247 SVGFrame->NotifyRedrawSuspended();
250 return NS_OK;
253 NS_IMETHODIMP
254 nsSVGDisplayContainerFrame::NotifyRedrawUnsuspended()
256 for (nsIFrame* kid = mFrames.FirstChild(); kid;
257 kid = kid->GetNextSibling()) {
258 nsISVGChildFrame* SVGFrame = nsnull;
259 CallQueryInterface(kid, &SVGFrame);
260 if (SVGFrame) {
261 SVGFrame->NotifyRedrawUnsuspended();
264 return NS_OK;
267 NS_IMETHODIMP
268 nsSVGDisplayContainerFrame::GetBBox(nsIDOMSVGRect **_retval)
270 return nsSVGUtils::GetBBox(&mFrames, _retval);
273 NS_IMETHODIMP
274 nsSVGDisplayContainerFrame::SetMatrixPropagation(PRBool aPropagate)
276 if (aPropagate) {
277 AddStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
278 } else {
279 RemoveStateBits(NS_STATE_SVG_PROPAGATE_TRANSFORM);
281 return NS_OK;
284 PRBool
285 nsSVGDisplayContainerFrame::GetMatrixPropagation()
287 return (GetStateBits() & NS_STATE_SVG_PROPAGATE_TRANSFORM) != 0;