[email protected] | 98af9aca | 2010-03-14 19:06:30 | [diff] [blame] | 1 | // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 5 | #include "base/file_util.h" |
| 6 | #include "base/path_service.h" |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 7 | #include "base/scoped_ptr.h" |
[email protected] | 98af9aca | 2010-03-14 19:06:30 | [diff] [blame] | 8 | #include "gfx/gfx_paths.h" |
[email protected] | 1125d80 | 2010-03-13 08:26:32 | [diff] [blame] | 9 | #include "gfx/icon_util.h" |
[email protected] | e0fc2f1 | 2010-03-14 23:30:59 | [diff] [blame] | 10 | #include "gfx/size.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 11 | #include "testing/gtest/include/gtest/gtest.h" |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 12 | #include "third_party/skia/include/core/SkBitmap.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 13 | |
| 14 | namespace { |
| 15 | |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 16 | static const char kSmallIconName[] = "icon_util/16_X_16_icon.ico"; |
| 17 | static const char kLargeIconName[] = "icon_util/128_X_128_icon.ico"; |
| 18 | static const char kTempIconFilename[] = "temp_test_icon.ico"; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 19 | |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 20 | class IconUtilTest : public testing::Test { |
| 21 | public: |
| 22 | IconUtilTest() { |
| 23 | PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_); |
| 24 | } |
| 25 | ~IconUtilTest() {} |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 26 | |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 27 | static const int kSmallIconWidth = 16; |
| 28 | static const int kSmallIconHeight = 16; |
| 29 | static const int kLargeIconWidth = 128; |
| 30 | static const int kLargeIconHeight = 128; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 31 | |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 32 | // Given a file name for an .ico file and an image dimentions, this |
| 33 | // function loads the icon and returns an HICON handle. |
| 34 | HICON LoadIconFromFile(const FilePath& filename, int width, int height) { |
| 35 | HICON icon = static_cast<HICON>(LoadImage(NULL, |
| 36 | filename.value().c_str(), |
| 37 | IMAGE_ICON, |
| 38 | width, |
| 39 | height, |
| 40 | LR_LOADTRANSPARENT | LR_LOADFROMFILE)); |
| 41 | return icon; |
| 42 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 43 | |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 44 | protected: |
| 45 | // The root directory for test files. |
| 46 | FilePath test_data_directory_; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 47 | |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 48 | private: |
| 49 | DISALLOW_COPY_AND_ASSIGN(IconUtilTest); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 50 | }; |
| 51 | |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 52 | } // namespace |
| 53 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 54 | // The following test case makes sure IconUtil::SkBitmapFromHICON fails |
| 55 | // gracefully when called with invalid input parameters. |
| 56 | TEST_F(IconUtilTest, TestIconToBitmapInvalidParameters) { |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 57 | FilePath icon_filename = test_data_directory_.AppendASCII(kSmallIconName); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 58 | gfx::Size icon_size(kSmallIconWidth, kSmallIconHeight); |
| 59 | HICON icon = LoadIconFromFile(icon_filename, |
| 60 | icon_size.width(), |
| 61 | icon_size.height()); |
| 62 | ASSERT_TRUE(icon != NULL); |
| 63 | |
| 64 | // Invalid size parameter. |
| 65 | gfx::Size invalid_icon_size(kSmallIconHeight, 0); |
| 66 | EXPECT_EQ(IconUtil::CreateSkBitmapFromHICON(icon, invalid_icon_size), |
| 67 | static_cast<SkBitmap*>(NULL)); |
| 68 | |
| 69 | // Invalid icon. |
| 70 | EXPECT_EQ(IconUtil::CreateSkBitmapFromHICON(NULL, icon_size), |
| 71 | static_cast<SkBitmap*>(NULL)); |
| 72 | |
| 73 | // The following code should succeed. |
| 74 | scoped_ptr<SkBitmap> bitmap; |
| 75 | bitmap.reset(IconUtil::CreateSkBitmapFromHICON(icon, icon_size)); |
| 76 | EXPECT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 77 | ::DestroyIcon(icon); |
| 78 | } |
| 79 | |
| 80 | // The following test case makes sure IconUtil::CreateHICONFromSkBitmap fails |
| 81 | // gracefully when called with invalid input parameters. |
| 82 | TEST_F(IconUtilTest, TestBitmapToIconInvalidParameters) { |
| 83 | HICON icon = NULL; |
| 84 | scoped_ptr<SkBitmap> bitmap; |
| 85 | |
| 86 | // Wrong bitmap format. |
| 87 | bitmap.reset(new SkBitmap); |
| 88 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 89 | bitmap->setConfig(SkBitmap::kA8_Config, kSmallIconWidth, kSmallIconHeight); |
| 90 | icon = IconUtil::CreateHICONFromSkBitmap(*bitmap); |
| 91 | EXPECT_EQ(icon, static_cast<HICON>(NULL)); |
| 92 | |
| 93 | // Invalid bitmap size. |
| 94 | bitmap.reset(new SkBitmap); |
| 95 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 96 | bitmap->setConfig(SkBitmap::kARGB_8888_Config, 0, 0); |
| 97 | icon = IconUtil::CreateHICONFromSkBitmap(*bitmap); |
| 98 | EXPECT_EQ(icon, static_cast<HICON>(NULL)); |
| 99 | |
| 100 | // Valid bitmap configuration but no pixels allocated. |
| 101 | bitmap.reset(new SkBitmap); |
| 102 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 103 | bitmap->setConfig(SkBitmap::kARGB_8888_Config, |
| 104 | kSmallIconWidth, |
| 105 | kSmallIconHeight); |
| 106 | icon = IconUtil::CreateHICONFromSkBitmap(*bitmap); |
| 107 | EXPECT_TRUE(icon == NULL); |
| 108 | } |
| 109 | |
| 110 | // The following test case makes sure IconUtil::CreateIconFileFromSkBitmap |
| 111 | // fails gracefully when called with invalid input parameters. |
| 112 | TEST_F(IconUtilTest, TestCreateIconFileInvalidParameters) { |
| 113 | scoped_ptr<SkBitmap> bitmap; |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 114 | FilePath valid_icon_filename = test_data_directory_.AppendASCII( |
| 115 | kSmallIconName); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 116 | std::wstring invalid_icon_filename(L"C:\\<>?.ico"); |
| 117 | |
| 118 | // Wrong bitmap format. |
| 119 | bitmap.reset(new SkBitmap); |
| 120 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 121 | bitmap->setConfig(SkBitmap::kA8_Config, kSmallIconWidth, kSmallIconHeight); |
| 122 | EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap, |
| 123 | valid_icon_filename)); |
| 124 | |
| 125 | // Invalid bitmap size. |
| 126 | bitmap.reset(new SkBitmap); |
| 127 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 128 | bitmap->setConfig(SkBitmap::kARGB_8888_Config, 0, 0); |
| 129 | EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap, |
| 130 | valid_icon_filename)); |
| 131 | |
| 132 | // Bitmap with no allocated pixels. |
| 133 | bitmap.reset(new SkBitmap); |
| 134 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 135 | bitmap->setConfig(SkBitmap::kARGB_8888_Config, |
| 136 | kSmallIconWidth, |
| 137 | kSmallIconHeight); |
| 138 | EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap, |
| 139 | valid_icon_filename)); |
| 140 | |
| 141 | // Invalid file name. |
| 142 | bitmap->allocPixels(); |
[email protected] | 0006be64 | 2008-08-27 16:43:19 | [diff] [blame] | 143 | // Setting the pixels to black. |
| 144 | memset(bitmap->getPixels(), 0, bitmap->width() * bitmap->height() * 4); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 145 | EXPECT_FALSE(IconUtil::CreateIconFileFromSkBitmap(*bitmap, |
| 146 | invalid_icon_filename)); |
| 147 | } |
| 148 | |
| 149 | // This test case makes sure that when we load an icon from disk and convert |
| 150 | // the HICON into a bitmap, the bitmap has the expected format and dimentions. |
| 151 | TEST_F(IconUtilTest, TestCreateSkBitmapFromHICON) { |
| 152 | scoped_ptr<SkBitmap> bitmap; |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 153 | FilePath small_icon_filename = test_data_directory_.AppendASCII( |
| 154 | kSmallIconName); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 155 | gfx::Size small_icon_size(kSmallIconWidth, kSmallIconHeight); |
| 156 | HICON small_icon = LoadIconFromFile(small_icon_filename, |
| 157 | small_icon_size.width(), |
| 158 | small_icon_size.height()); |
| 159 | ASSERT_NE(small_icon, static_cast<HICON>(NULL)); |
| 160 | bitmap.reset(IconUtil::CreateSkBitmapFromHICON(small_icon, small_icon_size)); |
| 161 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 162 | EXPECT_EQ(bitmap->width(), small_icon_size.width()); |
| 163 | EXPECT_EQ(bitmap->height(), small_icon_size.height()); |
| 164 | EXPECT_EQ(bitmap->config(), SkBitmap::kARGB_8888_Config); |
| 165 | ::DestroyIcon(small_icon); |
| 166 | |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 167 | FilePath large_icon_filename = test_data_directory_.AppendASCII( |
| 168 | kLargeIconName); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 169 | gfx::Size large_icon_size(kLargeIconWidth, kLargeIconHeight); |
| 170 | HICON large_icon = LoadIconFromFile(large_icon_filename, |
| 171 | large_icon_size.width(), |
| 172 | large_icon_size.height()); |
| 173 | ASSERT_NE(large_icon, static_cast<HICON>(NULL)); |
| 174 | bitmap.reset(IconUtil::CreateSkBitmapFromHICON(large_icon, large_icon_size)); |
| 175 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 176 | EXPECT_EQ(bitmap->width(), large_icon_size.width()); |
| 177 | EXPECT_EQ(bitmap->height(), large_icon_size.height()); |
| 178 | EXPECT_EQ(bitmap->config(), SkBitmap::kARGB_8888_Config); |
| 179 | ::DestroyIcon(large_icon); |
| 180 | } |
| 181 | |
| 182 | // This test case makes sure that when an HICON is created from an SkBitmap, |
| 183 | // the returned handle is valid and refers to an icon with the expected |
| 184 | // dimentions color depth etc. |
| 185 | TEST_F(IconUtilTest, TestBasicCreateHICONFromSkBitmap) { |
| 186 | scoped_ptr<SkBitmap> bitmap; |
| 187 | bitmap.reset(new SkBitmap); |
| 188 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 189 | bitmap->setConfig(SkBitmap::kARGB_8888_Config, |
| 190 | kSmallIconWidth, |
| 191 | kSmallIconHeight); |
| 192 | bitmap->allocPixels(); |
| 193 | HICON icon = IconUtil::CreateHICONFromSkBitmap(*bitmap); |
| 194 | EXPECT_NE(icon, static_cast<HICON>(NULL)); |
| 195 | ICONINFO icon_info; |
| 196 | ASSERT_TRUE(::GetIconInfo(icon, &icon_info)); |
| 197 | EXPECT_TRUE(icon_info.fIcon); |
| 198 | |
| 199 | // Now that have the icon information, we should obtain the specification of |
| 200 | // the icon's bitmap and make sure it matches the specification of the |
| 201 | // SkBitmap we started with. |
| 202 | // |
| 203 | // The bitmap handle contained in the icon information is a handle to a |
| 204 | // compatible bitmap so we need to call ::GetDIBits() in order to retrieve |
| 205 | // the bitmap's header information. |
| 206 | BITMAPINFO bitmap_info; |
| 207 | ::ZeroMemory(&bitmap_info, sizeof(BITMAPINFO)); |
| 208 | bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFO); |
| 209 | HDC hdc = ::GetDC(NULL); |
| 210 | int result = ::GetDIBits(hdc, |
| 211 | icon_info.hbmColor, |
| 212 | 0, |
| 213 | kSmallIconWidth, |
| 214 | NULL, |
| 215 | &bitmap_info, |
| 216 | DIB_RGB_COLORS); |
| 217 | ASSERT_GT(result, 0); |
| 218 | EXPECT_EQ(bitmap_info.bmiHeader.biWidth, kSmallIconWidth); |
| 219 | EXPECT_EQ(bitmap_info.bmiHeader.biHeight, kSmallIconHeight); |
| 220 | EXPECT_EQ(bitmap_info.bmiHeader.biPlanes, 1); |
| 221 | EXPECT_EQ(bitmap_info.bmiHeader.biBitCount, 32); |
| 222 | ::ReleaseDC(NULL, hdc); |
| 223 | ::DestroyIcon(icon); |
| 224 | } |
| 225 | |
| 226 | // The following test case makes sure IconUtil::CreateIconFileFromSkBitmap |
| 227 | // creates a valid .ico file given an SkBitmap. |
| 228 | TEST_F(IconUtilTest, TestCreateIconFile) { |
| 229 | scoped_ptr<SkBitmap> bitmap; |
[email protected] | 3865810 | 2010-07-30 14:01:59 | [diff] [blame^] | 230 | FilePath icon_filename = test_data_directory_.AppendASCII(kTempIconFilename); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 231 | |
| 232 | // Allocating the bitmap. |
| 233 | bitmap.reset(new SkBitmap); |
| 234 | ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL)); |
| 235 | bitmap->setConfig(SkBitmap::kARGB_8888_Config, |
| 236 | kSmallIconWidth, |
| 237 | kSmallIconHeight); |
| 238 | bitmap->allocPixels(); |
| 239 | |
| 240 | // Setting the pixels to black. |
| 241 | memset(bitmap->getPixels(), 0, bitmap->width() * bitmap->height() * 4); |
| 242 | |
| 243 | EXPECT_TRUE(IconUtil::CreateIconFileFromSkBitmap(*bitmap, |
| 244 | icon_filename)); |
| 245 | |
| 246 | // We are currently only testing that it is possible to load an icon from |
| 247 | // the .ico file we just created. We don't really check the additional icon |
| 248 | // images created by IconUtil::CreateIconFileFromSkBitmap. |
| 249 | HICON icon = LoadIconFromFile(icon_filename, |
| 250 | kSmallIconWidth, |
| 251 | kSmallIconHeight); |
| 252 | EXPECT_NE(icon, static_cast<HICON>(NULL)); |
| 253 | if (icon != NULL) { |
| 254 | ::DestroyIcon(icon); |
| 255 | } |
| 256 | } |