font compression: add prefilter support

This commit is contained in:
Gabor Kiss-Vamosi
2019-09-13 15:40:12 +02:00
parent 915046d3ba
commit f190c78195
3 changed files with 135 additions and 69 deletions

View File

@@ -319,7 +319,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
new_obj->realign.auto_realign = copy->realign.auto_realign;
#endif
/*Only copy the `event_cb`. `signal_cb` and `design_cb` will be copied the the derived
/*Only copy the `event_cb`. `signal_cb` and `design_cb` will be copied in the derived
* object type (e.g. `lv_btn`)*/
new_obj->event_cb = copy->event_cb;

View File

@@ -259,6 +259,9 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
uint8_t bitmask_init;
uint8_t bitmask;
/*bpp = 3 should be converted to bpp = 4 in lv_font_get_glyph_bitmap */
if(g.bpp == 3) g.bpp = 4;
switch(g.bpp) {
case 1:
bpp_opa_table = bpp1_opa_table;

View File

@@ -8,6 +8,7 @@
*********************/
#include "lv_font.h"
#include "lv_font_fmt_txt.h"
#include "../lv_draw/lv_draw.h"
#include "../lv_misc/lv_types.h"
#include "../lv_misc/lv_log.h"
#include "../lv_misc/lv_utils.h"
@@ -20,6 +21,11 @@
/**********************
* TYPEDEFS
**********************/
typedef enum {
RLE_STATE_SINGLE = 0,
RLE_STATE_REPEATE,
RLE_STATE_COUNTER,
}rle_state_t;
/**********************
* STATIC PROTOTYPES
@@ -29,12 +35,26 @@ static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t
static int32_t unicode_list_compare(const void * ref, const void * element);
static int32_t kern_pair_8_compare(const void * ref, const void * element);
static int32_t kern_pair_16_compare(const void * ref, const void * element);
static void decompress(const uint8_t * in, uint8_t * out, uint16_t px_num, uint8_t bpp);
static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord_t h, uint8_t bpp);
static void decompress_line(uint8_t * out, lv_coord_t w);
static uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len);
static void bits_write(uint8_t * out, uint32_t bit_pos, uint8_t val, uint8_t len);
static void rle_init(const uint8_t * in, uint8_t bpp);
static uint8_t rle_next(void);
/**********************
* STATIC VARIABLES
**********************/
static uint32_t rle_rdp;
static const uint8_t * rle_in;
static uint8_t rle_bpp;
static uint8_t rle_prev_v;
static uint8_t rle_cnt;
static rle_state_t rle_state;
/**********************
* GLOBAL PROTOTYPES
**********************/
@@ -61,11 +81,11 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unic
const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid];
// if(fdsc->bitmap_format == LV_FONT_FMT_TXT_PLAIN) {
// if(gdsc) return &fdsc->glyph_bitmap[gdsc->bitmap_index];
// }
// /*Handle compressed bitmap*/
// else
if(fdsc->bitmap_format == LV_FONT_FMT_TXT_PLAIN) {
if(gdsc) return &fdsc->glyph_bitmap[gdsc->bitmap_index];
}
/*Handle compressed bitmap*/
else
{
static uint8_t * buf = NULL;
@@ -84,7 +104,7 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unic
if(buf == NULL) return NULL;
}
decompress(&fdsc->glyph_bitmap[gdsc->bitmap_index], buf, gdsc->box_w * gdsc->box_h, fdsc->bpp);
decompress(&fdsc->glyph_bitmap[gdsc->bitmap_index], buf, gdsc->box_w , gdsc->box_h, fdsc->bpp);
return buf;
}
@@ -265,7 +285,57 @@ static int32_t kern_pair_16_compare(const void * ref, const void * element)
else return (int32_t) ref16_p[1] - element16_p[1];
}
/**
* The compress a glyph's bitmap
* @param in the compressed bitmap
* @param out buffer to store the result
* @param px_num number of pixels in the glyph (width * height)
* @param bpp bit per pixel (bpp = 3 will be converted to bpp = 4)
*/
static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord_t h, uint8_t bpp)
{
uint32_t wrp = 0;
uint8_t wr_size = bpp;
if(bpp == 3) wr_size = 4;
rle_init(in, bpp);
uint8_t * line_buf = lv_draw_get_buf(w * 2);
uint8_t * line_buf1 = line_buf;
uint8_t * line_buf2 = line_buf + w;
decompress_line(line_buf1, w);
lv_coord_t y;
lv_coord_t x;
for(x = 0; x < w; x++) {
bits_write(out,wrp, line_buf1[x], bpp);
wrp += wr_size;
}
for(y = 1; y < h; y++) {
decompress_line(line_buf2, w);
for(x = 0; x < w; x++) {
line_buf1[x] = line_buf2[x] ^ line_buf1[x];
bits_write(out,wrp, line_buf1[x], bpp);
wrp += wr_size;
}
}
}
/**
* Decompress one line. Store one pixel per byte
* @param out output buffer
* @param w width of the line in pixel count
*/
static void decompress_line(uint8_t * out, lv_coord_t w)
{
lv_coord_t i;
for(i = 0; i < w; i++) {
out[i] = rle_next();
}
}
/**
* Read bits from an input buffer. The read can cross byte boundary.
@@ -319,77 +389,70 @@ static void bits_write(uint8_t * out, uint32_t bit_pos, uint8_t val, uint8_t len
out[byte_pos] |= (val << bit_pos);
}
/**
* The compress a glyph's bitmap
* @param in the compressed bitmap
* @param out buffer to store the result
* @param px_num number of pixels in the glyph (width * height)
* @param bpp bit per pixel (bpp = 3 will be converted to bpp = 4)
*/
static void decompress(const uint8_t * in, uint8_t * out, uint16_t px_num, uint8_t bpp)
static void rle_init(const uint8_t * in, uint8_t bpp)
{
uint32_t rdp = 0;
uint32_t wrp = 0;
uint16_t px_cnt = 0;
uint8_t wr_size = bpp;
if(bpp == 3) wr_size = 4;
rle_in = in;
rle_bpp = bpp;
rle_state = RLE_STATE_SINGLE;
rle_rdp = 0;
rle_prev_v = 0;
rle_cnt = 0;
}
uint8_t act_val = get_bits(in, rdp, bpp);
rdp += bpp;
static uint8_t rle_next(void)
{
uint8_t v = 0;
uint8_t ret = 0;
while(px_cnt < px_num) {
bits_write(out, wrp, act_val, bpp);
wrp += wr_size;
px_cnt ++;
uint8_t next_val = get_bits(in, rdp, bpp);
rdp += bpp;
/*If the new value is different the it's simply the next pixel*/
if(act_val != next_val) {
act_val = next_val;
if(rle_state == RLE_STATE_SINGLE) {
ret = get_bits(rle_in, rle_rdp, rle_bpp);
if(rle_rdp != 0 && rle_prev_v == ret) {
rle_cnt = 0;
rle_state = RLE_STATE_REPEATE;
}
/*If the next px is the same the this pixel will be repeated */
else {
bits_write(out, wrp, next_val, bpp);
wrp += wr_size;
px_cnt ++;
uint8_t i;
for(i = 0; i < 11; i++) {
uint8_t r;
r = get_bits(in, rdp, 1);
rdp++;
if(r == 1) {
if(i != 10) { /*Ignore the 11th '1'*/
bits_write(out, wrp, next_val, bpp);
wrp += wr_size;
px_cnt++;
}
}
else break; /*Zero closes the repeats*/
}
/*After 11 repeats a 6 bit counter comes*/
if(i == 11) {
uint8_t cnt = get_bits(in, rdp, 6);
rdp += 6;
uint8_t i;
for(i = 0; i < cnt; i++) {
bits_write(out, wrp, next_val, bpp);
wrp += wr_size;
px_cnt ++;
rle_prev_v = ret;
rle_rdp += rle_bpp;
}
else if(rle_state == RLE_STATE_REPEATE) {
v = get_bits(rle_in, rle_rdp, 1);
rle_cnt++;
rle_rdp += 1;
if(v == 1) {
ret = rle_prev_v;
if(rle_cnt == 11) {
rle_cnt = get_bits(rle_in, rle_rdp, 6);
rle_rdp += 6;
if(rle_cnt != 0) {
rle_state = RLE_STATE_COUNTER;
} else {
ret = get_bits(rle_in, rle_rdp, rle_bpp);
rle_prev_v = ret;
rle_rdp += rle_bpp;
rle_state = RLE_STATE_SINGLE;
}
}
} else {
ret = get_bits(rle_in, rle_rdp, rle_bpp);
rle_prev_v = ret;
rle_rdp += rle_bpp;
rle_state = RLE_STATE_SINGLE;
}
/*Preload the next pixel*/
act_val = get_bits(in, rdp, bpp);
rdp += bpp;
}
else if(rle_state == RLE_STATE_COUNTER) {
ret = rle_prev_v;
rle_cnt--;
if(rle_cnt == 0) {
ret = get_bits(rle_in, rle_rdp, rle_bpp);
rle_prev_v = ret;
rle_rdp += rle_bpp;
rle_state = RLE_STATE_SINGLE;
}
}
return ret;
}
/** Code Comparator.