123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*********************
- * INCLUDES
- *********************/
- #include <os_common_api.h>
- /*********************
- * DEFINES
- *********************/
- /**********************
- * TYPEDEFS
- **********************/
- typedef enum {
- RLE_STATE_SINGLE = 0,
- RLE_STATE_REPEATE,
- RLE_STATE_COUNTER,
- } rle_state_t;
- /**********************
- * STATIC PROTOTYPES
- **********************/
- void decompress_glyf_bitmap(const uint8_t * in, uint8_t * out, int16_t w, int16_t h, uint8_t bpp, bool prefilter, uint8_t* linebuf1, uint8_t* linebuf2);
- static inline void decompress_line(uint8_t * out, int16_t w);
- static inline uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len);
- static inline void bits_write(uint8_t * out, uint32_t bit_pos, uint8_t val, uint8_t len);
- static inline void rle_init(const uint8_t * in, uint8_t bpp);
- static inline 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 FUNCTIONS
- **********************/
- /**
- * 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)
- * @param prefilter true: the lines are XORed
- */
- void decompress_glyf_bitmap(const uint8_t * in, uint8_t * out, int16_t w, int16_t h, uint8_t bpp, bool prefilter, uint8_t* linebuf1, uint8_t* linebuf2)
- {
- uint32_t wrp = 0;
- uint8_t wr_size = bpp;
- if(bpp == 3) wr_size = 4;
- rle_init(in, bpp);
- //uint8_t * line_buf1 = bitmap_font_cache_malloc(w);
- uint8_t* line_buf1 = linebuf1;
- uint8_t * line_buf2 = NULL;
- if(prefilter) {
- //line_buf2 = bitmap_font_cache_malloc(w);
- line_buf2 = linebuf2;
- }
- decompress_line(line_buf1, w);
- int16_t y;
- int16_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++) {
- if(prefilter) {
- 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;
- }
- }
- else {
- decompress_line(line_buf1, w);
- for(x = 0; x < w; x++) {
- bits_write(out, wrp, line_buf1[x], bpp);
- wrp += wr_size;
- }
- }
- }
- //bitmap_font_cache_free(line_buf1);
- //bitmap_font_cache_free(line_buf2);
- }
- /**
- * Decompress one line. Store one pixel per byte
- * @param out output buffer
- * @param w width of the line in pixel count
- */
- static inline void decompress_line(uint8_t * out, int16_t w)
- {
- int16_t i;
- for(i = 0; i < w; i++) {
- out[i] = rle_next();
- }
- }
- /**
- * Read bits from an input buffer. The read can cross byte boundary.
- * @param in the input buffer to read from.
- * @param bit_pos index of the first bit to read.
- * @param len number of bits to read (must be <= 8).
- * @return the read bits
- */
- static inline uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len)
- {
- uint8_t bit_mask;
- switch(len) {
- case 1:
- bit_mask = 0x1;
- break;
- case 2:
- bit_mask = 0x3;
- break;
- case 3:
- bit_mask = 0x7;
- break;
- case 4:
- bit_mask = 0xF;
- break;
- case 8:
- bit_mask = 0xFF;
- break;
- default:
- bit_mask = (uint16_t)((uint16_t) 1 << len) - 1;
- }
- uint32_t byte_pos = bit_pos >> 3;
- bit_pos = bit_pos & 0x7;
- if(bit_pos + len >= 8) {
- uint16_t in16 = (in[byte_pos] << 8) + in[byte_pos + 1];
- return (in16 >> (16 - bit_pos - len)) & bit_mask;
- }
- else {
- return (in[byte_pos] >> (8 - bit_pos - len)) & bit_mask;
- }
- }
- /**
- * Write `val` data to `bit_pos` position of `out`. The write can NOT cross byte boundary.
- * @param out buffer where to write
- * @param bit_pos bit index to write
- * @param val value to write
- * @param len length of bits to write from `val`. (Counted from the LSB).
- * @note `len == 3` will be converted to `len = 4` and `val` will be upscaled too
- */
- static inline void bits_write(uint8_t * out, uint32_t bit_pos, uint8_t val, uint8_t len)
- {
- if(len == 3) {
- len = 4;
- switch(val) {
- case 0:
- val = 0;
- break;
- case 1:
- val = 2;
- break;
- case 2:
- val = 4;
- break;
- case 3:
- val = 6;
- break;
- case 4:
- val = 9;
- break;
- case 5:
- val = 11;
- break;
- case 6:
- val = 13;
- break;
- case 7:
- val = 15;
- break;
- }
- }
- uint16_t byte_pos = bit_pos >> 3;
- bit_pos = bit_pos & 0x7;
- bit_pos = 8 - bit_pos - len;
- uint8_t bit_mask = (uint16_t)((uint16_t) 1 << len) - 1;
- out[byte_pos] &= ((~bit_mask) << bit_pos);
- out[byte_pos] |= (val << bit_pos);
- }
- static inline void rle_init(const uint8_t * in, uint8_t bpp)
- {
- rle_in = in;
- rle_bpp = bpp;
- rle_state = RLE_STATE_SINGLE;
- rle_rdp = 0;
- rle_prev_v = 0;
- rle_cnt = 0;
- }
- static inline uint8_t rle_next(void)
- {
- uint8_t v = 0;
- uint8_t ret = 0;
- 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;
- }
- 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;
- }
- }
- 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;
- }
|