Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/nine_image_painter.h" | 5 #include "ui/gfx/nine_image_painter.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | |
| 7 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 8 #include "ui/gfx/canvas.h" | 9 #include "ui/gfx/canvas.h" |
| 10 #include "ui/gfx/codec/png_codec.h" | |
| 9 #include "ui/gfx/geometry/insets.h" | 11 #include "ui/gfx/geometry/insets.h" |
| 10 #include "ui/gfx/geometry/rect.h" | 12 #include "ui/gfx/geometry/rect.h" |
| 11 #include "ui/gfx/image/image_skia.h" | 13 #include "ui/gfx/image/image_skia.h" |
| 12 | 14 |
| 13 namespace gfx { | 15 namespace gfx { |
| 14 | 16 |
| 17 static std::string GetPNGDataUrl(const SkBitmap& bitmap) { | |
| 18 std::vector<unsigned char> png_data; | |
| 19 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &png_data); | |
| 20 std::string data_url; | |
| 21 data_url.insert(data_url.end(), png_data.begin(), png_data.end()); | |
| 22 base::Base64Encode(data_url, &data_url); | |
| 23 data_url.insert(0, "data:image/png;base64,"); | |
| 24 | |
| 25 return data_url; | |
| 26 } | |
| 27 | |
| 15 TEST(NineImagePainterTest, GetSubsetRegions) { | 28 TEST(NineImagePainterTest, GetSubsetRegions) { |
| 16 SkBitmap src; | 29 SkBitmap src; |
| 17 src.allocN32Pixels(40, 50); | 30 src.allocN32Pixels(40, 50); |
| 18 const ImageSkia image_skia(ImageSkiaRep(src, 1.0)); | 31 const ImageSkia image_skia(ImageSkiaRep(src, 1.0)); |
| 19 const Insets insets(1, 2, 3, 4); | 32 const Insets insets(1, 2, 3, 4); |
| 20 std::vector<Rect> rects; | 33 std::vector<Rect> rects; |
| 21 NineImagePainter::GetSubsetRegions(image_skia, insets, &rects); | 34 NineImagePainter::GetSubsetRegions(image_skia, insets, &rects); |
| 22 ASSERT_EQ(9u, rects.size()); | 35 ASSERT_EQ(9u, rects.size()); |
| 23 EXPECT_EQ(gfx::Rect(0, 0, 2, 1), rects[0]); | 36 EXPECT_EQ(gfx::Rect(0, 0, 2, 1), rects[0]); |
| 24 EXPECT_EQ(gfx::Rect(2, 0, 34, 1), rects[1]); | 37 EXPECT_EQ(gfx::Rect(2, 0, 34, 1), rects[1]); |
| 25 EXPECT_EQ(gfx::Rect(36, 0, 4, 1), rects[2]); | 38 EXPECT_EQ(gfx::Rect(36, 0, 4, 1), rects[2]); |
| 26 EXPECT_EQ(gfx::Rect(0, 1, 2, 46), rects[3]); | 39 EXPECT_EQ(gfx::Rect(0, 1, 2, 46), rects[3]); |
| 27 EXPECT_EQ(gfx::Rect(2, 1, 34, 46), rects[4]); | 40 EXPECT_EQ(gfx::Rect(2, 1, 34, 46), rects[4]); |
| 28 EXPECT_EQ(gfx::Rect(36, 1, 4, 46), rects[5]); | 41 EXPECT_EQ(gfx::Rect(36, 1, 4, 46), rects[5]); |
| 29 EXPECT_EQ(gfx::Rect(0, 47, 2, 3), rects[6]); | 42 EXPECT_EQ(gfx::Rect(0, 47, 2, 3), rects[6]); |
| 30 EXPECT_EQ(gfx::Rect(2, 47, 34, 3), rects[7]); | 43 EXPECT_EQ(gfx::Rect(2, 47, 34, 3), rects[7]); |
| 31 EXPECT_EQ(gfx::Rect(36, 47, 4, 3), rects[8]); | 44 EXPECT_EQ(gfx::Rect(36, 47, 4, 3), rects[8]); |
| 32 } | 45 } |
| 33 | 46 |
| 34 TEST(NineImagePainterTest, PaintScale) { | 47 TEST(NineImagePainterTest, PaintHighDPI) { |
| 35 SkBitmap src; | 48 SkBitmap src; |
| 36 src.allocN32Pixels(100, 100); | 49 src.allocN32Pixels(100, 100); |
| 37 src.eraseColor(SK_ColorRED); | 50 src.eraseColor(SK_ColorRED); |
| 38 src.eraseArea(SkIRect::MakeXYWH(10, 10, 80, 80), SK_ColorGREEN); | 51 src.eraseArea(SkIRect::MakeXYWH(10, 10, 80, 80), SK_ColorGREEN); |
| 39 | 52 |
| 40 gfx::ImageSkia image(gfx::ImageSkiaRep(src, 0.0f)); | 53 float image_scale = 2.f; |
| 54 | |
| 55 gfx::ImageSkia image(gfx::ImageSkiaRep(src, image_scale)); | |
| 41 gfx::Insets insets(10, 10, 10, 10); | 56 gfx::Insets insets(10, 10, 10, 10); |
| 42 gfx::NineImagePainter painter(image, insets); | 57 gfx::NineImagePainter painter(image, insets); |
| 43 | 58 |
| 44 int image_scale = 2; | |
| 45 bool is_opaque = true; | 59 bool is_opaque = true; |
| 46 gfx::Canvas canvas(gfx::Size(400, 400), image_scale, is_opaque); | 60 gfx::Canvas canvas(gfx::Size(100, 100), image_scale, is_opaque); |
| 47 canvas.Scale(2, 1); | 61 canvas.Translate(gfx::Vector2d(20, 10)); |
| 48 | 62 |
| 49 gfx::Rect bounds(0, 0, 100, 100); | 63 gfx::Rect bounds(0, 0, 50, 50); |
| 50 painter.Paint(&canvas, bounds); | 64 painter.Paint(&canvas, bounds); |
| 51 | 65 |
| 52 SkBitmap result; | 66 SkBitmap result; |
| 53 const SkISize size = canvas.sk_canvas()->getDeviceSize(); | 67 const SkISize size = canvas.sk_canvas()->getDeviceSize(); |
| 54 result.allocN32Pixels(size.width(), size.height()); | 68 result.allocN32Pixels(size.width(), size.height()); |
| 55 canvas.sk_canvas()->readPixels(&result, 0, 0); | 69 canvas.sk_canvas()->readPixels(&result, 0, 0); |
| 56 | 70 |
| 57 SkIRect green_rect = SkIRect::MakeLTRB(40, 20, 360, 180); | 71 gfx::Vector2d paint_offset(40, 20); // Translated 20,10 with 2x dpi. |
|
Peter Kasting
2015/10/29 21:26:15
Why not store the original translation vector from
danakj
2015/10/29 22:15:12
Sure, done. Except the negative one is weird, I th
| |
| 58 for (int y = 0; y < 200; y++) { | 72 gfx::Rect green_rect = gfx::Rect(10, 10, 80, 80) + paint_offset; |
| 59 for (int x = 0; x < 400; x++) { | 73 for (int y = paint_offset.y(); y < 100 + paint_offset.y(); y++) { |
|
Peter Kasting
2015/10/29 21:26:15
You repeat this loop several times; factor out int
danakj
2015/10/29 22:15:12
Done.
| |
| 60 if (green_rect.contains(x, y)) { | 74 SCOPED_TRACE(y); |
| 61 ASSERT_EQ(SK_ColorGREEN, result.getColor(x, y)); | 75 for (int x = paint_offset.x(); x < 100 + paint_offset.x(); x++) { |
| 76 SCOPED_TRACE(x); | |
| 77 if (green_rect.Contains(x, y)) { | |
| 78 ASSERT_EQ(SK_ColorGREEN, result.getColor(x, y)) | |
| 79 << "Output image:\n" << GetPNGDataUrl(result); | |
| 62 } else { | 80 } else { |
| 63 ASSERT_EQ(SK_ColorRED, result.getColor(x, y)); | 81 ASSERT_EQ(SK_ColorRED, result.getColor(x, y)) << "Output image:\n" |
| 82 << GetPNGDataUrl(result); | |
| 64 } | 83 } |
| 65 } | 84 } |
| 66 } | 85 } |
| 67 } | 86 } |
| 68 | 87 |
| 69 TEST(NineImagePainterTest, PaintStaysInBounds) { | 88 TEST(NineImagePainterTest, PaintStaysInBounds) { |
| 70 // In this test the bounds rect is 1x1 but each image is 2x2. | 89 // In this test the bounds rect is 1x1 but each image is 2x2. |
| 71 // The NineImagePainter should not paint outside the bounds. | 90 // The NineImagePainter should not paint outside the bounds. |
| 72 | 91 |
| 73 SkBitmap src; | 92 SkBitmap src; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 for (int x = 1; x < 10; x++) { | 148 for (int x = 1; x < 10; x++) { |
| 130 if (green_rect.contains(x, y)) { | 149 if (green_rect.contains(x, y)) { |
| 131 ASSERT_EQ(SK_ColorGREEN, result.getColor(x, y)); | 150 ASSERT_EQ(SK_ColorGREEN, result.getColor(x, y)); |
| 132 } else { | 151 } else { |
| 133 ASSERT_EQ(SK_ColorRED, result.getColor(x, y)); | 152 ASSERT_EQ(SK_ColorRED, result.getColor(x, y)); |
| 134 } | 153 } |
| 135 } | 154 } |
| 136 } | 155 } |
| 137 } | 156 } |
| 138 | 157 |
| 139 TEST(NineImagePainterTest, PaintWithNagativeScale) { | 158 TEST(NineImagePainterTest, PaintWithScale) { |
| 140 SkBitmap src; | 159 SkBitmap src; |
| 141 src.allocN32Pixels(100, 100); | 160 src.allocN32Pixels(100, 100); |
| 142 src.eraseColor(SK_ColorRED); | 161 src.eraseColor(SK_ColorRED); |
| 143 src.eraseArea(SkIRect::MakeXYWH(10, 10, 80, 80), SK_ColorGREEN); | 162 src.eraseArea(SkIRect::MakeXYWH(10, 10, 80, 80), SK_ColorGREEN); |
| 144 | 163 |
| 145 gfx::ImageSkia image(gfx::ImageSkiaRep(src, 0.0f)); | 164 float image_scale = 2.f; |
| 165 | |
| 166 gfx::ImageSkia image(gfx::ImageSkiaRep(src, image_scale)); | |
| 146 gfx::Insets insets(10, 10, 10, 10); | 167 gfx::Insets insets(10, 10, 10, 10); |
| 147 gfx::NineImagePainter painter(image, insets); | 168 gfx::NineImagePainter painter(image, insets); |
| 148 | 169 |
| 149 int image_scale = 2; | |
| 150 bool is_opaque = true; | 170 bool is_opaque = true; |
| 151 gfx::Canvas canvas(gfx::Size(400, 400), image_scale, is_opaque); | 171 gfx::Canvas canvas(gfx::Size(400, 400), image_scale, is_opaque); |
| 152 canvas.Translate(gfx::Vector2d(200, 200)); | 172 canvas.Translate(gfx::Vector2d(20, 10)); |
| 153 canvas.Scale(-2, -1); | 173 canvas.Scale(2, 1); |
| 154 | 174 |
| 155 gfx::Rect bounds(0, 0, 100, 100); | 175 gfx::Rect bounds(0, 0, 50, 50); |
| 156 painter.Paint(&canvas, bounds); | 176 painter.Paint(&canvas, bounds); |
| 157 | 177 |
| 158 SkBitmap result; | 178 SkBitmap result; |
| 159 const SkISize size = canvas.sk_canvas()->getDeviceSize(); | 179 const SkISize size = canvas.sk_canvas()->getDeviceSize(); |
| 160 result.allocN32Pixels(size.width(), size.height()); | 180 result.allocN32Pixels(size.width(), size.height()); |
| 161 canvas.sk_canvas()->readPixels(&result, 0, 0); | 181 canvas.sk_canvas()->readPixels(&result, 0, 0); |
| 162 | 182 |
| 163 SkIRect green_rect = SkIRect::MakeLTRB(40, 220, 360, 380); | 183 gfx::Vector2d paint_offset(40, 20); // Translated 20,10 with 2x dpi. |
| 164 for (int y = 200; y < 400; y++) { | 184 gfx::Rect green_rect = gfx::Rect(20, 10, 160, 80) + paint_offset; |
| 165 for (int x = 0; x < 400; x++) { | 185 for (int y = paint_offset.y(); y < 100 + paint_offset.y(); y++) { |
| 166 if (green_rect.contains(x, y)) { | 186 SCOPED_TRACE(y); |
| 167 ASSERT_EQ(SK_ColorGREEN, result.getColor(x, y)); | 187 for (int x = paint_offset.x(); x < 200 + paint_offset.x(); x++) { |
| 188 SCOPED_TRACE(x); | |
| 189 if (green_rect.Contains(x, y)) { | |
| 190 ASSERT_EQ(SK_ColorGREEN, result.getColor(x, y)) | |
| 191 << "Output image:\n" << GetPNGDataUrl(result); | |
| 168 } else { | 192 } else { |
| 169 ASSERT_EQ(SK_ColorRED, result.getColor(x, y)); | 193 ASSERT_EQ(SK_ColorRED, result.getColor(x, y)) << "Output image:\n" |
| 194 << GetPNGDataUrl(result); | |
| 170 } | 195 } |
| 171 } | 196 } |
| 172 } | 197 } |
| 198 } | |
| 199 | |
| 200 TEST(NineImagePainterTest, PaintWithNegativeScale) { | |
| 201 SkBitmap src; | |
| 202 src.allocN32Pixels(100, 100); | |
| 203 src.eraseColor(SK_ColorRED); | |
| 204 src.eraseArea(SkIRect::MakeXYWH(10, 10, 80, 80), SK_ColorGREEN); | |
| 205 | |
| 206 float image_scale = 2.f; | |
| 207 | |
| 208 gfx::ImageSkia image(gfx::ImageSkiaRep(src, image_scale)); | |
| 209 gfx::Insets insets(10, 10, 10, 10); | |
| 210 gfx::NineImagePainter painter(image, insets); | |
| 211 | |
| 212 bool is_opaque = true; | |
| 213 gfx::Canvas canvas(gfx::Size(400, 400), image_scale, is_opaque); | |
| 214 canvas.Translate(gfx::Vector2d(70, 60)); | |
| 215 canvas.Scale(-1, -1); | |
| 216 | |
| 217 gfx::Rect bounds(0, 0, 50, 50); | |
| 218 painter.Paint(&canvas, bounds); | |
| 219 | |
| 220 SkBitmap result; | |
| 221 const SkISize size = canvas.sk_canvas()->getDeviceSize(); | |
| 222 result.allocN32Pixels(size.width(), size.height()); | |
| 223 canvas.sk_canvas()->readPixels(&result, 0, 0); | |
| 224 | |
| 225 // The painting space is 50x50 and the scale of -1m-1 means an offset of 50,50 | |
| 226 // would put the output in the top left corner. Since the offset is 70,60 it | |
| 227 // moves by 20,10. Since the output is 2x DPI it will become offset by 40,20. | |
| 228 gfx::Vector2d paint_offset(40, 20); | |
| 229 gfx::Rect green_rect = gfx::Rect(10, 10, 80, 80) + paint_offset; | |
| 230 for (int y = paint_offset.y(); y < 100 + paint_offset.y(); y++) { | |
| 231 SCOPED_TRACE(y); | |
| 232 for (int x = paint_offset.x(); x < 100 + paint_offset.x(); x++) { | |
| 233 SCOPED_TRACE(x); | |
| 234 if (green_rect.Contains(x, y)) { | |
| 235 ASSERT_EQ(SK_ColorGREEN, result.getColor(x, y)) | |
| 236 << "Output image:\n" << GetPNGDataUrl(result); | |
| 237 } else { | |
| 238 ASSERT_EQ(SK_ColorRED, result.getColor(x, y)) << "Output image:\n" | |
| 239 << GetPNGDataUrl(result); | |
| 240 } | |
| 241 } | |
| 242 } | |
| 173 } | 243 } |
| 174 | 244 |
| 175 } // namespace gfx | 245 } // namespace gfx |
| OLD | NEW |