Make Pango-handled text accept legacy CP1252-encoded text

This commit is contained in:
ManoloFLTK 2024-10-07 16:20:44 +02:00
parent 05d78e8ebd
commit 6e5f3f7ecb
4 changed files with 48 additions and 0 deletions

View File

@ -66,6 +66,7 @@ public:
PangoLayout *pango_layout() {return pango_layout_;}
void set_cairo(cairo_t *c, float f = 0);
static cairo_pattern_t *calc_cairo_mask(const Fl_RGB_Image *rgb);
static const char *clean_utf8(const char* str, int &n);
void check_status(void);

View File

@ -1311,11 +1311,50 @@ void Fl_Cairo_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize s) {
}
// Scans the input string str with fl_utf8decode() that accepts also non-UTF-8
// and processes it as if encoded in CP1252.
// Returns a true UTF-8 string and its length, possibly transformed from CP1252.
// If the input string is true UTF-8, returned string is the same memory as input.
// Otherwise, returned string is in private memory allocated inside clean_utf8()
// and extended when necessary.
const char *Fl_Cairo_Graphics_Driver::clean_utf8(const char* str, int &n) {
static char *utf8_buffer = NULL;
static int utf8_buffer_len = 0;
char *q = utf8_buffer;
const char *p = str;
const char *retval = str;
int len, len2;
const char *end = str + n;
char buf4[4];
while (p < end) {
unsigned codepoint = fl_utf8decode(p, end, &len);
len2 = fl_utf8encode(codepoint, buf4);
if (retval != str || len != len2) { // switch to using utf8_buffer
if (!utf8_buffer_len || utf8_buffer_len < (q - utf8_buffer) + len2) {
utf8_buffer_len += (q - utf8_buffer) + len2 + 1000;
utf8_buffer = (char *)realloc(utf8_buffer, utf8_buffer_len);
}
if (retval == str) {
retval = utf8_buffer;
q = utf8_buffer;
if (p > str) { memcpy(q, str, p - str); q += (p - str); }
}
memcpy(q, buf4, len2);
q += len2;
}
p += len;
}
if (retval != str) n = q - retval;
return retval;
}
void Fl_Cairo_Graphics_Driver::draw(const char* str, int n, float x, float y) {
if (!n) return;
cairo_save(cairo_);
Fl_Cairo_Font_Descriptor *fd = (Fl_Cairo_Font_Descriptor*)font_descriptor();
cairo_translate(cairo_, x - 1, y - (fd->line_height - fd->descent) / float(PANGO_SCALE) - 1);
str = clean_utf8(str, n);
pango_layout_set_text(pango_layout_, str, n);
pango_cairo_show_layout(cairo_, pango_layout_); // 1.1O
cairo_restore(cairo_);
@ -1383,6 +1422,7 @@ double Fl_Cairo_Graphics_Driver::width(const char* str, int n) {
int Fl_Cairo_Graphics_Driver::do_width_unscaled_(const char* str, int n) {
if (!n) return 0;
str = clean_utf8(str, n);
pango_layout_set_text(pango_layout_, str, n);
PangoRectangle p_rect;
pango_layout_get_extents(pango_layout_, NULL, &p_rect);
@ -1391,6 +1431,7 @@ int Fl_Cairo_Graphics_Driver::do_width_unscaled_(const char* str, int n) {
void Fl_Cairo_Graphics_Driver::text_extents(const char* txt, int n, int& dx, int& dy, int& w, int& h) {
txt = clean_utf8(txt, n);
pango_layout_set_text(pango_layout_, txt, n);
PangoRectangle ink_rect;
pango_layout_get_extents(pango_layout_, &ink_rect, NULL);

View File

@ -1572,6 +1572,7 @@ void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, dou
pango_layout_set_font_description(pango_layout_, pfd);
int pwidth, pheight;
cairo_save(cairo_);
str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n);
pango_layout_set_text(pango_layout_, str, n);
pango_layout_get_size(pango_layout_, &pwidth, &pheight);
if (pwidth > 0) {

View File

@ -18,6 +18,7 @@
#include "../../flstring.h"
#include "Fl_Xlib_Graphics_Driver.H"
#include "../Cairo/Fl_Cairo_Graphics_Driver.H"
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <FL/fl_string_functions.h> // fl_strdup()
@ -1208,6 +1209,7 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, i
double l = width_unscaled(str, n);
pango_matrix_rotate(&mat, angle); // 1.6
pango_context_set_matrix(pctxt_, &mat); // 1.6
str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n);
pango_layout_set_text(playout_, str, n);
int w, h;
pango_layout_get_pixel_size(playout_, &w, &h);
@ -1263,6 +1265,7 @@ void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, in
}
const char *old = 0;
if (!str2) old = pango_layout_get_text(playout_);
str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n);
if (!old || (int)strlen(old) != n || memcmp(str, old, n)) // do not re-set text if equal to text already in layout
pango_layout_set_text(playout_, str, n);
if (str2) free(str2);
@ -1335,6 +1338,7 @@ double Fl_Xlib_Graphics_Driver::do_width_unscaled_(const char* str, int n) {
if (!playout_) context();
int width, height;
pango_layout_set_font_description(playout_, pfd_array[font_]);
str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n);
pango_layout_set_text(playout_, str, n);
pango_layout_get_pixel_size(playout_, &width, &height);
return (double)width;
@ -1343,6 +1347,7 @@ double Fl_Xlib_Graphics_Driver::do_width_unscaled_(const char* str, int n) {
void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *str, int n, int &dx, int &dy, int &w, int &h) {
if (!playout_) context();
pango_layout_set_font_description(playout_, pfd_array[font_]);
str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n);
pango_layout_set_text(playout_, str, n);
int y_correction;
fl_pango_layout_get_pixel_extents(playout_, dx, dy, w, h, descent_unscaled(), height_unscaled(), y_correction);