mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-23 12:36:51 +03:00
[project @ 2005-03-26 01:12:27 by bursa]
Split box.c into box_construct.c, box_normalise.c, and box.c. svn path=/import/netsurf/; revision=1583
This commit is contained in:
parent
9b8a94cc39
commit
64d8f9d5ed
4
depend
4
depend
@ -29,7 +29,9 @@ arm-riscos-aof/gif.o arm-ncos-aof/gif.o x86_64-linux-debug/gif.o x86_64-linux-gt
|
||||
arm-riscos-aof/gifread.o arm-ncos-aof/gifread.o x86_64-linux-debug/gifread.o x86_64-linux-gtk/gifread.o : image/gifread.c image/bitmap.h utils/log.h
|
||||
arm-riscos-aof/jpeg.o arm-ncos-aof/jpeg.o x86_64-linux-debug/jpeg.o x86_64-linux-gtk/jpeg.o : image/jpeg.c content/content.h content/content_type.h css/css.h css/css_enum.h desktop/plotters.h image/bitmap.h image/gif.h image/gifread.h image/jpeg.h image/mng.h render/html.h riscos/draw.h riscos/plugin.h riscos/sprite.h utils/config.h utils/log.h utils/messages.h utils/pool.h utils/utils.h
|
||||
arm-riscos-aof/mng.o arm-ncos-aof/mng.o x86_64-linux-debug/mng.o x86_64-linux-gtk/mng.o : image/mng.c content/content.h content/content_type.h css/css.h css/css_enum.h desktop/browser.h desktop/options.h desktop/plotters.h desktop/tree.h image/bitmap.h image/gif.h image/gifread.h image/jpeg.h image/mng.h render/html.h riscos/draw.h riscos/plugin.h riscos/sprite.h utils/config.h utils/log.h utils/messages.h utils/pool.h utils/utils.h
|
||||
arm-riscos-aof/box.o arm-ncos-aof/box.o x86_64-linux-debug/box.o x86_64-linux-gtk/box.o : render/box.c content/content.h content/content_type.h css/css.h css/css_enum.h desktop/browser.h desktop/gui.h desktop/options.h desktop/tree.h image/bitmap.h image/gif.h image/gifread.h image/jpeg.h image/mng.h render/box.h render/font.h render/form.h render/html.h riscos/draw.h riscos/plugin.h riscos/sprite.h utils/config.h utils/log.h utils/messages.h utils/pool.h utils/url.h utils/utils.h
|
||||
arm-riscos-aof/box.o arm-ncos-aof/box.o x86_64-linux-debug/box.o x86_64-linux-gtk/box.o : render/box.c content/content.h content/content_type.h css/css.h css/css_enum.h image/bitmap.h image/gif.h image/gifread.h image/jpeg.h image/mng.h render/box.h render/form.h render/html.h riscos/draw.h riscos/plugin.h riscos/sprite.h utils/config.h utils/pool.h
|
||||
arm-riscos-aof/box_construct.o arm-ncos-aof/box_construct.o x86_64-linux-debug/box_construct.o x86_64-linux-gtk/box_construct.o : render/box_construct.c content/content.h content/content_type.h css/css.h css/css_enum.h desktop/browser.h desktop/gui.h desktop/options.h desktop/tree.h image/bitmap.h image/gif.h image/gifread.h image/jpeg.h image/mng.h render/box.h render/form.h render/html.h riscos/draw.h riscos/plugin.h riscos/sprite.h utils/config.h utils/log.h utils/messages.h utils/pool.h utils/url.h utils/utils.h
|
||||
arm-riscos-aof/box_normalise.o arm-ncos-aof/box_normalise.o x86_64-linux-debug/box_normalise.o x86_64-linux-gtk/box_normalise.o : render/box_normalise.c content/content.h content/content_type.h css/css.h css/css_enum.h desktop/browser.h desktop/gui.h image/bitmap.h image/gif.h image/gifread.h image/jpeg.h image/mng.h render/box.h render/html.h riscos/draw.h riscos/plugin.h riscos/sprite.h utils/config.h utils/log.h utils/pool.h
|
||||
arm-riscos-aof/form.o arm-ncos-aof/form.o x86_64-linux-debug/form.o x86_64-linux-gtk/form.o : render/form.c render/box.h render/form.h utils/config.h utils/log.h utils/pool.h utils/utils.h
|
||||
arm-riscos-aof/html.o arm-ncos-aof/html.o x86_64-linux-debug/html.o x86_64-linux-gtk/html.o : render/html.c content/content.h content/content_type.h content/fetch.h content/fetchcache.h css/css.h css/css_enum.h desktop/browser.h desktop/gui.h desktop/imagemap.h desktop/options.h desktop/tree.h image/bitmap.h image/gif.h image/gifread.h image/jpeg.h image/mng.h render/box.h render/font.h render/html.h render/layout.h riscos/draw.h riscos/plugin.h riscos/sprite.h utils/config.h utils/log.h utils/messages.h utils/pool.h utils/url.h utils/utils.h
|
||||
arm-riscos-aof/html_redraw.o arm-ncos-aof/html_redraw.o x86_64-linux-debug/html_redraw.o x86_64-linux-gtk/html_redraw.o : render/html_redraw.c content/content.h content/content_type.h css/css.h css/css_enum.h desktop/plotters.h image/bitmap.h image/gif.h image/gifread.h image/jpeg.h image/mng.h render/box.h render/font.h render/form.h render/html.h render/layout.h riscos/draw.h riscos/plugin.h riscos/sprite.h utils/config.h utils/log.h utils/messages.h utils/pool.h utils/utils.h
|
||||
|
4
makefile
4
makefile
@ -19,8 +19,8 @@
|
||||
|
||||
OBJECTS_COMMON = content.o fetch.o fetchcache.o url_store.o # content/
|
||||
OBJECTS_COMMON += css.o css_enum.o parser.o ruleset.o scanner.o # css/
|
||||
OBJECTS_COMMON += box.o form.o html.o html_redraw.o layout.o \
|
||||
list.o textplain.o # render/
|
||||
OBJECTS_COMMON += box.o box_construct.o box_normalise.o form.o html.o \
|
||||
html_redraw.o layout.o list.o textplain.o # render/
|
||||
OBJECTS_COMMON += messages.o pool.o translit.o url.o utils.o # utils/
|
||||
OBJECTS_COMMON += imagemap.o loginlist.o options.o tree.o # desktop/
|
||||
|
||||
|
3227
render/box.c
3227
render/box.c
File diff suppressed because it is too large
Load Diff
15
render/box.h
15
render/box.h
@ -2,12 +2,12 @@
|
||||
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
||||
* Licensed under the GNU General Public License,
|
||||
* http://www.opensource.org/licenses/gpl-license
|
||||
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
|
||||
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
|
||||
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Conversion of XML tree to box tree (interface).
|
||||
* Box tree construction and manipulation (interface).
|
||||
*
|
||||
* This stage of rendering converts a tree of xmlNodes (produced by libxml2)
|
||||
* to a tree of struct box. The box tree represents the structure of the
|
||||
@ -231,20 +231,21 @@ struct column {
|
||||
#define UNKNOWN_MAX_WIDTH INT_MAX
|
||||
|
||||
|
||||
bool xml_to_box(xmlNode *n, struct content *c);
|
||||
void box_dump(struct box *box, unsigned int depth);
|
||||
struct box * box_create(struct css_style *style,
|
||||
const char *href, const char *title,
|
||||
const char *id, pool box_pool);
|
||||
void box_add_child(struct box * parent, struct box *child);
|
||||
void box_add_child(struct box *parent, struct box *child);
|
||||
void box_insert_sibling(struct box *box, struct box *new_box);
|
||||
void box_free(struct box *box);
|
||||
void box_free_box(struct box *box);
|
||||
void box_free_object_params(struct object_params *op);
|
||||
void box_coords(struct box *box, int *x, int *y);
|
||||
struct box *box_at_point(struct box *box, int x, int y,
|
||||
int *box_x, int *box_y,
|
||||
struct content **content);
|
||||
struct box *box_object_at_point(struct content *c, int x, int y);
|
||||
struct box *box_find_by_id(struct box *box, const char *id);
|
||||
void box_dump(struct box *box, unsigned int depth);
|
||||
|
||||
bool box_vscrollbar_present(const struct box *box);
|
||||
bool box_hscrollbar_present(const struct box *box);
|
||||
@ -256,4 +257,8 @@ void box_scrollbar_dimensions(const struct box *box,
|
||||
int *well_width,
|
||||
int *bar_left, int *bar_width);
|
||||
|
||||
bool xml_to_box(xmlNode *n, struct content *c);
|
||||
|
||||
bool box_normalise_block(struct box *block, pool box_pool);
|
||||
|
||||
#endif
|
||||
|
2384
render/box_construct.c
Normal file
2384
render/box_construct.c
Normal file
File diff suppressed because it is too large
Load Diff
696
render/box_normalise.c
Normal file
696
render/box_normalise.c
Normal file
@ -0,0 +1,696 @@
|
||||
/*
|
||||
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
||||
* Licensed under the GNU General Public License,
|
||||
* http://www.opensource.org/licenses/gpl-license
|
||||
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
|
||||
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
|
||||
* Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
|
||||
* Copyright 2004 Kevin Bagust <kevin.bagust@ntlworld.com>
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Box tree normalisation (implementation).
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include "netsurf/css/css.h"
|
||||
#include "netsurf/render/box.h"
|
||||
#ifdef riscos
|
||||
#include "netsurf/desktop/gui.h"
|
||||
#endif
|
||||
#define NDEBUG
|
||||
#include "netsurf/utils/log.h"
|
||||
#include "netsurf/utils/pool.h"
|
||||
|
||||
|
||||
struct span_info {
|
||||
unsigned int row_span;
|
||||
bool auto_row;
|
||||
bool auto_column;
|
||||
};
|
||||
|
||||
struct columns {
|
||||
unsigned int current_column;
|
||||
bool extra;
|
||||
/* Number of columns in main part of table 1..max columns */
|
||||
unsigned int num_columns;
|
||||
/* Information about columns in main table,
|
||||
array 0 to num_columns - 1 */
|
||||
struct span_info *spans;
|
||||
/* Number of columns that have cells after a colspan 0 */
|
||||
unsigned int extra_columns;
|
||||
/* Number of rows in table */
|
||||
unsigned int num_rows;
|
||||
};
|
||||
|
||||
|
||||
static bool box_normalise_table(struct box *table, pool box_pool);
|
||||
static void box_normalise_table_spans(struct box *table);
|
||||
static bool box_normalise_table_row_group(struct box *row_group,
|
||||
struct columns *col_info,
|
||||
pool box_pool);
|
||||
static bool box_normalise_table_row(struct box *row,
|
||||
struct columns *col_info,
|
||||
pool box_pool);
|
||||
static bool calculate_table_row(struct columns *col_info,
|
||||
unsigned int col_span, unsigned int row_span,
|
||||
unsigned int *start_column);
|
||||
static bool box_normalise_inline_container(struct box *cont, pool box_pool);
|
||||
|
||||
|
||||
/**
|
||||
* Ensure the box tree is correctly nested by adding and removing nodes.
|
||||
*
|
||||
* \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL
|
||||
* \param box_pool pool to allocate new boxes in
|
||||
* \return true on success, false on memory exhaustion
|
||||
*
|
||||
* The tree is modified to satisfy the following:
|
||||
* \code
|
||||
* parent permitted child nodes
|
||||
* BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE
|
||||
* INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR
|
||||
* INLINE none
|
||||
* TABLE at least 1 TABLE_ROW_GROUP
|
||||
* TABLE_ROW_GROUP at least 1 TABLE_ROW
|
||||
* TABLE_ROW at least 1 TABLE_CELL
|
||||
* TABLE_CELL BLOCK, INLINE_CONTAINER, TABLE (same as BLOCK)
|
||||
* FLOAT_(LEFT|RIGHT) exactly 1 BLOCK or TABLE \endcode
|
||||
*/
|
||||
|
||||
bool box_normalise_block(struct box *block, pool box_pool)
|
||||
{
|
||||
struct box *child;
|
||||
struct box *next_child;
|
||||
struct box *table;
|
||||
struct css_style *style;
|
||||
|
||||
assert(block != 0);
|
||||
LOG(("block %p, block->type %u", block, block->type));
|
||||
assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK ||
|
||||
block->type == BOX_TABLE_CELL);
|
||||
gui_multitask();
|
||||
|
||||
for (child = block->children; child != 0; child = next_child) {
|
||||
LOG(("child %p, child->type = %d", child, child->type));
|
||||
next_child = child->next; /* child may be destroyed */
|
||||
switch (child->type) {
|
||||
case BOX_BLOCK:
|
||||
/* ok */
|
||||
if (!box_normalise_block(child, box_pool))
|
||||
return false;
|
||||
break;
|
||||
case BOX_INLINE_CONTAINER:
|
||||
if (!box_normalise_inline_container(child,
|
||||
box_pool))
|
||||
return false;
|
||||
break;
|
||||
case BOX_TABLE:
|
||||
if (!box_normalise_table(child, box_pool))
|
||||
return false;
|
||||
break;
|
||||
case BOX_INLINE:
|
||||
case BOX_INLINE_BLOCK:
|
||||
case BOX_FLOAT_LEFT:
|
||||
case BOX_FLOAT_RIGHT:
|
||||
case BOX_BR:
|
||||
/* should have been wrapped in inline
|
||||
container by convert_xml_to_box() */
|
||||
assert(0);
|
||||
break;
|
||||
case BOX_TABLE_ROW_GROUP:
|
||||
case BOX_TABLE_ROW:
|
||||
case BOX_TABLE_CELL:
|
||||
/* insert implied table */
|
||||
style = css_duplicate_style(block->style);
|
||||
if (!style)
|
||||
return false;
|
||||
css_cascade(style, &css_blank_style);
|
||||
table = box_create(style, block->href, 0, 0, box_pool);
|
||||
if (!table) {
|
||||
css_free_style(style);
|
||||
return false;
|
||||
}
|
||||
table->type = BOX_TABLE;
|
||||
if (child->prev == 0)
|
||||
block->children = table;
|
||||
else
|
||||
child->prev->next = table;
|
||||
table->prev = child->prev;
|
||||
while (child != 0 && (
|
||||
child->type == BOX_TABLE_ROW_GROUP ||
|
||||
child->type == BOX_TABLE_ROW ||
|
||||
child->type == BOX_TABLE_CELL)) {
|
||||
box_add_child(table, child);
|
||||
next_child = child->next;
|
||||
child->next = 0;
|
||||
child = next_child;
|
||||
}
|
||||
table->last->next = 0;
|
||||
table->next = next_child = child;
|
||||
if (table->next)
|
||||
table->next->prev = table;
|
||||
table->parent = block;
|
||||
if (!box_normalise_table(table, box_pool))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool box_normalise_table(struct box *table, pool box_pool)
|
||||
{
|
||||
struct box *child;
|
||||
struct box *next_child;
|
||||
struct box *row_group;
|
||||
struct css_style *style;
|
||||
struct columns col_info;
|
||||
|
||||
assert(table != 0);
|
||||
assert(table->type == BOX_TABLE);
|
||||
LOG(("table %p", table));
|
||||
col_info.num_columns = 1;
|
||||
col_info.current_column = 0;
|
||||
col_info.spans = malloc(2 * sizeof *col_info.spans);
|
||||
if (!col_info.spans)
|
||||
return false;
|
||||
col_info.spans[0].row_span = col_info.spans[1].row_span = 0;
|
||||
col_info.spans[0].auto_row = col_info.spans[0].auto_column =
|
||||
col_info.spans[1].auto_row = col_info.spans[1].auto_column = false;
|
||||
col_info.num_rows = col_info.extra_columns = 0;
|
||||
col_info.extra = false;
|
||||
|
||||
for (child = table->children; child != 0; child = next_child) {
|
||||
next_child = child->next;
|
||||
switch (child->type) {
|
||||
case BOX_TABLE_ROW_GROUP:
|
||||
/* ok */
|
||||
if (!box_normalise_table_row_group(child,
|
||||
&col_info, box_pool)) {
|
||||
free(col_info.spans);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BOX_BLOCK:
|
||||
case BOX_INLINE_CONTAINER:
|
||||
case BOX_TABLE:
|
||||
case BOX_TABLE_ROW:
|
||||
case BOX_TABLE_CELL:
|
||||
/* insert implied table row group */
|
||||
assert(table->style != NULL);
|
||||
style = css_duplicate_style(table->style);
|
||||
if (!style) {
|
||||
free(col_info.spans);
|
||||
return false;
|
||||
}
|
||||
css_cascade(style, &css_blank_style);
|
||||
row_group = box_create(style, table->href, 0,
|
||||
0, box_pool);
|
||||
if (!row_group) {
|
||||
free(col_info.spans);
|
||||
css_free_style(style);
|
||||
return false;
|
||||
}
|
||||
row_group->type = BOX_TABLE_ROW_GROUP;
|
||||
if (child->prev == 0)
|
||||
table->children = row_group;
|
||||
else
|
||||
child->prev->next = row_group;
|
||||
row_group->prev = child->prev;
|
||||
while (child != 0 && (
|
||||
child->type == BOX_BLOCK ||
|
||||
child->type == BOX_INLINE_CONTAINER ||
|
||||
child->type == BOX_TABLE ||
|
||||
child->type == BOX_TABLE_ROW ||
|
||||
child->type == BOX_TABLE_CELL)) {
|
||||
box_add_child(row_group, child);
|
||||
next_child = child->next;
|
||||
child->next = 0;
|
||||
child = next_child;
|
||||
}
|
||||
row_group->last->next = 0;
|
||||
row_group->next = next_child = child;
|
||||
if (row_group->next)
|
||||
row_group->next->prev = row_group;
|
||||
row_group->parent = table;
|
||||
if (!box_normalise_table_row_group(row_group,
|
||||
&col_info, box_pool)) {
|
||||
free(col_info.spans);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BOX_INLINE:
|
||||
case BOX_INLINE_BLOCK:
|
||||
case BOX_FLOAT_LEFT:
|
||||
case BOX_FLOAT_RIGHT:
|
||||
case BOX_BR:
|
||||
/* should have been wrapped in inline
|
||||
container by convert_xml_to_box() */
|
||||
assert(0);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%i\n", child->type);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
table->columns = col_info.num_columns;
|
||||
table->rows = col_info.num_rows;
|
||||
free(col_info.spans);
|
||||
|
||||
box_normalise_table_spans(table);
|
||||
|
||||
if (table->children == 0) {
|
||||
LOG(("table->children == 0, removing"));
|
||||
if (table->prev == 0)
|
||||
table->parent->children = table->next;
|
||||
else
|
||||
table->prev->next = table->next;
|
||||
if (table->next != 0)
|
||||
table->next->prev = table->prev;
|
||||
box_free(table);
|
||||
}
|
||||
|
||||
LOG(("table %p done", table));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void box_normalise_table_spans(struct box *table)
|
||||
{
|
||||
struct box *table_row_group;
|
||||
struct box *table_row;
|
||||
struct box *table_cell;
|
||||
unsigned int last_column;
|
||||
unsigned int max_extra = 0;
|
||||
bool extra;
|
||||
bool force = false;
|
||||
unsigned int rows_left = table->rows;
|
||||
|
||||
/* Scan table filling in table the width and height of table cells for
|
||||
cells with colspan = 0 or rowspan = 0. Ignore the colspan and
|
||||
rowspan of any cells that that follow an colspan = 0 */
|
||||
for (table_row_group = table->children; table_row_group != NULL;
|
||||
table_row_group = table_row_group->next) {
|
||||
for (table_row = table_row_group->children; NULL != table_row;
|
||||
table_row = table_row->next){
|
||||
last_column = 0;
|
||||
extra = false;
|
||||
for (table_cell = table_row->children; NULL != table_cell;
|
||||
table_cell = table_cell->next) {
|
||||
/* We hae reached the end of the row, and have passed
|
||||
a cell with colspan = 0 so ignore col and row spans */
|
||||
if (force || extra || (table_cell->start_column + 1 <=
|
||||
last_column)) {
|
||||
extra = true;
|
||||
table_cell->columns = 1;
|
||||
table_cell->rows = 1;
|
||||
if (table_cell->start_column <= max_extra) {
|
||||
max_extra = table_cell->start_column + 1;
|
||||
}
|
||||
table_cell->start_column += table->columns;
|
||||
} else {
|
||||
/* Fill out the number of columns or the number of rows
|
||||
if necessary */
|
||||
if (0 == table_cell->columns) {
|
||||
table_cell->columns = table->columns -
|
||||
table_cell->start_column;
|
||||
if ((0 == table_cell->start_column) &&
|
||||
(0 == table_cell->rows)) {
|
||||
force = true;
|
||||
}
|
||||
}
|
||||
assert(0 != table_cell->columns);
|
||||
if (0 == table_cell->rows) {
|
||||
table_cell->rows = rows_left;
|
||||
}
|
||||
assert(0 != table_cell->rows);
|
||||
last_column = table_cell->start_column + 1;
|
||||
}
|
||||
}
|
||||
rows_left--;
|
||||
}
|
||||
}
|
||||
table->columns += max_extra;
|
||||
}
|
||||
|
||||
|
||||
bool box_normalise_table_row_group(struct box *row_group,
|
||||
struct columns *col_info,
|
||||
pool box_pool)
|
||||
{
|
||||
struct box *child;
|
||||
struct box *next_child;
|
||||
struct box *row;
|
||||
struct css_style *style;
|
||||
|
||||
assert(row_group != 0);
|
||||
assert(row_group->type == BOX_TABLE_ROW_GROUP);
|
||||
LOG(("row_group %p", row_group));
|
||||
|
||||
for (child = row_group->children; child != 0; child = next_child) {
|
||||
next_child = child->next;
|
||||
switch (child->type) {
|
||||
case BOX_TABLE_ROW:
|
||||
/* ok */
|
||||
if (!box_normalise_table_row(child, col_info,
|
||||
box_pool))
|
||||
return false;
|
||||
break;
|
||||
case BOX_BLOCK:
|
||||
case BOX_INLINE_CONTAINER:
|
||||
case BOX_TABLE:
|
||||
case BOX_TABLE_ROW_GROUP:
|
||||
case BOX_TABLE_CELL:
|
||||
/* insert implied table row */
|
||||
assert(row_group->style != NULL);
|
||||
style = css_duplicate_style(row_group->style);
|
||||
if (!style)
|
||||
return false;
|
||||
css_cascade(style, &css_blank_style);
|
||||
row = box_create(style, row_group->href, 0,
|
||||
0, box_pool);
|
||||
if (!row) {
|
||||
css_free_style(style);
|
||||
return false;
|
||||
}
|
||||
row->type = BOX_TABLE_ROW;
|
||||
if (child->prev == 0)
|
||||
row_group->children = row;
|
||||
else
|
||||
child->prev->next = row;
|
||||
row->prev = child->prev;
|
||||
while (child != 0 && (
|
||||
child->type == BOX_BLOCK ||
|
||||
child->type == BOX_INLINE_CONTAINER ||
|
||||
child->type == BOX_TABLE ||
|
||||
child->type == BOX_TABLE_ROW_GROUP ||
|
||||
child->type == BOX_TABLE_CELL)) {
|
||||
box_add_child(row, child);
|
||||
next_child = child->next;
|
||||
child->next = 0;
|
||||
child = next_child;
|
||||
}
|
||||
row->last->next = 0;
|
||||
row->next = next_child = child;
|
||||
if (row->next)
|
||||
row->next->prev = row;
|
||||
row->parent = row_group;
|
||||
if (!box_normalise_table_row(row, col_info,
|
||||
box_pool))
|
||||
return false;
|
||||
break;
|
||||
case BOX_INLINE:
|
||||
case BOX_INLINE_BLOCK:
|
||||
case BOX_FLOAT_LEFT:
|
||||
case BOX_FLOAT_RIGHT:
|
||||
case BOX_BR:
|
||||
/* should have been wrapped in inline
|
||||
container by convert_xml_to_box() */
|
||||
assert(0);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (row_group->children == 0) {
|
||||
LOG(("row_group->children == 0, removing"));
|
||||
if (row_group->prev == 0)
|
||||
row_group->parent->children = row_group->next;
|
||||
else
|
||||
row_group->prev->next = row_group->next;
|
||||
if (row_group->next != 0)
|
||||
row_group->next->prev = row_group->prev;
|
||||
box_free(row_group);
|
||||
}
|
||||
|
||||
LOG(("row_group %p done", row_group));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool box_normalise_table_row(struct box *row,
|
||||
struct columns *col_info,
|
||||
pool box_pool)
|
||||
{
|
||||
struct box *child;
|
||||
struct box *next_child;
|
||||
struct box *cell;
|
||||
struct css_style *style;
|
||||
unsigned int i;
|
||||
|
||||
assert(row != 0);
|
||||
assert(row->type == BOX_TABLE_ROW);
|
||||
LOG(("row %p", row));
|
||||
|
||||
for (child = row->children; child != 0; child = next_child) {
|
||||
next_child = child->next;
|
||||
switch (child->type) {
|
||||
case BOX_TABLE_CELL:
|
||||
/* ok */
|
||||
if (!box_normalise_block(child, box_pool))
|
||||
return false;
|
||||
cell = child;
|
||||
break;
|
||||
case BOX_BLOCK:
|
||||
case BOX_INLINE_CONTAINER:
|
||||
case BOX_TABLE:
|
||||
case BOX_TABLE_ROW_GROUP:
|
||||
case BOX_TABLE_ROW:
|
||||
/* insert implied table cell */
|
||||
assert(row->style != NULL);
|
||||
style = css_duplicate_style(row->style);
|
||||
if (!style)
|
||||
return false;
|
||||
css_cascade(style, &css_blank_style);
|
||||
cell = box_create(style, row->href, 0, 0,
|
||||
box_pool);
|
||||
if (!cell) {
|
||||
css_free_style(style);
|
||||
return false;
|
||||
}
|
||||
cell->type = BOX_TABLE_CELL;
|
||||
if (child->prev == 0)
|
||||
row->children = cell;
|
||||
else
|
||||
child->prev->next = cell;
|
||||
cell->prev = child->prev;
|
||||
while (child != 0 && (
|
||||
child->type == BOX_BLOCK ||
|
||||
child->type == BOX_INLINE_CONTAINER ||
|
||||
child->type == BOX_TABLE ||
|
||||
child->type == BOX_TABLE_ROW_GROUP ||
|
||||
child->type == BOX_TABLE_ROW)) {
|
||||
box_add_child(cell, child);
|
||||
next_child = child->next;
|
||||
child->next = 0;
|
||||
child = next_child;
|
||||
}
|
||||
cell->last->next = 0;
|
||||
cell->next = next_child = child;
|
||||
if (cell->next)
|
||||
cell->next->prev = cell;
|
||||
cell->parent = row;
|
||||
if (!box_normalise_block(cell, box_pool))
|
||||
return false;
|
||||
break;
|
||||
case BOX_INLINE:
|
||||
case BOX_INLINE_BLOCK:
|
||||
case BOX_FLOAT_LEFT:
|
||||
case BOX_FLOAT_RIGHT:
|
||||
case BOX_BR:
|
||||
/* should have been wrapped in inline
|
||||
container by convert_xml_to_box() */
|
||||
assert(0);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (!calculate_table_row(col_info, cell->columns, cell->rows,
|
||||
&cell->start_column))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < col_info->num_columns; i++) {
|
||||
if ((col_info->spans[i].row_span != 0) && (!col_info->spans[i].auto_row)) {
|
||||
col_info->spans[i].row_span--;
|
||||
if ((col_info->spans[i].auto_column) && (0 == col_info->spans[i].row_span)) {
|
||||
col_info->spans[i].auto_column = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
col_info->current_column = 0;
|
||||
col_info->extra = false;
|
||||
|
||||
if (row->children == 0) {
|
||||
LOG(("row->children == 0, removing"));
|
||||
if (row->prev == 0)
|
||||
row->parent->children = row->next;
|
||||
else
|
||||
row->prev->next = row->next;
|
||||
if (row->next != 0)
|
||||
row->next->prev = row->prev;
|
||||
box_free(row);
|
||||
} else {
|
||||
col_info->num_rows++;
|
||||
}
|
||||
|
||||
LOG(("row %p done", row));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \return true on success, false on memory exhaustion
|
||||
*/
|
||||
|
||||
bool calculate_table_row(struct columns *col_info,
|
||||
unsigned int col_span, unsigned int row_span,
|
||||
unsigned int *start_column)
|
||||
{
|
||||
unsigned int cell_start_col;
|
||||
unsigned int cell_end_col;
|
||||
unsigned int i;
|
||||
struct span_info *spans;
|
||||
|
||||
if (!col_info->extra) {
|
||||
/* skip columns with cells spanning from above */
|
||||
while ((col_info->spans[col_info->current_column].row_span != 0) &&
|
||||
(!col_info->spans[col_info->current_column].auto_column)) {
|
||||
col_info->current_column++;
|
||||
}
|
||||
if (col_info->spans[col_info->current_column].auto_column) {
|
||||
col_info->extra = true;
|
||||
col_info->current_column = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cell_start_col = col_info->current_column;
|
||||
|
||||
/* If the current table cell follows a cell with colspan=0,
|
||||
ignore both colspan and rowspan just assume it is a standard
|
||||
size cell */
|
||||
if (col_info->extra) {
|
||||
col_info->current_column++;
|
||||
col_info->extra_columns = col_info->current_column;
|
||||
} else {
|
||||
/* If span to end of table, assume spaning single column
|
||||
at the moment */
|
||||
cell_end_col = cell_start_col + ((0 == col_span) ? 1 : col_span);
|
||||
|
||||
if (col_info->num_columns < cell_end_col) {
|
||||
spans = realloc(col_info->spans,
|
||||
sizeof *spans * (cell_end_col + 1));
|
||||
if (!spans)
|
||||
return false;
|
||||
col_info->spans = spans;
|
||||
col_info->num_columns = cell_end_col;
|
||||
|
||||
/* Mark new final column as sentinal */
|
||||
col_info->spans[cell_end_col].row_span = 0;
|
||||
col_info->spans[cell_end_col].auto_row =
|
||||
col_info->spans[cell_end_col].auto_column =
|
||||
false;
|
||||
}
|
||||
|
||||
if (0 == col_span) {
|
||||
col_info->spans[cell_start_col].auto_column = true;
|
||||
col_info->spans[cell_start_col].row_span = row_span;
|
||||
col_info->spans[cell_start_col].auto_row = (0 == row_span);
|
||||
} else {
|
||||
for (i = cell_start_col; i < cell_end_col; i++) {
|
||||
col_info->spans[i].row_span = (0 == row_span) ?
|
||||
1 : row_span;
|
||||
col_info->spans[i].auto_row = (0 == row_span);
|
||||
col_info->spans[i].auto_column = false;
|
||||
}
|
||||
}
|
||||
if (0 == col_span) {
|
||||
col_info->spans[cell_end_col].auto_column = true;
|
||||
}
|
||||
col_info->current_column = cell_end_col;
|
||||
}
|
||||
|
||||
*start_column = cell_start_col;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool box_normalise_inline_container(struct box *cont, pool box_pool)
|
||||
{
|
||||
struct box *child;
|
||||
struct box *next_child;
|
||||
|
||||
assert(cont != 0);
|
||||
assert(cont->type == BOX_INLINE_CONTAINER);
|
||||
LOG(("cont %p", cont));
|
||||
|
||||
for (child = cont->children; child != 0; child = next_child) {
|
||||
next_child = child->next;
|
||||
switch (child->type) {
|
||||
case BOX_INLINE:
|
||||
case BOX_BR:
|
||||
/* ok */
|
||||
break;
|
||||
case BOX_INLINE_BLOCK:
|
||||
/* ok */
|
||||
if (!box_normalise_block(child, box_pool))
|
||||
return false;
|
||||
break;
|
||||
case BOX_FLOAT_LEFT:
|
||||
case BOX_FLOAT_RIGHT:
|
||||
/* ok */
|
||||
assert(child->children != 0);
|
||||
switch (child->children->type) {
|
||||
case BOX_BLOCK:
|
||||
if (!box_normalise_block(
|
||||
child->children,
|
||||
box_pool))
|
||||
return false;
|
||||
break;
|
||||
case BOX_TABLE:
|
||||
if (!box_normalise_table(
|
||||
child->children,
|
||||
box_pool))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
if (child->children == 0) {
|
||||
/* the child has destroyed itself: remove float */
|
||||
if (child->prev == 0)
|
||||
child->parent->children = child->next;
|
||||
else
|
||||
child->prev->next = child->next;
|
||||
if (child->next != 0)
|
||||
child->next->prev = child->prev;
|
||||
box_free(child);
|
||||
}
|
||||
break;
|
||||
case BOX_BLOCK:
|
||||
case BOX_INLINE_CONTAINER:
|
||||
case BOX_TABLE:
|
||||
case BOX_TABLE_ROW_GROUP:
|
||||
case BOX_TABLE_ROW:
|
||||
case BOX_TABLE_CELL:
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
LOG(("cont %p done", cont));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user