1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-04-09 15:18:06 -05:00

Detect non-monospaced X fonts, and respond by drawing text one

character at a time centred in its character cell, as we do for
Pango. Gives much better results for those non-monospaced fonts
which are usable as terminal fonts, and shows up the problems with
the others more readily. (In particular, this means the preview pane
in the font selector now warns you there will be trouble if you
select such a font.)

[originally from svn r7949]
This commit is contained in:
Simon Tatham 2008-03-29 10:48:16 +00:00
parent 115898b2a5
commit cce6a5e2ec

View File

@ -27,10 +27,6 @@
* TODO on fontsel
* ---------------
*
* - start drawing X fonts one character at a time, at least if
* they're not fixed-width? Now we have that helpful pangram,
* we should make it work for everyone.
*
* - think about points versus pixels, harder than I already have
*
* - generalised style and padding polish
@ -145,6 +141,12 @@ struct x11font {
* whether we use gdk_draw_text_wc() or gdk_draw_text().
*/
int sixteen_bit;
/*
* `variable' is true iff the font is non-fixed-pitch. This
* enables some code which takes greater care over character
* positioning during text drawing.
*/
int variable;
/*
* Data passed in to unifont_create().
*/
@ -218,10 +220,10 @@ static int x11_font_width(GdkFont *font, int sixteen_bit)
if (sixteen_bit) {
XChar2b space;
space.byte1 = 0;
space.byte2 = ' ';
space.byte2 = '0';
return gdk_text_width(font, (const gchar *)&space, 2);
} else {
return gdk_char_width(font, ' ');
return gdk_char_width(font, '0');
}
}
@ -233,9 +235,9 @@ static unifont *x11font_create(GtkWidget *widget, const char *name,
GdkFont *font;
XFontStruct *xfs;
Display *disp;
Atom charset_registry, charset_encoding;
unsigned long registry_ret, encoding_ret;
int pubcs, realcs, sixteen_bit;
Atom charset_registry, charset_encoding, spacing;
unsigned long registry_ret, encoding_ret, spacing_ret;
int pubcs, realcs, sixteen_bit, variable;
int i;
font = gdk_font_load(name);
@ -250,6 +252,7 @@ static unifont *x11font_create(GtkWidget *widget, const char *name,
pubcs = realcs = CS_NONE;
sixteen_bit = FALSE;
variable = TRUE;
if (XGetFontProperty(xfs, charset_registry, &registry_ret) &&
XGetFontProperty(xfs, charset_encoding, &encoding_ret)) {
@ -298,6 +301,15 @@ static unifont *x11font_create(GtkWidget *widget, const char *name,
}
}
spacing = XInternAtom(disp, "SPACING", False);
if (XGetFontProperty(xfs, spacing, &spacing_ret)) {
char *spc;
spc = XGetAtomName(disp, (Atom)spacing_ret);
if (spc && strchr("CcMm", spc[0]))
variable = FALSE;
}
xfont = snew(struct x11font);
xfont->u.vt = &x11font_vtable;
xfont->u.width = x11_font_width(font, sixteen_bit);
@ -309,6 +321,7 @@ static unifont *x11font_create(GtkWidget *widget, const char *name,
xfont->fonts[0] = font;
xfont->allocated[0] = TRUE;
xfont->sixteen_bit = sixteen_bit;
xfont->variable = variable;
xfont->wide = wide;
xfont->bold = bold;
xfont->shadowoffset = shadowoffset;
@ -342,6 +355,38 @@ static void x11_alloc_subfont(struct x11font *xfont, int sfid)
sfree(derived_name);
}
static void x11font_really_draw_text(GdkDrawable *target, GdkFont *font,
GdkGC *gc, int x, int y,
const gchar *string, int clen, int nchars,
int shadowbold, int shadowoffset,
int fontvariable, int cellwidth)
{
int step = clen * nchars, nsteps = 1, centre = FALSE;
if (fontvariable) {
/*
* In a variable-pitch font, we draw one character at a
* time, and centre it in the character cell.
*/
step = clen;
nsteps = nchars;
centre = TRUE;
}
while (nsteps-- > 0) {
int X = x;
if (centre)
X += (cellwidth - gdk_text_width(font, string, step)) / 2;
gdk_draw_text(target, font, gc, X, y, string, step);
if (shadowbold)
gdk_draw_text(target, font, gc, X + shadowoffset, y, string, step);
x += cellwidth;
string += step;
}
}
static void x11font_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
int x, int y, const char *string, int len,
int wide, int bold, int cellwidth)
@ -349,6 +394,7 @@ static void x11font_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
struct x11font *xfont = (struct x11font *)font;
int sfid;
int shadowbold = FALSE;
int mult = (wide ? 2 : 1);
wide -= xfont->wide;
bold -= xfont->bold;
@ -404,18 +450,17 @@ static void x11font_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
xcs[i].byte2 = wcs[i];
}
gdk_draw_text(target, xfont->fonts[sfid], gc,
x, y, (gchar *)xcs, nchars*2);
if (shadowbold)
gdk_draw_text(target, xfont->fonts[sfid], gc,
x + xfont->shadowoffset, y, (gchar *)xcs, nchars*2);
x11font_really_draw_text(target, xfont->fonts[sfid], gc, x, y,
(gchar *)xcs, 2, nchars,
shadowbold, xfont->shadowoffset,
xfont->variable, cellwidth * mult);
sfree(xcs);
sfree(wcs);
} else {
gdk_draw_text(target, xfont->fonts[sfid], gc, x, y, string, len);
if (shadowbold)
gdk_draw_text(target, xfont->fonts[sfid], gc,
x + xfont->shadowoffset, y, string, len);
x11font_really_draw_text(target, xfont->fonts[sfid], gc, x, y,
string, 1, len,
shadowbold, xfont->shadowoffset,
xfont->variable, cellwidth * mult);
}
}