1// Copyright (c) 2012 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 "testing/gtest/include/gtest/gtest.h" 6#include "third_party/skia/include/core/SkBitmap.h" 7#include "ui/views/test/views_test_base.h" 8#include "ui/gfx/image/image.h" 9#include "ui/gfx/image/image_skia.h" 10#include "ui/views/corewm/image_grid.h" 11 12namespace views { 13namespace corewm { 14 15namespace { 16 17// Creates a gfx::Image with the requested dimensions. 18gfx::Image* CreateImage(const gfx::Size& size) { 19 SkBitmap bitmap; 20 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); 21 return new gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bitmap)); 22} 23 24} // namespace 25 26typedef ViewsTestBase ImageGridTest; 27 28// Test that an ImageGrid's layers are transformed correctly when SetSize() is 29// called. 30TEST_F(ImageGridTest, Basic) { 31 // Size of the images around the grid's border. 32 const int kBorder = 2; 33 34 scoped_ptr<gfx::Image> image_1x1(CreateImage(gfx::Size(1, 1))); 35 scoped_ptr<gfx::Image> image_1xB(CreateImage(gfx::Size(1, kBorder))); 36 scoped_ptr<gfx::Image> image_Bx1(CreateImage(gfx::Size(kBorder, 1))); 37 scoped_ptr<gfx::Image> image_BxB(CreateImage(gfx::Size(kBorder, kBorder))); 38 39 ImageGrid grid; 40 grid.SetImages(image_BxB.get(), image_1xB.get(), image_BxB.get(), 41 image_Bx1.get(), image_1x1.get(), image_Bx1.get(), 42 image_BxB.get(), image_1xB.get(), image_BxB.get()); 43 44 ImageGrid::TestAPI test_api(&grid); 45 ASSERT_TRUE(grid.top_left_layer() != NULL); 46 ASSERT_TRUE(grid.top_layer() != NULL); 47 ASSERT_TRUE(grid.top_right_layer() != NULL); 48 ASSERT_TRUE(grid.left_layer() != NULL); 49 ASSERT_TRUE(grid.center_layer() != NULL); 50 ASSERT_TRUE(grid.right_layer() != NULL); 51 ASSERT_TRUE(grid.bottom_left_layer() != NULL); 52 ASSERT_TRUE(grid.bottom_layer() != NULL); 53 ASSERT_TRUE(grid.bottom_right_layer() != NULL); 54 55 const gfx::Size size(20, 30); 56 grid.SetSize(size); 57 58 // The top-left layer should be flush with the top-left corner and unscaled. 59 EXPECT_EQ(gfx::RectF(0, 0, kBorder, kBorder).ToString(), 60 test_api.GetTransformedLayerBounds( 61 *grid.top_left_layer()).ToString()); 62 63 // The top layer should be flush with the top edge and stretched horizontally 64 // between the two top corners. 65 EXPECT_EQ(gfx::RectF( 66 kBorder, 0, size.width() - 2 * kBorder, kBorder).ToString(), 67 test_api.GetTransformedLayerBounds( 68 *grid.top_layer()).ToString()); 69 70 // The top-right layer should be flush with the top-right corner and unscaled. 71 EXPECT_EQ(gfx::RectF(size.width() - kBorder, 0, kBorder, kBorder).ToString(), 72 test_api.GetTransformedLayerBounds( 73 *grid.top_right_layer()).ToString()); 74 75 // The left layer should be flush with the left edge and stretched vertically 76 // between the two left corners. 77 EXPECT_EQ(gfx::RectF( 78 0, kBorder, kBorder, size.height() - 2 * kBorder).ToString(), 79 test_api.GetTransformedLayerBounds( 80 *grid.left_layer()).ToString()); 81 82 // The center layer should fill the space in the middle of the grid. 83 EXPECT_EQ(gfx::RectF( 84 kBorder, kBorder, size.width() - 2 * kBorder, 85 size.height() - 2 * kBorder).ToString(), 86 test_api.GetTransformedLayerBounds( 87 *grid.center_layer()).ToString()); 88 89 // The right layer should be flush with the right edge and stretched 90 // vertically between the two right corners. 91 EXPECT_EQ(gfx::RectF( 92 size.width() - kBorder, kBorder, 93 kBorder, size.height() - 2 * kBorder).ToString(), 94 test_api.GetTransformedLayerBounds( 95 *grid.right_layer()).ToString()); 96 97 // The bottom-left layer should be flush with the bottom-left corner and 98 // unscaled. 99 EXPECT_EQ(gfx::RectF(0, size.height() - kBorder, kBorder, kBorder).ToString(), 100 test_api.GetTransformedLayerBounds( 101 *grid.bottom_left_layer()).ToString()); 102 103 // The bottom layer should be flush with the bottom edge and stretched 104 // horizontally between the two bottom corners. 105 EXPECT_EQ(gfx::RectF( 106 kBorder, size.height() - kBorder, 107 size.width() - 2 * kBorder, kBorder).ToString(), 108 test_api.GetTransformedLayerBounds( 109 *grid.bottom_layer()).ToString()); 110 111 // The bottom-right layer should be flush with the bottom-right corner and 112 // unscaled. 113 EXPECT_EQ(gfx::RectF( 114 size.width() - kBorder, size.height() - kBorder, 115 kBorder, kBorder).ToString(), 116 test_api.GetTransformedLayerBounds( 117 *grid.bottom_right_layer()).ToString()); 118} 119 120// Test that an ImageGrid's layers are transformed correctly when 121// SetContentBounds() is called. 122TEST_F(ImageGridTest, SetContentBounds) { 123 // Size of the images around the grid's border. 124 const int kBorder = 2; 125 126 scoped_ptr<gfx::Image> image_1x1(CreateImage(gfx::Size(1, 1))); 127 scoped_ptr<gfx::Image> image_1xB(CreateImage(gfx::Size(1, kBorder))); 128 scoped_ptr<gfx::Image> image_Bx1(CreateImage(gfx::Size(kBorder, 1))); 129 scoped_ptr<gfx::Image> image_BxB(CreateImage(gfx::Size(kBorder, kBorder))); 130 131 ImageGrid grid; 132 grid.SetImages(image_BxB.get(), image_1xB.get(), image_BxB.get(), 133 image_Bx1.get(), image_1x1.get(), image_Bx1.get(), 134 image_BxB.get(), image_1xB.get(), image_BxB.get()); 135 136 ImageGrid::TestAPI test_api(&grid); 137 138 const gfx::Point origin(5, 10); 139 const gfx::Size size(20, 30); 140 grid.SetContentBounds(gfx::Rect(origin, size)); 141 142 // The master layer is positioned above the top-left corner of the content 143 // bounds and has height/width that contain the grid and bounds. 144 EXPECT_EQ(gfx::RectF(origin.x() - kBorder, 145 origin.y() - kBorder, 146 size.width() + 2 * kBorder, 147 size.height() + 2 * kBorder).ToString(), 148 test_api.GetTransformedLayerBounds(*grid.layer()).ToString()); 149} 150 151// Check that we don't crash if only a single image is supplied. 152TEST_F(ImageGridTest, SingleImage) { 153 const int kBorder = 1; 154 scoped_ptr<gfx::Image> image(CreateImage(gfx::Size(kBorder, kBorder))); 155 156 ImageGrid grid; 157 grid.SetImages(NULL, image.get(), NULL, 158 NULL, NULL, NULL, 159 NULL, NULL, NULL); 160 161 ImageGrid::TestAPI test_api(&grid); 162 EXPECT_TRUE(grid.top_left_layer() == NULL); 163 ASSERT_TRUE(grid.top_layer() != NULL); 164 EXPECT_TRUE(grid.top_right_layer() == NULL); 165 EXPECT_TRUE(grid.left_layer() == NULL); 166 EXPECT_TRUE(grid.center_layer() == NULL); 167 EXPECT_TRUE(grid.right_layer() == NULL); 168 EXPECT_TRUE(grid.bottom_left_layer() == NULL); 169 EXPECT_TRUE(grid.bottom_layer() == NULL); 170 EXPECT_TRUE(grid.bottom_right_layer() == NULL); 171 172 const gfx::Size kSize(10, 10); 173 grid.SetSize(kSize); 174 175 // The top layer should be scaled horizontally across the entire width, but it 176 // shouldn't be scaled vertically. 177 EXPECT_EQ(gfx::RectF(0, 0, kSize.width(), kBorder).ToString(), 178 test_api.GetTransformedLayerBounds( 179 *grid.top_layer()).ToString()); 180} 181 182// Check that we don't crash when we reset existing images to NULL and 183// reset NULL images to new ones. 184TEST_F(ImageGridTest, ResetImages) { 185 const int kBorder = 1; 186 scoped_ptr<gfx::Image> image(CreateImage(gfx::Size(kBorder, kBorder))); 187 188 ImageGrid grid; 189 grid.SetImages(NULL, image.get(), NULL, 190 NULL, NULL, NULL, 191 NULL, NULL, NULL); 192 193 // Only the top edge has a layer. 194 ImageGrid::TestAPI test_api(&grid); 195 ASSERT_TRUE(grid.top_left_layer() == NULL); 196 ASSERT_FALSE(grid.top_layer() == NULL); 197 ASSERT_TRUE(grid.top_right_layer() == NULL); 198 ASSERT_TRUE(grid.left_layer() == NULL); 199 ASSERT_TRUE(grid.center_layer() == NULL); 200 ASSERT_TRUE(grid.right_layer() == NULL); 201 ASSERT_TRUE(grid.bottom_left_layer() == NULL); 202 ASSERT_TRUE(grid.bottom_layer() == NULL); 203 ASSERT_TRUE(grid.bottom_right_layer() == NULL); 204 205 grid.SetImages(NULL, NULL, NULL, 206 NULL, NULL, NULL, 207 NULL, image.get(), NULL); 208 209 // Now only the bottom edge has a layer. 210 ASSERT_TRUE(grid.top_left_layer() == NULL); 211 ASSERT_TRUE(grid.top_layer() == NULL); 212 ASSERT_TRUE(grid.top_right_layer() == NULL); 213 ASSERT_TRUE(grid.left_layer() == NULL); 214 ASSERT_TRUE(grid.center_layer() == NULL); 215 ASSERT_TRUE(grid.right_layer() == NULL); 216 ASSERT_TRUE(grid.bottom_left_layer() == NULL); 217 ASSERT_FALSE(grid.bottom_layer() == NULL); 218 ASSERT_TRUE(grid.bottom_right_layer() == NULL); 219} 220 221// Test that side (top, left, right, bottom) layers that are narrower than their 222// adjacent corner layers stay pinned to the outside edges instead of getting 223// moved inwards or scaled. This exercises the scenario used for shadows. 224TEST_F(ImageGridTest, SmallerSides) { 225 const int kCorner = 2; 226 const int kEdge = 1; 227 228 scoped_ptr<gfx::Image> top_left_image( 229 CreateImage(gfx::Size(kCorner, kCorner))); 230 scoped_ptr<gfx::Image> top_image(CreateImage(gfx::Size(kEdge, kEdge))); 231 scoped_ptr<gfx::Image> top_right_image( 232 CreateImage(gfx::Size(kCorner, kCorner))); 233 scoped_ptr<gfx::Image> left_image(CreateImage(gfx::Size(kEdge, kEdge))); 234 scoped_ptr<gfx::Image> right_image(CreateImage(gfx::Size(kEdge, kEdge))); 235 236 ImageGrid grid; 237 grid.SetImages(top_left_image.get(), top_image.get(), top_right_image.get(), 238 left_image.get(), NULL, right_image.get(), 239 NULL, NULL, NULL); 240 ImageGrid::TestAPI test_api(&grid); 241 242 const gfx::Size kSize(20, 30); 243 grid.SetSize(kSize); 244 245 // The top layer should be flush with the top edge and stretched horizontally 246 // between the two top corners. 247 EXPECT_EQ(gfx::RectF( 248 kCorner, 0, kSize.width() - 2 * kCorner, kEdge).ToString(), 249 test_api.GetTransformedLayerBounds( 250 *grid.top_layer()).ToString()); 251 252 // The left layer should be flush with the left edge and stretched vertically 253 // between the top left corner and the bottom. 254 EXPECT_EQ(gfx::RectF( 255 0, kCorner, kEdge, kSize.height() - kCorner).ToString(), 256 test_api.GetTransformedLayerBounds( 257 *grid.left_layer()).ToString()); 258 259 // The right layer should be flush with the right edge and stretched 260 // vertically between the top right corner and the bottom. 261 EXPECT_EQ(gfx::RectF( 262 kSize.width() - kEdge, kCorner, 263 kEdge, kSize.height() - kCorner).ToString(), 264 test_api.GetTransformedLayerBounds( 265 *grid.right_layer()).ToString()); 266} 267 268// Test that we hide or clip layers as needed when the grid is assigned a small 269// size. 270TEST_F(ImageGridTest, TooSmall) { 271 const int kCorner = 5; 272 const int kCenter = 3; 273 const int kEdge = 3; 274 275 scoped_ptr<gfx::Image> top_left_image( 276 CreateImage(gfx::Size(kCorner, kCorner))); 277 scoped_ptr<gfx::Image> top_image(CreateImage(gfx::Size(kEdge, kEdge))); 278 scoped_ptr<gfx::Image> top_right_image( 279 CreateImage(gfx::Size(kCorner, kCorner))); 280 scoped_ptr<gfx::Image> left_image(CreateImage(gfx::Size(kEdge, kEdge))); 281 scoped_ptr<gfx::Image> center_image(CreateImage(gfx::Size(kCenter, kCenter))); 282 scoped_ptr<gfx::Image> right_image(CreateImage(gfx::Size(kEdge, kEdge))); 283 scoped_ptr<gfx::Image> bottom_left_image( 284 CreateImage(gfx::Size(kCorner, kCorner))); 285 scoped_ptr<gfx::Image> bottom_image(CreateImage(gfx::Size(kEdge, kEdge))); 286 scoped_ptr<gfx::Image> bottom_right_image( 287 CreateImage(gfx::Size(kCorner, kCorner))); 288 289 ImageGrid grid; 290 grid.SetImages( 291 top_left_image.get(), top_image.get(), top_right_image.get(), 292 left_image.get(), center_image.get(), right_image.get(), 293 bottom_left_image.get(), bottom_image.get(), bottom_right_image.get()); 294 ImageGrid::TestAPI test_api(&grid); 295 296 // Set a size that's smaller than the combined (unscaled) corner images. 297 const gfx::Size kSmallSize(kCorner + kCorner - 3, kCorner + kCorner - 5); 298 grid.SetSize(kSmallSize); 299 300 // The scalable images around the sides and in the center should be hidden. 301 EXPECT_FALSE(grid.top_layer()->visible()); 302 EXPECT_FALSE(grid.bottom_layer()->visible()); 303 EXPECT_FALSE(grid.left_layer()->visible()); 304 EXPECT_FALSE(grid.right_layer()->visible()); 305 EXPECT_FALSE(grid.center_layer()->visible()); 306 307 // The corner images' clip rects should sum to the expected size. 308 EXPECT_EQ(kSmallSize.width(), 309 test_api.top_left_clip_rect().width() + 310 test_api.top_right_clip_rect().width()); 311 EXPECT_EQ(kSmallSize.width(), 312 test_api.bottom_left_clip_rect().width() + 313 test_api.bottom_right_clip_rect().width()); 314 EXPECT_EQ(kSmallSize.height(), 315 test_api.top_left_clip_rect().height() + 316 test_api.bottom_left_clip_rect().height()); 317 EXPECT_EQ(kSmallSize.height(), 318 test_api.top_right_clip_rect().height() + 319 test_api.bottom_right_clip_rect().height()); 320 321 // Resize the grid to be large enough to show all images. 322 const gfx::Size kLargeSize(kCorner + kCorner + kCenter, 323 kCorner + kCorner + kCenter); 324 grid.SetSize(kLargeSize); 325 326 // The scalable images should be visible now. 327 EXPECT_TRUE(grid.top_layer()->visible()); 328 EXPECT_TRUE(grid.bottom_layer()->visible()); 329 EXPECT_TRUE(grid.left_layer()->visible()); 330 EXPECT_TRUE(grid.right_layer()->visible()); 331 EXPECT_TRUE(grid.center_layer()->visible()); 332 333 // We shouldn't be clipping the corner images anymore. 334 EXPECT_TRUE(test_api.top_left_clip_rect().IsEmpty()); 335 EXPECT_TRUE(test_api.top_right_clip_rect().IsEmpty()); 336 EXPECT_TRUE(test_api.bottom_left_clip_rect().IsEmpty()); 337 EXPECT_TRUE(test_api.bottom_right_clip_rect().IsEmpty()); 338} 339 340} // namespace corewm 341} // namespace views 342