LayoutRect RenderRegion::regionOverflowRect() const { // FIXME: Would like to just use hasOverflowClip() but we aren't a block yet. When RenderRegion is eliminated and // folded into RenderBlock, switch to hasOverflowClip(). bool clipX = style()->overflowX() != OVISIBLE; bool clipY = style()->overflowY() != OVISIBLE; if ((clipX && clipY) || !isValid() || !m_flowThread) return regionRect(); LayoutRect flowThreadOverflow = m_flowThread->visualOverflowRect(); // Only clip along the flow thread axis. LayoutUnit outlineSize = maximalOutlineSize(PaintPhaseOutline); LayoutRect clipRect; if (m_flowThread->isHorizontalWritingMode()) { LayoutUnit minY = isFirstRegion() ? (flowThreadOverflow.y() - outlineSize) : regionRect().y(); LayoutUnit maxY = isLastRegion() ? max(regionRect().maxY(), flowThreadOverflow.maxY()) + outlineSize : regionRect().maxY(); LayoutUnit minX = clipX ? regionRect().x() : (flowThreadOverflow.x() - outlineSize); LayoutUnit maxX = clipX ? regionRect().maxX() : (flowThreadOverflow.maxX() + outlineSize); clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY); } else { LayoutUnit minX = isFirstRegion() ? (flowThreadOverflow.x() - outlineSize) : regionRect().x(); LayoutUnit maxX = isLastRegion() ? max(regionRect().maxX(), flowThreadOverflow.maxX()) + outlineSize : regionRect().maxX(); LayoutUnit minY = clipY ? regionRect().y() : (flowThreadOverflow.y() - outlineSize); LayoutUnit maxY = clipY ? regionRect().maxY() : (flowThreadOverflow.maxY() + outlineSize); clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY); } return clipRect; }
void RenderNamedFlowFragment::updateOversetState() { ASSERT(isValid()); RenderNamedFlowThread* flowThread = namedFlowThread(); ASSERT(flowThread && (flowThread->inOverflowLayoutPhase() || flowThread->inFinalLayoutPhase())); LayoutUnit flowContentBottom = flowThread->flowContentBottom(); bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode(); LayoutUnit flowMin = flowContentBottom - (isHorizontalWritingMode ? flowThreadPortionRect().y() : flowThreadPortionRect().x()); LayoutUnit flowMax = flowContentBottom - (isHorizontalWritingMode ? flowThreadPortionRect().maxY() : flowThreadPortionRect().maxX()); RegionOversetState previousState = regionOversetState(); RegionOversetState state = RegionFit; if (flowMin <= 0) state = RegionEmpty; if (flowMax > 0 && isLastRegion()) state = RegionOverset; setRegionOversetState(state); // Determine whether the NamedFlow object should dispatch a regionOversetChange event if (previousState != state) flowThread->setDispatchRegionOversetChangeEvent(true); }
LayoutRect RenderRegion::rectFlowPortionForBox(const RenderBox* box, const LayoutRect& rect) const { RenderRegion* startRegion = 0; RenderRegion* endRegion = 0; m_flowThread->getRegionRangeForBox(box, startRegion, endRegion); LayoutRect mappedRect = m_flowThread->mapFromLocalToFlowThread(box, rect); if (flowThread()->isHorizontalWritingMode()) { if (this != startRegion) mappedRect.shiftYEdgeTo(std::max<LayoutUnit>(logicalTopForFlowThreadContent(), mappedRect.y())); if (this != endRegion) mappedRect.setHeight(std::max<LayoutUnit>(0, std::min<LayoutUnit>(logicalBottomForFlowThreadContent() - mappedRect.y(), mappedRect.height()))); } else { if (this != startRegion) mappedRect.shiftXEdgeTo(std::max<LayoutUnit>(logicalTopForFlowThreadContent(), mappedRect.x())); if (this != endRegion) mappedRect.setWidth(std::max<LayoutUnit>(0, std::min<LayoutUnit>(logicalBottomForFlowThreadContent() - mappedRect.x(), mappedRect.width()))); } bool isLastRegionWithRegionFragmentBreak = (isLastRegion() && (style().regionFragment() == BreakRegionFragment)); if (hasOverflowClip() || isLastRegionWithRegionFragmentBreak) mappedRect.intersect(flowThreadPortionRect()); return mappedRect.isEmpty() ? mappedRect : m_flowThread->mapFromFlowThreadToLocal(box, mappedRect); }
bool RenderNamedFlowFragment::shouldClipFlowThreadContent() const { if (fragmentContainer().hasOverflowClip()) return true; return isLastRegion() && (style().regionFragment() == BreakRegionFragment); }
LayoutRect RenderMultiColumnSet::flowThreadPortionOverflowRect(const LayoutRect& portionRect, unsigned index, unsigned colCount, int colGap) const { // This function determines the portion of the flow thread that paints for the column. Along the inline axis, columns are // unclipped at outside edges (i.e., the first and last column in the set), and they clip to half the column // gap along interior edges. // // In the block direction, we will not clip overflow out of the top of the first column, or out of the bottom of // the last column. This applies only to the true first column and last column across all column sets. // // FIXME: Eventually we will know overflow on a per-column basis, but we can't do this until we have a painting // mode that understands not to paint contents from a previous column in the overflow area of a following column. // This problem applies to regions and pages as well and is not unique to columns. bool isFirstColumn = !index; bool isLastColumn = index == colCount - 1; LayoutRect overflowRect(portionRect); if (isHorizontalWritingMode()) { if (isFirstColumn) { // Shift to the logical left overflow of the flow thread to make sure it's all covered. overflowRect.shiftXEdgeTo(min(flowThread()->visualOverflowRect().x(), portionRect.x())); } else { // Expand into half of the logical left column gap. overflowRect.shiftXEdgeTo(portionRect.x() - colGap / 2); } if (isLastColumn) { // Shift to the logical right overflow of the flow thread to ensure content can spill out of the column. overflowRect.shiftMaxXEdgeTo(max(flowThread()->visualOverflowRect().maxX(), portionRect.maxX())); } else { // Expand into half of the logical right column gap. overflowRect.shiftMaxXEdgeTo(portionRect.maxX() + colGap / 2); } } else { if (isFirstColumn) { // Shift to the logical left overflow of the flow thread to make sure it's all covered. overflowRect.shiftYEdgeTo(min(flowThread()->visualOverflowRect().y(), portionRect.y())); } else { // Expand into half of the logical left column gap. overflowRect.shiftYEdgeTo(portionRect.y() - colGap / 2); } if (isLastColumn) { // Shift to the logical right overflow of the flow thread to ensure content can spill out of the column. overflowRect.shiftMaxYEdgeTo(max(flowThread()->visualOverflowRect().maxY(), portionRect.maxY())); } else { // Expand into half of the logical right column gap. overflowRect.shiftMaxYEdgeTo(portionRect.maxY() + colGap / 2); } } return overflowRectForFlowThreadPortion(overflowRect, isFirstRegion() && isFirstColumn, isLastRegion() && isLastColumn); }
LayoutRect RenderRegion::flowThreadPortionOverflowRect() const { return overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegion(), isLastRegion()); }
LayoutRect RenderRegion::flowThreadPortionOverflowRect() { return overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegion(), isLastRegion(), VisualOverflow); }
LayoutRect RenderMultiColumnSet::flowThreadPortionOverflowRect(const LayoutRect& portionRect, unsigned index, unsigned colCount, LayoutUnit colGap) const { // This function determines the portion of the flow thread that paints for the column. Along the inline axis, columns are // unclipped at outside edges (i.e., the first and last column in the set), and they clip to half the column // gap along interior edges. // // In the block direction, we will not clip overflow out of the top of the first column, or out of the bottom of // the last column. This applies only to the true first column and last column across all column sets. // // FIXME: Eventually we will know overflow on a per-column basis, but we can't do this until we have a painting // mode that understands not to paint contents from a previous column in the overflow area of a following column. // This problem applies to regions and pages as well and is not unique to columns. bool isFirstColumn = !index; bool isLastColumn = index == colCount - 1; bool isLeftmostColumn = style()->isLeftToRightDirection() ? isFirstColumn : isLastColumn; bool isRightmostColumn = style()->isLeftToRightDirection() ? isLastColumn : isFirstColumn; // Calculate the overflow rectangle, based on the flow thread's, clipped at column logical // top/bottom unless it's the first/last column. LayoutRect overflowRect = overflowRectForFlowThreadPortion(portionRect, isFirstColumn && isFirstRegion(), isLastColumn && isLastRegion()); // Avoid overflowing into neighboring columns, by clipping in the middle of adjacent column // gaps. Also make sure that we avoid rounding errors. if (isHorizontalWritingMode()) { if (!isLeftmostColumn) overflowRect.shiftXEdgeTo(portionRect.x() - colGap / 2); if (!isRightmostColumn) overflowRect.shiftMaxXEdgeTo(portionRect.maxX() + colGap - colGap / 2); } else { if (!isLeftmostColumn) overflowRect.shiftYEdgeTo(portionRect.y() - colGap / 2); if (!isRightmostColumn) overflowRect.shiftMaxYEdgeTo(portionRect.maxY() + colGap - colGap / 2); } return overflowRect; }
void RenderRegion::computeOverflowFromFlowThread() { ASSERT(isValid()); LayoutRect layoutRect = overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegion(), isLastRegion(), LayoutOverflow); layoutRect.setLocation(contentBoxRect().location() + (layoutRect.location() - m_flowThreadPortionRect.location())); // FIXME: Correctly adjust the layout overflow for writing modes. addLayoutOverflow(layoutRect); updateLayerTransform(); updateScrollInfoAfterLayout(); }