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