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