1 /*
2  * Copyright (c) 1999, 2011, 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 <awt.h>
27 #include <sun_awt_Win32GraphicsEnvironment.h>
28 #include <sun_awt_Win32FontManager.h>
29 #include "awt_Canvas.h"
30 #include "awt_Win32GraphicsDevice.h"
31 #include "Devices.h"
32 #include "WindowsFlags.h"
33 #include "DllUtil.h"
34 
35 BOOL DWMIsCompositionEnabled();
36 
initScreens(JNIEnv * env)37 void initScreens(JNIEnv *env) {
38 
39     if (!Devices::UpdateInstance(env)) {
40         JNU_ThrowInternalError(env, "Could not update the devices array.");
41         return;
42     }
43 }
44 
45 /**
46  * This function attempts to make a Win32 API call to
47  *   BOOL SetProcessDPIAware(VOID);
48  * which is only present on Windows Vista, and which instructs the
49  * Vista Windows Display Manager that this application is High DPI Aware
50  * and does not need to be scaled by the WDM and lied about the
51  * actual system dpi.
52  */
53 static void
SetProcessDPIAwareProperty()54 SetProcessDPIAwareProperty()
55 {
56     typedef BOOL (WINAPI SetProcessDPIAwareFunc)(void);
57     static BOOL bAlreadySet = FALSE;
58 
59     // setHighDPIAware is set in WindowsFlags.cpp
60     if (!setHighDPIAware || bAlreadySet) {
61         return;
62     }
63 
64     bAlreadySet = TRUE;
65 
66     HMODULE hLibUser32Dll = JDK_LoadSystemLibrary("user32.dll");
67 
68     if (hLibUser32Dll != NULL) {
69         SetProcessDPIAwareFunc *lpSetProcessDPIAware =
70             (SetProcessDPIAwareFunc*)GetProcAddress(hLibUser32Dll,
71                                                     "SetProcessDPIAware");
72         if (lpSetProcessDPIAware != NULL) {
73             lpSetProcessDPIAware();
74         }
75         ::FreeLibrary(hLibUser32Dll);
76     }
77 }
78 
79 #define DWM_COMP_UNDEFINED (~(TRUE|FALSE))
80 static int dwmIsCompositionEnabled = DWM_COMP_UNDEFINED;
81 
82 /**
83  * This function is called from toolkit event handling code when
84  * WM_DWMCOMPOSITIONCHANGED event is received
85  */
DWMResetCompositionEnabled()86 void DWMResetCompositionEnabled() {
87     dwmIsCompositionEnabled = DWM_COMP_UNDEFINED;
88     (void)DWMIsCompositionEnabled();
89 }
90 
91 /**
92  * Returns true if dwm composition is enabled, false if it is not applicable
93  * (if the OS is not Vista) or dwm composition is disabled.
94  */
DWMIsCompositionEnabled()95 BOOL DWMIsCompositionEnabled() {
96     // cheaper to check than whether it's vista or not
97     if (dwmIsCompositionEnabled != DWM_COMP_UNDEFINED) {
98         return (BOOL)dwmIsCompositionEnabled;
99     }
100 
101     if (!IS_WINVISTA) {
102         dwmIsCompositionEnabled = FALSE;
103         return FALSE;
104     }
105 
106     BOOL bRes = FALSE;
107 
108     try {
109         BOOL bEnabled;
110         HRESULT res = DwmAPI::DwmIsCompositionEnabled(&bEnabled);
111         if (SUCCEEDED(res)) {
112             bRes = bEnabled;
113             J2dTraceLn1(J2D_TRACE_VERBOSE, " composition enabled: %d",bRes);
114         } else {
115             J2dTraceLn1(J2D_TRACE_ERROR,
116                     "IsDWMCompositionEnabled: error %x when detecting"\
117                     "if composition is enabled", res);
118         }
119     } catch (const DllUtil::Exception &) {
120         J2dTraceLn(J2D_TRACE_ERROR,
121                 "IsDWMCompositionEnabled: no DwmIsCompositionEnabled() "\
122                 "in dwmapi.dll or dwmapi.dll cannot be loaded");
123     }
124 
125     dwmIsCompositionEnabled = bRes;
126 
127     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
128     JNU_CallStaticMethodByName(env, NULL,
129                               "sun/awt/Win32GraphicsEnvironment",
130                               "dwmCompositionChanged", "(Z)V", (jboolean)bRes);
131     return bRes;
132 }
133 
134 /*
135  * Class:     sun_awt_Win32GraphicsEnvironment
136  * Method:    initDisplay
137  * Signature: ()V
138  */
139 JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsEnvironment_initDisplay(JNIEnv * env,jclass thisClass)140 Java_sun_awt_Win32GraphicsEnvironment_initDisplay(JNIEnv *env,
141                                                   jclass thisClass)
142 {
143     // This method needs to be called prior to any display-related activity
144     SetProcessDPIAwareProperty();
145 
146     DWMIsCompositionEnabled();
147 
148     initScreens(env);
149 }
150 
151 /*
152  * Class:     sun_awt_Win32GraphicsEnvironment
153  * Method:    getNumScreens
154  * Signature: ()I
155  */
156 JNIEXPORT jint JNICALL
Java_sun_awt_Win32GraphicsEnvironment_getNumScreens(JNIEnv * env,jobject thisobj)157 Java_sun_awt_Win32GraphicsEnvironment_getNumScreens(JNIEnv *env,
158                                                     jobject thisobj)
159 {
160     Devices::InstanceAccess devices;
161     return devices->GetNumDevices();
162 }
163 
164 /*
165  * Class:     sun_awt_Win32GraphicsEnvironment
166  * Method:    getDefaultScreen
167  * Signature: ()I
168  */
169 JNIEXPORT jint JNICALL
Java_sun_awt_Win32GraphicsEnvironment_getDefaultScreen(JNIEnv * env,jobject thisobj)170 Java_sun_awt_Win32GraphicsEnvironment_getDefaultScreen(JNIEnv *env,
171                                                        jobject thisobj)
172 {
173     return AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
174 }
175 
176 /*
177  * Class:     sun_awt_Win32FontManager
178  * Method:    registerFontWithPlatform
179  * Signature: (Ljava/lang/String;)V
180  */
181 JNIEXPORT void JNICALL
Java_sun_awt_Win32FontManager_registerFontWithPlatform(JNIEnv * env,jclass cl,jstring fontName)182 Java_sun_awt_Win32FontManager_registerFontWithPlatform(JNIEnv *env,
183                                                        jclass cl,
184                                                        jstring fontName)
185 {
186     LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, JNI_FALSE);
187     if (file) {
188         ::AddFontResourceEx(file, FR_PRIVATE, NULL);
189         JNU_ReleaseStringPlatformChars(env, fontName, file);
190     }
191 }
192 
193 
194 /*
195  * Class:     sun_awt_Win32FontManagerEnvironment
196  * Method:    deRegisterFontWithPlatform
197  * Signature: (Ljava/lang/String;)V
198  *
199  * This method intended for future use.
200  */
201 JNIEXPORT void JNICALL
Java_sun_awt_Win32FontManager_deRegisterFontWithPlatform(JNIEnv * env,jclass cl,jstring fontName)202 Java_sun_awt_Win32FontManager_deRegisterFontWithPlatform(JNIEnv *env,
203                                                          jclass cl,
204                                                          jstring fontName)
205 {
206     LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, JNI_FALSE);
207     if (file) {
208         ::RemoveFontResourceEx(file, FR_PRIVATE, NULL);
209         JNU_ReleaseStringPlatformChars(env, fontName, file);
210     }
211 }
212 
213 #define EUDCKEY_JA_JP  L"EUDC\\932"
214 #define EUDCKEY_ZH_CN  L"EUDC\\936"
215 #define EUDCKEY_ZH_TW  L"EUDC\\950"
216 #define EUDCKEY_KO_KR  L"EUDC\\949"
217 #define EUDCKEY_EN_US  L"EUDC\\1252"
218 #define LANGID_JA_JP   0x411
219 #define LANGID_ZH_CN   0x0804
220 #define LANGID_ZH_SG   0x1004
221 #define LANGID_ZH_TW   0x0404
222 #define LANGID_ZH_HK   0x0c04
223 #define LANGID_ZH_MO   0x1404
224 #define LANGID_KO_KR   0x0412
225 #define LANGID_EN_US   0x0409
226 
227 
228 JNIEXPORT jstring JNICALL
Java_sun_awt_Win32FontManager_getEUDCFontFile(JNIEnv * env,jclass cl)229 Java_sun_awt_Win32FontManager_getEUDCFontFile(JNIEnv *env, jclass cl) {
230     int    rc;
231     HKEY   key;
232     DWORD  type;
233     WCHAR  fontPathBuf[MAX_PATH + 1];
234     unsigned long fontPathLen = MAX_PATH + 1;
235     WCHAR  tmpPath[MAX_PATH + 1];
236     LPWSTR fontPath = fontPathBuf;
237     LPWSTR eudcKey = NULL;
238 
239     LANGID langID = GetSystemDefaultLangID();
240     //lookup for encoding ID, EUDC only supported in
241     //codepage 932, 936, 949, 950 (and unicode)
242     // On Windows 7, at least for me, it shows up in Cp1252 if
243     // I create a custom font. Might as well support that as it makes
244     // verification easier.
245     if (langID == LANGID_JA_JP) {
246         eudcKey = EUDCKEY_JA_JP;
247     } else if (langID == LANGID_ZH_CN || langID == LANGID_ZH_SG) {
248         eudcKey = EUDCKEY_ZH_CN;
249     } else if (langID == LANGID_ZH_HK || langID == LANGID_ZH_TW ||
250                langID == LANGID_ZH_MO) {
251       eudcKey = EUDCKEY_ZH_TW;
252     } else if (langID == LANGID_KO_KR) {
253         eudcKey = EUDCKEY_KO_KR;
254     } else if (langID == LANGID_EN_US) {
255         eudcKey = EUDCKEY_EN_US;
256     } else {
257         return NULL;
258     }
259 
260     rc = RegOpenKeyEx(HKEY_CURRENT_USER, eudcKey, 0, KEY_READ, &key);
261     if (rc != ERROR_SUCCESS) {
262         return NULL;
263     }
264     rc = RegQueryValueEx(key,
265                          L"SystemDefaultEUDCFont",
266                          0,
267                          &type,
268                          (LPBYTE)fontPath,
269                          &fontPathLen);
270     RegCloseKey(key);
271     if (rc != ERROR_SUCCESS || type != REG_SZ) {
272         return NULL;
273     }
274     fontPath[fontPathLen] = L'\0';
275     if (wcsstr(fontPath, L"%SystemRoot%")) {
276         //if the fontPath includes %SystemRoot%
277         LPWSTR systemRoot = _wgetenv(L"SystemRoot");
278         if (systemRoot != NULL
279             && swprintf(tmpPath, MAX_PATH, L"%s%s", systemRoot, fontPath + 12) != -1) {
280             fontPath = tmpPath;
281         }
282         else {
283             return NULL;
284         }
285     } else if (wcscmp(fontPath, L"EUDC.TTE") == 0) {
286         //else to see if it only inludes "EUDC.TTE"
287         WCHAR systemRoot[MAX_PATH + 1];
288         if (GetWindowsDirectory(systemRoot, MAX_PATH + 1) != 0) {
289             swprintf(tmpPath, MAX_PATH, L"%s\\FONTS\\EUDC.TTE", systemRoot);
290             fontPath = tmpPath;
291         }
292         else {
293             return NULL;
294         }
295     }
296     return JNU_NewStringPlatform(env, fontPath);
297 }
298 
299 /*
300  * Class:     sun_awt_Win32GraphicsEnvironment
301  * Method:    getXResolution
302  * Signature: ()I
303  */
304 JNIEXPORT jint JNICALL
Java_sun_awt_Win32GraphicsEnvironment_getXResolution(JNIEnv * env,jobject wge)305 Java_sun_awt_Win32GraphicsEnvironment_getXResolution(JNIEnv *env, jobject wge)
306 {
307     TRY;
308 
309     HWND hWnd = ::GetDesktopWindow();
310     HDC hDC = ::GetDC(hWnd);
311     jint result = ::GetDeviceCaps(hDC, LOGPIXELSX);
312     ::ReleaseDC(hWnd, hDC);
313     return result;
314 
315     CATCH_BAD_ALLOC_RET(0);
316 }
317 
318 /*
319  * Class:     sun_awt_Win32GraphicsEnvironment
320  * Method:    getYResolution
321  * Signature: ()I
322  */
323 JNIEXPORT jint JNICALL
Java_sun_awt_Win32GraphicsEnvironment_getYResolution(JNIEnv * env,jobject wge)324 Java_sun_awt_Win32GraphicsEnvironment_getYResolution(JNIEnv *env, jobject wge)
325 {
326     TRY;
327 
328     HWND hWnd = ::GetDesktopWindow();
329     HDC hDC = ::GetDC(hWnd);
330     jint result = ::GetDeviceCaps(hDC, LOGPIXELSY);
331     ::ReleaseDC(hWnd, hDC);
332     return result;
333 
334     CATCH_BAD_ALLOC_RET(0);
335 }
336 
337 /*
338  * Class:     sun_awt_Win32GraphicsEnvironment
339  * Method:    isVistaOS
340  * Signature: ()Z
341  */
Java_sun_awt_Win32GraphicsEnvironment_isVistaOS(JNIEnv * env,jclass wgeclass)342 JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsEnvironment_isVistaOS
343   (JNIEnv *env, jclass wgeclass)
344 {
345     return IS_WINVISTA;
346 }
347