diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index a0c130e3d67..383965a023d 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_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0; + + scaled_rect.X = (layoutRect->X + margin_x) * args.rel_width; 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 * args.rel_width; + 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,29 +5087,44 @@ 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_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0; - scaled_rect.X = rect->X * args.rel_width; + scaled_rect.X = (rect->X + margin_x) * args.rel_width; 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 * args.rel_width; + 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); + get_font_hfont(graphics, font, &gdifont); + oldfont = SelectObject(hdc, gdifont); + bounds->X = rect->X; bounds->Y = rect->Y; bounds->Width = 0.0; 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) + bounds->Width += margin_x * 2.0; + SelectObject(hdc, oldfont); DeleteObject(gdifont); @@ -5169,7 +5195,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 +5258,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_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0; + + scaled_rect.X = margin_x * rel_width; 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 * rel_width; + 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 db2542b947c..13b89be4d88 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"); @@ -4017,7 +4032,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); }