[3/3] gdiplus: Make GdipMeasureCharacterRanges/GdipMeasureString/GdipDrawString add extra space around the text.

Dmitry Timoshkov dmitry at baikal.ru
Fri Aug 24 01:44:43 CDT 2012


GdipMeasureString and GdipDrawString also add extra space to height of
the bounding rectangle, but that needs additional code changes.

These APIs use different logic for adding extra space, so at the moment
I don't see how gdip_format_string() can be used to do this in one place,
but if somebody has an idea how to do that - patches are welcome.
---
 dlls/gdiplus/graphics.c       | 53 ++++++++++++++++++++++++++++++++++++-------
 dlls/gdiplus/tests/graphics.c | 26 ++++++++++++++++-----
 2 files changed, 65 insertions(+), 14 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index a0c130e..9405b78 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -4932,6 +4932,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
     HDC hdc, temp_hdc=NULL;
     GpPointF pt[3];
     RectF scaled_rect;
+    REAL margin_x;
 
     TRACE("(%p %s %d %p %s %p %d %p)\n", graphics, debugstr_w(string),
             length, font, debugstr_rectf(layoutRect), stringFormat, regionCount, regions);
@@ -4965,10 +4966,18 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
     args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
                       (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
 
-    scaled_rect.X = layoutRect->X * args.rel_width;
+    /* FIXME: GenericTypographic format prevents extra margins */
+    margin_x = units_to_pixels(font->emSize / 6.0, font->unit, graphics->xres);
+
+    scaled_rect.X = layoutRect->X * args.rel_width + margin_x;
     scaled_rect.Y = layoutRect->Y * args.rel_height;
     scaled_rect.Width = layoutRect->Width * args.rel_width;
     scaled_rect.Height = layoutRect->Height * args.rel_height;
+    if (scaled_rect.Width >= 0.5)
+    {
+        scaled_rect.Width -= margin_x * 2.0;
+        if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
+    }
 
     get_font_hfont(graphics, font, &gdifont);
     oldfont = SelectObject(hdc, gdifont);
@@ -5042,6 +5051,8 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
     HDC temp_hdc=NULL, hdc;
     GpPointF pt[3];
     RectF scaled_rect;
+    REAL margin_x;
+    INT lines, glyphs;
 
     TRACE("(%p, %s, %i, %p, %s, %p, %p, %p, %p)\n", graphics,
         debugstr_wn(string, length), length, font, debugstr_rectf(rect), format,
@@ -5076,13 +5087,21 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
     args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
                       (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
 
-    get_font_hfont(graphics, font, &gdifont);
-    oldfont = SelectObject(hdc, gdifont);
+    /* FIXME: GenericTypographic format prevents extra margins */
+    margin_x = units_to_pixels(font->emSize / 6.0, font->unit, graphics->xres);
 
-    scaled_rect.X = rect->X * args.rel_width;
+    scaled_rect.X = rect->X * args.rel_width + margin_x;
     scaled_rect.Y = rect->Y * args.rel_height;
     scaled_rect.Width = rect->Width * args.rel_width;
     scaled_rect.Height = rect->Height * args.rel_height;
+    if (scaled_rect.Width >= 0.5)
+    {
+        scaled_rect.Width -= margin_x * 2.0;
+        if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
+    }
+
+    get_font_hfont(graphics, font, &gdifont);
+    oldfont = SelectObject(hdc, gdifont);
 
     if (scaled_rect.Width >= INT_MAX || scaled_rect.Width < 0.5) scaled_rect.Width = (REAL)(1 << 23);
     if (scaled_rect.Height >= INT_MAX || scaled_rect.Height < 0.5) scaled_rect.Height = (REAL)(1 << 23);
@@ -5093,12 +5112,22 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
     bounds->Height = 0.0;
 
     args.bounds = bounds;
-    args.codepointsfitted = codepointsfitted;
-    args.linesfilled = linesfilled;
+    args.codepointsfitted = &glyphs;
+    args.linesfilled = &lines;
+    lines = glyphs = 0;
 
     gdip_format_string(hdc, string, length, font, &scaled_rect, format,
         measure_string_callback, &args);
 
+    if (linesfilled) *linesfilled = lines;
+    if (codepointsfitted) *codepointsfitted = glyphs;
+
+    if (lines)
+    {
+        margin_x = pixels_to_units(margin_x, graphics->unit, graphics->xres);
+        bounds->Width += margin_x * 2.0;
+    }
+
     SelectObject(hdc, oldfont);
     DeleteObject(gdifont);
 
@@ -5169,7 +5198,7 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
     HFONT gdifont;
     GpPointF pt[3], rectcpy[4];
     POINT corners[4];
-    REAL rel_width, rel_height;
+    REAL rel_width, rel_height, margin_x;
     INT save_state;
     REAL offsety = 0.0;
     struct draw_string_args args;
@@ -5232,10 +5261,18 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
     rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height;
     transform_and_round_points(graphics, corners, rectcpy, 4);
 
-    scaled_rect.X = 0.0;
+    /* FIXME: GenericTypographic format prevents extra margins */
+    margin_x = units_to_pixels(font->emSize / 6.0, font->unit, graphics->xres);
+
+    scaled_rect.X = margin_x;
     scaled_rect.Y = 0.0;
     scaled_rect.Width = rel_width * rect->Width;
     scaled_rect.Height = rel_height * rect->Height;
+    if (scaled_rect.Width >= 0.5)
+    {
+        scaled_rect.Width -= margin_x * 2.0;
+        if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
+    }
 
     if (scaled_rect.Width >= INT_MAX || scaled_rect.Width < 0.5) scaled_rect.Width = (REAL)(1 << 23);
     if (scaled_rect.Height >= INT_MAX || scaled_rect.Height < 0.5) scaled_rect.Height = (REAL)(1 << 23);
diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c
index 1cd847d..f2c425d 100644
--- a/dlls/gdiplus/tests/graphics.c
+++ b/dlls/gdiplus/tests/graphics.c
@@ -3531,7 +3531,7 @@ static void test_GdipMeasureString(void)
         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);
+        expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
         expect(7, chars);
         expect(1, lines);
 
@@ -3547,7 +3547,7 @@ static void test_GdipMeasureString(void)
         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);
+        expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
         expect(7, chars);
         expect(1, lines);
 
@@ -3614,7 +3614,7 @@ static void test_GdipMeasureString(void)
             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);
+            expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
             expect(7, chars);
             expect(1, lines);
 
@@ -3630,7 +3630,7 @@ static void test_GdipMeasureString(void)
             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);
+            expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
             expect(7, chars);
             expect(1, lines);
 
@@ -3806,6 +3806,7 @@ static void test_font_height_scaling(void)
             /* margin = [bounds.width of 1] - [bounds.width of 2] / 2*/
             margin = bounds_1.Width - bounds_2.Width / 2.0;
             /*trace("margin %f\n", margin);*/
+            ok(margin > 0.0, "wrong margin %f\n", margin);
 
             status = GdipGetFontHeight(font, graphics, &height);
             expect(Ok, status);
@@ -3819,10 +3820,24 @@ static void test_font_height_scaling(void)
             status = GdipGetRegionBounds(region, graphics, &rect);
             expect(Ok, status);
             /*trace("region: %f,%f,%f,%f\n", rect.X, rect.Y, rect.Width, rect.Height);*/
+            /* FIXME: Wine uses integer gdi32 regions and rounding breaks things */
+            if (margin < 1.0)
+            todo_wine ok(rect.X > 0.0, "wrong rect.X %f\n", rect.X);
+            else
+            ok(rect.X > 0.0, "wrong rect.X %f\n", rect.X);
             expectf(0.0, rect.Y);
             /* before Win7 GdipMeasureCharacterRanges behaviour is completely broken */
-            match = fabs(margin - rect.X) <= margin / 25.0;
+            /* FIXME: Wine uses integer gdi32 regions and rounding breaks things */
+            if (margin < 1.0)
+            {
+            match = fabs(margin - rect.X) < 0.25;
+            ok(match || broken(!match) /* before win7 */, "Expected %f, got %f\n", margin, rect.X);
+            }
+            else
+            {
+            match = fabs(margin - rect.X) <= 0.5;
             ok(match || broken(!match) /* before win7 */, "Expected %f, got %f\n", margin, rect.X);
+            }
             if (!match)
             {
                 win_skip("GdipMeasureCharacterRanges ignores units before Win7\n");
@@ -4015,7 +4030,6 @@ static void test_measured_extra_space(void)
             /* margin = [bounds.width of 1] - [bounds.width of 2] / 2*/
             margin = units_to_pixels(bounds_1.Width - bounds_2.Width / 2.0, gfx_unit, dpi);
             /*trace("margin %f pixels\n", margin);*/
-todo_wine
             expectf_(font_size / 6.0, margin, font_size / 100.0);
         }
 
-- 
1.7.11.5




More information about the wine-patches mailing list