Can you print() transparent text?

Is it possible, or hopefully somehow easy, to print text without it masking the area behind the text black?

i.e. transparent text?

Coincidentally, I’ve just discovered and fixed a bug with being able to do that. After analysing the code in relation to issue 54, raised by @Pharap, I realised that the intent was that if you set the background colour to the same as the foreground colour, then the background becomes transparent and the text prints in whatever colour you chose.

However, this has never worked. If you set both to WHITE then both the text and background are printed in white (You get a white rectangle). If you set BLACK/BLACK then both the text and background are transparent (Nothing is printed but the cursor is moved).

I plan to release a new version of the Arduboy2 library in the next few days, which will include the fix. If you want the fix in a hurry for testing, PM me.

Note that printing inverse transparent text, where the background is solid but the text is transparent, will not be possible.

1 Like

Actually, under some circumstances you could get the effect of transparent text with a solid background. You could set text to BLACK and the text background to WHITE. You would then print the text first. Then you could draw anything, that only set white pixels, on top of the text. The text background would already be white, so whatever part of the object ended up over the (black) text would appear to be showing through the text.

The same could be done for the inverse, where transparent text with a solid black background could have black coloured objects (only black pixels drawn) “show through”.

The caveat is that, with this technique, you couldn’t have objects that drew both white and black pixels appear to be behind the “transparent” text. You also couldn’t have the case where transparent text with a solid black background has white pixels showing through the text (or the inverse).

Having looked at the code, I see what you mean and I think I see what the bug is.

To check I’m understanding the problem correctly,
and to break down the problem for anyone who is interested…

There’s quite a lot of possible values to account for, especially given that technically color and bg aren’t restricted to being just 0 and 1:

  • if color is non-zero and bg is zero value then
    • draw_background is true
    • draw_color will be color for character bits and bg for background bits
    • if(draw_color || draw_background) will always be true, hence font bits are drawn white and background bits are drawn black
  • if color is zero and bg is non-zero value then
    • draw_background is true
    • draw_color will be color for character bits and bg for background bits
    • if(draw_color || draw_background) will always be true, hence font bits are drawn black and background bits are drawn white
  • if color and bg are both 0 then
    • draw_background is false
    • draw_color is always 0, because color and bg are both 0
    • if(draw_color || draw_background) will always be false, hence nothing is drawn but the cursor still moves
  • if color and bg are the same non-zero value then
    • draw_background is false
    • draw_color is the specified non-zero value, because color and bg are both that same value
    • if(draw_color || draw_background) will always be true, hence all pixels will be drawn white, creating a white rectangle

Because I couldn’t resist, an example of a case that isn’t supposed to be allowed (let’s say the API considers it ‘undefined behaviour’)

  • if color and bg are two different non-zero values
    • draw_background is true, because bg != color
    • draw_color will be color for character bits and bg for background bits
    • if(draw_color || draw_background) will always be true, so the background will be drawn, but the font bits are only white if color is 1, and if bg is 1 the background bits are drawn white

There are three more similar cases, but I can’t be bothered to specify them all.

Here’s a sample program to see the effects of each possibility:


Anyway, I haven’t checked but I believe the test ought to be checking if(((line & 0x01) != 0) || draw_background).
I’m definitely looking forward to seeing what the bug fix is when it’s released.

It’s not huge in my game but curious how it is implemented in codespace is it like print(“a”,1,0) or something?

Drawing text in general, or specifically drawing text with a transparent background?

I know how to use print as it’s currently implemented I’m not that bad.

Knowing how to use something and knowing how something is implemented are two very different things.
Any beginner knows to call arduboy.begin() in setup(),
but few people actually know what begin() does in any great detail.

At any rate, I’m no closer to understanding what your question was referring to.


By the way, I don’t seem to be getting notifications of your replies.
Are you using the blue reply button at the bottom rather than using the reply buttons on the comments?

How would you implement the transparent text feature that @MLXXXp is making?

And yes blue button 4 lyfe.

Replace the area I highlighted earlier:

With the following:

      const bool draw_pixel = ((line & 0x01) != 0);

      if (draw_pixel || draw_background) {
        const uint8_t draw_color = draw_pixel ? color : bg;
        for (uint8_t a = 0; a < size; a++ ) {
          for (uint8_t b = 0; b < size; b++ ) {
            drawPixel(x + (i * size) + a, y + (j * size) + b, draw_color);
          }
        }
      }

(As an added bonus, it appears to be slightly cheaper.)

If you're too lazy to do so manually, here's a drop-in replacement Arduboy2.cpp https://gist.github.com/Pharap/e8cc599992a4047d765574e6821eb1cf

To demonstrate the difference…

Before:
FontTrial.Original.hex (19.8 KB)

After:
FontTrial.Modified.hex (19.8 KB)


Then expect slow replies.

Correct. That’s essentially how I fixed it. I’ve done a bit more refactoring of drawChar() for the next release, but with the same effect.

Ok, so, still wondering how you call the new print command.

I don’t think it just defaults to transparent text? How do you set it to transparent?

Set the both the background and the foreground colour to WHITE:

arduboy.setTextColor(WHITE);
arduboy.setTextBackground(WHITE);
arduboy.println(F("Hello"));

So, you’re telling me I can’t use the print function to draw filled rectangles any more?

1 Like

Or both to BLACK for black text with transparent background.

If anyone is doing this, my next Arduboy2 library release is going to break it.

You have a fillRect function for that.

If you need the font dimensions to calculate how big the box should be, they characters are 5x8, with 1 pixel gaps between characters and 0 pixel gaps between lines.

The next library release will be adding new functions to make calculating that information easier.

Having all three would be possible, but it would make the character printing function larger and probably slower.

If memory serves I printed on filled rectangles in tamaguino and a-maze…I’ll have to check it’s been awhile.

You can print on filled rectangles. You just will no longer be able to print filled white rectangles using arbitrary text.

You’ll still be able to print white rectangles by setting the text colour to BLACK and the background colour to WHITE and then printing spaces. Likewise, black rectangles by setting text to WHITE and background to BLACK and printing spaces.

Anyway, I’m pretty sure @bateske was being sarcastic.

The characters are actually 5x8, with the bottom row being used for line spacing or descenders. There’s not actually additional line space added. Certain characters will touch other certain characters directly below them.

Ah, I remembered the line spacing, I forgot about the descenders.
(I guess I haven’t been printing enough 'g’s and 'y’s. :P)

My mistake.

Sometimes I find it really hard to tell…

@bateske, would you like to borrow my :P emoticon?

1 Like