[project @ 2004-06-25 14:28:29 by bursa]

Parse CSS background shorthand property. Background rendering improvements.

svn path=/import/netsurf/; revision=1006
This commit is contained in:
James Bursa 2004-06-25 14:28:29 +00:00
parent bca6a63c45
commit aa6e904604
4 changed files with 319 additions and 187 deletions

View File

@ -1005,10 +1005,10 @@ void css_dump_style(const struct css_style * const style)
break; break;
} }
fprintf(stderr, " %s %s ", fprintf(stderr, " %s %s ",
css_background_attachment_name[
style->background_attachment],
css_background_repeat_name[ css_background_repeat_name[
style->background_repeat]); style->background_repeat],
css_background_attachment_name[
style->background_attachment]);
switch (style->background_position.horz.pos) { switch (style->background_position.horz.pos) {
case CSS_BACKGROUND_POSITION_LENGTH: case CSS_BACKGROUND_POSITION_LENGTH:
css_dump_length(&style->background_position. css_dump_length(&style->background_position.
@ -1038,6 +1038,7 @@ void css_dump_style(const struct css_style * const style)
vert.value.percent); vert.value.percent);
break; break;
case CSS_BACKGROUND_POSITION_INHERIT: case CSS_BACKGROUND_POSITION_INHERIT:
fprintf(stderr, "inherit");
break; break;
default: default:
fprintf(stderr, "UNKNOWN"); fprintf(stderr, "UNKNOWN");

View File

@ -54,42 +54,42 @@ typedef enum {
} css_text_decoration; } css_text_decoration;
typedef enum { typedef enum {
CSS_BACKGROUND_POSITION_LENGTH, CSS_BACKGROUND_IMAGE_NONE,
CSS_BACKGROUND_POSITION_PERCENT, CSS_BACKGROUND_IMAGE_INHERIT,
CSS_BACKGROUND_POSITION_INHERIT CSS_BACKGROUND_IMAGE_URI
} css_background_position; } css_background_image_type;
/** Part of struct css_style, for convenience. */
struct css_background_position {
enum {
CSS_BACKGROUND_POSITION_LENGTH,
CSS_BACKGROUND_POSITION_PERCENT,
CSS_BACKGROUND_POSITION_INHERIT
} pos;
union {
float percent;
struct css_length length;
} value;
};
/** Representation of a complete CSS 2 style. */ /** Representation of a complete CSS 2 style. */
struct css_style { struct css_style {
colour background_color; colour background_color;
css_background_attachment background_attachment; css_background_attachment background_attachment;
struct { struct {
enum { CSS_BACKGROUND_IMAGE_NONE, css_background_image_type type;
CSS_BACKGROUND_IMAGE_INHERIT, char *uri;
CSS_BACKGROUND_IMAGE_URI } type;
char *uri;
} background_image; } background_image;
struct { struct {
struct { struct css_background_position horz;
css_background_position pos; struct css_background_position vert;
union { } background_position;
float percent;
struct css_length length;
} value;
} horz;
struct {
css_background_position pos;
union {
float percent;
struct css_length length;
} value;
} vert;
} background_position;
css_background_repeat background_repeat; css_background_repeat background_repeat;
struct { struct {
colour color; colour color;
@ -119,7 +119,7 @@ struct css_style {
} value; } value;
} font_size; } font_size;
css_font_family font_family; css_font_family font_family;
css_font_weight font_weight; css_font_weight font_weight;
css_font_style font_style; css_font_style font_style;
css_font_variant font_variant; css_font_variant font_variant;
@ -167,14 +167,14 @@ struct css_style {
css_text_align text_align; css_text_align text_align;
css_text_decoration text_decoration; css_text_decoration text_decoration;
struct { struct {
enum { CSS_TEXT_INDENT_INHERIT, enum { CSS_TEXT_INDENT_INHERIT,
CSS_TEXT_INDENT_LENGTH, CSS_TEXT_INDENT_LENGTH,
CSS_TEXT_INDENT_PERCENT } size; CSS_TEXT_INDENT_PERCENT } size;
union { union {
struct css_length length; struct css_length length;
float percent; float percent;
} value ; } value ;
} text_indent; } text_indent;
css_text_transform text_transform; css_text_transform text_transform;
css_visibility visibility; css_visibility visibility;
@ -317,7 +317,7 @@ void css_destroy(struct content *c);
#ifdef CSS_INTERNALS #ifdef CSS_INTERNALS
struct css_node * css_new_node(struct content *stylesheet, struct css_node * css_new_node(struct content *stylesheet,
css_node_type type, css_node_type type,
const char *data, unsigned int data_length); const char *data, unsigned int data_length);
void css_free_node(struct css_node *node); void css_free_node(struct css_node *node);
struct css_selector * css_new_selector(css_selector_type type, struct css_selector * css_new_selector(css_selector_type type,
@ -349,7 +349,7 @@ void css_cascade(struct css_style * const style,
void css_merge(struct css_style * const style, void css_merge(struct css_style * const style,
const struct css_style * const apply); const struct css_style * const apply);
void css_parse_property_list(struct content *c, struct css_style * style, void css_parse_property_list(struct content *c, struct css_style * style,
char * str); char * str);
colour named_colour(const char *name); colour named_colour(const char *name);
void css_dump_style(const struct css_style * const style); void css_dump_style(const struct css_style * const style);
void css_dump_stylesheet(const struct css_stylesheet * stylesheet); void css_dump_stylesheet(const struct css_stylesheet * stylesheet);

View File

@ -11,6 +11,10 @@
* This file implements the last stage of CSS parsing. It converts trees of * This file implements the last stage of CSS parsing. It converts trees of
* struct css_node produced by the parser into struct style, and adds them to a * struct css_node produced by the parser into struct style, and adds them to a
* stylesheet. * stylesheet.
*
* This code is complicated by the CSS error handling rules. According to
* CSS 2.1 4.2 "Illegal values", the whole of a declaration must be legal for
* any of it to be used.
*/ */
#include <assert.h> #include <assert.h>
@ -34,13 +38,21 @@ static int parse_length(struct css_length * const length,
const struct css_node * const v, bool non_negative); const struct css_node * const v, bool non_negative);
static colour parse_colour(const struct css_node * const v); static colour parse_colour(const struct css_node * const v);
static colour css_parse_rgb(struct css_node *v); static colour css_parse_rgb(struct css_node *v);
static void parse_background(struct css_style * const s, const struct css_node * v); static void parse_background(struct css_style * const s,
const struct css_node * v);
static void parse_background_attachment(struct css_style * const s, const struct css_node * const v); static void parse_background_attachment(struct css_style * const s, const struct css_node * const v);
static void parse_background_color(struct css_style * const s, const struct css_node * const v); static void parse_background_color(struct css_style * const s, const struct css_node * const v);
static void parse_background_image(struct css_style * const s, const struct css_node * const v); static void parse_background_image(struct css_style * const s,
const struct css_node * const v);
static bool css_background_image_parse(const struct css_node *v,
css_background_image_type *type, char **uri);
static struct css_background_entry *css_background_lookup( static struct css_background_entry *css_background_lookup(
const struct css_node *v); const struct css_node *v);
static void parse_background_position(struct css_style * const s, const struct css_node * const v); static void parse_background_position(struct css_style * const s,
const struct css_node * const v);
static bool css_background_position_parse(const struct css_node **node,
struct css_background_position *horz,
struct css_background_position *vert);
static void parse_background_repeat(struct css_style * const s, const struct css_node * const v); static void parse_background_repeat(struct css_style * const s, const struct css_node * const v);
static void parse_border(struct css_style * const s, const struct css_node * v); static void parse_border(struct css_style * const s, const struct css_node * v);
static void parse_border_bottom(struct css_style * const s, const struct css_node * v); static void parse_border_bottom(struct css_style * const s, const struct css_node * v);
@ -522,52 +534,113 @@ colour css_parse_rgb(struct css_node *v)
} }
void parse_background(struct css_style * const s, const struct css_node * v) /**
* \name Individual property parsers.
* \{
*/
void parse_background(struct css_style * const s,
const struct css_node * v)
{ {
colour c; colour c = TRANSPARENT, c2;
css_background_attachment ba; css_background_image_type bi = CSS_BACKGROUND_IMAGE_NONE, bi2;
css_background_repeat br; char *bi_uri = 0;
for (; v; v = v->next) { css_background_repeat br = CSS_BACKGROUND_REPEAT_REPEAT, br2;
css_background_attachment ba = CSS_BACKGROUND_ATTACHMENT_SCROLL, ba2;
struct css_background_position horz =
{ CSS_BACKGROUND_POSITION_PERCENT, { 0 } };
struct css_background_position vert =
{ CSS_BACKGROUND_POSITION_PERCENT, { 0 } };
struct css_background_position horz2, vert2;
while (v) {
switch (v->type) { switch (v->type) {
/**\todo background-position */
case CSS_NODE_URI: case CSS_NODE_URI:
case CSS_NODE_STRING: case CSS_NODE_STRING:
parse_background_image(s, v); /* background-image */
if (!css_background_image_parse(v, &bi2,
&bi_uri))
return;
bi = bi2;
v = v->next;
break; break;
/*case CSS_NODE_DIMENSION:
case CSS_NODE_DIMENSION:
case CSS_NODE_PERCENTAGE: case CSS_NODE_PERCENTAGE:
parse_background_position(s, v); /* background-position */
v = v->naxt; if (!css_background_position_parse(&v,
break;*/ &horz2, &vert2))
return;
horz = horz2;
vert = vert2;
break;
case CSS_NODE_IDENT: case CSS_NODE_IDENT:
/* background-attachment */ /* could be background-image: none */
ba = css_background_attachment_parse(v->data, v->data_length); if (v->data_length == 4 &&
if (ba != CSS_BACKGROUND_ATTACHMENT_UNKNOWN) { strncasecmp(v->data, "none",
s->background_attachment = ba; 4) == 0) {
bi = CSS_BACKGROUND_IMAGE_NONE;
v = v->next;
break; break;
} }
/* background-repeat */ /* background-repeat */
br = css_background_repeat_parse(v->data, v->data_length); br2 = css_background_repeat_parse(v->data,
if (br != CSS_BACKGROUND_REPEAT_UNKNOWN) { v->data_length);
s->background_repeat = br; if (br2 != CSS_BACKGROUND_REPEAT_UNKNOWN) {
br = br2;
v = v->next;
break;
}
/* background-attachment */
ba2 = css_background_attachment_parse(v->data,
v->data_length);
if (ba2 != CSS_BACKGROUND_ATTACHMENT_UNKNOWN) {
ba = ba2;
v = v->next;
break;
}
/* background-position */
if (css_background_position_parse(&v,
&horz2, &vert2)) {
horz = horz2;
vert = vert2;
break; break;
} }
/* fall through */ /* fall through */
case CSS_NODE_HASH: case CSS_NODE_HASH:
case CSS_NODE_FUNCTION: case CSS_NODE_FUNCTION:
c = parse_colour(v); /* background-color */
if (c != CSS_COLOR_NONE) c2 = parse_colour(v);
s->background_color = c; if (c2 != CSS_COLOR_NONE) {
break; c = c2;
v = v->next;
break;
}
/* fall through */
default: default:
break; /* parsing failed */
return;
} }
} }
s->background_color = c;
s->background_image.type = bi;
s->background_image.uri = bi_uri;
s->background_repeat = br;
s->background_attachment = ba;
s->background_position.horz = horz;
s->background_position.vert = vert;
} }
void parse_background_attachment(struct css_style * const s, const struct css_node * const v)
void parse_background_attachment(struct css_style * const s,
const struct css_node * const v)
{ {
css_background_attachment z; css_background_attachment z;
if (v->type != CSS_NODE_IDENT || v->next != 0) if (v->type != CSS_NODE_IDENT || v->next != 0)
@ -577,19 +650,51 @@ void parse_background_attachment(struct css_style * const s, const struct css_no
s->background_attachment = z; s->background_attachment = z;
} }
void parse_background_color(struct css_style * const s, const struct css_node * const v)
void parse_background_color(struct css_style * const s,
const struct css_node * const v)
{ {
colour c = parse_colour(v); colour c;
if (v->next)
return;
c = parse_colour(v);
if (c != CSS_COLOR_NONE) if (c != CSS_COLOR_NONE)
s->background_color = c; s->background_color = c;
} }
void parse_background_image(struct css_style * const s, const struct css_node * const v)
void parse_background_image(struct css_style * const s,
const struct css_node * const v)
{
css_background_image_type type;
char *uri = 0;
if (v->next)
return;
if (!css_background_image_parse(v, &type, &uri))
return;
s->background_image.type = type;
s->background_image.uri = uri;
}
/**
* Parse a background-image property.
*
* \param node node to parse
* \param type updated to background image type
* \param uri updated to background image uri, if type is
* CSS_BACKGROUND_IMAGE_URI
* \return true on success, false on parse failure
*/
bool css_background_image_parse(const struct css_node *v,
css_background_image_type *type, char **uri)
{ {
bool string = false; bool string = false;
const char *u; const char *u;
char *t, *url; char *t, *url;
s->background_image.uri = 0;
switch (v->type) { switch (v->type) {
case CSS_NODE_URI: case CSS_NODE_URI:
@ -603,9 +708,8 @@ void parse_background_image(struct css_style * const s, const struct css_node *
u++; u++;
} }
url = strndup(u, v->data_length - (u - v->data)); url = strndup(u, v->data_length - (u - v->data));
if (!url) { if (!url)
return; return false;
}
for (t = url + strlen(url) - 2; for (t = url + strlen(url) - 2;
*t == ' ' || *t == '\t' || *t == '\r' || *t == ' ' || *t == '\t' || *t == '\r' ||
*t == '\n' || *t == '\f'; *t == '\n' || *t == '\f';
@ -620,32 +724,37 @@ void parse_background_image(struct css_style * const s, const struct css_node *
* content is the parent HTML content * content is the parent HTML content
*/ */
if (v->stylesheet->type == CONTENT_HTML) if (v->stylesheet->type == CONTENT_HTML)
s->background_image.uri = url_join(url, v->stylesheet->data.html.base_url); *uri = url_join(url, v->stylesheet->data.html.base_url);
else else
s->background_image.uri = url_join(url, v->stylesheet->url); *uri = url_join(url, v->stylesheet->url);
free(url); free(url);
if (!s->background_image.uri) return; if (!*uri)
s->background_image.type = CSS_BACKGROUND_IMAGE_URI; return false;
*type = CSS_BACKGROUND_IMAGE_URI;
break; break;
case CSS_NODE_STRING: case CSS_NODE_STRING:
url = strndup(v->data, v->data_length); url = strndup(v->data, v->data_length);
if (!url) if (!url)
return; return false;
s->background_image.uri = url_join(url, v->stylesheet->url); *uri = url_join(url, v->stylesheet->url);
free(url); free(url);
if (!s->background_image.uri) return; if (!*uri)
s->background_image.type = CSS_BACKGROUND_IMAGE_URI; return false;
*type = CSS_BACKGROUND_IMAGE_URI;
break; break;
case CSS_NODE_IDENT: case CSS_NODE_IDENT:
if (v->data_length == 7 && strncasecmp(v->data, "inherit", 7) == 0) if (v->data_length == 7 &&
s->background_image.type = CSS_BACKGROUND_IMAGE_INHERIT; strncasecmp(v->data, "inherit", 7) == 0)
else if (v->data_length == 4 && strncasecmp(v->data, "none", 4) == 0) *type = CSS_BACKGROUND_IMAGE_INHERIT;
s->background_image.type = CSS_BACKGROUND_IMAGE_NONE; else if (v->data_length == 4 &&
strncasecmp(v->data, "none", 4) == 0)
*type = CSS_BACKGROUND_IMAGE_NONE;
break; break;
default: default:
break; return false;
} }
return true;
} }
@ -695,128 +804,146 @@ struct css_background_entry *css_background_lookup(
void parse_background_position(struct css_style * const s, void parse_background_position(struct css_style * const s,
const struct css_node * v) const struct css_node * v)
{ {
struct css_node *w = v->next; const struct css_node *node = v;
struct css_background_entry *bg = 0, *bg2 = 0; struct css_background_position horz, vert;
if (w && w->next) if (v->next && v->next->next)
/* more than two nodes */
return; return;
if (!w) { /* only one value specified */ if (!css_background_position_parse(&node, &horz, &vert))
return;
if (node)
/* didn't parse all the nodes */
return;
s->background_position.horz = horz;
s->background_position.vert = vert;
}
/**
* Parse a background-position property.
*
* \param node list of nodes, updated to first unused node
* \param horz updated to horizontal background position
* \param vert updated to vertical background position
* \return true on success, false on parse failure
*/
bool css_background_position_parse(const struct css_node **node,
struct css_background_position *horz,
struct css_background_position *vert)
{
const struct css_node *v = *node;
const struct css_node *w = v->next;
struct css_background_entry *bg = 0, *bg2 = 0;
if (v->type == CSS_NODE_IDENT)
bg = css_background_lookup(v);
if (w && w->type == CSS_NODE_IDENT)
bg2 = css_background_lookup(w);
if (!(w && ((w->type == CSS_NODE_IDENT && bg2) ||
w->type == CSS_NODE_PERCENTAGE ||
w->type == CSS_NODE_DIMENSION))) {
/* only one value specified */
if (v->type == CSS_NODE_IDENT) { if (v->type == CSS_NODE_IDENT) {
if (v->data_length == 7 && if (v->data_length == 7 &&
strncasecmp(v->data, "inherit", 7) strncasecmp(v->data, "inherit", 7)
== 0) { == 0) {
s->background_position.horz.pos = horz->pos = vert->pos =
s->background_position.vert.pos =
CSS_BACKGROUND_POSITION_INHERIT; CSS_BACKGROUND_POSITION_INHERIT;
return; return false;
} }
bg = css_background_lookup(v);
if (!bg) if (!bg)
return; return false;
s->background_position.horz.pos = horz->pos = vert->pos = CSS_BACKGROUND_POSITION_PERCENT;
s->background_position.vert.pos = horz->value.percent = bg->horizontal ? bg->value : 50;
CSS_BACKGROUND_POSITION_PERCENT; vert->value.percent = bg->vertical ? bg->value : 50;
s->background_position.horz.value.percent =
bg->horizontal ? bg->value : 50;
s->background_position.vert.value.percent =
bg->vertical ? bg->value : 50;
} }
else if (v->type == CSS_NODE_PERCENTAGE) { else if (v->type == CSS_NODE_PERCENTAGE) {
s->background_position.horz.pos = horz->pos = vert->pos = CSS_BACKGROUND_POSITION_PERCENT;
s->background_position.vert.pos = horz->value.percent = atof(v->data);
CSS_BACKGROUND_POSITION_PERCENT; vert->value.percent = 50.0;
s->background_position.horz.value.percent =
atof(v->data);
s->background_position.vert.value.percent = 50.0;
} }
else if (v->type == CSS_NODE_DIMENSION) { else if (v->type == CSS_NODE_DIMENSION) {
if (parse_length(&s->background_position.horz.value. if (parse_length(&horz->value.
length, v, false) == 0) { length, v, false) == 0) {
s->background_position.horz.pos = horz->pos = CSS_BACKGROUND_POSITION_LENGTH;
CSS_BACKGROUND_POSITION_LENGTH; vert->pos = CSS_BACKGROUND_POSITION_PERCENT;
s->background_position.vert.pos = vert->value.percent = 50.0;
CSS_BACKGROUND_POSITION_PERCENT;
s->background_position.vert.value.percent =
50.0;
} }
} }
return; *node = w;
return true;
} }
/* two values specified */ /* two values specified */
if (v->type == CSS_NODE_IDENT && w->type == CSS_NODE_IDENT) { if (v->type == CSS_NODE_IDENT && w->type == CSS_NODE_IDENT) {
/* both keywords */ /* both keywords */
bg = css_background_lookup(v);
bg2 = css_background_lookup(w);
if (!bg || !bg2) if (!bg || !bg2)
return; return false;
if ((bg->horizontal && bg2->horizontal) || if ((bg->horizontal && bg2->horizontal) ||
(bg->vertical && bg2->vertical)) (bg->vertical && bg2->vertical))
return; return false;
s->background_position.horz.pos = horz->pos = vert->pos = CSS_BACKGROUND_POSITION_PERCENT;
s->background_position.vert.pos = horz->value.percent = vert->value.percent = 50;
CSS_BACKGROUND_POSITION_PERCENT;
s->background_position.horz.value.percent =
s->background_position.vert.value.percent = 50;
if (bg->horizontal) if (bg->horizontal)
s->background_position.horz.value.percent = bg->value; horz->value.percent = bg->value;
else if (bg2->horizontal) else if (bg2->horizontal)
s->background_position.horz.value.percent = bg2->value; horz->value.percent = bg2->value;
if (bg->vertical) if (bg->vertical)
s->background_position.vert.value.percent = bg->value; vert->value.percent = bg->value;
else if (bg2->vertical) else if (bg2->vertical)
s->background_position.vert.value.percent = bg2->value; vert->value.percent = bg2->value;
return; *node = w->next;
return true;
} }
if (v->type == CSS_NODE_IDENT) { /* horizontal value */ if (v->type == CSS_NODE_IDENT) { /* horizontal value */
bg = css_background_lookup(v);
if (!bg || bg->vertical) if (!bg || bg->vertical)
return; return false;
} }
if (w->type == CSS_NODE_IDENT) { /* vertical value */ if (w->type == CSS_NODE_IDENT) { /* vertical value */
bg2 = css_background_lookup(w);
if (!bg2 || bg2->horizontal) if (!bg2 || bg2->horizontal)
return; return false;
} }
if (v->type == CSS_NODE_IDENT) { /* horizontal value */ if (v->type == CSS_NODE_IDENT) { /* horizontal value */
s->background_position.horz.pos = horz->pos = CSS_BACKGROUND_POSITION_PERCENT;
CSS_BACKGROUND_POSITION_PERCENT; horz->value.percent = bg->value;
s->background_position.horz.value.percent = bg->value;
} else if (v->type == CSS_NODE_PERCENTAGE) { } else if (v->type == CSS_NODE_PERCENTAGE) {
s->background_position.horz.pos = horz->pos = CSS_BACKGROUND_POSITION_PERCENT;
CSS_BACKGROUND_POSITION_PERCENT; horz->value.percent = atof(v->data);
s->background_position.horz.value.percent = atof(v->data);
} else if (v->type == CSS_NODE_DIMENSION) { } else if (v->type == CSS_NODE_DIMENSION) {
if (parse_length(&s->background_position.horz.value.length, if (parse_length(&horz->value.length,
v, false) == 0) v, false) == 0)
s->background_position.horz.pos = horz->pos = CSS_BACKGROUND_POSITION_LENGTH;
CSS_BACKGROUND_POSITION_LENGTH;
} }
if (w->type == CSS_NODE_IDENT) { /* vertical value */ if (w->type == CSS_NODE_IDENT) { /* vertical value */
s->background_position.vert.pos = vert->pos = CSS_BACKGROUND_POSITION_PERCENT;
CSS_BACKGROUND_POSITION_PERCENT; vert->value.percent = bg2->value;
s->background_position.vert.value.percent = bg2->value;
} else if (w->type == CSS_NODE_PERCENTAGE) { } else if (w->type == CSS_NODE_PERCENTAGE) {
s->background_position.vert.pos = vert->pos = CSS_BACKGROUND_POSITION_PERCENT;
CSS_BACKGROUND_POSITION_PERCENT; vert->value.percent = atof(w->data);
s->background_position.vert.value.percent = atof(w->data);
} else if (w->type == CSS_NODE_DIMENSION) { } else if (w->type == CSS_NODE_DIMENSION) {
if (parse_length(&s->background_position.vert.value.length, if (parse_length(&vert->value.length,
w, false) == 0) w, false) == 0)
s->background_position.vert.pos = vert->pos = CSS_BACKGROUND_POSITION_LENGTH;
CSS_BACKGROUND_POSITION_LENGTH;
} }
*node = w->next;
return true;
} }
void parse_background_repeat(struct css_style * const s, const struct css_node * const v) void parse_background_repeat(struct css_style * const s,
const struct css_node * const v)
{ {
css_background_repeat z; css_background_repeat z;
if (v->type != CSS_NODE_IDENT || v->next != 0) if (v->type != CSS_NODE_IDENT || v->next != 0)
@ -826,6 +953,7 @@ void parse_background_repeat(struct css_style * const s, const struct css_node *
s->background_repeat = z; s->background_repeat = z;
} }
void parse_border_width(struct css_style * const s, void parse_border_width(struct css_style * const s,
const struct css_node * const v) const struct css_node * const v)
{ {
@ -1616,3 +1744,4 @@ css_text_decoration css_text_decoration_parse(const char * const s,
return CSS_TEXT_DECORATION_UNKNOWN; return CSS_TEXT_DECORATION_UNKNOWN;
} }
/** \} */

View File

@ -102,11 +102,7 @@ void html_redraw_box(struct content *content, struct box * box,
int padding_left, padding_top; int padding_left, padding_top;
int padding_width, padding_height; int padding_width, padding_height;
int x0, y0, x1, y1; int x0, y0, x1, y1;
int px0, py0, px1, py1;
int colour; int colour;
os_VDU_VAR_LIST(5) vars = { { os_VDUVAR_GWL_COL, os_VDUVAR_GWB_ROW,
os_VDUVAR_GWR_COL, os_VDUVAR_GWT_ROW, -1 } };
os_vdu_var cgw[4];
x += box->x * 2 * scale; x += box->x * 2 * scale;
y -= box->y * 2 * scale; y -= box->y * 2 * scale;
@ -215,38 +211,44 @@ void html_redraw_box(struct content *content, struct box * box,
y1 = clip_y1; y1 = clip_y1;
} }
/* find intersection of clip box and padding box */ /* background colour and image */
px0 = x < x0 ? x0 : x; if (box->style && (box->type != BOX_INLINE ||
py0 = y - padding_height < y0 ? y0 : y - padding_height; box->style != box->parent->parent->style)) {
px1 = x + padding_width < x1 ? x + padding_width : x1; /* find intersection of clip box and padding box */
py1 = y < y1 ? y : y1; int px0 = x < x0 ? x0 : x;
int py0 = y - padding_height < y0 ? y0 : y - padding_height;
int px1 = x + padding_width < x1 ? x + padding_width : x1;
int py1 = y < y1 ? y : y1;
/* background colour */ /* background colour */
if (box->style != 0 && box->style->background_color != TRANSPARENT) { /* optimisation: skip if fully repeated background image */
colourtrans_set_gcol(box->style->background_color << 8, if (box->style->background_color != TRANSPARENT &&
colourtrans_USE_ECFS, os_ACTION_OVERWRITE, 0); (!box->background ||
os_plot(os_MOVE_TO, px0, py0); box->style->background_repeat !=
if (px0 < px1 && py0 < py1) CSS_BACKGROUND_REPEAT_REPEAT)) {
os_plot(os_PLOT_RECTANGLE | os_PLOT_TO, px1, py1); colourtrans_set_gcol(box->style->background_color << 8,
current_background_color = box->style->background_color; colourtrans_USE_ECFS,
os_ACTION_OVERWRITE, 0);
os_plot(os_MOVE_TO, px0, py0);
if (px0 < px1 && py0 < py1)
os_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
px1, py1);
current_background_color = box->style->background_color;
}
if (box->background) {
/* clip to padding box */
html_redraw_clip(px0, py0, px1, py1);
/* plot background image */
html_redraw_background(x, y, width, clip_y1 - clip_y0,
box, scale);
/* restore previous graphics window */
html_redraw_clip(x0, y0, x1, y1);
}
} }
/* read current graphics window dimensions */
xos_read_vdu_variables((os_vdu_var_list const *) &vars, (int*)&cgw);
/* clip to padding box */
html_redraw_clip(px0, py0, px1, py1);
/* plot background image */
/* the if statement below causes regression on acornarcade.com
* but fixes some issues with the CSS testsuite background section */
// if (box->type != BOX_INLINE && box->background)
html_redraw_background(x, y, width, clip_y1-clip_y0, box, scale);
/* restore previous graphics window */
/* should probably take account of the eigvalues here... */
html_redraw_clip(cgw[0]*2, cgw[1]*2, cgw[2]*2, cgw[3]*2);
if (box->object) { if (box->object) {
content_redraw(box->object, x + padding_left, y - padding_top, content_redraw(box->object, x + padding_left, y - padding_top,
width, height, x0, y0, x1, y1, scale); width, height, x0, y0, x1, y1, scale);