예제 #1
0
inline LayoutUnit borderAndPaddingBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode)
{
    switch (writingMode) {
    case TopToBottomWritingMode: return renderer.borderTop() + renderer.paddingTop();
    case BottomToTopWritingMode: return renderer.borderBottom() + renderer.paddingBottom();
    case LeftToRightWritingMode: return renderer.borderLeft() + renderer.paddingLeft();
    case RightToLeftWritingMode: return renderer.borderRight() + renderer.paddingRight();
    }

    ASSERT_NOT_REACHED();
    return renderer.borderAndPaddingBefore();
}
예제 #2
0
inline LayoutUnit borderAndPaddingStartWithStyleForWritingMode(const RenderBox& renderer, const RenderStyle* style)
{
    if (style->isHorizontalWritingMode()) {
        if (style->isLeftToRightDirection())
            return renderer.borderLeft() + renderer.paddingLeft();

        return renderer.borderRight() + renderer.paddingRight();
    }
    if (style->isLeftToRightDirection())
        return renderer.borderTop() + renderer.paddingTop();

    return renderer.borderBottom() + renderer.paddingBottom();
}
예제 #3
0
static inline LayoutUnit borderStartWithStyleForWritingMode(const RenderBox& renderer, const RenderStyle& style)
{
    if (style.isHorizontalWritingMode()) {
        if (style.isLeftToRightDirection())
            return renderer.borderLeft();
        
        return renderer.borderRight();
    }
    if (style.isLeftToRightDirection())
        return renderer.borderTop();
    
    return renderer.borderBottom();
}
예제 #4
0
int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
{
    RenderBox* box = m_layer->renderBox();
    ASSERT(box);
    RenderStyle* s = box->style();
    if (isHorizontal()) {
        bool ltr = s->direction() == LTR;
        int clientWidth = box->clientWidth();
        int contentWidth = ltr ? box->rightmostPosition(true, false) : box->leftmostPosition(true, false);
        if (ltr)
            contentWidth += (box->paddingRight() - box->borderLeft());
        else {
            contentWidth = box->width() - contentWidth;
            contentWidth += (box->paddingLeft() - box->borderRight());
        }
        if (dir == MRIGHT) {
            if (stopAtContentEdge)
                return max(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
            else
                return ltr ? contentWidth : clientWidth;
        }
        else {
            if (stopAtContentEdge)
                return min(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
            else
                return ltr ? -clientWidth : -contentWidth;
        }
    }
    else {
        int contentHeight = box->lowestPosition(true, false) -
                            box->borderTop() + box->paddingBottom();
        int clientHeight = box->clientHeight();
        if (dir == MUP) {
            if (stopAtContentEdge)
                return min(contentHeight - clientHeight, 0);
            else
                return -clientHeight;
        }
        else {
            if (stopAtContentEdge)
                return max(contentHeight - clientHeight, 0);
            else
                return contentHeight;
        }
    }
}
예제 #5
0
int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
{
    RenderBox* box = m_layer->renderBox();
    ASSERT(box);
    RenderStyle* s = box->style();
    if (isHorizontal()) {
        bool ltr = s->isLeftToRightDirection();
        LayoutUnit clientWidth = box->clientWidth();
        LayoutUnit contentWidth = ltr ? box->maxPreferredLogicalWidth() : box->minPreferredLogicalWidth();
        if (ltr)
            contentWidth += (box->paddingRight() - box->borderLeft());
        else {
            contentWidth = box->width() - contentWidth;
            contentWidth += (box->paddingLeft() - box->borderRight());
        }
        if (dir == MRIGHT) {
            if (stopAtContentEdge)
                return max<LayoutUnit>(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
            else
                return ltr ? contentWidth : clientWidth;
        }
        else {
            if (stopAtContentEdge)
                return min<LayoutUnit>(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
            else
                return ltr ? -clientWidth : -contentWidth;
        }
    }
    else {
        int contentHeight = box->layoutOverflowRect().maxY() - box->borderTop() + box->paddingBottom();
        int clientHeight = box->clientHeight();
        if (dir == MUP) {
            if (stopAtContentEdge)
                 return min(contentHeight - clientHeight, 0);
            else
                return -clientHeight;
        }
        else {
            if (stopAtContentEdge)
                return max(contentHeight - clientHeight, 0);
            else 
                return contentHeight;
        }
    }    
}
예제 #6
0
bool RenderView::initializeLayoutState(LayoutState& state)
{
    bool isSeamlessAncestorInFlowThread = false;

    // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
    state.m_clipped = false;
    
    // Check the writing mode of the seamless ancestor. It has to match our document's writing mode, or we won't inherit any
    // pagination information.
    RenderBox* seamlessAncestor = enclosingSeamlessRenderer(document());
    LayoutState* seamlessLayoutState = seamlessAncestor ? seamlessAncestor->view().layoutState() : 0;
    bool shouldInheritPagination = seamlessLayoutState && !m_pageLogicalHeight && seamlessAncestor->style()->writingMode() == style()->writingMode();
    
    state.m_pageLogicalHeight = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeight : m_pageLogicalHeight;
    state.m_pageLogicalHeightChanged = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeightChanged : m_pageLogicalHeightChanged;
    state.m_isPaginated = state.m_pageLogicalHeight;
    if (state.m_isPaginated && shouldInheritPagination) {
        // Set up the correct pagination offset. We can use a negative offset in order to push the top of the RenderView into its correct place
        // on a page. We can take the iframe's offset from the logical top of the first page and make the negative into the pagination offset within the child
        // view.
        bool isFlipped = seamlessAncestor->style()->isFlippedBlocksWritingMode();
        LayoutSize layoutOffset = seamlessLayoutState->layoutOffset();
        LayoutSize iFrameOffset(layoutOffset.width() + seamlessAncestor->x() + (!isFlipped ? seamlessAncestor->borderLeft() + seamlessAncestor->paddingLeft() :
            seamlessAncestor->borderRight() + seamlessAncestor->paddingRight()),
            layoutOffset.height() + seamlessAncestor->y() + (!isFlipped ? seamlessAncestor->borderTop() + seamlessAncestor->paddingTop() :
            seamlessAncestor->borderBottom() + seamlessAncestor->paddingBottom()));
        
        LayoutSize offsetDelta = seamlessLayoutState->m_pageOffset - iFrameOffset;
        state.m_pageOffset = offsetDelta;
        
        // Set the current render flow thread to point to our ancestor. This will allow the seamless document to locate the correct
        // regions when doing a layout.
        if (seamlessAncestor->flowThreadContainingBlock()) {
            flowThreadController().setCurrentRenderFlowThread(seamlessAncestor->view().flowThreadController().currentRenderFlowThread());
            isSeamlessAncestorInFlowThread = true;
        }
    }

    // FIXME: We need to make line grids and exclusions work with seamless iframes as well here. Basically all layout state information needs
    // to propagate here and not just pagination information.
    return isSeamlessAncestorInFlowThread;
}
예제 #7
0
static void buildRendererHighlight(RenderObject* renderer, RenderRegion* region, const HighlightConfig& highlightConfig, Highlight* highlight, InspectorOverlay::CoordinateSystem coordinateSystem)
{
    Frame* containingFrame = renderer->document().frame();
    if (!containingFrame)
        return;

    highlight->setDataFromConfig(highlightConfig);
    FrameView* containingView = containingFrame->view();
    FrameView* mainView = containingFrame->page()->mainFrame().view();

    // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
    bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();

    if (isSVGRenderer) {
        highlight->type = HighlightTypeRects;
        renderer->absoluteQuads(highlight->quads);
        for (size_t i = 0; i < highlight->quads.size(); ++i)
            contentsQuadToCoordinateSystem(mainView, containingView, highlight->quads[i], coordinateSystem);
    } else if (renderer->isBox() || renderer->isRenderInline()) {
        LayoutRect contentBox;
        LayoutRect paddingBox;
        LayoutRect borderBox;
        LayoutRect marginBox;

        if (renderer->isBox()) {
            RenderBox* renderBox = toRenderBox(renderer);

            LayoutBoxExtent margins(renderBox->marginTop(), renderBox->marginRight(), renderBox->marginBottom(), renderBox->marginLeft());

            if (!renderBox->isOutOfFlowPositioned() && region) {
                RenderBox::LogicalExtentComputedValues computedValues;
                renderBox->computeLogicalWidthInRegion(computedValues, region);
                margins.mutableLogicalLeft(renderBox->style().writingMode()) = computedValues.m_margins.m_start;
                margins.mutableLogicalRight(renderBox->style().writingMode()) = computedValues.m_margins.m_end;
            }

            paddingBox = renderBox->clientBoxRectInRegion(region);
            contentBox = LayoutRect(paddingBox.x() + renderBox->paddingLeft(), paddingBox.y() + renderBox->paddingTop(),
                paddingBox.width() - renderBox->paddingLeft() - renderBox->paddingRight(), paddingBox.height() - renderBox->paddingTop() - renderBox->paddingBottom());
            borderBox = LayoutRect(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
                paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
            marginBox = LayoutRect(borderBox.x() - margins.left(), borderBox.y() - margins.top(),
                borderBox.width() + margins.left() + margins.right(), borderBox.height() + margins.top() + margins.bottom());
        } else {
            RenderInline* renderInline = toRenderInline(renderer);

            // RenderInline's bounding box includes paddings and borders, excludes margins.
            borderBox = renderInline->linesBoundingBox();
            paddingBox = LayoutRect(borderBox.x() + renderInline->borderLeft(), borderBox.y() + renderInline->borderTop(),
                borderBox.width() - renderInline->borderLeft() - renderInline->borderRight(), borderBox.height() - renderInline->borderTop() - renderInline->borderBottom());
            contentBox = LayoutRect(paddingBox.x() + renderInline->paddingLeft(), paddingBox.y() + renderInline->paddingTop(),
                paddingBox.width() - renderInline->paddingLeft() - renderInline->paddingRight(), paddingBox.height() - renderInline->paddingTop() - renderInline->paddingBottom());
            // Ignore marginTop and marginBottom for inlines.
            marginBox = LayoutRect(borderBox.x() - renderInline->marginLeft(), borderBox.y(),
                borderBox.width() + renderInline->horizontalMarginExtent(), borderBox.height());
        }

        FloatQuad absContentQuad;
        FloatQuad absPaddingQuad;
        FloatQuad absBorderQuad;
        FloatQuad absMarginQuad;

        if (region) {
            RenderFlowThread* flowThread = region->flowThread();

            // Figure out the quads in the space of the RenderFlowThread.
            absContentQuad = renderer->localToContainerQuad(FloatRect(contentBox), flowThread);
            absPaddingQuad = renderer->localToContainerQuad(FloatRect(paddingBox), flowThread);
            absBorderQuad = renderer->localToContainerQuad(FloatRect(borderBox), flowThread);
            absMarginQuad = renderer->localToContainerQuad(FloatRect(marginBox), flowThread);

            // Move the quad relative to the space of the current region.
            LayoutRect flippedRegionRect(region->flowThreadPortionRect());
            flowThread->flipForWritingMode(flippedRegionRect);

            FloatSize delta = region->contentBoxRect().location() - flippedRegionRect.location();
            absContentQuad.move(delta);
            absPaddingQuad.move(delta);
            absBorderQuad.move(delta);
            absMarginQuad.move(delta);

            // Resolve the absolute quads starting from the current region.
            absContentQuad = region->localToAbsoluteQuad(absContentQuad);
            absPaddingQuad = region->localToAbsoluteQuad(absPaddingQuad);
            absBorderQuad = region->localToAbsoluteQuad(absBorderQuad);
            absMarginQuad = region->localToAbsoluteQuad(absMarginQuad);
        } else {
            absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox));
            absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
            absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox));
            absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox));
        }

        contentsQuadToCoordinateSystem(mainView, containingView, absContentQuad, coordinateSystem);
        contentsQuadToCoordinateSystem(mainView, containingView, absPaddingQuad, coordinateSystem);
        contentsQuadToCoordinateSystem(mainView, containingView, absBorderQuad, coordinateSystem);
        contentsQuadToCoordinateSystem(mainView, containingView, absMarginQuad, coordinateSystem);

        highlight->type = HighlightTypeNode;
        highlight->quads.append(absMarginQuad);
        highlight->quads.append(absBorderQuad);
        highlight->quads.append(absPaddingQuad);
        highlight->quads.append(absContentQuad);
    }
}
예제 #8
0
bool GraphicsLayerAndroid::repaint()
{
    LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
        this, gPaused, m_needsRepaint, m_haveContents);

    if (!gPaused && m_haveContents && m_needsRepaint && !m_image) {
        // with SkPicture, we request the entire layer's content.
        IntRect layerBounds(0, 0, m_size.width(), m_size.height());

        RenderLayer* layer = renderLayerFromClient(m_client);
        if (!layer)
            return false;
        if (m_foregroundLayer) {
            PaintingPhase phase(this);
            // Paint the background into a separate context.
            phase.set(GraphicsLayerPaintBackground);
            if (!paintContext(m_contentLayer->recordContext(), layerBounds))
                return false;
            m_contentLayer->checkTextPresence();

            // Construct the foreground layer and draw.
            RenderBox* box = layer->renderBox();
            int outline = box->view()->maximalOutlineSize();
            IntRect contentsRect(0, 0,
                                 box->borderLeft() + box->borderRight() + layer->scrollWidth(),
                                 box->borderTop() + box->borderBottom() + layer->scrollHeight());
            contentsRect.inflate(outline);
            // Update the foreground layer size.
            m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
            // Paint everything else into the main recording canvas.
            phase.clear(GraphicsLayerPaintBackground);

            // Paint at 0,0.
            IntSize scroll = layer->scrolledContentOffset();
            layer->scrollToOffset(0, 0);
            // At this point, it doesn't matter if painting failed.
            (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
            m_foregroundLayer->checkTextPresence();
            layer->scrollToOffset(scroll.width(), scroll.height());

            // Construct the clip layer for masking the contents.
            IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
            // absoluteBoundingBoxRect does not include the outline so we need
            // to offset the position.
            int x = box->borderLeft() + outline;
            int y = box->borderTop() + outline;
            int width = clip.width() - box->borderLeft() - box->borderRight();
            int height = clip.height() - box->borderTop() - box->borderBottom();
            m_foregroundClipLayer->setPosition(x, y);
            m_foregroundClipLayer->setSize(width, height);

            // Need to offset the foreground layer by the clip layer in order
            // for the contents to be in the correct position.
            m_foregroundLayer->setPosition(-x, -y);
            // Set the scrollable bounds of the layer.
            m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());

            // Invalidate the entire layer for now, as webkit will only send the
            // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
            // offsetting the invals by the scroll position would not be enough.
            // TODO: have webkit send us invals even for non visible area
            SkRegion region;
            region.setRect(0, 0, contentsRect.width(), contentsRect.height());
            m_foregroundLayer->markAsDirty(region);
            m_foregroundLayer->needsRepaint();
        } else {
            // If there is no contents clip, we can draw everything into one
            // picture.
            if (!paintContext(m_contentLayer->recordContext(), layerBounds))
                return false;
            m_contentLayer->checkTextPresence();
            // Check for a scrollable iframe and report the scrolling
            // limits based on the view size.
            if (m_contentLayer->contentIsScrollable()) {
                FrameView* view = layer->renderer()->frame()->view();
                static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits(
                    m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
            }
        }

        LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
            this, m_size.width(), m_size.height(),
            m_contentLayer->getPosition().fX,
            m_contentLayer->getPosition().fY,
            m_contentLayer->getSize().width(),
            m_contentLayer->getSize().height());

        m_contentLayer->markAsDirty(m_dirtyRegion);
        m_dirtyRegion.setEmpty();
        m_contentLayer->needsRepaint();
        m_needsRepaint = false;

        return true;
    }
    if (m_needsRepaint && m_image && m_newImage) {
        // We need to tell the GL thread that we will need to repaint the
        // texture. Only do so if we effectively have a new image!
        m_contentLayer->markAsDirty(m_dirtyRegion);
        m_dirtyRegion.setEmpty();
        m_contentLayer->needsRepaint();
        m_newImage = false;
        m_needsRepaint = false;
        return true;
    }
    return false;
}
예제 #9
0
LayoutState::LayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo, bool containingBlockLogicalWidthChanged)
    : m_containingBlockLogicalWidthChanged(containingBlockLogicalWidthChanged)
    , m_columnInfo(columnInfo)
    , m_next(renderer.view()->layoutState())
    , m_renderer(renderer)
{
    m_flowThread = renderer.isRenderFlowThread() ? toRenderFlowThread(&renderer) : m_next->flowThread();
    renderer.view()->pushLayoutState(*this);
    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_layoutOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset;
    } else {
        m_layoutOffset = m_next->m_layoutOffset + offset;
    }

    if (renderer.isOutOfFlowPositioned() && !fixed) {
        if (RenderObject* container = renderer.container()) {
            if (container->style()->hasInFlowPosition() && container->isRenderInline())
                m_layoutOffset += toRenderInline(container)->offsetForInFlowPositionedInline(renderer);
        }
    }
    // 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;
        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 || m_next->m_columnInfo || renderer.flowThreadContainingBlock();
        }
    }

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

    // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}