1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
6
7 #include "third_party/blink/renderer/core/paint/background_image_geometry.h"
8 #include "third_party/blink/renderer/core/paint/box_painter_base.h"
9 #include "third_party/blink/renderer/core/paint/paint_info.h"
10 #include "third_party/blink/renderer/core/paint/paint_layer.h"
11 #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
12 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
13
14 namespace blink {
15
PaintBoxDecorationBackground(BoxPainterBase & box_painter,const PaintInfo & paint_info,const PhysicalOffset & paint_offset,const PhysicalRect & adjusted_frame_rect,BackgroundImageGeometry geometry,bool object_has_multiple_boxes,PhysicalBoxSides sides_to_include)16 void InlineBoxPainterBase::PaintBoxDecorationBackground(
17 BoxPainterBase& box_painter,
18 const PaintInfo& paint_info,
19 const PhysicalOffset& paint_offset,
20 const PhysicalRect& adjusted_frame_rect,
21 BackgroundImageGeometry geometry,
22 bool object_has_multiple_boxes,
23 PhysicalBoxSides sides_to_include) {
24 // Shadow comes first and is behind the background and border.
25 PaintNormalBoxShadow(paint_info, line_style_, adjusted_frame_rect);
26
27 Color background_color =
28 line_style_.VisitedDependentColor(GetCSSPropertyBackgroundColor());
29 PaintFillLayers(box_painter, paint_info, background_color,
30 line_style_.BackgroundLayers(), adjusted_frame_rect, geometry,
31 object_has_multiple_boxes);
32
33 PaintInsetBoxShadow(paint_info, line_style_, adjusted_frame_rect);
34
35 IntRect adjusted_clip_rect;
36 BorderPaintingType border_painting_type = GetBorderPaintType(
37 adjusted_frame_rect, adjusted_clip_rect, object_has_multiple_boxes);
38 switch (border_painting_type) {
39 case kDontPaintBorders:
40 break;
41 case kPaintBordersWithoutClip:
42 BoxPainterBase::PaintBorder(image_observer_, *document_, node_,
43 paint_info, adjusted_frame_rect, line_style_,
44 kBackgroundBleedNone, sides_to_include);
45 break;
46 case kPaintBordersWithClip:
47 // FIXME: What the heck do we do with RTL here? The math we're using is
48 // obviously not right, but it isn't even clear how this should work at
49 // all.
50 PhysicalRect image_strip_paint_rect =
51 PaintRectForImageStrip(adjusted_frame_rect, TextDirection::kLtr);
52 GraphicsContextStateSaver state_saver(paint_info.context);
53 paint_info.context.Clip(adjusted_clip_rect);
54 BoxPainterBase::PaintBorder(image_observer_, *document_, node_,
55 paint_info, image_strip_paint_rect,
56 line_style_);
57 break;
58 }
59 }
60
PaintFillLayers(BoxPainterBase & box_painter,const PaintInfo & info,const Color & c,const FillLayer & layer,const PhysicalRect & rect,BackgroundImageGeometry & geometry,bool object_has_multiple_boxes)61 void InlineBoxPainterBase::PaintFillLayers(BoxPainterBase& box_painter,
62 const PaintInfo& info,
63 const Color& c,
64 const FillLayer& layer,
65 const PhysicalRect& rect,
66 BackgroundImageGeometry& geometry,
67 bool object_has_multiple_boxes) {
68 // FIXME: This should be a for loop or similar. It's a little non-trivial to
69 // do so, however, since the layers need to be painted in reverse order.
70 if (layer.Next()) {
71 PaintFillLayers(box_painter, info, c, *layer.Next(), rect, geometry,
72 object_has_multiple_boxes);
73 }
74 PaintFillLayer(box_painter, info, c, layer, rect, geometry,
75 object_has_multiple_boxes);
76 }
77
PaintFillLayer(BoxPainterBase & box_painter,const PaintInfo & paint_info,const Color & c,const FillLayer & fill_layer,const PhysicalRect & paint_rect,BackgroundImageGeometry & geometry,bool object_has_multiple_boxes)78 void InlineBoxPainterBase::PaintFillLayer(BoxPainterBase& box_painter,
79 const PaintInfo& paint_info,
80 const Color& c,
81 const FillLayer& fill_layer,
82 const PhysicalRect& paint_rect,
83 BackgroundImageGeometry& geometry,
84 bool object_has_multiple_boxes) {
85 StyleImage* img = fill_layer.GetImage();
86 bool has_fill_image = img && img->CanRender();
87
88 if (!object_has_multiple_boxes ||
89 (!has_fill_image && !style_.HasBorderRadius())) {
90 box_painter.PaintFillLayer(paint_info, c, fill_layer, paint_rect,
91 kBackgroundBleedNone, geometry, false);
92 return;
93 }
94
95 // Handle fill images that clone or spans multiple lines.
96 bool multi_line = object_has_multiple_boxes &&
97 style_.BoxDecorationBreak() != EBoxDecorationBreak::kClone;
98 PhysicalRect rect =
99 multi_line ? PaintRectForImageStrip(paint_rect, style_.Direction())
100 : paint_rect;
101 GraphicsContextStateSaver state_saver(paint_info.context);
102 paint_info.context.Clip(PixelSnappedIntRect(paint_rect));
103 box_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
104 kBackgroundBleedNone, geometry, multi_line,
105 paint_rect.size);
106 }
107
108 } // namespace blink
109