Needed by Cygwin's mintty.exe.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/gdi32/font.c | 57 ++++++++++++++++++++++++++++++++++------- dlls/gdi32/tests/font.c | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 9 deletions(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index b06ff6d354a..d451f30c3ee 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -36,6 +36,7 @@ #include "winreg.h" #include "gdi_private.h" #include "wine/exception.h" +#include "wine/heap.h" #include "wine/unicode.h" #include "wine/debug.h"
@@ -3471,23 +3472,61 @@ done: /************************************************************************* * GetCharWidthFloatA [GDI32.@] */ -BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar, - UINT iLastChar, PFLOAT pxBuffer) +BOOL WINAPI GetCharWidthFloatA( HDC hdc, UINT first, UINT last, float *buffer ) { - FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer); - return FALSE; + WCHAR *wstr; + int i, wlen; + char *str; + + if (!(str = FONT_GetCharsByRangeA( hdc, first, last, &i ))) + return FALSE; + wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL ); + heap_free(str); + + for (i = 0; i < wlen; ++i) + { + if (!GetCharWidthFloatW( hdc, wstr[i], wstr[i], &buffer[i] )) + { + heap_free(wstr); + return FALSE; + } + } + heap_free(wstr); + return TRUE; }
/************************************************************************* * GetCharWidthFloatW [GDI32.@] */ -BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar, - UINT iLastChar, PFLOAT pxBuffer) +BOOL WINAPI GetCharWidthFloatW( HDC hdc, UINT first, UINT last, float *buffer ) { - FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer); - return FALSE; -} + DC *dc = get_dc_ptr( hdc ); + int *ibuffer; + PHYSDEV dev; + BOOL ret; + UINT i; + + TRACE("dc %p, first %#x, last %#x, buffer %p\n", dc, first, last, buffer); + + if (!dc) return FALSE;
+ if (!(ibuffer = heap_alloc( (last - first + 1) * sizeof(int) ))) + { + release_dc_ptr( dc ); + return FALSE; + } + + dev = GET_DC_PHYSDEV( dc, pGetCharWidth ); + if ((ret = dev->funcs->pGetCharWidth( dev, first, last, ibuffer ))) + { + float scale = fabs( dc->xformVport2World.eM11 ) / 16.0f; + for (i = first; i <= last; ++i) + buffer[i - first] = ibuffer[i - first] * scale; + } + + heap_free(ibuffer); + return ret; +}
/*********************************************************************** * * diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index b57effd349d..ccae09edc19 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -7189,6 +7189,51 @@ static void test_GetCharWidthInfo(void) ReleaseDC(NULL, hdc); }
+static int CALLBACK get_char_width_proc(const LOGFONTA *lf, + const TEXTMETRICA *tm, DWORD type, LPARAM ctx) +{ + HFONT font = CreateFontIndirectA(lf); + HDC dc = GetDC(NULL); + const char c = 'm'; + ABCFLOAT abcf; + int i, i32; + BOOL ret; + float f; + ABC abc; + + SelectObject(dc, font); + + ret = GetCharWidthFloatA(dc, c, c, &f); + ok(ret, "%s: GetCharWidthFloat() failed\n", lf->lfFaceName); + ret = GetCharWidth32A(dc, c, c, &i32); + ok(ret, "%s: GetCharWidth32A() failed\n", lf->lfFaceName); + ret = GetCharWidthA(dc, c, c, &i); + ok(ret, "%s: GetCharWidthA() failed\n", lf->lfFaceName); + ok(i == i32, "%s: mismatched widths %d/%d\n", lf->lfFaceName, i, i32); + ok((float)i / 16.0f == f, "%s: mismatched widths %d/%.8e\n", lf->lfFaceName, i, f); + + ret = GetCharABCWidthsFloatA(dc, c, c, &abcf); + ok(ret, "%s: GetCharABCWidths() failed\n", lf->lfFaceName); + if (GetCharABCWidthsA(dc, c, c, &abc)) + ok((float)abc.abcB == abcf.abcfB, "%s: mismatched widths %d/%.8e\n", + lf->lfFaceName, abc.abcB, abcf.abcfB); + + ReleaseDC(NULL, dc); + DeleteObject(font); + return 1; +} + +static void test_char_width(void) +{ + HDC dc = GetDC(NULL); + LOGFONTA lf = {0}; + + lf.lfCharSet = DEFAULT_CHARSET; + EnumFontFamiliesExA(dc, &lf, get_char_width_proc, 0, 0); + + ReleaseDC(NULL, dc); +} + START_TEST(font) { static const char *test_names[] = @@ -7271,6 +7316,7 @@ START_TEST(font) test_bitmap_font_glyph_index(); test_GetCharWidthI(); test_long_names(); + test_char_width();
/* These tests should be last test until RemoveFontResource * is properly implemented.
On Thu, Sep 26, 2019 at 09:17:03AM -0500, Zebediah Figura wrote:
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index b57effd349d..ccae09edc19 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -7189,6 +7189,51 @@ static void test_GetCharWidthInfo(void) ReleaseDC(NULL, hdc); }
+static int CALLBACK get_char_width_proc(const LOGFONTA *lf,
const TEXTMETRICA *tm, DWORD type, LPARAM ctx)
+{
- HFONT font = CreateFontIndirectA(lf);
- HDC dc = GetDC(NULL);
- const char c = 'm';
- ABCFLOAT abcf;
- int i, i32;
- BOOL ret;
- float f;
- ABC abc;
- SelectObject(dc, font);
- ret = GetCharWidthFloatA(dc, c, c, &f);
- ok(ret, "%s: GetCharWidthFloat() failed\n", lf->lfFaceName);
- ret = GetCharWidth32A(dc, c, c, &i32);
- ok(ret, "%s: GetCharWidth32A() failed\n", lf->lfFaceName);
- ret = GetCharWidthA(dc, c, c, &i);
- ok(ret, "%s: GetCharWidthA() failed\n", lf->lfFaceName);
- ok(i == i32, "%s: mismatched widths %d/%d\n", lf->lfFaceName, i, i32);
- ok((float)i / 16.0f == f, "%s: mismatched widths %d/%.8e\n", lf->lfFaceName, i, f);
This factor of sixteen is strange. Is it perhaps possible that the selected font has a ppem of sixteen and that GetCharWidthFloat() returns widths as a fraction of the em square width?
Huw.
On 10/16/2019 05:23 AM, Huw Davies wrote:
On Thu, Sep 26, 2019 at 09:17:03AM -0500, Zebediah Figura wrote:
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index b57effd349d..ccae09edc19 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -7189,6 +7189,51 @@ static void test_GetCharWidthInfo(void) ReleaseDC(NULL, hdc); }
+static int CALLBACK get_char_width_proc(const LOGFONTA *lf,
const TEXTMETRICA *tm, DWORD type, LPARAM ctx)
+{
- HFONT font = CreateFontIndirectA(lf);
- HDC dc = GetDC(NULL);
- const char c = 'm';
- ABCFLOAT abcf;
- int i, i32;
- BOOL ret;
- float f;
- ABC abc;
- SelectObject(dc, font);
- ret = GetCharWidthFloatA(dc, c, c, &f);
- ok(ret, "%s: GetCharWidthFloat() failed\n", lf->lfFaceName);
- ret = GetCharWidth32A(dc, c, c, &i32);
- ok(ret, "%s: GetCharWidth32A() failed\n", lf->lfFaceName);
- ret = GetCharWidthA(dc, c, c, &i);
- ok(ret, "%s: GetCharWidthA() failed\n", lf->lfFaceName);
- ok(i == i32, "%s: mismatched widths %d/%d\n", lf->lfFaceName, i, i32);
- ok((float)i / 16.0f == f, "%s: mismatched widths %d/%.8e\n", lf->lfFaceName, i, f);
This factor of sixteen is strange. Is it perhaps possible that the selected font has a ppem of sixteen and that GetCharWidthFloat() returns widths as a fraction of the em square width?
It is strange, but as the tests imply, it remained true for me for every font on my system. I didn't check the ppem, and it's possible they all have 16, but on the other hand mintty has that factor hard-coded in [1].
[1] https://github.com/mintty/mintty/blob/master/src/wintext.c
Huw.