summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--css/css.c12
-rw-r--r--css/css.h6
-rw-r--r--css/ruleset.c7
-rw-r--r--render/box.c75
-rw-r--r--render/box.h4
-rw-r--r--render/box_construct.c26
-rw-r--r--render/layout.c91
7 files changed, 142 insertions, 79 deletions
diff --git a/css/css.c b/css/css.c
index 76c7e6ca5..aeeec4084 100644
--- a/css/css.c
+++ b/css/css.c
@@ -180,7 +180,7 @@ const struct css_style css_base_style = {
CSS_FONT_STYLE_NORMAL,
CSS_FONT_VARIANT_NORMAL,
CSS_FONT_WEIGHT_NORMAL,
- { CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } },
+ { CSS_HEIGHT_AUTO, { { 1, CSS_UNIT_EM } } },
{ CSS_LETTER_SPACING_NORMAL, { 0, CSS_UNIT_PX } },
{ CSS_LINE_HEIGHT_ABSOLUTE, { 1.33 } },
{ CSS_LIST_STYLE_IMAGE_NONE, 0 },
@@ -265,7 +265,7 @@ const struct css_style css_empty_style = {
CSS_FONT_STYLE_NOT_SET,
CSS_FONT_VARIANT_NOT_SET,
CSS_FONT_WEIGHT_NOT_SET,
- { CSS_HEIGHT_NOT_SET, { 1, CSS_UNIT_EM } },
+ { CSS_HEIGHT_NOT_SET, { { 1, CSS_UNIT_EM } } },
{ CSS_LETTER_SPACING_NOT_SET, { 0, CSS_UNIT_PX } },
{ CSS_LINE_HEIGHT_NOT_SET, { 1.33 } },
{ CSS_LIST_STYLE_IMAGE_NOT_SET, 0 },
@@ -351,7 +351,7 @@ const struct css_style css_blank_style = {
CSS_FONT_STYLE_INHERIT,
CSS_FONT_VARIANT_INHERIT,
CSS_FONT_WEIGHT_INHERIT,
- { CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } },
+ { CSS_HEIGHT_AUTO, { { 1, CSS_UNIT_EM } } },
{ CSS_LETTER_SPACING_INHERIT, { 0, CSS_UNIT_PX } },
{ CSS_LINE_HEIGHT_INHERIT, { 1.33 } },
{ CSS_LIST_STYLE_IMAGE_INHERIT, 0 },
@@ -1903,7 +1903,11 @@ void css_dump_style(FILE *stream, const struct css_style * const style)
fprintf(stream, "auto");
break;
case CSS_HEIGHT_LENGTH:
- css_dump_length(stream, &style->height.length);
+ css_dump_length(stream, &style->height.value.length);
+ break;
+ case CSS_HEIGHT_PERCENT:
+ fprintf(stream, "%g%%",
+ style->height.value.percent);
break;
default:
fprintf(stream, "UNKNOWN");
diff --git a/css/css.h b/css/css.h
index a48d97ef8..b3ff34ea0 100644
--- a/css/css.h
+++ b/css/css.h
@@ -279,8 +279,12 @@ struct css_style {
enum { CSS_HEIGHT_INHERIT,
CSS_HEIGHT_AUTO,
CSS_HEIGHT_LENGTH,
+ CSS_HEIGHT_PERCENT,
CSS_HEIGHT_NOT_SET } height;
- struct css_length length;
+ union {
+ struct css_length length;
+ float percent;
+ } value;
} height;
struct {
diff --git a/css/ruleset.c b/css/ruleset.c
index 4529fba8d..d04f62359 100644
--- a/css/ruleset.c
+++ b/css/ruleset.c
@@ -2228,8 +2228,11 @@ void parse_height(struct css_style * const s, const struct css_node * const v)
if (v->type == CSS_NODE_IDENT && v->data_length == 4 &&
strncasecmp(v->data, "auto", 4) == 0)
s->height.height = CSS_HEIGHT_AUTO;
- else if ((v->type == CSS_NODE_DIMENSION || v->type == CSS_NODE_NUMBER) &&
- parse_length(&s->height.length, v, true) == 0)
+ else if (v->type == CSS_NODE_PERCENTAGE) {
+ s->height.height = CSS_HEIGHT_PERCENT;
+ s->height.value.percent = atof(v->data);
+ } else if ((v->type == CSS_NODE_DIMENSION || v->type == CSS_NODE_NUMBER) &&
+ parse_length(&s->height.value.length, v, true) == 0)
s->height.height = CSS_HEIGHT_LENGTH;
}
diff --git a/render/box.c b/render/box.c
index 1d72da607..023c444cc 100644
--- a/render/box.c
+++ b/render/box.c
@@ -102,6 +102,7 @@ struct box * box_create(struct css_style *style,
box->fallback = NULL;
box->inline_end = NULL;
box->float_children = NULL;
+ box->float_container = NULL;
box->next_float = NULL;
box->list_marker = NULL;
box->col = NULL;
@@ -551,7 +552,7 @@ void box_dump(FILE *stream, struct box *box, unsigned int depth)
fprintf(stream, "(%i %i %i %i) ",
box->descendant_x0, box->descendant_y0,
box->descendant_x1, box->descendant_y1);
-
+
fprintf(stream, "m(%i %i %i %i) ",
box->margin[TOP], box->margin[LEFT],
box->margin[BOTTOM], box->margin[RIGHT]);
@@ -685,9 +686,9 @@ struct box* box_duplicate_tree(struct box *root, struct content *c)
struct box *new_root;/**< Root of the new box tree*/
int box_number = 0;
struct box_dict_element *box_dict, *box_dict_end;
-
+
box_duplicate_last = NULL;
-
+
/* 1. Duplicate parent - children structure, list_markers*/
new_root = talloc_memdup(c, root, sizeof (struct box));
if (!box_duplicate_main_tree(new_root, c, &box_number))
@@ -695,32 +696,32 @@ struct box* box_duplicate_tree(struct box *root, struct content *c)
/* 2. Create address translation dictionary*/
/*TODO: dont save unnecessary addresses*/
-
+
box_dict_end = box_dict = malloc(box_number *
sizeof(struct box_dict_element));
-
+
if (box_dict == NULL)
return NULL;
box_duplicate_create_dict(root, new_root, &box_dict_end);
-
+
assert((box_dict_end - box_dict) == box_number);
-
+
/*3. Sort it*/
-
+
qsort(box_dict, (box_dict_end - box_dict), sizeof(struct box_dict_element),
(int (*)(const void *, const void *))box_compare_dict_elements);
-
+
/* 4. Update inline_end and float_children pointers */
-
+
box_duplicate_update(new_root, box_dict, (box_dict_end - box_dict));
-
+
free(box_dict);
-
+
return new_root;
}
/**
- * Recursively duplicates children of an element, and also if present - its
+ * Recursively duplicates children of an element, and also if present - its
* list_marker, style and text.
* \param box Current box to duplicate its children
* \param c talloc memory pool
@@ -730,9 +731,9 @@ struct box* box_duplicate_tree(struct box *root, struct content *c)
bool box_duplicate_main_tree(struct box *box, struct content *c, int *count)
{
struct box *b, *prev;
-
+
prev = NULL;
-
+
for (b = box->children; b; b = b->next) {
struct box *copy;
@@ -740,14 +741,14 @@ bool box_duplicate_main_tree(struct box *box, struct content *c, int *count)
copy = talloc_memdup(c, b, sizeof (struct box));
if (copy == NULL)
return false;
-
+
copy->parent = box;
-
+
if (prev != NULL)
prev->next = copy;
else
box->children = copy;
-
+
if (copy->type == BOX_INLINE) {
struct box_duplicate_llist *temp;
@@ -763,21 +764,21 @@ bool box_duplicate_main_tree(struct box *box, struct content *c, int *count)
box_duplicate_last->box->inline_end = copy;
copy->inline_end = box_duplicate_last->box;
-
+
temp = box_duplicate_last;
box_duplicate_last = temp->prev;
free(temp);
}
-
+
/* Recursively visit child */
if (!box_duplicate_main_tree(copy, c, count))
return false;
-
+
prev = copy;
}
-
+
box->last = prev;
-
+
if (box->object && option_suppress_images && (
#ifdef WITH_JPEG
box->object->type == CONTENT_JPEG ||
@@ -817,27 +818,27 @@ bool box_duplicate_main_tree(struct box *box, struct content *c, int *count)
#endif
false))
box->object = NULL;
-
+
if (box->list_marker) {
box->list_marker = talloc_memdup(c, box->list_marker,
sizeof *box->list_marker);
- if (box->list_marker == NULL)
+ if (box->list_marker == NULL)
return false;
box->list_marker->parent = box;
}
-
+
if (box->text) {
box->text = talloc_memdup(c, box->text, box->length);
- if (box->text == NULL)
+ if (box->text == NULL)
return false;
}
-
+
if (box->style) {
box->style = talloc_memdup(c, box->style, sizeof *box->style);
- if (box->style == NULL)
+ if (box->style == NULL)
return false;
}
-
+
/*Make layout calculate the size of this element later
(might change because of font change etc.) */
box->width = UNKNOWN_WIDTH;
@@ -845,7 +846,7 @@ bool box_duplicate_main_tree(struct box *box, struct content *c, int *count)
box->max_width = UNKNOWN_MAX_WIDTH;
(*count)++;
-
+
return true;
}
@@ -861,15 +862,15 @@ void box_duplicate_create_dict(struct box *old_box, struct box *new_box,
{
/**Children of the old and new boxes*/
struct box *b_old, *b_new;
-
+
for (b_old = old_box->children, b_new = new_box->children;
b_old != NULL && b_new != NULL;
b_old = b_old->next, b_new = b_new->next)
box_duplicate_create_dict(b_old, b_new, dict);
-
+
/*The new tree should be a exact copy*/
assert(b_old == NULL && b_new == NULL);
-
+
(*dict)->old = old_box;
(*dict)->new = new_box;
(*dict)++;
@@ -888,10 +889,10 @@ void box_duplicate_update(struct box *box,
struct box_dict_element *box_dict_element;
struct box *b;
struct box_dict_element element;
-
+
for (b = box->children; b; b = b->next)
box_duplicate_update(b, box_dict, n);
-
+
if (box->float_children) {
element.old = box->float_children;
box_dict_element = bsearch(&element,
@@ -900,7 +901,7 @@ void box_duplicate_update(struct box *box,
(int (*)(const void *, const void *))box_compare_dict_elements);
box->float_children = box_dict_element->new;
}
-
+
if (box->next_float) {
element.old = box->next_float;
box_dict_element = bsearch(&element,
diff --git a/render/box.h b/render/box.h
index c1cce449f..c66767225 100644
--- a/render/box.h
+++ b/render/box.h
@@ -190,7 +190,7 @@ struct box {
unsigned int start_column; /**< Start column for TABLE_CELL only. */
bool printed; /** Whether this box has already been printed*/
-
+
struct box *next; /**< Next sibling box, or 0. */
struct box *prev; /**< Previous sibling box, or 0. */
struct box *children; /**< First child box, or 0. */
@@ -207,6 +207,8 @@ struct box {
struct box *float_children;
/** Next sibling float box. */
struct box *next_float;
+ /** If box is a float, points to box's containing block */
+ struct box *float_container;
/** Level below which subsequent floats must be cleared.
* This is used only for boxes with float_children */
int clear_level;
diff --git a/render/box_construct.c b/render/box_construct.c
index fb605209b..94ca2ef57 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -583,9 +583,14 @@ bool box_construct_element(xmlNode *n, struct content *content,
float current;
for (child = box->children; child;
child = child->next) {
- current = css_len2px(
+ if (child->style->height.height ==
+ CSS_HEIGHT_LENGTH)
+ current = css_len2px(
&child->style->height.
- length, child->style);
+ value.length,
+ child->style);
+ else
+ current = 0;
if (child->type == BOX_TABLE_CELL &&
value > current) {
/* Row height exceeds cell
@@ -593,10 +598,11 @@ bool box_construct_element(xmlNode *n, struct content *content,
* to row height */
child->style->height.height =
CSS_HEIGHT_LENGTH;
- child->style->height.length.
- unit = CSS_UNIT_PX;
- child->style->height.length.
- value = value;
+ child->style->height.value.
+ length.unit =
+ CSS_UNIT_PX;
+ child->style->height.value.
+ length.value = value;
}
}
}
@@ -932,8 +938,8 @@ struct css_style * box_get_style(struct content *c,
* percentage heights mean, so ignore them */
} else {
style->height.height = CSS_HEIGHT_LENGTH;
- style->height.length.unit = CSS_UNIT_PX;
- style->height.length.value = value;
+ style->height.value.length.unit = CSS_UNIT_PX;
+ style->height.value.length.value = value;
}
xmlFree(s);
}
@@ -1027,8 +1033,8 @@ struct css_style * box_get_style(struct content *c,
int value = isdigit(s[0]) ? atoi(s): -1;
if (0 < value) {
style->height.height = CSS_HEIGHT_LENGTH;
- style->height.length.unit = CSS_UNIT_EM;
- style->height.length.value = value;
+ style->height.value.length.unit = CSS_UNIT_EM;
+ style->height.value.length.value = value;
}
xmlFree(s);
}
diff --git a/render/layout.c b/render/layout.c
index 1bf77fbcf..faffd750b 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -308,6 +308,9 @@ bool layout_block_context(struct box *block, struct content *content)
(box->style->position == CSS_POSITION_ABSOLUTE||
box->style->position == CSS_POSITION_FIXED)) {
box->x = box->parent->padding[LEFT];
+ layout_find_dimensions(box->parent->width, box,
+ box->style, NULL, &(box->height), NULL,
+ NULL, NULL, NULL, NULL);
/* absolute positioned; this element will establish
* its own block context when it gets laid out later,
* so no need to look at its children now. */
@@ -974,8 +977,8 @@ void layout_float_find_dimensions(int available_width,
* \param max_width updated to max-width, may be NULL
* \param min_width updated to min-width, may be NULL
* \param margin[4] filled with margins, may be NULL
- * \param padding[4] filled with paddings
- * \param border[4] filled with border widths
+ * \param padding[4] filled with paddings, may be NULL
+ * \param border[4] filled with border widths, may be NULL
*/
void layout_find_dimensions(int available_width,
@@ -983,6 +986,7 @@ void layout_find_dimensions(int available_width,
int *width, int *height, int *max_width, int *min_width,
int margin[4], int padding[4], int border[4])
{
+ struct box *containing_block = NULL;
unsigned int i;
int fixed = 0;
float frac = 0;
@@ -1015,7 +1019,33 @@ void layout_find_dimensions(int available_width,
if (height) {
switch (style->height.height) {
case CSS_HEIGHT_LENGTH:
- *height = css_len2px(&style->height.length, style);
+ *height = css_len2px(&style->height.value.length,
+ style);
+ break;
+ case CSS_HEIGHT_PERCENT:
+ if (box->float_container) {
+ containing_block = box->float_container;
+ } else if (box->parent && box->parent->type !=
+ BOX_INLINE_CONTAINER) {
+ containing_block = box->parent;
+ } else if (box->parent && box->parent->type ==
+ BOX_INLINE_CONTAINER) {
+ assert(box->parent->parent);
+ containing_block = box->parent->parent;
+ }
+ if (box->style->position == CSS_POSITION_ABSOLUTE ||
+ (containing_block &&
+ (containing_block->style->height.
+ height == CSS_HEIGHT_LENGTH ||
+ containing_block->style->height.
+ height == CSS_HEIGHT_PERCENT) &&
+ containing_block->height != AUTO)) {
+ *height = style->height.value.percent *
+ containing_block->height / 100;
+ } else {
+ /* else treated as auto; fall though */
+ *height = AUTO;
+ }
break;
case CSS_HEIGHT_AUTO:
default:
@@ -1094,25 +1124,31 @@ void layout_find_dimensions(int available_width,
}
}
- switch (style->padding[i].padding) {
- case CSS_PADDING_PERCENT:
- padding[i] = available_width *
- style->padding[i].value.percent / 100;
- break;
- case CSS_PADDING_LENGTH:
- default:
- padding[i] = css_len2px(&style->padding[i].
- value.length, style);
- break;
+ if (padding) {
+ switch (style->padding[i].padding) {
+ case CSS_PADDING_PERCENT:
+ padding[i] = available_width *
+ style->padding[i].value.
+ percent / 100;
+ break;
+ case CSS_PADDING_LENGTH:
+ default:
+ padding[i] = css_len2px(&style->padding[i].
+ value.length, style);
+ break;
+ }
}
- if (style->border[i].style == CSS_BORDER_STYLE_HIDDEN ||
- style->border[i].style == CSS_BORDER_STYLE_NONE)
- /* spec unclear: following Mozilla */
- border[i] = 0;
- else
- border[i] = css_len2px(&style->border[i].
- width.value, style);
+ if (border) {
+ if (style->border[i].style == CSS_BORDER_STYLE_HIDDEN ||
+ style->border[i].style ==
+ CSS_BORDER_STYLE_NONE)
+ /* spec unclear: following Mozilla */
+ border[i] = 0;
+ else
+ border[i] = css_len2px(&style->border[i].
+ width.value, style);
+ }
}
}
@@ -1536,7 +1572,7 @@ bool layout_line(struct box *first, int *width, int *y,
/* height */
switch (b->style->height.height) {
case CSS_HEIGHT_LENGTH:
- b->height = css_len2px(&b->style->height.length,
+ b->height = css_len2px(&b->style->height.value.length,
b->style);
break;
case CSS_HEIGHT_AUTO:
@@ -1735,6 +1771,7 @@ bool layout_line(struct box *first, int *width, int *y,
box_dump(stderr, cont, 0);
assert(0);
}
+ b->float_container = d->float_container = cont;
b->next_float = cont->float_children;
cont->float_children = b;
split_box = 0;
@@ -2104,7 +2141,8 @@ struct box *layout_minmax_line(struct box *first,
/* height */
switch (b->style->height.height) {
case CSS_HEIGHT_LENGTH:
- height = css_len2px(&b->style->height.length, b->style);
+ height = css_len2px(&b->style->height.value.length,
+ b->style);
break;
case CSS_HEIGHT_AUTO:
default:
@@ -2553,7 +2591,7 @@ bool layout_table(struct box *table, int available_width,
* to attempt to make cells as small as
* possible, so treat it as a minimum */
int h = (int) css_len2px(&c->style->
- height.length, c->style);
+ height.value.length, c->style);
if (c->height < h)
c->height = h;
}
@@ -2673,7 +2711,7 @@ bool layout_table(struct box *table, int available_width,
/* Take account of any table height specified within CSS/HTML */
if (style->height.height == CSS_HEIGHT_LENGTH) {
/* This is the minimum height for the table (see 17.5.3) */
- int min_height = css_len2px(&style->height.length, style);
+ int min_height = css_len2px(&style->height.value.length, style);
table->height = max(table_height, min_height);
} else {
@@ -3205,9 +3243,14 @@ bool layout_absolute(struct box *box, struct box *containing_block,
layout_compute_offsets(box, containing_block,
&top, &right, &bottom, &left);
+ /* Pass containing block into layout_find_dimensions via the float
+ * containing block box member. This is unused for absolutly positioned
+ * boxes because a box can't be floated and absolutly positioned. */
+ box->float_container = containing_block;
layout_find_dimensions(available_width, box, box->style,
&width, &height, &max_width, &min_width,
margin, padding, border);
+ box->float_container = NULL;
/* 10.3.7 */
LOG(("%i + %i + %i + %i + %i + %i + %i + %i + %i = %i",