From 159344852921967140b44de91e1eb717f23f6cde Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Thu, 8 Mar 2018 16:53:10 +0200 Subject: Implement print buffer and utf8 Now just raster modes and it's done. --- src/escpos/parser.rl | 134 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 95 insertions(+), 39 deletions(-) (limited to 'src/escpos/parser.rl') diff --git a/src/escpos/parser.rl b/src/escpos/parser.rl index 1e045c7..015c690 100644 --- a/src/escpos/parser.rl +++ b/src/escpos/parser.rl @@ -7,6 +7,7 @@ #include #include #include +#include "utf8.h" #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y)) @@ -14,8 +15,15 @@ static const uint8_t SPACING = 1; -struct raster { +struct utf8 { + uint32_t state; +}; + +struct cursor { size_t x, y, wy; +}; + +struct raster { struct font font; uint8_t barcode_height; uint8_t barcode_type; @@ -36,59 +44,91 @@ struct raster { }; static void -render_chr(struct escpos_canvas *canvas, struct raster *raster, const char chr) +init_canvas(struct escpos_canvas *canvas, struct cursor *cursor) +{ + assert(canvas && cursor); + memset(canvas->data, 0, canvas->w * canvas->h); + *cursor = (struct cursor){ .x = 0, .y = 0, .wy = 0 }; +} + +static void +init_raster(struct raster *raster) +{ + assert(raster); + *raster = (struct raster){ .font = _intlfonts_ucs }; +} + +static void +render_chr(struct escpos_canvas *canvas, struct cursor *cursor, const struct raster *raster, const uint32_t cp) { assert(canvas && raster); - const size_t off = canvas->w * raster->y + raster->x; - const struct glyph *glyph = &raster->font.ucs2glyph[MIN((uint8_t)MAX(chr, 0), raster->font.max_ucs)]; + const size_t off = canvas->w * cursor->y + cursor->x; + const struct glyph *glyph = &raster->font.ucs2glyph[MIN(MAX(cp, 0), raster->font.max_ucs)]; + const size_t width = div_round_up(glyph->width, 8); const uint8_t *data = &raster->font.data[glyph->offset]; for (size_t gy = 0; gy < raster->font.height; ++gy) { - for (size_t gx = 0; gx < glyph->width; gx += 8) { + for (size_t gx = 0; gx < width; ++gx) { for (uint8_t b = 0; b < 8; ++b) { - const size_t dst = off + (canvas->w * gy + gx + b); + const size_t dst = off + (canvas->w * gy + (gx * 4) + b); assert(dst < canvas->w * canvas->h); - canvas->data[dst] = data[div_round_up(glyph->width, 8) * gy + gx] & (1 << (7 - b)); + canvas->data[dst] = data[width * gy + gx] & (1 << (7 - b)); } } } - raster->x += MIN(glyph->width + SPACING, canvas->w - raster->x); - raster->wy = MIN(raster->y + MAX(raster->font.height, 1) - 1, canvas->h); + cursor->x += MIN(glyph->width + SPACING, canvas->w - cursor->x); + cursor->wy = MIN(cursor->y + MAX(raster->font.height, 1) - 1, canvas->h); } static void -init(struct escpos_canvas *canvas, struct raster *raster) +apply_canvas(struct escpos_canvas *dst, struct cursor *dst_cursor, struct escpos_canvas *src, struct cursor *src_cursor) { - assert(canvas && raster); - memset(canvas->data, 0, canvas->w * canvas->h); - *raster = (struct raster){ .font = _intlfonts_ucs }; - raster->x = raster->y = raster->wy = 0; + // According to epson docs, the justification is applied after print buffer is applied + // Thus we should apply justification here, need const struct *raster as input. + assert(dst && dst_cursor && src && src_cursor); + const size_t off = dst->w * dst_cursor->y + dst_cursor->x; + assert(off + src->w * src_cursor->wy <= dst->w * dst->h); + memcpy((char*)dst->data + off, src->data, src->w * src_cursor->wy); + dst_cursor->wy = MAX(dst_cursor->wy, src_cursor->wy); + init_canvas(src, src_cursor); } static void -lfd(const struct escpos_canvas *canvas, struct raster *raster, const uint8_t num) +render_checker(struct escpos_canvas *canvas) { - assert(canvas && raster); + for (size_t gy = 0; gy < canvas->w; ++gy) { + for (size_t gx = 0; gx < canvas->h; ++gx) { + const size_t dst = canvas->w * gy + gx; + assert(dst < canvas->w * canvas->h); + canvas->data[dst] = ((gy * gx) % 2); + } + } +} + +static void +lfd(const struct escpos_canvas *canvas, struct cursor *cursor, const struct raster *raster, const uint8_t num) +{ + assert(canvas && cursor); const size_t lf = (raster->font.height + SPACING) * num; - raster->x = 0; - raster->y += MIN(lf, canvas->h - raster->y); - raster->wy = raster->y + raster->font.height + SPACING; + cursor->x = 0; + cursor->y += MIN(lf, canvas->h - cursor->y); + cursor->wy = cursor->y + raster->font.height + SPACING; } static void -cut(const struct escpos_parser *parser, struct escpos_canvas *canvas, struct raster *raster) +cut(const struct escpos_parser *parser, struct escpos_canvas *canvas, struct cursor *cursor) { - assert(canvas && raster); - assert(raster->wy <= canvas->h); + assert(parser && canvas && cursor); + assert(cursor->wy <= canvas->h); - if (raster->wy > 0) { - parser->write(parser, canvas->data, canvas->w, MIN(canvas->h, raster->wy)); - memset(canvas->data, 0, canvas->w * canvas->h); - raster->x = raster->y = raster->wy = 0; + if (cursor->wy > 0) { + parser->write(parser, canvas->data, canvas->w, MIN(canvas->h, cursor->wy)); + init_canvas(canvas, cursor); } } %%{ machine escpos_parser; + alphtype unsigned char; include escpos_stack "stack.rl"; variable p ragel.p; variable pe ragel.pe; @@ -97,20 +137,25 @@ cut(const struct escpos_parser *parser, struct escpos_canvas *canvas, struct ras action init { puts("init"); - init(&parser->canvas, &raster); + init_canvas(&parser->canvas, &canvas_cursor); + init_canvas(&parser->print_buffer, &print_buffer_cursor); + init_raster(&raster); } action lfd { fprintf(stderr, "lfd %d\n", stack_get_num(&stack)); - lfd(&parser->canvas, &raster, stack_get_num(&stack)); + apply_canvas(&parser->canvas, &canvas_cursor, &parser->print_buffer, &print_buffer_cursor); + lfd(&parser->canvas, &canvas_cursor, &raster, stack_get_num(&stack)); } action lfv { fprintf(stderr, "lfv %d\n", stack_get_num(&stack)); + apply_canvas(&parser->canvas, &canvas_cursor, &parser->print_buffer, &print_buffer_cursor); + lfd(&parser->canvas, &canvas_cursor, &raster, stack_get_num(&stack)); const size_t lf = (raster.font.height + SPACING) * stack_get_num(&stack); - raster.x = 0; - raster.y -= MIN(lf, raster.y); - raster.wy = raster.y + raster.font.height + SPACING; + canvas_cursor.x = 0; + canvas_cursor.y -= MIN(lf, canvas_cursor.y); + canvas_cursor.wy = canvas_cursor.y + raster.font.height + SPACING; } action print_mode { @@ -137,7 +182,7 @@ cut(const struct escpos_parser *parser, struct escpos_canvas *canvas, struct ras action cut { fprintf(stderr, "cut %d\n", stack_get_num(&stack)); - cut(parser, &parser->canvas, &raster); + cut(parser, &parser->canvas, &canvas_cursor); } action emphasis { @@ -181,13 +226,16 @@ cut(const struct escpos_parser *parser, struct escpos_canvas *canvas, struct ras action text { putc(fc, stderr); - render_chr(&parser->canvas, &raster, fc); + uint32_t cp; + if (utf8_decode(&utf8.state, &cp, fc) == UTF8_ACCEPT) + render_chr(&parser->print_buffer, &print_buffer_cursor, &raster, cp); } action line { fputs("\\n", stderr); ragel_advance_line(&ragel); - lfd(&parser->canvas, &raster, 1); + apply_canvas(&parser->canvas, &canvas_cursor, &parser->print_buffer, &print_buffer_cursor); + lfd(&parser->canvas, &canvas_cursor, &raster, 1); } # Constants @@ -230,12 +278,18 @@ escpos_parser_parse(struct escpos_parser *parser, const char *name) assert(parser->read); assert(parser->write); - char var[256]; - struct stack stack = { .var.buf.mem = { .data = var, .len = sizeof(var) } }; + struct stack stack = { .var.buf.mem = parser->var }; struct ragel ragel = { .name = name, .lineno = 1 }; + struct utf8 utf8 = {0}; + + struct cursor canvas_cursor, print_buffer_cursor; + init_canvas(&parser->canvas, &canvas_cursor); + init_canvas(&parser->print_buffer, &print_buffer_cursor); struct raster raster; - init(&parser->canvas, &raster); + init_raster(&raster); + + // render_checker(&parser->canvas, &canvas_cursor); struct escpos_mem window = parser->window; for (bool eof = false; !ragel.error && !eof;) { @@ -245,8 +299,10 @@ escpos_parser_parse(struct escpos_parser *parser, const char *name) %% write exec; } - if (!ragel.error) - cut(parser, &parser->canvas, &raster); + if (!ragel.error) { + apply_canvas(&parser->canvas, &canvas_cursor, &parser->print_buffer, &print_buffer_cursor); + cut(parser, &parser->canvas, &canvas_cursor); + } return !ragel.error; } -- cgit v1.2.3