mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 09:12:24 +00:00
Pango-based font handling: combine display of adjacent characters
into a single gdk_draw_layout() where conveniently feasible, after some work with xtrace revealed this as a major source of pterm's slow display updates when using client-side fonts. Ideally we ought to be able to do better. I know exactly what sequence of X protocol operations I want to see on the wire, but I don't know how to persuade Pango to generate them. [originally from svn r8558]
This commit is contained in:
parent
8b88d653de
commit
4c0b7ba7e4
@ -892,28 +892,83 @@ static void pangofont_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
int clen;
|
int clen, n;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract a single UTF-8 character from the string.
|
* We want to display every character from this string in
|
||||||
|
* the centre of its own character cell. In the worst case,
|
||||||
|
* this requires a separate text-drawing call for each
|
||||||
|
* character; but in the common case where the font is
|
||||||
|
* properly fixed-width, we can draw many characters in one
|
||||||
|
* go which is much faster.
|
||||||
|
*
|
||||||
|
* This still isn't really ideal. If you look at what
|
||||||
|
* happens in the X protocol as a result of all of this, you
|
||||||
|
* find - naturally enough - that each call to
|
||||||
|
* gdk_draw_layout() generates a separate set of X RENDER
|
||||||
|
* operations involving creating a picture, setting a clip
|
||||||
|
* rectangle, doing some drawing and undoing the whole lot.
|
||||||
|
* In an ideal world, we should _always_ be able to turn the
|
||||||
|
* contents of this loop into a single RenderCompositeGlyphs
|
||||||
|
* operation which internally specifies inter-character
|
||||||
|
* deltas to get the spacing right, which would give us full
|
||||||
|
* speed _even_ in the worst case of a non-fixed-width font.
|
||||||
|
* However, Pango's architecture and documentation are so
|
||||||
|
* unhelpful that I have no idea how if at all to persuade
|
||||||
|
* them to do that.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start by extracting a single UTF-8 character from the
|
||||||
|
* string.
|
||||||
*/
|
*/
|
||||||
clen = 1;
|
clen = 1;
|
||||||
while (clen < len &&
|
while (clen < len &&
|
||||||
(unsigned char)string[clen] >= 0x80 &&
|
(unsigned char)string[clen] >= 0x80 &&
|
||||||
(unsigned char)string[clen] < 0xC0)
|
(unsigned char)string[clen] < 0xC0)
|
||||||
clen++;
|
clen++;
|
||||||
|
n = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See if that character has the width we expect.
|
||||||
|
*/
|
||||||
|
pango_layout_set_text(layout, string, clen);
|
||||||
|
pango_layout_get_pixel_extents(layout, NULL, &rect);
|
||||||
|
|
||||||
|
if (rect.width == cellwidth) {
|
||||||
|
/*
|
||||||
|
* Try extracting more characters, for as long as they
|
||||||
|
* stay well-behaved.
|
||||||
|
*/
|
||||||
|
while (clen < len) {
|
||||||
|
int oldclen = clen;
|
||||||
|
clen++; /* skip UTF-8 introducer byte */
|
||||||
|
while (clen < len &&
|
||||||
|
(unsigned char)string[clen] >= 0x80 &&
|
||||||
|
(unsigned char)string[clen] < 0xC0)
|
||||||
|
clen++;
|
||||||
|
n++;
|
||||||
|
pango_layout_set_text(layout, string, clen);
|
||||||
|
pango_layout_get_pixel_extents(layout, NULL, &rect);
|
||||||
|
if (rect.width != n * cellwidth) {
|
||||||
|
clen = oldclen;
|
||||||
|
n--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pango_layout_set_text(layout, string, clen);
|
pango_layout_set_text(layout, string, clen);
|
||||||
pango_layout_get_pixel_extents(layout, NULL, &rect);
|
pango_layout_get_pixel_extents(layout, NULL, &rect);
|
||||||
gdk_draw_layout(target, gc, x + (cellwidth - rect.width)/2,
|
gdk_draw_layout(target, gc, x + (n*cellwidth - rect.width)/2,
|
||||||
y + (pfont->u.height - rect.height)/2, layout);
|
y + (pfont->u.height - rect.height)/2, layout);
|
||||||
if (shadowbold)
|
if (shadowbold)
|
||||||
gdk_draw_layout(target, gc, x + (cellwidth - rect.width)/2 + pfont->shadowoffset,
|
gdk_draw_layout(target, gc, x + (n*cellwidth - rect.width)/2 + pfont->shadowoffset,
|
||||||
y + (pfont->u.height - rect.height)/2, layout);
|
y + (pfont->u.height - rect.height)/2, layout);
|
||||||
|
|
||||||
len -= clen;
|
len -= clen;
|
||||||
string += clen;
|
string += clen;
|
||||||
x += cellwidth;
|
x += n * cellwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
|
Loading…
Reference in New Issue
Block a user