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 3 // found in the LICENSE file. 4 5 #ifndef UI_GFX_ICON_UTIL_H_ 6 #define UI_GFX_ICON_UTIL_H_ 7 8 #include <windows.h> 9 #include <string> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "ui/gfx/gfx_export.h" 16 #include "ui/gfx/point.h" 17 #include "ui/gfx/size.h" 18 19 namespace base { 20 class FilePath; 21 } 22 23 namespace gfx { 24 class ImageFamily; 25 class Size; 26 } 27 class SkBitmap; 28 29 /////////////////////////////////////////////////////////////////////////////// 30 // 31 // The IconUtil class contains helper functions for manipulating Windows icons. 32 // The class interface contains methods for converting an HICON handle into an 33 // SkBitmap object and vice versa. The class can also create a .ico file given 34 // a PNG image contained in an SkBitmap object. The following code snippet 35 // shows an example usage of IconUtil::CreateHICONFromSkBitmap(): 36 // 37 // SkBitmap bitmap; 38 // 39 // // Fill |bitmap| with valid data 40 // bitmap.setConfig(...); 41 // bitmap.allocPixels(); 42 // 43 // ... 44 // 45 // // Convert the bitmap into a Windows HICON 46 // HICON icon = IconUtil::CreateHICONFromSkBitmap(bitmap); 47 // if (icon == NULL) { 48 // // Handle error 49 // ... 50 // } 51 // 52 // // Use the icon with a WM_SETICON message 53 // ::SendMessage(hwnd, WM_SETICON, static_cast<WPARAM>(ICON_BIG), 54 // reinterpret_cast<LPARAM>(icon)); 55 // 56 // // Destroy the icon when we are done 57 // ::DestroyIcon(icon); 58 // 59 /////////////////////////////////////////////////////////////////////////////// 60 class GFX_EXPORT IconUtil { 61 public: 62 // The size of the large icon entries in .ico files on Windows Vista+. 63 static const int kLargeIconSize = 256; 64 // The size of icons in the medium icons view on Windows Vista+. This is the 65 // maximum size Windows will display an icon that does not have a 256x256 66 // image, even at the large or extra large icons views. 67 static const int kMediumIconSize = 48; 68 69 // The dimensions for icon images in Windows icon files. All sizes are square; 70 // that is, the value 48 means a 48x48 pixel image. Sizes are listed in 71 // ascending order. 72 static const int kIconDimensions[]; 73 74 // The number of elements in kIconDimensions. 75 static const size_t kNumIconDimensions; 76 // The number of elements in kIconDimensions <= kMediumIconSize. 77 static const size_t kNumIconDimensionsUpToMediumSize; 78 79 // Given an SkBitmap object, the function converts the bitmap to a Windows 80 // icon and returns the corresponding HICON handle. If the function cannot 81 // convert the bitmap, NULL is returned. 82 // 83 // The client is responsible for destroying the icon when it is no longer 84 // needed by calling ::DestroyIcon(). 85 static HICON CreateHICONFromSkBitmap(const SkBitmap& bitmap); 86 87 // Given a valid HICON handle representing an icon, this function converts 88 // the icon into an SkBitmap object containing an ARGB bitmap using the 89 // dimensions specified in |s|. |s| must specify valid dimensions (both 90 // width() an height() must be greater than zero). If the function cannot 91 // convert the icon to a bitmap (most probably due to an invalid parameter), 92 // the return value is NULL. 93 // 94 // The client owns the returned bitmap object and is responsible for deleting 95 // it when it is no longer needed. 96 static SkBitmap* CreateSkBitmapFromHICON(HICON icon, const gfx::Size& s); 97 98 // Loads an icon resource as a SkBitmap for the specified |size| from a 99 // loaded .dll or .exe |module|. Supports loading smaller icon sizes as well 100 // as the Vista+ 256x256 PNG icon size. If the icon could not be loaded or 101 // found, returns a NULL scoped_ptr. 102 static scoped_ptr<SkBitmap> CreateSkBitmapFromIconResource(HMODULE module, 103 int resource_id, 104 int size); 105 106 // Given a valid HICON handle representing an icon, this function converts 107 // the icon into an SkBitmap object containing an ARGB bitmap using the 108 // dimensions of HICON. If the function cannot convert the icon to a bitmap 109 // (most probably due to an invalid parameter), the return value is NULL. 110 // 111 // The client owns the returned bitmap object and is responsible for deleting 112 // it when it is no longer needed. 113 static SkBitmap* CreateSkBitmapFromHICON(HICON icon); 114 115 // Creates Windows .ico file at |icon_path|. The icon file is created with 116 // multiple BMP representations at varying predefined dimensions (by resizing 117 // an appropriately sized image from |image_family|) because Windows uses 118 // different image sizes when loading icons, depending on where the icon is 119 // drawn (ALT+TAB window, desktop shortcut, Quick Launch, etc.). 120 // 121 // If |image_family| contains an image larger than 48x48, the resulting icon 122 // will contain all sizes up to 256x256. The 256x256 image will be stored in 123 // PNG format inside the .ico file. If not, the resulting icon will contain 124 // all sizes up to 48x48. 125 // 126 // The function returns true on success and false otherwise. Returns false if 127 // |image_family| is empty. 128 static bool CreateIconFileFromImageFamily( 129 const gfx::ImageFamily& image_family, 130 const base::FilePath& icon_path); 131 132 // Creates a cursor of the specified size from the DIB passed in. 133 // Returns the cursor on success or NULL on failure. 134 static HICON CreateCursorFromDIB(const gfx::Size& icon_size, 135 const gfx::Point& hotspot, 136 const void* dib_bits, 137 size_t dib_size); 138 139 private: 140 // The icon format is published in the MSDN but there is no definition of 141 // the icon file structures in any of the Windows header files so we need to 142 // define these structure within the class. We must make sure we use 2 byte 143 // packing so that the structures are layed out properly within the file. 144 // See: http://msdn.microsoft.com/en-us/library/ms997538.aspx 145 #pragma pack(push) 146 #pragma pack(2) 147 148 // ICONDIRENTRY contains meta data for an individual icon image within a 149 // .ico file. 150 struct ICONDIRENTRY { 151 BYTE bWidth; 152 BYTE bHeight; 153 BYTE bColorCount; 154 BYTE bReserved; 155 WORD wPlanes; 156 WORD wBitCount; 157 DWORD dwBytesInRes; 158 DWORD dwImageOffset; 159 }; 160 161 // ICONDIR Contains information about all the icon images contained within a 162 // single .ico file. 163 struct ICONDIR { 164 WORD idReserved; 165 WORD idType; 166 WORD idCount; 167 ICONDIRENTRY idEntries[1]; 168 }; 169 170 // GRPICONDIRENTRY contains meta data for an individual icon image within a 171 // RT_GROUP_ICON resource in an .exe or .dll. 172 struct GRPICONDIRENTRY { 173 BYTE bWidth; 174 BYTE bHeight; 175 BYTE bColorCount; 176 BYTE bReserved; 177 WORD wPlanes; 178 WORD wBitCount; 179 DWORD dwBytesInRes; 180 WORD nID; 181 }; 182 183 // GRPICONDIR Contains information about all the icon images contained within 184 // a RT_GROUP_ICON resource in an .exe or .dll. 185 struct GRPICONDIR { 186 WORD idReserved; 187 WORD idType; 188 WORD idCount; 189 GRPICONDIRENTRY idEntries[1]; 190 }; 191 192 // Contains the actual icon image. 193 struct ICONIMAGE { 194 BITMAPINFOHEADER icHeader; 195 RGBQUAD icColors[1]; 196 BYTE icXOR[1]; 197 BYTE icAND[1]; 198 }; 199 #pragma pack(pop) 200 201 friend class IconUtilTest; 202 203 // Used for indicating that the .ico contains an icon (rather than a cursor) 204 // image. This value is set in the |idType| field of the ICONDIR structure. 205 static const int kResourceTypeIcon = 1; 206 207 // Returns true if any pixel in the given pixels buffer has an non-zero alpha. 208 static bool PixelsHaveAlpha(const uint32* pixels, size_t num_pixels); 209 210 // A helper function that initializes a BITMAPV5HEADER structure with a set 211 // of values. 212 static void InitializeBitmapHeader(BITMAPV5HEADER* header, int width, 213 int height); 214 215 // Given a single SkBitmap object and pointers to the corresponding icon 216 // structures within the icon data buffer, this function sets the image 217 // information (dimensions, color depth, etc.) in the icon structures and 218 // also copies the underlying icon image into the appropriate location. 219 // The width and height of |bitmap| must be < 256. 220 // (Note that the 256x256 icon is treated specially, as a PNG, and should not 221 // use this method.) 222 // 223 // The function will set the data pointed to by |image_byte_count| with the 224 // number of image bytes written to the buffer. Note that the number of bytes 225 // includes only the image data written into the memory pointed to by 226 // |icon_image|. 227 static void SetSingleIconImageInformation(const SkBitmap& bitmap, 228 size_t index, 229 ICONDIR* icon_dir, 230 ICONIMAGE* icon_image, 231 size_t image_offset, 232 size_t* image_byte_count); 233 234 // Copies the bits of an SkBitmap object into a buffer holding the bits of 235 // the corresponding image for an icon within the .ico file. 236 static void CopySkBitmapBitsIntoIconBuffer(const SkBitmap& bitmap, 237 unsigned char* buffer, 238 size_t buffer_size); 239 240 // Given a set of bitmaps with varying dimensions, this function computes 241 // the amount of memory needed in order to store the bitmaps as image icons 242 // in a .ico file. 243 static size_t ComputeIconFileBufferSize(const std::vector<SkBitmap>& set); 244 245 // A helper function for computing various size components of a given bitmap. 246 // The different sizes can be used within the various .ico file structures. 247 // 248 // |xor_mask_size| - the size, in bytes, of the XOR mask in the ICONIMAGE 249 // structure. 250 // |and_mask_size| - the size, in bytes, of the AND mask in the ICONIMAGE 251 // structure. 252 // |bytes_in_resource| - the total number of bytes set in the ICONIMAGE 253 // structure. This value is equal to the sum of the 254 // bytes in the AND mask and the XOR mask plus the size 255 // of the BITMAPINFOHEADER structure. Note that since 256 // only 32bpp are handled by the IconUtil class, the 257 // icColors field in the ICONIMAGE structure is ignored 258 // and is not accounted for when computing the 259 // different size components. 260 static void ComputeBitmapSizeComponents(const SkBitmap& bitmap, 261 size_t* xor_mask_size, 262 size_t* bytes_in_resource); 263 264 // A helper function of CreateSkBitmapFromHICON. 265 static SkBitmap CreateSkBitmapFromHICONHelper(HICON icon, 266 const gfx::Size& s); 267 268 // Prevent clients from instantiating objects of that class by declaring the 269 // ctor/dtor as private. 270 DISALLOW_IMPLICIT_CONSTRUCTORS(IconUtil); 271 }; 272 273 #endif // UI_GFX_ICON_UTIL_H_ 274