Needed by Cygwin's mintty.exe.
Signed-off-by: Zebediah Figura <z.figura12(a)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.
--
2.23.0