summaryrefslogtreecommitdiff
path: root/source/html
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2018-03-20 15:58:36 +0100
committerTor Andersson <tor.andersson@artifex.com>2018-03-22 14:58:01 +0100
commite9111cc91f1a5e59200cb4c9c838b9966a94fcd6 (patch)
tree47596a5aaf5dc9d95e314e99869317d9caf6a188 /source/html
parent4987023bc163939687c2ceed2f7b2a2503893fb7 (diff)
downloadmupdf-e9111cc91f1a5e59200cb4c9c838b9966a94fcd6.tar.xz
html: Build box model for tables.
Does not layout the table boxes properly yet.
Diffstat (limited to 'source/html')
-rw-r--r--source/html/css-apply.c6
-rw-r--r--source/html/html-imp.h11
-rw-r--r--source/html/html-layout.c137
3 files changed, 141 insertions, 13 deletions
diff --git a/source/html/css-apply.c b/source/html/css-apply.c
index 6a91df0d..e5e78844 100644
--- a/source/html/css-apply.c
+++ b/source/html/css-apply.c
@@ -1125,6 +1125,12 @@ fz_get_css_match_display(fz_css_match *match)
return DIS_LIST_ITEM;
if (!strcmp(value->data, "inline-block"))
return DIS_INLINE_BLOCK;
+ if (!strcmp(value->data, "table"))
+ return DIS_TABLE;
+ if (!strcmp(value->data, "table-row"))
+ return DIS_TABLE_ROW;
+ if (!strcmp(value->data, "table-cell"))
+ return DIS_TABLE_CELL;
}
return DIS_INLINE;
}
diff --git a/source/html/html-imp.h b/source/html/html-imp.h
index a272548c..baab7c42 100644
--- a/source/html/html-imp.h
+++ b/source/html/html-imp.h
@@ -109,7 +109,7 @@ struct fz_css_match_s
fz_css_match_prop prop[64];
};
-enum { DIS_NONE, DIS_BLOCK, DIS_INLINE, DIS_LIST_ITEM, DIS_INLINE_BLOCK };
+enum { DIS_NONE, DIS_BLOCK, DIS_INLINE, DIS_LIST_ITEM, DIS_INLINE_BLOCK, DIS_TABLE, DIS_TABLE_ROW, DIS_TABLE_CELL };
enum { POS_STATIC, POS_RELATIVE, POS_ABSOLUTE, POS_FIXED };
enum { TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY };
enum { VA_BASELINE, VA_SUB, VA_SUPER, VA_TOP, VA_BOTTOM, VA_TEXT_TOP, VA_TEXT_BOTTOM };
@@ -180,10 +180,13 @@ struct fz_css_style_s
enum
{
- BOX_BLOCK, /* block-level: contains block, break, and flow boxes */
+ BOX_BLOCK, /* block-level: contains block, break, flow, and table boxes */
BOX_BREAK, /* block-level: empty <br> tag boxes */
BOX_FLOW, /* block-level: contains only inline boxes */
BOX_INLINE, /* inline-level: contains only inline boxes */
+ BOX_TABLE, /* table: contains table-row */
+ BOX_TABLE_ROW, /* table-row: contains table-cell */
+ BOX_TABLE_CELL, /* table-cell: contains block */
};
struct fz_html_s
@@ -196,10 +199,10 @@ struct fz_html_s
struct fz_html_box_s
{
- unsigned int type : 2;
+ unsigned int type : 3;
unsigned int is_first_flow : 1; /* for text-indent */
unsigned int markup_dir : 2;
- unsigned int list_item : 27;
+ unsigned int list_item : 26;
float x, y, w, b; /* content */
float padding[4];
float margin[4];
diff --git a/source/html/html-layout.c b/source/html/html-layout.c
index 41b1b676..3d49b8dd 100644
--- a/source/html/html-layout.c
+++ b/source/html/html-layout.c
@@ -550,6 +550,43 @@ static fz_html_box *insert_block_box(fz_context *ctx, fz_html_box *box, fz_html_
return top;
}
+static fz_html_box *insert_table_box(fz_context *ctx, fz_html_box *box, fz_html_box *top)
+{
+ top = insert_block_box(ctx, box, top);
+ box->type = BOX_TABLE;
+ return top;
+}
+
+static fz_html_box *insert_table_row_box(fz_context *ctx, fz_html_box *box, fz_html_box *top)
+{
+ fz_html_box *table = top;
+ while (table && table->type != BOX_TABLE)
+ table = table->up;
+ if (table)
+ {
+ insert_box(ctx, box, BOX_TABLE_ROW, table);
+ return table;
+ }
+ fz_warn(ctx, "table-row not inside table element");
+ insert_block_box(ctx, box, top);
+ return top;
+}
+
+static fz_html_box *insert_table_cell_box(fz_context *ctx, fz_html_box *box, fz_html_box *top)
+{
+ fz_html_box *tr = top;
+ while (tr && tr->type != BOX_TABLE_ROW)
+ tr = tr->up;
+ if (tr)
+ {
+ insert_box(ctx, box, BOX_TABLE_CELL, tr);
+ return tr;
+ }
+ fz_warn(ctx, "table-cell not inside table-row element");
+ insert_block_box(ctx, box, top);
+ return top;
+}
+
static fz_html_box *insert_break_box(fz_context *ctx, fz_html_box *box, fz_html_box *top)
{
if (top->type == BOX_BLOCK)
@@ -573,8 +610,15 @@ static fz_html_box *insert_break_box(fz_context *ctx, fz_html_box *box, fz_html_
static void insert_inline_box(fz_context *ctx, fz_html_box *box, fz_html_box *top, int markup_dir, struct genstate *g)
{
- if (top->type == BOX_BLOCK)
+ if (top->type == BOX_FLOW || top->type == BOX_INLINE)
{
+ insert_box(ctx, box, BOX_INLINE, top);
+ }
+ else
+ {
+ while (top->type != BOX_BLOCK && top->type != BOX_TABLE_CELL)
+ top = top->up;
+
if (top->last && top->last->type == BOX_FLOW)
{
insert_box(ctx, box, BOX_INLINE, top->last);
@@ -588,14 +632,6 @@ static void insert_inline_box(fz_context *ctx, fz_html_box *box, fz_html_box *to
g->at_bol = 1;
}
}
- else if (top->type == BOX_FLOW)
- {
- insert_box(ctx, box, BOX_INLINE, top);
- }
- else if (top->type == BOX_INLINE)
- {
- insert_box(ctx, box, BOX_INLINE, top);
- }
}
static fz_html_box *
@@ -736,6 +772,18 @@ generate_boxes(fz_context *ctx, fz_xml *node, fz_html_box *top,
box->href = fz_pool_strdup(ctx, g->pool, href);
}
}
+ else if (display == DIS_TABLE)
+ {
+ top = insert_table_box(ctx, box, top);
+ }
+ else if (display == DIS_TABLE_ROW)
+ {
+ top = insert_table_row_box(ctx, box, top);
+ }
+ else if (display == DIS_TABLE_CELL)
+ {
+ top = insert_table_cell_box(ctx, box, top);
+ }
else
{
fz_warn(ctx, "unknown box display type");
@@ -1373,6 +1421,65 @@ static int layout_block_page_break(fz_context *ctx, float *yp, float page_h, flo
}
static float layout_block(fz_context *ctx, fz_html_box *box, float em, float top_x, float *top_b, float top_w,
+ float page_h, float vertical, hb_buffer_t *hb_buf);
+
+static void layout_table(fz_context *ctx, fz_html_box *box, fz_html_box *top, float page_h, hb_buffer_t *hb_buf)
+{
+ fz_html_box *row, *cell, *child;
+ int col, ncol = 0;
+
+ box->em = fz_from_css_number(box->style.font_size, top->em, top->em, top->em);
+ box->x = top->x;
+ box->w = fz_from_css_number(box->style.width, box->em, top->w, top->w);
+ box->y = box->b = top->b;
+
+ for (row = box->down; row; row = row->next)
+ {
+ col = 0;
+ for (cell = row->down; cell; cell = cell->next)
+ ++col;
+ if (col > ncol)
+ ncol = col;
+ }
+
+ for (row = box->down; row; row = row->next)
+ {
+ col = 0;
+
+ row->em = fz_from_css_number(row->style.font_size, box->em, box->em, box->em);
+ row->x = box->x;
+ row->w = box->w;
+ row->y = row->b = box->b;
+
+ for (cell = row->down; cell; cell = cell->next)
+ {
+ float colw = row->w / ncol; // TODO: proper calculation
+
+ cell->em = fz_from_css_number(cell->style.font_size, row->em, row->em, row->em);
+ cell->y = cell->b = row->y;
+ cell->x = row->x + col * colw;
+ cell->w = colw;
+
+ for (child = cell->down; child; child = child->next)
+ {
+ if (child->type == BOX_BLOCK)
+ layout_block(ctx, child, cell->em, cell->x, &cell->b, cell->w, page_h, 0, hb_buf);
+ else if (child->type == BOX_FLOW)
+ layout_flow(ctx, child, cell, page_h, hb_buf);
+ cell->b = child->b;
+ }
+
+ if (cell->b > row->b)
+ row->b = cell->b;
+
+ ++col;
+ }
+
+ box->b = row->b;
+ }
+}
+
+static float layout_block(fz_context *ctx, fz_html_box *box, float em, float top_x, float *top_b, float top_w,
float page_h, float vertical, hb_buffer_t *hb_buf)
{
fz_html_box *child;
@@ -1438,6 +1545,12 @@ static float layout_block(fz_context *ctx, fz_html_box *box, float em, float top
}
box->b = child->b + child->padding[B] + child->border[B] + child->margin[B];
}
+ else if (child->type == BOX_TABLE)
+ {
+ layout_table(ctx, child, box, page_h, hb_buf);
+ first = 0;
+ box->b = child->b + child->padding[B] + child->border[B] + child->margin[B];
+ }
else if (child->type == BOX_BREAK)
{
box->b += fz_from_css_number_scale(style->line_height, em);
@@ -1868,6 +1981,9 @@ static void draw_block_box(fz_context *ctx, fz_html_box *box, float page_top, fl
{
switch (box->type)
{
+ case BOX_TABLE:
+ case BOX_TABLE_ROW:
+ case BOX_TABLE_CELL:
case BOX_BLOCK: draw_block_box(ctx, box, page_top, page_bot, dev, ctm, hb_buf); break;
case BOX_FLOW: draw_flow_box(ctx, box, page_top, page_bot, dev, ctm, hb_buf); break;
}
@@ -2411,6 +2527,9 @@ fz_debug_html_box(fz_context *ctx, fz_html_box *box, int level)
case BOX_BREAK: printf("break"); break;
case BOX_FLOW: printf("flow"); break;
case BOX_INLINE: printf("inline"); break;
+ case BOX_TABLE: printf("table"); break;
+ case BOX_TABLE_ROW: printf("table-row"); break;
+ case BOX_TABLE_CELL: printf("table-cell"); break;
}
printf(" em=%g x=%g y=%g w=%g b=%g\n", box->em, box->x, box->y, box->w, box->b);