mirror of
https://github.com/fltk/fltk.git
synced 2026-05-25 00:53:39 +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. The result is that FLTK text widgets input and draw correctly also complex emojis encoded with context-dependent codepoints. Function fl_utf8_remove_context_dependent() is no longer necessary.
This commit is contained in:
@@ -67,7 +67,6 @@ extern "C" {
|
||||
// external functions
|
||||
extern void fl_fix_focus();
|
||||
extern int fl_send_system_handlers(void *e);
|
||||
extern int fl_utf8_remove_context_dependent(char *text, int len);
|
||||
|
||||
// forward definition of functions in this file
|
||||
// converting cr lf converter function
|
||||
@@ -2957,7 +2956,6 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
|
||||
// insertText sent during handleEvent of a key without text cannot be processed in a single FL_KEYBOARD event.
|
||||
// Occurs with deadkey followed by non-text key. Occurs also with emoji palette.
|
||||
if (!in_key_event || !has_text_key) {
|
||||
Fl::e_length = fl_utf8_remove_context_dependent(Fl::e_text, Fl::e_length);
|
||||
Fl::handle(FL_KEYBOARD, target);
|
||||
Fl::e_length = 0;
|
||||
}
|
||||
|
||||
@@ -1572,19 +1572,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||
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
|
||||
unsigned u32 = // convert surrogate pair to UTF-32
|
||||
0x10000 + ((surrogate_pair[0] & 0x3ff) << 10) + (surrogate_pair[1] & 0x3ff);
|
||||
if (u32 >= 0x1F3FB && u32 <= 0x1F3FF) { // emoji modifiers FITZPATRICK
|
||||
Fl::e_length = 0; // skip them
|
||||
return 0;
|
||||
}
|
||||
Fl::e_length = fl_utf8fromwc(buffer, 1024, surrogate_pair, 2); // transform to UTF-8
|
||||
}
|
||||
} else if ( (u >= 0xFE00 && u <= 0xFE0F) // variation selectors
|
||||
|| u == 0x200D // zero-width joiner
|
||||
) {
|
||||
Fl::e_length = 0; // skip these context-dependent Unicode points
|
||||
return 0;
|
||||
} else {
|
||||
Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1); // process regular Unicode point
|
||||
}
|
||||
|
||||
@@ -101,7 +101,6 @@ extern Fl_Window *fl_xmousewin;
|
||||
|
||||
static void open_display_i(Display *d); // open display (internal)
|
||||
extern int fl_send_system_handlers(void *e);
|
||||
extern int fl_utf8_remove_context_dependent(char *text, int len);
|
||||
|
||||
#if FLTK_CONSOLIDATE_MOTION
|
||||
static Fl_Window *send_motion;
|
||||
@@ -1841,7 +1840,6 @@ int fl_handle(const XEvent& thisevent)
|
||||
len = XUtf8LookupString(Fl_X11_Screen_Driver::xim_ic, (XKeyPressedEvent *)&xevent.xkey,
|
||||
kp_buffer, kp_buffer_len, &keysym, &status);
|
||||
}
|
||||
len = fl_utf8_remove_context_dependent(kp_buffer, len);
|
||||
keysym = fl_KeycodeToKeysym(fl_display, keycode, 0);
|
||||
} else {
|
||||
//static XComposeStatus compose;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -53,7 +53,6 @@ extern "C" {
|
||||
bool fl_is_surface_from_GTK_titlebar (struct wl_surface *surface, struct libdecor_frame *frame,
|
||||
bool *using_GTK);
|
||||
}
|
||||
extern int fl_utf8_remove_context_dependent(char *text, int len);
|
||||
|
||||
// set this to 1 for keyboard debug output, 0 for no debug output
|
||||
#define DEBUG_KEYBOARD 0
|
||||
@@ -1017,10 +1016,7 @@ void text_input_commit_string(void *data, struct zwp_text_input_v3 *zwp_text_inp
|
||||
const char *text) {
|
||||
//printf("text_input_commit_string %s\n",text);
|
||||
free(pending_commit);
|
||||
if (text) {
|
||||
pending_commit = strdup(text);
|
||||
fl_utf8_remove_context_dependent(pending_commit, strlen(pending_commit));
|
||||
} else pending_commit = NULL;
|
||||
pending_commit = (text ? strdup(text) : NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1630,30 +1630,3 @@ unsigned fl_utf8from_mb(char* dst, unsigned dstlen, const char* src, unsigned sr
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifndef FL_DOXYGEN
|
||||
|
||||
/* This function removes from an UTF-8 string its context-dependent codepoints
|
||||
when there are any, and returns the length of the possibly shortened string.
|
||||
*/
|
||||
int fl_utf8_remove_context_dependent(char *text, int len) {
|
||||
if (len > 1 && fl_utf_nb_char((const uchar*)text, len) > 1) {
|
||||
// Some emojis are expressed by a series of Unicode points
|
||||
char *p = text, *end = text + len;
|
||||
while (p < end) { // loop over all unicode points of the series
|
||||
int l_point;
|
||||
unsigned u = fl_utf8decode(p, end, &l_point); // extract one such unicode point
|
||||
if ((u >= 0xFE00 && u <= 0xFE0F) // variation selectors
|
||||
|| u == 0x200D // zero-width joiner
|
||||
|| (u >= 0x1F3FB && u <= 0x1F3FF) // EMOJI MODIFIERS FITZPATRICK TYPE
|
||||
) { // remove context-dependent unicode points
|
||||
memmove((void*)p, p + l_point, (end - (p+l_point)) + 1);
|
||||
end -= l_point;
|
||||
len -= l_point;
|
||||
} else p += l_point; // keep other unicode points
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif // ! FL_DOXYGEN
|
||||
|
||||
Reference in New Issue
Block a user