Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: ui/gfx/icon_util.cc

Issue 11742007: Add support for adding 256x256 pngs to Windows .ico files. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/gfx/icon_util.h ('k') | ui/gfx/icon_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/file_util.h" 7 #include "base/file_util.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/win/scoped_gdi_object.h" 10 #include "base/win/scoped_gdi_object.h"
11 #include "base/win/scoped_handle.h" 11 #include "base/win/scoped_handle.h"
12 #include "base/win/scoped_hdc.h" 12 #include "base/win/scoped_hdc.h"
13 #include "skia/ext/image_operations.h" 13 #include "skia/ext/image_operations.h"
14 #include "third_party/skia/include/core/SkBitmap.h" 14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "ui/gfx/gdi_util.h" 15 #include "ui/gfx/gdi_util.h"
16 #include "ui/gfx/image/image.h"
16 #include "ui/gfx/size.h" 17 #include "ui/gfx/size.h"
17 18
18 namespace { 19 namespace {
19 struct ScopedICONINFO : ICONINFO { 20 struct ScopedICONINFO : ICONINFO {
20 ScopedICONINFO() { 21 ScopedICONINFO() {
21 hbmColor = NULL; 22 hbmColor = NULL;
22 hbmMask = NULL; 23 hbmMask = NULL;
23 } 24 }
24 25
25 ~ScopedICONINFO() { 26 ~ScopedICONINFO() {
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 } 276 }
276 277
277 ::SelectObject(dib_dc, old_obj); 278 ::SelectObject(dib_dc, old_obj);
278 ::DeleteObject(dib); 279 ::DeleteObject(dib);
279 ::DeleteDC(dib_dc); 280 ::DeleteDC(dib_dc);
280 281
281 return bitmap; 282 return bitmap;
282 } 283 }
283 284
284 bool IconUtil::CreateIconFileFromSkBitmap(const SkBitmap& bitmap, 285 bool IconUtil::CreateIconFileFromSkBitmap(const SkBitmap& bitmap,
286 const SkBitmap& large_bitmap,
285 const FilePath& icon_path) { 287 const FilePath& icon_path) {
286 // Only 32 bit ARGB bitmaps are supported. We also make sure the bitmap has 288 // Only 32 bit ARGB bitmaps are supported. We also make sure the bitmap has
287 // been properly initialized. 289 // been properly initialized.
288 SkAutoLockPixels bitmap_lock(bitmap); 290 SkAutoLockPixels bitmap_lock(bitmap);
289 if ((bitmap.config() != SkBitmap::kARGB_8888_Config) || 291 if ((bitmap.config() != SkBitmap::kARGB_8888_Config) ||
290 (bitmap.height() <= 0) || (bitmap.width() <= 0) || 292 (bitmap.height() <= 0) || (bitmap.width() <= 0) ||
291 (bitmap.getPixels() == NULL)) 293 (bitmap.getPixels() == NULL)) {
292 return false; 294 return false;
295 }
296
297 // If |large_bitmap| was specified, validate its dimension and convert to PNG.
298 scoped_refptr<base::RefCountedMemory> png_bytes;
299 if (!large_bitmap.empty()) {
300 CHECK_EQ(256, large_bitmap.width());
sky 2013/01/07 17:05:24 Why CHECK and not DCHECK?
Alexei Svitkine (slow) 2013/01/07 17:51:28 I could do a DCHECK. I guess I wanted to make sure
sky 2013/01/07 22:18:56 See http://dev.chromium.org/developers/coding-styl
Alexei Svitkine (slow) 2013/01/07 22:25:23 Ah, I didn't realise CHECKs had to meet those crit
301 CHECK_EQ(256, large_bitmap.height());
302 png_bytes = gfx::Image(large_bitmap).As1xPNGBytes();
303 }
293 304
294 // We start by creating the file. 305 // We start by creating the file.
295 base::win::ScopedHandle icon_file(::CreateFile(icon_path.value().c_str(), 306 base::win::ScopedHandle icon_file(::CreateFile(icon_path.value().c_str(),
296 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); 307 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
297 308
298 if (!icon_file.IsValid()) 309 if (!icon_file.IsValid())
299 return false; 310 return false;
300 311
301 // Creating a set of bitmaps corresponding to the icon images we'll end up 312 // Creating a set of bitmaps corresponding to the icon images we'll end up
302 // storing in the icon file. Each bitmap is created by resizing the given 313 // storing in the icon file. Each bitmap is created by resizing the given
303 // bitmap to the desired size. 314 // bitmap to the desired size.
304 std::vector<SkBitmap> bitmaps; 315 std::vector<SkBitmap> bitmaps;
305 CreateResizedBitmapSet(bitmap, &bitmaps); 316 CreateResizedBitmapSet(bitmap, &bitmaps);
306 DCHECK(!bitmaps.empty()); 317 DCHECK(!bitmaps.empty());
sky 2013/01/07 17:05:24 Is there a reason we can't add large_bitmap to bit
Alexei Svitkine (slow) 2013/01/07 17:51:28 Yes, because it has to be special-cased. Non-256x
307 size_t bitmap_count = bitmaps.size(); 318 size_t bitmap_count = bitmaps.size();
308 319
309 // Computing the total size of the buffer we need in order to store the 320 // Computing the total size of the buffer we need in order to store the
310 // images in the desired icon format. 321 // images in the desired icon format.
311 size_t buffer_size = ComputeIconFileBufferSize(bitmaps); 322 size_t buffer_size = ComputeIconFileBufferSize(bitmaps);
312 unsigned char* buffer = new unsigned char[buffer_size]; 323 // Account for the bytes needed for the PNG entry.
313 DCHECK(buffer != NULL); 324 if (png_bytes.get())
314 memset(buffer, 0, buffer_size); 325 buffer_size += sizeof(ICONDIRENTRY) + png_bytes->size();
315 326
316 // Setting the information in the structures residing within the buffer. 327 // Setting the information in the structures residing within the buffer.
317 // First, we set the information which doesn't require iterating through the 328 // First, we set the information which doesn't require iterating through the
318 // bitmap set and then we set the bitmap specific structures. In the latter 329 // bitmap set and then we set the bitmap specific structures. In the latter
319 // step we also copy the actual bits. 330 // step we also copy the actual bits.
320 ICONDIR* icon_dir = reinterpret_cast<ICONDIR*>(buffer); 331 std::vector<uint8> buffer(buffer_size);
332 ICONDIR* icon_dir = reinterpret_cast<ICONDIR*>(&buffer[0]);
321 icon_dir->idType = kResourceTypeIcon; 333 icon_dir->idType = kResourceTypeIcon;
322 icon_dir->idCount = bitmap_count; 334 icon_dir->idCount = bitmap_count;
323 size_t icon_dir_count = bitmap_count - 1; // Note DCHECK(!bitmaps.empty())! 335 size_t icon_dir_count = bitmap_count - 1; // Note DCHECK(!bitmaps.empty())!
336
337 // Increment counts if a PNG entry will be added.
338 if (png_bytes.get()) {
339 icon_dir->idCount++;
340 icon_dir_count++;
341 }
342
324 size_t offset = sizeof(ICONDIR) + (sizeof(ICONDIRENTRY) * icon_dir_count); 343 size_t offset = sizeof(ICONDIR) + (sizeof(ICONDIRENTRY) * icon_dir_count);
325 for (size_t i = 0; i < bitmap_count; i++) { 344 for (size_t i = 0; i < bitmap_count; i++) {
326 ICONIMAGE* image = reinterpret_cast<ICONIMAGE*>(buffer + offset); 345 ICONIMAGE* image = reinterpret_cast<ICONIMAGE*>(&buffer[offset]);
327 DCHECK_LT(offset, buffer_size); 346 DCHECK_LT(offset, buffer_size);
328 size_t icon_image_size = 0; 347 size_t icon_image_size = 0;
329 SetSingleIconImageInformation(bitmaps[i], i, icon_dir, image, offset, 348 SetSingleIconImageInformation(bitmaps[i], i, icon_dir, image, offset,
330 &icon_image_size); 349 &icon_image_size);
331 DCHECK_GT(icon_image_size, 0U); 350 DCHECK_GT(icon_image_size, 0U);
332 offset += icon_image_size; 351 offset += icon_image_size;
333 } 352 }
353
354 // Add the PNG entry, if necessary.
355 if (png_bytes.get()) {
356 ICONDIRENTRY* entry = &icon_dir->idEntries[bitmap_count];
357 entry->bWidth = 0;
358 entry->bHeight = 0;
359 entry->wPlanes = 1;
360 entry->wBitCount = 32;
361 entry->dwBytesInRes = png_bytes->size();
362 entry->dwImageOffset = offset;
363 memcpy(&buffer[offset], png_bytes->front(), png_bytes->size());
364 offset += png_bytes->size();
365 }
366
334 DCHECK_EQ(offset, buffer_size); 367 DCHECK_EQ(offset, buffer_size);
335 368
336 // Finally, writing the data info the file. 369 // Finally, write the data to the file.
337 DWORD bytes_written; 370 DWORD bytes_written;
338 bool delete_file = false; 371 bool delete_file = false;
339 if (!WriteFile(icon_file.Get(), buffer, buffer_size, &bytes_written, NULL) || 372 if (!WriteFile(icon_file.Get(), &buffer[0], buffer_size, &bytes_written,
340 bytes_written != buffer_size) 373 NULL) ||
374 bytes_written != buffer_size) {
341 delete_file = true; 375 delete_file = true;
376 }
342 377
343 ::CloseHandle(icon_file.Take()); 378 ::CloseHandle(icon_file.Take());
344 delete [] buffer;
345 if (delete_file) { 379 if (delete_file) {
346 bool success = file_util::Delete(icon_path, false); 380 bool success = file_util::Delete(icon_path, false);
347 DCHECK(success); 381 DCHECK(success);
348 } 382 }
349 383
350 return !delete_file; 384 return !delete_file;
351 } 385 }
352 386
353 bool IconUtil::PixelsHaveAlpha(const uint32* pixels, size_t num_pixels) { 387 bool IconUtil::PixelsHaveAlpha(const uint32* pixels, size_t num_pixels) {
354 for (const uint32* end = pixels + num_pixels; pixels != end; ++pixels) { 388 for (const uint32* end = pixels + num_pixels; pixels != end; ++pixels) {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 // Once we compute the size for a singe AND mask scan line, we multiply that 577 // Once we compute the size for a singe AND mask scan line, we multiply that
544 // number by the image height in order to get the total number of bytes for 578 // number by the image height in order to get the total number of bytes for
545 // the AND mask. Thus, for a 15X15 image, we need 15 * 4 which is 60 bytes 579 // the AND mask. Thus, for a 15X15 image, we need 15 * 4 which is 60 bytes
546 // for the monochrome bitmap representing the AND mask. 580 // for the monochrome bitmap representing the AND mask.
547 size_t and_line_length = (bitmap.width() + 7) >> 3; 581 size_t and_line_length = (bitmap.width() + 7) >> 3;
548 and_line_length = (and_line_length + 3) & ~3; 582 and_line_length = (and_line_length + 3) & ~3;
549 size_t and_mask_size = and_line_length * bitmap.height(); 583 size_t and_mask_size = and_line_length * bitmap.height();
550 size_t masks_size = *xor_mask_size + and_mask_size; 584 size_t masks_size = *xor_mask_size + and_mask_size;
551 *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER); 585 *bytes_in_resource = masks_size + sizeof(BITMAPINFOHEADER);
552 } 586 }
OLDNEW
« no previous file with comments | « ui/gfx/icon_util.h ('k') | ui/gfx/icon_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698