Read/calculate average character width for all fonts.
Work directly with 16-bit WCHARs; don't convert to CP1252.
This commit is contained in:
parent
4194fe48e3
commit
020146619c
|
@ -801,6 +801,60 @@ static BOOL SortFontMetrics()
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* PSDRV_CalcAvgCharWidth
|
||||
*
|
||||
* Calculate WinMetrics.sAvgCharWidth for a Type 1 font. Can also be used on
|
||||
* TrueType fonts, if font designer set OS/2:xAvgCharWidth to zero.
|
||||
*
|
||||
* Tries to use formula in TrueType specification; falls back to simple mean
|
||||
* if any lowercase latin letter (or space) is not present.
|
||||
*/
|
||||
inline static SHORT MeanCharWidth(const AFM *afm)
|
||||
{
|
||||
float w = 0.0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < afm->NumofMetrics; ++i)
|
||||
w += afm->Metrics[i].WX;
|
||||
|
||||
w /= afm->NumofMetrics;
|
||||
|
||||
return (SHORT)(w + 0.5);
|
||||
}
|
||||
|
||||
static const struct { LONG UV; int weight; } UVweight[27] =
|
||||
{
|
||||
{ 0x0061, 64 }, { 0x0062, 14 }, { 0x0063, 27 }, { 0x0064, 35 },
|
||||
{ 0x0065, 100 }, { 0x0066, 20 }, { 0x0067, 14 }, { 0x0068, 42 },
|
||||
{ 0x0069, 63 }, { 0x006a, 3 }, { 0x006b, 6 }, { 0x006c, 35 },
|
||||
{ 0x006d, 20 }, { 0x006e, 56 }, { 0x006f, 56 }, { 0x0070, 17 },
|
||||
{ 0x0071, 4 }, { 0x0072, 49 }, { 0x0073, 56 }, { 0x0074, 71 },
|
||||
{ 0x0075, 31 }, { 0x0076, 10 }, { 0x0077, 18 }, { 0x0078, 3 },
|
||||
{ 0x0079, 18 }, { 0x007a, 2 }, { 0x0020, 166 }
|
||||
};
|
||||
|
||||
SHORT PSDRV_CalcAvgCharWidth(const AFM *afm)
|
||||
{
|
||||
float w = 0.0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 27; ++i)
|
||||
{
|
||||
const AFMMETRICS *afmm;
|
||||
|
||||
afmm = PSDRV_UVMetrics(UVweight[i].UV, afm);
|
||||
if (afmm->UV != UVweight[i].UV) /* UVMetrics returns first glyph */
|
||||
return MeanCharWidth(afm); /* in font if UV is missing */
|
||||
|
||||
w += afmm->WX * (float)(UVweight[i].weight);
|
||||
}
|
||||
|
||||
w /= 1000.0;
|
||||
|
||||
return (SHORT)(w + 0.5);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* CalcWindowsMetrics
|
||||
*
|
||||
|
@ -871,6 +925,8 @@ static VOID CalcWindowsMetrics()
|
|||
wm.sLineGap = 1150 - (wm.sAscender - wm.sDescender);
|
||||
if (wm.sLineGap < 0)
|
||||
wm.sLineGap = 0;
|
||||
|
||||
wm.sAvgCharWidth = PSDRV_CalcAvgCharWidth(afm);
|
||||
|
||||
TRACE("Windows metrics for '%s':\n", afm->FullName);
|
||||
TRACE("\tsAscender = %i\n", wm.sAscender);
|
||||
|
@ -882,6 +938,7 @@ static VOID CalcWindowsMetrics()
|
|||
TRACE("\tsTypoLineGap = %i\n", wm.sTypoLineGap);
|
||||
TRACE("\tusWinAscent = %u\n", wm.usWinAscent);
|
||||
TRACE("\tusWinDescent = %u\n", wm.usWinDescent);
|
||||
TRACE("\tsAvgCharWidth = %i\n", wm.sAvgCharWidth);
|
||||
|
||||
afm->WinMetrics = wm;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h> /* for bsearch() */
|
||||
#include "winspool.h"
|
||||
#include "psdrv.h"
|
||||
#include "debugtools.h"
|
||||
|
@ -197,6 +198,7 @@ BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICW *metrics)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/***********************************************************************
|
||||
* PSDRV_UnicodeToANSI
|
||||
*/
|
||||
|
@ -224,9 +226,51 @@ char PSDRV_UnicodeToANSI(int u)
|
|||
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 AFM *afm)
|
||||
{
|
||||
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 ((afm->Metrics->UV & 0xff00) == 0xf000 && UV < 0x100)
|
||||
UV |= 0xf000;
|
||||
|
||||
key.UV = UV;
|
||||
|
||||
needle = bsearch(&key, afm->Metrics, afm->NumofMetrics, sizeof(AFMMETRICS),
|
||||
MetricsByUV);
|
||||
|
||||
if (needle == NULL)
|
||||
{
|
||||
WARN("No glyph for U+%.4lX in %s\n", UV, afm->FontName);
|
||||
needle = afm->Metrics;
|
||||
}
|
||||
|
||||
return needle;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* PSDRV_GetTextExtentPoint
|
||||
*/
|
||||
#if 0
|
||||
BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
|
||||
LPSIZE size )
|
||||
{
|
||||
|
@ -249,11 +293,34 @@ BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
|
|||
|
||||
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;
|
||||
|
||||
TRACE("%s %i\n", debugstr_wn(str, count), count);
|
||||
|
||||
for (i = 0; i < count && str[i] != '\0'; ++i)
|
||||
width += PSDRV_UVMetrics(str[i], physDev->font.afm)->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);
|
||||
|
||||
TRACE("cx=%li cy=%li\n", size->cx, size->cy);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* PSDRV_GetCharWidth
|
||||
*/
|
||||
#if 0
|
||||
BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
|
||||
LPINT buffer )
|
||||
{
|
||||
|
@ -268,7 +335,31 @@ BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL PSDRV_GetCharWidth(DC *dc, UINT firstChar, UINT lastChar, LPINT buffer)
|
||||
{
|
||||
PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
|
||||
UINT i;
|
||||
|
||||
TRACE("U+%.4X U+%.4X\n", firstChar, lastChar);
|
||||
|
||||
if (lastChar > 0xffff || firstChar > lastChar)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = firstChar; i <= lastChar; ++i)
|
||||
{
|
||||
*buffer = GDI_ROUND(PSDRV_UVMetrics(i, physDev->font.afm)->WX
|
||||
* physDev->font.scale);
|
||||
TRACE("U+%.4X: %i\n", i, *buffer);
|
||||
++buffer;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* PSDRV_SetFont
|
||||
|
|
|
@ -115,6 +115,9 @@ static char psrrectangle[] = /* x, y, width, height, -width */
|
|||
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 @@ BOOL PSDRV_WriteReencodeFont(DC *dc)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
BOOL PSDRV_WriteShow(DC *dc, LPCWSTR str, INT count)
|
||||
{
|
||||
char *buf, *buf1;
|
||||
|
@ -671,6 +675,33 @@ BOOL PSDRV_WriteShow(DC *dc, LPCWSTR str, INT count)
|
|||
|
||||
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)->font.afm)->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)
|
||||
{
|
||||
|
|
|
@ -421,6 +421,8 @@ INT PSDRV_GlyphListInit();
|
|||
GLYPHNAME *PSDRV_GlyphName(LPCSTR szName);
|
||||
VOID PSDRV_IndexGlyphList();
|
||||
BOOL PSDRV_GetTrueTypeMetrics();
|
||||
const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const AFM *afm);
|
||||
SHORT PSDRV_CalcAvgCharWidth(const AFM *afm);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -329,6 +329,7 @@ static BOOL ReadMetricsTables(AFM *afm)
|
|||
afm->WinMetrics.sTypoLineGap = os2->sTypoLineGap;
|
||||
afm->WinMetrics.usWinAscent = os2->usWinAscent;
|
||||
afm->WinMetrics.usWinDescent = os2->usWinDescent;
|
||||
afm->WinMetrics.sAvgCharWidth = os2->xAvgCharWidth;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -483,6 +484,11 @@ static BOOL ReadTrueTypeAFM(AFM *afm)
|
|||
if (ReadCharMetrics(afm) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
/* Can't do this check until character metrics are read */
|
||||
|
||||
if (afm->WinMetrics.sAvgCharWidth == 0)
|
||||
afm->WinMetrics.sAvgCharWidth = PSDRV_CalcAvgCharWidth(afm);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue