diff options
author | John Mark Bell <jmb@netsurf-browser.org> | 2007-09-17 14:53:02 +0000 |
---|---|---|
committer | John Mark Bell <jmb@netsurf-browser.org> | 2007-09-17 14:53:02 +0000 |
commit | ada0a418718dd2ee2f5a9b8a960eb350df625c53 (patch) | |
tree | dadf675030178499af7dfc8fe15db9a05042bc50 /render/html_redraw.c | |
parent | f025f23c52e884bfd0b87078a22670c7a53f8177 (diff) | |
download | netsurf-ada0a418718dd2ee2f5a9b8a960eb350df625c53.tar.gz netsurf-ada0a418718dd2ee2f5a9b8a960eb350df625c53.tar.bz2 |
Fix handling of backgrounds on <body> and <html>
svn path=/trunk/netsurf/; revision=3545
Diffstat (limited to 'render/html_redraw.c')
-rw-r--r-- | render/html_redraw.c | 164 |
1 files changed, 119 insertions, 45 deletions
diff --git a/render/html_redraw.c b/render/html_redraw.c index 8b1a73c0a..70d33f704 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -69,7 +69,7 @@ static bool html_redraw_file(int x, int y, int width, int height, struct box *box, float scale, colour background_colour); static bool html_redraw_background(int x, int y, struct box *box, float scale, int clip_x0, int clip_y0, int clip_x1, int clip_y1, - colour *background_colour); + colour *background_colour, struct box *background); static bool html_redraw_text_decoration(struct box *box, int x_parent, int y_parent, float scale, colour background_colour); @@ -159,6 +159,7 @@ bool html_redraw_box(struct box *box, int padding_left, padding_top, padding_width, padding_height; int x0, y0, x1, y1; int x_scrolled, y_scrolled; + struct box *bg_box = NULL; /* avoid trivial FP maths */ if (scale == 1.0) { @@ -273,10 +274,64 @@ bool html_redraw_box(struct box *box, } /* background colour and image */ - if ((box->style && box->type != BOX_BR && (box->type != BOX_INLINE || - box->style != box->parent->parent->style)) && - ((box->style->background_color != TRANSPARENT) || - (box->background))) { + + /* Thanks to backwards compatibility, CSS defines the following: + * + * + If the box is for the root element and it has a background, + * use that (and then process the body box with no special case) + * + If the box is for the root element and it has no background, + * then use the background (if any) from the body element as if + * it were specified on the root. Then, when the box for the body + * element is processed, ignore the background. + * + For any other box, just use its own styling. + */ + if (!box->parent) { + /* Root box */ + if (box->style && + (box->style->background_color != TRANSPARENT || + box->background)) { + /* With its own background */ + bg_box = box; + } else if (!box->style || + (box->style->background_color == TRANSPARENT && + !box->background)) { + /* Without its own background */ + if (box->children && box->children->style && + (box->children->style->background_color != + TRANSPARENT || + box->children->background)) { + /* But body has one, so use that */ + bg_box = box->children; + } + } + } else if (box->parent && !box->parent->parent) { + /* Body box */ + if (box->style && + (box->style->background_color != TRANSPARENT || + box->background)) { + /* With a background */ + if (box->parent->style && + (box->parent->style->background_color != + TRANSPARENT || + box->parent->background)) { + /* Root has own background; process normally */ + bg_box = box; + } + } + } else { + /* Any other box */ + bg_box = box; + } + + /* bg_box == NULL implies that this box should not have + * its background rendered. Otherwise filter out linebreaks, + * optimize away non-differing inlines and ensure the bg_box + * has something worth rendering */ + if (bg_box && (bg_box->style && bg_box->type != BOX_BR && + (bg_box->type != BOX_INLINE || + bg_box->style != bg_box->parent->parent->style)) && + ((bg_box->style->background_color != TRANSPARENT) || + (bg_box->background))) { /* find intersection of clip box and padding box */ int px0 = x < x0 ? x0 : x; int py0 = y < y0 ? y0 : y; @@ -288,7 +343,7 @@ bool html_redraw_box(struct box *box, /* plot background */ if (!html_redraw_background(x, y, box, scale, px0, py0, px1, py1, - ¤t_background_color)) + ¤t_background_color, bg_box)) return false; /* restore previous graphics window */ if (!plot.clip(x0, y0, x1, y1)) @@ -1095,12 +1150,17 @@ bool html_redraw_file(int x, int y, int width, int height, * \param box box to draw background image of * \param scale scale for redraw * \param background_colour current background colour + * \param background box containing background details (usually ::box) * \return true if successful, false otherwise + * + * The reason for the presence of ::background is the backwards compatibility + * mess that is backgrounds on <body>. The background will be drawn relative + * to ::box, using the background information contained within ::background. */ bool html_redraw_background(int x, int y, struct box *box, float scale, int clip_x0, int clip_y0, int clip_x1, int clip_y1, - colour *background_colour) + colour *background_colour, struct box *background) { bool repeat_x = false; bool repeat_y = false; @@ -1112,16 +1172,18 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, int ox = x, oy = y; struct box *parent; - plot_content = (box->background != NULL); + plot_content = (background->background != NULL); + if (plot_content) { /* handle background-repeat */ - switch (box->style->background_repeat) { + switch (background->style->background_repeat) { case CSS_BACKGROUND_REPEAT_REPEAT: repeat_x = repeat_y = true; - /* optimisation: only plot the colour if bitmap is not opaque */ - if (box->background->bitmap) + /* optimisation: only plot the colour if + * bitmap is not opaque */ + if (background->background->bitmap) plot_colour = !bitmap_get_opaque( - box->background->bitmap); + background->background->bitmap); break; case CSS_BACKGROUND_REPEAT_REPEAT_X: repeat_x = true; @@ -1136,47 +1198,53 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, } /* handle background-position */ - switch (box->style->background_position.horz.pos) { + switch (background->style->background_position.horz.pos) { case CSS_BACKGROUND_POSITION_PERCENT: x += (box->padding[LEFT] + box->width + - box->padding[RIGHT] - - box->background->width) * scale * - box->style->background_position.horz. - value.percent / 100; + box->padding[RIGHT] - + background->background->width) * scale * + background->style->background_position. + horz.value.percent / 100; break; case CSS_BACKGROUND_POSITION_LENGTH: - x += (int) (css_len2px(&box->style->background_position. - horz.value.length, box->style) * scale); + x += (int) (css_len2px(&background->style-> + background_position.horz.value.length, + background->style) * scale); break; default: break; } - switch (box->style->background_position.vert.pos) { + switch (background->style->background_position.vert.pos) { case CSS_BACKGROUND_POSITION_PERCENT: y += (box->padding[TOP] + box->height + - box->padding[BOTTOM] - - box->background->height) * scale * - box->style->background_position.vert. - value.percent / 100; + box->padding[BOTTOM] - + background->background->height) * scale * + background->style->background_position. + vert.value.percent / 100; break; case CSS_BACKGROUND_POSITION_LENGTH: - y += (int) (css_len2px(&box->style->background_position. - vert.value.length, box->style) * scale); + y += (int) (css_len2px(&background->style-> + background_position.vert.value.length, + background->style) * scale); break; default: break; } } - /* special case for table rows as their background needs to be clipped to - * all the cells */ + /* special case for table rows as their background needs + * to be clipped to all the cells */ if (box->type == BOX_TABLE_ROW) { - for (parent = box->parent; ((parent) && (parent->type != BOX_TABLE)); + for (parent = box->parent; + ((parent) && (parent->type != BOX_TABLE)); parent = parent->parent); assert(parent && (parent->style)); - clip_to_children = (parent->style->border_spacing.horz.value > 0) || - (parent->style->border_spacing.vert.value > 0); + + clip_to_children = + (parent->style->border_spacing.horz.value > 0) || + (parent->style->border_spacing.vert.value > 0); + if (clip_to_children) clip_box = box->children; } @@ -1190,9 +1258,12 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, clip_x0 = ox + (clip_box->x * scale); clip_y0 = oy + (clip_box->y * scale); clip_x1 = clip_x0 + (clip_box->padding[LEFT] + - clip_box->width + clip_box->padding[RIGHT]) * scale; + clip_box->width + + clip_box->padding[RIGHT]) * scale; clip_y1 = clip_y0 + (clip_box->padding[TOP] + - clip_box->height + clip_box->padding[BOTTOM]) * scale; + clip_box->height + + clip_box->padding[BOTTOM]) * scale; + if (clip_x0 < px0) clip_x0 = px0; if (clip_y0 < py0) clip_y0 = py0; if (clip_x1 > px1) clip_x1 = px1; @@ -1200,31 +1271,34 @@ bool html_redraw_background(int x, int y, struct box *box, float scale, /* <td> attributes override <tr> */ if ((clip_x0 >= clip_x1) || (clip_y0 >= clip_y1) || - (clip_box->style->background_color != TRANSPARENT) || + (clip_box->style->background_color != + TRANSPARENT) || (clip_box->background && clip_box->background->bitmap && - bitmap_get_opaque(clip_box->background->bitmap))) + bitmap_get_opaque( + clip_box->background->bitmap))) continue; } /* plot the background colour */ - if (box->style->background_color != TRANSPARENT) { - *background_colour = box->style->background_color; + if (background->style->background_color != TRANSPARENT) { + *background_colour = + background->style->background_color; if (plot_colour) - if (!plot.fill(clip_x0, clip_y0, clip_x1, clip_y1, - *background_colour)) + if (!plot.fill(clip_x0, clip_y0, + clip_x1, clip_y1, *background_colour)) return false; } /* and plot the image */ if (plot_content) { if (!plot.clip(clip_x0, clip_y0, clip_x1, clip_y1)) return false; - if (!content_redraw_tiled(box->background, x, y, - ceilf(box->background->width * scale), - ceilf(box->background->height * scale), - clip_x0, clip_y0, clip_x1, clip_y1, scale, - *background_colour, - repeat_x, repeat_y)) + if (!content_redraw_tiled(background->background, x, y, + ceilf(background->background->width * scale), + ceilf(background->background->height * scale), + clip_x0, clip_y0, clip_x1, clip_y1, scale, + *background_colour, + repeat_x, repeat_y)) return false; } |