Bug 537417 - [Win] FontMetrics returns different size after first drawText
Summary: [Win] FontMetrics returns different size after first drawText
Status: REOPENED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.9   Edit
Hardware: PC Windows 10
: P3 major with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-07-26 09:54 EDT by Thomas Singer CLA
Modified: 2021-04-06 03:23 EDT (History)
5 users (show)

See Also:


Attachments
Sample code (1.28 KB, text/plain)
2018-07-26 09:54 EDT, Thomas Singer CLA
no flags Details
Screenshot of the result on Windows 10 (15.28 KB, image/png)
2018-07-26 09:55 EDT, Thomas Singer CLA
no flags Details
Another snippet which can reproduce the problem with getHeight() method from FontMetrics class (1.03 KB, application/octet-stream)
2019-04-08 08:01 EDT, Nelu Cristian Tone CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Singer CLA 2018-07-26 09:54:26 EDT
Please run the attached snippet on Windows (I'm on Windows 10 with 200% zoom level; latest SWT master commit). The code will draw a couple of lines of text with a leading rectangle in the size of the font height reported by the fontMetrics. Though no font has been changed, the returned font height changes after the first drawText operation.
Comment 1 Thomas Singer CLA 2018-07-26 09:54:57 EDT
Created attachment 275144 [details]
Sample code
Comment 2 Thomas Singer CLA 2018-07-26 09:55:18 EDT
Created attachment 275145 [details]
Screenshot of the result on Windows 10
Comment 3 Alexandr Miloslavskiy CLA 2018-11-26 09:41:43 EST
Analysis:

Unfortunately, entire 'org.eclipse.swt.graphics.GC' is designed wrong, which causes multiple problems like the one reported.

The key problem is that WINAPI device context is used through two different "handles" at the same time:
1) GDI 'HDC'
2) GDI+ 'Graphics'
Where 'Graphics' is high-level wrapper for 'HDC'. SWT believes it's the only owner of 'HDC' and selected drawing objects will remain untouched. GDI+ also believes it's the only owner and can change drawing objects to its liking. This obviously causes unexpected conflicts like in the reported bug.

Microsoft explicitly documented that 'HDC' and 'Graphics' should not be used at the same time, see [1]. Some quotes from it:
* Generally, you should not interleave GDI and GDI+ calls on one target object.
* For example, it is okay to wrap a Graphics object around an HDC, but you should not access the HDC directly from GDI until the Graphics object is destroyed.
* Once the Graphics object is attached to the HDC, no GDI operations should be performed on the HDC until the Graphics object is destroyed or goes out of scope.
* If GDI output is required on the HDC, either destroy the Graphics object before using the original HDC or use Graphics::GetHDC() to get a new HDC and then follow the rules described earlier in this article for interoperability while using GDI on a GDI+ object.
* GDI+ output should not be attempted on the Graphics object for the life of the HDC (that is, until Graphics::ReleaseHDC() is called).

Some other examples of GC methods with problems:
* drawStringInPixels
* drawTextInPixels
* getAdvanceWidth

It seems that rather big changes will be needed to solve problem correctly.

[1] https://support.microsoft.com/en-us/help/311221/info-interoperability-between-gdi-and-gdi
Comment 4 Thomas Singer CLA 2018-11-26 12:49:29 EST
Alexandr, do you think fixing this would need SWT-API changes or could purely be managed inside the Windows GC implementation?
Comment 5 Alexandr Miloslavskiy CLA 2018-11-26 13:23:42 EST
It should be possible to fix it by changing Windows GC implementation, without any changes to public method signatures or anything like that.
Comment 6 Nelu Cristian Tone CLA 2019-04-08 08:01:24 EDT
Created attachment 278167 [details]
Another snippet which can reproduce the problem with getHeight() method from FontMetrics class

Another snippet which can reproduce the problem with getHeight() method from FontMetrics class.

I found two workarounds for the problem from this snippet:
1. Call gc.setAdvanced(false) at the begining and do not use anti-alias during painting
2. Reverse the order of the following lines in the snippet code
final int width = e.gc.stringExtent(text).x;
final int height = e.gc.getFontMetrics().getHeight();
Comment 7 Thomas Singer CLA 2019-04-16 03:17:29 EDT
Maybe bug 520974 is related?
Comment 8 Eclipse Genie CLA 2021-04-06 03:00:28 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 9 Thomas Singer CLA 2021-04-06 03:22:03 EDT
Please reopen.
Comment 10 Andrey Loskutov CLA 2021-04-06 03:23:45 EDT
.