Home | History | Annotate | Download | only in gfx
      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