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 "base/files/file_util.h" | 7 #include "base/files/file_util.h" |
8 #include "base/files/important_file_writer.h" | 8 #include "base/files/important_file_writer.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 // appropriate image for that size, and resizes it to the desired size. | 42 // appropriate image for that size, and resizes it to the desired size. |
43 // Returns true on success, false on failure. Failure can occur if | 43 // Returns true on success, false on failure. Failure can occur if |
44 // |image_family| is empty, all images in the family have size 0x0, or an image | 44 // |image_family| is empty, all images in the family have size 0x0, or an image |
45 // has no allocated pixel data. | 45 // has no allocated pixel data. |
46 // |resized_image_family| must be empty. | 46 // |resized_image_family| must be empty. |
47 bool BuildResizedImageFamily(const gfx::ImageFamily& image_family, | 47 bool BuildResizedImageFamily(const gfx::ImageFamily& image_family, |
48 gfx::ImageFamily* resized_image_family) { | 48 gfx::ImageFamily* resized_image_family) { |
49 DCHECK(resized_image_family); | 49 DCHECK(resized_image_family); |
50 DCHECK(resized_image_family->empty()); | 50 DCHECK(resized_image_family->empty()); |
51 | 51 |
| 52 // Determine whether there is an image bigger than 48x48 (kMediumIconSize). |
| 53 const gfx::Image* biggest = |
| 54 image_family.GetBest(IconUtil::kLargeIconSize, IconUtil::kLargeIconSize); |
| 55 if (!biggest || biggest->IsEmpty()) { |
| 56 // Either |image_family| is empty, or all images have size 0x0. |
| 57 return false; |
| 58 } |
| 59 |
| 60 bool has_bigger_than_medium = biggest->Width() > IconUtil::kMediumIconSize || |
| 61 biggest->Height() > IconUtil::kMediumIconSize; |
| 62 |
52 for (size_t i = 0; i < IconUtil::kNumIconDimensions; ++i) { | 63 for (size_t i = 0; i < IconUtil::kNumIconDimensions; ++i) { |
53 int dimension = IconUtil::kIconDimensions[i]; | 64 int dimension = IconUtil::kIconDimensions[i]; |
54 gfx::Size size(dimension, dimension); | 65 // Windows' "Large icons" view displays icons at full size only if there is |
55 const gfx::Image* best = image_family.GetBest(size); | 66 // a 256x256 (kLargeIconSize) image in the .ico file. Otherwise, it shrinks |
56 if (!best || best->IsEmpty()) { | 67 // icons to 48x48 (kMediumIconSize). Therefore, if there is no source icon |
57 // Either |image_family| is empty, or all images have size 0x0. | 68 // larger than 48x48, do not create any images larger than 48x48. |
| 69 // kIconDimensions is sorted in ascending order, so it is safe to break |
| 70 // here. |
| 71 if (!has_bigger_than_medium && dimension > IconUtil::kMediumIconSize) |
| 72 break; |
| 73 |
| 74 gfx::Image resized = image_family.CreateExact(dimension, dimension); |
| 75 if (resized.IsEmpty()) { |
| 76 // An error occurred in CreateExact (typically because the image had the |
| 77 // wrong pixel format). |
58 return false; | 78 return false; |
59 } | 79 } |
60 | 80 |
61 // Optimize for the "Large icons" view in Windows Vista+. This view displays | 81 resized_image_family->Add(resized); |
62 // icons at full size if only if there is a 256x256 (kLargeIconSize) image | |
63 // in the .ico file. Otherwise, it shrinks icons to 48x48 (kMediumIconSize). | |
64 if (dimension > IconUtil::kMediumIconSize && | |
65 best->Width() <= IconUtil::kMediumIconSize && | |
66 best->Height() <= IconUtil::kMediumIconSize) { | |
67 // There is no source icon larger than 48x48, so do not create any | |
68 // images larger than 48x48. kIconDimensions is sorted in ascending | |
69 // order, so it is safe to break here. | |
70 break; | |
71 } | |
72 | |
73 if (best->Size() == size) { | |
74 resized_image_family->Add(*best); | |
75 } else { | |
76 // There is no |dimension|x|dimension| source image. | |
77 // Resize this one to the desired size, and insert it. | |
78 SkBitmap best_bitmap = best->AsBitmap(); | |
79 // Only kARGB_8888 images are supported. | |
80 // This will also filter out images with no pixels. | |
81 if (best_bitmap.colorType() != kN32_SkColorType) | |
82 return false; | |
83 SkBitmap resized_bitmap = skia::ImageOperations::Resize( | |
84 best_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, | |
85 dimension, dimension); | |
86 resized_image_family->Add(gfx::Image::CreateFrom1xBitmap(resized_bitmap)); | |
87 } | |
88 } | 82 } |
89 return true; | 83 return true; |
90 } | 84 } |
91 | 85 |
92 // Creates a set of bitmaps from an image family. | 86 // Creates a set of bitmaps from an image family. |
93 // All images smaller than 256x256 are converted to SkBitmaps, and inserted into | 87 // All images smaller than 256x256 are converted to SkBitmaps, and inserted into |
94 // |bitmaps| in order of aspect ratio (thinnest to widest), and then ascending | 88 // |bitmaps| in order of aspect ratio (thinnest to widest), and then ascending |
95 // size order. If an image of exactly 256x256 is specified, it is converted into | 89 // size order. If an image of exactly 256x256 is specified, it is converted into |
96 // PNG format and stored in |png_bytes|. Images with width or height larger than | 90 // PNG format and stored in |png_bytes|. Images with width or height larger than |
97 // 256 are ignored. | 91 // 256 are ignored. |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 // Once we compute the size for a singe AND mask scan line, we multiply that | 688 // Once we compute the size for a singe AND mask scan line, we multiply that |
695 // number by the image height in order to get the total number of bytes for | 689 // number by the image height in order to get the total number of bytes for |
696 // the AND mask. Thus, for a 15X15 image, we need 15 * 4 which is 60 bytes | 690 // the AND mask. Thus, for a 15X15 image, we need 15 * 4 which is 60 bytes |
697 // for the monochrome bitmap representing the AND mask. | 691 // for the monochrome bitmap representing the AND mask. |
698 size_t and_line_length = (bitmap.width() + 7) >> 3; | 692 size_t and_line_length = (bitmap.width() + 7) >> 3; |
699 and_line_length = (and_line_length + 3) & ~3; | 693 and_line_length = (and_line_length + 3) & ~3; |
700 size_t and_mask_size = and_line_length * bitmap.height(); | 694 size_t and_mask_size = and_line_length * bitmap.height(); |
701 size_t masks_size = *xor_mask_size + and_mask_size; | 695 size_t masks_size = *xor_mask_size + and_mask_size; |
702 *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER); | 696 *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER); |
703 } | 697 } |
OLD | NEW |