diff options
-rw-r--r-- | base/win/resource_util.cc | 18 | ||||
-rw-r--r-- | base/win/resource_util.h | 15 | ||||
-rw-r--r-- | chrome/browser/app_icon_win.cc | 31 | ||||
-rw-r--r-- | chrome/browser/app_icon_win.h | 8 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_shortcut_manager_win.cc | 5 | ||||
-rw-r--r-- | ui/gfx/icon_util.cc | 62 | ||||
-rw-r--r-- | ui/gfx/icon_util.h | 34 | ||||
-rw-r--r-- | ui/gfx/icon_util_unittest.cc | 19 | ||||
-rw-r--r-- | ui/test/ui_unittests.rc | 36 | ||||
-rw-r--r-- | ui/test/ui_unittests_resource.h | 5 | ||||
-rw-r--r-- | ui/ui_unittests.gypi | 1 |
11 files changed, 207 insertions, 27 deletions
diff --git a/base/win/resource_util.cc b/base/win/resource_util.cc index de9f583..0c10078 100644 --- a/base/win/resource_util.cc +++ b/base/win/resource_util.cc @@ -7,8 +7,12 @@ namespace base { namespace win { -bool GetDataResourceFromModule(HMODULE module, int resource_id, - void** data, size_t* length) { + +bool GetResourceFromModule(HMODULE module, + int resource_id, + LPCTSTR resource_type, + void** data, + size_t* length) { if (!module) return false; @@ -18,7 +22,7 @@ bool GetDataResourceFromModule(HMODULE module, int resource_id, } HRSRC hres_info = FindResource(module, MAKEINTRESOURCE(resource_id), - L"BINDATA"); + resource_type); if (NULL == hres_info) return false; @@ -35,5 +39,13 @@ bool GetDataResourceFromModule(HMODULE module, int resource_id, *length = static_cast<size_t>(data_size); return true; } + +bool GetDataResourceFromModule(HMODULE module, + int resource_id, + void** data, + size_t* length) { + return GetResourceFromModule(module, resource_id, L"BINDATA", data, length); +} + } // namespace win } // namespace base diff --git a/base/win/resource_util.h b/base/win/resource_util.h index 9955402..f3444ae 100644 --- a/base/win/resource_util.h +++ b/base/win/resource_util.h @@ -16,11 +16,22 @@ namespace base { namespace win { +// Function for getting a data resource of the specified |resource_type| from +// a dll. Some resources are optional, especially in unit tests, so this +// returns false but doesn't raise an error if the resource can't be loaded. +bool BASE_EXPORT GetResourceFromModule(HMODULE module, + int resource_id, + LPCTSTR resource_type, + void** data, + size_t* length); + // Function for getting a data resource (BINDATA) from a dll. Some // resources are optional, especially in unit tests, so this returns false // but doesn't raise an error if the resource can't be loaded. -bool BASE_EXPORT GetDataResourceFromModule(HMODULE module, int resource_id, - void** data, size_t* length); +bool BASE_EXPORT GetDataResourceFromModule(HMODULE module, + int resource_id, + void** data, + size_t* length); } // namespace win } // namespace base diff --git a/chrome/browser/app_icon_win.cc b/chrome/browser/app_icon_win.cc index addec59..e893b4e 100644 --- a/chrome/browser/app_icon_win.cc +++ b/chrome/browser/app_icon_win.cc @@ -6,32 +6,35 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/common/chrome_constants.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/icon_util.h" #if defined(GOOGLE_CHROME_BUILD) #include "chrome/installer/util/install_util.h" #endif -HICON GetAppIcon() { +namespace { + +// Returns the resource id of the application icon. +int GetAppIconResourceId() { int icon_id = IDR_MAINFRAME; #if defined(GOOGLE_CHROME_BUILD) if (InstallUtil::IsChromeSxSProcess()) icon_id = IDR_SXS; #endif + return icon_id; +} + +} // namespace + +HICON GetAppIcon() { + const int icon_id = GetAppIconResourceId(); return LoadIcon(GetModuleHandle(chrome::kBrowserResourcesDll), MAKEINTRESOURCE(icon_id)); } -HICON GetAppIconForSize(int size) { - int icon_id = IDR_MAINFRAME; -#if defined(GOOGLE_CHROME_BUILD) - if (InstallUtil::IsChromeSxSProcess()) - icon_id = IDR_SXS; -#endif - return static_cast<HICON>( - LoadImage(GetModuleHandle(chrome::kBrowserResourcesDll), - MAKEINTRESOURCE(icon_id), - IMAGE_ICON, - size, - size, - LR_DEFAULTCOLOR | LR_DEFAULTSIZE)); +scoped_ptr<SkBitmap> GetAppIconForSize(int size) { + const int icon_id = GetAppIconResourceId(); + return IconUtil::CreateSkBitmapFromIconResource( + GetModuleHandle(chrome::kBrowserResourcesDll), icon_id, size); } diff --git a/chrome/browser/app_icon_win.h b/chrome/browser/app_icon_win.h index 40fee4cf..d15ac6c 100644 --- a/chrome/browser/app_icon_win.h +++ b/chrome/browser/app_icon_win.h @@ -7,11 +7,15 @@ #include <windows.h> +#include "base/memory/scoped_ptr.h" + +class SkBitmap; + HICON GetAppIcon(); // Retrieve the application icon for the given size. Note that if you specify a // size other than what is contained in chrome.dll (16x16, 32x32, 48x48), this -// might return a handle to a poorly resized icon. -HICON GetAppIconForSize(int size); +// might return a poorly resized icon. +scoped_ptr<SkBitmap> GetAppIconForSize(int size); #endif // CHROME_BROWSER_APP_ICON_WIN_H_ diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc index 0d78de1..5ba6965 100644 --- a/chrome/browser/profiles/profile_shortcut_manager_win.cc +++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc @@ -59,10 +59,7 @@ FilePath CreateChromeDesktopShortcutIconForProfile( const FilePath& profile_path, const SkBitmap& avatar_bitmap) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - HICON app_icon_handle = GetAppIconForSize(kShortcutIconSize); - scoped_ptr<SkBitmap> app_icon_bitmap( - IconUtil::CreateSkBitmapFromHICON(app_icon_handle)); - DestroyIcon(app_icon_handle); + scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize)); if (!app_icon_bitmap.get()) return FilePath(); diff --git a/ui/gfx/icon_util.cc b/ui/gfx/icon_util.cc index 4f4b4b7..5cce7e3 100644 --- a/ui/gfx/icon_util.cc +++ b/ui/gfx/icon_util.cc @@ -7,6 +7,7 @@ #include "base/file_util.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/win/resource_util.h" #include "base/win/scoped_gdi_object.h" #include "base/win/scoped_handle.h" #include "base/win/scoped_hdc.h" @@ -17,6 +18,7 @@ #include "ui/gfx/size.h" namespace { + struct ScopedICONINFO : ICONINFO { ScopedICONINFO() { hbmColor = NULL; @@ -30,7 +32,8 @@ struct ScopedICONINFO : ICONINFO { ::DeleteObject(hbmMask); } }; -} + +} // namespace // Defining the dimensions for the icon images. We store only one value because // we always resize to a square image; that is, the value 48 means that we are @@ -132,6 +135,63 @@ SkBitmap* IconUtil::CreateSkBitmapFromHICON(HICON icon, const gfx::Size& s) { return new SkBitmap(CreateSkBitmapFromHICONHelper(icon, s)); } +scoped_ptr<SkBitmap> IconUtil::CreateSkBitmapFromIconResource(HMODULE module, + int resource_id, + int size) { + DCHECK_LE(size, 256); + + // For everything except the Vista+ 256x256 icons, use |LoadImage()|. + if (size != 256) { + HICON icon_handle = + static_cast<HICON>(LoadImage(module, MAKEINTRESOURCE(resource_id), + IMAGE_ICON, size, size, + LR_DEFAULTCOLOR | LR_DEFAULTSIZE)); + scoped_ptr<SkBitmap> bitmap(IconUtil::CreateSkBitmapFromHICON(icon_handle)); + DestroyIcon(icon_handle); + return bitmap.Pass(); + } + + // For Vista+ 256x256 PNG icons, read the resource directly and find + // the corresponding icon entry to get its PNG bytes. + void* icon_dir_data = NULL; + size_t icon_dir_size = 0; + if (!base::win::GetResourceFromModule(module, resource_id, RT_GROUP_ICON, + &icon_dir_data, &icon_dir_size)) { + return scoped_ptr<SkBitmap>(); + } + DCHECK(icon_dir_data); + DCHECK_GE(icon_dir_size, sizeof(GRPICONDIR)); + + const GRPICONDIR* icon_dir = + reinterpret_cast<const GRPICONDIR*>(icon_dir_data); + const GRPICONDIRENTRY* large_icon_entry = NULL; + for (size_t i = 0; i < icon_dir->idCount; ++i) { + const GRPICONDIRENTRY* entry = &icon_dir->idEntries[i]; + // 256x256 icons are stored with width and height set to 0. + // See: http://en.wikipedia.org/wiki/ICO_(file_format) + if (entry->bWidth == 0 && entry->bHeight == 0) { + large_icon_entry = entry; + break; + } + } + if (!large_icon_entry) + return scoped_ptr<SkBitmap>(); + + void* png_data = NULL; + size_t png_size = 0; + if (!base::win::GetResourceFromModule(module, large_icon_entry->nID, RT_ICON, + &png_data, &png_size)) { + return scoped_ptr<SkBitmap>(); + } + DCHECK(png_data); + DCHECK_EQ(png_size, large_icon_entry->dwBytesInRes); + + const unsigned char* png_bytes = + reinterpret_cast<const unsigned char*>(png_data); + gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(png_bytes, png_size); + return scoped_ptr<SkBitmap>(new SkBitmap(image.AsBitmap())); +} + SkBitmap* IconUtil::CreateSkBitmapFromHICON(HICON icon) { // We start with validating parameters. if (!icon) diff --git a/ui/gfx/icon_util.h b/ui/gfx/icon_util.h index ae16e01..dfeea4c 100644 --- a/ui/gfx/icon_util.h +++ b/ui/gfx/icon_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" #include "ui/base/ui_export.h" #include "ui/gfx/point.h" #include "ui/gfx/size.h" @@ -73,6 +74,14 @@ class UI_EXPORT IconUtil { // it when it is no longer needed. static SkBitmap* CreateSkBitmapFromHICON(HICON icon, const gfx::Size& s); + // Loads an icon resource as a SkBitmap for the specified |size| from a + // loaded .dll or .exe |module|. Supports loading smaller icon sizes as well + // as the Vista+ 256x256 PNG icon size. If the icon could not be loaded or + // found, returns a NULL scoped_ptr. + static scoped_ptr<SkBitmap> CreateSkBitmapFromIconResource(HMODULE module, + int resource_id, + int size); + // Given a valid HICON handle representing an icon, this function converts // the icon into an SkBitmap object containing an ARGB bitmap using the // dimensions of HICON. If the function cannot convert the icon to a bitmap @@ -109,6 +118,7 @@ class UI_EXPORT IconUtil { // the icon file structures in any of the Windows header files so we need to // define these structure within the class. We must make sure we use 2 byte // packing so that the structures are layed out properly within the file. + // See: http://msdn.microsoft.com/en-us/library/ms997538.aspx #pragma pack(push) #pragma pack(2) @@ -134,6 +144,28 @@ class UI_EXPORT IconUtil { ICONDIRENTRY idEntries[1]; }; + // GRPICONDIRENTRY contains meta data for an individual icon image within a + // RT_GROUP_ICON resource in an .exe or .dll. + struct GRPICONDIRENTRY { + BYTE bWidth; + BYTE bHeight; + BYTE bColorCount; + BYTE bReserved; + WORD wPlanes; + WORD wBitCount; + DWORD dwBytesInRes; + WORD nID; + }; + + // GRPICONDIR Contains information about all the icon images contained within + // a RT_GROUP_ICON resource in an .exe or .dll. + struct GRPICONDIR { + WORD idReserved; + WORD idType; + WORD idCount; + GRPICONDIRENTRY idEntries[1]; + }; + // Contains the actual icon image. struct ICONIMAGE { BITMAPINFOHEADER icHeader; diff --git a/ui/gfx/icon_util_unittest.cc b/ui/gfx/icon_util_unittest.cc index c8963af..502c0eb 100644 --- a/ui/gfx/icon_util_unittest.cc +++ b/ui/gfx/icon_util_unittest.cc @@ -12,6 +12,7 @@ #include "ui/gfx/icon_util.h" #include "ui/gfx/image/image.h" #include "ui/gfx/size.h" +#include "ui/test/ui_unittests_resource.h" namespace { @@ -293,3 +294,21 @@ TEST_F(IconUtilTest, TestCreateIconFileWithLargeBitmap) { EXPECT_EQ(256, bitmap.width()); EXPECT_EQ(256, bitmap.height()); } + +TEST_F(IconUtilTest, TestCreateSkBitmapFromIconResource48x48) { + HMODULE module = GetModuleHandle(NULL); + scoped_ptr<SkBitmap> bitmap( + IconUtil::CreateSkBitmapFromIconResource(module, IDR_MAINFRAME, 48)); + ASSERT_TRUE(bitmap.get()); + EXPECT_EQ(48, bitmap->width()); + EXPECT_EQ(48, bitmap->height()); +} + +TEST_F(IconUtilTest, TestCreateSkBitmapFromIconResource256x256) { + HMODULE module = GetModuleHandle(NULL); + scoped_ptr<SkBitmap> bitmap( + IconUtil::CreateSkBitmapFromIconResource(module, IDR_MAINFRAME, 256)); + ASSERT_TRUE(bitmap.get()); + EXPECT_EQ(256, bitmap->width()); + EXPECT_EQ(256, bitmap->height()); +} diff --git a/ui/test/ui_unittests.rc b/ui/test/ui_unittests.rc new file mode 100644 index 0000000..771ce9f --- /dev/null +++ b/ui/test/ui_unittests.rc @@ -0,0 +1,36 @@ +// Microsoft Visual C++ generated resource script. +// +#include "ui_unittests_resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "ui_unittests.ico" + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// diff --git a/ui/test/ui_unittests_resource.h b/ui/test/ui_unittests_resource.h new file mode 100644 index 0000000..079d4d8 --- /dev/null +++ b/ui/test/ui_unittests_resource.h @@ -0,0 +1,5 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#define IDR_MAINFRAME 101 diff --git a/ui/ui_unittests.gypi b/ui/ui_unittests.gypi index fdcbfc3..c9572f6 100644 --- a/ui/ui_unittests.gypi +++ b/ui/ui_unittests.gypi @@ -157,6 +157,7 @@ }], ['OS == "win"', { 'sources': [ + 'test/ui_unittests.rc', 'base/dragdrop/os_exchange_data_win_unittest.cc', 'base/win/hwnd_subclass_unittest.cc', 'gfx/font_fallback_win_unittest.cc', |