Arduboy2 library support the INVERT colour

Continuing the discussion from XOR bitmap to background?:

Just a F.Y.I.: I made an attempt to make all the drawing functions in the Arduboy2 library support the INVERT colour. Unfortunately, many of the functions actually draw some of the pixels two (and possibly more) times. The first time, the pixel is XOR’d correctly, flipping its state, but the second time the XOR changes it back to its original state, so the result is “missing” pixels in the object that was drawn. Because of the time it would take me to fix and test the many places that this occurred, I decided to abandon my efforts.

Example of one of the places that “double” draws?

Circles and some filled objects.

1 Like

Since almost all drawing functions end up calling drawPixel(), that’s pretty much the only place you have to add the XOR. Also some bitmap functions and a few other places.

If you don’t care if the operations are fast or not, sure. :slight_smile:

I think I can imagine what are you saying for filled shapes… Rects shouldn’t be an issue though (that’d be a bug)… I don’t think circle should be either (probably also a bug)… no idea on triangles… but your right could be annoying to track down and fix those bugs.

I didn’t find any actual bugs in any code I looked at. It seems more like the code has been optimized for size, rather than speed. If overwriting a few pixels saved some calculations that would be needed to prevent it, then that’s what was done. When writing solid black or white, the desired result is still achieved.

For rectangles, I think it was just the corner pixels that were overwritten because both the horizontal and vertical sides are drawn using the full width and height. You could start one of the sides one pixel in and stop one pixel short but that would add a few lines of calculations, meaning more code.

For circles I think it’s just that the calculations would normally result in coordinates that would be fractions of a pixel but because integer math is being used, rounding errors result in pixel overlap. You could probably save the location of the last pixel written, and then if the next pixel is at the same coordinates, don’t write it. But again, that would just add extra code that isn’t necessary for “solid” colours.

For other objects, it was similar circumstances.

Anyway, instead of adding just some simple tests and XORs in drawPixel(), some bitmap functions and a few other places, it turned out that I would have had to make many other “fixes” and then would have to test everything to make sure it worked and that I hadn’t introduced any new bugs. So, I decided I didn’t want to spend the effort, especially since nobody has actually asked for 'invert" colour handling in the first place.

That’s not to say I wouldn’t consider adding support for it if someone else were to develop, test and submit the changes, though.

Hello this is Kevin from the future and I’m very curious on drawing some inverted circles.

Anyone can help?

More information would be useful.

Firstly, by ‘inverted’ I presume you mean that you want the circle to invert the colour of whatever pixel it’s ‘draw’ onto?

If so, by default it seems only drawBitmap supports that behaviour.
To get drawCircle or fillCircle to support that behaviour, at a minimum you’d have to modify drawPixel, and you might have to make some changes to drawFastVLine, fillCircleHelper and drawCircleHelper.

Secondly, would you need any size circle or only a certain number of sizes?

If you only need certain sizes then it would be much easier to keep some circle bitmaps in memory and use drawBitmap’s inversion capabilities.

Yeah the presumption follows this thread and the one before it as discussed before.

Theoretically any size circle.

Basically I was asking @MLXXXp or anyone else up on his offer to implement it as such.

You’re probably right to use draw bitmap as I suspect drawing large circles with an inverted method (pixel by pixel) is probably quite slow anyways so would likely want to not use that.

I can use the small ones anyways for what I had planned so shouldn’t be a problem to do it that way.

Saw this art and gonna have a go at creating it Arduboy.

1 Like

If you are just trying to reproduce that then simply use the invert command to invert everything on the screen. Then you can use the drawCircle commands as they are.

arduboy.invert(true);

Reminds me of metaballs…


Based on the image, I presume you’re planning to have some kind of aeroplane or spaceship fly around the screen emitting a stream of inverting-circle particles?

Honestly you’re almost certainly better off trying to pull it off with inverted bitmaps first, and only trying to modify the Arduboy drawing functions if that proves to be unsuitable, simply because it will be less hassle and because you can change how the circles look.

If you use the circle drawing function then the result won’t look quite the same as in the image anyway because those circles in the image are either hand drawn or using a different algorithm.
(Hand-drawn ones will potentially look better.)


If you find you do need to use the circle drawing functions (which as you note, will potentially be slower, especially for larger circles) then to start you’d probably have to change these lines:

To something like:

  uint8_t source = sBuffer[row_offset];
  uint8_t data = (source | bit);
  if (color == INVERT) data = (source ^ bit);
  if (color == WHITE) data ^= bit;
  sBuffer[row_offset] = data;

(I’m reasonably sure that’s correct, but I can’t vouch for speed.)

Based on what @MLXXXp said above it’s likely to take more than just that though. I suspect the existing drawing algorithms end up calling drawPixel on the same pixel twice, which is fine for drawing black or white but for inversion it would end up inverting the pixel twice, which is the same as not inverting it in the first place.

(Doing an inversion twice is typically the same as not doing anything in the first place: ~~0 == 0, !!true == true, --1 == 1.)

2 Likes