669a4aa215a3e69456266227dbabd59826485d8e
[WebKit-https.git] / Source / WebCore / rendering / RenderFragmentedFlow.cpp
1 /*
2  * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above
9  *    copyright notice, this list of conditions and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above
12  *    copyright notice, this list of conditions and the following
13  *    disclaimer in the documentation and/or other materials
14  *    provided with the distribution.
15  * 
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "RenderFragmentedFlow.h"
32
33 #include "HitTestRequest.h"
34 #include "HitTestResult.h"
35 #include "InlineElementBox.h"
36 #include "LayoutState.h"
37 #include "Node.h"
38 #include "PODIntervalTree.h"
39 #include "RenderBoxFragmentInfo.h"
40 #include "RenderFragmentContainer.h"
41 #include "RenderInline.h"
42 #include "RenderLayer.h"
43 #include "RenderLayerCompositor.h"
44 #include "RenderTableCell.h"
45 #include "RenderTableSection.h"
46 #include "RenderTheme.h"
47 #include "RenderView.h"
48 #include "TransformState.h"
49 #include <wtf/IsoMallocInlines.h>
50 #include <wtf/StackStats.h>
51
52 namespace WebCore {
53
54 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderFragmentedFlow);
55
56 RenderFragmentedFlow::RenderFragmentedFlow(Document& document, RenderStyle&& style)
57     : RenderBlockFlow(document, WTFMove(style))
58     , m_currentFragmentMaintainer(nullptr)
59     , m_fragmentsInvalidated(false)
60     , m_fragmentsHaveUniformLogicalWidth(true)
61     , m_fragmentsHaveUniformLogicalHeight(true)
62     , m_pageLogicalSizeChanged(false)
63 {
64     setIsRenderFragmentedFlow(true);
65 }
66
67 void RenderFragmentedFlow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
68 {
69     RenderBlockFlow::styleDidChange(diff, oldStyle);
70
71     if (oldStyle && oldStyle->writingMode() != style().writingMode())
72         invalidateFragments();
73 }
74
75 void RenderFragmentedFlow::removeFlowChildInfo(RenderElement& child)
76 {
77     if (is<RenderBlockFlow>(child))
78         removeLineFragmentInfo(downcast<RenderBlockFlow>(child));
79     if (is<RenderBox>(child))
80         removeRenderBoxFragmentInfo(downcast<RenderBox>(child));
81 }
82
83 void RenderFragmentedFlow::removeFragmentFromThread(RenderFragmentContainer* RenderFragmentContainer)
84 {
85     ASSERT(RenderFragmentContainer);
86     m_fragmentList.remove(RenderFragmentContainer);
87 }
88
89 void RenderFragmentedFlow::invalidateFragments(MarkingBehavior markingParents)
90 {
91     if (m_fragmentsInvalidated) {
92         ASSERT(selfNeedsLayout());
93         return;
94     }
95
96     m_fragmentRangeMap.clear();
97     m_breakBeforeToFragmentMap.clear();
98     m_breakAfterToFragmentMap.clear();
99     if (m_lineToFragmentMap)
100         m_lineToFragmentMap->clear();
101     setNeedsLayout(markingParents);
102
103     m_fragmentsInvalidated = true;
104 }
105
106 void RenderFragmentedFlow::validateFragments()
107 {
108     if (m_fragmentsInvalidated) {
109         m_fragmentsInvalidated = false;
110         m_fragmentsHaveUniformLogicalWidth = true;
111         m_fragmentsHaveUniformLogicalHeight = true;
112
113         if (hasFragments()) {
114             LayoutUnit previousFragmentLogicalWidth = 0;
115             LayoutUnit previousFragmentLogicalHeight = 0;
116             bool firstFragmentVisited = false;
117             
118             for (auto& fragment : m_fragmentList) {
119                 ASSERT(!fragment->needsLayout() || fragment->isRenderFragmentContainerSet());
120
121                 fragment->deleteAllRenderBoxFragmentInfo();
122
123                 LayoutUnit fragmentLogicalWidth = fragment->pageLogicalWidth();
124                 LayoutUnit fragmentLogicalHeight = fragment->pageLogicalHeight();
125
126                 if (!firstFragmentVisited)
127                     firstFragmentVisited = true;
128                 else {
129                     if (m_fragmentsHaveUniformLogicalWidth && previousFragmentLogicalWidth != fragmentLogicalWidth)
130                         m_fragmentsHaveUniformLogicalWidth = false;
131                     if (m_fragmentsHaveUniformLogicalHeight && previousFragmentLogicalHeight != fragmentLogicalHeight)
132                         m_fragmentsHaveUniformLogicalHeight = false;
133                 }
134
135                 previousFragmentLogicalWidth = fragmentLogicalWidth;
136             }
137
138             setFragmentRangeForBox(*this, m_fragmentList.first(), m_fragmentList.last());
139         }
140     }
141
142     updateLogicalWidth(); // Called to get the maximum logical width for the fragment.
143     updateFragmentsFragmentedFlowPortionRect();
144 }
145
146 void RenderFragmentedFlow::layout()
147 {
148     StackStats::LayoutCheckPoint layoutCheckPoint;
149
150     m_pageLogicalSizeChanged = m_fragmentsInvalidated && everHadLayout();
151
152     validateFragments();
153
154     RenderBlockFlow::layout();
155
156     m_pageLogicalSizeChanged = false;
157 }
158
159 void RenderFragmentedFlow::updateLogicalWidth()
160 {
161     LayoutUnit logicalWidth = initialLogicalWidth();
162     for (auto& fragment : m_fragmentList) {
163         ASSERT(!fragment->needsLayout() || fragment->isRenderFragmentContainerSet());
164         logicalWidth = std::max(fragment->pageLogicalWidth(), logicalWidth);
165     }
166     setLogicalWidth(logicalWidth);
167
168     // If the fragments have non-uniform logical widths, then insert inset information for the RenderFragmentedFlow.
169     for (auto& fragment : m_fragmentList) {
170         LayoutUnit fragmentLogicalWidth = fragment->pageLogicalWidth();
171         LayoutUnit logicalLeft = style().direction() == LTR ? LayoutUnit() : logicalWidth - fragmentLogicalWidth;
172         fragment->setRenderBoxFragmentInfo(this, logicalLeft, fragmentLogicalWidth, false);
173     }
174 }
175
176 RenderBox::LogicalExtentComputedValues RenderFragmentedFlow::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop) const
177 {
178     LogicalExtentComputedValues computedValues;
179     computedValues.m_position = logicalTop;
180     computedValues.m_extent = 0;
181
182     const LayoutUnit maxFlowSize = RenderFragmentedFlow::maxLogicalHeight();
183     for (auto& fragment : m_fragmentList) {
184         ASSERT(!fragment->needsLayout() || fragment->isRenderFragmentContainerSet());
185
186         LayoutUnit distanceToMaxSize = maxFlowSize - computedValues.m_extent;
187         computedValues.m_extent += std::min(distanceToMaxSize, fragment->logicalHeightOfAllFragmentedFlowContent());
188
189         // If we reached the maximum size there's no point in going further.
190         if (computedValues.m_extent == maxFlowSize)
191             return computedValues;
192     }
193     return computedValues;
194 }
195
196 bool RenderFragmentedFlow::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
197 {
198     if (hitTestAction == HitTestBlockBackground)
199         return false;
200     return RenderBlockFlow::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction);
201 }
202
203 bool RenderFragmentedFlow::shouldRepaint(const LayoutRect& r) const
204 {
205     if (view().printing() || r.isEmpty())
206         return false;
207
208     return true;
209 }
210
211 void RenderFragmentedFlow::repaintRectangleInFragments(const LayoutRect& repaintRect) const
212 {
213     if (!shouldRepaint(repaintRect) || !hasValidFragmentInfo())
214         return;
215
216     LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext()); // We can't use layout state to repaint, since the fragments are somewhere else.
217
218     for (auto& fragment : m_fragmentList)
219         fragment->repaintFragmentedFlowContent(repaintRect);
220 }
221
222 RenderFragmentContainer* RenderFragmentedFlow::fragmentAtBlockOffset(const RenderBox* clampBox, LayoutUnit offset, bool extendLastFragment) const
223 {
224     ASSERT(!m_fragmentsInvalidated);
225
226     if (m_fragmentList.isEmpty())
227         return nullptr;
228
229     if (m_fragmentList.size() == 1 && extendLastFragment)
230         return m_fragmentList.first();
231
232     if (offset <= 0)
233         return clampBox ? clampBox->clampToStartAndEndFragments(m_fragmentList.first()) : m_fragmentList.first();
234
235     FragmentSearchAdapter adapter(offset);
236     m_fragmentIntervalTree.allOverlapsWithAdapter<FragmentSearchAdapter>(adapter);
237
238     // If no fragment was found, the offset is in the flow thread overflow.
239     // The last fragment will contain the offset if extendLastFragment is set or if the last fragment is a set.
240     if (!adapter.result() && (extendLastFragment || m_fragmentList.last()->isRenderFragmentContainerSet()))
241         return clampBox ? clampBox->clampToStartAndEndFragments(m_fragmentList.last()) : m_fragmentList.last();
242
243     RenderFragmentContainer* fragment = adapter.result();
244     if (!clampBox)
245         return fragment;
246     return fragment ? clampBox->clampToStartAndEndFragments(fragment) : nullptr;
247 }
248
249 LayoutPoint RenderFragmentedFlow::adjustedPositionRelativeToOffsetParent(const RenderBoxModelObject& boxModelObject, const LayoutPoint& startPoint) const
250 {
251     LayoutPoint referencePoint = startPoint;
252     
253     const RenderBlock* objContainingBlock = boxModelObject.containingBlock();
254     // FIXME: This needs to be adapted for different writing modes inside the flow thread.
255     RenderFragmentContainer* startFragment = fragmentAtBlockOffset(objContainingBlock, referencePoint.y());
256     if (startFragment) {
257         // Take into account the offset coordinates of the fragment.
258         RenderBoxModelObject* startFragmentBox = startFragment;
259         RenderBoxModelObject* currObject = startFragmentBox;
260         RenderBoxModelObject* currOffsetParent;
261         while ((currOffsetParent = currObject->offsetParent())) {
262             referencePoint.move(currObject->offsetLeft(), currObject->offsetTop());
263             
264             // Since we're looking for the offset relative to the body, we must also
265             // take into consideration the borders of the fragment's offsetParent.
266             if (is<RenderBox>(*currOffsetParent) && !currOffsetParent->isBody())
267                 referencePoint.move(downcast<RenderBox>(*currOffsetParent).borderLeft(), downcast<RenderBox>(*currOffsetParent).borderTop());
268             
269             currObject = currOffsetParent;
270         }
271         
272         // We need to check if any of this box's containing blocks start in a different fragment
273         // and if so, drop the object's top position (which was computed relative to its containing block
274         // and is no longer valid) and recompute it using the fragment in which it flows as reference.
275         bool wasComputedRelativeToOtherFragment = false;
276         while (objContainingBlock && !is<RenderView>(*objContainingBlock)) {
277             // Check if this object is in a different fragment.
278             RenderFragmentContainer* parentStartFragment = nullptr;
279             RenderFragmentContainer* parentEndFragment = nullptr;
280             if (getFragmentRangeForBox(objContainingBlock, parentStartFragment, parentEndFragment) && parentStartFragment != startFragment) {
281                 wasComputedRelativeToOtherFragment = true;
282                 break;
283             }
284             objContainingBlock = objContainingBlock->containingBlock();
285         }
286         
287         if (wasComputedRelativeToOtherFragment) {
288             if (is<RenderBox>(boxModelObject)) {
289                 // Use borderBoxRectInFragment to account for variations such as percentage margins.
290                 LayoutRect borderBoxRect = downcast<RenderBox>(boxModelObject).borderBoxRectInFragment(startFragment, RenderBox::DoNotCacheRenderBoxFragmentInfo);
291                 referencePoint.move(borderBoxRect.location().x(), 0);
292             }
293             
294             // Get the logical top coordinate of the current object.
295             LayoutUnit top = 0;
296             if (is<RenderBlock>(boxModelObject))
297                 top = downcast<RenderBlock>(boxModelObject).offsetFromLogicalTopOfFirstPage();
298             else {
299                 if (boxModelObject.containingBlock())
300                     top = boxModelObject.containingBlock()->offsetFromLogicalTopOfFirstPage();
301                 
302                 if (is<RenderBox>(boxModelObject))
303                     top += downcast<RenderBox>(boxModelObject).topLeftLocation().y();
304                 else if (is<RenderInline>(boxModelObject))
305                     top -= downcast<RenderInline>(boxModelObject).borderTop();
306             }
307             
308             // Get the logical top of the fragment this object starts in
309             // and compute the object's top, relative to the fragment's top.
310             LayoutUnit fragmentLogicalTop = startFragment->pageLogicalTopForOffset(top);
311             LayoutUnit topRelativeToFragment = top - fragmentLogicalTop;
312             referencePoint.setY(startFragmentBox->offsetTop() + topRelativeToFragment);
313             
314             // Since the top has been overridden, check if the
315             // relative/sticky positioning must be reconsidered.
316             if (boxModelObject.isRelativelyPositioned())
317                 referencePoint.move(0, boxModelObject.relativePositionOffset().height());
318             else if (boxModelObject.isStickilyPositioned())
319                 referencePoint.move(0, boxModelObject.stickyPositionOffset().height());
320         }
321         
322         // Since we're looking for the offset relative to the body, we must also
323         // take into consideration the borders of the fragment.
324         referencePoint.move(startFragmentBox->borderLeft(), startFragmentBox->borderTop());
325     }
326     
327     return referencePoint;
328 }
329
330 LayoutUnit RenderFragmentedFlow::pageLogicalTopForOffset(LayoutUnit offset) const
331 {
332     RenderFragmentContainer* fragment = fragmentAtBlockOffset(0, offset, false);
333     return fragment ? fragment->pageLogicalTopForOffset(offset) : LayoutUnit();
334 }
335
336 LayoutUnit RenderFragmentedFlow::pageLogicalWidthForOffset(LayoutUnit offset) const
337 {
338     RenderFragmentContainer* fragment = fragmentAtBlockOffset(0, offset, true);
339     return fragment ? fragment->pageLogicalWidth() : contentLogicalWidth();
340 }
341
342 LayoutUnit RenderFragmentedFlow::pageLogicalHeightForOffset(LayoutUnit offset) const
343 {
344     RenderFragmentContainer* fragment = fragmentAtBlockOffset(0, offset, false);
345     if (!fragment)
346         return 0;
347
348     return fragment->pageLogicalHeight();
349 }
350
351 LayoutUnit RenderFragmentedFlow::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule) const
352 {
353     RenderFragmentContainer* fragment = fragmentAtBlockOffset(0, offset, false);
354     if (!fragment)
355         return 0;
356
357     LayoutUnit pageLogicalTop = fragment->pageLogicalTopForOffset(offset);
358     LayoutUnit pageLogicalHeight = fragment->pageLogicalHeight();
359     LayoutUnit pageLogicalBottom = pageLogicalTop + pageLogicalHeight;
360     LayoutUnit remainingHeight = pageLogicalBottom - offset;
361     if (pageBoundaryRule == IncludePageBoundary) {
362         // If IncludePageBoundary is set, the line exactly on the top edge of a
363         // fragment will act as being part of the previous fragment.
364         remainingHeight = intMod(remainingHeight, pageLogicalHeight);
365     }
366     return remainingHeight;
367 }
368
369 RenderFragmentContainer* RenderFragmentedFlow::mapFromFlowToFragment(TransformState& transformState) const
370 {
371     if (!hasValidFragmentInfo())
372         return nullptr;
373
374     RenderFragmentContainer* RenderFragmentContainer = currentFragment();
375     if (!RenderFragmentContainer) {
376         LayoutRect boxRect = transformState.mappedQuad().enclosingBoundingBox();
377         flipForWritingMode(boxRect);
378
379         LayoutPoint center = boxRect.center();
380         RenderFragmentContainer = fragmentAtBlockOffset(this, isHorizontalWritingMode() ? center.y() : center.x(), true);
381         if (!RenderFragmentContainer)
382             return nullptr;
383     }
384
385     LayoutRect flippedFragmentRect(RenderFragmentContainer->fragmentedFlowPortionRect());
386     flipForWritingMode(flippedFragmentRect);
387
388     transformState.move(RenderFragmentContainer->contentBoxRect().location() - flippedFragmentRect.location());
389
390     return RenderFragmentContainer;
391 }
392
393 void RenderFragmentedFlow::removeRenderBoxFragmentInfo(RenderBox& box)
394 {
395     if (!hasFragments())
396         return;
397
398     // If the fragment chain was invalidated the next layout will clear the box information from all the fragments.
399     if (m_fragmentsInvalidated) {
400         ASSERT(selfNeedsLayout());
401         return;
402     }
403
404     RenderFragmentContainer* startFragment = nullptr;
405     RenderFragmentContainer* endFragment = nullptr;
406     if (getFragmentRangeForBox(&box, startFragment, endFragment)) {
407         for (auto it = m_fragmentList.find(startFragment), end = m_fragmentList.end(); it != end; ++it) {
408             RenderFragmentContainer* fragment = *it;
409             fragment->removeRenderBoxFragmentInfo(box);
410             if (fragment == endFragment)
411                 break;
412         }
413     }
414
415 #ifndef NDEBUG
416     // We have to make sure we did not leave any RenderBoxFragmentInfo attached.
417     for (auto& fragment : m_fragmentList)
418         ASSERT(!fragment->renderBoxFragmentInfo(&box));
419 #endif
420
421     m_fragmentRangeMap.remove(&box);
422 }
423
424 void RenderFragmentedFlow::removeLineFragmentInfo(const RenderBlockFlow& blockFlow)
425 {
426     if (!m_lineToFragmentMap || blockFlow.lineLayoutPath() == SimpleLinesPath)
427         return;
428
429     for (auto* curr = blockFlow.firstRootBox(); curr; curr = curr->nextRootBox())
430         m_lineToFragmentMap->remove(curr);
431
432     ASSERT_WITH_SECURITY_IMPLICATION(checkLinesConsistency(blockFlow));
433 }
434
435 void RenderFragmentedFlow::logicalWidthChangedInFragmentsForBlock(const RenderBlock* block, bool& relayoutChildren)
436 {
437     if (!hasValidFragmentInfo())
438         return;
439
440     auto it = m_fragmentRangeMap.find(block);
441     if (it == m_fragmentRangeMap.end())
442         return;
443
444     RenderFragmentContainerRange& range = it->value;
445     bool rangeInvalidated = range.rangeInvalidated();
446     range.clearRangeInvalidated();
447
448     // If there will be a relayout anyway skip the next steps because they only verify
449     // the state of the ranges.
450     if (relayoutChildren)
451         return;
452
453     // Not necessary for the flow thread, since we already computed the correct info for it.
454     // If the fragments have changed invalidate the children.
455     if (block == this) {
456         relayoutChildren = m_pageLogicalSizeChanged;
457         return;
458     }
459
460     RenderFragmentContainer* startFragment = nullptr;
461     RenderFragmentContainer* endFragment = nullptr;
462     if (!getFragmentRangeForBox(block, startFragment, endFragment))
463         return;
464
465     for (auto it = m_fragmentList.find(startFragment), end = m_fragmentList.end(); it != end; ++it) {
466         RenderFragmentContainer* fragment = *it;
467         ASSERT(!fragment->needsLayout() || fragment->isRenderFragmentContainerSet());
468
469         // We have no information computed for this fragment so we need to do it.
470         std::unique_ptr<RenderBoxFragmentInfo> oldInfo = fragment->takeRenderBoxFragmentInfo(block);
471         if (!oldInfo) {
472             relayoutChildren = rangeInvalidated;
473             return;
474         }
475
476         LayoutUnit oldLogicalWidth = oldInfo->logicalWidth();
477         RenderBoxFragmentInfo* newInfo = block->renderBoxFragmentInfo(fragment);
478         if (!newInfo || newInfo->logicalWidth() != oldLogicalWidth) {
479             relayoutChildren = true;
480             return;
481         }
482
483         if (fragment == endFragment)
484             break;
485     }
486 }
487
488 LayoutUnit RenderFragmentedFlow::contentLogicalWidthOfFirstFragment() const
489 {
490     RenderFragmentContainer* firstValidFragmentInFlow = firstFragment();
491     if (!firstValidFragmentInFlow)
492         return 0;
493     return isHorizontalWritingMode() ? firstValidFragmentInFlow->contentWidth() : firstValidFragmentInFlow->contentHeight();
494 }
495
496 LayoutUnit RenderFragmentedFlow::contentLogicalHeightOfFirstFragment() const
497 {
498     RenderFragmentContainer* firstValidFragmentInFlow = firstFragment();
499     if (!firstValidFragmentInFlow)
500         return 0;
501     return isHorizontalWritingMode() ? firstValidFragmentInFlow->contentHeight() : firstValidFragmentInFlow->contentWidth();
502 }
503
504 LayoutUnit RenderFragmentedFlow::contentLogicalLeftOfFirstFragment() const
505 {
506     RenderFragmentContainer* firstValidFragmentInFlow = firstFragment();
507     if (!firstValidFragmentInFlow)
508         return 0;
509     return isHorizontalWritingMode() ? firstValidFragmentInFlow->fragmentedFlowPortionRect().x() : firstValidFragmentInFlow->fragmentedFlowPortionRect().y();
510 }
511
512 RenderFragmentContainer* RenderFragmentedFlow::firstFragment() const
513 {
514     if (!hasFragments())
515         return nullptr;
516     return m_fragmentList.first();
517 }
518
519 RenderFragmentContainer* RenderFragmentedFlow::lastFragment() const
520 {
521     if (!hasFragments())
522         return nullptr;
523     return m_fragmentList.last();
524 }
525
526 void RenderFragmentedFlow::clearRenderBoxFragmentInfoAndCustomStyle(const RenderBox& box,
527     const RenderFragmentContainer* newStartFragment, const RenderFragmentContainer* newEndFragment,
528     const RenderFragmentContainer* oldStartFragment, const RenderFragmentContainer* oldEndFragment)
529 {
530     ASSERT(newStartFragment && newEndFragment && oldStartFragment && oldEndFragment);
531
532     bool insideOldFragmentRange = false;
533     bool insideNewFragmentRange = false;
534     for (auto& fragment : m_fragmentList) {
535         if (oldStartFragment == fragment)
536             insideOldFragmentRange = true;
537         if (newStartFragment == fragment)
538             insideNewFragmentRange = true;
539
540         if (!(insideOldFragmentRange && insideNewFragmentRange)) {
541             if (fragment->renderBoxFragmentInfo(&box))
542                 fragment->removeRenderBoxFragmentInfo(box);
543         }
544
545         if (oldEndFragment == fragment)
546             insideOldFragmentRange = false;
547         if (newEndFragment == fragment)
548             insideNewFragmentRange = false;
549     }
550 }
551
552 void RenderFragmentedFlow::setFragmentRangeForBox(const RenderBox& box, RenderFragmentContainer* startFragment, RenderFragmentContainer* endFragment)
553 {
554     ASSERT(hasFragments());
555     ASSERT(startFragment && endFragment && startFragment->fragmentedFlow() == this && endFragment->fragmentedFlow() == this);
556     auto result = m_fragmentRangeMap.set(&box, RenderFragmentContainerRange(startFragment, endFragment));
557     if (result.isNewEntry)
558         return;
559
560     // If nothing changed, just bail.
561     auto& range = result.iterator->value;
562     if (range.startFragment() == startFragment && range.endFragment() == endFragment)
563         return;
564     clearRenderBoxFragmentInfoAndCustomStyle(box, startFragment, endFragment, range.startFragment(), range.endFragment());
565 }
566
567 bool RenderFragmentedFlow::hasCachedFragmentRangeForBox(const RenderBox& box) const
568 {
569     return m_fragmentRangeMap.contains(&box);
570 }
571
572 bool RenderFragmentedFlow::getFragmentRangeForBoxFromCachedInfo(const RenderBox* box, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const
573 {
574     ASSERT(box);
575     ASSERT(hasValidFragmentInfo());
576     ASSERT((startFragment == nullptr) && (endFragment == nullptr));
577
578     auto it = m_fragmentRangeMap.find(box);
579     if (it != m_fragmentRangeMap.end()) {
580         const RenderFragmentContainerRange& range = it->value;
581         startFragment = range.startFragment();
582         endFragment = range.endFragment();
583         ASSERT(m_fragmentList.contains(startFragment) && m_fragmentList.contains(endFragment));
584         return true;
585     }
586
587     return false;
588 }
589
590 bool RenderFragmentedFlow::getFragmentRangeForBox(const RenderBox* box, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const
591 {
592     ASSERT(box);
593
594     startFragment = endFragment = nullptr;
595     if (!hasValidFragmentInfo()) // We clear the ranges when we invalidate the fragments.
596         return false;
597
598     if (m_fragmentList.size() == 1) {
599         startFragment = endFragment = m_fragmentList.first();
600         return true;
601     }
602
603     if (getFragmentRangeForBoxFromCachedInfo(box, startFragment, endFragment))
604         return true;
605
606     return false;
607 }
608
609 bool RenderFragmentedFlow::computedFragmentRangeForBox(const RenderBox* box, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const
610 {
611     ASSERT(box);
612
613     startFragment = endFragment = nullptr;
614     if (!hasValidFragmentInfo()) // We clear the ranges when we invalidate the fragments.
615         return false;
616
617     if (getFragmentRangeForBox(box, startFragment, endFragment))
618         return true;
619
620     // Search the fragment range using the information provided by the containing block chain.
621     auto* containingBlock = const_cast<RenderBox*>(box);
622     while (!containingBlock->isRenderFragmentedFlow()) {
623         InlineElementBox* boxWrapper = containingBlock->inlineBoxWrapper();
624         if (boxWrapper && boxWrapper->root().containingFragment()) {
625             startFragment = endFragment = boxWrapper->root().containingFragment();
626             ASSERT(m_fragmentList.contains(startFragment));
627             return true;
628         }
629
630         // FIXME: Use the containingBlock() value once we patch all the layout systems to be fragment range aware
631         // (e.g. if we use containingBlock() the shadow controls of a video element won't get the range from the
632         // video box because it's not a block; they need to be patched separately).
633         ASSERT(containingBlock->parent());
634         containingBlock = &containingBlock->parent()->enclosingBox();
635         ASSERT(containingBlock);
636
637         // If a box doesn't have a cached fragment range it usually means the box belongs to a line so startFragment should be equal with endFragment.
638         // FIXME: Find the cases when this startFragment should not be equal with endFragment and make sure these boxes have cached fragment ranges.
639         if (containingBlock && hasCachedFragmentRangeForBox(*containingBlock)) {
640             startFragment = endFragment = fragmentAtBlockOffset(containingBlock, containingBlock->offsetFromLogicalTopOfFirstPage(), true);
641             return true;
642         }
643     }
644     ASSERT_NOT_REACHED();
645     return false;
646 }
647
648 bool RenderFragmentedFlow::fragmentInRange(const RenderFragmentContainer* targetFragment, const RenderFragmentContainer* startFragment, const RenderFragmentContainer* endFragment) const
649 {
650     ASSERT(targetFragment);
651
652     for (auto it = m_fragmentList.find(const_cast<RenderFragmentContainer*>(startFragment)), end = m_fragmentList.end(); it != end; ++it) {
653         const RenderFragmentContainer* currFragment = *it;
654         if (targetFragment == currFragment)
655             return true;
656         if (currFragment == endFragment)
657             break;
658     }
659
660     return false;
661 }
662
663 bool RenderFragmentedFlow::objectShouldFragmentInFlowFragment(const RenderObject* object, const RenderFragmentContainer* fragment) const
664 {
665     ASSERT(object);
666     ASSERT(fragment);
667     
668     RenderFragmentedFlow* fragmentedFlow = object->enclosingFragmentedFlow();
669     if (fragmentedFlow != this)
670         return false;
671
672     if (!m_fragmentList.contains(const_cast<RenderFragmentContainer*>(fragment)))
673         return false;
674     
675     RenderFragmentContainer* enclosingBoxStartFragment = nullptr;
676     RenderFragmentContainer* enclosingBoxEndFragment = nullptr;
677     // If the box has no range, do not check fragmentInRange. Boxes inside inlines do not get ranges.
678     // Instead, the containing RootInlineBox will abort when trying to paint inside the wrong fragment.
679     if (computedFragmentRangeForBox(&object->enclosingBox(), enclosingBoxStartFragment, enclosingBoxEndFragment)
680         && !fragmentInRange(fragment, enclosingBoxStartFragment, enclosingBoxEndFragment))
681         return false;
682     
683     return object->isBox() || object->isRenderInline();
684 }
685
686 bool RenderFragmentedFlow::objectInFlowFragment(const RenderObject* object, const RenderFragmentContainer* fragment) const
687 {
688     ASSERT(object);
689     ASSERT(fragment);
690
691     RenderFragmentedFlow* fragmentedFlow = object->enclosingFragmentedFlow();
692     if (fragmentedFlow != this)
693         return false;
694
695     if (!m_fragmentList.contains(const_cast<RenderFragmentContainer*>(fragment)))
696         return false;
697
698     RenderFragmentContainer* enclosingBoxStartFragment = nullptr;
699     RenderFragmentContainer* enclosingBoxEndFragment = nullptr;
700     if (!getFragmentRangeForBox(&object->enclosingBox(), enclosingBoxStartFragment, enclosingBoxEndFragment))
701         return false;
702
703     if (!fragmentInRange(fragment, enclosingBoxStartFragment, enclosingBoxEndFragment))
704         return false;
705
706     if (object->isBox())
707         return true;
708
709     LayoutRect objectABBRect = object->absoluteBoundingBoxRect(true);
710     if (!objectABBRect.width())
711         objectABBRect.setWidth(1);
712     if (!objectABBRect.height())
713         objectABBRect.setHeight(1); 
714     if (objectABBRect.intersects(fragment->absoluteBoundingBoxRect(true)))
715         return true;
716
717     if (fragment == lastFragment()) {
718         // If the object does not intersect any of the enclosing box fragments
719         // then the object is in last fragment.
720         for (auto it = m_fragmentList.find(enclosingBoxStartFragment), end = m_fragmentList.end(); it != end; ++it) {
721             const RenderFragmentContainer* currFragment = *it;
722             if (currFragment == fragment)
723                 break;
724             if (objectABBRect.intersects(currFragment->absoluteBoundingBoxRect(true)))
725                 return false;
726         }
727         return true;
728     }
729
730     return false;
731 }
732
733 #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
734 bool RenderFragmentedFlow::checkLinesConsistency(const RenderBlockFlow& removedBlock) const
735 {
736     if (!m_lineToFragmentMap)
737         return true;
738
739     for (auto& linePair : *m_lineToFragmentMap.get()) {
740         const RootInlineBox* line = linePair.key;
741         RenderFragmentContainer* fragment = linePair.value;
742         if (&line->blockFlow() == &removedBlock)
743             return false;
744         if (line->blockFlow().fragmentedFlowState() == NotInsideFragmentedFlow)
745             return false;
746         if (!m_fragmentList.contains(fragment))
747             return false;
748     }
749
750     return true;
751 }
752 #endif
753
754 void RenderFragmentedFlow::clearLinesToFragmentMap()
755 {
756     if (m_lineToFragmentMap)
757         m_lineToFragmentMap->clear();
758 }
759
760 void RenderFragmentedFlow::deleteLines()
761 {
762     clearLinesToFragmentMap();
763     RenderBlockFlow::deleteLines();
764 }
765
766 void RenderFragmentedFlow::willBeDestroyed()
767 {
768     clearLinesToFragmentMap();
769     RenderBlockFlow::willBeDestroyed();
770 }
771
772 void RenderFragmentedFlow::markFragmentsForOverflowLayoutIfNeeded()
773 {
774     if (!hasFragments())
775         return;
776
777     for (auto& fragment : m_fragmentList)
778         fragment->setNeedsSimplifiedNormalFlowLayout();
779 }
780
781 void RenderFragmentedFlow::updateFragmentsFragmentedFlowPortionRect()
782 {
783     LayoutUnit logicalHeight = 0;
784     // FIXME: Optimize not to clear the interval all the time. This implies manually managing the tree nodes lifecycle.
785     m_fragmentIntervalTree.clear();
786     for (auto& fragment : m_fragmentList) {
787         LayoutUnit fragmentLogicalWidth = fragment->pageLogicalWidth();
788         LayoutUnit fragmentLogicalHeight = std::min<LayoutUnit>(RenderFragmentedFlow::maxLogicalHeight() - logicalHeight, fragment->logicalHeightOfAllFragmentedFlowContent());
789
790         LayoutRect fragmentRect(style().direction() == LTR ? LayoutUnit() : logicalWidth() - fragmentLogicalWidth, logicalHeight, fragmentLogicalWidth, fragmentLogicalHeight);
791
792         fragment->setFragmentedFlowPortionRect(isHorizontalWritingMode() ? fragmentRect : fragmentRect.transposedRect());
793
794         m_fragmentIntervalTree.add(FragmentIntervalTree::createInterval(logicalHeight, logicalHeight + fragmentLogicalHeight, makeWeakPtr(fragment)));
795
796         logicalHeight += fragmentLogicalHeight;
797     }
798 }
799
800 // Even if we require the break to occur at offsetBreakInFragmentedFlow, because fragments may have min/max-height values,
801 // it is possible that the break will occur at a different offset than the original one required.
802 // offsetBreakAdjustment measures the different between the requested break offset and the current break offset.
803 bool RenderFragmentedFlow::addForcedFragmentBreak(const RenderBlock* block, LayoutUnit offsetBreakInFragmentedFlow, RenderBox*, bool, LayoutUnit* offsetBreakAdjustment)
804 {
805     // We need to update the fragments flow thread portion rect because we are going to process
806     // a break on these fragments.
807     updateFragmentsFragmentedFlowPortionRect();
808
809     // Simulate a fragment break at offsetBreakInFragmentedFlow. If it points inside an auto logical height fragment,
810     // then it determines the fragment computed auto height.
811     RenderFragmentContainer* fragment = fragmentAtBlockOffset(block, offsetBreakInFragmentedFlow);
812     if (!fragment)
813         return false;
814
815     LayoutUnit currentFragmentOffsetInFragmentedFlow = isHorizontalWritingMode() ? fragment->fragmentedFlowPortionRect().y() : fragment->fragmentedFlowPortionRect().x();
816
817     currentFragmentOffsetInFragmentedFlow += isHorizontalWritingMode() ? fragment->fragmentedFlowPortionRect().height() : fragment->fragmentedFlowPortionRect().width();
818
819     if (offsetBreakAdjustment)
820         *offsetBreakAdjustment = std::max<LayoutUnit>(0, currentFragmentOffsetInFragmentedFlow - offsetBreakInFragmentedFlow);
821
822     return false;
823 }
824
825 void RenderFragmentedFlow::collectLayerFragments(LayerFragments& layerFragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
826 {
827     ASSERT(!m_fragmentsInvalidated);
828     
829     for (auto& fragment : m_fragmentList)
830         fragment->collectLayerFragments(layerFragments, layerBoundingBox, dirtyRect);
831 }
832
833 LayoutRect RenderFragmentedFlow::fragmentsBoundingBox(const LayoutRect& layerBoundingBox)
834 {
835     ASSERT(!m_fragmentsInvalidated);
836     
837     LayoutRect result;
838     for (auto& fragment : m_fragmentList) {
839         LayerFragments fragments;
840         fragment->collectLayerFragments(fragments, layerBoundingBox, LayoutRect::infiniteRect());
841         for (const auto& fragment : fragments) {
842             LayoutRect fragmentRect(layerBoundingBox);
843             fragmentRect.intersect(fragment.paginationClip);
844             fragmentRect.move(fragment.paginationOffset);
845             result.unite(fragmentRect);
846         }
847     }
848     
849     return result;
850 }
851
852 LayoutUnit RenderFragmentedFlow::offsetFromLogicalTopOfFirstFragment(const RenderBlock* currentBlock) const
853 {
854     // As a last resort, take the slow path.
855     LayoutRect blockRect(0, 0, currentBlock->width(), currentBlock->height());
856     while (currentBlock && !is<RenderView>(*currentBlock) && !currentBlock->isRenderFragmentedFlow()) {
857         RenderBlock* containerBlock = currentBlock->containingBlock();
858         ASSERT(containerBlock);
859         if (!containerBlock)
860             return 0;
861         LayoutPoint currentBlockLocation = currentBlock->location();
862         if (is<RenderTableCell>(*currentBlock)) {
863             if (auto* section = downcast<RenderTableCell>(*currentBlock).section())
864                 currentBlockLocation.moveBy(section->location());
865         }
866
867         if (containerBlock->style().writingMode() != currentBlock->style().writingMode()) {
868             // We have to put the block rect in container coordinates
869             // and we have to take into account both the container and current block flipping modes
870             if (containerBlock->style().isFlippedBlocksWritingMode()) {
871                 if (containerBlock->isHorizontalWritingMode())
872                     blockRect.setY(currentBlock->height() - blockRect.maxY());
873                 else
874                     blockRect.setX(currentBlock->width() - blockRect.maxX());
875             }
876             currentBlock->flipForWritingMode(blockRect);
877         }
878         blockRect.moveBy(currentBlockLocation);
879         currentBlock = containerBlock;
880     }
881
882     return currentBlock->isHorizontalWritingMode() ? blockRect.y() : blockRect.x();
883 }
884
885 void RenderFragmentedFlow::FragmentSearchAdapter::collectIfNeeded(const FragmentInterval& interval)
886 {
887     if (m_result)
888         return;
889     if (interval.low() <= m_offset && interval.high() > m_offset)
890         m_result = interval.data();
891 }
892
893 void RenderFragmentedFlow::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
894 {
895     if (this == repaintContainer)
896         return;
897
898     if (RenderFragmentContainer* fragment = mapFromFlowToFragment(transformState)) {
899         // FIXME: The cast below is probably not the best solution, we may need to find a better way.
900         const RenderObject* fragmentObject = static_cast<const RenderObject*>(fragment);
901
902         // If the repaint container is nullptr, we have to climb up to the RenderView, otherwise swap
903         // it with the fragment's repaint container.
904         repaintContainer = repaintContainer ? fragment->containerForRepaint() : nullptr;
905
906         if (RenderFragmentedFlow* fragmentFragmentedFlow = fragment->enclosingFragmentedFlow()) {
907             RenderFragmentContainer* startFragment = nullptr;
908             RenderFragmentContainer* endFragment = nullptr;
909             if (fragmentFragmentedFlow->getFragmentRangeForBox(fragment, startFragment, endFragment)) {
910                 CurrentRenderFragmentContainerMaintainer fragmentMaintainer(*startFragment);
911                 fragmentObject->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
912                 return;
913             }
914         }
915
916         fragmentObject->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
917     }
918 }
919
920 // FIXME: Make this function faster. Walking the render tree is slow, better use a caching mechanism (e.g. |cachedOffsetFromLogicalTopOfFirstFragment|).
921 LayoutRect RenderFragmentedFlow::mapFromLocalToFragmentedFlow(const RenderBox* box, const LayoutRect& localRect) const
922 {
923     LayoutRect boxRect = localRect;
924
925     while (box && box != this) {
926         RenderBlock* containerBlock = box->containingBlock();
927         ASSERT(containerBlock);
928         if (!containerBlock)
929             return LayoutRect();
930         LayoutPoint currentBoxLocation = box->location();
931
932         if (containerBlock->style().writingMode() != box->style().writingMode())
933             box->flipForWritingMode(boxRect);
934
935         boxRect.moveBy(currentBoxLocation);
936         box = containerBlock;
937     }
938
939     return boxRect;
940 }
941
942 // FIXME: Make this function faster. Walking the render tree is slow, better use a caching mechanism (e.g. |cachedOffsetFromLogicalTopOfFirstFragment|).
943 LayoutRect RenderFragmentedFlow::mapFromFragmentedFlowToLocal(const RenderBox* box, const LayoutRect& rect) const
944 {
945     LayoutRect localRect = rect;
946     if (box == this)
947         return localRect;
948
949     RenderBlock* containerBlock = box->containingBlock();
950     ASSERT(containerBlock);
951     if (!containerBlock)
952         return LayoutRect();
953     localRect = mapFromFragmentedFlowToLocal(containerBlock, localRect);
954
955     LayoutPoint currentBoxLocation = box->location();
956     localRect.moveBy(-currentBoxLocation);
957
958     if (containerBlock->style().writingMode() != box->style().writingMode())
959         box->flipForWritingMode(localRect);
960
961     return localRect;
962 }
963
964 void RenderFragmentedFlow::flipForWritingModeLocalCoordinates(LayoutRect& rect) const
965 {
966     if (!style().isFlippedBlocksWritingMode())
967         return;
968     
969     if (isHorizontalWritingMode())
970         rect.setY(0 - rect.maxY());
971     else
972         rect.setX(0 - rect.maxX());
973 }
974
975 void RenderFragmentedFlow::addFragmentsVisualEffectOverflow(const RenderBox* box)
976 {
977     RenderFragmentContainer* startFragment = nullptr;
978     RenderFragmentContainer* endFragment = nullptr;
979     if (!getFragmentRangeForBox(box, startFragment, endFragment))
980         return;
981
982     for (auto iter = m_fragmentList.find(startFragment), end = m_fragmentList.end(); iter != end; ++iter) {
983         RenderFragmentContainer* fragment = *iter;
984
985         LayoutRect borderBox = box->borderBoxRectInFragment(fragment);
986         borderBox = box->applyVisualEffectOverflow(borderBox);
987         borderBox = fragment->rectFlowPortionForBox(box, borderBox);
988
989         fragment->addVisualOverflowForBox(box, borderBox);
990         if (fragment == endFragment)
991             break;
992     }
993 }
994
995 void RenderFragmentedFlow::addFragmentsVisualOverflowFromTheme(const RenderBlock* block)
996 {
997     RenderFragmentContainer* startFragment = nullptr;
998     RenderFragmentContainer* endFragment = nullptr;
999     if (!getFragmentRangeForBox(block, startFragment, endFragment))
1000         return;
1001
1002     for (auto iter = m_fragmentList.find(startFragment), end = m_fragmentList.end(); iter != end; ++iter) {
1003         RenderFragmentContainer* fragment = *iter;
1004
1005         LayoutRect borderBox = block->borderBoxRectInFragment(fragment);
1006         borderBox = fragment->rectFlowPortionForBox(block, borderBox);
1007
1008         FloatRect inflatedRect = borderBox;
1009         block->theme().adjustRepaintRect(*block, inflatedRect);
1010
1011         fragment->addVisualOverflowForBox(block, snappedIntRect(LayoutRect(inflatedRect)));
1012         if (fragment == endFragment)
1013             break;
1014     }
1015 }
1016
1017 void RenderFragmentedFlow::addFragmentsOverflowFromChild(const RenderBox* box, const RenderBox* child, const LayoutSize& delta)
1018 {
1019     RenderFragmentContainer* startFragment = nullptr;
1020     RenderFragmentContainer* endFragment = nullptr;
1021     if (!getFragmentRangeForBox(child, startFragment, endFragment))
1022         return;
1023
1024     RenderFragmentContainer* containerStartFragment = nullptr;
1025     RenderFragmentContainer* containerEndFragment = nullptr;
1026     if (!getFragmentRangeForBox(box, containerStartFragment, containerEndFragment))
1027         return;
1028
1029     for (auto iter = m_fragmentList.find(startFragment), end = m_fragmentList.end(); iter != end; ++iter) {
1030         RenderFragmentContainer* fragment = *iter;
1031         if (!fragmentInRange(fragment, containerStartFragment, containerEndFragment)) {
1032             if (fragment == endFragment)
1033                 break;
1034             continue;
1035         }
1036
1037         LayoutRect childLayoutOverflowRect = fragment->layoutOverflowRectForBoxForPropagation(child);
1038         childLayoutOverflowRect.move(delta);
1039         
1040         fragment->addLayoutOverflowForBox(box, childLayoutOverflowRect);
1041
1042         if (child->hasSelfPaintingLayer() || box->hasOverflowClip()) {
1043             if (fragment == endFragment)
1044                 break;
1045             continue;
1046         }
1047         LayoutRect childVisualOverflowRect = fragment->visualOverflowRectForBoxForPropagation(*child);
1048         childVisualOverflowRect.move(delta);
1049         fragment->addVisualOverflowForBox(box, childVisualOverflowRect);
1050
1051         if (fragment == endFragment)
1052             break;
1053     }
1054 }
1055     
1056 void RenderFragmentedFlow::addFragmentsLayoutOverflow(const RenderBox* box, const LayoutRect& layoutOverflow)
1057 {
1058     RenderFragmentContainer* startFragment = nullptr;
1059     RenderFragmentContainer* endFragment = nullptr;
1060     if (!getFragmentRangeForBox(box, startFragment, endFragment))
1061         return;
1062
1063     for (auto iter = m_fragmentList.find(startFragment), end = m_fragmentList.end(); iter != end; ++iter) {
1064         RenderFragmentContainer* fragment = *iter;
1065         LayoutRect layoutOverflowInFragment = fragment->rectFlowPortionForBox(box, layoutOverflow);
1066
1067         fragment->addLayoutOverflowForBox(box, layoutOverflowInFragment);
1068
1069         if (fragment == endFragment)
1070             break;
1071     }
1072 }
1073
1074 void RenderFragmentedFlow::addFragmentsVisualOverflow(const RenderBox* box, const LayoutRect& visualOverflow)
1075 {
1076     RenderFragmentContainer* startFragment = nullptr;
1077     RenderFragmentContainer* endFragment = nullptr;
1078     if (!getFragmentRangeForBox(box, startFragment, endFragment))
1079         return;
1080     
1081     for (RenderFragmentContainerList::iterator iter = m_fragmentList.find(startFragment); iter != m_fragmentList.end(); ++iter) {
1082         RenderFragmentContainer* fragment = *iter;
1083         LayoutRect visualOverflowInFragment = fragment->rectFlowPortionForBox(box, visualOverflow);
1084         
1085         fragment->addVisualOverflowForBox(box, visualOverflowInFragment);
1086         
1087         if (fragment == endFragment)
1088             break;
1089     }
1090 }
1091
1092 void RenderFragmentedFlow::clearFragmentsOverflow(const RenderBox* box)
1093 {
1094     RenderFragmentContainer* startFragment = nullptr;
1095     RenderFragmentContainer* endFragment = nullptr;
1096     if (!getFragmentRangeForBox(box, startFragment, endFragment))
1097         return;
1098
1099     for (auto iter = m_fragmentList.find(startFragment), end = m_fragmentList.end(); iter != end; ++iter) {
1100         RenderFragmentContainer* fragment = *iter;
1101         RenderBoxFragmentInfo* boxInfo = fragment->renderBoxFragmentInfo(box);
1102         if (boxInfo && boxInfo->overflow())
1103             boxInfo->clearOverflow();
1104
1105         if (fragment == endFragment)
1106             break;
1107     }
1108 }
1109
1110 RenderFragmentContainer* RenderFragmentedFlow::currentFragment() const
1111 {
1112     return m_currentFragmentMaintainer ? &m_currentFragmentMaintainer->fragment() : nullptr;
1113 }
1114
1115 ContainingFragmentMap& RenderFragmentedFlow::containingFragmentMap()
1116 {
1117     if (!m_lineToFragmentMap)
1118         m_lineToFragmentMap = std::make_unique<ContainingFragmentMap>();
1119
1120     return *m_lineToFragmentMap.get();
1121 }
1122
1123
1124 } // namespace WebCore