blob: 58427321f36e17fddaebbeab04154fcdab376cc2 [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 "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
#include "third_party/blink/renderer/core/paint/box_painter_base.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
namespace blink {
void InlineBoxPainterBase::PaintBoxDecorationBackground(
BoxPainterBase& box_painter,
const PaintInfo& paint_info,
const LayoutPoint& paint_offset,
LayoutRect adjusted_frame_rect,
BackgroundImageGeometry geometry,
bool object_has_multiple_boxes,
bool include_logical_left_edge,
bool include_logical_right_edge) {
// Shadow comes first and is behind the background and border.
PaintNormalBoxShadow(paint_info, line_style_, adjusted_frame_rect);
Color background_color =
line_style_.VisitedDependentColor(GetCSSPropertyBackgroundColor());
PaintFillLayers(box_painter, paint_info, background_color,
line_style_.BackgroundLayers(), adjusted_frame_rect, geometry,
object_has_multiple_boxes);
PaintInsetBoxShadow(paint_info, line_style_, adjusted_frame_rect);
IntRect adjusted_clip_rect;
BorderPaintingType border_painting_type = GetBorderPaintType(
adjusted_frame_rect, adjusted_clip_rect, object_has_multiple_boxes);
switch (border_painting_type) {
case kDontPaintBorders:
break;
case kPaintBordersWithoutClip:
BoxPainterBase::PaintBorder(
image_observer_, *document_, node_, paint_info, adjusted_frame_rect,
line_style_, kBackgroundBleedNone, include_logical_left_edge,
include_logical_right_edge);
break;
case kPaintBordersWithClip:
// FIXME: What the heck do we do with RTL here? The math we're using is
// obviously not right, but it isn't even clear how this should work at
// all.
LayoutRect image_strip_paint_rect =
PaintRectForImageStrip(adjusted_frame_rect, TextDirection::kLtr);
GraphicsContextStateSaver state_saver(paint_info.context);
paint_info.context.Clip(adjusted_clip_rect);
BoxPainterBase::PaintBorder(image_observer_, *document_, node_,
paint_info, image_strip_paint_rect,
line_style_);
break;
}
}
void InlineBoxPainterBase::PaintFillLayers(BoxPainterBase& box_painter,
const PaintInfo& info,
const Color& c,
const FillLayer& layer,
const LayoutRect& rect,
BackgroundImageGeometry& geometry,
bool object_has_multiple_boxes,
SkBlendMode op) {
// FIXME: This should be a for loop or similar. It's a little non-trivial to
// do so, however, since the layers need to be painted in reverse order.
if (layer.Next()) {
PaintFillLayers(box_painter, info, c, *layer.Next(), rect, geometry,
object_has_multiple_boxes, op);
}
PaintFillLayer(box_painter, info, c, layer, rect, geometry,
object_has_multiple_boxes, op);
}
void InlineBoxPainterBase::PaintFillLayer(BoxPainterBase& box_painter,
const PaintInfo& paint_info,
const Color& c,
const FillLayer& fill_layer,
const LayoutRect& paint_rect,
BackgroundImageGeometry& geometry,
bool object_has_multiple_boxes,
SkBlendMode op) {
StyleImage* img = fill_layer.GetImage();
bool has_fill_image = img && img->CanRender();
if (!object_has_multiple_boxes ||
(!has_fill_image && !style_.HasBorderRadius())) {
box_painter.PaintFillLayer(paint_info, c, fill_layer, paint_rect,
kBackgroundBleedNone, geometry, op, false);
return;
}
// Handle fill images that clone or spans multiple lines.
bool multi_line = object_has_multiple_boxes &&
style_.BoxDecorationBreak() != EBoxDecorationBreak::kClone;
LayoutRect rect = multi_line
? PaintRectForImageStrip(paint_rect, style_.Direction())
: paint_rect;
GraphicsContextStateSaver state_saver(paint_info.context);
paint_info.context.Clip(PixelSnappedIntRect(paint_rect));
box_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
kBackgroundBleedNone, geometry, op, multi_line,
paint_rect.Size());
}
} // namespace blink