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 CreateBitmapHeader(int width
, int height
, BITMAPINFOHEADER
* hdr
) {
13 CreateBitmapHeaderWithColorDepth(width
, height
, 32, hdr
);
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
);
21 hdr
->biHeight
= -height
; // minus means top-down bitmap
23 hdr
->biBitCount
= color_depth
;
24 hdr
->biCompression
= BI_RGB
; // no compression
26 hdr
->biXPelsPerMeter
= 1;
27 hdr
->biYPelsPerMeter
= 1;
29 hdr
->biClrImportant
= 0;
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
));
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;
48 // Creates a monochrome bitmap header.
49 void CreateMonochromeBitmapHeader(int width
,
51 BITMAPINFOHEADER
* hdr
) {
52 hdr
->biSize
= sizeof(BITMAPINFOHEADER
);
54 hdr
->biHeight
= -height
;
57 hdr
->biCompression
= BI_RGB
;
59 hdr
->biXPelsPerMeter
= 1;
60 hdr
->biYPelsPerMeter
= 1;
62 hdr
->biClrImportant
= 0;
65 void SubtractRectanglesFromRegion(HRGN hrgn
,
66 const std::vector
<gfx::Rect
>& cutouts
) {
68 HRGN cutout
= ::CreateRectRgn(0, 0, 0, 0);
69 for (size_t i
= 0; i
< cutouts
.size(); i
++) {
75 ::CombineRgn(hrgn
, hrgn
, cutout
, RGN_DIFF
);
77 ::DeleteObject(cutout
);
81 HRGN
ConvertPathToHRGN(const gfx::Path
& path
) {
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
);
92 return ::CreatePolygonRgn(windows_points
.get(), point_count
, ALTERNATE
);
94 return path
.CreateNativeRegion();
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
);
103 // If page fits DC - no scaling needed.
104 if (dc_width
>= page_width
&& dc_height
>= page_height
)
108 static_cast<double>(dc_width
) / static_cast<double>(page_width
);
110 static_cast<double>(dc_height
) / static_cast<double>(page_height
);
111 return std::min(x_factor
, y_factor
);
114 // Apply scaling to the DC.
115 bool ScaleDC(HDC dc
, double scale_factor
) {
116 SetGraphicsMode(dc
, GM_ADVANCED
);
118 xform
.eM11
= xform
.eM22
= scale_factor
;
119 return !!ModifyWorldTransform(dc
, &xform
, MWT_LEFTMULTIPLY
);
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.
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
);
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
);
142 DCHECK(rv
!= GDI_ERROR
);