Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 165640

Summary: [painting] GC.drawString draws 1 pixel too high compared to StyledText
Product: [Eclipse Project] Platform Reporter: Dani Megert <daniel_megert>
Component: TextAssignee: Dani Megert <daniel_megert>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: aleherb+eclipse, eclipse.felipe, snorthov
Version: 3.3   
Target Milestone: 3.3 M4   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
SWT snippet showing the bug none

Description Dani Megert CLA 2006-11-23 05:14:12 EST
N20061123-0010 and newer

We added a new feature to the editor that draws whitespace characters using a painter. To enable it either bind a key binding to the 'Show Whitespace Characters' command or do this:
1. Window > Customize perspective
2. click on the 'Commands' tab
3. check 'Editor Presentation'
4. click 'OK'
5. while a text editor is open click the pilcrow sign in the tool bar

==> out of the box 'Courier New Regular 10pt' is used as editor font and exactly that font exhibits the problem: the whitespace signs are drawn too high. This happens on Linux-GTK and WindowsXP.

Using a higher font size or another font (e.g. Arial) doesn't exhibit the problem.

Our WhitespaceCharacterPainter uses GC.drawString(...) and as x,y it uses what we get from StyledText.getLocationAtOffset(offset):
		Point pos= fTextWidget.getLocationAtOffset(offset);
		gc.drawString(s, pos.x, pos.y, true);


Since this new feature will appear in 3.3 M4 New and Noteworthy and because users with an out of the box workspace will run into this I'd like to have a fix for 3.3 M4 if possible.
Comment 1 Dani Megert CLA 2006-11-23 05:49:35 EST
Created attachment 54404 [details]
SWT snippet showing the bug
Comment 2 Felipe Heidrich CLA 2006-11-23 12:02:21 EST
Is not GC drawing one pixel too high, it is StyledText drawing  one pixel to low. The height of line in styledtext has to be high enough to fit the normal font, the bold, the italic, and the bold-italic. And when it draws it uses the max baseline of them all. That is avoid the line moving down when the user types the first bold word in the line.

The fix is to use TextLayou to draw (you will still need to set the baseline on it). Or use:
int baseline = text.getBaseline(index);
FontMetrics fm = event.gc.getFontMetrics();
int fontBaseline = fm.getAscent() + fm.getLeading();
event.gc.drawString(SEARCH_STRING, topLeft.x, topLeft.y + baseline - fontBaseline, true);

Using TextLayout:
int baseline = text.getBaseline(index);
int lineHeight = text.getLineHeight(index);
TextLayout tl = new TextLayout(display);
tl.setText(SEARCH_STRING);
tl.setFont(event.gc.getFont());
tl.setAscent(baseline);
tl.setDescent(lineHeight-baseline);
tl.draw(event.gc, topLeft.x, topLeft.y);
tl.dispose();

Note: it works with some fonts cause in some fonts the normal, the bold, the italic, and the bold-italic version all have the same metrics.

Final note: Personally I would use TextLayout instead of GC.drawString to workaround bug 78268.

Comment 3 Dani Megert CLA 2006-11-23 12:25:16 EST
Which of the two is cheaper? This code might be called often.
Comment 4 Felipe Heidrich CLA 2006-11-23 14:16:13 EST
(In reply to comment #3)
> Which of the two is cheaper? This code might be called often.

GC is cheaper
Comment 5 Steve Northover CLA 2006-11-28 17:48:58 EST
Note that TextLayout objects need to be disposed.
Comment 6 Dani Megert CLA 2006-12-01 04:55:34 EST
Fixed in HEAD.
Available in builds > N20061201-0010.