| 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/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 Loading... |
| 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 DCHECK_EQ(256, large_bitmap.width()); |
| 301 DCHECK_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()); |
| 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 Loading... |
| 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 } |
| OLD | NEW |