diff options
| author | Ian MacArthur <imacarthur@gmail.com> | 2011-04-12 10:08:58 +0000 |
|---|---|---|
| committer | Ian MacArthur <imacarthur@gmail.com> | 2011-04-12 10:08:58 +0000 |
| commit | 38a3c21ffd80c62d5f1f71a4f93c3c8873137fdf (patch) | |
| tree | 0d1fdaf3a4a06b8d92e113efa10568e6ad6ee3b7 | |
| parent | d065ca89fe27a4dafb9e243e323d065f6ce29bca (diff) | |
Modify win32 text width(ucs) function to handle surrogate pairs.
This now correctly measures glyphs whose codepoint requires a surrogate pair to represent it in UTF16.
NOTE 1: This code makes any UCS point > 0xFFFF a "special case" and measures it explicitly, rather than using the lookup table. This "explicit measure" may be slow, but actually seems OK in my tests, so far.
The lookup table still covers the basic multilingual plane and is used for any glyph <= 0xFFFF as before, so the behaviour for most existing bodies of text is unchanged.
This code also retains the historical behaviour under Win32 whereby strings are measured char-by-char rather than as a whole string - again this is intended to retain compatability with existing implementations.
It is proposed that we should move towards measuring entire strings in the future as this is conceivably more efficient and certainly more consistent - rendering is now largely done "string as a whole" so we ought to measure in that way too; though to date the differences seem tiny, as evdienced by the text rendering page of the unittest example.
NOTE 2: This does not fix the *rendering* of surrogate pairs under XP, which still seems to be broken. I suspect that TextOutW() may genuinely broken under XP, as it works fine on Vista, and it is not just my code that seems broken, other non-fltk programs exhibit the same aberrant behaviour. Measuring of surrogate pairs appears to work correctly though...
Maybe we are using TextOutW() wrongly?
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8580 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | src/fl_font_win32.cxx | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/src/fl_font_win32.cxx b/src/fl_font_win32.cxx index 13ae64855..fae064034 100644 --- a/src/fl_font_win32.cxx +++ b/src/fl_font_win32.cxx @@ -170,7 +170,6 @@ double Fl_GDI_Graphics_Driver::width(const char* c, int n) { char *end = (char *)&c[n]; while (i < n) { unsigned int ucs; -// int l = fl_utf2ucs((const unsigned char*)c + i, n - i, &ucs); int l; ucs = fl_utf8decode((const char*)(c + i), end, &l); // if (l < 1) l = 1; @@ -185,10 +184,34 @@ double Fl_GDI_Graphics_Driver::width(const char* c, int n) { double Fl_GDI_Graphics_Driver::width(unsigned int c) { Fl_Font_Descriptor *fl_fontsize = font_descriptor(); unsigned int r; + SIZE s; + // Special Case Handling of Unicode points over U+FFFF + // The logic (below) computes a lookup table for char widths + // on-the-fly, but the table only covers codepoints up to + // U+FFFF, which covers the basic multilingual plane, but + // not any higher plane, or glyphs that require surrogate-pairs + // to encode them in WinXX which is UTF16. + // This code assumes that these glyphs are rarely used and simply + // measures them explicitly if they occur - Which may be slow... + if(c > 0x0000FFFF) { // UTF16 surrogate pair is needed + if (!fl_gc) { // We have no valid gc, so nothing to measure - bail out + return 0.0; + } + int cc; // cell count + char utf8[8]; // Array for UTF-8 representation of c + unsigned short ucs[4]; // Array for UTF16 representation of c + // This fl_utf8encode / fl_utf8toUtf16 dance creates a UTF16 string + // from a UCS code point. + cc = fl_utf8encode(c, utf8); + cc = fl_utf8toUtf16(utf8, cc, ucs, 4); + GetTextExtentPoint32W(fl_gc, (WCHAR*)ucs, cc, &s); + return (double)s.cx; + } + // else - this falls through to the lookup-table for glyph widths + // in the basic multilingual plane r = (c & 0xFC00) >> 10; if (!fl_fontsize->width[r]) { fl_fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400); - SIZE s; unsigned short i = 0, ii = r * 0x400; // The following code makes a best effort attempt to obtain a valid fl_gc. // If no fl_gc is available at the time we call fl_width(), then we first @@ -199,9 +222,9 @@ double Fl_GDI_Graphics_Driver::width(unsigned int c) { HDC gc = fl_gc; HWND hWnd = 0; if (!gc) { // We have no valid gc, try and obtain one - // Use our first fltk window, or fallback to using the screen via GetDC(NULL) - hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL; - gc = GetDC(hWnd); + // Use our first fltk window, or fallback to using the screen via GetDC(NULL) + hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL; + gc = GetDC(hWnd); } if (!gc) Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!"); |
