From 1304964f92249a1f8e685db89aa694f77307d6ae Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Wed, 27 Apr 2011 13:50:49 +0000 Subject: Reduce number of page reflows and viewport redraws as images are fetched: + Flag known-sized boxes generated by images. + Treat them as replaced all through layout. + Only reflow the document for fetched images if we don't already have the box at the right size. svn path=/trunk/netsurf/; revision=12243 --- render/box.h | 3 ++- render/box_construct.c | 16 ++++++++++++++++ render/html.c | 47 ++++++++++++++++++++++++++++++++++++----------- render/html_redraw.c | 6 ++++-- render/layout.c | 41 +++++++++++++++++++++++++++-------------- 5 files changed, 85 insertions(+), 28 deletions(-) diff --git a/render/box.h b/render/box.h index 0703c6da5..e7c19ad6d 100644 --- a/render/box.h +++ b/render/box.h @@ -126,7 +126,8 @@ typedef enum { MEASURED = 1 << 5, /* text box width has been measured */ HAS_HEIGHT = 1 << 6, /* box has height (perhaps due to children) */ MAKE_HEIGHT = 1 << 7, /* box causes its own height */ - NEED_MIN = 1 << 8 /* minimum width is required for layout */ + NEED_MIN = 1 << 8, /* minimum width is required for layout */ + REPLACE_DIM = 1 << 9 /* replaced element has given dimensions */ } box_flags; /* Sides of a box */ diff --git a/render/box_construct.c b/render/box_construct.c index b47405c12..f780d0714 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -1159,6 +1159,11 @@ bool box_image(BOX_SPECIAL_PARAMS) bool ok; char *s, *url; xmlChar *alt, *src; + enum css_width_e wtype; + enum css_height_e htype; + css_fixed value = 0; + css_unit wunit = CSS_UNIT_PX; + css_unit hunit = CSS_UNIT_PX; if (box->style && css_computed_display(box->style, n->parent == NULL) == CSS_DISPLAY_NONE) @@ -1196,6 +1201,17 @@ bool box_image(BOX_SPECIAL_PARAMS) ok = html_fetch_object(content, url, box, image_types, content->available_width, 1000, false); free(url); + + wtype = css_computed_width(box->style, &value, &wunit); + htype = css_computed_height(box->style, &value, &hunit); + + if (wtype == CSS_WIDTH_SET && wunit != CSS_UNIT_PCT && + htype == CSS_HEIGHT_SET && hunit != CSS_UNIT_PCT) { + /* We know the dimensions the image will be shown at before it's + * fetched. */ + box->flags |= REPLACE_DIM; + } + return ok; } diff --git a/render/html.c b/render/html.c index cde8d79ef..cf9fdea81 100644 --- a/render/html.c +++ b/render/html.c @@ -1415,8 +1415,29 @@ nserror html_object_callback(hlcache_handle *object, break; case CONTENT_MSG_DONE: - html_object_done(box, object, o->background); - c->active--; + + if (box->flags & REPLACE_DIM) { + union content_msg_data data; + + c->active--; + html_object_done(box, object, o->background); + + if (!box_visible(box)) + break; + + box_coords(box, &x, &y); + + data.redraw.x = x + box->padding[LEFT]; + data.redraw.y = y + box->padding[TOP]; + data.redraw.width = box->width; + data.redraw.height = box->height; + data.redraw.full_redraw = true; + + content_broadcast(c, CONTENT_MSG_REDRAW, data); + } else { + c->active--; + html_object_done(box, object, o->background); + } break; case CONTENT_MSG_ERROR: @@ -1500,12 +1521,14 @@ nserror html_object_callback(hlcache_handle *object, /* If 1) the configuration option to reflow pages while objects are * fetched is set * 2) an object is newly fetched & converted, - * 3) the object's parent HTML is ready for reformat, - * 4) the time since the previous reformat is more than the + * 3) the box's dimensions need to change due to being replaced + * 4) the object's parent HTML is ready for reformat, + * 5) the time since the previous reformat is more than the * configured minimum time between reformats * then reformat the page to display newly fetched objects */ else if (option_incremental_reflow && event->type == CONTENT_MSG_DONE && + !(box->flags & REPLACE_DIM) && (c->status == CONTENT_STATUS_READY || c->status == CONTENT_STATUS_DONE) && (wallclock() > c->reformat_time)) { @@ -1532,14 +1555,16 @@ void html_object_done(struct box *box, hlcache_handle *object, box->object = object; - /* invalidate parent min, max widths */ - for (b = box; b; b = b->parent) - b->max_width = UNKNOWN_MAX_WIDTH; + if (!(box->flags & REPLACE_DIM)) { + /* invalidate parent min, max widths */ + for (b = box; b; b = b->parent) + b->max_width = UNKNOWN_MAX_WIDTH; - /* delete any clones of this box */ - while (box->next && (box->next->flags & CLONE)) { - /* box_free_box(box->next); */ - box->next = box->next->next; + /* delete any clones of this box */ + while (box->next && (box->next->flags & CLONE)) { + /* box_free_box(box->next); */ + box->next = box->next->next; + } } } diff --git a/render/html_redraw.c b/render/html_redraw.c index 9ae43bce1..c5d20b26f 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -427,7 +427,8 @@ bool html_redraw_box(struct box *box, int x_parent, int y_parent, if (bg_box && bg_box->type != BOX_BR && bg_box->type != BOX_TEXT && bg_box->type != BOX_INLINE_END && - (bg_box->type != BOX_INLINE || bg_box->object)) { + (bg_box->type != BOX_INLINE || bg_box->object || + box->flags & REPLACE_DIM)) { /* find intersection of clip box and border edge */ struct rect p; p.x0 = x - border_left < r.x0 ? r.x0 : x - border_left; @@ -471,7 +472,8 @@ bool html_redraw_box(struct box *box, int x_parent, int y_parent, /* borders for block level content and replaced inlines */ if (box->style && box->type != BOX_TEXT && box->type != BOX_INLINE_END && - (box->type != BOX_INLINE || box->object) && + (box->type != BOX_INLINE || box->object || + box->flags & REPLACE_DIM) && (border_top || border_right || border_bottom || border_left)) { if (!html_redraw_borders(box, x_parent, y_parent, diff --git a/render/layout.c b/render/layout.c index 2c97ead0a..ca3f84853 100644 --- a/render/layout.c +++ b/render/layout.c @@ -270,6 +270,8 @@ bool layout_block_context(struct box *block, int viewport_height, layout_get_object_dimensions(block, &block->width, &block->height, false, true); return true; + } else if (block->flags & REPLACE_DIM) { + return true; } /* special case if the block contains an radio button or checkbox */ @@ -359,8 +361,9 @@ bool layout_block_context(struct box *block, int viewport_height, * left and right margins to avoid any floats. */ lm = rm = 0; - if (box->type == BOX_BLOCK || box->object) { - if (!box->object && box->style && + if (box->type == BOX_BLOCK || box->object) { + if (!box->object && !(box->flags & REPLACE_DIM) && + box->style && css_computed_overflow(box->style) != CSS_OVERFLOW_VISIBLE) { /* box establishes new block formatting context @@ -1115,7 +1118,8 @@ void layout_block_find_dimensions(int available_width, int viewport_height, &width, &height, &max_width, &min_width, margin, padding, border); - if (box->object && content_get_type(box->object) != CONTENT_HTML) { + if (box->object && !(box->flags & REPLACE_DIM) && + content_get_type(box->object) != CONTENT_HTML) { /* block-level replaced element, see 10.3.4 and 10.6.2 */ layout_get_object_dimensions(box, &width, &height, true, true); @@ -1432,7 +1436,8 @@ void layout_float_find_dimensions(int available_width, padding[RIGHT] += scrollbar_width; padding[BOTTOM] += scrollbar_width; - if (box->object && content_get_type(box->object) != CONTENT_HTML) { + if (box->object && !(box->flags & REPLACE_DIM) && + content_get_type(box->object) != CONTENT_HTML) { /* Floating replaced element, with intrinsic width or height. * See 10.3.6 and 10.6.2 */ layout_get_object_dimensions(box, &width, &height, @@ -2011,7 +2016,8 @@ bool layout_inline_container(struct box *inline_container, int width, whitespace == CSS_WHITE_SPACE_PRE_WRAP); } - if ((!c->object && c->text && (c->length || is_pre)) || + if ((!c->object && !(c->flags & REPLACE_DIM) && c->text && + (c->length || is_pre)) || c->type == BOX_BR) has_text_children = true; } @@ -2363,7 +2369,8 @@ bool layout_line(struct box *first, int *width, int *y, continue; } - if (!b->object && !b->gadget) { + if (!b->object && !b->gadget && + !(b->flags & REPLACE_DIM)) { /* inline non-replaced, 10.3.1 and 10.6.1 */ b->height = line_height(b->style ? b->style : b->parent->parent->style); @@ -2458,7 +2465,7 @@ bool layout_line(struct box *first, int *width, int *y, b->height = AUTO; } - if (b->object) { + if (b->object && !(b->flags & REPLACE_DIM)) { layout_get_object_dimensions(b, &b->width, &b->height, true, true); } else { @@ -2551,7 +2558,7 @@ bool layout_line(struct box *first, int *width, int *y, } space_before = space_after; - if (b->object) + if (b->object || b->flags & REPLACE_DIM) space_after = 0; else if (b->text || b->type == BOX_INLINE_END) { if (b->space == UNKNOWN_WIDTH) { @@ -2705,6 +2712,7 @@ bool layout_line(struct box *first, int *width, int *y, if ((split_box->type == BOX_INLINE || split_box->type == BOX_TEXT) && !split_box->object && + !(split_box->flags & REPLACE_DIM) && !split_box->gadget && split_box->text) { /* skip leading spaces, otherwise code gets fooled into * thinking it's all one long word */ @@ -2858,7 +2866,8 @@ bool layout_line(struct box *first, int *width, int *y, d->y = *y; continue; } else if ((d->type == BOX_INLINE && - ((d->object || d->gadget) == false)) || + ((d->object || d->gadget) == false) && + !(d->flags & REPLACE_DIM)) || d->type == BOX_BR || d->type == BOX_TEXT || d->type == BOX_INLINE_END) { @@ -3012,7 +3021,8 @@ struct box *layout_minmax_line(struct box *first, assert(b->style); font_plot_style_from_css(b->style, &fstyle); - if (b->type == BOX_INLINE && !b->object) { + if (b->type == BOX_INLINE && !b->object && + !(b->flags & REPLACE_DIM)) { fixed = frac = 0; calculate_mbp_width(b->style, LEFT, true, true, true, &fixed, &frac); @@ -3040,7 +3050,8 @@ struct box *layout_minmax_line(struct box *first, continue; } - if (!b->object && !b->gadget) { + if (!b->object && !b->gadget && + !(b->flags & REPLACE_DIM)) { /* inline non-replaced, 10.3.1 and 10.6.1 */ if (!b->text) continue; @@ -3140,9 +3151,11 @@ struct box *layout_minmax_line(struct box *first, height = AUTO; } - if (b->object) { - layout_get_object_dimensions(b, &width, &height, - true, false); + if (b->object || (b->flags & REPLACE_DIM)) { + if (b->object) { + layout_get_object_dimensions(b, &width, &height, + true, false); + } fixed = frac = 0; calculate_mbp_width(b->style, LEFT, true, true, true, -- cgit v1.2.3