| 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 |