The attached patch makes a fundamental change to the way the PostScript driver deals with character encodings -- it ignores them. Instead, the driver now operates directly on 16-bit Unicode characters. This should be a more robust strategy for handling non-Latin, and especially multi-byte, character sets. I really have no idea, however, how the rest of Wine handles non-Latin characters. As an English speaker, I'm not well equipped to test it. So please give me your feedback. I particularly want to know if it breaks anything before I submit it. Thanks! -- ======================================================================== Ian Pilcher ian.pilcher(a)home.com ======================================================================== diff -urN ../wine-20010714cvs/dlls/wineps/font.c ./dlls/wineps/font.c --- ../wine-20010714cvs/dlls/wineps/font.c Sun Jul 15 16:07:36 2001 +++ ./dlls/wineps/font.c Sun Jul 15 16:27:27 2001 @@ -5,6 +5,7 @@ * */ #include <string.h> +#include <stdlib.h> /* for bsearch() */ #include "winspool.h" #include "psdrv.h" #include "debugtools.h" @@ -294,6 +295,7 @@ return TRUE; } +#if 0 /*********************************************************************** * PSDRV_UnicodeToANSI */ @@ -321,9 +323,52 @@ return 0xff; } } +#endif + +/****************************************************************************** + * PSDRV_UVMetrics + * + * Find the AFMMETRICS for a given UV. Returns first glyph in the font + * (space?) if the font does not have a glyph for the given UV. + */ +static int MetricsByUV(const void *a, const void *b) +{ + return (int)(((const AFMMETRICS *)a)->UV - ((const AFMMETRICS *)b)->UV); +} + +const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const PSDRV_PDEVICE *physDev) +{ + AFMMETRICS key; + const AFMMETRICS *needle; + + /* + * Ugly work-around for symbol fonts. Wine is sending characters which + * belong in the Unicode private use range (U+F020 - U+F0FF) as ASCII + * characters (U+0020 - U+00FF). + */ + + if ((physDev->font.afm->Metrics->UV & 0xff00) == 0xf000 && UV < 0x100) + UV |= 0xf000; + + key.UV = UV; + + needle = bsearch(&key, physDev->font.afm->Metrics, + physDev->font.afm->NumofMetrics, sizeof(AFMMETRICS), + MetricsByUV); + + if (needle == NULL) + { + WARN("No glyph for U+%.4lX in %s\n", UV, physDev->font.afm->FontName); + needle = physDev->font.afm->Metrics; + } + + return needle; +} + /*********************************************************************** * PSDRV_GetTextExtentPoint */ +#if 0 BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count, LPSIZE size ) { @@ -346,11 +391,30 @@ return TRUE; } +#endif +BOOL PSDRV_GetTextExtentPoint(DC *dc, LPCWSTR str, INT count, LPSIZE size) +{ + PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev; + int i; + float width = 0.0; + + for (i = 0; i < count && str[i] != '\0'; ++i) + width += PSDRV_UVMetrics(str[i], physDev)->WX; + + width *= physDev->font.scale; + + size->cx = GDI_ROUND((FLOAT)width * dc->xformVport2World.eM11); + size->cy = GDI_ROUND((FLOAT)physDev->font.tm.tmHeight * + dc->xformVport2World.eM22); + + return TRUE; +} /*********************************************************************** * PSDRV_GetCharWidth */ +#if 0 BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar, LPINT buffer ) { @@ -365,7 +429,24 @@ return TRUE; } +#endif +BOOL PSDRV_GetCharWidth(DC *dc, UINT firstChar, UINT lastChar, LPINT buffer) +{ + PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev; + UINT i; + + if (lastChar > 0xffff || firstChar > lastChar) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + for (i = firstChar; i < lastChar; ++i) + *buffer++ = PSDRV_UVMetrics(i, physDev)->WX * physDev->font.scale; + + return TRUE; +} /*********************************************************************** * PSDRV_SetFont diff -urN ../wine-20010714cvs/dlls/wineps/ps.c ./dlls/wineps/ps.c --- ../wine-20010714cvs/dlls/wineps/ps.c Sun Jul 15 16:07:36 2001 +++ ./dlls/wineps/ps.c Sun Jul 15 16:25:12 2001 @@ -115,6 +115,9 @@ static char psshow[] = /* string */ "(%s) show\n"; +static const char psglyphshow[] = /* glyph name */ +"/%s glyphshow\n"; + static char pssetfont[] = /* fontname, xscale, yscale, ascent, escapement */ "/%s findfont\n" "[%d 0 0 %d 0 0]\n" @@ -634,6 +637,7 @@ return TRUE; } +#if 0 BOOL PSDRV_WriteShow(DC *dc, LPCWSTR str, INT count) { char *buf, *buf1; @@ -671,6 +675,32 @@ return TRUE; } +#endif + +BOOL PSDRV_WriteShow(DC *dc, LPCWSTR str, INT count) +{ + char buf[128]; + int i; + + for (i = 0; i < count; ++i) + { + LPCSTR name; + int l; + + name = PSDRV_UVMetrics(str[i], (PSDRV_PDEVICE *)dc->physDev)->N->sz; + l = snprintf(buf, sizeof(buf), psglyphshow, name); + + if (l < sizeof(psglyphshow) - 2 || l > sizeof(buf) - 1) + { + WARN("Unusable glyph name '%s' - ignoring\n", name); + continue; + } + + PSDRV_WriteSpool(dc, buf, l); + } + + return TRUE; +} BOOL PSDRV_WriteFill(DC *dc) { diff -urN ../wine-20010714cvs/dlls/wineps/psdrv.h ./dlls/wineps/psdrv.h --- ../wine-20010714cvs/dlls/wineps/psdrv.h Tue May 29 17:06:11 2001 +++ ./dlls/wineps/psdrv.h Sun Jul 15 16:11:36 2001 @@ -421,6 +421,7 @@ GLYPHNAME *PSDRV_GlyphName(LPCSTR szName); VOID PSDRV_IndexGlyphList(); BOOL PSDRV_GetTrueTypeMetrics(); +const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const PSDRV_PDEVICE *physDev); #endif
participants (1)
-
Ian Pilcher