Index: cc/resources/content_layer_updater.cc |
diff --git a/cc/resources/content_layer_updater.cc b/cc/resources/content_layer_updater.cc |
index 8bd90e9d5a174768abab9709b7a3928540a2eac7..f6469ff052ea3063d5127bb8eb407a3a3060c3b0 100644 |
--- a/cc/resources/content_layer_updater.cc |
+++ b/cc/resources/content_layer_updater.cc |
@@ -14,6 +14,7 @@ |
#include "third_party/skia/include/core/SkScalar.h" |
#include "ui/gfx/rect_conversions.h" |
#include "ui/gfx/rect_f.h" |
+#include "ui/gfx/skia_util.h" |
namespace cc { |
@@ -25,7 +26,9 @@ ContentLayerUpdater::ContentLayerUpdater( |
layer_id_(layer_id), |
layer_is_opaque_(false), |
layer_fills_bounds_completely_(false), |
- painter_(painter.Pass()) {} |
+ painter_(painter.Pass()), |
+ background_color_(SK_ColorTRANSPARENT) { |
+} |
ContentLayerUpdater::~ContentLayerUpdater() {} |
@@ -35,27 +38,62 @@ void ContentLayerUpdater::set_rendering_stats_instrumentation( |
} |
void ContentLayerUpdater::PaintContents(SkCanvas* canvas, |
- const gfx::Rect& content_rect, |
+ const gfx::Size& layer_content_size, |
+ const gfx::Rect& paint_rect, |
float contents_width_scale, |
float contents_height_scale) { |
TRACE_EVENT0("cc", "ContentLayerUpdater::PaintContents"); |
if (!canvas) |
return; |
canvas->save(); |
- canvas->translate(SkFloatToScalar(-content_rect.x()), |
- SkFloatToScalar(-content_rect.y())); |
- |
- // The |canvas| backing should be sized to hold the |content_rect|. |
- DCHECK_EQ(content_rect.width(), canvas->getBaseLayerSize().width()); |
- DCHECK_EQ(content_rect.height(), canvas->getBaseLayerSize().height()); |
+ canvas->translate(SkIntToScalar(-paint_rect.x()), |
+ SkIntToScalar(-paint_rect.y())); |
+ |
+ // The |canvas| backing should be sized to hold the |paint_rect|. |
+ DCHECK_EQ(paint_rect.width(), canvas->getBaseLayerSize().width()); |
+ DCHECK_EQ(paint_rect.height(), canvas->getBaseLayerSize().height()); |
+ |
+ const bool is_scaled = |
+ contents_width_scale != 1.f || contents_height_scale != 1.f; |
+ |
+ if (is_scaled && (layer_is_opaque_ || layer_fills_bounds_completely_)) { |
+ // Even if completely covered, for rasterizations that touch the edge of the |
+ // layer, we also need to raster the background color underneath the last |
+ // texel (since the paint won't cover it). |
+ // |
+ // The final texel of content may only be partially covered by a |
+ // rasterization; this rect represents the content rect that is fully |
+ // covered by content. |
+ const gfx::Rect layer_content_rect = gfx::Rect(layer_content_size); |
+ gfx::Rect deflated_layer_content_rect = layer_content_rect; |
+ deflated_layer_content_rect.Inset(0, 0, 1, 1); |
+ |
+ if (!layer_content_rect.Contains(deflated_layer_content_rect)) { |
+ // Drawing at most 1 x 1 x (canvas width + canvas height) texels is 2-3X |
+ // faster than clearing, so special case this. |
+ DCHECK_LE(paint_rect.right(), layer_content_rect.right()); |
+ DCHECK_LE(paint_rect.bottom(), layer_content_rect.bottom()); |
+ canvas->save(); |
+ canvas->clipRect(gfx::RectToSkRect(layer_content_rect), |
+ SkRegion::kReplace_Op); |
+ canvas->clipRect(gfx::RectToSkRect(deflated_layer_content_rect), |
+ SkRegion::kDifference_Op); |
+ canvas->drawColor(background_color_, SkXfermode::kSrc_Mode); |
+ canvas->restore(); |
+ } |
+ } |
- gfx::Rect layer_rect = content_rect; |
- if (contents_width_scale != 1.f || contents_height_scale != 1.f) { |
+ gfx::Rect layer_rect; |
+ if (is_scaled) { |
canvas->scale(SkFloatToScalar(contents_width_scale), |
SkFloatToScalar(contents_height_scale)); |
+ // NOTE: this may go beyond the bounds of the layer, but that shouldn't |
+ // cause problems (anything beyond the layer is clipped out). |
layer_rect = gfx::ScaleToEnclosingRect( |
- content_rect, 1.f / contents_width_scale, 1.f / contents_height_scale); |
+ paint_rect, 1.f / contents_width_scale, 1.f / contents_height_scale); |
+ } else { |
+ layer_rect = paint_rect; |
} |
SkRect layer_sk_rect = SkRect::MakeXYWH( |
@@ -73,7 +111,7 @@ void ContentLayerUpdater::PaintContents(SkCanvas* canvas, |
painter_->Paint(canvas, layer_rect); |
canvas->restore(); |
- content_rect_ = content_rect; |
+ paint_rect_ = paint_rect; |
} |
void ContentLayerUpdater::SetOpaque(bool opaque) { |
@@ -84,4 +122,8 @@ void ContentLayerUpdater::SetFillsBoundsCompletely(bool fills_bounds) { |
layer_fills_bounds_completely_ = fills_bounds; |
} |
+void ContentLayerUpdater::SetBackgroundColor(SkColor background_color) { |
+ background_color_ = background_color; |
+} |
+ |
} // namespace cc |