2 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
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.
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
32 #include "core/rendering/RenderFlowThread.h"
34 #include "core/dom/Node.h"
35 #include "core/rendering/FlowThreadController.h"
36 #include "core/rendering/HitTestRequest.h"
37 #include "core/rendering/HitTestResult.h"
38 #include "core/rendering/LayoutRectRecorder.h"
39 #include "core/rendering/PaintInfo.h"
40 #include "core/rendering/RenderInline.h"
41 #include "core/rendering/RenderLayer.h"
42 #include "core/rendering/RenderRegion.h"
43 #include "core/rendering/RenderView.h"
44 #include "platform/PODIntervalTree.h"
45 #include "platform/geometry/TransformState.h"
49 RenderFlowThread::RenderFlowThread()
51 , m_previousRegionCount(0)
52 , m_regionsInvalidated(false)
53 , m_regionsHaveUniformLogicalHeight(true)
54 , m_pageLogicalSizeChanged(false)
56 setFlowThreadState(InsideOutOfFlowThread);
59 PassRefPtr<RenderStyle> RenderFlowThread::createFlowThreadStyle(RenderStyle* parentStyle)
61 RefPtr<RenderStyle> newStyle(RenderStyle::create());
62 newStyle->inheritFrom(parentStyle);
63 newStyle->setDisplay(BLOCK);
64 newStyle->setPosition(AbsolutePosition);
65 newStyle->setZIndex(0);
66 newStyle->setLeft(Length(0, Fixed));
67 newStyle->setTop(Length(0, Fixed));
68 newStyle->setWidth(Length(100, Percent));
69 newStyle->setHeight(Length(100, Percent));
70 newStyle->font().update(0);
72 return newStyle.release();
75 void RenderFlowThread::addRegionToThread(RenderRegion* renderRegion)
78 m_regionList.add(renderRegion);
79 renderRegion->setIsValid(true);
82 void RenderFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
85 m_regionList.remove(renderRegion);
88 void RenderFlowThread::invalidateRegions()
90 if (m_regionsInvalidated) {
91 ASSERT(selfNeedsLayout());
95 m_regionRangeMap.clear();
98 m_regionsInvalidated = true;
101 class CurrentRenderFlowThreadDisabler {
102 WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadDisabler);
104 CurrentRenderFlowThreadDisabler(RenderView* view)
106 , m_renderFlowThread(0)
108 m_renderFlowThread = m_view->flowThreadController()->currentRenderFlowThread();
109 if (m_renderFlowThread)
110 view->flowThreadController()->setCurrentRenderFlowThread(0);
112 ~CurrentRenderFlowThreadDisabler()
114 if (m_renderFlowThread)
115 m_view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread);
119 RenderFlowThread* m_renderFlowThread;
122 void RenderFlowThread::validateRegions()
124 if (m_regionsInvalidated) {
125 m_regionsInvalidated = false;
126 m_regionsHaveUniformLogicalHeight = true;
129 LayoutUnit previousRegionLogicalWidth = 0;
130 LayoutUnit previousRegionLogicalHeight = 0;
131 bool firstRegionVisited = false;
133 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
134 RenderRegion* region = *iter;
135 LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
136 LayoutUnit regionLogicalHeight = region->pageLogicalHeight();
138 if (!firstRegionVisited) {
139 firstRegionVisited = true;
141 if (m_regionsHaveUniformLogicalHeight && previousRegionLogicalHeight != regionLogicalHeight)
142 m_regionsHaveUniformLogicalHeight = false;
145 previousRegionLogicalWidth = regionLogicalWidth;
150 updateLogicalWidth(); // Called to get the maximum logical width for the region.
151 updateRegionsFlowThreadPortionRect();
154 void RenderFlowThread::layout()
156 LayoutRectRecorder recorder(*this);
157 m_pageLogicalSizeChanged = m_regionsInvalidated && everHadLayout();
161 CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this);
162 RenderBlockFlow::layout();
164 m_pageLogicalSizeChanged = false;
167 lastRegion()->expandToEncompassFlowThreadContentsIfNeeded();
170 void RenderFlowThread::updateLogicalWidth()
172 setLogicalWidth(initialLogicalWidth());
175 void RenderFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
177 computedValues.m_position = logicalTop;
178 computedValues.m_extent = 0;
180 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
181 RenderRegion* region = *iter;
182 computedValues.m_extent += region->logicalHeightOfAllFlowThreadContent();
186 LayoutRect RenderFlowThread::computeRegionClippingRect(const LayoutPoint& offset, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect) const
188 LayoutRect regionClippingRect(offset + (flowThreadPortionOverflowRect.location() - flowThreadPortionRect.location()), flowThreadPortionOverflowRect.size());
189 if (style()->isFlippedBlocksWritingMode())
190 regionClippingRect.move(flowThreadPortionRect.size() - flowThreadPortionOverflowRect.size());
191 return regionClippingRect;
194 bool RenderFlowThread::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
196 if (hitTestAction == HitTestBlockBackground)
198 return RenderBlockFlow::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction);
201 bool RenderFlowThread::shouldRepaint(const LayoutRect& r) const
203 if (view()->document().printing() || r.isEmpty())
209 void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect) const
211 if (!shouldRepaint(repaintRect) || !hasValidRegionInfo())
214 LayoutStateDisabler layoutStateDisabler(view()); // We can't use layout state to repaint, since the regions are somewhere else.
216 // We can't use currentFlowThread as it is possible to have interleaved flow threads and the wrong one could be used.
217 // Let each region figure out the proper enclosing flow thread.
218 CurrentRenderFlowThreadDisabler disabler(view());
220 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
221 RenderRegion* region = *iter;
223 region->repaintFlowThreadContent(repaintRect);
227 RenderRegion* RenderFlowThread::regionAtBlockOffset(LayoutUnit offset, bool extendLastRegion, RegionAutoGenerationPolicy autoGenerationPolicy)
229 ASSERT(!m_regionsInvalidated);
231 if (autoGenerationPolicy == AllowRegionAutoGeneration)
232 autoGenerateRegionsToBlockOffset(offset);
235 return m_regionList.isEmpty() ? 0 : m_regionList.first();
237 RegionSearchAdapter adapter(offset);
238 m_regionIntervalTree.allOverlapsWithAdapter<RegionSearchAdapter>(adapter);
240 // If no region was found, the offset is in the flow thread overflow.
241 // The last region will contain the offset if extendLastRegion is set or if the last region is a set.
242 if (!adapter.result() && !m_regionList.isEmpty())
243 return m_regionList.last();
245 return adapter.result();
248 RenderRegion* RenderFlowThread::regionFromAbsolutePointAndBox(IntPoint absolutePoint, const RenderBox* flowedBox)
253 RenderRegion* startRegion = 0;
254 RenderRegion* endRegion = 0;
255 getRegionRangeForBox(flowedBox, startRegion, endRegion);
260 for (RenderRegionList::iterator iter = m_regionList.find(startRegion); iter != m_regionList.end(); ++iter) {
261 RenderRegion* region = *iter;
262 IntRect regionAbsoluteRect(roundedIntPoint(region->localToAbsolute()), roundedIntSize(region->frameRect().size()));
263 if (regionAbsoluteRect.contains(absolutePoint))
266 if (region == endRegion)
273 LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const RenderBoxModelObject& boxModelObject, const LayoutPoint& startPoint)
275 LayoutPoint referencePoint = startPoint;
277 // FIXME: This needs to be adapted for different writing modes inside the flow thread.
278 RenderRegion* startRegion = regionAtBlockOffset(referencePoint.y());
280 // Take into account the offset coordinates of the region.
281 RenderObject* currObject = startRegion;
282 RenderObject* currOffsetParentRenderer;
283 Element* currOffsetParentElement;
284 while ((currOffsetParentElement = currObject->offsetParent()) && (currOffsetParentRenderer = currOffsetParentElement->renderer())) {
285 if (currObject->isBoxModelObject())
286 referencePoint.move(toRenderBoxModelObject(currObject)->offsetLeft(), toRenderBoxModelObject(currObject)->offsetTop());
288 // Since we're looking for the offset relative to the body, we must also
289 // take into consideration the borders of the region's offsetParent.
290 if (currOffsetParentRenderer->isBox() && !currOffsetParentRenderer->isBody())
291 referencePoint.move(toRenderBox(currOffsetParentRenderer)->borderLeft(), toRenderBox(currOffsetParentRenderer)->borderTop());
293 currObject = currOffsetParentRenderer;
296 // We need to check if any of this box's containing blocks start in a different region
297 // and if so, drop the object's top position (which was computed relative to its containing block
298 // and is no longer valid) and recompute it using the region in which it flows as reference.
299 bool wasComputedRelativeToOtherRegion = false;
300 const RenderBlock* objContainingBlock = boxModelObject.containingBlock();
301 while (objContainingBlock) {
302 // Check if this object is in a different region.
303 RenderRegion* parentStartRegion = 0;
304 RenderRegion* parentEndRegion = 0;
305 getRegionRangeForBox(objContainingBlock, parentStartRegion, parentEndRegion);
306 if (parentStartRegion && parentStartRegion != startRegion) {
307 wasComputedRelativeToOtherRegion = true;
310 objContainingBlock = objContainingBlock->containingBlock();
313 if (wasComputedRelativeToOtherRegion) {
314 // Get the logical top coordinate of the current object.
316 if (boxModelObject.isRenderBlock()) {
317 top = toRenderBlock(&boxModelObject)->offsetFromLogicalTopOfFirstPage();
319 if (boxModelObject.containingBlock())
320 top = boxModelObject.containingBlock()->offsetFromLogicalTopOfFirstPage();
322 if (boxModelObject.isBox())
323 top += toRenderBox(&boxModelObject)->topLeftLocation().y();
324 else if (boxModelObject.isRenderInline())
325 top -= toRenderInline(&boxModelObject)->borderTop();
328 // Get the logical top of the region this object starts in
329 // and compute the object's top, relative to the region's top.
330 LayoutUnit regionLogicalTop = startRegion->pageLogicalTopForOffset(top);
331 LayoutUnit topRelativeToRegion = top - regionLogicalTop;
332 referencePoint.setY(startRegion->offsetTop() + topRelativeToRegion);
334 // Since the top has been overriden, check if the
335 // relative/sticky positioning must be reconsidered.
336 if (boxModelObject.isRelPositioned())
337 referencePoint.move(0, boxModelObject.relativePositionOffset().height());
338 else if (boxModelObject.isStickyPositioned())
339 referencePoint.move(0, boxModelObject.stickyPositionOffset().height());
342 // Since we're looking for the offset relative to the body, we must also
343 // take into consideration the borders of the region.
344 referencePoint.move(startRegion->borderLeft(), startRegion->borderTop());
347 return referencePoint;
350 LayoutUnit RenderFlowThread::pageLogicalTopForOffset(LayoutUnit offset)
352 RenderRegion* region = regionAtBlockOffset(offset);
353 return region ? region->pageLogicalTopForOffset(offset) : LayoutUnit();
356 LayoutUnit RenderFlowThread::pageLogicalWidthForOffset(LayoutUnit offset)
358 RenderRegion* region = regionAtBlockOffset(offset, true);
359 return region ? region->pageLogicalWidth() : contentLogicalWidth();
362 LayoutUnit RenderFlowThread::pageLogicalHeightForOffset(LayoutUnit offset)
364 RenderRegion* region = regionAtBlockOffset(offset);
368 return region->pageLogicalHeight();
371 LayoutUnit RenderFlowThread::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule)
373 RenderRegion* region = regionAtBlockOffset(offset);
377 LayoutUnit pageLogicalTop = region->pageLogicalTopForOffset(offset);
378 LayoutUnit pageLogicalHeight = region->pageLogicalHeight();
379 LayoutUnit pageLogicalBottom = pageLogicalTop + pageLogicalHeight;
380 LayoutUnit remainingHeight = pageLogicalBottom - offset;
381 if (pageBoundaryRule == IncludePageBoundary) {
382 // If IncludePageBoundary is set, the line exactly on the top edge of a
383 // region will act as being part of the previous region.
384 remainingHeight = intMod(remainingHeight, pageLogicalHeight);
386 return remainingHeight;
389 RenderRegion* RenderFlowThread::mapFromFlowToRegion(TransformState& transformState) const
391 if (!hasValidRegionInfo())
394 LayoutRect boxRect = transformState.mappedQuad().enclosingBoundingBox();
395 flipForWritingMode(boxRect);
397 // FIXME: We need to refactor RenderObject::absoluteQuads to be able to split the quads across regions,
398 // for now we just take the center of the mapped enclosing box and map it to a region.
399 // Note: Using the center in order to avoid rounding errors.
401 LayoutPoint center = boxRect.center();
402 RenderRegion* renderRegion = const_cast<RenderFlowThread*>(this)->regionAtBlockOffset(isHorizontalWritingMode() ? center.y() : center.x(), true, DisallowRegionAutoGeneration);
406 LayoutRect flippedRegionRect(renderRegion->flowThreadPortionRect());
407 flipForWritingMode(flippedRegionRect);
409 transformState.move(renderRegion->contentBoxRect().location() - flippedRegionRect.location());
414 RenderRegion* RenderFlowThread::firstRegion() const
416 if (!hasValidRegionInfo())
418 return m_regionList.first();
421 RenderRegion* RenderFlowThread::lastRegion() const
423 if (!hasValidRegionInfo())
425 return m_regionList.last();
428 void RenderFlowThread::setRegionRangeForBox(const RenderBox* box, LayoutUnit offsetFromLogicalTopOfFirstPage)
433 // FIXME: Not right for differing writing-modes.
434 RenderRegion* startRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage, true);
435 RenderRegion* endRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage + box->logicalHeight(), true);
436 RenderRegionRangeMap::iterator it = m_regionRangeMap.find(box);
437 if (it == m_regionRangeMap.end()) {
438 m_regionRangeMap.set(box, RenderRegionRange(startRegion, endRegion));
442 // If nothing changed, just bail.
443 RenderRegionRange& range = it->value;
444 if (range.startRegion() == startRegion && range.endRegion() == endRegion)
447 range.setRange(startRegion, endRegion);
450 void RenderFlowThread::getRegionRangeForBox(const RenderBox* box, RenderRegion*& startRegion, RenderRegion*& endRegion) const
454 RenderRegionRangeMap::const_iterator it = m_regionRangeMap.find(box);
455 if (it == m_regionRangeMap.end())
458 const RenderRegionRange& range = it->value;
459 startRegion = range.startRegion();
460 endRegion = range.endRegion();
461 ASSERT(m_regionList.contains(startRegion) && m_regionList.contains(endRegion));
464 void RenderFlowThread::applyBreakAfterContent(LayoutUnit clientHeight)
466 // Simulate a region break at height. If it points inside an auto logical height region,
467 // then it may determine the region computed autoheight.
468 addForcedRegionBreak(clientHeight, this, false);
471 bool RenderFlowThread::regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const
473 ASSERT(targetRegion);
475 for (RenderRegionList::const_iterator it = m_regionList.find(const_cast<RenderRegion*>(startRegion)); it != m_regionList.end(); ++it) {
476 const RenderRegion* currRegion = *it;
477 if (targetRegion == currRegion)
479 if (currRegion == endRegion)
486 void RenderFlowThread::updateRegionsFlowThreadPortionRect()
488 LayoutUnit logicalHeight = 0;
489 // FIXME: Optimize not to clear the interval all the time. This implies manually managing the tree nodes lifecycle.
490 m_regionIntervalTree.clear();
491 m_regionIntervalTree.initIfNeeded();
492 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
493 RenderRegion* region = *iter;
495 LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
496 LayoutUnit regionLogicalHeight = std::min<LayoutUnit>(RenderFlowThread::maxLogicalHeight() - logicalHeight, region->logicalHeightOfAllFlowThreadContent());
498 LayoutRect regionRect(style()->direction() == LTR ? LayoutUnit() : logicalWidth() - regionLogicalWidth, logicalHeight, regionLogicalWidth, regionLogicalHeight);
500 region->setFlowThreadPortionRect(isHorizontalWritingMode() ? regionRect : regionRect.transposedRect());
502 m_regionIntervalTree.add(RegionIntervalTree::createInterval(logicalHeight, logicalHeight + regionLogicalHeight, region));
504 logicalHeight += regionLogicalHeight;
508 void RenderFlowThread::collectLayerFragments(LayerFragments& layerFragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
510 ASSERT(!m_regionsInvalidated);
512 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
513 RenderRegion* region = *iter;
514 region->collectLayerFragments(layerFragments, layerBoundingBox, dirtyRect);
518 LayoutRect RenderFlowThread::fragmentsBoundingBox(const LayoutRect& layerBoundingBox)
520 ASSERT(!m_regionsInvalidated);
523 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
524 RenderRegion* region = *iter;
525 LayerFragments fragments;
526 region->collectLayerFragments(fragments, layerBoundingBox, PaintInfo::infiniteRect());
527 for (size_t i = 0; i < fragments.size(); ++i) {
528 const LayerFragment& fragment = fragments.at(i);
529 LayoutRect fragmentRect(layerBoundingBox);
530 fragmentRect.intersect(fragment.paginationClip);
531 fragmentRect.moveBy(fragment.paginationOffset);
532 result.unite(fragmentRect);
539 bool RenderFlowThread::cachedOffsetFromLogicalTopOfFirstRegion(const RenderBox* box, LayoutUnit& result) const
541 RenderBoxToOffsetMap::const_iterator offsetIterator = m_boxesToOffsetMap.find(box);
542 if (offsetIterator == m_boxesToOffsetMap.end())
545 result = offsetIterator->value;
549 void RenderFlowThread::setOffsetFromLogicalTopOfFirstRegion(const RenderBox* box, LayoutUnit offset)
551 m_boxesToOffsetMap.set(box, offset);
554 void RenderFlowThread::clearOffsetFromLogicalTopOfFirstRegion(const RenderBox* box)
556 ASSERT(m_boxesToOffsetMap.contains(box));
557 m_boxesToOffsetMap.remove(box);
560 const RenderBox* RenderFlowThread::currentStatePusherRenderBox() const
562 const RenderObject* currentObject = m_statePusherObjectsStack.isEmpty() ? 0 : m_statePusherObjectsStack.last();
563 if (currentObject && currentObject->isBox())
564 return toRenderBox(currentObject);
569 void RenderFlowThread::pushFlowThreadLayoutState(const RenderObject* object)
571 if (const RenderBox* currentBoxDescendant = currentStatePusherRenderBox()) {
572 LayoutState* layoutState = currentBoxDescendant->view()->layoutState();
573 if (layoutState && layoutState->isPaginated()) {
574 ASSERT(layoutState->renderer() == currentBoxDescendant);
575 LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
576 setOffsetFromLogicalTopOfFirstRegion(currentBoxDescendant, currentBoxDescendant->isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width());
580 m_statePusherObjectsStack.add(object);
583 void RenderFlowThread::popFlowThreadLayoutState()
585 m_statePusherObjectsStack.removeLast();
587 if (const RenderBox* currentBoxDescendant = currentStatePusherRenderBox()) {
588 LayoutState* layoutState = currentBoxDescendant->view()->layoutState();
589 if (layoutState && layoutState->isPaginated())
590 clearOffsetFromLogicalTopOfFirstRegion(currentBoxDescendant);
594 LayoutUnit RenderFlowThread::offsetFromLogicalTopOfFirstRegion(const RenderBlock* currentBlock) const
596 // First check if we cached the offset for the block if it's an ancestor containing block of the box
597 // being currently laid out.
599 if (cachedOffsetFromLogicalTopOfFirstRegion(currentBlock, offset))
602 // If it's the current box being laid out, use the layout state.
603 const RenderBox* currentBoxDescendant = currentStatePusherRenderBox();
604 if (currentBlock == currentBoxDescendant) {
605 LayoutState* layoutState = view()->layoutState();
606 ASSERT(layoutState->renderer() == currentBlock);
607 ASSERT(layoutState && layoutState->isPaginated());
608 LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
609 return currentBoxDescendant->isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
612 // As a last resort, take the slow path.
613 LayoutRect blockRect(0, 0, currentBlock->width(), currentBlock->height());
614 while (currentBlock && !currentBlock->isRenderFlowThread()) {
615 RenderBlock* containerBlock = currentBlock->containingBlock();
616 ASSERT(containerBlock);
619 LayoutPoint currentBlockLocation = currentBlock->location();
621 if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) {
622 // We have to put the block rect in container coordinates
623 // and we have to take into account both the container and current block flipping modes
624 if (containerBlock->style()->isFlippedBlocksWritingMode()) {
625 if (containerBlock->isHorizontalWritingMode())
626 blockRect.setY(currentBlock->height() - blockRect.maxY());
628 blockRect.setX(currentBlock->width() - blockRect.maxX());
630 currentBlock->flipForWritingMode(blockRect);
632 blockRect.moveBy(currentBlockLocation);
633 currentBlock = containerBlock;
636 return currentBlock->isHorizontalWritingMode() ? blockRect.y() : blockRect.x();
639 void RenderFlowThread::RegionSearchAdapter::collectIfNeeded(const RegionInterval& interval)
643 if (interval.low() <= m_offset && interval.high() > m_offset)
644 m_result = interval.data();
647 void RenderFlowThread::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
649 if (this == repaintContainer)
652 if (RenderRegion* region = mapFromFlowToRegion(transformState)) {
653 // FIXME: The cast below is probably not the best solution, we may need to find a better way.
654 static_cast<const RenderObject*>(region)->mapLocalToContainer(region->containerForRepaint(), transformState, mode, wasFixed);
658 CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer(RenderFlowThread* renderFlowThread)
659 : m_renderFlowThread(renderFlowThread)
660 , m_previousRenderFlowThread(0)
662 if (!m_renderFlowThread)
664 RenderView* view = m_renderFlowThread->view();
665 m_previousRenderFlowThread = view->flowThreadController()->currentRenderFlowThread();
666 view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread);
669 CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer()
671 if (!m_renderFlowThread)
673 RenderView* view = m_renderFlowThread->view();
674 ASSERT(view->flowThreadController()->currentRenderFlowThread() == m_renderFlowThread);
675 view->flowThreadController()->setCurrentRenderFlowThread(m_previousRenderFlowThread);
679 } // namespace WebCore