GNOME Bugzilla – Bug 81895
GC setting linewidth is not isotropic
Last modified: 2011-02-04 16:16:03 UTC
A call to: gdk_gc_set_line_attributes(gc, line_width, line_style, GDK_CAP_ROUND, GDK_JOIN_ROUND); Followed by some line drawing calls at 0 and 45 degrees causes the 45 degree lines to be roughly sqrt(2)/2 wider than the 0 degree line.
Please attach a minimal but complete test program...
Implementing a whole own line renderer would be required to fix the massive limitations of the win16 GDI living under Windows9x. I've done some small improvements for straight horizontal and vertical lines recently but adding a whole renderer for a dying platform is really out of my scope. BTW: my 'simple but complete' test program is my Dia port :-) http://hans.breuer.org/dia
Not fixing it will mean that vector drawing gtk applications will always looking butt ugly under Windows-98. The platform might be dying, but since upgrading to newer Windows versions costs money, there is a huge amount of users that will remain with Windows-98 until their computers die. (Unless we manage to upgrade them to Linux. 8-) It seems to me that if the line drawing primitives are supported under GtkFB it shouldn't be much of an issue to get them to work under the higher level platform of Windows98 as well. Performance might be down the drain. But then, I don't know a thing about Windows API, and I really don't have any interest in learning. That's why I turned to Gtk/Gdk for my application in the first place.
Is the problem that the Win9x GDI itself draws diagonal lines too wide (but NT/2K/XP GDI doesn't), or that GDK on Win9x draws horizontal and vertical lines too narrow? Is the relative error constant regardless of line width, or is it more noticeable with relatively narrow lines?
Created attachment 8571 [details] Example program that draws lines at various widths and angles.
I've add as an attachement a small program that shows as the problem. I hope to add screenshots for the rendering of this program on various platforms tonight. This example also shows bug #81894.
I almost forgot. In my first comment I of course meant sqrt(2) wider.
Created attachment 8584 [details] Illustration of difference between rendering on win98 and X.
I just uploaded an image attachement that illustrates the difference in the rendering on windows 98 and on X. The image contains four different colors: black and white - rendering the same on win98 and on X red - pixels part of the line on win98 but not on X green - pixels part of the line on X but not on win98 The image has been scaled by a factor of two and I added a number in the center of each star with the line width used in the rendering. Between linewidths 2 and 5 there is a substantial difference in the rendering of lines at angles other than 0 and 90 degrees. Consider e.g. the 45 degree line at line width 4 which is three pixels wider than the corresponding rendering at X! At very thick lines this difference dissappear. There is a also a difference in the rendering of the caps, but I'll describe that in connection to bug #81894. I hope this helps in tracking down the bug.
Do you have the possibility to generate a similar image for X11 vs. NT, 2K or XP? (I can check it myself, too, but it would be nice to have a similar image here.)
Created attachment 8586 [details] Image produced by draw-star on Win2k.
I guess one could add to GDK/Win32 code to reduce the pen width used when drawing diagonal lines of width 4..6 or so on Win9x/Me. Is it worth it? Or might the behaviour depend on the display driver? In that case it probably isn't possible to do anything about it, except file a bug report with the card manufacturer...
I just realized that there is another bug in the line drawing that only appears on Win2k (We should add a XP screen shot as well). If you look in a zoomed up version on the 15,30 and 45 degree lines you will see that the outmost end of the line has an some additional vertical pixels added, that make no sense. I guess this is a bug in Win2k bug though and has nothing to do with gdk...
Ah, yes, those extra drawn pixels are because of code in gdk/win32 that tries to compensate for LineTo()'s "draws a line from the current position up to, but not including, the specified point" behaviour. But that code seems to be harmful, I'll remove it. The GDI docs are also rather vague, it's hard to say what they actually mean when they talk about "not including the end point". Sigh. Why can't Microsoft use mathematical, concise definitions like X11 does.
Simply _not_ drawing the endpoint does break the drawing of xpm icons. My local tree (gtk+ HEAD) has the somewhat smarter endpoint compensation to fix it again: --- from-cvs/gtk+/gdk/win32/gdkdrawable-win32.c Sat Jul 19 22:58:46 2003 +++ my-gtk/gtk+/gdk/win32/gdkdrawable-win32.c Fri Aug 01 15:26:28 2003 @@ -1219,6 +1219,7 @@ else GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) && GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2)); + } } else @@ -1226,6 +1227,22 @@ for (i = 0; i < nsegs; i++) GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) && GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2)); + + /* not drawing the end pixel does produce a crippled mask, look + * e.g. at xpm icons produced with gdk_pixbuf_new_from_xpm_data trough + * gdk_pixbuf_render_threshold_alpha (testgtk folder icon or + * Dia's toolbox icons) ... --hb + */ + if (gcwin32->pen_width <= 1) + { + GdkSegment *ps = &segs[nsegs-1]; + int xc = (ps->y2 == ps->y1) ? 0 : ((ps->x1 < ps->x2) ? 1 : -1); + int yc = (ps->x2 == ps->x1) ? 0 : ((ps->y1 < ps->y2) ? 1 : -1); + /* don't forget single point lines */ + xc = (0 == xc && 0 == yc) ? 1 : xc; + + GDI_CALL (LineTo, (hdc, ps->x2 + xc, ps->y2 + yc)); + } } }
And of course there was something wrong with it, from gtk-win32-production : /* Draw end pixel */ /* LineTo doesn't draw the last point, so if we have a pen width of 1, * we draw the end pixel separately... With wider pens we don't care. * //HB: But the NT developers don't read their API documentation ... */ so there needs to be a !IS_WINNT() before drawing it ...
Win9x-only bugs won't get fixed at this rate, at least not by me. Closing as WONTFIX.