| Index: Source/core/rendering/RenderMultiColumnSet.cpp
|
| diff --git a/Source/core/rendering/RenderMultiColumnSet.cpp b/Source/core/rendering/RenderMultiColumnSet.cpp
|
| deleted file mode 100644
|
| index 449073752ae1e6e73f252dc473a2ef0e76f621bd..0000000000000000000000000000000000000000
|
| --- a/Source/core/rendering/RenderMultiColumnSet.cpp
|
| +++ /dev/null
|
| @@ -1,515 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2012 Apple Inc. All rights reserved.
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions
|
| - * are met:
|
| - * 1. Redistributions of source code must retain the above copyright
|
| - * notice, this list of conditions and the following disclaimer.
|
| - * 2. Redistributions in binary form must reproduce the above copyright
|
| - * notice, this list of conditions and the following disclaimer in the
|
| - * documentation and/or other materials provided with the distribution.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
| - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
| - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
| - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
| - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
| - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
| - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
| - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| - */
|
| -
|
| -#include "config.h"
|
| -#include "core/rendering/RenderMultiColumnSet.h"
|
| -
|
| -#include "core/rendering/PaintInfo.h"
|
| -#include "core/rendering/RenderLayer.h"
|
| -#include "core/rendering/RenderMultiColumnBlock.h"
|
| -#include "core/rendering/RenderMultiColumnFlowThread.h"
|
| -
|
| -using namespace std;
|
| -
|
| -namespace WebCore {
|
| -
|
| -RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread)
|
| - : RenderRegionSet(0, flowThread)
|
| - , m_computedColumnCount(1)
|
| - , m_computedColumnWidth(0)
|
| - , m_computedColumnHeight(0)
|
| - , m_maxColumnHeight(LayoutUnit::max())
|
| - , m_minSpaceShortage(LayoutUnit::max())
|
| - , m_minimumColumnHeight(0)
|
| - , m_forcedBreaksCount(0)
|
| - , m_maximumDistanceBetweenForcedBreaks(0)
|
| - , m_forcedBreakOffset(0)
|
| -{
|
| -}
|
| -
|
| -RenderMultiColumnSet* RenderMultiColumnSet::createAnonymous(RenderFlowThread* flowThread)
|
| -{
|
| - Document& document = flowThread->document();
|
| - RenderMultiColumnSet* renderer = new RenderMultiColumnSet(flowThread);
|
| - renderer->setDocumentForAnonymous(&document);
|
| - return renderer;
|
| -}
|
| -
|
| -LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) const
|
| -{
|
| - RenderMultiColumnBlock* multicolBlock = toRenderMultiColumnBlock(parent());
|
| - LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderBefore() - multicolBlock->paddingBefore();
|
| -
|
| - height -= contentLogicalTop;
|
| - return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created.
|
| -}
|
| -
|
| -LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) const
|
| -{
|
| - LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x());
|
| - unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns);
|
| - return portionLogicalTop + columnIndex * computedColumnHeight();
|
| -}
|
| -
|
| -void RenderMultiColumnSet::setAndConstrainColumnHeight(LayoutUnit newHeight)
|
| -{
|
| - m_computedColumnHeight = newHeight;
|
| - if (m_computedColumnHeight > m_maxColumnHeight)
|
| - m_computedColumnHeight = m_maxColumnHeight;
|
| - // FIXME: the height may also be affected by the enclosing pagination context, if any.
|
| -}
|
| -
|
| -bool RenderMultiColumnSet::calculateBalancedHeight(bool initial)
|
| -{
|
| - ASSERT(toRenderMultiColumnBlock(parent())->requiresBalancing());
|
| - LayoutUnit oldColumnHeight = m_computedColumnHeight;
|
| - LayoutUnit currentMinSpaceShortage = m_minSpaceShortage;
|
| - m_minSpaceShortage = LayoutUnit::max();
|
| -
|
| - if (initial) {
|
| - // Start with the lowest imaginable column height.
|
| - LayoutUnit logicalHeightGuess = ceilf(float(flowThread()->logicalHeight()) / float(m_computedColumnCount));
|
| - logicalHeightGuess = max(logicalHeightGuess, m_minimumColumnHeight);
|
| - setAndConstrainColumnHeight(logicalHeightGuess);
|
| -
|
| - // The multicol container now typically needs at least one more layout pass with a new
|
| - // column height, but if height was specified, we only need to do this if we found that we
|
| - // might need less space than that. On the other hand, if we determined that the columns
|
| - // need to be as tall as the specified height of the container, we have already laid it out
|
| - // correctly, and there's no need for another pass.
|
| - return m_computedColumnHeight != oldColumnHeight;
|
| - }
|
| -
|
| - if (columnCount() <= computedColumnCount()) {
|
| - // With the current column height, the content fits without creating overflowing columns. We're done.
|
| - return false;
|
| - }
|
| -
|
| - // If the initial guessed column height wasn't enough, stretch it now. Stretch by the lowest
|
| - // amount of space shortage found during layout.
|
| -
|
| - ASSERT(currentMinSpaceShortage != LayoutUnit::max()); // If this can actually happen, we probably have a bug.
|
| - if (currentMinSpaceShortage == LayoutUnit::max())
|
| - return false; // So bail out rather than looping infinitely.
|
| -
|
| - setAndConstrainColumnHeight(m_computedColumnHeight + currentMinSpaceShortage);
|
| -
|
| - // If we reach the maximum column height (typically set by the height or max-height property),
|
| - // we may not be allowed to stretch further. Return true only if stretching
|
| - // succeeded. Otherwise, we're done.
|
| - ASSERT(m_computedColumnHeight >= oldColumnHeight); // We shouldn't be able to shrink the height!
|
| - return m_computedColumnHeight > oldColumnHeight;
|
| -}
|
| -
|
| -void RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage)
|
| -{
|
| - if (spaceShortage >= m_minSpaceShortage)
|
| - return;
|
| -
|
| - // The space shortage is what we use as our stretch amount. We need a positive number here in
|
| - // order to get anywhere.
|
| - ASSERT(spaceShortage > 0);
|
| -
|
| - m_minSpaceShortage = spaceShortage;
|
| -}
|
| -
|
| -void RenderMultiColumnSet::updateLogicalWidth()
|
| -{
|
| - RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
|
| - setComputedColumnWidthAndCount(parentBlock->columnWidth(), parentBlock->columnCount()); // FIXME: This will eventually vary if we are contained inside regions.
|
| -
|
| - // FIXME: When we add regions support, we'll start it off at the width of the multi-column
|
| - // block in that particular region.
|
| - setLogicalWidth(parentBox()->contentLogicalWidth());
|
| -
|
| - // If we overflow, increase our logical width.
|
| - unsigned colCount = columnCount();
|
| - LayoutUnit colGap = columnGap();
|
| - LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + (colCount - 1) * colGap;
|
| - LayoutUnit currentContentLogicalWidth = contentLogicalWidth();
|
| - LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentContentLogicalWidth);
|
| - if (!delta)
|
| - return;
|
| -
|
| - // Increase our logical width by the delta.
|
| - setLogicalWidth(logicalWidth() + delta);
|
| -}
|
| -
|
| -void RenderMultiColumnSet::prepareForLayout()
|
| -{
|
| - RenderMultiColumnBlock* multicolBlock = toRenderMultiColumnBlock(parent());
|
| - RenderStyle* multicolStyle = multicolBlock->style();
|
| -
|
| - // Set box logical top.
|
| - ASSERT(!previousSiblingBox() || !previousSiblingBox()->isRenderMultiColumnSet()); // FIXME: multiple set not implemented; need to examine previous set to calculate the correct logical top.
|
| - setLogicalTop(multicolBlock->borderBefore() + multicolBlock->paddingBefore());
|
| -
|
| - // Set box width.
|
| - updateLogicalWidth();
|
| -
|
| - if (multicolBlock->requiresBalancing()) {
|
| - // Set maximum column height. We will not stretch beyond this.
|
| - m_maxColumnHeight = LayoutUnit::max();
|
| - if (!multicolStyle->logicalHeight().isAuto())
|
| - m_maxColumnHeight = multicolBlock->computeContentLogicalHeight(multicolStyle->logicalHeight(), -1);
|
| - if (!multicolStyle->logicalMaxHeight().isUndefined()) {
|
| - LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHeight(multicolStyle->logicalMaxHeight(), -1);
|
| - if (m_maxColumnHeight > logicalMaxHeight)
|
| - m_maxColumnHeight = logicalMaxHeight;
|
| - }
|
| - m_maxColumnHeight = heightAdjustedForSetOffset(m_maxColumnHeight);
|
| - m_computedColumnHeight = 0; // Restart balancing.
|
| - } else {
|
| - setAndConstrainColumnHeight(heightAdjustedForSetOffset(multicolBlock->columnHeightAvailable()));
|
| - }
|
| -
|
| - // Nuke previously stored minimum column height. Contents may have changed for all we know.
|
| - m_minimumColumnHeight = 0;
|
| -}
|
| -
|
| -void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
|
| -{
|
| - computedValues.m_extent = m_computedColumnHeight;
|
| - computedValues.m_position = logicalTop;
|
| -}
|
| -
|
| -LayoutUnit RenderMultiColumnSet::columnGap() const
|
| -{
|
| - // FIXME: Eventually we will cache the column gap when the widths of columns start varying, but for now we just
|
| - // go to the parent block to get the gap.
|
| - RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
|
| - if (parentBlock->style()->hasNormalColumnGap())
|
| - return parentBlock->style()->fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
|
| - return parentBlock->style()->columnGap();
|
| -}
|
| -
|
| -unsigned RenderMultiColumnSet::columnCount() const
|
| -{
|
| - // We must always return a value of 1 or greater. Column count = 0 is a meaningless situation,
|
| - // and will confuse and cause problems in other parts of the code.
|
| - if (!computedColumnHeight())
|
| - return 1;
|
| -
|
| - // Our portion rect determines our column count. We have as many columns as needed to fit all the content.
|
| - LayoutUnit logicalHeightInColumns = flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().height() : flowThreadPortionRect().width();
|
| - unsigned count = ceil(static_cast<float>(logicalHeightInColumns) / computedColumnHeight());
|
| - ASSERT(count >= 1);
|
| - return count;
|
| -}
|
| -
|
| -LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const
|
| -{
|
| - LayoutUnit colLogicalWidth = computedColumnWidth();
|
| - LayoutUnit colLogicalHeight = computedColumnHeight();
|
| - LayoutUnit colLogicalTop = borderBefore() + paddingBefore();
|
| - LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft();
|
| - LayoutUnit colGap = columnGap();
|
| - if (style()->isLeftToRightDirection())
|
| - colLogicalLeft += index * (colLogicalWidth + colGap);
|
| - else
|
| - colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap);
|
| -
|
| - if (isHorizontalWritingMode())
|
| - return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight);
|
| - return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
|
| -}
|
| -
|
| -unsigned RenderMultiColumnSet::columnIndexAtOffset(LayoutUnit offset, ColumnIndexCalculationMode mode) const
|
| -{
|
| - LayoutRect portionRect(flowThreadPortionRect());
|
| -
|
| - // Handle the offset being out of range.
|
| - LayoutUnit flowThreadLogicalTop = isHorizontalWritingMode() ? portionRect.y() : portionRect.x();
|
| - if (offset < flowThreadLogicalTop)
|
| - return 0;
|
| - // If we're laying out right now, we cannot constrain against some logical bottom, since it
|
| - // isn't known yet. Otherwise, just return the last column if we're past the logical bottom.
|
| - if (mode == ClampToExistingColumns) {
|
| - LayoutUnit flowThreadLogicalBottom = isHorizontalWritingMode() ? portionRect.maxY() : portionRect.maxX();
|
| - if (offset >= flowThreadLogicalBottom)
|
| - return columnCount() - 1;
|
| - }
|
| -
|
| - // Just divide by the column height to determine the correct column.
|
| - return static_cast<float>(offset - flowThreadLogicalTop) / computedColumnHeight();
|
| -}
|
| -
|
| -LayoutRect RenderMultiColumnSet::flowThreadPortionRectAt(unsigned index) const
|
| -{
|
| - LayoutRect portionRect = flowThreadPortionRect();
|
| - if (isHorizontalWritingMode())
|
| - portionRect = LayoutRect(portionRect.x(), portionRect.y() + index * computedColumnHeight(), portionRect.width(), computedColumnHeight());
|
| - else
|
| - portionRect = LayoutRect(portionRect.x() + index * computedColumnHeight(), portionRect.y(), computedColumnHeight(), portionRect.height());
|
| - return portionRect;
|
| -}
|
| -
|
| -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 RenderMultiColumnSet::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
|
| -{
|
| - if (style()->visibility() != VISIBLE)
|
| - return;
|
| -
|
| - RenderBlock::paintObject(paintInfo, paintOffset);
|
| -
|
| - // FIXME: Right now we're only painting in the foreground phase.
|
| - // Columns should technically respect phases and allow for background/float/foreground overlap etc., just like
|
| - // RenderBlocks do. Note this is a pretty minor issue, since the old column implementation clipped columns
|
| - // anyway, thus making it impossible for them to overlap one another. It's also really unlikely that the columns
|
| - // would overlap another block.
|
| - if (!m_flowThread || !isValid() || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
|
| - return;
|
| -
|
| - paintColumnRules(paintInfo, paintOffset);
|
| -}
|
| -
|
| -void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
|
| -{
|
| - if (paintInfo.context->paintingDisabled())
|
| - return;
|
| -
|
| - RenderStyle* blockStyle = toRenderMultiColumnBlock(parent())->style();
|
| - const Color& ruleColor = resolveColor(blockStyle, CSSPropertyWebkitColumnRuleColor);
|
| - bool ruleTransparent = blockStyle->columnRuleIsTransparent();
|
| - EBorderStyle ruleStyle = blockStyle->columnRuleStyle();
|
| - LayoutUnit ruleThickness = blockStyle->columnRuleWidth();
|
| - LayoutUnit colGap = columnGap();
|
| - bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent;
|
| - if (!renderRule)
|
| - return;
|
| -
|
| - unsigned colCount = columnCount();
|
| - if (colCount <= 1)
|
| - return;
|
| -
|
| - bool antialias = shouldAntialiasLines(paintInfo.context);
|
| -
|
| - bool leftToRight = style()->isLeftToRightDirection();
|
| - LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth();
|
| - LayoutUnit ruleAdd = borderAndPaddingLogicalLeft();
|
| - LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogicalWidth();
|
| - LayoutUnit inlineDirectionSize = computedColumnWidth();
|
| - BoxSide boxSide = isHorizontalWritingMode()
|
| - ? leftToRight ? BSLeft : BSRight
|
| - : leftToRight ? BSTop : BSBottom;
|
| -
|
| - for (unsigned i = 0; i < colCount; i++) {
|
| - // Move to the next position.
|
| - if (leftToRight) {
|
| - ruleLogicalLeft += inlineDirectionSize + colGap / 2;
|
| - currLogicalLeftOffset += inlineDirectionSize + colGap;
|
| - } else {
|
| - ruleLogicalLeft -= (inlineDirectionSize + colGap / 2);
|
| - currLogicalLeftOffset -= (inlineDirectionSize + colGap);
|
| - }
|
| -
|
| - // Now paint the column rule.
|
| - if (i < colCount - 1) {
|
| - LayoutUnit ruleLeft = isHorizontalWritingMode() ? paintOffset.x() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x() + borderLeft() + paddingLeft();
|
| - LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + contentWidth();
|
| - LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd;
|
| - LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleThickness;
|
| - IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(ruleLeft, ruleTop, ruleRight, ruleBottom);
|
| - drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
|
| - }
|
| -
|
| - ruleLogicalLeft = currLogicalLeftOffset;
|
| - }
|
| -}
|
| -
|
| -void RenderMultiColumnSet::repaintFlowThreadContent(const LayoutRect& repaintRect) const
|
| -{
|
| - // Figure out the start and end columns and only check within that range so that we don't walk the
|
| - // entire column set. Put the repaint rect into flow thread coordinates by flipping it first.
|
| - LayoutRect flowThreadRepaintRect(repaintRect);
|
| - flowThread()->flipForWritingMode(flowThreadRepaintRect);
|
| -
|
| - // Now we can compare this rect with the flow thread portions owned by each column. First let's
|
| - // just see if the repaint rect intersects our flow thread portion at all.
|
| - LayoutRect clippedRect(flowThreadRepaintRect);
|
| - clippedRect.intersect(RenderRegion::flowThreadPortionOverflowRect());
|
| - if (clippedRect.isEmpty())
|
| - return;
|
| -
|
| - // Now we know we intersect at least one column. Let's figure out the logical top and logical
|
| - // bottom of the area we're repainting.
|
| - LayoutUnit repaintLogicalTop = isHorizontalWritingMode() ? flowThreadRepaintRect.y() : flowThreadRepaintRect.x();
|
| - LayoutUnit repaintLogicalBottom = (isHorizontalWritingMode() ? flowThreadRepaintRect.maxY() : flowThreadRepaintRect.maxX()) - 1;
|
| -
|
| - unsigned startColumn = columnIndexAtOffset(repaintLogicalTop);
|
| - unsigned endColumn = columnIndexAtOffset(repaintLogicalBottom);
|
| -
|
| - LayoutUnit colGap = columnGap();
|
| - unsigned colCount = columnCount();
|
| - for (unsigned i = startColumn; i <= endColumn; i++) {
|
| - LayoutRect colRect = columnRectAt(i);
|
| -
|
| - // Get the portion of the flow thread that corresponds to this column.
|
| - LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
|
| -
|
| - // Now get the overflow rect that corresponds to the column.
|
| - LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
|
| -
|
| - // Do a repaint for this specific column.
|
| - repaintFlowThreadContentRectangle(repaintRect, flowThreadPortion, flowThreadOverflowPortion, colRect.location());
|
| - }
|
| -}
|
| -
|
| -void RenderMultiColumnSet::collectLayerFragments(LayerFragments& fragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
|
| -{
|
| - // The two rectangles passed to this method are physical, except that we pretend that there's
|
| - // only one long column (that's how a flow thread works).
|
| - //
|
| - // Then there's the output from this method - the stuff we put into the list of fragments. The
|
| - // fragment.paginationOffset point is the actual physical translation required to get from a
|
| - // location in the flow thread to a location in a given column. The fragment.paginationClip
|
| - // rectangle, on the other hand, is in the same coordinate system as the two rectangles passed
|
| - // to this method (flow thread coordinates).
|
| - //
|
| - // All other rectangles in this method are sized physically, and the inline direction coordinate
|
| - // is physical too, but the block direction coordinate is "logical top". This is the same as
|
| - // e.g. RenderBox::frameRect(). These rectangles also pretend that there's only one long column,
|
| - // i.e. they are for the flow thread.
|
| -
|
| - // Put the layer bounds into flow thread-local coordinates by flipping it first. Since we're in
|
| - // a renderer, most rectangles are represented this way.
|
| - LayoutRect layerBoundsInFlowThread(layerBoundingBox);
|
| - flowThread()->flipForWritingMode(layerBoundsInFlowThread);
|
| -
|
| - // Now we can compare with the flow thread portions owned by each column. First let's
|
| - // see if the rect intersects our flow thread portion at all.
|
| - LayoutRect clippedRect(layerBoundsInFlowThread);
|
| - clippedRect.intersect(RenderRegion::flowThreadPortionOverflowRect());
|
| - if (clippedRect.isEmpty())
|
| - return;
|
| -
|
| - // Now we know we intersect at least one column. Let's figure out the logical top and logical
|
| - // bottom of the area we're checking.
|
| - LayoutUnit layerLogicalTop = isHorizontalWritingMode() ? layerBoundsInFlowThread.y() : layerBoundsInFlowThread.x();
|
| - LayoutUnit layerLogicalBottom = (isHorizontalWritingMode() ? layerBoundsInFlowThread.maxY() : layerBoundsInFlowThread.maxX()) - 1;
|
| -
|
| - // Figure out the start and end columns and only check within that range so that we don't walk the
|
| - // entire column set.
|
| - unsigned startColumn = columnIndexAtOffset(layerLogicalTop);
|
| - unsigned endColumn = columnIndexAtOffset(layerLogicalBottom);
|
| -
|
| - LayoutUnit colLogicalWidth = computedColumnWidth();
|
| - LayoutUnit colGap = columnGap();
|
| - unsigned colCount = columnCount();
|
| -
|
| - for (unsigned i = startColumn; i <= endColumn; i++) {
|
| - // Get the portion of the flow thread that corresponds to this column.
|
| - LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
|
| -
|
| - // Now get the overflow rect that corresponds to the column.
|
| - LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
|
| -
|
| - // In order to create a fragment we must intersect the portion painted by this column.
|
| - LayoutRect clippedRect(layerBoundsInFlowThread);
|
| - clippedRect.intersect(flowThreadOverflowPortion);
|
| - if (clippedRect.isEmpty())
|
| - continue;
|
| -
|
| - // We also need to intersect the dirty rect. We have to apply a translation and shift based off
|
| - // our column index.
|
| - LayoutPoint translationOffset;
|
| - LayoutUnit inlineOffset = i * (colLogicalWidth + colGap);
|
| - if (!style()->isLeftToRightDirection())
|
| - inlineOffset = -inlineOffset;
|
| - translationOffset.setX(inlineOffset);
|
| - LayoutUnit blockOffset = isHorizontalWritingMode() ? -flowThreadPortion.y() : -flowThreadPortion.x();
|
| - if (isFlippedBlocksWritingMode(style()->writingMode()))
|
| - blockOffset = -blockOffset;
|
| - translationOffset.setY(blockOffset);
|
| - if (!isHorizontalWritingMode())
|
| - translationOffset = translationOffset.transposedPoint();
|
| - // FIXME: The translation needs to include the multicolumn set's content offset within the
|
| - // multicolumn block as well. This won't be an issue until we start creating multiple multicolumn sets.
|
| -
|
| - // Shift the dirty rect to be in flow thread coordinates with this translation applied.
|
| - LayoutRect translatedDirtyRect(dirtyRect);
|
| - translatedDirtyRect.moveBy(-translationOffset);
|
| -
|
| - // See if we intersect the dirty rect.
|
| - clippedRect = layerBoundingBox;
|
| - clippedRect.intersect(translatedDirtyRect);
|
| - if (clippedRect.isEmpty())
|
| - continue;
|
| -
|
| - // Something does need to paint in this column. Make a fragment now and supply the physical translation
|
| - // offset and the clip rect for the column with that offset applied.
|
| - LayerFragment fragment;
|
| - fragment.paginationOffset = translationOffset;
|
| -
|
| - LayoutRect flippedFlowThreadOverflowPortion(flowThreadOverflowPortion);
|
| - // Flip it into more a physical (RenderLayer-style) rectangle.
|
| - flowThread()->flipForWritingMode(flippedFlowThreadOverflowPortion);
|
| - fragment.paginationClip = flippedFlowThreadOverflowPortion;
|
| - fragments.append(fragment);
|
| - }
|
| -}
|
| -
|
| -const char* RenderMultiColumnSet::renderName() const
|
| -{
|
| - return "RenderMultiColumnSet";
|
| -}
|
| -
|
| -}
|
|
|