blob: efd564e11fdc357e624087319de234e769e82d4e [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/paint/ReplacedPainter.h"
#include "core/layout/Layer.h"
#include "core/layout/LayoutReplaced.h"
#include "core/layout/PaintInfo.h"
#include "core/paint/BoxPainter.h"
#include "core/paint/GraphicsContextAnnotator.h"
#include "core/paint/ObjectPainter.h"
#include "core/paint/RenderDrawingRecorder.h"
#include "core/paint/RoundedInnerRectClipper.h"
namespace blink {
void ReplacedPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_layoutReplaced);
if (!m_layoutReplaced.shouldPaint(paintInfo, paintOffset))
return;
LayoutPoint adjustedPaintOffset = paintOffset + m_layoutReplaced.location();
LayoutRect paintRect(adjustedPaintOffset, m_layoutReplaced.size());
if (m_layoutReplaced.hasBoxDecorationBackground() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
m_layoutReplaced.paintBoxDecorationBackground(paintInfo, adjustedPaintOffset);
if (paintInfo.phase == PaintPhaseMask) {
RenderDrawingRecorder renderDrawingRecorder(paintInfo.context, m_layoutReplaced, paintInfo.phase, paintRect);
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) && m_layoutReplaced.style()->outlineWidth())
ObjectPainter(m_layoutReplaced).paintOutline(paintInfo, paintRect);
if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && !m_layoutReplaced.canHaveChildren() && paintInfo.phase != PaintPhaseClippingMask)
return;
if (!paintInfo.shouldPaintWithinRoot(&m_layoutReplaced))
return;
bool drawSelectionTint = m_layoutReplaced.selectionState() != LayoutObject::SelectionNone && !m_layoutReplaced.document().printing();
if (paintInfo.phase == PaintPhaseSelection) {
if (m_layoutReplaced.selectionState() == LayoutObject::SelectionNone)
return;
drawSelectionTint = false;
}
// FIXME(crbug.com/444591): Refactor this to not create a drawing recorder for renderers with children.
OwnPtr<RenderDrawingRecorder> renderDrawingRecorder;
if (!m_layoutReplaced.isSVGRoot())
renderDrawingRecorder = adoptPtr(new RenderDrawingRecorder(paintInfo.context, m_layoutReplaced, paintInfo.phase, paintRect));
if (renderDrawingRecorder && renderDrawingRecorder->canUseCachedDrawing())
return;
{
OwnPtr<RoundedInnerRectClipper> clipper;
bool completelyClippedOut = false;
if (m_layoutReplaced.style()->hasBorderRadius()) {
LayoutRect borderRect = LayoutRect(adjustedPaintOffset, m_layoutReplaced.size());
if (borderRect.isEmpty()) {
completelyClippedOut = true;
} else {
// 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(paintRect,
m_layoutReplaced.paddingTop() + m_layoutReplaced.borderTop(), m_layoutReplaced.paddingBottom() + m_layoutReplaced.borderBottom(), m_layoutReplaced.paddingLeft() + m_layoutReplaced.borderLeft(), m_layoutReplaced.paddingRight() + m_layoutReplaced.borderRight(), true, true);
clipper = adoptPtr(new RoundedInnerRectClipper(m_layoutReplaced, paintInfo, paintRect, roundedInnerRect, ApplyToContext));
}
}
if (!completelyClippedOut) {
if (paintInfo.phase == PaintPhaseClippingMask) {
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.
if (drawSelectionTint) {
LayoutRect selectionPaintingRect = m_layoutReplaced.localSelectionRect();
selectionPaintingRect.moveBy(adjustedPaintOffset);
paintInfo.context->fillRect(pixelSnappedIntRect(selectionPaintingRect), m_layoutReplaced.selectionBackgroundColor());
}
}
} // namespace blink