[01/17] gdiplus: Add more tests for GdipMeasureString using device with custom resolution. Take 4.
Dmitry Timoshkov
dmitry at baikal.ru
Wed Aug 8 22:53:33 CDT 2012
This version of the patch tests GdipMeasureString behaviour with all supported
by gdiplus logical font units.
---
dlls/gdiplus/tests/graphics.c | 414 +++++++++++++++++++++++++++++++-----------
1 file changed, 310 insertions(+), 104 deletions(-)
diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c
index e6b6513..9542df3 100644
--- a/dlls/gdiplus/tests/graphics.c
+++ b/dlls/gdiplus/tests/graphics.c
@@ -2,6 +2,7 @@
* Unit test suite for graphics objects
*
* Copyright (C) 2007 Google (Evan Stade)
+ * Copyright (C) 2012 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,19 +19,119 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <math.h>
+#include <assert.h>
+
#include "windows.h"
#include "gdiplus.h"
#include "wingdi.h"
#include "wine/test.h"
-#include <math.h>
#define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (INT)(expected), (INT)(got))
-#define expectf_(expected, got, precision) ok(fabs((expected) - (got)) < (precision), "Expected %f, got %f\n", (expected), (got))
+#define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
#define expectf(expected, got) expectf_((expected), (got), 0.001)
#define TABLE_LEN (23)
+static const REAL mm_per_inch = 25.4;
+static const REAL point_per_inch = 72.0;
static HWND hwnd;
+/* converts a given unit to its value in pixels */
+static REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
+{
+ switch (unit)
+ {
+ case UnitPixel:
+ case UnitDisplay:
+ return units;
+ case UnitPoint:
+ return units * dpi / point_per_inch;
+ case UnitInch:
+ return units * dpi;
+ case UnitDocument:
+ return units * dpi / 300.0; /* Per MSDN */
+ case UnitMillimeter:
+ return units * dpi / mm_per_inch;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+/* converts value in pixels to a given unit */
+REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi)
+{
+ switch (unit)
+ {
+ case UnitPixel:
+ case UnitDisplay:
+ return pixels;
+ case UnitPoint:
+ return pixels * point_per_inch / dpi;
+ case UnitInch:
+ return pixels / dpi;
+ case UnitDocument:
+ return pixels * 300.0 / dpi;
+ case UnitMillimeter:
+ return pixels * mm_per_inch / dpi;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static REAL units_scale(GpUnit from, GpUnit to, REAL dpi)
+{
+ REAL pixels = units_to_pixels(1.0, from, dpi);
+ return pixels_to_units(pixels, to, dpi);
+}
+
+static GpGraphics *create_graphics(REAL res_x, REAL res_y, GpUnit unit, REAL scale)
+{
+ GpStatus status;
+ union
+ {
+ GpBitmap *bitmap;
+ GpImage *image;
+ } u;
+ GpGraphics *graphics = NULL;
+ REAL res;
+
+ status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, NULL, &u.bitmap);
+ expect(Ok, status);
+
+ status = GdipBitmapSetResolution(u.bitmap, res_x, res_y);
+ expect(Ok, status);
+ status = GdipGetImageHorizontalResolution(u.image, &res);
+ expect(Ok, status);
+ expectf(res_x, res);
+ status = GdipGetImageVerticalResolution(u.image, &res);
+ expect(Ok, status);
+ expectf(res_y, res);
+
+ status = GdipGetImageGraphicsContext(u.image, &graphics);
+ expect(Ok, status);
+ /* image is intentionally leaked to make sure that there is no
+ side effects after its destruction.
+ status = GdipDisposeImage(u.image);
+ expect(Ok, status);
+ */
+
+ status = GdipGetDpiX(graphics, &res);
+ expect(Ok, status);
+ expectf(res_x, res);
+ status = GdipGetDpiY(graphics, &res);
+ expect(Ok, status);
+ expectf(res_y, res);
+
+ status = GdipSetPageUnit(graphics, unit);
+ expect(Ok, status);
+ status = GdipSetPageScale(graphics, scale);
+ expect(Ok, status);
+
+ return graphics;
+}
+
static void test_constructor_destructor(void)
{
GpStatus stat;
@@ -3306,139 +3407,244 @@ static void test_getdc_scaled(void)
static void test_GdipMeasureString(void)
{
- static const WCHAR fontname[] = { 'T','a','h','o','m','a',0 };
+ static const struct test_data
+ {
+ REAL res_x, res_y, page_scale;
+ GpUnit unit;
+ } td[] =
+ {
+ { 200.0, 200.0, 1.0, UnitPixel }, /* base */
+ { 200.0, 200.0, 2.0, UnitPixel },
+ { 200.0, 200.0, 1.0, UnitDisplay },
+ { 200.0, 200.0, 2.0, UnitDisplay },
+ { 200.0, 200.0, 1.0, UnitInch },
+ { 200.0, 200.0, 2.0, UnitInch },
+ { 200.0, 600.0, 1.0, UnitPoint },
+ { 200.0, 600.0, 2.0, UnitPoint },
+ { 200.0, 600.0, 1.0, UnitDocument },
+ { 200.0, 600.0, 2.0, UnitDocument },
+ { 200.0, 600.0, 1.0, UnitMillimeter },
+ { 200.0, 600.0, 2.0, UnitMillimeter },
+ { 200.0, 600.0, 1.0, UnitDisplay },
+ { 200.0, 600.0, 2.0, UnitDisplay },
+ { 200.0, 600.0, 1.0, UnitPixel },
+ { 200.0, 600.0, 2.0, UnitPixel },
+ };
+ static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
static const WCHAR string[] = { '1','2','3','4','5','6','7',0 };
GpStatus status;
GpGraphics *graphics;
GpFontFamily *family;
GpFont *font;
- HDC hdc;
GpStringFormat *format;
- RectF bounds, rc = { 0.0, 0.0, 0.0, 0.0 };
- REAL rval, dpi;
+ RectF bounds, rc, empty_rc = { 0.0, 0.0, 0.0, 0.0 };
+ REAL base_cx, base_cy, height;
+ INT chars, lines;
+ LOGFONTW lf;
+ HDC display;
+ UINT i, font_dpi;
+ REAL font_to_pixel_scale, font_size;
+ GpUnit font_unit, unit;
+
+ display = CreateCompatibleDC(0);
+ ok(display != 0, "CreateCompatibleDC failed\n");
+ font_dpi = GetDeviceCaps(display, LOGPIXELSY);
+ DeleteDC(display);
- hdc = CreateCompatibleDC(0);
- ok(hdc != 0, "CreateCompatibleDC failed\n");
- status = GdipCreateFromHDC(hdc, &graphics);
+ status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
expect(Ok, status);
- status = GdipGetDpiY(graphics, &dpi);
+ status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
expect(Ok, status);
- status = GdipCreateFontFamilyFromName(fontname, NULL, &family);
+
+ font_to_pixel_scale = units_scale(UnitPoint, UnitPixel, font_dpi);
+ trace("font to pixel, %u dpi => unit_scale %f\n", font_dpi, font_to_pixel_scale);
+
+ /* font size in pixels */
+ status = GdipCreateFont(family, 100.0, FontStyleRegular, UnitPixel, &font);
expect(Ok, status);
- status = GdipCreateFont(family, 18.0, FontStyleRegular, UnitPoint, &font);
+ status = GdipGetFontSize(font, &font_size);
expect(Ok, status);
- status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
+ expectf(100.0, font_size);
+ status = GdipGetFontUnit(font, &font_unit);
expect(Ok, status);
+ expect(UnitPixel, font_unit);
- if (dpi == 96.0)
+ for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
{
- status = GdipSetPageUnit(graphics, UnitDisplay);
- expect(Ok, status);
+ graphics = create_graphics(td[i].res_x, td[i].res_y, td[i].unit, td[i].page_scale);
- status = GdipGetFontHeightGivenDPI(font, dpi, &rval);
+ lf.lfHeight = 0xdeadbeef;
+ status = GdipGetLogFontW(font, graphics, &lf);
expect(Ok, status);
- expectf(28.968750, rval);
+ height = units_to_pixels(font_size, td[i].unit, td[i].res_y);
+ if (td[i].unit != UnitDisplay)
+ height *= td[i].page_scale;
+ /* FIXME: remove once Wine is fixed */
+ if (td[i].unit == UnitDisplay || (td[i].unit == UnitPixel && td[i].page_scale == 1.0))
+ ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %d (%f), got %d\n",
+ i, (LONG)(height + 0.5), height, lf.lfHeight);
+ else
+ {
+ todo_wine
+ ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %d (%f), got %d\n",
+ i, (LONG)(height + 0.5), height, lf.lfHeight);
+ /* further testing is useless */
+ GdipDeleteGraphics(graphics);
+ continue;
+ }
- status = GdipGetFontHeight(font, graphics, &rval);
- expect(Ok, status);
- expectf(28.968750, rval);
- status = GdipGetFontSize(font, &rval);
- expect(Ok, status);
- expectf(18.0, rval);
+ height = font_size * font_to_pixel_scale;
- status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, NULL, NULL);
+ rc = empty_rc;
+ bounds = empty_rc;
+ status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
expect(Ok, status);
- expectf(0.0, bounds.X);
- expectf(0.0, bounds.Y);
- expectf_(102.499985, bounds.Width, 11.5);
- expectf_(31.968744, bounds.Height, 3.1);
- }
- else
- skip("screen resolution %f dpi, test runs at 96 dpi\n", dpi);
-
- status = GdipSetPageUnit(graphics, UnitPoint);
- expect(Ok, status);
- status = GdipGetFontHeight(font, graphics, &rval);
- expect(Ok, status);
- expectf(21.726563, rval);
- status = GdipGetFontSize(font, &rval);
- expect(Ok, status);
- expectf(18.0, rval);
-
- status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, NULL, NULL);
- expect(Ok, status);
- expectf(0.0, bounds.X);
- expectf(0.0, bounds.Y);
- expectf_(76.875000, bounds.Width, 10.0);
- expectf_(23.976563, bounds.Height, 2.1);
+ if (i == 0)
+ {
+ base_cx = bounds.Width;
+ base_cy = bounds.Height;
+ }
- status = GdipSetPageUnit(graphics, UnitMillimeter);
- expect(Ok, status);
+ /* FIXME: remove once Wine is fixed */
+ if (fabs(height - bounds.Height) > height / 100.0)
+ {
+ /* further testing is useless */
+ GdipDeleteGraphics(graphics);
+ continue;
+ }
- status = GdipGetFontHeight(font, graphics, &rval);
- expect(Ok, status);
- expectf(7.664648, rval);
- status = GdipGetFontSize(font, &rval);
- expect(Ok, status);
- expectf(18.0, rval);
+ expectf(0.0, bounds.X);
+ expectf(0.0, bounds.Y);
+ expectf_(height, bounds.Height, height / 100.0);
+ expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.05);
+ expect(7, chars);
+ expect(1, lines);
+
+ /* make sure it really fits */
+ bounds.Width += 1.0;
+ bounds.Height += 1.0;
+ rc = bounds;
+ rc.X = 50.0;
+ rc.Y = 50.0;
+ bounds = empty_rc;
+ status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
+ expect(Ok, status);
+ expectf(50.0, bounds.X);
+ expectf(50.0, bounds.Y);
+ expectf_(height, bounds.Height, height / 100.0);
+ expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.05);
+ expect(7, chars);
+ expect(1, lines);
- status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, NULL, NULL);
- expect(Ok, status);
- expectf(0.0, bounds.X);
- expectf(0.0, bounds.Y);
- expectf_(27.119789, bounds.Width, 2.7);
- expectf_(8.458398, bounds.Height, 0.8);
+ status = GdipDeleteGraphics(graphics);
+ expect(Ok, status);
+ }
- GdipDeleteStringFormat(format);
GdipDeleteFont(font);
- GdipDeleteFontFamily(family);
- GdipDeleteGraphics(graphics);
- DeleteDC(hdc);
-}
-
-static GpGraphics *create_graphics(REAL res_x, REAL res_y, GpUnit unit, REAL scale)
-{
- GpStatus status;
- union
+ /* font size in logical units */
+ /* UnitPoint = 3, UnitInch = 4, UnitDocument = 5, UnitMillimeter = 6 */
+ for (unit = 3; unit <= 6; unit++)
{
- GpBitmap *bitmap;
- GpImage *image;
- } u;
- GpGraphics *graphics = NULL;
- REAL res;
-
- status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, NULL, &u.bitmap);
- expect(Ok, status);
-
- status = GdipBitmapSetResolution(u.bitmap, res_x, res_y);
- expect(Ok, status);
- status = GdipGetImageHorizontalResolution(u.image, &res);
- expect(Ok, status);
- expectf(res_x, res);
- status = GdipGetImageVerticalResolution(u.image, &res);
- expect(Ok, status);
- expectf(res_y, res);
+ /* create a font which final height is 100.0 pixels with 200 dpi device */
+ height = pixels_to_units(100.0 / font_to_pixel_scale, unit, 200.0);
+ status = GdipCreateFont(family, height, FontStyleRegular, unit, &font);
+ expect(Ok, status);
+ status = GdipGetFontSize(font, &font_size);
+ expect(Ok, status);
+ expectf(height, font_size);
+ status = GdipGetFontUnit(font, &font_unit);
+ expect(Ok, status);
+ expect(unit, font_unit);
+
+ for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ {
+ REAL unit_scale;
+
+ graphics = create_graphics(td[i].res_x, td[i].res_y, td[i].unit, td[i].page_scale);
+
+ lf.lfHeight = 0xdeadbeef;
+ status = GdipGetLogFontW(font, graphics, &lf);
+ expect(Ok, status);
+ if (td[i].unit == UnitDisplay || td[i].unit == UnitPixel)
+ height = units_to_pixels(font_size, font_unit, td[i].res_x);
+ else
+ height = units_to_pixels(font_size, font_unit, td[i].res_y);
+ /*trace("%.1f font units = %f pixels with %.1f dpi, page_scale %.1f\n", font_size, height, td[i].res_y, td[i].page_scale);*/
+todo_wine
+ ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %d (%f), got %d\n",
+ i, (LONG)(height + 0.5), height, lf.lfHeight);
+
+ if (td[i].unit == UnitDisplay || td[i].unit == UnitPixel)
+ unit_scale = units_scale(font_unit, td[i].unit, td[i].res_x);
+ else
+ unit_scale = units_scale(font_unit, td[i].unit, td[i].res_y);
+ /*trace("%u: %d to %d, %.1f dpi => unit_scale %f\n", i, font_unit, td[i].unit, td[i].res_y, unit_scale);*/
+ height = font_size * font_to_pixel_scale * unit_scale;
+ if (td[i].unit != UnitDisplay)
+ height /= td[i].page_scale;
+ /*trace("%u: %.1f font units = %f units with %.1f dpi, page_scale %.1f\n", i, font_size, height, td[i].res_y, td[i].page_scale);*/
+
+ rc = empty_rc;
+ bounds = empty_rc;
+ status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
+ expect(Ok, status);
+
+ if (i == 0)
+ {
+ base_cx = bounds.Width;
+ base_cy = bounds.Height;
+ }
- status = GdipGetImageGraphicsContext(u.image, &graphics);
- expect(Ok, status);
- status = GdipDisposeImage(u.image);
- expect(Ok, status);
+ /* FIXME: remove once Wine is fixed */
+ if (fabs(height - bounds.Height) > height / 85.0)
+ {
+ /* further testing is useless */
+ GdipDeleteGraphics(graphics);
+ continue;
+ }
- status = GdipGetDpiX(graphics, &res);
- expect(Ok, status);
- expectf(res_x, res);
- status = GdipGetDpiY(graphics, &res);
- expect(Ok, status);
- expectf(res_y, res);
+ expectf(0.0, bounds.X);
+ expectf(0.0, bounds.Y);
+ expectf_(height, bounds.Height, height / 85.0);
+ expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.05);
+ expect(7, chars);
+ expect(1, lines);
+
+ /* make sure it really fits */
+ bounds.Width += 1.0;
+ bounds.Height += 1.0;
+ rc = bounds;
+ rc.X = 50.0;
+ rc.Y = 50.0;
+ bounds = empty_rc;
+ status = GdipMeasureString(graphics, string, -1, font, &rc, format, &bounds, &chars, &lines);
+ expect(Ok, status);
+ expectf(50.0, bounds.X);
+ expectf(50.0, bounds.Y);
+ expectf_(height, bounds.Height, height / 85.0);
+ expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.05);
+ expect(7, chars);
+ expect(1, lines);
+
+ /* verify the result */
+ height = units_to_pixels(bounds.Height, td[i].unit, td[i].res_x);
+ if (td[i].unit != UnitDisplay)
+ height *= td[i].page_scale;
+ /*trace("%u: unit %u, %.1fx%.1f dpi, scale %.1f, height %f, pixels %f\n",
+ i, td[i].unit, td[i].res_x, td[i].res_y, td[i].page_scale, bounds.Height, height);*/
+ expectf_(100.0, height, 1.0);
+
+ status = GdipDeleteGraphics(graphics);
+ expect(Ok, status);
+ }
- status = GdipSetPageUnit(graphics, unit);
- expect(Ok, status);
- status = GdipSetPageScale(graphics, scale);
- expect(Ok, status);
+ GdipDeleteFont(font);
+ }
- return graphics;
+ GdipDeleteFontFamily(family);
+ GdipDeleteStringFormat(format);
}
static void test_transform(void)
--
1.7.11.4
More information about the wine-patches
mailing list