mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-01 11:32:48 -05:00
GTK: use only 16-bit X text drawing calls
Xlib and the X protocol provide text handling calls in versions that take both 8-bit and 16-bit character indices. They are mostly interchangable, except that of course the 8-bit calls can only access characters with codes up to 255. Heretofore, PuTTY used the 16-bit X calls when using a font in the "iso10646-1" encoding and 8-bit calls otherwise. This led to a lot of duplicate code, and in particular two large and almost identical implementations of x11font_cairo_draw*(). Now, PuTTY uses 16-bit calls throughout, even when using an 8-bit font encoding. This simplifies the code at the expense of needing an extra bit of conversion to expand the char array that we get from put_wc_to_mb() into an array of XChar2b when using an 8-bit font.
This commit is contained in:
152
unix/unifont.c
152
unix/unifont.c
@ -173,7 +173,8 @@ struct x11font {
|
|||||||
/*
|
/*
|
||||||
* `sixteen_bit' is true iff the font object is indexed by
|
* `sixteen_bit' is true iff the font object is indexed by
|
||||||
* values larger than a byte. That is, this flag tells us
|
* values larger than a byte. That is, this flag tells us
|
||||||
* whether we use XDrawString or XDrawString16, etc.
|
* whether the font is encoded in Unicode. If not, we need
|
||||||
|
* to translate text into the font character set.
|
||||||
*/
|
*/
|
||||||
bool sixteen_bit;
|
bool sixteen_bit;
|
||||||
/*
|
/*
|
||||||
@ -329,16 +330,10 @@ static char *x11_guess_derived_font_name(Display *disp, XFontStruct *xfs,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int x11_font_width(XFontStruct *xfs, bool sixteen_bit)
|
static int x11_font_width(XFontStruct *xfs)
|
||||||
{
|
{
|
||||||
if (sixteen_bit) {
|
XChar2b space = { 0, '0' };
|
||||||
XChar2b space;
|
|
||||||
space.byte1 = 0;
|
|
||||||
space.byte2 = '0';
|
|
||||||
return XTextWidth16(xfs, &space, 1);
|
return XTextWidth16(xfs, &space, 1);
|
||||||
} else {
|
|
||||||
return XTextWidth(xfs, "0", 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const XCharStruct *x11_char_struct(
|
static const XCharStruct *x11_char_struct(
|
||||||
@ -488,7 +483,7 @@ static unifont *x11font_create(GtkWidget *widget, const char *name,
|
|||||||
|
|
||||||
xfont = snew(struct x11font);
|
xfont = snew(struct x11font);
|
||||||
xfont->u.vt = &x11font_vtable;
|
xfont->u.vt = &x11font_vtable;
|
||||||
xfont->u.width = x11_font_width(xfs, sixteen_bit);
|
xfont->u.width = x11_font_width(xfs);
|
||||||
xfont->u.ascent = xfs->ascent;
|
xfont->u.ascent = xfs->ascent;
|
||||||
xfont->u.descent = xfs->descent;
|
xfont->u.descent = xfs->descent;
|
||||||
xfont->u.height = xfont->u.ascent + xfont->u.descent;
|
xfont->u.height = xfont->u.ascent + xfont->u.descent;
|
||||||
@ -585,20 +580,12 @@ static bool x11font_has_glyph(unifont *font, wchar_t glyph)
|
|||||||
#define GDK_DRAWABLE_XID(d) GDK_WINDOW_XID(d) /* GTK3's name for this */
|
#define GDK_DRAWABLE_XID(d) GDK_WINDOW_XID(d) /* GTK3's name for this */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int x11font_width_16(unifont_drawctx *ctx, x11font_individual *xfi,
|
static int x11font_width(unifont_drawctx *ctx, x11font_individual *xfi,
|
||||||
const void *vstring, int start, int length)
|
const XChar2b *string, int start, int length)
|
||||||
{
|
{
|
||||||
const XChar2b *string = (const XChar2b *)vstring;
|
|
||||||
return XTextWidth16(xfi->xfs, string+start, length);
|
return XTextWidth16(xfi->xfs, string+start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int x11font_width_8(unifont_drawctx *ctx, x11font_individual *xfi,
|
|
||||||
const void *vstring, int start, int length)
|
|
||||||
{
|
|
||||||
const char *string = (const char *)vstring;
|
|
||||||
return XTextWidth(xfi->xfs, string+start, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DRAW_TEXT_GDK
|
#ifdef DRAW_TEXT_GDK
|
||||||
static void x11font_gdk_setup(unifont_drawctx *ctx, x11font_individual *xfi,
|
static void x11font_gdk_setup(unifont_drawctx *ctx, x11font_individual *xfi,
|
||||||
Display *disp)
|
Display *disp)
|
||||||
@ -606,23 +593,13 @@ static void x11font_gdk_setup(unifont_drawctx *ctx, x11font_individual *xfi,
|
|||||||
XSetFont(disp, GDK_GC_XGC(ctx->u.gdk.gc), xfi->xfs->fid);
|
XSetFont(disp, GDK_GC_XGC(ctx->u.gdk.gc), xfi->xfs->fid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11font_gdk_draw_16(unifont_drawctx *ctx, x11font_individual *xfi,
|
static void x11font_gdk_draw(unifont_drawctx *ctx, x11font_individual *xfi,
|
||||||
Display *disp, int x, int y,
|
Display *disp, int x, int y,
|
||||||
const void *vstring, int start, int length)
|
const XChar2b *string, int start, int length)
|
||||||
{
|
{
|
||||||
const XChar2b *string = (const XChar2b *)vstring;
|
|
||||||
XDrawString16(disp, GDK_DRAWABLE_XID(ctx->u.gdk.target),
|
XDrawString16(disp, GDK_DRAWABLE_XID(ctx->u.gdk.target),
|
||||||
GDK_GC_XGC(ctx->u.gdk.gc), x, y, string+start, length);
|
GDK_GC_XGC(ctx->u.gdk.gc), x, y, string+start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11font_gdk_draw_8(unifont_drawctx *ctx, x11font_individual *xfi,
|
|
||||||
Display *disp, int x, int y,
|
|
||||||
const void *vstring, int start, int length)
|
|
||||||
{
|
|
||||||
const char *string = (const char *)vstring;
|
|
||||||
XDrawString(disp, GDK_DRAWABLE_XID(ctx->u.gdk.target),
|
|
||||||
GDK_GC_XGC(ctx->u.gdk.gc), x, y, string+start, length);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DRAW_TEXT_CAIRO
|
#ifdef DRAW_TEXT_CAIRO
|
||||||
@ -654,11 +631,10 @@ static void x11font_cairo_init_gc(x11font_individual *xfi, Display *disp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11font_cairo_draw_16(
|
static void x11font_cairo_draw(
|
||||||
unifont_drawctx *ctx, x11font_individual *xfi, Display *disp,
|
unifont_drawctx *ctx, x11font_individual *xfi, Display *disp,
|
||||||
int x, int y, const void *vstring, int start, int length)
|
int x, int y, const XChar2b *string, int start, int length)
|
||||||
{
|
{
|
||||||
const XChar2b *string = (const XChar2b *)vstring + start;
|
|
||||||
GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget);
|
GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget);
|
||||||
int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin));
|
int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin));
|
||||||
XCharStruct bounds;
|
XCharStruct bounds;
|
||||||
@ -693,88 +669,35 @@ static void x11font_cairo_draw_16(
|
|||||||
XFreePixmap(disp, pixmap);
|
XFreePixmap(disp, pixmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11font_cairo_draw_8(
|
|
||||||
unifont_drawctx *ctx, x11font_individual *xfi, Display *disp,
|
|
||||||
int x, int y, const void *vstring, int start, int length)
|
|
||||||
{
|
|
||||||
const char *string = (const char *)vstring + start;
|
|
||||||
GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget);
|
|
||||||
int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin));
|
|
||||||
XCharStruct bounds;
|
|
||||||
int pixwidth, pixheight, direction, font_ascent, font_descent;
|
|
||||||
Pixmap pixmap;
|
|
||||||
|
|
||||||
XTextExtents(xfi->xfs, string + start, length,
|
|
||||||
&direction, &font_ascent, &font_descent, &bounds);
|
|
||||||
pixwidth = bounds.rbearing - bounds.lbearing;
|
|
||||||
pixheight = bounds.ascent + bounds.descent;
|
|
||||||
if (pixwidth > 0 && pixheight > 0) {
|
|
||||||
pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin),
|
|
||||||
pixwidth, pixheight, 1);
|
|
||||||
x11font_cairo_init_gc(xfi, disp, pixmap);
|
|
||||||
XFillRectangle(disp, pixmap, xfi->gc, 0, 0, pixwidth, pixheight);
|
|
||||||
XDrawImageString(disp, pixmap, xfi->gc,
|
|
||||||
-bounds.lbearing, bounds.ascent,
|
|
||||||
string+start, length);
|
|
||||||
cairo_surface_t *surface = cairo_xlib_surface_create_for_bitmap(
|
|
||||||
disp, pixmap, ScreenOfDisplay(disp, widgetscr),
|
|
||||||
pixwidth, pixheight);
|
|
||||||
cairo_pattern_t *pattern = cairo_pattern_create_for_surface(surface);
|
|
||||||
/* We really don't want bilinear interpolation of bitmap fonts. */
|
|
||||||
cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
|
|
||||||
cairo_matrix_t xfrm;
|
|
||||||
cairo_matrix_init_translate(&xfrm,
|
|
||||||
-x - bounds.lbearing, -y + bounds.ascent);
|
|
||||||
cairo_pattern_set_matrix(pattern, &xfrm);
|
|
||||||
cairo_mask(ctx->u.cairo.cr, pattern);
|
|
||||||
cairo_pattern_destroy(pattern);
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
XFreePixmap(disp, pixmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* DRAW_TEXT_CAIRO */
|
#endif /* DRAW_TEXT_CAIRO */
|
||||||
|
|
||||||
struct x11font_drawfuncs {
|
struct x11font_drawfuncs {
|
||||||
int (*width)(unifont_drawctx *ctx, x11font_individual *xfi,
|
int (*width)(unifont_drawctx *ctx, x11font_individual *xfi,
|
||||||
const void *vstring, int start, int length);
|
const XChar2b *string, int start, int length);
|
||||||
void (*setup)(unifont_drawctx *ctx, x11font_individual *xfi,
|
void (*setup)(unifont_drawctx *ctx, x11font_individual *xfi,
|
||||||
Display *disp);
|
Display *disp);
|
||||||
void (*draw)(unifont_drawctx *ctx, x11font_individual *xfi, Display *disp,
|
void (*draw)(unifont_drawctx *ctx, x11font_individual *xfi, Display *disp,
|
||||||
int x, int y, const void *vstring, int start, int length);
|
int x, int y, const XChar2b *string, int start, int length);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This array has two entries per compiled-in drawtype; of each pair,
|
* This array has one entry per compiled-in drawtype.
|
||||||
* the first is for an 8-bit font and the second for 16-bit.
|
|
||||||
*/
|
*/
|
||||||
static const struct x11font_drawfuncs x11font_drawfuncs[2*DRAWTYPE_NTYPES] = {
|
static const struct x11font_drawfuncs x11font_drawfuncs[DRAWTYPE_NTYPES] = {
|
||||||
#ifdef DRAW_TEXT_GDK
|
#ifdef DRAW_TEXT_GDK
|
||||||
/* gdk, 8-bit */
|
/* gdk */
|
||||||
{
|
{
|
||||||
x11font_width_8,
|
x11font_width,
|
||||||
x11font_gdk_setup,
|
x11font_gdk_setup,
|
||||||
x11font_gdk_draw_8,
|
x11font_gdk_draw,
|
||||||
},
|
|
||||||
/* gdk, 16-bit */
|
|
||||||
{
|
|
||||||
x11font_width_16,
|
|
||||||
x11font_gdk_setup,
|
|
||||||
x11font_gdk_draw_16,
|
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef DRAW_TEXT_CAIRO
|
#ifdef DRAW_TEXT_CAIRO
|
||||||
/* cairo, 8-bit */
|
/* cairo */
|
||||||
{
|
{
|
||||||
x11font_width_8,
|
x11font_width,
|
||||||
x11font_cairo_setup,
|
x11font_cairo_setup,
|
||||||
x11font_cairo_draw_8,
|
x11font_cairo_draw,
|
||||||
},
|
|
||||||
/* [3] cairo, 16-bit */
|
|
||||||
{
|
|
||||||
x11font_width_16,
|
|
||||||
x11font_cairo_setup,
|
|
||||||
x11font_cairo_draw_16,
|
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@ -830,7 +753,7 @@ static void x11font_draw_text(unifont_drawctx *ctx, unifont *font,
|
|||||||
int sfid;
|
int sfid;
|
||||||
int shadowoffset = 0;
|
int shadowoffset = 0;
|
||||||
int mult = (wide ? 2 : 1);
|
int mult = (wide ? 2 : 1);
|
||||||
int index = 2 * (int)ctx->type;
|
int index = (int)ctx->type;
|
||||||
|
|
||||||
wide = wide && !xfont->wide;
|
wide = wide && !xfont->wide;
|
||||||
bold = bold && !xfont->bold;
|
bold = bold && !xfont->bold;
|
||||||
@ -857,25 +780,19 @@ static void x11font_draw_text(unifont_drawctx *ctx, unifont *font,
|
|||||||
if (!xfont->fonts[sfid].xfs)
|
if (!xfont->fonts[sfid].xfs)
|
||||||
return; /* we've tried our best, but no luck */
|
return; /* we've tried our best, but no luck */
|
||||||
|
|
||||||
|
XChar2b *xcs;
|
||||||
|
int i, xcslen;
|
||||||
if (xfont->sixteen_bit) {
|
if (xfont->sixteen_bit) {
|
||||||
/*
|
/*
|
||||||
* This X font has 16-bit character indices, which means
|
* This X font has 16-bit character indices, which means
|
||||||
* we can directly use our Unicode input string.
|
* we can directly use our Unicode input string.
|
||||||
*/
|
*/
|
||||||
XChar2b *xcs;
|
xcslen = len;
|
||||||
int i;
|
xcs = snewn(xcslen, XChar2b);
|
||||||
|
for (i = 0; i < xcslen; i++) {
|
||||||
xcs = snewn(len, XChar2b);
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
xcs[i].byte1 = string[i] >> 8;
|
xcs[i].byte1 = string[i] >> 8;
|
||||||
xcs[i].byte2 = string[i];
|
xcs[i].byte2 = string[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
x11font_really_draw_text(x11font_drawfuncs + index + 1, ctx,
|
|
||||||
&xfont->fonts[sfid], xfont->disp, x, y,
|
|
||||||
xcs, len, shadowoffset,
|
|
||||||
xfont->variable, cellwidth * mult);
|
|
||||||
sfree(xcs);
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* This X font has 8-bit indices, so we must convert to the
|
* This X font has 8-bit indices, so we must convert to the
|
||||||
@ -883,12 +800,19 @@ static void x11font_draw_text(unifont_drawctx *ctx, unifont *font,
|
|||||||
*/
|
*/
|
||||||
strbuf *sb = strbuf_new();
|
strbuf *sb = strbuf_new();
|
||||||
put_wc_to_mb(sb, xfont->real_charset, string, len, ".");
|
put_wc_to_mb(sb, xfont->real_charset, string, len, ".");
|
||||||
x11font_really_draw_text(x11font_drawfuncs + index + 0, ctx,
|
xcslen = sb->len;
|
||||||
&xfont->fonts[sfid], xfont->disp, x, y,
|
xcs = snewn(xcslen, XChar2b);
|
||||||
sb->s, sb->len, shadowoffset,
|
for (i = 0; i < xcslen; i++) {
|
||||||
xfont->variable, cellwidth * mult);
|
xcs[i].byte1 = 0;
|
||||||
|
xcs[i].byte2 = sb->s[i];
|
||||||
|
}
|
||||||
strbuf_free(sb);
|
strbuf_free(sb);
|
||||||
}
|
}
|
||||||
|
x11font_really_draw_text(x11font_drawfuncs + index, ctx,
|
||||||
|
&xfont->fonts[sfid], xfont->disp, x, y,
|
||||||
|
xcs, xcslen, shadowoffset,
|
||||||
|
xfont->variable, cellwidth * mult);
|
||||||
|
sfree(xcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11font_draw_combining(unifont_drawctx *ctx, unifont *font,
|
static void x11font_draw_combining(unifont_drawctx *ctx, unifont *font,
|
||||||
|
Reference in New Issue
Block a user