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

Reply via email to