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;
|
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
|
* CalcWindowsMetrics
|
||||||
*
|
*
|
||||||
@ -871,6 +925,8 @@ static VOID CalcWindowsMetrics()
|
|||||||
wm.sLineGap = 1150 - (wm.sAscender - wm.sDescender);
|
wm.sLineGap = 1150 - (wm.sAscender - wm.sDescender);
|
||||||
if (wm.sLineGap < 0)
|
if (wm.sLineGap < 0)
|
||||||
wm.sLineGap = 0;
|
wm.sLineGap = 0;
|
||||||
|
|
||||||
|
wm.sAvgCharWidth = PSDRV_CalcAvgCharWidth(afm);
|
||||||
|
|
||||||
TRACE("Windows metrics for '%s':\n", afm->FullName);
|
TRACE("Windows metrics for '%s':\n", afm->FullName);
|
||||||
TRACE("\tsAscender = %i\n", wm.sAscender);
|
TRACE("\tsAscender = %i\n", wm.sAscender);
|
||||||
@ -882,6 +938,7 @@ static VOID CalcWindowsMetrics()
|
|||||||
TRACE("\tsTypoLineGap = %i\n", wm.sTypoLineGap);
|
TRACE("\tsTypoLineGap = %i\n", wm.sTypoLineGap);
|
||||||
TRACE("\tusWinAscent = %u\n", wm.usWinAscent);
|
TRACE("\tusWinAscent = %u\n", wm.usWinAscent);
|
||||||
TRACE("\tusWinDescent = %u\n", wm.usWinDescent);
|
TRACE("\tusWinDescent = %u\n", wm.usWinDescent);
|
||||||
|
TRACE("\tsAvgCharWidth = %i\n", wm.sAvgCharWidth);
|
||||||
|
|
||||||
afm->WinMetrics = wm;
|
afm->WinMetrics = wm;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h> /* for bsearch() */
|
||||||
#include "winspool.h"
|
#include "winspool.h"
|
||||||
#include "psdrv.h"
|
#include "psdrv.h"
|
||||||
#include "debugtools.h"
|
#include "debugtools.h"
|
||||||
@ -197,6 +198,7 @@ BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICW *metrics)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* PSDRV_UnicodeToANSI
|
* PSDRV_UnicodeToANSI
|
||||||
*/
|
*/
|
||||||
@ -224,9 +226,51 @@ char PSDRV_UnicodeToANSI(int u)
|
|||||||
return 0xff;
|
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
|
* PSDRV_GetTextExtentPoint
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
|
BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
|
||||||
LPSIZE size )
|
LPSIZE size )
|
||||||
{
|
{
|
||||||
@ -249,11 +293,34 @@ BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
|
|||||||
|
|
||||||
return TRUE;
|
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
|
* PSDRV_GetCharWidth
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
|
BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
|
||||||
LPINT buffer )
|
LPINT buffer )
|
||||||
{
|
{
|
||||||
@ -268,7 +335,31 @@ BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
|
|||||||
|
|
||||||
return TRUE;
|
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
|
* PSDRV_SetFont
|
||||||
|
@ -115,6 +115,9 @@ static char psrrectangle[] = /* x, y, width, height, -width */
|
|||||||
static char psshow[] = /* string */
|
static char psshow[] = /* string */
|
||||||
"(%s) show\n";
|
"(%s) show\n";
|
||||||
|
|
||||||
|
static const char psglyphshow[] = /* glyph name */
|
||||||
|
"/%s glyphshow\n";
|
||||||
|
|
||||||
static char pssetfont[] = /* fontname, xscale, yscale, ascent, escapement */
|
static char pssetfont[] = /* fontname, xscale, yscale, ascent, escapement */
|
||||||
"/%s findfont\n"
|
"/%s findfont\n"
|
||||||
"[%d 0 0 %d 0 0]\n"
|
"[%d 0 0 %d 0 0]\n"
|
||||||
@ -634,6 +637,7 @@ BOOL PSDRV_WriteReencodeFont(DC *dc)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
BOOL PSDRV_WriteShow(DC *dc, LPCWSTR str, INT count)
|
BOOL PSDRV_WriteShow(DC *dc, LPCWSTR str, INT count)
|
||||||
{
|
{
|
||||||
char *buf, *buf1;
|
char *buf, *buf1;
|
||||||
@ -671,6 +675,33 @@ BOOL PSDRV_WriteShow(DC *dc, LPCWSTR str, INT count)
|
|||||||
|
|
||||||
return TRUE;
|
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)
|
BOOL PSDRV_WriteFill(DC *dc)
|
||||||
{
|
{
|
||||||
|
@ -421,6 +421,8 @@ INT PSDRV_GlyphListInit();
|
|||||||
GLYPHNAME *PSDRV_GlyphName(LPCSTR szName);
|
GLYPHNAME *PSDRV_GlyphName(LPCSTR szName);
|
||||||
VOID PSDRV_IndexGlyphList();
|
VOID PSDRV_IndexGlyphList();
|
||||||
BOOL PSDRV_GetTrueTypeMetrics();
|
BOOL PSDRV_GetTrueTypeMetrics();
|
||||||
|
const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const AFM *afm);
|
||||||
|
SHORT PSDRV_CalcAvgCharWidth(const AFM *afm);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -329,6 +329,7 @@ static BOOL ReadMetricsTables(AFM *afm)
|
|||||||
afm->WinMetrics.sTypoLineGap = os2->sTypoLineGap;
|
afm->WinMetrics.sTypoLineGap = os2->sTypoLineGap;
|
||||||
afm->WinMetrics.usWinAscent = os2->usWinAscent;
|
afm->WinMetrics.usWinAscent = os2->usWinAscent;
|
||||||
afm->WinMetrics.usWinDescent = os2->usWinDescent;
|
afm->WinMetrics.usWinDescent = os2->usWinDescent;
|
||||||
|
afm->WinMetrics.sAvgCharWidth = os2->xAvgCharWidth;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -483,6 +484,11 @@ static BOOL ReadTrueTypeAFM(AFM *afm)
|
|||||||
if (ReadCharMetrics(afm) == FALSE)
|
if (ReadCharMetrics(afm) == FALSE)
|
||||||
return 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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user