mirror of
https://github.com/reactos/wine.git
synced 2024-11-26 13:10:28 +00:00
gdi32: Ensure a fixed-pitch full-width character has double advance of a half-width character.
This commit is contained in:
parent
68d72f4792
commit
9aa8300f99
@ -5821,6 +5821,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||||||
BOOL needsTransform = FALSE;
|
BOOL needsTransform = FALSE;
|
||||||
BOOL tategaki = (font->GSUB_Table != NULL);
|
BOOL tategaki = (font->GSUB_Table != NULL);
|
||||||
UINT original_index;
|
UINT original_index;
|
||||||
|
FT_Fixed avgAdvance = 0;
|
||||||
|
|
||||||
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
|
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
|
||||||
buflen, buf, lpmat);
|
buflen, buf, lpmat);
|
||||||
@ -5957,10 +5958,26 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||||||
return GDI_ERROR;
|
return GDI_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(FT_IS_SCALABLE(incoming_font->ft_face)) {
|
||||||
|
TEXTMETRICW tm;
|
||||||
|
if (get_text_metrics(incoming_font, &tm) &&
|
||||||
|
!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
|
||||||
|
avgAdvance = pFT_MulFix(incoming_font->ntmAvgWidth,
|
||||||
|
incoming_font->ft_face->size->metrics.x_scale);
|
||||||
|
if (avgAdvance && (ft_face->glyph->metrics.horiAdvance+63) >> 6 == (avgAdvance*2+63) >> 6)
|
||||||
|
TRACE("Fixed-pitch full-width character detected\n");
|
||||||
|
else
|
||||||
|
avgAdvance = 0; /* cancel this feature */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!needsTransform) {
|
if(!needsTransform) {
|
||||||
left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
|
left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64;
|
||||||
right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
|
right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64;
|
||||||
adv = (INT)(ft_face->glyph->metrics.horiAdvance + 63) >> 6;
|
if (!avgAdvance)
|
||||||
|
adv = (INT)(ft_face->glyph->metrics.horiAdvance + 63) >> 6;
|
||||||
|
else
|
||||||
|
adv = (INT)((avgAdvance + 32) >> 6) * 2;
|
||||||
|
|
||||||
top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
|
top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
|
||||||
bottom = (ft_face->glyph->metrics.horiBearingY -
|
bottom = (ft_face->glyph->metrics.horiBearingY -
|
||||||
@ -6001,13 +6018,27 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||||||
vec.x = ft_face->glyph->metrics.horiAdvance;
|
vec.x = ft_face->glyph->metrics.horiAdvance;
|
||||||
vec.y = 0;
|
vec.y = 0;
|
||||||
pFT_Vector_Transform(&vec, &transMat);
|
pFT_Vector_Transform(&vec, &transMat);
|
||||||
lpgm->gmCellIncX = (vec.x+63) >> 6;
|
|
||||||
lpgm->gmCellIncY = -((vec.y+63) >> 6);
|
lpgm->gmCellIncY = -((vec.y+63) >> 6);
|
||||||
|
if (!avgAdvance || vec.y)
|
||||||
|
lpgm->gmCellIncX = (vec.x+63) >> 6;
|
||||||
|
else {
|
||||||
|
vec.x = avgAdvance;
|
||||||
|
vec.y = 0;
|
||||||
|
pFT_Vector_Transform(&vec, &transMat);
|
||||||
|
lpgm->gmCellIncX = ((vec.x+32) >> 6) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
vec.x = ft_face->glyph->metrics.horiAdvance;
|
vec.x = ft_face->glyph->metrics.horiAdvance;
|
||||||
vec.y = 0;
|
vec.y = 0;
|
||||||
pFT_Vector_Transform(&vec, &transMatUnrotated);
|
pFT_Vector_Transform(&vec, &transMatUnrotated);
|
||||||
adv = (vec.x+63) >> 6;
|
if (!avgAdvance || vec.y)
|
||||||
|
adv = (vec.x+63) >> 6;
|
||||||
|
else {
|
||||||
|
vec.x = avgAdvance;
|
||||||
|
vec.y = 0;
|
||||||
|
pFT_Vector_Transform(&vec, &transMatUnrotated);
|
||||||
|
adv = ((vec.x+32) >> 6) * 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lpgm->gmBlackBoxX = (right - left) >> 6;
|
lpgm->gmBlackBoxX = (right - left) >> 6;
|
||||||
|
@ -3552,6 +3552,38 @@ todo_wine
|
|||||||
DeleteDC(hdc);
|
DeleteDC(hdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CALLBACK create_fixed_pitch_font_proc(const LOGFONT *lpelfe,
|
||||||
|
const TEXTMETRIC *lpntme,
|
||||||
|
DWORD FontType, LPARAM lParam)
|
||||||
|
{
|
||||||
|
const NEWTEXTMETRICEX *lpntmex = (const NEWTEXTMETRICEX *)lpntme;
|
||||||
|
CHARSETINFO csi;
|
||||||
|
LOGFONT lf = *lpelfe;
|
||||||
|
HFONT hfont;
|
||||||
|
|
||||||
|
/* skip bitmap, proportional or vertical font */
|
||||||
|
if ((FontType & TRUETYPE_FONTTYPE) == 0 ||
|
||||||
|
(lf.lfPitchAndFamily & 0xf) != FIXED_PITCH ||
|
||||||
|
lf.lfFaceName[0] == '@')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* skip linked font */
|
||||||
|
if (!TranslateCharsetInfo((DWORD*)(INT_PTR)lpelfe->lfCharSet, &csi, TCI_SRCCHARSET) ||
|
||||||
|
(lpntmex->ntmFontSig.fsCsb[0] & csi.fs.fsCsb[0]) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* test with an odd height */
|
||||||
|
lf.lfHeight = -19;
|
||||||
|
lf.lfWidth = 0;
|
||||||
|
hfont = CreateFontIndirect(&lf);
|
||||||
|
if (hfont)
|
||||||
|
{
|
||||||
|
*(HFONT *)lParam = hfont;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void test_GetGlyphOutline(void)
|
static void test_GetGlyphOutline(void)
|
||||||
{
|
{
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
@ -3640,6 +3672,8 @@ static void test_GetGlyphOutline(void)
|
|||||||
|
|
||||||
for (i = 0; i < sizeof c / sizeof c[0]; ++i)
|
for (i = 0; i < sizeof c / sizeof c[0]; ++i)
|
||||||
{
|
{
|
||||||
|
static const MAT2 rotate_mat = {{0, 0}, {0, -1}, {0, 1}, {0, 0}};
|
||||||
|
|
||||||
lf.lfFaceName[0] = '\0';
|
lf.lfFaceName[0] = '\0';
|
||||||
lf.lfCharSet = c[i].cs;
|
lf.lfCharSet = c[i].cs;
|
||||||
lf.lfPitchAndFamily = 0;
|
lf.lfPitchAndFamily = 0;
|
||||||
@ -3670,6 +3704,60 @@ static void test_GetGlyphOutline(void)
|
|||||||
ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
|
ret2 = GetGlyphOutlineW(hdc, c[i].w, GGO_BITMAP, &gm2, 0, NULL, &mat);
|
||||||
ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
|
ok(ret == ret2 && memcmp(&gm, &gm2, sizeof gm) == 0, "%d %d\n", ret, ret2);
|
||||||
|
|
||||||
|
if (EnumFontFamiliesEx(hdc, &lf, create_fixed_pitch_font_proc, (LPARAM)&hfont, 0))
|
||||||
|
{
|
||||||
|
skip("Fixed-pitch TrueType font for charset %u is not available\n", c[i].cs);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DeleteObject(SelectObject(hdc, hfont));
|
||||||
|
if (c[i].a <= 0xff)
|
||||||
|
{
|
||||||
|
DeleteObject(SelectObject(hdc, old_hfont));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = GetObject(hfont, sizeof lf, &lf);
|
||||||
|
ok(ret > 0, "GetObject error %u\n", GetLastError());
|
||||||
|
|
||||||
|
ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
|
||||||
|
ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
|
||||||
|
ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
|
||||||
|
ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
|
||||||
|
trace("Tests with height=%d,half=%d,full=%d,face=%s,charset=%d\n",
|
||||||
|
-lf.lfHeight, gm.gmCellIncX, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
|
||||||
|
ok(gm2.gmCellIncX == gm.gmCellIncX * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
|
||||||
|
"expected %d, got %d (%s:%d)\n",
|
||||||
|
gm.gmCellIncX * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
|
||||||
|
|
||||||
|
ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &rotate_mat);
|
||||||
|
ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
|
||||||
|
ok(gm2.gmCellIncY == -lf.lfHeight,
|
||||||
|
"expected %d, got %d (%s:%d)\n",
|
||||||
|
-lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
|
||||||
|
|
||||||
|
lf.lfItalic = TRUE;
|
||||||
|
hfont = CreateFontIndirect(&lf);
|
||||||
|
ok(hfont != NULL, "CreateFontIndirect error %u\n", GetLastError());
|
||||||
|
DeleteObject(SelectObject(hdc, hfont));
|
||||||
|
ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
|
||||||
|
ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
|
||||||
|
ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
|
||||||
|
ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
|
||||||
|
ok(gm2.gmCellIncX == gm.gmCellIncX * 2 || broken(gm2.gmCellIncX == -lf.lfHeight),
|
||||||
|
"expected %d, got %d (%s:%d)\n",
|
||||||
|
gm.gmCellIncX * 2, gm2.gmCellIncX, lf.lfFaceName, lf.lfCharSet);
|
||||||
|
|
||||||
|
lf.lfItalic = FALSE;
|
||||||
|
lf.lfEscapement = lf.lfOrientation = 2700;
|
||||||
|
hfont = CreateFontIndirect(&lf);
|
||||||
|
ok(hfont != NULL, "CreateFontIndirect error %u\n", GetLastError());
|
||||||
|
DeleteObject(SelectObject(hdc, hfont));
|
||||||
|
ret = GetGlyphOutlineA(hdc, c[i].a, GGO_METRICS, &gm2, 0, NULL, &mat);
|
||||||
|
ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError());
|
||||||
|
ok(gm2.gmCellIncY == -lf.lfHeight,
|
||||||
|
"expected %d, got %d (%s:%d)\n",
|
||||||
|
-lf.lfHeight, gm2.gmCellIncY, lf.lfFaceName, lf.lfCharSet);
|
||||||
|
|
||||||
hfont = SelectObject(hdc, old_hfont);
|
hfont = SelectObject(hdc, old_hfont);
|
||||||
DeleteObject(hfont);
|
DeleteObject(hfont);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user