Example #1
0
void BlockPainter::paintObject(const PaintInfo& paintInfo,
                               const LayoutPoint& paintOffset) {
  const PaintPhase paintPhase = paintInfo.phase;

  if (shouldPaintSelfBlockBackground(paintPhase)) {
    if (m_layoutBlock.style()->visibility() == EVisibility::Visible &&
        m_layoutBlock.hasBoxDecorationBackground())
      m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset);
    // We're done. We don't bother painting any children.
    if (paintPhase == PaintPhaseSelfBlockBackgroundOnly)
      return;
  }

  if (paintInfo.paintRootBackgroundOnly())
    return;

  if (paintPhase == PaintPhaseMask &&
      m_layoutBlock.style()->visibility() == EVisibility::Visible) {
    m_layoutBlock.paintMask(paintInfo, paintOffset);
    return;
  }

  if (paintPhase == PaintPhaseClippingMask &&
      m_layoutBlock.style()->visibility() == EVisibility::Visible) {
    BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset);
    return;
  }

  if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting())
    ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset);

  if (paintPhase != PaintPhaseSelfOutlineOnly) {
    Optional<ScopedPaintChunkProperties> m_scopedScrollProperty;
    Optional<ScrollRecorder> scrollRecorder;
    Optional<PaintInfo> scrolledPaintInfo;
    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
      const auto* objectProperties = m_layoutBlock.paintProperties();
      if (auto* scroll =
              objectProperties ? objectProperties->scroll() : nullptr) {
        PaintChunkProperties properties(paintInfo.context.getPaintController()
                                            .currentPaintChunkProperties());
        auto* scrollTranslation = objectProperties->scrollTranslation();
        DCHECK(scrollTranslation);
        properties.transform = scrollTranslation;
        properties.scroll = scroll;
        m_scopedScrollProperty.emplace(
            paintInfo.context.getPaintController(), m_layoutBlock,
            DisplayItem::paintPhaseToDrawingType(paintPhase), properties);
        scrolledPaintInfo.emplace(paintInfo);
        scrolledPaintInfo->updateCullRect(
            scrollTranslation->matrix().toAffineTransform());
      }
    } else if (m_layoutBlock.hasOverflowClip()) {
      IntSize scrollOffset = m_layoutBlock.scrolledContentOffset();
      if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) {
        scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPhase,
                               scrollOffset);
        scrolledPaintInfo.emplace(paintInfo);
        AffineTransform transform;
        transform.translate(-scrollOffset.width(), -scrollOffset.height());
        scrolledPaintInfo->updateCullRect(transform);
      }
    }

    const PaintInfo& contentsPaintInfo =
        scrolledPaintInfo ? *scrolledPaintInfo : paintInfo;

    if (m_layoutBlock.isLayoutBlockFlow()) {
      BlockFlowPainter blockFlowPainter(toLayoutBlockFlow(m_layoutBlock));
      blockFlowPainter.paintContents(contentsPaintInfo, paintOffset);
      if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection ||
          paintPhase == PaintPhaseTextClip)
        blockFlowPainter.paintFloats(contentsPaintInfo, paintOffset);
    } else {
      paintContents(contentsPaintInfo, paintOffset);
    }
  }

  if (shouldPaintSelfOutline(paintPhase))
    ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset);

  // If the caret's node's layout object's containing block is this block, and
  // the paint action is PaintPhaseForeground, then paint the caret.
  if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret())
    paintCarets(paintInfo, paintOffset);
}
void BlockPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    const PaintPhase paintPhase = paintInfo.phase;

    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground)
        && m_layoutBlock.style()->visibility() == VISIBLE
        && m_layoutBlock.hasBoxDecorationBackground())
        m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset);

    if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == VISIBLE) {
        m_layoutBlock.paintMask(paintInfo, paintOffset);
        return;
    }

    if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibility() == VISIBLE) {
        BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset);
        return;
    }

    // FIXME: When Skia supports annotation rect covering (https://code.google.com/p/skia/issues/detail?id=3872),
    // this rect may be covered by foreground and descendant drawings. Then we may need a dedicated paint phase.
    if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting())
        ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset);

    {
        Optional<ScrollRecorder> scrollRecorder;
        Optional<PaintInfo> scrolledPaintInfo;
        if (m_layoutBlock.hasOverflowClip()) {
            IntSize scrollOffset = m_layoutBlock.scrolledContentOffset();
            if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) {
                scrollRecorder.emplace(*paintInfo.context, m_layoutBlock, paintPhase, scrollOffset);
                scrolledPaintInfo.emplace(paintInfo);
                scrolledPaintInfo->rect.move(scrollOffset);
            }
        }

        // We're done. We don't bother painting any children.
        if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackgroundOnly())
            return;

        const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintInfo : paintInfo;

        if (paintPhase != PaintPhaseSelfOutline)
            paintContents(contentsPaintInfo, paintOffset);

        if (paintPhase == PaintPhaseForeground && !paintInfo.isPrinting())
            m_layoutBlock.paintSelection(contentsPaintInfo, paintOffset); // Fill in gaps in selection on lines and between blocks.

        if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip)
            m_layoutBlock.paintFloats(contentsPaintInfo, paintOffset, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
    }

    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_layoutBlock.style()->hasOutline() && m_layoutBlock.style()->visibility() == VISIBLE) {
        // Don't paint focus ring for anonymous block continuation because the
        // inline element having outline-style:auto paints the whole focus ring.
        if (!m_layoutBlock.style()->outlineStyleIsAuto() || !m_layoutBlock.isAnonymousBlockContinuation())
            ObjectPainter(m_layoutBlock).paintOutline(paintInfo, LayoutRect(paintOffset, m_layoutBlock.size()), visualOverflowRectWithPaintOffset(m_layoutBlock, paintOffset));
    }

    if (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)
        paintContinuationOutlines(paintInfo, paintOffset);

    // If the caret's node's layout object's containing block is this block, and the paint action is PaintPhaseForeground,
    // then paint the caret.
    if (paintPhase == PaintPhaseForeground && hasCaret() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutBlock, DisplayItem::Caret)) {
        LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutBlock, DisplayItem::Caret, visualOverflowRectWithPaintOffset(m_layoutBlock, paintOffset));
        paintCarets(paintInfo, paintOffset);
    }
}
Example #3
0
void BlockPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && m_layoutBlock.childrenInline() && !paintInfo.context.paintController().skippingCache()) {
        if (m_layoutBlock.paintOffsetChanged(paintOffset)) {
            LineBoxListPainter(m_layoutBlock.lineBoxes()).invalidateLineBoxPaintOffsets(paintInfo);
            paintInfo.context.paintController().invalidatePaintOffset(m_layoutBlock);
        }
        // Set previousPaintOffset here in case that m_layoutBlock paints nothing and no
        // LayoutObjectDrawingRecorder updates its previousPaintOffset.
        // TODO(wangxianzhu): Integrate paint offset checking into new paint invalidation.
        m_layoutBlock.mutableForPainting().setPreviousPaintOffset(paintOffset);
    }

    const PaintPhase paintPhase = paintInfo.phase;

    if ((paintPhase == PaintPhaseSelfBlockBackground || paintPhase == PaintPhaseBlockBackground)
        && m_layoutBlock.style()->visibility() == VISIBLE
        && m_layoutBlock.hasBoxDecorationBackground())
        m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset);

    if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == VISIBLE) {
        m_layoutBlock.paintMask(paintInfo, paintOffset);
        return;
    }

    if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibility() == VISIBLE) {
        BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset);
        return;
    }

    // FIXME: When Skia supports annotation rect covering (https://code.google.com/p/skia/issues/detail?id=3872),
    // this rect may be covered by foreground and descendant drawings. Then we may need a dedicated paint phase.
    if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting())
        ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset);

    {
        Optional<ScrollRecorder> scrollRecorder;
        Optional<PaintInfo> scrolledPaintInfo;
        if (m_layoutBlock.hasOverflowClip()) {
            IntSize scrollOffset = m_layoutBlock.scrolledContentOffset();
            if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) {
                scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPhase, scrollOffset);
                scrolledPaintInfo.emplace(paintInfo);
                AffineTransform transform;
                transform.translate(-scrollOffset.width(), -scrollOffset.height());
                scrolledPaintInfo->updateCullRect(transform);
            }
        }

        // We're done. We don't bother painting any children.
        if (paintPhase == PaintPhaseSelfBlockBackground || paintInfo.paintRootBackgroundOnly())
            return;

        const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintInfo : paintInfo;

        if (paintPhase != PaintPhaseSelfOutline)
            paintContents(contentsPaintInfo, paintOffset);

        if (paintPhase == PaintPhaseForeground && !paintInfo.isPrinting())
            m_layoutBlock.paintSelection(contentsPaintInfo, paintOffset); // Fill in gaps in selection on lines and between blocks.

        if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip)
            m_layoutBlock.paintFloats(contentsPaintInfo, paintOffset);
    }

    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_layoutBlock.style()->hasOutline() && m_layoutBlock.style()->visibility() == VISIBLE)
        ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset);

    // If the caret's node's layout object's containing block is this block, and the paint action is PaintPhaseForeground,
    // then paint the caret.
    if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutBlock, DisplayItem::Caret, paintOffset)) {
        LayoutRect bounds = m_layoutBlock.visualOverflowRect();
        bounds.moveBy(paintOffset);
        LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutBlock, DisplayItem::Caret, bounds, paintOffset);
        paintCarets(paintInfo, paintOffset);
    }
}