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