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 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 */ 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 */ 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 */ 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 */ 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 bi.bmiHeader.biHeight = -(INT)height; 250 ::GetDIBits(hdc, hBitmap, 0, height, buf, 251 reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS); 252 253 /* reserving memory for the worst case */ 254 if (!IS_SAFE_SIZE_MUL(width / 2 + 1, height)) { 255 throw std::bad_alloc(); 256 } 257 RGNDATA * pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc, 258 sizeof(RGNDATAHEADER), 259 sizeof(RECT), (width / 2 + 1) * height); 260 RGNDATAHEADER * pRgnHdr = (RGNDATAHEADER *) pRgnData; 261 pRgnHdr->dwSize = sizeof(RGNDATAHEADER); 262 pRgnHdr->iType = RDH_RECTANGLES; 263 pRgnHdr->nRgnSize = 0; 264 pRgnHdr->rcBound.top = 0; 265 pRgnHdr->rcBound.left = 0; 266 pRgnHdr->rcBound.bottom = height; 267 pRgnHdr->rcBound.right = width; 268 269 pRgnHdr->nCount = BitmapToYXBandedRectangles(32, width, height, buf, 270 (RECT_T *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER))); 271 272 HRGN rgn = ::ExtCreateRegion(NULL, 273 sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, 274 pRgnData); 275 276 free(pRgnData); 277 ::DeleteDC(hdc); 278 free(buf); 279 280 return rgn; 281 } 282 283 /** 284 * Makes a copy of the given bitmap. Blends every pixel of the source 285 * with the given blendColor and alpha. If alpha == 0, the function 286 * simply makes a plain copy of the source without any blending. 287 */ 288 HBITMAP BitmapUtil::BlendCopy(HBITMAP hSrcBitmap, COLORREF blendColor, 289 BYTE alpha) 290 { 291 HDC hdc = ::CreateCompatibleDC(NULL); 292 HBITMAP oldBitmap = (HBITMAP)::SelectObject(hdc, hSrcBitmap); 293 294 BITMAPINFOEX bi; 295 ::ZeroMemory(&bi, sizeof(bi)); 296 297 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 298 299 BOOL r = ::GetDIBits(hdc, hSrcBitmap, 0, 0, NULL, 300 reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS); 301 302 if (!r || bi.bmiHeader.biBitCount != 32) 303 { 304 ::DeleteDC(hdc); 305 return NULL; 306 } 307 308 UINT width = bi.bmiHeader.biWidth; 309 UINT height = abs(bi.bmiHeader.biHeight); 310 311 BYTE * buf = (BYTE*)safe_Malloc(bi.bmiHeader.biSizeImage); 312 bi.bmiHeader.biHeight = -(INT)height; 313 ::GetDIBits(hdc, hSrcBitmap, 0, height, buf, 314 reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS); 315 316 UINT widthBytes = width * bi.bmiHeader.biBitCount / 8; 317 UINT alignedWidth = (((widthBytes - 1) / 4) + 1) * 4; 318 UINT i, j; 319 320 for (j = 0; j < height; j++) { 321 BYTE *pSrc = (BYTE *) buf + j * alignedWidth; 322 for (i = 0; i < width; i++, pSrc += 4) { 323 // Note: if the current alpha is zero, the other three color 324 // components may (theoretically) contain some uninitialized 325 // data. The developer does not expect to display them, 326 // hence we handle this situation differently. 327 if (pSrc[3] == 0) { 328 pSrc[0] = GetBValue(blendColor) * alpha / 255; 329 pSrc[1] = GetGValue(blendColor) * alpha / 255; 330 pSrc[2] = GetRValue(blendColor) * alpha / 255; 331 pSrc[3] = alpha; 332 } else { 333 pSrc[0] = (GetBValue(blendColor) * alpha / 255) + 334 (pSrc[0] * (255 - alpha) / 255); 335 pSrc[1] = (GetGValue(blendColor) * alpha / 255) + 336 (pSrc[1] * (255 - alpha) / 255); 337 pSrc[2] = (GetRValue(blendColor) * alpha / 255) + 338 (pSrc[2] * (255 - alpha) / 255); 339 pSrc[3] = (alpha * alpha / 255) + 340 (pSrc[3] * (255 - alpha) / 255); 341 } 342 } 343 } 344 345 HBITMAP hDstBitmap = ::CreateDIBitmap(hdc, 346 reinterpret_cast<BITMAPINFOHEADER*>(&bi), 347 CBM_INIT, 348 buf, 349 reinterpret_cast<BITMAPINFO*>(&bi), 350 DIB_RGB_COLORS 351 ); 352 353 ::SelectObject(hdc, oldBitmap); 354 ::DeleteDC(hdc); 355 free(buf); 356 357 return hDstBitmap; 358 } 359 360 /** 361 * Creates a 32 bit ARGB bitmap. Returns the bitmap handle. The *bitmapBits 362 * contains the pointer to the bitmap data or NULL if an error occurred. 363 */ 364 HBITMAP BitmapUtil::CreateARGBBitmap(int width, int height, void ** bitmapBitsPtr) 365 { 366 BITMAPINFOHEADER bmi; 367 368 ::ZeroMemory(&bmi, sizeof(bmi)); 369 bmi.biSize = sizeof(BITMAPINFOHEADER); 370 bmi.biWidth = width; 371 bmi.biHeight = -height; 372 bmi.biPlanes = 1; 373 bmi.biBitCount = 32; 374 bmi.biCompression = BI_RGB; 375 376 return ::CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS, 377 bitmapBitsPtr, NULL, 0); 378 }