icon_util_unittest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// Use of this source code is governed by a BSD-style license that can be
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// found in the LICENSE file.
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/gfx/icon_util.h"
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "base/file_util.h"
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "base/files/scoped_temp_dir.h"
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "base/memory/scoped_ptr.h"
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "base/path_service.h"
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "testing/gtest/include/gtest/gtest.h"
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "third_party/skia/include/core/SkBitmap.h"
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/gfx/gfx_paths.h"
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/gfx/icon_util_unittests_resource.h"
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/gfx/image/image.h"
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/gfx/image/image_family.h"
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/gfx/size.h"
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvernamespace {
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverstatic const char kSmallIconName[] = "icon_util/16_X_16_icon.ico";
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverstatic const char kLargeIconName[] = "icon_util/128_X_128_icon.ico";
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverstatic const char kTempIconFilename[] = "temp_test_icon.ico";
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}  // namespace
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass IconUtilTest : public testing::Test {
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public:
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void SetUp() OVERRIDE {
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_);
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    temp_directory_.CreateUniqueTempDir();
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  static const int kSmallIconWidth = 16;
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  static const int kSmallIconHeight = 16;
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  static const int kLargeIconWidth = 128;
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  static const int kLargeIconHeight = 128;
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Given a file name for an .ico file and an image dimensions, this
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // function loads the icon and returns an HICON handle.
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  HICON LoadIconFromFile(const base::FilePath& filename,
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                         int width, int height) {
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    HICON icon = static_cast<HICON>(LoadImage(NULL,
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                    filename.value().c_str(),
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                    IMAGE_ICON,
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                    width,
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                    height,
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                    LR_LOADTRANSPARENT | LR_LOADFROMFILE));
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return icon;
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  SkBitmap CreateBlackSkBitmap(int width, int height) {
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    SkBitmap bitmap;
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    bitmap.allocN32Pixels(width, height);
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // Setting the pixels to transparent-black.
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    memset(bitmap.getPixels(), 0, width * height * 4);
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return bitmap;
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Loads an .ico file from |icon_filename| and asserts that it contains all of
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // the expected icon sizes up to and including |max_icon_size|, and no other
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // icons. If |max_icon_size| >= 256, this tests for a 256x256 PNG icon entry.
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  void CheckAllIconSizes(const base::FilePath& icon_filename,
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                         int max_icon_size);
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected:
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // The root directory for test files. This should be treated as read-only.
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  base::FilePath test_data_directory_;
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Directory for creating files by this test.
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  base::ScopedTempDir temp_directory_;
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver};
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvervoid IconUtilTest::CheckAllIconSizes(const base::FilePath& icon_filename,
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                     int max_icon_size) {
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  ASSERT_TRUE(base::PathExists(icon_filename));
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Determine how many icons to expect, based on |max_icon_size|.
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  int expected_num_icons = 0;
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  for (size_t i = 0; i < IconUtil::kNumIconDimensions; ++i) {
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (IconUtil::kIconDimensions[i] > max_icon_size)
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      break;
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ++expected_num_icons;
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // First, use the Windows API to load the icon, a basic validity test.
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  HICON icon = LoadIconFromFile(icon_filename, kSmallIconWidth,
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                kSmallIconHeight);
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  EXPECT_NE(static_cast<HICON>(NULL), icon);
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  if (icon != NULL)
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ::DestroyIcon(icon);
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Read the file completely into memory.
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  std::string icon_data;
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  ASSERT_TRUE(base::ReadFileToString(icon_filename, &icon_data));
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  ASSERT_GE(icon_data.length(), sizeof(IconUtil::ICONDIR));
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Ensure that it has exactly the expected number and sizes of icons, in the
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // expected order. This matches each entry of the loaded file's icon directory
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // with the corresponding element of kIconDimensions.
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Also extracts the 256x256 entry as png_entry.
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  const IconUtil::ICONDIR* icon_dir =
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      reinterpret_cast<const IconUtil::ICONDIR*>(icon_data.data());
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  EXPECT_EQ(expected_num_icons, icon_dir->idCount);
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  ASSERT_GE(IconUtil::kNumIconDimensions, icon_dir->idCount);
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  ASSERT_GE(icon_data.length(),
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            sizeof(IconUtil::ICONDIR) +
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                icon_dir->idCount * sizeof(IconUtil::ICONDIRENTRY));
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  const IconUtil::ICONDIRENTRY* png_entry = NULL;
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  for (size_t i = 0; i < icon_dir->idCount; ++i) {
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    const IconUtil::ICONDIRENTRY* entry = &icon_dir->idEntries[i];
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // Mod 256 because as a special case in ICONDIRENTRY, the value 0 represents
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // a width or height of 256.
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    int expected_size = IconUtil::kIconDimensions[i] % 256;
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    EXPECT_EQ(expected_size, static_cast<int>(entry->bWidth));
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    EXPECT_EQ(expected_size, static_cast<int>(entry->bHeight));
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (entry->bWidth == 0 && entry->bHeight == 0) {
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      EXPECT_EQ(NULL, png_entry);
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      png_entry = entry;
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  if (max_icon_size >= 256) {
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ASSERT_TRUE(png_entry);
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // Convert the PNG entry data back to a SkBitmap to ensure it's valid.
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ASSERT_GE(icon_data.length(),
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver              png_entry->dwImageOffset + png_entry->dwBytesInRes);
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    const unsigned char* png_bytes = reinterpret_cast<const unsigned char*>(
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        icon_data.data() + png_entry->dwImageOffset);
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        png_bytes, png_entry->dwBytesInRes);
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    SkBitmap bitmap = image.AsBitmap();
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    EXPECT_EQ(256, bitmap.width());
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    EXPECT_EQ(256, bitmap.height());
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// The following test case makes sure IconUtil::SkBitmapFromHICON fails
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// gracefully when called with invalid input parameters.
141324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverTEST_F(IconUtilTest, TestIconToBitmapInvalidParameters) {
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  base::FilePath icon_filename =
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      test_data_directory_.AppendASCII(kSmallIconName);
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  gfx::Size icon_size(kSmallIconWidth, kSmallIconHeight);
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  HICON icon = LoadIconFromFile(icon_filename,
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                icon_size.width(),
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                icon_size.height());
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  ASSERT_TRUE(icon != NULL);
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Invalid size parameter.
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  gfx::Size invalid_icon_size(kSmallIconHeight, 0);
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  EXPECT_EQ(IconUtil::CreateSkBitmapFromHICON(icon, invalid_icon_size),
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            static_cast<SkBitmap*>(NULL));
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Invalid icon.
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  EXPECT_EQ(IconUtil::CreateSkBitmapFromHICON(NULL, icon_size),
157            static_cast<SkBitmap*>(NULL));
158
159  // The following code should succeed.
160  scoped_ptr<SkBitmap> bitmap;
161  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(icon, icon_size));
162  EXPECT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
163  ::DestroyIcon(icon);
164}
165
166// The following test case makes sure IconUtil::CreateHICONFromSkBitmap fails
167// gracefully when called with invalid input parameters.
168TEST_F(IconUtilTest, TestBitmapToIconInvalidParameters) {
169  HICON icon = NULL;
170  scoped_ptr<SkBitmap> bitmap;
171
172  // Wrong bitmap format.
173  bitmap.reset(new SkBitmap);
174  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
175  bitmap->setInfo(SkImageInfo::MakeA8(kSmallIconWidth, kSmallIconHeight));
176  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
177  EXPECT_EQ(icon, static_cast<HICON>(NULL));
178
179  // Invalid bitmap size.
180  bitmap.reset(new SkBitmap);
181  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
182  bitmap->setInfo(SkImageInfo::MakeN32Premul(0, 0));
183  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
184  EXPECT_EQ(icon, static_cast<HICON>(NULL));
185
186  // Valid bitmap configuration but no pixels allocated.
187  bitmap.reset(new SkBitmap);
188  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
189  bitmap->setInfo(SkImageInfo::MakeN32Premul(kSmallIconWidth,
190                                             kSmallIconHeight));
191  icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
192  EXPECT_TRUE(icon == NULL);
193}
194
195// The following test case makes sure IconUtil::CreateIconFileFromImageFamily
196// fails gracefully when called with invalid input parameters.
197TEST_F(IconUtilTest, TestCreateIconFileInvalidParameters) {
198  scoped_ptr<SkBitmap> bitmap;
199  gfx::ImageFamily image_family;
200  base::FilePath valid_icon_filename = temp_directory_.path().AppendASCII(
201      kTempIconFilename);
202  base::FilePath invalid_icon_filename = temp_directory_.path().AppendASCII(
203      "<>?.ico");
204
205  // Wrong bitmap format.
206  bitmap.reset(new SkBitmap);
207  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
208  // Must allocate pixels or else ImageSkia will ignore the bitmap and just
209  // return an empty image.
210  bitmap->allocPixels(SkImageInfo::MakeA8(kSmallIconWidth, kSmallIconHeight));
211  memset(bitmap->getPixels(), 0, bitmap->width() * bitmap->height());
212  image_family.Add(gfx::Image::CreateFrom1xBitmap(*bitmap));
213  EXPECT_FALSE(IconUtil::CreateIconFileFromImageFamily(image_family,
214                                                       valid_icon_filename));
215  EXPECT_FALSE(base::PathExists(valid_icon_filename));
216
217  // Invalid bitmap size.
218  image_family.clear();
219  bitmap.reset(new SkBitmap);
220  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
221  bitmap->allocPixels(SkImageInfo::MakeN32Premul(0, 0));
222  image_family.Add(gfx::Image::CreateFrom1xBitmap(*bitmap));
223  EXPECT_FALSE(IconUtil::CreateIconFileFromImageFamily(image_family,
224                                                       valid_icon_filename));
225  EXPECT_FALSE(base::PathExists(valid_icon_filename));
226
227  // Bitmap with no allocated pixels.
228  image_family.clear();
229  bitmap.reset(new SkBitmap);
230  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
231  bitmap->setInfo(SkImageInfo::MakeN32Premul(kSmallIconWidth,
232                                             kSmallIconHeight));
233  image_family.Add(gfx::Image::CreateFrom1xBitmap(*bitmap));
234  EXPECT_FALSE(IconUtil::CreateIconFileFromImageFamily(image_family,
235                                                       valid_icon_filename));
236  EXPECT_FALSE(base::PathExists(valid_icon_filename));
237
238  // Invalid file name.
239  image_family.clear();
240  bitmap->allocPixels();
241  // Setting the pixels to black.
242  memset(bitmap->getPixels(), 0, bitmap->width() * bitmap->height() * 4);
243  image_family.Add(gfx::Image::CreateFrom1xBitmap(*bitmap));
244  EXPECT_FALSE(IconUtil::CreateIconFileFromImageFamily(image_family,
245                                                       invalid_icon_filename));
246  EXPECT_FALSE(base::PathExists(invalid_icon_filename));
247}
248
249// This test case makes sure IconUtil::CreateIconFileFromImageFamily fails if
250// the image family is empty or invalid.
251TEST_F(IconUtilTest, TestCreateIconFileEmptyImageFamily) {
252  base::FilePath icon_filename = temp_directory_.path().AppendASCII(
253      kTempIconFilename);
254
255  // Empty image family.
256  EXPECT_FALSE(IconUtil::CreateIconFileFromImageFamily(gfx::ImageFamily(),
257                                                       icon_filename));
258  EXPECT_FALSE(base::PathExists(icon_filename));
259
260  // Image family with only an empty image.
261  gfx::ImageFamily image_family;
262  image_family.Add(gfx::Image());
263  EXPECT_FALSE(IconUtil::CreateIconFileFromImageFamily(image_family,
264                                                       icon_filename));
265  EXPECT_FALSE(base::PathExists(icon_filename));
266}
267
268// This test case makes sure that when we load an icon from disk and convert
269// the HICON into a bitmap, the bitmap has the expected format and dimensions.
270TEST_F(IconUtilTest, TestCreateSkBitmapFromHICON) {
271  scoped_ptr<SkBitmap> bitmap;
272  base::FilePath small_icon_filename = test_data_directory_.AppendASCII(
273      kSmallIconName);
274  gfx::Size small_icon_size(kSmallIconWidth, kSmallIconHeight);
275  HICON small_icon = LoadIconFromFile(small_icon_filename,
276                                      small_icon_size.width(),
277                                      small_icon_size.height());
278  ASSERT_NE(small_icon, static_cast<HICON>(NULL));
279  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(small_icon, small_icon_size));
280  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
281  EXPECT_EQ(bitmap->width(), small_icon_size.width());
282  EXPECT_EQ(bitmap->height(), small_icon_size.height());
283  EXPECT_EQ(bitmap->colorType(), kN32_SkColorType);
284  ::DestroyIcon(small_icon);
285
286  base::FilePath large_icon_filename = test_data_directory_.AppendASCII(
287      kLargeIconName);
288  gfx::Size large_icon_size(kLargeIconWidth, kLargeIconHeight);
289  HICON large_icon = LoadIconFromFile(large_icon_filename,
290                                      large_icon_size.width(),
291                                      large_icon_size.height());
292  ASSERT_NE(large_icon, static_cast<HICON>(NULL));
293  bitmap.reset(IconUtil::CreateSkBitmapFromHICON(large_icon, large_icon_size));
294  ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
295  EXPECT_EQ(bitmap->width(), large_icon_size.width());
296  EXPECT_EQ(bitmap->height(), large_icon_size.height());
297  EXPECT_EQ(bitmap->colorType(), kN32_SkColorType);
298  ::DestroyIcon(large_icon);
299}
300
301// This test case makes sure that when an HICON is created from an SkBitmap,
302// the returned handle is valid and refers to an icon with the expected
303// dimensions color depth etc.
304TEST_F(IconUtilTest, TestBasicCreateHICONFromSkBitmap) {
305  SkBitmap bitmap = CreateBlackSkBitmap(kSmallIconWidth, kSmallIconHeight);
306  HICON icon = IconUtil::CreateHICONFromSkBitmap(bitmap);
307  EXPECT_NE(icon, static_cast<HICON>(NULL));
308  ICONINFO icon_info;
309  ASSERT_TRUE(::GetIconInfo(icon, &icon_info));
310  EXPECT_TRUE(icon_info.fIcon);
311
312  // Now that have the icon information, we should obtain the specification of
313  // the icon's bitmap and make sure it matches the specification of the
314  // SkBitmap we started with.
315  //
316  // The bitmap handle contained in the icon information is a handle to a
317  // compatible bitmap so we need to call ::GetDIBits() in order to retrieve
318  // the bitmap's header information.
319  BITMAPINFO bitmap_info;
320  ::ZeroMemory(&bitmap_info, sizeof(BITMAPINFO));
321  bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFO);
322  HDC hdc = ::GetDC(NULL);
323  int result = ::GetDIBits(hdc,
324                           icon_info.hbmColor,
325                           0,
326                           kSmallIconWidth,
327                           NULL,
328                           &bitmap_info,
329                           DIB_RGB_COLORS);
330  ASSERT_GT(result, 0);
331  EXPECT_EQ(bitmap_info.bmiHeader.biWidth, kSmallIconWidth);
332  EXPECT_EQ(bitmap_info.bmiHeader.biHeight, kSmallIconHeight);
333  EXPECT_EQ(bitmap_info.bmiHeader.biPlanes, 1);
334  EXPECT_EQ(bitmap_info.bmiHeader.biBitCount, 32);
335  ::ReleaseDC(NULL, hdc);
336  ::DestroyIcon(icon);
337}
338
339// This test case makes sure that CreateIconFileFromImageFamily creates a
340// valid .ico file given an ImageFamily, and appropriately creates all icon
341// sizes from the given input.
342TEST_F(IconUtilTest, TestCreateIconFileFromImageFamily) {
343  gfx::ImageFamily image_family;
344  base::FilePath icon_filename =
345      temp_directory_.path().AppendASCII(kTempIconFilename);
346
347  // Test with only a 16x16 icon. Should only scale up to 48x48.
348  image_family.Add(gfx::Image::CreateFrom1xBitmap(
349      CreateBlackSkBitmap(kSmallIconWidth, kSmallIconHeight)));
350  ASSERT_TRUE(IconUtil::CreateIconFileFromImageFamily(image_family,
351                                                      icon_filename));
352  CheckAllIconSizes(icon_filename, 48);
353
354  // Test with a 48x48 icon. Should only scale down.
355  image_family.Add(gfx::Image::CreateFrom1xBitmap(CreateBlackSkBitmap(48, 48)));
356  ASSERT_TRUE(IconUtil::CreateIconFileFromImageFamily(image_family,
357                                                      icon_filename));
358  CheckAllIconSizes(icon_filename, 48);
359
360  // Test with a 64x64 icon. Should scale up to 256x256.
361  image_family.Add(gfx::Image::CreateFrom1xBitmap(CreateBlackSkBitmap(64, 64)));
362  ASSERT_TRUE(IconUtil::CreateIconFileFromImageFamily(image_family,
363                                                      icon_filename));
364  CheckAllIconSizes(icon_filename, 256);
365
366  // Test with a 256x256 icon. Should include the 256x256 in the output.
367  image_family.Add(gfx::Image::CreateFrom1xBitmap(
368      CreateBlackSkBitmap(256, 256)));
369  ASSERT_TRUE(IconUtil::CreateIconFileFromImageFamily(image_family,
370                                                      icon_filename));
371  CheckAllIconSizes(icon_filename, 256);
372
373  // Test with a 49x49 icon. Should scale up to 256x256, but exclude the
374  // original 49x49 representation from the output.
375  image_family.clear();
376  image_family.Add(gfx::Image::CreateFrom1xBitmap(CreateBlackSkBitmap(49, 49)));
377  ASSERT_TRUE(IconUtil::CreateIconFileFromImageFamily(image_family,
378                                                      icon_filename));
379  CheckAllIconSizes(icon_filename, 256);
380
381  // Test with a non-square 16x32 icon. Should scale up to 48, but exclude the
382  // original 16x32 representation from the output.
383  image_family.clear();
384  image_family.Add(gfx::Image::CreateFrom1xBitmap(CreateBlackSkBitmap(16, 32)));
385  ASSERT_TRUE(IconUtil::CreateIconFileFromImageFamily(image_family,
386                                                      icon_filename));
387  CheckAllIconSizes(icon_filename, 48);
388
389  // Test with a non-square 32x49 icon. Should scale up to 256, but exclude the
390  // original 32x49 representation from the output.
391  image_family.Add(gfx::Image::CreateFrom1xBitmap(CreateBlackSkBitmap(32, 49)));
392  ASSERT_TRUE(IconUtil::CreateIconFileFromImageFamily(image_family,
393                                                      icon_filename));
394  CheckAllIconSizes(icon_filename, 256);
395
396  // Test with an empty and non-empty image.
397  // The empty image should be ignored.
398  image_family.clear();
399  image_family.Add(gfx::Image());
400  image_family.Add(gfx::Image::CreateFrom1xBitmap(CreateBlackSkBitmap(16, 16)));
401  ASSERT_TRUE(IconUtil::CreateIconFileFromImageFamily(image_family,
402                                                       icon_filename));
403  CheckAllIconSizes(icon_filename, 48);
404}
405
406TEST_F(IconUtilTest, TestCreateSkBitmapFromIconResource48x48) {
407  HMODULE module = GetModuleHandle(NULL);
408  scoped_ptr<SkBitmap> bitmap(
409      IconUtil::CreateSkBitmapFromIconResource(module, IDR_MAINFRAME, 48));
410  ASSERT_TRUE(bitmap.get());
411  EXPECT_EQ(48, bitmap->width());
412  EXPECT_EQ(48, bitmap->height());
413}
414
415TEST_F(IconUtilTest, TestCreateSkBitmapFromIconResource256x256) {
416  HMODULE module = GetModuleHandle(NULL);
417  scoped_ptr<SkBitmap> bitmap(
418      IconUtil::CreateSkBitmapFromIconResource(module, IDR_MAINFRAME, 256));
419  ASSERT_TRUE(bitmap.get());
420  EXPECT_EQ(256, bitmap->width());
421  EXPECT_EQ(256, bitmap->height());
422}
423
424// This tests that kNumIconDimensionsUpToMediumSize has the correct value.
425TEST_F(IconUtilTest, TestNumIconDimensionsUpToMediumSize) {
426  ASSERT_LE(IconUtil::kNumIconDimensionsUpToMediumSize,
427            IconUtil::kNumIconDimensions);
428  EXPECT_EQ(IconUtil::kMediumIconSize,
429            IconUtil::kIconDimensions[
430                IconUtil::kNumIconDimensionsUpToMediumSize - 1]);
431}
432