From 718178aa8819dce0dac99ab204c697e0e7e27e75 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 3 Jun 2017 19:01:50 +0000 Subject: [PATCH] [GDIPLUS] Sync with Wine Staging 2.9. CORE-13362 11fc5c0 gdiplus: Prefer using pre-multiplied ARGB data in the scaler. 17162a9 gdiplus: Remove ceilf/floorf calls from bilinear scaler. (v2) 6bade0c gdiplus: Change multiplications by additions in the x/y scaler loops. db49130 gdiplus: Change the order of x/y loops in the scaler. 9247b54 gdiplus: Set correct color space flags for grayscale images. 81ccd6b gdiplus: Force conversion of 8 bpp grayscale PNG images to 32 bpp BGRA. 4fe61f3 gdiplus: Ignore an externally set DC clipping region. a188922 gdiplus: Ignore an externally set DC origin. b8a8e1b gdiplus: Check SHADEBLENDCAPS only for printer devices. c2a4f19 gdiplus: Fix compilation on systems that don't support nameless unions. 29a55bc gdiplus: Use software mode to draw semi-transparent lines when necessary. c89de1d gdiplus: Use better naming for line alignment format field. 69b41e7 gdiplus: Fix generic string formats behavior. a3f0a59 gdiplus: Avoid infinite recursion in flatten_bezier(). 36c9ac3 gdiplus: Check for null in GdipGetFontHeight. 7f25431 gdiplus: Fix GdipCreateStreamOnFile spec file entry. 43e36d6 gdiplus: Simplify and standardize the heap_xxx() declarations. svn path=/trunk/; revision=74795 --- reactos/dll/win32/gdiplus/font.c | 2 + reactos/dll/win32/gdiplus/gdiplus.c | 2 + reactos/dll/win32/gdiplus/gdiplus.spec | 2 +- reactos/dll/win32/gdiplus/gdiplus_private.h | 22 +-- reactos/dll/win32/gdiplus/graphics.c | 174 ++++++++++++++++---- reactos/dll/win32/gdiplus/graphicspath.c | 8 +- reactos/dll/win32/gdiplus/image.c | 2 +- reactos/dll/win32/gdiplus/stringformat.c | 73 +++++--- reactos/media/doc/README.WINE | 2 +- 9 files changed, 213 insertions(+), 74 deletions(-) diff --git a/reactos/dll/win32/gdiplus/font.c b/reactos/dll/win32/gdiplus/font.c index a731d5634fa..57f90e7caad 100644 --- a/reactos/dll/win32/gdiplus/font.c +++ b/reactos/dll/win32/gdiplus/font.c @@ -543,6 +543,8 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font, TRACE("%p %p %p\n", font, graphics, height); + if (!font || !height) return InvalidParameter; + stat = GdipGetFontHeightGivenDPI(font, font->family->dpi, &font_height); if (stat != Ok) return stat; diff --git a/reactos/dll/win32/gdiplus/gdiplus.c b/reactos/dll/win32/gdiplus/gdiplus.c index b3ed4aa86ff..c34bed8ad8b 100644 --- a/reactos/dll/win32/gdiplus/gdiplus.c +++ b/reactos/dll/win32/gdiplus/gdiplus.c @@ -46,11 +46,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/reactos/dll/win32/gdiplus/gdiplus.spec b/reactos/dll/win32/gdiplus/gdiplus.spec index cb46c7f4d14..09a61093674 100644 --- a/reactos/dll/win32/gdiplus/gdiplus.spec +++ b/reactos/dll/win32/gdiplus/gdiplus.spec @@ -120,7 +120,7 @@ 120 stdcall GdipCreateRegionRectI(ptr ptr) 121 stdcall GdipCreateRegionRgnData(ptr long ptr) 122 stdcall GdipCreateSolidFill(long ptr) -123 stdcall GdipCreateStreamOnFile(ptr long ptr) +123 stdcall GdipCreateStreamOnFile(wstr long ptr) 124 stdcall GdipCreateStringFormat(long long ptr) 125 stdcall GdipCreateTexture2(ptr long float float float float ptr) 126 stdcall GdipCreateTexture2I(ptr long long long long long ptr) diff --git a/reactos/dll/win32/gdiplus/gdiplus_private.h b/reactos/dll/win32/gdiplus/gdiplus_private.h index 91fdec5010a..08251293920 100644 --- a/reactos/dll/win32/gdiplus/gdiplus_private.h +++ b/reactos/dll/win32/gdiplus/gdiplus_private.h @@ -56,22 +56,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); #define GIF_DISPOSE_RESTORE_TO_BKGND 2 #define GIF_DISPOSE_RESTORE_TO_PREV 3 -static void *heap_alloc(size_t len) __WINE_ALLOC_SIZE(1); -static inline void *heap_alloc(size_t len) +static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) { - return HeapAlloc(GetProcessHeap(), 0, len); + return HeapAlloc(GetProcessHeap(), 0, size); } -static void *heap_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1); -static inline void *heap_alloc_zero(size_t len) +static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t size) { - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); } -static void *heap_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2); -static inline void *heap_realloc(void *mem, size_t len) +static inline void* __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t size) { - return HeapReAlloc(GetProcessHeap(), 0, mem, len); + return HeapReAlloc(GetProcessHeap(), 0, mem, size); } static inline BOOL heap_free(void *mem) @@ -452,6 +449,8 @@ struct GpFont{ Unit unit; }; +extern const struct GpStringFormat default_drawstring_format DECLSPEC_HIDDEN; + struct GpStringFormat{ INT attr; LANGID lang; @@ -459,7 +458,7 @@ struct GpStringFormat{ StringAlignment align; StringTrimming trimming; HotkeyPrefix hkprefix; - StringAlignment vertalign; + StringAlignment line_align; StringDigitSubstitute digitsub; INT tabcount; REAL firsttab; @@ -469,6 +468,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/reactos/dll/win32/gdiplus/graphics.c b/reactos/dll/win32/gdiplus/graphics.c index 29ac5d3baf7..be169318105 100644 --- a/reactos/dll/win32/gdiplus/graphics.c +++ b/reactos/dll/win32/gdiplus/graphics.c @@ -519,12 +519,23 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL, fmt); } +/* NOTE: start and end pixels must be in pre-multiplied ARGB format */ +static inline ARGB blend_colors_premult(ARGB start, ARGB end, REAL position) +{ + UINT pos = position * 255.0f + 0.5f; + return + (((((start >> 24) ) << 8) + (((end >> 24) ) - ((start >> 24) )) * pos) >> 8) << 24 | + (((((start >> 16) & 0xff) << 8) + (((end >> 16) & 0xff) - ((start >> 16) & 0xff)) * pos) >> 8) << 16 | + (((((start >> 8) & 0xff) << 8) + (((end >> 8) & 0xff) - ((start >> 8) & 0xff)) * pos) >> 8) << 8 | + (((((start ) & 0xff) << 8) + (((end ) & 0xff) - ((start ) & 0xff)) * pos) >> 8); +} + static ARGB blend_colors(ARGB start, ARGB end, REAL position) { INT start_a, end_a, final_a; INT pos; - pos = gdip_round(position * 0xff); + pos = (INT)(position * 255.0f + 0.5f); start_a = ((start >> 24) & 0xff) * (pos ^ 0xff); end_a = ((end >> 24) & 0xff) * pos; @@ -926,6 +937,11 @@ static ARGB sample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT wi return ((DWORD*)(bits))[(x - src_rect->X) + (y - src_rect->Y) * src_rect->Width]; } +static inline int positive_ceilf(float f) +{ + return f - (int)f > 0.0f ? f + 1.0f : f; +} + static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width, UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes, InterpolationMode interpolation, PixelOffsetMode offset_mode) @@ -946,12 +962,12 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT ARGB top, bottom; float x_offset; - leftxf = floorf(point->X); - leftx = (INT)leftxf; - rightx = (INT)ceilf(point->X); - topyf = floorf(point->Y); - topy = (INT)topyf; - bottomy = (INT)ceilf(point->Y); + leftx = (INT)point->X; + leftxf = (REAL)leftx; + rightx = positive_ceilf(point->X); + topy = (INT)point->Y; + topyf = (REAL)topy; + bottomy = positive_ceilf(point->Y); if (leftx == rightx && topy == bottomy) return sample_bitmap_pixel(src_rect, bits, width, height, @@ -995,17 +1011,95 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT } } +static ARGB resample_bitmap_pixel_premult(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width, + UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes, + InterpolationMode interpolation, PixelOffsetMode offset_mode) +{ + static int fixme; + + switch (interpolation) + { + default: + if (!fixme++) + FIXME("Unimplemented interpolation %i\n", interpolation); + /* fall-through */ + case InterpolationModeBilinear: + { + REAL leftxf, topyf; + INT leftx, rightx, topy, bottomy; + ARGB topleft, topright, bottomleft, bottomright; + ARGB top, bottom; + float x_offset; + + leftx = (INT)point->X; + leftxf = (REAL)leftx; + rightx = positive_ceilf(point->X); + topy = (INT)point->Y; + topyf = (REAL)topy; + bottomy = positive_ceilf(point->Y); + + if (leftx == rightx && topy == bottomy) + return sample_bitmap_pixel(src_rect, bits, width, height, + leftx, topy, attributes); + + topleft = sample_bitmap_pixel(src_rect, bits, width, height, + leftx, topy, attributes); + topright = sample_bitmap_pixel(src_rect, bits, width, height, + rightx, topy, attributes); + bottomleft = sample_bitmap_pixel(src_rect, bits, width, height, + leftx, bottomy, attributes); + bottomright = sample_bitmap_pixel(src_rect, bits, width, height, + rightx, bottomy, attributes); + + x_offset = point->X - leftxf; + top = blend_colors_premult(topleft, topright, x_offset); + bottom = blend_colors_premult(bottomleft, bottomright, x_offset); + + return blend_colors_premult(top, bottom, point->Y - topyf); + } + case InterpolationModeNearestNeighbor: + { + FLOAT pixel_offset; + switch (offset_mode) + { + default: + case PixelOffsetModeNone: + case PixelOffsetModeHighSpeed: + pixel_offset = 0.5; + break; + + case PixelOffsetModeHalf: + case PixelOffsetModeHighQuality: + pixel_offset = 0.0; + break; + } + return sample_bitmap_pixel(src_rect, bits, width, height, + floorf(point->X + pixel_offset), point->Y + pixel_offset, attributes); + } + + } +} + static REAL intersect_line_scanline(const GpPointF *p1, const GpPointF *p2, REAL y) { return (p1->X - p2->X) * (p2->Y - y) / (p2->Y - p1->Y) + p2->X; } -static BOOL brush_can_fill_path(GpBrush *brush) +/* is_fill is TRUE if filling regions, FALSE for drawing primitives */ +static BOOL brush_can_fill_path(GpBrush *brush, BOOL is_fill) { switch (brush->bt) { case BrushTypeSolidColor: - return TRUE; + { + if (is_fill) + return TRUE; + else + { + /* cannot draw semi-transparent colors */ + return (((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000; + } + } case BrushTypeHatchFill: { GpHatch *hatch = (GpHatch*)brush; @@ -3003,8 +3097,10 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image lockeddata.Scan0 = src_data; if (!do_resampling && bitmap->format == PixelFormat32bppPARGB) lockeddata.PixelFormat = apply_image_attributes(imageAttributes, NULL, 0, 0, 0, ColorAdjustTypeBitmap, bitmap->format); - else + else if (imageAttributes != &defaultImageAttributes) lockeddata.PixelFormat = PixelFormat32bppARGB; + else + lockeddata.PixelFormat = PixelFormat32bppPARGB; stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf, lockeddata.PixelFormat, &lockeddata); @@ -3024,6 +3120,8 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image if (do_resampling) { + REAL delta_xx, delta_xy, delta_yx, delta_yy; + /* Transform the bits as needed to the destination. */ dst_data = dst_dyn_data = heap_alloc_zero(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top)); if (!dst_data) @@ -3041,24 +3139,42 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X; y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y; - for (x=dst_area.left; x= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight) - *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf, - imageAttributes, interpolation, offset_mode); + { + if (lockeddata.PixelFormat != PixelFormat32bppPARGB) + *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf, + imageAttributes, interpolation, offset_mode); + else + *dst_color = resample_bitmap_pixel_premult(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf, + imageAttributes, interpolation, offset_mode); + } else *dst_color = 0; + + delta_xx += x_dx; + delta_yx += y_dx; } + + delta_xy += x_dy; + delta_yy += y_dy; } } else @@ -3784,7 +3900,7 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) if (path->pathdata.Count == 0) return Ok; - if (!graphics->hdc) + if (!graphics->hdc || !brush_can_fill_path(pen->brush, FALSE)) retval = SOFTWARE_GdipDrawPath(graphics, pen, path); else retval = GDI32_GdipDrawPath(graphics, pen, path); @@ -4034,7 +4150,7 @@ static GpStatus GDI32_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath GpStatus retval; HRGN hrgn=NULL; - if(!graphics->hdc || !brush_can_fill_path(brush)) + if(!graphics->hdc || !brush_can_fill_path(brush, TRUE)) return NotImplemented; save_state = SaveDC(graphics->hdc); @@ -4327,7 +4443,7 @@ static GpStatus GDI32_GdipFillRegion(GpGraphics* graphics, GpBrush* brush, HRGN hrgn; RECT rc; - if(!graphics->hdc || !brush_can_fill_path(brush)) + if(!graphics->hdc || !brush_can_fill_path(brush, TRUE)) return NotImplemented; status = GdipGetRegionHRgn(region, graphics, &hrgn); @@ -4908,7 +5024,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); @@ -4916,15 +5031,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; @@ -5074,7 +5181,6 @@ GpStatus gdip_format_string(HDC hdc, heap_free(stringdup); heap_free(hotkeyprefix_offsets); - GdipDeleteStringFormat(dyn_format); return stat; } @@ -5426,19 +5532,19 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string /* Should be no need to explicitly test for StringAlignmentNear as * that is default behavior if no alignment is passed. */ - if(format->vertalign != StringAlignmentNear){ + if(format->line_align != StringAlignmentNear){ RectF bounds, in_rect = *rect; in_rect.Height = 0.0; /* avoid height clipping */ GdipMeasureString(graphics, string, length, font, &in_rect, format, &bounds, 0, 0); TRACE("bounds %s\n", debugstr_rectf(&bounds)); - if(format->vertalign == StringAlignmentCenter) + if(format->line_align == StringAlignmentCenter) offsety = (rect->Height - bounds.Height) / 2; - else if(format->vertalign == StringAlignmentFar) + else if(format->line_align == StringAlignmentFar) offsety = (rect->Height - bounds.Height); } - TRACE("vertical align %d, offsety %f\n", format->vertalign, offsety); + TRACE("line align %d, offsety %f\n", format->line_align, offsety); } save_state = SaveDC(hdc); diff --git a/reactos/dll/win32/gdiplus/graphicspath.c b/reactos/dll/win32/gdiplus/graphicspath.c index 507f77a9e2e..22af560a9d7 100644 --- a/reactos/dll/win32/gdiplus/graphicspath.c +++ b/reactos/dll/win32/gdiplus/graphicspath.c @@ -128,6 +128,10 @@ static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, R mp[2].X = (mp[1].X + mp[3].X) / 2.0; mp[2].Y = (mp[1].Y + mp[3].Y) / 2.0; + if ((x2 == mp[0].X && y2 == mp[0].Y && x3 == mp[1].X && y3 == mp[1].Y) || + (x2 == mp[3].X && y2 == mp[3].Y && x3 == mp[4].X && y3 == mp[4].Y)) + return TRUE; + pt = end->pt; pt_st = start->pt; /* check flatness as a half of distance between middle point and a linearized path */ @@ -1010,13 +1014,13 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT heap_free(backup); return status; } - if (format && format->vertalign == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height) + if (format && format->line_align == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height) { float inc = layoutRect->Height + layoutRect->Y - args.maxY; inc /= 2; for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i) path->pathdata.Points[i].Y += inc; - } else if (format && format->vertalign == StringAlignmentFar) { + } else if (format && format->line_align == StringAlignmentFar) { float inc = layoutRect->Height + layoutRect->Y - args.maxY; for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i) path->pathdata.Points[i].Y += inc; diff --git a/reactos/dll/win32/gdiplus/image.c b/reactos/dll/win32/gdiplus/image.c index c80e0cde4ff..0cb4a18efa9 100644 --- a/reactos/dll/win32/gdiplus/image.c +++ b/reactos/dll/win32/gdiplus/image.c @@ -40,7 +40,6 @@ static const struct { &GUID_WICPixelFormat1bppIndexed, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW }, { &GUID_WICPixelFormat4bppIndexed, PixelFormat4bppIndexed, WICBitmapPaletteTypeFixedHalftone8 }, { &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 }, - { &GUID_WICPixelFormat32bppGrayFloat, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedGray256 }, { &GUID_WICPixelFormat8bppIndexed, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat16bppBGR555, PixelFormat16bppRGB555, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat24bppBGR, PixelFormat24bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, @@ -49,6 +48,7 @@ static const struct { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppCMYK, PixelFormat32bppCMYK, WICBitmapPaletteTypeFixedHalftone256 }, + { &GUID_WICPixelFormat32bppGrayFloat, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedGray256 }, { &GUID_WICPixelFormat64bppCMYK, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat64bppRGBA, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { NULL } diff --git a/reactos/dll/win32/gdiplus/stringformat.c b/reactos/dll/win32/gdiplus/stringformat.c index 6341148949a..4d19b6d798c 100644 --- a/reactos/dll/win32/gdiplus/stringformat.c +++ b/reactos/dll/win32/gdiplus/stringformat.c @@ -19,6 +19,47 @@ #include "gdiplus_private.h" +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) { @@ -53,6 +94,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); @@ -62,17 +106,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; } @@ -128,7 +165,7 @@ GpStatus WINGDIPAPI GdipGetStringFormatLineAlign(GpStringFormat *format, if(!format || !align) return InvalidParameter; - *align = format->vertalign; + *align = format->line_align; return Ok; } @@ -232,7 +269,7 @@ GpStatus WINGDIPAPI GdipSetStringFormatLineAlign(GpStringFormat *format, if(!format) return InvalidParameter; - format->vertalign = align; + format->line_align = align; return Ok; } @@ -357,24 +394,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/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index b1a613457f5..bb368d8fd02 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -68,7 +68,7 @@ reactos/dll/win32/dciman32 # Synced to WineStaging-1.9.11 reactos/dll/win32/faultrep # Synced to WineStaging-1.9.11 reactos/dll/win32/fontsub # Synced to WineStaging-1.9.13 reactos/dll/win32/fusion # Synced to WineStaging-1.9.23 -reactos/dll/win32/gdiplus # Synced to WineStaging-2.2 +reactos/dll/win32/gdiplus # Synced to WineStaging-2.9 reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-2.2 reactos/dll/win32/hlink # Synced to WineStaging-2.2 reactos/dll/win32/hnetcfg # Synced to WineStaging-1.9.16