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"; |
-} |
- |
-} |