void TableCellPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    LayoutTable* table = m_layoutTableCell.table();
    if (!table->collapseBorders() && m_layoutTableCell.style()->emptyCells() == EmptyCellsHide && !m_layoutTableCell.firstChild())
        return;

    bool needsToPaintBorder = m_layoutTableCell.styleRef().hasBorderDecoration() && !table->collapseBorders();
    if (!m_layoutTableCell.hasBackground() && !m_layoutTableCell.styleRef().boxShadow() && !needsToPaintBorder)
        return;

    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutTableCell, DisplayItem::BoxDecorationBackground))
        return;

    LayoutRect visualOverflowRect = m_layoutTableCell.visualOverflowRect();
    visualOverflowRect.moveBy(paintOffset);
    // TODO(chrishtr): the pixel-snapping here is likely incorrect.
    LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutTableCell, DisplayItem::BoxDecorationBackground, pixelSnappedIntRect(visualOverflowRect));

    LayoutRect paintRect = paintBounds(paintOffset, DoNotAddOffsetFromParent);

    BoxPainter::paintBoxShadow(paintInfo, paintRect, m_layoutTableCell.styleRef(), Normal);

    // Paint our cell background.
    paintBackgroundsBehindCell(paintInfo, paintOffset, &m_layoutTableCell, DisplayItem::BoxDecorationBackground);

    BoxPainter::paintBoxShadow(paintInfo, paintRect, m_layoutTableCell.styleRef(), Inset);

    if (!needsToPaintBorder)
        return;

    BoxPainter::paintBorder(m_layoutTableCell, paintInfo, paintRect, m_layoutTableCell.styleRef());
}
예제 #2
0
void TableCellPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!paintInfo.shouldPaintWithinRoot(&m_layoutTableCell))
        return;

    LayoutTable* table = m_layoutTableCell.table();
    if (!table->collapseBorders() && m_layoutTableCell.style()->emptyCells() == HIDE && !m_layoutTableCell.firstChild())
        return;

    bool needsToPaintBorder = m_layoutTableCell.styleRef().hasBorder() && !table->collapseBorders();
    if (!m_layoutTableCell.hasBackground() && !m_layoutTableCell.styleRef().boxShadow() && !needsToPaintBorder)
        return;

    LayoutRect paintRect = paintBounds(paintOffset, DoNotAddOffsetFromParent);
    LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutTableCell, DisplayItem::BoxDecorationBackground, pixelSnappedIntRect(paintRect));
    if (recorder.canUseCachedDrawing())
        return;

    BoxPainter::paintBoxShadow(paintInfo, paintRect, m_layoutTableCell.styleRef(), Normal);

    // Paint our cell background.
    paintBackgroundsBehindCell(paintInfo, paintOffset, &m_layoutTableCell);

    BoxPainter::paintBoxShadow(paintInfo, paintRect, m_layoutTableCell.styleRef(), Inset);

    if (!needsToPaintBorder)
        return;

    BoxPainter::paintBorder(m_layoutTableCell, paintInfo, paintRect, m_layoutTableCell.styleRef());
}
예제 #3
0
void TableCellPainter::paintBackgroundsBehindCell(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutObject* backgroundObject)
{
    if (!paintInfo.shouldPaintWithinRoot(&m_layoutTableCell))
        return;

    if (!backgroundObject)
        return;

    if (m_layoutTableCell.style()->visibility() != VISIBLE)
        return;

    LayoutTable* tableElt = m_layoutTableCell.table();
    if (!tableElt->collapseBorders() && m_layoutTableCell.style()->emptyCells() == HIDE && !m_layoutTableCell.firstChild())
        return;

    Color c = backgroundObject->resolveColor(CSSPropertyBackgroundColor);
    const FillLayer& bgLayer = backgroundObject->style()->backgroundLayers();

    LayoutRect paintRect = paintBounds(paintOffset, backgroundObject != &m_layoutTableCell ? AddOffsetFromParent : DoNotAddOffsetFromParent);

    if (bgLayer.hasImage() || c.alpha()) {
        // We have to clip here because the background would paint
        // on top of the borders otherwise.  This only matters for cells and rows.
        bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == &m_layoutTableCell || backgroundObject == m_layoutTableCell.parent()) && tableElt->collapseBorders();
        GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip);
        if (shouldClip) {
            LayoutRect clipRect(paintRect.location(), m_layoutTableCell.size());
            clipRect.expand(m_layoutTableCell.borderInsets());
            paintInfo.context->clip(clipRect);
        }
        BoxPainter(m_layoutTableCell).paintFillLayers(paintInfo, c, bgLayer, paintRect, BackgroundBleedNone, SkXfermode::kSrcOver_Mode, backgroundObject);
    }
}
예제 #4
0
void TableCellPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!paintInfo.shouldPaintWithinRoot(&m_renderTableCell))
        return;

    RenderTable* tableElt = m_renderTableCell.table();
    if (!tableElt->collapseBorders() && m_renderTableCell.style()->emptyCells() == HIDE && !m_renderTableCell.firstChild())
        return;

    LayoutRect paintRect = paintBounds(paintOffset, DoNotAddOffsetFromParent);
    RenderDrawingRecorder recorder(paintInfo.context, m_renderTableCell, paintInfo.phase, pixelSnappedIntRect(paintRect));
    if (recorder.canUseCachedDrawing())
        return;

    BoxPainter::paintBoxShadow(paintInfo, paintRect, m_renderTableCell.style(), Normal);

    // Paint our cell background.
    paintBackgroundsBehindCell(paintInfo, paintOffset, &m_renderTableCell);

    BoxPainter::paintBoxShadow(paintInfo, paintRect, m_renderTableCell.style(), Inset);

    if (!m_renderTableCell.style()->hasBorder() || tableElt->collapseBorders())
        return;

    BoxPainter::paintBorder(m_renderTableCell, paintInfo, paintRect, m_renderTableCell.style());
}
예제 #5
0
void TableCellPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_layoutTableCell.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    LayoutTable* tableElt = m_layoutTableCell.table();
    if (!tableElt->collapseBorders() && m_layoutTableCell.style()->emptyCells() == HIDE && !m_layoutTableCell.firstChild())
        return;

    BoxPainter(m_layoutTableCell).paintMaskImages(paintInfo, paintBounds(paintOffset, DoNotAddOffsetFromParent));
}
void TableCellPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_layoutTableCell.style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    LayoutTable* tableElt = m_layoutTableCell.table();
    if (!tableElt->collapseBorders() && m_layoutTableCell.style()->emptyCells() == EmptyCellsHide && !m_layoutTableCell.firstChild())
        return;

    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutTableCell, paintInfo.phase))
        return;

    LayoutRect paintRect = paintBounds(paintOffset, DoNotAddOffsetFromParent);
    LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutTableCell, paintInfo.phase, paintRect);
    BoxPainter(m_layoutTableCell).paintMaskImages(paintInfo, paintRect);
}
예제 #7
0
void TableCellPainter::paintBackgroundsBehindCell(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutObject* backgroundObject, DisplayItem::Type type)
{
    if (!paintInfo.shouldPaintWithinRoot(&m_layoutTableCell))
        return;

    if (!backgroundObject)
        return;

    if (m_layoutTableCell.style()->visibility() != VISIBLE)
        return;

    LayoutTable* tableElt = m_layoutTableCell.table();
    if (!tableElt->collapseBorders() && m_layoutTableCell.style()->emptyCells() == HIDE && !m_layoutTableCell.firstChild())
        return;

    LayoutRect paintRect = paintBounds(paintOffset, backgroundObject != &m_layoutTableCell ? AddOffsetFromParent : DoNotAddOffsetFromParent);

    // Record drawing only if the cell is painting background from containers.
    Optional<LayoutObjectDrawingRecorder> recorder;
    if (backgroundObject != &m_layoutTableCell) {
        LayoutPoint adjustedPaintOffset = paintRect.location();
        if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutTableCell, type, adjustedPaintOffset))
            return;
        recorder.emplace(*paintInfo.context, m_layoutTableCell, type, paintRect, adjustedPaintOffset);
    } else {
        ASSERT(paintRect.location() == paintOffset);
    }

    Color c = backgroundObject->resolveColor(CSSPropertyBackgroundColor);
    const FillLayer& bgLayer = backgroundObject->style()->backgroundLayers();
    if (bgLayer.hasImage() || c.alpha()) {
        // We have to clip here because the background would paint
        // on top of the borders otherwise.  This only matters for cells and rows.
        bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == &m_layoutTableCell || backgroundObject == m_layoutTableCell.parent()) && tableElt->collapseBorders();
        GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip);
        if (shouldClip) {
            LayoutRect clipRect(paintRect.location(), m_layoutTableCell.size());
            clipRect.expand(m_layoutTableCell.borderInsets());
            paintInfo.context->clip(pixelSnappedIntRect(clipRect));
        }
        BoxPainter(m_layoutTableCell).paintFillLayers(paintInfo, c, bgLayer, paintRect, BackgroundBleedNone, SkXfermode::kSrcOver_Mode, backgroundObject);
    }
}
void TableCellPainter::paintCollapsedBorders(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, const CollapsedBorderValue& currentBorderValue)
{
    if (m_layoutTableCell.style()->visibility() != VISIBLE)
        return;

    const ComputedStyle& styleForCellFlow = m_layoutTableCell.styleForCellFlow();
    const CollapsedBorderValue* leftBorderValue = cachedCollapsedLeftBorder(styleForCellFlow);
    const CollapsedBorderValue* rightBorderValue = cachedCollapsedRightBorder(styleForCellFlow);
    const CollapsedBorderValue* topBorderValue = cachedCollapsedTopBorder(styleForCellFlow);
    const CollapsedBorderValue* bottomBorderValue = cachedCollapsedBottomBorder(styleForCellFlow);

    int displayItemType = DisplayItem::TableCollapsedBorderBase;
    int topWidth = 0;
    int bottomWidth = 0;
    int leftWidth = 0;
    int rightWidth = 0;
    if (topBorderValue) {
        if (topBorderValue->shouldPaint(currentBorderValue))
            displayItemType |= DisplayItem::TableCollapsedBorderTop;
        topWidth = topBorderValue->width();
    }
    if (bottomBorderValue) {
        if (bottomBorderValue->shouldPaint(currentBorderValue))
            displayItemType |= DisplayItem::TableCollapsedBorderBottom;
        bottomWidth = bottomBorderValue->width();
    }
    if (leftBorderValue) {
        if (leftBorderValue->shouldPaint(currentBorderValue))
            displayItemType |= DisplayItem::TableCollapsedBorderLeft;
        leftWidth = leftBorderValue->width();
    }
    if (rightBorderValue) {
        if (rightBorderValue->shouldPaint(currentBorderValue))
            displayItemType |= DisplayItem::TableCollapsedBorderRight;
        rightWidth = rightBorderValue->width();
    }
    if (displayItemType == DisplayItem::TableCollapsedBorderBase)
        return;

    // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
    LayoutRect paintRect = paintBounds(paintOffset, AddOffsetFromParent);
    IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2,
        paintRect.y() - topWidth / 2,
        paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2,
        paintRect.height() + topWidth / 2 + (bottomWidth + 1) / 2);

    if (!paintInfo.cullRect().intersectsCullRect(borderRect))
        return;

    GraphicsContext& graphicsContext = paintInfo.context;
    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(graphicsContext, m_layoutTableCell, static_cast<DisplayItem::Type>(displayItemType)))
        return;

    LayoutObjectDrawingRecorder recorder(graphicsContext, m_layoutTableCell, static_cast<DisplayItem::Type>(displayItemType), borderRect);
    Color cellColor = m_layoutTableCell.resolveColor(CSSPropertyColor);

    // We never paint diagonals at the joins.  We simply let the border with the highest
    // precedence paint on top of borders with lower precedence.
    if (displayItemType & DisplayItem::TableCollapsedBorderTop) {
        ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.y(), borderRect.maxX(), borderRect.y() + topWidth, BSTop,
            topBorderValue->color().resolve(cellColor), collapsedBorderStyle(topBorderValue->style()), 0, 0, true);
    }
    if (displayItemType & DisplayItem::TableCollapsedBorderBottom) {
        ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), BSBottom,
            bottomBorderValue->color().resolve(cellColor), collapsedBorderStyle(bottomBorderValue->style()), 0, 0, true);
    }
    if (displayItemType & DisplayItem::TableCollapsedBorderLeft) {
        ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.y(), borderRect.x() + leftWidth, borderRect.maxY(), BSLeft,
            leftBorderValue->color().resolve(cellColor), collapsedBorderStyle(leftBorderValue->style()), 0, 0, true);
    }
    if (displayItemType & DisplayItem::TableCollapsedBorderRight) {
        ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.maxX() - rightWidth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), BSRight,
            rightBorderValue->color().resolve(cellColor), collapsedBorderStyle(rightBorderValue->style()), 0, 0, true);
    }
}
예제 #9
0
void TableCellPainter::paintCollapsedBorders(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    ASSERT(paintInfo.phase == PaintPhaseCollapsedTableBorders);

    if (!paintInfo.shouldPaintWithinRoot(&m_layoutTableCell) || m_layoutTableCell.style()->visibility() != VISIBLE)
        return;

    LayoutRect paintRect = paintBounds(paintOffset, AddOffsetFromParent);

    LayoutRect drawingCullRect(paintRect);
    drawingCullRect.expandEdges(m_layoutTableCell.table()->outerBorderTop(), m_layoutTableCell.table()->outerBorderRight(),
        m_layoutTableCell.table()->outerBorderBottom(), m_layoutTableCell.table()->outerBorderLeft());
    if (drawingCullRect.y() >= paintInfo.rect.maxY())
        return;

    if (drawingCullRect.maxY() <= paintInfo.rect.y())
        return;

    const CollapsedBorderValue* tableCurrentBorderValue = m_layoutTableCell.table()->currentBorderValue();
    if (!tableCurrentBorderValue)
        return;

    const ComputedStyle& styleForCellFlow = m_layoutTableCell.styleForCellFlow();
    const CollapsedBorderValue& leftBorderValue = cachedCollapsedLeftBorder(styleForCellFlow);
    const CollapsedBorderValue& rightBorderValue = cachedCollapsedRightBorder(styleForCellFlow);
    const CollapsedBorderValue& topBorderValue = cachedCollapsedTopBorder(styleForCellFlow);
    const CollapsedBorderValue& bottomBorderValue = cachedCollapsedBottomBorder(styleForCellFlow);

    bool shouldPaintTop = topBorderValue.shouldPaint(*tableCurrentBorderValue);
    bool shouldPaintBottom = bottomBorderValue.shouldPaint(*tableCurrentBorderValue);
    bool shouldPaintLeft = leftBorderValue.shouldPaint(*tableCurrentBorderValue);
    bool shouldPaintRight = rightBorderValue.shouldPaint(*tableCurrentBorderValue);

    if (!shouldPaintTop && !shouldPaintBottom && !shouldPaintLeft && !shouldPaintRight)
        return;

    GraphicsContext* graphicsContext = paintInfo.context;
    LayoutObjectDrawingRecorder recorder(*graphicsContext, m_layoutTableCell, paintInfo.phase, drawingCullRect);
    if (recorder.canUseCachedDrawing())
        return;

    bool antialias = BoxPainter::shouldAntialiasLines(graphicsContext);

    // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
    int topWidth = topBorderValue.width();
    int bottomWidth = bottomBorderValue.width();
    int leftWidth = leftBorderValue.width();
    int rightWidth = rightBorderValue.width();

    IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2,
        paintRect.y() - topWidth / 2,
        paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2,
        paintRect.height() + topWidth / 2 + (bottomWidth + 1) / 2);

    Color cellColor = m_layoutTableCell.resolveColor(CSSPropertyColor);

    // We never paint diagonals at the joins.  We simply let the border with the highest
    // precedence paint on top of borders with lower precedence.
    if (shouldPaintTop) {
        ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.y(), borderRect.maxX(), borderRect.y() + topWidth, BSTop,
            topBorderValue.color().resolve(cellColor), collapsedBorderStyle(topBorderValue.style()), 0, 0, antialias);
    }
    if (shouldPaintBottom) {
        ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), BSBottom,
            bottomBorderValue.color().resolve(cellColor), collapsedBorderStyle(bottomBorderValue.style()), 0, 0, antialias);
    }
    if (shouldPaintLeft) {
        ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.x(), borderRect.y(), borderRect.x() + leftWidth, borderRect.maxY(), BSLeft,
            leftBorderValue.color().resolve(cellColor), collapsedBorderStyle(leftBorderValue.style()), 0, 0, antialias);
    }
    if (shouldPaintRight) {
        ObjectPainter::drawLineForBoxSide(graphicsContext, borderRect.maxX() - rightWidth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), BSRight,
            rightBorderValue.color().resolve(cellColor), collapsedBorderStyle(rightBorderValue.style()), 0, 0, antialias);
    }
}
예제 #10
0
void TableCellPainter::paintCollapsedBorders(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    ASSERT(paintInfo.phase == PaintPhaseCollapsedTableBorders);

    if (!paintInfo.shouldPaintWithinRoot(&m_renderTableCell) || m_renderTableCell.style()->visibility() != VISIBLE)
        return;

    LayoutRect paintRect = paintBounds(paintOffset, AddOffsetFromParent);
    if (paintRect.y() - m_renderTableCell.table()->outerBorderTop() >= paintInfo.rect.maxY())
        return;

    if (paintRect.maxY() + m_renderTableCell.table()->outerBorderBottom() <= paintInfo.rect.y())
        return;

    if (!m_renderTableCell.table()->currentBorderValue())
        return;

    RenderDrawingRecorder recorder(paintInfo.context, m_renderTableCell, paintInfo.phase, paintRect);
    if (recorder.canUseCachedDrawing())
        return;

    const RenderStyle* styleForCellFlow = m_renderTableCell.styleForCellFlow();
    CollapsedBorderValue leftVal = cachedCollapsedLeftBorder(styleForCellFlow);
    CollapsedBorderValue rightVal = cachedCollapsedRightBorder(styleForCellFlow);
    CollapsedBorderValue topVal = cachedCollapsedTopBorder(styleForCellFlow);
    CollapsedBorderValue bottomVal = cachedCollapsedBottomBorder(styleForCellFlow);

    // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
    int topWidth = topVal.width();
    int bottomWidth = bottomVal.width();
    int leftWidth = leftVal.width();
    int rightWidth = rightVal.width();

    IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2,
        paintRect.y() - topWidth / 2,
        paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2,
        paintRect.height() + topWidth / 2 + (bottomWidth + 1) / 2);

    EBorderStyle topStyle = collapsedBorderStyle(topVal.style());
    EBorderStyle bottomStyle = collapsedBorderStyle(bottomVal.style());
    EBorderStyle leftStyle = collapsedBorderStyle(leftVal.style());
    EBorderStyle rightStyle = collapsedBorderStyle(rightVal.style());

    bool renderTop = topStyle > BHIDDEN && !topVal.isTransparent();
    bool renderBottom = bottomStyle > BHIDDEN && !bottomVal.isTransparent();
    bool renderLeft = leftStyle > BHIDDEN && !leftVal.isTransparent();
    bool renderRight = rightStyle > BHIDDEN && !rightVal.isTransparent();

    // We never paint diagonals at the joins.  We simply let the border with the highest
    // precedence paint on top of borders with lower precedence.
    CollapsedBorders borders;
    borders.addBorder(topVal, BSTop, renderTop, borderRect.x(), borderRect.y(), borderRect.maxX(), borderRect.y() + topWidth, topStyle);
    borders.addBorder(bottomVal, BSBottom, renderBottom, borderRect.x(), borderRect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), bottomStyle);
    borders.addBorder(leftVal, BSLeft, renderLeft, borderRect.x(), borderRect.y(), borderRect.x() + leftWidth, borderRect.maxY(), leftStyle);
    borders.addBorder(rightVal, BSRight, renderRight, borderRect.maxX() - rightWidth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), rightStyle);

    GraphicsContext* graphicsContext = paintInfo.context;
    bool antialias = BoxPainter::shouldAntialiasLines(graphicsContext);

    for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
        if (border->borderValue.isSameIgnoringColor(*m_renderTableCell.table()->currentBorderValue())) {
            ObjectPainter::drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side,
                border->borderValue.color().resolve(m_renderTableCell.resolveColor(CSSPropertyColor)), border->style, 0, 0, antialias);
        }
    }
}