ropod7 / pyboard_drive

23 stars 11 forks source link

Better font support wirh robert-hh fonts for SSD1963 #35

Open mchobby opened 8 years ago

mchobby commented 8 years ago

Hi Roman, I did have a check for robert-hh project and I think we should definitively switch to that font definition.

robert-hh's TFTFont class

If we look to the the TFTFont class (find it here) we have the needed things with get_ch() to get the data:

class TFTFont(object):
    def __init__(self, font, index, vert, horiz, nchars, firstchar = 32):
        self.firstchar = firstchar  # ord(first_character) Future use: absent from C file.
        self.nchars = nchars        # No. of chars in font
        self.bits_horiz = horiz     # Width in pixels of char if rendered as monospaced
        self.bits_vert = vert       # Height in pixels
        self._index = index
        self._font = font

    def get_ch(self, ch):
        from uctypes import addressof
        relch = ch - self.firstchar
        if relch > self.nchars or relch < 0:
            relch = 0 # instead of value error, typically this is space
            # raise ValueError('Character value {:} is unsupported.'.format(ch))
        offset = relch * 2            # index is 2 bytes/char
        offset =  self._index[offset] + (self._index[offset + 1] << 8)
        delta = (relch + 1) * 2            # index is 2 bytes/char
        delta =  (self._index[delta] + (self._index[delta + 1] << 8)) - offset
        return addressof(self._font) + offset, self.bits_vert, (delta * 8) // self.bits_vert

And the font includes the properties like font vertical and horizontal size as well as firstchar (ordinal) and number of characters.

Robert-hh's Font collection

The last refactoring of the font collection looks interesting, it's also self describing and use the TFTTont class.

Robert-hh's fonts collection

import TFTfont
xxxxx
dejavu12 = TFTfont.TFTFont(_dejavu12, _dejavu12_index, 21, 19, 96)

fonts = {"dejavu12":dejavu12,
}

font loading

I think that best approach would be:

Fonts can be created with the GLCD free font creator GLCD produces c style font coding.

The robert-hh's code includes cfonts_to_packed_py.py . This file is designed to transform c font style to "python-code" style.

TFTFont extension

If needed, the TFTFont could be derivated in a TFTFontFile class loading the data from a binary file. Slower but would allow to use laarrrgeeer font without surging the memory.

Nice add-ons

I did also noticed a nice snip of code emulating a vt100 terminal. Just an interesting curiosity vt100.py

mchobby commented 8 years ago

Working on the robert-hh's font decoding to the TFT driver

>>> from afonts.dejavu14 import *                                               
>>> dejavu14                                                                    
<TFTFont object at 200034f0>  
>>> for item in dejavu14.get_ch( ord('A') ):                                    
...     print( bin( item ) )                                                    
...                                                                             
...                                                                             
...                                                                             
0b100000000000000101101011111001                                                
0b11000                                                                         
0b1111

this would require some additional work

mchobby commented 8 years ago

OK, I did decode the font. I placed the robert-hh's dejavu14.py font inside a afonts subfolder (to not corrupt your driver). I did also copied the the TFTFont class (find it here) inside the root directory.

Finally, by reading the Robert's code, I did decode the data returned by TFTFont.get_ch() with the following code:

from afonts.dejavu14 import *

fontptr, rows, cols = dejavu14.get_ch(ord('A')) 
pix_count = cols * rows # number of bits in the char

print( "pix_count: %i" % pix_count )

@micropython.viper        
def displaySCR_bmp(bits: ptr8, size: int, cols:int ):
    bm_ptr = 0
    mask   = 0x80

    # used to convert rows to
    # human readeable string
    s = ''
    scount = 0

    while size:
        # Original Robert code use this test 
        #    if bits[bm_ptr] & mask:
        #        
        # Stack the bits inside a "printable" row 
        if bits[bm_ptr] & mask :
            s = s+'*'
        else: 
            s = s+'.'
        scount = scount +1 # also count the stacked bit/pixels

    # display the "row"
        if scount==cols:
            print( s )
            s = ''
            scount=0

        # Original code
        mask >>= 1
        if mask == 0: # mask reset & data ptr advance on byte exhaust
            mask = 0x80
            bm_ptr += 1
        size -= 1

displaySCR_bmp( fontptr, pix_count, cols )

Which produced the following result:

pix_count: 360
...............
......***......
......***......
.....**.**.....
.....**.**.....
.....**.**.....
....**...**....
....**...**....
...***...***...
...**.....**...
...**.....**...
..***.....***..
..***********..
..***********..
.**.........**.
.**.........**.
.**.........**.
**...........**
...............
...............
...............
...............
...............
...............

Catched :-)

ropod7 commented 8 years ago

Hi, Dominique. How obout speed up using this method, or it just obout low memory cost?

mchobby commented 8 years ago

Memory vs Speed

It is more about the lower memory cost. Performances in drawing text on screen is maybe not the most critical... but this should be fast enough anyway. Using a bytearray will store the data in memory as "binary" with minimal interpreter usage. Byte array could also been read from a file instead of in-memory storage. That would be suitable for super-large or multiple font usage... keeping memory footprint as low as possible.

Producing fonts

I'm also considering to produce such TFTFont data from the FreeTypeGenerator.

ropod7 commented 8 years ago

I had thinking obout font caching as bytecode to, but you wrote that you have some ideas in this way movement. Should be good if we have some solutions in this case.

Sorry, I am away from my development at this moment, soon I must include my time in this project back.