gdi32: Add a few helper functions for computing font metrics.

oldstable
Alexandre Julliard 2011-10-19 14:09:33 +02:00
parent 0101149c7a
commit ca4177997c
1 changed files with 95 additions and 97 deletions

View File

@ -562,6 +562,8 @@ static const WCHAR szDefaultFallbackLink[] = {'M','i','c','r','o','s','o','f','t
static BOOL use_default_fallback = FALSE;
static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph);
static BOOL get_outline_text_metrics(GdiFont *font);
static BOOL get_text_metrics(GdiFont *font, LPTEXTMETRICW ptm);
static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s',' ','N','T','\\',
@ -4426,7 +4428,7 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
font->name = strdupW(face->family->FamilyName);
font->ntmFlags = face->ntmFlags;
if (WineEngGetOutlineTextMetrics(font, 0, NULL))
if (get_outline_text_metrics(font))
{
memcpy(&pntm->ntmTm, &font->potm->otmTextMetrics, sizeof(TEXTMETRICW));
@ -4444,7 +4446,7 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
}
else
{
WineEngGetTextMetrics(font, (TEXTMETRICW *)&pntm->ntmTm);
get_text_metrics(font, (TEXTMETRICW *)&pntm->ntmTm);
pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
@ -4962,6 +4964,9 @@ DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
got_default = TRUE;
}
GDI_CheckNotLock();
EnterCriticalSection( &freetype_cs );
for(i = 0; i < count; i++)
{
pgi[i] = get_glyph_index(font, lpstr[i]);
@ -4977,7 +4982,7 @@ DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
else
{
TEXTMETRICW textm;
WineEngGetTextMetrics(font, &textm);
get_text_metrics(font, &textm);
default_char = textm.tmDefaultChar;
}
got_default = TRUE;
@ -4985,6 +4990,7 @@ DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
pgi[i] = default_char;
}
}
LeaveCriticalSection( &freetype_cs );
return count;
}
@ -5000,17 +5006,9 @@ static inline BOOL is_identity_MAT2(const MAT2 *matrix)
return !memcmp(matrix, &identity, sizeof(MAT2));
}
/*************************************************************
* WineEngGetGlyphOutline
*
* Behaves in exactly the same way as the win32 api GetGlyphOutline
* except that the first parameter is the HWINEENGFONT of the font in
* question rather than an HDC.
*
*/
DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
const MAT2* lpmat)
static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
const MAT2* lpmat)
{
static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
FT_Face ft_face = incoming_font->ft_face;
@ -5036,9 +5034,6 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
font->font_desc.matrix.eM11, font->font_desc.matrix.eM12,
font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
GDI_CheckNotLock();
EnterCriticalSection( &freetype_cs );
if(format & GGO_GLYPH_INDEX) {
glyph_index = get_GSUB_vert_glyph(incoming_font,glyph);
original_index = glyph;
@ -5070,7 +5065,6 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
lpgm->gmCellIncX, lpgm->gmCellIncY);
LeaveCriticalSection( &freetype_cs );
return 1; /* FIXME */
}
}
@ -5083,7 +5077,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
{
TEXTMETRICW tm;
WineEngGetTextMetrics(font, &tm);
get_text_metrics(font, &tm);
widthRatio = (double)font->aveWidth;
widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
@ -5169,7 +5163,6 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
if(err) {
WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
LeaveCriticalSection( &freetype_cs );
return GDI_ERROR;
}
@ -5249,7 +5242,6 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
if(format == GGO_METRICS)
{
LeaveCriticalSection( &freetype_cs );
return 1; /* FIXME */
}
@ -5259,7 +5251,6 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
format == GGO_GRAY8_BITMAP))
{
TRACE("loaded a bitmap\n");
LeaveCriticalSection( &freetype_cs );
return GDI_ERROR;
}
@ -5305,7 +5296,6 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
default:
FIXME("loaded glyph format %x\n", ft_face->glyph->format);
LeaveCriticalSection( &freetype_cs );
return GDI_ERROR;
}
break;
@ -5338,7 +5328,6 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
src += ft_face->glyph->bitmap.pitch;
dst += pitch;
}
LeaveCriticalSection( &freetype_cs );
return needed;
}
case ft_glyph_format_outline:
@ -5365,15 +5354,11 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
else if(format == GGO_GRAY8_BITMAP)
mult = 64;
else /* format == WINE_GGO_GRAY16_BITMAP */
{
LeaveCriticalSection( &freetype_cs );
return needed;
}
break;
}
default:
FIXME("loaded glyph format %x\n", ft_face->glyph->format);
LeaveCriticalSection( &freetype_cs );
return GDI_ERROR;
}
@ -5530,14 +5515,12 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
default:
FIXME ("loaded glyph format %x\n", ft_face->glyph->format);
LeaveCriticalSection ( &freetype_cs );
return GDI_ERROR;
}
break;
}
#else
LeaveCriticalSection( &freetype_cs );
return GDI_ERROR;
#endif
@ -5723,10 +5706,8 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
default:
FIXME("Unsupported format %d\n", format);
LeaveCriticalSection( &freetype_cs );
return GDI_ERROR;
}
LeaveCriticalSection( &freetype_cs );
return needed;
}
@ -5873,21 +5854,11 @@ static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *
#undef SCALE_Y
}
/*************************************************************
* WineEngGetTextMetrics
*
*/
BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
static BOOL get_text_metrics(GdiFont *font, LPTEXTMETRICW ptm)
{
GDI_CheckNotLock();
EnterCriticalSection( &freetype_cs );
if(!font->potm) {
if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
if(!get_bitmap_text_metrics(font))
{
LeaveCriticalSection( &freetype_cs );
return FALSE;
}
if(!font->potm)
{
if (!get_outline_text_metrics(font) && !get_bitmap_text_metrics(font)) return FALSE;
/* Make sure that the font has sane width/height ratio */
if (font->aveWidth)
@ -5899,10 +5870,8 @@ BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
}
}
}
*ptm = font->potm->otmTextMetrics;
scale_font_metrics(font, ptm);
LeaveCriticalSection( &freetype_cs );
return TRUE;
}
@ -5918,15 +5887,11 @@ static BOOL face_has_symbol_charmap(FT_Face ft_face)
return FALSE;
}
/*************************************************************
* WineEngGetOutlineTextMetrics
*
*/
UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
OUTLINETEXTMETRICW *potm)
static BOOL get_outline_text_metrics(GdiFont *font)
{
BOOL ret = FALSE;
FT_Face ft_face = font->ft_face;
UINT needed, lenfam, lensty, ret;
UINT needed, lenfam, lensty;
TT_OS2 *pOS2;
TT_HoriHeader *pHori;
TT_Postscript *pPost;
@ -5939,23 +5904,9 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
TRACE("font=%p\n", font);
if(!FT_IS_SCALABLE(ft_face))
return 0;
return FALSE;
GDI_CheckNotLock();
EnterCriticalSection( &freetype_cs );
if(font->potm) {
if(cbSize >= font->potm->otmSize)
{
memcpy(potm, font->potm, font->potm->otmSize);
scale_outline_font_metrics(font, potm);
}
LeaveCriticalSection( &freetype_cs );
return font->potm->otmSize;
}
needed = sizeof(*potm);
needed = sizeof(*font->potm);
lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
family_nameW = strdupW(font->name);
@ -5991,14 +5942,12 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
if(!pOS2) {
FIXME("Can't find OS/2 table - not TT font?\n");
ret = 0;
goto end;
}
pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
if(!pHori) {
FIXME("Can't find HHEA table - not TT font?\n");
ret = 0;
goto end;
}
@ -6234,18 +6183,69 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
strcpyW((WCHAR*)cp, family_nameW);
strcatW((WCHAR*)cp, spaceW);
strcatW((WCHAR*)cp, style_nameW);
ret = needed;
if(potm && needed <= cbSize)
{
memcpy(potm, font->potm, font->potm->otmSize);
scale_outline_font_metrics(font, potm);
}
ret = TRUE;
end:
HeapFree(GetProcessHeap(), 0, style_nameW);
HeapFree(GetProcessHeap(), 0, family_nameW);
return ret;
}
/*************************************************************
* WineEngGetGlyphOutline
*
*/
DWORD WineEngGetGlyphOutline(GdiFont *font, UINT glyph, UINT format,
LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf,
const MAT2* lpmat)
{
DWORD ret;
GDI_CheckNotLock();
EnterCriticalSection( &freetype_cs );
ret = get_glyph_outline( font, glyph, format, lpgm, buflen, buf, lpmat );
LeaveCriticalSection( &freetype_cs );
return ret;
}
/*************************************************************
* WineEngGetTextMetrics
*
*/
BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm)
{
BOOL ret;
GDI_CheckNotLock();
EnterCriticalSection( &freetype_cs );
ret = get_text_metrics( font, ptm );
LeaveCriticalSection( &freetype_cs );
return ret;
}
/*************************************************************
* WineEngGetOutlineTextMetrics
*
*/
UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize,
OUTLINETEXTMETRICW *potm)
{
UINT ret = 0;
TRACE("font=%p\n", font);
GDI_CheckNotLock();
EnterCriticalSection( &freetype_cs );
if (font->potm || get_outline_text_metrics( font ))
{
if(cbSize >= font->potm->otmSize)
{
memcpy(potm, font->potm, font->potm->otmSize);
scale_outline_font_metrics(font, potm);
}
ret = font->potm->otmSize;
}
LeaveCriticalSection( &freetype_cs );
return ret;
}
@ -6332,8 +6332,8 @@ static BOOL freetype_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, L
EnterCriticalSection( &freetype_cs );
for(c = firstChar; c <= lastChar; c++) {
get_glyph_index_linked(physdev->font, c, &linked_font, &glyph_index);
WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv;
}
LeaveCriticalSection( &freetype_cs );
@ -6363,8 +6363,8 @@ BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar,
for(c = firstChar; c <= lastChar; c++) {
get_glyph_index_linked(font, c, &linked_font, &glyph_index);
WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb;
buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx;
buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb -
@ -6394,8 +6394,8 @@ BOOL WineEngGetCharABCWidthsFloat(GdiFont *font, UINT first, UINT last, LPABCFLO
for (c = first; c <= last; c++)
{
get_glyph_index_linked(font, c, &linked_font, &glyph_index);
WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
buffer[c - first].abcfA = FONT_GM(linked_font, glyph_index)->lsb;
buffer[c - first].abcfB = FONT_GM(linked_font, glyph_index)->bbx;
buffer[c - first].abcfC = FONT_GM(linked_font, glyph_index)->adv -
@ -6428,8 +6428,8 @@ BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD
get_glyph_index_linked(font, 'a', &linked_font, &glyph_index);
if (!pgi)
for(c = firstChar; c < firstChar+count; c++) {
WineEngGetGlyphOutline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
get_glyph_outline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb;
buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx;
buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb
@ -6437,8 +6437,8 @@ BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD
}
else
for(c = 0; c < count; c++) {
WineEngGetGlyphOutline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
get_glyph_outline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb;
buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx;
buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv
@ -6476,13 +6476,13 @@ static BOOL freetype_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR wstr, INT count,
EnterCriticalSection( &freetype_cs );
size->cx = 0;
WineEngGetTextMetrics( physdev->font, &tm );
get_text_metrics( physdev->font, &tm );
size->cy = tm.tmHeight;
for(idx = 0; idx < count; idx++) {
get_glyph_index_linked( physdev->font, wstr[idx], &linked_font, &glyph_index );
WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
get_glyph_outline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
&gm, 0, NULL, &identity);
size->cx += FONT_GM(linked_font,glyph_index)->adv;
ext = size->cx;
if (! pnfit || ext <= max_ext) {
@ -6519,13 +6519,11 @@ BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count,
EnterCriticalSection( &freetype_cs );
size->cx = 0;
WineEngGetTextMetrics(font, &tm);
get_text_metrics(font, &tm);
size->cy = tm.tmHeight;
for(idx = 0; idx < count; idx++) {
WineEngGetGlyphOutline(font, indices[idx],
GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL,
&identity);
get_glyph_outline(font, indices[idx], GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &identity);
size->cx += FONT_GM(font,indices[idx])->adv;
ext = size->cx;
if (! pnfit || ext <= max_ext) {