summaryrefslogtreecommitdiff
path: root/source/html/layout.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2014-11-12 15:38:45 +0100
committerTor Andersson <tor.andersson@artifex.com>2014-12-03 12:25:51 +0100
commitc90b2253e40cc5646319bcc79e69b1dc7154db92 (patch)
treeadc347f56a56101a3063d838d5a4d81d719d5d80 /source/html/layout.c
parentd50623858386a8d99f71e6361296a50db164f103 (diff)
downloadmupdf-c90b2253e40cc5646319bcc79e69b1dc7154db92.tar.xz
html: Line breaking and font styling.
Diffstat (limited to 'source/html/layout.c')
-rw-r--r--source/html/layout.c106
1 files changed, 80 insertions, 26 deletions
diff --git a/source/html/layout.c b/source/html/layout.c
index 6d9753ba..d07b2dab 100644
--- a/source/html/layout.c
+++ b/source/html/layout.c
@@ -30,8 +30,6 @@ static const char *default_css =
"center{text-align:center}"
"svg{display:none}";
-static fz_font *font = NULL;
-
enum
{
BOX_BLOCK, /* block-level: contains block and flow boxes */
@@ -218,8 +216,9 @@ static void insert_inline_box(fz_context *ctx, struct box *box, struct box *top)
}
}
-static void generate_boxes(fz_context *ctx, fz_xml *node, struct box *top, struct rule *rule, struct style *up_style)
+static void generate_boxes(html_document *doc, fz_xml *node, struct box *top, struct rule *rule, struct style *up_style)
{
+ fz_context *ctx = doc->ctx;
struct style style;
struct box *box;
int display;
@@ -257,7 +256,7 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, struct box *top, struc
}
if (fz_xml_down(node))
- generate_boxes(ctx, fz_xml_down(node), box, rule, &style);
+ generate_boxes(doc, fz_xml_down(node), box, rule, &style);
// TODO: remove empty flow boxes
}
@@ -268,60 +267,117 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, struct box *top, struc
generate_text(ctx, box, fz_xml_text(node));
}
- compute_style(&box->style, &style);
+ compute_style(doc, &box->style, &style);
node = fz_xml_next(node);
}
}
-static void layout_text(fz_context *ctx, struct flow *node, struct box *top, float em)
+static void measure_word(fz_context *ctx, struct flow *node, float em)
{
const char *s;
int c, g;
float w;
em = from_number(node->style->font_size, em, em);
- node->x = top->x + top->w;
- node->y = top->y;
- node->h = em;
+ node->x = 0;
+ node->y = 0;
+ node->h = from_number_scale(node->style->line_height, em, em, em);
w = 0;
s = node->text;
while (*s)
{
s += fz_chartorune(&c, s);
- g = fz_encode_character(ctx, font, c);
- w += fz_advance_glyph(ctx, font, g) * em;
+ g = fz_encode_character(ctx, node->style->font, c);
+ w += fz_advance_glyph(ctx, node->style->font, g) * em;
}
node->w = w;
node->em = em;
}
+static float layout_line(fz_context *ctx, float indent, struct flow *node, struct flow *end, struct box *box)
+{
+ float x = box->x + indent;
+ float y = box->y + box->h;
+ float h = 0;
+
+ while (node != end)
+ {
+ node->x = x;
+ node->y = y;
+ x += node->w;
+ if (node->h > h)
+ h = node->h;
+ node = node->next;
+ }
+
+ return h;
+}
+
static void layout_flow(fz_context *ctx, struct box *box, struct box *top, float em)
{
- struct flow *node;
+ struct flow *node, *first_word, *last_glue;
+ float line_w, line_h;
+ float indent;
em = from_number(box->style.font_size, em, em);
+ indent = from_number(top->style.text_indent, em, top->w);
+
box->x = top->x;
box->y = top->y + top->h;
- box->h = 0;
box->w = 0;
+ box->h = 0;
+ first_word = box->flow_head;
+ last_glue = NULL;
+ line_w = indent;
for (node = box->flow_head; node; node = node->next)
{
- layout_text(ctx, node, box, em);
- if (node->h > box->h)
- box->h = node->h;
- box->w += node->w;
+ if (node->type == FLOW_GLUE)
+ last_glue = node;
+
+ measure_word(ctx, node, em);
+ if (last_glue && line_w + node->w > top->w)
+ {
+ line_h = layout_line(ctx, indent, first_word, last_glue, box);
+ if (line_w > box->w)
+ box->w = line_w;
+ box->h += line_h;
+
+ if (node == last_glue && node->next)
+ {
+ node = node->next;
+ measure_word(ctx, node, em);
+ }
+
+ first_word = node;
+ last_glue = NULL;
+ line_w = node->w;
+ indent = 0;
+ }
+ else if (line_w + node->w > top->w)
+ {
+ printf("WARNING: line overflow! (%s)\n", node->text);
+ line_w += node->w;
+ }
+ else
+ {
+ line_w += node->w;
+ }
}
+
+ line_h = layout_line(ctx, indent, first_word, NULL, box);
+ if (line_w > box->w)
+ box->w = line_w;
+ box->h += line_h;
}
static void layout_block(fz_context *ctx, struct box *box, struct box *top, float em, float top_collapse_margin)
{
struct box *child;
float box_collapse_margin;
- float bottom;
em = from_number(box->style.font_size, em, em);
@@ -422,8 +478,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);
+// if (box->flow_head)
+// print_flow(ctx, box->flow_head, level + 1);
box = box->next;
}
}
@@ -446,7 +502,7 @@ draw_flow_box(fz_context *ctx, struct box *box, fz_device *dev, const fz_matrix
if (node->type == FLOW_WORD)
{
fz_scale(&trm, node->em, -node->em);
- text = fz_new_text(ctx, font, &trm, 0);
+ text = fz_new_text(ctx, node->style->font, &trm, 0);
x = node->x;
y = node->y + node->em * 0.8;
@@ -454,9 +510,9 @@ draw_flow_box(fz_context *ctx, struct box *box, fz_device *dev, const fz_matrix
while (*s)
{
s += fz_chartorune(&c, s);
- g = fz_encode_character(ctx, font, c);
+ g = fz_encode_character(ctx, node->style->font, c);
fz_add_text(ctx, text, g, c, x, y);
- x += fz_advance_glyph(ctx, font, g) * node->em;
+ x += fz_advance_glyph(ctx, node->style->font, g) * node->em;
}
fz_fill_text(dev, text, ctm, fz_device_gray(ctx), black, 1);
@@ -586,8 +642,6 @@ html_layout_document(html_document *doc, float w, float h)
else strcpy(dirname, "./");
#endif
- font = html_load_font(doc->ctx, "serif", "normal", "normal", "normal");
-
css = fz_parse_css(doc->ctx, NULL, default_css);
css = load_css(doc->ctx, css, doc->xml);
@@ -602,7 +656,7 @@ html_layout_document(html_document *doc, float w, float h)
win_box->w = w;
win_box->h = 0;
- generate_boxes(doc->ctx, doc->xml, root_box, css, &style);
+ generate_boxes(doc, doc->xml, root_box, css, &style);
layout_block(doc->ctx, root_box, win_box, 12, 0);