You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
686 lines
16 KiB
686 lines
16 KiB
/* epd_font.c */ |
|
|
|
/* Includes */ |
|
#include "epd.h" |
|
#include "epd_font.h" |
|
#include "epd_fonts.h" |
|
#include "util.h" |
|
|
|
/* Definitions */ |
|
#define EPD_FONT_DATA_STRUCT_SIZE 23 |
|
#define epd_pgm_read(adr) (*(const uint8_t *) (adr)) |
|
|
|
/* Function Prototypes */ |
|
static void epd_read_fontcfg(epd_fontcfg_t *cfg, epd_font_t *font); |
|
static uint8_t epd_font_get_byte(epd_font_t *font, uint8_t offset); |
|
static uint16_t epd_font_get_word(epd_font_t *font, uint8_t offset); |
|
static void epd_update_ref_height(epd_t *epd); |
|
static uint16_t epd_ascii_next(UNUSED epd_t *epd, uint8_t b); |
|
static uint16_t epd_utf8_next(epd_t *epd, uint8_t b); |
|
static uint8_t epd_draw_string(epd_t *epd, uint32_t x, uint32_t y, const char *str); |
|
static uint8_t epd_draw_glyph(epd_t *epd, uint32_t x, uint32_t y, uint16_t encoding); |
|
static uint8_t epd_font_draw_glyph(epd_t *epd, uint32_t x, uint32_t y, uint16_t encoding); |
|
epd_font_t *epd_font_get_glyph_data(epd_t *epd, uint16_t encoding); |
|
static int8_t epd_font_decode_glyph(epd_t *epd, const uint8_t *glyph_data); |
|
static void epd_font_setup_decode(epd_t *epd, const uint8_t *glyph_data); |
|
static int8_t epd_font_decode_get_signed_bits(epd_font_decode_t *f, uint8_t cnt); |
|
static uint8_t epd_font_decode_get_unsigned_bits(epd_font_decode_t *f, uint8_t cnt); |
|
static void epd_font_decode_len(epd_t *epd, uint8_t len, uint8_t is_foreground); |
|
|
|
/* Function Definitions */ |
|
void epd_font_set(epd_t *epd, epd_font_t *font) |
|
{ |
|
if(epd->font != font) |
|
{ |
|
epd->font = font; |
|
epd_read_fontcfg(&(epd->fontdata.cfg), font); |
|
epd_update_ref_height(epd); |
|
} |
|
} |
|
|
|
static void epd_read_fontcfg(epd_fontcfg_t *cfg, epd_font_t *font) |
|
{ |
|
/* offset 0 */ |
|
cfg->glyph_cnt = epd_font_get_byte(font, 0); |
|
cfg->bbx_mode = epd_font_get_byte(font, 1); |
|
cfg->bits_per_0 = epd_font_get_byte(font, 2); |
|
cfg->bits_per_1 = epd_font_get_byte(font, 3); |
|
|
|
/* offset 4 */ |
|
cfg->bits_per_char_width = epd_font_get_byte(font, 4); |
|
cfg->bits_per_char_height = epd_font_get_byte(font, 5); |
|
cfg->bits_per_char_x = epd_font_get_byte(font, 6); |
|
cfg->bits_per_char_y = epd_font_get_byte(font, 7); |
|
cfg->bits_per_delta_x = epd_font_get_byte(font, 8); |
|
|
|
/* offset 9 */ |
|
cfg->max_char_width = epd_font_get_byte(font, 9); |
|
cfg->max_char_height = epd_font_get_byte(font, 10); |
|
cfg->x_offset = epd_font_get_byte(font, 11); |
|
cfg->y_offset = epd_font_get_byte(font, 12); |
|
|
|
/* offset 13 */ |
|
cfg->ascent_A = epd_font_get_byte(font, 13); |
|
cfg->descent_g = epd_font_get_byte(font, 14); |
|
cfg->ascent_para = epd_font_get_byte(font, 15); |
|
cfg->descent_para = epd_font_get_byte(font, 16); |
|
|
|
/* offset 17 */ |
|
cfg->start_pos_upper_A = epd_font_get_word(font, 17); |
|
cfg->start_pos_lower_a = epd_font_get_word(font, 19); |
|
|
|
#ifdef EPD_WITH_UNICODE |
|
/* offset 21 */ |
|
fontcfg->start_pos_unicode = epd_font_get_word(font, 21); |
|
#endif |
|
} |
|
|
|
static uint8_t epd_font_get_byte(epd_font_t *font, uint8_t offset) |
|
{ |
|
font += offset; |
|
return epd_pgm_read(font); |
|
} |
|
|
|
static uint16_t epd_font_get_word(epd_font_t *font, uint8_t offset) |
|
{ |
|
uint16_t pos; |
|
|
|
font += offset; |
|
pos = epd_pgm_read(font); |
|
font++; |
|
pos <<= 8; |
|
pos += epd_pgm_read(font); |
|
|
|
return pos; |
|
} |
|
|
|
static void epd_update_ref_height(epd_t *epd) |
|
{ |
|
return_if_fail(epd->font); |
|
|
|
epd->fontdata.ref_ascent = epd->fontdata.cfg.ascent_A; |
|
epd->fontdata.ref_descent = epd->fontdata.cfg.descent_g; |
|
if(epd->fontdata.height_mode == EPD_FONT_HEIGHT_MODE_TEXT) |
|
{ |
|
} |
|
else if(epd->fontdata.height_mode == EPD_FONT_HEIGHT_MODE_XTEXT) |
|
{ |
|
if(epd->fontdata.ref_ascent < epd->fontdata.cfg.ascent_para) |
|
{ |
|
epd->fontdata.ref_ascent = epd->fontdata.cfg.ascent_para; |
|
} |
|
if(epd->fontdata.ref_descent > epd->fontdata.cfg.descent_para) |
|
{ |
|
epd->fontdata.ref_descent = epd->fontdata.cfg.descent_para; |
|
} |
|
} |
|
else |
|
{ |
|
if(epd->fontdata.ref_ascent < epd->fontdata.cfg.max_char_height + epd->fontdata.cfg.y_offset) |
|
{ |
|
epd->fontdata.ref_ascent = epd->fontdata.cfg.max_char_height + epd->fontdata.cfg.y_offset; |
|
} |
|
if(epd->fontdata.ref_descent > epd->fontdata.cfg.y_offset) |
|
{ |
|
epd->fontdata.ref_descent = epd->fontdata.cfg.y_offset; |
|
} |
|
} |
|
} |
|
|
|
uint8_t epd_draw_str(epd_t *epd, uint32_t x, uint32_t y, const char *str) |
|
{ |
|
epd->fontdata.char_cb = epd_ascii_next; |
|
return epd_draw_string(epd, x, y, str); |
|
} |
|
|
|
uint8_t epd_draw_utf8(epd_t *epd, uint32_t x, uint32_t y, const char *str) |
|
{ |
|
epd->fontdata.char_cb = epd_utf8_next; |
|
return epd_draw_string(epd, x, y, str); |
|
} |
|
|
|
static uint16_t epd_ascii_next(UNUSED epd_t *epd, uint8_t b) |
|
{ |
|
if(b == 0 || b == '\n') /* '\n' terminates the string to support the string list procedures */ |
|
{ |
|
return 0xffff; /* end of string detected*/ |
|
} |
|
|
|
return b; |
|
} |
|
|
|
/* |
|
pass a byte from an utf8 encoded string to the utf8 decoder state machine |
|
returns |
|
0xfffe: no glyph, just continue |
|
0xffff: end of string |
|
anything else: The decoded encoding |
|
*/ |
|
static uint16_t epd_utf8_next(epd_t *epd, uint8_t b) |
|
{ |
|
if(b == 0 || b == '\n') /* '\n' terminates the string to support the string list procedures */ |
|
{ |
|
return 0xffff; /* end of string detected, pending UTF8 is discarded */ |
|
} |
|
if(epd->fontdata.utf8_state == 0) |
|
{ |
|
if(b >= 0xfc) /* 6 byte sequence */ |
|
{ |
|
epd->fontdata.utf8_state = 5; |
|
b &= 0x01; |
|
} |
|
else if(b >= 0xf8) |
|
{ |
|
epd->fontdata.utf8_state = 4; |
|
b &= 0x03; |
|
} |
|
else if(b >= 0xf0) |
|
{ |
|
epd->fontdata.utf8_state = 3; |
|
b &= 0x07; |
|
} |
|
else if(b >= 0xe0) |
|
{ |
|
epd->fontdata.utf8_state = 2; |
|
b &= 0x0f; |
|
} |
|
else if(b >= 0xc0) |
|
{ |
|
epd->fontdata.utf8_state = 1; |
|
b &= 0x1f; |
|
} |
|
else |
|
{ |
|
/* do nothing, just use the value as encoding */ |
|
return b; |
|
} |
|
epd->fontdata.encoding = b; |
|
return 0xfffe; |
|
} |
|
else |
|
{ |
|
epd->fontdata.utf8_state--; |
|
/* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */ |
|
epd->fontdata.encoding <<= 6; |
|
b &= 0x3f; |
|
epd->fontdata.encoding |= b; |
|
if(epd->fontdata.utf8_state != 0) |
|
{ |
|
return 0xfffe; /* nothing to do yet */ |
|
} |
|
} |
|
|
|
return epd->fontdata.encoding; |
|
} |
|
|
|
/* reset the internal state machine */ |
|
void epd_utf8_init(epd_t *epd) |
|
{ |
|
epd->fontdata.utf8_state = 0; |
|
} |
|
|
|
static uint8_t epd_draw_string(epd_t *epd, uint32_t x, uint32_t y, const char *str) |
|
{ |
|
uint16_t e; |
|
uint8_t delta, sum; |
|
epd_utf8_init(epd); |
|
sum = 0; |
|
for(;;) |
|
{ |
|
e = epd->fontdata.char_cb(epd, (uint8_t) *str); |
|
if(e == 0xffff) |
|
break; |
|
str++; |
|
if(e != 0xfffe) |
|
{ |
|
delta = epd_draw_glyph(epd, x, y, e); |
|
|
|
#ifdef EPD_WITH_FONT_ROTATION |
|
switch(epd->fontdata.decode.dir) |
|
{ |
|
case 0: |
|
x += delta; |
|
break; |
|
case 1: |
|
y += delta; |
|
break; |
|
case 2: |
|
x -= delta; |
|
break; |
|
case 3: |
|
y -= delta; |
|
break; |
|
} |
|
|
|
/* |
|
// requires 10 bytes more on avr |
|
x = epd_add_vector_x(x, delta, 0, epd->fontdata.decode.dir); |
|
y = epd_add_vector_y(y, delta, 0, epd->fontdata.decode.dir); |
|
*/ |
|
|
|
#else |
|
x += delta; |
|
#endif |
|
|
|
sum += delta; |
|
} |
|
} |
|
return sum; |
|
} |
|
|
|
static uint8_t epd_draw_glyph(epd_t *epd, uint32_t x, uint32_t y, uint16_t encoding) |
|
{ |
|
#ifdef EPD_WITH_FONT_ROTATION |
|
switch(epd->fontdata.decode.dir) |
|
{ |
|
case 0: |
|
y += epd->font_calc_vref(epd); |
|
break; |
|
case 1: |
|
x -= epd->font_calc_vref(epd); |
|
break; |
|
case 2: |
|
y -= epd->font_calc_vref(epd); |
|
break; |
|
case 3: |
|
x += epd->font_calc_vref(epd); |
|
break; |
|
} |
|
#else |
|
/* FIXME */ |
|
/* y += epd->font_calc_vref(epd); */ |
|
#endif |
|
return epd_font_draw_glyph(epd, x, y, encoding); |
|
} |
|
|
|
static uint8_t epd_font_draw_glyph(epd_t *epd, uint32_t x, uint32_t y, uint16_t encoding) |
|
{ |
|
uint8_t dx = 0; |
|
epd->fontdata.decode.target_x = x; |
|
epd->fontdata.decode.target_y = y; |
|
//epd->fontdata.decode.is_transparent = is_transparent; this is already set |
|
//epd->fontdata.decode.dir = dir; |
|
const uint8_t *glyph_data = epd_font_get_glyph_data(epd, encoding); |
|
if(glyph_data != NULL) |
|
{ |
|
dx = epd_font_decode_glyph(epd, glyph_data); |
|
} |
|
return dx; |
|
} |
|
|
|
/* |
|
Description: |
|
Find the starting point of the glyph data. |
|
Args: |
|
encoding: Encoding (ASCII or Unicode) of the glyph |
|
Return: |
|
Address of the glyph data or NULL, if the encoding is not avialable in the font. |
|
*/ |
|
epd_font_t *epd_font_get_glyph_data(epd_t *epd, uint16_t encoding) |
|
{ |
|
epd_font_t *font = epd->font; |
|
font += EPD_FONT_DATA_STRUCT_SIZE; |
|
|
|
if(encoding <= 255) |
|
{ |
|
if(encoding >= 'a') |
|
{ |
|
font += epd->fontdata.cfg.start_pos_lower_a; |
|
} |
|
else if(encoding >= 'A') |
|
{ |
|
font += epd->fontdata.cfg.start_pos_upper_A; |
|
} |
|
|
|
for(;;) |
|
{ |
|
if(epd_pgm_read(font + 1) == 0) |
|
{ |
|
break; |
|
} |
|
if(epd_pgm_read(font) == encoding) |
|
{ |
|
return font + 2; /* skip encoding and glyph size */ |
|
} |
|
font += epd_pgm_read(font + 1); |
|
} |
|
} |
|
#ifdef EPD_WITH_UNICODE |
|
else |
|
{ |
|
uint16_t e; |
|
const uint8_t *unicode_lookup_table; |
|
|
|
font += epd->fontdata.cfg.start_pos_unicode; |
|
unicode_lookup_table = font; |
|
|
|
/* issue 596: search for the glyph start in the unicode lookup table */ |
|
do |
|
{ |
|
font += epd_font_get_word(unicode_lookup_table, 0); |
|
e = epd_font_get_word(unicode_lookup_table, 2); |
|
unicode_lookup_table+=4; |
|
} while(e < encoding); |
|
|
|
for(;;) |
|
{ |
|
e = epd_pgm_read(font); |
|
e <<= 8; |
|
e |= epd_pgm_read(font + 1); |
|
|
|
if(e == 0) |
|
break; |
|
|
|
if(e == encoding) |
|
{ |
|
return font+3; /* skip encoding and glyph size */ |
|
} |
|
font += epd_pgm_read(font + 2); |
|
} |
|
} |
|
#endif |
|
|
|
return NULL; |
|
} |
|
|
|
/* |
|
Description: |
|
Decode and draw a glyph. |
|
Args: |
|
glyph_data: Pointer to the compressed glyph data of the font |
|
epd->fontdata.decode.target_x X position |
|
epd->fontdata.decode.target_y Y position |
|
epd->fontdata.decode.is_transparent Transparent mode |
|
Return: |
|
Width (delta x advance) of the glyph. |
|
Calls: |
|
epd_font_decode_len() |
|
*/ |
|
/* optimized */ |
|
int8_t epd_font_decode_glyph(epd_t *epd, const uint8_t *glyph_data) |
|
{ |
|
uint8_t a, b; |
|
int8_t x, y; |
|
int8_t d; |
|
int8_t h; |
|
epd_font_decode_t *decode = &(epd->fontdata.decode); |
|
|
|
epd_font_setup_decode(epd, glyph_data); /* set values in epd->fontdata.decode data structure */ |
|
h = epd->fontdata.decode.glyph_height; |
|
|
|
x = epd_font_decode_get_signed_bits(decode, epd->fontdata.cfg.bits_per_char_x); |
|
y = epd_font_decode_get_signed_bits(decode, epd->fontdata.cfg.bits_per_char_y); |
|
d = epd_font_decode_get_signed_bits(decode, epd->fontdata.cfg.bits_per_delta_x); |
|
|
|
if(decode->glyph_width > 0) |
|
{ |
|
#ifdef EPD_WITH_FONT_ROTATION |
|
decode->target_x = epd_add_vector_x(decode->target_x, x, -(h+y), decode->dir); |
|
decode->target_y = epd_add_vector_y(decode->target_y, x, -(h+y), decode->dir); |
|
|
|
//epd_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir); |
|
|
|
#else |
|
decode->target_x += x; |
|
decode->target_y -= h+y; |
|
#endif |
|
//epd_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir); |
|
|
|
#ifdef EPD_WITH_INTERSECTION |
|
{ |
|
uint32_t x0, x1, y0, y1; |
|
x0 = decode->target_x; |
|
y0 = decode->target_y; |
|
x1 = x0; |
|
y1 = y0; |
|
|
|
#ifdef EPD_WITH_FONT_ROTATION |
|
switch(decode->dir) |
|
{ |
|
case 0: |
|
x1 += decode->glyph_width; |
|
y1 += h; |
|
break; |
|
case 1: |
|
x0 -= h; |
|
x0++; /* shift down, because of assymetric boundaries for the interseciton test */ |
|
x1++; |
|
y1 += decode->glyph_width; |
|
break; |
|
case 2: |
|
x0 -= decode->glyph_width; |
|
x0++; /* shift down, because of assymetric boundaries for the interseciton test */ |
|
x1++; |
|
y0 -= h; |
|
y0++; /* shift down, because of assymetric boundaries for the interseciton test */ |
|
y1++; |
|
break; |
|
case 3: |
|
x1 += h; |
|
y0 -= decode->glyph_width; |
|
y0++; /* shift down, because of assymetric boundaries for the interseciton test */ |
|
y1++; |
|
break; |
|
} |
|
#else /* EPD_WITH_FONT_ROTATION */ |
|
x1 += decode->glyph_width; |
|
y1 += h; |
|
#endif |
|
|
|
if(epd_IsIntersection(epd, x0, y0, x1, y1) == 0) |
|
return d; |
|
} |
|
#endif /* EPD_WITH_INTERSECTION */ |
|
|
|
/* reset local x/y position */ |
|
decode->x = 0; |
|
decode->y = 0; |
|
|
|
/* decode glyph */ |
|
for(;;) |
|
{ |
|
a = epd_font_decode_get_unsigned_bits(decode, epd->fontdata.cfg.bits_per_0); |
|
b = epd_font_decode_get_unsigned_bits(decode, epd->fontdata.cfg.bits_per_1); |
|
do |
|
{ |
|
epd_font_decode_len(epd, a, 0); |
|
epd_font_decode_len(epd, b, 1); |
|
} while(epd_font_decode_get_unsigned_bits(decode, 1) != 0); |
|
|
|
if(decode->y >= h) |
|
{ |
|
break; |
|
} |
|
} |
|
|
|
/* restore the epd draw color, because this is modified by the decode algo */ |
|
epd->draw_color = decode->fg_color; |
|
} |
|
return d; |
|
} |
|
|
|
static void epd_font_setup_decode(epd_t *epd, const uint8_t *glyph_data) |
|
{ |
|
epd_font_decode_t *decode = &(epd->fontdata.decode); |
|
decode->decode_ptr = glyph_data; |
|
decode->decode_bit_pos = 0; |
|
|
|
/* 8 Nov 2015, this is already done in the glyph data search procedure */ |
|
/* |
|
decode->decode_ptr += 1; |
|
decode->decode_ptr += 1; |
|
*/ |
|
|
|
decode->glyph_width = epd_font_decode_get_unsigned_bits(decode, epd->fontdata.cfg.bits_per_char_width); |
|
decode->glyph_height = epd_font_decode_get_unsigned_bits(decode, epd->fontdata.cfg.bits_per_char_height); |
|
|
|
decode->fg_color = epd->draw_color; |
|
decode->bg_color = (decode->fg_color == 0 ? 1 : 0); |
|
} |
|
|
|
/* |
|
2 bit --> cnt = 2 |
|
-2,-1,0. 1 |
|
|
|
3 bit --> cnt = 3 |
|
-2,-1,0. 1 |
|
-4,-3,-2,-1,0,1,2,3 |
|
|
|
if(x < 0) |
|
r = bits(x-1)+1; |
|
else |
|
r = bits(x)+1; |
|
|
|
*/ |
|
/* optimized */ |
|
static int8_t epd_font_decode_get_signed_bits(epd_font_decode_t *f, uint8_t cnt) |
|
{ |
|
int8_t v, d; |
|
v = (int8_t)epd_font_decode_get_unsigned_bits(f, cnt); |
|
d = 1; |
|
cnt--; |
|
d <<= cnt; |
|
v -= d; |
|
return v; |
|
//return (int8_t)epd_font_decode_get_unsigned_bits(f, cnt) - ((1<<cnt)>>1); |
|
} |
|
|
|
/* optimized */ |
|
static uint8_t epd_font_decode_get_unsigned_bits(epd_font_decode_t *f, uint8_t cnt) |
|
{ |
|
uint8_t val; |
|
uint8_t bit_pos = f->decode_bit_pos; |
|
uint8_t bit_pos_plus_cnt; |
|
|
|
val = epd_pgm_read(f->decode_ptr); |
|
|
|
val >>= bit_pos; |
|
bit_pos_plus_cnt = bit_pos; |
|
bit_pos_plus_cnt += cnt; |
|
if(bit_pos_plus_cnt >= 8) |
|
{ |
|
f->decode_ptr++; |
|
val |= epd_pgm_read(f->decode_ptr) << (8 - bit_pos); |
|
bit_pos_plus_cnt -= 8; |
|
} |
|
val &= (1U << cnt) - 1; |
|
|
|
f->decode_bit_pos = bit_pos_plus_cnt; |
|
return val; |
|
} |
|
|
|
/* |
|
Description: |
|
Draw a run-length area of the glyph. "len" can have any size and the line |
|
length has to be wrapped at the glyph border. |
|
Args: |
|
len: Length of the line |
|
is_foreground foreground/background? |
|
epd->fontdata.decode.target_x X position |
|
epd->fontdata.decode.target_y Y position |
|
epd->fontdata.decode.is_transparent Transparent mode |
|
Return: |
|
- |
|
Calls: |
|
epd_Draw90Line() |
|
Called by: |
|
epd_font_decode_glyph() |
|
*/ |
|
/* optimized */ |
|
static void epd_font_decode_len(epd_t *epd, uint8_t len, uint8_t is_foreground) |
|
{ |
|
uint8_t cnt; /* total number of remaining pixels, which have to be drawn */ |
|
uint8_t rem; /* remaining pixel to the right edge of the glyph */ |
|
uint8_t current; /* number of pixels, which need to be drawn for the draw procedure */ |
|
/* current is either equal to cnt or equal to rem */ |
|
|
|
/* local coordinates of the glyph */ |
|
uint8_t lx,ly; |
|
|
|
/* target position on the screen */ |
|
uint16_t x, y; |
|
|
|
epd_font_decode_t *decode = &(epd->fontdata.decode); |
|
|
|
cnt = len; |
|
|
|
/* get the local position */ |
|
lx = decode->x; |
|
ly = decode->y; |
|
|
|
for(;;) |
|
{ |
|
/* calculate the number of pixel to the right edge of the glyph */ |
|
rem = decode->glyph_width; |
|
rem -= lx; |
|
|
|
/* calculate how many pixel to draw. This is either to the right edge */ |
|
/* or lesser, if not enough pixel are left */ |
|
current = rem; |
|
if(cnt < rem) |
|
current = cnt; |
|
|
|
/* now draw the line, but apply the rotation around the glyph target position */ |
|
//epd_font_decode_draw_pixel(epd, lx,ly,current, is_foreground); |
|
|
|
/* get target position */ |
|
x = decode->target_x; |
|
y = decode->target_y; |
|
|
|
/* apply rotation */ |
|
#ifdef EPD_WITH_FONT_ROTATION |
|
|
|
x = epd_add_vector_x(x, lx, ly, decode->dir); |
|
y = epd_add_vector_y(y, lx, ly, decode->dir); |
|
|
|
//epd_add_vector(&x, &y, lx, ly, decode->dir); |
|
|
|
#else |
|
x += lx; |
|
y += ly; |
|
#endif |
|
|
|
/* draw foreground and background (if required) */ |
|
if(is_foreground) |
|
{ |
|
epd->draw_color = decode->fg_color; /* draw_color will be restored later */ |
|
epd_draw_line(epd, |
|
x, |
|
y, |
|
current, |
|
#ifdef EPD_WITH_FONT_ROTATION |
|
decode->dir |
|
#else |
|
EPD_DIR_L2R |
|
#endif |
|
); |
|
} |
|
else if(decode->is_transparent == 0) |
|
{ |
|
epd->draw_color = decode->bg_color; /* draw_color will be restored later */ |
|
epd_draw_line(epd, |
|
x, |
|
y, |
|
current, |
|
#ifdef EPD_WITH_FONT_ROTATION |
|
decode->dir |
|
#else |
|
EPD_DIR_L2R |
|
#endif |
|
); |
|
} |
|
|
|
/* check, whether the end of the run length code has been reached */ |
|
if(cnt < rem) |
|
{ |
|
break; |
|
} |
|
cnt -= rem; |
|
lx = 0; |
|
ly++; |
|
} |
|
lx += cnt; |
|
|
|
decode->x = lx; |
|
decode->y = ly; |
|
}
|
|
|