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             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             DTRACE_PRINTLN3("Error: hres=0x%x lastError=0x%x %s\n", hres,
265                                                 lastError, msgBuffer);
266         }
267     }
268 #endif
269 }
270 
271 
272 /*
273  * Class:     sun_awt_windows_ThemeReader
274  * Method:    openTheme
275  * Signature: (Ljava/lang/String;)J
276  */
Java_sun_awt_windows_ThemeReader_openTheme(JNIEnv * env,jclass klass,jstring widget)277 JNIEXPORT jlong JNICALL Java_sun_awt_windows_ThemeReader_openTheme
278 (JNIEnv *env, jclass klass, jstring widget) {
279 
280     LPCTSTR str = (LPCTSTR) JNU_GetStringPlatformChars(env, widget, NULL);
281     if (str == NULL) {
282         JNU_ThrowOutOfMemoryError(env, 0);
283         return 0;
284     }
285     // We need to open the Theme on a Window that will stick around.
286     // The best one for that purpose is the Toolkit window.
287     HTHEME htheme = OpenThemeData(AwtToolkit::GetInstance().GetHWnd(), str);
288     JNU_ReleaseStringPlatformChars(env, widget, str);
289     return (jlong) htheme;
290 }
291 
292 /*
293  * Class:     sun_awt_windows_ThemeReader
294  * Method:    setWindowTheme
295  * Signature: (Ljava/lang/String;)V
296  */
Java_sun_awt_windows_ThemeReader_setWindowTheme(JNIEnv * env,jclass klass,jstring subAppName)297 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_setWindowTheme
298 (JNIEnv *env, jclass klass, jstring subAppName) {
299 
300     LPCTSTR str = NULL;
301     if (subAppName != NULL) {
302         str = (LPCTSTR) JNU_GetStringPlatformChars(env, subAppName, NULL);
303     }
304     // We need to set the Window theme on the same theme that we opened it with.
305     HRESULT hres = SetWindowTheme(AwtToolkit::GetInstance().GetHWnd(), str, NULL);
306     assert_result(hres, env);
307     if (subAppName != NULL) {
308         JNU_ReleaseStringPlatformChars(env, subAppName, str);
309     }
310 }
311 
312 /*
313  * Class:     sun_awt_windows_ThemeReader
314  * Method:    closeTheme
315  * Signature: (J)V
316  */
Java_sun_awt_windows_ThemeReader_closeTheme(JNIEnv * env,jclass klass,jlong theme)317 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_closeTheme
318 (JNIEnv *env, jclass klass, jlong theme) {
319 
320     HRESULT hres = CloseThemeData((HTHEME)theme);
321     assert_result(hres, env);
322 }
323 
copyDIBToBufferedImage(int * pDstBits,int * pSrcBits,BOOL transparent,int w,int h,int stride)324 static void copyDIBToBufferedImage(int *pDstBits, int *pSrcBits,
325                 BOOL transparent, int w, int h, int stride) {
326 
327     int offsetToNextLine = stride - w;
328     int *dst = pDstBits;
329     int *src = pSrcBits;
330     double alphaScale;
331     int r,g,b,a;
332     int pixel;
333 
334     BOOL translucent = FALSE;
335 
336     for (int i=0;i<h;i++) {
337         for (int j=0;j<w;j++) {
338             pixel = *src++;
339             a = (pixel & ALPHA_MASK)  >> ALPHA_SHIFT;
340             if ((a != 0) && (a != 255)) {
341                 translucent = TRUE;
342                 break;
343             }
344         }
345         if (translucent) break;
346     }
347     src = pSrcBits;
348 
349     if (translucent) {
350         for (int i=0;i<h;i++) {
351             for (int j=0;j<w;j++) {
352                 pixel = *src++;
353                 if (pixel != 0) {
354                     // The UxTheme API seems to do the blending and
355                     // premultiply the resulting values.
356                     // so we have to divide by the alpha to get the
357                     // original component values.
358                     a = (pixel & ALPHA_MASK)  >> ALPHA_SHIFT;
359                     if ((a != 255) && (a != 0)) {
360                         r = (pixel & RED_MASK)  >> RED_SHIFT;
361                         g = (pixel & GREEN_MASK)  >> GREEN_SHIFT;
362                         b = (pixel & BLUE_MASK);
363                         alphaScale = 255.0 / a;
364                         r = (int) ((double) r * alphaScale);
365                         if (r > 255) r = 255;
366                         g = (int) ((double) g * alphaScale);
367                         if (g > 255) g = 255;
368                         b = (int) ((double) b * alphaScale);
369                         if (b > 255) b = 255;
370                         pixel = (a << ALPHA_SHIFT) | (r << RED_SHIFT) |
371                                                    (g << GREEN_SHIFT) | b ;
372                     }
373                     else {
374                         // Frame maximize and minimize buttons
375                         // have transparent pixels with alpha
376                         // set to FF and nontransparent pixels have zero alpha.
377                         pixel |= 0xFF000000;
378                     }
379                 }
380                 *dst++ = pixel;
381             }
382             dst += offsetToNextLine;
383         }
384     }
385     else if (transparent) {
386          for (int i=0;i<h;i++) {
387              for (int j=0;j<w;j++) {
388                  pixel = *src++;
389                  if (pixel == 0) {
390                      *dst++ = 0;
391                  }
392                  else {
393                      *dst++ = 0xFF000000 | pixel;
394                  }
395              }
396              dst += offsetToNextLine;
397          }
398      }
399      else {
400          for (int i=0;i<h;i++) {
401              for (int j=0;j<w;j++) {
402                  pixel = *src++;
403                  *dst++ = 0xFF000000 | pixel;
404              }
405              dst += offsetToNextLine;
406          }
407      }
408 
409 }
410 
411 
412 
413 /*
414  * Class:     sun_awt_windows_ThemeReader
415  * Method:    paintBackground
416  * Signature: ([IJIIIIIII)V
417  */
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)418 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_paintBackground
419   (JNIEnv *env, jclass klass, jintArray array, jlong theme, jint part, jint state,
420     jint x, jint y, jint w, jint h, jint stride) {
421 
422     int *pDstBits=NULL;
423     int *pSrcBits=NULL;
424     HDC memDC,defaultDC;
425     HBITMAP hDibSection = NULL;
426     RECT rect;
427     BITMAPINFO bmi;
428     HTHEME hTheme = (HTHEME) theme;
429 
430     DTRACE_PRINTLN3("Java_sun_awt_windows_ThemeReader_paintButtonBackground w=%d h=%d\n stride=%d\n",w,h,stride);
431 
432     if (hTheme == NULL) {
433         JNU_ThrowInternalError(env, "HTHEME is null");
434         return;
435     }
436 
437     defaultDC = GetDC(NULL);
438 
439     memDC = CreateCompatibleDC(defaultDC);
440 
441     static const int BITS_PER_PIXEL = 32;
442 
443     ZeroMemory(&bmi,sizeof(BITMAPINFO));
444     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
445     bmi.bmiHeader.biWidth = w;
446     bmi.bmiHeader.biHeight = -h;
447     bmi.bmiHeader.biPlanes = 1;
448     bmi.bmiHeader.biBitCount = BITS_PER_PIXEL;
449     bmi.bmiHeader.biCompression = BI_RGB;
450     bmi.bmiHeader.biSizeImage = w * h * (BITS_PER_PIXEL>>3);
451 
452 
453     hDibSection = ::CreateDIBSection(memDC, (BITMAPINFO*) &bmi,
454             DIB_RGB_COLORS, (void **) &pSrcBits,
455             NULL, 0);
456     if (hDibSection == NULL) {
457         DTRACE_PRINTLN("Error creating DIB section");
458         ReleaseDC(NULL,defaultDC);
459         return;
460     }
461 
462     SelectObject(memDC,hDibSection);
463 
464     rect.left = 0;
465     rect.top = 0;
466     rect.bottom = h;
467     rect.right = w;
468 
469     ZeroMemory(pSrcBits,(BITS_PER_PIXEL>>3)*w*h);
470 
471     HRESULT hres = DrawThemeBackground(hTheme, memDC, part, state, &rect, NULL);
472     assert_result(hres, env);
473     if (SUCCEEDED(hres)) {
474         // Make sure GDI is done.
475         GdiFlush();
476         // Copy the resulting pixels to our Java BufferedImage.
477         pDstBits = (int *)env->GetPrimitiveArrayCritical(array, 0);
478         BOOL transparent = FALSE;
479         transparent = IsThemeBackgroundPartiallyTransparent(hTheme,part,state);
480         copyDIBToBufferedImage(pDstBits, pSrcBits, transparent, w, h, stride);
481         env->ReleasePrimitiveArrayCritical(array, pDstBits, 0);
482     }
483 
484     // Delete resources.
485     DeleteObject(hDibSection);
486     DeleteDC(memDC);
487     ReleaseDC(NULL,defaultDC);
488 }
489 
newInsets(JNIEnv * env,jint top,jint left,jint bottom,jint right)490 jobject newInsets(JNIEnv *env, jint top, jint left, jint bottom, jint right) {
491     if (env->EnsureLocalCapacity(2) < 0) {
492         return NULL;
493     }
494 
495     static jclass insetsClassID = NULL;
496 
497     if (insetsClassID == NULL) {
498         jclass insetsClassIDLocal = env->FindClass("java/awt/Insets");
499         CHECK_NULL_RETURN(insetsClassIDLocal, NULL);
500         insetsClassID = (jclass)env->NewGlobalRef(insetsClassIDLocal);
501         env->DeleteLocalRef(insetsClassIDLocal);
502     }
503 
504     jobject insets = env->NewObject(insetsClassID,
505         AwtToolkit::insetsMID,
506         top, left, bottom, right);
507 
508     if (safe_ExceptionOccurred(env)) {
509         env->ExceptionDescribe();
510         env->ExceptionClear();
511     }
512 
513     return insets;
514 }
515 
516 /*
517  * Class:     sun_awt_windows_ThemeReader
518  * Method:    getThemeMargins
519  * Signature: (JIII)Ljava/awt/Insets;
520  */
Java_sun_awt_windows_ThemeReader_getThemeMargins(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint property)521 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getThemeMargins
522 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint property) {
523     MARGINS margins;
524     HTHEME hTheme = (HTHEME) theme;
525 
526     if (hTheme != NULL) {
527         HRESULT hres = GetThemeMargins(hTheme, NULL, part, state, property, NULL, &margins);
528         assert_result(hres, env);
529         if (FAILED(hres)) {
530             return NULL;
531         }
532 
533         return newInsets(env,
534                 margins.cyTopHeight,
535                 margins.cxLeftWidth, margins.cyBottomHeight, margins.cxRightWidth);
536     }
537     return NULL;
538 }
539 
540 /*
541  * Class: sun_awt_windows_ThemeReader
542  * Method: isThemePartDefined
543  * Signature: (JII)Z
544  */
Java_sun_awt_windows_ThemeReader_isThemePartDefined(JNIEnv * env,jclass klass,jlong theme,jint part,jint state)545 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_isThemePartDefined
546 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state) {
547     HTHEME hTheme = (HTHEME) theme;
548     return JNI_IS_TRUE(IsThemePartDefined(hTheme, part, state));
549 }
550 
551 /*
552  * Class:     sun_awt_windows_ThemeReader
553  * Method:    getColor
554  * Signature: (JIII)Ljava/awt/Color;
555  */
Java_sun_awt_windows_ThemeReader_getColor(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint type)556 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getColor
557 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint type) {
558 
559     HTHEME hTheme = (HTHEME) theme;
560 
561     if (hTheme != NULL) {
562         COLORREF color=0;
563 
564         if (GetThemeColor(hTheme, part, state, type, &color) != S_OK) {
565             return NULL;
566         }
567 
568         if (env->EnsureLocalCapacity(1) < 0) {
569             return NULL;
570         }
571 
572         static jmethodID colorMID = NULL;
573         static jclass colorClassID = NULL;
574 
575         if (colorClassID == NULL) {
576             jclass colorClassIDLocal = env->FindClass("java/awt/Color");
577             CHECK_NULL_RETURN(colorClassIDLocal, NULL);
578             colorClassID = (jclass)env->NewGlobalRef(colorClassIDLocal);
579             env->DeleteLocalRef(colorClassIDLocal);
580         }
581 
582         if (colorMID == NULL) {
583             colorMID = env->GetMethodID(colorClassID, "<init>", "(III)V");
584             CHECK_NULL_RETURN(colorMID, NULL);
585         }
586         jobject colorObj = env->NewObject(colorClassID,
587                 colorMID, GetRValue(color), GetGValue(color),GetBValue(color));
588 
589         if (safe_ExceptionOccurred(env)) {
590             env->ExceptionDescribe();
591             env->ExceptionClear();
592         }
593 
594         return colorObj;
595     }
596     return NULL;
597 }
598 
599 /*
600  * Class:     sun_awt_windows_ThemeReader
601  * Method:    getInt
602  * Signature: (JIII)I
603  */
Java_sun_awt_windows_ThemeReader_getInt(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)604 JNIEXPORT jint JNICALL Java_sun_awt_windows_ThemeReader_getInt
605 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) {
606 
607     HTHEME hTheme = (HTHEME) theme;
608     int retVal = -1;
609     if (hTheme != NULL) {
610         HRESULT hres = GetThemeInt(hTheme, part, state, prop, &retVal);
611         assert_result(hres, env);
612     }
613     return retVal;
614 }
615 
616 /*
617  * Class:     sun_awt_windows_ThemeReader
618  * Method:    getEnum
619  * Signature: (JIII)I
620  */
Java_sun_awt_windows_ThemeReader_getEnum(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)621 JNIEXPORT jint JNICALL Java_sun_awt_windows_ThemeReader_getEnum
622 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) {
623     HTHEME hTheme = (HTHEME) theme;
624     int retVal = -1;
625     if (hTheme != NULL) {
626         HRESULT hres = GetThemeEnumValue(hTheme, part, state, prop, &retVal);
627         assert_result(hres, env);
628     }
629     return retVal;
630 }
631 
632 /*
633  * Class:     sun_awt_windows_ThemeReader
634  * Method:    getBoolean
635  * Signature: (JIII)Z
636  */
Java_sun_awt_windows_ThemeReader_getBoolean(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)637 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_getBoolean
638 (JNIEnv *env, jclass klass, jlong  theme, jint part, jint state, jint prop) {
639     HTHEME hTheme = (HTHEME) theme;
640     BOOL retVal = FALSE;
641     if (hTheme != NULL) {
642         HRESULT hres = GetThemeBool(hTheme, part, state, prop, &retVal);
643         assert_result(hres, env);
644     }
645     return JNI_IS_TRUE(retVal);
646 }
647 
648 /*
649  * Class:     sun_awt_windows_ThemeReader
650  * Method:    getSysBoolean
651  * Signature: (JI)Z
652  */
Java_sun_awt_windows_ThemeReader_getSysBoolean(JNIEnv * env,jclass klass,jlong theme,jint prop)653 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_getSysBoolean
654 (JNIEnv *env, jclass klass, jlong  theme, jint prop) {
655     HTHEME hTheme = (HTHEME)theme;
656     if (hTheme != NULL) {
657         return JNI_IS_TRUE(GetThemeSysBool(hTheme, prop));
658     }
659     return JNI_FALSE;
660 }
661 
662 /*
663  * Class:     sun_awt_windows_ThemeReader
664  * Method:    getPoint
665  * Signature: (JIII)Ljava/awt/Point;
666  */
Java_sun_awt_windows_ThemeReader_getPoint(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)667 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPoint
668 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) {
669     HTHEME hTheme = (HTHEME) theme;
670     POINT point;
671 
672     if (hTheme != NULL) {
673         if (GetThemePosition(hTheme, part, state, prop, &point) != S_OK) {
674             return NULL;
675         }
676 
677         if (env->EnsureLocalCapacity(2) < 0) {
678             return NULL;
679         }
680 
681         static jmethodID pointMID = NULL;
682         static jclass pointClassID = NULL;
683 
684         if (pointClassID == NULL) {
685             jclass pointClassIDLocal = env->FindClass("java/awt/Point");
686             CHECK_NULL_RETURN(pointClassIDLocal, NULL);
687             pointClassID = (jclass)env->NewGlobalRef(pointClassIDLocal);
688             env->DeleteLocalRef(pointClassIDLocal);
689         }
690 
691         if (pointMID == NULL) {
692             pointMID = env->GetMethodID(pointClassID, "<init>", "(II)V");
693             CHECK_NULL_RETURN(pointMID, NULL);
694         }
695         jobject pointObj = env->NewObject(pointClassID, pointMID, point.x, point.y);
696 
697         if (safe_ExceptionOccurred(env)) {
698             env->ExceptionDescribe();
699             env->ExceptionClear();
700         }
701 
702         return pointObj;
703     }
704     return NULL;
705 }
706 
707 /*
708  * Class:     sun_awt_windows_ThemeReader
709  * Method:    getPosition
710  * Signature: (JIII)Ljava/awt/Dimension;
711  */
Java_sun_awt_windows_ThemeReader_getPosition(JNIEnv * env,jclass klass,jlong theme,jint part,jint state,jint prop)712 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPosition
713 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) {
714 
715     HTHEME hTheme = (HTHEME) theme;
716     if (hTheme != NULL) {
717 
718         POINT point;
719 
720         HRESULT hres = GetThemePosition(hTheme, part, state, prop, &point);
721         assert_result(hres, env);
722         if (FAILED(hres)) {
723             return NULL;
724         }
725 
726 
727         if (env->EnsureLocalCapacity(2) < 0) {
728             return NULL;
729         }
730 
731         static jmethodID dimMID = NULL;
732         static jclass dimClassID = NULL;
733         if (dimClassID == NULL) {
734             jclass dimClassIDLocal = env->FindClass("java/awt/Dimension");
735             CHECK_NULL_RETURN(dimClassIDLocal, NULL);
736             dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal);
737             env->DeleteLocalRef(dimClassIDLocal);
738         }
739         if (dimMID == NULL) {
740             dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V");
741             CHECK_NULL_RETURN(dimMID, NULL);
742         }
743         jobject dimObj = env->NewObject(dimClassID, dimMID, point.x, point.y);
744 
745         if (safe_ExceptionOccurred(env)) {
746             env->ExceptionDescribe();
747             env->ExceptionClear();
748         }
749 
750         return dimObj;
751     }
752     return NULL;
753 }
754 
rescale(SIZE * size)755 void rescale(SIZE *size) {
756     static int dpiX = -1;
757     static int dpiY = -1;
758     if (dpiX == -1 || dpiY == -1) {
759         HWND hWnd = ::GetDesktopWindow();
760         HDC hDC = ::GetDC(hWnd);
761         dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX);
762         dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY);
763         ::ReleaseDC(hWnd, hDC);
764     }
765 
766     if (dpiX !=0 && dpiX != 96) {
767         float invScaleX = 96.0f / dpiX;
768         size->cx = ROUND_TO_INT(size->cx * invScaleX);
769     }
770     if (dpiY != 0 && dpiY != 96) {
771         float invScaleY = 96.0f / dpiY;
772         size->cy = ROUND_TO_INT(size->cy * invScaleY);
773     }
774 }
775 
776 /*
777  * Class:     sun_awt_windows_ThemeReader
778  * Method:    getPartSize
779  * Signature: (JII)Ljava/awt/Dimension;
780  */
Java_sun_awt_windows_ThemeReader_getPartSize(JNIEnv * env,jclass klass,jlong theme,jint part,jint state)781 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPartSize
782 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state) {
783     if (theme != NULL) {
784         SIZE size;
785 
786         if (SUCCEEDED(GetThemePartSize((HTHEME)theme, NULL, part, state,
787            NULL, TS_TRUE, &size)) && (env->EnsureLocalCapacity(2) >= 0)) {
788 
789             static jmethodID dimMID = NULL;
790             static jclass dimClassID = NULL;
791             if (dimClassID == NULL) {
792                 jclass dimClassIDLocal = env->FindClass("java/awt/Dimension");
793                 CHECK_NULL_RETURN(dimClassIDLocal, NULL);
794                 dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal);
795                 env->DeleteLocalRef(dimClassIDLocal);
796             }
797             if (dimMID == NULL) {
798                 dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V");
799                 CHECK_NULL_RETURN(dimMID, NULL);
800             }
801 
802             rescale(&size);
803             jobject dimObj = env->NewObject(dimClassID, dimMID, size.cx, size.cy);
804             if (safe_ExceptionOccurred(env)) {
805                 env->ExceptionDescribe();
806                 env->ExceptionClear();
807             }
808 
809             return dimObj;
810         }
811     }
812     return NULL;
813 }
814 
815 /*
816  * Class:     sun_awt_windows_ThemeReader
817  * Method:    getThemeBackgroundContentMargins
818  * Signature: (JIIII)Ljava/awt/Insets;
819  */
Java_sun_awt_windows_ThemeReader_getThemeBackgroundContentMargins(JNIEnv * env,jclass klass,jlong hTheme,jint part,jint state,jint boundingWidth,jint boundingHeight)820 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getThemeBackgroundContentMargins
821 (JNIEnv *env, jclass klass, jlong hTheme, jint part, jint state,
822 jint boundingWidth, jint boundingHeight) {
823     if (hTheme != NULL) {
824         RECT boundingRect;
825         boundingRect.left = 0;
826         boundingRect.top = 0;
827         boundingRect.right = boundingWidth;
828         boundingRect.bottom = boundingHeight;
829         RECT contentRect;
830         if (SUCCEEDED(GetThemeBackgroundContentRect((HTHEME) hTheme, NULL, part,
831                                                     state, &boundingRect,
832                                                     &contentRect))) {
833             return newInsets(env,
834                              contentRect.top, contentRect.left,
835                              boundingHeight - contentRect.bottom,
836                              boundingWidth - contentRect.right);
837         }
838     }
839     return NULL;
840 }
841 
842 /*
843  * Class:     sun_awt_windows_ThemeReader
844  * Method:    getThemeTransitionDuration
845  * Signature: (JIIII)J
846  */
847 JNIEXPORT jlong JNICALL
Java_sun_awt_windows_ThemeReader_getThemeTransitionDuration(JNIEnv * env,jclass klass,jlong theme,jint part,jint stateFrom,jint stateTo,jint propId)848 Java_sun_awt_windows_ThemeReader_getThemeTransitionDuration
849 (JNIEnv *env, jclass klass, jlong theme, jint part, jint stateFrom,
850  jint stateTo, jint propId) {
851     jlong rv = -1;
852     if (GetThemeTransitionDuration != NULL) {
853         DWORD duration = 0;
854         if (SUCCEEDED(GetThemeTransitionDuration((HTHEME) theme, part,
855                                       stateFrom, stateTo, propId, &duration))) {
856             rv = duration;
857         }
858     }
859     return rv;
860 }
861 
862 /*
863  * Class:     sun_awt_windows_ThemeReader
864  * Method:    isGetThemeTransitionDurationDefined
865  * Signature: ()Z
866  */
867 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_ThemeReader_isGetThemeTransitionDurationDefined(JNIEnv * env,jclass klass)868 Java_sun_awt_windows_ThemeReader_isGetThemeTransitionDurationDefined
869 (JNIEnv *env, jclass klass) {
870     return (GetThemeTransitionDuration != NULL) ? JNI_TRUE : JNI_FALSE;
871 }
872