Boutique watch face – lessons learnt

Hello, I have released a new watch face Boutique this week.

Maybe you have noticed that the second hand is 1 Hz animated, the background has full colors and even the second hand and the time / font is antialiazed (it is drawn with multiple colors and does not have jagged lines). And I still have a 10 kB of free peak memory 🙂 How did I do that?

Refreshing every 1 second
To be able to update the watch face every second, you can split the logic between the “full refresh” and “partial refresh”. Full refresh is done once per minute, when everything static is drawn into the background bitmap. The partial refresh just adds the second hand over the already drawn image. There are very strict rules for this, the average execution time per draw can be only 30 ms.

The basic template for this is very simple, you can set the clipping rectangle, so only the needed pixels are redrawn every second: sample code

But this may still not be enough. You can make the clipping rectangle smaller. Or you need to optimize every line of your logic, for example the sin/cos values of angles can be pre-calculated at the beginning: sample code

In a similar way, the normal of each angle can be obtained as the opposite value of the angle: [y, -x]

So the polygon of the second hand can be calculated and drawn like this: sample code

Background bitmap and the memory
You need to specify which colors the background image has, and also what is the color palette of the background bitmap. You can see that 2 colors have a certain size, then 4 colors, 16 colors etc. For the 240x240px large bitmap, it means approximately 29 kB for the background bitmap, and another 30 kB for the loaded image itself. This is not good, because you have only 92 kB of memory even on the newest devices (and all the source code, values in the settings and other resources are also calculated to this limit).

You don’t need to load the image in onLayout. You can split it to four 120x120px images. Then you can load it in the onUpdate method. After each of them is drawn, you can set it back to null. In this case, you need only 7 kB of memory instead of 30 kB 🙂 sample code

Antialiazed fonts and the fixed color palette bitmap
So, you have the background bitmap and you want to draw also some fonts. But there is a problem, you cannot draw antialiased fonts into a bitmap with a fixed color palette. All you can do is to load a custom font, and draw it with just one color. It will look jagged, especially is smaller sizes. So, how to fix this?

You can generate a custom font with the Bitmap font generator. Export the font as the .fnt file with .png images. Create a second font with the copy of these images and add them the 150% of brightness. You will now have two fonts, one will be a slightly more bold. So you can draw the bold font first with a darker color, then the original font with the normal color. You will see that it looks quite well 🙂

Custom font and special characters
Yeah, so you have used a custom font, but it cannot contain all characters… If you want to show the location, or days/month names, they can contain a lot of special characters (for example the “září” in Czech alphabet). So, the most dirty solution is to remove all the diacritics: source code

Leave a Reply

Your email address will not be published. Required fields are marked *