From e3f00b8546f666498633747b8df314c242ef79bc Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 1 Mar 2011 20:00:41 +0000 Subject: Cache space widths. svn path=/trunk/netsurf/; revision=11877 --- desktop/textinput.c | 47 ++++++++++++++++++++++-------------------- render/box.h | 10 +++++---- render/box_construct.c | 7 ++++--- render/html.h | 2 +- render/html_redraw.c | 11 +++------- render/layout.c | 55 +++++++++++++++++++++++++++----------------------- render/textplain.c | 2 +- 7 files changed, 70 insertions(+), 64 deletions(-) diff --git a/desktop/textinput.c b/desktop/textinput.c index 70fdca6c4..be6eb0227 100644 --- a/desktop/textinput.c +++ b/desktop/textinput.c @@ -45,7 +45,6 @@ #include "utils/utf8.h" #include "utils/utils.h" - /** ghost caret used to indicate the insertion point when dragging text into a textarea/input field */ struct caret ghost_caret; @@ -96,6 +95,8 @@ static bool word_right(const char *text, size_t len, size_t *poffset, static bool ensure_caret_visible(struct browser_window *bw, struct box *textarea); +#define SPACE_LEN(b) ((b->space == 0) ? 0 : 1) + /** * Remove the given text caret from the window by invalidating it * and causing its former position to be redrawn. @@ -424,11 +425,11 @@ bool browser_window_textarea_callback(struct browser_window *bw, selection_clear(bw->sel, false); if (end_box != text_box || - char_offset < text_box->length + text_box->space) { + char_offset < text_box->length + SPACE_LEN(text_box)) { /* there's something at the end of the line to delete */ - textarea_cut(bw, text_box, char_offset, - end_box, end_box->length + end_box->space, - false); + textarea_cut(bw, text_box, char_offset, end_box, + end_box->length + SPACE_LEN(end_box), + false); reflow = true; break; } @@ -753,11 +754,11 @@ bool browser_window_textarea_callback(struct browser_window *bw, if (reflow) textarea_reflow(bw, textarea, inline_container); - if (text_box->length + text_box->space <= char_offset) { + if (text_box->length + SPACE_LEN(text_box) <= char_offset) { if (text_box->next && text_box->next->type == BOX_TEXT) { /* the text box has been split when reflowing and the caret is in the second part */ - char_offset -= (text_box->length + text_box->space); + char_offset -= (text_box->length + SPACE_LEN(text_box)); text_box = text_box->next; assert(text_box); assert(char_offset <= text_box->length); @@ -771,7 +772,7 @@ bool browser_window_textarea_callback(struct browser_window *bw, (text_box->next && text_box->next->type == BOX_BR)); - char_offset = text_box->length + text_box->space; + char_offset = text_box->length + SPACE_LEN(text_box); } } @@ -1376,13 +1377,13 @@ bool browser_window_textarea_paste_text(struct browser_window *bw, char_offset = textarea->gadget->caret_box_offset; text_box = textarea->gadget->caret_text_box; - while ((char_offset > text_box->length + text_box->space) && + while ((char_offset > text_box->length + SPACE_LEN(text_box)) && (text_box->next) && (text_box->next->type == BOX_TEXT)) { LOG(("Caret out of range: Was %d in boxlen %d " "space %d", char_offset, - text_box->length, text_box->space)); - char_offset -= text_box->length + text_box->space; + text_box->length, SPACE_LEN(text_box))); + char_offset -= text_box->length + SPACE_LEN(text_box); text_box = text_box->next; } @@ -1716,15 +1717,15 @@ bool textbox_insert(struct browser_window *bw, struct box *text_box, /* insert in text box */ text = talloc_realloc(current_content, text_box->text, char, - text_box->length + text_box->space + utf8_len + 1); + text_box->length + SPACE_LEN(text_box) + utf8_len + 1); if (!text) { warn_user("NoMemory", 0); return false; } text_box->text = text; - if (text_box->space && - char_offset == text_box->length + text_box->space) { + if (text_box->space != 0 && + char_offset == text_box->length + SPACE_LEN(text_box)) { if (hide) text_box->space = 0; else { @@ -1798,18 +1799,18 @@ bool textbox_delete(struct browser_window *bw, struct box *text_box, } /* delete from visible textbox */ - if (next_offset <= text_box->length + text_box->space) { + if (next_offset <= text_box->length + SPACE_LEN(text_box)) { /* handle removal of trailing space */ - if (text_box->space && next_offset > text_box->length) { + if (text_box->space != 0 && next_offset > text_box->length) { if (char_offset > 0) { /* is the trailing character still a space? */ int tmp = utf8_prev(text_box->text, char_offset); if (isspace(text_box->text[tmp])) char_offset = tmp; else - text_box->space = false; + text_box->space = 0; } else { - text_box->space = false; + text_box->space = 0; } text_box->length = char_offset; @@ -1846,7 +1847,7 @@ bool textbox_delete(struct browser_window *bw, struct box *text_box, bool delete_handler(struct browser_window *bw, struct box *b, int offset, size_t length) { - size_t text_length = b->length + b->space; + size_t text_length = b->length + SPACE_LEN(b); /* only remove if its not the first box */ if (offset <= 0 && length >= text_length && b->prev != NULL) { @@ -2053,21 +2054,23 @@ bool textarea_cut(struct browser_window *bw, /* append box text to clipboard and then delete it */ if (clipboard && !gui_add_to_clipboard(box->text + start_idx, - box->length - start_idx, box->space)) { + box->length - start_idx, + SPACE_LEN(box))) { gui_commit_clipboard(); return false; } if (del) { if (!delete_handler(bw, box, start_idx, - (box->length + box->space) - + (box->length + SPACE_LEN(box)) - start_idx) && clipboard) { gui_commit_clipboard(); return false; } } else { textbox_delete(bw, box, start_idx, - (box->length + box->space) - start_idx); + (box->length + SPACE_LEN(box)) - + start_idx); } } diff --git a/render/box.h b/render/box.h index b4151ca3b..e49bfddd7 100644 --- a/render/box.h +++ b/render/box.h @@ -101,6 +101,10 @@ struct object_params; struct object_param; +#define UNKNOWN_WIDTH INT_MAX +#define UNKNOWN_MAX_WIDTH INT_MAX + + /** Type of a struct box. */ typedef enum { BOX_BLOCK, BOX_INLINE_CONTAINER, BOX_INLINE, @@ -187,8 +191,8 @@ struct box { char *text; /**< Text, or 0 if none. Unterminated. */ size_t length; /**< Length of text. */ - /** Text is followed by a space. */ - unsigned int space : 1; + /** Width of space after current text (depends on font and size). */ + int space; /** This box is a continuation of the previous box (eg from line * breaking). */ unsigned int clone : 1; @@ -293,8 +297,6 @@ extern const char *TARGET_TOP; extern const char *TARGET_BLANK; -#define UNKNOWN_WIDTH INT_MAX -#define UNKNOWN_MAX_WIDTH INT_MAX void *box_style_alloc(void *ptr, size_t len, void *pw); struct box * box_create(css_select_results *styles, css_computed_style *style, diff --git a/render/box_construct.c b/render/box_construct.c index 6f91629fd..092edb3ba 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -718,7 +718,8 @@ bool box_construct_text(xmlNode *n, struct content *content, assert((*inline_container)->last != 0); - (*inline_container)->last->space = 1; + (*inline_container)->last->space = + UNKNOWN_WIDTH; } free(text); @@ -759,7 +760,7 @@ bool box_construct_text(xmlNode *n, struct content *content, /* strip ending space char off */ if (box->length > 1 && box->text[box->length - 1] == ' ') { - box->space = 1; + box->space = UNKNOWN_WIDTH; box->length--; } @@ -797,7 +798,7 @@ bool box_construct_text(xmlNode *n, struct content *content, memmove(box->text, &box->text[1], box->length); if (box->prev != NULL) - box->prev->space = 1; + box->prev->space = UNKNOWN_WIDTH; } } else { diff --git a/render/html.h b/render/html.h index ee2f041bf..c06252a4f 100644 --- a/render/html.h +++ b/render/html.h @@ -225,7 +225,7 @@ size_t html_selection_drag_end(struct hlcache_handle *h, browser_mouse_state mouse, int x, int y, int dir); bool text_redraw(const char *utf8_text, size_t utf8_len, - size_t offset, bool space, + size_t offset, int space, const plot_font_style_t *fstyle, int x, int y, const struct rect *clip, diff --git a/render/html_redraw.c b/render/html_redraw.c index 428289efc..75dcf18aa 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -820,7 +820,7 @@ bool html_redraw_text_box(struct box *box, int x, int y, * \param utf8_text pointer to UTF-8 text string * \param utf8_len length of string, in bytes * \param offset byte offset within textual representation - * \param space indicates whether string is followed by a space + * \param space width of space that follows string (0 = no space) * \param fstyle text style to use * \param x x ordinate at which to plot text * \param y y ordinate at which to plot text @@ -832,7 +832,7 @@ bool html_redraw_text_box(struct box *box, int x, int y, */ bool text_redraw(const char *utf8_text, size_t utf8_len, - size_t offset, bool space, const plot_font_style_t *fstyle, + size_t offset, int space, const plot_font_style_t *fstyle, int x, int y, const struct rect *clip, int height, float scale, bool excluded) { @@ -891,12 +891,7 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, /* is there a trailing space that should be highlighted * as well? */ if (end_idx > utf8_len) { - int spc_width; - /* \todo is there a more elegant/efficient - * solution? */ - if (nsfont.font_width(fstyle, " ", 1, - &spc_width)) - endx += spc_width; + endx += space; } if (scale != 1.0) { diff --git a/render/layout.c b/render/layout.c index 0a6292e82..3fc94f0c6 100644 --- a/render/layout.c +++ b/render/layout.c @@ -1922,6 +1922,11 @@ static bool layout_text_box_split(struct content *content, struct box *c2; const struct font_functions *font_func = content->data.html.font_func; + if (split_box->space == 0 || split_box->space == UNKNOWN_WIDTH) { + font_func->font_width(fstyle, " ", 1, &split_box->space); + } + space_width = split_box->space; + /* Create clone of split_box, c2 */ c2 = talloc_memdup(content, split_box, sizeof *c2); if (!c2) @@ -1935,14 +1940,12 @@ static bool layout_text_box_split(struct content *content, return false; /* Set c2 according to the remaining text */ - font_func->font_width(fstyle, " ", 1, &space_width); c2->width -= new_width + space_width; c2->length = split_box->length - (new_length + 1); /* Update split_box for its reduced text */ split_box->length = new_length; split_box->width = new_width; - split_box->space = 1; /* Insert c2 into box list */ c2->next = split_box->next; @@ -2100,13 +2103,13 @@ bool layout_line(struct box *first, int *width, int *y, } } else if (b->type == BOX_INLINE_END) { b->width = 0; - if (b->space) { - /** \todo optimize out */ + if (b->space == UNKNOWN_WIDTH) { font_func->font_width(&fstyle, " ", 1, - &space_after); - } else { - space_after = 0; + &b->space); + /** \todo handle errors */ } + space_after = b->space; + x += b->padding[RIGHT] + b->border[RIGHT].width + b->margin[RIGHT]; continue; @@ -2153,18 +2156,17 @@ bool layout_line(struct box *first, int *width, int *y, b->width += SCROLLBAR_WIDTH; } else { font_func->font_width(&fstyle, b->text, - b->length, &b->width); + b->length, &b->width); } } x += b->width; - if (b->space) - /** \todo optimize out */ + if (b->space == UNKNOWN_WIDTH) { font_func->font_width(&fstyle, " ", 1, - &space_after); - else - space_after = 0; - + &b->space); + /** \todo handle errors */ + } + space_after = b->space; continue; } @@ -2285,16 +2287,17 @@ bool layout_line(struct box *first, int *width, int *y, if (b->object) space_after = 0; else if (b->text || b->type == BOX_INLINE_END) { - space_after = 0; - if (b->space) { + if (b->space == UNKNOWN_WIDTH) { font_plot_style_from_css(b->style, &fstyle); - /** \todo handle errors, optimize */ + /** \todo handle errors */ font_func->font_width(&fstyle, " ", 1, - &space_after); + &b->space); } - } else + space_after = b->space; + } else { space_after = 0; + } split_box = b; move_y = true; inline_count++; @@ -2726,9 +2729,10 @@ struct box *layout_minmax_line(struct box *first, &fixed, &frac); if (0 < fixed) max += fixed; - if (b->next && b->space) { - font_func->font_width(&fstyle, " ", 1, &width); - max += width; + if (b->next && b->space == UNKNOWN_WIDTH) { + font_func->font_width(&fstyle, " ", 1, + &b->space); + max += b->space; } continue; } @@ -2772,9 +2776,10 @@ struct box *layout_minmax_line(struct box *first, } } max += b->width; - if (b->next && b->space) { - font_func->font_width(&fstyle, " ", 1, &width); - max += width; + if (b->next && b->space == UNKNOWN_WIDTH) { + font_func->font_width(&fstyle, " ", 1, + &b->space); + max += b->space; } /* min = widest word */ diff --git a/render/textplain.c b/render/textplain.c index 0879841fe..3a3ffd184 100644 --- a/render/textplain.c +++ b/render/textplain.c @@ -612,7 +612,7 @@ bool textplain_redraw(struct content *c, int x, int y, next_offset = utf8_next(text, length, next_offset); if (!text_redraw(text + offset, next_offset - offset, - line[lineno].start + offset, false, + line[lineno].start + offset, 0, &textplain_style, tx, y + (lineno * scaled_line_height), clip, line_height, scale, false)) -- cgit v1.2.3