static void layout_flow(fz_context *ctx, fz_html *box, fz_html *top, float em, float page_h) { fz_html_flow *node, *line, *mark; float line_w; float indent; int align; int line_align; em = fz_from_css_number(box->style.font_size, em, em); indent = box->is_first_flow ? fz_from_css_number(top->style.text_indent, em, top->w) : 0; align = top->style.text_align; if (box->flow_dir == BIDI_RIGHT_TO_LEFT) { if (align == TA_LEFT) align = TA_RIGHT; else if (align == TA_RIGHT) align = TA_LEFT; } box->x = top->x; box->y = top->y + top->h; box->w = top->w; box->h = 0; if (!box->flow_head) return; for (node = box->flow_head; node; node = node->next) { if (node->type == FLOW_IMAGE) { float w = 0, h = 0; find_accumulated_margins(ctx, box, &w, &h); measure_image(ctx, node, top->w - w, page_h - h); } else { measure_word(ctx, node, em); } } /* start by skipping whitespace (and newline) at the beginning of tags */ node = box->flow_head; if (node->type == FLOW_BREAK) node = node->next; while (node && node->type == FLOW_GLUE) node = node->next; mark = NULL; line = node; line_w = indent; while (node) { switch (node->type) { case FLOW_WORD: break; case FLOW_IMAGE: /* TODO: break before/after image */ mark = node; break; case FLOW_GLUE: mark = node; break; case FLOW_BREAK: line_align = align == TA_JUSTIFY ? TA_LEFT : align; flush_line(ctx, box, page_h, top->w, line_align, indent, line, node); indent = 0; line = node->next; line_w = 0; mark = NULL; break; } if (mark && line_w + node->w > top->w) { flush_line(ctx, box, page_h, top->w, align, indent, line, mark); indent = 0; node = mark; while (node && node->type == FLOW_GLUE) node = node->next; line = node; line_w = 0; mark = NULL; } if (node) { line_w += node->w; node = node->next; } } if (line) { line_align = align == TA_JUSTIFY ? TA_LEFT : align; flush_line(ctx, box, page_h, top->w, line_align, indent, line, NULL); } }
static void layout_flow(fz_context *ctx, fz_html *box, fz_html *top, float em, float page_h) { fz_html_flow *node, *line_start, *word_start, *word_end, *line_end; float glue_w; float word_w; float line_w; float indent; float avail, line_h; float baseline; int align; em = fz_from_css_number(box->style.font_size, em, em); indent = box->is_first_flow ? fz_from_css_number(top->style.text_indent, em, top->w) : 0; align = top->style.text_align; box->x = top->x; box->y = top->y + top->h; box->w = top->w; box->h = 0; if (!box->flow_head) return; for (node = box->flow_head; node; node = node->next) if (node->type == FLOW_IMAGE) measure_image(ctx, node, top->w, page_h); else measure_word(ctx, node, em); line_start = find_next_word(box->flow_head, &glue_w); line_end = NULL; line_w = indent; word_w = 0; word_start = line_start; while (word_start) { word_end = find_next_glue(word_start, &word_w); if (line_w + word_w <= top->w) { line_w += word_w; glue_w = 0; line_end = word_end; word_start = find_next_word(word_end, &glue_w); word_w = glue_w; } else { avail = page_h - fmodf(box->y + box->h, page_h); line_h = measure_line(line_start, line_end, &baseline); if (line_h > avail) box->h += avail; layout_line(ctx, indent, top->w, line_w, align, line_start, line_end, box, baseline); box->h += line_h; word_start = find_next_word(line_end, &glue_w); line_start = word_start; line_end = NULL; indent = 0; line_w = 0; word_w = 0; } } /* don't justify the last line of a paragraph */ if (align == TA_JUSTIFY) align = TA_LEFT; if (line_start) { avail = page_h - fmodf(box->y + box->h, page_h); line_h = measure_line(line_start, line_end, &baseline); if (line_h > avail) box->h += avail; layout_line(ctx, indent, top->w, line_w, align, line_start, line_end, box, baseline); box->h += line_h; } }