1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 03:22:48 -05:00

Reinstate as much of the Windows font-linking behaviour as I can

easily manage, by adopting a hybrid approach to Unicode text
display. The old approach of simply calling ExtTextOutW provided
font linking without us having to lift a finger, but didn't do the
right thing when it came to bidirectional or Arabic-shaped text.
Arabeyes' replacement exact_textout() supported the latter, but
turned out to break the former (with no warning from the Windows API
documentation, so it's not their fault).

So now I've got a second wrapper layer called general_textout(),
which splits the input string into substrings based on bidi
character class. Any character liable to cause bidi or shaping
behaviour if fed straight to ExtTextOutW is instead fed through
Arabeyes' exact_textout(), but the rest is fed straight to
ExtTextOutW as it used to be.

The effect appears to be that font linking is restored for all
characters _except_ Arabic and other bidi scripts, which means in
particular that we are no longer in a state of regression over 0.57.
(0.57 would have done font linking on Arabic as well, but would also
have misbidied it, so we've merely exchanged one failure mode for
another slightly less harmful one in that situation.)

[originally from svn r6910]
This commit is contained in:
Simon Tatham
2006-11-18 15:10:48 +00:00
parent 53843b7392
commit 230d400ddc
3 changed files with 120 additions and 6 deletions

View File

@ -1260,6 +1260,89 @@ static void exact_textout(HDC hdc, int x, int y, CONST RECT *lprc,
lprc, buffer, cbCount, lpDx);
}
/*
* The exact_textout() wrapper, unfortunately, destroys the useful
* Windows `font linking' behaviour: automatic handling of Unicode
* code points not supported in this font by falling back to a font
* which does contain them. Therefore, we adopt a multi-layered
* approach: for any potentially-bidi text, we use exact_textout(),
* and for everything else we use a simple ExtTextOut as we did
* before exact_textout() was introduced.
*/
static void general_textout(HDC hdc, int x, int y, CONST RECT *lprc,
unsigned short *lpString, UINT cbCount,
CONST INT *lpDx, int opaque)
{
int i, j, xp, xn;
RECT newrc;
#ifdef FIXME_REMOVE_BEFORE_CHECKIN
int k;
debug(("general_textout: %d,%d", x, y));
for(k=0;k<cbCount;k++)debug((" U+%04X", lpString[k]));
debug(("\n rect: [%d,%d %d,%d]", lprc->left, lprc->top, lprc->right, lprc->bottom));
debug(("\n"));
#endif
xp = xn = x;
for (i = 0; i < cbCount ;) {
int rtl = is_rtl(lpString[i]);
xn += lpDx[i];
for (j = i+1; j < cbCount; j++) {
if (rtl != is_rtl(lpString[j]))
break;
xn += lpDx[j];
}
/*
* Now [i,j) indicates a maximal substring of lpString
* which should be displayed using the same textout
* function.
*/
if (rtl) {
newrc.left = lprc->left + xp - x;
newrc.right = lprc->left + xn - x;
newrc.top = lprc->top;
newrc.bottom = lprc->bottom;
#ifdef FIXME_REMOVE_BEFORE_CHECKIN
{
int k;
debug((" exact_textout: %d,%d", xp, y));
for(k=0;k<j-i;k++)debug((" U+%04X", lpString[i+k]));
debug(("\n rect: [%d,%d %d,%d]\n", newrc.left, newrc.top, newrc.right, newrc.bottom));
}
#endif
exact_textout(hdc, xp, y, &newrc, lpString+i, j-i, lpDx+i, opaque);
} else {
#ifdef FIXME_REMOVE_BEFORE_CHECKIN
{
int k;
debug((" ExtTextOut : %d,%d", xp, y));
for(k=0;k<j-i;k++)debug((" U+%04X", lpString[i+k]));
debug(("\n rect: [%d,%d %d,%d]\n", newrc.left, newrc.top, newrc.right, newrc.bottom));
}
#endif
newrc.left = lprc->left + xp - x;
newrc.right = lprc->left + xn - x;
newrc.top = lprc->top;
newrc.bottom = lprc->bottom;
ExtTextOutW(hdc, xp, y, ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0),
&newrc, lpString+i, j-i, lpDx+i);
}
i = j;
xp = xn;
}
#ifdef FIXME_REMOVE_BEFORE_CHECKIN
debug(("general_textout: done, xn=%d\n", xn));
#endif
assert(xn - x == lprc->right - lprc->left);
}
/*
* Initialise all the fonts we will need initially. There may be as many as
* three or as few as one. The other (poentially) twentyone fonts are done
@ -3295,12 +3378,8 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
wbuf[i] = text[i];
/* print Glyphs as they are, without Windows' Shaping*/
exact_textout(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust,
&line_box, wbuf, len, IpDx, !(attr & TATTR_COMBINING));
/* ExtTextOutW(hdc, x,
y - font_height * (lattr == LATTR_BOT) + text_adjust,
ETO_CLIPPED | ETO_OPAQUE, &line_box, wbuf, len, IpDx);
*/
general_textout(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust,
&line_box, wbuf, len, IpDx, !(attr & TATTR_COMBINING));
/* And the shadow bold hack. */
if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {