icon_util.h 11 KB

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