Replace PassRef with Ref/Ref&& across the board.
[WebKit-https.git] / Source / WebCore / rendering / RenderRegion.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 "RenderRegion.h"
32
33 #include "FlowThreadController.h"
34 #include "GraphicsContext.h"
35 #include "HitTestResult.h"
36 #include "IntRect.h"
37 #include "LayoutRepainter.h"
38 #include "PaintInfo.h"
39 #include "Range.h"
40 #include "RenderBoxRegionInfo.h"
41 #include "RenderInline.h"
42 #include "RenderIterator.h"
43 #include "RenderLayer.h"
44 #include "RenderNamedFlowFragment.h"
45 #include "RenderNamedFlowThread.h"
46 #include "RenderView.h"
47 #include "StyleResolver.h"
48
49 namespace WebCore {
50
51 RenderRegion::RenderRegion(Element& element, Ref<RenderStyle>&& style, RenderFlowThread* flowThread)
52     : RenderBlockFlow(element, WTF::move(style))
53     , m_flowThread(flowThread)
54     , m_parentNamedFlowThread(nullptr)
55     , m_isValid(false)
56 {
57 }
58
59 RenderRegion::RenderRegion(Document& document, Ref<RenderStyle>&& style, RenderFlowThread* flowThread)
60     : RenderBlockFlow(document, WTF::move(style))
61     , m_flowThread(flowThread)
62     , m_parentNamedFlowThread(nullptr)
63     , m_isValid(false)
64 {
65 }
66
67 LayoutPoint RenderRegion::mapRegionPointIntoFlowThreadCoordinates(const LayoutPoint& point)
68 {
69     // Assuming the point is relative to the region block, 3 cases will be considered:
70     // a) top margin, padding or border.
71     // b) bottom margin, padding or border.
72     // c) non-content region area.
73
74     LayoutUnit pointLogicalTop(isHorizontalWritingMode() ? point.y() : point.x());
75     LayoutUnit pointLogicalLeft(isHorizontalWritingMode() ? point.x() : point.y());
76     LayoutUnit flowThreadLogicalTop(isHorizontalWritingMode() ? m_flowThreadPortionRect.y() : m_flowThreadPortionRect.x());
77     LayoutUnit flowThreadLogicalLeft(isHorizontalWritingMode() ? m_flowThreadPortionRect.x() : m_flowThreadPortionRect.y());
78     LayoutUnit flowThreadPortionTopBound(isHorizontalWritingMode() ? m_flowThreadPortionRect.height() : m_flowThreadPortionRect.width());
79     LayoutUnit flowThreadPortionLeftBound(isHorizontalWritingMode() ? m_flowThreadPortionRect.width() : m_flowThreadPortionRect.height());
80     LayoutUnit flowThreadPortionTopMax(isHorizontalWritingMode() ? m_flowThreadPortionRect.maxY() : m_flowThreadPortionRect.maxX());
81     LayoutUnit flowThreadPortionLeftMax(isHorizontalWritingMode() ? m_flowThreadPortionRect.maxX() : m_flowThreadPortionRect.maxY());
82     LayoutUnit effectiveFixedPointDenominator;
83     effectiveFixedPointDenominator.setRawValue(1);
84
85     if (pointLogicalTop < 0) {
86         LayoutPoint pointInThread(0, flowThreadLogicalTop);
87         return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
88     }
89
90     if (pointLogicalTop >= flowThreadPortionTopBound) {
91         LayoutPoint pointInThread(flowThreadPortionLeftBound, flowThreadPortionTopMax - effectiveFixedPointDenominator);
92         return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
93     }
94
95     if (pointLogicalLeft < 0) {
96         LayoutPoint pointInThread(flowThreadLogicalLeft, pointLogicalTop + flowThreadLogicalTop);
97         return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
98     }
99     if (pointLogicalLeft >= flowThreadPortionLeftBound) {
100         LayoutPoint pointInThread(flowThreadPortionLeftMax - effectiveFixedPointDenominator, pointLogicalTop + flowThreadLogicalTop);
101         return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
102     }
103     LayoutPoint pointInThread(pointLogicalLeft + flowThreadLogicalLeft, pointLogicalTop + flowThreadLogicalTop);
104     return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
105 }
106
107 VisiblePosition RenderRegion::positionForPoint(const LayoutPoint& point, const RenderRegion* region)
108 {
109     if (!isValid() || !m_flowThread->firstChild()) // checking for empty region blocks.
110         return RenderBlock::positionForPoint(point, region);
111
112     return m_flowThread->positionForPoint(mapRegionPointIntoFlowThreadCoordinates(point), this);
113 }
114
115 LayoutUnit RenderRegion::pageLogicalWidth() const
116 {
117     ASSERT(isValid());
118     return m_flowThread->isHorizontalWritingMode() ? contentWidth() : contentHeight();
119 }
120
121 LayoutUnit RenderRegion::pageLogicalHeight() const
122 {
123     ASSERT(isValid());
124     return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
125 }
126
127 LayoutUnit RenderRegion::logicalHeightOfAllFlowThreadContent() const
128 {
129     return pageLogicalHeight();
130 }
131
132 LayoutRect RenderRegion::flowThreadPortionOverflowRect()
133 {
134     return overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegion(), isLastRegion(), VisualOverflow);
135 }
136
137 LayoutPoint RenderRegion::flowThreadPortionLocation() const
138 {
139     LayoutPoint portionLocation;
140     LayoutRect portionRect = flowThreadPortionRect();
141
142     if (flowThread()->style().isFlippedBlocksWritingMode()) {
143         LayoutRect flippedFlowThreadPortionRect(portionRect);
144         flowThread()->flipForWritingMode(flippedFlowThreadPortionRect);
145         portionLocation = flippedFlowThreadPortionRect.location();
146     } else
147         portionLocation = portionRect.location();
148
149     return portionLocation;
150 }
151
152 LayoutRect RenderRegion::overflowRectForFlowThreadPortion(const LayoutRect& flowThreadPortionRect, bool isFirstPortion, bool isLastPortion, OverflowType overflowType)
153 {
154     ASSERT(isValid());
155
156     if (shouldClipFlowThreadContent())
157         return flowThreadPortionRect;
158
159     LayoutRect flowThreadOverflow = overflowType == VisualOverflow ? visualOverflowRectForBox(*m_flowThread) : layoutOverflowRectForBox(m_flowThread);
160
161     // We are interested about the outline size only when computing the visual overflow.
162     LayoutUnit outlineSize = overflowType == VisualOverflow ? LayoutUnit(maximalOutlineSize(PaintPhaseOutline)) : LayoutUnit();
163     LayoutRect clipRect;
164     if (m_flowThread->isHorizontalWritingMode()) {
165         LayoutUnit minY = isFirstPortion ? (flowThreadOverflow.y() - outlineSize) : flowThreadPortionRect.y();
166         LayoutUnit maxY = isLastPortion ? std::max(flowThreadPortionRect.maxY(), flowThreadOverflow.maxY()) + outlineSize : flowThreadPortionRect.maxY();
167         bool clipX = style().overflowX() != OVISIBLE;
168         LayoutUnit minX = clipX ? flowThreadPortionRect.x() : std::min(flowThreadPortionRect.x(), flowThreadOverflow.x() - outlineSize);
169         LayoutUnit maxX = clipX ? flowThreadPortionRect.maxX() : std::max(flowThreadPortionRect.maxX(), (flowThreadOverflow.maxX() + outlineSize));
170         clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
171     } else {
172         LayoutUnit minX = isFirstPortion ? (flowThreadOverflow.x() - outlineSize) : flowThreadPortionRect.x();
173         LayoutUnit maxX = isLastPortion ? std::max(flowThreadPortionRect.maxX(), flowThreadOverflow.maxX()) + outlineSize : flowThreadPortionRect.maxX();
174         bool clipY = style().overflowY() != OVISIBLE;
175         LayoutUnit minY = clipY ? flowThreadPortionRect.y() : std::min(flowThreadPortionRect.y(), (flowThreadOverflow.y() - outlineSize));
176         LayoutUnit maxY = clipY ? flowThreadPortionRect.maxY() : std::max(flowThreadPortionRect.y(), (flowThreadOverflow.maxY() + outlineSize));
177         clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
178     }
179
180     return clipRect;
181 }
182
183 LayoutUnit RenderRegion::pageLogicalTopForOffset(LayoutUnit /* offset */) const
184 {
185     return flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x();
186 }
187
188 bool RenderRegion::isFirstRegion() const
189 {
190     ASSERT(isValid());
191
192     return m_flowThread->firstRegion() == this;
193 }
194
195 bool RenderRegion::isLastRegion() const
196 {
197     ASSERT(isValid());
198
199     return m_flowThread->lastRegion() == this;
200 }
201
202 bool RenderRegion::shouldClipFlowThreadContent() const
203 {
204     return hasOverflowClip();
205 }
206
207 void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
208 {
209     RenderBlockFlow::styleDidChange(diff, oldStyle);
210
211     if (!isValid())
212         return;
213
214     if (oldStyle && oldStyle->writingMode() != style().writingMode())
215         m_flowThread->regionChangedWritingMode(this);
216 }
217
218 void RenderRegion::computeOverflowFromFlowThread()
219 {
220     ASSERT(isValid());
221
222     LayoutRect layoutRect = layoutOverflowRectForBox(m_flowThread);
223     layoutRect.setLocation(contentBoxRect().location() + (layoutRect.location() - m_flowThreadPortionRect.location()));
224
225     // FIXME: Correctly adjust the layout overflow for writing modes.
226     addLayoutOverflow(layoutRect);
227     RenderFlowThread* enclosingRenderFlowThread = flowThreadContainingBlock();
228     if (enclosingRenderFlowThread)
229         enclosingRenderFlowThread->addRegionsLayoutOverflow(this, layoutRect);
230
231     updateLayerTransform();
232     updateScrollInfoAfterLayout();
233 }
234
235 void RenderRegion::repaintFlowThreadContent(const LayoutRect& repaintRect)
236 {
237     repaintFlowThreadContentRectangle(repaintRect, flowThreadPortionRect(), contentBoxRect().location());
238 }
239
240 void RenderRegion::repaintFlowThreadContentRectangle(const LayoutRect& repaintRect, const LayoutRect& flowThreadPortionRect, const LayoutPoint& regionLocation, const LayoutRect* flowThreadPortionClipRect)
241 {
242     ASSERT(isValid());
243
244     // We only have to issue a repaint in this region if the region rect intersects the repaint rect.
245     LayoutRect clippedRect(repaintRect);
246
247     if (flowThreadPortionClipRect) {
248         LayoutRect flippedFlowThreadPortionClipRect(*flowThreadPortionClipRect);
249         flowThread()->flipForWritingMode(flippedFlowThreadPortionClipRect);
250         clippedRect.intersect(flippedFlowThreadPortionClipRect);
251     }
252
253     if (clippedRect.isEmpty())
254         return;
255
256     LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
257     flowThread()->flipForWritingMode(flippedFlowThreadPortionRect); // Put the region rects into physical coordinates.
258
259     // Put the region rect into the region's physical coordinate space.
260     clippedRect.setLocation(regionLocation + (clippedRect.location() - flippedFlowThreadPortionRect.location()));
261
262     // Now switch to the region's writing mode coordinate space and let it repaint itself.
263     flipForWritingMode(clippedRect);
264     
265     // Issue the repaint.
266     repaintRectangle(clippedRect);
267 }
268
269 void RenderRegion::installFlowThread()
270 {
271     m_flowThread = &view().flowThreadController().ensureRenderFlowThreadWithName(style().regionThread());
272
273     // By now the flow thread should already be added to the rendering tree,
274     // so we go up the rendering parents and check that this region is not part of the same
275     // flow that it actually needs to display. It would create a circular reference.
276
277     auto closestFlowThreadAncestor = ancestorsOfType<RenderNamedFlowThread>(*this).first();
278     if (!closestFlowThreadAncestor) {
279         m_parentNamedFlowThread = nullptr;
280         return;
281     }
282
283     m_parentNamedFlowThread = &*closestFlowThreadAncestor;
284 }
285
286 void RenderRegion::attachRegion()
287 {
288     if (documentBeingDestroyed())
289         return;
290     
291     // A region starts off invalid.
292     setIsValid(false);
293
294     // Initialize the flow thread reference and create the flow thread object if needed.
295     // The flow thread lifetime is influenced by the number of regions attached to it,
296     // and we are attaching the region to the flow thread.
297     installFlowThread();
298     
299     if (m_flowThread == m_parentNamedFlowThread)
300         return;
301
302     // Only after adding the region to the thread, the region is marked to be valid.
303     m_flowThread->addRegionToThread(this);
304 }
305
306 void RenderRegion::detachRegion()
307 {
308     if (m_flowThread)
309         m_flowThread->removeRegionFromThread(this);
310     m_flowThread = nullptr;
311 }
312
313 RenderBoxRegionInfo* RenderRegion::renderBoxRegionInfo(const RenderBox* box) const
314 {
315     ASSERT(isValid());
316     return m_renderBoxRegionInfo.get(box);
317 }
318
319 RenderBoxRegionInfo* RenderRegion::setRenderBoxRegionInfo(const RenderBox* box, LayoutUnit logicalLeftInset, LayoutUnit logicalRightInset,
320     bool containingBlockChainIsInset)
321 {
322     ASSERT(isValid());
323
324     std::unique_ptr<RenderBoxRegionInfo>& boxInfo = m_renderBoxRegionInfo.add(box, std::make_unique<RenderBoxRegionInfo>(logicalLeftInset, logicalRightInset, containingBlockChainIsInset)).iterator->value;
325     return boxInfo.get();
326 }
327
328 std::unique_ptr<RenderBoxRegionInfo> RenderRegion::takeRenderBoxRegionInfo(const RenderBox* box)
329 {
330     return m_renderBoxRegionInfo.take(box);
331 }
332
333 void RenderRegion::removeRenderBoxRegionInfo(const RenderBox* box)
334 {
335     m_renderBoxRegionInfo.remove(box);
336 }
337
338 void RenderRegion::deleteAllRenderBoxRegionInfo()
339 {
340     m_renderBoxRegionInfo.clear();
341 }
342
343 LayoutUnit RenderRegion::logicalTopOfFlowThreadContentRect(const LayoutRect& rect) const
344 {
345     ASSERT(isValid());
346     return flowThread()->isHorizontalWritingMode() ? rect.y() : rect.x();
347 }
348
349 LayoutUnit RenderRegion::logicalBottomOfFlowThreadContentRect(const LayoutRect& rect) const
350 {
351     ASSERT(isValid());
352     return flowThread()->isHorizontalWritingMode() ? rect.maxY() : rect.maxX();
353 }
354
355 void RenderRegion::insertedIntoTree()
356 {
357     attachRegion();
358     if (isValid())
359         RenderBlockFlow::insertedIntoTree();
360 }
361
362 void RenderRegion::willBeRemovedFromTree()
363 {
364     RenderBlockFlow::willBeRemovedFromTree();
365
366     detachRegion();
367 }
368
369 void RenderRegion::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
370 {
371     if (!isValid()) {
372         RenderBlockFlow::computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
373         return;
374     }
375
376     minLogicalWidth = m_flowThread->minPreferredLogicalWidth();
377     maxLogicalWidth = m_flowThread->maxPreferredLogicalWidth();
378 }
379
380 void RenderRegion::computePreferredLogicalWidths()
381 {
382     ASSERT(preferredLogicalWidthsDirty());
383
384     if (!isValid()) {
385         RenderBlockFlow::computePreferredLogicalWidths();
386         return;
387     }
388
389     // FIXME: Currently, the code handles only the <length> case for min-width/max-width.
390     // It should also support other values, like percentage, calc or viewport relative.
391     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
392
393     const RenderStyle& styleToUse = style();
394     if (styleToUse.logicalWidth().isFixed() && styleToUse.logicalWidth().value() > 0)
395         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalWidth().value());
396     else
397         computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
398
399     if (styleToUse.logicalMinWidth().isFixed() && styleToUse.logicalMinWidth().value() > 0) {
400         m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
401         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
402     }
403
404     if (styleToUse.logicalMaxWidth().isFixed()) {
405         m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
406         m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
407     }
408
409     LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
410     m_minPreferredLogicalWidth += borderAndPadding;
411     m_maxPreferredLogicalWidth += borderAndPadding;
412     setPreferredLogicalWidthsDirty(false);
413 }
414
415 void RenderRegion::adjustRegionBoundsFromFlowThreadPortionRect(LayoutRect& regionBounds) const
416 {
417     LayoutRect flippedFlowThreadPortionRect = flowThreadPortionRect();
418     flowThread()->flipForWritingMode(flippedFlowThreadPortionRect);
419     regionBounds.moveBy(flippedFlowThreadPortionRect.location());
420 }
421
422 void RenderRegion::ensureOverflowForBox(const RenderBox* box, RefPtr<RenderOverflow>& overflow, bool forceCreation)
423 {
424     ASSERT(m_flowThread->renderRegionList().contains(this));
425     ASSERT(isValid());
426
427     RenderBoxRegionInfo* boxInfo = renderBoxRegionInfo(box);
428     if (!boxInfo && !forceCreation)
429         return;
430
431     if (boxInfo && boxInfo->overflow()) {
432         overflow = boxInfo->overflow();
433         return;
434     }
435     
436     LayoutRect borderBox = box->borderBoxRectInRegion(this);
437     LayoutRect clientBox;
438     ASSERT(m_flowThread->objectShouldFragmentInFlowRegion(box, this));
439
440     if (!borderBox.isEmpty()) {
441         borderBox = rectFlowPortionForBox(box, borderBox);
442         
443         clientBox = box->clientBoxRectInRegion(this);
444         clientBox = rectFlowPortionForBox(box, clientBox);
445         
446         m_flowThread->flipForWritingModeLocalCoordinates(borderBox);
447         m_flowThread->flipForWritingModeLocalCoordinates(clientBox);
448     }
449
450     if (boxInfo) {
451         boxInfo->createOverflow(clientBox, borderBox);
452         overflow = boxInfo->overflow();
453     } else
454         overflow = adoptRef(new RenderOverflow(clientBox, borderBox));
455 }
456
457 LayoutRect RenderRegion::rectFlowPortionForBox(const RenderBox* box, const LayoutRect& rect) const
458 {
459     LayoutRect mappedRect = m_flowThread->mapFromLocalToFlowThread(box, rect);
460
461     RenderRegion* startRegion = nullptr;
462     RenderRegion* endRegion = nullptr;
463     if (m_flowThread->getRegionRangeForBox(box, startRegion, endRegion)) {
464         if (flowThread()->isHorizontalWritingMode()) {
465             if (this != startRegion)
466                 mappedRect.shiftYEdgeTo(std::max<LayoutUnit>(logicalTopForFlowThreadContent(), mappedRect.y()));
467             if (this != endRegion)
468                 mappedRect.setHeight(std::max<LayoutUnit>(0, std::min<LayoutUnit>(logicalBottomForFlowThreadContent() - mappedRect.y(), mappedRect.height())));
469         } else {
470             if (this != startRegion)
471                 mappedRect.shiftXEdgeTo(std::max<LayoutUnit>(logicalTopForFlowThreadContent(), mappedRect.x()));
472             if (this != endRegion)
473                 mappedRect.setWidth(std::max<LayoutUnit>(0, std::min<LayoutUnit>(logicalBottomForFlowThreadContent() - mappedRect.x(), mappedRect.width())));
474         }
475     }
476
477     return m_flowThread->mapFromFlowThreadToLocal(box, mappedRect);
478 }
479
480 void RenderRegion::addLayoutOverflowForBox(const RenderBox* box, const LayoutRect& rect)
481 {
482     if (rect.isEmpty())
483         return;
484
485     RefPtr<RenderOverflow> regionOverflow;
486     ensureOverflowForBox(box, regionOverflow, false);
487
488     if (!regionOverflow)
489         return;
490
491     regionOverflow->addLayoutOverflow(rect);
492 }
493
494 void RenderRegion::addVisualOverflowForBox(const RenderBox* box, const LayoutRect& rect)
495 {
496     if (rect.isEmpty())
497         return;
498
499     RefPtr<RenderOverflow> regionOverflow;
500     ensureOverflowForBox(box, regionOverflow, false);
501
502     if (!regionOverflow)
503         return;
504
505     LayoutRect flippedRect = rect;
506     flowThread()->flipForWritingModeLocalCoordinates(flippedRect);
507     regionOverflow->addVisualOverflow(flippedRect);
508 }
509
510 LayoutRect RenderRegion::layoutOverflowRectForBox(const RenderBox* box)
511 {
512     RefPtr<RenderOverflow> overflow;
513     ensureOverflowForBox(box, overflow, true);
514     
515     ASSERT(overflow);
516     return overflow->layoutOverflowRect();
517 }
518
519 LayoutRect RenderRegion::visualOverflowRectForBox(const RenderBoxModelObject& box)
520 {
521     if (is<RenderInline>(box)) {
522         const RenderInline& inlineBox = downcast<RenderInline>(box);
523         return inlineBox.linesVisualOverflowBoundingBoxInRegion(this);
524     }
525
526     if (is<RenderBox>(box)) {
527         RefPtr<RenderOverflow> overflow;
528         ensureOverflowForBox(&downcast<RenderBox>(box), overflow, true);
529
530         ASSERT(overflow);
531         return overflow->visualOverflowRect();
532     }
533
534     ASSERT_NOT_REACHED();
535     return LayoutRect();
536 }
537
538 // FIXME: This doesn't work for writing modes.
539 LayoutRect RenderRegion::layoutOverflowRectForBoxForPropagation(const RenderBox* box)
540 {
541     // Only propagate interior layout overflow if we don't clip it.
542     LayoutRect rect = box->borderBoxRectInRegion(this);
543     rect = rectFlowPortionForBox(box, rect);
544     if (!box->hasOverflowClip())
545         rect.unite(layoutOverflowRectForBox(box));
546
547     bool hasTransform = box->hasTransform();
548     if (box->isInFlowPositioned() || hasTransform) {
549         if (hasTransform)
550             rect = box->layer()->currentTransform().mapRect(rect);
551
552         if (box->isInFlowPositioned())
553             rect.move(box->offsetForInFlowPosition());
554     }
555
556     return rect;
557 }
558
559 LayoutRect RenderRegion::visualOverflowRectForBoxForPropagation(const RenderBoxModelObject& box)
560 {
561     LayoutRect rect = visualOverflowRectForBox(box);
562     flowThread()->flipForWritingModeLocalCoordinates(rect);
563
564     return rect;
565 }
566
567 CurrentRenderRegionMaintainer::CurrentRenderRegionMaintainer(RenderRegion& region)
568     : m_region(region)
569 {
570     RenderFlowThread* flowThread = region.flowThread();
571     // A flow thread can have only one current region.
572     ASSERT(!flowThread->currentRegion());
573     flowThread->setCurrentRegionMaintainer(this);
574 }
575
576 CurrentRenderRegionMaintainer::~CurrentRenderRegionMaintainer()
577 {
578     RenderFlowThread* flowThread = m_region.flowThread();
579     flowThread->setCurrentRegionMaintainer(nullptr);
580 }
581
582 } // namespace WebCore