Bug 480979 part 1. Introduce FrameConstructionItem and restructure existing Construc...
[mozilla-central.git] / layout / base / nsCSSFrameConstructor.h
blobaec3538df37d2d24f9d96d7abb748446270f49d0
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 mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 * construction of a frame tree that is nearly isomorphic to the content
40 * tree and updating of that tree in response to dynamic changes
43 #ifndef nsCSSFrameConstructor_h___
44 #define nsCSSFrameConstructor_h___
46 #include "nsCOMPtr.h"
47 #include "nsILayoutHistoryState.h"
48 #include "nsIXBLService.h"
49 #include "nsQuoteList.h"
50 #include "nsCounterManager.h"
51 #include "nsDataHashtable.h"
52 #include "nsHashKeys.h"
53 #include "nsThreadUtils.h"
54 #include "nsPageContentFrame.h"
55 #include "nsIViewManager.h"
57 class nsIDocument;
58 struct nsFrameItems;
59 struct nsAbsoluteItems;
60 class nsStyleContext;
61 struct nsStyleContent;
62 struct nsStyleDisplay;
63 class nsIPresShell;
64 class nsFrameManager;
65 class nsIDOMHTMLSelectElement;
66 class nsPresContext;
67 class nsStyleChangeList;
68 class nsIFrame;
69 struct nsGenConInitializer;
70 class ChildIterator;
72 struct nsFindFrameHint
74 nsIFrame *mPrimaryFrameForPrevSibling; // weak ref to the primary frame for the content for which we need a frame
75 nsFindFrameHint() : mPrimaryFrameForPrevSibling(nsnull) { }
78 typedef void (nsLazyFrameConstructionCallback)
79 (nsIContent* aContent, nsIFrame* aFrame, void* aArg);
81 class nsFrameConstructorState;
82 class nsFrameConstructorSaveState;
84 class nsCSSFrameConstructor
86 public:
87 nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell);
88 ~nsCSSFrameConstructor(void) {
89 NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?");
90 NS_ASSERTION(mFocusSuppressCount == 0, "Focus suppression will be wrong");
93 // Maintain global objects - gXBLService
94 static nsIXBLService * GetXBLService();
95 static void ReleaseGlobals() { NS_IF_RELEASE(gXBLService); }
97 // get the alternate text for a content node
98 static void GetAlternateTextFor(nsIContent* aContent,
99 nsIAtom* aTag, // content object's tag
100 nsXPIDLString& aAltText);
101 private:
102 // These are not supported and are not implemented!
103 nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy);
104 nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy);
106 public:
107 // XXXbz this method needs to actually return errors!
108 nsresult ConstructRootFrame(nsIContent* aDocElement,
109 nsIFrame** aNewFrame);
111 nsresult ReconstructDocElementHierarchy();
113 nsresult ContentAppended(nsIContent* aContainer,
114 PRInt32 aNewIndexInContainer);
116 nsresult ContentInserted(nsIContent* aContainer,
117 nsIContent* aChild,
118 PRInt32 aIndexInContainer,
119 nsILayoutHistoryState* aFrameState);
121 nsresult ContentRemoved(nsIContent* aContainer,
122 nsIContent* aChild,
123 PRInt32 aIndexInContainer,
124 PRBool* aDidReconstruct);
126 nsresult CharacterDataChanged(nsIContent* aContent,
127 PRBool aAppend);
129 nsresult ContentStatesChanged(nsIContent* aContent1,
130 nsIContent* aContent2,
131 PRInt32 aStateMask);
133 // Process the children of aContent and indicate that frames should be
134 // created for them. This is used for lazily built content such as that
135 // inside popups so that it is only created when the popup is opened.
136 // If aIsSynch is true, this method constructs the frames synchronously.
137 // aCallback will be called with three arguments, the first is the value
138 // of aContent, the second is aContent's primary frame, and the third is
139 // the value of aArg.
140 // aCallback will always be called even if the children of aContent had
141 // been generated earlier.
142 nsresult AddLazyChildren(nsIContent* aContent,
143 nsLazyFrameConstructionCallback* aCallback,
144 void* aArg, PRBool aIsSynch = PR_FALSE);
146 // Should be called when a frame is going to be destroyed and
147 // WillDestroyFrameTree hasn't been called yet.
148 void NotifyDestroyingFrame(nsIFrame* aFrame);
150 nsresult AttributeChanged(nsIContent* aContent,
151 PRInt32 aNameSpaceID,
152 nsIAtom* aAttribute,
153 PRInt32 aModType,
154 PRUint32 aStateMask);
156 void BeginUpdate();
157 void EndUpdate();
158 void RecalcQuotesAndCounters();
160 void WillDestroyFrameTree(PRBool aDestroyingPresShell);
162 // Get an integer that increments every time there is a style change
163 // as a result of a change to the :hover content state.
164 PRUint32 GetHoverGeneration() const { return mHoverGeneration; }
166 // Note: It's the caller's responsibility to make sure to wrap a
167 // ProcessRestyledFrames call in a view update batch and a script blocker.
168 // This function does not call ProcessAttachedQueue() on the binding manager.
169 // If the caller wants that to happen synchronously, it needs to handle that
170 // itself.
171 nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray);
173 private:
175 // Note: It's the caller's responsibility to make sure to wrap a
176 // ProcessOneRestyle call in a view update batch.
177 // This function does not call ProcessAttachedQueue() on the binding manager.
178 // If the caller wants that to happen synchronously, it needs to handle that
179 // itself.
180 void ProcessOneRestyle(nsIContent* aContent, nsReStyleHint aRestyleHint,
181 nsChangeHint aChangeHint);
183 public:
184 // Restyling for a ContentInserted (notification after insertion) or
185 // for a CharacterDataChanged. |aContainer| must be non-null; when
186 // the container is null, no work is needed.
187 void RestyleForInsertOrChange(nsIContent* aContainer,
188 nsIContent* aChild);
189 // This would be the same as RestyleForInsertOrChange if we got the
190 // notification before the removal. However, we get it after, so we
191 // have to use the index. |aContainer| must be non-null; when the
192 // container is null, no work is needed.
193 void RestyleForRemove(nsIContent* aContainer, nsIContent* aOldChild,
194 PRInt32 aIndexInContainer);
195 // Same for a ContentAppended. |aContainer| must be non-null; when
196 // the container is null, no work is needed.
197 void RestyleForAppend(nsIContent* aContainer,
198 PRInt32 aNewIndexInContainer);
200 // Note: It's the caller's responsibility to make sure to wrap a
201 // ProcessPendingRestyles call in a view update batch and a script blocker.
202 // This function does not call ProcessAttachedQueue() on the binding manager.
203 // If the caller wants that to happen synchronously, it needs to handle that
204 // itself.
205 void ProcessPendingRestyles();
207 // Rebuilds all style data by throwing out the old rule tree and
208 // building a new one, and additionally applying aExtraHint (which
209 // must not contain nsChangeHint_ReconstructFrame) to the root frame.
210 void RebuildAllStyleData(nsChangeHint aExtraHint);
212 void PostRestyleEvent(nsIContent* aContent, nsReStyleHint aRestyleHint,
213 nsChangeHint aMinChangeHint);
214 private:
215 void PostRestyleEventInternal();
216 public:
219 * Asynchronously clear style data from the root frame downwards and ensure
220 * it will all be rebuilt. This is safe to call anytime; it will schedule
221 * a restyle and take effect next time style changes are flushed.
222 * This method is used to recompute the style data when some change happens
223 * outside of any style rules, like a color preference change or a change
224 * in a system font size, or to fix things up when an optimization in the
225 * style data has become invalid. We assume that the root frame will not
226 * need to be reframed.
228 void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint);
230 // Request to create a continuing frame
231 nsresult CreateContinuingFrame(nsPresContext* aPresContext,
232 nsIFrame* aFrame,
233 nsIFrame* aParentFrame,
234 nsIFrame** aContinuingFrame,
235 PRBool aIsFluid = PR_TRUE);
237 // Copy over fixed frames from aParentFrame's prev-in-flow
238 nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
240 // Request to find the primary frame associated with a given content object.
241 // This is typically called by the pres shell when there is no mapping in
242 // the pres shell hash table
243 nsresult FindPrimaryFrameFor(nsFrameManager* aFrameManager,
244 nsIContent* aContent,
245 nsIFrame** aFrame,
246 nsFindFrameHint* aHint);
248 // Get the XBL insertion point for a child
249 nsresult GetInsertionPoint(nsIFrame* aParentFrame,
250 nsIContent* aChildContent,
251 nsIFrame** aInsertionPoint,
252 PRBool* aMultiple = nsnull);
254 nsresult CreateListBoxContent(nsPresContext* aPresContext,
255 nsIFrame* aParentFrame,
256 nsIFrame* aPrevFrame,
257 nsIContent* aChild,
258 nsIFrame** aResult,
259 PRBool aIsAppend,
260 PRBool aIsScrollbar,
261 nsILayoutHistoryState* aFrameState);
263 nsresult RemoveMappingsForFrameSubtree(nsIFrame* aRemovedFrame);
265 // GetInitialContainingBlock() is deprecated in favor of GetRootElementFrame();
266 // nsIFrame* GetInitialContainingBlock() { return mRootElementFrame; }
267 // This returns the outermost frame for the root element
268 nsIFrame* GetRootElementFrame() { return mRootElementFrame; }
269 // This returns the frame for the root element that does not
270 // have a psuedo-element style
271 nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
272 nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
274 // Get the frame that is the parent of the root element.
275 nsIFrame* GetDocElementContainingBlock()
276 { return mDocElementContainingBlock; }
278 // Returns true if we've torn down the frame tree.
279 // Usually this means we've started destroying the presentation, but
280 // we could also have mostly torn it down in preparation for
281 // reconstructing frames for the entire document.
282 PRBool IsDestroyingFrameTree() { return mIsDestroyingFrameTree; }
284 private:
285 struct FrameConstructionItem;
287 nsresult ReconstructDocElementHierarchyInternal();
289 nsresult ReinsertContent(nsIContent* aContainer,
290 nsIContent* aChild);
292 nsresult ConstructPageFrame(nsIPresShell* aPresShell,
293 nsPresContext* aPresContext,
294 nsIFrame* aParentFrame,
295 nsIFrame* aPrevPageFrame,
296 nsIFrame*& aPageFrame,
297 nsIFrame*& aCanvasFrame);
299 void DoContentStateChanged(nsIContent* aContent,
300 PRInt32 aStateMask);
302 /* aMinHint is the minimal change that should be made to the element */
303 void RestyleElement(nsIContent* aContent,
304 nsIFrame* aPrimaryFrame,
305 nsChangeHint aMinHint);
307 void RestyleLaterSiblings(nsIContent* aContent);
309 nsresult InitAndRestoreFrame (const nsFrameConstructorState& aState,
310 nsIContent* aContent,
311 nsIFrame* aParentFrame,
312 nsIFrame* aPrevInFlow,
313 nsIFrame* aNewFrame,
314 PRBool aAllowCounters = PR_TRUE);
316 already_AddRefed<nsStyleContext>
317 ResolveStyleContext(nsIFrame* aParentFrame,
318 nsIContent* aContent);
320 nsresult ConstructFrame(nsFrameConstructorState& aState,
321 nsIContent* aContent,
322 nsIFrame* aParentFrame,
323 nsFrameItems& aFrameItems);
325 void AddFrameConstructionItem(nsFrameConstructorState& aState,
326 nsIContent* aContent,
327 nsIFrame* aParentFrame,
328 nsTArray<FrameConstructionItem>& aItems);
330 nsresult ConstructDocElementFrame(nsFrameConstructorState& aState,
331 nsIContent* aDocElement,
332 nsIFrame* aParentFrame,
333 nsIFrame** aNewFrame);
335 nsresult ConstructDocElementTableFrame(nsIContent* aDocElement,
336 nsIFrame* aParentFrame,
337 nsIFrame** aNewTableFrame,
338 nsFrameConstructorState& aState);
341 * CreateAttributeContent creates a single content/frame combination for an
342 * |attr(foo)| generated content.
344 * @param aParentContent the parent content for the generated content
345 * @param aParentFrame the parent frame for the generated frame
346 * @param aAttrNamespace the namespace of the attribute in question
347 * @param aAttrName the localname of the attribute
348 * @param aStyleContext the style context to use
349 * @param aGeneratedContent the array of generated content to append the
350 * created content to.
351 * @param [out] aNewContent the content node we create
352 * @param [out] aNewFrame the new frame we create
354 nsresult CreateAttributeContent(nsIContent* aParentContent,
355 nsIFrame* aParentFrame,
356 PRInt32 aAttrNamespace,
357 nsIAtom* aAttrName,
358 nsStyleContext* aStyleContext,
359 nsCOMArray<nsIContent>& aGeneratedContent,
360 nsIContent** aNewContent,
361 nsIFrame** aNewFrame);
364 * Create a text node containing the given string. If aText is non-null
365 * then we also set aText to the returned node.
367 already_AddRefed<nsIContent> CreateGenConTextNode(const nsString& aString,
368 nsCOMPtr<nsIDOMCharacterData>* aText,
369 nsGenConInitializer* aInitializer);
372 * Create a content node for the given generated content style.
373 * The caller takes care of making it SetNativeAnonymous, binding it
374 * to the document, and creating frames for it.
375 * @param aParentContent is the node that has the before/after style
376 * @param aStyleContext is the 'before' or 'after' pseudo-element
377 * style context
378 * @param aContentIndex is the index of the content item to create
380 already_AddRefed<nsIContent> CreateGeneratedContent(nsIContent* aParentContent,
381 nsStyleContext* aStyleContext,
382 PRUint32 aContentIndex);
384 void CreateGeneratedContentItem(nsFrameConstructorState& aState,
385 nsIFrame* aFrame,
386 nsIContent* aContent,
387 nsStyleContext* aStyleContext,
388 nsIAtom* aPseudoElement,
389 nsTArray<FrameConstructionItem>& aItems);
391 // This method can change aFrameList: it can chop off the end and
392 // put it in a special sibling of aParentFrame. It can also change
393 // aState by moving some floats out of it.
394 nsresult AppendFrames(nsFrameConstructorState& aState,
395 nsIContent* aContainer,
396 nsIFrame* aParentFrame,
397 nsFrameItems& aFrameList,
398 nsIFrame* aAfterFrame);
400 // BEGIN TABLE SECTION
402 * Construct an outer table frame. This is the FrameConstructionData
403 * callback used for the job.
405 nsresult ConstructTable(nsFrameConstructorState& aState,
406 nsIContent* aContent,
407 nsIFrame* aParentFrame,
408 nsIAtom* aTag,
409 PRInt32 aNameSpaceID,
410 nsStyleContext* aStyleContext,
411 const nsStyleDisplay* aDisplay,
412 nsFrameItems& aFrameItems,
413 nsIFrame** aNewFrame);
416 * Construct some part of a table other than the outer table frame. This is
417 * the FrameConstructionData callback used for the job.
419 nsresult ConstructTablePart(nsFrameConstructorState& aState,
420 nsIContent* aContent,
421 nsIFrame* aParentFrame,
422 nsIAtom* aTag,
423 PRInt32 aNameSpaceID,
424 nsStyleContext* aStyleContext,
425 const nsStyleDisplay* aDisplay,
426 nsFrameItems& aFrameItems,
427 nsIFrame** aNewFrame);
430 * ConstructTableFrame will construct the outer and inner table frames and
431 * return them. Unless aIsPseudo is PR_TRUE, it will put the inner frame in
432 * the child list of the outer frame, and will put any pseudo frames it had
433 * to create into aChildItems. The newly-created outer frame will either be
434 * in aChildItems or a descendant of a pseudo in aChildItems (unless it's
435 * positioned or floated, in which case its placeholder will be in
436 * aChildItems).
438 nsresult ConstructTableFrame(nsFrameConstructorState& aState,
439 nsIContent* aContent,
440 nsIFrame* aContentParent,
441 nsStyleContext* aStyleContext,
442 PRInt32 aNameSpaceID,
443 PRBool aIsPseudo,
444 nsFrameItems& aChildItems,
445 nsIFrame*& aNewOuterFrame,
446 nsIFrame*& aNewInnerFrame);
448 nsresult ConstructTableCaptionFrame(nsFrameConstructorState& aState,
449 nsIContent* aContent,
450 nsIFrame* aParent,
451 nsStyleContext* aStyleContext,
452 PRInt32 aNameSpaceID,
453 nsFrameItems& aChildItems,
454 nsIFrame*& aNewFrame,
455 PRBool* aHasPseudoParent);
457 nsresult ConstructTableRowGroupFrame(nsFrameConstructorState& aState,
458 nsIContent* aContent,
459 nsIFrame* aParent,
460 nsStyleContext* aStyleContext,
461 PRInt32 aNameSpaceID,
462 PRBool aIsPseudo,
463 nsFrameItems& aChildItems,
464 nsIFrame*& aNewFrame,
465 PRBool* aHasPseudoParent);
467 nsresult ConstructTableColGroupFrame(nsFrameConstructorState& aState,
468 nsIContent* aContent,
469 nsIFrame* aParent,
470 nsStyleContext* aStyleContext,
471 PRInt32 aNameSpaceID,
472 PRBool aIsPseudo,
473 nsFrameItems& aChildItems,
474 nsIFrame*& aNewFrame,
475 PRBool* aHasPseudoParent);
477 nsresult ConstructTableRowFrame(nsFrameConstructorState& aState,
478 nsIContent* aContent,
479 nsIFrame* aParent,
480 nsStyleContext* aStyleContext,
481 PRInt32 aNameSpaceID,
482 PRBool aIsPseudo,
483 nsFrameItems& aChildItems,
484 nsIFrame*& aNewFrame,
485 PRBool* aHasPseudoParent);
487 nsresult ConstructTableColFrame(nsFrameConstructorState& aState,
488 nsIContent* aContent,
489 nsIFrame* aParent,
490 nsStyleContext* aStyleContext,
491 PRInt32 aNameSpaceID,
492 PRBool aIsPseudo,
493 nsFrameItems& aChildItems,
494 nsIFrame*& aNewFrame,
495 PRBool* aHasPseudoParent);
497 nsresult ConstructTableCellFrame(nsFrameConstructorState& aState,
498 nsIContent* aContent,
499 nsIFrame* aParentFrame,
500 nsStyleContext* aStyleContext,
501 PRInt32 aNameSpaceID,
502 PRBool aIsPseudo,
503 nsFrameItems& aChildItems,
504 nsIFrame*& aNewCellOuterFrame,
505 nsIFrame*& aNewCellInnerFrame,
506 PRBool* aHasPseudoParent);
508 nsresult CreatePseudoTableFrame(PRInt32 aNameSpaceID,
509 nsFrameConstructorState& aState,
510 nsIFrame* aParentFrameIn = nsnull);
512 nsresult CreatePseudoRowGroupFrame(PRInt32 aNameSpaceID,
513 nsFrameConstructorState& aState,
514 nsIFrame* aParentFrameIn = nsnull);
516 nsresult CreatePseudoColGroupFrame(PRInt32 aNameSpaceID,
517 nsFrameConstructorState& aState,
518 nsIFrame* aParentFrameIn = nsnull);
520 nsresult CreatePseudoRowFrame(PRInt32 aNameSpaceID,
521 nsFrameConstructorState& aState,
522 nsIFrame* aParentFrameIn = nsnull);
524 nsresult CreatePseudoCellFrame(PRInt32 aNameSpaceID,
525 nsFrameConstructorState& aState,
526 nsIFrame* aParentFrameIn = nsnull);
528 nsresult GetPseudoTableFrame(PRInt32 aNameSpaceID,
529 nsFrameConstructorState& aState,
530 nsIFrame& aParentFrameIn);
532 nsresult GetPseudoColGroupFrame(PRInt32 aNameSpaceID,
533 nsFrameConstructorState& aState,
534 nsIFrame& aParentFrameIn);
536 nsresult GetPseudoRowGroupFrame(PRInt32 aNameSpaceID,
537 nsFrameConstructorState& aState,
538 nsIFrame& aParentFrameIn);
540 nsresult GetPseudoRowFrame(PRInt32 aNameSpaceID,
541 nsFrameConstructorState& aState,
542 nsIFrame& aParentFrameIn);
544 nsresult GetPseudoCellFrame(PRInt32 aNameSpaceID,
545 nsFrameConstructorState& aState,
546 nsIFrame& aParentFrameIn);
548 nsresult CreateRequiredPseudoFrames(PRInt32 aNameSpaceID,
549 nsIFrame& aParentFrameIn,
550 nsIAtom* aChildFrameType,
551 nsFrameConstructorState& aState,
552 nsIFrame*& aParentFrame,
553 PRBool& aIsPseudoParent);
555 private:
556 /* A constructor function that just creates an nsIFrame object. The caller
557 is responsible for initializing the object, adding it to frame lists,
558 constructing frames for the children, etc.
560 @param nsIPresShell the presshell whose arena should be used to allocate
561 the frame.
562 @param nsStyleContext the style context to use for the frame. */
563 typedef nsIFrame* (* FrameCreationFunc)(nsIPresShell*, nsStyleContext*);
565 /* A function that can be used to get a FrameConstructionData. Such
566 a function is allowed to return null.
568 @param nsIContent the node for which the frame is being constructed.
569 @param nsStyleContext the style context to be used for the frame.
571 struct FrameConstructionData;
572 typedef const FrameConstructionData*
573 (* FrameConstructionDataGetter)(nsIContent*, nsStyleContext*);
575 /* A constructor function that's used for complicated construction tasks.
576 This is expected to create the new frame, initialize it, add whatever
577 needs to be added to aFrameItems (XXXbz is that really necessary? Could
578 caller add? Might there be cases when *aNewFrame or its placeholder is
579 not the thing that ends up in aFrameItems? If not, would it be safe to do
580 the add into the frame construction state after processing kids? Look
581 into this as a followup!), process children as needed, etc. It is NOT
582 expected to deal with the primary frame map.
584 @param aState the frame construction state to use.
585 @param aContent the content node to construct the frame for.
586 @param aParentFrame the frame to set as the parent of the
587 newly-constructed frame.
588 @param aTag the content's XBL-resolved tag.
589 @param aNameSpaceID the content's XBL-resolved namespace.
590 @param aStyleContext the style context to use for the new frame.
591 @param aFrameItems the frame list to add the new frame (or its
592 placeholder) to.
593 @param aFrame out param handing out the frame that was constructed. This
594 frame is what the caller will add to the primary frame map.
596 typedef nsresult
597 (nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState,
598 nsIContent* aContent,
599 nsIFrame* aParentFrame,
600 nsIAtom* aTag,
601 PRInt32 aNameSpaceID,
602 nsStyleContext* aStyleContext,
603 const nsStyleDisplay* aStyleDisplay,
604 nsFrameItems& aFrameItems,
605 nsIFrame** aFrame);
607 /* Bits that modify the way a FrameConstructionData is handled */
609 /* If the FCDATA_SKIP_FRAMEMAP bit is set, then the frame created should not
610 be added to the primary frame map. This flag should not be used with
611 FCDATA_MAY_NEED_SCROLLFRAME, since scrollframe construction will add to
612 the frame map. */
613 #define FCDATA_SKIP_FRAMEMAP 0x1
614 /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
615 FrameConstructionData is a getter function that can be used to get the
616 actual FrameConstructionData to use. */
617 #define FCDATA_FUNC_IS_DATA_GETTER 0x2
618 /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData
619 has an mFullConstructor. In this case, there is no relevant mData or
620 mFunc */
621 #define FCDATA_FUNC_IS_FULL_CTOR 0x4
622 /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to
623 float or be absolutely positioned. This cannot be used with
624 FCDATA_FUNC_IS_FULL_CTOR */
625 #define FCDATA_DISALLOW_OUT_OF_FLOW 0x8
626 /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a
627 null absolute containing block before processing children for this
628 frame. If this is not set, the frame will be pushed as the
629 absolute containing block as needed, based on its style */
630 #define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10
631 #ifdef MOZ_MATHML
632 /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame
633 will be wrapped in blocks. This is only usable for MathML at the
634 moment. */
635 #define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20
636 #endif /* MOZ_MATHML */
637 /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the
638 content. If this bit is set, nothing else in the struct needs to be
639 set. */
640 #define FCDATA_SUPPRESS_FRAME 0x40
641 /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
642 a scrollframe if its overflow type so requires. This flag should not be
643 used with FCDATA_SKIP_FRAMEMAP, since scrollframe construction will add to
644 the frame map. */
645 #define FCDATA_MAY_NEED_SCROLLFRAME 0x80
646 #ifdef MOZ_XUL
647 /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame. These need
648 some really weird special handling. */
649 #define FCDATA_IS_POPUP 0x100
650 #endif /* MOZ_XUL */
651 /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
652 absolute containing block, no matter what its style says. */
653 #define FCDATA_SKIP_ABSPOS_PUSH 0x200
654 /* If FCDATA_FORCE_VIEW is set, then force creation of a view for the frame.
655 this is only used if a scrollframe is not created and a full constructor
656 isn't used, so this flag shouldn't be used with
657 FCDATA_MAY_NEED_SCROLLFRAME or FCDATA_FUNC_IS_FULL_CTOR. */
658 #define FCDATA_FORCE_VIEW 0x400
659 /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated
660 content when processing kids of this frame. This should not be used with
661 FCDATA_FUNC_IS_FULL_CTOR */
662 #define FCDATA_DISALLOW_GENERATED_CONTENT 0x800
663 /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of
664 table-related thing and we should not attempt to fetch a table-cell parent
665 for it if it's inside another table-related frame. */
666 #define FCDATA_IS_TABLE_PART 0x1000
668 /* Structure representing information about how a frame should be
669 constructed. */
670 struct FrameConstructionData {
671 // Flag bits that can modify the way the construction happens
672 PRUint32 mBits;
673 // We have exactly one of three types of functions, so use a union for
674 // better cache locality for the ones that aren't pointer-to-member. That
675 // one needs to be separate, because we can't cast between it and the
676 // others and hence wouldn't be able to initialize the union without a
677 // constructor and all the resulting generated code. See documentation
678 // above for FrameCreationFunc, FrameConstructionDataGetter, and
679 // FrameFullConstructor to see what the functions would do.
680 union Func {
681 FrameCreationFunc mCreationFunc;
682 FrameConstructionDataGetter mDataGetter;
683 } mFunc;
684 FrameFullConstructor mFullConstructor;
687 /* Structure representing a mapping of an atom to a FrameConstructionData.
688 This can be used with non-static atoms, assuming that the nsIAtom* is
689 stored somewhere that this struct can point to (that is, a static
690 nsIAtom*) and that it's allocated before the struct is ever used. */
691 struct FrameConstructionDataByTag {
692 // Pointer to nsIAtom* is used because we want to initialize this
693 // statically, so before our atom tables are set up.
694 const nsIAtom * const * const mTag;
695 const FrameConstructionData mData;
698 /* Structure representing a mapping of an integer to a
699 FrameConstructionData. There are no magic integer values here. */
700 struct FrameConstructionDataByInt {
701 /* Could be used for display or whatever else */
702 const PRInt32 mInt;
703 const FrameConstructionData mData;
706 /* A function that takes an integer, content, style context, and array of
707 FrameConstructionDataByInts and finds the appropriate frame construction
708 data to use and returns it. This can return null if none of the integers
709 match or if the matching integer has a FrameConstructionDataGetter that
710 returns null. */
711 static const FrameConstructionData*
712 FindDataByInt(PRInt32 aInt, nsIContent* aContent,
713 nsStyleContext* aStyleContext,
714 const FrameConstructionDataByInt* aDataPtr,
715 PRUint32 aDataLength);
717 /* A function that takes a tag, content, style context, and array of
718 FrameConstructionDataByTags and finds the appropriate frame construction
719 data to use and returns it. This can return null if none of the tags
720 match or if the matching tag has a FrameConstructionDataGetter that
721 returns null. */
722 static const FrameConstructionData*
723 FindDataByTag(nsIAtom* aTag, nsIContent* aContent,
724 nsStyleContext* aStyleContext,
725 const FrameConstructionDataByTag* aDataPtr,
726 PRUint32 aDataLength);
728 /* A struct representing an item for which frames might need to be
729 * constructed. This contains all the information needed to construct the
730 * frame other than the parent frame and whatever would be stored in the
731 * frame constructor state. */
732 struct FrameConstructionItem {
733 FrameConstructionItem() :
734 mIsGeneratedContent(PR_FALSE) {}
735 ~FrameConstructionItem() {
736 if (mIsGeneratedContent) {
737 mContent->UnbindFromTree();
738 NS_RELEASE(mContent);
742 // The FrameConstructionData to use.
743 const FrameConstructionData* mFCData;
744 // The nsIContent node to use when initializing the new frame.
745 nsIContent* mContent;
746 // The XBL-resolved tag name to use for frame construction.
747 nsIAtom* mTag;
748 // The XBL-resolved namespace to use for frame construction.
749 PRInt32 mNameSpaceID;
750 // The style context to use for creating the new frame.
751 nsRefPtr<nsStyleContext> mStyleContext;
752 // Whether to allow page-break stuff around this frame.
753 PRPackedBool mAllowPageBreaks;
754 // Whether this is a text content item.
755 PRPackedBool mIsText;
756 // Whether this is generated content. If it is, mContent is a strong
757 // pointer.
758 PRPackedBool mIsGeneratedContent;
760 private:
761 FrameConstructionItem(const FrameConstructionItem& aOther); /* not implemented */
765 * Function to adjust aParentFrame and aFrameItems to deal with table
766 * pseudo-frames that may have to be inserted.
767 * @param aState the nsFrameConstructorState we're using.
768 * @param aChildContent the content node we want to construct a frame for
769 * @param aParentFrame the frame we think should be the parent. This will be
770 * adjusted to point to a pseudo-frame if needed.
771 * @param aFCData the FrameConstructionData that would be used for frame
772 * construction.
773 * @param aNameSpaceID namespace that will be used for frame construction
774 * @param aStyleContext the style context for aChildContent
775 * @param aFrameItems the framelist we think we need to put the child frame
776 * into. If we have to construct pseudo-frames, we'll modify the
777 * pointer to point to the list the child frame should go into.
778 * @param aSaveState the nsFrameConstructorSaveState we can use for pushing a
779 * float containing block if we have to do it.
780 * @param aSuppressFrame whether we should not create a frame below this
781 * parent
782 * @param aCreatedPseudo whether we had to create a pseudo-parent
783 * @return NS_OK on success, NS_ERROR_OUT_OF_MEMORY and such as needed.
785 // XXXbz this function should really go away once we rework pseudo-frame
786 // handling to be better. This should simply be part of the job of
787 // GetGeometricParent, and stuff like the frameitems and parent frame should
788 // be kept track of in the state...
789 nsresult AdjustParentFrame(nsFrameConstructorState& aState,
790 nsIContent* aChildContent,
791 nsIFrame* & aParentFrame,
792 const FrameConstructionData* aFCData,
793 PRInt32 aNameSpaceID,
794 nsStyleContext* aStyleContext,
795 nsFrameItems* & aFrameItems,
796 nsFrameConstructorSaveState& aSaveState,
797 PRBool& aSuppressFrame,
798 PRBool& aCreatedPseudo);
800 // END TABLE SECTION
802 protected:
803 static nsresult CreatePlaceholderFrameFor(nsIPresShell* aPresShell,
804 nsIContent* aContent,
805 nsIFrame* aFrame,
806 nsStyleContext* aStyleContext,
807 nsIFrame* aParentFrame,
808 nsIFrame* aPrevInFlow,
809 nsIFrame** aPlaceholderFrame);
811 private:
812 // ConstructButtonFrame puts the new frame in aFrameItems and
813 // handles the kids of the button.
814 nsresult ConstructButtonFrame(nsFrameConstructorState& aState,
815 nsIContent* aContent,
816 nsIFrame* aParentFrame,
817 nsIAtom* aTag,
818 PRInt32 aNameSpaceID,
819 nsStyleContext* aStyleContext,
820 const nsStyleDisplay* aStyleDisplay,
821 nsFrameItems& aFrameItems,
822 nsIFrame** aNewFrame);
824 // ConstructSelectFrame puts the new frame in aFrameItems and
825 // handles the kids of the select.
826 nsresult ConstructSelectFrame(nsFrameConstructorState& aState,
827 nsIContent* aContent,
828 nsIFrame* aParentFrame,
829 nsIAtom* aTag,
830 PRInt32 aNameSpaceID,
831 nsStyleContext* aStyleContext,
832 const nsStyleDisplay* aStyleDisplay,
833 nsFrameItems& aFrameItems,
834 nsIFrame** aNewFrame);
836 // ConstructFieldSetFrame puts the new frame in aFrameItems and
837 // handles the kids of the fieldset
838 nsresult ConstructFieldSetFrame(nsFrameConstructorState& aState,
839 nsIContent* aContent,
840 nsIFrame* aParentFrame,
841 nsIAtom* aTag,
842 PRInt32 aNameSpaceID,
843 nsStyleContext* aStyleContext,
844 const nsStyleDisplay* aStyleDisplay,
845 nsFrameItems& aFrameItems,
846 nsIFrame** aNewFrame);
848 static const FrameConstructionData* FindTextData(nsIFrame* aParentFrame);
850 nsresult ConstructTextFrame(const FrameConstructionData* aData,
851 nsFrameConstructorState& aState,
852 nsIContent* aContent,
853 nsIFrame* aParentFrame,
854 nsStyleContext* aStyleContext,
855 nsFrameItems& aFrameItems,
856 PRBool aPseudoParent);
858 nsresult ConstructPageBreakFrame(nsFrameConstructorState& aState,
859 nsIContent* aContent,
860 nsIFrame* aParentFrame,
861 nsStyleContext* aStyleContext,
862 nsFrameItems& aFrameItems);
864 // Construct a page break frame if page-break-before:always is set in aStyleContext
865 // and add it to aFrameItems. Return true if page-break-after:always is set on aStyleContext.
866 // Don't do this for row groups, rows or cell, because tables handle those internally.
867 PRBool PageBreakBefore(nsFrameConstructorState& aState,
868 nsIContent* aContent,
869 nsIFrame* aParentFrame,
870 nsStyleContext* aStyleContext,
871 const FrameConstructionData* aFCData,
872 nsFrameItems& aFrameItems);
874 // Function to find FrameConstructionData for aContent. Will return
875 // null if aContent is not HTML.
876 static const FrameConstructionData* FindHTMLData(nsIContent* aContent,
877 nsIAtom* aTag,
878 PRInt32 aNameSpaceID,
879 nsIFrame* aParentFrame,
880 nsStyleContext* aStyleContext);
881 // HTML data-finding helper functions
882 static const FrameConstructionData*
883 FindImgData(nsIContent* aContent, nsStyleContext* aStyleContext);
884 static const FrameConstructionData*
885 FindImgControlData(nsIContent* aContent, nsStyleContext* aStyleContext);
886 static const FrameConstructionData*
887 FindInputData(nsIContent* aContent, nsStyleContext* aStyleContext);
888 static const FrameConstructionData*
889 FindObjectData(nsIContent* aContent, nsStyleContext* aStyleContext);
891 /* Construct a frame from the given FrameConstructionData. This function
892 will handle adding the frame to frame lists, processing children, adding
893 it to the primary frame map, and so forth.
895 @param aData the FrameConstructionData to use. Must not be null.
896 @param aState the frame construction state to use.
897 @param aContent the content node to construct the frame for.
898 @param aParentFrame the frame to set as the parent of the
899 newly-constructed frame.
900 @param aTag the content's XBL-resolved tag.
901 @param aNameSpaceID the content's XBL-resolved namespace ID.
902 @param aStyleContext the style context to use for the new frame.
903 @param aFrameItems the frame list to add the new frame (or its
904 placeholder) to.
905 @param aHasPseudoParent whether aParentFrame is a table pseudo-frame.
907 nsresult ConstructFrameFromData(const FrameConstructionData* aData,
908 nsFrameConstructorState& aState,
909 nsIContent* aContent,
910 nsIFrame* aParentFrame,
911 nsIAtom* aTag,
912 PRInt32 aNameSpaceID,
913 nsStyleContext* aStyleContext,
914 nsFrameItems& aFrameItems,
915 PRBool aHasPseudoParent);
917 // possible flags for AddFrameConstructionItemInternal's aFlags argument
918 /* Allow xbl:base to affect the tag/namespace used. */
919 #define ITEM_ALLOW_XBL_BASE 0x1
920 /* Allow page-break before and after items to be created if the
921 style asks for them. */
922 #define ITEM_ALLOW_PAGE_BREAK 0x2
923 /* The item is a generated content item. */
924 #define ITEM_IS_GENERATED_CONTENT 0x4
925 void AddFrameConstructionItemInternal(nsFrameConstructorState& aState,
926 nsIContent* aContent,
927 nsIFrame* aParentFrame,
928 nsIAtom* aTag,
929 PRInt32 aNameSpaceID,
930 nsStyleContext* aStyleContext,
931 PRUint32 aFlags,
932 nsTArray<FrameConstructionItem>& aItems);
934 nsresult ConstructFramesFromItem(nsFrameConstructorState& aState,
935 FrameConstructionItem& aItem,
936 nsIFrame* aParentFrame,
937 nsFrameItems& aFrameItems);
939 nsresult CreateAnonymousFrames(nsFrameConstructorState& aState,
940 nsIContent* aParent,
941 nsIFrame* aParentFrame,
942 nsFrameItems& aChildItems);
944 nsresult GetAnonymousContent(nsIContent* aParent,
945 nsIFrame* aParentFrame,
946 nsTArray<nsIContent*>& aAnonContent);
948 //MathML Mod - RBS
949 #ifdef MOZ_MATHML
951 * Takes the frames in aBlockItems and wraps them in a new anonymous block
952 * frame whose content is aContent and whose parent will be aParentFrame.
953 * The anonymous block is added to aNewItems and aBlockItems is cleared.
955 nsresult FlushAccumulatedBlock(nsFrameConstructorState& aState,
956 nsIContent* aContent,
957 nsIFrame* aParentFrame,
958 nsFrameItems* aBlockItems,
959 nsFrameItems* aNewItems);
961 // Function to find FrameConstructionData for aContent. Will return
962 // null if aContent is not MathML.
963 static const FrameConstructionData* FindMathMLData(nsIContent* aContent,
964 nsIAtom* aTag,
965 PRInt32 aNameSpaceID,
966 nsStyleContext* aStyleContext);
967 #endif
969 // Function to find FrameConstructionData for aContent. Will return
970 // null if aContent is not XUL.
971 static const FrameConstructionData* FindXULTagData(nsIContent* aContent,
972 nsIAtom* aTag,
973 PRInt32 aNameSpaceID,
974 nsStyleContext* aStyleContext);
975 // XUL data-finding helper functions and structures
976 #ifdef MOZ_XUL
977 static const FrameConstructionData*
978 FindPopupGroupData(nsIContent* aContent, nsStyleContext* aStyleContext);
979 // sXULTextBoxData used for both labels and descriptions
980 static const FrameConstructionData sXULTextBoxData;
981 static const FrameConstructionData*
982 FindXULLabelData(nsIContent* aContent, nsStyleContext* aStyleContext);
983 static const FrameConstructionData*
984 FindXULDescriptionData(nsIContent* aContent, nsStyleContext* aStyleContext);
985 #ifdef XP_MACOSX
986 static const FrameConstructionData*
987 FindXULMenubarData(nsIContent* aContent, nsStyleContext* aStyleContext);
988 #endif /* XP_MACOSX */
989 static const FrameConstructionData*
990 FindXULListBoxBodyData(nsIContent* aContent, nsStyleContext* aStyleContext);
991 static const FrameConstructionData*
992 FindXULListItemData(nsIContent* aContent, nsStyleContext* aStyleContext);
993 #endif /* MOZ_XUL */
995 // Function to find FrameConstructionData for aContent using one of the XUL
996 // display types. Will return null if aDisplay doesn't have a XUL display
997 // type. This function performs no other checks, so should only be called if
998 // we know for sure that the content is not something that should get a frame
999 // constructed by tag.
1000 static const FrameConstructionData*
1001 FindXULDisplayData(const nsStyleDisplay* aDisplay,
1002 nsIContent* aContent,
1003 nsStyleContext* aStyleContext);
1005 // SVG - rods
1006 #ifdef MOZ_SVG
1007 static const FrameConstructionData* FindSVGData(nsIContent* aContent,
1008 nsIAtom* aTag,
1009 PRInt32 aNameSpaceID,
1010 nsIFrame* aParentFrame,
1011 nsStyleContext* aStyleContext);
1013 nsresult ConstructSVGForeignObjectFrame(nsFrameConstructorState& aState,
1014 nsIContent* aContent,
1015 nsIFrame* aParentFrame,
1016 nsIAtom* aTag,
1017 PRInt32 aNameSpaceID,
1018 nsStyleContext* aStyleContext,
1019 const nsStyleDisplay* aStyleDisplay,
1020 nsFrameItems& aFrameItems,
1021 nsIFrame** aNewFrame);
1022 #endif
1024 /* Not static because it does PropagateScrollToViewport. If this
1025 changes, make this static */
1026 const FrameConstructionData*
1027 FindDisplayData(const nsStyleDisplay* aDisplay, nsIContent* aContent);
1030 * Construct a scrollable block frame
1032 nsresult ConstructScrollableBlock(nsFrameConstructorState& aState,
1033 nsIContent* aContent,
1034 nsIFrame* aParentFrame,
1035 nsIAtom* aTag,
1036 PRInt32 aNameSpaceID,
1037 nsStyleContext* aStyleContext,
1038 const nsStyleDisplay* aDisplay,
1039 nsFrameItems& aFrameItems,
1040 nsIFrame** aNewFrame);
1043 * Construct a non-scrollable block frame
1045 nsresult ConstructNonScrollableBlock(nsFrameConstructorState& aState,
1046 nsIContent* aContent,
1047 nsIFrame* aParentFrame,
1048 nsIAtom* aTag,
1049 PRInt32 aNameSpaceID,
1050 nsStyleContext* aStyleContext,
1051 const nsStyleDisplay* aDisplay,
1052 nsFrameItems& aFrameItems,
1053 nsIFrame** aNewFrame);
1056 * Construct the frames for the children of aContent. "children" is defined
1057 * as "whatever ChildIterator returns for aContent". This means we're
1058 * basically operating on children in the "flattened tree" per sXBL/XBL2.
1059 * This method will also handle constructing ::before, ::after,
1060 * ::first-letter, and ::first-line frames, as needed and if allowed.
1062 * If the parent is a float containing block, this method will handle pushing
1063 * it as the float containing block in aState (so there's no need for callers
1064 * to push it themselves).
1066 * @param aState the frame construction state
1067 * @param aContent the content node whose children need frames
1068 * @param aStyleContext the style context for aContent
1069 * @param aFrame the frame to use as the parent frame for the new in-flow
1070 * kids. Note that this must be its own content insertion frame, but
1071 * need not be be the primary frame for aContent. This frame will be
1072 * pushed as the float containing block, as needed. aFrame is also
1073 * used to find the parent style context for the kids' style contexts
1074 * (not necessary aFrame's style context).
1075 * @param aCanHaveGeneratedContent Whether to allow :before and
1076 * :after styles on the parent.
1077 * @param aFrameItems the list in which we should place the in-flow children
1078 * @param aAllowBlockStyles Whether to allow first-letter and first-line
1079 * styles on the parent.
1080 * @param aTableCreator if non-null, will just make this method call
1081 * TableProcessChildren between constructing the ::before and ::after
1082 * content instead of doing whatever it would normally do.
1084 nsresult ProcessChildren(nsFrameConstructorState& aState,
1085 nsIContent* aContent,
1086 nsStyleContext* aStyleContext,
1087 nsIFrame* aFrame,
1088 const PRBool aCanHaveGeneratedContent,
1089 nsFrameItems& aFrameItems,
1090 const PRBool aAllowBlockStyles);
1092 nsIFrame* GetFrameFor(nsIContent* aContent);
1095 * These two functions are used when we start frame creation from a non-root
1096 * element. They should recreate the same state that we would have
1097 * arrived at if we had built frames from the root frame to aFrame.
1098 * Therefore, any calls to PushFloatContainingBlock and
1099 * PushAbsoluteContainingBlock during frame construction should get
1100 * corresponding logic in these functions.
1102 public:
1103 nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame);
1104 private:
1105 nsIFrame* GetFloatContainingBlock(nsIFrame* aFrame);
1107 nsIContent* PropagateScrollToViewport();
1109 // Build a scroll frame:
1110 // Calls BeginBuildingScrollFrame, InitAndRestoreFrame, and then FinishBuildingScrollFrame.
1111 // Sets the primary frame for the content to the output aNewFrame.
1112 // @param aNewFrame the created scrollframe --- output only
1113 // @param aParentFrame the geometric parent that the scrollframe will have.
1114 nsresult
1115 BuildScrollFrame(nsFrameConstructorState& aState,
1116 nsIContent* aContent,
1117 nsStyleContext* aContentStyle,
1118 nsIFrame* aScrolledFrame,
1119 nsIFrame* aParentFrame,
1120 nsIFrame*& aNewFrame);
1122 // Builds the initial ScrollFrame
1123 already_AddRefed<nsStyleContext>
1124 BeginBuildingScrollFrame(nsFrameConstructorState& aState,
1125 nsIContent* aContent,
1126 nsStyleContext* aContentStyle,
1127 nsIFrame* aParentFrame,
1128 nsIAtom* aScrolledPseudo,
1129 PRBool aIsRoot,
1130 nsIFrame*& aNewFrame);
1132 // Completes the building of the scrollframe:
1133 // Creates a view for the scrolledframe and makes it the child of the scrollframe.
1134 void
1135 FinishBuildingScrollFrame(nsIFrame* aScrollFrame,
1136 nsIFrame* aScrolledFrame);
1138 // InitializeSelectFrame puts scrollFrame in aFrameItems if aBuildCombobox is false
1139 nsresult
1140 InitializeSelectFrame(nsFrameConstructorState& aState,
1141 nsIFrame* scrollFrame,
1142 nsIFrame* scrolledFrame,
1143 nsIContent* aContent,
1144 nsIFrame* aParentFrame,
1145 nsStyleContext* aStyleContext,
1146 PRBool aBuildCombobox,
1147 nsFrameItems& aFrameItems);
1149 nsresult MaybeRecreateFramesForContent(nsIContent* aContent);
1151 nsresult RecreateFramesForContent(nsIContent* aContent);
1153 // If removal of aFrame from the frame tree requires reconstruction of some
1154 // containing block (either of aFrame or of its parent) due to {ib} splits,
1155 // recreate the relevant containing block. The return value indicates
1156 // whether this happened. If this method returns true, *aResult is the
1157 // return value of ReframeContainingBlock. If this method returns false, the
1158 // value of *aResult is no affected. aFrame and aResult must not be null.
1159 // aFrame must be the result of a GetPrimaryFrameFor() call (which means its
1160 // parent is also not null).
1161 PRBool MaybeRecreateContainerForIBSplitterFrame(nsIFrame* aFrame,
1162 nsresult* aResult);
1164 nsresult CreateContinuingOuterTableFrame(nsIPresShell* aPresShell,
1165 nsPresContext* aPresContext,
1166 nsIFrame* aFrame,
1167 nsIFrame* aParentFrame,
1168 nsIContent* aContent,
1169 nsStyleContext* aStyleContext,
1170 nsIFrame** aContinuingFrame);
1172 nsresult CreateContinuingTableFrame(nsIPresShell* aPresShell,
1173 nsPresContext* aPresContext,
1174 nsIFrame* aFrame,
1175 nsIFrame* aParentFrame,
1176 nsIContent* aContent,
1177 nsStyleContext* aStyleContext,
1178 nsIFrame** aContinuingFrame);
1180 //----------------------------------------
1182 // Methods support creating block frames and their children
1184 already_AddRefed<nsStyleContext>
1185 GetFirstLetterStyle(nsIContent* aContent,
1186 nsStyleContext* aStyleContext);
1188 already_AddRefed<nsStyleContext>
1189 GetFirstLineStyle(nsIContent* aContent,
1190 nsStyleContext* aStyleContext);
1192 PRBool ShouldHaveFirstLetterStyle(nsIContent* aContent,
1193 nsStyleContext* aStyleContext);
1195 // Check whether a given block has first-letter style. Make sure to
1196 // only pass in blocks! And don't pass in null either.
1197 PRBool HasFirstLetterStyle(nsIFrame* aBlockFrame);
1199 PRBool ShouldHaveFirstLineStyle(nsIContent* aContent,
1200 nsStyleContext* aStyleContext);
1202 void ShouldHaveSpecialBlockStyle(nsIContent* aContent,
1203 nsStyleContext* aStyleContext,
1204 PRBool* aHaveFirstLetterStyle,
1205 PRBool* aHaveFirstLineStyle);
1207 // |aContentParentFrame| should be null if it's really the same as
1208 // |aParentFrame|.
1209 // @param aFrameItems where we want to put the block in case it's in-flow.
1210 // @param aNewFrame an in/out parameter. On input it is the block to be
1211 // constructed. On output it is reset to the outermost
1212 // frame constructed (e.g. if we need to wrap the block in an
1213 // nsColumnSetFrame.
1214 // @param aParentFrame is the desired parent for the (possibly wrapped)
1215 // block
1216 // @param aContentParent is the parent the block would have if it
1217 // were in-flow
1218 nsresult ConstructBlock(nsFrameConstructorState& aState,
1219 const nsStyleDisplay* aDisplay,
1220 nsIContent* aContent,
1221 nsIFrame* aParentFrame,
1222 nsIFrame* aContentParentFrame,
1223 nsStyleContext* aStyleContext,
1224 nsIFrame** aNewFrame,
1225 nsFrameItems& aFrameItems,
1226 PRBool aAbsPosContainer);
1228 nsresult ConstructInline(nsFrameConstructorState& aState,
1229 nsIContent* aContent,
1230 nsIFrame* aParentFrame,
1231 nsIAtom* aTag,
1232 PRInt32 aNameSpaceID,
1233 nsStyleContext* aStyleContext,
1234 const nsStyleDisplay* aDisplay,
1235 nsFrameItems& aFrameItems,
1236 nsIFrame** aNewFrame);
1239 * Move an already-constructed framelist into the inline frame at
1240 * the tail end of an {ib} split.
1242 * @param aState the frame construction state we're using right now.
1243 * @param aExistingEndFrame the already-existing end frame.
1244 * @param aFramesToMove The frame list to move over
1245 * @param aBlockPart the block part of the {ib} split.
1246 * @param aTargetState if non-null, the target state to pass to
1247 * MoveChildrenTo for float reparenting.
1248 * XXXbz test float reparenting?
1250 void MoveFramesToEndOfIBSplit(nsFrameConstructorState& aState,
1251 nsIFrame* aExistingEndFrame,
1252 nsIFrame* aFramesToMove,
1253 nsIFrame* aBlockPart,
1254 nsFrameConstructorState* aTargetState);
1256 nsresult ProcessInlineChildren(nsFrameConstructorState& aState,
1257 nsIContent* aContent,
1258 nsIFrame* aFrame,
1259 PRBool aCanHaveGeneratedContent,
1260 nsFrameItems& aFrameItems,
1261 PRBool* aKidsAllInline);
1263 // Determine whether we need to wipe out what we just did and start over
1264 // because we're doing something like adding block kids to an inline frame
1265 // (and therefore need an {ib} split). If aIsAppend is true, aPrevSibling is
1266 // ignored. Otherwise it may be used to determine whether to reframe when
1267 // inserting into the block of an {ib} split.
1268 // @return PR_TRUE if we reconstructed the containing block, PR_FALSE
1269 // otherwise
1270 PRBool WipeContainingBlock(nsFrameConstructorState& aState,
1271 nsIFrame* aContainingBlock,
1272 nsIFrame* aFrame,
1273 const nsFrameItems& aFrameList,
1274 PRBool aIsAppend,
1275 nsIFrame* aPrevSibling);
1277 nsresult ReframeContainingBlock(nsIFrame* aFrame);
1279 nsresult StyleChangeReflow(nsIFrame* aFrame);
1281 /** Helper function that searches the immediate child frames
1282 * (and their children if the frames are "special")
1283 * for a frame that maps the specified content object
1285 * @param aParentFrame the primary frame for aParentContent
1286 * @param aContent the content node for which we seek a frame
1287 * @param aParentContent the parent for aContent
1288 * @param aHint an optional hint used to make the search for aFrame faster
1290 nsIFrame* FindFrameWithContent(nsFrameManager* aFrameManager,
1291 nsIFrame* aParentFrame,
1292 nsIContent* aParentContent,
1293 nsIContent* aContent,
1294 nsFindFrameHint* aHint);
1296 //----------------------------------------
1298 // Methods support :first-letter style
1300 void CreateFloatingLetterFrame(nsFrameConstructorState& aState,
1301 nsIFrame* aBlockFrame,
1302 nsIContent* aTextContent,
1303 nsIFrame* aTextFrame,
1304 nsIContent* aBlockContent,
1305 nsIFrame* aParentFrame,
1306 nsStyleContext* aStyleContext,
1307 nsFrameItems& aResult);
1309 nsresult CreateLetterFrame(nsIFrame* aBlockFrame,
1310 nsIContent* aTextContent,
1311 nsIFrame* aParentFrame,
1312 nsFrameItems& aResult);
1314 nsresult WrapFramesInFirstLetterFrame(nsIContent* aBlockContent,
1315 nsIFrame* aBlockFrame,
1316 nsFrameItems& aBlockFrames);
1318 nsresult WrapFramesInFirstLetterFrame(nsIFrame* aBlockFrame,
1319 nsIFrame* aParentFrame,
1320 nsIFrame* aParentFrameList,
1321 nsIFrame** aModifiedParent,
1322 nsIFrame** aTextFrame,
1323 nsIFrame** aPrevFrame,
1324 nsFrameItems& aLetterFrame,
1325 PRBool* aStopLooking);
1327 nsresult RecoverLetterFrames(nsIFrame* aBlockFrame);
1330 nsresult RemoveLetterFrames(nsPresContext* aPresContext,
1331 nsIPresShell* aPresShell,
1332 nsFrameManager* aFrameManager,
1333 nsIFrame* aBlockFrame);
1335 // Recursive helper for RemoveLetterFrames
1336 nsresult RemoveFirstLetterFrames(nsPresContext* aPresContext,
1337 nsIPresShell* aPresShell,
1338 nsFrameManager* aFrameManager,
1339 nsIFrame* aFrame,
1340 PRBool* aStopLooking);
1342 // Special remove method for those pesky floating first-letter frames
1343 nsresult RemoveFloatingFirstLetterFrames(nsPresContext* aPresContext,
1344 nsIPresShell* aPresShell,
1345 nsFrameManager* aFrameManager,
1346 nsIFrame* aBlockFrame,
1347 PRBool* aStopLooking);
1349 // Capture state for the frame tree rooted at the frame associated with the
1350 // content object, aContent
1351 nsresult CaptureStateForFramesOf(nsIContent* aContent,
1352 nsILayoutHistoryState* aHistoryState);
1354 // Capture state for the frame tree rooted at aFrame.
1355 nsresult CaptureStateFor(nsIFrame* aFrame,
1356 nsILayoutHistoryState* aHistoryState);
1358 //----------------------------------------
1360 // Methods support :first-line style
1362 nsresult WrapFramesInFirstLineFrame(nsFrameConstructorState& aState,
1363 nsIContent* aBlockContent,
1364 nsIFrame* aBlockFrame,
1365 nsFrameItems& aFrameItems);
1367 nsresult AppendFirstLineFrames(nsFrameConstructorState& aState,
1368 nsIContent* aContent,
1369 nsIFrame* aBlockFrame,
1370 nsFrameItems& aFrameItems);
1372 nsresult InsertFirstLineFrames(nsFrameConstructorState& aState,
1373 nsIContent* aContent,
1374 nsIFrame* aBlockFrame,
1375 nsIFrame** aParentFrame,
1376 nsIFrame* aPrevSibling,
1377 nsFrameItems& aFrameItems);
1379 nsresult RemoveFixedItems(const nsFrameConstructorState& aState,
1380 nsIFrame* aRootElementFrame);
1382 // Find the right frame to use for aContent when looking for sibling
1383 // frames for aTargetContent. If aPrevSibling is true, this
1384 // will look for last continuations, etc, as necessary. This calls
1385 // IsValidSibling as needed; if that returns false it returns null.
1387 // @param aTargetContentDisplay the CSS display enum for aTargetContent if
1388 // already known, UNSET_DISPLAY otherwise.
1389 nsIFrame* FindFrameForContentSibling(nsIContent* aContent,
1390 nsIContent* aTargetContent,
1391 PRUint8& aTargetContentDisplay,
1392 PRBool aPrevSibling);
1394 // Find the ``rightmost'' frame for the content immediately preceding the one
1395 // aIter points to, following continuations if necessary. aIter is passed by
1396 // value on purpose, so as not to modify the callee's iterator.
1397 nsIFrame* FindPreviousSibling(const ChildIterator& aFirst,
1398 ChildIterator aIter);
1400 // Find the frame for the content node immediately following the one aIter
1401 // points to, following continuations if necessary. aIter is passed by value
1402 // on purpose, so as not to modify the callee's iterator.
1403 nsIFrame* FindNextSibling(ChildIterator aIter,
1404 const ChildIterator& aLast);
1406 // see if aContent and aSibling are legitimate siblings due to restrictions
1407 // imposed by table columns
1408 // XXXbz this code is generally wrong, since the frame for aContent
1409 // may be constructed based on tag, not based on aDisplay!
1410 PRBool IsValidSibling(nsIFrame* aSibling,
1411 nsIContent* aContent,
1412 PRUint8& aDisplay);
1414 void QuotesDirty() {
1415 NS_PRECONDITION(mUpdateCount != 0, "Instant quote updates are bad news");
1416 mQuotesDirty = PR_TRUE;
1419 void CountersDirty() {
1420 NS_PRECONDITION(mUpdateCount != 0, "Instant counter updates are bad news");
1421 mCountersDirty = PR_TRUE;
1424 public:
1425 struct RestyleData;
1426 friend struct RestyleData;
1428 struct RestyleData {
1429 nsReStyleHint mRestyleHint; // What we want to restyle
1430 nsChangeHint mChangeHint; // The minimal change hint for "self"
1433 struct RestyleEnumerateData : public RestyleData {
1434 nsCOMPtr<nsIContent> mContent;
1437 class RestyleEvent;
1438 friend class RestyleEvent;
1440 class RestyleEvent : public nsRunnable {
1441 public:
1442 NS_DECL_NSIRUNNABLE
1443 RestyleEvent(nsCSSFrameConstructor *aConstructor)
1444 : mConstructor(aConstructor) {
1445 NS_PRECONDITION(aConstructor, "Must have a constructor!");
1447 void Revoke() { mConstructor = nsnull; }
1448 private:
1449 nsCSSFrameConstructor *mConstructor;
1452 friend class nsFrameConstructorState;
1454 private:
1456 class LazyGenerateChildrenEvent;
1457 friend class LazyGenerateChildrenEvent;
1459 // See comments of nsCSSFrameConstructor::AddLazyChildren()
1460 class LazyGenerateChildrenEvent : public nsRunnable {
1461 public:
1462 NS_DECL_NSIRUNNABLE
1463 LazyGenerateChildrenEvent(nsIContent *aContent,
1464 nsIPresShell *aPresShell,
1465 nsLazyFrameConstructionCallback* aCallback,
1466 void* aArg)
1467 : mContent(aContent), mPresShell(aPresShell), mCallback(aCallback), mArg(aArg)
1470 private:
1471 nsCOMPtr<nsIContent> mContent;
1472 nsCOMPtr<nsIPresShell> mPresShell;
1473 nsLazyFrameConstructionCallback* mCallback;
1474 void* mArg;
1477 nsIDocument* mDocument; // Weak ref
1478 nsIPresShell* mPresShell; // Weak ref
1480 // See the comment at the start of ConstructRootFrame for more details
1481 // about the following frames.
1483 // This is just the outermost frame for the root element.
1484 nsIFrame* mRootElementFrame;
1485 // This is the frame for the root element that has no pseudo-element style.
1486 nsIFrame* mRootElementStyleFrame;
1487 // This is the containing block for fixed-pos frames --- the viewport
1488 nsIFrame* mFixedContainingBlock;
1489 // This is the containing block that contains the root element ---
1490 // the real "initial containing block" according to CSS 2.1.
1491 nsIFrame* mDocElementContainingBlock;
1492 nsIFrame* mGfxScrollFrame;
1493 nsIFrame* mPageSequenceFrame;
1494 nsQuoteList mQuoteList;
1495 nsCounterManager mCounterManager;
1496 PRUint16 mUpdateCount;
1497 PRUint32 mFocusSuppressCount;
1498 PRPackedBool mQuotesDirty : 1;
1499 PRPackedBool mCountersDirty : 1;
1500 PRPackedBool mIsDestroyingFrameTree : 1;
1501 PRPackedBool mRebuildAllStyleData : 1;
1502 // This is true if mDocElementContainingBlock supports absolute positioning
1503 PRPackedBool mHasRootAbsPosContainingBlock : 1;
1504 PRUint32 mHoverGeneration;
1505 nsChangeHint mRebuildAllExtraHint;
1507 nsRevocableEventPtr<RestyleEvent> mRestyleEvent;
1509 nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
1511 nsDataHashtable<nsISupportsHashKey, RestyleData> mPendingRestyles;
1513 static nsIXBLService * gXBLService;
1516 #endif /* nsCSSFrameConstructor_h___ */