##
# @module    font
# @brief     Load RFT font to FT81x's memory
# @author    Henry Daitx
# @date      Apr 2018
# @copyright Racelogic Ltd., 2018
#

import ft8xx as ft
import gui
import ustruct as us

class Font_Loader:

    def read_file(self, fn):
        with open(fn, 'rb') as f:
            if f.read(4) != b'RF0 ':
                raise Exception('unrecognized font file format')
            first_char, nchars, total_data_len = us.unpack('<BBL', f.read(6))
            zdata = f.read()
        return first_char, total_data_len, zdata

    def set_base_address(self, mempos, mempos_end, total_data_len):
        if mempos is not None and mempos_end is not None:
            raise Exception('only one of mempos, mempos_end may be specified')
        # Decompress data at the end of RAM_G, into a multiple-of-4 address
        # Default starting position in RAM_G for the font data: it uses all the
        # space until the end of RAM_G
        if mempos is not None:
            pos = mempos
        elif mempos_end is not None:
            pos = mempos_end - total_data_len
        else:
            pos = 1048576 - total_data_len
        base = ft.RAM_G + pos
        base &= ~3
        return base

    def load(self, fn, font_handle, mempos=None, mempos_end=None):
        first_char, total_data_len, zdata = self.read_file(fn)
        base = self.set_base_address(mempos, mempos_end, total_data_len)

        gui.pause(True)
        ft.cpcmd_inflate(base, len(zdata), ft.addressof(zdata))
        font_metrics_start = base
        font_bmp_start = base + 148
        # Read length from metrics block
        # length = ft.rd32(font_metrics_start + 144)
        # Read parameters from metrics block
        fmt = ft.rd32(font_metrics_start + 128)
        stride = ft.rd32(font_metrics_start + 132)
        width = ft.rd32(font_metrics_start + 136)
        height = ft.rd32(font_metrics_start + 140)
        # Write correct image data address
        ft.wr32(font_metrics_start + 144, font_bmp_start)
        # Print glyph info
        # print(width, height)
        # Setup font
        ft.cp_start()
        ft.cp_cmd(gui.DL_BITMAP_HANDLE(font_handle))
        ft.cp_cmd(gui.DL_BITMAP_SOURCE(font_bmp_start))
        ft.cp_cmd(gui.DL_BITMAP_LAYOUT(fmt, stride, height))
        ft.cp_cmd(gui.DL_BITMAP_SIZE(0, 0, 0, width, height))
        ft.cpcmd_setfont2(font_handle, font_metrics_start, first_char)
        ft.cp_finish()
        gui.pause(False)

        return (base, base + total_data_len)


# Convenience definition
font_loader_obj = Font_Loader()
def load_font(*args, **kwargs):
    return font_loader_obj.load(*args, **kwargs)
