| // Copyright 2012 The Chromium Authors |
| // 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 <stddef.h> |
| #include <stdint.h> |
| #include <memory> |
| #include <vector> |
| |
| #include "base/win/scoped_gdi_object.h" |
| #include "ui/gfx/geometry/point.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/gfx_export.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 |
| // base::win::ScopedHICON icon(IconUtil::CreateHICONFromSkBitmap(bitmap)); |
| // if (!icon.is_valid()) { |
| // // Handle error |
| // ... |
| // } |
| // |
| // // Use the icon with a WM_SETICON message |
| // ::SendMessage(hwnd, WM_SETICON, static_cast<WPARAM>(ICON_BIG), |
| // reinterpret_cast<LPARAM>(icon.get())); |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| class GFX_EXPORT IconUtil { |
| public: |
| // ATOMIC_WRITE ensures that a partially written icon won't be created even if |
| // Chrome crashes part way through, but ATOMIC_WRITE is more expensive than |
| // NORMAL_WRITE. See CreateIconFileFromImageFamily. ATOMIC_WRITE is the |
| // default for historical reasons. |
| enum WriteType { ATOMIC_WRITE, NORMAL_WRITE }; |
| // The size of the large icon entries in .ico files on Windows Vista+. |
| enum { 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. |
| enum { 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; |
| |
| // Prevent clients from instantiating objects of that class. |
| IconUtil() = delete; |
| IconUtil(const IconUtil&) = delete; |
| IconUtil& operator=(const IconUtil&) = delete; |
| |
| // Given an SkBitmap object, the function converts the bitmap to a Windows |
| // icon and returns the corresponding HICON handle if conversion succeeds. |
| static base::win::ScopedHICON 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 returned SkBitmap's isNull() method will return true. |
| 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 std::unique_ptr<gfx::ImageFamily> CreateImageFamilyFromIconResource( |
| HMODULE module, |
| int resource_id); |
| |
| // 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 returned SkBitmap's |
| // isNull() method will return true. |
| 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, |
| WriteType write_type = ATOMIC_WRITE); |
| |
| // Creates a cursor of the specified size from the SkBitmap passed in. |
| // Returns the cursor on success or NULL on failure. |
| static base::win::ScopedHICON CreateCursorFromSkBitmap( |
| const SkBitmap& bitmap, |
| const gfx::Point& hotspot); |
| |
| // Given a valid HICON handle representing an icon, this function retrieves |
| // the hot spot of the icon. |
| static gfx::Point GetHotSpotFromHICON(HICON icon); |
| |
| 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 laid 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; |
| |
| // Returns true if any pixel in the given pixels buffer has an non-zero alpha. |
| static bool PixelsHaveAlpha(const uint32_t* 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, |
| DWORD 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, |
| DWORD* bytes_in_resource); |
| |
| // A helper function of CreateSkBitmapFromHICON. |
| static SkBitmap CreateSkBitmapFromHICONHelper(HICON icon, |
| const gfx::Size& s); |
| }; |
| |
| #endif // UI_GFX_ICON_UTIL_H_ |