layout/base/nsCSSFrameConstructor.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial