GNOME Bugzilla – Bug 306396
lasso selection made slowly is not visible
Last modified: 2016-05-13 20:21:37 UTC
Please describe the problem: With GIMP version 2.2.7, when carefully (slowly) selecting a hand-drawn region using the lasso tool, the path being selected is largely invisible while being drawn--especially when the mouse moves from upper left to lower right. When the selection is complete, the marching ants are properly visible. I've only tried this on Windows XP but it happens on two different computers and on both those computers, it does not happen with GIMP version 1.2.5 Steps to reproduce: 1. create a new/empty image with file->new 2. click the lasso tool in the main gimp window 3. in the new image window, click and very slowly drag from upper left to lower right and see only an occasional dot along the path the mouse has taken. Actual results: The path being selected is mostly not visible Expected results: A black line should be drawn along the path the mouse has taken Does this happen every time? Yes if the mouse is moved slowly in the direction from upper left to lower right. Other information: The win32 GIMP binaries are those built by Jernej Simoncic. I think version 2.2.6 had the same problem.
Hmm. A screenshot would be very helpful here, but obviously that's not so easy to get. There have been reports of similar-sounding problems that turned out to be caused by malfunctioning graphics accelerators -- are your two computers different enough that this can't be the answer? (The solution that worked in the similar cases was to reduce the level of graphics acceleration.) Incidentally, your "Expected results" are wrong. The curve should not be black, it should be drawn in XOR mode, which changes black to white and white to black. XOR drawing also has the unfortunate property that it is hard to see when the underlying color is approximately medium gray.
Thanks for your message, I stand corrected about black line but in this case (on new/blank/white image) I think it should be black and is mostly white. If I fill the new image with black and do a lasso selection, it draws an invisible black line with occasional white dot. Computer #1 is a Dell dimension 4600 running WinXP native with built-in intel-extreme video at 1600x1200. Computer #2 is a Dell optiplex gx270 running linux native and WinXP under vmware. The native video card is nvidia GeForce FX 5200. On computer #1, turning graphics hardware acceleration down to NONE and disabling "write combining" (and then rebooting) made no difference for this problem. A screenshot is indeed hard to get however I think I can accurately describe what you would see. The mouse draws a white line on a white background except that once in a while (perhaps once per inch) a black dot will appear. Usually the starting point (where I click before dragging) will be visible as a dot. I think a clue might be the difference between dragging from upper left to lower right and lower right to upper left. The down and right draws invisible and the up and left seems to draw a dotted line of very close black and white pixels (more than one pixel wide). It is as if the XOR drawing is XORing with an NxN pattern of pixels, then moving less than N pixels and XORing again leaving a trail of twice XORd pixels (which are invisible) in one direction but because of the pattern, visible in the other direction.
Created attachment 47780 [details] during selection with mouse button down
Created attachment 47781 [details] when the mouse button is released, the path becomes visible
Looks like my additional explanation comment didn't post. I'll try again. I figured out how to get a screenshot for you. On computer #2 I can do it from the native linux host with xv and a time delay. The selection in gimp was made slowly (over about 20 seconds starting at the top and going counterclockwise). You can not see the path in the first attachment while the mouse is down but when I release the mouse button, you can see it in the second attachment. I see the status of this bug is still NEEDINFO and I gather I'm supposed to provide that but I'm not sure what else to say. Thanks
Removing NEEDINFO since no further info is needed at this time. My guess, since this only happens when you move slowly, is that for some reason lots of pixels are being XOR-drawn twice and therefore not showing up.
The problem is however not reproducible so there's little chance that it can be addressed and it doesn't seem to make much sense to keep a bug report open for it then.
I can reproduce this on Windows XP.
Oh. Why hasn't this been reassigned to GTK+ then? It appears to be a GDK problem.
I suspect a flaw in the Windows implementation of the function gdk_draw_segments(). The easiest way to check, I think, would be to activate one of the painting tools and look at the brush outline that is drawn -- if I am right, there should be a lot of missing points. (Try something simple like a circular brush.)
I think you're suggesting: 1) create new image 2) choose "paint fuzzy brush strokes" tool 3) choose a non-fuzzy circular brush (I tried size 1, 3, 15) 4) mouse down, move in a slow counterclockwise circular path, mouse up The above works perfectly. I also tried the "draw in ink" tool and the "paint hard edged pixels" tool with various brushes and they all worked OK as well. Thanks.
Created attachment 47950 [details] Screenshot of a brush outline The brush outlines have missing points at approximately the same angles as mentioned in this report.
Thanks, that pretty much confirms my guess. Because of the complexity of this bug report, instead of reassigning I am creating a new bug report (bug #308413) that identifies what seems to be the core issue, and making this a dependent of it.
Actually the outline of a 50 pixel radius hard circular brush looks exactly like Schumi's screenshot in Comment #12 on Linux, too... (So if that is a bug, it is a different one, and cross-platform.) But the trail of the lasso tool indeed has random dropouts on Windows.
Hmm, if I comment out the drawing of a final extra one-pixel segment for narrow pens in draw_segments(), the trail of the lasso tool is correct. Sigh... but that code can't be just removed, that will break other things. I will have to figure out what the special case is for the lasso tool's trail when it shouldn't be done.
I think I'm on to it now. The problem is that X11 has separate CapButt and CapNotLast line endcap styles. As GDK was written originally to be just a thin veneer over X11, GDK also has separate GDK_CAP_BUTT and GDK_CAP_NOT_LAST endcap styles. Win32 GDI has only the cap style equivalent to CapNotLast, PS_ENDCAP_FLAT. (Plus the styles equivalent to CapRound and CapProjecting, PS_ENDCAP_ROUND and PS_ENDCAP_SQUARE.) GIMP uses GDK_CAP_NOT_LAST when drawing the trail of the lasso, see gimp_draw_tool_draw_line() and gimp_canvas_gc_new(). Currently the code in gdk/win32 treats GDK_CAP_NOT_LAST like GDK_CAP_BUTT. It should be modified to save the GDK cap style in the GdkGCWin32, and then when drawing lines check that. If the cap style is the default GDK_CAP_BUTT, it should draw the end "point" explicitly, as now. But if it is GDK_CAP_NOT_LAST, it should *not* do that, as in that case the cap style the caller wants already matches what GDI provides.
Solving this isn't made any easier by the fact that at least on my XP, drawing horizontal segments to the left with LineTo() *does* draw the end pixel, but leaves the *first* pixel undrawn. Ditto for vertical segments drawn upwards. This might also be a bug in the graphics driver, of course. Argh... Maybe gdk/win32 should test the behaviour of GDI's line drawing on the machine when it starts? Hmm, actually the above seems to hold also for some oblique segments. Oh, this crap is horrible, horrible. Maybe we really do need to drop using GDI to draw lines and plop in code from libpixman, or cairo, or something? Brrr.
Created attachment 48092 [details] [review] intermediate patch Here's a patch that helps a lot. Note that there is still some unconditional debugging output in there. I am not sure whether the bug workaround code in draw_segments() is worth it. (The first two if cases after the "There seems to b a bug" comment.) I have no idea whether this is a bug in all (NT-based) Windowses, just in XP SP2, or in my graphics driver. Even without that part of the patch, GIMP's lasso trail works much better.
Below is a test program. It draws line segments in various directions. The red and blue segment pairs are drawn in opposite directions. At each segment end a black cross is first drawn, thus if you see a black pixel in the middle of the cross, it means that the LineTo hasn't drawn that pixel, and if you see a coloured pixel, the LineTo has drawn that pixel. It accepts the followind one-character "commands": f - use PS_GEOMETRIC|PS_ENDCAP_FLAT pens s - use PS_GEOMETRIC|PS_ENDCAP_SQUARE pens r - use PS_GEOMETRIC|PS_ENDCAP_ROUND pens c - use PS_COSMETIC pens of width 1 0, 1, ..9 if using a PS_GEOMETRIC pen, set pen width It's hard to describe how Windows decides when to draw which end pixel of segments drawn with a geometric PS_ENDCAP_FLAT narrow (width <= 1) pen. It depends the slope of the segment, but which way the segment is drawn has no effect. Only for cosmetic pens (which always are width 1) does the drawing direction matter, and then again the slope has no effect. Anyway, after some experimentation, I think the way to achieve X11 compatibility would be: - For narrow lines with GDK_CAP_NOT_LAST, use a cosmetic pen - For narrow lines with GDK_CAP_BUTT, use a geometric pen with PS_ENDCAP_SQUARE - For wider lines, pixel exactness probably isn't that relevant, use whatever seems logical... I haven't yet implemented that and checked whether it makes sense...
Created attachment 48098 [details] test program "lines.c"
Created attachment 48127 [details] [review] Suggested patch OK, so here is the patch that I would like to commit. Please test. I checked that the following stuff that are affected by the changes still work: - GIMP's guide lines look OK - The "pixmap" test in testgtk looks OK - Dashed focus indications look OK Plus, the cause of this bug report, GIMP's lasso tool: Now it leaves a nice trail without gaps no matter which way and how fast or slow you drag the mouse
As for the brush outline issue, see bug #308710
Patch applied (with further improvements) to HEAD and gtk-2-6: 2005-06-23 Tor Lillqvist <tml@novell.com> Improve and simplify line segment rendering on Win32, especially the implementation of GDK_CAP_NOT_LAST, and dashed lines. Fixes bug #306396. * gdk/win32/gdkprivate-win32.h (GdkGCWin32): Save the GdkGC's line_style, cap_style and join_style as such in the GdkGCWin32. Don't need to keep the pen_double_dash flag, we can check the line_style. * gdk/win32/gdkgc-win32.c (fixup_pen): New internal function. Sets up the GDI pen type, style, end cap and join attributes to use based on the pen width, GDK line style, end cap style, and join style. For a narrow (zero-width) GDK pen with the GDK_CAP_NOT_LAST end cap style, which typically are used for XOR drawing where it is essential that the last pixel is not drawn, use a GDI cosmetic pen. Only for a cosmetic pen does GDI not draw the last pixel. I deduced this by experimetation, the documentation is rather vague. For other GDK pens use a geometric GDI pen. If the width is 0 or 1 and the GDK end cap style is GDK_CAP_BUTT, and the line style is GDK_LINE_SOLID, use PS_ENDCAP_ROUND. This ensures that also single-pixel length lines are drawn. (For sngle-pixel width lines roundness as such is of course irrelevant.) For dashed lines, use PS_ENDCAP_FLAT. For wide lines use PS_ENDCAP_FLAT, _ROUND or _SQUARE, respectively, for GDK_CAP_BUTT, GDK_CAP_ROUND and GDK_CAP_PROJECTING. For one pixel on-off dashed lines, use PS_ALTERNATE, it seems to work better than PS_USERSTYLE. For other dashed lines, use PS_USERSTYLE and the dashes as set by the user (or the default four-pixel on-off style). (gdk_win32_gc_values_to_win32values, gdk_win32_gc_set_dashes): Call fixup_pen() to do the pen settings after modifying some of the GDK GC attributes that affect pens. * gdk/win32/gdkdrawable-win32.c (render_line_horizontal, render_line_vertical, draw_segments): Check GdkGCWin32::line_style instead of the the removed pen_double_dash member. Don't use PATCOPY unconditionally in the PatBlt() call, use a raster ope code that depends on the GC function in use. (draw_rectangle, draw_segments, draw_lines): Be more careful in deciding when to do the manual dash rendering. (draw_segments): Don't do any manual "last point" drawing at all. The above changes takes care of narrow line segments being drawn correctly in most cases, at least on NT-based Windows.
*** Bug 314911 has been marked as a duplicate of this bug. ***