8076545: Text size is twice bigger under Windows L&F on Win 8.1 with HiDPI display

8149453: [hidpi] JFileChooser does not scale properly on Windows with HiDPI display and Windows L&F
8149368: [hidpi] JLabel font is twice bigger than JTextArea font on Windows 7,HiDPI, Windows L&F

Reviewed-by: flar, serb
This commit is contained in:
Alexander Scherbatiy 2016-03-15 09:16:56 -07:00
parent 1948e2f95f
commit b6e44767c0
4 changed files with 142 additions and 35 deletions

View File

@ -31,6 +31,8 @@
#include "awt_Object.h"
#include "awt_Component.h"
#include "math.h"
// Important note about VC6 and VC7 (or XP Platform SDK) !
//
// These type definitions have been imported from UxTheme.h
@ -745,6 +747,23 @@ JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPosition
return NULL;
}
void rescale(SIZE *size) {
HWND hWnd = ::GetDesktopWindow();
HDC hDC = ::GetDC(hWnd);
int dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX);
int dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY);
if (dpiX !=0 && dpiX != 96) {
float invScaleX = 96.0f / dpiX;
size->cx = (int)round(size->cx * invScaleX);
}
if (dpiY != 0 && dpiY != 96) {
float invScaleY = 96.0f / dpiY;
size->cy = (int)round(size->cy * invScaleY);
}
::ReleaseDC(hWnd, hDC);
}
/*
* Class: sun_awt_windows_ThemeReader
* Method: getPartSize
@ -770,6 +789,8 @@ JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPartSize
dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V");
CHECK_NULL_RETURN(dimMID, NULL);
}
rescale(&size);
jobject dimObj = env->NewObject(dimClassID, dimMID, size.cx, size.cy);
if (safe_ExceptionOccurred(env)) {
env->ExceptionDescribe();

View File

@ -35,6 +35,8 @@
#include <shellapi.h>
#include <shlobj.h>
#include "math.h"
// WDesktopProperties fields
jfieldID AwtDesktopProperties::pDataID = 0;
jmethodID AwtDesktopProperties::setBooleanPropertyID = 0;
@ -79,18 +81,35 @@ void AwtDesktopProperties::GetWindowsParameters() {
}
}
void getInvScale(float &invScaleX, float &invScaleY) {
HWND hWnd = ::GetDesktopWindow();
HDC hDC = ::GetDC(hWnd);
int dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX);
int dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY);
::ReleaseDC(hWnd, hDC);
invScaleX = (dpiX == 0.0f) ? 1.0f : 96.0f / dpiX;
invScaleY = (dpiY == 0.0f) ? 1.0f : 96.0f / dpiY;
}
int rescale(int value, float invScale){
return invScale == 1.0f ? value : (int)round(value * invScale);
}
void AwtDesktopProperties::GetSystemProperties() {
HDC dc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
if (dc != NULL) {
try {
SetFontProperty(dc, ANSI_FIXED_FONT, TEXT("win.ansiFixed.font"));
SetFontProperty(dc, ANSI_VAR_FONT, TEXT("win.ansiVar.font"));
SetFontProperty(dc, DEVICE_DEFAULT_FONT, TEXT("win.deviceDefault.font"));
SetFontProperty(dc, DEFAULT_GUI_FONT, TEXT("win.defaultGUI.font"));
SetFontProperty(dc, OEM_FIXED_FONT, TEXT("win.oemFixed.font"));
SetFontProperty(dc, SYSTEM_FONT, TEXT("win.system.font"));
SetFontProperty(dc, SYSTEM_FIXED_FONT, TEXT("win.systemFixed.font"));
float invScaleX;
float invScaleY;
getInvScale(invScaleX, invScaleY);
SetFontProperty(dc, ANSI_FIXED_FONT, TEXT("win.ansiFixed.font"), 1.0f);
SetFontProperty(dc, ANSI_VAR_FONT, TEXT("win.ansiVar.font"), 1.0f);
SetFontProperty(dc, DEVICE_DEFAULT_FONT, TEXT("win.deviceDefault.font"), 1.0f);
SetFontProperty(dc, DEFAULT_GUI_FONT, TEXT("win.defaultGUI.font"), invScaleY);
SetFontProperty(dc, OEM_FIXED_FONT, TEXT("win.oemFixed.font"), 1.0f);
SetFontProperty(dc, SYSTEM_FONT, TEXT("win.system.font"), 1.0f);
SetFontProperty(dc, SYSTEM_FIXED_FONT, TEXT("win.systemFixed.font"), 1.0f);
}
catch (std::bad_alloc&) {
DeleteDC(dc);
@ -266,31 +285,35 @@ void AwtDesktopProperties::GetNonClientParameters() {
}
VERIFY( SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncmetrics.cbSize, &ncmetrics, FALSE) );
SetFontProperty( TEXT("win.frame.captionFont"), ncmetrics.lfCaptionFont );
SetIntegerProperty( TEXT("win.frame.captionHeight"), ncmetrics.iCaptionHeight );
SetIntegerProperty( TEXT("win.frame.captionButtonWidth"), ncmetrics.iCaptionWidth );
SetIntegerProperty( TEXT("win.frame.captionButtonHeight"), ncmetrics.iCaptionHeight );
SetFontProperty( TEXT("win.frame.smallCaptionFont"), ncmetrics.lfSmCaptionFont );
SetIntegerProperty( TEXT("win.frame.smallCaptionHeight"), ncmetrics.iSmCaptionHeight );
SetIntegerProperty( TEXT("win.frame.smallCaptionButtonWidth"), ncmetrics.iSmCaptionWidth );
SetIntegerProperty( TEXT("win.frame.smallCaptionButtonHeight"), ncmetrics.iSmCaptionHeight );
SetIntegerProperty( TEXT("win.frame.sizingBorderWidth"), ncmetrics.iBorderWidth );
float invScaleX;
float invScaleY;
getInvScale(invScaleX, invScaleY);
SetFontProperty(TEXT("win.frame.captionFont"), ncmetrics.lfCaptionFont, invScaleY);
SetIntegerProperty(TEXT("win.frame.captionHeight"), rescale(ncmetrics.iCaptionHeight, invScaleY));
SetIntegerProperty(TEXT("win.frame.captionButtonWidth"), rescale(ncmetrics.iCaptionWidth, invScaleX));
SetIntegerProperty(TEXT("win.frame.captionButtonHeight"), rescale(ncmetrics.iCaptionHeight, invScaleY));
SetFontProperty(TEXT("win.frame.smallCaptionFont"), ncmetrics.lfSmCaptionFont, invScaleY);
SetIntegerProperty(TEXT("win.frame.smallCaptionHeight"), rescale(ncmetrics.iSmCaptionHeight, invScaleY));
SetIntegerProperty(TEXT("win.frame.smallCaptionButtonWidth"), rescale(ncmetrics.iSmCaptionWidth, invScaleX));
SetIntegerProperty(TEXT("win.frame.smallCaptionButtonHeight"), rescale(ncmetrics.iSmCaptionHeight, invScaleY));
SetIntegerProperty(TEXT("win.frame.sizingBorderWidth"), rescale(ncmetrics.iBorderWidth, invScaleX));
// menu properties
SetFontProperty( TEXT("win.menu.font"), ncmetrics.lfMenuFont );
SetIntegerProperty( TEXT("win.menu.height"), ncmetrics.iMenuHeight );
SetIntegerProperty( TEXT("win.menu.buttonWidth"), ncmetrics.iMenuWidth );
SetFontProperty(TEXT("win.menu.font"), ncmetrics.lfMenuFont, invScaleY);
SetIntegerProperty(TEXT("win.menu.height"), rescale(ncmetrics.iMenuHeight, invScaleY));
SetIntegerProperty(TEXT("win.menu.buttonWidth"), rescale(ncmetrics.iMenuWidth, invScaleX));
// scrollbar properties
SetIntegerProperty( TEXT("win.scrollbar.width"), ncmetrics.iScrollWidth );
SetIntegerProperty( TEXT("win.scrollbar.height"), ncmetrics.iScrollHeight );
SetIntegerProperty(TEXT("win.scrollbar.width"), rescale(ncmetrics.iScrollWidth, invScaleX));
SetIntegerProperty(TEXT("win.scrollbar.height"), rescale(ncmetrics.iScrollHeight, invScaleY));
// status bar and tooltip properties
SetFontProperty( TEXT("win.status.font"), ncmetrics.lfStatusFont );
SetFontProperty( TEXT("win.tooltip.font"), ncmetrics.lfStatusFont );
SetFontProperty(TEXT("win.status.font"), ncmetrics.lfStatusFont, invScaleY);
SetFontProperty(TEXT("win.tooltip.font"), ncmetrics.lfStatusFont, invScaleY);
// message box properties
SetFontProperty( TEXT("win.messagebox.font"), ncmetrics.lfMessageFont );
SetFontProperty(TEXT("win.messagebox.font"), ncmetrics.lfMessageFont, invScaleY);
}
void AwtDesktopProperties::GetIconParameters() {
@ -302,10 +325,13 @@ void AwtDesktopProperties::GetIconParameters() {
iconmetrics.cbSize = sizeof(iconmetrics);
VERIFY( SystemParametersInfo(SPI_GETICONMETRICS, iconmetrics.cbSize, &iconmetrics, FALSE) );
SetIntegerProperty(TEXT("win.icon.hspacing"), iconmetrics.iHorzSpacing);
SetIntegerProperty(TEXT("win.icon.vspacing"), iconmetrics.iVertSpacing);
float invScaleX;
float invScaleY;
getInvScale(invScaleX, invScaleY);
SetIntegerProperty(TEXT("win.icon.hspacing"), rescale(iconmetrics.iHorzSpacing, invScaleX));
SetIntegerProperty(TEXT("win.icon.vspacing"), rescale(iconmetrics.iVertSpacing, invScaleY));
SetBooleanProperty(TEXT("win.icon.titleWrappingOn"), iconmetrics.iTitleWrap != 0);
SetFontProperty(TEXT("win.icon.font"), iconmetrics.lfFont);
SetFontProperty(TEXT("win.icon.font"), iconmetrics.lfFont, invScaleY);
}
/*
Windows settings for these are also in the registry
@ -718,6 +744,7 @@ void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) {
}
void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) {
jstring key = JNU_NewStringPlatform(GetEnv(), propName);
if (key == NULL) {
throw std::bad_alloc();
@ -752,8 +779,8 @@ void AwtDesktopProperties::SetColorProperty(LPCTSTR propName, DWORD value) {
}
void AwtDesktopProperties::SetFontProperty(HDC dc, int fontID,
LPCTSTR propName) {
HGDIOBJ font = GetStockObject(fontID);
LPCTSTR propName, float invScale) {
HGDIOBJ font = GetStockObject(fontID);
if (font != NULL && SelectObject(dc, font) != NULL) {
int length = GetTextFace(dc, 0, NULL);
@ -789,8 +816,8 @@ void AwtDesktopProperties::SetFontProperty(HDC dc, int fontID,
throw std::bad_alloc();
}
jint pointSize = metrics.tmHeight -
metrics.tmInternalLeading;
jint pointSize = rescale(metrics.tmHeight -
metrics.tmInternalLeading, invScale);
jint style = java_awt_Font_PLAIN;
if (metrics.tmWeight >= FW_BOLD) {
@ -818,7 +845,8 @@ void AwtDesktopProperties::SetFontProperty(HDC dc, int fontID,
}
}
void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & font) {
void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & font,
float invScale) {
jstring fontName;
jint pointSize;
jint style;
@ -836,7 +864,7 @@ void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & fon
ReleaseDC(NULL, hdc);
#endif
// Java uses point sizes, but assumes 1 pixel = 1 point
pointSize = -font.lfHeight;
pointSize = rescale(-font.lfHeight, invScale);
// convert Windows font style to Java style
style = java_awt_Font_PLAIN;

View File

@ -73,8 +73,8 @@ class AwtDesktopProperties {
void SetIntegerProperty(LPCTSTR, int);
void SetStringProperty(LPCTSTR, LPTSTR);
void SetColorProperty(LPCTSTR, DWORD);
void SetFontProperty(HDC, int, LPCTSTR);
void SetFontProperty(LPCTSTR, const LOGFONT &);
void SetFontProperty(HDC, int, LPCTSTR, float invScale);
void SetFontProperty(LPCTSTR, const LOGFONT &, float invScale);
void SetSoundProperty(LPCTSTR, LPCTSTR);
JNIEnv * GetEnv() {

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.metal.MetalLookAndFeel;
/*
* @test
* @bug 8076545
* @summary Text size is twice bigger under Windows L&F on Win 8.1 with
* HiDPI display
*/
public class FontScalingTest {
public static void main(String[] args) throws Exception {
int metalFontSize = getFontSize(MetalLookAndFeel.class.getName());
int systemFontSize = getFontSize(UIManager.getSystemLookAndFeelClassName());
if (Math.abs(systemFontSize - metalFontSize) > 8) {
throw new RuntimeException("System L&F is too big!");
}
}
private static int getFontSize(String laf) throws Exception {
UIManager.setLookAndFeel(laf);
final int[] sizes = new int[1];
SwingUtilities.invokeAndWait(() -> {
JButton button = new JButton("Test");
sizes[0] = button.getFont().getSize();
});
return sizes[0];
}
}