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 mozilla.org code.
16 : *
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.
21 : *
22 : * Contributor(s):
23 : *
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.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : /*
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
41 : */
42 :
43 : #ifndef nsCSSFrameConstructor_h___
44 : #define nsCSSFrameConstructor_h___
45 :
46 : #include "mozilla/Attributes.h"
47 :
48 : #include "nsCOMPtr.h"
49 : #include "nsILayoutHistoryState.h"
50 : #include "nsIXBLService.h"
51 : #include "nsQuoteList.h"
52 : #include "nsCounterManager.h"
53 : #include "nsHashKeys.h"
54 : #include "nsThreadUtils.h"
55 : #include "nsPageContentFrame.h"
56 : #include "nsCSSPseudoElements.h"
57 : #include "RestyleTracker.h"
58 : #include "nsIAnonymousContentCreator.h"
59 : #include "nsFrameManager.h"
60 :
61 : class nsIDocument;
62 : struct nsFrameItems;
63 : struct nsAbsoluteItems;
64 : class nsStyleContext;
65 : struct nsStyleContent;
66 : struct nsStyleDisplay;
67 : class nsIPresShell;
68 : class nsIDOMHTMLSelectElement;
69 : class nsPresContext;
70 : class nsStyleChangeList;
71 : class nsIFrame;
72 : struct nsGenConInitializer;
73 : class ChildIterator;
74 : class nsICSSAnonBoxPseudo;
75 : class nsPageContentFrame;
76 : struct PendingBinding;
77 : class nsRefreshDriver;
78 :
79 : class nsFrameConstructorState;
80 : class nsFrameConstructorSaveState;
81 :
82 : class nsCSSFrameConstructor : public nsFrameManager
83 : {
84 : friend class nsRefreshDriver;
85 :
86 : public:
87 : typedef mozilla::dom::Element Element;
88 : typedef mozilla::css::RestyleTracker RestyleTracker;
89 :
90 : nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell);
91 0 : ~nsCSSFrameConstructor(void) {
92 0 : NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?");
93 0 : }
94 :
95 : struct RestyleData;
96 : friend struct RestyleData;
97 :
98 : // Maintain global objects - gXBLService
99 : static nsIXBLService * GetXBLService();
100 1403 : static void ReleaseGlobals() { NS_IF_RELEASE(gXBLService); }
101 :
102 : // get the alternate text for a content node
103 : static void GetAlternateTextFor(nsIContent* aContent,
104 : nsIAtom* aTag, // content object's tag
105 : nsXPIDLString& aAltText);
106 :
107 : private:
108 : nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
109 : nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
110 :
111 : public:
112 : // XXXbz this method needs to actually return errors!
113 : nsresult ConstructRootFrame(nsIFrame** aNewFrame);
114 :
115 : nsresult ReconstructDocElementHierarchy();
116 :
117 : // Create frames for content nodes that are marked as needing frames. This
118 : // should be called before ProcessPendingRestyles.
119 : // Note: It's the caller's responsibility to make sure to wrap a
120 : // CreateNeededFrames call in a view update batch and a script blocker.
121 : void CreateNeededFrames();
122 :
123 : private:
124 : void CreateNeededFrames(nsIContent* aContent);
125 :
126 : enum Operation {
127 : CONTENTAPPEND,
128 : CONTENTINSERT
129 : };
130 :
131 : // aChild is the child being inserted for inserts, and the first
132 : // child being appended for appends.
133 : bool MaybeConstructLazily(Operation aOperation,
134 : nsIContent* aContainer,
135 : nsIContent* aChild);
136 :
137 : // Issues a single ContentInserted for each child of aContainer in the range
138 : // [aStartChild, aEndChild).
139 : void IssueSingleInsertNofications(nsIContent* aContainer,
140 : nsIContent* aStartChild,
141 : nsIContent* aEndChild,
142 : bool aAllowLazyConstruction);
143 :
144 : // Checks if the children of aContainer in the range [aStartChild, aEndChild)
145 : // can be inserted/appended to one insertion point together. If so, returns
146 : // that insertion point. If not, returns null and issues single
147 : // ContentInserted calls for each child. aEndChild = nsnull indicates that we
148 : // are dealing with an append.
149 : nsIFrame* GetRangeInsertionPoint(nsIContent* aContainer,
150 : nsIFrame* aParentFrame,
151 : nsIContent* aStartChild,
152 : nsIContent* aEndChild,
153 : bool aAllowLazyConstruction);
154 :
155 : // Returns true if parent was recreated due to frameset child, false otherwise.
156 : bool MaybeRecreateForFrameset(nsIFrame* aParentFrame,
157 : nsIContent* aStartChild,
158 : nsIContent* aEndChild);
159 :
160 : public:
161 : /**
162 : * Lazy frame construction is controlled by the aAllowLazyConstruction bool
163 : * parameter of nsCSSFrameConstructor::ContentAppended/Inserted. It is true
164 : * for all inserts/appends as passed from the presshell, except for the
165 : * insert of the root element, which is always non-lazy. Even if the
166 : * aAllowLazyConstruction passed to ContentAppended/Inserted is true we still
167 : * may not be able to construct lazily, so we call MaybeConstructLazily.
168 : * MaybeConstructLazily does not allow lazy construction if any of the
169 : * following are true:
170 : * -we are in chrome
171 : * -the container is in a native anonymous subtree
172 : * -the container is XUL
173 : * -is any of the appended/inserted nodes are XUL or editable
174 : * -(for inserts) the child is anonymous. In the append case this function
175 : * must not be called with anonymous children.
176 : * The XUL and chrome checks are because XBL bindings only get applied at
177 : * frame construction time and some things depend on the bindings getting
178 : * attached synchronously. The editable checks are because the editor seems
179 : * to expect frames to be constructed synchronously.
180 : *
181 : * If MaybeConstructLazily returns false we construct as usual, but if it
182 : * returns true then it adds NODE_NEEDS_FRAME bits to the newly
183 : * inserted/appended nodes and adds NODE_DESCENDANTS_NEED_FRAMES bits to the
184 : * container and up along the parent chain until it hits the root or another
185 : * node with that bit set. Then it posts a restyle event to ensure that a
186 : * flush happens to construct those frames.
187 : *
188 : * When the flush happens the presshell calls
189 : * nsCSSFrameConstructor::CreateNeededFrames. CreateNeededFrames follows any
190 : * nodes with NODE_DESCENDANTS_NEED_FRAMES set down the content tree looking
191 : * for nodes with NODE_NEEDS_FRAME set. It calls ContentAppended for any runs
192 : * of nodes with NODE_NEEDS_FRAME set that are at the end of their childlist,
193 : * and ContentRangeInserted for any other runs that aren't.
194 : *
195 : * If a node is removed from the document then we don't bother unsetting any
196 : * of the lazy bits that might be set on it, its descendants, or any of its
197 : * ancestor nodes because that is a slow operation, the work might be wasted
198 : * if another node gets inserted in its place, and we can clear the bits
199 : * quicker by processing the content tree from top down the next time we call
200 : * CreateNeededFrames. (We do clear the bits when BindToTree is called on any
201 : * nsIContent; so any nodes added to the document will not have any lazy bits
202 : * set.)
203 : */
204 :
205 : // If aAllowLazyConstruction is true then frame construction of the new
206 : // children can be done lazily.
207 : nsresult ContentAppended(nsIContent* aContainer,
208 : nsIContent* aFirstNewContent,
209 : bool aAllowLazyConstruction);
210 :
211 : // If aAllowLazyConstruction is true then frame construction of the new child
212 : // can be done lazily.
213 : nsresult ContentInserted(nsIContent* aContainer,
214 : nsIContent* aChild,
215 : nsILayoutHistoryState* aFrameState,
216 : bool aAllowLazyConstruction);
217 :
218 : // Like ContentInserted but handles inserting the children of aContainer in
219 : // the range [aStartChild, aEndChild). aStartChild must be non-null.
220 : // aEndChild may be null to indicate the range includes all kids after
221 : // aStartChild. If aAllowLazyConstruction is true then frame construction of
222 : // the new children can be done lazily. It is only allowed to be true when
223 : // inserting a single node.
224 : nsresult ContentRangeInserted(nsIContent* aContainer,
225 : nsIContent* aStartChild,
226 : nsIContent* aEndChild,
227 : nsILayoutHistoryState* aFrameState,
228 : bool aAllowLazyConstruction);
229 :
230 : enum RemoveFlags { REMOVE_CONTENT, REMOVE_FOR_RECONSTRUCTION };
231 : nsresult ContentRemoved(nsIContent* aContainer,
232 : nsIContent* aChild,
233 : nsIContent* aOldNextSibling,
234 : RemoveFlags aFlags,
235 : bool* aDidReconstruct);
236 :
237 : nsresult CharacterDataChanged(nsIContent* aContent,
238 : CharacterDataChangeInfo* aInfo);
239 :
240 : nsresult ContentStateChanged(nsIContent* aContent,
241 : nsEventStates aStateMask);
242 :
243 : // generate the child frames and process bindings
244 : nsresult GenerateChildFrames(nsIFrame* aFrame);
245 :
246 : // Should be called when a frame is going to be destroyed and
247 : // WillDestroyFrameTree hasn't been called yet.
248 : void NotifyDestroyingFrame(nsIFrame* aFrame);
249 :
250 : void AttributeWillChange(Element* aElement,
251 : PRInt32 aNameSpaceID,
252 : nsIAtom* aAttribute,
253 : PRInt32 aModType);
254 : void AttributeChanged(Element* aElement,
255 : PRInt32 aNameSpaceID,
256 : nsIAtom* aAttribute,
257 : PRInt32 aModType);
258 :
259 : void BeginUpdate();
260 : void EndUpdate();
261 : void RecalcQuotesAndCounters();
262 :
263 : // Gets called when the presshell is destroying itself and also
264 : // when we tear down our frame tree to reconstruct it
265 : void WillDestroyFrameTree();
266 :
267 : // Get an integer that increments every time there is a style change
268 : // as a result of a change to the :hover content state.
269 0 : PRUint32 GetHoverGeneration() const { return mHoverGeneration; }
270 :
271 : // Note: It's the caller's responsibility to make sure to wrap a
272 : // ProcessRestyledFrames call in a view update batch and a script blocker.
273 : // This function does not call ProcessAttachedQueue() on the binding manager.
274 : // If the caller wants that to happen synchronously, it needs to handle that
275 : // itself.
276 : nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray);
277 :
278 : private:
279 :
280 : friend class mozilla::css::RestyleTracker;
281 :
282 : void RestyleForEmptyChange(Element* aContainer);
283 :
284 : public:
285 : // Restyling for a ContentInserted (notification after insertion) or
286 : // for a CharacterDataChanged. |aContainer| must be non-null; when
287 : // the container is null, no work is needed.
288 : void RestyleForInsertOrChange(Element* aContainer, nsIContent* aChild);
289 :
290 : // This would be the same as RestyleForInsertOrChange if we got the
291 : // notification before the removal. However, we get it after, so we need the
292 : // following sibling in addition to the old child. |aContainer| must be
293 : // non-null; when the container is null, no work is needed. aFollowingSibling
294 : // is the sibling that used to come after aOldChild before the removal.
295 : void RestyleForRemove(Element* aContainer,
296 : nsIContent* aOldChild,
297 : nsIContent* aFollowingSibling);
298 : // Same for a ContentAppended. |aContainer| must be non-null; when
299 : // the container is null, no work is needed.
300 : void RestyleForAppend(Element* aContainer, nsIContent* aFirstNewContent);
301 :
302 : // Process any pending restyles. This should be called after
303 : // CreateNeededFrames.
304 : // Note: It's the caller's responsibility to make sure to wrap a
305 : // ProcessPendingRestyles call in a view update batch and a script blocker.
306 : // This function does not call ProcessAttachedQueue() on the binding manager.
307 : // If the caller wants that to happen synchronously, it needs to handle that
308 : // itself.
309 : void ProcessPendingRestyles();
310 :
311 : // Rebuilds all style data by throwing out the old rule tree and
312 : // building a new one, and additionally applying aExtraHint (which
313 : // must not contain nsChangeHint_ReconstructFrame) to the root frame.
314 : void RebuildAllStyleData(nsChangeHint aExtraHint);
315 :
316 : // See PostRestyleEventCommon below.
317 0 : void PostRestyleEvent(Element* aElement,
318 : nsRestyleHint aRestyleHint,
319 : nsChangeHint aMinChangeHint)
320 : {
321 0 : nsPresContext *presContext = mPresShell->GetPresContext();
322 0 : if (presContext) {
323 : PostRestyleEventCommon(aElement, aRestyleHint, aMinChangeHint,
324 0 : presContext->IsProcessingAnimationStyleChange());
325 : }
326 0 : }
327 :
328 : // See PostRestyleEventCommon below.
329 0 : void PostAnimationRestyleEvent(Element* aElement,
330 : nsRestyleHint aRestyleHint,
331 : nsChangeHint aMinChangeHint)
332 : {
333 0 : PostRestyleEventCommon(aElement, aRestyleHint, aMinChangeHint, true);
334 0 : }
335 : private:
336 : /**
337 : * Notify the frame constructor that an element needs to have its
338 : * style recomputed.
339 : * @param aElement: The element to be restyled.
340 : * @param aRestyleHint: Which nodes need to have selector matching run
341 : * on them.
342 : * @param aMinChangeHint: A minimum change hint for aContent and its
343 : * descendants.
344 : * @param aForAnimation: Whether the style should be computed with or
345 : * without animation data. Animation code
346 : * sometimes needs to pass true; other code
347 : * should generally pass the the pres context's
348 : * IsProcessingAnimationStyleChange() value
349 : * (which is the default value).
350 : */
351 : void PostRestyleEventCommon(Element* aElement,
352 : nsRestyleHint aRestyleHint,
353 : nsChangeHint aMinChangeHint,
354 : bool aForAnimation);
355 : void PostRestyleEventInternal(bool aForLazyConstruction);
356 : public:
357 :
358 : /**
359 : * Asynchronously clear style data from the root frame downwards and ensure
360 : * it will all be rebuilt. This is safe to call anytime; it will schedule
361 : * a restyle and take effect next time style changes are flushed.
362 : * This method is used to recompute the style data when some change happens
363 : * outside of any style rules, like a color preference change or a change
364 : * in a system font size, or to fix things up when an optimization in the
365 : * style data has become invalid. We assume that the root frame will not
366 : * need to be reframed.
367 : */
368 : void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint);
369 :
370 : // Request to create a continuing frame
371 : nsresult CreateContinuingFrame(nsPresContext* aPresContext,
372 : nsIFrame* aFrame,
373 : nsIFrame* aParentFrame,
374 : nsIFrame** aContinuingFrame,
375 : bool aIsFluid = true);
376 :
377 : // Copy over fixed frames from aParentFrame's prev-in-flow
378 : nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
379 :
380 : // Get the XBL insertion point for a child
381 : nsresult GetInsertionPoint(nsIFrame* aParentFrame,
382 : nsIContent* aChildContent,
383 : nsIFrame** aInsertionPoint,
384 : bool* aMultiple = nsnull);
385 :
386 : nsresult CreateListBoxContent(nsPresContext* aPresContext,
387 : nsIFrame* aParentFrame,
388 : nsIFrame* aPrevFrame,
389 : nsIContent* aChild,
390 : nsIFrame** aResult,
391 : bool aIsAppend,
392 : bool aIsScrollbar,
393 : nsILayoutHistoryState* aFrameState);
394 :
395 : // GetInitialContainingBlock() is deprecated in favor of GetRootElementFrame();
396 : // nsIFrame* GetInitialContainingBlock() { return mRootElementFrame; }
397 : // This returns the outermost frame for the root element
398 0 : nsIFrame* GetRootElementFrame() { return mRootElementFrame; }
399 : // This returns the frame for the root element that does not
400 : // have a psuedo-element style
401 0 : nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
402 0 : nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
403 :
404 : // Get the frame that is the parent of the root element.
405 0 : nsIFrame* GetDocElementContainingBlock()
406 0 : { return mDocElementContainingBlock; }
407 :
408 : private:
409 : struct FrameConstructionItem;
410 : class FrameConstructionItemList;
411 :
412 : nsresult ConstructPageFrame(nsIPresShell* aPresShell,
413 : nsPresContext* aPresContext,
414 : nsIFrame* aParentFrame,
415 : nsIFrame* aPrevPageFrame,
416 : nsIFrame*& aPageFrame,
417 : nsIFrame*& aCanvasFrame);
418 :
419 : /* aMinHint is the minimal change that should be made to the element */
420 : // XXXbz do we really need the aPrimaryFrame argument here?
421 : void RestyleElement(Element* aElement,
422 : nsIFrame* aPrimaryFrame,
423 : nsChangeHint aMinHint,
424 : RestyleTracker& aRestyleTracker,
425 : bool aRestyleDescendants);
426 :
427 : nsresult InitAndRestoreFrame (const nsFrameConstructorState& aState,
428 : nsIContent* aContent,
429 : nsIFrame* aParentFrame,
430 : nsIFrame* aPrevInFlow,
431 : nsIFrame* aNewFrame,
432 : bool aAllowCounters = true);
433 :
434 : // aState can be null if not available; it's used as an optimization.
435 : // XXXbz IsValidSibling is the only caller that doesn't pass a state here!
436 : already_AddRefed<nsStyleContext>
437 : ResolveStyleContext(nsIFrame* aParentFrame,
438 : nsIContent* aContent,
439 : nsFrameConstructorState* aState);
440 : already_AddRefed<nsStyleContext>
441 : ResolveStyleContext(nsStyleContext* aParentStyleContext,
442 : nsIContent* aContent,
443 : nsFrameConstructorState* aState);
444 :
445 : // Construct a frame for aContent and put it in aFrameItems. This should
446 : // only be used in cases when it's known that the frame won't need table
447 : // pseudo-frame construction and the like.
448 : nsresult ConstructFrame(nsFrameConstructorState& aState,
449 : nsIContent* aContent,
450 : nsIFrame* aParentFrame,
451 : nsFrameItems& aFrameItems);
452 :
453 : // Add the frame construction items for the given aContent and aParentFrame
454 : // to the list. This might add more than one item in some rare cases.
455 : // If aSuppressWhiteSpaceOptimizations is true, optimizations that
456 : // may suppress the construction of white-space-only text frames
457 : // must be skipped for these items and items around them.
458 : void AddFrameConstructionItems(nsFrameConstructorState& aState,
459 : nsIContent* aContent,
460 : bool aSuppressWhiteSpaceOptimizations,
461 : nsIFrame* aParentFrame,
462 : FrameConstructionItemList& aItems);
463 :
464 : // Construct the frames for the document element. This must always return a
465 : // singe new frame (which may, of course, have a bunch of kids).
466 : // XXXbz no need to return a frame here, imo.
467 : nsresult ConstructDocElementFrame(Element* aDocElement,
468 : nsILayoutHistoryState* aFrameState,
469 : nsIFrame** aNewFrame);
470 :
471 : // Set up our mDocElementContainingBlock correctly for the given root
472 : // content.
473 : nsresult SetUpDocElementContainingBlock(nsIContent* aDocElement);
474 :
475 : /**
476 : * CreateAttributeContent creates a single content/frame combination for an
477 : * |attr(foo)| generated content.
478 : *
479 : * @param aParentContent the parent content for the generated content
480 : * @param aParentFrame the parent frame for the generated frame
481 : * @param aAttrNamespace the namespace of the attribute in question
482 : * @param aAttrName the localname of the attribute
483 : * @param aStyleContext the style context to use
484 : * @param aGeneratedContent the array of generated content to append the
485 : * created content to.
486 : * @param [out] aNewContent the content node we create
487 : * @param [out] aNewFrame the new frame we create
488 : */
489 : nsresult CreateAttributeContent(nsIContent* aParentContent,
490 : nsIFrame* aParentFrame,
491 : PRInt32 aAttrNamespace,
492 : nsIAtom* aAttrName,
493 : nsStyleContext* aStyleContext,
494 : nsCOMArray<nsIContent>& aGeneratedContent,
495 : nsIContent** aNewContent,
496 : nsIFrame** aNewFrame);
497 :
498 : /**
499 : * Create a text node containing the given string. If aText is non-null
500 : * then we also set aText to the returned node.
501 : */
502 : already_AddRefed<nsIContent> CreateGenConTextNode(nsFrameConstructorState& aState,
503 : const nsString& aString,
504 : nsCOMPtr<nsIDOMCharacterData>* aText,
505 : nsGenConInitializer* aInitializer);
506 :
507 : /**
508 : * Create a content node for the given generated content style.
509 : * The caller takes care of making it SetNativeAnonymous, binding it
510 : * to the document, and creating frames for it.
511 : * @param aParentContent is the node that has the before/after style
512 : * @param aStyleContext is the 'before' or 'after' pseudo-element
513 : * style context
514 : * @param aContentIndex is the index of the content item to create
515 : */
516 : already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState,
517 : nsIContent* aParentContent,
518 : nsStyleContext* aStyleContext,
519 : PRUint32 aContentIndex);
520 :
521 : // aFrame may be null; this method doesn't use it directly in any case.
522 : void CreateGeneratedContentItem(nsFrameConstructorState& aState,
523 : nsIFrame* aFrame,
524 : nsIContent* aContent,
525 : nsStyleContext* aStyleContext,
526 : nsCSSPseudoElements::Type aPseudoElement,
527 : FrameConstructionItemList& aItems);
528 :
529 : // This method can change aFrameList: it can chop off the beginning and put
530 : // it in aParentFrame while putting the remainder into a special sibling of
531 : // aParentFrame. aPrevSibling must be the frame after which aFrameList is to
532 : // be placed on aParentFrame's principal child list. It may be null if
533 : // aFrameList is being added at the beginning of the child list.
534 : nsresult AppendFramesToParent(nsFrameConstructorState& aState,
535 : nsIFrame* aParentFrame,
536 : nsFrameItems& aFrameList,
537 : nsIFrame* aPrevSibling,
538 : bool aIsRecursiveCall = false);
539 :
540 : // BEGIN TABLE SECTION
541 : /**
542 : * Construct an outer table frame. This is the FrameConstructionData
543 : * callback used for the job.
544 : */
545 : nsresult ConstructTable(nsFrameConstructorState& aState,
546 : FrameConstructionItem& aItem,
547 : nsIFrame* aParentFrame,
548 : const nsStyleDisplay* aDisplay,
549 : nsFrameItems& aFrameItems,
550 : nsIFrame** aNewFrame);
551 :
552 : /**
553 : * FrameConstructionData callback used for constructing table rows.
554 : */
555 : nsresult ConstructTableRow(nsFrameConstructorState& aState,
556 : FrameConstructionItem& aItem,
557 : nsIFrame* aParentFrame,
558 : const nsStyleDisplay* aStyleDisplay,
559 : nsFrameItems& aFrameItems,
560 : nsIFrame** aNewFrame);
561 :
562 : /**
563 : * FrameConstructionData callback used for constructing table columns.
564 : */
565 : nsresult ConstructTableCol(nsFrameConstructorState& aState,
566 : FrameConstructionItem& aItem,
567 : nsIFrame* aParentFrame,
568 : const nsStyleDisplay* aStyleDisplay,
569 : nsFrameItems& aFrameItems,
570 : nsIFrame** aNewFrame);
571 :
572 : /**
573 : * FrameConstructionData callback used for constructing table cells.
574 : */
575 : nsresult ConstructTableCell(nsFrameConstructorState& aState,
576 : FrameConstructionItem& aItem,
577 : nsIFrame* aParentFrame,
578 : const nsStyleDisplay* aStyleDisplay,
579 : nsFrameItems& aFrameItems,
580 : nsIFrame** aNewFrame);
581 :
582 : private:
583 : /* An enum of possible parent types for anonymous table object construction */
584 : enum ParentType {
585 : eTypeBlock = 0, /* This includes all non-table-related frames */
586 : eTypeRow,
587 : eTypeRowGroup,
588 : eTypeColGroup,
589 : eTypeTable,
590 : eParentTypeCount
591 : };
592 :
593 : /* 3 bits is enough to handle our ParentType values */
594 : #define FCDATA_PARENT_TYPE_OFFSET 29
595 : /* Macro to get the desired parent type out of an mBits member of
596 : FrameConstructionData */
597 : #define FCDATA_DESIRED_PARENT_TYPE(_bits) \
598 : ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET)
599 : /* Macro to create FrameConstructionData bits out of a desired parent type */
600 : #define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type) \
601 : (((PRUint32)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
602 :
603 : /* Get the parent type that aParentFrame has. */
604 0 : static ParentType GetParentType(nsIFrame* aParentFrame) {
605 0 : return GetParentType(aParentFrame->GetType());
606 : }
607 :
608 : /* Get the parent type for the given nsIFrame type atom */
609 : static ParentType GetParentType(nsIAtom* aFrameType);
610 :
611 : /* A constructor function that just creates an nsIFrame object. The caller
612 : is responsible for initializing the object, adding it to frame lists,
613 : constructing frames for the children, etc.
614 :
615 : @param nsIPresShell the presshell whose arena should be used to allocate
616 : the frame.
617 : @param nsStyleContext the style context to use for the frame. */
618 : typedef nsIFrame* (* FrameCreationFunc)(nsIPresShell*, nsStyleContext*);
619 :
620 : /* A function that can be used to get a FrameConstructionData. Such
621 : a function is allowed to return null.
622 :
623 : @param nsIContent the node for which the frame is being constructed.
624 : @param nsStyleContext the style context to be used for the frame.
625 : */
626 : struct FrameConstructionData;
627 : typedef const FrameConstructionData*
628 : (* FrameConstructionDataGetter)(Element*, nsStyleContext*);
629 :
630 : /* A constructor function that's used for complicated construction tasks.
631 : This is expected to create the new frame, initialize it, add whatever
632 : needs to be added to aFrameItems (XXXbz is that really necessary? Could
633 : caller add? Might there be cases when *aNewFrame or its placeholder is
634 : not the thing that ends up in aFrameItems? If not, would it be safe to do
635 : the add into the frame construction state after processing kids? Look
636 : into this as a followup!), process children as needed, etc. It is NOT
637 : expected to deal with setting the frame on the content.
638 :
639 : @param aState the frame construction state to use.
640 : @param aItem the frame construction item to use
641 : @param aParentFrame the frame to set as the parent of the
642 : newly-constructed frame.
643 : @param aStyleDisplay the display struct from aItem's mStyleContext
644 : @param aFrameItems the frame list to add the new frame (or its
645 : placeholder) to.
646 : @param aFrame out param handing out the frame that was constructed. This
647 : frame is what the caller will set as the frame on the content.
648 : */
649 : typedef nsresult
650 : (nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState,
651 : FrameConstructionItem& aItem,
652 : nsIFrame* aParentFrame,
653 : const nsStyleDisplay* aStyleDisplay,
654 : nsFrameItems& aFrameItems,
655 : nsIFrame** aFrame);
656 :
657 : /* Bits that modify the way a FrameConstructionData is handled */
658 :
659 : /* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not
660 : be set as the primary frame on the content node. This should only be used
661 : in very rare cases when we create more than one frame for a given content
662 : node. */
663 : #define FCDATA_SKIP_FRAMESET 0x1
664 : /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
665 : FrameConstructionData is a getter function that can be used to get the
666 : actual FrameConstructionData to use. */
667 : #define FCDATA_FUNC_IS_DATA_GETTER 0x2
668 : /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData
669 : has an mFullConstructor. In this case, there is no relevant mData or
670 : mFunc */
671 : #define FCDATA_FUNC_IS_FULL_CTOR 0x4
672 : /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to
673 : float or be absolutely positioned. This can also be used with
674 : FCDATA_FUNC_IS_FULL_CTOR to indicate what the full-constructor
675 : function will do. */
676 : #define FCDATA_DISALLOW_OUT_OF_FLOW 0x8
677 : /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a
678 : null absolute containing block before processing children for this
679 : frame. If this is not set, the frame will be pushed as the
680 : absolute containing block as needed, based on its style */
681 : #define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10
682 : /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame
683 : will be wrapped in blocks. This is only usable for MathML at the
684 : moment. */
685 : #define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20
686 : /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the
687 : content. If this bit is set, nothing else in the struct needs to be
688 : set. */
689 : #define FCDATA_SUPPRESS_FRAME 0x40
690 : /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
691 : a scrollframe if its overflow type so requires. */
692 : #define FCDATA_MAY_NEED_SCROLLFRAME 0x80
693 : #ifdef MOZ_XUL
694 : /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame. These need
695 : some really weird special handling. */
696 : #define FCDATA_IS_POPUP 0x100
697 : #endif /* MOZ_XUL */
698 : /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
699 : absolute containing block, no matter what its style says. */
700 : #define FCDATA_SKIP_ABSPOS_PUSH 0x200
701 : /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated
702 : content when processing kids of this frame. This should not be used with
703 : FCDATA_FUNC_IS_FULL_CTOR */
704 : #define FCDATA_DISALLOW_GENERATED_CONTENT 0x400
705 : /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of
706 : table-related thing and we should not attempt to fetch a table-cell parent
707 : for it if it's inside another table-related frame. */
708 : #define FCDATA_IS_TABLE_PART 0x800
709 : /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS
710 : inline box. */
711 : #define FCDATA_IS_INLINE 0x1000
712 : /* If FCDATA_IS_LINE_PARTICIPANT is set, the frame is something that will
713 : return true for IsFrameOfType(nsIFrame::eLineParticipant) */
714 : #define FCDATA_IS_LINE_PARTICIPANT 0x2000
715 : /* If FCDATA_IS_LINE_BREAK is set, the frame is something that will
716 : induce a line break boundary before and after itself. */
717 : #define FCDATA_IS_LINE_BREAK 0x4000
718 : /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing
719 : children. This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */
720 : #define FCDATA_ALLOW_BLOCK_STYLES 0x8000
721 : /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant
722 : FrameConstructionItem instead of trying to process the content's children.
723 : This can be used with or without FCDATA_FUNC_IS_FULL_CTOR.
724 : The child items might still need table pseudo processing. */
725 : #define FCDATA_USE_CHILD_ITEMS 0x10000
726 : /* If FCDATA_FORCED_NON_SCROLLABLE_BLOCK is set, then this block
727 : would have been scrollable but has been forced to be
728 : non-scrollable due to being in a paginated context. */
729 : #define FCDATA_FORCED_NON_SCROLLABLE_BLOCK 0x20000
730 : /* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a
731 : block formatting context wrapper around the kids of this frame
732 : using the FrameConstructionData's mPseudoAtom for its anonymous
733 : box type. */
734 : #define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000
735 :
736 : /* Structure representing information about how a frame should be
737 : constructed. */
738 : struct FrameConstructionData {
739 : // Flag bits that can modify the way the construction happens
740 : PRUint32 mBits;
741 : // We have exactly one of three types of functions, so use a union for
742 : // better cache locality for the ones that aren't pointer-to-member. That
743 : // one needs to be separate, because we can't cast between it and the
744 : // others and hence wouldn't be able to initialize the union without a
745 : // constructor and all the resulting generated code. See documentation
746 : // above for FrameCreationFunc, FrameConstructionDataGetter, and
747 : // FrameFullConstructor to see what the functions would do.
748 : union Func {
749 : FrameCreationFunc mCreationFunc;
750 : FrameConstructionDataGetter mDataGetter;
751 : } mFunc;
752 : FrameFullConstructor mFullConstructor;
753 : // For cases when FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, the
754 : // anonymous box type to use for that wrapper.
755 : nsICSSAnonBoxPseudo * const * const mAnonBoxPseudo;
756 : };
757 :
758 : /* Structure representing a mapping of an atom to a FrameConstructionData.
759 : This can be used with non-static atoms, assuming that the nsIAtom* is
760 : stored somewhere that this struct can point to (that is, a static
761 : nsIAtom*) and that it's allocated before the struct is ever used. */
762 : struct FrameConstructionDataByTag {
763 : // Pointer to nsIAtom* is used because we want to initialize this
764 : // statically, so before our atom tables are set up.
765 : const nsIAtom * const * const mTag;
766 : const FrameConstructionData mData;
767 : };
768 :
769 : /* Structure representing a mapping of an integer to a
770 : FrameConstructionData. There are no magic integer values here. */
771 : struct FrameConstructionDataByInt {
772 : /* Could be used for display or whatever else */
773 : const PRInt32 mInt;
774 : const FrameConstructionData mData;
775 : };
776 :
777 : /* Structure that has a FrameConstructionData and style context pseudo-type
778 : for a table pseudo-frame */
779 : struct PseudoParentData {
780 : const FrameConstructionData mFCData;
781 : nsICSSAnonBoxPseudo * const * const mPseudoType;
782 : };
783 : /* Array of such structures that we use to properly construct table
784 : pseudo-frames as needed */
785 : static const PseudoParentData sPseudoParentData[eParentTypeCount];
786 :
787 : /* A function that takes an integer, content, style context, and array of
788 : FrameConstructionDataByInts and finds the appropriate frame construction
789 : data to use and returns it. This can return null if none of the integers
790 : match or if the matching integer has a FrameConstructionDataGetter that
791 : returns null. */
792 : static const FrameConstructionData*
793 : FindDataByInt(PRInt32 aInt, Element* aElement,
794 : nsStyleContext* aStyleContext,
795 : const FrameConstructionDataByInt* aDataPtr,
796 : PRUint32 aDataLength);
797 :
798 : /* A function that takes a tag, content, style context, and array of
799 : FrameConstructionDataByTags and finds the appropriate frame construction
800 : data to use and returns it. This can return null if none of the tags
801 : match or if the matching tag has a FrameConstructionDataGetter that
802 : returns null. */
803 : static const FrameConstructionData*
804 : FindDataByTag(nsIAtom* aTag, Element* aElement,
805 : nsStyleContext* aStyleContext,
806 : const FrameConstructionDataByTag* aDataPtr,
807 : PRUint32 aDataLength);
808 :
809 : /* A class representing a list of FrameConstructionItems */
810 : class FrameConstructionItemList {
811 : public:
812 0 : FrameConstructionItemList() :
813 : mInlineCount(0),
814 : mBlockCount(0),
815 : mLineParticipantCount(0),
816 : mItemCount(0),
817 : mLineBoundaryAtStart(false),
818 : mLineBoundaryAtEnd(false),
819 0 : mParentHasNoXBLChildren(false)
820 : {
821 0 : PR_INIT_CLIST(&mItems);
822 0 : memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
823 0 : }
824 :
825 0 : ~FrameConstructionItemList() {
826 0 : PRCList* cur = PR_NEXT_LINK(&mItems);
827 0 : while (cur != &mItems) {
828 0 : PRCList* next = PR_NEXT_LINK(cur);
829 0 : delete ToItem(cur);
830 0 : cur = next;
831 : }
832 :
833 : // Leaves our mItems pointing to deleted memory in both directions,
834 : // but that's OK at this point.
835 0 : }
836 :
837 0 : void SetLineBoundaryAtStart(bool aBoundary) { mLineBoundaryAtStart = aBoundary; }
838 0 : void SetLineBoundaryAtEnd(bool aBoundary) { mLineBoundaryAtEnd = aBoundary; }
839 0 : void SetParentHasNoXBLChildren(bool aHasNoXBLChildren) {
840 0 : mParentHasNoXBLChildren = aHasNoXBLChildren;
841 0 : }
842 0 : bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; }
843 0 : bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; }
844 0 : bool ParentHasNoXBLChildren() { return mParentHasNoXBLChildren; }
845 0 : bool IsEmpty() const { return PR_CLIST_IS_EMPTY(&mItems); }
846 0 : bool AnyItemsNeedBlockParent() const { return mLineParticipantCount != 0; }
847 0 : bool AreAllItemsInline() const { return mInlineCount == mItemCount; }
848 0 : bool AreAllItemsBlock() const { return mBlockCount == mItemCount; }
849 0 : bool AllWantParentType(ParentType aDesiredParentType) const {
850 0 : return mDesiredParentCounts[aDesiredParentType] == mItemCount;
851 : }
852 :
853 : // aSuppressWhiteSpaceOptimizations is true if optimizations that
854 : // skip constructing whitespace frames for this item or items
855 : // around it cannot be performed.
856 0 : FrameConstructionItem* AppendItem(const FrameConstructionData* aFCData,
857 : nsIContent* aContent,
858 : nsIAtom* aTag,
859 : PRInt32 aNameSpaceID,
860 : PendingBinding* aPendingBinding,
861 : already_AddRefed<nsStyleContext> aStyleContext,
862 : bool aSuppressWhiteSpaceOptimizations)
863 : {
864 : FrameConstructionItem* item =
865 : new FrameConstructionItem(aFCData, aContent, aTag, aNameSpaceID,
866 : aPendingBinding, aStyleContext,
867 0 : aSuppressWhiteSpaceOptimizations);
868 0 : PR_APPEND_LINK(item, &mItems);
869 0 : ++mItemCount;
870 0 : ++mDesiredParentCounts[item->DesiredParentType()];
871 0 : return item;
872 : }
873 :
874 0 : void InlineItemAdded() { ++mInlineCount; }
875 0 : void BlockItemAdded() { ++mBlockCount; }
876 0 : void LineParticipantItemAdded() { ++mLineParticipantCount; }
877 :
878 : class Iterator;
879 : friend class Iterator;
880 :
881 : class Iterator {
882 : public:
883 0 : Iterator(FrameConstructionItemList& list) :
884 : mCurrent(PR_NEXT_LINK(&list.mItems)),
885 : mEnd(&list.mItems),
886 0 : mList(list)
887 0 : {}
888 0 : Iterator(const Iterator& aOther) :
889 : mCurrent(aOther.mCurrent),
890 : mEnd(aOther.mEnd),
891 0 : mList(aOther.mList)
892 0 : {}
893 :
894 0 : bool operator==(const Iterator& aOther) const {
895 0 : NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
896 0 : return mCurrent == aOther.mCurrent;
897 : }
898 0 : bool operator!=(const Iterator& aOther) const {
899 0 : return !(*this == aOther);
900 : }
901 0 : Iterator& operator=(const Iterator& aOther) {
902 0 : NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
903 0 : mCurrent = aOther.mCurrent;
904 0 : return *this;
905 : }
906 :
907 0 : FrameConstructionItemList* List() {
908 0 : return &mList;
909 : }
910 :
911 : operator FrameConstructionItem& () {
912 : return item();
913 : }
914 :
915 0 : FrameConstructionItem& item() {
916 0 : return *FrameConstructionItemList::ToItem(mCurrent);
917 : }
918 0 : bool IsDone() const { return mCurrent == mEnd; }
919 0 : bool AtStart() const { return mCurrent == PR_NEXT_LINK(mEnd); }
920 0 : void Next() {
921 0 : NS_ASSERTION(!IsDone(), "Should have checked IsDone()!");
922 0 : mCurrent = PR_NEXT_LINK(mCurrent);
923 0 : }
924 0 : void Prev() {
925 0 : NS_ASSERTION(!AtStart(), "Should have checked AtStart()!");
926 0 : mCurrent = PR_PREV_LINK(mCurrent);
927 0 : }
928 0 : void SetToEnd() { mCurrent = mEnd; }
929 :
930 : // Skip over all items that want a parent type different from the given
931 : // one. Return whether the iterator is done after doing that. The
932 : // iterator must not be done when this is called.
933 : inline bool SkipItemsWantingParentType(ParentType aParentType);
934 :
935 : // Skip over whitespace. Return whether the iterator is done after doing
936 : // that. The iterator must not be done, and must be pointing to a
937 : // whitespace item when this is called.
938 : inline bool SkipWhitespace(nsFrameConstructorState& aState);
939 :
940 : // Remove the item pointed to by this iterator from its current list and
941 : // Append it to aTargetList. This iterator is advanced to point to the
942 : // next item in its list. aIter must not be done. aOther must not be
943 : // the list this iterator is iterating over..
944 : void AppendItemToList(FrameConstructionItemList& aTargetList);
945 :
946 : // As above, but moves all items starting with this iterator until we
947 : // get to aEnd; the item pointed to by aEnd is not stolen. This method
948 : // might have optimizations over just looping and doing StealItem for
949 : // some special cases. After this method returns, this iterator will
950 : // point to the item aEnd points to now; aEnd is not modified.
951 : // aTargetList must not be the list this iterator is iterating over.
952 : void AppendItemsToList(const Iterator& aEnd,
953 : FrameConstructionItemList& aTargetList);
954 :
955 : // Insert aItem in this iterator's list right before the item pointed to
956 : // by this iterator. After the insertion, this iterator will continue to
957 : // point to the item it now points to (the one just after the
958 : // newly-inserted item). This iterator is allowed to be done; in that
959 : // case this call just appends the given item to the list.
960 : void InsertItem(FrameConstructionItem* aItem);
961 :
962 : // Delete the items between this iterator and aEnd, including the item
963 : // this iterator currently points to but not including the item pointed
964 : // to by aEnd. When this returns, this iterator will point to the same
965 : // item as aEnd. This iterator must not equal aEnd when this method is
966 : // called.
967 : void DeleteItemsTo(const Iterator& aEnd);
968 :
969 : private:
970 : PRCList* mCurrent;
971 : PRCList* mEnd;
972 : FrameConstructionItemList& mList;
973 : };
974 :
975 : private:
976 0 : static FrameConstructionItem* ToItem(PRCList* item) {
977 0 : return static_cast<FrameConstructionItem*>(item);
978 : }
979 :
980 : // Adjust our various counts for aItem being added or removed. aDelta
981 : // should be either +1 or -1 depending on which is happening.
982 : void AdjustCountsForItem(FrameConstructionItem* aItem, PRInt32 aDelta);
983 :
984 : PRCList mItems;
985 : PRUint32 mInlineCount;
986 : PRUint32 mBlockCount;
987 : PRUint32 mLineParticipantCount;
988 : PRUint32 mItemCount;
989 : PRUint32 mDesiredParentCounts[eParentTypeCount];
990 : // True if there is guaranteed to be a line boundary before the
991 : // frames created by these items
992 : bool mLineBoundaryAtStart;
993 : // True if there is guaranteed to be a line boundary after the
994 : // frames created by these items
995 : bool mLineBoundaryAtEnd;
996 : // True if the parent is guaranteed to have no XBL anonymous children
997 : bool mParentHasNoXBLChildren;
998 : };
999 :
1000 : typedef FrameConstructionItemList::Iterator FCItemIterator;
1001 :
1002 : /* A struct representing an item for which frames might need to be
1003 : * constructed. This contains all the information needed to construct the
1004 : * frame other than the parent frame and whatever would be stored in the
1005 : * frame constructor state. */
1006 : struct FrameConstructionItem : public PRCList {
1007 : // No need to PR_INIT_CLIST in the constructor because the only
1008 : // place that creates us immediately appends us.
1009 0 : FrameConstructionItem(const FrameConstructionData* aFCData,
1010 : nsIContent* aContent,
1011 : nsIAtom* aTag,
1012 : PRInt32 aNameSpaceID,
1013 : PendingBinding* aPendingBinding,
1014 : already_AddRefed<nsStyleContext> aStyleContext,
1015 : bool aSuppressWhiteSpaceOptimizations) :
1016 : mFCData(aFCData), mContent(aContent), mTag(aTag),
1017 : mNameSpaceID(aNameSpaceID),
1018 : mPendingBinding(aPendingBinding), mStyleContext(aStyleContext),
1019 : mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
1020 : mIsText(false), mIsGeneratedContent(false),
1021 : mIsRootPopupgroup(false), mIsAllInline(false), mIsBlock(false),
1022 : mHasInlineEnds(false), mIsPopup(false),
1023 0 : mIsLineParticipant(false)
1024 0 : {}
1025 0 : ~FrameConstructionItem() {
1026 0 : if (mIsGeneratedContent) {
1027 0 : mContent->UnbindFromTree();
1028 0 : NS_RELEASE(mContent);
1029 : }
1030 0 : }
1031 :
1032 0 : ParentType DesiredParentType() {
1033 0 : return FCDATA_DESIRED_PARENT_TYPE(mFCData->mBits);
1034 : }
1035 :
1036 : // Don't call this unless the frametree really depends on the answer!
1037 : // Especially so for generated content, where we don't want to reframe
1038 : // things.
1039 : bool IsWhitespace(nsFrameConstructorState& aState) const;
1040 :
1041 0 : bool IsLineBoundary() const {
1042 0 : return mIsBlock || (mFCData->mBits & FCDATA_IS_LINE_BREAK);
1043 : }
1044 :
1045 : // The FrameConstructionData to use.
1046 : const FrameConstructionData* mFCData;
1047 : // The nsIContent node to use when initializing the new frame.
1048 : nsIContent* mContent;
1049 : // The XBL-resolved tag name to use for frame construction.
1050 : nsIAtom* mTag;
1051 : // The XBL-resolved namespace to use for frame construction.
1052 : PRInt32 mNameSpaceID;
1053 : // The PendingBinding for this frame construction item, if any. May be
1054 : // null. We maintain a list of PendingBindings in the frame construction
1055 : // state in the order in which AddToAttachedQueue should be called on them:
1056 : // depth-first, post-order traversal order. Since we actually traverse the
1057 : // DOM in a mix of breadth-first and depth-first, it is the responsibility
1058 : // of whoever constructs FrameConstructionItem kids of a given
1059 : // FrameConstructionItem to push its mPendingBinding as the current
1060 : // insertion point before doing so and pop it afterward.
1061 : PendingBinding* mPendingBinding;
1062 : // The style context to use for creating the new frame.
1063 : nsRefPtr<nsStyleContext> mStyleContext;
1064 : // Whether optimizations to skip constructing textframes around
1065 : // this content need to be suppressed.
1066 : bool mSuppressWhiteSpaceOptimizations;
1067 : // Whether this is a text content item.
1068 : bool mIsText;
1069 : // Whether this is a generated content container.
1070 : // If it is, mContent is a strong pointer.
1071 : bool mIsGeneratedContent;
1072 : // Whether this is an item for the root popupgroup.
1073 : bool mIsRootPopupgroup;
1074 : // Whether construction from this item will create only frames that are
1075 : // IsInlineOutside() in the principal child list. This is not precise, but
1076 : // conservative: if true the frames will really be inline, whereas if false
1077 : // they might still all be inline.
1078 : bool mIsAllInline;
1079 : // Whether construction from this item will create only frames that are
1080 : // IsBlockOutside() in the principal child list. This is not precise, but
1081 : // conservative: if true the frames will really be blocks, whereas if false
1082 : // they might still be blocks (and in particular, out-of-flows that didn't
1083 : // find a containing block).
1084 : bool mIsBlock;
1085 : // Whether construction from this item will give leading and trailing
1086 : // inline frames. This is equal to mIsAllInline, except for inline frame
1087 : // items, where it's always true, whereas mIsAllInline might be false due
1088 : // to {ib} splits.
1089 : bool mHasInlineEnds;
1090 : // Whether construction from this item will create a popup that needs to
1091 : // go into the global popup items.
1092 : bool mIsPopup;
1093 : // Whether this item should be treated as a line participant
1094 : bool mIsLineParticipant;
1095 :
1096 : // Child frame construction items.
1097 : FrameConstructionItemList mChildItems;
1098 :
1099 : private:
1100 : FrameConstructionItem(const FrameConstructionItem& aOther); /* not implemented */
1101 : };
1102 :
1103 : /**
1104 : * Function to create the table pseudo items we need.
1105 : * @param aItems the child frame construction items before pseudo creation
1106 : * @param aParentFrame the parent frame we're creating pseudos for
1107 : */
1108 : inline nsresult CreateNeededTablePseudos(nsFrameConstructorState& aState,
1109 : FrameConstructionItemList& aItems,
1110 : nsIFrame* aParentFrame);
1111 :
1112 : /**
1113 : * Function to adjust aParentFrame to deal with captions.
1114 : * @param aParentFrame the frame we think should be the parent. This will be
1115 : * adjusted to point to the right parent frame.
1116 : * @param aFCData the FrameConstructionData that would be used for frame
1117 : * construction.
1118 : * @param aStyleContext the style context for aChildContent
1119 : */
1120 : // XXXbz this function should really go away once we rework pseudo-frame
1121 : // handling to be better. This should simply be part of the job of
1122 : // GetGeometricParent, and stuff like the frameitems and parent frame should
1123 : // be kept track of in the state...
1124 : void AdjustParentFrame(nsIFrame* & aParentFrame,
1125 : const FrameConstructionData* aFCData,
1126 : nsStyleContext* aStyleContext);
1127 :
1128 : // END TABLE SECTION
1129 :
1130 : protected:
1131 : static nsresult CreatePlaceholderFrameFor(nsIPresShell* aPresShell,
1132 : nsIContent* aContent,
1133 : nsIFrame* aFrame,
1134 : nsStyleContext* aStyleContext,
1135 : nsIFrame* aParentFrame,
1136 : nsIFrame* aPrevInFlow,
1137 : nsFrameState aTypeBit,
1138 : nsIFrame** aPlaceholderFrame);
1139 :
1140 : private:
1141 : // ConstructSelectFrame puts the new frame in aFrameItems and
1142 : // handles the kids of the select.
1143 : nsresult ConstructSelectFrame(nsFrameConstructorState& aState,
1144 : FrameConstructionItem& aItem,
1145 : nsIFrame* aParentFrame,
1146 : const nsStyleDisplay* aStyleDisplay,
1147 : nsFrameItems& aFrameItems,
1148 : nsIFrame** aNewFrame);
1149 :
1150 : // ConstructFieldSetFrame puts the new frame in aFrameItems and
1151 : // handles the kids of the fieldset
1152 : nsresult ConstructFieldSetFrame(nsFrameConstructorState& aState,
1153 : FrameConstructionItem& aItem,
1154 : nsIFrame* aParentFrame,
1155 : const nsStyleDisplay* aStyleDisplay,
1156 : nsFrameItems& aFrameItems,
1157 : nsIFrame** aNewFrame);
1158 :
1159 : // aParentFrame might be null. If it is, that means it was an
1160 : // inline frame.
1161 : static const FrameConstructionData* FindTextData(nsIFrame* aParentFrame);
1162 :
1163 : nsresult ConstructTextFrame(const FrameConstructionData* aData,
1164 : nsFrameConstructorState& aState,
1165 : nsIContent* aContent,
1166 : nsIFrame* aParentFrame,
1167 : nsStyleContext* aStyleContext,
1168 : nsFrameItems& aFrameItems);
1169 :
1170 : // If aPossibleTextContent is a text node and doesn't have a frame, append a
1171 : // frame construction item for it to aItems.
1172 : void AddTextItemIfNeeded(nsFrameConstructorState& aState,
1173 : nsIFrame* aParentFrame,
1174 : nsIContent* aPossibleTextContent,
1175 : FrameConstructionItemList& aItems);
1176 :
1177 : // If aParentContent's child aContent is a text node and
1178 : // doesn't have a frame, try to create a frame for it.
1179 : void ReframeTextIfNeeded(nsIContent* aParentContent,
1180 : nsIContent* aContent);
1181 :
1182 : void AddPageBreakItem(nsIContent* aContent,
1183 : nsStyleContext* aMainStyleContext,
1184 : FrameConstructionItemList& aItems);
1185 :
1186 : // Function to find FrameConstructionData for aElement. Will return
1187 : // null if aElement is not HTML.
1188 : // aParentFrame might be null. If it is, that means it was an
1189 : // inline frame.
1190 : static const FrameConstructionData* FindHTMLData(Element* aContent,
1191 : nsIAtom* aTag,
1192 : PRInt32 aNameSpaceID,
1193 : nsIFrame* aParentFrame,
1194 : nsStyleContext* aStyleContext);
1195 : // HTML data-finding helper functions
1196 : static const FrameConstructionData*
1197 : FindImgData(Element* aElement, nsStyleContext* aStyleContext);
1198 : static const FrameConstructionData*
1199 : FindImgControlData(Element* aElement, nsStyleContext* aStyleContext);
1200 : static const FrameConstructionData*
1201 : FindInputData(Element* aElement, nsStyleContext* aStyleContext);
1202 : static const FrameConstructionData*
1203 : FindObjectData(Element* aElement, nsStyleContext* aStyleContext);
1204 : static const FrameConstructionData*
1205 : FindCanvasData(Element* aElement, nsStyleContext* aStyleContext);
1206 :
1207 : /* Construct a frame from the given FrameConstructionItem. This function
1208 : will handle adding the frame to frame lists, processing children, setting
1209 : the frame as the primary frame for the item's content, and so forth.
1210 :
1211 : @param aItem the FrameConstructionItem to use.
1212 : @param aState the frame construction state to use.
1213 : @param aParentFrame the frame to set as the parent of the
1214 : newly-constructed frame.
1215 : @param aFrameItems the frame list to add the new frame (or its
1216 : placeholder) to.
1217 : */
1218 : nsresult ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
1219 : nsFrameConstructorState& aState,
1220 : nsIFrame* aParentFrame,
1221 : nsFrameItems& aFrameItems);
1222 :
1223 : // possible flags for AddFrameConstructionItemInternal's aFlags argument
1224 : /* Allow xbl:base to affect the tag/namespace used. */
1225 : #define ITEM_ALLOW_XBL_BASE 0x1
1226 : /* Allow page-break before and after items to be created if the
1227 : style asks for them. */
1228 : #define ITEM_ALLOW_PAGE_BREAK 0x2
1229 : /* The item is a generated content item. */
1230 : #define ITEM_IS_GENERATED_CONTENT 0x4
1231 : // The guts of AddFrameConstructionItems
1232 : // aParentFrame might be null. If it is, that means it was an
1233 : // inline frame.
1234 : void AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
1235 : nsIContent* aContent,
1236 : nsIFrame* aParentFrame,
1237 : nsIAtom* aTag,
1238 : PRInt32 aNameSpaceID,
1239 : bool aSuppressWhiteSpaceOptimizations,
1240 : nsStyleContext* aStyleContext,
1241 : PRUint32 aFlags,
1242 : FrameConstructionItemList& aItems);
1243 :
1244 : /**
1245 : * Construct frames for the given item list and parent frame, and put the
1246 : * resulting frames in aFrameItems.
1247 : */
1248 : nsresult ConstructFramesFromItemList(nsFrameConstructorState& aState,
1249 : FrameConstructionItemList& aItems,
1250 : nsIFrame* aParentFrame,
1251 : nsFrameItems& aFrameItems);
1252 : nsresult ConstructFramesFromItem(nsFrameConstructorState& aState,
1253 : FCItemIterator& aItem,
1254 : nsIFrame* aParentFrame,
1255 : nsFrameItems& aFrameItems);
1256 : static bool AtLineBoundary(FCItemIterator& aIter);
1257 :
1258 : nsresult CreateAnonymousFrames(nsFrameConstructorState& aState,
1259 : nsIContent* aParent,
1260 : nsIFrame* aParentFrame,
1261 : PendingBinding * aPendingBinding,
1262 : nsFrameItems& aChildItems);
1263 :
1264 : nsresult GetAnonymousContent(nsIContent* aParent,
1265 : nsIFrame* aParentFrame,
1266 : nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonContent);
1267 :
1268 : //MathML Mod - RBS
1269 : /**
1270 : * Takes the frames in aBlockItems and wraps them in a new anonymous block
1271 : * frame whose content is aContent and whose parent will be aParentFrame.
1272 : * The anonymous block is added to aNewItems and aBlockItems is cleared.
1273 : */
1274 : nsresult FlushAccumulatedBlock(nsFrameConstructorState& aState,
1275 : nsIContent* aContent,
1276 : nsIFrame* aParentFrame,
1277 : nsFrameItems* aBlockItems,
1278 : nsFrameItems* aNewItems);
1279 :
1280 : // Function to find FrameConstructionData for aContent. Will return
1281 : // null if aContent is not MathML.
1282 : static const FrameConstructionData* FindMathMLData(Element* aElement,
1283 : nsIAtom* aTag,
1284 : PRInt32 aNameSpaceID,
1285 : nsStyleContext* aStyleContext);
1286 :
1287 : // Function to find FrameConstructionData for aContent. Will return
1288 : // null if aContent is not XUL.
1289 : static const FrameConstructionData* FindXULTagData(Element* aElement,
1290 : nsIAtom* aTag,
1291 : PRInt32 aNameSpaceID,
1292 : nsStyleContext* aStyleContext);
1293 : // XUL data-finding helper functions and structures
1294 : #ifdef MOZ_XUL
1295 : static const FrameConstructionData*
1296 : FindPopupGroupData(Element* aElement, nsStyleContext* aStyleContext);
1297 : // sXULTextBoxData used for both labels and descriptions
1298 : static const FrameConstructionData sXULTextBoxData;
1299 : static const FrameConstructionData*
1300 : FindXULLabelData(Element* aElement, nsStyleContext* aStyleContext);
1301 : static const FrameConstructionData*
1302 : FindXULDescriptionData(Element* aElement, nsStyleContext* aStyleContext);
1303 : #ifdef XP_MACOSX
1304 : static const FrameConstructionData*
1305 : FindXULMenubarData(Element* aElement, nsStyleContext* aStyleContext);
1306 : #endif /* XP_MACOSX */
1307 : static const FrameConstructionData*
1308 : FindXULListBoxBodyData(Element* aElement, nsStyleContext* aStyleContext);
1309 : static const FrameConstructionData*
1310 : FindXULListItemData(Element* aElement, nsStyleContext* aStyleContext);
1311 : #endif /* MOZ_XUL */
1312 :
1313 : // Function to find FrameConstructionData for aContent using one of the XUL
1314 : // display types. Will return null if aDisplay doesn't have a XUL display
1315 : // type. This function performs no other checks, so should only be called if
1316 : // we know for sure that the content is not something that should get a frame
1317 : // constructed by tag.
1318 : static const FrameConstructionData*
1319 : FindXULDisplayData(const nsStyleDisplay* aDisplay,
1320 : Element* aElement,
1321 : nsStyleContext* aStyleContext);
1322 :
1323 : // SVG - rods
1324 : static const FrameConstructionData* FindSVGData(Element* aElement,
1325 : nsIAtom* aTag,
1326 : PRInt32 aNameSpaceID,
1327 : nsIFrame* aParentFrame,
1328 : nsStyleContext* aStyleContext);
1329 :
1330 : /* Not static because it does PropagateScrollToViewport. If this
1331 : changes, make this static */
1332 : const FrameConstructionData*
1333 : FindDisplayData(const nsStyleDisplay* aDisplay, Element* aElement,
1334 : nsStyleContext* aStyleContext);
1335 :
1336 : /**
1337 : * Construct a scrollable block frame
1338 : */
1339 : nsresult ConstructScrollableBlock(nsFrameConstructorState& aState,
1340 : FrameConstructionItem& aItem,
1341 : nsIFrame* aParentFrame,
1342 : const nsStyleDisplay* aDisplay,
1343 : nsFrameItems& aFrameItems,
1344 : nsIFrame** aNewFrame);
1345 :
1346 : /**
1347 : * Construct a non-scrollable block frame
1348 : */
1349 : nsresult ConstructNonScrollableBlock(nsFrameConstructorState& aState,
1350 : FrameConstructionItem& aItem,
1351 : nsIFrame* aParentFrame,
1352 : const nsStyleDisplay* aDisplay,
1353 : nsFrameItems& aFrameItems,
1354 : nsIFrame** aNewFrame);
1355 :
1356 : /**
1357 : * Construct the frames for the children of aContent. "children" is defined
1358 : * as "whatever ChildIterator returns for aContent". This means we're
1359 : * basically operating on children in the "flattened tree" per sXBL/XBL2.
1360 : * This method will also handle constructing ::before, ::after,
1361 : * ::first-letter, and ::first-line frames, as needed and if allowed.
1362 : *
1363 : * If the parent is a float containing block, this method will handle pushing
1364 : * it as the float containing block in aState (so there's no need for callers
1365 : * to push it themselves).
1366 : *
1367 : * @param aState the frame construction state
1368 : * @param aContent the content node whose children need frames
1369 : * @param aStyleContext the style context for aContent
1370 : * @param aFrame the frame to use as the parent frame for the new in-flow
1371 : * kids. Note that this must be its own content insertion frame, but
1372 : * need not be be the primary frame for aContent. This frame will be
1373 : * pushed as the float containing block, as needed. aFrame is also
1374 : * used to find the parent style context for the kids' style contexts
1375 : * (not necessary aFrame's style context).
1376 : * @param aCanHaveGeneratedContent Whether to allow :before and
1377 : * :after styles on the parent.
1378 : * @param aFrameItems the list in which we should place the in-flow children
1379 : * @param aAllowBlockStyles Whether to allow first-letter and first-line
1380 : * styles on the parent.
1381 : * @param aPendingBinding Make sure to push this into aState before doing any
1382 : * child item construction.
1383 : * @param aPossiblyLeafFrame if non-null, this should be used for the isLeaf
1384 : * test and the anonymous content creation. If null, aFrame will be
1385 : * used.
1386 : */
1387 : nsresult ProcessChildren(nsFrameConstructorState& aState,
1388 : nsIContent* aContent,
1389 : nsStyleContext* aStyleContext,
1390 : nsIFrame* aFrame,
1391 : const bool aCanHaveGeneratedContent,
1392 : nsFrameItems& aFrameItems,
1393 : const bool aAllowBlockStyles,
1394 : PendingBinding* aPendingBinding,
1395 : nsIFrame* aPossiblyLeafFrame = nsnull);
1396 :
1397 : nsIFrame* GetFrameFor(nsIContent* aContent);
1398 :
1399 : /**
1400 : * These two functions are used when we start frame creation from a non-root
1401 : * element. They should recreate the same state that we would have
1402 : * arrived at if we had built frames from the root frame to aFrame.
1403 : * Therefore, any calls to PushFloatContainingBlock and
1404 : * PushAbsoluteContainingBlock during frame construction should get
1405 : * corresponding logic in these functions.
1406 : */
1407 : public:
1408 : nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame);
1409 : private:
1410 : nsIFrame* GetFloatContainingBlock(nsIFrame* aFrame);
1411 :
1412 : nsIContent* PropagateScrollToViewport();
1413 :
1414 : // Build a scroll frame:
1415 : // Calls BeginBuildingScrollFrame, InitAndRestoreFrame, and then FinishBuildingScrollFrame.
1416 : // @param aNewFrame the created scrollframe --- output only
1417 : // @param aParentFrame the geometric parent that the scrollframe will have.
1418 : nsresult
1419 : BuildScrollFrame(nsFrameConstructorState& aState,
1420 : nsIContent* aContent,
1421 : nsStyleContext* aContentStyle,
1422 : nsIFrame* aScrolledFrame,
1423 : nsIFrame* aParentFrame,
1424 : nsIFrame*& aNewFrame);
1425 :
1426 : // Builds the initial ScrollFrame
1427 : already_AddRefed<nsStyleContext>
1428 : BeginBuildingScrollFrame(nsFrameConstructorState& aState,
1429 : nsIContent* aContent,
1430 : nsStyleContext* aContentStyle,
1431 : nsIFrame* aParentFrame,
1432 : nsIAtom* aScrolledPseudo,
1433 : bool aIsRoot,
1434 : nsIFrame*& aNewFrame);
1435 :
1436 : // Completes the building of the scrollframe:
1437 : // Creates a view for the scrolledframe and makes it the child of the scrollframe.
1438 : void
1439 : FinishBuildingScrollFrame(nsIFrame* aScrollFrame,
1440 : nsIFrame* aScrolledFrame);
1441 :
1442 : // InitializeSelectFrame puts scrollFrame in aFrameItems if aBuildCombobox is false
1443 : // aBuildCombobox indicates if we are building a combobox that has a dropdown
1444 : // popup widget or not.
1445 : nsresult
1446 : InitializeSelectFrame(nsFrameConstructorState& aState,
1447 : nsIFrame* scrollFrame,
1448 : nsIFrame* scrolledFrame,
1449 : nsIContent* aContent,
1450 : nsIFrame* aParentFrame,
1451 : nsStyleContext* aStyleContext,
1452 : bool aBuildCombobox,
1453 : PendingBinding* aPendingBinding,
1454 : nsFrameItems& aFrameItems);
1455 :
1456 : nsresult MaybeRecreateFramesForElement(Element* aElement);
1457 :
1458 : // If aAsyncInsert is true then a restyle event will be posted to handle the
1459 : // required ContentInserted call instead of doing it immediately.
1460 : nsresult RecreateFramesForContent(nsIContent* aContent, bool aAsyncInsert);
1461 :
1462 : // If removal of aFrame from the frame tree requires reconstruction of some
1463 : // containing block (either of aFrame or of its parent) due to {ib} splits or
1464 : // table pseudo-frames, recreate the relevant frame subtree. The return value
1465 : // indicates whether this happened. If this method returns true, *aResult is
1466 : // the return value of ReframeContainingBlock or RecreateFramesForContent. If
1467 : // this method returns false, the value of *aResult is not affected. aFrame
1468 : // and aResult must not be null. aFrame must be the result of a
1469 : // GetPrimaryFrame() call on a content node (which means its parent is also
1470 : // not null).
1471 : bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
1472 : nsresult* aResult);
1473 :
1474 : nsresult CreateContinuingOuterTableFrame(nsIPresShell* aPresShell,
1475 : nsPresContext* aPresContext,
1476 : nsIFrame* aFrame,
1477 : nsIFrame* aParentFrame,
1478 : nsIContent* aContent,
1479 : nsStyleContext* aStyleContext,
1480 : nsIFrame** aContinuingFrame);
1481 :
1482 : nsresult CreateContinuingTableFrame(nsIPresShell* aPresShell,
1483 : nsPresContext* aPresContext,
1484 : nsIFrame* aFrame,
1485 : nsIFrame* aParentFrame,
1486 : nsIContent* aContent,
1487 : nsStyleContext* aStyleContext,
1488 : nsIFrame** aContinuingFrame);
1489 :
1490 : //----------------------------------------
1491 :
1492 : // Methods support creating block frames and their children
1493 :
1494 : already_AddRefed<nsStyleContext>
1495 : GetFirstLetterStyle(nsIContent* aContent,
1496 : nsStyleContext* aStyleContext);
1497 :
1498 : already_AddRefed<nsStyleContext>
1499 : GetFirstLineStyle(nsIContent* aContent,
1500 : nsStyleContext* aStyleContext);
1501 :
1502 : bool ShouldHaveFirstLetterStyle(nsIContent* aContent,
1503 : nsStyleContext* aStyleContext);
1504 :
1505 : // Check whether a given block has first-letter style. Make sure to
1506 : // only pass in blocks! And don't pass in null either.
1507 : bool HasFirstLetterStyle(nsIFrame* aBlockFrame);
1508 :
1509 : bool ShouldHaveFirstLineStyle(nsIContent* aContent,
1510 : nsStyleContext* aStyleContext);
1511 :
1512 : void ShouldHaveSpecialBlockStyle(nsIContent* aContent,
1513 : nsStyleContext* aStyleContext,
1514 : bool* aHaveFirstLetterStyle,
1515 : bool* aHaveFirstLineStyle);
1516 :
1517 : // |aContentParentFrame| should be null if it's really the same as
1518 : // |aParentFrame|.
1519 : // @param aFrameItems where we want to put the block in case it's in-flow.
1520 : // @param aNewFrame an in/out parameter. On input it is the block to be
1521 : // constructed. On output it is reset to the outermost
1522 : // frame constructed (e.g. if we need to wrap the block in an
1523 : // nsColumnSetFrame.
1524 : // @param aParentFrame is the desired parent for the (possibly wrapped)
1525 : // block
1526 : // @param aContentParent is the parent the block would have if it
1527 : // were in-flow
1528 : // @param aPendingBinding the pending binding from this block's frame
1529 : // construction item.
1530 : nsresult ConstructBlock(nsFrameConstructorState& aState,
1531 : const nsStyleDisplay* aDisplay,
1532 : nsIContent* aContent,
1533 : nsIFrame* aParentFrame,
1534 : nsIFrame* aContentParentFrame,
1535 : nsStyleContext* aStyleContext,
1536 : nsIFrame** aNewFrame,
1537 : nsFrameItems& aFrameItems,
1538 : bool aAbsPosContainer,
1539 : PendingBinding* aPendingBinding);
1540 :
1541 : nsresult ConstructInline(nsFrameConstructorState& aState,
1542 : FrameConstructionItem& aItem,
1543 : nsIFrame* aParentFrame,
1544 : const nsStyleDisplay* aDisplay,
1545 : nsFrameItems& aFrameItems,
1546 : nsIFrame** aNewFrame);
1547 :
1548 : /**
1549 : * Create any additional {ib} siblings needed to contain aChildItems and put
1550 : * them in aSiblings.
1551 : *
1552 : * @param aState the frame constructor state
1553 : * @param aInitialInline is an already-existing inline frame that will be
1554 : * part of this {ib} split and come before everything
1555 : * in aSiblings.
1556 : * @param aIsPositioned true if aInitialInline is positioned.
1557 : * @param aChildItems is a child list starting with a block; this method
1558 : * assumes that the inline has already taken all the
1559 : * children it wants. When the method returns aChildItems
1560 : * will be empty.
1561 : * @param aSiblings the nsFrameItems to put the newly-created siblings into.
1562 : *
1563 : * This method is responsible for making any SetFrameIsSpecial calls that are
1564 : * needed.
1565 : */
1566 : void CreateIBSiblings(nsFrameConstructorState& aState,
1567 : nsIFrame* aInitialInline,
1568 : bool aIsPositioned,
1569 : nsFrameItems& aChildItems,
1570 : nsFrameItems& aSiblings);
1571 :
1572 : /**
1573 : * For an inline aParentItem, construct its list of child
1574 : * FrameConstructionItems and set its mIsAllInline flag appropriately.
1575 : */
1576 : void BuildInlineChildItems(nsFrameConstructorState& aState,
1577 : FrameConstructionItem& aParentItem);
1578 :
1579 : // Determine whether we need to wipe out what we just did and start over
1580 : // because we're doing something like adding block kids to an inline frame
1581 : // (and therefore need an {ib} split). aPrevSibling must be correct, even in
1582 : // aIsAppend cases. Passing aIsAppend false even when an append is happening
1583 : // is ok in terms of correctness, but can lead to unnecessary reframing. If
1584 : // aIsAppend is true, then the caller MUST call
1585 : // nsCSSFrameConstructor::AppendFrames (as opposed to
1586 : // nsFrameManager::InsertFrames directly) to add the new frames.
1587 : // @return true if we reconstructed the containing block, false
1588 : // otherwise
1589 : bool WipeContainingBlock(nsFrameConstructorState& aState,
1590 : nsIFrame* aContainingBlock,
1591 : nsIFrame* aFrame,
1592 : FrameConstructionItemList& aItems,
1593 : bool aIsAppend,
1594 : nsIFrame* aPrevSibling);
1595 :
1596 : nsresult ReframeContainingBlock(nsIFrame* aFrame);
1597 :
1598 : nsresult StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint);
1599 :
1600 : //----------------------------------------
1601 :
1602 : // Methods support :first-letter style
1603 :
1604 : void CreateFloatingLetterFrame(nsFrameConstructorState& aState,
1605 : nsIFrame* aBlockFrame,
1606 : nsIContent* aTextContent,
1607 : nsIFrame* aTextFrame,
1608 : nsIContent* aBlockContent,
1609 : nsIFrame* aParentFrame,
1610 : nsStyleContext* aStyleContext,
1611 : nsFrameItems& aResult);
1612 :
1613 : nsresult CreateLetterFrame(nsIFrame* aBlockFrame,
1614 : nsIFrame* aBlockContinuation,
1615 : nsIContent* aTextContent,
1616 : nsIFrame* aParentFrame,
1617 : nsFrameItems& aResult);
1618 :
1619 : nsresult WrapFramesInFirstLetterFrame(nsIContent* aBlockContent,
1620 : nsIFrame* aBlockFrame,
1621 : nsFrameItems& aBlockFrames);
1622 :
1623 : /**
1624 : * Looks in the block aBlockFrame for a text frame that contains the
1625 : * first-letter of the block and creates the necessary first-letter frames
1626 : * and returns them in aLetterFrames.
1627 : *
1628 : * @param aBlockFrame the (first-continuation of) the block we are creating a
1629 : * first-letter frame for
1630 : * @param aBlockContinuation the current continuation of the block that we
1631 : * are looking in for a textframe with suitable
1632 : * contents for first-letter
1633 : * @param aParentFrame the current frame whose children we are looking at for
1634 : * a suitable first-letter textframe
1635 : * @param aParentFrameList the first child of aParentFrame
1636 : * @param aModifiedParent returns the parent of the textframe that contains
1637 : * the first-letter
1638 : * @param aTextFrame returns the textframe that had the first-letter
1639 : * @param aPrevFrame returns the previous sibling of aTextFrame
1640 : * @param aLetterFrames returns the frames that were created
1641 : * @param aStopLooking returns whether we should stop looking for a
1642 : * first-letter either because it was found or won't be
1643 : * found
1644 : */
1645 : nsresult WrapFramesInFirstLetterFrame(nsIFrame* aBlockFrame,
1646 : nsIFrame* aBlockContinuation,
1647 : nsIFrame* aParentFrame,
1648 : nsIFrame* aParentFrameList,
1649 : nsIFrame** aModifiedParent,
1650 : nsIFrame** aTextFrame,
1651 : nsIFrame** aPrevFrame,
1652 : nsFrameItems& aLetterFrames,
1653 : bool* aStopLooking);
1654 :
1655 : nsresult RecoverLetterFrames(nsIFrame* aBlockFrame);
1656 :
1657 : //
1658 : nsresult RemoveLetterFrames(nsPresContext* aPresContext,
1659 : nsIPresShell* aPresShell,
1660 : nsIFrame* aBlockFrame);
1661 :
1662 : // Recursive helper for RemoveLetterFrames
1663 : nsresult RemoveFirstLetterFrames(nsPresContext* aPresContext,
1664 : nsIPresShell* aPresShell,
1665 : nsIFrame* aFrame,
1666 : nsIFrame* aBlockFrame,
1667 : bool* aStopLooking);
1668 :
1669 : // Special remove method for those pesky floating first-letter frames
1670 : nsresult RemoveFloatingFirstLetterFrames(nsPresContext* aPresContext,
1671 : nsIPresShell* aPresShell,
1672 : nsIFrame* aBlockFrame,
1673 : bool* aStopLooking);
1674 :
1675 : // Capture state for the frame tree rooted at the frame associated with the
1676 : // content object, aContent
1677 : nsresult CaptureStateForFramesOf(nsIContent* aContent,
1678 : nsILayoutHistoryState* aHistoryState);
1679 :
1680 : // Capture state for the frame tree rooted at aFrame.
1681 : nsresult CaptureStateFor(nsIFrame* aFrame,
1682 : nsILayoutHistoryState* aHistoryState);
1683 :
1684 : //----------------------------------------
1685 :
1686 : // Methods support :first-line style
1687 :
1688 : // This method chops the initial inline-outside frames out of aFrameItems.
1689 : // If aLineFrame is non-null, it appends them to that frame. Otherwise, it
1690 : // creates a new line frame, sets the inline frames as its initial child
1691 : // list, and inserts that line frame at the front of what's left of
1692 : // aFrameItems. In both cases, the kids are reparented to the line frame.
1693 : // After this call, aFrameItems holds the frames that need to become kids of
1694 : // the block (possibly including line frames).
1695 : nsresult WrapFramesInFirstLineFrame(nsFrameConstructorState& aState,
1696 : nsIContent* aBlockContent,
1697 : nsIFrame* aBlockFrame,
1698 : nsIFrame* aLineFrame,
1699 : nsFrameItems& aFrameItems);
1700 :
1701 : // Handle the case when a block with first-line style is appended to (by
1702 : // possibly calling WrapFramesInFirstLineFrame as needed).
1703 : nsresult AppendFirstLineFrames(nsFrameConstructorState& aState,
1704 : nsIContent* aContent,
1705 : nsIFrame* aBlockFrame,
1706 : nsFrameItems& aFrameItems);
1707 :
1708 : nsresult InsertFirstLineFrames(nsFrameConstructorState& aState,
1709 : nsIContent* aContent,
1710 : nsIFrame* aBlockFrame,
1711 : nsIFrame** aParentFrame,
1712 : nsIFrame* aPrevSibling,
1713 : nsFrameItems& aFrameItems);
1714 :
1715 : // Find the right frame to use for aContent when looking for sibling
1716 : // frames for aTargetContent. If aPrevSibling is true, this
1717 : // will look for last continuations, etc, as necessary. This calls
1718 : // IsValidSibling as needed; if that returns false it returns null.
1719 : //
1720 : // @param aTargetContentDisplay the CSS display enum for aTargetContent if
1721 : // already known, UNSET_DISPLAY otherwise. It will be filled in if needed.
1722 : nsIFrame* FindFrameForContentSibling(nsIContent* aContent,
1723 : nsIContent* aTargetContent,
1724 : PRUint8& aTargetContentDisplay,
1725 : bool aPrevSibling);
1726 :
1727 : // Find the ``rightmost'' frame for the content immediately preceding the one
1728 : // aIter points to, following continuations if necessary. aIter is passed by
1729 : // value on purpose, so as not to modify the caller's iterator.
1730 : nsIFrame* FindPreviousSibling(const ChildIterator& aFirst,
1731 : ChildIterator aIter,
1732 : PRUint8& aTargetContentDisplay);
1733 :
1734 : // Find the frame for the content node immediately following the one aIter
1735 : // points to, following continuations if necessary. aIter is passed by value
1736 : // on purpose, so as not to modify the caller's iterator.
1737 : nsIFrame* FindNextSibling(ChildIterator aIter,
1738 : const ChildIterator& aLast,
1739 : PRUint8& aTargetContentDisplay);
1740 :
1741 : // Find the right previous sibling for an insertion. This also updates the
1742 : // parent frame to point to the correct continuation of the parent frame to
1743 : // use, and returns whether this insertion is to be treated as an append.
1744 : // aChild is the child being inserted.
1745 : // aIsRangeInsertSafe returns whether it is safe to do a range insert with
1746 : // aChild being the first child in the range. It is the callers'
1747 : // responsibility to check whether a range insert is safe with regards to
1748 : // fieldsets.
1749 : // The skip parameters are used to ignore a range of children when looking
1750 : // for a sibling. All nodes starting from aStartSkipChild and up to but not
1751 : // including aEndSkipChild will be skipped over when looking for sibling
1752 : // frames. Skipping a range can deal with XBL but not when there are multiple
1753 : // insertion points.
1754 : nsIFrame* GetInsertionPrevSibling(nsIFrame*& aParentFrame, /* inout */
1755 : nsIContent* aContainer,
1756 : nsIContent* aChild,
1757 : bool* aIsAppend,
1758 : bool* aIsRangeInsertSafe,
1759 : nsIContent* aStartSkipChild = nsnull,
1760 : nsIContent *aEndSkipChild = nsnull);
1761 :
1762 : // see if aContent and aSibling are legitimate siblings due to restrictions
1763 : // imposed by table columns
1764 : // XXXbz this code is generally wrong, since the frame for aContent
1765 : // may be constructed based on tag, not based on aDisplay!
1766 : bool IsValidSibling(nsIFrame* aSibling,
1767 : nsIContent* aContent,
1768 : PRUint8& aDisplay);
1769 :
1770 0 : void QuotesDirty() {
1771 0 : NS_PRECONDITION(mUpdateCount != 0, "Instant quote updates are bad news");
1772 0 : mQuotesDirty = true;
1773 0 : mDocument->SetNeedLayoutFlush();
1774 0 : }
1775 :
1776 0 : void CountersDirty() {
1777 0 : NS_PRECONDITION(mUpdateCount != 0, "Instant counter updates are bad news");
1778 0 : mCountersDirty = true;
1779 0 : mDocument->SetNeedLayoutFlush();
1780 0 : }
1781 :
1782 : public:
1783 :
1784 : friend class nsFrameConstructorState;
1785 :
1786 : private:
1787 :
1788 : nsIDocument* mDocument; // Weak ref
1789 :
1790 : // See the comment at the start of ConstructRootFrame for more details
1791 : // about the following frames.
1792 :
1793 : // This is just the outermost frame for the root element.
1794 : nsIFrame* mRootElementFrame;
1795 : // This is the frame for the root element that has no pseudo-element style.
1796 : nsIFrame* mRootElementStyleFrame;
1797 : // This is the containing block for fixed-pos frames --- the
1798 : // viewport or page frame
1799 : nsIFrame* mFixedContainingBlock;
1800 : // This is the containing block that contains the root element ---
1801 : // the real "initial containing block" according to CSS 2.1.
1802 : nsIFrame* mDocElementContainingBlock;
1803 : nsIFrame* mGfxScrollFrame;
1804 : nsIFrame* mPageSequenceFrame;
1805 : nsQuoteList mQuoteList;
1806 : nsCounterManager mCounterManager;
1807 : PRUint16 mUpdateCount;
1808 : bool mQuotesDirty : 1;
1809 : bool mCountersDirty : 1;
1810 : bool mIsDestroyingFrameTree : 1;
1811 : bool mRebuildAllStyleData : 1;
1812 : // This is true if mDocElementContainingBlock supports absolute positioning
1813 : bool mHasRootAbsPosContainingBlock : 1;
1814 : // True if we're already waiting for a refresh notification
1815 : bool mObservingRefreshDriver : 1;
1816 : // True if we're in the middle of a nsRefreshDriver refresh
1817 : bool mInStyleRefresh : 1;
1818 : PRUint32 mHoverGeneration;
1819 : nsChangeHint mRebuildAllExtraHint;
1820 :
1821 : nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
1822 :
1823 : RestyleTracker mPendingRestyles;
1824 : RestyleTracker mPendingAnimationRestyles;
1825 :
1826 : static nsIXBLService * gXBLService;
1827 : };
1828 :
1829 : #endif /* nsCSSFrameConstructor_h___ */
|