Bug 1104435 part 2 - Make AnimationPlayer derive from nsISupports; r=smaug
[gecko.git] / layout / base / nsCSSFrameConstructor.h
blob12706f0cb8fbb6b815dd16fa909af5169f4fbd7c
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * construction of a frame tree that is nearly isomorphic to the content
8 * tree and updating of that tree in response to dynamic changes
9 */
11 #ifndef nsCSSFrameConstructor_h___
12 #define nsCSSFrameConstructor_h___
14 #include "mozilla/Attributes.h"
16 #include "nsCOMPtr.h"
17 #include "nsILayoutHistoryState.h"
18 #include "nsQuoteList.h"
19 #include "nsCounterManager.h"
20 #include "nsCSSPseudoElements.h"
21 #include "nsIAnonymousContentCreator.h"
22 #include "nsFrameManager.h"
23 #include "nsIDocument.h"
24 #include "ScrollbarStyles.h"
26 struct nsFrameItems;
27 struct nsAbsoluteItems;
28 class nsStyleContext;
29 struct nsStyleDisplay;
30 class nsIDOMHTMLSelectElement;
31 struct nsGenConInitializer;
33 class nsContainerFrame;
34 class nsFirstLineFrame;
35 class nsICSSAnonBoxPseudo;
36 class nsPageContentFrame;
37 struct PendingBinding;
38 class nsGenericDOMDataNode;
40 class nsFrameConstructorState;
41 class nsFrameConstructorSaveState;
43 namespace mozilla {
45 class RestyleManager;
47 namespace dom {
49 class FlattenedChildIterator;
54 class nsCSSFrameConstructor : public nsFrameManager
56 public:
57 typedef mozilla::dom::Element Element;
59 friend class mozilla::RestyleManager;
61 nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell,
62 nsStyleSet* aStyleSet);
63 ~nsCSSFrameConstructor(void) {
64 NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?");
67 // get the alternate text for a content node
68 static void GetAlternateTextFor(nsIContent* aContent,
69 nsIAtom* aTag, // content object's tag
70 nsXPIDLString& aAltText);
72 private:
73 nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
74 nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
76 public:
77 mozilla::RestyleManager* RestyleManager() const
78 { return mPresShell->GetPresContext()->RestyleManager(); }
80 nsIFrame* ConstructRootFrame();
82 nsresult ReconstructDocElementHierarchy();
84 // Create frames for content nodes that are marked as needing frames. This
85 // should be called before ProcessPendingRestyles.
86 // Note: It's the caller's responsibility to make sure to wrap a
87 // CreateNeededFrames call in a view update batch and a script blocker.
88 void CreateNeededFrames();
90 private:
91 void CreateNeededFrames(nsIContent* aContent);
93 enum Operation {
94 CONTENTAPPEND,
95 CONTENTINSERT
98 // aChild is the child being inserted for inserts, and the first
99 // child being appended for appends.
100 bool MaybeConstructLazily(Operation aOperation,
101 nsIContent* aContainer,
102 nsIContent* aChild);
104 // Issues a single ContentInserted for each child of aContainer in the range
105 // [aStartChild, aEndChild).
106 void IssueSingleInsertNofications(nsIContent* aContainer,
107 nsIContent* aStartChild,
108 nsIContent* aEndChild,
109 bool aAllowLazyConstruction);
112 * Data that represents an insertion point for some child content.
114 struct InsertionPoint
116 InsertionPoint()
117 : mParentFrame(nullptr), mContainer(nullptr), mMultiple(false) {}
118 InsertionPoint(nsContainerFrame* aParentFrame, nsIContent* aContainer,
119 bool aMultiple = false)
120 : mParentFrame(aParentFrame), mContainer(aContainer),
121 mMultiple(aMultiple) {}
123 * The parent frame to use if the inserted children needs to create
124 * frame(s). May be null, which signals that we shouldn't try to
125 * create frames for the inserted children; either because there are
126 * no parent frame or because there are multiple insertion points and
127 * we will call IssueSingleInsertNofications for each child instead.
128 * mContainer should not be used when mParentFrame is null.
130 nsContainerFrame* mParentFrame;
132 * The flattened tree parent for the inserted children.
133 * It's undefined if mParentFrame is null.
135 nsIContent* mContainer;
137 * If true then there are multiple insertion points, which means consumers
138 * should insert children individually into the node's flattened tree parent.
140 bool mMultiple;
143 * Checks if the children of aContainer in the range [aStartChild, aEndChild)
144 * can be inserted/appended to one insertion point together. If so, returns
145 * that insertion point. If not, returns with InsertionPoint.mFrame == nullptr
146 * and issues single ContentInserted calls for each child.
147 * aEndChild = nullptr indicates that we are dealing with an append.
149 InsertionPoint GetRangeInsertionPoint(nsIContent* aContainer,
150 nsIContent* aStartChild,
151 nsIContent* aEndChild,
152 bool aAllowLazyConstruction);
154 // Returns true if parent was recreated due to frameset child, false otherwise.
155 bool MaybeRecreateForFrameset(nsIFrame* aParentFrame,
156 nsIContent* aStartChild,
157 nsIContent* aEndChild);
159 public:
161 * Lazy frame construction is controlled by the aAllowLazyConstruction bool
162 * parameter of nsCSSFrameConstructor::ContentAppended/Inserted. It is true
163 * for all inserts/appends as passed from the presshell, except for the
164 * insert of the root element, which is always non-lazy. Even if the
165 * aAllowLazyConstruction passed to ContentAppended/Inserted is true we still
166 * may not be able to construct lazily, so we call MaybeConstructLazily.
167 * MaybeConstructLazily does not allow lazy construction if any of the
168 * following are true:
169 * -we are in chrome
170 * -the container is in a native anonymous subtree
171 * -the container is XUL
172 * -is any of the appended/inserted nodes are XUL or editable
173 * -(for inserts) the child is anonymous. In the append case this function
174 * must not be called with anonymous children.
175 * The XUL and chrome checks are because XBL bindings only get applied at
176 * frame construction time and some things depend on the bindings getting
177 * attached synchronously. The editable checks are because the editor seems
178 * to expect frames to be constructed synchronously.
180 * If MaybeConstructLazily returns false we construct as usual, but if it
181 * returns true then it adds NODE_NEEDS_FRAME bits to the newly
182 * inserted/appended nodes and adds NODE_DESCENDANTS_NEED_FRAMES bits to the
183 * container and up along the parent chain until it hits the root or another
184 * node with that bit set. Then it posts a restyle event to ensure that a
185 * flush happens to construct those frames.
187 * When the flush happens the presshell calls
188 * nsCSSFrameConstructor::CreateNeededFrames. CreateNeededFrames follows any
189 * nodes with NODE_DESCENDANTS_NEED_FRAMES set down the content tree looking
190 * for nodes with NODE_NEEDS_FRAME set. It calls ContentAppended for any runs
191 * of nodes with NODE_NEEDS_FRAME set that are at the end of their childlist,
192 * and ContentRangeInserted for any other runs that aren't.
194 * If a node is removed from the document then we don't bother unsetting any
195 * of the lazy bits that might be set on it, its descendants, or any of its
196 * ancestor nodes because that is a slow operation, the work might be wasted
197 * if another node gets inserted in its place, and we can clear the bits
198 * quicker by processing the content tree from top down the next time we call
199 * CreateNeededFrames. (We do clear the bits when BindToTree is called on any
200 * nsIContent; so any nodes added to the document will not have any lazy bits
201 * set.)
204 // If aAllowLazyConstruction is true then frame construction of the new
205 // children can be done lazily.
206 nsresult ContentAppended(nsIContent* aContainer,
207 nsIContent* aFirstNewContent,
208 bool aAllowLazyConstruction);
210 // If aAllowLazyConstruction is true then frame construction of the new child
211 // can be done lazily.
212 nsresult ContentInserted(nsIContent* aContainer,
213 nsIContent* aChild,
214 nsILayoutHistoryState* aFrameState,
215 bool aAllowLazyConstruction);
217 // Like ContentInserted but handles inserting the children of aContainer in
218 // the range [aStartChild, aEndChild). aStartChild must be non-null.
219 // aEndChild may be null to indicate the range includes all kids after
220 // aStartChild. If aAllowLazyConstruction is true then frame construction of
221 // the new children can be done lazily. It is only allowed to be true when
222 // inserting a single node.
223 nsresult ContentRangeInserted(nsIContent* aContainer,
224 nsIContent* aStartChild,
225 nsIContent* aEndChild,
226 nsILayoutHistoryState* aFrameState,
227 bool aAllowLazyConstruction);
229 enum RemoveFlags {
230 REMOVE_CONTENT, REMOVE_FOR_RECONSTRUCTION, REMOVE_DESTROY_FRAMES };
232 * Recreate or destroy frames for aChild in aContainer.
233 * aFlags == REMOVE_CONTENT means aChild has been removed from the document.
234 * aFlags == REMOVE_FOR_RECONSTRUCTION means the caller will reconstruct the
235 * frames later.
236 * In both the above cases, this method will in some cases try to reconstruct
237 * the frames (aDidReconstruct is then set to true), it's just that in the
238 * former case aChild isn't in the document so no frames will be created for
239 * it. Ancestors may have been reframed though.
240 * aFlags == REMOVE_DESTROY_FRAMES is the same as REMOVE_FOR_RECONSTRUCTION
241 * except it will never try to reconstruct frames. Instead, the caller is
242 * responsible for doing that, on the content returned in aDestroyedFramesFor.
243 * The layout frame state is guarranted to be captured for the removed frames
244 * only when aFlags == REMOVE_DESTROY_FRAMES, otherwise it will only be
245 * captured if we reconstructed frames for an ancestor.
247 nsresult ContentRemoved(nsIContent* aContainer,
248 nsIContent* aChild,
249 nsIContent* aOldNextSibling,
250 RemoveFlags aFlags,
251 bool* aDidReconstruct,
252 nsIContent** aDestroyedFramesFor = nullptr);
254 nsresult CharacterDataChanged(nsIContent* aContent,
255 CharacterDataChangeInfo* aInfo);
257 // If aContent is a text node that has been optimized away due to being
258 // whitespace next to a block boundary (or for some other reason), stop
259 // doing that and create a frame for it if it should have one. This recreates
260 // frames so be careful (although this should not change actual layout).
261 // Returns the frame for aContent if there is one.
262 nsIFrame* EnsureFrameForTextNode(nsGenericDOMDataNode* aContent);
264 // generate the child frames and process bindings
265 nsresult GenerateChildFrames(nsContainerFrame* aFrame);
267 // Should be called when a frame is going to be destroyed and
268 // WillDestroyFrameTree hasn't been called yet.
269 void NotifyDestroyingFrame(nsIFrame* aFrame);
271 void BeginUpdate();
272 void EndUpdate();
273 void RecalcQuotesAndCounters();
275 // Called when any counter style is changed.
276 void NotifyCounterStylesAreDirty();
278 // Gets called when the presshell is destroying itself and also
279 // when we tear down our frame tree to reconstruct it
280 void WillDestroyFrameTree();
283 * Destroy the frames for aContent. Note that this may destroy frames
284 * for an ancestor instead - aDestroyedFramesFor contains the content node
285 * where frames were actually destroyed (which should be used in the
286 * ContentInserted call to recreate frames). The frame tree state
287 * is captured before the frames are destroyed and can be retrieved using
288 * GetLastCapturedLayoutHistoryState().
290 void DestroyFramesFor(nsIContent* aContent,
291 nsIContent** aDestroyedFramesFor);
293 // Request to create a continuing frame. This method never returns null.
294 nsIFrame* CreateContinuingFrame(nsPresContext* aPresContext,
295 nsIFrame* aFrame,
296 nsContainerFrame* aParentFrame,
297 bool aIsFluid = true);
299 // Copy over fixed frames from aParentFrame's prev-in-flow
300 nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
303 * Get the XBL insertion point for aChild in aContainer.
305 InsertionPoint GetInsertionPoint(nsIContent* aContainer, nsIContent* aChild);
307 nsresult CreateListBoxContent(nsPresContext* aPresContext,
308 nsContainerFrame* aParentFrame,
309 nsIFrame* aPrevFrame,
310 nsIContent* aChild,
311 nsIFrame** aResult,
312 bool aIsAppend,
313 bool aIsScrollbar,
314 nsILayoutHistoryState* aFrameState);
316 // GetInitialContainingBlock() is deprecated in favor of GetRootElementFrame();
317 // nsIFrame* GetInitialContainingBlock() { return mRootElementFrame; }
318 // This returns the outermost frame for the root element
319 nsContainerFrame* GetRootElementFrame() { return mRootElementFrame; }
320 // This returns the frame for the root element that does not
321 // have a psuedo-element style
322 nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
323 nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
325 // Get the frame that is the parent of the root element.
326 nsContainerFrame* GetDocElementContainingBlock()
327 { return mDocElementContainingBlock; }
330 * Return the layout history state that was captured in the last
331 * ContentRemoved / RecreateFramesForContent call.
333 nsILayoutHistoryState* GetLastCapturedLayoutHistoryState()
335 return mTempFrameTreeState;
338 private:
339 struct FrameConstructionItem;
340 class FrameConstructionItemList;
342 nsContainerFrame* ConstructPageFrame(nsIPresShell* aPresShell,
343 nsPresContext* aPresContext,
344 nsContainerFrame* aParentFrame,
345 nsIFrame* aPrevPageFrame,
346 nsContainerFrame*& aCanvasFrame);
348 void InitAndRestoreFrame (const nsFrameConstructorState& aState,
349 nsIContent* aContent,
350 nsContainerFrame* aParentFrame,
351 nsIFrame* aNewFrame,
352 bool aAllowCounters = true);
354 // aState can be null if not available; it's used as an optimization.
355 // XXXbz IsValidSibling is the only caller that doesn't pass a state here!
356 already_AddRefed<nsStyleContext>
357 ResolveStyleContext(nsIFrame* aParentFrame,
358 nsIContent* aContainer,
359 nsIContent* aChild,
360 nsFrameConstructorState* aState);
361 already_AddRefed<nsStyleContext>
362 ResolveStyleContext(nsIFrame* aParentFrame,
363 nsIContent* aChild,
364 nsFrameConstructorState* aState);
365 already_AddRefed<nsStyleContext>
366 ResolveStyleContext(const InsertionPoint& aInsertion,
367 nsIContent* aChild,
368 nsFrameConstructorState* aState);
369 already_AddRefed<nsStyleContext>
370 ResolveStyleContext(nsStyleContext* aParentStyleContext,
371 nsIContent* aContent,
372 nsFrameConstructorState* aState);
374 // Add the frame construction items for the given aContent and aParentFrame
375 // to the list. This might add more than one item in some rare cases.
376 // If aSuppressWhiteSpaceOptimizations is true, optimizations that
377 // may suppress the construction of white-space-only text frames
378 // must be skipped for these items and items around them.
379 void AddFrameConstructionItems(nsFrameConstructorState& aState,
380 nsIContent* aContent,
381 bool aSuppressWhiteSpaceOptimizations,
382 const InsertionPoint& aInsertion,
383 FrameConstructionItemList& aItems);
385 // Helper method for AddFrameConstructionItems etc.
386 // Unsets the need-frame/restyle bits on aContent.
387 // return true iff we should attempt to create frames for aContent.
388 bool ShouldCreateItemsForChild(nsFrameConstructorState& aState,
389 nsIContent* aContent,
390 nsContainerFrame* aParentFrame);
392 // Helper method for AddFrameConstructionItems etc.
393 // Make sure ShouldCreateItemsForChild() returned true before calling this.
394 void DoAddFrameConstructionItems(nsFrameConstructorState& aState,
395 nsIContent* aContent,
396 nsStyleContext* aStyleContext,
397 bool aSuppressWhiteSpaceOptimizations,
398 nsContainerFrame* aParentFrame,
399 nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
400 FrameConstructionItemList& aItems);
402 // Construct the frames for the document element. This can return null if the
403 // document element is display:none, or if the document element has a
404 // not-yet-loaded XBL binding, or if it's an SVG element that's not <svg>.
405 nsIFrame* ConstructDocElementFrame(Element* aDocElement,
406 nsILayoutHistoryState* aFrameState);
408 // Set up our mDocElementContainingBlock correctly for the given root
409 // content.
410 void SetUpDocElementContainingBlock(nsIContent* aDocElement);
413 * CreateAttributeContent creates a single content/frame combination for an
414 * |attr(foo)| generated content.
416 * @param aParentContent the parent content for the generated content
417 * @param aParentFrame the parent frame for the generated frame
418 * @param aAttrNamespace the namespace of the attribute in question
419 * @param aAttrName the localname of the attribute
420 * @param aStyleContext the style context to use
421 * @param aGeneratedContent the array of generated content to append the
422 * created content to.
423 * @param [out] aNewContent the content node we create
424 * @param [out] aNewFrame the new frame we create
426 nsresult CreateAttributeContent(nsIContent* aParentContent,
427 nsIFrame* aParentFrame,
428 int32_t aAttrNamespace,
429 nsIAtom* aAttrName,
430 nsStyleContext* aStyleContext,
431 nsCOMArray<nsIContent>& aGeneratedContent,
432 nsIContent** aNewContent,
433 nsIFrame** aNewFrame);
436 * Create a text node containing the given string. If aText is non-null
437 * then we also set aText to the returned node.
439 already_AddRefed<nsIContent> CreateGenConTextNode(nsFrameConstructorState& aState,
440 const nsString& aString,
441 nsRefPtr<nsTextNode>* aText,
442 nsGenConInitializer* aInitializer);
445 * Create a content node for the given generated content style.
446 * The caller takes care of making it SetIsNativeAnonymousRoot, binding it
447 * to the document, and creating frames for it.
448 * @param aParentContent is the node that has the before/after style
449 * @param aStyleContext is the 'before' or 'after' pseudo-element
450 * style context
451 * @param aContentIndex is the index of the content item to create
453 already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState,
454 nsIContent* aParentContent,
455 nsStyleContext* aStyleContext,
456 uint32_t aContentIndex);
458 // aFrame may be null; this method doesn't use it directly in any case.
459 void CreateGeneratedContentItem(nsFrameConstructorState& aState,
460 nsContainerFrame* aFrame,
461 nsIContent* aContent,
462 nsStyleContext* aStyleContext,
463 nsCSSPseudoElements::Type aPseudoElement,
464 FrameConstructionItemList& aItems);
466 // This method can change aFrameList: it can chop off the beginning and put
467 // it in aParentFrame while putting the remainder into a ib-split sibling of
468 // aParentFrame. aPrevSibling must be the frame after which aFrameList is to
469 // be placed on aParentFrame's principal child list. It may be null if
470 // aFrameList is being added at the beginning of the child list.
471 nsresult AppendFramesToParent(nsFrameConstructorState& aState,
472 nsContainerFrame* aParentFrame,
473 nsFrameItems& aFrameList,
474 nsIFrame* aPrevSibling,
475 bool aIsRecursiveCall = false);
477 // BEGIN TABLE SECTION
479 * Construct an outer table frame. This is the FrameConstructionData
480 * callback used for the job.
482 nsIFrame* ConstructTable(nsFrameConstructorState& aState,
483 FrameConstructionItem& aItem,
484 nsContainerFrame* aParentFrame,
485 const nsStyleDisplay* aDisplay,
486 nsFrameItems& aFrameItems);
489 * FrameConstructionData callback for constructing table rows and row groups.
491 nsIFrame* ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
492 FrameConstructionItem& aItem,
493 nsContainerFrame* aParentFrame,
494 const nsStyleDisplay* aStyleDisplay,
495 nsFrameItems& aFrameItems);
498 * FrameConstructionData callback used for constructing table columns.
500 nsIFrame* ConstructTableCol(nsFrameConstructorState& aState,
501 FrameConstructionItem& aItem,
502 nsContainerFrame* aParentFrame,
503 const nsStyleDisplay* aStyleDisplay,
504 nsFrameItems& aFrameItems);
507 * FrameConstructionData callback used for constructing table cells.
509 nsIFrame* ConstructTableCell(nsFrameConstructorState& aState,
510 FrameConstructionItem& aItem,
511 nsContainerFrame* aParentFrame,
512 const nsStyleDisplay* aStyleDisplay,
513 nsFrameItems& aFrameItems);
515 private:
516 /* An enum of possible parent types for anonymous table or ruby object
517 construction */
518 enum ParentType {
519 eTypeBlock = 0, /* This includes all non-table-related frames */
520 eTypeRow,
521 eTypeRowGroup,
522 eTypeColGroup,
523 eTypeTable,
524 eTypeRuby,
525 eTypeRubyBase,
526 eTypeRubyBaseContainer,
527 eTypeRubyText,
528 eTypeRubyTextContainer,
529 eParentTypeCount
532 /* 4 bits is enough to handle our ParentType values */
533 #define FCDATA_PARENT_TYPE_OFFSET 28
534 /* Macro to get the desired parent type out of an mBits member of
535 FrameConstructionData */
536 #define FCDATA_DESIRED_PARENT_TYPE(_bits) \
537 ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET)
538 /* Macro to create FrameConstructionData bits out of a desired parent type */
539 #define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type) \
540 (((uint32_t)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
542 /* Get the parent type that aParentFrame has. */
543 static ParentType GetParentType(nsIFrame* aParentFrame) {
544 return GetParentType(aParentFrame->GetType());
547 /* Get the parent type for the given nsIFrame type atom */
548 static ParentType GetParentType(nsIAtom* aFrameType);
550 static bool IsRubyParentType(ParentType aParentType) {
551 return (aParentType == eTypeRuby ||
552 aParentType == eTypeRubyBase ||
553 aParentType == eTypeRubyBaseContainer ||
554 aParentType == eTypeRubyText ||
555 aParentType == eTypeRubyTextContainer);
558 static bool IsTableParentType(ParentType aParentType) {
559 return (aParentType == eTypeTable ||
560 aParentType == eTypeRow ||
561 aParentType == eTypeRowGroup ||
562 aParentType == eTypeColGroup);
565 /* A constructor function that just creates an nsIFrame object. The caller
566 is responsible for initializing the object, adding it to frame lists,
567 constructing frames for the children, etc.
569 @param nsIPresShell the presshell whose arena should be used to allocate
570 the frame.
571 @param nsStyleContext the style context to use for the frame. */
572 typedef nsIFrame* (* FrameCreationFunc)(nsIPresShell*, nsStyleContext*);
573 typedef nsContainerFrame* (* ContainerFrameCreationFunc)(nsIPresShell*, nsStyleContext*);
575 /* A function that can be used to get a FrameConstructionData. Such
576 a function is allowed to return null.
578 @param nsIContent the node for which the frame is being constructed.
579 @param nsStyleContext the style context to be used for the frame.
581 struct FrameConstructionData;
582 typedef const FrameConstructionData*
583 (* FrameConstructionDataGetter)(Element*, nsStyleContext*);
585 /* A constructor function that's used for complicated construction tasks.
586 This is expected to create the new frame, initialize it, add whatever
587 needs to be added to aFrameItems (XXXbz is that really necessary? Could
588 caller add? Might there be cases when the returned frame or its
589 placeholder is not the thing that ends up in aFrameItems? If not, would
590 it be safe to do the add into the frame construction state after
591 processing kids? Look into this as a followup!), process children as
592 needed, etc. It is NOT expected to deal with setting the frame on the
593 content.
595 @param aState the frame construction state to use.
596 @param aItem the frame construction item to use
597 @param aParentFrame the frame to set as the parent of the
598 newly-constructed frame.
599 @param aStyleDisplay the display struct from aItem's mStyleContext
600 @param aFrameItems the frame list to add the new frame (or its
601 placeholder) to.
602 @return the frame that was constructed. This frame is what the caller
603 will set as the frame on the content. Guaranteed non-null.
605 typedef nsIFrame*
606 (nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState,
607 FrameConstructionItem& aItem,
608 nsContainerFrame* aParentFrame,
609 const nsStyleDisplay* aStyleDisplay,
610 nsFrameItems& aFrameItems);
612 /* Bits that modify the way a FrameConstructionData is handled */
614 /* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not
615 be set as the primary frame on the content node. This should only be used
616 in very rare cases when we create more than one frame for a given content
617 node. */
618 #define FCDATA_SKIP_FRAMESET 0x1
619 /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
620 FrameConstructionData is a getter function that can be used to get the
621 actual FrameConstructionData to use. */
622 #define FCDATA_FUNC_IS_DATA_GETTER 0x2
623 /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData
624 has an mFullConstructor. In this case, there is no relevant mData or
625 mFunc */
626 #define FCDATA_FUNC_IS_FULL_CTOR 0x4
627 /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to
628 float or be absolutely positioned. This can also be used with
629 FCDATA_FUNC_IS_FULL_CTOR to indicate what the full-constructor
630 function will do. */
631 #define FCDATA_DISALLOW_OUT_OF_FLOW 0x8
632 /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a
633 null absolute containing block before processing children for this
634 frame. If this is not set, the frame will be pushed as the
635 absolute containing block as needed, based on its style */
636 #define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10
637 /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame
638 will be wrapped in blocks. This is only usable for MathML at the
639 moment. */
640 #define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20
641 /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the
642 content. If this bit is set, nothing else in the struct needs to be
643 set. */
644 #define FCDATA_SUPPRESS_FRAME 0x40
645 /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
646 a scrollframe if its overflow type so requires. */
647 #define FCDATA_MAY_NEED_SCROLLFRAME 0x80
648 #ifdef MOZ_XUL
649 /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame. These need
650 some really weird special handling. */
651 #define FCDATA_IS_POPUP 0x100
652 #endif /* MOZ_XUL */
653 /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
654 absolute containing block, no matter what its style says. */
655 #define FCDATA_SKIP_ABSPOS_PUSH 0x200
656 /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated
657 content when processing kids of this frame. This should not be used with
658 FCDATA_FUNC_IS_FULL_CTOR */
659 #define FCDATA_DISALLOW_GENERATED_CONTENT 0x400
660 /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of
661 table-related thing and we should not attempt to fetch a table-cell parent
662 for it if it's inside another table-related frame. */
663 #define FCDATA_IS_TABLE_PART 0x800
664 /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS
665 inline box. */
666 #define FCDATA_IS_INLINE 0x1000
667 /* If FCDATA_IS_LINE_PARTICIPANT is set, the frame is something that will
668 return true for IsFrameOfType(nsIFrame::eLineParticipant) */
669 #define FCDATA_IS_LINE_PARTICIPANT 0x2000
670 /* If FCDATA_IS_LINE_BREAK is set, the frame is something that will
671 induce a line break boundary before and after itself. */
672 #define FCDATA_IS_LINE_BREAK 0x4000
673 /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing
674 children. This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */
675 #define FCDATA_ALLOW_BLOCK_STYLES 0x8000
676 /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant
677 FrameConstructionItem instead of trying to process the content's children.
678 This can be used with or without FCDATA_FUNC_IS_FULL_CTOR.
679 The child items might still need table pseudo processing. */
680 #define FCDATA_USE_CHILD_ITEMS 0x10000
681 /* If FCDATA_FORCED_NON_SCROLLABLE_BLOCK is set, then this block
682 would have been scrollable but has been forced to be
683 non-scrollable due to being in a paginated context. */
684 #define FCDATA_FORCED_NON_SCROLLABLE_BLOCK 0x20000
685 /* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a
686 block formatting context wrapper around the kids of this frame
687 using the FrameConstructionData's mPseudoAtom for its anonymous
688 box type. */
689 #define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000
690 /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of
691 an SVG text frame. */
692 #define FCDATA_IS_SVG_TEXT 0x80000
694 * display:contents
696 #define FCDATA_IS_CONTENTS 0x100000
698 /* Structure representing information about how a frame should be
699 constructed. */
700 struct FrameConstructionData {
701 // Flag bits that can modify the way the construction happens
702 uint32_t mBits;
703 // We have exactly one of three types of functions, so use a union for
704 // better cache locality for the ones that aren't pointer-to-member. That
705 // one needs to be separate, because we can't cast between it and the
706 // others and hence wouldn't be able to initialize the union without a
707 // constructor and all the resulting generated code. See documentation
708 // above for FrameCreationFunc, FrameConstructionDataGetter, and
709 // FrameFullConstructor to see what the functions would do.
710 union Func {
711 FrameCreationFunc mCreationFunc;
712 FrameConstructionDataGetter mDataGetter;
713 } mFunc;
714 FrameFullConstructor mFullConstructor;
715 // For cases when FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, the
716 // anonymous box type to use for that wrapper.
717 nsICSSAnonBoxPseudo * const * const mAnonBoxPseudo;
720 /* Structure representing a mapping of an atom to a FrameConstructionData.
721 This can be used with non-static atoms, assuming that the nsIAtom* is
722 stored somewhere that this struct can point to (that is, a static
723 nsIAtom*) and that it's allocated before the struct is ever used. */
724 struct FrameConstructionDataByTag {
725 // Pointer to nsIAtom* is used because we want to initialize this
726 // statically, so before our atom tables are set up.
727 const nsIAtom * const * const mTag;
728 const FrameConstructionData mData;
731 /* Structure representing a mapping of an integer to a
732 FrameConstructionData. There are no magic integer values here. */
733 struct FrameConstructionDataByInt {
734 /* Could be used for display or whatever else */
735 const int32_t mInt;
736 const FrameConstructionData mData;
739 /* Structure that has a FrameConstructionData and style context pseudo-type
740 for a table pseudo-frame */
741 struct PseudoParentData {
742 const FrameConstructionData mFCData;
743 nsICSSAnonBoxPseudo * const * const mPseudoType;
745 /* Array of such structures that we use to properly construct table
746 pseudo-frames as needed */
747 static const PseudoParentData sPseudoParentData[eParentTypeCount];
749 /* A function that takes an integer, content, style context, and array of
750 FrameConstructionDataByInts and finds the appropriate frame construction
751 data to use and returns it. This can return null if none of the integers
752 match or if the matching integer has a FrameConstructionDataGetter that
753 returns null. */
754 static const FrameConstructionData*
755 FindDataByInt(int32_t aInt, Element* aElement,
756 nsStyleContext* aStyleContext,
757 const FrameConstructionDataByInt* aDataPtr,
758 uint32_t aDataLength);
760 /* A function that takes a tag, content, style context, and array of
761 FrameConstructionDataByTags and finds the appropriate frame construction
762 data to use and returns it. This can return null if none of the tags
763 match or if the matching tag has a FrameConstructionDataGetter that
764 returns null. */
765 static const FrameConstructionData*
766 FindDataByTag(nsIAtom* aTag, Element* aElement,
767 nsStyleContext* aStyleContext,
768 const FrameConstructionDataByTag* aDataPtr,
769 uint32_t aDataLength);
771 /* A class representing a list of FrameConstructionItems */
772 class FrameConstructionItemList {
773 public:
774 FrameConstructionItemList() :
775 mInlineCount(0),
776 mBlockCount(0),
777 mLineParticipantCount(0),
778 mItemCount(0),
779 mLineBoundaryAtStart(false),
780 mLineBoundaryAtEnd(false),
781 mParentHasNoXBLChildren(false),
782 mTriedConstructingFrames(false)
784 PR_INIT_CLIST(&mItems);
785 memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
788 ~FrameConstructionItemList() {
789 PRCList* cur = PR_NEXT_LINK(&mItems);
790 while (cur != &mItems) {
791 PRCList* next = PR_NEXT_LINK(cur);
792 delete ToItem(cur);
793 cur = next;
796 // Leaves our mItems pointing to deleted memory in both directions,
797 // but that's OK at this point.
799 // Create the undisplayed entries for our mUndisplayedItems, if any, but
800 // only if we have tried constructing frames for this item list. If we
801 // haven't, then we're just throwing it away and will probably try again.
802 if (!mUndisplayedItems.IsEmpty() && mTriedConstructingFrames) {
803 // We could store the frame manager in a member, but just
804 // getting it off the style context is not too bad.
805 nsFrameManager *mgr =
806 mUndisplayedItems[0].mStyleContext->PresContext()->FrameManager();
807 for (uint32_t i = 0; i < mUndisplayedItems.Length(); ++i) {
808 UndisplayedItem& item = mUndisplayedItems[i];
809 mgr->SetUndisplayedContent(item.mContent, item.mStyleContext);
814 void SetLineBoundaryAtStart(bool aBoundary) { mLineBoundaryAtStart = aBoundary; }
815 void SetLineBoundaryAtEnd(bool aBoundary) { mLineBoundaryAtEnd = aBoundary; }
816 void SetParentHasNoXBLChildren(bool aHasNoXBLChildren) {
817 mParentHasNoXBLChildren = aHasNoXBLChildren;
819 void SetTriedConstructingFrames() { mTriedConstructingFrames = true; }
820 bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; }
821 bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; }
822 bool ParentHasNoXBLChildren() { return mParentHasNoXBLChildren; }
823 bool IsEmpty() const { return PR_CLIST_IS_EMPTY(&mItems); }
824 bool AnyItemsNeedBlockParent() const { return mLineParticipantCount != 0; }
825 bool AreAllItemsInline() const { return mInlineCount == mItemCount; }
826 bool AreAllItemsBlock() const { return mBlockCount == mItemCount; }
827 bool AllWantParentType(ParentType aDesiredParentType) const {
828 return mDesiredParentCounts[aDesiredParentType] == mItemCount;
831 // aSuppressWhiteSpaceOptimizations is true if optimizations that
832 // skip constructing whitespace frames for this item or items
833 // around it cannot be performed.
834 FrameConstructionItem* AppendItem(const FrameConstructionData* aFCData,
835 nsIContent* aContent,
836 nsIAtom* aTag,
837 int32_t aNameSpaceID,
838 PendingBinding* aPendingBinding,
839 already_AddRefed<nsStyleContext>&& aStyleContext,
840 bool aSuppressWhiteSpaceOptimizations,
841 nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren)
843 FrameConstructionItem* item =
844 new FrameConstructionItem(aFCData, aContent, aTag, aNameSpaceID,
845 aPendingBinding, aStyleContext,
846 aSuppressWhiteSpaceOptimizations,
847 aAnonChildren);
848 PR_APPEND_LINK(item, &mItems);
849 ++mItemCount;
850 ++mDesiredParentCounts[item->DesiredParentType()];
851 return item;
854 void AppendUndisplayedItem(nsIContent* aContent,
855 nsStyleContext* aStyleContext) {
856 mUndisplayedItems.AppendElement(UndisplayedItem(aContent, aStyleContext));
859 void InlineItemAdded() { ++mInlineCount; }
860 void BlockItemAdded() { ++mBlockCount; }
861 void LineParticipantItemAdded() { ++mLineParticipantCount; }
863 class Iterator;
864 friend class Iterator;
866 class Iterator {
867 public:
868 explicit Iterator(FrameConstructionItemList& list) :
869 mCurrent(PR_NEXT_LINK(&list.mItems)),
870 mEnd(&list.mItems),
871 mList(list)
873 Iterator(const Iterator& aOther) :
874 mCurrent(aOther.mCurrent),
875 mEnd(aOther.mEnd),
876 mList(aOther.mList)
879 bool operator==(const Iterator& aOther) const {
880 NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
881 return mCurrent == aOther.mCurrent;
883 bool operator!=(const Iterator& aOther) const {
884 return !(*this == aOther);
886 Iterator& operator=(const Iterator& aOther) {
887 NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
888 mCurrent = aOther.mCurrent;
889 return *this;
892 FrameConstructionItemList* List() {
893 return &mList;
896 operator FrameConstructionItem& () {
897 return item();
900 FrameConstructionItem& item() {
901 MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
902 return *FrameConstructionItemList::ToItem(mCurrent);
905 const FrameConstructionItem& item() const {
906 MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
907 return *FrameConstructionItemList::ToItem(mCurrent);
910 bool IsDone() const { return mCurrent == mEnd; }
911 bool AtStart() const { return mCurrent == PR_NEXT_LINK(mEnd); }
912 void Next() {
913 NS_ASSERTION(!IsDone(), "Should have checked IsDone()!");
914 mCurrent = PR_NEXT_LINK(mCurrent);
916 void Prev() {
917 NS_ASSERTION(!AtStart(), "Should have checked AtStart()!");
918 mCurrent = PR_PREV_LINK(mCurrent);
920 void SetToEnd() { mCurrent = mEnd; }
922 // Skip over all items that want the given parent type. Return whether
923 // the iterator is done after doing that. The iterator must not be done
924 // when this is called.
925 inline bool SkipItemsWantingParentType(ParentType aParentType);
927 // Skip over all items that want a parent type different from the given
928 // one. Return whether the iterator is done after doing that. The
929 // iterator must not be done when this is called.
930 inline bool SkipItemsNotWantingParentType(ParentType aParentType);
932 // Skip over non-replaced inline frames and positioned frames.
933 // Return whether the iterator is done after doing that.
934 // The iterator must not be done when this is called.
935 inline bool SkipItemsThatNeedAnonFlexOrGridItem(
936 const nsFrameConstructorState& aState);
938 // Skip to the first frame that is a non-replaced inline or is
939 // positioned. Return whether the iterator is done after doing that.
940 // The iterator must not be done when this is called.
941 inline bool SkipItemsThatDontNeedAnonFlexOrGridItem(
942 const nsFrameConstructorState& aState);
944 // Skip over all items that do not want a ruby parent. Return whether
945 // the iterator is done after doing that. The iterator must not be done
946 // when this is called.
947 inline bool SkipItemsNotWantingRubyParent();
949 // Skip over whitespace. Return whether the iterator is done after doing
950 // that. The iterator must not be done, and must be pointing to a
951 // whitespace item when this is called.
952 inline bool SkipWhitespace(nsFrameConstructorState& aState);
954 // Remove the item pointed to by this iterator from its current list and
955 // Append it to aTargetList. This iterator is advanced to point to the
956 // next item in its list. aIter must not be done. aOther must not be
957 // the list this iterator is iterating over..
958 void AppendItemToList(FrameConstructionItemList& aTargetList);
960 // As above, but moves all items starting with this iterator until we
961 // get to aEnd; the item pointed to by aEnd is not stolen. This method
962 // might have optimizations over just looping and doing StealItem for
963 // some special cases. After this method returns, this iterator will
964 // point to the item aEnd points to now; aEnd is not modified.
965 // aTargetList must not be the list this iterator is iterating over.
966 void AppendItemsToList(const Iterator& aEnd,
967 FrameConstructionItemList& aTargetList);
969 // Insert aItem in this iterator's list right before the item pointed to
970 // by this iterator. After the insertion, this iterator will continue to
971 // point to the item it now points to (the one just after the
972 // newly-inserted item). This iterator is allowed to be done; in that
973 // case this call just appends the given item to the list.
974 void InsertItem(FrameConstructionItem* aItem);
976 // Delete the items between this iterator and aEnd, including the item
977 // this iterator currently points to but not including the item pointed
978 // to by aEnd. When this returns, this iterator will point to the same
979 // item as aEnd. This iterator must not equal aEnd when this method is
980 // called.
981 void DeleteItemsTo(const Iterator& aEnd);
983 private:
984 PRCList* mCurrent;
985 PRCList* mEnd;
986 FrameConstructionItemList& mList;
989 private:
990 static FrameConstructionItem* ToItem(PRCList* item) {
991 return static_cast<FrameConstructionItem*>(item);
994 struct UndisplayedItem {
995 UndisplayedItem(nsIContent* aContent, nsStyleContext* aStyleContext) :
996 mContent(aContent), mStyleContext(aStyleContext)
999 nsIContent * const mContent;
1000 nsRefPtr<nsStyleContext> mStyleContext;
1003 // Adjust our various counts for aItem being added or removed. aDelta
1004 // should be either +1 or -1 depending on which is happening.
1005 void AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta);
1007 PRCList mItems;
1008 uint32_t mInlineCount;
1009 uint32_t mBlockCount;
1010 uint32_t mLineParticipantCount;
1011 uint32_t mItemCount;
1012 uint32_t mDesiredParentCounts[eParentTypeCount];
1013 // True if there is guaranteed to be a line boundary before the
1014 // frames created by these items
1015 bool mLineBoundaryAtStart;
1016 // True if there is guaranteed to be a line boundary after the
1017 // frames created by these items
1018 bool mLineBoundaryAtEnd;
1019 // True if the parent is guaranteed to have no XBL anonymous children
1020 bool mParentHasNoXBLChildren;
1021 // True if we have tried constructing frames from this list
1022 bool mTriedConstructingFrames;
1024 nsTArray<UndisplayedItem> mUndisplayedItems;
1027 typedef FrameConstructionItemList::Iterator FCItemIterator;
1029 /* A struct representing an item for which frames might need to be
1030 * constructed. This contains all the information needed to construct the
1031 * frame other than the parent frame and whatever would be stored in the
1032 * frame constructor state. */
1033 struct FrameConstructionItem : public PRCList {
1034 // No need to PR_INIT_CLIST in the constructor because the only
1035 // place that creates us immediately appends us.
1036 FrameConstructionItem(const FrameConstructionData* aFCData,
1037 nsIContent* aContent,
1038 nsIAtom* aTag,
1039 int32_t aNameSpaceID,
1040 PendingBinding* aPendingBinding,
1041 already_AddRefed<nsStyleContext>& aStyleContext,
1042 bool aSuppressWhiteSpaceOptimizations,
1043 nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren) :
1044 mFCData(aFCData), mContent(aContent), mTag(aTag),
1045 mNameSpaceID(aNameSpaceID),
1046 mPendingBinding(aPendingBinding), mStyleContext(aStyleContext),
1047 mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
1048 mIsText(false), mIsGeneratedContent(false),
1049 mIsAnonymousContentCreatorContent(false),
1050 mIsRootPopupgroup(false), mIsAllInline(false), mIsBlock(false),
1051 mHasInlineEnds(false), mIsPopup(false),
1052 mIsLineParticipant(false), mIsForSVGAElement(false)
1054 if (aAnonChildren) {
1055 NS_ASSERTION(!(mFCData->mBits & FCDATA_FUNC_IS_FULL_CTOR) ||
1056 mFCData->mFullConstructor ==
1057 &nsCSSFrameConstructor::ConstructInline,
1058 "This is going to fail");
1059 NS_ASSERTION(!(mFCData->mBits & FCDATA_USE_CHILD_ITEMS),
1060 "nsIAnonymousContentCreator::CreateAnonymousContent "
1061 "implementations should not output a list where the "
1062 "items have children in this case");
1063 mAnonChildren.SwapElements(*aAnonChildren);
1066 ~FrameConstructionItem() {
1067 if (mIsGeneratedContent) {
1068 mContent->UnbindFromTree();
1069 NS_RELEASE(mContent);
1073 ParentType DesiredParentType() {
1074 return FCDATA_DESIRED_PARENT_TYPE(mFCData->mBits);
1077 // Indicates whether (when in a flex or grid container) this item needs
1078 // to be wrapped in an anonymous block.
1079 bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState);
1081 // Don't call this unless the frametree really depends on the answer!
1082 // Especially so for generated content, where we don't want to reframe
1083 // things.
1084 bool IsWhitespace(nsFrameConstructorState& aState) const;
1086 bool IsLineBoundary() const {
1087 return mIsBlock || (mFCData->mBits & FCDATA_IS_LINE_BREAK);
1090 // The FrameConstructionData to use.
1091 const FrameConstructionData* mFCData;
1092 // The nsIContent node to use when initializing the new frame.
1093 nsIContent* mContent;
1094 // The XBL-resolved tag name to use for frame construction.
1095 nsIAtom* mTag;
1096 // The XBL-resolved namespace to use for frame construction.
1097 int32_t mNameSpaceID;
1098 // The PendingBinding for this frame construction item, if any. May be
1099 // null. We maintain a list of PendingBindings in the frame construction
1100 // state in the order in which AddToAttachedQueue should be called on them:
1101 // depth-first, post-order traversal order. Since we actually traverse the
1102 // DOM in a mix of breadth-first and depth-first, it is the responsibility
1103 // of whoever constructs FrameConstructionItem kids of a given
1104 // FrameConstructionItem to push its mPendingBinding as the current
1105 // insertion point before doing so and pop it afterward.
1106 PendingBinding* mPendingBinding;
1107 // The style context to use for creating the new frame.
1108 nsRefPtr<nsStyleContext> mStyleContext;
1109 // Whether optimizations to skip constructing textframes around
1110 // this content need to be suppressed.
1111 bool mSuppressWhiteSpaceOptimizations;
1112 // Whether this is a text content item.
1113 bool mIsText;
1114 // Whether this is a generated content container.
1115 // If it is, mContent is a strong pointer.
1116 bool mIsGeneratedContent;
1117 // Whether this is an item for nsIAnonymousContentCreator content.
1118 bool mIsAnonymousContentCreatorContent;
1119 // Whether this is an item for the root popupgroup.
1120 bool mIsRootPopupgroup;
1121 // Whether construction from this item will create only frames that are
1122 // IsInlineOutside() in the principal child list. This is not precise, but
1123 // conservative: if true the frames will really be inline, whereas if false
1124 // they might still all be inline.
1125 bool mIsAllInline;
1126 // Whether construction from this item will create only frames that are
1127 // IsBlockOutside() in the principal child list. This is not precise, but
1128 // conservative: if true the frames will really be blocks, whereas if false
1129 // they might still be blocks (and in particular, out-of-flows that didn't
1130 // find a containing block).
1131 bool mIsBlock;
1132 // Whether construction from this item will give leading and trailing
1133 // inline frames. This is equal to mIsAllInline, except for inline frame
1134 // items, where it's always true, whereas mIsAllInline might be false due
1135 // to {ib} splits.
1136 bool mHasInlineEnds;
1137 // Whether construction from this item will create a popup that needs to
1138 // go into the global popup items.
1139 bool mIsPopup;
1140 // Whether this item should be treated as a line participant
1141 bool mIsLineParticipant;
1142 // Whether this item is for an SVG <a> element
1143 bool mIsForSVGAElement;
1145 // Child frame construction items.
1146 FrameConstructionItemList mChildItems;
1148 // ContentInfo list for children that have yet to have
1149 // FrameConstructionItem objects created for them. This exists because
1150 // AddFrameConstructionItemsInternal needs a valid frame, but in the case
1151 // that nsIAnonymousContentCreator::CreateAnonymousContent returns items
1152 // that have their own children (so we have a tree of ContentInfo objects
1153 // rather than a flat list) we don't yet have a frame to provide to
1154 // AddFrameConstructionItemsInternal in order to create the items for the
1155 // grandchildren. That prevents FrameConstructionItems from being created
1156 // for these grandchildren (and any descendants that they may have),
1157 // otherwise they could have been added to the mChildItems member of their
1158 // parent FrameConstructionItem. As it is, the grandchildren ContentInfo
1159 // list has to be stored in this mAnonChildren member in order to delay
1160 // construction of the FrameConstructionItems for the grandchildren until
1161 // a frame has been created for their parent item.
1162 nsTArray<nsIAnonymousContentCreator::ContentInfo> mAnonChildren;
1164 private:
1165 FrameConstructionItem(const FrameConstructionItem& aOther) MOZ_DELETE; /* not implemented */
1169 * Function to create the anonymous flex or grid items that we need.
1170 * If aParentFrame is not a nsFlexContainerFrame or nsGridContainerFrame then
1171 * this method is a NOP.
1172 * @param aItems the child frame construction items before pseudo creation
1173 * @param aParentFrame the parent frame
1175 void CreateNeededAnonFlexOrGridItems(nsFrameConstructorState& aState,
1176 FrameConstructionItemList& aItems,
1177 nsIFrame* aParentFrame);
1179 enum RubyWhitespaceType
1181 eRubyNotWhitespace,
1182 eRubyInterLevelWhitespace,
1183 // Includes inter-base and inter-annotation whitespace
1184 eRubyInterLeafWhitespace,
1185 eRubyInterSegmentWhitespace
1189 * Function to compute the whitespace type according to the display
1190 * values of the previous and the next elements.
1192 static inline RubyWhitespaceType ComputeRubyWhitespaceType(
1193 uint_fast8_t aPrevDisplay, uint_fast8_t aNextDisplay);
1196 * Function to interpret the type of whitespace between
1197 * |aStartIter| and |aEndIter|.
1199 static inline RubyWhitespaceType InterpretRubyWhitespace(
1200 nsFrameConstructorState& aState,
1201 const FCItemIterator& aStartIter, const FCItemIterator& aEndIter);
1204 * Function to wrap consecutive misparented inline content into
1205 * a ruby base box or a ruby text box.
1207 void WrapItemsInPseudoRubyLeafBox(FCItemIterator& aIter,
1208 nsStyleContext* aParentStyle,
1209 nsIContent* aParentContent);
1212 * Function to wrap consecutive misparented items
1213 * into a ruby level container.
1215 inline void WrapItemsInPseudoRubyLevelContainer(
1216 nsFrameConstructorState& aState, FCItemIterator& aIter,
1217 nsStyleContext* aParentStyle, nsIContent* aParentContent);
1220 * Function to trim leading and trailing whitespaces.
1222 inline void TrimLeadingAndTrailingWhitespaces(
1223 nsFrameConstructorState& aState, FrameConstructionItemList& aItems);
1226 * Function to create internal ruby boxes.
1228 inline void CreateNeededPseudoInternalRubyBoxes(
1229 nsFrameConstructorState& aState,
1230 FrameConstructionItemList& aItems, nsIFrame* aParentFrame);
1233 * Function to create the pseudo intermediate containers we need.
1234 * @param aItems the child frame construction items before pseudo creation
1235 * @param aParentFrame the parent frame we're creating pseudos for
1237 inline void CreateNeededPseudoContainers(nsFrameConstructorState& aState,
1238 FrameConstructionItemList& aItems,
1239 nsIFrame* aParentFrame);
1242 * Function to wrap consecutive items into a pseudo parent.
1244 inline void WrapItemsInPseudoParent(nsIContent* aParentContent,
1245 nsStyleContext* aParentStyle,
1246 ParentType aWrapperType,
1247 FCItemIterator& aIter,
1248 const FCItemIterator& aEndIter);
1251 * Function to create the pseudo siblings we need.
1253 inline void CreateNeededPseudoSiblings(nsFrameConstructorState& aState,
1254 FrameConstructionItemList& aItems,
1255 nsIFrame* aParentFrame);
1258 * Function to adjust aParentFrame to deal with captions.
1259 * @param aParentFrame the frame we think should be the parent. This will be
1260 * adjusted to point to the right parent frame.
1261 * @param aFCData the FrameConstructionData that would be used for frame
1262 * construction.
1263 * @param aStyleContext the style context for aChildContent
1265 // XXXbz this function should really go away once we rework pseudo-frame
1266 // handling to be better. This should simply be part of the job of
1267 // GetGeometricParent, and stuff like the frameitems and parent frame should
1268 // be kept track of in the state...
1269 void AdjustParentFrame(nsContainerFrame** aParentFrame,
1270 const FrameConstructionData* aFCData,
1271 nsStyleContext* aStyleContext);
1273 // END TABLE SECTION
1275 protected:
1276 static nsIFrame* CreatePlaceholderFrameFor(nsIPresShell* aPresShell,
1277 nsIContent* aContent,
1278 nsIFrame* aFrame,
1279 nsStyleContext* aStyleContext,
1280 nsContainerFrame* aParentFrame,
1281 nsIFrame* aPrevInFlow,
1282 nsFrameState aTypeBit);
1284 private:
1285 // ConstructSelectFrame puts the new frame in aFrameItems and
1286 // handles the kids of the select.
1287 nsIFrame* ConstructSelectFrame(nsFrameConstructorState& aState,
1288 FrameConstructionItem& aItem,
1289 nsContainerFrame* aParentFrame,
1290 const nsStyleDisplay* aStyleDisplay,
1291 nsFrameItems& aFrameItems);
1293 // ConstructFieldSetFrame puts the new frame in aFrameItems and
1294 // handles the kids of the fieldset
1295 nsIFrame* ConstructFieldSetFrame(nsFrameConstructorState& aState,
1296 FrameConstructionItem& aItem,
1297 nsContainerFrame* aParentFrame,
1298 const nsStyleDisplay* aStyleDisplay,
1299 nsFrameItems& aFrameItems);
1301 // aParentFrame might be null. If it is, that means it was an
1302 // inline frame.
1303 static const FrameConstructionData* FindTextData(nsIFrame* aParentFrame);
1305 void ConstructTextFrame(const FrameConstructionData* aData,
1306 nsFrameConstructorState& aState,
1307 nsIContent* aContent,
1308 nsContainerFrame* aParentFrame,
1309 nsStyleContext* aStyleContext,
1310 nsFrameItems& aFrameItems);
1312 // If aPossibleTextContent is a text node and doesn't have a frame, append a
1313 // frame construction item for it to aItems.
1314 void AddTextItemIfNeeded(nsFrameConstructorState& aState,
1315 const InsertionPoint& aInsertion,
1316 nsIContent* aPossibleTextContent,
1317 FrameConstructionItemList& aItems);
1319 // If aParentContent's child aContent is a text node and
1320 // doesn't have a frame, try to create a frame for it.
1321 void ReframeTextIfNeeded(nsIContent* aParentContent,
1322 nsIContent* aContent);
1324 void AddPageBreakItem(nsIContent* aContent,
1325 nsStyleContext* aMainStyleContext,
1326 FrameConstructionItemList& aItems);
1328 // Function to find FrameConstructionData for aElement. Will return
1329 // null if aElement is not HTML.
1330 // aParentFrame might be null. If it is, that means it was an
1331 // inline frame.
1332 static const FrameConstructionData* FindHTMLData(Element* aContent,
1333 nsIAtom* aTag,
1334 int32_t aNameSpaceID,
1335 nsIFrame* aParentFrame,
1336 nsStyleContext* aStyleContext);
1337 // HTML data-finding helper functions
1338 static const FrameConstructionData*
1339 FindImgData(Element* aElement, nsStyleContext* aStyleContext);
1340 static const FrameConstructionData*
1341 FindImgControlData(Element* aElement, nsStyleContext* aStyleContext);
1342 static const FrameConstructionData*
1343 FindInputData(Element* aElement, nsStyleContext* aStyleContext);
1344 static const FrameConstructionData*
1345 FindObjectData(Element* aElement, nsStyleContext* aStyleContext);
1346 static const FrameConstructionData*
1347 FindCanvasData(Element* aElement, nsStyleContext* aStyleContext);
1349 /* Construct a frame from the given FrameConstructionItem. This function
1350 will handle adding the frame to frame lists, processing children, setting
1351 the frame as the primary frame for the item's content, and so forth.
1353 @param aItem the FrameConstructionItem to use.
1354 @param aState the frame construction state to use.
1355 @param aParentFrame the frame to set as the parent of the
1356 newly-constructed frame.
1357 @param aFrameItems the frame list to add the new frame (or its
1358 placeholder) to.
1360 void ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
1361 nsFrameConstructorState& aState,
1362 nsContainerFrame* aParentFrame,
1363 nsFrameItems& aFrameItems);
1365 // possible flags for AddFrameConstructionItemInternal's aFlags argument
1366 /* Allow xbl:base to affect the tag/namespace used. */
1367 #define ITEM_ALLOW_XBL_BASE 0x1
1368 /* Allow page-break before and after items to be created if the
1369 style asks for them. */
1370 #define ITEM_ALLOW_PAGE_BREAK 0x2
1371 /* The item is a generated content item. */
1372 #define ITEM_IS_GENERATED_CONTENT 0x4
1373 /* The item is within an SVG text block frame. */
1374 #define ITEM_IS_WITHIN_SVG_TEXT 0x8
1375 /* The item allows items to be created for SVG <textPath> children. */
1376 #define ITEM_ALLOWS_TEXT_PATH_CHILD 0x10
1377 /* The item is content created by an nsIAnonymousContentCreator frame */
1378 #define ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT 0x20
1379 // The guts of AddFrameConstructionItems
1380 // aParentFrame might be null. If it is, that means it was an
1381 // inline frame.
1382 void AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
1383 nsIContent* aContent,
1384 nsContainerFrame* aParentFrame,
1385 nsIAtom* aTag,
1386 int32_t aNameSpaceID,
1387 bool aSuppressWhiteSpaceOptimizations,
1388 nsStyleContext* aStyleContext,
1389 uint32_t aFlags,
1390 nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
1391 FrameConstructionItemList& aItems);
1394 * Construct frames for the given item list and parent frame, and put the
1395 * resulting frames in aFrameItems.
1397 void ConstructFramesFromItemList(nsFrameConstructorState& aState,
1398 FrameConstructionItemList& aItems,
1399 nsContainerFrame* aParentFrame,
1400 nsFrameItems& aFrameItems);
1401 void ConstructFramesFromItem(nsFrameConstructorState& aState,
1402 FCItemIterator& aItem,
1403 nsContainerFrame* aParentFrame,
1404 nsFrameItems& aFrameItems);
1405 static bool AtLineBoundary(FCItemIterator& aIter);
1407 nsresult CreateAnonymousFrames(nsFrameConstructorState& aState,
1408 nsIContent* aParent,
1409 nsContainerFrame* aParentFrame,
1410 PendingBinding* aPendingBinding,
1411 nsFrameItems& aChildItems);
1413 nsresult GetAnonymousContent(nsIContent* aParent,
1414 nsIFrame* aParentFrame,
1415 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonContent);
1417 //MathML Mod - RBS
1419 * Takes the frames in aBlockItems and wraps them in a new anonymous block
1420 * frame whose content is aContent and whose parent will be aParentFrame.
1421 * The anonymous block is added to aNewItems and aBlockItems is cleared.
1423 void FlushAccumulatedBlock(nsFrameConstructorState& aState,
1424 nsIContent* aContent,
1425 nsContainerFrame* aParentFrame,
1426 nsFrameItems& aBlockItems,
1427 nsFrameItems& aNewItems);
1429 // Function to find FrameConstructionData for aContent. Will return
1430 // null if aContent is not MathML.
1431 static const FrameConstructionData* FindMathMLData(Element* aElement,
1432 nsIAtom* aTag,
1433 int32_t aNameSpaceID,
1434 nsStyleContext* aStyleContext);
1436 // Function to find FrameConstructionData for aContent. Will return
1437 // null if aContent is not XUL.
1438 static const FrameConstructionData* FindXULTagData(Element* aElement,
1439 nsIAtom* aTag,
1440 int32_t aNameSpaceID,
1441 nsStyleContext* aStyleContext);
1442 // XUL data-finding helper functions and structures
1443 #ifdef MOZ_XUL
1444 static const FrameConstructionData*
1445 FindPopupGroupData(Element* aElement, nsStyleContext* aStyleContext);
1446 // sXULTextBoxData used for both labels and descriptions
1447 static const FrameConstructionData sXULTextBoxData;
1448 static const FrameConstructionData*
1449 FindXULLabelData(Element* aElement, nsStyleContext* aStyleContext);
1450 static const FrameConstructionData*
1451 FindXULDescriptionData(Element* aElement, nsStyleContext* aStyleContext);
1452 #ifdef XP_MACOSX
1453 static const FrameConstructionData*
1454 FindXULMenubarData(Element* aElement, nsStyleContext* aStyleContext);
1455 #endif /* XP_MACOSX */
1456 static const FrameConstructionData*
1457 FindXULListBoxBodyData(Element* aElement, nsStyleContext* aStyleContext);
1458 static const FrameConstructionData*
1459 FindXULListItemData(Element* aElement, nsStyleContext* aStyleContext);
1460 #endif /* MOZ_XUL */
1462 // Function to find FrameConstructionData for aContent using one of the XUL
1463 // display types. Will return null if aDisplay doesn't have a XUL display
1464 // type. This function performs no other checks, so should only be called if
1465 // we know for sure that the content is not something that should get a frame
1466 // constructed by tag.
1467 static const FrameConstructionData*
1468 FindXULDisplayData(const nsStyleDisplay* aDisplay,
1469 Element* aElement,
1470 nsStyleContext* aStyleContext);
1473 * Constructs an outer frame, an anonymous child that wraps its real
1474 * children, and its descendant frames. This is used by both ConstructOuterSVG
1475 * and ConstructMarker, which both want an anonymous block child for their
1476 * children to go in to.
1478 nsContainerFrame* ConstructFrameWithAnonymousChild(
1479 nsFrameConstructorState& aState,
1480 FrameConstructionItem& aItem,
1481 nsContainerFrame* aParentFrame,
1482 const nsStyleDisplay* aDisplay,
1483 nsFrameItems& aFrameItems,
1484 ContainerFrameCreationFunc aConstructor,
1485 ContainerFrameCreationFunc aInnerConstructor,
1486 nsICSSAnonBoxPseudo* aInnerPseudo,
1487 bool aCandidateRootFrame);
1490 * Construct an nsSVGOuterSVGFrame.
1492 nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState,
1493 FrameConstructionItem& aItem,
1494 nsContainerFrame* aParentFrame,
1495 const nsStyleDisplay* aDisplay,
1496 nsFrameItems& aFrameItems);
1499 * Construct an nsSVGMarkerFrame.
1501 nsIFrame* ConstructMarker(nsFrameConstructorState& aState,
1502 FrameConstructionItem& aItem,
1503 nsContainerFrame* aParentFrame,
1504 const nsStyleDisplay* aDisplay,
1505 nsFrameItems& aFrameItems);
1507 static const FrameConstructionData* FindSVGData(Element* aElement,
1508 nsIAtom* aTag,
1509 int32_t aNameSpaceID,
1510 nsIFrame* aParentFrame,
1511 bool aIsWithinSVGText,
1512 bool aAllowsTextPathChild,
1513 nsStyleContext* aStyleContext);
1515 /* Not static because it does PropagateScrollToViewport. If this
1516 changes, make this static */
1517 const FrameConstructionData*
1518 FindDisplayData(const nsStyleDisplay* aDisplay, Element* aElement,
1519 nsIFrame* aParentFrame, nsStyleContext* aStyleContext);
1522 * Construct a scrollable block frame
1524 nsIFrame* ConstructScrollableBlock(nsFrameConstructorState& aState,
1525 FrameConstructionItem& aItem,
1526 nsContainerFrame* aParentFrame,
1527 const nsStyleDisplay* aDisplay,
1528 nsFrameItems& aFrameItems);
1531 * Construct a non-scrollable block frame
1533 nsIFrame* ConstructNonScrollableBlock(nsFrameConstructorState& aState,
1534 FrameConstructionItem& aItem,
1535 nsContainerFrame* aParentFrame,
1536 const nsStyleDisplay* aDisplay,
1537 nsFrameItems& aFrameItems);
1540 * This adds FrameConstructionItem objects to aItemsToConstruct for the
1541 * anonymous content returned by an nsIAnonymousContentCreator::
1542 * CreateAnonymousContent implementation.
1544 void AddFCItemsForAnonymousContent(
1545 nsFrameConstructorState& aState,
1546 nsContainerFrame* aFrame,
1547 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
1548 FrameConstructionItemList& aItemsToConstruct,
1549 uint32_t aExtraFlags = 0);
1552 * Construct the frames for the children of aContent. "children" is defined
1553 * as "whatever FlattenedChildIterator returns for aContent". This means we're
1554 * basically operating on children in the "flattened tree" per sXBL/XBL2.
1555 * This method will also handle constructing ::before, ::after,
1556 * ::first-letter, and ::first-line frames, as needed and if allowed.
1558 * If the parent is a float containing block, this method will handle pushing
1559 * it as the float containing block in aState (so there's no need for callers
1560 * to push it themselves).
1562 * @param aState the frame construction state
1563 * @param aContent the content node whose children need frames
1564 * @param aStyleContext the style context for aContent
1565 * @param aParentFrame the frame to use as the parent frame for the new in-flow
1566 * kids. Note that this must be its own content insertion frame, but
1567 * need not be be the primary frame for aContent. This frame will be
1568 * pushed as the float containing block, as needed. aFrame is also
1569 * used to find the parent style context for the kids' style contexts
1570 * (not necessary aFrame's style context).
1571 * @param aCanHaveGeneratedContent Whether to allow :before and
1572 * :after styles on the parent.
1573 * @param aFrameItems the list in which we should place the in-flow children
1574 * @param aAllowBlockStyles Whether to allow first-letter and first-line
1575 * styles on the parent.
1576 * @param aPendingBinding Make sure to push this into aState before doing any
1577 * child item construction.
1578 * @param aPossiblyLeafFrame if non-null, this should be used for the isLeaf
1579 * test and the anonymous content creation. If null, aFrame will be
1580 * used.
1582 void ProcessChildren(nsFrameConstructorState& aState,
1583 nsIContent* aContent,
1584 nsStyleContext* aStyleContext,
1585 nsContainerFrame* aParentFrame,
1586 const bool aCanHaveGeneratedContent,
1587 nsFrameItems& aFrameItems,
1588 const bool aAllowBlockStyles,
1589 PendingBinding* aPendingBinding,
1590 nsIFrame* aPossiblyLeafFrame = nullptr);
1593 * These two functions are used when we start frame creation from a non-root
1594 * element. They should recreate the same state that we would have
1595 * arrived at if we had built frames from the root frame to aFrame.
1596 * Therefore, any calls to PushFloatContainingBlock and
1597 * PushAbsoluteContainingBlock during frame construction should get
1598 * corresponding logic in these functions.
1600 public:
1601 enum ContainingBlockType {
1602 ABS_POS,
1603 FIXED_POS
1605 nsContainerFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame,
1606 ContainingBlockType aType);
1607 nsContainerFrame* GetFloatContainingBlock(nsIFrame* aFrame);
1609 private:
1610 nsIContent* PropagateScrollToViewport();
1612 // Build a scroll frame:
1613 // Calls BeginBuildingScrollFrame, InitAndRestoreFrame, and then FinishBuildingScrollFrame.
1614 // @param aNewFrame the created scrollframe --- output only
1615 // @param aParentFrame the geometric parent that the scrollframe will have.
1616 void
1617 BuildScrollFrame(nsFrameConstructorState& aState,
1618 nsIContent* aContent,
1619 nsStyleContext* aContentStyle,
1620 nsIFrame* aScrolledFrame,
1621 nsContainerFrame* aParentFrame,
1622 nsContainerFrame*& aNewFrame);
1624 // Builds the initial ScrollFrame
1625 already_AddRefed<nsStyleContext>
1626 BeginBuildingScrollFrame(nsFrameConstructorState& aState,
1627 nsIContent* aContent,
1628 nsStyleContext* aContentStyle,
1629 nsContainerFrame* aParentFrame,
1630 nsIAtom* aScrolledPseudo,
1631 bool aIsRoot,
1632 nsContainerFrame*& aNewFrame);
1634 // Completes the building of the scrollframe:
1635 // Creates a view for the scrolledframe and makes it the child of the scrollframe.
1636 void
1637 FinishBuildingScrollFrame(nsContainerFrame* aScrollFrame,
1638 nsIFrame* aScrolledFrame);
1640 // InitializeSelectFrame puts scrollFrame in aFrameItems if aBuildCombobox is false
1641 // aBuildCombobox indicates if we are building a combobox that has a dropdown
1642 // popup widget or not.
1643 nsresult
1644 InitializeSelectFrame(nsFrameConstructorState& aState,
1645 nsContainerFrame* aScrollFrame,
1646 nsContainerFrame* aScrolledFrame,
1647 nsIContent* aContent,
1648 nsContainerFrame* aParentFrame,
1649 nsStyleContext* aStyleContext,
1650 bool aBuildCombobox,
1651 PendingBinding* aPendingBinding,
1652 nsFrameItems& aFrameItems);
1655 * ReResolve style for aElement then recreate frames if required.
1656 * Do nothing for other types of style changes, except for undisplayed nodes
1657 * (display:none/contents) which will have their style context updated in the
1658 * frame manager undisplayed maps.
1659 * @return null if frames were recreated, the new style context otherwise
1661 nsStyleContext* MaybeRecreateFramesForElement(Element* aElement);
1664 * Recreate frames for aContent.
1665 * @param aContent the content to recreate frames for
1666 * @param aAsyncInsert if true then a restyle event will be posted to handle
1667 * the required ContentInserted call instead of doing it immediately.
1668 * @param aFlags normally you want to pass REMOVE_FOR_RECONSTRUCTION here
1669 * @param aDestroyedFramesFor if non-null, it will contain the content that
1670 * was actually reframed - it may be different than aContent.
1672 nsresult
1673 RecreateFramesForContent(nsIContent* aContent,
1674 bool aAsyncInsert,
1675 RemoveFlags aFlags,
1676 nsIContent** aDestroyedFramesFor);
1678 // If removal of aFrame from the frame tree requires reconstruction of some
1679 // containing block (either of aFrame or of its parent) due to {ib} splits or
1680 // table pseudo-frames, recreate the relevant frame subtree. The return value
1681 // indicates whether this happened. If this method returns true, *aResult is
1682 // the return value of ReframeContainingBlock or RecreateFramesForContent. If
1683 // this method returns false, the value of *aResult is not affected. aFrame
1684 // and aResult must not be null. aFrame must be the result of a
1685 // GetPrimaryFrame() call on a content node (which means its parent is also
1686 // not null). If this method returns true, aDestroyedFramesFor contains the
1687 // content that was reframed.
1688 bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
1689 RemoveFlags aFlags,
1690 nsresult* aResult,
1691 nsIContent** aDestroyedFramesFor);
1693 nsIFrame* CreateContinuingOuterTableFrame(nsIPresShell* aPresShell,
1694 nsPresContext* aPresContext,
1695 nsIFrame* aFrame,
1696 nsContainerFrame* aParentFrame,
1697 nsIContent* aContent,
1698 nsStyleContext* aStyleContext);
1700 nsIFrame* CreateContinuingTableFrame(nsIPresShell* aPresShell,
1701 nsPresContext* aPresContext,
1702 nsIFrame* aFrame,
1703 nsContainerFrame* aParentFrame,
1704 nsIContent* aContent,
1705 nsStyleContext* aStyleContext);
1707 //----------------------------------------
1709 // Methods support creating block frames and their children
1711 already_AddRefed<nsStyleContext>
1712 GetFirstLetterStyle(nsIContent* aContent,
1713 nsStyleContext* aStyleContext);
1715 already_AddRefed<nsStyleContext>
1716 GetFirstLineStyle(nsIContent* aContent,
1717 nsStyleContext* aStyleContext);
1719 bool ShouldHaveFirstLetterStyle(nsIContent* aContent,
1720 nsStyleContext* aStyleContext);
1722 // Check whether a given block has first-letter style. Make sure to
1723 // only pass in blocks! And don't pass in null either.
1724 bool HasFirstLetterStyle(nsIFrame* aBlockFrame);
1726 bool ShouldHaveFirstLineStyle(nsIContent* aContent,
1727 nsStyleContext* aStyleContext);
1729 void ShouldHaveSpecialBlockStyle(nsIContent* aContent,
1730 nsStyleContext* aStyleContext,
1731 bool* aHaveFirstLetterStyle,
1732 bool* aHaveFirstLineStyle);
1734 // |aContentParentFrame| should be null if it's really the same as
1735 // |aParentFrame|.
1736 // @param aFrameItems where we want to put the block in case it's in-flow.
1737 // @param aNewFrame an in/out parameter. On input it is the block to be
1738 // constructed. On output it is reset to the outermost
1739 // frame constructed (e.g. if we need to wrap the block in an
1740 // nsColumnSetFrame.
1741 // @param aParentFrame is the desired parent for the (possibly wrapped)
1742 // block
1743 // @param aContentParent is the parent the block would have if it
1744 // were in-flow
1745 // @param aPositionedFrameForAbsPosContainer if non-null, then the new
1746 // block should be an abs-pos container and aPositionedFrameForAbsPosContainer
1747 // is the frame whose style is making this block an abs-pos container.
1748 // @param aPendingBinding the pending binding from this block's frame
1749 // construction item.
1750 void ConstructBlock(nsFrameConstructorState& aState,
1751 const nsStyleDisplay* aDisplay,
1752 nsIContent* aContent,
1753 nsContainerFrame* aParentFrame,
1754 nsContainerFrame* aContentParentFrame,
1755 nsStyleContext* aStyleContext,
1756 nsContainerFrame** aNewFrame,
1757 nsFrameItems& aFrameItems,
1758 nsIFrame* aPositionedFrameForAbsPosContainer,
1759 PendingBinding* aPendingBinding);
1761 nsIFrame* ConstructInline(nsFrameConstructorState& aState,
1762 FrameConstructionItem& aItem,
1763 nsContainerFrame* aParentFrame,
1764 const nsStyleDisplay* aDisplay,
1765 nsFrameItems& aFrameItems);
1768 * Create any additional {ib} siblings needed to contain aChildItems and put
1769 * them in aSiblings.
1771 * @param aState the frame constructor state
1772 * @param aInitialInline is an already-existing inline frame that will be
1773 * part of this {ib} split and come before everything
1774 * in aSiblings.
1775 * @param aIsPositioned true if aInitialInline is positioned.
1776 * @param aChildItems is a child list starting with a block; this method
1777 * assumes that the inline has already taken all the
1778 * children it wants. When the method returns aChildItems
1779 * will be empty.
1780 * @param aSiblings the nsFrameItems to put the newly-created siblings into.
1782 * This method is responsible for making any SetFrameIsIBSplit calls that are
1783 * needed.
1785 void CreateIBSiblings(nsFrameConstructorState& aState,
1786 nsContainerFrame* aInitialInline,
1787 bool aIsPositioned,
1788 nsFrameItems& aChildItems,
1789 nsFrameItems& aSiblings);
1792 * For an inline aParentItem, construct its list of child
1793 * FrameConstructionItems and set its mIsAllInline flag appropriately.
1795 void BuildInlineChildItems(nsFrameConstructorState& aState,
1796 FrameConstructionItem& aParentItem,
1797 bool aItemIsWithinSVGText,
1798 bool aItemAllowsTextPathChild);
1800 // Determine whether we need to wipe out what we just did and start over
1801 // because we're doing something like adding block kids to an inline frame
1802 // (and therefore need an {ib} split). aPrevSibling must be correct, even in
1803 // aIsAppend cases. Passing aIsAppend false even when an append is happening
1804 // is ok in terms of correctness, but can lead to unnecessary reframing. If
1805 // aIsAppend is true, then the caller MUST call
1806 // nsCSSFrameConstructor::AppendFramesToParent (as opposed to
1807 // nsFrameManager::InsertFrames directly) to add the new frames.
1808 // @return true if we reconstructed the containing block, false
1809 // otherwise
1810 bool WipeContainingBlock(nsFrameConstructorState& aState,
1811 nsIFrame* aContainingBlock,
1812 nsIFrame* aFrame,
1813 FrameConstructionItemList& aItems,
1814 bool aIsAppend,
1815 nsIFrame* aPrevSibling);
1817 nsresult ReframeContainingBlock(nsIFrame* aFrame,
1818 RemoveFlags aFlags,
1819 nsIContent** aReframeContent);
1821 //----------------------------------------
1823 // Methods support :first-letter style
1825 void CreateFloatingLetterFrame(nsFrameConstructorState& aState,
1826 nsContainerFrame* aBlockFrame,
1827 nsIContent* aTextContent,
1828 nsIFrame* aTextFrame,
1829 nsContainerFrame* aParentFrame,
1830 nsStyleContext* aStyleContext,
1831 nsFrameItems& aResult);
1833 void CreateLetterFrame(nsContainerFrame* aBlockFrame,
1834 nsContainerFrame* aBlockContinuation,
1835 nsIContent* aTextContent,
1836 nsContainerFrame* aParentFrame,
1837 nsFrameItems& aResult);
1839 void WrapFramesInFirstLetterFrame(nsIContent* aBlockContent,
1840 nsContainerFrame* aBlockFrame,
1841 nsFrameItems& aBlockFrames);
1844 * Looks in the block aBlockFrame for a text frame that contains the
1845 * first-letter of the block and creates the necessary first-letter frames
1846 * and returns them in aLetterFrames.
1848 * @param aBlockFrame the (first-continuation of) the block we are creating a
1849 * first-letter frame for
1850 * @param aBlockContinuation the current continuation of the block that we
1851 * are looking in for a textframe with suitable
1852 * contents for first-letter
1853 * @param aParentFrame the current frame whose children we are looking at for
1854 * a suitable first-letter textframe
1855 * @param aParentFrameList the first child of aParentFrame
1856 * @param aModifiedParent returns the parent of the textframe that contains
1857 * the first-letter
1858 * @param aTextFrame returns the textframe that had the first-letter
1859 * @param aPrevFrame returns the previous sibling of aTextFrame
1860 * @param aLetterFrames returns the frames that were created
1861 * @param aStopLooking returns whether we should stop looking for a
1862 * first-letter either because it was found or won't be
1863 * found
1865 void WrapFramesInFirstLetterFrame(nsContainerFrame* aBlockFrame,
1866 nsContainerFrame* aBlockContinuation,
1867 nsContainerFrame* aParentFrame,
1868 nsIFrame* aParentFrameList,
1869 nsContainerFrame** aModifiedParent,
1870 nsIFrame** aTextFrame,
1871 nsIFrame** aPrevFrame,
1872 nsFrameItems& aLetterFrames,
1873 bool* aStopLooking);
1875 void RecoverLetterFrames(nsContainerFrame* aBlockFrame);
1878 nsresult RemoveLetterFrames(nsPresContext* aPresContext,
1879 nsIPresShell* aPresShell,
1880 nsContainerFrame* aBlockFrame);
1882 // Recursive helper for RemoveLetterFrames
1883 nsresult RemoveFirstLetterFrames(nsPresContext* aPresContext,
1884 nsIPresShell* aPresShell,
1885 nsContainerFrame* aFrame,
1886 nsContainerFrame* aBlockFrame,
1887 bool* aStopLooking);
1889 // Special remove method for those pesky floating first-letter frames
1890 nsresult RemoveFloatingFirstLetterFrames(nsPresContext* aPresContext,
1891 nsIPresShell* aPresShell,
1892 nsIFrame* aBlockFrame,
1893 bool* aStopLooking);
1895 // Capture state for the frame tree rooted at the frame associated with the
1896 // content object, aContent
1897 void CaptureStateForFramesOf(nsIContent* aContent,
1898 nsILayoutHistoryState* aHistoryState);
1900 //----------------------------------------
1902 // Methods support :first-line style
1904 // This method chops the initial inline-outside frames out of aFrameItems.
1905 // If aLineFrame is non-null, it appends them to that frame. Otherwise, it
1906 // creates a new line frame, sets the inline frames as its initial child
1907 // list, and inserts that line frame at the front of what's left of
1908 // aFrameItems. In both cases, the kids are reparented to the line frame.
1909 // After this call, aFrameItems holds the frames that need to become kids of
1910 // the block (possibly including line frames).
1911 void WrapFramesInFirstLineFrame(nsFrameConstructorState& aState,
1912 nsIContent* aBlockContent,
1913 nsContainerFrame* aBlockFrame,
1914 nsFirstLineFrame* aLineFrame,
1915 nsFrameItems& aFrameItems);
1917 // Handle the case when a block with first-line style is appended to (by
1918 // possibly calling WrapFramesInFirstLineFrame as needed).
1919 void AppendFirstLineFrames(nsFrameConstructorState& aState,
1920 nsIContent* aContent,
1921 nsContainerFrame* aBlockFrame,
1922 nsFrameItems& aFrameItems);
1924 nsresult InsertFirstLineFrames(nsFrameConstructorState& aState,
1925 nsIContent* aContent,
1926 nsIFrame* aBlockFrame,
1927 nsContainerFrame** aParentFrame,
1928 nsIFrame* aPrevSibling,
1929 nsFrameItems& aFrameItems);
1932 * Find the right frame to use for aContent when looking for sibling
1933 * frames for aTargetContent. If aPrevSibling is true, this
1934 * will look for last continuations, etc, as necessary. This calls
1935 * IsValidSibling as needed; if that returns false it returns null.
1937 * @param aContent the content to search for frames
1938 * @param aTargetContent the content we're finding a sibling frame for
1939 * @param aTargetContentDisplay the CSS display enum for aTargetContent if
1940 * already known, UNSET_DISPLAY otherwise. It will be filled in
1941 * if needed.
1942 * @param aParentFrame the nearest ancestor frame, used internally for
1943 * finding ::after / ::before frames
1944 * @param aPrevSibling true if we're searching in reverse DOM order
1946 nsIFrame* FindFrameForContentSibling(nsIContent* aContent,
1947 nsIContent* aTargetContent,
1948 uint8_t& aTargetContentDisplay,
1949 nsContainerFrame* aParentFrame,
1950 bool aPrevSibling);
1953 * Find the frame for the content immediately preceding the one aIter
1954 * points to, following continuations if necessary. aIter is passed by
1955 * value on purpose, so as not to modify the caller's iterator.
1957 * @param aIter should be positioned such that aIter.GetPreviousChild()
1958 * is the first content to search for frames
1959 * @param aTargetContent the content we're finding a sibling frame for
1960 * @param aTargetContentDisplay the CSS display enum for aTargetContent if
1961 * already known, UNSET_DISPLAY otherwise. It will be filled in
1962 * if needed.
1963 * @param aParentFrame the nearest ancestor frame, used inernally for
1964 * finding ::after / ::before frames
1966 nsIFrame* FindPreviousSibling(mozilla::dom::FlattenedChildIterator aIter,
1967 nsIContent* aTargetContent,
1968 uint8_t& aTargetContentDisplay,
1969 nsContainerFrame* aParentFrame);
1972 * Find the frame for the content node immediately following the one aIter
1973 * points to, following continuations if necessary. aIter is passed by value
1974 * on purpose, so as not to modify the caller's iterator.
1976 * @param aIter should be positioned such that aIter.GetNextChild()
1977 * is the first content to search for frames
1978 * @param aTargetContent the content we're finding a sibling frame for
1979 * @param aTargetContentDisplay the CSS display enum for aTargetContent if
1980 * already known, UNSET_DISPLAY otherwise. It will be filled in
1981 * if needed.
1982 * @param aParentFrame the nearest ancestor frame, used inernally for
1983 * finding ::after / ::before frames
1985 nsIFrame* FindNextSibling(mozilla::dom::FlattenedChildIterator aIter,
1986 nsIContent* aTargetContent,
1987 uint8_t& aTargetContentDisplay,
1988 nsContainerFrame* aParentFrame);
1990 // Find the right previous sibling for an insertion. This also updates the
1991 // parent frame to point to the correct continuation of the parent frame to
1992 // use, and returns whether this insertion is to be treated as an append.
1993 // aChild is the child being inserted.
1994 // aIsRangeInsertSafe returns whether it is safe to do a range insert with
1995 // aChild being the first child in the range. It is the callers'
1996 // responsibility to check whether a range insert is safe with regards to
1997 // fieldsets.
1998 // The skip parameters are used to ignore a range of children when looking
1999 // for a sibling. All nodes starting from aStartSkipChild and up to but not
2000 // including aEndSkipChild will be skipped over when looking for sibling
2001 // frames. Skipping a range can deal with XBL but not when there are multiple
2002 // insertion points.
2003 nsIFrame* GetInsertionPrevSibling(InsertionPoint* aInsertion, // inout
2004 nsIContent* aChild,
2005 bool* aIsAppend,
2006 bool* aIsRangeInsertSafe,
2007 nsIContent* aStartSkipChild = nullptr,
2008 nsIContent *aEndSkipChild = nullptr);
2011 * Return the insertion frame of the primary frame of aContent, or its nearest
2012 * ancestor that isn't display:contents.
2014 nsContainerFrame* GetContentInsertionFrameFor(nsIContent* aContent);
2016 // see if aContent and aSibling are legitimate siblings due to restrictions
2017 // imposed by table columns
2018 // XXXbz this code is generally wrong, since the frame for aContent
2019 // may be constructed based on tag, not based on aDisplay!
2020 bool IsValidSibling(nsIFrame* aSibling,
2021 nsIContent* aContent,
2022 uint8_t& aDisplay);
2024 void QuotesDirty() {
2025 NS_PRECONDITION(mUpdateCount != 0, "Instant quote updates are bad news");
2026 mQuotesDirty = true;
2027 mDocument->SetNeedLayoutFlush();
2030 void CountersDirty() {
2031 NS_PRECONDITION(mUpdateCount != 0, "Instant counter updates are bad news");
2032 mCountersDirty = true;
2033 mDocument->SetNeedLayoutFlush();
2037 * Add the pair (aContent, aStyleContext) to the undisplayed items
2038 * in aList as needed. This method enforces the invariant that all
2039 * style contexts in the undisplayed content map must be non-pseudo
2040 * contexts and also handles unbinding undisplayed generated content
2041 * as needed.
2043 void SetAsUndisplayedContent(nsFrameConstructorState& aState,
2044 FrameConstructionItemList& aList,
2045 nsIContent* aContent,
2046 nsStyleContext* aStyleContext,
2047 bool aIsGeneratedContent);
2048 // Create touch caret frame.
2049 void ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
2050 nsIFrame* aFrame,
2051 nsIContent* aDocElement);
2053 public:
2055 friend class nsFrameConstructorState;
2057 private:
2059 nsIDocument* mDocument; // Weak ref
2061 // See the comment at the start of ConstructRootFrame for more details
2062 // about the following frames.
2064 // This is just the outermost frame for the root element.
2065 nsContainerFrame* mRootElementFrame;
2066 // This is the frame for the root element that has no pseudo-element style.
2067 nsIFrame* mRootElementStyleFrame;
2068 // This is the containing block that contains the root element ---
2069 // the real "initial containing block" according to CSS 2.1.
2070 nsContainerFrame* mDocElementContainingBlock;
2071 nsIFrame* mGfxScrollFrame;
2072 nsIFrame* mPageSequenceFrame;
2073 nsQuoteList mQuoteList;
2074 nsCounterManager mCounterManager;
2075 // Current ProcessChildren depth.
2076 uint16_t mCurrentDepth;
2077 uint16_t mUpdateCount;
2078 bool mQuotesDirty : 1;
2079 bool mCountersDirty : 1;
2080 bool mIsDestroyingFrameTree : 1;
2081 // This is true if mDocElementContainingBlock supports absolute positioning
2082 bool mHasRootAbsPosContainingBlock : 1;
2083 bool mAlwaysCreateFramesForIgnorableWhitespace : 1;
2085 nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
2088 #endif /* nsCSSFrameConstructor_h___ */