mirror of
https://github.com/fltk/fltk.git
synced 2026-05-26 01:46:58 +08:00
Improve handling of text containing context-dependent unicode points.
This commit makes platforms Windows and macOS compute string widths with the same mechanism as what is in place for platforms Wayland/X11: - the width of a string containing a single codepoint is computed and memorized in the table of character widths; - the width of a string containing several codepoints is computed as such rather than as the sum of the widths of its composing characters. This commit also fixes how text input under Windows is processed when a character needs encoding as a surrogate. The result is that FLTK text widgets input and draw correctly also complex emojis encoded with context-dependent codepoints.
This commit is contained in:
+17
-2
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Windows-specific code for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2024 by Bill Spitzak and others.
|
||||
// Copyright 1998-2026 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@@ -1510,7 +1510,22 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||
static char buffer[1024];
|
||||
if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
|
||||
wchar_t u = (wchar_t)wParam;
|
||||
Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
|
||||
// Windows emoji palette triggered with Windows + dot sends 2 or more WM_CHAR messages:
|
||||
// the 2 components of a surrogate pair, or variation selectors, or zero-width joiner,
|
||||
// or emoji modifiers FITZPATRICK or extra Unicode points.
|
||||
if (u >= 0xD800 && u <= 0xDFFF) { // handle the 2 components of a surrogate pair
|
||||
static wchar_t surrogate_pair[2];
|
||||
if (IS_HIGH_SURROGATE(u)) {
|
||||
surrogate_pair[0] = u; // memorize the 1st member of the pair
|
||||
Fl::e_length = 0;
|
||||
return 0; // and wait for next WM_CHAR message that will give the 2nd member
|
||||
} else {
|
||||
surrogate_pair[1] = u; // memorize the 2nd member of the pair
|
||||
Fl::e_length = fl_utf8fromwc(buffer, 1024, surrogate_pair, 2); // transform to UTF-8
|
||||
}
|
||||
} else {
|
||||
Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1); // process regular Unicode point
|
||||
}
|
||||
buffer[Fl::e_length] = 0;
|
||||
} else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
|
||||
if (state & FL_NUM_LOCK) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Windows font utilities for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2025 by Bill Spitzak and others.
|
||||
// Copyright 1998-2026 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@@ -366,6 +366,27 @@ Fl_Fontsize Fl_GDI_Graphics_Driver::size_unscaled() {
|
||||
}
|
||||
|
||||
double Fl_GDI_Graphics_Driver::width_unscaled(const char* c, int n) {
|
||||
if (n == 0) return 0;
|
||||
int len1 = fl_utf8len1(*c);
|
||||
if (n > len1 && len1 > 0) { // a text with several codepoints: compute its typographical width
|
||||
int wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
|
||||
if (wn >= wstr_len) {
|
||||
wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
|
||||
wstr_len = wn + 1;
|
||||
wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
|
||||
}
|
||||
HDC gc2 = gc_;
|
||||
HWND hWnd;
|
||||
if (!gc2) {
|
||||
hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL;
|
||||
gc2 = GetDC(hWnd);
|
||||
}
|
||||
SelectObject(gc2, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
|
||||
SIZE s;
|
||||
GetTextExtentPoint32W(gc2, (WCHAR*)wstr, wn, &s);
|
||||
if (gc2 && gc2 != gc_) ReleaseDC(hWnd, gc2);
|
||||
return (double)s.cx;
|
||||
}
|
||||
int i = 0;
|
||||
if (!font_descriptor()) return -1.0;
|
||||
double w = 0.0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MacOS font selection routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2018 by Bill Spitzak and others.
|
||||
// Copyright 1998-2026 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@@ -300,6 +300,21 @@ void Fl_Quartz_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
|
||||
}
|
||||
|
||||
double Fl_Quartz_Graphics_Driver::width(const char* txt, int n) {
|
||||
if (n == 0) return 0;
|
||||
int len1 = fl_utf8len1(*txt);
|
||||
if (len1 > 0 && n > len1) { // a text with several codepoints: compute its typographical width
|
||||
CFStringRef str = CFStringCreateWithBytes(NULL, (const UInt8*)txt, n, kCFStringEncodingUTF8, false);
|
||||
if (str) {
|
||||
CFDictionarySetValue(attributes, kCTFontAttributeName, valid_font_descriptor()->fontref);
|
||||
CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str, attributes);
|
||||
CFRelease(str);
|
||||
CTLineRef ctline = CTLineCreateWithAttributedString(mastr);
|
||||
CFRelease(mastr);
|
||||
double d = CTLineGetTypographicBounds(ctline, NULL, NULL, NULL);
|
||||
CFRelease(ctline);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
int wc_len = n;
|
||||
UniChar *uniStr = mac_Utf8_to_Utf16(txt, n, &wc_len);
|
||||
return width(uniStr, wc_len);
|
||||
|
||||
Reference in New Issue
Block a user