summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/win/resource_util.cc18
-rw-r--r--base/win/resource_util.h15
-rw-r--r--chrome/browser/app_icon_win.cc31
-rw-r--r--chrome/browser/app_icon_win.h8
-rw-r--r--chrome/browser/profiles/profile_shortcut_manager_win.cc5
-rw-r--r--ui/gfx/icon_util.cc62
-rw-r--r--ui/gfx/icon_util.h34
-rw-r--r--ui/gfx/icon_util_unittest.cc19
-rw-r--r--ui/test/ui_unittests.rc36
-rw-r--r--ui/test/ui_unittests_resource.h5
-rw-r--r--ui/ui_unittests.gypi1
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',