OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/icon_util.h" | 5 #include "ui/gfx/icon_util.h" |
6 | 6 |
| 7 #include <memory> |
| 8 |
7 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
8 #include "base/files/important_file_writer.h" | 10 #include "base/files/important_file_writer.h" |
9 #include "base/logging.h" | 11 #include "base/logging.h" |
10 #include "base/macros.h" | 12 #include "base/macros.h" |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/trace_event/trace_event.h" | 13 #include "base/trace_event/trace_event.h" |
13 #include "base/win/resource_util.h" | 14 #include "base/win/resource_util.h" |
14 #include "base/win/scoped_gdi_object.h" | 15 #include "base/win/scoped_gdi_object.h" |
15 #include "base/win/scoped_handle.h" | 16 #include "base/win/scoped_handle.h" |
16 #include "base/win/scoped_hdc.h" | 17 #include "base/win/scoped_hdc.h" |
17 #include "skia/ext/image_operations.h" | 18 #include "skia/ext/image_operations.h" |
18 #include "third_party/skia/include/core/SkBitmap.h" | 19 #include "third_party/skia/include/core/SkBitmap.h" |
19 #include "ui/gfx/gdi_util.h" | 20 #include "ui/gfx/gdi_util.h" |
20 #include "ui/gfx/geometry/size.h" | 21 #include "ui/gfx/geometry/size.h" |
21 #include "ui/gfx/image/image.h" | 22 #include "ui/gfx/image/image.h" |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 // transparent) and the XOR mask contains the actual image pixels. If the XOR | 198 // transparent) and the XOR mask contains the actual image pixels. If the XOR |
198 // mask bitmap has an alpha channel, the AND monochrome bitmap won't | 199 // mask bitmap has an alpha channel, the AND monochrome bitmap won't |
199 // actually be used for computing the pixel transparency. Even though all our | 200 // actually be used for computing the pixel transparency. Even though all our |
200 // bitmap has an alpha channel, Windows might not agree when all alpha values | 201 // bitmap has an alpha channel, Windows might not agree when all alpha values |
201 // are zero. So the monochrome bitmap is created with all pixels transparent | 202 // are zero. So the monochrome bitmap is created with all pixels transparent |
202 // for this case. Otherwise, it is created with all pixels opaque. | 203 // for this case. Otherwise, it is created with all pixels opaque. |
203 bool bitmap_has_alpha_channel = | 204 bool bitmap_has_alpha_channel = |
204 PixelsHaveAlpha(static_cast<const uint32_t*>(bitmap.getPixels()), | 205 PixelsHaveAlpha(static_cast<const uint32_t*>(bitmap.getPixels()), |
205 bitmap.width() * bitmap.height()); | 206 bitmap.width() * bitmap.height()); |
206 | 207 |
207 scoped_ptr<uint8_t[]> mask_bits; | 208 std::unique_ptr<uint8_t[]> mask_bits; |
208 if (!bitmap_has_alpha_channel) { | 209 if (!bitmap_has_alpha_channel) { |
209 // Bytes per line with paddings to make it word alignment. | 210 // Bytes per line with paddings to make it word alignment. |
210 size_t bytes_per_line = (bitmap.width() + 0xF) / 16 * 2; | 211 size_t bytes_per_line = (bitmap.width() + 0xF) / 16 * 2; |
211 size_t mask_bits_size = bytes_per_line * bitmap.height(); | 212 size_t mask_bits_size = bytes_per_line * bitmap.height(); |
212 | 213 |
213 mask_bits.reset(new uint8_t[mask_bits_size]); | 214 mask_bits.reset(new uint8_t[mask_bits_size]); |
214 DCHECK(mask_bits.get()); | 215 DCHECK(mask_bits.get()); |
215 | 216 |
216 // Make all pixels transparent. | 217 // Make all pixels transparent. |
217 memset(mask_bits.get(), 0xFF, mask_bits_size); | 218 memset(mask_bits.get(), 0xFF, mask_bits_size); |
(...skipping 21 matching lines...) Expand all Loading... |
239 return NULL; | 240 return NULL; |
240 ScopedICONINFO icon_info; | 241 ScopedICONINFO icon_info; |
241 if (!::GetIconInfo(icon, &icon_info)) | 242 if (!::GetIconInfo(icon, &icon_info)) |
242 return NULL; | 243 return NULL; |
243 if (!icon_info.fIcon) | 244 if (!icon_info.fIcon) |
244 return NULL; | 245 return NULL; |
245 return new SkBitmap(CreateSkBitmapFromHICONHelper(icon, s)); | 246 return new SkBitmap(CreateSkBitmapFromHICONHelper(icon, s)); |
246 } | 247 } |
247 | 248 |
248 // static | 249 // static |
249 scoped_ptr<gfx::ImageFamily> IconUtil::CreateImageFamilyFromIconResource( | 250 std::unique_ptr<gfx::ImageFamily> IconUtil::CreateImageFamilyFromIconResource( |
250 HMODULE module, | 251 HMODULE module, |
251 int resource_id) { | 252 int resource_id) { |
252 // Read the resource directly so we can get the icon image sizes. This data | 253 // Read the resource directly so we can get the icon image sizes. This data |
253 // will also be used to directly get the PNG bytes for large images. | 254 // will also be used to directly get the PNG bytes for large images. |
254 void* icon_dir_data = NULL; | 255 void* icon_dir_data = NULL; |
255 size_t icon_dir_size = 0; | 256 size_t icon_dir_size = 0; |
256 if (!base::win::GetResourceFromModule(module, resource_id, RT_GROUP_ICON, | 257 if (!base::win::GetResourceFromModule(module, resource_id, RT_GROUP_ICON, |
257 &icon_dir_data, &icon_dir_size)) { | 258 &icon_dir_data, &icon_dir_size)) { |
258 return nullptr; | 259 return nullptr; |
259 } | 260 } |
260 DCHECK(icon_dir_data); | 261 DCHECK(icon_dir_data); |
261 DCHECK_GE(icon_dir_size, sizeof(GRPICONDIR)); | 262 DCHECK_GE(icon_dir_size, sizeof(GRPICONDIR)); |
262 | 263 |
263 const GRPICONDIR* icon_dir = | 264 const GRPICONDIR* icon_dir = |
264 reinterpret_cast<const GRPICONDIR*>(icon_dir_data); | 265 reinterpret_cast<const GRPICONDIR*>(icon_dir_data); |
265 scoped_ptr<gfx::ImageFamily> result(new gfx::ImageFamily); | 266 std::unique_ptr<gfx::ImageFamily> result(new gfx::ImageFamily); |
266 for (size_t i = 0; i < icon_dir->idCount; ++i) { | 267 for (size_t i = 0; i < icon_dir->idCount; ++i) { |
267 const GRPICONDIRENTRY* entry = &icon_dir->idEntries[i]; | 268 const GRPICONDIRENTRY* entry = &icon_dir->idEntries[i]; |
268 if (entry->bWidth != 0 || entry->bHeight != 0) { | 269 if (entry->bWidth != 0 || entry->bHeight != 0) { |
269 // Ignore the low-bit-depth versions of the icon. | 270 // Ignore the low-bit-depth versions of the icon. |
270 if (entry->wBitCount != 32) | 271 if (entry->wBitCount != 32) |
271 continue; | 272 continue; |
272 | 273 |
273 // For everything except the Vista+ 256x256 icons, use |LoadImage()|. | 274 // For everything except the Vista+ 256x256 icons, use |LoadImage()|. |
274 base::win::ScopedHICON icon_handle(static_cast<HICON>(LoadImage( | 275 base::win::ScopedHICON icon_handle(static_cast<HICON>(LoadImage( |
275 module, MAKEINTRESOURCE(resource_id), IMAGE_ICON, entry->bWidth, | 276 module, MAKEINTRESOURCE(resource_id), IMAGE_ICON, entry->bWidth, |
276 entry->bHeight, LR_DEFAULTCOLOR | LR_DEFAULTSIZE))); | 277 entry->bHeight, LR_DEFAULTCOLOR | LR_DEFAULTSIZE))); |
277 scoped_ptr<SkBitmap> bitmap( | 278 std::unique_ptr<SkBitmap> bitmap( |
278 IconUtil::CreateSkBitmapFromHICON(icon_handle.get())); | 279 IconUtil::CreateSkBitmapFromHICON(icon_handle.get())); |
279 result->Add(gfx::Image::CreateFrom1xBitmap(*bitmap)); | 280 result->Add(gfx::Image::CreateFrom1xBitmap(*bitmap)); |
280 } else { | 281 } else { |
281 // 256x256 icons are stored with width and height set to 0. | 282 // 256x256 icons are stored with width and height set to 0. |
282 // See: http://en.wikipedia.org/wiki/ICO_(file_format) | 283 // See: http://en.wikipedia.org/wiki/ICO_(file_format) |
283 void* png_data = NULL; | 284 void* png_data = NULL; |
284 size_t png_size = 0; | 285 size_t png_size = 0; |
285 if (!base::win::GetResourceFromModule(module, entry->nID, RT_ICON, | 286 if (!base::win::GetResourceFromModule(module, entry->nID, RT_ICON, |
286 &png_data, &png_size)) { | 287 &png_data, &png_size)) { |
287 return nullptr; | 288 return nullptr; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 // bitmap has an alpha channel is by looking through the pixels and checking | 406 // bitmap has an alpha channel is by looking through the pixels and checking |
406 // whether there are non-zero alpha bytes. | 407 // whether there are non-zero alpha bytes. |
407 // | 408 // |
408 // We start by drawing the AND mask into our DIB. | 409 // We start by drawing the AND mask into our DIB. |
409 size_t num_pixels = s.GetArea(); | 410 size_t num_pixels = s.GetArea(); |
410 memset(bits, 0, num_pixels * 4); | 411 memset(bits, 0, num_pixels * 4); |
411 ::DrawIconEx(dib_dc, 0, 0, icon, s.width(), s.height(), 0, NULL, DI_MASK); | 412 ::DrawIconEx(dib_dc, 0, 0, icon, s.width(), s.height(), 0, NULL, DI_MASK); |
412 | 413 |
413 // Capture boolean opacity. We may not use it if we find out the bitmap has | 414 // Capture boolean opacity. We may not use it if we find out the bitmap has |
414 // an alpha channel. | 415 // an alpha channel. |
415 scoped_ptr<bool[]> opaque(new bool[num_pixels]); | 416 std::unique_ptr<bool[]> opaque(new bool[num_pixels]); |
416 for (size_t i = 0; i < num_pixels; ++i) | 417 for (size_t i = 0; i < num_pixels; ++i) |
417 opaque[i] = !bits[i]; | 418 opaque[i] = !bits[i]; |
418 | 419 |
419 // Then draw the image itself which is really the XOR mask. | 420 // Then draw the image itself which is really the XOR mask. |
420 memset(bits, 0, num_pixels * 4); | 421 memset(bits, 0, num_pixels * 4); |
421 ::DrawIconEx(dib_dc, 0, 0, icon, s.width(), s.height(), 0, NULL, DI_NORMAL); | 422 ::DrawIconEx(dib_dc, 0, 0, icon, s.width(), s.height(), 0, NULL, DI_NORMAL); |
422 memcpy(bitmap.getPixels(), static_cast<void*>(bits), num_pixels * 4); | 423 memcpy(bitmap.getPixels(), static_cast<void*>(bits), num_pixels * 4); |
423 | 424 |
424 // Finding out whether the bitmap has an alpha channel. | 425 // Finding out whether the bitmap has an alpha channel. |
425 bool bitmap_has_alpha_channel = PixelsHaveAlpha( | 426 bool bitmap_has_alpha_channel = PixelsHaveAlpha( |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 // Once we compute the size for a singe AND mask scan line, we multiply that | 690 // Once we compute the size for a singe AND mask scan line, we multiply that |
690 // number by the image height in order to get the total number of bytes for | 691 // number by the image height in order to get the total number of bytes for |
691 // the AND mask. Thus, for a 15X15 image, we need 15 * 4 which is 60 bytes | 692 // the AND mask. Thus, for a 15X15 image, we need 15 * 4 which is 60 bytes |
692 // for the monochrome bitmap representing the AND mask. | 693 // for the monochrome bitmap representing the AND mask. |
693 size_t and_line_length = (bitmap.width() + 7) >> 3; | 694 size_t and_line_length = (bitmap.width() + 7) >> 3; |
694 and_line_length = (and_line_length + 3) & ~3; | 695 and_line_length = (and_line_length + 3) & ~3; |
695 size_t and_mask_size = and_line_length * bitmap.height(); | 696 size_t and_mask_size = and_line_length * bitmap.height(); |
696 size_t masks_size = *xor_mask_size + and_mask_size; | 697 size_t masks_size = *xor_mask_size + and_mask_size; |
697 *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER); | 698 *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER); |
698 } | 699 } |
OLD | NEW |