Beispiel #1
0
LayoutState::LayoutState(RenderObject& root)
    : m_clipped(false)
    , m_isPaginated(false)
    , m_pageLogicalHeightChanged(false)
#if !ASSERT_DISABLED && ENABLE(SATURATED_LAYOUT_ARITHMETIC)
    , m_layoutDeltaXSaturated(false)
    , m_layoutDeltaYSaturated(false)
#endif    
    , m_lineGrid(0)
    , m_pageLogicalHeight(0)
#ifndef NDEBUG
    , m_renderer(&root)
#endif
{
    RenderElement* container = root.container();
    FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), UseTransforms);
    m_paintOffset = LayoutSize(absContentPoint.x(), absContentPoint.y());

    if (container->hasOverflowClip()) {
        m_clipped = true;
        RenderBox* containerBox = toRenderBox(container);
        m_clipRect = LayoutRect(toLayoutPoint(m_paintOffset), containerBox->cachedSizeForOverflowClip());
        m_paintOffset -= containerBox->scrolledContentOffset();
    }
}
LayoutPoint LayoutMultiColumnFlowThread::visualPointToFlowThreadPoint(const LayoutPoint& visualPoint) const
{
    LayoutUnit blockOffset = isHorizontalWritingMode() ? visualPoint.y() : visualPoint.x();
    const LayoutMultiColumnSet* columnSet = nullptr;
    for (const LayoutMultiColumnSet* candidate = firstMultiColumnSet(); candidate; candidate = candidate->nextSiblingMultiColumnSet()) {
        columnSet = candidate;
        if (candidate->logicalBottom() > blockOffset)
            break;
    }
    return columnSet ? columnSet->visualPointToFlowThreadPoint(toLayoutPoint(visualPoint + location() - columnSet->location())) : visualPoint;
}
Beispiel #3
0
LayoutState::LayoutState(RenderObject& root)
    : m_clipped(false)
    , m_isPaginated(false)
    , m_pageLogicalHeightChanged(false)
#if !ASSERT_DISABLED
    , m_layoutDeltaXSaturated(false)
    , m_layoutDeltaYSaturated(false)
#endif    
#ifndef NDEBUG
    , m_renderer(&root)
#endif
{
    if (RenderElement* container = root.container()) {
        FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), UseTransforms);
        m_paintOffset = LayoutSize(absContentPoint.x(), absContentPoint.y());

        if (container->hasOverflowClip()) {
            m_clipped = true;
            auto& containerBox = downcast<RenderBox>(*container);
            m_clipRect = LayoutRect(toLayoutPoint(m_paintOffset), containerBox.cachedSizeForOverflowClip());
            m_paintOffset -= containerBox.scrolledContentOffset();
        }
    }
}
void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
{
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameView = m_page->mainFrame().view();
    if (!frameView)
        return;

    // Main frame.
    if (scrollingNodeID == frameView->scrollLayerID()) {
        bool oldProgrammaticScroll = frameView->inProgrammaticScroll();
        frameView->setInProgrammaticScroll(programmaticScroll);

        frameView->setConstrainsScrollingToContentEdge(false);
        frameView->notifyScrollPositionChanged(roundedIntPoint(scrollPosition));
        frameView->setConstrainsScrollingToContentEdge(true);

        frameView->setInProgrammaticScroll(oldProgrammaticScroll);

        if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
            GraphicsLayer* counterScrollingLayer = counterScrollingLayerForFrameView(frameView);
            GraphicsLayer* insetClipLayer = insetClipLayerForFrameView(frameView);
            GraphicsLayer* contentShadowLayer = contentShadowLayerForFrameView(frameView);
            GraphicsLayer* scrolledContentsLayer = rootContentLayerForFrameView(frameView);
            GraphicsLayer* headerLayer = headerLayerForFrameView(frameView);
            GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
            LayoutSize scrollOffsetForFixed = frameView->scrollOffsetForFixedPosition();

            float topContentInset = frameView->topContentInset();
            FloatPoint positionForInsetClipLayer = FloatPoint(0, FrameView::yPositionForInsetClipLayer(scrollPosition, topContentInset));
            FloatPoint positionForContentsLayer = FloatPoint(scrolledContentsLayer->position().x(),
                FrameView::yPositionForRootContentLayer(scrollPosition, topContentInset, frameView->headerHeight()));
            FloatPoint positionForHeaderLayer = FloatPoint(scrollOffsetForFixed.width(), FrameView::yPositionForHeaderLayer(scrollPosition, topContentInset));
            FloatPoint positionForFooterLayer = FloatPoint(scrollOffsetForFixed.width(),
                FrameView::yPositionForFooterLayer(scrollPosition, topContentInset, frameView->totalContentsSize().height(), frameView->footerHeight()));

            if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition) {
                scrollLayer->setPosition(-frameView->scrollPosition());
                if (counterScrollingLayer)
                    counterScrollingLayer->setPosition(toLayoutPoint(scrollOffsetForFixed));
                if (insetClipLayer)
                    insetClipLayer->setPosition(positionForInsetClipLayer);
                if (contentShadowLayer)
                    contentShadowLayer->setPosition(positionForContentsLayer);
                if (scrolledContentsLayer)
                    scrolledContentsLayer->setPosition(positionForContentsLayer);
                if (headerLayer)
                    headerLayer->setPosition(positionForHeaderLayer);
                if (footerLayer)
                    footerLayer->setPosition(positionForFooterLayer);
            } else {
                scrollLayer->syncPosition(-frameView->scrollPosition());
                if (counterScrollingLayer)
                    counterScrollingLayer->syncPosition(toLayoutPoint(scrollOffsetForFixed));
                if (insetClipLayer)
                    insetClipLayer->syncPosition(positionForInsetClipLayer);
                if (contentShadowLayer)
                    contentShadowLayer->syncPosition(positionForContentsLayer);
                if (scrolledContentsLayer)
                    scrolledContentsLayer->syncPosition(positionForContentsLayer);
                if (headerLayer)
                    headerLayer->syncPosition(positionForHeaderLayer);
                if (footerLayer)
                    footerLayer->syncPosition(positionForFooterLayer);

                LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
                syncChildPositions(viewportRect);
            }
        }

        return;
    }

    // Overflow-scroll area.
    if (ScrollableArea* scrollableArea = frameView->scrollableAreaForScrollLayerID(scrollingNodeID)) {
        scrollableArea->setIsUserScroll(scrollingLayerPositionAction == SyncScrollingLayerPosition);
        scrollableArea->scrollToOffsetWithoutAnimation(scrollPosition);
        scrollableArea->setIsUserScroll(false);
    }
}
void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
{
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameViewPtr = frameViewForScrollingNode(scrollingNodeID);
    if (!frameViewPtr)
        return;

    FrameView& frameView = *frameViewPtr;

    if (scrollingNodeID == frameView.scrollLayerID()) {
        bool oldProgrammaticScroll = frameView.inProgrammaticScroll();
        frameView.setInProgrammaticScroll(programmaticScroll);

        frameView.setConstrainsScrollingToContentEdge(false);
        frameView.notifyScrollPositionChanged(roundedIntPoint(scrollPosition));
        frameView.setConstrainsScrollingToContentEdge(true);

        frameView.setInProgrammaticScroll(oldProgrammaticScroll);

        if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
            GraphicsLayer* counterScrollingLayer = counterScrollingLayerForFrameView(frameView);
            GraphicsLayer* insetClipLayer = insetClipLayerForFrameView(frameView);
            GraphicsLayer* contentShadowLayer = contentShadowLayerForFrameView(frameView);
            GraphicsLayer* scrolledContentsLayer = rootContentLayerForFrameView(frameView);
            GraphicsLayer* headerLayer = headerLayerForFrameView(frameView);
            GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
            LayoutSize scrollOffsetForFixed = frameView.scrollOffsetForFixedPosition();

            float topContentInset = frameView.topContentInset();
            FloatPoint positionForInsetClipLayer = FloatPoint(0, FrameView::yPositionForInsetClipLayer(scrollPosition, topContentInset));
            FloatPoint positionForContentsLayer = FloatPoint(scrolledContentsLayer->position().x(),
                FrameView::yPositionForRootContentLayer(scrollPosition, topContentInset, frameView.headerHeight()));
            FloatPoint positionForHeaderLayer = FloatPoint(scrollOffsetForFixed.width(), FrameView::yPositionForHeaderLayer(scrollPosition, topContentInset));
            FloatPoint positionForFooterLayer = FloatPoint(scrollOffsetForFixed.width(),
                FrameView::yPositionForFooterLayer(scrollPosition, topContentInset, frameView.totalContentsSize().height(), frameView.footerHeight()));

            if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition) {
                scrollLayer->setPosition(-frameView.scrollPosition());
                if (counterScrollingLayer)
                    counterScrollingLayer->setPosition(toLayoutPoint(scrollOffsetForFixed));
                if (insetClipLayer)
                    insetClipLayer->setPosition(positionForInsetClipLayer);
                if (contentShadowLayer)
                    contentShadowLayer->setPosition(positionForContentsLayer);
                if (scrolledContentsLayer)
                    scrolledContentsLayer->setPosition(positionForContentsLayer);
                if (headerLayer)
                    headerLayer->setPosition(positionForHeaderLayer);
                if (footerLayer)
                    footerLayer->setPosition(positionForFooterLayer);
            } else {
                scrollLayer->syncPosition(-frameView.scrollPosition());
                if (counterScrollingLayer)
                    counterScrollingLayer->syncPosition(toLayoutPoint(scrollOffsetForFixed));
                if (insetClipLayer)
                    insetClipLayer->syncPosition(positionForInsetClipLayer);
                if (contentShadowLayer)
                    contentShadowLayer->syncPosition(positionForContentsLayer);
                if (scrolledContentsLayer)
                    scrolledContentsLayer->syncPosition(positionForContentsLayer);
                if (headerLayer)
                    headerLayer->syncPosition(positionForHeaderLayer);
                if (footerLayer)
                    footerLayer->syncPosition(positionForFooterLayer);

                LayoutRect viewportRect = frameView.viewportConstrainedVisibleContentRect();
                syncChildPositions(viewportRect);
            }
        }

#if PLATFORM(COCOA)
        if (m_page->expectsWheelEventTriggers()) {
            frameView.scrollAnimator().setWheelEventTestTrigger(m_page->testTrigger());
            if (const auto& trigger = m_page->testTrigger())
                trigger->removeTestDeferralForReason(reinterpret_cast<WheelEventTestTrigger::ScrollableAreaIdentifier>(scrollingNodeID), WheelEventTestTrigger::ScrollingThreadSyncNeeded);
        }
#endif
        
        return;
    }

    // Overflow-scroll area.
    if (ScrollableArea* scrollableArea = frameView.scrollableAreaForScrollLayerID(scrollingNodeID)) {
        scrollableArea->setIsUserScroll(scrollingLayerPositionAction == SyncScrollingLayerPosition);
        scrollableArea->scrollToOffsetWithoutAnimation(scrollPosition);
        scrollableArea->setIsUserScroll(false);
        if (scrollingLayerPositionAction == SetScrollingLayerPosition)
            m_page->editorClient().overflowScrollPositionChanged();

#if PLATFORM(COCOA)
        if (m_page->expectsWheelEventTriggers()) {
            frameView.scrollAnimator().setWheelEventTestTrigger(m_page->testTrigger());
            if (const auto& trigger = m_page->testTrigger())
                trigger->removeTestDeferralForReason(reinterpret_cast<WheelEventTestTrigger::ScrollableAreaIdentifier>(scrollingNodeID), WheelEventTestTrigger::ScrollingThreadSyncNeeded);
        }
#endif
    }
}
Beispiel #6
0
LayoutState::LayoutState(std::unique_ptr<LayoutState> next, RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged)
    : m_next(WTFMove(next))
#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() && is<RenderInline>(*container))
                m_paintOffset += downcast<RenderInline>(*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(toLayoutPoint(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 || 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;
        m_isPaginated = true;
    } 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;
            m_isPaginated = false;
        } else
            m_isPaginated = m_pageLogicalHeight || renderer->flowThreadContainingBlock();
    }
    
    // Propagate line grid information.
    propagateLineGridInfo(renderer);

    m_layoutDelta = m_next->m_layoutDelta;
#if !ASSERT_DISABLED
    m_layoutDeltaXSaturated = m_next->m_layoutDeltaXSaturated;
    m_layoutDeltaYSaturated = m_next->m_layoutDeltaYSaturated;
#endif

    if (lineGrid() && (lineGrid()->style().writingMode() == renderer->style().writingMode()) && is<RenderMultiColumnFlowThread>(*renderer))
        downcast<RenderMultiColumnFlowThread>(*renderer).computeLineGridPaginationOrigin(*this);

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

    // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
void MultiColumnFragmentainerGroup::collectLayerFragments(PaintLayerFragments& fragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect) const
{
    // |layerBoundingBox| is in the flow thread coordinate space, relative to the top/left edge of
    // the flow thread, but note that it has been converted with respect to writing mode (so that
    // it's visual/physical in that sense).
    //
    // |dirtyRect| is visual, relative to the multicol container.
    //
    // Then there's the output from this method - the stuff we put into the list of fragments. The
    // fragment.paginationOffset point is the actual visual 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 flow thread coordinates, but otherwise completely
    // physical in terms of writing mode.

    LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread();
    bool isHorizontalWritingMode = m_columnSet.isHorizontalWritingMode();

    // Put the layer bounds into flow thread-local coordinates by flipping it first. Since we're in
    // a layoutObject, 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(m_columnSet.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());

    // Figure out the start and end columns for the layer and only check within that range so that
    // we don't walk the entire column row.
    unsigned startColumn;
    unsigned endColumn;
    columnIntervalForBlockRangeInFlowThread(layerLogicalTop, layerLogicalBottom, startColumn, endColumn);

    // Now intersect with the columns actually occupied by the dirty rect, to narrow it down even further.
    unsigned firstColumnInDirtyRect, lastColumnInDirtyRect;
    columnIntervalForVisualRect(dirtyRect, firstColumnInDirtyRect, lastColumnInDirtyRect);
    if (firstColumnInDirtyRect > endColumn || lastColumnInDirtyRect < startColumn)
        return; // The two column intervals are disjoint. There's nothing to collect.
    if (startColumn < firstColumnInDirtyRect)
        startColumn = firstColumnInDirtyRect;
    if (endColumn > lastColumnInDirtyRect)
        endColumn = lastColumnInDirtyRect;
    ASSERT(endColumn >= startColumn);

    for (unsigned i = startColumn; i <= endColumn; i++) {
        PaintLayerFragment fragment;

        // Set the physical translation offset.
        fragment.paginationOffset = toLayoutPoint(flowThreadTranslationAtOffset(logicalTopInFlowThreadAt(i)));

        // Set the overflow clip rect that corresponds to the column.
        fragment.paginationClip = flowThreadPortionOverflowRectAt(i);
        // Flip it into more a physical (PaintLayer-style) rectangle.
        flowThread->flipForWritingMode(fragment.paginationClip);

        fragments.append(fragment);
    }
}