peterhinch / micropython-font-to-py

A Python 3 utility to convert fonts to Python source capable of being frozen as bytecode
MIT License
368 stars 67 forks source link

Problem with some fonts conversion - glyph data IndexError #24

Closed amirotin closed 4 years ago

amirotin commented 4 years ago

Hi. I'm trying to convert some fonts, but when i use Pixel Writer class i got error

  File "D:\Work\Micropython\tt.py", line 16, in <module>
    data = glyph[srow * gbytes + gbyte]
IndexError: index out of bounds on dimension 1

Here is my code

import font

COLOR_BLACK   = 0x0000
COLOR_RED     = 0x07E0

glyph, char_height, char_width = font.get_ch('1')

div, mod = divmod(char_width, 8)
gbytes = div + 1 if mod else div

char_image = bytearray()
for srow in range(char_height):
    for scol in range(char_width):
        gbyte, gbit = divmod(scol, 8)
        if gbit == 0: 
            data = glyph[srow * gbytes + gbyte]
        pixel = COLOR_RED if data & (1 << (7 - gbit)) else COLOR_BLACK
        char_image.append(pixel>>8)
        char_image.append(pixel & 0xff)

for testing, I'm trying to get an image of the number 1. This does not work with any of the fonts if I use the Cyrillic character set. On some fonts, the standard set does not work either. Error is same in all cases. I attached some fonts that i'm trying to use pixel_sans_serif 8.zip free_pixel 16.zip minecraftia 8.zip

peterhinch commented 4 years ago

The error message looks odd. On current MicroPython an out of range error appears as "IndexError: memoryview index out of range". What version of MicroPython are you using, and on what platform? Rather than the source fonts, your converted Python font files would be more informative.

amirotin commented 4 years ago

Sorry, I was checking the script on a regular python 3.6.6 and copied the error from there. On MicroPython error is IndexError: memoryview index out of range. Here is one of converted fonts with command font_to_py.py -k cyrillic FreePixel.ttf 16 freepixel.py

MicroPython v1.11-8-g48dcbbe60 on 2019-05-29; ESP module with ESP8266 freepixel.zip

peterhinch commented 4 years ago

I can replicate your error, but I can find no fault with the font file: the glyph "1" can be rendered correctly:

>>> import font_test
>>> font_test.test_font('freepixel', '123')
Vertical map
Normal bit order
Proportional spacing
Dimensions height*max_width 17 * 9
Start char "!" (ord 33) end char "ё" (ord 1105)
...........................
...........................
...........................
....#......####.....####...
...##.....#....#...#....#..
..#.#.....#....#........#..
....#..........#.......#...
....#.........#......##....
....#........#.........#...
....#.......#..........#...
....#......#............#..
....#......#............#..
....#.....#........#...#...
..#####...######....###....
...........................
...........................
...........................
>>> 

I suspect something is wrong with the way you are rendering it, but I haven't yet managed to spot the problem. I'll study your code later today.

Note that font_test.py must be run under Python 3.

amirotin commented 4 years ago

font_test.py works for me too. As for my code - i just took your writer.py _printchar function and it works fine with your fonts in writer folder (courier20.py, font10.py, ...)

peterhinch commented 4 years ago

I think the problem is that you have created a vertically mapped font but are rendering it using the algorithm for horizontal mapping. Unless you need vertical mapping you might like to simply re-create the Python font file with horizontal mapping using the -x option. If you need vertical mapping you'll need to adapt your code.

Most of my example fonts are horizontally mapped as this is the best fit for most display hardware.

amirotin commented 4 years ago

Yep, that it is. My fault, didn't check this moment. Thanks for help!