diff options
-rwxr-xr-x | atari/plot/font_freetype.c | 5 | ||||
-rw-r--r-- | atari/plot/font_internal.c | 9 | ||||
-rwxr-xr-x | atari/plot/font_vdi.c | 2 | ||||
-rw-r--r-- | beos/font.cpp | 29 | ||||
-rw-r--r-- | framebuffer/font_freetype.c | 24 | ||||
-rw-r--r-- | framebuffer/font_internal.c | 27 | ||||
-rw-r--r-- | gtk/font_pango.c | 34 | ||||
-rw-r--r-- | monkey/font.c | 26 | ||||
-rw-r--r-- | render/font.h | 15 | ||||
-rw-r--r-- | render/layout.c | 99 | ||||
-rw-r--r-- | riscos/font.c | 17 | ||||
-rw-r--r-- | windows/font.c | 8 |
12 files changed, 176 insertions, 119 deletions
diff --git a/atari/plot/font_freetype.c b/atari/plot/font_freetype.c index 8db7cc2c0..ed850bce2 100755 --- a/atari/plot/font_freetype.c +++ b/atari/plot/font_freetype.c @@ -443,8 +443,9 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle, last_space_idx = nxtchr;
}
*actual_x += glyph->advance.x >> 16;
- if (*actual_x > x) {
- /* string has exceeded available width return previous space*/
+ if (*actual_x > x && last_space_idx != 0) {
+ /* string has exceeded available width and we've
+ * found a space; return previous space */
*actual_x = last_space_x;
*char_offset = last_space_idx;
return true;
diff --git a/atari/plot/font_internal.c b/atari/plot/font_internal.c index 3db29eba5..2b0025a71 100644 --- a/atari/plot/font_internal.c +++ b/atari/plot/font_internal.c @@ -118,7 +118,7 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const size_t length,int x, size_t *char_offset, int *actual_x )
{
const struct fb_font_desc* fb_font = fb_get_font(fstyle);
- *char_offset = x / fb_font->width;
+ int c_off = *char_offset = x / fb_font->width;
if (*char_offset > length) {
*char_offset = length;
} else {
@@ -127,6 +127,13 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const break;
(*char_offset)--;
}
+ if (*char_offset == 0) {
+ *char_offset = c_off;
+ while (*char_offset < length &&
+ string[*char_offset] != ' ') {
+ (*char_offset)++;
+ }
+ }
}
*actual_x = *char_offset * fb_font->width;
return( 1 );
diff --git a/atari/plot/font_vdi.c b/atari/plot/font_vdi.c index 4ebab24fb..340759f02 100755 --- a/atari/plot/font_vdi.c +++ b/atari/plot/font_vdi.c @@ -164,7 +164,7 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const last_space_idx = nxtchr;
} *actual_x += cellw; - if (*actual_x > x) { + if (*actual_x > x && last_space_idx != 0) { *actual_x = last_space_x; *char_offset = last_space_idx; //printf("at: %s\n", lstr); diff --git a/beos/font.cpp b/beos/font.cpp index a7b1a0c96..7d04c6857 100644 --- a/beos/font.cpp +++ b/beos/font.cpp @@ -157,17 +157,24 @@ bool nsfont_position_in_string(const plot_font_style_t *fstyle, /** * Find where to split a string to make it fit a width. * - * \param fstyle style for this text - * \param string UTF-8 string to measure - * \param length length of string - * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] - * \param actual_x updated to x coordinate of character closest to x + * \param fstyle style for this text + * \param string UTF-8 string to measure + * \param length length of string, in bytes + * \param x width available + * \param char_offset updated to offset in string of actual_x, [1..length] + * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ bool nsfont_split(const plot_font_style_t *fstyle, @@ -189,13 +196,13 @@ bool nsfont_split(const plot_font_style_t *fstyle, int i; int last_space = 0; font.GetEscapements(string, len, escapements); - // slow but it should work + // very slow but it should work for (i = 0; string[index] && i < len; i++) { if (string[index] == ' ') { last_x = current; last_space = index; } - if (x < current) { + if (x < current && last_space != 0) { *actual_x = (int)last_x; *char_offset = last_space; return true; diff --git a/framebuffer/font_freetype.c b/framebuffer/font_freetype.c index c2279a116..987b101c7 100644 --- a/framebuffer/font_freetype.c +++ b/framebuffer/font_freetype.c @@ -497,15 +497,22 @@ static bool nsfont_position_in_string(const plot_font_style_t *fstyle, * * \param fstyle style for this text * \param string UTF-8 string to measure - * \param length length of string + * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ static bool nsfont_split(const plot_font_style_t *fstyle, @@ -532,10 +539,9 @@ static bool nsfont_split(const plot_font_style_t *fstyle, } *actual_x += glyph->advance.x >> 16; - if (*actual_x > x) { - /* string has exceeded available width return previous - * space - */ + if (*actual_x > x && last_space_idx != 0) { + /* string has exceeded available width and we've + * found a space; return previous space */ *actual_x = last_space_x; *char_offset = last_space_idx; return true; diff --git a/framebuffer/font_internal.c b/framebuffer/font_internal.c index 6535ac4d5..ff2bfa1ef 100644 --- a/framebuffer/font_internal.c +++ b/framebuffer/font_internal.c @@ -121,20 +121,28 @@ static bool nsfont_position_in_string(const plot_font_style_t *fstyle, } + /** * Find where to split a string to make it fit a width. * * \param fstyle style for this text * \param string UTF-8 string to measure - * \param length length of string + * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ static bool nsfont_split(const plot_font_style_t *fstyle, @@ -143,7 +151,7 @@ static bool nsfont_split(const plot_font_style_t *fstyle, { const struct fb_font_desc* fb_font = fb_get_font(fstyle); - *char_offset = x / fb_font->width; + int c_off = *char_offset = x / fb_font->width; if (*char_offset > length) { *char_offset = length; } else { @@ -152,6 +160,13 @@ static bool nsfont_split(const plot_font_style_t *fstyle, break; (*char_offset)--; } + if (*char_offset == 0) { + *char_offset = c_off; + while (*char_offset < length && + string[*char_offset] != ' ') { + (*char_offset)++; + } + } } *actual_x = *char_offset * fb_font->width; return true; diff --git a/gtk/font_pango.c b/gtk/font_pango.c index 00131b416..de115fa64 100644 --- a/gtk/font_pango.c +++ b/gtk/font_pango.c @@ -153,17 +153,24 @@ bool nsfont_position_in_string(const plot_font_style_t *fstyle, /** * Find where to split a string to make it fit a width. * - * \param fstyle plot style for this text - * \param string UTF-8 string to measure - * \param length length of string - * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] - * \param actual_x updated to x coordinate of character closest to x + * \param fstyle style for this text + * \param string UTF-8 string to measure + * \param length length of string, in bytes + * \param x width available + * \param char_offset updated to offset in string of actual_x, [1..length] + * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ bool nsfont_split(const plot_font_style_t *fstyle, @@ -197,15 +204,6 @@ bool nsfont_split(const plot_font_style_t *fstyle, /* Pango split the text. The line's start_index indicates the * start of the character after the line break. */ index = line->start_index; - - /* We must ensure that the split character is a space so that - * we meet the API postcondition. Therefore, scan backwards - * through the string and stop when we hit the start of - * the string or find a space. */ - while (index > 0) { - if (string[--index] == ' ') - break; - } } g_object_unref(layout); diff --git a/monkey/font.c b/monkey/font.c index 759c3e935..7f390a49b 100644 --- a/monkey/font.c +++ b/monkey/font.c @@ -59,23 +59,29 @@ static bool nsfont_position_in_string(const plot_font_style_t *fstyle, * * \param fstyle style for this text * \param string UTF-8 string to measure - * \param length length of string + * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ static bool nsfont_split(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { - - *char_offset = x / (fstyle->size / FONT_SIZE_SCALE); + int c_off = *char_offset = x / (fstyle->size / FONT_SIZE_SCALE); if (*char_offset > length) { *char_offset = length; } else { @@ -84,6 +90,12 @@ static bool nsfont_split(const plot_font_style_t *fstyle, break; (*char_offset)--; } + if (*char_offset == 0) { + *char_offset = c_off; + while (*char_offset < length && string[*char_offset] != ' ') { + (*char_offset)++; + } + } } *actual_x = *char_offset * (fstyle->size / FONT_SIZE_SCALE); return true; diff --git a/render/font.h b/render/font.h index bc7dc7fba..bc8df2335 100644 --- a/render/font.h +++ b/render/font.h @@ -73,13 +73,20 @@ struct font_functions * \param string UTF-8 string to measure * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ bool (*font_split)(const plot_font_style_t *fstyle, const char *string, size_t length, diff --git a/render/layout.c b/render/layout.c index 331e1efdb..3fd50d18d 100644 --- a/render/layout.c +++ b/render/layout.c @@ -2147,20 +2147,21 @@ static bool layout_text_box_split(html_content *content, int space_width = split_box->space; struct box *c2; const struct font_functions *font_func = content->font_func; + bool space = (split_box->text[new_length] == ' '); + int used_length = new_length + (space ? 1 : 0); - if (space_width == 0) { - /* Currently split_box has no space. */ - /* Get the space width because the split_box will need it */ - /* Don't set it in split_box yet, or it will get cloned. */ + if ((space && space_width == 0) || space_width == UNKNOWN_WIDTH) { + /* We're need to add a space, and we don't know how big + * it's to be, OR we have a space of unknown width anyway; + * Calculate space width */ font_func->font_width(fstyle, " ", 1, &space_width); - } else if (space_width == UNKNOWN_WIDTH) { - /* Split_box has a space but its width is unknown. */ - /* Get the space width because the split_box will need it */ - /* Set it in split_box, so it gets cloned. */ - font_func->font_width(fstyle, " ", 1, &space_width); - split_box->space = space_width; } + if (split_box->space == UNKNOWN_WIDTH) + split_box->space = space_width; + if (!space) + space_width = 0; + /* Create clone of split_box, c2 */ c2 = talloc_memdup(content->bctx, split_box, sizeof *c2); if (!c2) @@ -2173,18 +2174,18 @@ static bool layout_text_box_split(html_content *content, /* TODO: Move text inputs to core textarea widget and remove * this */ c2->text = talloc_strndup(content->bctx, - split_box->text + new_length + 1, - split_box->length - (new_length + 1)); + split_box->text + used_length, + split_box->length - used_length); if (!c2->text) return false; } else { - c2->text += new_length + 1; + c2->text += used_length; } /* Set c2 according to the remaining text */ c2->width -= new_width + space_width; c2->flags &= ~MEASURED; /* width has been estimated */ - c2->length = split_box->length - (new_length + 1); + c2->length = split_box->length - used_length; /* Update split_box for its reduced text */ split_box->width = new_width; @@ -2200,7 +2201,14 @@ static bool layout_text_box_split(html_content *content, c2->next->prev = c2; else c2->parent->last = c2; - +#ifdef LAYOUT_DEBUG + LOG(("split_box %p len: %u \"%.*s\"", + split_box, split_box->length, + split_box->length, split_box->text)); + LOG((" new_box %p len: %u \"%.*s\"", + c2, c2->length, + c2->length, c2->text)); +#endif return true; } @@ -2696,8 +2704,7 @@ bool layout_line(struct box *first, int *width, int *y, if (x1 - x0 < x && split_box) { /* the last box went over the end */ - unsigned int i; - size_t space = 0; + size_t split = 0; int w; bool no_wrap = css_computed_white_space( split_box->style) == CSS_WHITE_SPACE_NOWRAP || @@ -2706,56 +2713,45 @@ bool layout_line(struct box *first, int *width, int *y, x = x_previous; - if ((split_box->type == BOX_INLINE || + if (!no_wrap && (split_box->type == BOX_INLINE || split_box->type == BOX_TEXT) && !split_box->object && !(split_box->flags & REPLACE_DIM) && !(split_box->flags & IFRAME) && !split_box->gadget && split_box->text) { - /* skip leading spaces, otherwise code gets fooled into - * thinking it's all one long word */ - for (i = 0; i != split_box->length && - split_box->text[i] == ' '; i++) - ; - /* find end of word */ - for (; i != split_box->length && - split_box->text[i] != ' '; i++) - ; - if (i != split_box->length) - space = i; - } - /* space != 0 implies split_box->text != 0 */ - - if (space == 0 || no_wrap) - w = split_box->width; - else { font_plot_style_from_css(split_box->style, &fstyle); /** \todo handle errors */ - font_func->font_width(&fstyle, split_box->text, - space, &w); + font_func->font_split(&fstyle, + split_box->text, split_box->length, + x1 - x0 - x - space_before, &split, &w); } + /* split == 0 implies that text can't be split */ + + if (split == 0) + w = split_box->width; + #ifdef LAYOUT_DEBUG - LOG(("splitting: split_box %p \"%.*s\", space %zu, w %i, " + LOG(("splitting: split_box %p \"%.*s\", spilt %zu, w %i, " "left %p, right %p, inline_count %u", split_box, (int) split_box->length, - split_box->text, space, w, + split_box->text, split, w, left, right, inline_count)); #endif - if ((space == 0 || x1 - x0 <= x + space_before + w) && + if ((split == 0 || x1 - x0 <= x + space_before + w) && !left && !right && inline_count == 1) { /* first word of box doesn't fit, but no floats and * first box on line so force in */ - if (space == 0 || no_wrap) { + if (split == 0 || split == split_box->length) { /* only one word in this box, or not text * or white-space:nowrap */ b = split_box->next; } else { /* cut off first word for this line */ if (!layout_text_box_split(content, &fstyle, - split_box, space, w)) + split_box, split, w)) return false; b = split_box->next; } @@ -2763,7 +2759,7 @@ bool layout_line(struct box *first, int *width, int *y, #ifdef LAYOUT_DEBUG LOG(("forcing")); #endif - } else if ((space == 0 || x1 - x0 <= x + space_before + w) && + } else if ((split == 0 || x1 - x0 <= x + space_before + w) && inline_count == 1) { /* first word of first box doesn't fit, but a float is * taking some of the width so move below it */ @@ -2790,7 +2786,7 @@ bool layout_line(struct box *first, int *width, int *y, #ifdef LAYOUT_DEBUG LOG(("moving below float")); #endif - } else if (space == 0 || x1 - x0 <= x + space_before + w) { + } else if (split == 0 || x1 - x0 <= x + space_before + w) { /* first word of box doesn't fit so leave box for next * line */ b = split_box; @@ -2799,21 +2795,14 @@ bool layout_line(struct box *first, int *width, int *y, #endif } else { /* fit as many words as possible */ - assert(space != 0); - font_plot_style_from_css(split_box->style, &fstyle); - /** \todo handle errors */ - font_func->font_split(&fstyle, - split_box->text, split_box->length, - x1 - x0 - x - space_before, &space, &w); + assert(split != 0); #ifdef LAYOUT_DEBUG LOG(("'%.*s' %i %zu %i", (int) split_box->length, - split_box->text, x1 - x0, space, w)); + split_box->text, x1 - x0, split, w)); #endif - if (space == 0) - space = 1; - if (space != split_box->length) { + if (split != split_box->length) { if (!layout_text_box_split(content, &fstyle, - split_box, space, w)) + split_box, split, w)) return false; b = split_box->next; } diff --git a/riscos/font.c b/riscos/font.c index 8d4c6d337..b949a570d 100644 --- a/riscos/font.c +++ b/riscos/font.c @@ -319,15 +319,22 @@ bool nsfont_position_in_string(const plot_font_style_t *fstyle, * * \param fstyle style for this text * \param string UTF-8 string to measure - * \param length length of string + * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ bool nsfont_split(const plot_font_style_t *fstyle, diff --git a/windows/font.c b/windows/font.c index 9a5d9ebc6..564a7dec0 100644 --- a/windows/font.c +++ b/windows/font.c @@ -208,14 +208,22 @@ static bool nsfont_split(const plot_font_style_t *style, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { + int c_off; nsfont_position_in_string(style, string, length, x, char_offset, actual_x); + c_off = *char_offset; if (*char_offset == length) { printf("%s %d\n",string, (int)(*char_offset)); return true; } while ((string[*char_offset] != ' ') && (*char_offset > 0)) (*char_offset)--; + if (*char_offset == 0) { + *char_offset = c_off; + while (*char_offset < length && string[*char_offset] != ' ') { + (*char_offset)++; + } + } nsfont_position_in_string(style, string, *char_offset, x, char_offset, actual_x); return true; |