diff options
author | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-01 13:18:30 +0000 |
---|---|---|
committer | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-01 13:18:30 +0000 |
commit | 8765dcb4accfde35362c34eb32614a17f16b700d (patch) | |
tree | aed584b3e0e46a71840f988e3d7f97b7a33b8a22 | |
parent | 74719923dedc68db453f366de6bb0acf66d8516b (diff) | |
download | chromium_src-8765dcb4accfde35362c34eb32614a17f16b700d.zip chromium_src-8765dcb4accfde35362c34eb32614a17f16b700d.tar.gz chromium_src-8765dcb4accfde35362c34eb32614a17f16b700d.tar.bz2 |
cc: Fix PicturePile clearing for non-origin canvases
When canvases are larger than content, and content is stretched and
terminates on a non-integer pixel boundary, then the area underneath
that content must be cleared first. The clearing code attempted to
clear a 2 pixel wide strip, but was not translating it, so it only
worked for canvases located at the origin.
R=brianderson@chromium.org
BUG=296672
Review URL: https://codereview.chromium.org/51433003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@232349 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/resources/picture_pile_impl.cc | 5 | ||||
-rw-r--r-- | cc/resources/picture_pile_impl_unittest.cc | 79 |
2 files changed, 55 insertions, 29 deletions
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc index 3d0f5ec..3411b7f 100644 --- a/cc/resources/picture_pile_impl.cc +++ b/cc/resources/picture_pile_impl.cc @@ -112,18 +112,17 @@ void PicturePileImpl::RasterToBitmap( gfx::SizeF total_content_size = gfx::ScaleSize(tiling_.total_size(), contents_scale); gfx::Rect content_rect(gfx::ToCeiledSize(total_content_size)); - gfx::Rect deflated_content_rect = content_rect; - content_rect.Intersect(canvas_rect); // 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. + gfx::Rect deflated_content_rect = content_rect; deflated_content_rect.Inset(0, 0, 1, 1); - deflated_content_rect.Intersect(canvas_rect); if (!deflated_content_rect.Contains(canvas_rect)) { // Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X // faster than clearing, so special case this. canvas->save(); + canvas->translate(-canvas_rect.x(), -canvas_rect.y()); gfx::Rect inflated_content_rect = content_rect; inflated_content_rect.Inset(0, 0, -1, -1); canvas->clipRect(gfx::RectToSkRect(inflated_content_rect), diff --git a/cc/resources/picture_pile_impl_unittest.cc b/cc/resources/picture_pile_impl_unittest.cc index c68b185..16a875e 100644 --- a/cc/resources/picture_pile_impl_unittest.cc +++ b/cc/resources/picture_pile_impl_unittest.cc @@ -635,49 +635,76 @@ TEST(PicturePileImplTest, PixelRefIteratorLazyRefsBaseNonLazy) { } } +// Note: this test will always pass in debug because the canvas is cleared +// to the NonPaintedFillColor first. TEST(PicturePileImpl, RasterContentsOpaque) { gfx::Size tile_size(1000, 1000); gfx::Size layer_bounds(3, 5); float contents_scale = 1.5f; + float raster_divisions = 2.f; scoped_refptr<FakePicturePileImpl> pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); // Because the caller sets content opaque, it also promises that it // has at least filled in layer_bounds opaquely. - SkPaint red_paint; - red_paint.setColor(SK_ColorRED); - pile->add_draw_rect_with_paint(gfx::Rect(layer_bounds), red_paint); + SkPaint white_paint; + white_paint.setColor(SK_ColorWHITE); + pile->add_draw_rect_with_paint(gfx::Rect(layer_bounds), white_paint); pile->SetMinContentsScale(contents_scale); - pile->set_background_color(SK_ColorRED); + pile->set_background_color(SK_ColorBLACK); pile->set_contents_opaque(true); pile->RerecordPile(); gfx::Size content_bounds( gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale))); - // Simulate a canvas rect larger than the content bounds. Every pixel - // up to one pixel outside the content bounds is guaranteed to be opaque. - // Outside of that is undefined. - gfx::Rect canvas_rect(content_bounds); - canvas_rect.Inset(0, 0, -1, -1); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, - canvas_rect.width(), - canvas_rect.height()); - bitmap.allocPixels(); - SkCanvas canvas(bitmap); - - FakeRenderingStatsInstrumentation rendering_stats_instrumentation; - - pile->RasterToBitmap( - &canvas, canvas_rect, contents_scale, &rendering_stats_instrumentation); - - SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); - int num_pixels = bitmap.width() * bitmap.height(); - for (int i = 0; i < num_pixels; ++i) { - EXPECT_EQ(SkColorGetA(pixels[i]), 255u); + // Simulate drawing into different tiles at different offsets. + int step_x = std::ceil(content_bounds.width() / raster_divisions); + int step_y = std::ceil(content_bounds.height() / raster_divisions); + for (int offset_x = 0; offset_x < content_bounds.width(); + offset_x += step_x) { + for (int offset_y = 0; offset_y < content_bounds.height(); + offset_y += step_y) { + gfx::Rect content_rect(offset_x, offset_y, step_x, step_y); + content_rect.Intersect(gfx::Rect(content_bounds)); + + // Simulate a canvas rect larger than the content rect. Every pixel + // up to one pixel outside the content rect is guaranteed to be opaque. + // Outside of that is undefined. + gfx::Rect canvas_rect(content_rect); + canvas_rect.Inset(0, 0, -1, -1); + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + canvas_rect.width(), + canvas_rect.height()); + bitmap.allocPixels(); + SkCanvas canvas(bitmap); + canvas.clear(SK_ColorTRANSPARENT); + + FakeRenderingStatsInstrumentation rendering_stats_instrumentation; + + pile->RasterToBitmap(&canvas, + canvas_rect, + contents_scale, + &rendering_stats_instrumentation); + + SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); + int num_pixels = bitmap.width() * bitmap.height(); + bool all_white = true; + for (int i = 0; i < num_pixels; ++i) { + EXPECT_EQ(SkColorGetA(pixels[i]), 255u); + all_white &= (SkColorGetR(pixels[i]) == 255); + all_white &= (SkColorGetG(pixels[i]) == 255); + all_white &= (SkColorGetB(pixels[i]) == 255); + } + + // If the canvas doesn't extend past the edge of the content, + // it should be entirely white. Otherwise, the edge of the content + // will be non-white. + EXPECT_EQ(all_white, gfx::Rect(content_bounds).Contains(canvas_rect)); + } } } |