Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/f081ffb7e8f9533cc74bacc7e836a79ae9b0808d
...commit
http://git.netsurf-browser.org/netsurf.git/commit/f081ffb7e8f9533cc74bacc7e836a79ae9b0808d
...tree
http://git.netsurf-browser.org/netsurf.git/tree/f081ffb7e8f9533cc74bacc7e836a79ae9b0808d
The branch, master has been updated
via f081ffb7e8f9533cc74bacc7e836a79ae9b0808d (commit)
from 4c68def4321911e417a98deb1d394fb96e42100f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=f081ffb7e8f9533cc74bacc7e836a79ae9b0808d
commit f081ffb7e8f9533cc74bacc7e836a79ae9b0808d
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
fix win32 font measurement of non ascii strings.
This greatly improves line breaking and font measurement in the
windows frontend.
diff --git a/frontends/windows/font.c b/frontends/windows/font.c
index 7389bd8..3e81a80 100644
--- a/frontends/windows/font.c
+++ b/frontends/windows/font.c
@@ -93,23 +93,31 @@ HFONT get_font(const plot_font_style_t *style)
{
char *face = NULL;
DWORD family;
+ int nHeight;
+ HDC hdc;
+ HFONT font;
+
switch(style->family) {
case PLOT_FONT_FAMILY_SERIF:
face = strdup(nsoption_charp(font_serif));
family = FF_ROMAN | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_MONOSPACE:
face = strdup(nsoption_charp(font_mono));
family = FF_MODERN | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_CURSIVE:
face = strdup(nsoption_charp(font_cursive));
family = FF_SCRIPT | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_FANTASY:
face = strdup(nsoption_charp(font_fantasy));
family = FF_DECORATIVE | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_SANS_SERIF:
default:
face = strdup(nsoption_charp(font_sans));
@@ -117,30 +125,30 @@ HFONT get_font(const plot_font_style_t *style)
break;
}
- int nHeight = -10;
+ nHeight = -10;
- HDC hdc = GetDC(font_hwnd);
+ hdc = GetDC(font_hwnd);
nHeight = -MulDiv(style->size, GetDeviceCaps(hdc, LOGPIXELSY), 72 *
PLOT_STYLE_SCALE);
ReleaseDC(font_hwnd, hdc);
- HFONT font = CreateFont(
- nHeight, /* height */
- 0, /* width */
- 0, /* escapement*/
- 0, /* orientation */
- style->weight,
- (style->flags & FONTF_ITALIC) ? TRUE : FALSE,
- FALSE, /* underline */
- FALSE, /* strike */
- DEFAULT_CHARSET, /* for locale */
- OUT_DEFAULT_PRECIS, /* general 'best match' */
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- family,
- face /* name of font face */
- );
- if (face != NULL)
+ font = CreateFont(nHeight, /* height */
+ 0, /* width */
+ 0, /* escapement*/
+ 0, /* orientation */
+ style->weight,
+ (style->flags & FONTF_ITALIC) ? TRUE : FALSE,
+ FALSE, /* underline */
+ FALSE, /* strike */
+ DEFAULT_CHARSET, /* for locale */
+ OUT_DEFAULT_PRECIS, /* general 'best match' */
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ family,
+ face); /* name of font face */
+
+ if (face != NULL) {
free(face);
+ }
if (font == NULL) {
if (style->family == PLOT_FONT_FAMILY_MONOSPACE) {
@@ -149,50 +157,67 @@ HFONT get_font(const plot_font_style_t *style)
font = (HFONT) GetStockObject(ANSI_VAR_FONT);
}
}
- if (font == NULL)
+
+ if (font == NULL) {
font = (HFONT) GetStockObject(SYSTEM_FONT);
+ }
+
return font;
}
+/* size of temporary wide character string for computing string width */
+#define WSTRLEN 4096
+
/**
* Measure the width of a string.
*
* \param[in] style plot style for this text
- * \param[in] string UTF-8 string to measure
- * \param[in] length length of string, in bytes
+ * \param[in] utf8str string encoded in UTF-8 to measure
+ * \param[in] utf8len length of string, in bytes
* \param[out] width updated to width of string[0..length)
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
win32_font_width(const plot_font_style_t *style,
- const char *string,
- size_t length,
+ const char *utf8str,
+ size_t utf8len,
int *width)
{
+ nserror ret = NSERROR_OK;
HDC hdc;
HFONT font;
HFONT fontbak;
- SIZE s;
- nserror ret = NSERROR_OK;
+ SIZE sizl; /* size in logical units */
+ BOOL wres;
+ int wclen; /* wide char length */
+ static WCHAR wstr[WSTRLEN]; /* temporary wide char string */
- if (length == 0) {
+ if (utf8len == 0) {
*width = 0;
- } else {
- hdc = GetDC(NULL);
- font = get_font(style);
- fontbak = SelectObject(hdc, font);
+ return ret;
+ }
- /* may well need to convert utf-8 to lpctstr */
- if (GetTextExtentPoint32A(hdc, string, length, &s) != 0) {
- *width = s.cx;
+ hdc = GetDC(NULL);
+ font = get_font(style);
+ fontbak = SelectObject(hdc, font);
+
+ wclen = MultiByteToWideChar(CP_UTF8, 0, utf8str, utf8len, wstr,
WSTRLEN);
+ if (wclen != 0) {
+ wres = GetTextExtentPoint32W(hdc, wstr, wclen, &sizl);
+ if (wres == FALSE) {
+ ret = NSERROR_INVALID;
} else {
- ret = NSERROR_UNKNOWN;
+ *width = sizl.cx;
}
- font = SelectObject(hdc, fontbak);
- DeleteObject(font);
- ReleaseDC(NULL, hdc);
+ } else {
+ ret = NSERROR_NOSPACE;
}
+
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+
return ret;
}
@@ -200,19 +225,19 @@ win32_font_width(const plot_font_style_t *style,
/**
* Find the position in a string where an x coordinate falls.
*
- * \param style css_style for this text, with style->font_size.size ==
+ * \param style css_style for this text, with style->font_size.size ==
* CSS_FONT_SIZE_LENGTH
- * \param string UTF-8 string to measure
- * \param length length of string
- * \param x x coordinate to search for
- * \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 utf8str string to measure encoded in UTF-8
+ * \param utf8len length of string
+ * \param x coordinate to search for
+ * \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
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
win32_font_position(const plot_font_style_t *style,
- const char *string,
- size_t length,
+ const char *utf8str,
+ size_t utf8len,
int x,
size_t *char_offset,
int *actual_x)
@@ -224,26 +249,29 @@ win32_font_position(const plot_font_style_t *style,
int offset;
nserror ret = NSERROR_OK;
- if ((length == 0) || (x < 1)) {
+ /* deal with zero length input or invalid search co-ordiate */
+ if ((utf8len == 0) || (x < 1)) {
*char_offset = 0;
*actual_x = 0;
+ return ret;
+ }
+
+ hdc = GetDC(NULL);
+ font = get_font(style);
+ fontbak = SelectObject(hdc, font);
+
+ if ((GetTextExtentExPointA(hdc, utf8str, utf8len, x, &offset, NULL, &s)
!= 0) &&
+ (GetTextExtentPoint32A(hdc, utf8str, offset, &s) != 0)) {
+ *char_offset = (size_t)offset;
+ *actual_x = s.cx;
} else {
- hdc = GetDC(NULL);
- font = get_font(style);
- fontbak = SelectObject(hdc, font);
-
- if ((GetTextExtentExPointA(hdc, string, length, x, &offset,
NULL,&s) != 0) &&
- (GetTextExtentPoint32A(hdc, string, offset, &s) != 0)) {
- *char_offset = (size_t)offset;
- *actual_x = s.cx;
- } else {
- ret = NSERROR_UNKNOWN;
- }
- font = SelectObject(hdc, fontbak);
- DeleteObject(font);
- ReleaseDC(NULL, hdc);
+ ret = NSERROR_UNKNOWN;
}
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+
return ret;
}
@@ -256,7 +284,7 @@ win32_font_position(const plot_font_style_t *style,
* \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[out] offset updated to offset in string of actual_x, [0..length]
* \param actual_x updated to x coordinate of character closest to x
* \return NSERROR_OK on success otherwise appropriate error code
*
@@ -269,52 +297,48 @@ win32_font_split(const plot_font_style_t *style,
const char *string,
size_t length,
int x,
- size_t *char_offset,
+ size_t *offset,
int *actual_x)
{
+ nserror res;
int c_off;
- nserror ret = NSERROR_UNKNOWN;
-
- if (win32_font_position(style,
- string,
- length,
- x,
- char_offset,
- actual_x) == NSERROR_OK) {
- c_off = *char_offset;
- if (*char_offset == length) {
- ret = NSERROR_OK;
- } else {
- bool success;
- 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)++;
- }
- }
-
- success = win32_font_width(style,
- string,
- *char_offset,
- actual_x);
- if (success) {
- ret = NSERROR_OK;
- }
+
+ /* get the offset into teh string on the proposed position */
+ res = win32_font_position(style, string, length, x, offset, actual_x);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* return the whole string fits in the proposed length */
+ if (*offset == length) {
+ return NSERROR_OK;
+ }
+
+ c_off = *offset;
+
+ /* walk backwards through string looking for space to break on */
+ while ((string[*offset] != ' ') &&
+ (*offset > 0)) {
+ (*offset)--;
+ }
+
+ /* walk forwards through string looking for space if back failed */
+ if (*offset == 0) {
+ *offset = c_off;
+ while ((*offset < length) &&
+ (string[*offset] != ' ')) {
+ (*offset)++;
}
}
+ /* find the actual string width of the break */
+ res = win32_font_width(style, string, *offset, actual_x);
NSLOG(netsurf, DEEPDEBUG,
"ret %d Split %u chars at %ipx: Split at char %i (%ipx) - %.*s",
- ret, length, x, *char_offset, *actual_x, *char_offset, string);
+ res, length, x, *offset, *actual_x, *offset, string);
- return ret;
+ return res;
}
-----------------------------------------------------------------------
Summary of changes:
frontends/windows/font.c | 220 +++++++++++++++++++++++++---------------------
1 file changed, 122 insertions(+), 98 deletions(-)
diff --git a/frontends/windows/font.c b/frontends/windows/font.c
index 7389bd8..3e81a80 100644
--- a/frontends/windows/font.c
+++ b/frontends/windows/font.c
@@ -93,23 +93,31 @@ HFONT get_font(const plot_font_style_t *style)
{
char *face = NULL;
DWORD family;
+ int nHeight;
+ HDC hdc;
+ HFONT font;
+
switch(style->family) {
case PLOT_FONT_FAMILY_SERIF:
face = strdup(nsoption_charp(font_serif));
family = FF_ROMAN | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_MONOSPACE:
face = strdup(nsoption_charp(font_mono));
family = FF_MODERN | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_CURSIVE:
face = strdup(nsoption_charp(font_cursive));
family = FF_SCRIPT | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_FANTASY:
face = strdup(nsoption_charp(font_fantasy));
family = FF_DECORATIVE | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_SANS_SERIF:
default:
face = strdup(nsoption_charp(font_sans));
@@ -117,30 +125,30 @@ HFONT get_font(const plot_font_style_t *style)
break;
}
- int nHeight = -10;
+ nHeight = -10;
- HDC hdc = GetDC(font_hwnd);
+ hdc = GetDC(font_hwnd);
nHeight = -MulDiv(style->size, GetDeviceCaps(hdc, LOGPIXELSY), 72 *
PLOT_STYLE_SCALE);
ReleaseDC(font_hwnd, hdc);
- HFONT font = CreateFont(
- nHeight, /* height */
- 0, /* width */
- 0, /* escapement*/
- 0, /* orientation */
- style->weight,
- (style->flags & FONTF_ITALIC) ? TRUE : FALSE,
- FALSE, /* underline */
- FALSE, /* strike */
- DEFAULT_CHARSET, /* for locale */
- OUT_DEFAULT_PRECIS, /* general 'best match' */
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- family,
- face /* name of font face */
- );
- if (face != NULL)
+ font = CreateFont(nHeight, /* height */
+ 0, /* width */
+ 0, /* escapement*/
+ 0, /* orientation */
+ style->weight,
+ (style->flags & FONTF_ITALIC) ? TRUE : FALSE,
+ FALSE, /* underline */
+ FALSE, /* strike */
+ DEFAULT_CHARSET, /* for locale */
+ OUT_DEFAULT_PRECIS, /* general 'best match' */
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ family,
+ face); /* name of font face */
+
+ if (face != NULL) {
free(face);
+ }
if (font == NULL) {
if (style->family == PLOT_FONT_FAMILY_MONOSPACE) {
@@ -149,50 +157,67 @@ HFONT get_font(const plot_font_style_t *style)
font = (HFONT) GetStockObject(ANSI_VAR_FONT);
}
}
- if (font == NULL)
+
+ if (font == NULL) {
font = (HFONT) GetStockObject(SYSTEM_FONT);
+ }
+
return font;
}
+/* size of temporary wide character string for computing string width */
+#define WSTRLEN 4096
+
/**
* Measure the width of a string.
*
* \param[in] style plot style for this text
- * \param[in] string UTF-8 string to measure
- * \param[in] length length of string, in bytes
+ * \param[in] utf8str string encoded in UTF-8 to measure
+ * \param[in] utf8len length of string, in bytes
* \param[out] width updated to width of string[0..length)
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
win32_font_width(const plot_font_style_t *style,
- const char *string,
- size_t length,
+ const char *utf8str,
+ size_t utf8len,
int *width)
{
+ nserror ret = NSERROR_OK;
HDC hdc;
HFONT font;
HFONT fontbak;
- SIZE s;
- nserror ret = NSERROR_OK;
+ SIZE sizl; /* size in logical units */
+ BOOL wres;
+ int wclen; /* wide char length */
+ static WCHAR wstr[WSTRLEN]; /* temporary wide char string */
- if (length == 0) {
+ if (utf8len == 0) {
*width = 0;
- } else {
- hdc = GetDC(NULL);
- font = get_font(style);
- fontbak = SelectObject(hdc, font);
+ return ret;
+ }
- /* may well need to convert utf-8 to lpctstr */
- if (GetTextExtentPoint32A(hdc, string, length, &s) != 0) {
- *width = s.cx;
+ hdc = GetDC(NULL);
+ font = get_font(style);
+ fontbak = SelectObject(hdc, font);
+
+ wclen = MultiByteToWideChar(CP_UTF8, 0, utf8str, utf8len, wstr,
WSTRLEN);
+ if (wclen != 0) {
+ wres = GetTextExtentPoint32W(hdc, wstr, wclen, &sizl);
+ if (wres == FALSE) {
+ ret = NSERROR_INVALID;
} else {
- ret = NSERROR_UNKNOWN;
+ *width = sizl.cx;
}
- font = SelectObject(hdc, fontbak);
- DeleteObject(font);
- ReleaseDC(NULL, hdc);
+ } else {
+ ret = NSERROR_NOSPACE;
}
+
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+
return ret;
}
@@ -200,19 +225,19 @@ win32_font_width(const plot_font_style_t *style,
/**
* Find the position in a string where an x coordinate falls.
*
- * \param style css_style for this text, with style->font_size.size ==
+ * \param style css_style for this text, with style->font_size.size ==
* CSS_FONT_SIZE_LENGTH
- * \param string UTF-8 string to measure
- * \param length length of string
- * \param x x coordinate to search for
- * \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 utf8str string to measure encoded in UTF-8
+ * \param utf8len length of string
+ * \param x coordinate to search for
+ * \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
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
win32_font_position(const plot_font_style_t *style,
- const char *string,
- size_t length,
+ const char *utf8str,
+ size_t utf8len,
int x,
size_t *char_offset,
int *actual_x)
@@ -224,26 +249,29 @@ win32_font_position(const plot_font_style_t *style,
int offset;
nserror ret = NSERROR_OK;
- if ((length == 0) || (x < 1)) {
+ /* deal with zero length input or invalid search co-ordiate */
+ if ((utf8len == 0) || (x < 1)) {
*char_offset = 0;
*actual_x = 0;
+ return ret;
+ }
+
+ hdc = GetDC(NULL);
+ font = get_font(style);
+ fontbak = SelectObject(hdc, font);
+
+ if ((GetTextExtentExPointA(hdc, utf8str, utf8len, x, &offset, NULL, &s)
!= 0) &&
+ (GetTextExtentPoint32A(hdc, utf8str, offset, &s) != 0)) {
+ *char_offset = (size_t)offset;
+ *actual_x = s.cx;
} else {
- hdc = GetDC(NULL);
- font = get_font(style);
- fontbak = SelectObject(hdc, font);
-
- if ((GetTextExtentExPointA(hdc, string, length, x, &offset,
NULL,&s) != 0) &&
- (GetTextExtentPoint32A(hdc, string, offset, &s) != 0)) {
- *char_offset = (size_t)offset;
- *actual_x = s.cx;
- } else {
- ret = NSERROR_UNKNOWN;
- }
- font = SelectObject(hdc, fontbak);
- DeleteObject(font);
- ReleaseDC(NULL, hdc);
+ ret = NSERROR_UNKNOWN;
}
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+
return ret;
}
@@ -256,7 +284,7 @@ win32_font_position(const plot_font_style_t *style,
* \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[out] offset updated to offset in string of actual_x, [0..length]
* \param actual_x updated to x coordinate of character closest to x
* \return NSERROR_OK on success otherwise appropriate error code
*
@@ -269,52 +297,48 @@ win32_font_split(const plot_font_style_t *style,
const char *string,
size_t length,
int x,
- size_t *char_offset,
+ size_t *offset,
int *actual_x)
{
+ nserror res;
int c_off;
- nserror ret = NSERROR_UNKNOWN;
-
- if (win32_font_position(style,
- string,
- length,
- x,
- char_offset,
- actual_x) == NSERROR_OK) {
- c_off = *char_offset;
- if (*char_offset == length) {
- ret = NSERROR_OK;
- } else {
- bool success;
- 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)++;
- }
- }
-
- success = win32_font_width(style,
- string,
- *char_offset,
- actual_x);
- if (success) {
- ret = NSERROR_OK;
- }
+
+ /* get the offset into teh string on the proposed position */
+ res = win32_font_position(style, string, length, x, offset, actual_x);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* return the whole string fits in the proposed length */
+ if (*offset == length) {
+ return NSERROR_OK;
+ }
+
+ c_off = *offset;
+
+ /* walk backwards through string looking for space to break on */
+ while ((string[*offset] != ' ') &&
+ (*offset > 0)) {
+ (*offset)--;
+ }
+
+ /* walk forwards through string looking for space if back failed */
+ if (*offset == 0) {
+ *offset = c_off;
+ while ((*offset < length) &&
+ (string[*offset] != ' ')) {
+ (*offset)++;
}
}
+ /* find the actual string width of the break */
+ res = win32_font_width(style, string, *offset, actual_x);
NSLOG(netsurf, DEEPDEBUG,
"ret %d Split %u chars at %ipx: Split at char %i (%ipx) - %.*s",
- ret, length, x, *char_offset, *actual_x, *char_offset, string);
+ res, length, x, *offset, *actual_x, *offset, string);
- return ret;
+ return res;
}
--
NetSurf Browser
_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org