// 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. #ifndef UI_GFX_ICON_UTIL_H_ #define UI_GFX_ICON_UTIL_H_ #include <windows.h> #include <string> #include <vector> #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "ui/gfx/gfx_export.h" #include "ui/gfx/point.h" #include "ui/gfx/size.h" namespace base { class FilePath; } namespace gfx { class ImageFamily; class Size; } class SkBitmap; /////////////////////////////////////////////////////////////////////////////// // // The IconUtil class contains helper functions for manipulating Windows icons. // The class interface contains methods for converting an HICON handle into an // SkBitmap object and vice versa. The class can also create a .ico file given // a PNG image contained in an SkBitmap object. The following code snippet // shows an example usage of IconUtil::CreateHICONFromSkBitmap(): // // SkBitmap bitmap; // // // Fill |bitmap| with valid data // bitmap.setConfig(...); // bitmap.allocPixels(); // // ... // // // Convert the bitmap into a Windows HICON // HICON icon = IconUtil::CreateHICONFromSkBitmap(bitmap); // if (icon == NULL) { // // Handle error // ... // } // // // Use the icon with a WM_SETICON message // ::SendMessage(hwnd, WM_SETICON, static_cast<WPARAM>(ICON_BIG), // reinterpret_cast<LPARAM>(icon)); // // // Destroy the icon when we are done // ::DestroyIcon(icon); // /////////////////////////////////////////////////////////////////////////////// class GFX_EXPORT IconUtil { public: // The size of the large icon entries in .ico files on Windows Vista+. static const int kLargeIconSize = 256; // The size of icons in the medium icons view on Windows Vista+. This is the // maximum size Windows will display an icon that does not have a 256x256 // image, even at the large or extra large icons views. static const int kMediumIconSize = 48; // The dimensions for icon images in Windows icon files. All sizes are square; // that is, the value 48 means a 48x48 pixel image. Sizes are listed in // ascending order. static const int kIconDimensions[]; // The number of elements in kIconDimensions. static const size_t kNumIconDimensions; // The number of elements in kIconDimensions <= kMediumIconSize. static const size_t kNumIconDimensionsUpToMediumSize; // Given an SkBitmap object, the function converts the bitmap to a Windows // icon and returns the corresponding HICON handle. If the function cannot // convert the bitmap, NULL is returned. // // The client is responsible for destroying the icon when it is no longer // needed by calling ::DestroyIcon(). static HICON CreateHICONFromSkBitmap(const SkBitmap& bitmap); // Given a valid HICON handle representing an icon, this function converts // the icon into an SkBitmap object containing an ARGB bitmap using the // dimensions specified in |s|. |s| must specify valid dimensions (both // width() an height() must be greater than zero). If the function cannot // convert the icon to a bitmap (most probably due to an invalid parameter), // the return value is NULL. // // The client owns the returned bitmap object and is responsible for deleting // 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 // (most probably due to an invalid parameter), the return value is NULL. // // The client owns the returned bitmap object and is responsible for deleting // it when it is no longer needed. static SkBitmap* CreateSkBitmapFromHICON(HICON icon); // Creates Windows .ico file at |icon_path|. The icon file is created with // multiple BMP representations at varying predefined dimensions (by resizing // an appropriately sized image from |image_family|) because Windows uses // different image sizes when loading icons, depending on where the icon is // drawn (ALT+TAB window, desktop shortcut, Quick Launch, etc.). // // If |image_family| contains an image larger than 48x48, the resulting icon // will contain all sizes up to 256x256. The 256x256 image will be stored in // PNG format inside the .ico file. If not, the resulting icon will contain // all sizes up to 48x48. // // The function returns true on success and false otherwise. Returns false if // |image_family| is empty. static bool CreateIconFileFromImageFamily( const gfx::ImageFamily& image_family, const base::FilePath& icon_path); // Creates a cursor of the specified size from the DIB passed in. // Returns the cursor on success or NULL on failure. static HICON CreateCursorFromDIB(const gfx::Size& icon_size, const gfx::Point& hotspot, const void* dib_bits, size_t dib_size); private: // The icon format is published in the MSDN but there is no definition of // 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) // ICONDIRENTRY contains meta data for an individual icon image within a // .ico file. struct ICONDIRENTRY { BYTE bWidth; BYTE bHeight; BYTE bColorCount; BYTE bReserved; WORD wPlanes; WORD wBitCount; DWORD dwBytesInRes; DWORD dwImageOffset; }; // ICONDIR Contains information about all the icon images contained within a // single .ico file. struct ICONDIR { WORD idReserved; WORD idType; WORD idCount; 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; RGBQUAD icColors[1]; BYTE icXOR[1]; BYTE icAND[1]; }; #pragma pack(pop) friend class IconUtilTest; // Used for indicating that the .ico contains an icon (rather than a cursor) // image. This value is set in the |idType| field of the ICONDIR structure. static const int kResourceTypeIcon = 1; // Returns true if any pixel in the given pixels buffer has an non-zero alpha. static bool PixelsHaveAlpha(const uint32* pixels, size_t num_pixels); // A helper function that initializes a BITMAPV5HEADER structure with a set // of values. static void InitializeBitmapHeader(BITMAPV5HEADER* header, int width, int height); // Given a single SkBitmap object and pointers to the corresponding icon // structures within the icon data buffer, this function sets the image // information (dimensions, color depth, etc.) in the icon structures and // also copies the underlying icon image into the appropriate location. // The width and height of |bitmap| must be < 256. // (Note that the 256x256 icon is treated specially, as a PNG, and should not // use this method.) // // The function will set the data pointed to by |image_byte_count| with the // number of image bytes written to the buffer. Note that the number of bytes // includes only the image data written into the memory pointed to by // |icon_image|. static void SetSingleIconImageInformation(const SkBitmap& bitmap, size_t index, ICONDIR* icon_dir, ICONIMAGE* icon_image, size_t image_offset, size_t* image_byte_count); // Copies the bits of an SkBitmap object into a buffer holding the bits of // the corresponding image for an icon within the .ico file. static void CopySkBitmapBitsIntoIconBuffer(const SkBitmap& bitmap, unsigned char* buffer, size_t buffer_size); // Given a set of bitmaps with varying dimensions, this function computes // the amount of memory needed in order to store the bitmaps as image icons // in a .ico file. static size_t ComputeIconFileBufferSize(const std::vector<SkBitmap>& set); // A helper function for computing various size components of a given bitmap. // The different sizes can be used within the various .ico file structures. // // |xor_mask_size| - the size, in bytes, of the XOR mask in the ICONIMAGE // structure. // |and_mask_size| - the size, in bytes, of the AND mask in the ICONIMAGE // structure. // |bytes_in_resource| - the total number of bytes set in the ICONIMAGE // structure. This value is equal to the sum of the // bytes in the AND mask and the XOR mask plus the size // of the BITMAPINFOHEADER structure. Note that since // only 32bpp are handled by the IconUtil class, the // icColors field in the ICONIMAGE structure is ignored // and is not accounted for when computing the // different size components. static void ComputeBitmapSizeComponents(const SkBitmap& bitmap, size_t* xor_mask_size, size_t* bytes_in_resource); // A helper function of CreateSkBitmapFromHICON. static SkBitmap CreateSkBitmapFromHICONHelper(HICON icon, const gfx::Size& s); // Prevent clients from instantiating objects of that class by declaring the // ctor/dtor as private. DISALLOW_IMPLICIT_CONSTRUCTORS(IconUtil); }; #endif // UI_GFX_ICON_UTIL_H_