blob: 6ca509a6462f747ec445d522a5f4b7dd84888597 [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 "core/paint/BoxDecorationData.h"
#include "core/layout/LayoutBox.h"
#include "core/paint/BoxPainter.h"
#include "core/style/BorderEdge.h"
#include "core/style/ComputedStyle.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/GraphicsContext.h"
namespace blink {
BoxDecorationData::BoxDecorationData(const LayoutBox& layoutBox) {
backgroundColor =
layoutBox.style()->visitedDependentColor(CSSPropertyBackgroundColor);
hasBackground =
backgroundColor.alpha() || layoutBox.style()->hasBackgroundImage();
ASSERT(hasBackground == layoutBox.style()->hasBackground());
hasBorderDecoration = layoutBox.style()->hasBorderDecoration();
hasAppearance = layoutBox.style()->hasAppearance();
bleedAvoidance = determineBackgroundBleedAvoidance(layoutBox);
}
namespace {
bool borderObscuresBackgroundEdge(const ComputedStyle& style) {
BorderEdge edges[4];
style.getBorderEdgeInfo(edges);
for (auto& edge : edges) {
if (!edge.obscuresBackgroundEdge())
return false;
}
return true;
}
} // anonymous namespace
BackgroundBleedAvoidance BoxDecorationData::determineBackgroundBleedAvoidance(
const LayoutBox& layoutBox) {
if (layoutBox.isDocumentElement())
return BackgroundBleedNone;
if (!hasBackground)
return BackgroundBleedNone;
const ComputedStyle& boxStyle = layoutBox.styleRef();
const bool hasBorderRadius = boxStyle.hasBorderRadius();
if (!hasBorderDecoration || !hasBorderRadius ||
layoutBox.canRenderBorderImage()) {
if (layoutBox.backgroundShouldAlwaysBeClipped())
return BackgroundBleedClipOnly;
// Border radius clipping may require layer bleed avoidance if we are going
// to draw an image over something else, because we do not want the
// antialiasing to lead to bleeding
if (boxStyle.hasBackgroundImage() && hasBorderRadius) {
// But if the top layer is opaque for the purposes of background painting,
// we do not need the bleed avoidance because we will not paint anything
// behind the top layer. But only if we need to draw something
// underneath.
const FillLayer& fillLayer = layoutBox.style()->backgroundLayers();
if ((backgroundColor.alpha() || fillLayer.next()) &&
!fillLayer.imageOccludesNextLayers(layoutBox))
return BackgroundBleedClipLayer;
}
return BackgroundBleedNone;
}
if (borderObscuresBackgroundEdge(boxStyle))
return BackgroundBleedShrinkBackground;
return BackgroundBleedClipLayer;
}
} // namespace blink