void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect, bool immediate) { if (!shouldRepaint(repaintRect) || !hasValidRegionInfo()) return; for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { RenderRegion* region = *iter; if (!region->isValid()) continue; // We only have to issue a repaint in this region if the region rect intersects the repaint rect. LayoutRect flippedRegionRect(region->regionRect()); LayoutRect flippedRegionOverflowRect(region->regionOverflowRect()); flipForWritingMode(flippedRegionRect); // Put the region rects into physical coordinates. flipForWritingMode(flippedRegionOverflowRect); LayoutRect clippedRect(repaintRect); clippedRect.intersect(flippedRegionOverflowRect); if (clippedRect.isEmpty()) continue; // Put the region rect into the region's physical coordinate space. clippedRect.setLocation(region->contentBoxRect().location() + (clippedRect.location() - flippedRegionRect.location())); // Now switch to the region's writing mode coordinate space and let it repaint itself. region->flipForWritingMode(clippedRect); LayoutStateDisabler layoutStateDisabler(view()); // We can't use layout state to repaint, since the region is somewhere else. // Can't use currentFlowThread as it possible to have imbricated flow threads and the wrong one could be used, // so, we let each region figure out the proper enclosing flow thread CurrentRenderFlowThreadDisabler disabler(view()); region->repaintRectangle(clippedRect, immediate); } }
RenderRegion* RenderFlowThread::mapFromFlowToRegion(TransformState& transformState) const { if (!hasValidRegionInfo()) return 0; LayoutRect boxRect = transformState.mappedQuad().enclosingBoundingBox(); flipForWritingMode(boxRect); // FIXME: We need to refactor RenderObject::absoluteQuads to be able to split the quads across regions, // for now we just take the center of the mapped enclosing box and map it to a region. // Note: Using the center in order to avoid rounding errors. LayoutPoint center = boxRect.center(); RenderRegion* renderRegion = regionAtBlockOffset(isHorizontalWritingMode() ? center.y() : center.x(), true); if (!renderRegion) return 0; LayoutRect flippedRegionRect(renderRegion->flowThreadPortionRect()); flipForWritingMode(flippedRegionRect); transformState.move(renderRegion->contentBoxRect().location() - flippedRegionRect.location()); return renderRegion; }
RenderRegion* RenderMultiColumnFlowThread::mapFromFlowToRegion(TransformState& transformState) const { if (!hasValidRegionInfo()) return nullptr; // Get back into our local flow thread space. LayoutRect boxRect = transformState.mappedQuad().enclosingBoundingBox(); flipForWritingMode(boxRect); // FIXME: We need to refactor RenderObject::absoluteQuads to be able to split the quads across regions, // for now we just take the center of the mapped enclosing box and map it to a column. LayoutPoint center = boxRect.center(); LayoutUnit centerOffset = isHorizontalWritingMode() ? center.y() : center.x(); RenderRegion* renderRegion = const_cast<RenderMultiColumnFlowThread*>(this)->regionAtBlockOffset(this, centerOffset, true, DisallowRegionAutoGeneration); if (!renderRegion) return nullptr; // Now that we know which multicolumn set we hit, we need to get the appropriate translation offset for the column. RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(renderRegion); LayoutPoint translationOffset = columnSet->columnTranslationForOffset(centerOffset); // Now we know how we want the rect to be translated into the region. LayoutRect flippedRegionRect(renderRegion->flowThreadPortionRect()); if (isHorizontalWritingMode()) flippedRegionRect.setHeight(columnSet->computedColumnHeight()); else flippedRegionRect.setWidth(columnSet->computedColumnHeight()); flipForWritingMode(flippedRegionRect); flippedRegionRect.moveBy(-translationOffset); // There is an additional offset to apply, which is the offset of the region within the multi-column space. transformState.move(renderRegion->contentBoxRect().location() - flippedRegionRect.location()); return renderRegion; }