1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/base/nsCSSFrameConstructor.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1809 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * construction of a frame tree that is nearly isomorphic to the content 1.11 + * tree and updating of that tree in response to dynamic changes 1.12 + */ 1.13 + 1.14 +#ifndef nsCSSFrameConstructor_h___ 1.15 +#define nsCSSFrameConstructor_h___ 1.16 + 1.17 +#include "mozilla/Attributes.h" 1.18 + 1.19 +#include "nsCOMPtr.h" 1.20 +#include "nsILayoutHistoryState.h" 1.21 +#include "nsQuoteList.h" 1.22 +#include "nsCounterManager.h" 1.23 +#include "nsCSSPseudoElements.h" 1.24 +#include "nsIAnonymousContentCreator.h" 1.25 +#include "nsFrameManager.h" 1.26 +#include "nsIDocument.h" 1.27 + 1.28 +struct nsFrameItems; 1.29 +struct nsAbsoluteItems; 1.30 +class nsStyleContext; 1.31 +struct nsStyleDisplay; 1.32 +class nsIDOMHTMLSelectElement; 1.33 +struct nsGenConInitializer; 1.34 + 1.35 +class nsICSSAnonBoxPseudo; 1.36 +class nsPageContentFrame; 1.37 +struct PendingBinding; 1.38 +class nsGenericDOMDataNode; 1.39 + 1.40 +class nsFrameConstructorState; 1.41 +class nsFrameConstructorSaveState; 1.42 + 1.43 +namespace mozilla { 1.44 + 1.45 +class RestyleManager; 1.46 + 1.47 +namespace dom { 1.48 + 1.49 +class FlattenedChildIterator; 1.50 + 1.51 +} 1.52 +} 1.53 + 1.54 +class nsCSSFrameConstructor : public nsFrameManager 1.55 +{ 1.56 +public: 1.57 + typedef mozilla::dom::Element Element; 1.58 + 1.59 + friend class mozilla::RestyleManager; 1.60 + 1.61 + nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell, 1.62 + nsStyleSet* aStyleSet); 1.63 + ~nsCSSFrameConstructor(void) { 1.64 + NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?"); 1.65 + } 1.66 + 1.67 + // get the alternate text for a content node 1.68 + static void GetAlternateTextFor(nsIContent* aContent, 1.69 + nsIAtom* aTag, // content object's tag 1.70 + nsXPIDLString& aAltText); 1.71 + 1.72 +private: 1.73 + nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) MOZ_DELETE; 1.74 + nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) MOZ_DELETE; 1.75 + 1.76 +public: 1.77 + mozilla::RestyleManager* RestyleManager() const 1.78 + { return mPresShell->GetPresContext()->RestyleManager(); } 1.79 + 1.80 + nsIFrame* ConstructRootFrame(); 1.81 + 1.82 + nsresult ReconstructDocElementHierarchy(); 1.83 + 1.84 + // Create frames for content nodes that are marked as needing frames. This 1.85 + // should be called before ProcessPendingRestyles. 1.86 + // Note: It's the caller's responsibility to make sure to wrap a 1.87 + // CreateNeededFrames call in a view update batch and a script blocker. 1.88 + void CreateNeededFrames(); 1.89 + 1.90 +private: 1.91 + void CreateNeededFrames(nsIContent* aContent); 1.92 + 1.93 + enum Operation { 1.94 + CONTENTAPPEND, 1.95 + CONTENTINSERT 1.96 + }; 1.97 + 1.98 + // aChild is the child being inserted for inserts, and the first 1.99 + // child being appended for appends. 1.100 + bool MaybeConstructLazily(Operation aOperation, 1.101 + nsIContent* aContainer, 1.102 + nsIContent* aChild); 1.103 + 1.104 + // Issues a single ContentInserted for each child of aContainer in the range 1.105 + // [aStartChild, aEndChild). 1.106 + void IssueSingleInsertNofications(nsIContent* aContainer, 1.107 + nsIContent* aStartChild, 1.108 + nsIContent* aEndChild, 1.109 + bool aAllowLazyConstruction); 1.110 + 1.111 + // Checks if the children of aContainer in the range [aStartChild, aEndChild) 1.112 + // can be inserted/appended to one insertion point together. If so, returns 1.113 + // that insertion point. If not, returns null and issues single 1.114 + // ContentInserted calls for each child. aEndChild = nullptr indicates that we 1.115 + // are dealing with an append. 1.116 + nsIFrame* GetRangeInsertionPoint(nsIContent* aContainer, 1.117 + nsIContent* aStartChild, 1.118 + nsIContent* aEndChild, 1.119 + bool aAllowLazyConstruction); 1.120 + 1.121 + // Returns true if parent was recreated due to frameset child, false otherwise. 1.122 + bool MaybeRecreateForFrameset(nsIFrame* aParentFrame, 1.123 + nsIContent* aStartChild, 1.124 + nsIContent* aEndChild); 1.125 + 1.126 +public: 1.127 + /** 1.128 + * Lazy frame construction is controlled by the aAllowLazyConstruction bool 1.129 + * parameter of nsCSSFrameConstructor::ContentAppended/Inserted. It is true 1.130 + * for all inserts/appends as passed from the presshell, except for the 1.131 + * insert of the root element, which is always non-lazy. Even if the 1.132 + * aAllowLazyConstruction passed to ContentAppended/Inserted is true we still 1.133 + * may not be able to construct lazily, so we call MaybeConstructLazily. 1.134 + * MaybeConstructLazily does not allow lazy construction if any of the 1.135 + * following are true: 1.136 + * -we are in chrome 1.137 + * -the container is in a native anonymous subtree 1.138 + * -the container is XUL 1.139 + * -is any of the appended/inserted nodes are XUL or editable 1.140 + * -(for inserts) the child is anonymous. In the append case this function 1.141 + * must not be called with anonymous children. 1.142 + * The XUL and chrome checks are because XBL bindings only get applied at 1.143 + * frame construction time and some things depend on the bindings getting 1.144 + * attached synchronously. The editable checks are because the editor seems 1.145 + * to expect frames to be constructed synchronously. 1.146 + * 1.147 + * If MaybeConstructLazily returns false we construct as usual, but if it 1.148 + * returns true then it adds NODE_NEEDS_FRAME bits to the newly 1.149 + * inserted/appended nodes and adds NODE_DESCENDANTS_NEED_FRAMES bits to the 1.150 + * container and up along the parent chain until it hits the root or another 1.151 + * node with that bit set. Then it posts a restyle event to ensure that a 1.152 + * flush happens to construct those frames. 1.153 + * 1.154 + * When the flush happens the presshell calls 1.155 + * nsCSSFrameConstructor::CreateNeededFrames. CreateNeededFrames follows any 1.156 + * nodes with NODE_DESCENDANTS_NEED_FRAMES set down the content tree looking 1.157 + * for nodes with NODE_NEEDS_FRAME set. It calls ContentAppended for any runs 1.158 + * of nodes with NODE_NEEDS_FRAME set that are at the end of their childlist, 1.159 + * and ContentRangeInserted for any other runs that aren't. 1.160 + * 1.161 + * If a node is removed from the document then we don't bother unsetting any 1.162 + * of the lazy bits that might be set on it, its descendants, or any of its 1.163 + * ancestor nodes because that is a slow operation, the work might be wasted 1.164 + * if another node gets inserted in its place, and we can clear the bits 1.165 + * quicker by processing the content tree from top down the next time we call 1.166 + * CreateNeededFrames. (We do clear the bits when BindToTree is called on any 1.167 + * nsIContent; so any nodes added to the document will not have any lazy bits 1.168 + * set.) 1.169 + */ 1.170 + 1.171 + // If aAllowLazyConstruction is true then frame construction of the new 1.172 + // children can be done lazily. 1.173 + nsresult ContentAppended(nsIContent* aContainer, 1.174 + nsIContent* aFirstNewContent, 1.175 + bool aAllowLazyConstruction); 1.176 + 1.177 + // If aAllowLazyConstruction is true then frame construction of the new child 1.178 + // can be done lazily. 1.179 + nsresult ContentInserted(nsIContent* aContainer, 1.180 + nsIContent* aChild, 1.181 + nsILayoutHistoryState* aFrameState, 1.182 + bool aAllowLazyConstruction); 1.183 + 1.184 + // Like ContentInserted but handles inserting the children of aContainer in 1.185 + // the range [aStartChild, aEndChild). aStartChild must be non-null. 1.186 + // aEndChild may be null to indicate the range includes all kids after 1.187 + // aStartChild. If aAllowLazyConstruction is true then frame construction of 1.188 + // the new children can be done lazily. It is only allowed to be true when 1.189 + // inserting a single node. 1.190 + nsresult ContentRangeInserted(nsIContent* aContainer, 1.191 + nsIContent* aStartChild, 1.192 + nsIContent* aEndChild, 1.193 + nsILayoutHistoryState* aFrameState, 1.194 + bool aAllowLazyConstruction); 1.195 + 1.196 + enum RemoveFlags { REMOVE_CONTENT, REMOVE_FOR_RECONSTRUCTION }; 1.197 + nsresult ContentRemoved(nsIContent* aContainer, 1.198 + nsIContent* aChild, 1.199 + nsIContent* aOldNextSibling, 1.200 + RemoveFlags aFlags, 1.201 + bool* aDidReconstruct); 1.202 + 1.203 + nsresult CharacterDataChanged(nsIContent* aContent, 1.204 + CharacterDataChangeInfo* aInfo); 1.205 + 1.206 + // If aContent is a text node that has been optimized away due to being 1.207 + // whitespace next to a block boundary (or for some other reason), stop 1.208 + // doing that and create a frame for it if it should have one. This recreates 1.209 + // frames so be careful (although this should not change actual layout). 1.210 + // Returns the frame for aContent if there is one. 1.211 + nsIFrame* EnsureFrameForTextNode(nsGenericDOMDataNode* aContent); 1.212 + 1.213 + // generate the child frames and process bindings 1.214 + nsresult GenerateChildFrames(nsIFrame* aFrame); 1.215 + 1.216 + // Should be called when a frame is going to be destroyed and 1.217 + // WillDestroyFrameTree hasn't been called yet. 1.218 + void NotifyDestroyingFrame(nsIFrame* aFrame); 1.219 + 1.220 + void BeginUpdate(); 1.221 + void EndUpdate(); 1.222 + void RecalcQuotesAndCounters(); 1.223 + 1.224 + // Gets called when the presshell is destroying itself and also 1.225 + // when we tear down our frame tree to reconstruct it 1.226 + void WillDestroyFrameTree(); 1.227 + 1.228 + // Request to create a continuing frame. This method never returns null. 1.229 + nsIFrame* CreateContinuingFrame(nsPresContext* aPresContext, 1.230 + nsIFrame* aFrame, 1.231 + nsIFrame* aParentFrame, 1.232 + bool aIsFluid = true); 1.233 + 1.234 + // Copy over fixed frames from aParentFrame's prev-in-flow 1.235 + nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame); 1.236 + 1.237 + // Get the XBL insertion point for a child 1.238 + nsIFrame* GetInsertionPoint(nsIContent* aContainer, 1.239 + nsIContent* aChildContent, 1.240 + bool* aMultiple = nullptr); 1.241 + 1.242 + nsresult CreateListBoxContent(nsPresContext* aPresContext, 1.243 + nsIFrame* aParentFrame, 1.244 + nsIFrame* aPrevFrame, 1.245 + nsIContent* aChild, 1.246 + nsIFrame** aResult, 1.247 + bool aIsAppend, 1.248 + bool aIsScrollbar, 1.249 + nsILayoutHistoryState* aFrameState); 1.250 + 1.251 + // GetInitialContainingBlock() is deprecated in favor of GetRootElementFrame(); 1.252 + // nsIFrame* GetInitialContainingBlock() { return mRootElementFrame; } 1.253 + // This returns the outermost frame for the root element 1.254 + nsIFrame* GetRootElementFrame() { return mRootElementFrame; } 1.255 + // This returns the frame for the root element that does not 1.256 + // have a psuedo-element style 1.257 + nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; } 1.258 + nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; } 1.259 + 1.260 + // Get the frame that is the parent of the root element. 1.261 + nsIFrame* GetDocElementContainingBlock() 1.262 + { return mDocElementContainingBlock; } 1.263 + 1.264 +private: 1.265 + struct FrameConstructionItem; 1.266 + class FrameConstructionItemList; 1.267 + 1.268 + nsIFrame* ConstructPageFrame(nsIPresShell* aPresShell, 1.269 + nsPresContext* aPresContext, 1.270 + nsIFrame* aParentFrame, 1.271 + nsIFrame* aPrevPageFrame, 1.272 + nsIFrame*& aCanvasFrame); 1.273 + 1.274 + void InitAndRestoreFrame (const nsFrameConstructorState& aState, 1.275 + nsIContent* aContent, 1.276 + nsIFrame* aParentFrame, 1.277 + nsIFrame* aNewFrame, 1.278 + bool aAllowCounters = true); 1.279 + 1.280 + // aState can be null if not available; it's used as an optimization. 1.281 + // XXXbz IsValidSibling is the only caller that doesn't pass a state here! 1.282 + already_AddRefed<nsStyleContext> 1.283 + ResolveStyleContext(nsIFrame* aParentFrame, 1.284 + nsIContent* aContent, 1.285 + nsFrameConstructorState* aState); 1.286 + already_AddRefed<nsStyleContext> 1.287 + ResolveStyleContext(nsStyleContext* aParentStyleContext, 1.288 + nsIContent* aContent, 1.289 + nsFrameConstructorState* aState); 1.290 + 1.291 + // Add the frame construction items for the given aContent and aParentFrame 1.292 + // to the list. This might add more than one item in some rare cases. 1.293 + // If aSuppressWhiteSpaceOptimizations is true, optimizations that 1.294 + // may suppress the construction of white-space-only text frames 1.295 + // must be skipped for these items and items around them. 1.296 + void AddFrameConstructionItems(nsFrameConstructorState& aState, 1.297 + nsIContent* aContent, 1.298 + bool aSuppressWhiteSpaceOptimizations, 1.299 + nsIFrame* aParentFrame, 1.300 + FrameConstructionItemList& aItems); 1.301 + 1.302 + // Construct the frames for the document element. This can return null if the 1.303 + // document element is display:none, or if the document element has a 1.304 + // not-yet-loaded XBL binding, or if it's an SVG element that's not <svg>. 1.305 + nsIFrame* ConstructDocElementFrame(Element* aDocElement, 1.306 + nsILayoutHistoryState* aFrameState); 1.307 + 1.308 + // Set up our mDocElementContainingBlock correctly for the given root 1.309 + // content. 1.310 + void SetUpDocElementContainingBlock(nsIContent* aDocElement); 1.311 + 1.312 + /** 1.313 + * CreateAttributeContent creates a single content/frame combination for an 1.314 + * |attr(foo)| generated content. 1.315 + * 1.316 + * @param aParentContent the parent content for the generated content 1.317 + * @param aParentFrame the parent frame for the generated frame 1.318 + * @param aAttrNamespace the namespace of the attribute in question 1.319 + * @param aAttrName the localname of the attribute 1.320 + * @param aStyleContext the style context to use 1.321 + * @param aGeneratedContent the array of generated content to append the 1.322 + * created content to. 1.323 + * @param [out] aNewContent the content node we create 1.324 + * @param [out] aNewFrame the new frame we create 1.325 + */ 1.326 + nsresult CreateAttributeContent(nsIContent* aParentContent, 1.327 + nsIFrame* aParentFrame, 1.328 + int32_t aAttrNamespace, 1.329 + nsIAtom* aAttrName, 1.330 + nsStyleContext* aStyleContext, 1.331 + nsCOMArray<nsIContent>& aGeneratedContent, 1.332 + nsIContent** aNewContent, 1.333 + nsIFrame** aNewFrame); 1.334 + 1.335 + /** 1.336 + * Create a text node containing the given string. If aText is non-null 1.337 + * then we also set aText to the returned node. 1.338 + */ 1.339 + already_AddRefed<nsIContent> CreateGenConTextNode(nsFrameConstructorState& aState, 1.340 + const nsString& aString, 1.341 + nsCOMPtr<nsIDOMCharacterData>* aText, 1.342 + nsGenConInitializer* aInitializer); 1.343 + 1.344 + /** 1.345 + * Create a content node for the given generated content style. 1.346 + * The caller takes care of making it SetIsNativeAnonymousRoot, binding it 1.347 + * to the document, and creating frames for it. 1.348 + * @param aParentContent is the node that has the before/after style 1.349 + * @param aStyleContext is the 'before' or 'after' pseudo-element 1.350 + * style context 1.351 + * @param aContentIndex is the index of the content item to create 1.352 + */ 1.353 + already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState, 1.354 + nsIContent* aParentContent, 1.355 + nsStyleContext* aStyleContext, 1.356 + uint32_t aContentIndex); 1.357 + 1.358 + // aFrame may be null; this method doesn't use it directly in any case. 1.359 + void CreateGeneratedContentItem(nsFrameConstructorState& aState, 1.360 + nsIFrame* aFrame, 1.361 + nsIContent* aContent, 1.362 + nsStyleContext* aStyleContext, 1.363 + nsCSSPseudoElements::Type aPseudoElement, 1.364 + FrameConstructionItemList& aItems); 1.365 + 1.366 + // This method can change aFrameList: it can chop off the beginning and put 1.367 + // it in aParentFrame while putting the remainder into a ib-split sibling of 1.368 + // aParentFrame. aPrevSibling must be the frame after which aFrameList is to 1.369 + // be placed on aParentFrame's principal child list. It may be null if 1.370 + // aFrameList is being added at the beginning of the child list. 1.371 + nsresult AppendFramesToParent(nsFrameConstructorState& aState, 1.372 + nsIFrame* aParentFrame, 1.373 + nsFrameItems& aFrameList, 1.374 + nsIFrame* aPrevSibling, 1.375 + bool aIsRecursiveCall = false); 1.376 + 1.377 + // BEGIN TABLE SECTION 1.378 + /** 1.379 + * Construct an outer table frame. This is the FrameConstructionData 1.380 + * callback used for the job. 1.381 + */ 1.382 + nsIFrame* ConstructTable(nsFrameConstructorState& aState, 1.383 + FrameConstructionItem& aItem, 1.384 + nsIFrame* aParentFrame, 1.385 + const nsStyleDisplay* aDisplay, 1.386 + nsFrameItems& aFrameItems); 1.387 + 1.388 + /** 1.389 + * FrameConstructionData callback for constructing table rows and row groups. 1.390 + */ 1.391 + nsIFrame* ConstructTableRowOrRowGroup(nsFrameConstructorState& aState, 1.392 + FrameConstructionItem& aItem, 1.393 + nsIFrame* aParentFrame, 1.394 + const nsStyleDisplay* aStyleDisplay, 1.395 + nsFrameItems& aFrameItems); 1.396 + 1.397 + /** 1.398 + * FrameConstructionData callback used for constructing table columns. 1.399 + */ 1.400 + nsIFrame* ConstructTableCol(nsFrameConstructorState& aState, 1.401 + FrameConstructionItem& aItem, 1.402 + nsIFrame* aParentFrame, 1.403 + const nsStyleDisplay* aStyleDisplay, 1.404 + nsFrameItems& aFrameItems); 1.405 + 1.406 + /** 1.407 + * FrameConstructionData callback used for constructing table cells. 1.408 + */ 1.409 + nsIFrame* ConstructTableCell(nsFrameConstructorState& aState, 1.410 + FrameConstructionItem& aItem, 1.411 + nsIFrame* aParentFrame, 1.412 + const nsStyleDisplay* aStyleDisplay, 1.413 + nsFrameItems& aFrameItems); 1.414 + 1.415 +private: 1.416 + /* An enum of possible parent types for anonymous table object construction */ 1.417 + enum ParentType { 1.418 + eTypeBlock = 0, /* This includes all non-table-related frames */ 1.419 + eTypeRow, 1.420 + eTypeRowGroup, 1.421 + eTypeColGroup, 1.422 + eTypeTable, 1.423 + eParentTypeCount 1.424 + }; 1.425 + 1.426 + /* 3 bits is enough to handle our ParentType values */ 1.427 +#define FCDATA_PARENT_TYPE_OFFSET 29 1.428 + /* Macro to get the desired parent type out of an mBits member of 1.429 + FrameConstructionData */ 1.430 +#define FCDATA_DESIRED_PARENT_TYPE(_bits) \ 1.431 + ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET) 1.432 + /* Macro to create FrameConstructionData bits out of a desired parent type */ 1.433 +#define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type) \ 1.434 + (((uint32_t)(_type)) << FCDATA_PARENT_TYPE_OFFSET) 1.435 + 1.436 + /* Get the parent type that aParentFrame has. */ 1.437 + static ParentType GetParentType(nsIFrame* aParentFrame) { 1.438 + return GetParentType(aParentFrame->GetType()); 1.439 + } 1.440 + 1.441 + /* Get the parent type for the given nsIFrame type atom */ 1.442 + static ParentType GetParentType(nsIAtom* aFrameType); 1.443 + 1.444 + /* A constructor function that just creates an nsIFrame object. The caller 1.445 + is responsible for initializing the object, adding it to frame lists, 1.446 + constructing frames for the children, etc. 1.447 + 1.448 + @param nsIPresShell the presshell whose arena should be used to allocate 1.449 + the frame. 1.450 + @param nsStyleContext the style context to use for the frame. */ 1.451 + typedef nsIFrame* (* FrameCreationFunc)(nsIPresShell*, nsStyleContext*); 1.452 + 1.453 + /* A function that can be used to get a FrameConstructionData. Such 1.454 + a function is allowed to return null. 1.455 + 1.456 + @param nsIContent the node for which the frame is being constructed. 1.457 + @param nsStyleContext the style context to be used for the frame. 1.458 + */ 1.459 + struct FrameConstructionData; 1.460 + typedef const FrameConstructionData* 1.461 + (* FrameConstructionDataGetter)(Element*, nsStyleContext*); 1.462 + 1.463 + /* A constructor function that's used for complicated construction tasks. 1.464 + This is expected to create the new frame, initialize it, add whatever 1.465 + needs to be added to aFrameItems (XXXbz is that really necessary? Could 1.466 + caller add? Might there be cases when the returned frame or its 1.467 + placeholder is not the thing that ends up in aFrameItems? If not, would 1.468 + it be safe to do the add into the frame construction state after 1.469 + processing kids? Look into this as a followup!), process children as 1.470 + needed, etc. It is NOT expected to deal with setting the frame on the 1.471 + content. 1.472 + 1.473 + @param aState the frame construction state to use. 1.474 + @param aItem the frame construction item to use 1.475 + @param aParentFrame the frame to set as the parent of the 1.476 + newly-constructed frame. 1.477 + @param aStyleDisplay the display struct from aItem's mStyleContext 1.478 + @param aFrameItems the frame list to add the new frame (or its 1.479 + placeholder) to. 1.480 + @return the frame that was constructed. This frame is what the caller 1.481 + will set as the frame on the content. Guaranteed non-null. 1.482 + */ 1.483 + typedef nsIFrame* 1.484 + (nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState, 1.485 + FrameConstructionItem& aItem, 1.486 + nsIFrame* aParentFrame, 1.487 + const nsStyleDisplay* aStyleDisplay, 1.488 + nsFrameItems& aFrameItems); 1.489 + 1.490 + /* Bits that modify the way a FrameConstructionData is handled */ 1.491 + 1.492 + /* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not 1.493 + be set as the primary frame on the content node. This should only be used 1.494 + in very rare cases when we create more than one frame for a given content 1.495 + node. */ 1.496 +#define FCDATA_SKIP_FRAMESET 0x1 1.497 + /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the 1.498 + FrameConstructionData is a getter function that can be used to get the 1.499 + actual FrameConstructionData to use. */ 1.500 +#define FCDATA_FUNC_IS_DATA_GETTER 0x2 1.501 + /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData 1.502 + has an mFullConstructor. In this case, there is no relevant mData or 1.503 + mFunc */ 1.504 +#define FCDATA_FUNC_IS_FULL_CTOR 0x4 1.505 + /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to 1.506 + float or be absolutely positioned. This can also be used with 1.507 + FCDATA_FUNC_IS_FULL_CTOR to indicate what the full-constructor 1.508 + function will do. */ 1.509 +#define FCDATA_DISALLOW_OUT_OF_FLOW 0x8 1.510 + /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a 1.511 + null absolute containing block before processing children for this 1.512 + frame. If this is not set, the frame will be pushed as the 1.513 + absolute containing block as needed, based on its style */ 1.514 +#define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10 1.515 + /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame 1.516 + will be wrapped in blocks. This is only usable for MathML at the 1.517 + moment. */ 1.518 +#define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20 1.519 + /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the 1.520 + content. If this bit is set, nothing else in the struct needs to be 1.521 + set. */ 1.522 +#define FCDATA_SUPPRESS_FRAME 0x40 1.523 + /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in 1.524 + a scrollframe if its overflow type so requires. */ 1.525 +#define FCDATA_MAY_NEED_SCROLLFRAME 0x80 1.526 +#ifdef MOZ_XUL 1.527 + /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame. These need 1.528 + some really weird special handling. */ 1.529 +#define FCDATA_IS_POPUP 0x100 1.530 +#endif /* MOZ_XUL */ 1.531 + /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an 1.532 + absolute containing block, no matter what its style says. */ 1.533 +#define FCDATA_SKIP_ABSPOS_PUSH 0x200 1.534 + /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated 1.535 + content when processing kids of this frame. This should not be used with 1.536 + FCDATA_FUNC_IS_FULL_CTOR */ 1.537 +#define FCDATA_DISALLOW_GENERATED_CONTENT 0x400 1.538 + /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of 1.539 + table-related thing and we should not attempt to fetch a table-cell parent 1.540 + for it if it's inside another table-related frame. */ 1.541 +#define FCDATA_IS_TABLE_PART 0x800 1.542 + /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS 1.543 + inline box. */ 1.544 +#define FCDATA_IS_INLINE 0x1000 1.545 + /* If FCDATA_IS_LINE_PARTICIPANT is set, the frame is something that will 1.546 + return true for IsFrameOfType(nsIFrame::eLineParticipant) */ 1.547 +#define FCDATA_IS_LINE_PARTICIPANT 0x2000 1.548 + /* If FCDATA_IS_LINE_BREAK is set, the frame is something that will 1.549 + induce a line break boundary before and after itself. */ 1.550 +#define FCDATA_IS_LINE_BREAK 0x4000 1.551 + /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing 1.552 + children. This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */ 1.553 +#define FCDATA_ALLOW_BLOCK_STYLES 0x8000 1.554 + /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant 1.555 + FrameConstructionItem instead of trying to process the content's children. 1.556 + This can be used with or without FCDATA_FUNC_IS_FULL_CTOR. 1.557 + The child items might still need table pseudo processing. */ 1.558 +#define FCDATA_USE_CHILD_ITEMS 0x10000 1.559 + /* If FCDATA_FORCED_NON_SCROLLABLE_BLOCK is set, then this block 1.560 + would have been scrollable but has been forced to be 1.561 + non-scrollable due to being in a paginated context. */ 1.562 +#define FCDATA_FORCED_NON_SCROLLABLE_BLOCK 0x20000 1.563 + /* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a 1.564 + block formatting context wrapper around the kids of this frame 1.565 + using the FrameConstructionData's mPseudoAtom for its anonymous 1.566 + box type. */ 1.567 +#define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000 1.568 + /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of 1.569 + an SVG text frame. */ 1.570 +#define FCDATA_IS_SVG_TEXT 0x80000 1.571 + 1.572 + /* Structure representing information about how a frame should be 1.573 + constructed. */ 1.574 + struct FrameConstructionData { 1.575 + // Flag bits that can modify the way the construction happens 1.576 + uint32_t mBits; 1.577 + // We have exactly one of three types of functions, so use a union for 1.578 + // better cache locality for the ones that aren't pointer-to-member. That 1.579 + // one needs to be separate, because we can't cast between it and the 1.580 + // others and hence wouldn't be able to initialize the union without a 1.581 + // constructor and all the resulting generated code. See documentation 1.582 + // above for FrameCreationFunc, FrameConstructionDataGetter, and 1.583 + // FrameFullConstructor to see what the functions would do. 1.584 + union Func { 1.585 + FrameCreationFunc mCreationFunc; 1.586 + FrameConstructionDataGetter mDataGetter; 1.587 + } mFunc; 1.588 + FrameFullConstructor mFullConstructor; 1.589 + // For cases when FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, the 1.590 + // anonymous box type to use for that wrapper. 1.591 + nsICSSAnonBoxPseudo * const * const mAnonBoxPseudo; 1.592 + }; 1.593 + 1.594 + /* Structure representing a mapping of an atom to a FrameConstructionData. 1.595 + This can be used with non-static atoms, assuming that the nsIAtom* is 1.596 + stored somewhere that this struct can point to (that is, a static 1.597 + nsIAtom*) and that it's allocated before the struct is ever used. */ 1.598 + struct FrameConstructionDataByTag { 1.599 + // Pointer to nsIAtom* is used because we want to initialize this 1.600 + // statically, so before our atom tables are set up. 1.601 + const nsIAtom * const * const mTag; 1.602 + const FrameConstructionData mData; 1.603 + }; 1.604 + 1.605 + /* Structure representing a mapping of an integer to a 1.606 + FrameConstructionData. There are no magic integer values here. */ 1.607 + struct FrameConstructionDataByInt { 1.608 + /* Could be used for display or whatever else */ 1.609 + const int32_t mInt; 1.610 + const FrameConstructionData mData; 1.611 + }; 1.612 + 1.613 + /* Structure that has a FrameConstructionData and style context pseudo-type 1.614 + for a table pseudo-frame */ 1.615 + struct PseudoParentData { 1.616 + const FrameConstructionData mFCData; 1.617 + nsICSSAnonBoxPseudo * const * const mPseudoType; 1.618 + }; 1.619 + /* Array of such structures that we use to properly construct table 1.620 + pseudo-frames as needed */ 1.621 + static const PseudoParentData sPseudoParentData[eParentTypeCount]; 1.622 + 1.623 + /* A function that takes an integer, content, style context, and array of 1.624 + FrameConstructionDataByInts and finds the appropriate frame construction 1.625 + data to use and returns it. This can return null if none of the integers 1.626 + match or if the matching integer has a FrameConstructionDataGetter that 1.627 + returns null. */ 1.628 + static const FrameConstructionData* 1.629 + FindDataByInt(int32_t aInt, Element* aElement, 1.630 + nsStyleContext* aStyleContext, 1.631 + const FrameConstructionDataByInt* aDataPtr, 1.632 + uint32_t aDataLength); 1.633 + 1.634 + /* A function that takes a tag, content, style context, and array of 1.635 + FrameConstructionDataByTags and finds the appropriate frame construction 1.636 + data to use and returns it. This can return null if none of the tags 1.637 + match or if the matching tag has a FrameConstructionDataGetter that 1.638 + returns null. */ 1.639 + static const FrameConstructionData* 1.640 + FindDataByTag(nsIAtom* aTag, Element* aElement, 1.641 + nsStyleContext* aStyleContext, 1.642 + const FrameConstructionDataByTag* aDataPtr, 1.643 + uint32_t aDataLength); 1.644 + 1.645 + /* A class representing a list of FrameConstructionItems */ 1.646 + class FrameConstructionItemList { 1.647 + public: 1.648 + FrameConstructionItemList() : 1.649 + mInlineCount(0), 1.650 + mBlockCount(0), 1.651 + mLineParticipantCount(0), 1.652 + mItemCount(0), 1.653 + mLineBoundaryAtStart(false), 1.654 + mLineBoundaryAtEnd(false), 1.655 + mParentHasNoXBLChildren(false), 1.656 + mTriedConstructingFrames(false) 1.657 + { 1.658 + PR_INIT_CLIST(&mItems); 1.659 + memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts)); 1.660 + } 1.661 + 1.662 + ~FrameConstructionItemList() { 1.663 + PRCList* cur = PR_NEXT_LINK(&mItems); 1.664 + while (cur != &mItems) { 1.665 + PRCList* next = PR_NEXT_LINK(cur); 1.666 + delete ToItem(cur); 1.667 + cur = next; 1.668 + } 1.669 + 1.670 + // Leaves our mItems pointing to deleted memory in both directions, 1.671 + // but that's OK at this point. 1.672 + 1.673 + // Create the undisplayed entries for our mUndisplayedItems, if any, but 1.674 + // only if we have tried constructing frames for this item list. If we 1.675 + // haven't, then we're just throwing it away and will probably try again. 1.676 + if (!mUndisplayedItems.IsEmpty() && mTriedConstructingFrames) { 1.677 + // We could store the frame manager in a member, but just 1.678 + // getting it off the style context is not too bad. 1.679 + nsFrameManager *mgr = 1.680 + mUndisplayedItems[0].mStyleContext->PresContext()->FrameManager(); 1.681 + for (uint32_t i = 0; i < mUndisplayedItems.Length(); ++i) { 1.682 + UndisplayedItem& item = mUndisplayedItems[i]; 1.683 + mgr->SetUndisplayedContent(item.mContent, item.mStyleContext); 1.684 + } 1.685 + } 1.686 + } 1.687 + 1.688 + void SetLineBoundaryAtStart(bool aBoundary) { mLineBoundaryAtStart = aBoundary; } 1.689 + void SetLineBoundaryAtEnd(bool aBoundary) { mLineBoundaryAtEnd = aBoundary; } 1.690 + void SetParentHasNoXBLChildren(bool aHasNoXBLChildren) { 1.691 + mParentHasNoXBLChildren = aHasNoXBLChildren; 1.692 + } 1.693 + void SetTriedConstructingFrames() { mTriedConstructingFrames = true; } 1.694 + bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; } 1.695 + bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; } 1.696 + bool ParentHasNoXBLChildren() { return mParentHasNoXBLChildren; } 1.697 + bool IsEmpty() const { return PR_CLIST_IS_EMPTY(&mItems); } 1.698 + bool AnyItemsNeedBlockParent() const { return mLineParticipantCount != 0; } 1.699 + bool AreAllItemsInline() const { return mInlineCount == mItemCount; } 1.700 + bool AreAllItemsBlock() const { return mBlockCount == mItemCount; } 1.701 + bool AllWantParentType(ParentType aDesiredParentType) const { 1.702 + return mDesiredParentCounts[aDesiredParentType] == mItemCount; 1.703 + } 1.704 + 1.705 + // aSuppressWhiteSpaceOptimizations is true if optimizations that 1.706 + // skip constructing whitespace frames for this item or items 1.707 + // around it cannot be performed. 1.708 + FrameConstructionItem* AppendItem(const FrameConstructionData* aFCData, 1.709 + nsIContent* aContent, 1.710 + nsIAtom* aTag, 1.711 + int32_t aNameSpaceID, 1.712 + PendingBinding* aPendingBinding, 1.713 + already_AddRefed<nsStyleContext>&& aStyleContext, 1.714 + bool aSuppressWhiteSpaceOptimizations, 1.715 + nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren) 1.716 + { 1.717 + FrameConstructionItem* item = 1.718 + new FrameConstructionItem(aFCData, aContent, aTag, aNameSpaceID, 1.719 + aPendingBinding, aStyleContext, 1.720 + aSuppressWhiteSpaceOptimizations, 1.721 + aAnonChildren); 1.722 + PR_APPEND_LINK(item, &mItems); 1.723 + ++mItemCount; 1.724 + ++mDesiredParentCounts[item->DesiredParentType()]; 1.725 + return item; 1.726 + } 1.727 + 1.728 + void AppendUndisplayedItem(nsIContent* aContent, 1.729 + nsStyleContext* aStyleContext) { 1.730 + mUndisplayedItems.AppendElement(UndisplayedItem(aContent, aStyleContext)); 1.731 + } 1.732 + 1.733 + void InlineItemAdded() { ++mInlineCount; } 1.734 + void BlockItemAdded() { ++mBlockCount; } 1.735 + void LineParticipantItemAdded() { ++mLineParticipantCount; } 1.736 + 1.737 + class Iterator; 1.738 + friend class Iterator; 1.739 + 1.740 + class Iterator { 1.741 + public: 1.742 + Iterator(FrameConstructionItemList& list) : 1.743 + mCurrent(PR_NEXT_LINK(&list.mItems)), 1.744 + mEnd(&list.mItems), 1.745 + mList(list) 1.746 + {} 1.747 + Iterator(const Iterator& aOther) : 1.748 + mCurrent(aOther.mCurrent), 1.749 + mEnd(aOther.mEnd), 1.750 + mList(aOther.mList) 1.751 + {} 1.752 + 1.753 + bool operator==(const Iterator& aOther) const { 1.754 + NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?"); 1.755 + return mCurrent == aOther.mCurrent; 1.756 + } 1.757 + bool operator!=(const Iterator& aOther) const { 1.758 + return !(*this == aOther); 1.759 + } 1.760 + Iterator& operator=(const Iterator& aOther) { 1.761 + NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?"); 1.762 + mCurrent = aOther.mCurrent; 1.763 + return *this; 1.764 + } 1.765 + 1.766 + FrameConstructionItemList* List() { 1.767 + return &mList; 1.768 + } 1.769 + 1.770 + operator FrameConstructionItem& () { 1.771 + return item(); 1.772 + } 1.773 + 1.774 + FrameConstructionItem& item() { 1.775 + return *FrameConstructionItemList::ToItem(mCurrent); 1.776 + } 1.777 + bool IsDone() const { return mCurrent == mEnd; } 1.778 + bool AtStart() const { return mCurrent == PR_NEXT_LINK(mEnd); } 1.779 + void Next() { 1.780 + NS_ASSERTION(!IsDone(), "Should have checked IsDone()!"); 1.781 + mCurrent = PR_NEXT_LINK(mCurrent); 1.782 + } 1.783 + void Prev() { 1.784 + NS_ASSERTION(!AtStart(), "Should have checked AtStart()!"); 1.785 + mCurrent = PR_PREV_LINK(mCurrent); 1.786 + } 1.787 + void SetToEnd() { mCurrent = mEnd; } 1.788 + 1.789 + // Skip over all items that want a parent type different from the given 1.790 + // one. Return whether the iterator is done after doing that. The 1.791 + // iterator must not be done when this is called. 1.792 + inline bool SkipItemsWantingParentType(ParentType aParentType); 1.793 + 1.794 + // Skip over non-replaced inline frames and positioned frames. 1.795 + // Return whether the iterator is done after doing that. 1.796 + // The iterator must not be done when this is called. 1.797 + inline bool SkipItemsThatNeedAnonFlexItem( 1.798 + const nsFrameConstructorState& aState); 1.799 + 1.800 + // Skip to the first frame that is a non-replaced inline or is 1.801 + // positioned. Return whether the iterator is done after doing that. 1.802 + // The iterator must not be done when this is called. 1.803 + inline bool SkipItemsThatDontNeedAnonFlexItem( 1.804 + const nsFrameConstructorState& aState); 1.805 + 1.806 + // Skip over whitespace. Return whether the iterator is done after doing 1.807 + // that. The iterator must not be done, and must be pointing to a 1.808 + // whitespace item when this is called. 1.809 + inline bool SkipWhitespace(nsFrameConstructorState& aState); 1.810 + 1.811 + // Remove the item pointed to by this iterator from its current list and 1.812 + // Append it to aTargetList. This iterator is advanced to point to the 1.813 + // next item in its list. aIter must not be done. aOther must not be 1.814 + // the list this iterator is iterating over.. 1.815 + void AppendItemToList(FrameConstructionItemList& aTargetList); 1.816 + 1.817 + // As above, but moves all items starting with this iterator until we 1.818 + // get to aEnd; the item pointed to by aEnd is not stolen. This method 1.819 + // might have optimizations over just looping and doing StealItem for 1.820 + // some special cases. After this method returns, this iterator will 1.821 + // point to the item aEnd points to now; aEnd is not modified. 1.822 + // aTargetList must not be the list this iterator is iterating over. 1.823 + void AppendItemsToList(const Iterator& aEnd, 1.824 + FrameConstructionItemList& aTargetList); 1.825 + 1.826 + // Insert aItem in this iterator's list right before the item pointed to 1.827 + // by this iterator. After the insertion, this iterator will continue to 1.828 + // point to the item it now points to (the one just after the 1.829 + // newly-inserted item). This iterator is allowed to be done; in that 1.830 + // case this call just appends the given item to the list. 1.831 + void InsertItem(FrameConstructionItem* aItem); 1.832 + 1.833 + // Delete the items between this iterator and aEnd, including the item 1.834 + // this iterator currently points to but not including the item pointed 1.835 + // to by aEnd. When this returns, this iterator will point to the same 1.836 + // item as aEnd. This iterator must not equal aEnd when this method is 1.837 + // called. 1.838 + void DeleteItemsTo(const Iterator& aEnd); 1.839 + 1.840 + private: 1.841 + PRCList* mCurrent; 1.842 + PRCList* mEnd; 1.843 + FrameConstructionItemList& mList; 1.844 + }; 1.845 + 1.846 + private: 1.847 + static FrameConstructionItem* ToItem(PRCList* item) { 1.848 + return static_cast<FrameConstructionItem*>(item); 1.849 + } 1.850 + 1.851 + struct UndisplayedItem { 1.852 + UndisplayedItem(nsIContent* aContent, nsStyleContext* aStyleContext) : 1.853 + mContent(aContent), mStyleContext(aStyleContext) 1.854 + {} 1.855 + 1.856 + nsIContent * const mContent; 1.857 + nsRefPtr<nsStyleContext> mStyleContext; 1.858 + }; 1.859 + 1.860 + // Adjust our various counts for aItem being added or removed. aDelta 1.861 + // should be either +1 or -1 depending on which is happening. 1.862 + void AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta); 1.863 + 1.864 + PRCList mItems; 1.865 + uint32_t mInlineCount; 1.866 + uint32_t mBlockCount; 1.867 + uint32_t mLineParticipantCount; 1.868 + uint32_t mItemCount; 1.869 + uint32_t mDesiredParentCounts[eParentTypeCount]; 1.870 + // True if there is guaranteed to be a line boundary before the 1.871 + // frames created by these items 1.872 + bool mLineBoundaryAtStart; 1.873 + // True if there is guaranteed to be a line boundary after the 1.874 + // frames created by these items 1.875 + bool mLineBoundaryAtEnd; 1.876 + // True if the parent is guaranteed to have no XBL anonymous children 1.877 + bool mParentHasNoXBLChildren; 1.878 + // True if we have tried constructing frames from this list 1.879 + bool mTriedConstructingFrames; 1.880 + 1.881 + nsTArray<UndisplayedItem> mUndisplayedItems; 1.882 + }; 1.883 + 1.884 + typedef FrameConstructionItemList::Iterator FCItemIterator; 1.885 + 1.886 + /* A struct representing an item for which frames might need to be 1.887 + * constructed. This contains all the information needed to construct the 1.888 + * frame other than the parent frame and whatever would be stored in the 1.889 + * frame constructor state. */ 1.890 + struct FrameConstructionItem : public PRCList { 1.891 + // No need to PR_INIT_CLIST in the constructor because the only 1.892 + // place that creates us immediately appends us. 1.893 + FrameConstructionItem(const FrameConstructionData* aFCData, 1.894 + nsIContent* aContent, 1.895 + nsIAtom* aTag, 1.896 + int32_t aNameSpaceID, 1.897 + PendingBinding* aPendingBinding, 1.898 + already_AddRefed<nsStyleContext>& aStyleContext, 1.899 + bool aSuppressWhiteSpaceOptimizations, 1.900 + nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren) : 1.901 + mFCData(aFCData), mContent(aContent), mTag(aTag), 1.902 + mNameSpaceID(aNameSpaceID), 1.903 + mPendingBinding(aPendingBinding), mStyleContext(aStyleContext), 1.904 + mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations), 1.905 + mIsText(false), mIsGeneratedContent(false), 1.906 + mIsAnonymousContentCreatorContent(false), 1.907 + mIsRootPopupgroup(false), mIsAllInline(false), mIsBlock(false), 1.908 + mHasInlineEnds(false), mIsPopup(false), 1.909 + mIsLineParticipant(false), mIsForSVGAElement(false) 1.910 + { 1.911 + if (aAnonChildren) { 1.912 + NS_ASSERTION(!(mFCData->mBits & FCDATA_FUNC_IS_FULL_CTOR) || 1.913 + mFCData->mFullConstructor == 1.914 + &nsCSSFrameConstructor::ConstructInline, 1.915 + "This is going to fail"); 1.916 + NS_ASSERTION(!(mFCData->mBits & FCDATA_USE_CHILD_ITEMS), 1.917 + "nsIAnonymousContentCreator::CreateAnonymousContent " 1.918 + "implementations should not output a list where the " 1.919 + "items have children in this case"); 1.920 + mAnonChildren.SwapElements(*aAnonChildren); 1.921 + } 1.922 + } 1.923 + ~FrameConstructionItem() { 1.924 + if (mIsGeneratedContent) { 1.925 + mContent->UnbindFromTree(); 1.926 + NS_RELEASE(mContent); 1.927 + } 1.928 + } 1.929 + 1.930 + ParentType DesiredParentType() { 1.931 + return FCDATA_DESIRED_PARENT_TYPE(mFCData->mBits); 1.932 + } 1.933 + 1.934 + // Indicates whether (when in a flexbox container) this item needs to be 1.935 + // wrapped in an anonymous block. 1.936 + bool NeedsAnonFlexItem(const nsFrameConstructorState& aState); 1.937 + 1.938 + // Don't call this unless the frametree really depends on the answer! 1.939 + // Especially so for generated content, where we don't want to reframe 1.940 + // things. 1.941 + bool IsWhitespace(nsFrameConstructorState& aState) const; 1.942 + 1.943 + bool IsLineBoundary() const { 1.944 + return mIsBlock || (mFCData->mBits & FCDATA_IS_LINE_BREAK); 1.945 + } 1.946 + 1.947 + // The FrameConstructionData to use. 1.948 + const FrameConstructionData* mFCData; 1.949 + // The nsIContent node to use when initializing the new frame. 1.950 + nsIContent* mContent; 1.951 + // The XBL-resolved tag name to use for frame construction. 1.952 + nsIAtom* mTag; 1.953 + // The XBL-resolved namespace to use for frame construction. 1.954 + int32_t mNameSpaceID; 1.955 + // The PendingBinding for this frame construction item, if any. May be 1.956 + // null. We maintain a list of PendingBindings in the frame construction 1.957 + // state in the order in which AddToAttachedQueue should be called on them: 1.958 + // depth-first, post-order traversal order. Since we actually traverse the 1.959 + // DOM in a mix of breadth-first and depth-first, it is the responsibility 1.960 + // of whoever constructs FrameConstructionItem kids of a given 1.961 + // FrameConstructionItem to push its mPendingBinding as the current 1.962 + // insertion point before doing so and pop it afterward. 1.963 + PendingBinding* mPendingBinding; 1.964 + // The style context to use for creating the new frame. 1.965 + nsRefPtr<nsStyleContext> mStyleContext; 1.966 + // Whether optimizations to skip constructing textframes around 1.967 + // this content need to be suppressed. 1.968 + bool mSuppressWhiteSpaceOptimizations; 1.969 + // Whether this is a text content item. 1.970 + bool mIsText; 1.971 + // Whether this is a generated content container. 1.972 + // If it is, mContent is a strong pointer. 1.973 + bool mIsGeneratedContent; 1.974 + // Whether this is an item for nsIAnonymousContentCreator content. 1.975 + bool mIsAnonymousContentCreatorContent; 1.976 + // Whether this is an item for the root popupgroup. 1.977 + bool mIsRootPopupgroup; 1.978 + // Whether construction from this item will create only frames that are 1.979 + // IsInlineOutside() in the principal child list. This is not precise, but 1.980 + // conservative: if true the frames will really be inline, whereas if false 1.981 + // they might still all be inline. 1.982 + bool mIsAllInline; 1.983 + // Whether construction from this item will create only frames that are 1.984 + // IsBlockOutside() in the principal child list. This is not precise, but 1.985 + // conservative: if true the frames will really be blocks, whereas if false 1.986 + // they might still be blocks (and in particular, out-of-flows that didn't 1.987 + // find a containing block). 1.988 + bool mIsBlock; 1.989 + // Whether construction from this item will give leading and trailing 1.990 + // inline frames. This is equal to mIsAllInline, except for inline frame 1.991 + // items, where it's always true, whereas mIsAllInline might be false due 1.992 + // to {ib} splits. 1.993 + bool mHasInlineEnds; 1.994 + // Whether construction from this item will create a popup that needs to 1.995 + // go into the global popup items. 1.996 + bool mIsPopup; 1.997 + // Whether this item should be treated as a line participant 1.998 + bool mIsLineParticipant; 1.999 + // Whether this item is for an SVG <a> element 1.1000 + bool mIsForSVGAElement; 1.1001 + 1.1002 + // Child frame construction items. 1.1003 + FrameConstructionItemList mChildItems; 1.1004 + 1.1005 + // ContentInfo list for children that have yet to have 1.1006 + // FrameConstructionItem objects created for them. This exists because 1.1007 + // AddFrameConstructionItemsInternal needs a valid frame, but in the case 1.1008 + // that nsIAnonymousContentCreator::CreateAnonymousContent returns items 1.1009 + // that have their own children (so we have a tree of ContentInfo objects 1.1010 + // rather than a flat list) we don't yet have a frame to provide to 1.1011 + // AddFrameConstructionItemsInternal in order to create the items for the 1.1012 + // grandchildren. That prevents FrameConstructionItems from being created 1.1013 + // for these grandchildren (and any descendants that they may have), 1.1014 + // otherwise they could have been added to the mChildItems member of their 1.1015 + // parent FrameConstructionItem. As it is, the grandchildren ContentInfo 1.1016 + // list has to be stored in this mAnonChildren member in order to delay 1.1017 + // construction of the FrameConstructionItems for the grandchildren until 1.1018 + // a frame has been created for their parent item. 1.1019 + nsTArray<nsIAnonymousContentCreator::ContentInfo> mAnonChildren; 1.1020 + 1.1021 + private: 1.1022 + FrameConstructionItem(const FrameConstructionItem& aOther) MOZ_DELETE; /* not implemented */ 1.1023 + }; 1.1024 + 1.1025 + /** 1.1026 + * Function to create the anonymous flex items that we need. 1.1027 + * If aParentFrame is not a nsFlexContainerFrame then this method is a NOP. 1.1028 + * @param aItems the child frame construction items before pseudo creation 1.1029 + * @param aParentFrame the parent frame 1.1030 + */ 1.1031 + void CreateNeededAnonFlexItems(nsFrameConstructorState& aState, 1.1032 + FrameConstructionItemList& aItems, 1.1033 + nsIFrame* aParentFrame); 1.1034 + 1.1035 + /** 1.1036 + * Function to create the table pseudo items we need. 1.1037 + * @param aItems the child frame construction items before pseudo creation 1.1038 + * @param aParentFrame the parent frame we're creating pseudos for 1.1039 + */ 1.1040 + inline void CreateNeededTablePseudos(nsFrameConstructorState& aState, 1.1041 + FrameConstructionItemList& aItems, 1.1042 + nsIFrame* aParentFrame); 1.1043 + 1.1044 + /** 1.1045 + * Function to adjust aParentFrame to deal with captions. 1.1046 + * @param aParentFrame the frame we think should be the parent. This will be 1.1047 + * adjusted to point to the right parent frame. 1.1048 + * @param aFCData the FrameConstructionData that would be used for frame 1.1049 + * construction. 1.1050 + * @param aStyleContext the style context for aChildContent 1.1051 + */ 1.1052 + // XXXbz this function should really go away once we rework pseudo-frame 1.1053 + // handling to be better. This should simply be part of the job of 1.1054 + // GetGeometricParent, and stuff like the frameitems and parent frame should 1.1055 + // be kept track of in the state... 1.1056 + void AdjustParentFrame(nsIFrame* & aParentFrame, 1.1057 + const FrameConstructionData* aFCData, 1.1058 + nsStyleContext* aStyleContext); 1.1059 + 1.1060 + // END TABLE SECTION 1.1061 + 1.1062 +protected: 1.1063 + static nsIFrame* CreatePlaceholderFrameFor(nsIPresShell* aPresShell, 1.1064 + nsIContent* aContent, 1.1065 + nsIFrame* aFrame, 1.1066 + nsStyleContext* aStyleContext, 1.1067 + nsIFrame* aParentFrame, 1.1068 + nsIFrame* aPrevInFlow, 1.1069 + nsFrameState aTypeBit); 1.1070 + 1.1071 +private: 1.1072 + // ConstructSelectFrame puts the new frame in aFrameItems and 1.1073 + // handles the kids of the select. 1.1074 + nsIFrame* ConstructSelectFrame(nsFrameConstructorState& aState, 1.1075 + FrameConstructionItem& aItem, 1.1076 + nsIFrame* aParentFrame, 1.1077 + const nsStyleDisplay* aStyleDisplay, 1.1078 + nsFrameItems& aFrameItems); 1.1079 + 1.1080 + // ConstructFieldSetFrame puts the new frame in aFrameItems and 1.1081 + // handles the kids of the fieldset 1.1082 + nsIFrame* ConstructFieldSetFrame(nsFrameConstructorState& aState, 1.1083 + FrameConstructionItem& aItem, 1.1084 + nsIFrame* aParentFrame, 1.1085 + const nsStyleDisplay* aStyleDisplay, 1.1086 + nsFrameItems& aFrameItems); 1.1087 + 1.1088 + // aParentFrame might be null. If it is, that means it was an 1.1089 + // inline frame. 1.1090 + static const FrameConstructionData* FindTextData(nsIFrame* aParentFrame); 1.1091 + 1.1092 + void ConstructTextFrame(const FrameConstructionData* aData, 1.1093 + nsFrameConstructorState& aState, 1.1094 + nsIContent* aContent, 1.1095 + nsIFrame* aParentFrame, 1.1096 + nsStyleContext* aStyleContext, 1.1097 + nsFrameItems& aFrameItems); 1.1098 + 1.1099 + // If aPossibleTextContent is a text node and doesn't have a frame, append a 1.1100 + // frame construction item for it to aItems. 1.1101 + void AddTextItemIfNeeded(nsFrameConstructorState& aState, 1.1102 + nsIFrame* aParentFrame, 1.1103 + nsIContent* aPossibleTextContent, 1.1104 + FrameConstructionItemList& aItems); 1.1105 + 1.1106 + // If aParentContent's child aContent is a text node and 1.1107 + // doesn't have a frame, try to create a frame for it. 1.1108 + void ReframeTextIfNeeded(nsIContent* aParentContent, 1.1109 + nsIContent* aContent); 1.1110 + 1.1111 + void AddPageBreakItem(nsIContent* aContent, 1.1112 + nsStyleContext* aMainStyleContext, 1.1113 + FrameConstructionItemList& aItems); 1.1114 + 1.1115 + // Function to find FrameConstructionData for aElement. Will return 1.1116 + // null if aElement is not HTML. 1.1117 + // aParentFrame might be null. If it is, that means it was an 1.1118 + // inline frame. 1.1119 + static const FrameConstructionData* FindHTMLData(Element* aContent, 1.1120 + nsIAtom* aTag, 1.1121 + int32_t aNameSpaceID, 1.1122 + nsIFrame* aParentFrame, 1.1123 + nsStyleContext* aStyleContext); 1.1124 + // HTML data-finding helper functions 1.1125 + static const FrameConstructionData* 1.1126 + FindImgData(Element* aElement, nsStyleContext* aStyleContext); 1.1127 + static const FrameConstructionData* 1.1128 + FindImgControlData(Element* aElement, nsStyleContext* aStyleContext); 1.1129 + static const FrameConstructionData* 1.1130 + FindInputData(Element* aElement, nsStyleContext* aStyleContext); 1.1131 + static const FrameConstructionData* 1.1132 + FindObjectData(Element* aElement, nsStyleContext* aStyleContext); 1.1133 + static const FrameConstructionData* 1.1134 + FindCanvasData(Element* aElement, nsStyleContext* aStyleContext); 1.1135 + 1.1136 + /* Construct a frame from the given FrameConstructionItem. This function 1.1137 + will handle adding the frame to frame lists, processing children, setting 1.1138 + the frame as the primary frame for the item's content, and so forth. 1.1139 + 1.1140 + @param aItem the FrameConstructionItem to use. 1.1141 + @param aState the frame construction state to use. 1.1142 + @param aParentFrame the frame to set as the parent of the 1.1143 + newly-constructed frame. 1.1144 + @param aFrameItems the frame list to add the new frame (or its 1.1145 + placeholder) to. 1.1146 + */ 1.1147 + void ConstructFrameFromItemInternal(FrameConstructionItem& aItem, 1.1148 + nsFrameConstructorState& aState, 1.1149 + nsIFrame* aParentFrame, 1.1150 + nsFrameItems& aFrameItems); 1.1151 + 1.1152 + // possible flags for AddFrameConstructionItemInternal's aFlags argument 1.1153 + /* Allow xbl:base to affect the tag/namespace used. */ 1.1154 +#define ITEM_ALLOW_XBL_BASE 0x1 1.1155 + /* Allow page-break before and after items to be created if the 1.1156 + style asks for them. */ 1.1157 +#define ITEM_ALLOW_PAGE_BREAK 0x2 1.1158 + /* The item is a generated content item. */ 1.1159 +#define ITEM_IS_GENERATED_CONTENT 0x4 1.1160 + /* The item is within an SVG text block frame. */ 1.1161 +#define ITEM_IS_WITHIN_SVG_TEXT 0x8 1.1162 + /* The item allows items to be created for SVG <textPath> children. */ 1.1163 +#define ITEM_ALLOWS_TEXT_PATH_CHILD 0x10 1.1164 + /* The item is content created by an nsIAnonymousContentCreator frame */ 1.1165 +#define ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT 0x20 1.1166 + // The guts of AddFrameConstructionItems 1.1167 + // aParentFrame might be null. If it is, that means it was an 1.1168 + // inline frame. 1.1169 + void AddFrameConstructionItemsInternal(nsFrameConstructorState& aState, 1.1170 + nsIContent* aContent, 1.1171 + nsIFrame* aParentFrame, 1.1172 + nsIAtom* aTag, 1.1173 + int32_t aNameSpaceID, 1.1174 + bool aSuppressWhiteSpaceOptimizations, 1.1175 + nsStyleContext* aStyleContext, 1.1176 + uint32_t aFlags, 1.1177 + nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren, 1.1178 + FrameConstructionItemList& aItems); 1.1179 + 1.1180 + /** 1.1181 + * Construct frames for the given item list and parent frame, and put the 1.1182 + * resulting frames in aFrameItems. 1.1183 + */ 1.1184 + void ConstructFramesFromItemList(nsFrameConstructorState& aState, 1.1185 + FrameConstructionItemList& aItems, 1.1186 + nsIFrame* aParentFrame, 1.1187 + nsFrameItems& aFrameItems); 1.1188 + void ConstructFramesFromItem(nsFrameConstructorState& aState, 1.1189 + FCItemIterator& aItem, 1.1190 + nsIFrame* aParentFrame, 1.1191 + nsFrameItems& aFrameItems); 1.1192 + static bool AtLineBoundary(FCItemIterator& aIter); 1.1193 + 1.1194 + nsresult CreateAnonymousFrames(nsFrameConstructorState& aState, 1.1195 + nsIContent* aParent, 1.1196 + nsIFrame* aParentFrame, 1.1197 + PendingBinding * aPendingBinding, 1.1198 + nsFrameItems& aChildItems); 1.1199 + 1.1200 + nsresult GetAnonymousContent(nsIContent* aParent, 1.1201 + nsIFrame* aParentFrame, 1.1202 + nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonContent); 1.1203 + 1.1204 +//MathML Mod - RBS 1.1205 + /** 1.1206 + * Takes the frames in aBlockItems and wraps them in a new anonymous block 1.1207 + * frame whose content is aContent and whose parent will be aParentFrame. 1.1208 + * The anonymous block is added to aNewItems and aBlockItems is cleared. 1.1209 + */ 1.1210 + void FlushAccumulatedBlock(nsFrameConstructorState& aState, 1.1211 + nsIContent* aContent, 1.1212 + nsIFrame* aParentFrame, 1.1213 + nsFrameItems& aBlockItems, 1.1214 + nsFrameItems& aNewItems); 1.1215 + 1.1216 + // Function to find FrameConstructionData for aContent. Will return 1.1217 + // null if aContent is not MathML. 1.1218 + static const FrameConstructionData* FindMathMLData(Element* aElement, 1.1219 + nsIAtom* aTag, 1.1220 + int32_t aNameSpaceID, 1.1221 + nsStyleContext* aStyleContext); 1.1222 + 1.1223 + // Function to find FrameConstructionData for aContent. Will return 1.1224 + // null if aContent is not XUL. 1.1225 + static const FrameConstructionData* FindXULTagData(Element* aElement, 1.1226 + nsIAtom* aTag, 1.1227 + int32_t aNameSpaceID, 1.1228 + nsStyleContext* aStyleContext); 1.1229 + // XUL data-finding helper functions and structures 1.1230 +#ifdef MOZ_XUL 1.1231 + static const FrameConstructionData* 1.1232 + FindPopupGroupData(Element* aElement, nsStyleContext* aStyleContext); 1.1233 + // sXULTextBoxData used for both labels and descriptions 1.1234 + static const FrameConstructionData sXULTextBoxData; 1.1235 + static const FrameConstructionData* 1.1236 + FindXULLabelData(Element* aElement, nsStyleContext* aStyleContext); 1.1237 + static const FrameConstructionData* 1.1238 + FindXULDescriptionData(Element* aElement, nsStyleContext* aStyleContext); 1.1239 +#ifdef XP_MACOSX 1.1240 + static const FrameConstructionData* 1.1241 + FindXULMenubarData(Element* aElement, nsStyleContext* aStyleContext); 1.1242 +#endif /* XP_MACOSX */ 1.1243 + static const FrameConstructionData* 1.1244 + FindXULListBoxBodyData(Element* aElement, nsStyleContext* aStyleContext); 1.1245 + static const FrameConstructionData* 1.1246 + FindXULListItemData(Element* aElement, nsStyleContext* aStyleContext); 1.1247 +#endif /* MOZ_XUL */ 1.1248 + 1.1249 + // Function to find FrameConstructionData for aContent using one of the XUL 1.1250 + // display types. Will return null if aDisplay doesn't have a XUL display 1.1251 + // type. This function performs no other checks, so should only be called if 1.1252 + // we know for sure that the content is not something that should get a frame 1.1253 + // constructed by tag. 1.1254 + static const FrameConstructionData* 1.1255 + FindXULDisplayData(const nsStyleDisplay* aDisplay, 1.1256 + Element* aElement, 1.1257 + nsStyleContext* aStyleContext); 1.1258 + 1.1259 + /** 1.1260 + * Constructs an outer frame, an anonymous child that wraps its real 1.1261 + * children, and its descendant frames. This is used by both ConstructOuterSVG 1.1262 + * and ConstructMarker, which both want an anonymous block child for their 1.1263 + * children to go in to. 1.1264 + */ 1.1265 + nsIFrame* ConstructFrameWithAnonymousChild( 1.1266 + nsFrameConstructorState& aState, 1.1267 + FrameConstructionItem& aItem, 1.1268 + nsIFrame* aParentFrame, 1.1269 + const nsStyleDisplay* aDisplay, 1.1270 + nsFrameItems& aFrameItems, 1.1271 + FrameCreationFunc aConstructor, 1.1272 + FrameCreationFunc aInnerConstructor, 1.1273 + nsICSSAnonBoxPseudo* aInnerPseudo, 1.1274 + bool aCandidateRootFrame); 1.1275 + 1.1276 + /** 1.1277 + * Construct an nsSVGOuterSVGFrame. 1.1278 + */ 1.1279 + nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState, 1.1280 + FrameConstructionItem& aItem, 1.1281 + nsIFrame* aParentFrame, 1.1282 + const nsStyleDisplay* aDisplay, 1.1283 + nsFrameItems& aFrameItems); 1.1284 + 1.1285 + /** 1.1286 + * Construct an nsSVGMarkerFrame. 1.1287 + */ 1.1288 + nsIFrame* ConstructMarker(nsFrameConstructorState& aState, 1.1289 + FrameConstructionItem& aItem, 1.1290 + nsIFrame* aParentFrame, 1.1291 + const nsStyleDisplay* aDisplay, 1.1292 + nsFrameItems& aFrameItems); 1.1293 + 1.1294 + static const FrameConstructionData* FindSVGData(Element* aElement, 1.1295 + nsIAtom* aTag, 1.1296 + int32_t aNameSpaceID, 1.1297 + nsIFrame* aParentFrame, 1.1298 + bool aIsWithinSVGText, 1.1299 + bool aAllowsTextPathChild, 1.1300 + nsStyleContext* aStyleContext); 1.1301 + 1.1302 + /* Not static because it does PropagateScrollToViewport. If this 1.1303 + changes, make this static */ 1.1304 + const FrameConstructionData* 1.1305 + FindDisplayData(const nsStyleDisplay* aDisplay, Element* aElement, 1.1306 + nsIFrame* aParentFrame, nsStyleContext* aStyleContext); 1.1307 + 1.1308 + /** 1.1309 + * Construct a scrollable block frame 1.1310 + */ 1.1311 + nsIFrame* ConstructScrollableBlock(nsFrameConstructorState& aState, 1.1312 + FrameConstructionItem& aItem, 1.1313 + nsIFrame* aParentFrame, 1.1314 + const nsStyleDisplay* aDisplay, 1.1315 + nsFrameItems& aFrameItems); 1.1316 + 1.1317 + /** 1.1318 + * Construct a non-scrollable block frame 1.1319 + */ 1.1320 + nsIFrame* ConstructNonScrollableBlock(nsFrameConstructorState& aState, 1.1321 + FrameConstructionItem& aItem, 1.1322 + nsIFrame* aParentFrame, 1.1323 + const nsStyleDisplay* aDisplay, 1.1324 + nsFrameItems& aFrameItems); 1.1325 + 1.1326 + /** 1.1327 + * This adds FrameConstructionItem objects to aItemsToConstruct for the 1.1328 + * anonymous content returned by an nsIAnonymousContentCreator:: 1.1329 + * CreateAnonymousContent implementation. 1.1330 + */ 1.1331 + void AddFCItemsForAnonymousContent( 1.1332 + nsFrameConstructorState& aState, 1.1333 + nsIFrame* aFrame, 1.1334 + nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems, 1.1335 + FrameConstructionItemList& aItemsToConstruct, 1.1336 + uint32_t aExtraFlags = 0); 1.1337 + 1.1338 + /** 1.1339 + * Construct the frames for the children of aContent. "children" is defined 1.1340 + * as "whatever FlattenedChildIterator returns for aContent". This means we're 1.1341 + * basically operating on children in the "flattened tree" per sXBL/XBL2. 1.1342 + * This method will also handle constructing ::before, ::after, 1.1343 + * ::first-letter, and ::first-line frames, as needed and if allowed. 1.1344 + * 1.1345 + * If the parent is a float containing block, this method will handle pushing 1.1346 + * it as the float containing block in aState (so there's no need for callers 1.1347 + * to push it themselves). 1.1348 + * 1.1349 + * @param aState the frame construction state 1.1350 + * @param aContent the content node whose children need frames 1.1351 + * @param aStyleContext the style context for aContent 1.1352 + * @param aFrame the frame to use as the parent frame for the new in-flow 1.1353 + * kids. Note that this must be its own content insertion frame, but 1.1354 + * need not be be the primary frame for aContent. This frame will be 1.1355 + * pushed as the float containing block, as needed. aFrame is also 1.1356 + * used to find the parent style context for the kids' style contexts 1.1357 + * (not necessary aFrame's style context). 1.1358 + * @param aCanHaveGeneratedContent Whether to allow :before and 1.1359 + * :after styles on the parent. 1.1360 + * @param aFrameItems the list in which we should place the in-flow children 1.1361 + * @param aAllowBlockStyles Whether to allow first-letter and first-line 1.1362 + * styles on the parent. 1.1363 + * @param aPendingBinding Make sure to push this into aState before doing any 1.1364 + * child item construction. 1.1365 + * @param aPossiblyLeafFrame if non-null, this should be used for the isLeaf 1.1366 + * test and the anonymous content creation. If null, aFrame will be 1.1367 + * used. 1.1368 + */ 1.1369 + void ProcessChildren(nsFrameConstructorState& aState, 1.1370 + nsIContent* aContent, 1.1371 + nsStyleContext* aStyleContext, 1.1372 + nsIFrame* aFrame, 1.1373 + const bool aCanHaveGeneratedContent, 1.1374 + nsFrameItems& aFrameItems, 1.1375 + const bool aAllowBlockStyles, 1.1376 + PendingBinding* aPendingBinding, 1.1377 + nsIFrame* aPossiblyLeafFrame = nullptr); 1.1378 + 1.1379 + nsIFrame* GetFrameFor(nsIContent* aContent); 1.1380 + 1.1381 + /** 1.1382 + * These two functions are used when we start frame creation from a non-root 1.1383 + * element. They should recreate the same state that we would have 1.1384 + * arrived at if we had built frames from the root frame to aFrame. 1.1385 + * Therefore, any calls to PushFloatContainingBlock and 1.1386 + * PushAbsoluteContainingBlock during frame construction should get 1.1387 + * corresponding logic in these functions. 1.1388 + */ 1.1389 +public: 1.1390 + enum ContainingBlockType { 1.1391 + ABS_POS, 1.1392 + FIXED_POS 1.1393 + }; 1.1394 + nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame, ContainingBlockType aType); 1.1395 + nsIFrame* GetFloatContainingBlock(nsIFrame* aFrame); 1.1396 + 1.1397 +private: 1.1398 + nsIContent* PropagateScrollToViewport(); 1.1399 + 1.1400 + // Build a scroll frame: 1.1401 + // Calls BeginBuildingScrollFrame, InitAndRestoreFrame, and then FinishBuildingScrollFrame. 1.1402 + // @param aNewFrame the created scrollframe --- output only 1.1403 + // @param aParentFrame the geometric parent that the scrollframe will have. 1.1404 + nsresult 1.1405 + BuildScrollFrame(nsFrameConstructorState& aState, 1.1406 + nsIContent* aContent, 1.1407 + nsStyleContext* aContentStyle, 1.1408 + nsIFrame* aScrolledFrame, 1.1409 + nsIFrame* aParentFrame, 1.1410 + nsIFrame*& aNewFrame); 1.1411 + 1.1412 + // Builds the initial ScrollFrame 1.1413 + already_AddRefed<nsStyleContext> 1.1414 + BeginBuildingScrollFrame(nsFrameConstructorState& aState, 1.1415 + nsIContent* aContent, 1.1416 + nsStyleContext* aContentStyle, 1.1417 + nsIFrame* aParentFrame, 1.1418 + nsIAtom* aScrolledPseudo, 1.1419 + bool aIsRoot, 1.1420 + nsIFrame*& aNewFrame); 1.1421 + 1.1422 + // Completes the building of the scrollframe: 1.1423 + // Creates a view for the scrolledframe and makes it the child of the scrollframe. 1.1424 + void 1.1425 + FinishBuildingScrollFrame(nsIFrame* aScrollFrame, 1.1426 + nsIFrame* aScrolledFrame); 1.1427 + 1.1428 + // InitializeSelectFrame puts scrollFrame in aFrameItems if aBuildCombobox is false 1.1429 + // aBuildCombobox indicates if we are building a combobox that has a dropdown 1.1430 + // popup widget or not. 1.1431 + nsresult 1.1432 + InitializeSelectFrame(nsFrameConstructorState& aState, 1.1433 + nsIFrame* scrollFrame, 1.1434 + nsIFrame* scrolledFrame, 1.1435 + nsIContent* aContent, 1.1436 + nsIFrame* aParentFrame, 1.1437 + nsStyleContext* aStyleContext, 1.1438 + bool aBuildCombobox, 1.1439 + PendingBinding* aPendingBinding, 1.1440 + nsFrameItems& aFrameItems); 1.1441 + 1.1442 + nsresult MaybeRecreateFramesForElement(Element* aElement); 1.1443 + 1.1444 + // If aAsyncInsert is true then a restyle event will be posted to handle the 1.1445 + // required ContentInserted call instead of doing it immediately. 1.1446 + nsresult RecreateFramesForContent(nsIContent* aContent, bool aAsyncInsert); 1.1447 + 1.1448 + // If removal of aFrame from the frame tree requires reconstruction of some 1.1449 + // containing block (either of aFrame or of its parent) due to {ib} splits or 1.1450 + // table pseudo-frames, recreate the relevant frame subtree. The return value 1.1451 + // indicates whether this happened. If this method returns true, *aResult is 1.1452 + // the return value of ReframeContainingBlock or RecreateFramesForContent. If 1.1453 + // this method returns false, the value of *aResult is not affected. aFrame 1.1454 + // and aResult must not be null. aFrame must be the result of a 1.1455 + // GetPrimaryFrame() call on a content node (which means its parent is also 1.1456 + // not null). 1.1457 + bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, 1.1458 + nsresult* aResult); 1.1459 + 1.1460 + nsIFrame* CreateContinuingOuterTableFrame(nsIPresShell* aPresShell, 1.1461 + nsPresContext* aPresContext, 1.1462 + nsIFrame* aFrame, 1.1463 + nsIFrame* aParentFrame, 1.1464 + nsIContent* aContent, 1.1465 + nsStyleContext* aStyleContext); 1.1466 + 1.1467 + nsIFrame* CreateContinuingTableFrame(nsIPresShell* aPresShell, 1.1468 + nsPresContext* aPresContext, 1.1469 + nsIFrame* aFrame, 1.1470 + nsIFrame* aParentFrame, 1.1471 + nsIContent* aContent, 1.1472 + nsStyleContext* aStyleContext); 1.1473 + 1.1474 + //---------------------------------------- 1.1475 + 1.1476 + // Methods support creating block frames and their children 1.1477 + 1.1478 + already_AddRefed<nsStyleContext> 1.1479 + GetFirstLetterStyle(nsIContent* aContent, 1.1480 + nsStyleContext* aStyleContext); 1.1481 + 1.1482 + already_AddRefed<nsStyleContext> 1.1483 + GetFirstLineStyle(nsIContent* aContent, 1.1484 + nsStyleContext* aStyleContext); 1.1485 + 1.1486 + bool ShouldHaveFirstLetterStyle(nsIContent* aContent, 1.1487 + nsStyleContext* aStyleContext); 1.1488 + 1.1489 + // Check whether a given block has first-letter style. Make sure to 1.1490 + // only pass in blocks! And don't pass in null either. 1.1491 + bool HasFirstLetterStyle(nsIFrame* aBlockFrame); 1.1492 + 1.1493 + bool ShouldHaveFirstLineStyle(nsIContent* aContent, 1.1494 + nsStyleContext* aStyleContext); 1.1495 + 1.1496 + void ShouldHaveSpecialBlockStyle(nsIContent* aContent, 1.1497 + nsStyleContext* aStyleContext, 1.1498 + bool* aHaveFirstLetterStyle, 1.1499 + bool* aHaveFirstLineStyle); 1.1500 + 1.1501 + // |aContentParentFrame| should be null if it's really the same as 1.1502 + // |aParentFrame|. 1.1503 + // @param aFrameItems where we want to put the block in case it's in-flow. 1.1504 + // @param aNewFrame an in/out parameter. On input it is the block to be 1.1505 + // constructed. On output it is reset to the outermost 1.1506 + // frame constructed (e.g. if we need to wrap the block in an 1.1507 + // nsColumnSetFrame. 1.1508 + // @param aParentFrame is the desired parent for the (possibly wrapped) 1.1509 + // block 1.1510 + // @param aContentParent is the parent the block would have if it 1.1511 + // were in-flow 1.1512 + // @param aPositionedFrameForAbsPosContainer if non-null, then the new 1.1513 + // block should be an abs-pos container and aPositionedFrameForAbsPosContainer 1.1514 + // is the frame whose style is making this block an abs-pos container. 1.1515 + // @param aPendingBinding the pending binding from this block's frame 1.1516 + // construction item. 1.1517 + void ConstructBlock(nsFrameConstructorState& aState, 1.1518 + const nsStyleDisplay* aDisplay, 1.1519 + nsIContent* aContent, 1.1520 + nsIFrame* aParentFrame, 1.1521 + nsIFrame* aContentParentFrame, 1.1522 + nsStyleContext* aStyleContext, 1.1523 + nsIFrame** aNewFrame, 1.1524 + nsFrameItems& aFrameItems, 1.1525 + nsIFrame* aPositionedFrameForAbsPosContainer, 1.1526 + PendingBinding* aPendingBinding); 1.1527 + 1.1528 + nsIFrame* ConstructInline(nsFrameConstructorState& aState, 1.1529 + FrameConstructionItem& aItem, 1.1530 + nsIFrame* aParentFrame, 1.1531 + const nsStyleDisplay* aDisplay, 1.1532 + nsFrameItems& aFrameItems); 1.1533 + 1.1534 + /** 1.1535 + * Create any additional {ib} siblings needed to contain aChildItems and put 1.1536 + * them in aSiblings. 1.1537 + * 1.1538 + * @param aState the frame constructor state 1.1539 + * @param aInitialInline is an already-existing inline frame that will be 1.1540 + * part of this {ib} split and come before everything 1.1541 + * in aSiblings. 1.1542 + * @param aIsPositioned true if aInitialInline is positioned. 1.1543 + * @param aChildItems is a child list starting with a block; this method 1.1544 + * assumes that the inline has already taken all the 1.1545 + * children it wants. When the method returns aChildItems 1.1546 + * will be empty. 1.1547 + * @param aSiblings the nsFrameItems to put the newly-created siblings into. 1.1548 + * 1.1549 + * This method is responsible for making any SetFrameIsIBSplit calls that are 1.1550 + * needed. 1.1551 + */ 1.1552 + void CreateIBSiblings(nsFrameConstructorState& aState, 1.1553 + nsIFrame* aInitialInline, 1.1554 + bool aIsPositioned, 1.1555 + nsFrameItems& aChildItems, 1.1556 + nsFrameItems& aSiblings); 1.1557 + 1.1558 + /** 1.1559 + * For an inline aParentItem, construct its list of child 1.1560 + * FrameConstructionItems and set its mIsAllInline flag appropriately. 1.1561 + */ 1.1562 + void BuildInlineChildItems(nsFrameConstructorState& aState, 1.1563 + FrameConstructionItem& aParentItem, 1.1564 + bool aItemIsWithinSVGText, 1.1565 + bool aItemAllowsTextPathChild); 1.1566 + 1.1567 + // Determine whether we need to wipe out what we just did and start over 1.1568 + // because we're doing something like adding block kids to an inline frame 1.1569 + // (and therefore need an {ib} split). aPrevSibling must be correct, even in 1.1570 + // aIsAppend cases. Passing aIsAppend false even when an append is happening 1.1571 + // is ok in terms of correctness, but can lead to unnecessary reframing. If 1.1572 + // aIsAppend is true, then the caller MUST call 1.1573 + // nsCSSFrameConstructor::AppendFrames (as opposed to 1.1574 + // nsFrameManager::InsertFrames directly) to add the new frames. 1.1575 + // @return true if we reconstructed the containing block, false 1.1576 + // otherwise 1.1577 + bool WipeContainingBlock(nsFrameConstructorState& aState, 1.1578 + nsIFrame* aContainingBlock, 1.1579 + nsIFrame* aFrame, 1.1580 + FrameConstructionItemList& aItems, 1.1581 + bool aIsAppend, 1.1582 + nsIFrame* aPrevSibling); 1.1583 + 1.1584 + nsresult ReframeContainingBlock(nsIFrame* aFrame); 1.1585 + 1.1586 + //---------------------------------------- 1.1587 + 1.1588 + // Methods support :first-letter style 1.1589 + 1.1590 + void CreateFloatingLetterFrame(nsFrameConstructorState& aState, 1.1591 + nsIFrame* aBlockFrame, 1.1592 + nsIContent* aTextContent, 1.1593 + nsIFrame* aTextFrame, 1.1594 + nsIContent* aBlockContent, 1.1595 + nsIFrame* aParentFrame, 1.1596 + nsStyleContext* aStyleContext, 1.1597 + nsFrameItems& aResult); 1.1598 + 1.1599 + void CreateLetterFrame(nsIFrame* aBlockFrame, 1.1600 + nsIFrame* aBlockContinuation, 1.1601 + nsIContent* aTextContent, 1.1602 + nsIFrame* aParentFrame, 1.1603 + nsFrameItems& aResult); 1.1604 + 1.1605 + void WrapFramesInFirstLetterFrame(nsIContent* aBlockContent, 1.1606 + nsIFrame* aBlockFrame, 1.1607 + nsFrameItems& aBlockFrames); 1.1608 + 1.1609 + /** 1.1610 + * Looks in the block aBlockFrame for a text frame that contains the 1.1611 + * first-letter of the block and creates the necessary first-letter frames 1.1612 + * and returns them in aLetterFrames. 1.1613 + * 1.1614 + * @param aBlockFrame the (first-continuation of) the block we are creating a 1.1615 + * first-letter frame for 1.1616 + * @param aBlockContinuation the current continuation of the block that we 1.1617 + * are looking in for a textframe with suitable 1.1618 + * contents for first-letter 1.1619 + * @param aParentFrame the current frame whose children we are looking at for 1.1620 + * a suitable first-letter textframe 1.1621 + * @param aParentFrameList the first child of aParentFrame 1.1622 + * @param aModifiedParent returns the parent of the textframe that contains 1.1623 + * the first-letter 1.1624 + * @param aTextFrame returns the textframe that had the first-letter 1.1625 + * @param aPrevFrame returns the previous sibling of aTextFrame 1.1626 + * @param aLetterFrames returns the frames that were created 1.1627 + * @param aStopLooking returns whether we should stop looking for a 1.1628 + * first-letter either because it was found or won't be 1.1629 + * found 1.1630 + */ 1.1631 + void WrapFramesInFirstLetterFrame(nsIFrame* aBlockFrame, 1.1632 + nsIFrame* aBlockContinuation, 1.1633 + nsIFrame* aParentFrame, 1.1634 + nsIFrame* aParentFrameList, 1.1635 + nsIFrame** aModifiedParent, 1.1636 + nsIFrame** aTextFrame, 1.1637 + nsIFrame** aPrevFrame, 1.1638 + nsFrameItems& aLetterFrames, 1.1639 + bool* aStopLooking); 1.1640 + 1.1641 + void RecoverLetterFrames(nsIFrame* aBlockFrame); 1.1642 + 1.1643 + // 1.1644 + nsresult RemoveLetterFrames(nsPresContext* aPresContext, 1.1645 + nsIPresShell* aPresShell, 1.1646 + nsIFrame* aBlockFrame); 1.1647 + 1.1648 + // Recursive helper for RemoveLetterFrames 1.1649 + nsresult RemoveFirstLetterFrames(nsPresContext* aPresContext, 1.1650 + nsIPresShell* aPresShell, 1.1651 + nsIFrame* aFrame, 1.1652 + nsIFrame* aBlockFrame, 1.1653 + bool* aStopLooking); 1.1654 + 1.1655 + // Special remove method for those pesky floating first-letter frames 1.1656 + nsresult RemoveFloatingFirstLetterFrames(nsPresContext* aPresContext, 1.1657 + nsIPresShell* aPresShell, 1.1658 + nsIFrame* aBlockFrame, 1.1659 + bool* aStopLooking); 1.1660 + 1.1661 + // Capture state for the frame tree rooted at the frame associated with the 1.1662 + // content object, aContent 1.1663 + void CaptureStateForFramesOf(nsIContent* aContent, 1.1664 + nsILayoutHistoryState* aHistoryState); 1.1665 + 1.1666 + //---------------------------------------- 1.1667 + 1.1668 + // Methods support :first-line style 1.1669 + 1.1670 + // This method chops the initial inline-outside frames out of aFrameItems. 1.1671 + // If aLineFrame is non-null, it appends them to that frame. Otherwise, it 1.1672 + // creates a new line frame, sets the inline frames as its initial child 1.1673 + // list, and inserts that line frame at the front of what's left of 1.1674 + // aFrameItems. In both cases, the kids are reparented to the line frame. 1.1675 + // After this call, aFrameItems holds the frames that need to become kids of 1.1676 + // the block (possibly including line frames). 1.1677 + void WrapFramesInFirstLineFrame(nsFrameConstructorState& aState, 1.1678 + nsIContent* aBlockContent, 1.1679 + nsIFrame* aBlockFrame, 1.1680 + nsIFrame* aLineFrame, 1.1681 + nsFrameItems& aFrameItems); 1.1682 + 1.1683 + // Handle the case when a block with first-line style is appended to (by 1.1684 + // possibly calling WrapFramesInFirstLineFrame as needed). 1.1685 + void AppendFirstLineFrames(nsFrameConstructorState& aState, 1.1686 + nsIContent* aContent, 1.1687 + nsIFrame* aBlockFrame, 1.1688 + nsFrameItems& aFrameItems); 1.1689 + 1.1690 + nsresult InsertFirstLineFrames(nsFrameConstructorState& aState, 1.1691 + nsIContent* aContent, 1.1692 + nsIFrame* aBlockFrame, 1.1693 + nsIFrame** aParentFrame, 1.1694 + nsIFrame* aPrevSibling, 1.1695 + nsFrameItems& aFrameItems); 1.1696 + 1.1697 + // Find the right frame to use for aContent when looking for sibling 1.1698 + // frames for aTargetContent. If aPrevSibling is true, this 1.1699 + // will look for last continuations, etc, as necessary. This calls 1.1700 + // IsValidSibling as needed; if that returns false it returns null. 1.1701 + // 1.1702 + // @param aTargetContentDisplay the CSS display enum for aTargetContent if 1.1703 + // already known, UNSET_DISPLAY otherwise. It will be filled in if needed. 1.1704 + nsIFrame* FindFrameForContentSibling(nsIContent* aContent, 1.1705 + nsIContent* aTargetContent, 1.1706 + uint8_t& aTargetContentDisplay, 1.1707 + bool aPrevSibling); 1.1708 + 1.1709 + // Find the ``rightmost'' frame for the content immediately preceding the one 1.1710 + // aIter points to, following continuations if necessary. aIter is passed by 1.1711 + // value on purpose, so as not to modify the caller's iterator. 1.1712 + nsIFrame* FindPreviousSibling(mozilla::dom::FlattenedChildIterator aIter, 1.1713 + uint8_t& aTargetContentDisplay); 1.1714 + 1.1715 + // Find the frame for the content node immediately following the one aIter 1.1716 + // points to, following continuations if necessary. aIter is passed by value 1.1717 + // on purpose, so as not to modify the caller's iterator. 1.1718 + nsIFrame* FindNextSibling(mozilla::dom::FlattenedChildIterator aIter, 1.1719 + uint8_t& aTargetContentDisplay); 1.1720 + 1.1721 + // Find the right previous sibling for an insertion. This also updates the 1.1722 + // parent frame to point to the correct continuation of the parent frame to 1.1723 + // use, and returns whether this insertion is to be treated as an append. 1.1724 + // aChild is the child being inserted. 1.1725 + // aIsRangeInsertSafe returns whether it is safe to do a range insert with 1.1726 + // aChild being the first child in the range. It is the callers' 1.1727 + // responsibility to check whether a range insert is safe with regards to 1.1728 + // fieldsets. 1.1729 + // The skip parameters are used to ignore a range of children when looking 1.1730 + // for a sibling. All nodes starting from aStartSkipChild and up to but not 1.1731 + // including aEndSkipChild will be skipped over when looking for sibling 1.1732 + // frames. Skipping a range can deal with XBL but not when there are multiple 1.1733 + // insertion points. 1.1734 + nsIFrame* GetInsertionPrevSibling(nsIFrame*& aParentFrame, /* inout */ 1.1735 + nsIContent* aContainer, 1.1736 + nsIContent* aChild, 1.1737 + bool* aIsAppend, 1.1738 + bool* aIsRangeInsertSafe, 1.1739 + nsIContent* aStartSkipChild = nullptr, 1.1740 + nsIContent *aEndSkipChild = nullptr); 1.1741 + 1.1742 + // see if aContent and aSibling are legitimate siblings due to restrictions 1.1743 + // imposed by table columns 1.1744 + // XXXbz this code is generally wrong, since the frame for aContent 1.1745 + // may be constructed based on tag, not based on aDisplay! 1.1746 + bool IsValidSibling(nsIFrame* aSibling, 1.1747 + nsIContent* aContent, 1.1748 + uint8_t& aDisplay); 1.1749 + 1.1750 + void QuotesDirty() { 1.1751 + NS_PRECONDITION(mUpdateCount != 0, "Instant quote updates are bad news"); 1.1752 + mQuotesDirty = true; 1.1753 + mDocument->SetNeedLayoutFlush(); 1.1754 + } 1.1755 + 1.1756 + void CountersDirty() { 1.1757 + NS_PRECONDITION(mUpdateCount != 0, "Instant counter updates are bad news"); 1.1758 + mCountersDirty = true; 1.1759 + mDocument->SetNeedLayoutFlush(); 1.1760 + } 1.1761 + 1.1762 + /** 1.1763 + * Add the pair (aContent, aStyleContext) to the undisplayed items 1.1764 + * in aList as needed. This method enforces the invariant that all 1.1765 + * style contexts in the undisplayed content map must be non-pseudo 1.1766 + * contexts and also handles unbinding undisplayed generated content 1.1767 + * as needed. 1.1768 + */ 1.1769 + static void SetAsUndisplayedContent(FrameConstructionItemList& aList, 1.1770 + nsIContent* aContent, 1.1771 + nsStyleContext* aStyleContext, 1.1772 + bool aIsGeneratedContent); 1.1773 + 1.1774 +public: 1.1775 + 1.1776 + friend class nsFrameConstructorState; 1.1777 + 1.1778 +private: 1.1779 + 1.1780 + nsIDocument* mDocument; // Weak ref 1.1781 + 1.1782 + // See the comment at the start of ConstructRootFrame for more details 1.1783 + // about the following frames. 1.1784 + 1.1785 + // This is just the outermost frame for the root element. 1.1786 + nsIFrame* mRootElementFrame; 1.1787 + // This is the frame for the root element that has no pseudo-element style. 1.1788 + nsIFrame* mRootElementStyleFrame; 1.1789 + // This is the containing block for fixed-pos frames --- the 1.1790 + // viewport or page frame 1.1791 + nsIFrame* mFixedContainingBlock; 1.1792 + // This is the containing block that contains the root element --- 1.1793 + // the real "initial containing block" according to CSS 2.1. 1.1794 + nsIFrame* mDocElementContainingBlock; 1.1795 + nsIFrame* mGfxScrollFrame; 1.1796 + nsIFrame* mPageSequenceFrame; 1.1797 + nsQuoteList mQuoteList; 1.1798 + nsCounterManager mCounterManager; 1.1799 + // Current ProcessChildren depth. 1.1800 + uint16_t mCurrentDepth; 1.1801 + uint16_t mUpdateCount; 1.1802 + bool mQuotesDirty : 1; 1.1803 + bool mCountersDirty : 1; 1.1804 + bool mIsDestroyingFrameTree : 1; 1.1805 + // This is true if mDocElementContainingBlock supports absolute positioning 1.1806 + bool mHasRootAbsPosContainingBlock : 1; 1.1807 + bool mAlwaysCreateFramesForIgnorableWhitespace : 1; 1.1808 + 1.1809 + nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState; 1.1810 +}; 1.1811 + 1.1812 +#endif /* nsCSSFrameConstructor_h___ */