phoreglad / pico-epaper

Module for driving Waveshare Pico e-Paper 3.7 display. Now with support for partial updates.
37 stars 6 forks source link

Centering text? #2

Closed wumfi closed 2 years ago

wumfi commented 2 years ago

Is there a simple way of working out the width of the rendered object after calling wri.printstring?

I'd like to be able to centre text based on the screen width. I've been playing around with .clip_width and .char_width methods, but they don't seem to be set to the actual length of the rendered text on the screen. I tried the following in the REPL:

txt="This is a test"
from Pico_ePaper import Eink
from writer import Writer
import sys
sys.path.append("/fonts")
import dinomouse20, dinomouse30, dinomouse40
import framebuf
class DummyDevice(framebuf.FrameBuffer):
    def __init__(self, width, height, buf_format):
        self.width = width
        self.height = height
        self._buf = bytearray(self.width * self.height // 8)
        super().__init__(self._buf, self.width, self.height, buf_format)
        self.fill(1)

epd = Eink(rotation=270)
Data loading time: 6816 ms

dummy = DummyDevice(epd.width, epd.height, framebuf.MONO_HLSB)
wri = Writer(dummy, dinomouse40)
wri.set_clip(row_clip=True, col_clip=True, wrap=True)
wri.printstring(txt, invert=True)
Writer.set_textpos(dummy, 0, 0)

Orientation: Horizontal. Reversal: False. Width: 480. Height: 280.
Start row = 0 col = 0
(True, True, True)
(0, 0)

wri.char_width
19

epd.fill()
epd.blit(dummy, int(epd.width/2)-int(wri.char_width/2), 100, key=1)
epd.show()
Data loading time: 6842 ms

Renders as this.

Apologies if I'm using the wrong terminology, or indeed, using the wrong forum to ask questions. I'm very much at the beginning of my MicroPython journey, and trying to learn as I go along.

phoreglad commented 2 years ago

You should use stringlen() method to find out the length of rendered text in pixels and then do some math to calculate text position. The same goes for vertical centering, but you should use font height. That works only for one line text since the Writer class doesn't calculate the width/length of multiline text. To do that you'd probably have to divide your text into single lines and position them appropriately.

Using: Writer.set_textpos(dummy, (epd.height-wri.height)//2, (epd.width-wri.stringlen(text))//2) to set the text position should center it horizontally and vertically.

One important thing to note. With this method of using Writer you should always blit dummy buffer on position 0, 0: epd.blit(dummy, 0, 0, key=1) and use Writer set_textpos() method to change the text position.

I've also noticed that you're using an older version of my driver, so you might consider updating it to the newest version. There were some bugfixes and massive speed up (~10x) for landscape mode.

wumfi commented 2 years ago

Firstly, thank you for explaining the centering calculations. Oddly though, if I take your recommendation:

Writer.set_textpos(dummy, (epd.height-wri.height)//2, (epd.width-wri.stringlen(text))//2)
epd.blit(dummy, 0, 0, key=1)

The text is rendered top-left of the screen. However, if I switch it round to:

Writer.set_textpos(dummy, 0, 0)
epd.blit(dummy, (epd.height-wri.height)//2, (epd.width-wri.stringlen(txt))//2, key=1)

It works as expected.

It should be noted also that I'm not running this on a Pico, I'm using a TinyS2 attached to the pins on the back of the screen via a breadboard currently. I needed internet, so can't use the Pico. Perhaps that's why I'm seeing different output? I'm happy to test using a Pico if you would like me to.

Also, thank you for the new library. I've just tried it and it's certainly is a lot quicker! However, I've been using the one on the partial-updates branch as it benefits my project. Are you planning on merging that into main?

phoreglad commented 2 years ago

I have just noticed that you're writing text to screen before setting text position. set_textpos() method should be used before printstring().

Also, thank you for the new library. I've just tried it and it's certainly is a lot quicker! However, I've been using the one on the partial-updates branch as it benefits my project. Are you planning on merging that into main?

I'm still not sure that the current implementation of differential/partial updates is how I want it to look like so I'm not planning to merge it to main at this time. That being said partial-updates branch also has been updated with some speedups, so you might want to grab its newer version regardless. I'll try to update it further to be as fast as main, but it may take some time.

PS I've converted this issue to "discussion", mainly because I want to try this feature out and this conversation isn't related to any specific issue with the library.