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.
5 #include "ui/gfx/gdi_util.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
12 void CreateBitmapHeaderWithColorDepth(LONG width
,
15 BITMAPINFOHEADER
* hdr
) {
16 // These values are shared with gfx::PlatformDevice
17 hdr
->biSize
= sizeof(BITMAPINFOHEADER
);
19 hdr
->biHeight
= -height
; // minus means top-down bitmap
21 hdr
->biBitCount
= color_depth
;
22 hdr
->biCompression
= BI_RGB
; // no compression
24 hdr
->biXPelsPerMeter
= 1;
25 hdr
->biYPelsPerMeter
= 1;
27 hdr
->biClrImportant
= 0;
34 void CreateBitmapHeader(int width
, int height
, BITMAPINFOHEADER
* hdr
) {
35 CreateBitmapHeaderWithColorDepth(width
, height
, 32, hdr
);
38 void CreateBitmapV4Header(int width
, int height
, BITMAPV4HEADER
* hdr
) {
39 // Because bmp v4 header is just an extension, we just create a v3 header and
40 // copy the bits over to the v4 header.
41 BITMAPINFOHEADER header_v3
;
42 CreateBitmapHeader(width
, height
, &header_v3
);
43 memset(hdr
, 0, sizeof(BITMAPV4HEADER
));
44 memcpy(hdr
, &header_v3
, sizeof(BITMAPINFOHEADER
));
46 // Correct the size of the header and fill in the mask values.
47 hdr
->bV4Size
= sizeof(BITMAPV4HEADER
);
48 hdr
->bV4RedMask
= 0x00ff0000;
49 hdr
->bV4GreenMask
= 0x0000ff00;
50 hdr
->bV4BlueMask
= 0x000000ff;
51 hdr
->bV4AlphaMask
= 0xff000000;
54 // Creates a monochrome bitmap header.
55 void CreateMonochromeBitmapHeader(int width
,
57 BITMAPINFOHEADER
* hdr
) {
58 CreateBitmapHeaderWithColorDepth(width
, height
, 1, hdr
);
61 void SubtractRectanglesFromRegion(HRGN hrgn
,
62 const std::vector
<gfx::Rect
>& cutouts
) {
64 HRGN cutout
= ::CreateRectRgn(0, 0, 0, 0);
65 for (size_t i
= 0; i
< cutouts
.size(); i
++) {
71 ::CombineRgn(hrgn
, hrgn
, cutout
, RGN_DIFF
);
73 ::DeleteObject(cutout
);
77 HRGN
ConvertPathToHRGN(const gfx::Path
& path
) {
78 int point_count
= path
.getPoints(NULL
, 0);
79 scoped_ptr
<SkPoint
[]> points(new SkPoint
[point_count
]);
80 path
.getPoints(points
.get(), point_count
);
81 scoped_ptr
<POINT
[]> windows_points(new POINT
[point_count
]);
82 for (int i
= 0; i
< point_count
; ++i
) {
83 windows_points
[i
].x
= SkScalarRoundToInt(points
[i
].fX
);
84 windows_points
[i
].y
= SkScalarRoundToInt(points
[i
].fY
);
87 return ::CreatePolygonRgn(windows_points
.get(), point_count
, ALTERNATE
);
91 float CalculatePageScale(HDC dc
, int page_width
, int page_height
) {
92 int dc_width
= GetDeviceCaps(dc
, HORZRES
);
93 int dc_height
= GetDeviceCaps(dc
, VERTRES
);
95 // If page fits DC - no scaling needed.
96 if (dc_width
>= page_width
&& dc_height
>= page_height
)
100 static_cast<float>(dc_width
) / static_cast<float>(page_width
);
102 static_cast<float>(dc_height
) / static_cast<float>(page_height
);
103 return std::min(x_factor
, y_factor
);
106 // Apply scaling to the DC.
107 bool ScaleDC(HDC dc
, float scale_factor
) {
108 SetGraphicsMode(dc
, GM_ADVANCED
);
110 xform
.eM11
= xform
.eM22
= scale_factor
;
111 return !!ModifyWorldTransform(dc
, &xform
, MWT_LEFTMULTIPLY
);
114 void StretchDIBits(HDC hdc
, int dest_x
, int dest_y
, int dest_w
, int dest_h
,
115 int src_x
, int src_y
, int src_w
, int src_h
, void* pixels
,
116 const BITMAPINFO
* bitmap_info
) {
117 // When blitting a rectangle that touches the bottom, left corner of the
118 // bitmap, StretchDIBits looks at it top-down! For more details, see
119 // http://wiki.allegro.cc/index.php?title=StretchDIBits.
121 int bitmap_h
= -bitmap_info
->bmiHeader
.biHeight
;
122 int bottom_up_src_y
= bitmap_h
- src_y
- src_h
;
123 if (bottom_up_src_y
== 0 && src_x
== 0 && src_h
!= bitmap_h
) {
124 rv
= ::StretchDIBits(hdc
,
125 dest_x
, dest_h
+ dest_y
- 1, dest_w
, -dest_h
,
126 src_x
, bitmap_h
- src_y
+ 1, src_w
, -src_h
,
127 pixels
, bitmap_info
, DIB_RGB_COLORS
, SRCCOPY
);
129 rv
= ::StretchDIBits(hdc
,
130 dest_x
, dest_y
, dest_w
, dest_h
,
131 src_x
, bottom_up_src_y
, src_w
, src_h
,
132 pixels
, bitmap_info
, DIB_RGB_COLORS
, SRCCOPY
);
134 DCHECK(rv
!= GDI_ERROR
);