Esempio n. 1
0
LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const
{
    LayoutUnit colLogicalWidth = computedColumnWidth();
    LayoutUnit colLogicalHeight = computedColumnHeight();
    LayoutUnit colLogicalTop = borderAndPaddingBefore();
    LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft();
    LayoutUnit colGap = columnGap();
    
    RenderBlockFlow* parentFlow = toRenderBlockFlow(parent());
    bool progressionReversed = parentFlow->multiColumnFlowThread()->progressionIsReversed();
    bool progressionInline = parentFlow->multiColumnFlowThread()->progressionIsInline();
    
    if (progressionInline) {
        if (style().isLeftToRightDirection() ^ progressionReversed)
            colLogicalLeft += index * (colLogicalWidth + colGap);
        else
            colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap);
    } else {
        if (!progressionReversed)
            colLogicalTop += index * (colLogicalHeight + colGap);
        else
            colLogicalTop += contentLogicalHeight() - colLogicalHeight - index * (colLogicalHeight + colGap);
    }
    
    if (isHorizontalWritingMode())
        return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight);
    return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
}
IntRect computeTextBoundingBox(const RenderText& textRenderer, const Layout& layout)
{
    auto resolver = lineResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
    auto it = resolver.begin();
    auto end = resolver.end();
    if (it == end)
        return IntRect();
    auto firstLineRect = *it;
    float left = firstLineRect.x();
    float right = firstLineRect.maxX();
    float bottom = firstLineRect.maxY();
    for (++it; it != end; ++it) {
        auto rect = *it;
        if (rect.x() < left)
            left = rect.x();
        if (rect.maxX() > right)
            right = rect.maxX();
        if (rect.maxY() > bottom)
            bottom = rect.maxY();
    }
    float x = left;
    float y = firstLineRect.y();
    float width = right - left;
    float height = bottom - y;
    return enclosingIntRect(FloatRect(x, y, width, height));
}
Esempio n. 3
0
static inline InlineFlowBox* flowBoxForRenderer(RenderObject* renderer)
{
    if (!renderer)
        return 0;

    if (renderer->isRenderBlockFlow()) {
        // If we're given a block element, it has to be a RenderSVGText.
        ASSERT(renderer->isSVGText());
        RenderBlockFlow& renderBlock = toRenderBlockFlow(*renderer);

        // RenderSVGText only ever contains a single line box.
        InlineFlowBox* flowBox = renderBlock.firstLineBox();
        ASSERT(flowBox == renderBlock.lastLineBox());
        return flowBox;
    }

    if (renderer->isRenderInline()) {
        // We're given a RenderSVGInline or objects that derive from it (RenderSVGTSpan / RenderSVGTextPath)
        RenderInline& renderInline = toRenderInline(*renderer);

        // RenderSVGInline only ever contains a single line box.
        InlineFlowBox* flowBox = renderInline.firstLineBox();
        ASSERT(flowBox == renderInline.lastLineBox());
        return flowBox;
    }

    ASSERT_NOT_REACHED();
    return 0;
}
void RenderMultiColumnFlowThread::evacuateAndDestroy()
{
    RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
    m_beingEvacuated = true;

    // Delete the line box tree.
    deleteLines();

    LayoutStateDisabler layoutStateDisabler(&view());

    // First promote all children of the flow thread. Before we move them to the flow thread's
    // container, we need to unregister the flow thread, so that they aren't just re-added again to
    // the flow thread that we're trying to empty.
    multicolContainer->setMultiColumnFlowThread(nullptr);
    moveAllChildrenTo(multicolContainer, true);

    // Move spanners back to their original DOM position in the tree, and destroy the placeholders.
    SpannerMap::iterator it;
    while ((it = m_spannerMap.begin()) != m_spannerMap.end()) {
        RenderBox* spanner = it->key;
        RenderMultiColumnSpannerPlaceholder* placeholder = it->value;
        RenderBlockFlow* originalContainer = toRenderBlockFlow(placeholder->parent());
        multicolContainer->removeChild(*spanner);
        originalContainer->addChild(spanner, placeholder);
        placeholder->destroy();
        m_spannerMap.remove(it);
    }

    // Remove all sets.
    while (RenderMultiColumnSet* columnSet = firstMultiColumnSet())
        columnSet->destroy();

    destroy();
}
Esempio n. 5
0
void RenderMultiColumnSet::prepareForLayout()
{
    RenderBlockFlow* multicolBlock = toRenderBlockFlow(parent());
    const 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->borderAndPaddingBefore());

    // Set box width.
    updateLogicalWidth();

    if (multicolBlock->multiColumnFlowThread()->requiresBalancing()) {
        // Set maximum column height. We will not stretch beyond this.
        m_maxColumnHeight = RenderFlowThread::maxLogicalHeight();
        if (!multicolStyle.logicalHeight().isAuto()) {
            m_maxColumnHeight = multicolBlock->computeContentLogicalHeight(multicolStyle.logicalHeight());
            if (m_maxColumnHeight == -1)
                m_maxColumnHeight = RenderFlowThread::maxLogicalHeight();
        }
        if (!multicolStyle.logicalMaxHeight().isUndefined()) {
            LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHeight(multicolStyle.logicalMaxHeight());
            if (logicalMaxHeight != -1 && m_maxColumnHeight > logicalMaxHeight)
                m_maxColumnHeight = logicalMaxHeight;
        }
        m_maxColumnHeight = heightAdjustedForSetOffset(m_maxColumnHeight);
        m_computedColumnHeight = 0; // Restart balancing.
    } else
        setAndConstrainColumnHeight(heightAdjustedForSetOffset(multicolBlock->multiColumnFlowThread()->columnHeightAvailable()));

    clearForcedBreaks();

    // Nuke previously stored minimum column height. Contents may have changed for all we know.
    m_minimumColumnHeight = 0;
}
Esempio n. 6
0
LayoutUnit RootInlineBox::selectionTopAdjustedForPrecedingBlock() const
{
    const RootInlineBox& rootBox = root();
    LayoutUnit top = selectionTop();

    RenderObject::SelectionState blockSelectionState = rootBox.blockFlow().selectionState();
    if (blockSelectionState != RenderObject::SelectionInside && blockSelectionState != RenderObject::SelectionEnd)
        return top;

    LayoutSize offsetToBlockBefore;
    if (RenderBlock* block = rootBox.blockFlow().blockBeforeWithinSelectionRoot(offsetToBlockBefore)) {
        if (block->isRenderBlockFlow()) {
            if (RootInlineBox* lastLine = toRenderBlockFlow(block)->lastRootBox()) {
                RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
                if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
                    return top;

                LayoutUnit lastLineSelectionBottom = lastLine->selectionBottom() + offsetToBlockBefore.height();
                top = std::max(top, lastLineSelectionBottom);
            }
        }
    }

    return top;
}
IntPoint computeTextFirstRunLocation(const RenderText& textRenderer, const Layout& layout)
{
    auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
    auto begin = resolver.begin();
    if (begin == resolver.end())
        return IntPoint();
    return flooredIntPoint((*begin).rect().location());
}
Esempio n. 8
0
LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) const
{
    RenderBlockFlow* multicolBlock = toRenderBlockFlow(parent());
    LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderAndPaddingBefore();

    height -= contentLogicalTop;
    return std::max(height, LayoutUnit::fromPixel(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created.
}
Esempio n. 9
0
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.
    RenderBlockFlow* parentBlock = toRenderBlockFlow(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();
}
Esempio n. 10
0
void RenderMultiColumnSet::updateLogicalWidth()
{
    RenderBlockFlow* parentBlock = toRenderBlockFlow(parent());
    setComputedColumnWidthAndCount(parentBlock->multiColumnFlowThread()->columnWidth(), parentBlock->multiColumnFlowThread()->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());
}
Esempio n. 11
0
void RenderMultiColumnSet::addForcedBreak(LayoutUnit offsetFromFirstPage)
{
    if (!toRenderBlockFlow(parent())->multiColumnFlowThread()->requiresBalancing())
        return;
    if (!m_contentRuns.isEmpty() && offsetFromFirstPage <= m_contentRuns.last().breakOffset())
        return;
    // Append another item as long as we haven't exceeded used column count. What ends up in the
    // overflow area shouldn't affect column balancing.
    if (m_contentRuns.size() < m_computedColumnCount)
        m_contentRuns.append(ContentRun(offsetFromFirstPage));
}
Esempio n. 12
0
Vector<IntRect> collectTextAbsoluteRects(const RenderText& textRenderer, const Layout& layout, const LayoutPoint& accumulatedOffset)
{
    Vector<IntRect> rects;
    auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
        const auto& run = *it;
        auto rect = run.rect();
        rects.append(enclosingIntRect(FloatRect(accumulatedOffset + rect.location(), rect.size())));
    }
    return rects;
}
Esempio n. 13
0
Vector<FloatQuad> collectTextAbsoluteQuads(const RenderText& textRenderer, const Layout& layout, bool* wasFixed)
{
    Vector<FloatQuad> quads;
    auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
        const auto& run = *it;
        auto rect = run.rect();
        quads.append(textRenderer.localToAbsoluteQuad(FloatQuad(rect), 0, wasFixed));
    }
    return quads;
}
Esempio n. 14
0
LayoutUnit RenderMultiColumnSet::initialBlockOffsetForPainting() const
{
    RenderBlockFlow* parentFlow = toRenderBlockFlow(parent());
    bool progressionReversed = parentFlow->multiColumnFlowThread()->progressionIsReversed();
    bool progressionIsInline = parentFlow->multiColumnFlowThread()->progressionIsInline();
    
    LayoutUnit result = 0;
    if (!progressionIsInline && progressionReversed) {
        LayoutRect colRect = columnRectAt(0);
        result = isHorizontalWritingMode() ? colRect.y() : colRect.x();
        if (style().isFlippedBlocksWritingMode())
            result = -result;
    }
    return result;
}
Esempio n. 15
0
void RenderMultiColumnSet::adjustRegionBoundsFromFlowThreadPortionRect(const LayoutPoint& layerOffset, LayoutRect& regionBounds)
{
    LayoutUnit layerLogicalTop = isHorizontalWritingMode() ? layerOffset.y() : layerOffset.x();
    unsigned startColumn = columnIndexAtOffset(layerLogicalTop);
    
    LayoutUnit colGap = columnGap();
    LayoutUnit colLogicalWidth = computedColumnWidth();
    
    LayoutRect flowThreadPortion = flowThreadPortionRectAt(startColumn);
    LayoutPoint translationOffset;
    
    RenderBlockFlow* parentFlow = toRenderBlockFlow(parent());
    bool progressionReversed = parentFlow->multiColumnFlowThread()->progressionIsReversed();
    bool progressionIsInline = parentFlow->multiColumnFlowThread()->progressionIsInline();
    
    LayoutUnit initialBlockOffset = initialBlockOffsetForPainting();
    
    LayoutUnit inlineOffset = progressionIsInline ? startColumn * (colLogicalWidth + colGap) : LayoutUnit();
    
    bool leftToRight = style().isLeftToRightDirection() ^ progressionReversed;
    if (!leftToRight) {
        inlineOffset = -inlineOffset;
        if (progressionReversed)
            inlineOffset += contentLogicalWidth() - colLogicalWidth;
    }
    translationOffset.setX(inlineOffset);
    LayoutUnit blockOffset = initialBlockOffset + (isHorizontalWritingMode() ? -flowThreadPortion.y() : -flowThreadPortion.x());
    if (!progressionIsInline) {
        if (!progressionReversed)
            blockOffset = startColumn * colGap;
        else
            blockOffset -= startColumn * (computedColumnHeight() + colGap);
    }
    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.
    
    regionBounds.moveBy(roundedIntPoint(-translationOffset));
}
Esempio n. 16
0
void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
{
    // This condition is rarely hit since this function is usually called on
    // anonymous blocks which can no longer carry positioned objects (see r120761)
    // or when fullRemoveInsert is false.
    if (fullRemoveInsert && isRenderBlock()) {
        RenderBlock* block = toRenderBlock(this);
        block->removePositionedObjects(0);
        if (block->isRenderBlockFlow())
            toRenderBlockFlow(block)->removeFloatingObjects();
    }

    ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
    for (RenderObject* child = startChild; child && child != endChild; ) {
        // Save our next sibling as moveChildTo will clear it.
        RenderObject* nextSibling = child->nextSibling();
        moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);
        child = nextSibling;
    }
}
Esempio n. 17
0
LayoutRect RenderMultiColumnSet::flowThreadPortionOverflowRect(const LayoutRect& portionRect, unsigned index, unsigned colCount, LayoutUnit colGap)
{
    // 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.
    
    RenderBlockFlow* parentFlow = toRenderBlockFlow(parent());
    bool progressionReversed = parentFlow->multiColumnFlowThread()->progressionIsReversed();
    
    bool isFirstColumn = !index;
    bool isLastColumn = index == colCount - 1;
    bool isLeftmostColumn = style().isLeftToRightDirection() ^ progressionReversed ? isFirstColumn : isLastColumn;
    bool isRightmostColumn = style().isLeftToRightDirection() ^ progressionReversed ? 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(), VisualOverflow);

    // 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;
}
Esempio n. 18
0
static PassRefPtr<InspectorObject> buildObjectForRegionHighlight(FrameView* mainView, RenderRegion* region)
{
    FrameView* containingView = region->frame().view();
    if (!containingView)
        return nullptr;

    RenderBlockFlow* regionContainer = toRenderBlockFlow(region->parent());
    LayoutRect borderBox = regionContainer->borderBoxRect();
    borderBox.setWidth(borderBox.width() + regionContainer->verticalScrollbarWidth());
    borderBox.setHeight(borderBox.height() + regionContainer->horizontalScrollbarHeight());

    // Create incoming and outgoing boxes that we use to chain the regions toghether.
    const LayoutSize linkBoxSize(10, 10);
    const LayoutSize linkBoxMidpoint(linkBoxSize.width() / 2, linkBoxSize.height() / 2);
    
    LayoutRect incomingRectBox = LayoutRect(borderBox.location() - linkBoxMidpoint, linkBoxSize);
    LayoutRect outgoingRectBox = LayoutRect(borderBox.location() - linkBoxMidpoint + borderBox.size(), linkBoxSize);

    // Move the link boxes slightly inside the region border box.
    LayoutUnit maxUsableHeight = std::max(LayoutUnit(), borderBox.height() - linkBoxMidpoint.height());
    LayoutUnit linkBoxVerticalOffset = std::min(LayoutUnit::fromPixel(15), maxUsableHeight);
    incomingRectBox.move(0, linkBoxVerticalOffset);
    outgoingRectBox.move(0, -linkBoxVerticalOffset);

    FloatQuad borderRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(borderBox));
    FloatQuad incomingRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(incomingRectBox));
    FloatQuad outgoingRectQuad = regionContainer->localToAbsoluteQuad(FloatRect(outgoingRectBox));

    contentsQuadToPage(mainView, containingView, borderRectQuad);
    contentsQuadToPage(mainView, containingView, incomingRectQuad);
    contentsQuadToPage(mainView, containingView, outgoingRectQuad);

    RefPtr<InspectorObject> regionObject = InspectorObject::create();

    regionObject->setArray("borderQuad", buildArrayForQuad(borderRectQuad));
    regionObject->setArray("incomingQuad", buildArrayForQuad(incomingRectQuad));
    regionObject->setArray("outgoingQuad", buildArrayForQuad(outgoingRectQuad));

    return regionObject.release();
}
void RenderMultiColumnFlowThread::autoGenerateRegionsToBlockOffset(LayoutUnit /*offset*/)
{
    // This function ensures we have the correct column set information at all times.
    // For a simple multi-column layout in continuous media, only one column set child is required.
    // Once a column is nested inside an enclosing pagination context, the number of column sets
    // required becomes 2n-1, where n is the total number of nested pagination contexts. For example:
    //
    // Column layout with no enclosing pagination model = 2 * 1 - 1 = 1 column set.
    // Columns inside pages = 2 * 2 - 1 = 3 column sets (bottom of first page, all the subsequent pages, then the last page).
    // Columns inside columns inside pages = 2 * 3 - 1 = 5 column sets.
    //
    // In addition, column spans will force a column set to "split" into before/after sets around the spanning element.
    //
    // Finally, we will need to deal with columns inside regions. If regions have variable widths, then there will need
    // to be unique column sets created inside any region whose width is different from its surrounding regions. This is
    // actually pretty similar to the spanning case, in that we break up the column sets whenever the width varies.
    //
    // FIXME: For now just make one column set. This matches the old multi-column code.
    // Right now our goal is just feature parity with the old multi-column code so that we can switch over to the
    // new code as soon as possible.
    RenderMultiColumnSet* firstSet = toRenderMultiColumnSet(firstRegion());
    if (firstSet)
        return;
    
    invalidateRegions();

    RenderBlockFlow* parentBlock = toRenderBlockFlow(parent());
    firstSet = new RenderMultiColumnSet(*this, RenderStyle::createAnonymousStyleWithDisplay(&parentBlock->style(), BLOCK));
    firstSet->initializeStyle();
    parentBlock->RenderBlock::addChild(firstSet);

    // Even though we aren't placed yet, we can go ahead and set up our size. At this point we're
    // typically in the middle of laying out the thread, attempting to paginate, and we need to do
    // some rudimentary "layout" of the set now, so that pagination will work.
    firstSet->prepareForLayout();

    validateRegions();
}
Esempio n. 20
0
bool RenderMultiColumnSet::recalculateBalancedHeight(bool initial)
{
    ASSERT(toRenderBlockFlow(parent())->multiColumnFlowThread()->requiresBalancing());

    LayoutUnit oldColumnHeight = m_computedColumnHeight;
    if (initial)
        distributeImplicitBreaks();
    LayoutUnit newColumnHeight = calculateBalancedHeight(initial);
    setAndConstrainColumnHeight(newColumnHeight);

    // After having calculated an initial column height, the multicol container typically needs at
    // least one more layout pass with a new column height, but if a height was specified, we only
    // need to do this if we think that we need less space than specified. Conversely, 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.

    if (m_computedColumnHeight == oldColumnHeight)
        return false; // No change. We're done.

    m_minSpaceShortage = RenderFlowThread::maxLogicalHeight();
    clearForcedBreaks();
    return true; // Need another pass.
}
void RenderMultiColumnFlowThread::flowThreadDescendantInserted(RenderObject* descendant)
{
    if (gShiftingSpanner || m_beingEvacuated || descendant->isInFlowRenderFlowThread())
        return;
    RenderObject* subtreeRoot = descendant;
    for (; descendant; descendant = (descendant ? descendant->nextInPreOrder(subtreeRoot) : nullptr)) {
        if (descendant->isRenderMultiColumnSpannerPlaceholder()) {
            // A spanner's placeholder has been inserted. The actual spanner renderer is moved from
            // where it would otherwise occur (if it weren't a spanner) to becoming a sibling of the
            // column sets.
            RenderMultiColumnSpannerPlaceholder* placeholder = toRenderMultiColumnSpannerPlaceholder(descendant);
            if (placeholder->flowThread() != this) {
                // This isn't our spanner! It shifted here from an ancestor multicolumn block. It's going to end up
                // becoming our spanner instead, but for it to do that we first have to nuke the original spanner,
                // and get the spanner content back into this flow thread.
                RenderBox* spanner = placeholder->spanner();

                // Get info for the move of the original content back into our flow thread.
                RenderBoxModelObject* placeholderParent = toRenderBoxModelObject(placeholder->parent());

                // We have to nuke the placeholder, since the ancestor already lost the mapping to it when
                // we shifted the placeholder down into this flow thread.
                RenderObject* placeholderNextSibling = placeholderParent->removeChild(*placeholder);

                // Get the ancestor multicolumn flow thread to clean up its mess.
                RenderBlockFlow* ancestorBlock = toRenderBlockFlow(spanner->parent());
                ancestorBlock->multiColumnFlowThread()->flowThreadRelativeWillBeRemoved(spanner);

                // Now move the original content into our flow thread. It will end up calling flowThreadDescendantInserted
                // on the new content only, and everything will get set up properly.
                ancestorBlock->moveChildTo(placeholderParent, spanner, placeholderNextSibling, true);

                // Advance descendant.
                descendant = placeholderNextSibling;

                // If the spanner was the subtree root, then we're done, since there is nothing else left to insert.
                if (!descendant)
                    return;

                // Now that we have done this, we can continue past the spanning content, since we advanced
                // descendant already.
                if (descendant)
                    descendant = descendant->previousInPreOrder(subtreeRoot);

                continue;
            }

            ASSERT(!m_spannerMap.get(placeholder->spanner()));
            m_spannerMap.add(placeholder->spanner(), placeholder);
            ASSERT(!placeholder->firstChild()); // There should be no children here, but if there are, we ought to skip them.
            continue;
        }
        RenderBlockFlow* multicolContainer = multiColumnBlockFlow();
        RenderObject* nextRendererInFlowThread = descendant->nextInPreOrderAfterChildren(this);
        RenderObject* insertBeforeMulticolChild = nullptr;
        if (isValidColumnSpanner(this, descendant)) {
            // This is a spanner (column-span:all). Such renderers are moved from where they would
            // otherwise occur in the render tree to becoming a direct child of the multicol container,
            // so that they live among the column sets. This simplifies the layout implementation, and
            // basically just relies on regular block layout done by the RenderBlockFlow that
            // establishes the multicol container.
            RenderBlockFlow* container = toRenderBlockFlow(descendant->parent());
            RenderMultiColumnSet* setToSplit = nullptr;
            if (nextRendererInFlowThread) {
                setToSplit = findSetRendering(descendant);
                if (setToSplit) {
                    setToSplit->setNeedsLayout();
                    insertBeforeMulticolChild = setToSplit->nextSibling();
                }
            }
            // Moving a spanner's renderer so that it becomes a sibling of the column sets requires us
            // to insert an anonymous placeholder in the tree where the spanner's renderer otherwise
            // would have been. This is needed for a two reasons: We need a way of separating inline
            // content before and after the spanner, so that it becomes separate line boxes. Secondly,
            // this placeholder serves as a break point for column sets, so that, when encountered, we
            // end flowing one column set and move to the next one.
            RenderMultiColumnSpannerPlaceholder* placeholder = RenderMultiColumnSpannerPlaceholder::createAnonymous(this, toRenderBox(descendant), &container->style());
            container->addChild(placeholder, descendant->nextSibling());
            container->removeChild(*descendant);

            // This is a guard to stop an ancestor flow thread from processing the spanner.
            gShiftingSpanner = true;
            multicolContainer->RenderBlock::addChild(descendant, insertBeforeMulticolChild);
            gShiftingSpanner = false;

            // The spanner has now been moved out from the flow thread, but we don't want to
            // examine its children anyway. They are all part of the spanner and shouldn't trigger
            // creation of column sets or anything like that. Continue at its original position in
            // the tree, i.e. where the placeholder was just put.
            if (subtreeRoot == descendant)
                subtreeRoot = placeholder;
            descendant = placeholder;
        } else {
            // This is regular multicol content, i.e. not part of a spanner.
            if (nextRendererInFlowThread && nextRendererInFlowThread->isRenderMultiColumnSpannerPlaceholder()) {
                // Inserted right before a spanner. Is there a set for us there?
                RenderMultiColumnSpannerPlaceholder* placeholder = toRenderMultiColumnSpannerPlaceholder(nextRendererInFlowThread);
                if (RenderObject* previous = placeholder->spanner()->previousSibling()) {
                    if (previous->isRenderMultiColumnSet())
                        continue; // There's already a set there. Nothing to do.
                }
                insertBeforeMulticolChild = placeholder->spanner();
            } else if (RenderMultiColumnSet* lastSet = lastMultiColumnSet()) {
                // This child is not an immediate predecessor of a spanner, which means that if this
                // child precedes a spanner at all, there has to be a column set created for us there
                // already. If it doesn't precede any spanner at all, on the other hand, we need a
                // column set at the end of the multicol container. We don't really check here if the
                // child inserted precedes any spanner or not (as that's an expensive operation). Just
                // make sure we have a column set at the end. It's no big deal if it remains unused.
                if (!lastSet->nextSibling())
                    continue;
            }
        }
        // Need to create a new column set when there's no set already created. We also always insert
        // another column set after a spanner. Even if it turns out that there are no renderers
        // following the spanner, there may be bottom margins there, which take up space.
        RenderMultiColumnSet* newSet = new RenderMultiColumnSet(*this, RenderStyle::createAnonymousStyleWithDisplay(&multicolContainer->style(), BLOCK));
        newSet->initializeStyle();
        multicolContainer->RenderBlock::addChild(newSet, insertBeforeMulticolChild);
        invalidateRegions();

        // We cannot handle immediate column set siblings at the moment (and there's no need for
        // it, either). There has to be at least one spanner separating them.
        ASSERT(!previousColumnSetOrSpannerSiblingOf(newSet) || !previousColumnSetOrSpannerSiblingOf(newSet)->isRenderMultiColumnSet());
        ASSERT(!nextColumnSetOrSpannerSiblingOf(newSet) || !nextColumnSetOrSpannerSiblingOf(newSet)->isRenderMultiColumnSet());
    }
}
Esempio n. 22
0
void RenderMultiColumnSet::collectLayerFragments(LayerFragments& fragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
{
    // Let's start by introducing the different coordinate systems involved here. They are different
    // in how they deal with writing modes and columns. RenderLayer rectangles tend to be more
    // physical than the rectangles used in RenderObject & co.
    //
    // The two rectangles passed to this method are physical, except that we pretend that there's
    // only one long column (that's the flow thread). They are relative to the top left corner of
    // the flow thread. All rectangles being compared to the dirty rect also need to be in this
    // coordinate system.
    //
    // Then there's the output from this method - the stuff we put into the list of fragments. The
    // translationOffset point is the actual physical translation required to get from a location in
    // the flow thread to a location in some column. The paginationClip rectangle is in the same
    // coordinate system as the two rectangles passed to this method (i.e. physical, in flow thread
    // coordinates, pretending that there's only one long column).
    //
    // All other rectangles in this method are slightly less physical, when it comes to how they are
    // used with different writing modes, but they aren't really logical either. They are just like
    // RenderBox::frameRect(). More precisely, the sizes are physical, and the inline direction
    // coordinate is too, but the block direction coordinate is always "logical top". These
    // rectangles also pretend that there's only one long column, i.e. they are for the flow thread.
    //
    // To sum up: input and output from this method are "physical" RenderLayer-style rectangles and
    // points, while inside this method we mostly use the RenderObject-style rectangles (with the
    // block direction coordinate always being logical top).

    // 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();
    
    RenderBlockFlow* parentFlow = toRenderBlockFlow(parent());
    bool progressionReversed = parentFlow->multiColumnFlowThread()->progressionIsReversed();
    bool progressionIsInline = parentFlow->multiColumnFlowThread()->progressionIsInline();
    
    LayoutUnit initialBlockOffset = initialBlockOffsetForPainting();
    
    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 = progressionIsInline ? i * (colLogicalWidth + colGap) : LayoutUnit();
        
        bool leftToRight = style().isLeftToRightDirection() ^ progressionReversed;
        if (!leftToRight) {
            inlineOffset = -inlineOffset;
            if (progressionReversed)
                inlineOffset += contentLogicalWidth() - colLogicalWidth;
        }
        translationOffset.setX(inlineOffset);
        LayoutUnit blockOffset = initialBlockOffset + (isHorizontalWritingMode() ? -flowThreadPortion.y() : -flowThreadPortion.x());
        if (!progressionIsInline) {
            if (!progressionReversed)
                blockOffset = i * colGap;
            else
                blockOffset -= i * (computedColumnHeight() + colGap);
        }
        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);
    }
}
Esempio n. 23
0
static PassRefPtr<InspectorObject> buildObjectForElementInfo(Node* node)
{
    if (!node->isElementNode() || !node->document().frame())
        return nullptr;

    RefPtr<InspectorObject> elementInfo = InspectorObject::create();

    Element* element = toElement(node);
    bool isXHTML = element->document().isXHTMLDocument();
    elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower());
    elementInfo->setString("idValue", element->getIdAttribute());
    HashSet<AtomicString> usedClassNames;
    if (element->hasClass() && element->isStyledElement()) {
        StringBuilder classNames;
        const SpaceSplitString& classNamesString = toStyledElement(element)->classNames();
        size_t classNameCount = classNamesString.size();
        for (size_t i = 0; i < classNameCount; ++i) {
            const AtomicString& className = classNamesString[i];
            if (usedClassNames.contains(className))
                continue;
            usedClassNames.add(className);
            classNames.append('.');
            classNames.append(className);
        }
        elementInfo->setString("className", classNames.toString());
    }

    RenderElement* renderer = element->renderer();
    Frame* containingFrame = node->document().frame();
    FrameView* containingView = containingFrame->view();
    IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
    RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : nullptr;
    elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), *modelObject) : boundingBox.width()));
    elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), *modelObject) : boundingBox.height()));
    
    if (renderer->isRenderNamedFlowFragmentContainer()) {
        RenderNamedFlowFragment* region = toRenderBlockFlow(renderer)->renderNamedFlowFragment();
        if (region->isValid()) {
            RenderFlowThread* flowThread = region->flowThread();
            ASSERT(flowThread && flowThread->isRenderNamedFlowThread());
            RefPtr<InspectorObject> regionFlowInfo = InspectorObject::create();
            regionFlowInfo->setString("name", toRenderNamedFlowThread(flowThread)->flowThreadName());
            regionFlowInfo->setArray("regions", buildObjectForCSSRegionsHighlight(region, flowThread));
            elementInfo->setObject("regionFlowInfo", regionFlowInfo.release());
        }
    }

    RenderFlowThread* containingFlowThread = renderer->flowThreadContainingBlock();
    if (containingFlowThread && containingFlowThread->isRenderNamedFlowThread()) {
        RefPtr<InspectorObject> contentFlowInfo = InspectorObject::create();
        contentFlowInfo->setString("name", toRenderNamedFlowThread(containingFlowThread)->flowThreadName());
        elementInfo->setObject("contentFlowInfo", contentFlowInfo.release());
    }

#if ENABLE(CSS_SHAPES)
    if (renderer->isBox()) {
        RenderBox* renderBox = toRenderBox(renderer);
        if (RefPtr<InspectorObject> shapeObject = buildObjectForShapeOutside(containingFrame, renderBox))
            elementInfo->setObject("shapeOutsideInfo", shapeObject.release());
    }
#endif

    // Need to enable AX to get the computed role.
    if (!WebCore::AXObjectCache::accessibilityEnabled())
        WebCore::AXObjectCache::enableAccessibility();

    if (AXObjectCache* axObjectCache = node->document().axObjectCache()) {
        if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node))
            elementInfo->setString("role", axObject->computedRoleString());
    }

    return elementInfo.release();
}
Esempio n. 24
0
RenderBlockFlow& RootInlineBox::blockFlow() const
{
    return toRenderBlockFlow(renderer());
}
Esempio n. 25
0
void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (paintInfo.context->paintingDisabled())
        return;

    RenderMultiColumnFlowThread* flowThread = toRenderBlockFlow(parent())->multiColumnFlowThread();
    const RenderStyle& blockStyle = parent()->style();
    const Color& ruleColor = blockStyle.visitedDependentColor(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);

    if (flowThread->progressionIsInline()) {
        bool leftToRight = style().isLeftToRightDirection() ^ flowThread->progressionIsReversed();
        LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth();
        LayoutUnit ruleAdd = logicalLeftOffsetForContent();
        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;
        }
    } else {
        bool topToBottom = !style().isFlippedBlocksWritingMode() ^ flowThread->progressionIsReversed();
        LayoutUnit ruleLeft = isHorizontalWritingMode() ? LayoutUnit() : colGap / 2 - colGap - ruleThickness / 2;
        LayoutUnit ruleWidth = isHorizontalWritingMode() ? contentWidth() : ruleThickness;
        LayoutUnit ruleTop = isHorizontalWritingMode() ? colGap / 2 - colGap - ruleThickness / 2 : LayoutUnit();
        LayoutUnit ruleHeight = isHorizontalWritingMode() ? ruleThickness : contentHeight();
        LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight);

        if (!topToBottom) {
            if (isHorizontalWritingMode())
                ruleRect.setY(height() - ruleRect.maxY());
            else
                ruleRect.setX(width() - ruleRect.maxX());
        }

        ruleRect.moveBy(paintOffset);

        BoxSide boxSide = isHorizontalWritingMode() ? topToBottom ? BSTop : BSBottom : topToBottom ? BSLeft : BSRight;

        LayoutSize step(0, topToBottom ? computedColumnHeight() + colGap : -(computedColumnHeight() + colGap));
        if (!isHorizontalWritingMode())
            step = step.transposedSize();

        for (unsigned i = 1; i < colCount; i++) {
            ruleRect.move(step);
            IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect);
            drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
        }
    }
}
Esempio n. 26
0
RenderLayer* RenderRegion::regionContainerLayer() const
{
    ASSERT(parent() && parent()->isRenderNamedFlowFragmentContainer());
    return toRenderBlockFlow(parent())->layer();
}
Esempio n. 27
0
LayoutState::LayoutState(std::unique_ptr<LayoutState> next, RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo)
    : m_columnInfo(columnInfo)
    , m_lineGrid(0)
    , m_next(std::move(next))
#if ENABLE(CSS_SHAPES)
    , m_shapeInsideInfo(0)
#endif
#ifndef NDEBUG
    , m_renderer(renderer)
#endif
{
    ASSERT(m_next);

    bool fixed = renderer->isOutOfFlowPositioned() && renderer->style().position() == FixedPosition;
    if (fixed) {
        // FIXME: This doesn't work correctly with transforms.
        FloatPoint fixedOffset = renderer->view().localToAbsolute(FloatPoint(), IsFixed);
        m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset;
    } else
        m_paintOffset = m_next->m_paintOffset + offset;

    if (renderer->isOutOfFlowPositioned() && !fixed) {
        if (RenderElement* container = renderer->container()) {
            if (container->isInFlowPositioned() && container->isRenderInline())
                m_paintOffset += toRenderInline(container)->offsetForInFlowPositionedInline(renderer);
        }
    }

    m_layoutOffset = m_paintOffset;

    if (renderer->isInFlowPositioned() && renderer->hasLayer())
        m_paintOffset += renderer->layer()->offsetForInFlowPosition();

    m_clipped = !fixed && m_next->m_clipped;
    if (m_clipped)
        m_clipRect = m_next->m_clipRect;

    if (renderer->hasOverflowClip()) {
        LayoutRect clipRect(toPoint(m_paintOffset) + renderer->view().layoutDelta(), renderer->cachedSizeForOverflowClip());
        if (m_clipped)
            m_clipRect.intersect(clipRect);
        else {
            m_clipRect = clipRect;
            m_clipped = true;
        }

        m_paintOffset -= renderer->scrolledContentOffset();
    }

    // If we establish a new page height, then cache the offset to the top of the first page.
    // We can compare this later on to figure out what part of the page we're actually on,
    if (pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread()) {
        m_pageLogicalHeight = pageLogicalHeight;
        bool isFlipped = renderer->style().isFlippedBlocksWritingMode();
        m_pageOffset = LayoutSize(m_layoutOffset.width() + (!isFlipped ? renderer->borderLeft() + renderer->paddingLeft() : renderer->borderRight() + renderer->paddingRight()),
                               m_layoutOffset.height() + (!isFlipped ? renderer->borderTop() + renderer->paddingTop() : renderer->borderBottom() + renderer->paddingBottom()));
        m_pageLogicalHeightChanged = pageLogicalHeightChanged;
    } else {
        // If we don't establish a new page height, then propagate the old page height and offset down.
        m_pageLogicalHeight = m_next->m_pageLogicalHeight;
        m_pageLogicalHeightChanged = m_next->m_pageLogicalHeightChanged;
        m_pageOffset = m_next->m_pageOffset;
        
        // Disable pagination for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and
        // writing mode roots.
        if (renderer->isUnsplittableForPagination())
            m_pageLogicalHeight = 0;
    }
    
    // Propagate line grid information.
    propagateLineGridInfo(renderer);

    if (!m_columnInfo)
        m_columnInfo = m_next->m_columnInfo;

#if ENABLE(CSS_SHAPES)
    if (renderer->isRenderBlock()) {
        const RenderBlock* renderBlock = toRenderBlock(renderer);
        m_shapeInsideInfo = renderBlock->shapeInsideInfo();
        if (!m_shapeInsideInfo && m_next->m_shapeInsideInfo && renderBlock->allowsShapeInsideInfoSharing())
            m_shapeInsideInfo = m_next->m_shapeInsideInfo;
    }
#endif

    m_layoutDelta = m_next->m_layoutDelta;
#if !ASSERT_DISABLED && ENABLE(SATURATED_LAYOUT_ARITHMETIC)
    m_layoutDeltaXSaturated = m_next->m_layoutDeltaXSaturated;
    m_layoutDeltaYSaturated = m_next->m_layoutDeltaYSaturated;
#endif
    
    m_isPaginated = m_pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread();

    if (lineGrid() && renderer->hasColumns() && renderer->style().hasInlineColumnAxis())
        computeLineGridPaginationOrigin(renderer);

    // If we have a new grid to track, then add it to our set.
    if (renderer->style().lineGrid() != RenderStyle::initialLineGrid() && renderer->isRenderBlockFlow())
        establishLineGrid(toRenderBlockFlow(renderer));

    // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
Esempio n. 28
0
RenderBlockFlow& RenderNamedFlowFragment::fragmentContainer() const
{
    ASSERT(parent());
    ASSERT(parent()->isRenderNamedFlowFragmentContainer());
    return *toRenderBlockFlow(parent());
}