[2/2] gdiplus: Add support for generic typographic string format.

Dmitry Timoshkov dmitry at baikal.ru
Mon Sep 3 03:57:17 CDT 2012


Application in the bug 31601 depends on this.
---
 dlls/gdiplus/gdiplus_private.h |  1 +
 dlls/gdiplus/graphics.c        | 89 ++++++++++++++++++++++++------------------
 dlls/gdiplus/stringformat.c    |  4 ++
 3 files changed, 56 insertions(+), 38 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 9c0e722..d44c969 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -368,6 +368,7 @@ struct GpStringFormat{
     REAL *tabs;
     CharacterRange *character_ranges;
     INT range_count;
+    BOOL generic_typographic;
 };
 
 struct GpFontCollection{
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 96e2533..e986c94 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -46,6 +46,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
 #define ANCHOR_WIDTH (2.0)
 #define MAX_ITERS (50)
 
+static GpStatus draw_driver_string(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
+                                   GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format,
+                                   GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
+                                   INT flags, GDIPCONST GpMatrix *matrix);
+
 /* Converts angle (in degrees) to x/y coordinates */
 static void deg2xy(REAL angle, REAL x_0, REAL y_0, REAL *x, REAL *y)
 {
@@ -2110,7 +2115,8 @@ end:
     return stat;
 }
 
-static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font, HFONT *hfont)
+static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font,
+                           GDIPCONST GpStringFormat *format, HFONT *hfont)
 {
     HDC hdc = CreateCompatibleDC(0);
     GpPointF pt[3];
@@ -2119,7 +2125,7 @@ static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font, HFONT *
     HFONT unscaled_font;
     TEXTMETRICW textmet;
 
-    font_to_pixel_scale = units_scale(UnitPoint, UnitPixel, font->family->dpi);
+    font_to_pixel_scale = (format && format->generic_typographic) ? 1.0 : units_scale(UnitPoint, UnitPixel, font->family->dpi);
 
     if (font->unit == UnitPixel)
         font_height = font->emSize * font_to_pixel_scale;
@@ -4972,8 +4978,8 @@ 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));
 
-    /* FIXME: GenericTypographic format prevents extra margins */
-    margin_x = units_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0;
+    margin_x = stringFormat->generic_typographic ? 0.0 : font->emSize / 6.0;
+    margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
 
     scaled_rect.X = (layoutRect->X + margin_x) * args.rel_width;
     scaled_rect.Y = layoutRect->Y * args.rel_height;
@@ -4993,7 +4999,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
         if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
     }
 
-    get_font_hfont(graphics, font, &gdifont);
+    get_font_hfont(graphics, font, stringFormat, &gdifont);
     oldfont = SelectObject(hdc, gdifont);
 
     for (i=0; i<stringFormat->range_count; i++)
@@ -5101,8 +5107,8 @@ 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));
 
-    /* FIXME: GenericTypographic format prevents extra margins */
-    margin_x = units_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0;
+    margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
+    margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
 
     scaled_rect.X = (rect->X + margin_x) * args.rel_width;
     scaled_rect.Y = rect->Y * args.rel_height;
@@ -5123,7 +5129,7 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
     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);
+    get_font_hfont(graphics, font, format, &gdifont);
     oldfont = SelectObject(hdc, gdifont);
 
     bounds->X = rect->X;
@@ -5173,7 +5179,7 @@ static GpStatus draw_string_callback(HDC hdc,
     position.X = args->x + bounds->X / args->rel_width;
     position.Y = args->y + bounds->Y / args->rel_height + args->ascent;
 
-    stat = GdipDrawDriverString(args->graphics, &string[index], length, font,
+    stat = draw_driver_string(args->graphics, &string[index], length, font, format,
         args->brush, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance, NULL);
 
@@ -5280,8 +5286,8 @@ 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);
 
-    /* FIXME: GenericTypographic format prevents extra margins */
-    margin_x = units_scale(font->unit, graphics->unit, graphics->xres) * font->emSize / 6.0;
+    margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
+    margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
 
     scaled_rect.X = margin_x * rel_width;
     scaled_rect.Y = 0.0;
@@ -5310,7 +5316,7 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
         SelectClipRgn(hdc, rgn);
     }
 
-    get_font_hfont(graphics, font, &gdifont);
+    get_font_hfont(graphics, font, format, &gdifont);
     SelectObject(hdc, gdifont);
 
     args.graphics = graphics;
@@ -6269,7 +6275,7 @@ GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT
     if (matrix)
         FIXME("Ignoring matrix\n");
 
-    get_font_hfont(graphics, font, &hfont);
+    get_font_hfont(graphics, font, NULL, &hfont);
 
     hdc = CreateCompatibleDC(0);
     SelectObject(hdc, hfont);
@@ -6345,9 +6351,9 @@ GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT
 }
 
 static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
-                                     GDIPCONST GpFont *font, GDIPCONST GpBrush *brush,
-                                     GDIPCONST PointF *positions, INT flags,
-                                     GDIPCONST GpMatrix *matrix )
+                                           GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format,
+                                           GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
+                                           INT flags, GDIPCONST GpMatrix *matrix)
 {
     static const INT unsupported_flags = ~(DriverStringOptionsRealizedAdvance|DriverStringOptionsCmapLookup);
     INT save_state;
@@ -6371,7 +6377,7 @@ static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT1
     pt = positions[0];
     GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &pt, 1);
 
-    get_font_hfont(graphics, font, &hfont);
+    get_font_hfont(graphics, font, format, &hfont);
     SelectObject(graphics->hdc, hfont);
 
     SetTextAlign(graphics->hdc, TA_BASELINE|TA_LEFT);
@@ -6386,9 +6392,9 @@ static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT1
 }
 
 static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
-                                         GDIPCONST GpFont *font, GDIPCONST GpBrush *brush,
-                                         GDIPCONST PointF *positions, INT flags,
-                                         GDIPCONST GpMatrix *matrix )
+                                        GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format,
+                                        GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
+                                        INT flags, GDIPCONST GpMatrix *matrix)
 {
     static const INT unsupported_flags = ~(DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance);
     GpStatus stat;
@@ -6446,7 +6452,7 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
         GdipFree(real_positions);
     }
 
-    get_font_hfont(graphics, font, &hfont);
+    get_font_hfont(graphics, font, format, &hfont);
 
     hdc = CreateCompatibleDC(0);
     SelectObject(hdc, hfont);
@@ -6579,6 +6585,28 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
     return stat;
 }
 
+static GpStatus draw_driver_string(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
+                                   GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format,
+                                   GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
+                                   INT flags, GDIPCONST GpMatrix *matrix)
+{
+    GpStatus stat = NotImplemented;
+
+    if (length == -1)
+        length = strlenW(text);
+
+    if (graphics->hdc &&
+        ((flags & DriverStringOptionsRealizedAdvance) || length <= 1) &&
+        brush->bt == BrushTypeSolidColor &&
+        (((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000)
+        stat = GDI32_GdipDrawDriverString(graphics, text, length, font, format,
+                                          brush, positions, flags, matrix);
+    if (stat == NotImplemented)
+        stat = SOFTWARE_GdipDrawDriverString(graphics, text, length, font, format,
+                                             brush, positions, flags, matrix);
+    return stat;
+}
+
 /*****************************************************************************
  * GdipDrawDriverString [GDIPLUS.@]
  */
@@ -6587,28 +6615,13 @@ GpStatus WINGDIPAPI GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16
                                          GDIPCONST PointF *positions, INT flags,
                                          GDIPCONST GpMatrix *matrix )
 {
-    GpStatus stat=NotImplemented;
-
     TRACE("(%p %s %p %p %p %d %p)\n", graphics, debugstr_wn(text, length), font, brush, positions, flags, matrix);
 
     if (!graphics || !text || !font || !brush || !positions)
         return InvalidParameter;
 
-    if (length == -1)
-        length = strlenW(text);
-
-    if (graphics->hdc &&
-        ((flags & DriverStringOptionsRealizedAdvance) || length <= 1) &&
-        brush->bt == BrushTypeSolidColor &&
-        (((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000)
-        stat = GDI32_GdipDrawDriverString(graphics, text, length, font, brush,
-            positions, flags, matrix);
-
-    if (stat == NotImplemented)
-        stat = SOFTWARE_GdipDrawDriverString(graphics, text, length, font, brush,
-            positions, flags, matrix);
-
-    return stat;
+    return draw_driver_string(graphics, text, length, font, NULL,
+                              brush, positions, flags, matrix);
 }
 
 GpStatus WINGDIPAPI GdipRecordMetafileStream(IStream *stream, HDC hdc, EmfType type, GDIPCONST GpRect *frameRect,
diff --git a/dlls/gdiplus/stringformat.c b/dlls/gdiplus/stringformat.c
index cf6ea1f..7d6bcb0 100644
--- a/dlls/gdiplus/stringformat.c
+++ b/dlls/gdiplus/stringformat.c
@@ -50,6 +50,7 @@ GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang,
     (*format)->digitsub = StringDigitSubstituteUser;
     (*format)->character_ranges = NULL;
     (*format)->range_count = 0;
+    (*format)->generic_typographic = FALSE;
     /* tabstops */
     (*format)->tabcount = 0;
     (*format)->firsttab = 0.0;
@@ -386,6 +387,9 @@ GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **forma
     (*format)->hkprefix  = HotkeyPrefixNone;
     (*format)->align     = StringAlignmentNear;
     (*format)->vertalign = StringAlignmentNear;
+    (*format)->generic_typographic = TRUE;
+
+    TRACE("%p => %p\n", format, *format);
 
     return Ok;
 }
-- 
1.7.11.5




More information about the wine-patches mailing list