/src/mozilla-central/layout/generic/nsBlockFrame.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | /* |
8 | | * rendering object for CSS display:block, inline-block, and list-item |
9 | | * boxes, also used for various anonymous boxes |
10 | | */ |
11 | | |
12 | | #ifndef nsBlockFrame_h___ |
13 | | #define nsBlockFrame_h___ |
14 | | |
15 | | #include "nsContainerFrame.h" |
16 | | #include "nsHTMLParts.h" |
17 | | #include "nsLineBox.h" |
18 | | #include "nsCSSPseudoElements.h" |
19 | | #include "nsFloatManager.h" |
20 | | |
21 | | enum class LineReflowStatus { |
22 | | // The line was completely reflowed and fit in available width, and we should |
23 | | // try to pull up content from the next line if possible. |
24 | | OK, |
25 | | // The line was completely reflowed and fit in available width, but we should |
26 | | // not try to pull up content from the next line. |
27 | | Stop, |
28 | | // We need to reflow the line again at its current vertical position. The |
29 | | // new reflow should not try to pull up any frames from the next line. |
30 | | RedoNoPull, |
31 | | // We need to reflow the line again using the floats from its height |
32 | | // this reflow, since its height made it hit floats that were not |
33 | | // adjacent to its top. |
34 | | RedoMoreFloats, |
35 | | // We need to reflow the line again at a lower vertical postion where there |
36 | | // may be more horizontal space due to different float configuration. |
37 | | RedoNextBand, |
38 | | // The line did not fit in the available vertical space. Try pushing it to |
39 | | // the next page or column if it's not the first line on the current page/column. |
40 | | Truncated |
41 | | }; |
42 | | |
43 | | class nsBlockInFlowLineIterator; |
44 | | class nsBulletFrame; |
45 | | namespace mozilla { |
46 | | class BlockReflowInput; |
47 | | class ServoRestyleState; |
48 | | class ServoStyleSet; |
49 | | } // namespace mozilla |
50 | | |
51 | | /** |
52 | | * Some invariants: |
53 | | * -- The overflow out-of-flows list contains the out-of- |
54 | | * flow frames whose placeholders are in the overflow list. |
55 | | * -- A given piece of content has at most one placeholder |
56 | | * frame in a block's normal child list. |
57 | | * -- While a block is being reflowed, and from then until |
58 | | * its next-in-flow is reflowed it may have a |
59 | | * PushedFloatProperty frame property that points to |
60 | | * an nsFrameList. This list contains continuations for |
61 | | * floats whose prev-in-flow is in the block's regular float |
62 | | * list and first-in-flows of floats that did not fit, but |
63 | | * whose placeholders are in the block or one of its |
64 | | * prev-in-flows. |
65 | | * -- In all these frame lists, if there are two frames for |
66 | | * the same content appearing in the list, then the frames |
67 | | * appear with the prev-in-flow before the next-in-flow. |
68 | | * -- While reflowing a block, its overflow line list |
69 | | * will usually be empty but in some cases will have lines |
70 | | * (while we reflow the block at its shrink-wrap width). |
71 | | * In this case any new overflowing content must be |
72 | | * prepended to the overflow lines. |
73 | | */ |
74 | | |
75 | | /* |
76 | | * Base class for block and inline frames. |
77 | | * The block frame has an additional child list, kAbsoluteList, which |
78 | | * contains the absolutely positioned frames. |
79 | | */ |
80 | | class nsBlockFrame : public nsContainerFrame |
81 | | { |
82 | | using BlockReflowInput = mozilla::BlockReflowInput; |
83 | | |
84 | | public: |
85 | | NS_DECL_FRAMEARENA_HELPERS(nsBlockFrame) |
86 | | |
87 | | typedef nsLineList::iterator LineIterator; |
88 | | typedef nsLineList::const_iterator ConstLineIterator; |
89 | | typedef nsLineList::reverse_iterator ReverseLineIterator; |
90 | | typedef nsLineList::const_reverse_iterator ConstReverseLineIterator; |
91 | | |
92 | 0 | LineIterator LinesBegin() { return mLines.begin(); } |
93 | 0 | LineIterator LinesEnd() { return mLines.end(); } |
94 | 0 | ConstLineIterator LinesBegin() const { return mLines.begin(); } |
95 | 0 | ConstLineIterator LinesEnd() const { return mLines.end(); } |
96 | 0 | ReverseLineIterator LinesRBegin() { return mLines.rbegin(); } |
97 | 0 | ReverseLineIterator LinesREnd() { return mLines.rend(); } |
98 | 0 | ConstReverseLineIterator LinesRBegin() const { return mLines.rbegin(); } |
99 | 0 | ConstReverseLineIterator LinesREnd() const { return mLines.rend(); } |
100 | 0 | LineIterator LinesBeginFrom(nsLineBox* aList) { return mLines.begin(aList); } |
101 | 0 | ReverseLineIterator LinesRBeginFrom(nsLineBox* aList) { return mLines.rbegin(aList); } |
102 | | |
103 | | friend nsBlockFrame* NS_NewBlockFrame(nsIPresShell* aPresShell, |
104 | | ComputedStyle* aStyle); |
105 | | |
106 | | // nsQueryFrame |
107 | | NS_DECL_QUERYFRAME |
108 | | |
109 | | // nsIFrame |
110 | | void Init(nsIContent* aContent, |
111 | | nsContainerFrame* aParent, |
112 | | nsIFrame* aPrevInFlow) override; |
113 | | void SetInitialChildList(ChildListID aListID, |
114 | | nsFrameList& aChildList) override; |
115 | | void AppendFrames(ChildListID aListID, |
116 | | nsFrameList& aFrameList) override; |
117 | | void InsertFrames(ChildListID aListID, |
118 | | nsIFrame* aPrevFrame, |
119 | | nsFrameList& aFrameList) override; |
120 | | void RemoveFrame(ChildListID aListID, |
121 | | nsIFrame* aOldFrame) override; |
122 | | const nsFrameList& GetChildList(ChildListID aListID) const override; |
123 | | void GetChildLists(nsTArray<ChildList>* aLists) const override; |
124 | | nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const override; |
125 | | bool GetVerticalAlignBaseline(mozilla::WritingMode aWM, |
126 | | nscoord* aBaseline) const override |
127 | 0 | { |
128 | 0 | nscoord lastBaseline; |
129 | 0 | if (GetNaturalBaselineBOffset(aWM, BaselineSharingGroup::eLast, &lastBaseline)) { |
130 | 0 | *aBaseline = BSize() - lastBaseline; |
131 | 0 | return true; |
132 | 0 | } |
133 | 0 | return false; |
134 | 0 | } |
135 | | bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM, |
136 | | BaselineSharingGroup aBaselineGroup, |
137 | | nscoord* aBaseline) const override; |
138 | | nscoord GetCaretBaseline() const override; |
139 | | void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override; |
140 | | nsSplittableType GetSplittableType() const override; |
141 | | bool IsFloatContainingBlock() const override; |
142 | | void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
143 | | const nsDisplayListSet& aLists) override; |
144 | | bool IsFrameOfType(uint32_t aFlags) const override |
145 | 0 | { |
146 | 0 | return nsContainerFrame::IsFrameOfType(aFlags & |
147 | 0 | ~(nsIFrame::eCanContainOverflowContainers | |
148 | 0 | nsIFrame::eBlockFrame)); |
149 | 0 | } |
150 | | |
151 | | void InvalidateFrame(uint32_t aDisplayItemKey = 0, bool aRebuildDisplayItems = true) override; |
152 | | void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0, bool aRebuildDisplayItems = true) override; |
153 | | |
154 | | #ifdef DEBUG_FRAME_DUMP |
155 | | void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const override; |
156 | | nsresult GetFrameName(nsAString& aResult) const override; |
157 | | #endif |
158 | | |
159 | | #ifdef DEBUG |
160 | | const char* LineReflowStatusToString(LineReflowStatus aLineReflowStatus) const; |
161 | | #endif |
162 | | |
163 | | #ifdef ACCESSIBILITY |
164 | | mozilla::a11y::AccType AccessibleType() override; |
165 | | #endif |
166 | | |
167 | | // Line cursor methods to speed up line searching in which one query |
168 | | // result is expected to be close to the next in general. This is |
169 | | // mainly for searching line(s) containing a point. It is also used |
170 | | // as a cache for local computation. Use AutoLineCursorSetup for the |
171 | | // latter case so that it wouldn't interact unexpectedly with the |
172 | | // former. The basic idea for the former is that we set the cursor |
173 | | // property if the lines' overflowArea.VisualOverflow().ys and |
174 | | // overflowArea.VisualOverflow().yMosts are non-decreasing |
175 | | // (considering only non-empty overflowArea.VisualOverflow()s; empty |
176 | | // overflowArea.VisualOverflow()s never participate in event handling |
177 | | // or painting), and the block has sufficient number of lines. The |
178 | | // cursor property points to a "recently used" line. If we get a |
179 | | // series of requests that work on lines |
180 | | // "near" the cursor, then we can find those nearby lines quickly by |
181 | | // starting our search at the cursor. |
182 | | |
183 | | // Clear out line cursor because we're disturbing the lines (i.e., Reflow) |
184 | | void ClearLineCursor(); |
185 | | // Get the first line that might contain y-coord 'y', or nullptr if you must search |
186 | | // all lines. If nonnull is returned then we guarantee that the lines' |
187 | | // combinedArea.ys and combinedArea.yMosts are non-decreasing. |
188 | | // The actual line returned might not contain 'y', but if not, it is guaranteed |
189 | | // to be before any line which does contain 'y'. |
190 | | nsLineBox* GetFirstLineContaining(nscoord y); |
191 | | // Set the line cursor to our first line. Only call this if you |
192 | | // guarantee that either the lines' combinedArea.ys and combinedArea. |
193 | | // yMosts are non-decreasing, or the line cursor is cleared before |
194 | | // building the display list of this frame. |
195 | | void SetupLineCursor(); |
196 | | |
197 | | /** |
198 | | * Helper RAII class for automatically set and clear line cursor for |
199 | | * temporary use. If the frame already has line cursor, this would be |
200 | | * a no-op. |
201 | | */ |
202 | | class MOZ_STACK_CLASS AutoLineCursorSetup |
203 | | { |
204 | | public: |
205 | | explicit AutoLineCursorSetup(nsBlockFrame* aFrame) |
206 | | : mFrame(aFrame) |
207 | | , mOrigCursor(aFrame->GetLineCursor()) |
208 | 0 | { |
209 | 0 | if (!mOrigCursor) { |
210 | 0 | mFrame->SetupLineCursor(); |
211 | 0 | } |
212 | 0 | } |
213 | | ~AutoLineCursorSetup() |
214 | 0 | { |
215 | 0 | if (mOrigCursor) { |
216 | 0 | mFrame->SetProperty(LineCursorProperty(), mOrigCursor); |
217 | 0 | } else { |
218 | 0 | mFrame->ClearLineCursor(); |
219 | 0 | } |
220 | 0 | } |
221 | | |
222 | | private: |
223 | | nsBlockFrame* mFrame; |
224 | | nsLineBox* mOrigCursor; |
225 | | }; |
226 | | |
227 | | void ChildIsDirty(nsIFrame* aChild) override; |
228 | | bool IsVisibleInSelection(mozilla::dom::Selection* aSelection) override; |
229 | | |
230 | | bool IsEmpty() override; |
231 | | bool CachedIsEmpty() override; |
232 | | bool IsSelfEmpty() override; |
233 | | |
234 | | // Given that we have a bullet, does it actually draw something, i.e., |
235 | | // do we have either a 'list-style-type' or 'list-style-image' that is |
236 | | // not 'none'? |
237 | | bool BulletIsEmpty() const; |
238 | | |
239 | | /** |
240 | | * Return the bullet text equivalent. |
241 | | */ |
242 | | void GetSpokenBulletText(nsAString& aText) const; |
243 | | |
244 | | /** |
245 | | * Return true if there's a bullet. |
246 | | */ |
247 | 0 | bool HasBullet() const { |
248 | 0 | return HasOutsideBullet() || HasInsideBullet(); |
249 | 0 | } |
250 | | |
251 | | /** |
252 | | * @return true if this frame has an inside bullet frame. |
253 | | */ |
254 | 0 | bool HasInsideBullet() const { |
255 | 0 | return 0 != (mState & NS_BLOCK_FRAME_HAS_INSIDE_BULLET); |
256 | 0 | } |
257 | | |
258 | | /** |
259 | | * @return true if this frame has an outside bullet frame. |
260 | | */ |
261 | 0 | bool HasOutsideBullet() const { |
262 | 0 | return 0 != (mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET); |
263 | 0 | } |
264 | | |
265 | | /** |
266 | | * @return the bullet frame or nullptr if we don't have one. |
267 | | */ |
268 | 0 | nsBulletFrame* GetBullet() const { |
269 | 0 | nsBulletFrame* outside = GetOutsideBullet(); |
270 | 0 | return outside ? outside : GetInsideBullet(); |
271 | 0 | } |
272 | | |
273 | | /** |
274 | | * @return the first-letter frame or nullptr if we don't have one. |
275 | | */ |
276 | | nsIFrame* GetFirstLetter() const; |
277 | | |
278 | | /** |
279 | | * @return the ::first-line frame or nullptr if we don't have one. |
280 | | */ |
281 | | nsIFrame* GetFirstLineFrame() const; |
282 | | |
283 | | void MarkIntrinsicISizesDirty() override; |
284 | | private: |
285 | | void CheckIntrinsicCacheAgainstShrinkWrapState(); |
286 | | public: |
287 | | nscoord GetMinISize(gfxContext *aRenderingContext) override; |
288 | | nscoord GetPrefISize(gfxContext *aRenderingContext) override; |
289 | | |
290 | | nsRect ComputeTightBounds(DrawTarget* aDrawTarget) const override; |
291 | | |
292 | | nsresult GetPrefWidthTightBounds(gfxContext* aContext, |
293 | | nscoord* aX, |
294 | | nscoord* aXMost) override; |
295 | | |
296 | | /** |
297 | | * Compute the final block size of this frame. |
298 | | * |
299 | | * @param aReflowInput Data structure passed from parent during reflow. |
300 | | * @param aReflowStatus A pointer to the reflow status for when we're finished |
301 | | * doing reflow. this will get set appropriately if the block-size |
302 | | * causes us to exceed the current available (page) block-size. |
303 | | * @param aContentBSize The block-size of content, precomputed outside of this |
304 | | * function. The final block-size that is used in aMetrics will be set |
305 | | * to either this or the available block-size, whichever is larger, in |
306 | | * the case where our available block-size is constrained, and we |
307 | | * overflow that available block-size. |
308 | | * @param aBorderPadding The margins representing the border padding for block |
309 | | * frames. Can be 0. |
310 | | * @param aFinalSize Out parameter for final block-size. |
311 | | * @param aConsumed The block-size already consumed by our previous-in-flows. |
312 | | */ |
313 | | void ComputeFinalBSize(const ReflowInput& aReflowInput, |
314 | | nsReflowStatus* aStatus, |
315 | | nscoord aContentBSize, |
316 | | const mozilla::LogicalMargin& aBorderPadding, |
317 | | mozilla::LogicalSize& aFinalSize, |
318 | | nscoord aConsumed); |
319 | | |
320 | | void Reflow(nsPresContext* aPresContext, |
321 | | ReflowOutput& aDesiredSize, |
322 | | const ReflowInput& aReflowInput, |
323 | | nsReflowStatus& aStatus) override; |
324 | | |
325 | | nsresult AttributeChanged(int32_t aNameSpaceID, |
326 | | nsAtom* aAttribute, |
327 | | int32_t aModType) override; |
328 | | |
329 | | /** |
330 | | * Move any frames on our overflow list to the end of our principal list. |
331 | | * @return true if there were any overflow frames |
332 | | */ |
333 | | bool DrainSelfOverflowList() override; |
334 | | |
335 | | nsresult StealFrame(nsIFrame* aChild) override; |
336 | | |
337 | | void DeleteNextInFlowChild(nsIFrame* aNextInFlow, |
338 | | bool aDeletingEmptyFrames) override; |
339 | | |
340 | | /** |
341 | | * This is a special method that allows a child class of nsBlockFrame to |
342 | | * return a special, customized nsStyleText object to the nsLineLayout |
343 | | * constructor. It is used when the nsBlockFrame child needs to specify its |
344 | | * custom rendering style. |
345 | | */ |
346 | | virtual const nsStyleText* StyleTextForLineLayout(); |
347 | | |
348 | | /** |
349 | | * Determines whether the collapsed margin carried out of the last |
350 | | * line includes the margin-top of a line with clearance (in which |
351 | | * case we must avoid collapsing that margin with our bottom margin) |
352 | | */ |
353 | | bool CheckForCollapsedBEndMarginFromClearanceLine(); |
354 | | |
355 | | static nsresult GetCurrentLine(BlockReflowInput *aState, nsLineBox **aOutCurrentLine); |
356 | | |
357 | | /** |
358 | | * Determine if this block is a margin root at the top/bottom edges. |
359 | | */ |
360 | | void IsMarginRoot(bool* aBStartMarginRoot, bool* aBEndMarginRoot); |
361 | | |
362 | | static bool BlockNeedsFloatManager(nsIFrame* aBlock); |
363 | | |
364 | | /** |
365 | | * Returns whether aFrame is a block frame that will wrap its contents |
366 | | * around floats intruding on it from the outside. (aFrame need not |
367 | | * be a block frame, but if it's not, the result will be false.) |
368 | | */ |
369 | | static bool BlockCanIntersectFloats(nsIFrame* aFrame); |
370 | | |
371 | | /** |
372 | | * Returns the inline size that needs to be cleared past floats for |
373 | | * blocks that cannot intersect floats. aState must already have |
374 | | * GetAvailableSpace called on it for the block-dir position that we |
375 | | * care about (which need not be its current mBCoord) |
376 | | */ |
377 | | struct ReplacedElementISizeToClear { |
378 | | // Note that we care about the inline-start margin but can ignore |
379 | | // the inline-end margin. |
380 | | nscoord marginIStart, borderBoxISize; |
381 | | }; |
382 | | static ReplacedElementISizeToClear |
383 | | ISizeToClearPastFloats(const BlockReflowInput& aState, |
384 | | const mozilla::LogicalRect& aFloatAvailableSpace, |
385 | | nsIFrame* aFrame); |
386 | | |
387 | | /** |
388 | | * Creates a contination for aFloat and adds it to the list of overflow floats. |
389 | | * Also updates aState.mReflowStatus to include the float's incompleteness. |
390 | | * Must only be called while this block frame is in reflow. |
391 | | * aFloatStatus must be the float's true, unmodified reflow status. |
392 | | */ |
393 | | void SplitFloat(BlockReflowInput& aState, |
394 | | nsIFrame* aFloat, |
395 | | const nsReflowStatus& aFloatStatus); |
396 | | |
397 | | /** |
398 | | * Walks up the frame tree, starting with aCandidate, and returns the first |
399 | | * block frame that it encounters. |
400 | | */ |
401 | | static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate); |
402 | | |
403 | | struct FrameLines { |
404 | | nsLineList mLines; |
405 | | nsFrameList mFrames; |
406 | | }; |
407 | | |
408 | | /** |
409 | | * Update the styles of our various pseudo-elements (bullets, first-line, |
410 | | * etc, but _not_ first-letter). |
411 | | */ |
412 | | void UpdatePseudoElementStyles(mozilla::ServoRestyleState& aRestyleState); |
413 | | |
414 | | // Update our first-letter styles during stylo post-traversal. This needs to |
415 | | // be done at a slightly different time than our other pseudo-elements. |
416 | | void UpdateFirstLetterStyle(mozilla::ServoRestyleState& aRestyleState); |
417 | | |
418 | | protected: |
419 | | explicit nsBlockFrame(ComputedStyle* aStyle, ClassID aID = kClassID) |
420 | | : nsContainerFrame(aStyle, aID) |
421 | | , mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN) |
422 | | , mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN) |
423 | 0 | { |
424 | | #ifdef DEBUG |
425 | | InitDebugFlags(); |
426 | | #endif |
427 | | } |
428 | | |
429 | | virtual ~nsBlockFrame(); |
430 | | |
431 | | #ifdef DEBUG |
432 | | already_AddRefed<ComputedStyle> GetFirstLetterStyle(nsPresContext* aPresContext); |
433 | | #endif |
434 | | |
435 | | NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(LineCursorProperty, nsLineBox) |
436 | 0 | bool HasLineCursor() { return GetStateBits() & NS_BLOCK_HAS_LINE_CURSOR; } |
437 | 0 | nsLineBox* GetLineCursor() { |
438 | 0 | return HasLineCursor() ? GetProperty(LineCursorProperty()) : nullptr; |
439 | 0 | } |
440 | | |
441 | 0 | nsLineBox* NewLineBox(nsIFrame* aFrame, bool aIsBlock) { |
442 | 0 | return NS_NewLineBox(PresShell(), aFrame, aIsBlock); |
443 | 0 | } |
444 | 0 | nsLineBox* NewLineBox(nsLineBox* aFromLine, nsIFrame* aFrame, int32_t aCount) { |
445 | 0 | return NS_NewLineBox(PresShell(), aFromLine, aFrame, aCount); |
446 | 0 | } |
447 | 0 | void FreeLineBox(nsLineBox* aLine) { |
448 | 0 | if (aLine == GetLineCursor()) { |
449 | 0 | ClearLineCursor(); |
450 | 0 | } |
451 | 0 | aLine->Destroy(PresShell()); |
452 | 0 | } |
453 | | /** |
454 | | * Helper method for StealFrame. |
455 | | */ |
456 | | void RemoveFrameFromLine(nsIFrame* aChild, nsLineList::iterator aLine, |
457 | | nsFrameList& aFrameList, nsLineList& aLineList); |
458 | | |
459 | | void TryAllLines(nsLineList::iterator* aIterator, |
460 | | nsLineList::iterator* aStartIterator, |
461 | | nsLineList::iterator* aEndIterator, |
462 | | bool* aInOverflowLines, |
463 | | FrameLines** aOverflowLines); |
464 | | |
465 | | /** move the frames contained by aLine by aDeltaBCoord |
466 | | * if aLine is a block, its child floats are added to the state manager |
467 | | */ |
468 | | void SlideLine(BlockReflowInput& aState, |
469 | | nsLineBox* aLine, nscoord aDeltaBCoord); |
470 | | |
471 | | void UpdateLineContainerSize(nsLineBox* aLine, |
472 | | const nsSize& aNewContainerSize); |
473 | | |
474 | | // helper for SlideLine and UpdateLineContainerSize |
475 | | void MoveChildFramesOfLine(nsLineBox* aLine, nscoord aDeltaBCoord); |
476 | | |
477 | | void ComputeFinalSize(const ReflowInput& aReflowInput, |
478 | | BlockReflowInput& aState, |
479 | | ReflowOutput& aMetrics, |
480 | | nscoord* aBottomEdgeOfChildren); |
481 | | |
482 | | void ComputeOverflowAreas(const nsRect& aBounds, |
483 | | const nsStyleDisplay* aDisplay, |
484 | | nscoord aBottomEdgeOfChildren, |
485 | | nsOverflowAreas& aOverflowAreas); |
486 | | |
487 | | /** |
488 | | * Add the frames in aFrameList to this block after aPrevSibling. |
489 | | * This block thinks in terms of lines, but the frame construction code |
490 | | * knows nothing about lines at all so we need to find the line that |
491 | | * contains aPrevSibling and add aFrameList after aPrevSibling on that line. |
492 | | * New lines are created as necessary to handle block data in aFrameList. |
493 | | * This function will clear aFrameList. |
494 | | */ |
495 | | void AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling); |
496 | | |
497 | | /** |
498 | | * Perform Bidi resolution on this frame |
499 | | */ |
500 | | nsresult ResolveBidi(); |
501 | | |
502 | | /** |
503 | | * Test whether the frame is a form control in a visual Bidi page. |
504 | | * This is necessary for backwards-compatibility, because most visual |
505 | | * pages use logical order for form controls so that they will |
506 | | * display correctly on native widgets in OSs with Bidi support |
507 | | * @param aPresContext the pres context |
508 | | * @return whether the frame is a BIDI form control |
509 | | */ |
510 | | bool IsVisualFormControl(nsPresContext* aPresContext); |
511 | | |
512 | | /** |
513 | | * Helper function to create bullet frame. |
514 | | * @param aCreateBulletList true to create bullet list; otherwise number list. |
515 | | * @param aListStylePositionInside true to put the list position inside; |
516 | | * otherwise outside. |
517 | | */ |
518 | | void CreateBulletFrameForListItem(bool aCreateBulletList, |
519 | | bool aListStylePositionInside); |
520 | | |
521 | | public: |
522 | | /** |
523 | | * Does all the real work for removing aDeletedFrame |
524 | | * -- finds the line containing aDeletedFrame |
525 | | * -- removes all aDeletedFrame next-in-flows (or all continuations, |
526 | | * if REMOVE_FIXED_CONTINUATIONS is given) |
527 | | * -- marks lines dirty as needed |
528 | | * -- marks textruns dirty (unless FRAMES_ARE_EMPTY is given, in which |
529 | | * case textruns do not need to be dirtied) |
530 | | * -- destroys all removed frames |
531 | | */ |
532 | | enum { |
533 | | REMOVE_FIXED_CONTINUATIONS = 0x02, |
534 | | FRAMES_ARE_EMPTY = 0x04 |
535 | | }; |
536 | | void DoRemoveFrame(nsIFrame* aDeletedFrame, uint32_t aFlags) |
537 | 0 | { |
538 | 0 | AutoPostDestroyData data(PresContext()); |
539 | 0 | DoRemoveFrameInternal(aDeletedFrame, aFlags, data.mData); |
540 | 0 | } |
541 | | |
542 | | void ReparentFloats(nsIFrame* aFirstFrame, nsBlockFrame* aOldParent, |
543 | | bool aReparentSiblings, ReparentingDirection aDirection); |
544 | | |
545 | | virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override; |
546 | | |
547 | | virtual void UnionChildOverflow(nsOverflowAreas& aOverflowAreas) override; |
548 | | |
549 | | /** Load all of aFrame's floats into the float manager iff aFrame is not a |
550 | | * block formatting context. Handles all necessary float manager translations; |
551 | | * assumes float manager is in aFrame's parent's coord system. |
552 | | * Safe to call on non-blocks (does nothing). |
553 | | */ |
554 | | static void RecoverFloatsFor(nsIFrame* aFrame, |
555 | | nsFloatManager& aFloatManager, |
556 | | mozilla::WritingMode aWM, |
557 | | const nsSize& aContainerSize); |
558 | | |
559 | | /** |
560 | | * Determine if we have any pushed floats from a previous continuation. |
561 | | * |
562 | | * @returns true, if any of the floats at the beginning of our mFloats list |
563 | | * have the NS_FRAME_IS_PUSHED_FLOAT bit set; false otherwise. |
564 | | */ |
565 | 0 | bool HasPushedFloatsFromPrevContinuation() const { |
566 | 0 | if (!mFloats.IsEmpty()) { |
567 | 0 | // If we have pushed floats, then they should be at the beginning of our |
568 | 0 | // float list. |
569 | 0 | if (mFloats.FirstChild()->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) { |
570 | 0 | return true; |
571 | 0 | } |
572 | 0 | } |
573 | 0 | |
574 | | #ifdef DEBUG |
575 | | // Double-check the above assertion that pushed floats should be at the |
576 | | // beginning of our floats list. |
577 | | for (nsFrameList::Enumerator e(mFloats); !e.AtEnd(); e.Next()) { |
578 | | nsIFrame* f = e.get(); |
579 | | NS_ASSERTION(!(f->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT), |
580 | | "pushed floats must be at the beginning of the float list"); |
581 | | } |
582 | | #endif |
583 | | |
584 | 0 | // We may have a pending push of pushed floats too: |
585 | 0 | if (HasPushedFloats()) { |
586 | 0 | // XXX we can return 'true' here once we make HasPushedFloats |
587 | 0 | // not lie. (see nsBlockFrame::RemoveFloat) |
588 | 0 | auto* pushedFloats = GetPushedFloats(); |
589 | 0 | return pushedFloats && !pushedFloats->IsEmpty(); |
590 | 0 | } |
591 | 0 | return false; |
592 | 0 | } |
593 | | |
594 | | virtual bool RenumberChildFrames(int32_t* aOrdinal, |
595 | | int32_t aDepth, |
596 | | int32_t aIncrement, |
597 | | bool aForCounting) override; |
598 | | |
599 | | // @see nsIFrame::AddSizeOfExcludingThisForTree |
600 | | void AddSizeOfExcludingThisForTree(nsWindowSizes&) const override; |
601 | | |
602 | | protected: |
603 | | /** @see DoRemoveFrame */ |
604 | | void DoRemoveFrameInternal(nsIFrame* aDeletedFrame, uint32_t aFlags, |
605 | | PostDestroyData& data); |
606 | | |
607 | | /** grab overflow lines from this block's prevInFlow, and make them |
608 | | * part of this block's mLines list. |
609 | | * @return true if any lines were drained. |
610 | | */ |
611 | | bool DrainOverflowLines(); |
612 | | |
613 | | /** |
614 | | * @return false iff this block does not have a float on any child list. |
615 | | * This function is O(1). |
616 | | */ |
617 | 0 | bool MaybeHasFloats() const { |
618 | 0 | if (!mFloats.IsEmpty()) { |
619 | 0 | return true; |
620 | 0 | } |
621 | 0 | // XXX this could be replaced with HasPushedFloats() if we enforced |
622 | 0 | // removing the property when the frame list becomes empty. |
623 | 0 | nsFrameList* list = GetPushedFloats(); |
624 | 0 | if (list && !list->IsEmpty()) { |
625 | 0 | return true; |
626 | 0 | } |
627 | 0 | // For the OverflowOutOfFlowsProperty I think we do enforce that, but it's |
628 | 0 | // a mix of out-of-flow frames, so that's why the method name has "Maybe". |
629 | 0 | return GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS; |
630 | 0 | } |
631 | | |
632 | | /** |
633 | | * Moves frames from our PushedFloats list back into our mFloats list. |
634 | | */ |
635 | | void DrainSelfPushedFloats(); |
636 | | |
637 | | /** |
638 | | * First calls DrainSelfPushedFloats() then grabs pushed floats from this |
639 | | * block's prev-in-flow, and splice them into this block's mFloats list too. |
640 | | */ |
641 | | void DrainPushedFloats(); |
642 | | |
643 | | /** Load all our floats into the float manager (without reflowing them). |
644 | | * Assumes float manager is in our own coordinate system. |
645 | | */ |
646 | | void RecoverFloats(nsFloatManager& aFloatManager, |
647 | | mozilla::WritingMode aWM, |
648 | | const nsSize& aContainerSize); |
649 | | |
650 | | /** Reflow pushed floats |
651 | | */ |
652 | | void ReflowPushedFloats(BlockReflowInput& aState, |
653 | | nsOverflowAreas& aOverflowAreas, |
654 | | nsReflowStatus& aStatus); |
655 | | |
656 | | /** Find any trailing BR clear from the last line of the block (or its PIFs) |
657 | | */ |
658 | | mozilla::StyleClear FindTrailingClear(); |
659 | | |
660 | | /** |
661 | | * Remove a float from our float list. |
662 | | */ |
663 | | void RemoveFloat(nsIFrame* aFloat); |
664 | | /** |
665 | | * Remove a float from the float cache for the line its placeholder is on. |
666 | | */ |
667 | | void RemoveFloatFromFloatCache(nsIFrame* aFloat); |
668 | | |
669 | | void CollectFloats(nsIFrame* aFrame, nsFrameList& aList, |
670 | 0 | bool aCollectFromSiblings) { |
671 | 0 | if (MaybeHasFloats()) { |
672 | 0 | DoCollectFloats(aFrame, aList, aCollectFromSiblings); |
673 | 0 | } |
674 | 0 | } |
675 | | void DoCollectFloats(nsIFrame* aFrame, nsFrameList& aList, |
676 | | bool aCollectFromSiblings); |
677 | | |
678 | | // Remove a float, abs, rel positioned frame from the appropriate block's list |
679 | | static void DoRemoveOutOfFlowFrame(nsIFrame* aFrame); |
680 | | |
681 | | /** set up the conditions necessary for an resize reflow |
682 | | * the primary task is to mark the minimumly sufficient lines dirty. |
683 | | */ |
684 | | void PrepareResizeReflow(BlockReflowInput& aState); |
685 | | |
686 | | /** reflow all lines that have been marked dirty */ |
687 | | void ReflowDirtyLines(BlockReflowInput& aState); |
688 | | |
689 | | /** Mark a given line dirty due to reflow being interrupted on or before it */ |
690 | | void MarkLineDirtyForInterrupt(nsLineBox* aLine); |
691 | | |
692 | | //---------------------------------------- |
693 | | // Methods for line reflow |
694 | | /** |
695 | | * Reflow a line. |
696 | | * @param aState the current reflow state |
697 | | * @param aLine the line to reflow. can contain a single block frame |
698 | | * or contain 1 or more inline frames. |
699 | | * @param aKeepReflowGoing [OUT] indicates whether the caller should continue to reflow more lines |
700 | | */ |
701 | | void ReflowLine(BlockReflowInput& aState, |
702 | | LineIterator aLine, |
703 | | bool* aKeepReflowGoing); |
704 | | |
705 | | // Return false if it needs another reflow because of reduced space |
706 | | // between floats that are next to it (but not next to its top), and |
707 | | // return true otherwise. |
708 | | bool PlaceLine(BlockReflowInput& aState, |
709 | | nsLineLayout& aLineLayout, |
710 | | LineIterator aLine, |
711 | | nsFloatManager::SavedState* aFloatStateBeforeLine, |
712 | | nsFlowAreaRect& aFlowArea, // in-out |
713 | | nscoord& aAvailableSpaceBSize, // in-out |
714 | | bool* aKeepReflowGoing); |
715 | | |
716 | | /** |
717 | | * If NS_BLOCK_LOOK_FOR_DIRTY_FRAMES is set, call MarkLineDirty |
718 | | * on any line with a child frame that is dirty. |
719 | | */ |
720 | | void LazyMarkLinesDirty(); |
721 | | |
722 | | /** |
723 | | * Mark |aLine| dirty, and, if necessary because of possible |
724 | | * pull-up, mark the previous line dirty as well. Also invalidates textruns |
725 | | * on those lines because the text in the lines might have changed due to |
726 | | * addition/removal of frames. |
727 | | * @param aLine the line to mark dirty |
728 | | * @param aLineList the line list containing that line |
729 | | */ |
730 | | void MarkLineDirty(LineIterator aLine, const nsLineList* aLineList); |
731 | | |
732 | | // XXX where to go |
733 | | bool IsLastLine(BlockReflowInput& aState, |
734 | | LineIterator aLine); |
735 | | |
736 | | void DeleteLine(BlockReflowInput& aState, |
737 | | nsLineList::iterator aLine, |
738 | | nsLineList::iterator aLineEnd); |
739 | | |
740 | | //---------------------------------------- |
741 | | // Methods for individual frame reflow |
742 | | |
743 | | bool ShouldApplyBStartMargin(BlockReflowInput& aState, |
744 | | nsLineBox* aLine, |
745 | | nsIFrame* aChildFrame); |
746 | | |
747 | | void ReflowBlockFrame(BlockReflowInput& aState, |
748 | | LineIterator aLine, |
749 | | bool* aKeepGoing); |
750 | | |
751 | | void ReflowInlineFrames(BlockReflowInput& aState, |
752 | | LineIterator aLine, |
753 | | bool* aKeepLineGoing); |
754 | | |
755 | | void DoReflowInlineFrames(BlockReflowInput& aState, |
756 | | nsLineLayout& aLineLayout, |
757 | | LineIterator aLine, |
758 | | nsFlowAreaRect& aFloatAvailableSpace, |
759 | | nscoord& aAvailableSpaceBSize, |
760 | | nsFloatManager::SavedState* aFloatStateBeforeLine, |
761 | | bool* aKeepReflowGoing, |
762 | | LineReflowStatus* aLineReflowStatus, |
763 | | bool aAllowPullUp); |
764 | | |
765 | | void ReflowInlineFrame(BlockReflowInput& aState, |
766 | | nsLineLayout& aLineLayout, |
767 | | LineIterator aLine, |
768 | | nsIFrame* aFrame, |
769 | | LineReflowStatus* aLineReflowStatus); |
770 | | |
771 | | // Compute the available inline size for a float. |
772 | | mozilla::LogicalRect AdjustFloatAvailableSpace( |
773 | | BlockReflowInput& aState, |
774 | | const mozilla::LogicalRect& aFloatAvailableSpace, |
775 | | nsIFrame* aFloatFrame); |
776 | | // Computes the border-box inline size of the float |
777 | | nscoord ComputeFloatISize(BlockReflowInput& aState, |
778 | | const mozilla::LogicalRect& aFloatAvailableSpace, |
779 | | nsIFrame* aFloat); |
780 | | // An incomplete aReflowStatus indicates the float should be split |
781 | | // but only if the available height is constrained. |
782 | | // aAdjustedAvailableSpace is the result of calling |
783 | | // nsBlockFrame::AdjustFloatAvailableSpace. |
784 | | void ReflowFloat(BlockReflowInput& aState, |
785 | | const mozilla::LogicalRect& aAdjustedAvailableSpace, |
786 | | nsIFrame* aFloat, |
787 | | mozilla::LogicalMargin& aFloatMargin, |
788 | | mozilla::LogicalMargin& aFloatOffsets, |
789 | | // Whether the float's position |
790 | | // (aAdjustedAvailableSpace) has been pushed down |
791 | | // due to the presence of other floats. |
792 | | bool aFloatPushedDown, |
793 | | nsReflowStatus& aReflowStatus); |
794 | | |
795 | | //---------------------------------------- |
796 | | // Methods for pushing/pulling lines/frames |
797 | | |
798 | | /** |
799 | | * Create a next-in-flow, if necessary, for aFrame. If a new frame is |
800 | | * created, place it in aLine if aLine is not null. |
801 | | * @param aState the block reflow state |
802 | | * @param aLine where to put a new frame |
803 | | * @param aFrame the frame |
804 | | * @return true if a new frame was created, false if not |
805 | | */ |
806 | | bool CreateContinuationFor(BlockReflowInput& aState, |
807 | | nsLineBox* aLine, |
808 | | nsIFrame* aFrame); |
809 | | |
810 | | /** |
811 | | * Push aLine (and any after it), since it cannot be placed on this |
812 | | * page/column. Set aKeepReflowGoing to false and set |
813 | | * flag aState.mReflowStatus as incomplete. |
814 | | */ |
815 | | void PushTruncatedLine(BlockReflowInput& aState, |
816 | | LineIterator aLine, |
817 | | bool* aKeepReflowGoing); |
818 | | |
819 | | void SplitLine(BlockReflowInput& aState, |
820 | | nsLineLayout& aLineLayout, |
821 | | LineIterator aLine, |
822 | | nsIFrame* aFrame, |
823 | | LineReflowStatus* aLineReflowStatus); |
824 | | |
825 | | /** |
826 | | * Pull a frame from the next available location (one of our lines or |
827 | | * one of our next-in-flows lines). |
828 | | * @return the pulled frame or nullptr |
829 | | */ |
830 | | nsIFrame* PullFrame(BlockReflowInput& aState, |
831 | | LineIterator aLine); |
832 | | |
833 | | /** |
834 | | * Try to pull a frame out of a line pointed at by aFromLine. |
835 | | * |
836 | | * Note: pulling a frame from a line that is a place-holder frame |
837 | | * doesn't automatically remove the corresponding float from the |
838 | | * line's float array. This happens indirectly: either the line gets |
839 | | * emptied (and destroyed) or the line gets reflowed (because we mark |
840 | | * it dirty) and the code at the top of ReflowLine empties the |
841 | | * array. So eventually, it will be removed, just not right away. |
842 | | * |
843 | | * @return the pulled frame or nullptr |
844 | | */ |
845 | | nsIFrame* PullFrameFrom(nsLineBox* aLine, |
846 | | nsBlockFrame* aFromContainer, |
847 | | nsLineList::iterator aFromLine); |
848 | | |
849 | | /** |
850 | | * Push the line after aLineBefore to the overflow line list. |
851 | | * @param aLineBefore a line in 'mLines' (or LinesBegin() when |
852 | | * pushing the first line) |
853 | | */ |
854 | | void PushLines(BlockReflowInput& aState, |
855 | | nsLineList::iterator aLineBefore); |
856 | | |
857 | | void PropagateFloatDamage(BlockReflowInput& aState, |
858 | | nsLineBox* aLine, |
859 | | nscoord aDeltaBCoord); |
860 | | |
861 | | void CheckFloats(BlockReflowInput& aState); |
862 | | |
863 | | //---------------------------------------- |
864 | | // List handling kludge |
865 | | |
866 | | void ReflowBullet(nsIFrame* aBulletFrame, |
867 | | BlockReflowInput& aState, |
868 | | ReflowOutput& aMetrics, |
869 | | nscoord aLineTop); |
870 | | |
871 | | //---------------------------------------- |
872 | | |
873 | | virtual nsILineIterator* GetLineIterator() override; |
874 | | |
875 | | public: |
876 | 0 | bool HasOverflowLines() const { |
877 | 0 | return 0 != (GetStateBits() & NS_BLOCK_HAS_OVERFLOW_LINES); |
878 | 0 | } |
879 | | FrameLines* GetOverflowLines() const; |
880 | | protected: |
881 | | FrameLines* RemoveOverflowLines(); |
882 | | void SetOverflowLines(FrameLines* aOverflowLines); |
883 | | void DestroyOverflowLines(); |
884 | | |
885 | | /** |
886 | | * This class is useful for efficiently modifying the out of flow |
887 | | * overflow list. It gives the client direct writable access to |
888 | | * the frame list temporarily but ensures that property is only |
889 | | * written back if absolutely necessary. |
890 | | */ |
891 | | struct nsAutoOOFFrameList { |
892 | | nsFrameList mList; |
893 | | |
894 | | explicit nsAutoOOFFrameList(nsBlockFrame* aBlock) |
895 | | : mPropValue(aBlock->GetOverflowOutOfFlows()) |
896 | 0 | , mBlock(aBlock) { |
897 | 0 | if (mPropValue) { |
898 | 0 | mList = *mPropValue; |
899 | 0 | } |
900 | 0 | } |
901 | 0 | ~nsAutoOOFFrameList() { |
902 | 0 | mBlock->SetOverflowOutOfFlows(mList, mPropValue); |
903 | 0 | } |
904 | | protected: |
905 | | nsFrameList* const mPropValue; |
906 | | nsBlockFrame* const mBlock; |
907 | | }; |
908 | | friend struct nsAutoOOFFrameList; |
909 | | |
910 | | nsFrameList* GetOverflowOutOfFlows() const; |
911 | | void SetOverflowOutOfFlows(const nsFrameList& aList, nsFrameList* aPropValue); |
912 | | |
913 | | /** |
914 | | * @return the inside bullet frame or nullptr if we don't have one. |
915 | | */ |
916 | | nsBulletFrame* GetInsideBullet() const; |
917 | | |
918 | | /** |
919 | | * @return the outside bullet frame or nullptr if we don't have one. |
920 | | */ |
921 | | nsBulletFrame* GetOutsideBullet() const; |
922 | | |
923 | | /** |
924 | | * @return the outside bullet frame list frame property. |
925 | | */ |
926 | | nsFrameList* GetOutsideBulletList() const; |
927 | | |
928 | | /** |
929 | | * @return true if this frame has pushed floats. |
930 | | */ |
931 | 0 | bool HasPushedFloats() const { |
932 | 0 | return 0 != (GetStateBits() & NS_BLOCK_HAS_PUSHED_FLOATS); |
933 | 0 | } |
934 | | |
935 | | // Get the pushed floats list, which is used for *temporary* storage |
936 | | // of floats during reflow, between when we decide they don't fit in |
937 | | // this block until our next continuation takes them. |
938 | | nsFrameList* GetPushedFloats() const; |
939 | | // Get the pushed floats list, or if there is not currently one, |
940 | | // make a new empty one. |
941 | | nsFrameList* EnsurePushedFloats(); |
942 | | // Remove and return the pushed floats list. |
943 | | nsFrameList* RemovePushedFloats(); |
944 | | |
945 | | // Resolve a ComputedStyle for our bullet frame. aType should be |
946 | | // mozListBullet or mozListNumber. Passing in the style set is an |
947 | | // optimization, because all callsites have it. |
948 | | already_AddRefed<ComputedStyle> ResolveBulletStyle( |
949 | | mozilla::CSSPseudoElementType aType, |
950 | | mozilla::ServoStyleSet* aStyleSet); |
951 | | |
952 | | #ifdef DEBUG |
953 | | void VerifyLines(bool aFinalCheckOK); |
954 | | void VerifyOverflowSituation(); |
955 | | int32_t GetDepth() const; |
956 | | #endif |
957 | | |
958 | | // FIXME The two variables should go through a renaming refactoring to reflect |
959 | | // the fact that they mean an inline size, not a width. |
960 | | nscoord mMinWidth, mPrefWidth; |
961 | | |
962 | | nsLineList mLines; |
963 | | |
964 | | // List of all floats in this block |
965 | | // XXXmats blocks rarely have floats, make it a frame property |
966 | | nsFrameList mFloats; |
967 | | |
968 | | friend class mozilla::BlockReflowInput; |
969 | | friend class nsBlockInFlowLineIterator; |
970 | | |
971 | | #ifdef DEBUG |
972 | | public: |
973 | | static bool gLamePaintMetrics; |
974 | | static bool gLameReflowMetrics; |
975 | | static bool gNoisy; |
976 | | static bool gNoisyDamageRepair; |
977 | | static bool gNoisyIntrinsic; |
978 | | static bool gNoisyReflow; |
979 | | static bool gReallyNoisyReflow; |
980 | | static bool gNoisyFloatManager; |
981 | | static bool gVerifyLines; |
982 | | static bool gDisableResizeOpt; |
983 | | |
984 | | static int32_t gNoiseIndent; |
985 | | |
986 | | static const char* kReflowCommandType[]; |
987 | | |
988 | | protected: |
989 | | static void InitDebugFlags(); |
990 | | #endif |
991 | | }; |
992 | | |
993 | | #ifdef DEBUG |
994 | | class AutoNoisyIndenter { |
995 | | public: |
996 | | explicit AutoNoisyIndenter(bool aDoIndent) : mIndented(aDoIndent) { |
997 | | if (mIndented) { |
998 | | nsBlockFrame::gNoiseIndent++; |
999 | | } |
1000 | | } |
1001 | | ~AutoNoisyIndenter() { |
1002 | | if (mIndented) { |
1003 | | nsBlockFrame::gNoiseIndent--; |
1004 | | } |
1005 | | } |
1006 | | private: |
1007 | | bool mIndented; |
1008 | | }; |
1009 | | #endif |
1010 | | |
1011 | | /** |
1012 | | * Iterates over all lines in the prev-in-flows/next-in-flows of this block. |
1013 | | */ |
1014 | | class nsBlockInFlowLineIterator { |
1015 | | public: |
1016 | | typedef nsBlockFrame::LineIterator LineIterator; |
1017 | | /** |
1018 | | * Set up the iterator to point to aLine which must be a normal line |
1019 | | * in aFrame (not an overflow line). |
1020 | | */ |
1021 | | nsBlockInFlowLineIterator(nsBlockFrame* aFrame, LineIterator aLine); |
1022 | | /** |
1023 | | * Set up the iterator to point to the first line found starting from |
1024 | | * aFrame. Sets aFoundValidLine to false if there is no such line. |
1025 | | * After aFoundValidLine has returned false, don't call any methods on this |
1026 | | * object again. |
1027 | | */ |
1028 | | nsBlockInFlowLineIterator(nsBlockFrame* aFrame, bool* aFoundValidLine); |
1029 | | /** |
1030 | | * Set up the iterator to point to the line that contains aFindFrame (either |
1031 | | * directly or indirectly). If aFrame is out of flow, or contained in an |
1032 | | * out-of-flow, finds the line containing the out-of-flow's placeholder. If |
1033 | | * the frame is not found, sets aFoundValidLine to false. After |
1034 | | * aFoundValidLine has returned false, don't call any methods on this |
1035 | | * object again. |
1036 | | */ |
1037 | | nsBlockInFlowLineIterator(nsBlockFrame* aFrame, nsIFrame* aFindFrame, |
1038 | | bool* aFoundValidLine); |
1039 | | |
1040 | 0 | LineIterator GetLine() { return mLine; } |
1041 | | bool IsLastLineInList(); |
1042 | 0 | nsBlockFrame* GetContainer() { return mFrame; } |
1043 | 0 | bool GetInOverflow() { return mLineList != &mFrame->mLines; } |
1044 | | |
1045 | | /** |
1046 | | * Returns the current line list we're iterating, null means |
1047 | | * we're iterating |mLines| of the container. |
1048 | | */ |
1049 | 0 | nsLineList* GetLineList() { return mLineList; } |
1050 | | |
1051 | | /** |
1052 | | * Returns the end-iterator of whatever line list we're in. |
1053 | | */ |
1054 | | LineIterator End(); |
1055 | | |
1056 | | /** |
1057 | | * Returns false if there are no more lines. After this has returned false, |
1058 | | * don't call any methods on this object again. |
1059 | | */ |
1060 | | bool Next(); |
1061 | | /** |
1062 | | * Returns false if there are no more lines. After this has returned false, |
1063 | | * don't call any methods on this object again. |
1064 | | */ |
1065 | | bool Prev(); |
1066 | | |
1067 | | private: |
1068 | | friend class nsBlockFrame; |
1069 | | friend class nsBidiPresUtils; |
1070 | | // XXX nsBlockFrame uses this internally in one place. Try to remove it. |
1071 | | // XXX uhm, and nsBidiPresUtils::Resolve too. |
1072 | | nsBlockInFlowLineIterator(nsBlockFrame* aFrame, LineIterator aLine, bool aInOverflow); |
1073 | | |
1074 | | nsBlockFrame* mFrame; |
1075 | | LineIterator mLine; |
1076 | | nsLineList* mLineList; // the line list mLine is in |
1077 | | |
1078 | | /** |
1079 | | * Moves iterator to next valid line reachable from the current block. |
1080 | | * Returns false if there are no valid lines. |
1081 | | */ |
1082 | | bool FindValidLine(); |
1083 | | }; |
1084 | | |
1085 | | #endif /* nsBlockFrame_h___ */ |