diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2014-11-04 17:02:33 +0100 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2014-12-03 12:25:51 +0100 |
commit | 24d9a0f9720f7faade99f34c478bb24225174e91 (patch) | |
tree | da71bd66008a74769d23a378218d6bd632848453 /source | |
parent | b8f932bba1ca5003700a8c6465e6b67bffb5ea38 (diff) | |
download | mupdf-24d9a0f9720f7faade99f34c478bb24225174e91.tar.xz |
html: Create word and glue list for flow boxes.
Diffstat (limited to 'source')
-rw-r--r-- | source/html/layout.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/source/html/layout.c b/source/html/layout.c index 898e0eb7..3bdb26af 100644 --- a/source/html/layout.c +++ b/source/html/layout.c @@ -43,9 +43,30 @@ struct box float x, y, w, h; struct box *up, *down, *last, *next; fz_xml *node; + struct flow *flow_head, **flow_tail; struct computed_style style; }; +enum +{ + FLOW_WORD, + FLOW_GLUE, +}; + +struct flow +{ + int type; + struct computed_style *style; + char *text, *broken_text; + float width, broken_width; + struct flow *next; +}; + +static int iswhite(int c) +{ + return c == ' ' || c == '\t' || c == '\r' || c == '\n'; +} + struct box *new_box(fz_context *ctx, fz_xml *node) { struct box *box; @@ -63,6 +84,9 @@ struct box *new_box(fz_context *ctx, fz_xml *node) box->node = node; + box->flow_head = NULL; + box->flow_tail = &box->flow_head; + return box; } @@ -185,6 +209,61 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, struct box *top, struc } } +static struct flow *add_flow(fz_context *ctx, struct box *top, struct computed_style *style, int type) +{ + struct flow *flow = fz_malloc_struct(ctx, struct flow); + flow->type = type; + flow->style = style; + *top->flow_tail = flow; + top->flow_tail = &flow->next; + return flow; +} + +static void add_flow_space(fz_context *ctx, struct box *top, struct computed_style *style, float em) +{ + struct flow *flow; + + /* delete space at the beginning of the line */ + if (!top->flow_head) + return; + + flow = add_flow(ctx, top, style, FLOW_GLUE); + flow->text = " "; + flow->width = 0.5 * em; + flow->broken_text = ""; + flow->broken_width = 0; +} + +static void add_flow_word(fz_context *ctx, struct box *top, struct computed_style *style, float em, const char *a, const char *b) +{ + struct flow *flow = add_flow(ctx, top, style, FLOW_WORD); + flow->text = fz_malloc(ctx, b - a + 1); + memcpy(flow->text, a, b - a); + flow->text[b - a] = 0; + flow->width = (b - a) * 0.5 * em; +} + +static void layout_text(fz_context *ctx, struct box *top, const char *text, struct computed_style *style, float em) +{ + while (*text) + { + if (iswhite(*text)) + { + ++text; + while (iswhite(*text)) + ++text; + add_flow_space(ctx, top, style, em); + } + if (*text) + { + const char *mark = text++; + while (*text && !iswhite(*text)) + ++text; + add_flow_word(ctx, top, style, em, mark, text); + } + } +} + static void layout_inline(fz_context *ctx, struct box *box, struct box *top, float em) { struct box *child; @@ -200,6 +279,8 @@ static void layout_inline(fz_context *ctx, struct box *box, struct box *top, flo s = fz_xml_text(box->node); if (s) { + layout_text(ctx, top, s, &box->style, em); + box->w += strlen(s) * 0.5 * em; } @@ -254,7 +335,10 @@ static void layout_block(fz_context *ctx, struct box *box, struct box *top, floa if (child->type == BOX_BLOCK) layout_block(ctx, child, box, em); else if (child->type == BOX_FLOW) + { layout_flow(ctx, child, box, em); + // TOOD: remove flow box if no flow content + } box->h += child->h; } @@ -266,6 +350,21 @@ static void indent(int level) while (level--) printf(" "); } +static void print_flow(fz_context *ctx, struct flow *flow, int level) +{ + while (flow) + { + printf(" "); + indent(level); + switch (flow->type) + { + case FLOW_WORD: printf("word \"%s\"\n", flow->text); break; + case FLOW_GLUE: printf("glue \"%s\" / \"%s\"\n", flow->text, flow->broken_text); break; + } + flow = flow->next; + } +} + static void print_box(fz_context *ctx, struct box *box, int level) { while (box) @@ -288,6 +387,8 @@ static void print_box(fz_context *ctx, struct box *box, int level) printf("\n"); if (box->down) print_box(ctx, box->down, level + 1); + if (box->flow_head) + print_flow(ctx, box->flow_head, level + 1); box = box->next; } } |