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 #include "ui/gfx/gdi_util.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/memory/scoped_ptr.h"
      9 
     10 namespace gfx {
     11 
     12 void CreateBitmapHeader(int width, int height, BITMAPINFOHEADER* hdr) {
     13   CreateBitmapHeaderWithColorDepth(width, height, 32, hdr);
     14 }
     15 
     16 void CreateBitmapHeaderWithColorDepth(int width, int height, int color_depth,
     17                                       BITMAPINFOHEADER* hdr) {
     18   // These values are shared with gfx::PlatformDevice
     19   hdr->biSize = sizeof(BITMAPINFOHEADER);
     20   hdr->biWidth = width;
     21   hdr->biHeight = -height;  // minus means top-down bitmap
     22   hdr->biPlanes = 1;
     23   hdr->biBitCount = color_depth;
     24   hdr->biCompression = BI_RGB;  // no compression
     25   hdr->biSizeImage = 0;
     26   hdr->biXPelsPerMeter = 1;
     27   hdr->biYPelsPerMeter = 1;
     28   hdr->biClrUsed = 0;
     29   hdr->biClrImportant = 0;
     30 }
     31 
     32 void CreateBitmapV4Header(int width, int height, BITMAPV4HEADER* hdr) {
     33   // Because bmp v4 header is just an extension, we just create a v3 header and
     34   // copy the bits over to the v4 header.
     35   BITMAPINFOHEADER header_v3;
     36   CreateBitmapHeader(width, height, &header_v3);
     37   memset(hdr, 0, sizeof(BITMAPV4HEADER));
     38   memcpy(hdr, &header_v3, sizeof(BITMAPINFOHEADER));
     39 
     40   // Correct the size of the header and fill in the mask values.
     41   hdr->bV4Size = sizeof(BITMAPV4HEADER);
     42   hdr->bV4RedMask   = 0x00ff0000;
     43   hdr->bV4GreenMask = 0x0000ff00;
     44   hdr->bV4BlueMask  = 0x000000ff;
     45   hdr->bV4AlphaMask = 0xff000000;
     46 }
     47 
     48 // Creates a monochrome bitmap header.
     49 void CreateMonochromeBitmapHeader(int width,
     50                                   int height,
     51                                   BITMAPINFOHEADER* hdr) {
     52   hdr->biSize = sizeof(BITMAPINFOHEADER);
     53   hdr->biWidth = width;
     54   hdr->biHeight = -height;
     55   hdr->biPlanes = 1;
     56   hdr->biBitCount = 1;
     57   hdr->biCompression = BI_RGB;
     58   hdr->biSizeImage = 0;
     59   hdr->biXPelsPerMeter = 1;
     60   hdr->biYPelsPerMeter = 1;
     61   hdr->biClrUsed = 0;
     62   hdr->biClrImportant = 0;
     63 }
     64 
     65 void SubtractRectanglesFromRegion(HRGN hrgn,
     66                                   const std::vector<gfx::Rect>& cutouts) {
     67   if (cutouts.size()) {
     68     HRGN cutout = ::CreateRectRgn(0, 0, 0, 0);
     69     for (size_t i = 0; i < cutouts.size(); i++) {
     70       ::SetRectRgn(cutout,
     71                    cutouts[i].x(),
     72                    cutouts[i].y(),
     73                    cutouts[i].right(),
     74                    cutouts[i].bottom());
     75       ::CombineRgn(hrgn, hrgn, cutout, RGN_DIFF);
     76     }
     77     ::DeleteObject(cutout);
     78   }
     79 }
     80 
     81 HRGN ConvertPathToHRGN(const gfx::Path& path) {
     82 #if defined(USE_AURA)
     83   int point_count = path.getPoints(NULL, 0);
     84   scoped_ptr<SkPoint[]> points(new SkPoint[point_count]);
     85   path.getPoints(points.get(), point_count);
     86   scoped_ptr<POINT[]> windows_points(new POINT[point_count]);
     87   for (int i = 0; i < point_count; ++i) {
     88     windows_points[i].x = SkScalarRoundToInt(points[i].fX);
     89     windows_points[i].y = SkScalarRoundToInt(points[i].fY);
     90   }
     91 
     92   return ::CreatePolygonRgn(windows_points.get(), point_count, ALTERNATE);
     93 #elif defined(OS_WIN)
     94   return path.CreateNativeRegion();
     95 #endif
     96 }
     97 
     98 
     99 double CalculatePageScale(HDC dc, int page_width, int page_height) {
    100   int dc_width = GetDeviceCaps(dc, HORZRES);
    101   int dc_height = GetDeviceCaps(dc, VERTRES);
    102 
    103   // If page fits DC - no scaling needed.
    104   if (dc_width >= page_width && dc_height >= page_height)
    105     return 1.0;
    106 
    107   double x_factor =
    108       static_cast<double>(dc_width) / static_cast<double>(page_width);
    109   double y_factor =
    110       static_cast<double>(dc_height) / static_cast<double>(page_height);
    111   return std::min(x_factor, y_factor);
    112 }
    113 
    114 // Apply scaling to the DC.
    115 bool ScaleDC(HDC dc, double scale_factor) {
    116   SetGraphicsMode(dc, GM_ADVANCED);
    117   XFORM xform = {0};
    118   xform.eM11 = xform.eM22 = scale_factor;
    119   return !!ModifyWorldTransform(dc, &xform, MWT_LEFTMULTIPLY);
    120 }
    121 
    122 void StretchDIBits(HDC hdc, int dest_x, int dest_y, int dest_w, int dest_h,
    123                    int src_x, int src_y, int src_w, int src_h, void* pixels,
    124                    const BITMAPINFO* bitmap_info) {
    125   // When blitting a rectangle that touches the bottom, left corner of the
    126   // bitmap, StretchDIBits looks at it top-down!  For more details, see
    127   // http://wiki.allegro.cc/index.php?title=StretchDIBits.
    128   int rv;
    129   int bitmap_h = -bitmap_info->bmiHeader.biHeight;
    130   int bottom_up_src_y = bitmap_h - src_y - src_h;
    131   if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap_h) {
    132     rv = ::StretchDIBits(hdc,
    133                          dest_x, dest_h + dest_y - 1, dest_w, -dest_h,
    134                          src_x, bitmap_h - src_y + 1, src_w, -src_h,
    135                          pixels, bitmap_info, DIB_RGB_COLORS, SRCCOPY);
    136   } else {
    137     rv = ::StretchDIBits(hdc,
    138                          dest_x, dest_y, dest_w, dest_h,
    139                          src_x, bottom_up_src_y, src_w, src_h,
    140                          pixels, bitmap_info, DIB_RGB_COLORS, SRCCOPY);
    141   }
    142   DCHECK(rv != GDI_ERROR);
    143 }
    144 
    145 }  // namespace gfx
    146