1 /*
2 * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "stdhdrs.h"
27 #include "windows.h"
28 #include <windowsx.h>
29 #include <zmouse.h>
30
31 #include "GraphicsPrimitiveMgr.h"
32
33 #include "awt.h"
34 #include "awt_BitmapUtil.h"
35
36 // Platform-dependent RECT_[EQ | SET | INC_HEIGHT] macros
37 #include "utility/rect.h"
38
CreateTransparencyMaskFromARGB(int width,int height,int * imageData)39 HBITMAP BitmapUtil::CreateTransparencyMaskFromARGB(int width, int height, int* imageData)
40 {
41 //Scan lines should be aligned to word boundary
42 if (!IS_SAFE_SIZE_ADD(width, 15)) return NULL;
43 char* buf = SAFE_SIZE_NEW_ARRAY2(char, (width + 15) / 16 * 2, height);
44 if (buf == NULL) return NULL;
45 int* srcPos = imageData;
46 char* bufPos = buf;
47 int tmp = 0;
48 int cbit = 0x80;
49 for (int i = 0; i < height; i++) {
50 for (int j = 0; j < width; j++) {
51 //cbit is shifted right for every pixel
52 //next byte is stored when cbit is zero
53 if ((cbit & 0xFF) == 0x00) {
54 *bufPos = tmp;
55 bufPos++;
56 tmp = 0;
57 cbit = 0x80;
58 }
59 unsigned char alpha = (*srcPos >> 0x18) & 0xFF;
60 if (alpha == 0x00) {
61 tmp |= cbit;
62 }
63 cbit >>= 1;
64 srcPos++;
65 }
66 //save last word at the end of scan line even if it's incomplete
67 *bufPos = tmp;
68 bufPos++;
69 tmp = 0;
70 cbit = 0x80;
71 //add word-padding byte if necessary
72 if (((bufPos - buf) & 0x01) == 0x01) {
73 *bufPos = 0;
74 bufPos++;
75 }
76 }
77 HBITMAP bmp = CreateBitmap(width, height, 1, 1, buf);
78 delete[] buf;
79
80 return bmp;
81 }
82
83 //BITMAPINFO extended with
84 typedef struct tagBITMAPINFOEX {
85 BITMAPINFOHEADER bmiHeader;
86 DWORD dwMasks[256];
87 } BITMAPINFOEX, *LPBITMAPINFOEX;
88
89 /*
90 * Creates 32-bit ARGB bitmap from specified RAW data.
91 * This function may not work on OS prior to Win95.
92 * See MSDN articles for CreateDIBitmap, BITMAPINFOHEADER,
93 * BITMAPV4HEADER, BITMAPV5HEADER for additional info.
94 */
CreateV4BitmapFromARGB(int width,int height,int * imageData)95 HBITMAP BitmapUtil::CreateV4BitmapFromARGB(int width, int height, int* imageData)
96 {
97 BITMAPINFOEX bitmapInfo;
98 HDC hDC;
99 char *bitmapData;
100 HBITMAP hTempBitmap;
101 HBITMAP hBitmap;
102
103 hDC = ::GetDC(::GetDesktopWindow());
104 if (!hDC) {
105 return NULL;
106 }
107
108 memset(&bitmapInfo, 0, sizeof(BITMAPINFOEX));
109 bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
110 bitmapInfo.bmiHeader.biWidth = width;
111 bitmapInfo.bmiHeader.biHeight = -height;
112 bitmapInfo.bmiHeader.biPlanes = 1;
113 bitmapInfo.bmiHeader.biBitCount = 32;
114 bitmapInfo.bmiHeader.biCompression = BI_RGB;
115
116 hTempBitmap = ::CreateDIBSection(hDC, (BITMAPINFO*)&(bitmapInfo),
117 DIB_RGB_COLORS,
118 (void**)&(bitmapData),
119 NULL, 0);
120
121 if (!bitmapData) {
122 ReleaseDC(::GetDesktopWindow(), hDC);
123 return NULL;
124 }
125
126 int* src = imageData;
127 char* dest = bitmapData;
128 for (int i = 0; i < height; i++ ) {
129 for (int j = 0; j < width; j++ ) {
130 unsigned char alpha = (*src >> 0x18) & 0xFF;
131 if (alpha == 0) {
132 dest[3] = dest[2] = dest[1] = dest[0] = 0;
133 } else {
134 dest[3] = alpha;
135 dest[2] = (*src >> 0x10) & 0xFF;
136 dest[1] = (*src >> 0x08) & 0xFF;
137 dest[0] = *src & 0xFF;
138 }
139 src++;
140 dest += 4;
141 }
142 }
143
144 hBitmap = CreateDIBitmap(hDC,
145 (BITMAPINFOHEADER*)&bitmapInfo,
146 CBM_INIT,
147 (void *)bitmapData,
148 (BITMAPINFO*)&bitmapInfo,
149 DIB_RGB_COLORS);
150
151 ::DeleteObject(hTempBitmap);
152 ::ReleaseDC(::GetDesktopWindow(), hDC);
153 ::GdiFlush();
154 return hBitmap;
155 }
156
157 /*
158 * Creates 32-bit premultiplied ARGB bitmap from specified ARGBPre data.
159 * This function may not work on OS prior to Win95.
160 * See MSDN articles for CreateDIBitmap, BITMAPINFOHEADER,
161 * BITMAPV4HEADER, BITMAPV5HEADER for additional info.
162 */
CreateBitmapFromARGBPre(int width,int height,int srcStride,int * imageData)163 HBITMAP BitmapUtil::CreateBitmapFromARGBPre(int width, int height,
164 int srcStride,
165 int* imageData)
166 {
167 BITMAPINFOHEADER bmi;
168 void *bitmapBits = NULL;
169
170 ZeroMemory(&bmi, sizeof(bmi));
171 bmi.biSize = sizeof(bmi);
172 bmi.biWidth = width;
173 bmi.biHeight = -height;
174 bmi.biPlanes = 1;
175 bmi.biBitCount = 32;
176 bmi.biCompression = BI_RGB;
177
178 HBITMAP hBitmap =
179 ::CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS,
180 &bitmapBits, NULL, 0);
181
182 if (!bitmapBits) {
183 return NULL;
184 }
185
186 int dstStride = width * 4;
187
188 if (srcStride == dstStride) {
189 memcpy(bitmapBits, (void*)imageData, srcStride * height);
190 } else if (height > 0) {
191 void *pSrcPixels = (void*)imageData;
192 void *pDstPixels = bitmapBits;
193 do {
194 memcpy(pDstPixels, pSrcPixels, dstStride);
195 pSrcPixels = PtrAddBytes(pSrcPixels, srcStride);
196 pDstPixels = PtrAddBytes(pDstPixels, dstStride);
197 } while (--height > 0);
198 }
199
200 return hBitmap;
201 }
202
203 extern "C" {
204
205 /**
206 * This method is called from the WGL pipeline when it needs to create a bitmap
207 * needed to update the layered window.
208 */
BitmapUtil_CreateBitmapFromARGBPre(int width,int height,int srcStride,int * imageData)209 HBITMAP BitmapUtil_CreateBitmapFromARGBPre(int width, int height,
210 int srcStride,
211 int* imageData)
212 {
213 return BitmapUtil::CreateBitmapFromARGBPre(width, height,
214 srcStride, imageData);
215
216 }
217
218 } /* extern "C" */
219
220
221 /**
222 * Transforms the given bitmap into an HRGN representing the transparency
223 * of the bitmap. The bitmap MUST BE 32bpp. Alpha value == 0 is considered
224 * transparent, alpha > 0 - opaque.
225 */
BitmapToRgn(HBITMAP hBitmap)226 HRGN BitmapUtil::BitmapToRgn(HBITMAP hBitmap)
227 {
228 HDC hdc = ::CreateCompatibleDC(NULL);
229 ::SelectObject(hdc, hBitmap);
230
231 BITMAPINFOEX bi;
232 ::ZeroMemory(&bi, sizeof(bi));
233
234 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
235
236 BOOL r = ::GetDIBits(hdc, hBitmap, 0, 0, NULL,
237 reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS);
238
239 if (!r || bi.bmiHeader.biBitCount != 32)
240 {
241 ::DeleteDC(hdc);
242 return NULL;
243 }
244
245 UINT width = bi.bmiHeader.biWidth;
246 UINT height = abs(bi.bmiHeader.biHeight);
247
248 BYTE * buf = (BYTE*)safe_Malloc(bi.bmiHeader.biSizeImage);
249 if (!buf) {
250 ::DeleteDC(hdc);
251 return NULL;
252 }
253 bi.bmiHeader.biHeight = -(INT)height;
254 ::GetDIBits(hdc, hBitmap, 0, height, buf,
255 reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS);
256
257 /* reserving memory for the worst case */
258 if (!IS_SAFE_SIZE_MUL(width / 2 + 1, height)) {
259 ::DeleteDC(hdc);
260 free(buf);
261 return NULL;
262 }
263 RGNDATA * pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc,
264 sizeof(RGNDATAHEADER),
265 sizeof(RECT), (width / 2 + 1) * height);
266 if (!pRgnData) {
267 ::DeleteDC(hdc);
268 free(buf);
269 return NULL;
270 }
271 RGNDATAHEADER * pRgnHdr = (RGNDATAHEADER *) pRgnData;
272 pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
273 pRgnHdr->iType = RDH_RECTANGLES;
274 pRgnHdr->nRgnSize = 0;
275 pRgnHdr->rcBound.top = 0;
276 pRgnHdr->rcBound.left = 0;
277 pRgnHdr->rcBound.bottom = height;
278 pRgnHdr->rcBound.right = width;
279
280 pRgnHdr->nCount = BitmapToYXBandedRectangles(32, width, height, buf,
281 (RECT_T *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER)));
282
283 HRGN rgn = ::ExtCreateRegion(NULL,
284 sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount,
285 pRgnData);
286
287 free(pRgnData);
288 ::DeleteDC(hdc);
289 free(buf);
290
291 return rgn;
292 }
293
294 /**
295 * Makes a copy of the given bitmap. Blends every pixel of the source
296 * with the given blendColor and alpha. If alpha == 0, the function
297 * simply makes a plain copy of the source without any blending.
298 */
BlendCopy(HBITMAP hSrcBitmap,COLORREF blendColor,BYTE alpha)299 HBITMAP BitmapUtil::BlendCopy(HBITMAP hSrcBitmap, COLORREF blendColor,
300 BYTE alpha)
301 {
302 HDC hdc = ::CreateCompatibleDC(NULL);
303 HBITMAP oldBitmap = (HBITMAP)::SelectObject(hdc, hSrcBitmap);
304
305 BITMAPINFOEX bi;
306 ::ZeroMemory(&bi, sizeof(bi));
307
308 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
309
310 BOOL r = ::GetDIBits(hdc, hSrcBitmap, 0, 0, NULL,
311 reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS);
312
313 if (!r || bi.bmiHeader.biBitCount != 32)
314 {
315 ::DeleteDC(hdc);
316 return NULL;
317 }
318
319 UINT width = bi.bmiHeader.biWidth;
320 UINT height = abs(bi.bmiHeader.biHeight);
321
322 BYTE * buf = (BYTE*)safe_Malloc(bi.bmiHeader.biSizeImage);
323 if (!buf) {
324 ::DeleteDC(hdc);
325 return NULL;
326 }
327 bi.bmiHeader.biHeight = -(INT)height;
328 ::GetDIBits(hdc, hSrcBitmap, 0, height, buf,
329 reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS);
330
331 UINT widthBytes = width * bi.bmiHeader.biBitCount / 8;
332 UINT alignedWidth = (((widthBytes - 1) / 4) + 1) * 4;
333 UINT i, j;
334
335 for (j = 0; j < height; j++) {
336 BYTE *pSrc = (BYTE *) buf + j * alignedWidth;
337 for (i = 0; i < width; i++, pSrc += 4) {
338 // Note: if the current alpha is zero, the other three color
339 // components may (theoretically) contain some uninitialized
340 // data. The developer does not expect to display them,
341 // hence we handle this situation differently.
342 if (pSrc[3] == 0) {
343 pSrc[0] = GetBValue(blendColor) * alpha / 255;
344 pSrc[1] = GetGValue(blendColor) * alpha / 255;
345 pSrc[2] = GetRValue(blendColor) * alpha / 255;
346 pSrc[3] = alpha;
347 } else {
348 pSrc[0] = (GetBValue(blendColor) * alpha / 255) +
349 (pSrc[0] * (255 - alpha) / 255);
350 pSrc[1] = (GetGValue(blendColor) * alpha / 255) +
351 (pSrc[1] * (255 - alpha) / 255);
352 pSrc[2] = (GetRValue(blendColor) * alpha / 255) +
353 (pSrc[2] * (255 - alpha) / 255);
354 pSrc[3] = (alpha * alpha / 255) +
355 (pSrc[3] * (255 - alpha) / 255);
356 }
357 }
358 }
359
360 HBITMAP hDstBitmap = ::CreateDIBitmap(hdc,
361 reinterpret_cast<BITMAPINFOHEADER*>(&bi),
362 CBM_INIT,
363 buf,
364 reinterpret_cast<BITMAPINFO*>(&bi),
365 DIB_RGB_COLORS
366 );
367
368 ::SelectObject(hdc, oldBitmap);
369 ::DeleteDC(hdc);
370 free(buf);
371
372 return hDstBitmap;
373 }
374
375 /**
376 * Creates a 32 bit ARGB bitmap. Returns the bitmap handle. The *bitmapBits
377 * contains the pointer to the bitmap data or NULL if an error occurred.
378 */
CreateARGBBitmap(int width,int height,void ** bitmapBitsPtr)379 HBITMAP BitmapUtil::CreateARGBBitmap(int width, int height, void ** bitmapBitsPtr)
380 {
381 BITMAPINFOHEADER bmi;
382
383 ::ZeroMemory(&bmi, sizeof(bmi));
384 bmi.biSize = sizeof(BITMAPINFOHEADER);
385 bmi.biWidth = width;
386 bmi.biHeight = -height;
387 bmi.biPlanes = 1;
388 bmi.biBitCount = 32;
389 bmi.biCompression = BI_RGB;
390
391 return ::CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS,
392 bitmapBitsPtr, NULL, 0);
393 }
394