1 /*
   2  * Copyright (c) 2011, 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 "common.h"
  27 
  28 #include "Pixels.h"
  29 
  30 #include "com_sun_glass_ui_Pixels_Format.h"
  31 #include "com_sun_glass_ui_win_WinPixels.h"
  32 
  33 Bitmap::Bitmap(int width, int height)
  34 {
  35     BYTE *mpixels = new BYTE[width * height];
  36     memset(mpixels, 0, width * height);
  37     Attach(::CreateBitmap(width, height, 1, 1, mpixels));
  38     delete[] mpixels;
  39     ASSERT((HBITMAP)*this);
  40 }
  41 
  42 Bitmap::Bitmap(int width, int height, void **data, HDC hdc)
  43 {
  44     ASSERT(width && height && data);
  45 
  46     BITMAPV5HEADER bmi = {0};
  47     bmi.bV5Width = width;
  48     bmi.bV5Height = -height;
  49     bmi.bV5Planes = 1;
  50     bmi.bV5BitCount = 32;
  51 
  52     bmi.bV5Size = sizeof(BITMAPV5HEADER);
  53     bmi.bV5Compression = BI_BITFIELDS;
  54     bmi.bV5XPelsPerMeter = 72;
  55     bmi.bV5YPelsPerMeter = 72;
  56     bmi.bV5RedMask   = 0x00FF0000;
  57     bmi.bV5GreenMask = 0x0000FF00;
  58     bmi.bV5BlueMask  = 0x000000FF;
  59     bmi.bV5AlphaMask = 0xFF000000;
  60 
  61     Attach(::CreateDIBSection(
  62         hdc,
  63         (BITMAPINFO*)&bmi,
  64         DIB_RGB_COLORS,
  65         data,
  66         NULL,
  67         0));
  68 
  69     ASSERT((HBITMAP)*this);
  70 }
  71 
  72 Bitmap::Bitmap(Pixels & pixels)
  73 {
  74     Attach(::CreateBitmap(pixels.GetWidth(), pixels.GetHeight(), 1, 32, pixels.GetBits()));
  75     ASSERT((HBITMAP)*this);
  76 }
  77 
  78 DIBitmap::DIBitmap(Pixels & pixels)
  79 {
  80     int const width = pixels.GetWidth();
  81     int const height = pixels.GetHeight();
  82     void * const bits = pixels.GetBits();
  83 
  84     void *bitmapBits = NULL;
  85     jsize imageSize = width * height * 4;
  86 
  87     BITMAPINFOHEADER bmi = {0};
  88     bmi.biSize = sizeof(bmi);
  89     bmi.biWidth = width;
  90     bmi.biHeight = -height;
  91     bmi.biPlanes = 1;
  92     bmi.biBitCount = 32;
  93     bmi.biCompression = BI_RGB;
  94     bmi.biSizeImage = imageSize;
  95 
  96     HBITMAP hBitmap = ::CreateDIBSection(NULL, (BITMAPINFO *)&bmi, DIB_RGB_COLORS, &bitmapBits, NULL, 0);
  97 
  98     if (bitmapBits) {
  99         memcpy(bitmapBits, bits, imageSize);
 100         Attach(hBitmap);
 101     }
 102     ASSERT((HBITMAP)*this);
 103 }
 104 
 105 HICON Pixels::CreateIcon(JNIEnv *env, jobject jPixels, BOOL fIcon, jint x, jint y)
 106 {
 107     Pixels pixels(env, jPixels);
 108 
 109     Bitmap mask(pixels.GetWidth(), pixels.GetHeight());
 110     Bitmap bitmap(pixels);
 111 
 112     ICONINFO iconInfo;
 113     memset(&iconInfo, 0, sizeof(ICONINFO));
 114     iconInfo.hbmMask = mask;
 115     iconInfo.hbmColor = bitmap;
 116     iconInfo.fIcon = fIcon;
 117     iconInfo.xHotspot = x;
 118     iconInfo.yHotspot = y;
 119     HICON hIcon = ::CreateIconIndirect(&iconInfo);
 120     ASSERT(hIcon);
 121 
 122     ::GdiFlush();
 123 
 124     return hIcon;
 125 }
 126 
 127 Pixels::Pixels(JNIEnv *env, jobject jPixels)
 128 {
 129     env->CallVoidMethod(jPixels, javaIDs.Pixels.attachData, ptr_to_jlong(this));
 130     CheckAndClearException(env);
 131 }
 132 
 133 void Pixels::AttachInt(JNIEnv *env, jint w, jint h, jobject buf, jintArray array, jint offset)
 134 {
 135     width = w;
 136     height = h;
 137     ints.Attach(env, buf, array, offset);
 138 }
 139 
 140 void Pixels::AttachByte(JNIEnv *env, jint w, jint h, jobject buf, jbyteArray array, jint offset)
 141 {
 142     width = w;
 143     height = h;
 144     bytes.Attach(env, buf, array, offset);
 145 }
 146 
 147 void * Pixels::GetBits()
 148 {
 149     if (ints) {
 150         return ints.GetPtr();
 151     }
 152     if (bytes) {
 153         return bytes.GetPtr();
 154     }
 155     return NULL;
 156 }
 157 
 158 HANDLE BaseBitmap::GetGlobalDIB()
 159 {
 160     HBITMAP hBitmap = (HBITMAP)*this;
 161     BITMAP bm;
 162     ::GetObject(hBitmap, sizeof(bm), &bm);
 163 
 164     jsize imageSize = bm.bmWidth*bm.bmHeight*4;
 165 
 166     //BITMAPV5HEADER converts to ordinal BITMAPINFOHEADER
 167     //as in/out parameter of GetDIBits call.
 168     //Negative height is not supported by MS Wordpad. Sorry.
 169     BITMAPINFOHEADER bmi = {0};
 170     bmi.biSize = sizeof(bmi);
 171     bmi.biWidth = bm.bmWidth;
 172     bmi.biHeight = bm.bmHeight;
 173     bmi.biPlanes = 1;
 174     bmi.biBitCount = 32;
 175     bmi.biCompression = BI_RGB;
 176     bmi.biSizeImage = imageSize;
 177 
 178     HANDLE hDIB = ::GlobalAlloc(GHND, bmi.biSize + imageSize);
 179     if (hDIB) {
 180         bool success = false;
 181         HDC hDC = ::GetDC(NULL);
 182         if (hDC) {
 183             BITMAPINFOHEADER *pbi = (BITMAPINFOHEADER *)::GlobalLock(hDIB);
 184             if (pbi) {
 185                 *pbi = bmi;
 186                 success = ::GetDIBits(hDC, hBitmap,
 187                     0, bm.bmHeight,
 188                     (LPSTR)pbi + bmi.biSize,
 189                     (LPBITMAPINFO)pbi,
 190                     DIB_RGB_COLORS) != 0;
 191                 ::GlobalUnlock(hDIB);
 192             }
 193             ::ReleaseDC(NULL, hDC);
 194         }
 195         if (!success) {
 196             ::GlobalFree(hDIB);
 197             hDIB = NULL;
 198         }
 199     }
 200     return hDIB;
 201 }
 202 
 203 extern "C" {
 204 
 205 /*
 206  * Class:     com_sun_glass_ui_win_WinPixels
 207  * Method:    _initIDs
 208  * Signature: ()I
 209  */
 210 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinPixels__1initIDs
 211     (JNIEnv *env, jclass cls)
 212 {
 213     javaIDs.Pixels.attachData = env->GetMethodID(cls, "attachData", "(J)V");
 214     ASSERT(javaIDs.Pixels.attachData);
 215 
 216     return com_sun_glass_ui_Pixels_Format_BYTE_BGRA_PRE;
 217 }
 218 
 219 /*
 220  * Class:     com_sun_glass_ui_win_WinPixels
 221  * Method:    _attachInt
 222  * Signature: (JIILjava/nio/IntBuffer;[II)V
 223  */
 224 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinPixels__1attachInt
 225     (JNIEnv *env, jobject pixels, jlong ptr, jint w, jint h, jobject buf, jintArray array, jint offset)
 226 {
 227     ((Pixels*)jlong_to_ptr(ptr))->AttachInt(env, w, h, buf, array, offset);
 228 }
 229 
 230 /*
 231  * Class:     com_sun_glass_ui_win_WinPixels
 232  * Method:    _attachByte
 233  * Signature: (JIILjava/nio/ByteBuffer;[BI)V
 234  */
 235 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinPixels__1attachByte
 236     (JNIEnv *env, jobject pixels, jlong ptr, jint w, jint h, jobject buf, jbyteArray array, jint offset)
 237 {
 238     ((Pixels*)jlong_to_ptr(ptr))->AttachByte(env, w, h, buf, array, offset);
 239 }
 240 
 241 /*
 242  * Class:     com_sun_glass_ui_win_WinPixels
 243  * Method:    _fillDirectByteBuffer
 244  * Signature: (Ljava/nio/ByteBuffer;)V
 245  */
 246 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinPixels__1fillDirectByteBuffer
 247     (JNIEnv *env, jobject jPixels, jobject bb)
 248 {
 249     Pixels pixels(env, jPixels);
 250 
 251     memcpy(env->GetDirectBufferAddress(bb), pixels.GetBits(),
 252             pixels.GetWidth() * pixels.GetHeight() * 4);
 253 }
 254 
 255 } // extern "C"
 256