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