1 // Copyright 2011 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.
5 #include "cc/resources/content_layer_updater.h"
7 #include "base/trace_event/trace_event.h"
8 #include "cc/resources/layer_painter.h"
9 #include "third_party/skia/include/core/SkCanvas.h"
10 #include "third_party/skia/include/core/SkRect.h"
11 #include "third_party/skia/include/core/SkScalar.h"
12 #include "ui/gfx/geometry/rect_conversions.h"
13 #include "ui/gfx/geometry/rect_f.h"
14 #include "ui/gfx/skia_util.h"
18 ContentLayerUpdater::ContentLayerUpdater(scoped_ptr
<LayerPainter
> painter
,
20 : layer_id_(layer_id
),
21 layer_is_opaque_(false),
22 layer_fills_bounds_completely_(false),
23 painter_(painter
.Pass()),
24 background_color_(SK_ColorTRANSPARENT
) {
27 ContentLayerUpdater::~ContentLayerUpdater() {}
29 void ContentLayerUpdater::PaintContents(SkCanvas
* canvas
,
30 const gfx::Size
& layer_content_size
,
31 const gfx::Rect
& paint_rect
,
32 float contents_width_scale
,
33 float contents_height_scale
) {
34 TRACE_EVENT0("cc", "ContentLayerUpdater::PaintContents");
38 canvas
->translate(SkIntToScalar(-paint_rect
.x()),
39 SkIntToScalar(-paint_rect
.y()));
41 // The |canvas| backing should be sized to hold the |paint_rect|.
42 DCHECK_EQ(paint_rect
.width(), canvas
->getBaseLayerSize().width());
43 DCHECK_EQ(paint_rect
.height(), canvas
->getBaseLayerSize().height());
45 const bool is_scaled
=
46 contents_width_scale
!= 1.f
|| contents_height_scale
!= 1.f
;
48 if (is_scaled
&& (layer_is_opaque_
|| layer_fills_bounds_completely_
)) {
49 // Even if completely covered, for rasterizations that touch the edge of the
50 // layer, we also need to raster the background color underneath the last
51 // texel (since the paint won't cover it).
53 // The final texel of content may only be partially covered by a
54 // rasterization; this rect represents the content rect that is fully
55 // covered by content.
56 const gfx::Rect layer_content_rect
= gfx::Rect(layer_content_size
);
57 gfx::Rect deflated_layer_content_rect
= layer_content_rect
;
58 deflated_layer_content_rect
.Inset(0, 0, 1, 1);
60 if (!layer_content_rect
.Contains(deflated_layer_content_rect
)) {
61 // Drawing at most 1 x 1 x (canvas width + canvas height) texels is 2-3X
62 // faster than clearing, so special case this.
63 DCHECK_LE(paint_rect
.right(), layer_content_rect
.right());
64 DCHECK_LE(paint_rect
.bottom(), layer_content_rect
.bottom());
66 canvas
->clipRect(gfx::RectToSkRect(layer_content_rect
),
67 SkRegion::kReplace_Op
);
68 canvas
->clipRect(gfx::RectToSkRect(deflated_layer_content_rect
),
69 SkRegion::kDifference_Op
);
70 canvas
->drawColor(background_color_
, SkXfermode::kSrc_Mode
);
77 canvas
->scale(SkFloatToScalar(contents_width_scale
),
78 SkFloatToScalar(contents_height_scale
));
80 // NOTE: this may go beyond the bounds of the layer, but that shouldn't
81 // cause problems (anything beyond the layer is clipped out).
82 layer_rect
= gfx::ScaleToEnclosingRect(
83 paint_rect
, 1.f
/ contents_width_scale
, 1.f
/ contents_height_scale
);
85 layer_rect
= paint_rect
;
88 SkRect layer_sk_rect
= SkRect::MakeXYWH(
89 layer_rect
.x(), layer_rect
.y(), layer_rect
.width(), layer_rect
.height());
91 canvas
->clipRect(layer_sk_rect
);
93 // If the layer has opaque contents or will fill the bounds completely there
94 // is no need to clear the canvas before painting.
95 if (!layer_is_opaque_
&& !layer_fills_bounds_completely_
) {
96 TRACE_EVENT0("cc", "Clear");
97 canvas
->drawColor(SK_ColorTRANSPARENT
, SkXfermode::kSrc_Mode
);
100 painter_
->Paint(canvas
, layer_rect
);
103 paint_rect_
= paint_rect
;
106 void ContentLayerUpdater::SetOpaque(bool opaque
) {
107 layer_is_opaque_
= opaque
;
110 void ContentLayerUpdater::SetFillsBoundsCompletely(bool fills_bounds
) {
111 layer_fills_bounds_completely_
= fills_bounds
;
114 void ContentLayerUpdater::SetBackgroundColor(SkColor background_color
) {
115 background_color_
= background_color
;