summaryrefslogtreecommitdiff
path: root/source/html
diff options
context:
space:
mode:
Diffstat (limited to 'source/html')
-rw-r--r--source/html/html-layout.c124
1 files changed, 69 insertions, 55 deletions
diff --git a/source/html/html-layout.c b/source/html/html-layout.c
index f9fcacce..d76dd2a8 100644
--- a/source/html/html-layout.c
+++ b/source/html/html-layout.c
@@ -104,51 +104,51 @@ static void fz_drop_html_flow(fz_context *ctx, fz_html_flow *flow)
}
}
-static fz_html_flow *add_flow(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style, int type)
+static fz_html_flow *add_flow(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box, int type)
{
fz_html_flow *flow = fz_pool_alloc(ctx, pool, sizeof *flow);
flow->type = type;
flow->expand = 0;
flow->bidi_level = 0;
flow->breaks_line = 0;
- flow->style = style;
+ flow->box = inline_box;
*top->flow_tail = flow;
top->flow_tail = &flow->next;
return flow;
}
-static void add_flow_space(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style)
+static void add_flow_space(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box)
{
- fz_html_flow *flow = add_flow(ctx, pool, top, style, FLOW_SPACE);
+ fz_html_flow *flow = add_flow(ctx, pool, top, inline_box, FLOW_SPACE);
flow->expand = 1;
}
-static void add_flow_break(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style)
+static void add_flow_break(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box)
{
- (void)add_flow(ctx, pool, top, style, FLOW_BREAK);
+ (void)add_flow(ctx, pool, top, inline_box, FLOW_BREAK);
}
-static void add_flow_sbreak(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style)
+static void add_flow_sbreak(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box)
{
- (void)add_flow(ctx, pool, top, style, FLOW_SBREAK);
+ (void)add_flow(ctx, pool, top, inline_box, FLOW_SBREAK);
}
-static void add_flow_shyphen(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style)
+static void add_flow_shyphen(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box)
{
- (void)add_flow(ctx, pool, top, style, FLOW_SHYPHEN);
+ (void)add_flow(ctx, pool, top, inline_box, FLOW_SHYPHEN);
}
-static void add_flow_word(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style, const char *a, const char *b)
+static void add_flow_word(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box, const char *a, const char *b)
{
- fz_html_flow *flow = add_flow(ctx, pool, top, style, FLOW_WORD);
+ fz_html_flow *flow = add_flow(ctx, pool, top, inline_box, FLOW_WORD);
flow->content.text = fz_pool_alloc(ctx, pool, b - a + 1);
memcpy(flow->content.text, a, b - a);
flow->content.text[b - a] = 0;
}
-static void add_flow_image(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style, fz_image *img)
+static void add_flow_image(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box, fz_image *img)
{
- fz_html_flow *flow = add_flow(ctx, pool, top, style, FLOW_IMAGE);
+ fz_html_flow *flow = add_flow(ctx, pool, top, inline_box, FLOW_IMAGE);
flow->content.image = fz_keep_image(ctx, img);
}
@@ -179,18 +179,18 @@ static fz_html_flow *split_flow(fz_context *ctx, fz_pool *pool, fz_html_flow *fl
return new_flow;
}
-static void flush_space(fz_context *ctx, fz_pool *pool, fz_html *flow, fz_css_style *style, struct genstate *g)
+static void flush_space(fz_context *ctx, fz_pool *pool, fz_html *flow, fz_html *inline_box, struct genstate *g)
{
static const char *space = " ";
- int bsp = style->white_space & WS_ALLOW_BREAK_SPACE;
+ int bsp = inline_box->style.white_space & WS_ALLOW_BREAK_SPACE;
if (g->emit_white)
{
if (!g->at_bol)
{
if (bsp)
- add_flow_space(ctx, pool, flow, style);
+ add_flow_space(ctx, pool, flow, inline_box);
else
- add_flow_word(ctx, pool, flow, style, space, space+1);
+ add_flow_word(ctx, pool, flow, inline_box, space, space+1);
}
g->emit_white = 0;
}
@@ -254,7 +254,7 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch
text += 2;
else
text += 1;
- add_flow_break(ctx, pool, flow, &box->style);
+ add_flow_break(ctx, pool, flow, box);
g->at_bol = 1;
}
else if (iswhite(*text))
@@ -273,9 +273,9 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch
{
// TODO: tabs
if (bsp)
- add_flow_space(ctx, pool, flow, &box->style);
+ add_flow_space(ctx, pool, flow, box);
else
- add_flow_word(ctx, pool, flow, &box->style, space, space+1);
+ add_flow_word(ctx, pool, flow, box, space, space+1);
++text;
}
g->last_brk_cls = UCDN_LINEBREAK_CLASS_WJ; /* don't add sbreaks after a space */
@@ -285,7 +285,7 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch
const char *prev, *mark = text;
int c;
- flush_space(ctx, pool, flow, &box->style, g);
+ flush_space(ctx, pool, flow, box, g);
if (g->at_bol)
g->last_brk_cls = UCDN_LINEBREAK_CLASS_WJ;
@@ -297,8 +297,8 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch
if (c == 0xAD) /* soft hyphen */
{
if (mark != prev)
- add_flow_word(ctx, pool, flow, &box->style, mark, prev);
- add_flow_shyphen(ctx, pool, flow, &box->style);
+ add_flow_word(ctx, pool, flow, box, mark, prev);
+ add_flow_shyphen(ctx, pool, flow, box);
mark = text;
g->last_brk_cls = UCDN_LINEBREAK_CLASS_WJ; /* don't add sbreaks after a soft hyphen */
}
@@ -317,8 +317,8 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch
if (brk == '_')
{
if (mark != prev)
- add_flow_word(ctx, pool, flow, &box->style, mark, prev);
- add_flow_sbreak(ctx, pool, flow, &box->style);
+ add_flow_word(ctx, pool, flow, box, mark, prev);
+ add_flow_sbreak(ctx, pool, flow, box);
mark = prev;
}
@@ -327,7 +327,7 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch
}
}
if (mark != text)
- add_flow_word(ctx, pool, flow, &box->style, mark, text);
+ add_flow_word(ctx, pool, flow, box, mark, text);
g->at_bol = 0;
}
@@ -353,15 +353,15 @@ static void generate_image(fz_context *ctx, fz_pool *pool, fz_archive *zip, cons
fz_var(buf);
fz_var(img);
- flush_space(ctx, pool, flow, &box->style, g);
+ flush_space(ctx, pool, flow, box, g);
fz_try(ctx)
{
buf = fz_read_archive_entry(ctx, zip, path);
img = fz_new_image_from_buffer(ctx, buf);
- add_flow_sbreak(ctx, pool, flow, &box->style);
- add_flow_image(ctx, pool, flow, &box->style, img);
- add_flow_sbreak(ctx, pool, flow, &box->style);
+ add_flow_sbreak(ctx, pool, flow, box);
+ add_flow_image(ctx, pool, flow, box, img);
+ add_flow_sbreak(ctx, pool, flow, box);
}
fz_always(ctx)
{
@@ -372,7 +372,7 @@ static void generate_image(fz_context *ctx, fz_pool *pool, fz_archive *zip, cons
{
const char *alt = "[image]";
fz_warn(ctx, "html: cannot add image src='%s'", src);
- add_flow_word(ctx, pool, flow, &box->style, alt, alt + 7);
+ add_flow_word(ctx, pool, flow, box, alt, alt + 7);
}
g->at_bol = 0;
@@ -536,7 +536,7 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, fz_html *top,
fz_html *flow = top;
while (flow->type != BOX_FLOW)
flow = flow->up;
- add_flow_break(ctx, g->pool, flow, &top->style);
+ add_flow_break(ctx, g->pool, flow, top);
}
else
{
@@ -847,14 +847,14 @@ static void measure_string(fz_context *ctx, fz_html_flow *node, float em, hb_buf
string_walker walker;
const char *s;
- em = fz_from_css_number(node->style->font_size, em, em);
+ em = node->box->em;
node->x = 0;
node->y = 0;
node->w = 0;
- node->h = fz_from_css_number_scale(node->style->line_height, em, em, em);
+ node->h = fz_from_css_number_scale(node->box->style.line_height, em, em, em);
s = get_node_text(ctx, node);
- init_string_walker(ctx, &walker, hb_buf, node->bidi_level & 1, node->style->font, node->script, s);
+ init_string_walker(ctx, &walker, hb_buf, node->bidi_level & 1, node->box->style.font, node->script, s);
while (walk_string(&walker))
{
int x = 0;
@@ -862,8 +862,6 @@ static void measure_string(fz_context *ctx, fz_html_flow *node, float em, hb_buf
x += walker.glyph_pos[i].x_advance;
node->w += x * em / walker.scale;
}
-
- node->em = em;
}
static float measure_line(fz_html_flow *node, fz_html_flow *end, float *baseline)
@@ -878,8 +876,8 @@ static float measure_line(fz_html_flow *node, fz_html_flow *end, float *baseline
}
else
{
- float a = node->em * 0.8;
- float d = node->em * 0.2;
+ float a = node->box->em * 0.8;
+ float d = node->box->em * 0.2;
if (a > max_a) max_a = a;
if (d > max_d) max_d = d;
}
@@ -991,25 +989,25 @@ static void layout_line(fz_context *ctx, float indent, float page_w, float line_
node->x = x;
x += w;
- switch (node->style->vertical_align)
+ switch (node->box->style.vertical_align)
{
default:
case VA_BASELINE:
va = 0;
break;
case VA_SUB:
- va = node->em * 0.2f;
+ va = node->box->em * 0.2f;
break;
case VA_SUPER:
- va = node->em * -0.3f;
+ va = node->box->em * -0.3f;
break;
case VA_TOP:
case VA_TEXT_TOP:
- va = -baseline + node->em * 0.8;
+ va = -baseline + node->box->em * 0.8;
break;
case VA_BOTTOM:
case VA_TEXT_BOTTOM:
- va = -baseline + line_h - node->em * 0.2;
+ va = -baseline + line_h - node->box->em * 0.2;
break;
}
@@ -1046,13 +1044,24 @@ static void flush_line(fz_context *ctx, fz_html *box, float page_h, float page_w
box->h += line_h;
}
+static void layout_flow_inline(fz_context *ctx, fz_html *box, fz_html *top, float em)
+{
+ while (box)
+ {
+ box->em = fz_from_css_number(box->style.font_size, em, em);
+ if (box->down)
+ layout_flow_inline(ctx, box->down, box, box->em);
+ box = box->next;
+ }
+}
+
static void layout_flow(fz_context *ctx, fz_html *box, fz_html *top, float em, float page_h, hb_buffer_t *hb_buf)
{
fz_html_flow *node, *line, *candidate;
float line_w, candidate_w, indent, break_w, nonbreak_w;
int line_align, align;
- em = fz_from_css_number(box->style.font_size, em, em);
+ em = box->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;
@@ -1072,6 +1081,9 @@ static void layout_flow(fz_context *ctx, fz_html *box, fz_html *top, float em, f
if (!box->flow_head)
return;
+ if (box->down)
+ layout_flow_inline(ctx, box->down, box, em);
+
for (node = box->flow_head; node; node = node->next)
{
if (node->type == FLOW_IMAGE)
@@ -1283,6 +1295,8 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p
for (node = box->flow_head; node; node = node->next)
{
+ fz_css_style *style = &node->box->style;
+
if (node->type == FLOW_IMAGE)
{
if (node->y >= page_bot || node->y + node->h <= page_top)
@@ -1306,12 +1320,12 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p
continue;
if (node->type == FLOW_SHYPHEN && !node->breaks_line)
continue;
- if (node->style->visibility != V_VISIBLE)
+ if (style->visibility != V_VISIBLE)
continue;
- color[0] = node->style->color.r / 255.0f;
- color[1] = node->style->color.g / 255.0f;
- color[2] = node->style->color.b / 255.0f;
+ color[0] = style->color.r / 255.0f;
+ color[1] = style->color.g / 255.0f;
+ color[2] = style->color.b / 255.0f;
if (color[0] != prev_color[0] || color[1] != prev_color[1] || color[2] != prev_color[2])
{
@@ -1335,18 +1349,18 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p
x = node->x;
y = node->y;
- trm.a = node->em;
+ trm.a = node->box->em;
trm.b = 0;
trm.c = 0;
- trm.d = -node->em;
+ trm.d = -node->box->em;
trm.e = x;
trm.f = y;
s = get_node_text(ctx, node);
- init_string_walker(ctx, &walker, hb_buf, node->bidi_level & 1, node->style->font, node->script, s);
+ init_string_walker(ctx, &walker, hb_buf, node->bidi_level & 1, style->font, node->script, s);
while (walk_string(&walker))
{
- float node_scale = node->em / walker.scale;
+ float node_scale = node->box->em / walker.scale;
unsigned int i;
int c, k, n;
@@ -1408,7 +1422,7 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p
fz_drop_text(ctx, text);
text = NULL;
}
- if (node->style->visibility == V_VISIBLE)
+ if (style->visibility == V_VISIBLE)
{
fz_matrix local_ctm = *ctm;
fz_pre_translate(&local_ctm, node->x, node->y);