Skip to content

Commit fbc1b3a

Browse files
ShahzaibIbrahimakoch-yatta
authored andcommitted
[win32] Calculate Scaling for Font without Device#getDPI()
This commit solves two interconneted issues. Wrong layouting when text is printed and wrongly scaled fonts for printing. Device#getDPI returns values for Display and Printer that lead to wrong assumption using getDPI e.g. in the ScalingSWTFontRegistry. Printing text is broken because Printer DPI (e.g. 600) is way different from the Monitor DPI (96) that lead to inconsistent Font behavior in the different scenarios. Now font scaling is utilizing the zoom level instead of DPI in relavant scenarios.
1 parent 9d3673c commit fbc1b3a

File tree

5 files changed

+50
-42
lines changed

5 files changed

+50
-42
lines changed

bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,11 @@ void cacheLineData(StyledText styledText) {
304304
}
305305
}
306306
}
307-
Point screenDPI = styledText.getDisplay().getDPI();
307+
308308
Point printerDPI = printer.getDPI();
309309
resources = new HashMap<> ();
310+
int scaleFactorX = printerDPI.x / 100;
311+
int scaleFactorY = printerDPI.y / 100;
310312
for (int i = 0; i < lineCount; i++) {
311313
Color color = printerRenderer.getLineBackground(i, null);
312314
if (color != null) {
@@ -323,7 +325,7 @@ void cacheLineData(StyledText styledText) {
323325
}
324326
int indent = printerRenderer.getLineIndent(i, 0);
325327
if (indent != 0) {
326-
printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x);
328+
printerRenderer.setLineIndent(i, 1, indent * scaleFactorX);
327329
}
328330
}
329331
StyleRange[] styles = printerRenderer.styles;
@@ -367,17 +369,17 @@ void cacheLineData(StyledText styledText) {
367369
if (!printOptions.printTextFontStyle) {
368370
style.fontStyle = SWT.NORMAL;
369371
}
370-
style.rise = style.rise * printerDPI.y / screenDPI.y;
372+
style.rise = style.rise * scaleFactorY;
371373
GlyphMetrics metrics = style.metrics;
372374
if (metrics != null) {
373-
metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y;
374-
metrics.descent = metrics.descent * printerDPI.y / screenDPI.y;
375-
metrics.width = metrics.width * printerDPI.x / screenDPI.x;
375+
metrics.ascent = metrics.ascent * scaleFactorY;
376+
metrics.descent = metrics.descent * scaleFactorY;
377+
metrics.width = metrics.width * scaleFactorX;
376378
}
377379
}
378-
lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y;
380+
lineSpacing = styledText.lineSpacing * scaleFactorY;
379381
if (printOptions.printLineNumbers) {
380-
printMargin = 3 * printerDPI.x / screenDPI.x;
382+
printMargin = 3 * scaleFactorX;
381383
}
382384
}
383385
/**

bundles/org.eclipse.swt/Eclipse SWT Printing/win32/org/eclipse/swt/printing/Printer.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ protected void create(DeviceData deviceData) {
268268
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
269269
}
270270

271+
@Override
272+
protected int getDeviceZoom() {
273+
// Printer directly renders on pixel basis, so the zoom must be fixed to 100
274+
return 100;
275+
}
276+
271277
/**
272278
* Invokes platform specific functionality to allocate a new GC handle.
273279
* <p>
@@ -295,8 +301,9 @@ public long internal_new_GC(GCData data) {
295301
data.style |= SWT.LEFT_TO_RIGHT;
296302
}
297303
data.device = this;
298-
data.font = Font.win32_new(this, OS.GetCurrentObject(handle, OS.OBJ_FONT));
304+
data.font = Font.win32_new(this, OS.GetCurrentObject(handle, OS.OBJ_FONT), getDeviceZoom());
299305
isGCCreated = true;
306+
data.nativeZoom = getDeviceZoom();
300307
}
301308
return handle;
302309
}

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Device.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,20 @@ int computePixels(float height) {
268268
}
269269

270270
float computePoints(LOGFONT logFont, long hFont) {
271-
return computePoints(logFont, hFont, -1);
271+
return computePoints(logFont, hFont, SWT.DEFAULT);
272272
}
273273

274-
float computePoints(LOGFONT logFont, long hFont, int currentFontDPI) {
274+
float computePoints(LOGFONT logFont, long hFont, int zoom) {
275275
long hDC = internal_new_GC (null);
276-
int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY);
276+
277+
float conversionFactor = 72f;
278+
if (isAutoScalable() && zoom != SWT.DEFAULT) {
279+
// For auto scalable devices we need to use a dynamic
280+
// DPI value that is extracted from the zoom
281+
conversionFactor /= DPIUtil.mapZoomToDPI(zoom);
282+
} else {
283+
conversionFactor /= OS.GetDeviceCaps(hDC, OS.LOGPIXELSY);
284+
}
277285
int pixels = 0;
278286
if (logFont.lfHeight > 0) {
279287
/*
@@ -292,14 +300,7 @@ float computePoints(LOGFONT logFont, long hFont, int currentFontDPI) {
292300
pixels = -logFont.lfHeight;
293301
}
294302
internal_dispose_GC (hDC, null);
295-
float adjustedZoomFactor = 1.0f;
296-
if (currentFontDPI > 0) {
297-
// as Device::computePoints will always return point on the basis of the
298-
// primary monitor zoom, a custom zoomFactor must be calculated if the font
299-
// is used for a different zoom level
300-
adjustedZoomFactor *= (float) logPixelsY / (float) currentFontDPI;
301-
}
302-
return adjustedZoomFactor * pixels * 72f / logPixelsY;
303+
return pixels * conversionFactor;
303304
}
304305

305306
/**

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Font.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public FontData[] getFontData() {
213213
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
214214
LOGFONT logFont = new LOGFONT ();
215215
OS.GetObject(handle, LOGFONT.sizeof, logFont);
216-
float heightInPoints = device.computePoints(logFont, handle, DPIUtil.mapZoomToDPI(zoom));
216+
float heightInPoints = device.computePoints(logFont, handle, zoom);
217217
return new FontData[] {FontData.win32_new(logFont, heightInPoints)};
218218
}
219219

@@ -280,7 +280,7 @@ private static int extractZoom(Device device) {
280280
if (device == null) {
281281
return DPIUtil.getNativeDeviceZoom();
282282
}
283-
return DPIUtil.mapDPIToZoom(device._getDPIx());
283+
return device.getDeviceZoom();
284284
}
285285

286286
/**
@@ -331,8 +331,15 @@ public static Font win32_new(Device device, long handle) {
331331
* @since 3.126
332332
*/
333333
public static Font win32_new(Device device, long handle, int zoom) {
334-
Font font = win32_new(device, handle);
334+
Font font = new Font(device);
335335
font.zoom = zoom;
336+
font.handle = handle;
337+
/*
338+
* When created this way, Font doesn't own its .handle, and
339+
* for this reason it can't be disposed. Tell leak detector
340+
* to just ignore it.
341+
*/
342+
font.ignoreNonDisposed();
336343
return font;
337344
}
338345

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ScalingSWTFontRegistry.java

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ private Font getScaledFont(int targetZoom) {
5353

5454
private Font scaleFont(int zoom) {
5555
FontData fontData = baseFont.getFontData()[0];
56-
fontData.data.lfHeight = computePixels(zoom, fontData);
56+
int baseZoom = computeZoom(fontData);
57+
int zoomScaleFactor = Math.round(1.0f * zoom / baseZoom);
58+
fontData.data.lfHeight *= zoomScaleFactor;
5759
Font scaledFont = Font.win32_new(device, fontData, zoom);
5860
addScaledFont(zoom, scaledFont);
5961
return scaledFont;
@@ -168,24 +170,13 @@ private Font getOrCreateFont(ScaledFontContainer container, int zoom) {
168170
}
169171

170172
private int computeZoom(FontData fontData) {
171-
int dpi = device.getDPI().x;
172-
int pixelsAtPrimaryMonitorZoom = computePixels(fontData.height);
173-
int value = DPIUtil.mapDPIToZoom(dpi) * fontData.data.lfHeight / pixelsAtPrimaryMonitorZoom;
174-
return value;
175-
}
176-
177-
private int computePixels(int zoom, FontData fontData) {
178-
int dpi = device.getDPI().x;
179-
int adjustedLogFontHeight = computePixels(fontData.height);
180-
int primaryZoom = DPIUtil.mapDPIToZoom(dpi);
181-
if (zoom != primaryZoom) {
182-
adjustedLogFontHeight *= (1f * zoom / primaryZoom);
173+
int pixelHeight = fontData.data.lfHeight;
174+
float currentPointHeight = fontData.height;
175+
if (pixelHeight == 0 || Math.abs(currentPointHeight) < 0.001) {
176+
// if there is no font yet available, we use a defined zoom
177+
return 100;
183178
}
184-
return adjustedLogFontHeight;
185-
}
186-
187-
private int computePixels(float height) {
188-
int dpi = device.getDPI().x;
189-
return -(int)(0.5f + (height * dpi / 72f));
179+
float pointHeightOn100 = -(pixelHeight / 96f * 72f);
180+
return Math.round(100.0f * pointHeightOn100 / currentPointHeight);
190181
}
191182
}

0 commit comments

Comments
 (0)