Bug 1867190 - Initialise the PHC allocate delay later r=glandium
[gecko.git] / layout / base / nsCSSFrameConstructor.h
blob1b48fd15dcc4307a5d9d2aae35c947cf5d8256bc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
8 * construction of a frame tree that is nearly isomorphic to the content
9 * tree and updating of that tree in response to dynamic changes
12 #ifndef nsCSSFrameConstructor_h___
13 #define nsCSSFrameConstructor_h___
15 #include "mozilla/ArenaAllocator.h"
16 #include "mozilla/Attributes.h"
17 #include "mozilla/ContainStyleScopeManager.h"
18 #include "mozilla/FunctionRef.h"
19 #include "mozilla/LinkedList.h"
20 #include "mozilla/Maybe.h"
21 #include "mozilla/ScrollStyles.h"
22 #include "mozilla/UniquePtr.h"
23 #include "mozilla/PresShell.h"
25 #include "nsCOMPtr.h"
26 #include "nsILayoutHistoryState.h"
27 #include "nsIAnonymousContentCreator.h"
28 #include "nsFrameManager.h"
29 #include "nsIFrame.h"
31 struct nsStyleDisplay;
32 struct nsGenConInitializer;
34 class nsBlockFrame;
35 class nsContainerFrame;
36 class nsFirstLineFrame;
37 class nsFirstLetterFrame;
38 class nsCSSAnonBoxPseudoStaticAtom;
39 class nsPageSequenceFrame;
41 class nsPageContentFrame;
43 class nsFrameConstructorState;
45 namespace mozilla {
47 class ComputedStyle;
48 class PresShell;
49 class PrintedSheetFrame;
50 class RestyleManager;
52 namespace dom {
54 class CharacterData;
55 class Text;
56 class FlattenedChildIterator;
58 } // namespace dom
59 } // namespace mozilla
61 class nsCSSFrameConstructor final : public nsFrameManager {
62 public:
63 using ComputedStyle = mozilla::ComputedStyle;
64 using PseudoStyleType = mozilla::PseudoStyleType;
65 using PresShell = mozilla::PresShell;
66 using Element = mozilla::dom::Element;
67 using Text = mozilla::dom::Text;
69 // FIXME(emilio): Is this really needed?
70 friend class mozilla::RestyleManager;
72 nsCSSFrameConstructor(mozilla::dom::Document* aDocument,
73 PresShell* aPresShell);
74 ~nsCSSFrameConstructor() { MOZ_ASSERT(mFCItemsInUse == 0); }
76 static void GetAlternateTextFor(const Element&, nsAString& aAltText);
78 private:
79 nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) = delete;
80 nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) = delete;
82 public:
83 /**
84 * Whether insertion should be done synchronously or asynchronously.
86 * Generally, insertion is synchronous if we're entering frame construction
87 * from restyle processing, and async if we're removing stuff, or need to
88 * reconstruct some ancestor.
90 * Note that constructing async from frame construction will post a restyle
91 * event, but won't need another whole refresh driver tick to go in. Instead
92 * change hint processing will keep going as long as there are changes in the
93 * queue.
95 enum class InsertionKind {
96 Sync,
97 Async,
100 mozilla::RestyleManager* RestyleManager() const {
101 return mPresShell->GetPresContext()->RestyleManager();
104 nsIFrame* ConstructRootFrame();
106 private:
107 enum Operation { CONTENTAPPEND, CONTENTINSERT };
109 // aChild is the child being inserted for inserts, and the first
110 // child being appended for appends.
111 void ConstructLazily(Operation aOperation, nsIContent* aChild);
113 #ifdef DEBUG
114 void CheckBitsForLazyFrameConstruction(nsIContent* aParent);
115 #else
116 void CheckBitsForLazyFrameConstruction(nsIContent*) {}
117 #endif
119 // Issues a single ContentInserted for each child in the range
120 // [aStartChild, aEndChild).
121 void IssueSingleInsertNofications(nsIContent* aStartChild,
122 nsIContent* aEndChild, InsertionKind);
125 * Data that represents an insertion point for some child content.
127 struct InsertionPoint {
128 InsertionPoint() : mParentFrame(nullptr), mContainer(nullptr) {}
130 InsertionPoint(nsContainerFrame* aParentFrame, nsIContent* aContainer)
131 : mParentFrame(aParentFrame), mContainer(aContainer) {}
134 * The parent frame to use if the inserted children needs to create
135 * frame(s). May be null, which signals that we shouldn't try to
136 * create frames for the inserted children; either because there are
137 * no parent frame or because there are multiple insertion points and
138 * we will call IssueSingleInsertNofications for each child instead.
139 * mContainer should not be used when mParentFrame is null.
141 nsContainerFrame* mParentFrame;
143 * The flattened tree parent for the inserted children.
144 * It's undefined if mParentFrame is null.
146 nsIContent* mContainer;
149 * Whether it is required to insert children one-by-one instead of as a
150 * range.
152 bool IsMultiple() const;
156 * Checks if the children in the range [aStartChild, aEndChild) can be
157 * inserted/appended to one insertion point together.
159 * If so, returns that insertion point. If not, returns with
160 * InsertionPoint.mFrame == nullptr and issues single ContentInserted calls
161 * for each child.
163 * aEndChild = nullptr indicates that we are dealing with an append.
165 InsertionPoint GetRangeInsertionPoint(nsIContent* aStartChild,
166 nsIContent* aEndChild, InsertionKind);
168 // Returns true if parent was recreated due to frameset child, false
169 // otherwise.
170 bool MaybeRecreateForFrameset(nsIFrame* aParentFrame, nsIContent* aStartChild,
171 nsIContent* aEndChild);
174 * For each child in the aStartChild/aEndChild range, calls
175 * NoteDirtyDescendantsForServo on their flattened tree parents. This is
176 * used when content is inserted into the document and we decide that
177 * we can do lazy frame construction. It handles children being rebound to
178 * different insertion points by calling NoteDirtyDescendantsForServo on each
179 * child's flattened tree parent. Only used when we are styled by Servo.
181 void LazilyStyleNewChildRange(nsIContent* aStartChild, nsIContent* aEndChild);
184 * For each child in the aStartChild/aEndChild range, calls StyleNewChildren
185 * on their flattened tree parents. This is used when content is inserted
186 * into the document and we decide that we cannot do lazy frame construction.
187 * It handles children being rebound to different insertion points by calling
188 * StyleNewChildren on each child's flattened tree parent. Only used when we
189 * are styled by Servo.
191 void StyleNewChildRange(nsIContent* aStartChild, nsIContent* aEndChild);
193 public:
195 * Lazy frame construction is controlled by the InsertionKind parameter of
196 * nsCSSFrameConstructor::ContentAppended/Inserted. It is true for all
197 * inserts/appends as passed from the presshell, except for the insert of the
198 * root element, which is always non-lazy.
200 * If we construct lazily, then we add NODE_NEEDS_FRAME bits to the newly
201 * inserted/appended nodes and adds NODE_DESCENDANTS_NEED_FRAMES bits to the
202 * container and up along the parent chain until it hits the root or another
203 * node with that bit set. Then it posts a restyle event to ensure that a
204 * flush happens to construct those frames.
206 * When the flush happens the RestyleManager walks the dirty nodes during
207 * ProcessPostTraversal, and ends up calling Content{Appended,Inserted} with
208 * InsertionKind::Sync in ProcessRestyledFrames.
210 * If a node is removed from the document then we don't bother unsetting any
211 * of the lazy bits that might be set on it, its descendants, or any of its
212 * ancestor nodes because that is a slow operation, the work might be wasted
213 * if another node gets inserted in its place, and we can clear the bits
214 * quicker by processing the content tree from top down the next time we
215 * reconstruct frames. (We do clear the bits when BindToTree is called on any
216 * nsIContent; so any nodes added to the document will not have any lazy bits
217 * set.)
220 // If the insertion kind is Async then frame construction of the new children
221 // can be done lazily.
222 void ContentAppended(nsIContent* aFirstNewContent, InsertionKind);
224 // If the insertion kind is Async then frame construction of the new child
225 // can be done lazily.
226 void ContentInserted(nsIContent* aChild, InsertionKind);
228 // Like ContentInserted but handles inserting the children in the range
229 // [aStartChild, aEndChild). aStartChild must be non-null. aEndChild may be
230 // null to indicate the range includes all kids after aStartChild.
232 // If aInsertionKind is Async then frame construction of the new children can
233 // be done lazily. It is only allowed to be Async when inserting a single
234 // node.
235 void ContentRangeInserted(nsIContent* aStartChild, nsIContent* aEndChild,
236 InsertionKind aInsertionKind);
238 enum RemoveFlags {
239 REMOVE_CONTENT,
240 REMOVE_FOR_RECONSTRUCTION,
244 * Recreate or destroy frames for aChild.
246 * aFlags == REMOVE_CONTENT means aChild has been removed from the document.
247 * aFlags == REMOVE_FOR_RECONSTRUCTION means the caller will reconstruct the
248 * frames later.
250 * In both the above cases, this method will in some cases try to reconstruct
251 * frames on some ancestor of aChild. This can happen regardless of the value
252 * of aFlags.
254 * The return value indicates whether this "reconstruct an ancestor" action
255 * took place. If true is returned, that means that the frame subtree rooted
256 * at some ancestor of aChild's frame was destroyed and will be reconstructed
257 * async.
259 bool ContentRemoved(nsIContent* aChild, nsIContent* aOldNextSibling,
260 RemoveFlags aFlags);
262 void CharacterDataChanged(nsIContent* aContent,
263 const CharacterDataChangeInfo& aInfo);
265 // If aContent is a text node that has been optimized away due to being
266 // whitespace next to a block boundary (or for some other reason), ensure that
267 // a frame for it is created the next time frames are flushed, if it can
268 // possibly have a frame at all.
270 // Returns whether there are chances for the frame to be unsuppressed.
271 bool EnsureFrameForTextNodeIsCreatedAfterFlush(
272 mozilla::dom::CharacterData* aContent);
274 // Should be called when a frame is going to be destroyed and
275 // WillDestroyFrameTree hasn't been called yet.
276 void NotifyDestroyingFrame(nsIFrame* aFrame);
278 void RecalcQuotesAndCounters();
280 // Called when any counter style is changed.
281 void NotifyCounterStylesAreDirty();
283 // Gets called when the presshell is destroying itself and also
284 // when we tear down our frame tree to reconstruct it
285 void WillDestroyFrameTree();
288 * Destroy the frames for aContent. Note that this may destroy frames
289 * for an ancestor instead.
291 * Returns whether a reconstruct was posted for any ancestor.
293 bool DestroyFramesFor(nsIContent* aContent);
295 // Request to create a continuing frame. This method never returns null.
296 nsIFrame* CreateContinuingFrame(nsIFrame* aFrame,
297 nsContainerFrame* aParentFrame,
298 bool aIsFluid = true);
300 void SetNextPageContentFramePageName(const nsAtom* aAtom) {
301 MOZ_ASSERT(!mNextPageContentFramePageName,
302 "PageContentFrame page name was already set");
303 mNextPageContentFramePageName = aAtom;
306 // Copy over fixed frames from aParentFrame's prev-in-flow
307 nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
310 * Get the insertion point for aChild.
312 InsertionPoint GetInsertionPoint(nsIContent* aChild);
315 * Return the insertion frame of the primary frame of aContent, or its nearest
316 * ancestor that isn't display:contents.
318 nsContainerFrame* GetContentInsertionFrameFor(nsIContent* aContent);
320 // GetInitialContainingBlock() is deprecated in favor of
321 // GetRootElementFrame(); nsIFrame* GetInitialContainingBlock() { return
322 // mRootElementFrame; } This returns the outermost frame for the root element
323 nsContainerFrame* GetRootElementFrame() { return mRootElementFrame; }
324 // This returns the frame for the root element that does not
325 // have a psuedo-element style
326 nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
327 nsPageSequenceFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
328 // Returns the outermost canvas frame. There's usually one per document, but
329 // if but if we're in printing / paginated mode we might have multiple: one
330 // per page plus the background one.
331 nsCanvasFrame* GetCanvasFrame() { return mCanvasFrame; }
332 // Get the frame that is the parent of the root element's frame.
333 nsCanvasFrame* GetDocElementContainingBlock() {
334 return mDocElementContainingBlock;
337 void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
339 #if defined(ACCESSIBILITY) || defined(MOZ_LAYOUT_DEBUGGER)
340 // Exposed only for nsLayoutUtils::GetMarkerSpokenText and
341 // nsLayoutDebuggingTools to use.
342 mozilla::ContainStyleScopeManager& GetContainStyleScopeManager() {
343 return mContainStyleScopeManager;
345 #endif
347 private:
348 struct FrameConstructionItem;
349 class FrameConstructionItemList;
351 mozilla::PrintedSheetFrame* ConstructPrintedSheetFrame(
352 PresShell* aPresShell, nsContainerFrame* aParentFrame,
353 nsIFrame* aPrevSheetFrame);
355 nsContainerFrame* ConstructPageFrame(PresShell* aPresShell,
356 nsContainerFrame* aParentFrame,
357 nsIFrame* aPrevPageFrame,
358 nsCanvasFrame*& aCanvasFrame);
360 void InitAndRestoreFrame(const nsFrameConstructorState& aState,
361 nsIContent* aContent, nsContainerFrame* aParentFrame,
362 nsIFrame* aNewFrame, bool aAllowCounters = true);
364 already_AddRefed<ComputedStyle> ResolveComputedStyle(nsIContent* aContent);
366 enum class ItemFlag : uint8_t {
367 // Allow page-break before and after items to be created if the
368 // style asks for them.
369 AllowPageBreak,
370 IsGeneratedContent,
371 IsWithinSVGText,
372 // The item allows items to be created for SVG <textPath> children.
373 AllowTextPathChild,
374 // The item is content created by an nsIAnonymousContentCreator frame.
375 IsAnonymousContentCreatorContent,
376 // The item will be the rendered legend of a <fieldset>.
377 IsForRenderedLegend,
378 // This will be an outside ::marker.
379 IsForOutsideMarker,
382 using ItemFlags = mozilla::EnumSet<ItemFlag>;
384 // Add the frame construction items for the given aContent and aParentFrame
385 // to the list. This might add more than one item in some rare cases.
386 // If aSuppressWhiteSpaceOptimizations is true, optimizations that
387 // may suppress the construction of white-space-only text frames
388 // must be skipped for these items and items around them.
389 void AddFrameConstructionItems(nsFrameConstructorState& aState,
390 nsIContent* aContent,
391 bool aSuppressWhiteSpaceOptimizations,
392 const ComputedStyle& aParentStyle,
393 const InsertionPoint& aInsertion,
394 FrameConstructionItemList& aItems,
395 ItemFlags = {});
397 // Helper method for AddFrameConstructionItems etc.
398 // Unsets the need-frame/restyle bits on aContent.
399 // return true iff we should attempt to create frames for aContent.
400 bool ShouldCreateItemsForChild(nsFrameConstructorState& aState,
401 nsIContent* aContent,
402 nsContainerFrame* aParentFrame);
404 // Construct the frames for the document element. This can return null if the
405 // document element is display:none, or if it's an SVG element that's not
406 // <svg>, etc.
407 nsIFrame* ConstructDocElementFrame(Element* aDocElement);
409 // Set up our mDocElementContainingBlock correctly for the given root
410 // content.
411 void SetUpDocElementContainingBlock(nsIContent* aDocElement);
414 * CreateAttributeContent creates a single content/frame combination for an
415 * |attr(foo)| generated content.
417 * @param aParentContent the parent content for the generated content (that
418 * is, the originating element).
419 * @param aParentFrame the parent frame for the generated frame
420 * @param aAttrNamespace the namespace of the attribute in question
421 * @param aAttrName the localname of the attribute
422 * @param aComputedStyle the style to use
423 * @param aGeneratedContent the array of generated content to append the
424 * created content to.
425 * @param [out] aNewContent the content node we create
426 * @param [out] aNewFrame the new frame we create
428 void CreateAttributeContent(const Element& aParentContent,
429 nsIFrame* aParentFrame, int32_t aAttrNamespace,
430 nsAtom* aAttrName, ComputedStyle* aComputedStyle,
431 nsCOMArray<nsIContent>& aGeneratedContent,
432 nsIContent** aNewContent, nsIFrame** aNewFrame);
435 * Create a text node containing the given string. If aText is non-null
436 * then we also set aText to the returned node.
438 already_AddRefed<nsIContent> CreateGenConTextNode(
439 nsFrameConstructorState& aState, const nsAString& aString,
440 mozilla::UniquePtr<nsGenConInitializer> aInitializer);
443 * Create a content node for the given generated content style.
444 * The caller takes care of making it SetIsNativeAnonymousRoot, binding it
445 * to the document, and creating frames for it.
446 * @param aOriginatingElement is the node that has the before/after style.
447 * @param aComputedStyle is the 'before' or 'after' pseudo-element style.
448 * @param aContentIndex is the index of the content item to create.
449 * @param aAddChild callback to be called for each generated content child.
451 void CreateGeneratedContent(
452 nsFrameConstructorState& aState, Element& aOriginatingElement,
453 ComputedStyle& aPseudoStyle, uint32_t aContentIndex,
454 const mozilla::FunctionRef<void(nsIContent*)> aAddChild);
457 * Create child content nodes for a ::marker from its 'list-style-*' values.
459 void CreateGeneratedContentFromListStyle(
460 nsFrameConstructorState& aState, Element& aOriginatingElement,
461 const ComputedStyle& aPseudoStyle,
462 const mozilla::FunctionRef<void(nsIContent*)> aAddChild);
464 * Create child content nodes for a ::marker from its 'list-style-type'.
466 void CreateGeneratedContentFromListStyleType(
467 nsFrameConstructorState& aState, Element& aOriginatingElement,
468 const ComputedStyle& aPseudoStyle,
469 const mozilla::FunctionRef<void(nsIContent*)> aAddChild);
471 // aParentFrame may be null; this method doesn't use it directly in any case.
472 void CreateGeneratedContentItem(nsFrameConstructorState& aState,
473 nsContainerFrame* aParentFrame,
474 Element& aOriginatingElement, ComputedStyle&,
475 PseudoStyleType aPseudoElement,
476 FrameConstructionItemList& aItems,
477 ItemFlags aExtraFlags = {});
479 // This method is called by ContentAppended() and ContentRangeInserted() when
480 // appending flowed frames to a parent's principal child list. It handles the
481 // case where the parent is the trailing inline of an ib-split or is the last
482 // continuation of a ::-moz-column-content in an nsColumnSetFrame.
484 // This method can change aFrameList: it can chop off the beginning and put it
485 // in aParentFrame while either putting the remainder into an ib-split sibling
486 // of aParentFrame or creating aParentFrame's column-span siblings for the
487 // remainder.
489 // aPrevSibling must be the frame after which aFrameList is to be placed on
490 // aParentFrame's principal child list. It may be null if aFrameList is being
491 // added at the beginning of the child list.
492 void AppendFramesToParent(nsFrameConstructorState& aState,
493 nsContainerFrame* aParentFrame,
494 nsFrameList& aFrameList, nsIFrame* aPrevSibling,
495 bool aIsRecursiveCall = false);
497 // BEGIN TABLE SECTION
499 * Construct a table wrapper frame. This is the FrameConstructionData
500 * callback used for the job.
502 nsIFrame* ConstructTable(nsFrameConstructorState& aState,
503 FrameConstructionItem& aItem,
504 nsContainerFrame* aParentFrame,
505 const nsStyleDisplay* aDisplay,
506 nsFrameList& aFrameList);
509 * FrameConstructionData callback for constructing table rows and row groups.
511 nsIFrame* ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
512 FrameConstructionItem& aItem,
513 nsContainerFrame* aParentFrame,
514 const nsStyleDisplay* aStyleDisplay,
515 nsFrameList& aFrameList);
518 * FrameConstructionData callback used for constructing table columns.
520 nsIFrame* ConstructTableCol(nsFrameConstructorState& aState,
521 FrameConstructionItem& aItem,
522 nsContainerFrame* aParentFrame,
523 const nsStyleDisplay* aStyleDisplay,
524 nsFrameList& aFrameList);
527 * FrameConstructionData callback used for constructing table cells.
529 nsIFrame* ConstructTableCell(nsFrameConstructorState& aState,
530 FrameConstructionItem& aItem,
531 nsContainerFrame* aParentFrame,
532 const nsStyleDisplay* aStyleDisplay,
533 nsFrameList& aFrameList);
535 private:
536 /* An enum of possible parent types for anonymous table or ruby object
537 construction */
538 enum ParentType {
539 eTypeBlock = 0, /* This includes all non-table-related frames */
540 eTypeRow,
541 eTypeRowGroup,
542 eTypeColGroup,
543 eTypeTable,
544 eTypeRuby,
545 eTypeRubyBase,
546 eTypeRubyBaseContainer,
547 eTypeRubyText,
548 eTypeRubyTextContainer,
549 eParentTypeCount
552 /* 4 bits is enough to handle our ParentType values */
553 #define FCDATA_PARENT_TYPE_OFFSET 28
554 /* Macro to get the desired parent type out of an mBits member of
555 FrameConstructionData */
556 #define FCDATA_DESIRED_PARENT_TYPE(_bits) \
557 ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET)
558 /* Macro to create FrameConstructionData bits out of a desired parent type */
559 #define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type) \
560 (((uint32_t)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
562 /* Get the parent type that aParentFrame has. */
563 static ParentType GetParentType(nsIFrame* aParentFrame) {
564 return GetParentType(aParentFrame->Type());
567 /* Get the parent type for the given LayoutFrameType */
568 static ParentType GetParentType(mozilla::LayoutFrameType aFrameType);
570 static bool IsRubyParentType(ParentType aParentType) {
571 return (aParentType == eTypeRuby || aParentType == eTypeRubyBase ||
572 aParentType == eTypeRubyBaseContainer ||
573 aParentType == eTypeRubyText ||
574 aParentType == eTypeRubyTextContainer);
577 static bool IsTableParentType(ParentType aParentType) {
578 return (aParentType == eTypeTable || aParentType == eTypeRow ||
579 aParentType == eTypeRowGroup || aParentType == eTypeColGroup);
582 /* A constructor function that just creates an nsIFrame object. The caller
583 is responsible for initializing the object, adding it to frame lists,
584 constructing frames for the children, etc.
586 @param PresShell the presshell whose arena should be used to allocate
587 the frame.
588 @param ComputedStyle the style to use for the frame. */
589 using FrameCreationFunc = nsIFrame* (*)(PresShell*, ComputedStyle*);
590 using ContainerFrameCreationFunc = nsContainerFrame* (*)(PresShell*,
591 ComputedStyle*);
592 using BlockFrameCreationFunc = nsBlockFrame* (*)(PresShell*, ComputedStyle*);
594 /* A function that can be used to get a FrameConstructionData. Such
595 a function is allowed to return null.
597 @param nsIContent the node for which the frame is being constructed.
598 @param ComputedStyle the style to be used for the frame.
600 struct FrameConstructionData;
601 using FrameConstructionDataGetter =
602 const FrameConstructionData* (*)(const Element&, ComputedStyle&);
604 /* A constructor function that's used for complicated construction tasks.
605 This is expected to create the new frame, initialize it, add whatever
606 needs to be added to aFrameList (XXXbz is that really necessary? Could
607 caller add? Might there be cases when the returned frame or its
608 placeholder is not the thing that ends up in aFrameList? If not, would
609 it be safe to do the add into the frame construction state after
610 processing kids? Look into this as a followup!), process children as
611 needed, etc. It is NOT expected to deal with setting the frame on the
612 content.
614 @param aState the frame construction state to use.
615 @param aItem the frame construction item to use
616 @param aParentFrame the frame to set as the parent of the
617 newly-constructed frame.
618 @param aStyleDisplay the display struct from aItem's mComputedStyle
619 @param aFrameList the frame list to add the new frame (or its
620 placeholder) to.
621 @return the frame that was constructed. This frame is what the caller
622 will set as the frame on the content. Guaranteed non-null.
624 using FrameFullConstructor =
625 nsIFrame* (nsCSSFrameConstructor::*)(nsFrameConstructorState& aState,
626 FrameConstructionItem& aItem,
627 nsContainerFrame* aParentFrame,
628 const nsStyleDisplay* aStyleDisplay,
629 nsFrameList& aFrameList);
631 /* Bits that modify the way a FrameConstructionData is handled */
633 /* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not
634 be set as the primary frame on the content node. This should only be used
635 in very rare cases when we create more than one frame for a given content
636 node. */
637 #define FCDATA_SKIP_FRAMESET 0x1
638 /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
639 FrameConstructionData is a getter function that can be used to get the
640 actual FrameConstructionData to use. */
641 #define FCDATA_FUNC_IS_DATA_GETTER 0x2
642 /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData
643 has an mFullConstructor. In this case, there is no relevant mData or
644 mFunc */
645 #define FCDATA_FUNC_IS_FULL_CTOR 0x4
646 /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to
647 float or be absolutely positioned. This can also be used with
648 FCDATA_FUNC_IS_FULL_CTOR to indicate what the full-constructor
649 function will do. */
650 #define FCDATA_DISALLOW_OUT_OF_FLOW 0x8
651 /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a
652 null absolute containing block before processing children for this
653 frame. If this is not set, the frame will be pushed as the
654 absolute containing block as needed, based on its style */
655 #define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10
656 /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame
657 will be wrapped in blocks. This is only usable for MathML at the
658 moment. */
659 #define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20
660 /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the
661 content. If this bit is set, nothing else in the struct needs to be
662 set. */
663 #define FCDATA_SUPPRESS_FRAME 0x40
664 /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
665 a scrollframe if its overflow type so requires. */
666 #define FCDATA_MAY_NEED_SCROLLFRAME 0x80
667 /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame. These need
668 some really weird special handling. */
669 #define FCDATA_IS_POPUP 0x100
670 /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
671 absolute containing block, no matter what its style says. */
672 #define FCDATA_SKIP_ABSPOS_PUSH 0x200
673 /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated
674 content when processing kids of this frame. This should not be used with
675 FCDATA_FUNC_IS_FULL_CTOR */
676 #define FCDATA_DISALLOW_GENERATED_CONTENT 0x400
677 /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of
678 table-related thing and we should not attempt to fetch a table-cell parent
679 for it if it's inside another table-related frame. */
680 #define FCDATA_IS_TABLE_PART 0x800
681 /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS
682 inline box. */
683 #define FCDATA_IS_INLINE 0x1000
684 /* If FCDATA_IS_LINE_PARTICIPANT is set, the frame is something that will
685 return true for IsLineParticipant() */
686 #define FCDATA_IS_LINE_PARTICIPANT 0x2000
687 /* If FCDATA_IS_LINE_BREAK is set, the frame is something that will
688 induce a line break boundary before and after itself. */
689 #define FCDATA_IS_LINE_BREAK 0x4000
690 /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing
691 children of a block (i.e. allow ::first-letter/line).
692 This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */
693 #define FCDATA_ALLOW_BLOCK_STYLES 0x8000
694 /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant
695 FrameConstructionItem instead of trying to process the content's children.
696 This can be used with or without FCDATA_FUNC_IS_FULL_CTOR.
697 The child items might still need table pseudo processing. */
698 #define FCDATA_USE_CHILD_ITEMS 0x10000
699 /* If FCDATA_FORCED_NON_SCROLLABLE_BLOCK is set, then this block
700 would have been scrollable but has been forced to be
701 non-scrollable due to being in a paginated context. */
702 #define FCDATA_FORCED_NON_SCROLLABLE_BLOCK 0x20000
703 /* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a
704 block formatting context wrapper around the kids of this frame
705 using the FrameConstructionData's mPseudoAtom for its anonymous
706 box type. */
707 #define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000
708 /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of
709 an SVG text frame. */
710 #define FCDATA_IS_SVG_TEXT 0x80000
712 * If FCDATA_ALLOW_GRID_FLEX_COLUMN is set, then we should create a
713 * grid/flex/column container instead of a block wrapper when the styles says
714 * so. This bit is meaningful only if FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS
715 * is also set.
717 #define FCDATA_ALLOW_GRID_FLEX_COLUMN 0x200000
719 * Whether the kids of this FrameConstructionData should be flagged as having
720 * a wrapper anon box parent. This should only be set if
721 * FCDATA_USE_CHILD_ITEMS is set.
723 #define FCDATA_IS_WRAPPER_ANON_BOX 0x400000
725 /* Structure representing information about how a frame should be
726 constructed. */
727 struct FrameConstructionData {
728 // We have exactly one of three types of functions, so use a union for
729 // better cache locality.
730 union Func {
731 FrameCreationFunc mCreationFunc;
732 FrameConstructionDataGetter mDataGetter;
733 FrameFullConstructor mFullConstructor;
735 explicit constexpr Func(FrameCreationFunc aFunc) : mCreationFunc(aFunc) {}
736 explicit constexpr Func(FrameConstructionDataGetter aDataGetter)
737 : mDataGetter(aDataGetter) {}
738 explicit constexpr Func(FrameFullConstructor aCtor)
739 : mFullConstructor(aCtor) {}
740 } mFunc;
741 // Flag bits that can modify the way the construction happens
742 const uint32_t mBits = 0;
743 // For cases when FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, the
744 // anonymous box type to use for that wrapper.
745 PseudoStyleType const mAnonBoxPseudo = PseudoStyleType::NotPseudo;
747 constexpr FrameConstructionData() : FrameConstructionData(nullptr) {}
749 MOZ_IMPLICIT constexpr FrameConstructionData(std::nullptr_t,
750 uint32_t aBits = 0)
751 : mFunc(static_cast<FrameCreationFunc>(nullptr)), mBits(aBits) {}
753 MOZ_IMPLICIT constexpr FrameConstructionData(
754 FrameCreationFunc aCreationFunc, uint32_t aBits = 0)
755 : mFunc(aCreationFunc), mBits(aBits) {}
756 constexpr FrameConstructionData(FrameCreationFunc aCreationFunc,
757 uint32_t aBits,
758 PseudoStyleType aAnonBoxPseudo)
759 : mFunc(aCreationFunc),
760 mBits(aBits | FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS),
761 mAnonBoxPseudo(aAnonBoxPseudo) {}
762 MOZ_IMPLICIT constexpr FrameConstructionData(
763 FrameConstructionDataGetter aDataGetter, uint32_t aBits = 0)
764 : mFunc(aDataGetter),
765 mBits(aBits | FCDATA_FUNC_IS_DATA_GETTER),
766 mAnonBoxPseudo(PseudoStyleType::NotPseudo) {}
767 MOZ_IMPLICIT constexpr FrameConstructionData(FrameFullConstructor aCtor,
768 uint32_t aBits = 0)
769 : mFunc(aCtor),
770 mBits(aBits | FCDATA_FUNC_IS_FULL_CTOR),
771 mAnonBoxPseudo(PseudoStyleType::NotPseudo) {}
774 /* Structure representing a mapping of an atom to a FrameConstructionData.
775 This can be used with non-static atoms, assuming that the nsAtom* is
776 stored somewhere that this struct can point to (that is, a static
777 nsAtom*) and that it's allocated before the struct is ever used. */
778 struct FrameConstructionDataByTag {
779 const nsStaticAtom* const mTag;
780 const FrameConstructionData mData;
783 /* Structure representing a mapping of an integer to a
784 FrameConstructionData. There are no magic integer values here. */
785 struct FrameConstructionDataByInt {
786 /* Could be used for display or whatever else */
787 const int32_t mInt;
788 const FrameConstructionData mData;
791 struct FrameConstructionDataByDisplay {
792 #ifdef DEBUG
793 const mozilla::StyleDisplay mDisplay;
794 #endif
795 const FrameConstructionData mData;
798 /* Structure that has a FrameConstructionData and style pseudo-type
799 for a table pseudo-frame */
800 struct PseudoParentData {
801 const FrameConstructionData mFCData;
802 mozilla::PseudoStyleType const mPseudoType;
804 /* Array of such structures that we use to properly construct table
805 pseudo-frames as needed */
806 static const PseudoParentData sPseudoParentData[eParentTypeCount];
808 const FrameConstructionData* FindDataForContent(nsIContent&, ComputedStyle&,
809 nsIFrame* aParentFrame,
810 ItemFlags aFlags);
812 // aParentFrame might be null. If it is, that means it was an inline frame.
813 static const FrameConstructionData* FindTextData(const Text&,
814 nsIFrame* aParentFrame);
815 const FrameConstructionData* FindElementData(const Element&, ComputedStyle&,
816 nsIFrame* aParentFrame,
817 ItemFlags aFlags);
818 const FrameConstructionData* FindElementTagData(const Element&,
819 ComputedStyle&,
820 nsIFrame* aParentFrame,
821 ItemFlags aFlags);
823 /* A function that takes an integer, content, style, and array of
824 FrameConstructionDataByInts and finds the appropriate frame construction
825 data to use and returns it. This can return null if none of the integers
826 match or if the matching integer has a FrameConstructionDataGetter that
827 returns null. */
828 static const FrameConstructionData* FindDataByInt(
829 int32_t aInt, const Element&, ComputedStyle&,
830 const FrameConstructionDataByInt* aDataPtr, uint32_t aDataLength);
833 * A function that takes a tag, content, style, and array of
834 * FrameConstructionDataByTags and finds the appropriate frame construction
835 * data to use and returns it.
837 * This can return null if none of the tags match or if the matching tag has a
838 * FrameConstructionDataGetter that returns null. In the case that the tags
839 * actually match, aTagFound will be true, even if the return value is null.
841 static const FrameConstructionData* FindDataByTag(
842 const Element& aElement, ComputedStyle& aComputedStyle,
843 const FrameConstructionDataByTag* aDataPtr, uint32_t aDataLength);
845 /* A class representing a list of FrameConstructionItems. Instances of this
846 class are only created as AutoFrameConstructionItemList, or as a member
847 of FrameConstructionItem. */
848 class FrameConstructionItemList {
849 public:
850 void Reset(nsCSSFrameConstructor* aFCtor) {
851 Destroy(aFCtor);
852 this->~FrameConstructionItemList();
853 new (this) FrameConstructionItemList();
856 void SetLineBoundaryAtStart(bool aBoundary) {
857 mLineBoundaryAtStart = aBoundary;
859 void SetLineBoundaryAtEnd(bool aBoundary) {
860 mLineBoundaryAtEnd = aBoundary;
862 void SetParentHasNoShadowDOM(bool aValue) {
863 mParentHasNoShadowDOM = aValue;
865 bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; }
866 bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; }
867 bool ParentHasNoShadowDOM() { return mParentHasNoShadowDOM; }
868 bool IsEmpty() const { return mItems.isEmpty(); }
869 bool AreAllItemsInline() const { return mInlineCount == mItemCount; }
870 bool AreAllItemsBlock() const { return mBlockCount == mItemCount; }
871 bool AllWantParentType(ParentType aDesiredParentType) const {
872 return mDesiredParentCounts[aDesiredParentType] == mItemCount;
875 // aSuppressWhiteSpaceOptimizations is true if optimizations that
876 // skip constructing whitespace frames for this item or items
877 // around it cannot be performed.
878 // Also, the return value is always non-null, thanks to infallible 'new'.
879 FrameConstructionItem* AppendItem(
880 nsCSSFrameConstructor* aFCtor, const FrameConstructionData* aFCData,
881 nsIContent* aContent, already_AddRefed<ComputedStyle>&& aComputedStyle,
882 bool aSuppressWhiteSpaceOptimizations) {
883 FrameConstructionItem* item = new (aFCtor)
884 FrameConstructionItem(aFCData, aContent, std::move(aComputedStyle),
885 aSuppressWhiteSpaceOptimizations);
886 mItems.insertBack(item);
887 ++mItemCount;
888 ++mDesiredParentCounts[item->DesiredParentType()];
889 return item;
892 // Arguments are the same as AppendItem().
893 FrameConstructionItem* PrependItem(
894 nsCSSFrameConstructor* aFCtor, const FrameConstructionData* aFCData,
895 nsIContent* aContent, already_AddRefed<ComputedStyle>&& aComputedStyle,
896 bool aSuppressWhiteSpaceOptimizations) {
897 FrameConstructionItem* item = new (aFCtor)
898 FrameConstructionItem(aFCData, aContent, std::move(aComputedStyle),
899 aSuppressWhiteSpaceOptimizations);
900 mItems.insertFront(item);
901 ++mItemCount;
902 ++mDesiredParentCounts[item->DesiredParentType()];
903 return item;
906 void InlineItemAdded() { ++mInlineCount; }
907 void BlockItemAdded() { ++mBlockCount; }
909 class Iterator {
910 public:
911 explicit Iterator(FrameConstructionItemList& aList)
912 : mCurrent(aList.mItems.getFirst()), mList(aList) {}
913 Iterator(const Iterator& aOther) = default;
915 bool operator==(const Iterator& aOther) const {
916 MOZ_ASSERT(&mList == &aOther.mList, "Iterators for different lists?");
917 return mCurrent == aOther.mCurrent;
919 bool operator!=(const Iterator& aOther) const {
920 return !(*this == aOther);
922 Iterator& operator=(const Iterator& aOther) {
923 MOZ_ASSERT(&mList == &aOther.mList, "Iterators for different lists?");
924 mCurrent = aOther.mCurrent;
925 return *this;
928 FrameConstructionItemList* List() { return &mList; }
930 FrameConstructionItem& item() {
931 MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
932 return *mCurrent;
935 const FrameConstructionItem& item() const {
936 MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
937 return *mCurrent;
940 bool IsDone() const { return mCurrent == nullptr; }
941 bool AtStart() const { return mCurrent == mList.mItems.getFirst(); }
942 void Next() {
943 NS_ASSERTION(!IsDone(), "Should have checked IsDone()!");
944 mCurrent = mCurrent->getNext();
946 void Prev() {
947 NS_ASSERTION(!AtStart(), "Should have checked AtStart()!");
948 mCurrent = mCurrent ? mCurrent->getPrevious() : mList.mItems.getLast();
950 void SetToEnd() { mCurrent = nullptr; }
952 // Skip over all items that want the given parent type. Return whether
953 // the iterator is done after doing that. The iterator must not be done
954 // when this is called.
955 inline bool SkipItemsWantingParentType(ParentType aParentType);
957 // Skip over all items that want a parent type different from the given
958 // one. Return whether the iterator is done after doing that. The
959 // iterator must not be done when this is called.
960 inline bool SkipItemsNotWantingParentType(ParentType aParentType);
962 // Skip over non-replaced inline frames and positioned frames.
963 // Return whether the iterator is done after doing that.
964 // The iterator must not be done when this is called.
965 inline bool SkipItemsThatNeedAnonFlexOrGridItem(
966 const nsFrameConstructorState& aState, bool aIsWebkitBox);
968 // Skip to the first frame that is a non-replaced inline or is
969 // positioned. Return whether the iterator is done after doing that.
970 // The iterator must not be done when this is called.
971 inline bool SkipItemsThatDontNeedAnonFlexOrGridItem(
972 const nsFrameConstructorState& aState, bool aIsWebkitBox);
974 // Skip over all items that do not want a ruby parent. Return whether
975 // the iterator is done after doing that. The iterator must not be done
976 // when this is called.
977 inline bool SkipItemsNotWantingRubyParent();
979 // Skip over whitespace. Return whether the iterator is done after doing
980 // that. The iterator must not be done, and must be pointing to a
981 // whitespace item when this is called.
982 inline bool SkipWhitespace(nsFrameConstructorState& aState);
984 // Remove the item pointed to by this iterator from its current list and
985 // Append it to aTargetList. This iterator is advanced to point to the
986 // next item in its list. aIter must not be done. aTargetList must not
987 // be the list this iterator is iterating over..
988 void AppendItemToList(FrameConstructionItemList& aTargetList);
990 // As above, but moves all items starting with this iterator until we
991 // get to aEnd; the item pointed to by aEnd is not stolen. This method
992 // might have optimizations over just looping and doing StealItem for
993 // some special cases. After this method returns, this iterator will
994 // point to the item aEnd points to now; aEnd is not modified.
995 // aTargetList must not be the list this iterator is iterating over.
996 void AppendItemsToList(nsCSSFrameConstructor* aFCtor,
997 const Iterator& aEnd,
998 FrameConstructionItemList& aTargetList);
1000 // Insert aItem in this iterator's list right before the item pointed to
1001 // by this iterator. After the insertion, this iterator will continue to
1002 // point to the item it now points to (the one just after the
1003 // newly-inserted item). This iterator is allowed to be done; in that
1004 // case this call just appends the given item to the list.
1005 void InsertItem(FrameConstructionItem* aItem);
1007 // Delete the items between this iterator and aEnd, including the item
1008 // this iterator currently points to but not including the item pointed
1009 // to by aEnd. When this returns, this iterator will point to the same
1010 // item as aEnd. This iterator must not equal aEnd when this method is
1011 // called.
1012 void DeleteItemsTo(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd);
1014 private:
1015 FrameConstructionItem* mCurrent;
1016 FrameConstructionItemList& mList;
1019 protected:
1020 FrameConstructionItemList()
1021 : mInlineCount(0),
1022 mBlockCount(0),
1023 mItemCount(0),
1024 mLineBoundaryAtStart(false),
1025 mLineBoundaryAtEnd(false),
1026 mParentHasNoShadowDOM(false) {
1027 MOZ_COUNT_CTOR(FrameConstructionItemList);
1028 memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
1031 void Destroy(nsCSSFrameConstructor* aFCtor) {
1032 while (FrameConstructionItem* item = mItems.popFirst()) {
1033 item->Delete(aFCtor);
1037 // Prevent stack instances (except as AutoFrameConstructionItemList).
1038 friend struct FrameConstructionItem;
1039 ~FrameConstructionItemList() {
1040 MOZ_COUNT_DTOR(FrameConstructionItemList);
1041 MOZ_ASSERT(mItems.isEmpty(), "leaking");
1044 private:
1045 // Not allocated from the heap!
1046 void* operator new(size_t) = delete;
1047 void* operator new[](size_t) = delete;
1048 #ifdef _MSC_VER /* Visual Studio */
1049 void operator delete(void*) { MOZ_CRASH("FrameConstructionItemList::del"); }
1050 #else
1051 void operator delete(void*) = delete;
1052 #endif
1053 void operator delete[](void*) = delete;
1054 // Placement new is used by Reset().
1055 void* operator new(size_t, void* aPtr) { return aPtr; }
1057 struct UndisplayedItem {
1058 UndisplayedItem(nsIContent* aContent, ComputedStyle* aComputedStyle)
1059 : mContent(aContent), mComputedStyle(aComputedStyle) {}
1061 nsIContent* const mContent;
1062 RefPtr<ComputedStyle> mComputedStyle;
1065 // Adjust our various counts for aItem being added or removed. aDelta
1066 // should be either +1 or -1 depending on which is happening.
1067 void AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta);
1069 mozilla::LinkedList<FrameConstructionItem> mItems;
1070 uint32_t mInlineCount;
1071 uint32_t mBlockCount;
1072 uint32_t mItemCount;
1073 uint32_t mDesiredParentCounts[eParentTypeCount];
1074 // True if there is guaranteed to be a line boundary before the
1075 // frames created by these items
1076 bool mLineBoundaryAtStart;
1077 // True if there is guaranteed to be a line boundary after the
1078 // frames created by these items
1079 bool mLineBoundaryAtEnd;
1080 // True if the parent is guaranteed to have no shadow tree.
1081 bool mParentHasNoShadowDOM;
1084 /* A struct representing a list of FrameConstructionItems on the stack. */
1085 struct MOZ_RAII AutoFrameConstructionItemList final
1086 : public FrameConstructionItemList {
1087 template <typename... Args>
1088 explicit AutoFrameConstructionItemList(nsCSSFrameConstructor* aFCtor,
1089 Args&&... args)
1090 : FrameConstructionItemList(std::forward<Args>(args)...),
1091 mFCtor(aFCtor) {
1092 MOZ_ASSERT(mFCtor);
1094 ~AutoFrameConstructionItemList() { Destroy(mFCtor); }
1096 private:
1097 nsCSSFrameConstructor* const mFCtor;
1100 typedef FrameConstructionItemList::Iterator FCItemIterator;
1102 /* A struct representing an item for which frames might need to be
1103 * constructed. This contains all the information needed to construct the
1104 * frame other than the parent frame and whatever would be stored in the
1105 * frame constructor state. You probably want to use
1106 * AutoFrameConstructionItem instead of this struct. */
1107 struct FrameConstructionItem final
1108 : public mozilla::LinkedListElement<FrameConstructionItem> {
1109 FrameConstructionItem(const FrameConstructionData* aFCData,
1110 nsIContent* aContent,
1111 already_AddRefed<ComputedStyle>&& aComputedStyle,
1112 bool aSuppressWhiteSpaceOptimizations)
1113 : mFCData(aFCData),
1114 mContent(aContent),
1115 mComputedStyle(std::move(aComputedStyle)),
1116 mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
1117 mIsText(false),
1118 mIsGeneratedContent(false),
1119 mIsAllInline(false),
1120 mIsBlock(false),
1121 mIsPopup(false),
1122 mIsLineParticipant(false),
1123 mIsRenderedLegend(false) {
1124 MOZ_COUNT_CTOR(FrameConstructionItem);
1127 void* operator new(size_t, nsCSSFrameConstructor* aFCtor) {
1128 return aFCtor->AllocateFCItem();
1131 void Delete(nsCSSFrameConstructor* aFCtor) {
1132 mChildItems.Destroy(aFCtor);
1133 if (mIsGeneratedContent) {
1134 mContent->UnbindFromTree();
1135 NS_RELEASE(mContent);
1137 this->~FrameConstructionItem();
1138 aFCtor->FreeFCItem(this);
1141 ParentType DesiredParentType() {
1142 return FCDATA_DESIRED_PARENT_TYPE(mFCData->mBits);
1145 // Indicates whether (when in a flex or grid container) this item needs
1146 // to be wrapped in an anonymous block. (Note that we implement
1147 // -webkit-box/-webkit-inline-box using our standard flexbox frame class,
1148 // but we use different rules for what gets wrapped. The aIsWebkitBox
1149 // parameter here tells us whether to use those different rules.)
1150 bool NeedsAnonFlexOrGridItem(const nsFrameConstructorState& aState,
1151 bool aIsWebkitBox);
1153 // Don't call this unless the frametree really depends on the answer!
1154 // Especially so for generated content, where we don't want to reframe
1155 // things.
1156 bool IsWhitespace(nsFrameConstructorState& aState) const;
1158 bool IsLineBoundary() const {
1159 return mIsBlock || (mFCData->mBits & FCDATA_IS_LINE_BREAK);
1162 // Child frame construction items.
1163 FrameConstructionItemList mChildItems;
1165 // The FrameConstructionData to use.
1166 const FrameConstructionData* mFCData;
1167 // The nsIContent node to use when initializing the new frame.
1168 nsIContent* mContent;
1169 // The style to use for creating the new frame.
1170 RefPtr<ComputedStyle> mComputedStyle;
1171 // Whether optimizations to skip constructing textframes around
1172 // this content need to be suppressed.
1173 bool mSuppressWhiteSpaceOptimizations : 1;
1174 // Whether this is a text content item.
1175 bool mIsText : 1;
1176 // Whether this is a generated content container.
1177 // If it is, mContent is a strong pointer.
1178 bool mIsGeneratedContent : 1;
1179 // Whether construction from this item will create only frames that are
1180 // IsInlineOutside() in the principal child list. This is not precise, but
1181 // conservative: if true the frames will really be inline, whereas if false
1182 // they might still all be inline.
1183 bool mIsAllInline : 1;
1184 // Whether construction from this item will create only frames that are
1185 // IsBlockOutside() in the principal child list. This is not precise, but
1186 // conservative: if true the frames will really be blocks, whereas if false
1187 // they might still be blocks (and in particular, out-of-flows that didn't
1188 // find a containing block).
1189 bool mIsBlock : 1;
1190 // Whether construction from this item will create a popup that needs to
1191 // go into the global popup items.
1192 bool mIsPopup : 1;
1193 // Whether this item should be treated as a line participant
1194 bool mIsLineParticipant : 1;
1195 // Whether this item is the rendered legend of a <fieldset>
1196 bool mIsRenderedLegend : 1;
1198 private:
1199 // Not allocated from the general heap - instead, use the new/Delete APIs
1200 // that take a nsCSSFrameConstructor* (which manages our arena allocation).
1201 void* operator new(size_t) = delete;
1202 void* operator new[](size_t) = delete;
1203 #ifdef _MSC_VER /* Visual Studio */
1204 void operator delete(void*) { MOZ_CRASH("FrameConstructionItem::delete"); }
1205 #else
1206 void operator delete(void*) = delete;
1207 #endif
1208 void operator delete[](void*) = delete;
1209 FrameConstructionItem(const FrameConstructionItem& aOther) = delete;
1210 // Not allocated from the stack!
1211 ~FrameConstructionItem() {
1212 MOZ_COUNT_DTOR(FrameConstructionItem);
1213 MOZ_ASSERT(mChildItems.IsEmpty(), "leaking");
1218 * Convenience struct to assist in managing a temporary FrameConstructionItem
1219 * using a local variable. Castable to FrameConstructionItem so that it can
1220 * be passed transparently to functions that expect that type.
1221 * (This struct exists because FrameConstructionItem is arena-allocated, and
1222 * it's nice to abstract away its allocation/deallocation.)
1224 struct MOZ_RAII AutoFrameConstructionItem final {
1225 template <typename... Args>
1226 explicit AutoFrameConstructionItem(nsCSSFrameConstructor* aFCtor,
1227 Args&&... args)
1228 : mFCtor(aFCtor),
1229 mItem(new(aFCtor)
1230 FrameConstructionItem(std::forward<Args>(args)...)) {
1231 MOZ_ASSERT(mFCtor);
1233 ~AutoFrameConstructionItem() { mItem->Delete(mFCtor); }
1234 operator FrameConstructionItem&() { return *mItem; }
1236 private:
1237 nsCSSFrameConstructor* const mFCtor;
1238 FrameConstructionItem* const mItem;
1242 * Updates the nsFrameConstructorState auto page-name value, and restores the
1243 * previous value on destruction.
1244 * See https://drafts.csswg.org/css-page-3/#using-named-pages
1246 * To track this, this will automatically add PageValuesProperty to
1247 * the frame.
1249 * Note that this does not add PageValuesProperty to the frame when not in a
1250 * paginated context.
1252 class MOZ_RAII AutoFrameConstructionPageName final {
1253 nsFrameConstructorState& mState;
1254 const nsAtom* mNameToRestore;
1256 public:
1257 AutoFrameConstructionPageName(const AutoFrameConstructionPageName&) =
1258 delete;
1259 AutoFrameConstructionPageName(AutoFrameConstructionPageName&&) = delete;
1260 AutoFrameConstructionPageName(nsFrameConstructorState& aState,
1261 nsIFrame* const aFrame);
1262 ~AutoFrameConstructionPageName();
1266 * Function to create the anonymous flex or grid items that we need.
1267 * If aParentFrame is not a nsFlexContainerFrame or nsGridContainerFrame then
1268 * this method is a NOP.
1269 * @param aItems the child frame construction items before pseudo creation
1270 * @param aParentFrame the parent frame
1272 void CreateNeededAnonFlexOrGridItems(nsFrameConstructorState& aState,
1273 FrameConstructionItemList& aItems,
1274 nsIFrame* aParentFrame);
1276 enum RubyWhitespaceType {
1277 eRubyNotWhitespace,
1278 eRubyInterLevelWhitespace,
1279 // Includes inter-base and inter-annotation whitespace
1280 eRubyInterLeafWhitespace,
1281 eRubyInterSegmentWhitespace
1285 * Function to compute the whitespace type according to the display
1286 * values of the previous and the next elements.
1288 static inline RubyWhitespaceType ComputeRubyWhitespaceType(
1289 mozilla::StyleDisplay aPrevDisplay, mozilla::StyleDisplay aNextDisplay);
1292 * Function to interpret the type of whitespace between
1293 * |aStartIter| and |aEndIter|.
1295 static inline RubyWhitespaceType InterpretRubyWhitespace(
1296 nsFrameConstructorState& aState, const FCItemIterator& aStartIter,
1297 const FCItemIterator& aEndIter);
1300 * Function to wrap consecutive misparented inline content into
1301 * a ruby base box or a ruby text box.
1303 void WrapItemsInPseudoRubyLeafBox(FCItemIterator& aIter,
1304 ComputedStyle* aParentStyle,
1305 nsIContent* aParentContent);
1308 * Function to wrap consecutive misparented items
1309 * into a ruby level container.
1311 inline void WrapItemsInPseudoRubyLevelContainer(
1312 nsFrameConstructorState& aState, FCItemIterator& aIter,
1313 ComputedStyle* aParentStyle, nsIContent* aParentContent);
1316 * Function to trim leading and trailing whitespaces.
1318 inline void TrimLeadingAndTrailingWhitespaces(
1319 nsFrameConstructorState& aState, FrameConstructionItemList& aItems);
1322 * Function to create internal ruby boxes.
1324 inline void CreateNeededPseudoInternalRubyBoxes(
1325 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
1326 nsIFrame* aParentFrame);
1329 * Function to create the pseudo intermediate containers we need.
1330 * @param aItems the child frame construction items before pseudo creation
1331 * @param aParentFrame the parent frame we're creating pseudos for
1333 inline void CreateNeededPseudoContainers(nsFrameConstructorState& aState,
1334 FrameConstructionItemList& aItems,
1335 nsIFrame* aParentFrame);
1338 * Function to wrap consecutive items into a pseudo parent.
1340 inline void WrapItemsInPseudoParent(nsIContent* aParentContent,
1341 ComputedStyle* aParentStyle,
1342 ParentType aWrapperType,
1343 FCItemIterator& aIter,
1344 const FCItemIterator& aEndIter);
1347 * Function to create the pseudo siblings we need.
1349 inline void CreateNeededPseudoSiblings(nsFrameConstructorState& aState,
1350 FrameConstructionItemList& aItems,
1351 nsIFrame* aParentFrame);
1353 // END TABLE SECTION
1355 protected:
1356 static nsIFrame* CreatePlaceholderFrameFor(PresShell* aPresShell,
1357 nsIContent* aContent,
1358 nsIFrame* aFrame,
1359 nsContainerFrame* aParentFrame,
1360 nsIFrame* aPrevInFlow,
1361 nsFrameState aTypeBit);
1363 private:
1364 // ConstructSelectFrame puts the new frame in aFrameList and
1365 // handles the kids of the select.
1366 nsIFrame* ConstructSelectFrame(nsFrameConstructorState& aState,
1367 FrameConstructionItem& aItem,
1368 nsContainerFrame* aParentFrame,
1369 const nsStyleDisplay* aStyleDisplay,
1370 nsFrameList& aFrameList);
1372 // ConstructFieldSetFrame puts the new frame in aFrameList and
1373 // handles the kids of the fieldset
1374 nsIFrame* ConstructFieldSetFrame(nsFrameConstructorState& aState,
1375 FrameConstructionItem& aItem,
1376 nsContainerFrame* aParentFrame,
1377 const nsStyleDisplay* aStyleDisplay,
1378 nsFrameList& aFrameList);
1380 // Creates a block frame wrapping an anonymous ruby frame.
1381 nsIFrame* ConstructBlockRubyFrame(nsFrameConstructorState& aState,
1382 FrameConstructionItem& aItem,
1383 nsContainerFrame* aParentFrame,
1384 const nsStyleDisplay* aStyleDisplay,
1385 nsFrameList& aFrameList);
1387 void ConstructTextFrame(const FrameConstructionData* aData,
1388 nsFrameConstructorState& aState, nsIContent* aContent,
1389 nsContainerFrame* aParentFrame,
1390 ComputedStyle* aComputedStyle,
1391 nsFrameList& aFrameList);
1393 // If aPossibleTextContent is a text node and doesn't have a frame, append a
1394 // frame construction item for it to aItems.
1395 void AddTextItemIfNeeded(nsFrameConstructorState& aState,
1396 const ComputedStyle& aParentStyle,
1397 const InsertionPoint& aInsertion,
1398 nsIContent* aPossibleTextContent,
1399 FrameConstructionItemList& aItems);
1401 // If aContent is a text node and doesn't have a frame, try to create a frame
1402 // for it.
1403 void ReframeTextIfNeeded(nsIContent* aContent);
1405 enum InsertPageBreakLocation { eBefore, eAfter };
1406 inline void AppendPageBreakItem(nsIContent* aContent,
1407 FrameConstructionItemList& aItems) {
1408 InsertPageBreakItem(aContent, aItems, InsertPageBreakLocation::eAfter);
1410 inline void PrependPageBreakItem(nsIContent* aContent,
1411 FrameConstructionItemList& aItems) {
1412 InsertPageBreakItem(aContent, aItems, InsertPageBreakLocation::eBefore);
1414 void InsertPageBreakItem(nsIContent* aContent,
1415 FrameConstructionItemList& aItems,
1416 InsertPageBreakLocation location);
1418 // Function to find FrameConstructionData for aElement. Will return
1419 // null if aElement is not HTML.
1420 // aParentFrame might be null. If it is, that means it was an
1421 // inline frame.
1422 static const FrameConstructionData* FindHTMLData(const Element&,
1423 nsIFrame* aParentFrame,
1424 ComputedStyle&);
1425 // HTML data-finding helper functions
1426 static const FrameConstructionData* FindImgData(const Element&,
1427 ComputedStyle&);
1428 static const FrameConstructionData* FindGeneratedImageData(const Element&,
1429 ComputedStyle&);
1430 static const FrameConstructionData* FindImgControlData(const Element&,
1431 ComputedStyle&);
1432 static const FrameConstructionData* FindSearchControlData(const Element&,
1433 ComputedStyle&);
1434 static const FrameConstructionData* FindInputData(const Element&,
1435 ComputedStyle&);
1436 static const FrameConstructionData* FindObjectData(const Element&,
1437 ComputedStyle&);
1438 static const FrameConstructionData* FindCanvasData(const Element&,
1439 ComputedStyle&);
1440 // <details> always creates a block per spec.
1441 static const FrameConstructionData* FindDetailsData(const Element&,
1442 ComputedStyle&);
1444 /* Construct a frame from the given FrameConstructionItem. This function
1445 will handle adding the frame to frame lists, processing children, setting
1446 the frame as the primary frame for the item's content, and so forth.
1448 @param aItem the FrameConstructionItem to use.
1449 @param aState the frame construction state to use.
1450 @param aParentFrame the frame to set as the parent of the
1451 newly-constructed frame.
1452 @param aFrameList the frame list to add the new frame (or its
1453 placeholder) to.
1455 void ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
1456 nsFrameConstructorState& aState,
1457 nsContainerFrame* aParentFrame,
1458 nsFrameList& aFrameList);
1460 // The guts of AddFrameConstructionItems
1461 // aParentFrame might be null. If it is, that means it was an
1462 // inline frame.
1463 void AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
1464 nsIContent* aContent,
1465 nsContainerFrame* aParentFrame,
1466 bool aSuppressWhiteSpaceOptimizations,
1467 ComputedStyle*, ItemFlags,
1468 FrameConstructionItemList& aItems);
1471 * Construct frames for the given item list and parent frame, and put the
1472 * resulting frames in aFrameList.
1474 void ConstructFramesFromItemList(nsFrameConstructorState& aState,
1475 FrameConstructionItemList& aItems,
1476 nsContainerFrame* aParentFrame,
1477 bool aParentIsWrapperAnonBox,
1478 nsFrameList& aFrameList);
1479 void ConstructFramesFromItem(nsFrameConstructorState& aState,
1480 FCItemIterator& aItem,
1481 nsContainerFrame* aParentFrame,
1482 nsFrameList& aFrameList);
1483 static bool AtLineBoundary(FCItemIterator& aIter);
1485 nsresult GetAnonymousContent(
1486 nsIContent* aParent, nsIFrame* aParentFrame,
1487 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonContent);
1489 // MathML Mod - RBS
1491 * Takes the frames in aBlockList and wraps them in a new anonymous block
1492 * frame whose content is aContent and whose parent will be aParentFrame.
1493 * The anonymous block is added to aNewList and aBlockList is cleared.
1495 void FlushAccumulatedBlock(nsFrameConstructorState& aState,
1496 nsIContent* aContent,
1497 nsContainerFrame* aParentFrame,
1498 nsFrameList& aBlockList, nsFrameList& aNewList);
1500 // Function to find FrameConstructionData for an element. Will return
1501 // null if the element is not MathML.
1502 static const FrameConstructionData* FindMathMLData(const Element&,
1503 ComputedStyle&);
1505 // Function to find FrameConstructionData for an element. Will return
1506 // null if the element is not XUL.
1507 static const FrameConstructionData* FindXULTagData(const Element&,
1508 ComputedStyle&);
1509 // XUL data-finding helper functions and structures
1510 static const FrameConstructionData* FindPopupGroupData(const Element&,
1511 ComputedStyle&);
1512 static const FrameConstructionData* FindXULButtonData(const Element&,
1513 ComputedStyle&);
1514 static const FrameConstructionData* FindXULLabelOrDescriptionData(
1515 const Element&, ComputedStyle&);
1516 #ifdef XP_MACOSX
1517 static const FrameConstructionData* FindXULMenubarData(const Element&,
1518 ComputedStyle&);
1519 #endif /* XP_MACOSX */
1522 * Constructs an outer frame, an anonymous child that wraps its real
1523 * children, and its descendant frames. This is used by both
1524 * ConstructOuterSVG and ConstructMarker, which both want an anonymous block
1525 * child for their children to go in to.
1527 nsContainerFrame* ConstructFrameWithAnonymousChild(
1528 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
1529 nsContainerFrame* aParentFrame, nsFrameList& aFrameList,
1530 ContainerFrameCreationFunc aConstructor,
1531 ContainerFrameCreationFunc aInnerConstructor,
1532 mozilla::PseudoStyleType aInnerPseudo, bool aCandidateRootFrame);
1535 * Construct an SVGOuterSVGFrame.
1537 nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState,
1538 FrameConstructionItem& aItem,
1539 nsContainerFrame* aParentFrame,
1540 const nsStyleDisplay* aDisplay,
1541 nsFrameList& aFrameList);
1544 * Construct an SVGMarkerFrame.
1546 nsIFrame* ConstructMarker(nsFrameConstructorState& aState,
1547 FrameConstructionItem& aItem,
1548 nsContainerFrame* aParentFrame,
1549 const nsStyleDisplay* aDisplay,
1550 nsFrameList& aFrameList);
1552 static const FrameConstructionData* FindSVGData(const Element&,
1553 nsIFrame* aParentFrame,
1554 bool aIsWithinSVGText,
1555 bool aAllowsTextPathChild,
1556 ComputedStyle&);
1558 // Not static because it does PropagateScrollToViewport. If this
1559 // changes, make this static.
1560 const FrameConstructionData* FindDisplayData(const nsStyleDisplay&,
1561 const Element&);
1564 * Construct a scrollable block frame
1566 nsIFrame* ConstructScrollableBlock(nsFrameConstructorState& aState,
1567 FrameConstructionItem& aItem,
1568 nsContainerFrame* aParentFrame,
1569 const nsStyleDisplay* aDisplay,
1570 nsFrameList& aFrameList);
1573 * Construct a non-scrollable block frame
1575 nsIFrame* ConstructNonScrollableBlock(nsFrameConstructorState& aState,
1576 FrameConstructionItem& aItem,
1577 nsContainerFrame* aParentFrame,
1578 const nsStyleDisplay* aDisplay,
1579 nsFrameList& aFrameList);
1582 * This adds FrameConstructionItem objects to aItemsToConstruct for the
1583 * anonymous content returned by an nsIAnonymousContentCreator::
1584 * CreateAnonymousContent implementation.
1585 * This includes an AutoFrameConstructionPageName argument as it is always
1586 * the caller's responsibility to handle page-name tracking before calling
1587 * this function.
1589 void AddFCItemsForAnonymousContent(
1590 nsFrameConstructorState& aState, nsContainerFrame* aFrame,
1591 const nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
1592 FrameConstructionItemList& aItemsToConstruct,
1593 const AutoFrameConstructionPageName& aUnusedPageNameTracker);
1596 * Construct the frames for the children of aContent. "children" is defined
1597 * as "whatever FlattenedChildIterator returns for aContent". This means
1598 * we're basically operating on children in the "flattened tree":
1600 * https://drafts.csswg.org/css-scoping/#flat-tree
1602 * This method will also handle constructing ::before, ::after,
1603 * ::first-letter, and ::first-line frames, as needed and if allowed.
1605 * If the parent is a float containing block, this method will handle pushing
1606 * it as the float containing block in aState (so there's no need for callers
1607 * to push it themselves).
1609 * @param aState the frame construction state
1610 * @param aContent the content node whose children need frames
1611 * @param aComputedStyle the style for aContent
1612 * @param aParentFrame the frame to use as the parent frame for the new
1613 * in-flow kids. Note that this must be its own content insertion frame, but
1614 * need not be be the primary frame for aContent. This frame will be
1615 * pushed as the float containing block, as needed. aFrame is also
1616 * used to find the parent style for the kids' style
1617 * (not necessary aFrame's style).
1618 * @param aCanHaveGeneratedContent Whether to allow :before and
1619 * :after styles on the parent.
1620 * @param aFrameList the list in which we should place the in-flow children
1621 * @param aAllowBlockStyles Whether to allow first-letter and first-line
1622 * styles on the parent.
1623 * @param aPossiblyLeafFrame if non-null, this should be used for the isLeaf
1624 * test and the anonymous content creation. If null, aFrame will be
1625 * used.
1627 void ProcessChildren(nsFrameConstructorState& aState, nsIContent* aContent,
1628 ComputedStyle* aComputedStyle,
1629 nsContainerFrame* aParentFrame,
1630 const bool aCanHaveGeneratedContent,
1631 nsFrameList& aFrameList, const bool aAllowBlockStyles,
1632 nsIFrame* aPossiblyLeafFrame = nullptr);
1635 * These two functions are used when we start frame creation from a non-root
1636 * element. They should recreate the same state that we would have
1637 * arrived at if we had built frames from the root frame to aFrame.
1638 * Therefore, any calls to PushFloatContainingBlock and
1639 * PushAbsoluteContainingBlock during frame construction should get
1640 * corresponding logic in these functions.
1642 public:
1643 enum ContainingBlockType { ABS_POS, FIXED_POS };
1644 nsContainerFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame,
1645 ContainingBlockType aType);
1646 nsContainerFrame* GetFloatContainingBlock(nsIFrame* aFrame);
1648 private:
1649 // Build a scroll frame:
1650 // Calls BeginBuildingScrollFrame, InitAndRestoreFrame, and then
1651 // FinishBuildingScrollFrame.
1652 // @param aNewFrame the created scrollframe --- output only
1653 // @param aParentFrame the geometric parent that the scrollframe will have.
1654 void BuildScrollFrame(nsFrameConstructorState& aState, nsIContent* aContent,
1655 ComputedStyle* aContentStyle, nsIFrame* aScrolledFrame,
1656 nsContainerFrame* aParentFrame,
1657 nsContainerFrame*& aNewFrame);
1659 // Builds the initial ScrollFrame
1660 already_AddRefed<ComputedStyle> BeginBuildingScrollFrame(
1661 nsFrameConstructorState& aState, nsIContent* aContent,
1662 ComputedStyle* aContentStyle, nsContainerFrame* aParentFrame,
1663 mozilla::PseudoStyleType aScrolledPseudo, bool aIsRoot,
1664 nsContainerFrame*& aNewFrame);
1666 // Completes the building of the scrollframe:
1667 // Creates a view for the scrolledframe and makes it the child of the
1668 // scrollframe.
1669 void FinishBuildingScrollFrame(nsContainerFrame* aScrollFrame,
1670 nsIFrame* aScrolledFrame);
1672 void InitializeListboxSelect(nsFrameConstructorState& aState,
1673 nsContainerFrame* aScrollFrame,
1674 nsContainerFrame* aScrolledFrame,
1675 nsIContent* aContent,
1676 nsContainerFrame* aParentFrame,
1677 ComputedStyle* aComputedStyle,
1678 nsFrameList& aFrameList);
1681 * Recreate frames for aContent.
1682 * @param aContent the content to recreate frames for
1683 * @param aFlags normally you want to pass REMOVE_FOR_RECONSTRUCTION here
1685 void RecreateFramesForContent(nsIContent* aContent,
1686 InsertionKind aInsertionKind);
1689 * Handles change of rowspan and colspan attributes on table cells.
1691 void UpdateTableCellSpans(nsIContent* aContent);
1693 // If removal of aFrame from the frame tree requires reconstruction of some
1694 // containing block (either of aFrame or of its parent) due to {ib} splits or
1695 // table pseudo-frames, recreate the relevant frame subtree. The return value
1696 // indicates whether this happened. aFrame must be the result of a
1697 // GetPrimaryFrame() call on a content node (which means its parent is also
1698 // not null).
1699 bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame);
1701 nsIFrame* CreateContinuingOuterTableFrame(nsIFrame* aFrame,
1702 nsContainerFrame* aParentFrame,
1703 nsIContent* aContent,
1704 ComputedStyle* aComputedStyle);
1706 nsIFrame* CreateContinuingTableFrame(nsIFrame* aFrame,
1707 nsContainerFrame* aParentFrame,
1708 nsIContent* aContent,
1709 ComputedStyle* aComputedStyle);
1711 //----------------------------------------
1713 // Methods support creating block frames and their children
1715 already_AddRefed<ComputedStyle> GetFirstLetterStyle(
1716 nsIContent* aContent, ComputedStyle* aComputedStyle);
1718 already_AddRefed<ComputedStyle> GetFirstLineStyle(
1719 nsIContent* aContent, ComputedStyle* aComputedStyle);
1721 bool ShouldHaveFirstLetterStyle(nsIContent* aContent,
1722 ComputedStyle* aComputedStyle);
1724 // Check whether a given block has first-letter style. Make sure to
1725 // only pass in blocks! And don't pass in null either.
1726 bool HasFirstLetterStyle(nsIFrame* aBlockFrame);
1728 bool ShouldHaveFirstLineStyle(nsIContent* aContent,
1729 ComputedStyle* aComputedStyle);
1731 void ShouldHaveSpecialBlockStyle(nsIContent* aContent,
1732 ComputedStyle* aComputedStyle,
1733 bool* aHaveFirstLetterStyle,
1734 bool* aHaveFirstLineStyle);
1736 // |aContentParentFrame| should be null if it's really the same as
1737 // |aParentFrame|.
1738 // @param aFrameList where we want to put the block in case it's in-flow.
1739 // @param aNewFrame an in/out parameter. On input it is the block to be
1740 // constructed. On output it is reset to the outermost
1741 // frame constructed (e.g. if we need to wrap the block in an
1742 // nsColumnSetFrame.
1743 // @param aParentFrame is the desired parent for the (possibly wrapped)
1744 // block
1745 // @param aContentParent is the parent the block would have if it
1746 // were in-flow
1747 // @param aPositionedFrameForAbsPosContainer if non-null, then the new
1748 // block should be an abs-pos container and aPositionedFrameForAbsPosContainer
1749 // is the frame whose style is making this block an abs-pos container.
1750 void ConstructBlock(nsFrameConstructorState& aState, nsIContent* aContent,
1751 nsContainerFrame* aParentFrame,
1752 nsContainerFrame* aContentParentFrame,
1753 ComputedStyle* aComputedStyle,
1754 nsContainerFrame** aNewFrame, nsFrameList& aFrameList,
1755 nsIFrame* aPositionedFrameForAbsPosContainer);
1757 // Build the initial column hierarchy around aColumnContent. This function
1758 // should be called before constructing aColumnContent's children.
1760 // Before calling FinishBuildingColumns(), we need to create column-span
1761 // siblings for aColumnContent's children. Caller can use helpers
1762 // MayNeedToCreateColumnSpanSiblings() and CreateColumnSpanSiblings() to
1763 // check whether column-span siblings might need to be created and to do
1764 // the actual work of creating them if they're needed.
1766 // @param aColumnContent the block that we're wrapping in a ColumnSet. On
1767 // entry to this function it has aComputedStyle as its style. After
1768 // this function returns, aColumnContent has a ::-moz-column-content
1769 // anonymous box style.
1770 // @param aParentFrame the parent frame we want to use for the
1771 // ColumnSetWrapperFrame (which would have been the parent of
1772 // aColumnContent if we were not creating a column hierarchy).
1773 // @param aContent is the content of the aColumnContent.
1774 // @return the outermost ColumnSetWrapperFrame.
1775 nsBlockFrame* BeginBuildingColumns(nsFrameConstructorState& aState,
1776 nsIContent* aContent,
1777 nsContainerFrame* aParentFrame,
1778 nsContainerFrame* aColumnContent,
1779 ComputedStyle* aComputedStyle);
1781 // Complete building the column hierarchy by first wrapping each
1782 // non-column-span child in aChildList in a ColumnSetFrame (skipping
1783 // column-span children), and reparenting them to have aColumnSetWrapper
1784 // as their parent.
1786 // @param aColumnSetWrapper is the frame returned by
1787 // BeginBuildingColumns(), and is the grandparent of aColumnContent.
1788 // @param aColumnContent is the block frame passed into
1789 // BeginBuildingColumns()
1790 // @param aColumnContentSiblings contains the aColumnContent's siblings, which
1791 // are the column spanners and aColumnContent's continuations returned
1792 // by CreateColumnSpanSiblings(). It'll become empty after this call.
1793 void FinishBuildingColumns(nsFrameConstructorState& aState,
1794 nsContainerFrame* aColumnSetWrapper,
1795 nsContainerFrame* aColumnContent,
1796 nsFrameList& aColumnContentSiblings);
1798 // Return whether aBlockFrame's children in aChildList, which might
1799 // contain column-span, may need to be wrapped in
1800 // ::moz-column-span-wrapper and promoted as aBlockFrame's siblings.
1802 // @param aBlockFrame is the parent of the frames in aChildList.
1804 // Note: This a check without actually looking into each frame in the
1805 // child list, so it may return false positive.
1806 bool MayNeedToCreateColumnSpanSiblings(nsContainerFrame* aBlockFrame,
1807 const nsFrameList& aChildList);
1809 // Wrap consecutive runs of column-span kids and runs of non-column-span
1810 // kids in blocks for aInitialBlock's children.
1812 // @param aInitialBlock is the parent of those frames in aChildList.
1813 // @param aChildList must begin with a column-span kid. It becomes empty
1814 // after this call.
1815 // @param aPositionedFrame if non-null, it's the frame whose style is making
1816 // aInitialBlock an abs-pos container.
1818 // Return those wrapping blocks in nsFrameList.
1819 nsFrameList CreateColumnSpanSiblings(nsFrameConstructorState& aState,
1820 nsContainerFrame* aInitialBlock,
1821 nsFrameList& aChildList,
1822 nsIFrame* aPositionedFrame);
1824 // Reconstruct the multi-column containing block of aParentFrame when we want
1825 // to insert aFrameList into aParentFrame immediately after aPrevSibling but
1826 // cannot fix the frame tree because aFrameList contains some column-spans.
1828 // Note: This method is intended to be called as a helper in ContentAppended()
1829 // and ContentRangeInserted(). It assumes aState was set up locally and wasn't
1830 // used to construct any ancestors of aParentFrame in aFrameList.
1832 // @param aParentFrame the to-be parent frame for aFrameList.
1833 // @param aFrameList the frames to be inserted. It will be cleared if we need
1834 // reconstruction.
1835 // @param aPrevSibling the position where the frames in aFrameList are going
1836 // to be inserted. Nullptr means aFrameList is being inserted at
1837 // the beginning.
1838 // @return true if the multi-column containing block of aParentFrame is
1839 // reconstructed; false otherwise.
1840 bool MaybeRecreateForColumnSpan(nsFrameConstructorState& aState,
1841 nsContainerFrame* aParentFrame,
1842 nsFrameList& aFrameList,
1843 nsIFrame* aPrevSibling);
1845 nsIFrame* ConstructInline(nsFrameConstructorState& aState,
1846 FrameConstructionItem& aItem,
1847 nsContainerFrame* aParentFrame,
1848 const nsStyleDisplay* aDisplay,
1849 nsFrameList& aFrameList);
1852 * Create any additional {ib} siblings needed to contain aChildList and put
1853 * them in aSiblings.
1855 * @param aState the frame constructor state
1856 * @param aInitialInline is an already-existing inline frame that will be
1857 * part of this {ib} split and come before everything
1858 * in aSiblings.
1859 * @param aIsPositioned true if aInitialInline is positioned.
1860 * @param aChildList is a child list starting with a block; this method
1861 * assumes that the inline has already taken all the
1862 * children it wants. When the method returns aChildList
1863 * will be empty.
1864 * @param aSiblings the nsFrameList to put the newly-created siblings into.
1866 * This method is responsible for making any SetFrameIsIBSplit calls that are
1867 * needed.
1869 void CreateIBSiblings(nsFrameConstructorState& aState,
1870 nsContainerFrame* aInitialInline, bool aIsPositioned,
1871 nsFrameList& aChildList, nsFrameList& aSiblings);
1874 * For an inline aParentItem, construct its list of child
1875 * FrameConstructionItems and set its mIsAllInline flag appropriately.
1877 void BuildInlineChildItems(nsFrameConstructorState& aState,
1878 FrameConstructionItem& aParentItem,
1879 bool aItemIsWithinSVGText,
1880 bool aItemAllowsTextPathChild);
1882 // Determine whether we need to wipe out aFrame (the insertion parent) and
1883 // rebuild the entire subtree when we insert or append new content under
1884 // aFrame.
1886 // This is similar to WipeContainingBlock(), but is called before constructing
1887 // any frame construction items. Any container frames which need reframing
1888 // regardless of the content inserted or appended can add a check in this
1889 // method.
1891 // @return true if we reconstructed the insertion parent frame; false
1892 // otherwise
1893 bool WipeInsertionParent(nsContainerFrame* aFrame);
1895 // Determine whether we need to wipe out what we just did and start over
1896 // because we're doing something like adding block kids to an inline frame
1897 // (and therefore need an {ib} split). aPrevSibling must be correct, even in
1898 // aIsAppend cases. Passing aIsAppend false even when an append is happening
1899 // is ok in terms of correctness, but can lead to unnecessary reframing. If
1900 // aIsAppend is true, then the caller MUST call
1901 // nsCSSFrameConstructor::AppendFramesToParent (as opposed to
1902 // nsFrameManager::InsertFrames directly) to add the new frames.
1903 // @return true if we reconstructed the containing block, false
1904 // otherwise
1905 bool WipeContainingBlock(nsFrameConstructorState& aState,
1906 nsIFrame* aContainingBlock, nsIFrame* aFrame,
1907 FrameConstructionItemList& aItems, bool aIsAppend,
1908 nsIFrame* aPrevSibling);
1910 void ReframeContainingBlock(nsIFrame* aFrame);
1912 //----------------------------------------
1914 // Methods support :first-letter style
1916 nsFirstLetterFrame* CreateFloatingLetterFrame(
1917 nsFrameConstructorState& aState, mozilla::dom::Text* aTextContent,
1918 nsIFrame* aTextFrame, nsContainerFrame* aParentFrame,
1919 ComputedStyle* aParentStyle, ComputedStyle* aComputedStyle,
1920 nsFrameList& aResult);
1922 void CreateLetterFrame(nsContainerFrame* aBlockFrame,
1923 nsContainerFrame* aBlockContinuation,
1924 mozilla::dom::Text* aTextContent,
1925 nsContainerFrame* aParentFrame, nsFrameList& aResult);
1927 void WrapFramesInFirstLetterFrame(nsContainerFrame* aBlockFrame,
1928 nsFrameList& aBlockFrames);
1931 * Looks in the block aBlockFrame for a text frame that contains the
1932 * first-letter of the block and creates the necessary first-letter frames
1933 * and returns them in aLetterFrames.
1935 * @param aBlockFrame the (first-continuation of) the block we are creating a
1936 * first-letter frame for
1937 * @param aBlockContinuation the current continuation of the block that we
1938 * are looking in for a textframe with suitable
1939 * contents for first-letter
1940 * @param aParentFrame the current frame whose children we are looking at for
1941 * a suitable first-letter textframe
1942 * @param aParentFrameList the first child of aParentFrame
1943 * @param aModifiedParent returns the parent of the textframe that contains
1944 * the first-letter
1945 * @param aTextFrame returns the textframe that had the first-letter
1946 * @param aPrevFrame returns the previous sibling of aTextFrame
1947 * @param aLetterFrames returns the frames that were created
1949 void WrapFramesInFirstLetterFrame(
1950 nsContainerFrame* aBlockFrame, nsContainerFrame* aBlockContinuation,
1951 nsContainerFrame* aParentFrame, nsIFrame* aParentFrameList,
1952 nsContainerFrame** aModifiedParent, nsIFrame** aTextFrame,
1953 nsIFrame** aPrevFrame, nsFrameList& aLetterFrames, bool* aStopLooking);
1955 void RecoverLetterFrames(nsContainerFrame* aBlockFrame);
1957 void RemoveLetterFrames(PresShell* aPresShell, nsContainerFrame* aBlockFrame);
1959 // Recursive helper for RemoveLetterFrames
1960 void RemoveFirstLetterFrames(PresShell* aPresShell, nsContainerFrame* aFrame,
1961 nsContainerFrame* aBlockFrame,
1962 bool* aStopLooking);
1964 // Special remove method for those pesky floating first-letter frames
1965 void RemoveFloatingFirstLetterFrames(PresShell* aPresShell,
1966 nsIFrame* aBlockFrame);
1968 // Capture state for the frame tree rooted at the frame associated with the
1969 // content object, aContent
1970 void CaptureStateForFramesOf(nsIContent* aContent,
1971 nsILayoutHistoryState* aHistoryState);
1973 //----------------------------------------
1975 // Methods support :first-line style
1977 // This method chops the initial inline-outside frames out of aFrameList.
1978 // If aLineFrame is non-null, it appends them to that frame. Otherwise, it
1979 // creates a new line frame, sets the inline frames as its initial child
1980 // list, and inserts that line frame at the front of what's left of
1981 // aFrameList. In both cases, the kids are reparented to the line frame.
1982 // After this call, aFrameList holds the frames that need to become kids of
1983 // the block (possibly including line frames).
1984 void WrapFramesInFirstLineFrame(nsFrameConstructorState& aState,
1985 nsIContent* aBlockContent,
1986 nsContainerFrame* aBlockFrame,
1987 nsFirstLineFrame* aLineFrame,
1988 nsFrameList& aFrameList);
1990 // Handle the case when a block with first-line style is appended to (by
1991 // possibly calling WrapFramesInFirstLineFrame as needed).
1992 void AppendFirstLineFrames(nsFrameConstructorState& aState,
1993 nsIContent* aContent,
1994 nsContainerFrame* aBlockFrame,
1995 nsFrameList& aFrameList);
1998 * When aFrameList is being inserted into aParentFrame, and aParentFrame has
1999 * pseudo-element-affected styles, it's possible that we're inserting under a
2000 * ::first-line frame. In that case, with servo's style system, the styles we
2001 * resolved for aFrameList are wrong (they don't take ::first-line into
2002 * account), and we should fix them up, which is what this method does.
2004 * This method does not mutate aFrameList.
2006 void CheckForFirstLineInsertion(nsIFrame* aParentFrame,
2007 nsFrameList& aFrameList);
2010 * Find the next frame for appending to a given insertion point.
2012 * We're appending, so this is almost always null, except for a few edge
2013 * cases.
2015 nsIFrame* FindNextSiblingForAppend(const InsertionPoint&);
2017 // The direction in which we should look for siblings.
2018 enum class SiblingDirection {
2019 Forward,
2020 Backward,
2024 * Find the frame for the content immediately next to the one aIter points to,
2025 * in the direction SiblingDirection indicates, following continuations if
2026 * necessary.
2028 * aIter is passed by const reference on purpose, so as not to modify the
2029 * caller's iterator.
2031 * @param aIter should be positioned such that aIter.GetPreviousChild()
2032 * is the first content to search for frames
2033 * @param aTargetContentDisplay the CSS display enum for the content aIter
2034 * points to if already known. It will be filled in if needed.
2036 template <SiblingDirection>
2037 nsIFrame* FindSibling(
2038 const mozilla::dom::FlattenedChildIterator& aIter,
2039 mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay);
2041 // Helper for the implementation of FindSibling.
2043 // Beware that this function does mutate the iterator.
2044 template <SiblingDirection>
2045 nsIFrame* FindSiblingInternal(
2046 mozilla::dom::FlattenedChildIterator&, nsIContent* aTargetContent,
2047 mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay);
2049 // An alias of FindSibling<SiblingDirection::Forward>.
2050 nsIFrame* FindNextSibling(
2051 const mozilla::dom::FlattenedChildIterator& aIter,
2052 mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay);
2053 // An alias of FindSibling<SiblingDirection::Backwards>.
2054 nsIFrame* FindPreviousSibling(
2055 const mozilla::dom::FlattenedChildIterator& aIter,
2056 mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay);
2058 // Given a potential first-continuation sibling frame for aTargetContent,
2059 // verify that it is an actual valid sibling for it, and return the
2060 // appropriate continuation the new frame for aTargetContent should be
2061 // inserted next to.
2062 nsIFrame* AdjustSiblingFrame(
2063 nsIFrame* aSibling, nsIContent* aTargetContent,
2064 mozilla::Maybe<mozilla::StyleDisplay>& aTargetContentDisplay,
2065 SiblingDirection aDirection);
2067 // Find the right previous sibling for an insertion. This also updates the
2068 // parent frame to point to the correct continuation of the parent frame to
2069 // use, and returns whether this insertion is to be treated as an append.
2070 // aChild is the child being inserted.
2071 // aIsRangeInsertSafe returns whether it is safe to do a range insert with
2072 // aChild being the first child in the range. It is the callers'
2073 // responsibility to check whether a range insert is safe with regards to
2074 // fieldsets.
2075 // The skip parameters are used to ignore a range of children when looking
2076 // for a sibling. All nodes starting from aStartSkipChild and up to but not
2077 // including aEndSkipChild will be skipped over when looking for sibling
2078 // frames. Skipping a range can deal with shadow DOM, but not when there are
2079 // multiple insertion points.
2080 nsIFrame* GetInsertionPrevSibling(InsertionPoint* aInsertion, // inout
2081 nsIContent* aChild, bool* aIsAppend,
2082 bool* aIsRangeInsertSafe,
2083 nsIContent* aStartSkipChild = nullptr,
2084 nsIContent* aEndSkipChild = nullptr);
2086 // see if aContent and aSibling are legitimate siblings due to restrictions
2087 // imposed by table columns
2088 // XXXbz this code is generally wrong, since the frame for aContent
2089 // may be constructed based on tag, not based on aDisplay!
2090 bool IsValidSibling(nsIFrame* aSibling, nsIContent* aContent,
2091 mozilla::Maybe<mozilla::StyleDisplay>& aDisplay);
2093 void QuotesDirty();
2094 void CountersDirty();
2096 void ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
2097 nsContainerFrame* aFrame,
2098 nsIContent* aDocElement,
2099 nsFrameList&);
2101 public:
2102 friend class nsFrameConstructorState;
2104 private:
2105 // For allocating FrameConstructionItems from the mFCItemPool arena.
2106 friend struct FrameConstructionItem;
2107 void* AllocateFCItem();
2108 void FreeFCItem(FrameConstructionItem*);
2110 mozilla::dom::Document* mDocument; // Weak ref
2112 // See the comment at the start of ConstructRootFrame for more details
2113 // about the following frames.
2115 // This is just the outermost frame for the root element.
2116 nsContainerFrame* mRootElementFrame = nullptr;
2117 // This is the frame for the root element that has no pseudo-element style.
2118 nsIFrame* mRootElementStyleFrame = nullptr;
2119 // This is the containing block that contains the root element ---
2120 // the real "initial containing block" according to CSS 2.1.
2121 nsCanvasFrame* mDocElementContainingBlock = nullptr;
2122 // This is usually mDocElementContainingBlock, except when printing, where it
2123 // is the canvas frame that is under all the printed pages.
2124 nsCanvasFrame* mCanvasFrame = nullptr;
2125 nsPageSequenceFrame* mPageSequenceFrame = nullptr;
2127 // FrameConstructionItem arena + list of freed items available for re-use.
2128 mozilla::ArenaAllocator<4096, 8> mFCItemPool;
2130 // This indicates what page name to use for the next nsPageContentFrame.
2131 // Set when CSS named pages cause a breakpoint.
2132 // This does not apply to the first page content frame, which has its name
2133 // set by nsPageContentFrame::EnsurePageName() during first reflow.
2134 RefPtr<const nsAtom> mNextPageContentFramePageName;
2136 struct FreeFCItemLink {
2137 FreeFCItemLink* mNext;
2139 FreeFCItemLink* mFirstFreeFCItem;
2140 size_t mFCItemsInUse;
2142 mozilla::ContainStyleScopeManager mContainStyleScopeManager;
2144 // Current ProcessChildren depth.
2145 uint16_t mCurrentDepth;
2146 bool mQuotesDirty : 1;
2147 bool mCountersDirty : 1;
2148 bool mAlwaysCreateFramesForIgnorableWhitespace : 1;
2150 // The layout state from our history entry (to restore scroll positions and
2151 // such from history), or a new one if there was none (so we can store scroll
2152 // positions and such during reframe).
2154 // FIXME(bug 1397239): This can leak some state sometimes for the lifetime of
2155 // the frame constructor, which is not great.
2156 nsCOMPtr<nsILayoutHistoryState> mFrameTreeState;
2159 #endif /* nsCSSFrameConstructor_h___ */