1 /*
2  * Copyright (c) 2003, 2017, 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 "sun_awt_windows_ThemeReader.h"
27 #include <string.h>
28 
29 #include "awt.h"
30 #include "awt_Toolkit.h"
31 #include "awt_Object.h"
32 #include "awt_Component.h"
33 
34 #include "math.h"
35 
36 // Important note about VC6 and VC7 (or XP Platform SDK)   !
37 //
38 // These type definitions have been imported from UxTheme.h
39 // They have been imported instead of including them, because
40 // currently we don't require Platform SDK for building J2SE and
41 // VC6 includes do not have UxTheme.h. When we move to VC7
42 // we should remove these imports and just include
43 //
44 //  Uncomment these when we start using VC 7 (or XP Platform SDK)
45 //
46 //  #include <uxtheme.h>
47 //  #incldue <tmschema.h>
48 
49 
50 // Remove everyting inside this ifdef when we start using VC 7 (or XP Platform SDK)
51 #ifndef  _UXTHEME_H_
52 typedef HANDLE HTHEME;          // handle to a section of theme data for class
53 
54 typedef enum {
55     TS_MIN,
56     TS_TRUE,
57     TS_DRAW
58 } THEME_SIZE;
59 
60 
61 // Remove these when we start using VC 7 (or XP Platform SDK)
62 typedef struct _MARGINS
63 {
64     int cxLeftWidth;      // width of left border that retains its size
65     int cxRightWidth;     // width of right border that retains its size
66     int cyTopHeight;      // height of top border that retains its size
67     int cyBottomHeight;   // height of bottom border that retains its size
68 } MARGINS, *PMARGINS;
69 
70 #define TMT_TRANSPARENT 2201
71 #endif // _UXTHEME_H_
72 
73 #if defined(_MSC_VER) && _MSC_VER >= 1800
74 #  define ROUND_TO_INT(num)    ((int) round(num))
75 #else
76 #  define ROUND_TO_INT(num)    ((int) floor((num) + 0.5))
77 #endif
78 
79 #define ALPHA_MASK 0xff000000
80 #define RED_MASK 0xff0000
81 #define GREEN_MASK 0xff00
82 #define BLUE_MASK 0xff
83 #define ALPHA_SHIFT 24
84 #define RED_SHIFT 16
85 #define GREEN_SHIFT 8
86 
87 
88 typedef HRESULT(__stdcall *PFNCLOSETHEMEDATA)(HTHEME hTheme);
89 
90 typedef HRESULT(__stdcall *PFNDRAWTHEMEBACKGROUND)(HTHEME hTheme, HDC hdc,
91         int iPartId, int iStateId, const RECT *pRect,  const RECT *pClipRect);
92 
93 typedef HTHEME(__stdcall *PFNOPENTHEMEDATA)(HWND hwnd, LPCWSTR pszClassList);
94 
95 typedef HRESULT (__stdcall *PFNDRAWTHEMETEXT)(HTHEME hTheme, HDC hdc,
96           int iPartId, int iStateId, LPCWSTR pszText, int iCharCount,
97           DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect);
98 
99 typedef HRESULT (__stdcall *PFNGETTHEMEBACKGROUNDCONTENTRECT)(HTHEME hTheme,
100         HDC hdc, int iPartId, int iStateId,  const RECT *pBoundingRect,
101         RECT *pContentRect);
102 
103 typedef HRESULT (__stdcall *PFNGETTHEMEMARGINS)(HTHEME hTheme,
104         OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId,
105         OPTIONAL RECT *prc, OUT MARGINS *pMargins);
106 
107 typedef BOOL (__stdcall *PFNISTHEMEPARTDEFINED)(HTHEME hTheme, int iPartId, int iStateId);
108 
109 typedef HRESULT (__stdcall *PFNGETTHEMEBOOL)(HTHEME hTheme, int iPartId,
110         int iStateId, int iPropId, BOOL *pfVal);
111 
112 typedef BOOL (__stdcall *PFNGETTHEMESYSBOOL)(HTHEME hTheme, int iPropId);
113 
114 typedef HRESULT (__stdcall *PFNGETTHEMECOLOR)(HTHEME hTheme, int iPartId,
115         int iStateId, int iPropId, COLORREF *pColor);
116 
117 typedef HRESULT (__stdcall *PFNGETTHEMEENUMVALUE)(HTHEME hTheme, int iPartId,
118         int iStateId, int iPropId, int *val);
119 typedef HRESULT (__stdcall *PFNGETTHEMEINT)(HTHEME hTheme, int iPartId,
120         int iStateId, int iPropId, int *val);
121 typedef HRESULT (__stdcall *PFNGETTHEMEPARTSIZE)(HTHEME hTheme, HDC hdc,
122         int iPartId, int iStateId, RECT *prc, THEME_SIZE eSize, SIZE *size);
123 
124 typedef HRESULT (__stdcall *PFNGETTHEMEPOSITION)(HTHEME hTheme, int iPartId,
125         int iStateId, int propID, POINT *point);
126 
127 typedef HRESULT(__stdcall *PFNSETWINDOWTHEME)(HWND hwnd, LPCWSTR pszSubAppName,
128             LPCWSTR pszSubIdList);
129 
130 typedef HRESULT (__stdcall *PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT)
131                 (HTHEME hTheme, int iPartId, int iStateId);
132 
133 typedef HRESULT (__stdcall *PFNGETTHEMETRANSITIONDURATION)
134                 (HTHEME hTheme, int iPartId, int iStateIdFrom, int iStateIdTo,
135                  int iPropId, DWORD *pdwDuration);
136 
137 static PFNOPENTHEMEDATA OpenThemeData = NULL;
138 static PFNDRAWTHEMEBACKGROUND DrawThemeBackground = NULL;
139 static PFNCLOSETHEMEDATA CloseThemeData = NULL;
140 static PFNDRAWTHEMETEXT DrawThemeText = NULL;
141 static PFNGETTHEMEBACKGROUNDCONTENTRECT GetThemeBackgroundContentRect = NULL;
142 static PFNGETTHEMEMARGINS GetThemeMargins = NULL;
143 static PFNISTHEMEPARTDEFINED IsThemePartDefined = NULL;
144 static PFNGETTHEMEBOOL GetThemeBool=NULL;
145 static PFNGETTHEMESYSBOOL GetThemeSysBool=NULL;
146 static PFNGETTHEMECOLOR GetThemeColor=NULL;
147 static PFNGETTHEMEENUMVALUE GetThemeEnumValue = NULL;
148 static PFNGETTHEMEINT GetThemeInt = NULL;
149 static PFNGETTHEMEPARTSIZE GetThemePartSize = NULL;
150 static PFNGETTHEMEPOSITION GetThemePosition = NULL;
151 static PFNSETWINDOWTHEME SetWindowTheme = NULL;
152 static PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT
153                                    IsThemeBackgroundPartiallyTransparent = NULL;
154 //this function might not exist on Windows XP
155 static PFNGETTHEMETRANSITIONDURATION GetThemeTransitionDuration = NULL;
156 
157 
InitThemes()158 BOOL InitThemes() {
159     static HMODULE hModThemes = NULL;
160     hModThemes = JDK_LoadSystemLibrary("UXTHEME.DLL");
161     DTRACE_PRINTLN1("InitThemes hModThemes = %x\n", hModThemes);
162     if(hModThemes) {
163         DTRACE_PRINTLN("Loaded UxTheme.dll\n");
164         OpenThemeData = (PFNOPENTHEMEDATA)GetProcAddress(hModThemes,
165                                                         "OpenThemeData");
166         DrawThemeBackground = (PFNDRAWTHEMEBACKGROUND)GetProcAddress(
167                                         hModThemes, "DrawThemeBackground");
168         CloseThemeData = (PFNCLOSETHEMEDATA)GetProcAddress(
169                                                 hModThemes, "CloseThemeData");
170         DrawThemeText = (PFNDRAWTHEMETEXT)GetProcAddress(
171                                         hModThemes, "DrawThemeText");
172         GetThemeBackgroundContentRect = (PFNGETTHEMEBACKGROUNDCONTENTRECT)
173                 GetProcAddress(hModThemes, "GetThemeBackgroundContentRect");
174         GetThemeMargins = (PFNGETTHEMEMARGINS)GetProcAddress(
175                                         hModThemes, "GetThemeMargins");
176         IsThemePartDefined = (PFNISTHEMEPARTDEFINED)GetProcAddress(
177                                         hModThemes, "IsThemePartDefined");
178         GetThemeBool = (PFNGETTHEMEBOOL)GetProcAddress(
179                                         hModThemes, "GetThemeBool");
180         GetThemeSysBool = (PFNGETTHEMESYSBOOL)GetProcAddress(hModThemes,
181                                                         "GetThemeSysBool");
182         GetThemeColor = (PFNGETTHEMECOLOR)GetProcAddress(hModThemes,
183                                                         "GetThemeColor");
184         GetThemeEnumValue = (PFNGETTHEMEENUMVALUE)GetProcAddress(hModThemes,
185                                                 "GetThemeEnumValue");
186         GetThemeInt = (PFNGETTHEMEINT)GetProcAddress(hModThemes, "GetThemeInt");
187         GetThemePosition = (PFNGETTHEMEPOSITION)GetProcAddress(hModThemes,
188                                                         "GetThemePosition");
189         GetThemePartSize = (PFNGETTHEMEPARTSIZE)GetProcAddress(hModThemes,
190                                                          "GetThemePartSize");
191         SetWindowTheme = (PFNSETWINDOWTHEME)GetProcAddress(hModThemes,
192                                                         "SetWindowTheme");
193         IsThemeBackgroundPartiallyTransparent =
194             (PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT)GetProcAddress(hModThemes,
195                                        "IsThemeBackgroundPartiallyTransparent");
196         //this function might not exist
197         GetThemeTransitionDuration =
198             (PFNGETTHEMETRANSITIONDURATION)GetProcAddress(hModThemes,
199                                         "GetThemeTransitionDuration");
200 
201         if(OpenThemeData
202            && DrawThemeBackground
203            && CloseThemeData
204            && DrawThemeText
205            && GetThemeBackgroundContentRect
206            && GetThemeMargins
207            && IsThemePartDefined
208            && GetThemeBool
209            && GetThemeSysBool
210            && GetThemeColor
211            && GetThemeEnumValue
212            && GetThemeInt
213            && GetThemePartSize
214            && GetThemePosition
215            && SetWindowTheme
216            && IsThemeBackgroundPartiallyTransparent
217           ) {
218               DTRACE_PRINTLN("Loaded function pointers.\n");
219               // We need to make sure we can load the Theme. This may not be
220               // the case on a WinXP machine with classic mode enabled.
221               HTHEME hTheme = OpenThemeData(AwtToolkit::GetInstance().GetHWnd(), L"Button");
222               if(hTheme) {
223                   DTRACE_PRINTLN("Loaded Theme data.\n");
224                   CloseThemeData(hTheme);
225                   return TRUE;
226               }
227             } else {
228                FreeLibrary(hModThemes);
229                hModThemes = NULL;
230             }
231     }
232     return FALSE;
233 }
234 
Java_sun_awt_windows_ThemeReader_initThemes(JNIEnv * env,jclass klass)235 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_initThemes
236 (JNIEnv *env, jclass klass) {
237     static BOOL TryLoadingThemeLib = FALSE;
238     static BOOL Themed = FALSE;
239     if (!TryLoadingThemeLib) {
240         Themed = InitThemes();
241         TryLoadingThemeLib = TRUE;
242     }
243     return JNI_IS_TRUE(Themed);
244 }
245 
246 
247 
assert_result(HRESULT hres,JNIEnv * env)248 static void assert_result(HRESULT hres, JNIEnv *env) {
249 #ifdef _DEBUG
250     if (hres != 0) {
251         DWORD lastError = GetLastError();
252         if (lastError != 0) {
253             LPSTR msgBuffer = NULL;
254             DWORD fret= FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
255                     FORMAT_MESSAGE_FROM_SYSTEM |
256                     FORMAT_MESSAGE_IGNORE_INSERTS,
257                     NULL,
258                     lastError,
259                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
260                     (LPSTR)&msgBuffer,
261                     // it's an output parameter when allocate buffer is used
262                     0,
263                     NULL);
264             if (fret != 0) {
265                 DTRACE_PRINTLN3("Error: hres=0x%x lastError=0x%x %s\n", hres,
266                                                 lastError, msgBuffer);
267                 LocalFree(msgBuffer);
268             } else {
269                 DTRACE_PRINTLN2("Error: hres=0x%x lastError=0x%x \n", hres,
270                                                 lastError);
271             }
272         }
273     }
274 #endif
275 }
276 
277 
278 /*
279  * Class:     sun_awt_windows_ThemeReader
280  * Method:    openTheme
281  * Signature: (Ljava/lang/String;)J
282  */
Java_sun_awt_windows_ThemeReader_openTheme(JNIEnv * env,jclass klass,jstring widget)283 JNIEXPORT jlong JNICALL Java_sun_awt_windows_ThemeReader_openTheme
284 (JNIEnv *env, jclass klass, jstring widget) {
285 
286     LPCTSTR str = (LPCTSTR) JNU_GetStringPlatformChars(env, widget, NULL);
287     if (str == NULL) {
288         JNU_ThrowOutOfMemoryError(env, 0);
289         return 0;
290     }
291     // We need to open the Theme on a Window that will stick around.
292     // The best one for that purpose is the Toolkit window.
293     HTHEME htheme = OpenThemeData(AwtToolkit::GetInstance().GetHWnd(), str);
294     JNU_ReleaseStringPlatformChars(env, widget, str);
295     return (jlong) htheme;
296 }
297 
298 /*
299  * Class:     sun_awt_windows_ThemeReader
300  * Method:    setWindowTheme
301  * Signature: (Ljava/lang/String;)V
302  */
Java_sun_awt_windows_ThemeReader_setWindowTheme(JNIEnv * env,jclass klass,jstring subAppName)303 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_setWindowTheme
304 (JNIEnv *env, jclass klass, jstring subAppName) {
305 
306     LPCTSTR str = NULL;
307     if (subAppName != NULL) {
308         str = (LPCTSTR) JNU_GetStringPlatformChars(env, subAppName, NULL);
309     }
310     // We need to set the Window theme on the same theme that we opened it with.
311     HRESULT hres = SetWindowTheme(AwtToolkit::GetInstance().GetHWnd(), str, NULL);
312     assert_result(hres, env);
313     if (subAppName != NULL) {
314         JNU_ReleaseStringPlatformChars(env, subAppName, str);
315     }
316 }
317 
318 /*
319  * Class:     sun_awt_windows_ThemeReader
320  * Method:    closeTheme
321  * Signature: (J)V
322  */
Java_sun_awt_windows_ThemeReader_closeTheme(JNIEnv * env,jclass klass,jlong theme)323 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_closeTheme
324 (JNIEnv *env, jclass klass, jlong theme) {
325 
326     HRESULT hres = CloseThemeData((HTHEME)theme);
327     assert_result(hres, env);
328 }
329 
copyDIBToBufferedImage(int * pDstBits,int * pSrcBits,BOOL transparent,int w,int h,int stride)330 static void copyDIBToBufferedImage(int *pDstBits, int *pSrcBits,
331                 BOOL transparent, int w, int h, int stride) {
332 
333     int offsetToNextLine = stride - w;
334     int *dst = pDstBits;
335     int *src = pSrcBits;
336     double alphaScale;
337     int r,g,b,a;
338     int pixel;
339 
340     BOOL translucent = FALSE;
341 
342     for (int i=0;i<h;i++) {
343         for (int j=0;j<w;j++) {
344             pixel = *src++;
345             a = (pixel & ALPHA_MASK)  >> ALPHA_SHIFT;
346             if ((a != 0) && (a != 255)) {
347                 translucent = TRUE;
348                 break;
349             }
350         }
351         if (translucent) break;
352     }
353     src = pSrcBits;
354 
355     if (translucent) {
356         for (int i=0;i<h;i++) {
357             for (int j=0;j<w;j++) {
358                 pixel = *src++;
359                 if (pixel != 0) {
360                     // The UxTheme API seems to do the blending and
361                     // premultiply the resulting values.
362                     // so we have to divide by the alpha to get the
363                     // original component values.
364                     a = (pixel & ALPHA_MASK)  >> ALPHA_SHIFT;
365                     if ((a != 255) && (a != 0)) {
366                         r = (pixel & RED_MASK)  >> RED_SHIFT;
367                         g = (pixel & GREEN_MASK)  >> GREEN_SHIFT;
368                         b = (pixel & BLUE_MASK);
369                         alphaScale = 255.0 / a;
370                         r = (int) ((double) r * alphaScale);
371                         if (r > 255) r = 255;
372                         g = (int) ((double) g * alphaScale);
373                         if (g > 255) g = 255;
374                         b = (int) ((double) b * alphaScale);
375                         if (b > 255) b = 255;
376                         pixel = (a << ALPHA_SHIFT) | (r << RED_SHIFT) |
377                                                    (g << GREEN_SHIFT) | b ;
378                     }
379                     else {
380                         // Frame maximize and minimize buttons
381                         // have transparent pixels with alpha
382                         // set to FF and nontransparent pixels have zero alpha.
383                         pixel |= 0xFF000000;
384                     }
385                 }
386                 *dst++ = pixel;
387             }
388             dst += offsetToNextLine;
389         }
390     }
391     else if (transparent) {
392          for (int i=0;i<h;i++) {
393              for (int j=0;j<w;j++) {
394                  pixel = *src++;
395                  if (pixel == 0) {
396                      *dst++ = 0;
397                  }
398                  else {
399                      *dst++ = 0xFF000000 | pixel;
400                  }
401              }
402              dst += offsetToNextLine;
403          }
404      }
405      else {
406          for (int i=0;i<h;i++) {
407              for (int j=0;j<w;j++) {
408                  pixel = *src++;
409                  *dst++ = 0xFF000000 | pixel;
410              }
411              dst += offsetToNextLine;
412          }
413      }
414 
415 }
416 
417 
418 
419 /*
420  * Class:     sun_awt_windows_ThemeReader
421  * Method:    paintBackground
422  * Signature: ([IJIIIIIII)V
423  */
Java_sun_awt_windows_ThemeReader_paintBackground(JNIEnv * env,jclass klass,jintArray array,jlong theme,jint part,jint state,jint x,jint y,jint w,jint h,jint stride)424 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_paintBackground
425   (JNIEnv *env, jclass klass, jintArray array, jlong theme, jint part, jint state,
426     jint x, jint y, jint w, jint h, jint stride) {
427 
428     int *pDstBits=NULL;
429     int *pSrcBits=NULL;
430     HDC memDC,defaultDC;
431     HBITMAP hDibSection = NULL;
432     RECT rect;
433     BITMAPINFO bmi;
434     HTHEME hTheme = (HTHEME) theme;
435 
436     DTRACE_PRINTLN3("Java_sun_awt_windows_ThemeReader_paintButtonBackground w=%d h=%d\n stride=%d\n",w,h,stride);
437 
438     if (hTheme == NULL) {
439         JNU_ThrowInternalError(env, "HTHEME is null");
440         return;
441     }
442 
443     defaultDC = GetDC(NULL);
444 
445     memDC = CreateCompatibleDC(defaultDC);
446 
447     static const int BITS_PER_PIXEL = 32;
448 
449     ZeroMemory(&bmi,sizeof(BITMAPINFO));
450     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
451     bmi.bmiHeader.biWidth = w;
452     bmi.bmiHeader.biHeight = -h;
453     bmi.bmiHeader.biPlanes = 1;
454     bmi.bmiHeader.biBitCount = BITS_PER_PIXEL;
455     bmi.bmiHeader.biCompression = BI_RGB;
456     bmi.bmiHeader.biSizeImage = w * h * (BITS_PER_PIXEL>>3);
457 
458 
459     hDibSection = ::CreateDIBSection(memDC, (BITMAPINFO*) &bmi,
460             DIB_RGB_COLORS, (void **) &pSrcBits,
461             NULL, 0);
462     if (hDibSection == NULL) {
463         DTRACE_PRINTLN("Error creating DIB section");
464         ReleaseDC(NULL,defaultDC);
465         return;
466     }
467 
468     SelectObject(memDC,hDibSection);
469 
470     rect.left = 0;
471     rect.top = 0;
472     rect.bottom = h;
473     rect.right = w;
474 
475     ZeroMemory(pSrcBits,(BITS_PER_PIXEL>>3)*w*h);
476 
477     HRESULT hres = DrawThemeBackground(hTheme, memDC, part, state, &rect, NULL);
478     assert_result(hres, env);
479     if (SUCCEEDED(hres)) {
480         // Make sure GDI is done.
481         GdiFlush();
482         // Copy the resulting pixels to our Java BufferedImage.
483         pDstBits = (int *)env->GetPrimitiveArrayCritical(array, 0);
484         BOOL transparent = FALSE;
485         transparent = IsThemeBackgroundPartiallyTransparent(hTheme,part,state);
486         copyDIBToBufferedImage(pDstBits, pSrcBits, transparent, w, h, stride);
487         env->ReleasePrimitiveArrayCritical(array, pDstBits, 0);
488     }
489 
490     // Delete resources.
491     DeleteObject(hDibSection);
492     DeleteDC(memDC);
493     ReleaseDC(NULL,defaultDC);
494 }
495 
newInsets(JNIEnv * env,jint top,jint left,jint bottom,jint right)496 jobject newInsets(JNIEnv *env, jint top, jint left, jint bottom, jint right) {
497     if (env->EnsureLocalCapacity(2) < 0) {
498         return NULL;
499     }
500 
501     static jclass insetsClassID = NULL;
502 
503     if (insetsClassID == NULL) {
504         jclass insetsClassIDLocal = env->FindClass("java/awt/Insets");
505         CHECK_NULL_RETURN(insetsClassIDLocal, NULL);
506         insetsClassID = (jclass)env->NewGlobalRef(insetsClassIDLocal);
507         env->DeleteLocalRef(insetsClassIDLocal);
508     }
509 
510     jobject insets = env->NewObject(insetsClassID,
511         AwtToolkit::insetsMID,
512         top, left, bottom, right);
513 
514     if (safe_ExceptionOccurred(env)) {
515         env->ExceptionDescribe();
516         env->ExceptionClear();
517     }
518 
519     return insets;
520 }
521 
522 /*
523  * Class:     sun_awt_windows_ThemeReader
524  * Method:    getThemeMargins
525  * Signature: (JIII)Ljava/awt/Insets;
526  */
Java_sun_awt_windows_ThemeReader_getThemeMargins(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint property)527 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getThemeMargins
528 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint property) {
529     MARGINS margins;
530     HTHEME hTheme = (HTHEME) theme;
531 
532     if (hTheme != NULL) {
533         HRESULT hres = GetThemeMargins(hTheme, NULL, part, state, property, NULL, &margins);
534         assert_result(hres, env);
535         if (FAILED(hres)) {
536             return NULL;
537         }
538 
539         return newInsets(env,
540                 margins.cyTopHeight,
541                 margins.cxLeftWidth, margins.cyBottomHeight, margins.cxRightWidth);
542     }
543     return NULL;
544 }
545 
546 /*
547  * Class: sun_awt_windows_ThemeReader
548  * Method: isThemePartDefined
549  * Signature: (JII)Z
550  */
Java_sun_awt_windows_ThemeReader_isThemePartDefined(JNIEnv * env,jclass klass,jlong theme,jint part,jint state)551 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_isThemePartDefined
552 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state) {
553     HTHEME hTheme = (HTHEME) theme;
554     return JNI_IS_TRUE(IsThemePartDefined(hTheme, part, state));
555 }
556 
557 /*
558  * Class:     sun_awt_windows_ThemeReader
559  * Method:    getColor
560  * Signature: (JIII)Ljava/awt/Color;
561  */
Java_sun_awt_windows_ThemeReader_getColor(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint type)562 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getColor
563 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint type) {
564 
565     HTHEME hTheme = (HTHEME) theme;
566 
567     if (hTheme != NULL) {
568         COLORREF color=0;
569 
570         if (GetThemeColor(hTheme, part, state, type, &color) != S_OK) {
571             return NULL;
572         }
573 
574         if (env->EnsureLocalCapacity(1) < 0) {
575             return NULL;
576         }
577 
578         static jmethodID colorMID = NULL;
579         static jclass colorClassID = NULL;
580 
581         if (colorClassID == NULL) {
582             jclass colorClassIDLocal = env->FindClass("java/awt/Color");
583             CHECK_NULL_RETURN(colorClassIDLocal, NULL);
584             colorClassID = (jclass)env->NewGlobalRef(colorClassIDLocal);
585             env->DeleteLocalRef(colorClassIDLocal);
586         }
587 
588         if (colorMID == NULL) {
589             colorMID = env->GetMethodID(colorClassID, "<init>", "(III)V");
590             CHECK_NULL_RETURN(colorMID, NULL);
591         }
592         jobject colorObj = env->NewObject(colorClassID,
593                 colorMID, GetRValue(color), GetGValue(color),GetBValue(color));
594 
595         if (safe_ExceptionOccurred(env)) {
596             env->ExceptionDescribe();
597             env->ExceptionClear();
598         }
599 
600         return colorObj;
601     }
602     return NULL;
603 }
604 
605 /*
606  * Class:     sun_awt_windows_ThemeReader
607  * Method:    getInt
608  * Signature: (JIII)I
609  */
Java_sun_awt_windows_ThemeReader_getInt(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)610 JNIEXPORT jint JNICALL Java_sun_awt_windows_ThemeReader_getInt
611 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) {
612 
613     HTHEME hTheme = (HTHEME) theme;
614     int retVal = -1;
615     if (hTheme != NULL) {
616         HRESULT hres = GetThemeInt(hTheme, part, state, prop, &retVal);
617         assert_result(hres, env);
618     }
619     return retVal;
620 }
621 
622 /*
623  * Class:     sun_awt_windows_ThemeReader
624  * Method:    getEnum
625  * Signature: (JIII)I
626  */
Java_sun_awt_windows_ThemeReader_getEnum(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)627 JNIEXPORT jint JNICALL Java_sun_awt_windows_ThemeReader_getEnum
628 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) {
629     HTHEME hTheme = (HTHEME) theme;
630     int retVal = -1;
631     if (hTheme != NULL) {
632         HRESULT hres = GetThemeEnumValue(hTheme, part, state, prop, &retVal);
633         assert_result(hres, env);
634     }
635     return retVal;
636 }
637 
638 /*
639  * Class:     sun_awt_windows_ThemeReader
640  * Method:    getBoolean
641  * Signature: (JIII)Z
642  */
Java_sun_awt_windows_ThemeReader_getBoolean(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)643 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_getBoolean
644 (JNIEnv *env, jclass klass, jlong  theme, jint part, jint state, jint prop) {
645     HTHEME hTheme = (HTHEME) theme;
646     BOOL retVal = FALSE;
647     if (hTheme != NULL) {
648         HRESULT hres = GetThemeBool(hTheme, part, state, prop, &retVal);
649         assert_result(hres, env);
650     }
651     return JNI_IS_TRUE(retVal);
652 }
653 
654 /*
655  * Class:     sun_awt_windows_ThemeReader
656  * Method:    getSysBoolean
657  * Signature: (JI)Z
658  */
Java_sun_awt_windows_ThemeReader_getSysBoolean(JNIEnv * env,jclass klass,jlong theme,jint prop)659 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_getSysBoolean
660 (JNIEnv *env, jclass klass, jlong  theme, jint prop) {
661     HTHEME hTheme = (HTHEME)theme;
662     if (hTheme != NULL) {
663         return JNI_IS_TRUE(GetThemeSysBool(hTheme, prop));
664     }
665     return JNI_FALSE;
666 }
667 
668 /*
669  * Class:     sun_awt_windows_ThemeReader
670  * Method:    getPoint
671  * Signature: (JIII)Ljava/awt/Point;
672  */
Java_sun_awt_windows_ThemeReader_getPoint(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)673 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPoint
674 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) {
675     HTHEME hTheme = (HTHEME) theme;
676     POINT point;
677 
678     if (hTheme != NULL) {
679         if (GetThemePosition(hTheme, part, state, prop, &point) != S_OK) {
680             return NULL;
681         }
682 
683         if (env->EnsureLocalCapacity(2) < 0) {
684             return NULL;
685         }
686 
687         static jmethodID pointMID = NULL;
688         static jclass pointClassID = NULL;
689 
690         if (pointClassID == NULL) {
691             jclass pointClassIDLocal = env->FindClass("java/awt/Point");
692             CHECK_NULL_RETURN(pointClassIDLocal, NULL);
693             pointClassID = (jclass)env->NewGlobalRef(pointClassIDLocal);
694             env->DeleteLocalRef(pointClassIDLocal);
695         }
696 
697         if (pointMID == NULL) {
698             pointMID = env->GetMethodID(pointClassID, "<init>", "(II)V");
699             CHECK_NULL_RETURN(pointMID, NULL);
700         }
701         jobject pointObj = env->NewObject(pointClassID, pointMID, point.x, point.y);
702 
703         if (safe_ExceptionOccurred(env)) {
704             env->ExceptionDescribe();
705             env->ExceptionClear();
706         }
707 
708         return pointObj;
709     }
710     return NULL;
711 }
712 
713 /*
714  * Class:     sun_awt_windows_ThemeReader
715  * Method:    getPosition
716  * Signature: (JIII)Ljava/awt/Dimension;
717  */
Java_sun_awt_windows_ThemeReader_getPosition(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)718 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPosition
719 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) {
720 
721     HTHEME hTheme = (HTHEME) theme;
722     if (hTheme != NULL) {
723 
724         POINT point;
725 
726         HRESULT hres = GetThemePosition(hTheme, part, state, prop, &point);
727         assert_result(hres, env);
728         if (FAILED(hres)) {
729             return NULL;
730         }
731 
732 
733         if (env->EnsureLocalCapacity(2) < 0) {
734             return NULL;
735         }
736 
737         static jmethodID dimMID = NULL;
738         static jclass dimClassID = NULL;
739         if (dimClassID == NULL) {
740             jclass dimClassIDLocal = env->FindClass("java/awt/Dimension");
741             CHECK_NULL_RETURN(dimClassIDLocal, NULL);
742             dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal);
743             env->DeleteLocalRef(dimClassIDLocal);
744         }
745         if (dimMID == NULL) {
746             dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V");
747             CHECK_NULL_RETURN(dimMID, NULL);
748         }
749         jobject dimObj = env->NewObject(dimClassID, dimMID, point.x, point.y);
750 
751         if (safe_ExceptionOccurred(env)) {
752             env->ExceptionDescribe();
753             env->ExceptionClear();
754         }
755 
756         return dimObj;
757     }
758     return NULL;
759 }
760 
rescale(SIZE * size)761 void rescale(SIZE *size) {
762     static int dpiX = -1;
763     static int dpiY = -1;
764     if (dpiX == -1 || dpiY == -1) {
765         HWND hWnd = ::GetDesktopWindow();
766         HDC hDC = ::GetDC(hWnd);
767         dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX);
768         dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY);
769         ::ReleaseDC(hWnd, hDC);
770     }
771 
772     if (dpiX !=0 && dpiX != 96) {
773         float invScaleX = 96.0f / dpiX;
774         size->cx = ROUND_TO_INT(size->cx * invScaleX);
775     }
776     if (dpiY != 0 && dpiY != 96) {
777         float invScaleY = 96.0f / dpiY;
778         size->cy = ROUND_TO_INT(size->cy * invScaleY);
779     }
780 }
781 
782 /*
783  * Class:     sun_awt_windows_ThemeReader
784  * Method:    getPartSize
785  * Signature: (JII)Ljava/awt/Dimension;
786  */
Java_sun_awt_windows_ThemeReader_getPartSize(JNIEnv * env,jclass klass,jlong theme,jint part,jint state)787 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPartSize
788 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state) {
789     if (theme != NULL) {
790         SIZE size;
791 
792         if (SUCCEEDED(GetThemePartSize((HTHEME)theme, NULL, part, state,
793            NULL, TS_TRUE, &size)) && (env->EnsureLocalCapacity(2) >= 0)) {
794 
795             static jmethodID dimMID = NULL;
796             static jclass dimClassID = NULL;
797             if (dimClassID == NULL) {
798                 jclass dimClassIDLocal = env->FindClass("java/awt/Dimension");
799                 CHECK_NULL_RETURN(dimClassIDLocal, NULL);
800                 dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal);
801                 env->DeleteLocalRef(dimClassIDLocal);
802             }
803             if (dimMID == NULL) {
804                 dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V");
805                 CHECK_NULL_RETURN(dimMID, NULL);
806             }
807 
808             rescale(&size);
809             jobject dimObj = env->NewObject(dimClassID, dimMID, size.cx, size.cy);
810             if (safe_ExceptionOccurred(env)) {
811                 env->ExceptionDescribe();
812                 env->ExceptionClear();
813             }
814 
815             return dimObj;
816         }
817     }
818     return NULL;
819 }
820 
821 /*
822  * Class:     sun_awt_windows_ThemeReader
823  * Method:    getThemeBackgroundContentMargins
824  * Signature: (JIIII)Ljava/awt/Insets;
825  */
Java_sun_awt_windows_ThemeReader_getThemeBackgroundContentMargins(JNIEnv * env,jclass klass,jlong hTheme,jint part,jint state,jint boundingWidth,jint boundingHeight)826 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getThemeBackgroundContentMargins
827 (JNIEnv *env, jclass klass, jlong hTheme, jint part, jint state,
828 jint boundingWidth, jint boundingHeight) {
829     if (hTheme != NULL) {
830         RECT boundingRect;
831         boundingRect.left = 0;
832         boundingRect.top = 0;
833         boundingRect.right = boundingWidth;
834         boundingRect.bottom = boundingHeight;
835         RECT contentRect;
836         if (SUCCEEDED(GetThemeBackgroundContentRect((HTHEME) hTheme, NULL, part,
837                                                     state, &boundingRect,
838                                                     &contentRect))) {
839             return newInsets(env,
840                              contentRect.top, contentRect.left,
841                              boundingHeight - contentRect.bottom,
842                              boundingWidth - contentRect.right);
843         }
844     }
845     return NULL;
846 }
847 
848 /*
849  * Class:     sun_awt_windows_ThemeReader
850  * Method:    getThemeTransitionDuration
851  * Signature: (JIIII)J
852  */
853 JNIEXPORT jlong JNICALL
Java_sun_awt_windows_ThemeReader_getThemeTransitionDuration(JNIEnv * env,jclass klass,jlong theme,jint part,jint stateFrom,jint stateTo,jint propId)854 Java_sun_awt_windows_ThemeReader_getThemeTransitionDuration
855 (JNIEnv *env, jclass klass, jlong theme, jint part, jint stateFrom,
856  jint stateTo, jint propId) {
857     jlong rv = -1;
858     if (GetThemeTransitionDuration != NULL) {
859         DWORD duration = 0;
860         if (SUCCEEDED(GetThemeTransitionDuration((HTHEME) theme, part,
861                                       stateFrom, stateTo, propId, &duration))) {
862             rv = duration;
863         }
864     }
865     return rv;
866 }
867 
868 /*
869  * Class:     sun_awt_windows_ThemeReader
870  * Method:    isGetThemeTransitionDurationDefined
871  * Signature: ()Z
872  */
873 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_ThemeReader_isGetThemeTransitionDurationDefined(JNIEnv * env,jclass klass)874 Java_sun_awt_windows_ThemeReader_isGetThemeTransitionDurationDefined
875 (JNIEnv *env, jclass klass) {
876     return (GetThemeTransitionDuration != NULL) ? JNI_TRUE : JNI_FALSE;
877 }
878