[A89] Re: filling ellipses


[Prev][Next][Index][Thread]

[A89] Re: filling ellipses




I was writing a rather lengthy reply to this which I lost on a crash;
hopefully I've remembered everything that I originally had in here =( :

> Does anyone know a good fast way to fill an ellipse (using not only black
and white, but xor)?
> There is a draw ellipse function, but nothing for filling it.  A for loop
decrementing the radius
> by one doesn't work; it leaves out a few pixels.  You can't use a decimal
radius, which might
> work.

Even if you could decrease the radius in smaller increments, it wouldn't
work as long as you're using XOR.  Any attempt to draw concentric ellipses
that would cover every pixel would certainly have some overlap, and
overlapping XOR's is not good (XOR'ing a pixel a second time will undo the
first XOR.  In fact, overlap could be why you had a few pixels "left out" in
the first place).

> I was thinking along the lines of either calculating horizontal points on
the circle then
> connecting them with a line or doing a pixel test thing, sweeping across,
filling once it detects
> the edge of the circle.

Are you doing an ellipse, or a circle?  It sounds more like a circle (yes, I
know a circle IS an ellipse.  That's not my point =)  Either way, the
routine I describe below should be good.

> The problem is, I'm not sure if this could be efficient if you're drawing
> onto a background.  Another idea was to create an array when you begin
that symbolizes the
> rectangle around the ellipse, then use ones and zeros to create the filled
circle, basically as a
> sprite in a different form, then copy it to the screen pixel by pixel.
I'm not sure that any of
> these will be very fast, though.

This is a very good question =)  After thinking about it for a few minutes,
I think I came up with a good solution:

First, use HeapAlloc() to reserve a chunk of memory the same size as the LCD
memory (240/8*128 bytes, IIRC).  Then use PortSet() to redirect the TIOS
routines to draw to this new "virtual screen" (VS for short).  Clear the VS.
The use the TIOS ellipse routine to draw your ellipse on the VS, using solid
black (not XOR).

Then you can use a very simple routine to fill the ellipse.  Start at the
top row, and repeat for each row through the bottom row.  Scan from
left-to-right to find the leftmost set pixel, then scan from right-to-left
to find the rightmost set pixel.  Draw a solid black line (again, black, not
XOR) connecting these two pixels, then move on to the next row.  (Make sure
that it doesn't screw up on blank rows, though.)

When this is done, the VS will should your filled ellipse, in solid black,
on an otherwise clear white screen.  Now simply XOR the VS with normal LCD
memory, and your filled ellipse will have been XOR'd onto the screen!
Afterwards, be sure to use HeapFree() and PortRestore().

If you want to draw a solid black ellipse to the screen, simply repeat this
procedure but OR it onto the screen instead of XOR'ing.  If you want a solid
white ellipse, get the filled ellipse in the VS, then invert it (by XOR'ing
every byte of the VS with 0xFF), and then AND it onto the screen.


With any luck, this should be very fast, and it should certainly cover all
pixels.  If you have any more questions, don't hesitate to ask them!

    -Scott





Follow-Ups: