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 }