예제 #1
0
void SVGImagePainter::paint(PaintInfo& paintInfo)
{
    ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGImage);

    if (paintInfo.phase != PaintPhaseForeground
        || m_renderSVGImage.style()->visibility() == HIDDEN
        || !m_renderSVGImage.imageResource()->hasImage())
        return;

    FloatRect boundingBox = m_renderSVGImage.paintInvalidationRectInLocalCoordinates();
    if (!SVGRenderSupport::paintInfoIntersectsPaintInvalidationRect(boundingBox, m_renderSVGImage.localToParentTransform(), paintInfo))
        return;

    PaintInfo childPaintInfo(paintInfo);
    GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false);

    childPaintInfo.applyTransform(m_renderSVGImage.localToParentTransform(), &stateSaver);

    if (!m_renderSVGImage.objectBoundingBox().isEmpty()) {
        // SVGRenderingContext may taint the state - make sure we're always saving.
        stateSaver.saveIfNeeded();

        SVGRenderingContext renderingContext(&m_renderSVGImage, childPaintInfo);
        if (renderingContext.isRenderingPrepared()) {
            if (m_renderSVGImage.style()->svgStyle().bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_renderSVGImage.bufferedForeground()))
                return;

            paintForeground(m_renderSVGImage, childPaintInfo);
        }
    }

    if (m_renderSVGImage.style()->outlineWidth())
        ObjectPainter(m_renderSVGImage).paintOutline(childPaintInfo, IntRect(boundingBox));
}
void InlinePainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && !paintInfo.context->paintController().skippingCache()) {
        if (m_layoutInline.paintOffsetChanged(paintOffset)) {
            paintInfo.context->paintController().invalidatePaintOffset(m_layoutInline);
            LineBoxListPainter(*m_layoutInline.lineBoxes()).invalidateLineBoxPaintOffsets(paintInfo);
        }
        // Set previousPaintOffset here in case that m_layoutInline paints nothing and no
        // LayoutObjectDrawingRecorder updates its previousPaintOffset.
        // TODO(wangxianzhu): Integrate paint offset checking into new paint invalidation.
        m_layoutInline.mutableForPainting().setPreviousPaintOffset(paintOffset);
    }

    // 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 (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting())
        ObjectPainter(m_layoutInline).addPDFURLRectIfNeeded(paintInfo, paintOffset);

    if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseChildOutlines) {
        ObjectPainter painter(m_layoutInline);
        if (paintInfo.phase != PaintPhaseSelfOutline)
            painter.paintInlineChildrenOutlines(paintInfo, paintOffset);
        if (paintInfo.phase != PaintPhaseChildOutlines && !m_layoutInline.isElementContinuation())
            painter.paintOutline(paintInfo, paintOffset);
        return;
    }

    LineBoxListPainter(*m_layoutInline.lineBoxes()).paint(m_layoutInline, paintInfo, paintOffset);
}
예제 #3
0
void BlockFlowPainter::paintFloats(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!m_layoutBlockFlow.floatingObjects())
        return;

    ASSERT(paintInfo.phase == PaintPhaseFloat);
    PaintInfo floatPaintInfo(paintInfo);
    floatPaintInfo.phase = PaintPhaseForeground;

    for (const auto& floatingObject : m_layoutBlockFlow.floatingObjects()->set()) {
        if (!floatingObject->shouldPaint())
            continue;

        const LayoutBox* floatingLayoutObject = floatingObject->layoutObject();
        if (floatingLayoutObject->hasSelfPaintingLayer())
            continue;

        // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make this much cleaner.
        LayoutPoint childPoint = m_layoutBlockFlow.flipFloatForWritingModeForChild(
            *floatingObject, LayoutPoint(paintOffset.x()
            + m_layoutBlockFlow.xPositionForFloatIncludingMargin(*floatingObject) - floatingLayoutObject->location().x(), paintOffset.y()
            + m_layoutBlockFlow.yPositionForFloatIncludingMargin(*floatingObject) - floatingLayoutObject->location().y()));
        ObjectPainter(*floatingLayoutObject).paintAsPseudoStackingContext(floatPaintInfo, childPoint);
    }
}
예제 #4
0
void SVGImagePainter::paint(const PaintInfo& paintInfo)
{
    if (paintInfo.phase != PaintPhaseForeground
        || m_layoutSVGImage.style()->visibility() == HIDDEN
        || !m_layoutSVGImage.imageResource()->hasImage())
        return;

    FloatRect boundingBox = m_layoutSVGImage.paintInvalidationRectInLocalCoordinates();
    if (!paintInfo.cullRect().intersectsCullRect(m_layoutSVGImage.localToParentTransform(), boundingBox))
        return;

    PaintInfo paintInfoBeforeFiltering(paintInfo);
    // Images cannot have children so do not call updateCullRect.
    TransformRecorder transformRecorder(paintInfoBeforeFiltering.context, m_layoutSVGImage, m_layoutSVGImage.localToParentTransform());
    {
        SVGPaintContext paintContext(m_layoutSVGImage, paintInfoBeforeFiltering);
        if (paintContext.applyClipMaskAndFilterIfNecessary() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintContext.paintInfo().context, m_layoutSVGImage, paintContext.paintInfo().phase, LayoutPoint())) {
            LayoutObjectDrawingRecorder recorder(paintContext.paintInfo().context, m_layoutSVGImage, paintContext.paintInfo().phase, boundingBox, LayoutPoint());
            paintForeground(paintContext.paintInfo());
        }
    }

    if (m_layoutSVGImage.style()->outlineWidth()) {
        PaintInfo outlinePaintInfo(paintInfoBeforeFiltering);
        outlinePaintInfo.phase = PaintPhaseSelfOutline;
        ObjectPainter(m_layoutSVGImage).paintOutline(outlinePaintInfo, LayoutPoint(boundingBox.location()));
    }
}
예제 #5
0
void BlockFlowPainter::paintFloats(const PaintInfo& paintInfo,
                                   const LayoutPoint& paintOffset) {
  if (!m_layoutBlockFlow.floatingObjects())
    return;

  DCHECK(paintInfo.phase == PaintPhaseFloat ||
         paintInfo.phase == PaintPhaseSelection ||
         paintInfo.phase == PaintPhaseTextClip);
  PaintInfo floatPaintInfo(paintInfo);
  if (paintInfo.phase == PaintPhaseFloat)
    floatPaintInfo.phase = PaintPhaseForeground;

  for (const auto& floatingObject :
       m_layoutBlockFlow.floatingObjects()->set()) {
    if (!floatingObject->shouldPaint())
      continue;

    const LayoutBox* floatingLayoutObject = floatingObject->layoutObject();
    // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make
    // this much cleaner.
    LayoutPoint childPoint = m_layoutBlockFlow.flipFloatForWritingModeForChild(
        *floatingObject,
        LayoutPoint(paintOffset.x() +
                        m_layoutBlockFlow.xPositionForFloatIncludingMargin(
                            *floatingObject) -
                        floatingLayoutObject->location().x(),
                    paintOffset.y() +
                        m_layoutBlockFlow.yPositionForFloatIncludingMargin(
                            *floatingObject) -
                        floatingLayoutObject->location().y()));
    ObjectPainter(*floatingLayoutObject)
        .paintAllPhasesAtomically(floatPaintInfo, childPoint);
  }
}
void TableSectionPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_layoutTableSection);

    ASSERT(!m_layoutTableSection.needsLayout());
    // avoid crashing on bugs that cause us to paint with dirty layout
    if (m_layoutTableSection.needsLayout())
        return;

    unsigned totalRows = m_layoutTableSection.numRows();
    unsigned totalCols = m_layoutTableSection.table()->columns().size();

    if (!totalRows || !totalCols)
        return;

    LayoutPoint adjustedPaintOffset = paintOffset + m_layoutTableSection.location();
    {
        BoxClipper boxClipper(m_layoutTableSection, paintInfo, adjustedPaintOffset, ForceContentsClip);
        paintObject(paintInfo, adjustedPaintOffset);
    }

    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && m_layoutTableSection.style()->visibility() == VISIBLE) {
        LayoutRect visualOverflowRect(m_layoutTableSection.visualOverflowRect());
        visualOverflowRect.moveBy(adjustedPaintOffset);
        ObjectPainter(m_layoutTableSection).paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, m_layoutTableSection.size()), visualOverflowRect);
    }
}
예제 #7
0
void BlockPainter::paintInlineBox(const InlineBox& inlineBox,
                                  const PaintInfo& paintInfo,
                                  const LayoutPoint& paintOffset) {
  if (paintInfo.phase != PaintPhaseForeground &&
      paintInfo.phase != PaintPhaseSelection)
    return;

  // Text clips are painted only for the direct inline children of the object
  // that has a text clip style on it, not block children.
  DCHECK(paintInfo.phase != PaintPhaseTextClip);

  LayoutPoint childPoint = paintOffset;
  if (inlineBox.parent()
          ->getLineLayoutItem()
          .style()
          ->isFlippedBlocksWritingMode()) {
    // Faster than calling containingBlock().
    childPoint =
        LineLayoutAPIShim::layoutObjectFrom(inlineBox.getLineLayoutItem())
            ->containingBlock()
            ->flipForWritingModeForChild(
                toLayoutBox(LineLayoutAPIShim::layoutObjectFrom(
                    inlineBox.getLineLayoutItem())),
                childPoint);
  }

  ObjectPainter(
      *LineLayoutAPIShim::constLayoutObjectFrom(inlineBox.getLineLayoutItem()))
      .paintAllPhasesAtomically(paintInfo, childPoint);
}
예제 #8
0
static void addPDFURLRectsForInlineChildrenRecursively(const LayoutObject& layoutObject, const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    for (LayoutObject* child = layoutObject.slowFirstChild(); child; child = child->nextSibling()) {
        if (!child->isLayoutInline() || toLayoutBoxModelObject(child)->hasSelfPaintingLayer())
            continue;
        ObjectPainter(*child).addPDFURLRectIfNeeded(paintInfo, paintOffset);
        addPDFURLRectsForInlineChildrenRecursively(*child, paintInfo, paintOffset);
    }
}
예제 #9
0
void InlinePainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // 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 (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting())
        ObjectPainter(m_layoutInline).addPDFURLRectIfNeeded(paintInfo, paintOffset);

    LineBoxListPainter(*m_layoutInline.lineBoxes()).paint(&m_layoutInline, paintInfo, paintOffset);
}
예제 #10
0
void BlockPainter::paintAllChildPhasesAtomically(
    const LayoutBox& child,
    const PaintInfo& paintInfo,
    const LayoutPoint& paintOffset) {
  LayoutPoint childPoint =
      m_layoutBlock.flipForWritingModeForChild(&child, paintOffset);
  if (!child.hasSelfPaintingLayer() && !child.isFloating())
    ObjectPainter(child).paintAllPhasesAtomically(paintInfo, childPoint);
}
예제 #11
0
void InlinePainter::paintOutline(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    const ComputedStyle& styleToUse = m_layoutInline.styleRef();
    if (!styleToUse.hasOutline())
        return;

    if (styleToUse.outlineStyleIsAuto()) {
        if (!LayoutTheme::theme().shouldDrawDefaultFocusRing(&m_layoutInline))
            return;
        if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutInline, paintInfo.phase))
            return;

        Vector<LayoutRect> focusRingRects;
        m_layoutInline.addOutlineRects(focusRingRects, paintOffset);

        LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutInline, paintInfo.phase, outlinePaintRect(focusRingRects, LayoutPoint()));
        // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
        ObjectPainter(m_layoutInline).paintFocusRing(paintInfo, styleToUse, focusRingRects);
        return;
    }

    if (styleToUse.outlineStyle() == BNONE)
        return;

    GraphicsContext* graphicsContext = paintInfo.context;
    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*graphicsContext, m_layoutInline, paintInfo.phase))
        return;

    Vector<LayoutRect> rects;

    rects.append(LayoutRect());
    for (InlineFlowBox* curr = m_layoutInline.firstLineBox(); curr; curr = curr->nextLineBox()) {
        RootInlineBox& root = curr->root();
        LayoutUnit top = std::max<LayoutUnit>(root.lineTop(), curr->logicalTop());
        LayoutUnit bottom = std::min<LayoutUnit>(root.lineBottom(), curr->logicalBottom());
        rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
    }
    rects.append(LayoutRect());

    Color outlineColor = m_layoutInline.resolveColor(styleToUse, CSSPropertyOutlineColor);
    bool useTransparencyLayer = outlineColor.hasAlpha();

    LayoutObjectDrawingRecorder recorder(*graphicsContext, m_layoutInline, paintInfo.phase, outlinePaintRect(rects, paintOffset));
    if (useTransparencyLayer) {
        graphicsContext->beginLayer(static_cast<float>(outlineColor.alpha()) / 255);
        outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
    }

    for (unsigned i = 1; i < rects.size() - 1; i++)
        paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);

    if (useTransparencyLayer)
        graphicsContext->endLayer();
}
예제 #12
0
void BlockPainter::paintInlineBox(const InlineBox& inlineBox, const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!paintInfo.shouldPaintWithinRoot(&inlineBox.layoutObject()) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
        return;

    LayoutPoint childPoint = paintOffset;
    if (inlineBox.parent()->lineLayoutItem().style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock().
        childPoint = inlineBox.layoutObject().containingBlock()->flipForWritingModeForChild(&toLayoutBox(inlineBox.layoutObject()), childPoint);

    ObjectPainter(inlineBox.layoutObject()).paintAsPseudoStackingContext(paintInfo, childPoint);
}
void PartPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!m_layoutPart.shouldPaint(paintInfo, paintOffset))
        return;

    LayoutPoint adjustedPaintOffset = paintOffset + m_layoutPart.location();
    LayoutRect borderRect(adjustedPaintOffset, m_layoutPart.size());

    if (m_layoutPart.hasBoxDecorationBackground() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
        BoxPainter(m_layoutPart).paintBoxDecorationBackground(paintInfo, adjustedPaintOffset);

    if (paintInfo.phase == PaintPhaseMask) {
        BoxPainter(m_layoutPart).paintMask(paintInfo, adjustedPaintOffset);
        return;
    }

    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && m_layoutPart.style()->hasOutline())
        ObjectPainter(m_layoutPart).paintOutline(paintInfo, adjustedPaintOffset);

    if (paintInfo.phase != PaintPhaseForeground)
        return;

    {
        Optional<RoundedInnerRectClipper> clipper;
        if (m_layoutPart.style()->hasBorderRadius()) {
            if (borderRect.isEmpty())
                return;

            FloatRoundedRect roundedInnerRect = m_layoutPart.style()->getRoundedInnerBorderFor(borderRect,
                LayoutRectOutsets(
                    -(m_layoutPart.paddingTop() + m_layoutPart.borderTop()),
                    -(m_layoutPart.paddingRight() + m_layoutPart.borderRight()),
                    -(m_layoutPart.paddingBottom() + m_layoutPart.borderBottom()),
                    -(m_layoutPart.paddingLeft() + m_layoutPart.borderLeft())),
                true, true);
            clipper.emplace(m_layoutPart, paintInfo, borderRect, roundedInnerRect, ApplyToDisplayList);
        }

        if (m_layoutPart.widget())
            m_layoutPart.paintContents(paintInfo, paintOffset);
    }

    // Paint a partially transparent wash over selected widgets.
    if (isSelected() && !paintInfo.isPrinting() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutPart, paintInfo.phase, adjustedPaintOffset)) {
        LayoutRect rect = m_layoutPart.localSelectionRect();
        rect.moveBy(adjustedPaintOffset);
        IntRect selectionRect = pixelSnappedIntRect(rect);
        LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutPart, paintInfo.phase, selectionRect, adjustedPaintOffset);
        paintInfo.context->fillRect(selectionRect, m_layoutPart.selectionBackgroundColor());
    }

    if (m_layoutPart.canResize())
        ScrollableAreaPainter(*m_layoutPart.layer()->scrollableArea()).paintResizer(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.cullRect());
}
예제 #14
0
void TablePainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    PaintPhase paintPhase = paintInfo.phase;
    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && m_layoutTable.hasBoxDecorationBackground() && m_layoutTable.style()->visibility() == VISIBLE)
        paintBoxDecorationBackground(paintInfo, paintOffset);

    if (paintPhase == PaintPhaseMask) {
        paintMask(paintInfo, paintOffset);
        return;
    }

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

    // We don't paint our own background, but we do let the kids paint their backgrounds.
    if (paintPhase == PaintPhaseChildBlockBackgrounds)
        paintPhase = PaintPhaseChildBlockBackground;

    PaintInfo info(paintInfo);
    info.phase = paintPhase;
    info.updatePaintingRootForChildren(&m_layoutTable);

    for (LayoutObject* child = m_layoutTable.firstChild(); child; child = child->nextSibling()) {
        if (child->isBox() && !toLayoutBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
            LayoutPoint childPoint = m_layoutTable.flipForWritingModeForChild(toLayoutBox(child), paintOffset);
            child->paint(info, childPoint);
        }
    }

    if (m_layoutTable.collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && m_layoutTable.style()->visibility() == VISIBLE) {
        // Using our cached sorted styles, we then do individual passes,
        // painting each style of border from lowest precedence to highest precedence.
        info.phase = PaintPhaseCollapsedTableBorders;
        LayoutTable::CollapsedBorderValues collapsedBorders = m_layoutTable.collapsedBorders();
        size_t count = collapsedBorders.size();
        for (size_t i = 0; i < count; ++i) {
            // FIXME: pass this value into children rather than storing temporarily on the LayoutTable object.
            m_layoutTable.setCurrentBorderValue(&collapsedBorders[i]);
            for (LayoutTableSection* section = m_layoutTable.bottomSection(); section; section = m_layoutTable.sectionAbove(section)) {
                LayoutPoint childPoint = m_layoutTable.flipForWritingModeForChild(section, paintOffset);
                section->paint(info, childPoint);
            }
        }
        m_layoutTable.setCurrentBorderValue(0);
    }

    // Paint outline.
    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_layoutTable.style()->hasOutline() && m_layoutTable.style()->visibility() == VISIBLE) {
        LayoutRect overflowRect(m_layoutTable.visualOverflowRect());
        overflowRect.moveBy(paintOffset);
        ObjectPainter(m_layoutTable).paintOutline(paintInfo, LayoutRect(paintOffset, m_layoutTable.size()), overflowRect);
    }
}
예제 #15
0
void InlinePainter::paintOutline(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    RenderStyle* styleToUse = m_renderInline.style();
    if (!styleToUse->hasOutline())
        return;

    LayoutRect bounds;
    if (RuntimeEnabledFeatures::slimmingPaintEnabled()) {
        // FIXME: Use tighter bounds.
        RenderBlock* cb = m_renderInline.containingBlock();
        bounds = cb->visualOverflowRect();
        bounds.moveBy(paintOffset);
    }
    RenderDrawingRecorder recorder(paintInfo.context, m_renderInline, paintInfo.phase, bounds);
    if (recorder.canUseCachedDrawing())
        return;

    if (styleToUse->outlineStyleIsAuto()) {
        if (RenderTheme::theme().shouldDrawDefaultFocusRing(&m_renderInline)) {
            // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
            ObjectPainter(m_renderInline).paintFocusRing(paintInfo, paintOffset, styleToUse);
        }
        return;
    }

    if (styleToUse->outlineStyle() == BNONE)
        return;

    Vector<LayoutRect> rects;

    rects.append(LayoutRect());
    for (InlineFlowBox* curr = m_renderInline.firstLineBox(); curr; curr = curr->nextLineBox()) {
        RootInlineBox& root = curr->root();
        LayoutUnit top = std::max<LayoutUnit>(root.lineTop(), curr->logicalTop());
        LayoutUnit bottom = std::min<LayoutUnit>(root.lineBottom(), curr->logicalBottom());
        rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
    }
    rects.append(LayoutRect());

    Color outlineColor = m_renderInline.resolveColor(styleToUse, CSSPropertyOutlineColor);
    bool useTransparencyLayer = outlineColor.hasAlpha();

    GraphicsContext* graphicsContext = paintInfo.context;
    if (useTransparencyLayer) {
        graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255);
        outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
    }

    for (unsigned i = 1; i < rects.size() - 1; i++)
        paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);

    if (useTransparencyLayer)
        graphicsContext->endLayer();
}
예제 #16
0
void TablePainter::paintObject(const PaintInfo& paintInfo,
                               const LayoutPoint& paintOffset) {
  PaintPhase paintPhase = paintInfo.phase;

  if (shouldPaintSelfBlockBackground(paintPhase)) {
    paintBoxDecorationBackground(paintInfo, paintOffset);
    if (paintPhase == PaintPhaseSelfBlockBackgroundOnly)
      return;
  }

  if (paintPhase == PaintPhaseMask) {
    paintMask(paintInfo, paintOffset);
    return;
  }

  if (paintPhase != PaintPhaseSelfOutlineOnly) {
    PaintInfo paintInfoForDescendants = paintInfo.forDescendants();

    for (LayoutObject* child = m_layoutTable.firstChild(); child;
         child = child->nextSibling()) {
      if (child->isBox() && !toLayoutBox(child)->hasSelfPaintingLayer() &&
          (child->isTableSection() || child->isTableCaption())) {
        LayoutPoint childPoint = m_layoutTable.flipForWritingModeForChild(
            toLayoutBox(child), paintOffset);
        child->paint(paintInfoForDescendants, childPoint);
      }
    }

    if (m_layoutTable.collapseBorders() &&
        shouldPaintDescendantBlockBackgrounds(paintPhase) &&
        m_layoutTable.style()->visibility() == EVisibility::Visible) {
      // Using our cached sorted styles, we then do individual passes,
      // painting each style of border from lowest precedence to highest
      // precedence.
      LayoutTable::CollapsedBorderValues collapsedBorders =
          m_layoutTable.collapsedBorders();
      size_t count = collapsedBorders.size();
      for (size_t i = 0; i < count; ++i) {
        for (LayoutTableSection* section = m_layoutTable.bottomSection();
             section; section = m_layoutTable.sectionAbove(section)) {
          LayoutPoint childPoint =
              m_layoutTable.flipForWritingModeForChild(section, paintOffset);
          TableSectionPainter(*section).paintCollapsedBorders(
              paintInfoForDescendants, childPoint, collapsedBorders[i]);
        }
      }
    }
  }

  if (shouldPaintSelfOutline(paintPhase))
    ObjectPainter(m_layoutTable).paintOutline(paintInfo, paintOffset);
}
예제 #17
0
void SVGInlineFlowBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);

    {
        SVGPaintContext paintContext(m_svgInlineFlowBox.layoutObject(), paintInfo);
        if (paintContext.applyClipMaskAndFilterIfNecessary()) {
            for (InlineBox* child = m_svgInlineFlowBox.firstChild(); child; child = child->nextOnLine())
                child->paint(paintContext.paintInfo(), paintOffset, 0, 0);
        }
    }

    if (m_svgInlineFlowBox.layoutObject().styleRef().hasOutline()) {
        PaintInfo outlinePaintInfo(paintInfo);
        outlinePaintInfo.phase = PaintPhaseSelfOutline;
        ObjectPainter(m_svgInlineFlowBox.layoutObject()).paintOutline(outlinePaintInfo, paintOffset);
    }
}
예제 #18
0
void InlinePainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // 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 (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting())
        ObjectPainter(m_layoutInline).addPDFURLRectIfNeeded(paintInfo, paintOffset);

    if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseChildOutlines) {
        ObjectPainter painter(m_layoutInline);
        if (paintInfo.phase != PaintPhaseSelfOutline)
            painter.paintInlineChildrenOutlines(paintInfo, paintOffset);
        if (paintInfo.phase != PaintPhaseChildOutlines && !m_layoutInline.isElementContinuation())
            painter.paintOutline(paintInfo, paintOffset);
        return;
    }

    LineBoxListPainter(*m_layoutInline.lineBoxes()).paint(&m_layoutInline, paintInfo, paintOffset);
}
void SVGImagePainter::paint(const PaintInfo& paintInfo)
{
    if (paintInfo.phase != PaintPhaseForeground
        || m_layoutSVGImage.style()->visibility() == HIDDEN
        || !m_layoutSVGImage.imageResource()->hasImage())
        return;

    FloatRect boundingBox = m_layoutSVGImage.paintInvalidationRectInLocalCoordinates();
    if (!paintInfo.intersectsCullRect(m_layoutSVGImage.localToParentTransform(), boundingBox))
        return;

    PaintInfo paintInfoBeforeFiltering(paintInfo);
    // Images cannot have children so do not call updateCullRectForSVGTransform.
    TransformRecorder transformRecorder(*paintInfoBeforeFiltering.context, m_layoutSVGImage, m_layoutSVGImage.localToParentTransform());
    {
        SVGPaintContext paintContext(m_layoutSVGImage, paintInfoBeforeFiltering);
        if (paintContext.applyClipMaskAndFilterIfNecessary() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintContext.paintInfo().context, m_layoutSVGImage, paintContext.paintInfo().phase)) {
            LayoutObjectDrawingRecorder recorder(*paintContext.paintInfo().context, m_layoutSVGImage, paintContext.paintInfo().phase, boundingBox);
            // There's no need to cache a buffered SkPicture with slimming
            // paint because it's automatically done in the display list.
            if (m_layoutSVGImage.style()->svgStyle().bufferedRendering() != BR_STATIC || RuntimeEnabledFeatures::slimmingPaintEnabled()) {
                paintForeground(paintContext.paintInfo());
            } else {
                RefPtr<const SkPicture>& bufferedForeground = m_layoutSVGImage.bufferedForeground();
                if (!bufferedForeground) {
                    paintContext.paintInfo().context->beginRecording(m_layoutSVGImage.objectBoundingBox());
                    paintForeground(paintContext.paintInfo());
                    bufferedForeground = paintContext.paintInfo().context->endRecording();
                }

                paintContext.paintInfo().context->drawPicture(bufferedForeground.get());
            }
        }
    }

    if (m_layoutSVGImage.style()->outlineWidth()) {
        PaintInfo outlinePaintInfo(paintInfoBeforeFiltering);
        outlinePaintInfo.phase = PaintPhaseSelfOutline;
        LayoutRect layoutBoundingBox(boundingBox);
        LayoutRect visualOverflowRect = ObjectPainter::outlineBounds(layoutBoundingBox, m_layoutSVGImage.styleRef());
        ObjectPainter(m_layoutSVGImage).paintOutline(outlinePaintInfo, layoutBoundingBox, visualOverflowRect);
    }
}
예제 #20
0
void BlockFlowPainter::paintContents(const PaintInfo& paintInfo,
                                     const LayoutPoint& paintOffset) {
  // Avoid painting descendants of the root element when stylesheets haven't
  // loaded. This eliminates FOUC.  It's ok not to draw, because later on, when
  // all the stylesheets do load, styleResolverMayHaveChanged() on Document will
  // trigger a full paint invalidation.
  if (m_layoutBlockFlow.document().didLayoutWithPendingStylesheets() &&
      !m_layoutBlockFlow.isLayoutView())
    return;

  if (!m_layoutBlockFlow.childrenInline()) {
    BlockPainter(m_layoutBlockFlow).paintContents(paintInfo, paintOffset);
    return;
  }
  if (shouldPaintDescendantOutlines(paintInfo.phase))
    ObjectPainter(m_layoutBlockFlow)
        .paintInlineChildrenOutlines(paintInfo, paintOffset);
  else
    LineBoxListPainter(m_layoutBlockFlow.lineBoxes())
        .paint(m_layoutBlockFlow, paintInfo, paintOffset);
}
예제 #21
0
void SVGForeignObjectPainter::paint(const PaintInfo& paintInfo) {
  if (paintInfo.phase != PaintPhaseForeground &&
      paintInfo.phase != PaintPhaseSelection)
    return;

  PaintInfo paintInfoBeforeFiltering(paintInfo);
  paintInfoBeforeFiltering.updateCullRect(
      m_layoutSVGForeignObject.localSVGTransform());
  SVGTransformContext transformContext(
      paintInfoBeforeFiltering.context, m_layoutSVGForeignObject,
      m_layoutSVGForeignObject.localSVGTransform());

  Optional<FloatClipRecorder> clipRecorder;
  if (SVGLayoutSupport::isOverflowHidden(&m_layoutSVGForeignObject))
    clipRecorder.emplace(paintInfoBeforeFiltering.context,
                         m_layoutSVGForeignObject,
                         paintInfoBeforeFiltering.phase,
                         m_layoutSVGForeignObject.viewportRect());

  SVGPaintContext paintContext(m_layoutSVGForeignObject,
                               paintInfoBeforeFiltering);
  bool continueRendering = true;
  if (paintContext.paintInfo().phase == PaintPhaseForeground)
    continueRendering = paintContext.applyClipMaskAndFilterIfNecessary();

  if (continueRendering) {
    // Paint all phases of FO elements atomically as though the FO element
    // established its own stacking context.  The delegate forwards calls to
    // paint() in LayoutObject::paintAllPhasesAtomically() to
    // BlockPainter::paint(), instead of m_layoutSVGForeignObject.paint() (which
    // would call this method again).
    BlockPainterDelegate delegate(m_layoutSVGForeignObject);
    ObjectPainter(delegate).paintAllPhasesAtomically(paintContext.paintInfo(),
                                                     LayoutPoint());
  }
}
예제 #22
0
void SVGImagePainter::paint(const PaintInfo& paintInfo)
{
    ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGImage);

    if (paintInfo.phase != PaintPhaseForeground
        || m_renderSVGImage.style()->visibility() == HIDDEN
        || !m_renderSVGImage.imageResource()->hasImage())
        return;

    FloatRect boundingBox = m_renderSVGImage.paintInvalidationRectInLocalCoordinates();

    PaintInfo childPaintInfo(paintInfo);
    GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
    TransformRecorder transformRecorder(*childPaintInfo.context, m_renderSVGImage.displayItemClient(), m_renderSVGImage.localToParentTransform());
    SVGRenderingContext renderingContext(&m_renderSVGImage, childPaintInfo);
    if (renderingContext.isRenderingPrepared()) {
        RenderDrawingRecorder recorder(childPaintInfo.context, m_renderSVGImage, childPaintInfo.phase, boundingBox);
        if (!recorder.canUseCachedDrawing()) {
            if (m_renderSVGImage.style()->svgStyle().bufferedRendering() != BR_STATIC) {
                paintForeground(childPaintInfo);
            } else {
                RefPtr<const SkPicture>& bufferedForeground = m_renderSVGImage.bufferedForeground();
                if (!bufferedForeground) {
                    childPaintInfo.context->beginRecording(m_renderSVGImage.objectBoundingBox());
                    paintForeground(childPaintInfo);
                    bufferedForeground = childPaintInfo.context->endRecording();
                }

                childPaintInfo.context->drawPicture(bufferedForeground.get());
            }
        }
    }

    if (m_renderSVGImage.style()->outlineWidth())
        ObjectPainter(m_renderSVGImage).paintOutline(childPaintInfo, IntRect(boundingBox));
}
예제 #23
0
void BlockPainter::paintContents(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // Avoid painting descendants of the root element when stylesheets haven't loaded. This eliminates FOUC.
    // It's ok not to draw, because later on, when all the stylesheets do load, styleResolverChanged() on the Document
    // will do a full paint invalidation.
    if (m_layoutBlock.document().didLayoutWithPendingStylesheets() && !m_layoutBlock.isLayoutView())
        return;

    if (m_layoutBlock.childrenInline()) {
        if (paintInfo.phase == PaintPhaseDescendantOutlines)
            ObjectPainter(m_layoutBlock).paintInlineChildrenOutlines(paintInfo, paintOffset);
        else
            LineBoxListPainter(m_layoutBlock.lineBoxes()).paint(m_layoutBlock, paintInfo, paintOffset);
    } else {
        PaintPhase newPhase = (paintInfo.phase == PaintPhaseDescendantOutlines) ? PaintPhaseOutline : paintInfo.phase;
        newPhase = (newPhase == PaintPhaseDescendantBlockBackgrounds) ? PaintPhaseBlockBackground : newPhase;

        // We don't paint our own background, but we do let the kids paint their backgrounds.
        PaintInfo paintInfoForChild(paintInfo);
        paintInfoForChild.phase = newPhase;
        paintInfoForChild.updatePaintingRootForChildren(&m_layoutBlock);
        m_layoutBlock.paintChildren(paintInfoForChild, paintOffset);
    }
}
예제 #24
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);
    }
}
예제 #25
0
void ReplacedPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!m_layoutReplaced.shouldPaint(paintInfo, paintOffset))
        return;

    LayoutPoint adjustedPaintOffset = paintOffset + m_layoutReplaced.location();
    LayoutRect borderRect(adjustedPaintOffset, m_layoutReplaced.size());

    if (m_layoutReplaced.hasBoxDecorationBackground() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
        m_layoutReplaced.paintBoxDecorationBackground(paintInfo, adjustedPaintOffset);

    if (paintInfo.phase == PaintPhaseMask) {
        m_layoutReplaced.paintMask(paintInfo, adjustedPaintOffset);
        return;
    }

    if (paintInfo.phase == PaintPhaseClippingMask && (!m_layoutReplaced.hasLayer() || !m_layoutReplaced.layer()->hasCompositedClippingMask()))
        return;

    if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
        if (m_layoutReplaced.styleRef().outlineWidth())
            ObjectPainter(m_layoutReplaced).paintOutline(paintInfo, adjustedPaintOffset);
        return;
    }

    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && !m_layoutReplaced.canHaveChildren() && paintInfo.phase != PaintPhaseClippingMask)
        return;

    if (!paintInfo.shouldPaintWithinRoot(&m_layoutReplaced))
        return;

    if (paintInfo.phase == PaintPhaseSelection)
        if (m_layoutReplaced.selectionState() == SelectionNone)
            return;

    {
        Optional<RoundedInnerRectClipper> clipper;
        bool completelyClippedOut = false;
        if (m_layoutReplaced.style()->hasBorderRadius()) {
            if (borderRect.isEmpty()) {
                completelyClippedOut = true;
            } else if (shouldApplyViewportClip(m_layoutReplaced)) {
                // Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
                FloatRoundedRect roundedInnerRect = m_layoutReplaced.style()->getRoundedInnerBorderFor(borderRect,
                    LayoutRectOutsets(
                        -(m_layoutReplaced.paddingTop() + m_layoutReplaced.borderTop()),
                        -(m_layoutReplaced.paddingRight() + m_layoutReplaced.borderRight()),
                        -(m_layoutReplaced.paddingBottom() + m_layoutReplaced.borderBottom()),
                        -(m_layoutReplaced.paddingLeft() + m_layoutReplaced.borderLeft())),
                    true, true);

                clipper.emplace(m_layoutReplaced, paintInfo, borderRect, roundedInnerRect, ApplyToDisplayList);
            }
        }

        if (!completelyClippedOut) {
            if (paintInfo.phase == PaintPhaseClippingMask) {
                BoxPainter(m_layoutReplaced).paintClippingMask(paintInfo, adjustedPaintOffset);
            } else {
                m_layoutReplaced.paintReplaced(paintInfo, adjustedPaintOffset);
            }
        }
    }

    // The selection tint never gets clipped by border-radius rounding, since we want it to run right up to the edges of
    // surrounding content.
    bool drawSelectionTint = paintInfo.phase == PaintPhaseForeground && m_layoutReplaced.selectionState() != SelectionNone && !paintInfo.isPrinting();
    if (drawSelectionTint && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutReplaced, DisplayItem::SelectionTint, adjustedPaintOffset)) {
        LayoutRect selectionPaintingRect = m_layoutReplaced.localSelectionRect();
        selectionPaintingRect.moveBy(adjustedPaintOffset);
        IntRect selectionPaintingIntRect = pixelSnappedIntRect(selectionPaintingRect);

        LayoutObjectDrawingRecorder drawingRecorder(paintInfo.context, m_layoutReplaced, DisplayItem::SelectionTint, selectionPaintingIntRect, adjustedPaintOffset);
        paintInfo.context.fillRect(selectionPaintingIntRect, m_layoutReplaced.selectionBackgroundColor());
    }
}
예제 #26
0
void TableRowPainter::paintOutline(const PaintInfo& paintInfo,
                                   const LayoutPoint& paintOffset) {
    DCHECK(shouldPaintSelfOutline(paintInfo.phase));
    LayoutPoint adjustedPaintOffset = paintOffset + m_layoutTableRow.location();
    ObjectPainter(m_layoutTableRow).paintOutline(paintInfo, adjustedPaintOffset);
}
예제 #27
0
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);
    }
}
예제 #28
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 SVGShapePainter::paint(const PaintInfo& paintInfo)
{
    if (paintInfo.phase != PaintPhaseForeground
        || m_layoutSVGShape.style()->visibility() == HIDDEN
        || m_layoutSVGShape.isShapeEmpty())
        return;

    FloatRect boundingBox = m_layoutSVGShape.paintInvalidationRectInLocalCoordinates();
    if (!paintInfo.cullRect().intersectsCullRect(m_layoutSVGShape.localTransform(), boundingBox))
        return;

    PaintInfo paintInfoBeforeFiltering(paintInfo);
    // Shapes cannot have children so do not call updateCullRect.
    TransformRecorder transformRecorder(paintInfoBeforeFiltering.context, m_layoutSVGShape, m_layoutSVGShape.localTransform());
    {
        SVGPaintContext paintContext(m_layoutSVGShape, paintInfoBeforeFiltering);
        if (paintContext.applyClipMaskAndFilterIfNecessary() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintContext.paintInfo().context, m_layoutSVGShape, paintContext.paintInfo().phase, LayoutPoint())) {
            LayoutObjectDrawingRecorder recorder(paintContext.paintInfo().context, m_layoutSVGShape, paintContext.paintInfo().phase, boundingBox, LayoutPoint());
            const SVGComputedStyle& svgStyle = m_layoutSVGShape.style()->svgStyle();

            bool shouldAntiAlias = svgStyle.shapeRendering() != SR_CRISPEDGES;

            for (int i = 0; i < 3; i++) {
                switch (svgStyle.paintOrderType(i)) {
                case PT_FILL: {
                    SkPaint fillPaint;
                    if (!SVGPaintContext::paintForLayoutObject(paintContext.paintInfo(), m_layoutSVGShape.styleRef(), m_layoutSVGShape, ApplyToFillMode, fillPaint))
                        break;
                    fillPaint.setAntiAlias(shouldAntiAlias);
                    fillShape(paintContext.paintInfo().context, fillPaint, fillRuleFromStyle(paintContext.paintInfo(), svgStyle));
                    break;
                }
                case PT_STROKE:
                    if (svgStyle.hasVisibleStroke()) {
                        GraphicsContextStateSaver stateSaver(paintContext.paintInfo().context, false);
                        AffineTransform nonScalingTransform;
                        const AffineTransform* additionalPaintServerTransform = 0;

                        if (m_layoutSVGShape.hasNonScalingStroke()) {
                            nonScalingTransform = m_layoutSVGShape.nonScalingStrokeTransform();
                            if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
                                return;

                            // Non-scaling stroke needs to reset the transform back to the host transform.
                            additionalPaintServerTransform = &nonScalingTransform;
                        }

                        SkPaint strokePaint;
                        if (!SVGPaintContext::paintForLayoutObject(paintContext.paintInfo(), m_layoutSVGShape.styleRef(), m_layoutSVGShape, ApplyToStrokeMode, strokePaint, additionalPaintServerTransform))
                            break;
                        strokePaint.setAntiAlias(shouldAntiAlias);

                        StrokeData strokeData;
                        SVGLayoutSupport::applyStrokeStyleToStrokeData(strokeData, m_layoutSVGShape.styleRef(), m_layoutSVGShape, m_layoutSVGShape.dashScaleFactor());
                        strokeData.setupPaint(&strokePaint);

                        strokeShape(paintContext.paintInfo().context, strokePaint);
                    }
                    break;
                case PT_MARKERS:
                    paintMarkers(paintContext.paintInfo(), boundingBox);
                    break;
                default:
                    ASSERT_NOT_REACHED();
                    break;
                }
            }
        }
    }

    if (m_layoutSVGShape.style()->outlineWidth()) {
        PaintInfo outlinePaintInfo(paintInfoBeforeFiltering);
        outlinePaintInfo.phase = PaintPhaseSelfOutlineOnly;
        ObjectPainter(m_layoutSVGShape).paintOutline(outlinePaintInfo, LayoutPoint(boundingBox.location()));
    }
}
예제 #30
0
void BlockPainter::paintChildAsPseudoStackingContext(const LayoutBox& child, const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    LayoutPoint childPoint = m_layoutBlock.flipForWritingModeForChild(&child, paintOffset);
    if (!child.hasSelfPaintingLayer() && !child.isFloating())
        ObjectPainter(child).paintAsPseudoStackingContext(paintInfo, childPoint);
}