[PATCH 2/3] gdiplus: Fix generic string formats behavior

Nikolay Sivov nsivov at codeweavers.com
Thu Apr 27 17:20:31 CDT 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/gdiplus/gdiplus.c            |  2 ++
 dlls/gdiplus/gdiplus_private.h    |  5 +++
 dlls/gdiplus/graphics.c           | 12 +------
 dlls/gdiplus/stringformat.c       | 69 ++++++++++++++++++++++++++-------------
 dlls/gdiplus/tests/stringformat.c | 52 +++++++++++++++++++++++++++--
 5 files changed, 104 insertions(+), 36 deletions(-)

diff --git a/dlls/gdiplus/gdiplus.c b/dlls/gdiplus/gdiplus.c
index 128145581d..d114ff797e 100644
--- a/dlls/gdiplus/gdiplus.c
+++ b/dlls/gdiplus/gdiplus.c
@@ -63,11 +63,13 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
     {
     case DLL_PROCESS_ATTACH:
         DisableThreadLibraryCalls( hinst );
+        init_generic_string_formats();
         break;
 
     case DLL_PROCESS_DETACH:
         if (reserved) break;
         free_installed_fonts();
+        free_generic_string_formats();
         break;
     }
     return TRUE;
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 9b0151b36c..443370a787 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -441,6 +441,8 @@ struct GpFont{
     Unit unit;
 };
 
+extern const struct GpStringFormat default_drawstring_format DECLSPEC_HIDDEN;
+
 struct GpStringFormat{
     INT attr;
     LANGID lang;
@@ -458,6 +460,9 @@ struct GpStringFormat{
     BOOL generic_typographic;
 };
 
+extern void init_generic_string_formats(void) DECLSPEC_HIDDEN;
+extern void free_generic_string_formats(void) DECLSPEC_HIDDEN;
+
 struct GpFontCollection{
     GpFontFamily **FontFamilies;
     INT count;
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index bd37d925d3..beedb9ea4a 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -4909,7 +4909,6 @@ GpStatus gdip_format_string(HDC hdc,
     INT hotkeyprefix_count=0;
     INT hotkeyprefix_pos=0, hotkeyprefix_end_pos=0;
     BOOL seen_prefix = FALSE;
-    GpStringFormat *dyn_format=NULL;
 
     if(length == -1) length = lstrlenW(string);
 
@@ -4917,15 +4916,7 @@ GpStatus gdip_format_string(HDC hdc,
     if(!stringdup) return OutOfMemory;
 
     if (!format)
-    {
-        stat = GdipStringFormatGetGenericDefault(&dyn_format);
-        if (stat != Ok)
-        {
-            heap_free(stringdup);
-            return stat;
-        }
-        format = dyn_format;
-    }
+        format = &default_drawstring_format;
 
     nwidth = rect->Width;
     nheight = rect->Height;
@@ -5075,7 +5066,6 @@ GpStatus gdip_format_string(HDC hdc,
 
     heap_free(stringdup);
     heap_free(hotkeyprefix_offsets);
-    GdipDeleteStringFormat(dyn_format);
 
     return stat;
 }
diff --git a/dlls/gdiplus/stringformat.c b/dlls/gdiplus/stringformat.c
index b89458bdeb..660731d7ce 100644
--- a/dlls/gdiplus/stringformat.c
+++ b/dlls/gdiplus/stringformat.c
@@ -32,6 +32,47 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
 
+const GpStringFormat default_drawstring_format =
+{
+    0,
+    LANG_NEUTRAL,
+    LANG_NEUTRAL,
+    StringAlignmentNear,
+    StringTrimmingCharacter,
+    HotkeyPrefixNone,
+    StringAlignmentNear,
+    StringDigitSubstituteUser,
+    0,
+    0.0,
+    NULL,
+    NULL,
+    0,
+    FALSE
+};
+
+static GpStringFormat generic_default_format;
+static GpStringFormat generic_typographic_format;
+
+void init_generic_string_formats(void)
+{
+    memcpy(&generic_default_format, &default_drawstring_format, sizeof(generic_default_format));
+
+    memcpy(&generic_typographic_format, &default_drawstring_format, sizeof(generic_typographic_format));
+    generic_typographic_format.attr = StringFormatFlagsNoFitBlackBox | StringFormatFlagsLineLimit |
+        StringFormatFlagsNoClip;
+    generic_typographic_format.trimming = StringTrimmingNone;
+    generic_typographic_format.generic_typographic = TRUE;
+}
+
+void free_generic_string_formats(void)
+{
+    heap_free(generic_default_format.character_ranges);
+    heap_free(generic_default_format.tabs);
+
+    heap_free(generic_typographic_format.character_ranges);
+    heap_free(generic_typographic_format.tabs);
+}
+
 GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang,
     GpStringFormat **format)
 {
@@ -66,6 +107,9 @@ GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format)
     if(!format)
         return InvalidParameter;
 
+    if (format == &generic_default_format || format == &generic_typographic_format)
+        return Ok;
+
     heap_free(format->character_ranges);
     heap_free(format->tabs);
     heap_free(format);
@@ -75,17 +119,10 @@ GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format)
 
 GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format)
 {
-    GpStatus stat;
-
     if (!format)
         return InvalidParameter;
 
-    stat = GdipCreateStringFormat(0, LANG_NEUTRAL, format);
-    if(stat != Ok)
-        return stat;
-
-    (*format)->align     = StringAlignmentNear;
-    (*format)->vertalign = StringAlignmentNear;
+    *format = &generic_default_format;
 
     return Ok;
 }
@@ -370,24 +407,10 @@ GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpSt
 
 GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format)
 {
-    GpStatus stat;
-
     if(!format)
         return InvalidParameter;
 
-    stat = GdipCreateStringFormat(StringFormatFlagsNoFitBlackBox |
-                                  StringFormatFlagsLineLimit |
-                                  StringFormatFlagsNoClip, LANG_NEUTRAL, format);
-    if(stat != Ok)
-        return stat;
-
-    (*format)->digitlang = LANG_NEUTRAL;
-    (*format)->digitsub  = StringDigitSubstituteUser;
-    (*format)->trimming  = StringTrimmingNone;
-    (*format)->hkprefix  = HotkeyPrefixNone;
-    (*format)->align     = StringAlignmentNear;
-    (*format)->vertalign = StringAlignmentNear;
-    (*format)->generic_typographic = TRUE;
+    *format = &generic_typographic_format;
 
     TRACE("%p => %p\n", format, *format);
 
diff --git a/dlls/gdiplus/tests/stringformat.c b/dlls/gdiplus/tests/stringformat.c
index f7f7a8f498..0774e1b79d 100644
--- a/dlls/gdiplus/tests/stringformat.c
+++ b/dlls/gdiplus/tests/stringformat.c
@@ -140,7 +140,7 @@ static void test_digitsubstitution(void)
 
 static void test_getgenerictypographic(void)
 {
-    GpStringFormat *format;
+    GpStringFormat *format, *format2;
     GpStatus stat;
     INT flags;
     INT n;
@@ -157,6 +157,12 @@ static void test_getgenerictypographic(void)
     stat = GdipStringFormatGetGenericTypographic(&format);
     expect(Ok, stat);
 
+    stat = GdipStringFormatGetGenericTypographic(&format2);
+    expect(Ok, stat);
+    ok(format == format2, "expected same format object\n");
+    stat = GdipDeleteStringFormat(format2);
+    expect(Ok, stat);
+
     GdipGetStringFormatFlags(format, &flags);
     GdipGetStringFormatAlign(format, &align);
     GdipGetStringFormatLineAlign(format, &line_align);
@@ -175,6 +181,24 @@ static void test_getgenerictypographic(void)
     expect(LANG_NEUTRAL, digitlang);
     expect(0, tabcount);
 
+    /* Change format parameters, release, get format object again. */
+    stat = GdipSetStringFormatFlags(format, StringFormatFlagsNoWrap);
+    expect(Ok, stat);
+
+    stat = GdipGetStringFormatFlags(format, &flags);
+    expect(Ok, stat);
+    expect(StringFormatFlagsNoWrap, flags);
+
+    stat = GdipDeleteStringFormat(format);
+    expect(Ok, stat);
+
+    stat = GdipStringFormatGetGenericTypographic(&format);
+    expect(Ok, stat);
+
+    stat = GdipGetStringFormatFlags(format, &flags);
+    expect(Ok, stat);
+    expect(StringFormatFlagsNoWrap, flags);
+
     stat = GdipDeleteStringFormat(format);
     expect(Ok, stat);
 }
@@ -286,7 +310,7 @@ static void test_tabstops(void)
 
 static void test_getgenericdefault(void)
 {
-    GpStringFormat *format;
+    GpStringFormat *format, *format2;
     GpStatus stat;
 
     INT flags;
@@ -304,6 +328,12 @@ static void test_getgenericdefault(void)
     stat = GdipStringFormatGetGenericDefault(&format);
     expect(Ok, stat);
 
+    stat = GdipStringFormatGetGenericDefault(&format2);
+    expect(Ok, stat);
+    ok(format == format2, "expected same format object\n");
+    stat = GdipDeleteStringFormat(format2);
+    expect(Ok, stat);
+
     GdipGetStringFormatFlags(format, &flags);
     GdipGetStringFormatAlign(format, &align);
     GdipGetStringFormatLineAlign(format, &line_align);
@@ -321,6 +351,24 @@ static void test_getgenericdefault(void)
     expect(LANG_NEUTRAL, digitlang);
     expect(0, tabcount);
 
+    /* Change default format parameters, release, get format object again. */
+    stat = GdipSetStringFormatFlags(format, StringFormatFlagsNoWrap);
+    expect(Ok, stat);
+
+    stat = GdipGetStringFormatFlags(format, &flags);
+    expect(Ok, stat);
+    expect(StringFormatFlagsNoWrap, flags);
+
+    stat = GdipDeleteStringFormat(format);
+    expect(Ok, stat);
+
+    stat = GdipStringFormatGetGenericDefault(&format);
+    expect(Ok, stat);
+
+    stat = GdipGetStringFormatFlags(format, &flags);
+    expect(Ok, stat);
+    expect(StringFormatFlagsNoWrap, flags);
+
     stat = GdipDeleteStringFormat(format);
     expect(Ok, stat);
 }
-- 
2.11.0




More information about the wine-patches mailing list