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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 48, // Alt+Tab icon size. | 154 48, // Alt+Tab icon size. |
155 64, // Recommended by the MSDN as a nice to have icon size. | 155 64, // Recommended by the MSDN as a nice to have icon size. |
156 96, // Recommended by the MSDN as a nice to have icon size. | 156 96, // Recommended by the MSDN as a nice to have icon size. |
157 128, // Used by the Shell (e.g. for shortcuts). | 157 128, // Used by the Shell (e.g. for shortcuts). |
158 256 // Used by Vista onwards for large icons. | 158 256 // Used by Vista onwards for large icons. |
159 }; | 159 }; |
160 | 160 |
161 const size_t IconUtil::kNumIconDimensions = arraysize(kIconDimensions); | 161 const size_t IconUtil::kNumIconDimensions = arraysize(kIconDimensions); |
162 const size_t IconUtil::kNumIconDimensionsUpToMediumSize = 9; | 162 const size_t IconUtil::kNumIconDimensionsUpToMediumSize = 9; |
163 | 163 |
164 HICON IconUtil::CreateHICONFromSkBitmap(const SkBitmap& bitmap) { | 164 base::win::ScopedHICON IconUtil::CreateHICONFromSkBitmap( |
| 165 const SkBitmap& bitmap) { |
165 // Only 32 bit ARGB bitmaps are supported. We also try to perform as many | 166 // Only 32 bit ARGB bitmaps are supported. We also try to perform as many |
166 // validations as we can on the bitmap. | 167 // validations as we can on the bitmap. |
167 SkAutoLockPixels bitmap_lock(bitmap); | 168 SkAutoLockPixels bitmap_lock(bitmap); |
168 if ((bitmap.colorType() != kN32_SkColorType) || | 169 if ((bitmap.colorType() != kN32_SkColorType) || |
169 (bitmap.width() <= 0) || (bitmap.height() <= 0) || | 170 (bitmap.width() <= 0) || (bitmap.height() <= 0) || |
170 (bitmap.getPixels() == NULL)) | 171 (bitmap.getPixels() == NULL)) |
171 return NULL; | 172 return base::win::ScopedHICON(); |
172 | 173 |
173 // We start by creating a DIB which we'll use later on in order to create | 174 // We start by creating a DIB which we'll use later on in order to create |
174 // the HICON. We use BITMAPV5HEADER since the bitmap we are about to convert | 175 // the HICON. We use BITMAPV5HEADER since the bitmap we are about to convert |
175 // may contain an alpha channel and the V5 header allows us to specify the | 176 // may contain an alpha channel and the V5 header allows us to specify the |
176 // alpha mask for the DIB. | 177 // alpha mask for the DIB. |
177 BITMAPV5HEADER bitmap_header; | 178 BITMAPV5HEADER bitmap_header; |
178 InitializeBitmapHeader(&bitmap_header, bitmap.width(), bitmap.height()); | 179 InitializeBitmapHeader(&bitmap_header, bitmap.width(), bitmap.height()); |
179 | 180 |
180 void* bits = NULL; | 181 void* bits = NULL; |
181 HBITMAP dib; | 182 HBITMAP dib; |
182 | 183 |
183 { | 184 { |
184 base::win::ScopedGetDC hdc(NULL); | 185 base::win::ScopedGetDC hdc(NULL); |
185 dib = ::CreateDIBSection(hdc, reinterpret_cast<BITMAPINFO*>(&bitmap_header), | 186 dib = ::CreateDIBSection(hdc, reinterpret_cast<BITMAPINFO*>(&bitmap_header), |
186 DIB_RGB_COLORS, &bits, NULL, 0); | 187 DIB_RGB_COLORS, &bits, NULL, 0); |
187 } | 188 } |
188 if (!dib || !bits) | 189 if (!dib || !bits) |
189 return NULL; | 190 return base::win::ScopedHICON(); |
190 | 191 |
191 memcpy(bits, bitmap.getPixels(), bitmap.width() * bitmap.height() * 4); | 192 memcpy(bits, bitmap.getPixels(), bitmap.width() * bitmap.height() * 4); |
192 | 193 |
193 // Icons are generally created using an AND and XOR masks where the AND | 194 // Icons are generally created using an AND and XOR masks where the AND |
194 // specifies boolean transparency (the pixel is either opaque or | 195 // specifies boolean transparency (the pixel is either opaque or |
195 // transparent) and the XOR mask contains the actual image pixels. If the XOR | 196 // transparent) and the XOR mask contains the actual image pixels. If the XOR |
196 // mask bitmap has an alpha channel, the AND monochrome bitmap won't | 197 // mask bitmap has an alpha channel, the AND monochrome bitmap won't |
197 // actually be used for computing the pixel transparency. Even though all our | 198 // actually be used for computing the pixel transparency. Even though all our |
198 // bitmap has an alpha channel, Windows might not agree when all alpha values | 199 // bitmap has an alpha channel, Windows might not agree when all alpha values |
199 // are zero. So the monochrome bitmap is created with all pixels transparent | 200 // are zero. So the monochrome bitmap is created with all pixels transparent |
(...skipping 18 matching lines...) Expand all Loading... |
218 HBITMAP mono_bitmap = ::CreateBitmap(bitmap.width(), bitmap.height(), 1, 1, | 219 HBITMAP mono_bitmap = ::CreateBitmap(bitmap.width(), bitmap.height(), 1, 1, |
219 reinterpret_cast<LPVOID>(mask_bits.get())); | 220 reinterpret_cast<LPVOID>(mask_bits.get())); |
220 DCHECK(mono_bitmap); | 221 DCHECK(mono_bitmap); |
221 | 222 |
222 ICONINFO icon_info; | 223 ICONINFO icon_info; |
223 icon_info.fIcon = TRUE; | 224 icon_info.fIcon = TRUE; |
224 icon_info.xHotspot = 0; | 225 icon_info.xHotspot = 0; |
225 icon_info.yHotspot = 0; | 226 icon_info.yHotspot = 0; |
226 icon_info.hbmMask = mono_bitmap; | 227 icon_info.hbmMask = mono_bitmap; |
227 icon_info.hbmColor = dib; | 228 icon_info.hbmColor = dib; |
228 HICON icon = ::CreateIconIndirect(&icon_info); | 229 base::win::ScopedHICON icon(CreateIconIndirect(&icon_info)); |
229 ::DeleteObject(dib); | 230 ::DeleteObject(dib); |
230 ::DeleteObject(mono_bitmap); | 231 ::DeleteObject(mono_bitmap); |
231 return icon; | 232 return icon; |
232 } | 233 } |
233 | 234 |
234 SkBitmap* IconUtil::CreateSkBitmapFromHICON(HICON icon, const gfx::Size& s) { | 235 SkBitmap* IconUtil::CreateSkBitmapFromHICON(HICON icon, const gfx::Size& s) { |
235 // We start with validating parameters. | 236 // We start with validating parameters. |
236 if (!icon || s.IsEmpty()) | 237 if (!icon || s.IsEmpty()) |
237 return NULL; | 238 return NULL; |
238 ScopedICONINFO icon_info; | 239 ScopedICONINFO icon_info; |
(...skipping 23 matching lines...) Expand all Loading... |
262 reinterpret_cast<const GRPICONDIR*>(icon_dir_data); | 263 reinterpret_cast<const GRPICONDIR*>(icon_dir_data); |
263 scoped_ptr<gfx::ImageFamily> result(new gfx::ImageFamily); | 264 scoped_ptr<gfx::ImageFamily> result(new gfx::ImageFamily); |
264 for (size_t i = 0; i < icon_dir->idCount; ++i) { | 265 for (size_t i = 0; i < icon_dir->idCount; ++i) { |
265 const GRPICONDIRENTRY* entry = &icon_dir->idEntries[i]; | 266 const GRPICONDIRENTRY* entry = &icon_dir->idEntries[i]; |
266 if (entry->bWidth != 0 || entry->bHeight != 0) { | 267 if (entry->bWidth != 0 || entry->bHeight != 0) { |
267 // Ignore the low-bit-depth versions of the icon. | 268 // Ignore the low-bit-depth versions of the icon. |
268 if (entry->wBitCount != 32) | 269 if (entry->wBitCount != 32) |
269 continue; | 270 continue; |
270 | 271 |
271 // For everything except the Vista+ 256x256 icons, use |LoadImage()|. | 272 // For everything except the Vista+ 256x256 icons, use |LoadImage()|. |
272 HICON icon_handle = static_cast<HICON>(LoadImage( | 273 base::win::ScopedHICON icon_handle(static_cast<HICON>(LoadImage( |
273 module, MAKEINTRESOURCE(resource_id), IMAGE_ICON, entry->bWidth, | 274 module, MAKEINTRESOURCE(resource_id), IMAGE_ICON, entry->bWidth, |
274 entry->bHeight, LR_DEFAULTCOLOR | LR_DEFAULTSIZE)); | 275 entry->bHeight, LR_DEFAULTCOLOR | LR_DEFAULTSIZE))); |
275 scoped_ptr<SkBitmap> bitmap( | 276 scoped_ptr<SkBitmap> bitmap( |
276 IconUtil::CreateSkBitmapFromHICON(icon_handle)); | 277 IconUtil::CreateSkBitmapFromHICON(icon_handle.get())); |
277 DestroyIcon(icon_handle); | |
278 result->Add(gfx::Image::CreateFrom1xBitmap(*bitmap)); | 278 result->Add(gfx::Image::CreateFrom1xBitmap(*bitmap)); |
279 } else { | 279 } else { |
280 // 256x256 icons are stored with width and height set to 0. | 280 // 256x256 icons are stored with width and height set to 0. |
281 // See: http://en.wikipedia.org/wiki/ICO_(file_format) | 281 // See: http://en.wikipedia.org/wiki/ICO_(file_format) |
282 void* png_data = NULL; | 282 void* png_data = NULL; |
283 size_t png_size = 0; | 283 size_t png_size = 0; |
284 if (!base::win::GetResourceFromModule(module, entry->nID, RT_ICON, | 284 if (!base::win::GetResourceFromModule(module, entry->nID, RT_ICON, |
285 &png_data, &png_size)) { | 285 &png_data, &png_size)) { |
286 return nullptr; | 286 return nullptr; |
287 } | 287 } |
(...skipping 18 matching lines...) Expand all Loading... |
306 if (!::GetIconInfo(icon, &icon_info)) | 306 if (!::GetIconInfo(icon, &icon_info)) |
307 return NULL; | 307 return NULL; |
308 | 308 |
309 if (!::GetObject(icon_info.hbmMask, sizeof(bitmap_info), &bitmap_info)) | 309 if (!::GetObject(icon_info.hbmMask, sizeof(bitmap_info), &bitmap_info)) |
310 return NULL; | 310 return NULL; |
311 | 311 |
312 gfx::Size icon_size(bitmap_info.bmWidth, bitmap_info.bmHeight); | 312 gfx::Size icon_size(bitmap_info.bmWidth, bitmap_info.bmHeight); |
313 return new SkBitmap(CreateSkBitmapFromHICONHelper(icon, icon_size)); | 313 return new SkBitmap(CreateSkBitmapFromHICONHelper(icon, icon_size)); |
314 } | 314 } |
315 | 315 |
316 HICON IconUtil::CreateCursorFromDIB(const gfx::Size& icon_size, | 316 base::win::ScopedHICON IconUtil::CreateCursorFromDIB(const gfx::Size& icon_size, |
317 const gfx::Point& hotspot, | 317 const gfx::Point& hotspot, |
318 const void* dib_bits, | 318 const void* dib_bits, |
319 size_t dib_size) { | 319 size_t dib_size) { |
320 BITMAPINFO icon_bitmap_info = {}; | 320 BITMAPINFO icon_bitmap_info = {}; |
321 gfx::CreateBitmapHeader( | 321 gfx::CreateBitmapHeader( |
322 icon_size.width(), | 322 icon_size.width(), |
323 icon_size.height(), | 323 icon_size.height(), |
324 reinterpret_cast<BITMAPINFOHEADER*>(&icon_bitmap_info)); | 324 reinterpret_cast<BITMAPINFOHEADER*>(&icon_bitmap_info)); |
325 | 325 |
326 base::win::ScopedGetDC dc(NULL); | 326 base::win::ScopedGetDC dc(NULL); |
327 base::win::ScopedCreateDC working_dc(CreateCompatibleDC(dc)); | 327 base::win::ScopedCreateDC working_dc(CreateCompatibleDC(dc)); |
328 base::win::ScopedGDIObject<HBITMAP> bitmap_handle( | 328 base::win::ScopedGDIObject<HBITMAP> bitmap_handle( |
329 CreateDIBSection(dc, | 329 CreateDIBSection(dc, |
330 &icon_bitmap_info, | 330 &icon_bitmap_info, |
331 DIB_RGB_COLORS, | 331 DIB_RGB_COLORS, |
332 0, | 332 0, |
333 0, | 333 0, |
334 0)); | 334 0)); |
335 if (dib_size > 0) { | 335 if (dib_size > 0) { |
336 SetDIBits(0, | 336 SetDIBits(0, |
337 bitmap_handle, | 337 bitmap_handle.get(), |
338 0, | 338 0, |
339 icon_size.height(), | 339 icon_size.height(), |
340 dib_bits, | 340 dib_bits, |
341 &icon_bitmap_info, | 341 &icon_bitmap_info, |
342 DIB_RGB_COLORS); | 342 DIB_RGB_COLORS); |
343 } | 343 } |
344 | 344 |
345 HBITMAP old_bitmap = reinterpret_cast<HBITMAP>( | 345 HBITMAP old_bitmap = reinterpret_cast<HBITMAP>( |
346 SelectObject(working_dc.Get(), bitmap_handle)); | 346 SelectObject(working_dc.Get(), bitmap_handle.get())); |
347 SetBkMode(working_dc.Get(), TRANSPARENT); | 347 SetBkMode(working_dc.Get(), TRANSPARENT); |
348 SelectObject(working_dc.Get(), old_bitmap); | 348 SelectObject(working_dc.Get(), old_bitmap); |
349 | 349 |
350 base::win::ScopedGDIObject<HBITMAP> mask( | 350 base::win::ScopedGDIObject<HBITMAP> mask( |
351 CreateBitmap(icon_size.width(), | 351 CreateBitmap(icon_size.width(), |
352 icon_size.height(), | 352 icon_size.height(), |
353 1, | 353 1, |
354 1, | 354 1, |
355 NULL)); | 355 NULL)); |
356 ICONINFO ii = {0}; | 356 ICONINFO ii = {0}; |
357 ii.fIcon = FALSE; | 357 ii.fIcon = FALSE; |
358 ii.xHotspot = hotspot.x(); | 358 ii.xHotspot = hotspot.x(); |
359 ii.yHotspot = hotspot.y(); | 359 ii.yHotspot = hotspot.y(); |
360 ii.hbmMask = mask; | 360 ii.hbmMask = mask.get(); |
361 ii.hbmColor = bitmap_handle; | 361 ii.hbmColor = bitmap_handle.get(); |
362 | 362 |
363 return CreateIconIndirect(&ii); | 363 return base::win::ScopedHICON(CreateIconIndirect(&ii)); |
364 } | 364 } |
365 | 365 |
366 SkBitmap IconUtil::CreateSkBitmapFromHICONHelper(HICON icon, | 366 SkBitmap IconUtil::CreateSkBitmapFromHICONHelper(HICON icon, |
367 const gfx::Size& s) { | 367 const gfx::Size& s) { |
368 DCHECK(icon); | 368 DCHECK(icon); |
369 DCHECK(!s.IsEmpty()); | 369 DCHECK(!s.IsEmpty()); |
370 | 370 |
371 // Allocating memory for the SkBitmap object. We are going to create an ARGB | 371 // Allocating memory for the SkBitmap object. We are going to create an ARGB |
372 // bitmap so we should set the configuration appropriately. | 372 // bitmap so we should set the configuration appropriately. |
373 SkBitmap bitmap; | 373 SkBitmap bitmap; |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 // 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 |
689 // 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 |
690 // 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 |
691 // for the monochrome bitmap representing the AND mask. | 691 // for the monochrome bitmap representing the AND mask. |
692 size_t and_line_length = (bitmap.width() + 7) >> 3; | 692 size_t and_line_length = (bitmap.width() + 7) >> 3; |
693 and_line_length = (and_line_length + 3) & ~3; | 693 and_line_length = (and_line_length + 3) & ~3; |
694 size_t and_mask_size = and_line_length * bitmap.height(); | 694 size_t and_mask_size = and_line_length * bitmap.height(); |
695 size_t masks_size = *xor_mask_size + and_mask_size; | 695 size_t masks_size = *xor_mask_size + and_mask_size; |
696 *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER); | 696 *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER); |
697 } | 697 } |
OLD | NEW |