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.
If you don’t care if the operations are fast or not, sure.
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.
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.
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.)