Using fbc 0.90.1 win32 (7-17-2013) for this.
It appears that line has an issue interpreting patterns/bitmasks when the drawing area is too close to the horizontal end of the screen.
dim as unsigned short pat = &b0000000011111111
dim as integer patwidth = 16
dim as integer w = 640, h = 480
screenres w, h, 32
line (0, 0)-(639, 479), rgb(0, 128, 128), bf
line (0, 10)-step(patwidth - 1, 0), rgb(0, 0, 0)
line (w - patwidth + 1, 10)-step(patwidth - 1, 0), rgb(0, 0, 0)
line (0, 10)-step(patwidth - 1, 0), rgb(255, 255, 255), , pat
line (w - patwidth + 1, 10)-step(patwidth - 1, 0), rgb(255, 255, 255), , pat
sleep
Running this will produce two lines using the same pattern, drawing a black unpatterned line first, then a white patterned one over it. The one on the left begins with black, then becomes white when the pattern kicks in. The one on the right is in reverse order. It appears as though the pattern begins reading from the LSB first when the end of the line extends past the end of the screen. Changing the width value in the step pair to patwidth - 2 corrects the issue.
Is this intended behavior, or compatibility with a QB-inherited quirk in some way? (I no longer have an active installation of QB, being on 64-bit Windows, so I couldn't check.)
This also appears to happen near the end of any
FB.IMAGEbuffer created byimagecreate().I can reproduce the issue. This program also shows how the behaviour changes near the screen edges:
On the left edge of the screen, when starting drawing with negative x values, I see that the pattern is applied to the actual pixels drawn, excluding the logical pixels that are being clipped. I think that's wrong behaviour. It should apply the pattern to the logically drawn pixels, no matter whether they're being clipped or not.
On the right edge of the screen, when starting drawing at screenwidth-patternwidth+1 it apparently turns around the pattern (or swaps the pattern bytes) which I think is wrong behaviour too. Here it also should apply the pattern to logically drawn pixels, no matter what clipping happens.
I've looked at the source code of
fb_GfxLine(), and turns out that it optimizes drawing of horizontal and vertical lines, as opposed to diagonal ones.Fixing this issue for the horizontal/vertical cases is relatively easy, but fixing it for the diagonal case is a different story, because it's not possible (really? at least not as easy) to calculate how many pixels would have been drawn if they hadn't been clipped. The clipping is done before the drawing algorithm starts...
The only way I can see to fix it would be to adjust the algorithm to do clipping for every pixel, instead of the whole line at once. However, that is much slower, and to prevent the case when no pattern is used at all from becoming slower, we'd need to duplicate a whole lot of code...
Last edit: dkl 2014-05-22
I've reimplemented the clipping code in [870ed1], and learned quite a bit about Bresenham's algorithm in the process.
Here's some mouse-driven testing code:
No green pixels should appear inside the box: the clipped line should perfectly cover the unclipped line.
Related
Commit: [870ed1]