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
This commit is contained in:
parent
d0e7a5ecac
commit
1304964f92
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue