From 687ee5ded52115bddf55e1dbf1402aef8373fa9c Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 5 Mar 2017 21:15:16 +0000 Subject: [PATCH] [GDIPLUS] Sync with Wine Staging 2.2. CORE-12823 818b141 gdiplus: Add support for more image color formats. f8f0a35 gdiplus: Implement GdipInitializePalette. (v2) 973bba9 gdiplus: Ignore an externally set DC clipping region. 650b8d0 gdiplus: Ignore an externally set DC origin. e100661 gdiplus: Add GdipCreateHBITMAPFromBitmap tests when bitmap bits are locked. b58276a gdiplus: Reimplement GdipCreateHBITMAPFromBitmap so it can work on locked bitmaps. 5673d82 gdiplus: GpBitmap can be only locked once, get rid of numlocks field. 0eaaa15 gdiplus: Make GpBitmap->bitmapbits access thread safe. 4e685eb gdiplus: Added GdipGetCustomLineCapType(). 36bb9d9 gdiplus: Fix some spec file entries. f870708 gdiplus: Make some GdipDraw*Path() functions static. 046fc19 gdiplus: Fix memory leak in format_string_callback error path. 5018594 gdiplus: Create the FontFamily before checking for duplicates. 0d6a4b0 gdiplus: Don't include rotated fonts in the installed font collection. svn path=/trunk/; revision=74098 --- reactos/dll/win32/gdiplus/customlinecap.c | 12 ++ reactos/dll/win32/gdiplus/font.c | 27 +++-- reactos/dll/win32/gdiplus/gdiplus.spec | 14 +-- reactos/dll/win32/gdiplus/gdiplus_private.h | 16 ++- reactos/dll/win32/gdiplus/graphics.c | 11 +- reactos/dll/win32/gdiplus/graphicspath.c | 1 + reactos/dll/win32/gdiplus/image.c | 118 ++++++++++++++------ reactos/media/doc/README.WINE | 2 +- 8 files changed, 143 insertions(+), 58 deletions(-) diff --git a/reactos/dll/win32/gdiplus/customlinecap.c b/reactos/dll/win32/gdiplus/customlinecap.c index 3d7e51af564..3380b1438a8 100644 --- a/reactos/dll/win32/gdiplus/customlinecap.c +++ b/reactos/dll/win32/gdiplus/customlinecap.c @@ -65,6 +65,7 @@ GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath* fillPath, GpPath* strokePath *customCap = heap_alloc_zero(sizeof(GpCustomLineCap)); if(!*customCap) return OutOfMemory; + (*customCap)->type = CustomLineCapTypeDefault; if(strokePath){ (*customCap)->fill = FALSE; pathdata = &strokePath->pathdata; @@ -233,6 +234,17 @@ GpStatus WINGDIPAPI GdipGetCustomLineCapBaseCap(GpCustomLineCap *customCap, GpLi return Ok; } +GpStatus WINGDIPAPI GdipGetCustomLineCapType(GpCustomLineCap *customCap, CustomLineCapType *type) +{ + TRACE("(%p, %p)\n", customCap, type); + + if(!customCap || !type) + return InvalidParameter; + + *type = customCap->type; + return Ok; +} + GpStatus WINGDIPAPI GdipCreateAdjustableArrowCap(REAL height, REAL width, BOOL fill, GpAdjustableArrowCap **cap) { diff --git a/reactos/dll/win32/gdiplus/font.c b/reactos/dll/win32/gdiplus/font.c index 399595f36d4..a731d5634fa 100644 --- a/reactos/dll/win32/gdiplus/font.c +++ b/reactos/dll/win32/gdiplus/font.c @@ -1584,15 +1584,18 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, DWORD type, LPARAM lParam) { GpFontCollection* fonts = (GpFontCollection*)lParam; + GpFontFamily* family; int i; if (type == RASTER_FONTTYPE) return 1; - /* skip duplicates */ - for (i=0; icount; i++) - if (strcmpiW(lfw->lfFaceName, fonts->FontFamilies[i]->FamilyName) == 0) - return 1; + /* skip rotated fonts */ + if (lfw->lfFaceName[0] == '@') + return 1; + + if (fonts->count && strcmpiW(lfw->lfFaceName, fonts->FontFamilies[fonts->count-1]->FamilyName) == 0) + return 1; if (fonts->allocated == fonts->count) { @@ -1608,11 +1611,21 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, fonts->allocated = new_alloc_count; } - if (GdipCreateFontFamilyFromName(lfw->lfFaceName, NULL, &fonts->FontFamilies[fonts->count]) == Ok) - fonts->count++; - else + if (GdipCreateFontFamilyFromName(lfw->lfFaceName, NULL, &family) != Ok) return 0; + /* skip duplicates */ + for (i=0; icount; i++) + { + if (strcmpiW(family->FamilyName, fonts->FontFamilies[i]->FamilyName) == 0) + { + GdipDeleteFontFamily(family); + return 1; + } + } + + fonts->FontFamilies[fonts->count++] = family; + return 1; } diff --git a/reactos/dll/win32/gdiplus/gdiplus.spec b/reactos/dll/win32/gdiplus/gdiplus.spec index 4186b5b35ba..cb46c7f4d14 100644 --- a/reactos/dll/win32/gdiplus/gdiplus.spec +++ b/reactos/dll/win32/gdiplus/gdiplus.spec @@ -172,8 +172,8 @@ 172 stdcall GdipDrawImagePointsRectI(ptr ptr ptr long long long long long long ptr ptr ptr) 173 stdcall GdipDrawImageRect(ptr ptr float float float float) 174 stdcall GdipDrawImageRectI(ptr ptr long long long long) -175 stdcall GdipDrawImageRectRect(ptr ptr float float float float float float float float long ptr long ptr) -176 stdcall GdipDrawImageRectRectI(ptr ptr long long long long long long long long long ptr long ptr) +175 stdcall GdipDrawImageRectRect(ptr ptr float float float float float float float float long ptr ptr ptr) +176 stdcall GdipDrawImageRectRectI(ptr ptr long long long long long long long long long ptr ptr ptr) 177 stdcall GdipDrawLine(ptr ptr float float float float) 178 stdcall GdipDrawLineI(ptr ptr long long long long) 179 stdcall GdipDrawLines(ptr ptr ptr long) @@ -189,7 +189,7 @@ 189 stdcall GdipDrawRectanglesI(ptr ptr ptr long) 190 stdcall GdipDrawString(ptr wstr long ptr ptr ptr ptr) 191 stdcall GdipEmfToWmfBits(ptr long ptr long long) -192 stdcall GdipEndContainer(ptr ptr) +192 stdcall GdipEndContainer(ptr long) 193 stdcall GdipEnumerateMetafileDestPoint(ptr ptr ptr ptr ptr ptr) 194 stdcall GdipEnumerateMetafileDestPointI(ptr ptr ptr ptr ptr ptr) 195 stub GdipEnumerateMetafileDestPoints @@ -240,7 +240,7 @@ 240 stdcall GdipGetCustomLineCapBaseInset(ptr ptr) 241 stub GdipGetCustomLineCapStrokeCaps 242 stdcall GdipGetCustomLineCapStrokeJoin(ptr ptr) -243 stub GdipGetCustomLineCapType +243 stdcall GdipGetCustomLineCapType(ptr ptr) 244 stdcall GdipGetCustomLineCapWidthScale(ptr ptr) 245 stdcall GdipGetDC(ptr ptr) 246 stdcall GdipGetDpiX(ptr ptr) @@ -563,7 +563,7 @@ 563 stdcall GdipSetPropertyItem(ptr ptr) 564 stdcall GdipSetRenderingOrigin(ptr long long) 565 stdcall GdipSetSmoothingMode(ptr long) -566 stdcall GdipSetSolidFillColor(ptr ptr) +566 stdcall GdipSetSolidFillColor(ptr long) 567 stdcall GdipSetStringFormatAlign(ptr long) 568 stdcall GdipSetStringFormatDigitSubstitution(ptr long long) 569 stdcall GdipSetStringFormatFlags(ptr long) @@ -604,8 +604,8 @@ 604 stdcall GdipWidenPath(ptr ptr ptr float) 605 stdcall GdipWindingModeOutline(ptr ptr float) 606 stdcall GdiplusNotificationHook(ptr) -607 stdcall GdiplusNotificationUnhook(ptr) -608 stdcall GdiplusShutdown(ptr) GdiplusShutdown_wrapper +607 stdcall GdiplusNotificationUnhook(long) +608 stdcall GdiplusShutdown(long) GdiplusShutdown_wrapper 609 stdcall GdiplusStartup(ptr ptr ptr) 610 stdcall GdipFindFirstImageItem(ptr ptr) 611 stub GdipFindNextImageItem diff --git a/reactos/dll/win32/gdiplus/gdiplus_private.h b/reactos/dll/win32/gdiplus/gdiplus_private.h index f729bfcda23..91fdec5010a 100644 --- a/reactos/dll/win32/gdiplus/gdiplus_private.h +++ b/reactos/dll/win32/gdiplus/gdiplus_private.h @@ -335,6 +335,7 @@ struct GpPathIterator{ }; struct GpCustomLineCap{ + CustomLineCapType type; GpPathData pathdata; BOOL fill; /* TRUE for fill, FALSE for stroke */ GpLineCap cap; /* as far as I can tell, this value is ignored */ @@ -355,6 +356,7 @@ struct GpImage{ UINT frame_count, current_frame; ColorPalette *palette; REAL xres, yres; + LONG busy; }; struct GpMetafile{ @@ -397,7 +399,6 @@ struct GpBitmap{ INT height; PixelFormat format; ImageLockMode lockmode; - INT numlocks; BYTE *bitmapbits; /* pointer to the buffer we passed in BitmapLockBits */ HBITMAP hbitmap; HDC hdc; @@ -522,4 +523,17 @@ GpStatus gdip_format_string(HDC hdc, void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN; +static inline BOOL image_lock(GpImage *image, BOOL *unlock) +{ + LONG tid = GetCurrentThreadId(), owner_tid; + owner_tid = InterlockedCompareExchange(&image->busy, tid, 0); + *unlock = !owner_tid; + return !owner_tid || owner_tid==tid; +} + +static inline void image_unlock(GpImage *image, BOOL unlock) +{ + if (unlock) image->busy = 0; +} + #endif /* __WINE_GP_PRIVATE_H_ */ diff --git a/reactos/dll/win32/gdiplus/graphics.c b/reactos/dll/win32/gdiplus/graphics.c index 56d482d0d7f..158e2b48efe 100644 --- a/reactos/dll/win32/gdiplus/graphics.c +++ b/reactos/dll/win32/gdiplus/graphics.c @@ -493,8 +493,9 @@ static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst save = SaveDC(graphics->hdc); - if (hrgn) - ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); + SetViewportOrgEx(graphics->hdc, 0, 0, NULL); + + ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY); if (hregion) ExtSelectClipRgn(graphics->hdc, hregion, RGN_AND); @@ -3371,7 +3372,7 @@ GpStatus WINGDIPAPI GdipDrawLinesI(GpGraphics *graphics, GpPen *pen, GDIPCONST return retval; } -GpStatus GDI32_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) +static GpStatus GDI32_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) { INT save_state; GpStatus retval; @@ -3397,7 +3398,7 @@ end: return retval; } -GpStatus SOFTWARE_GdipDrawThinPath(GpGraphics *graphics, GpPen *pen, GpPath *path) +static GpStatus SOFTWARE_GdipDrawThinPath(GpGraphics *graphics, GpPen *pen, GpPath *path) { GpStatus stat; GpPath* flat_path; @@ -3695,7 +3696,7 @@ GpStatus SOFTWARE_GdipDrawThinPath(GpGraphics *graphics, GpPen *pen, GpPath *pat return stat; } -GpStatus SOFTWARE_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) +static GpStatus SOFTWARE_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) { GpStatus stat; GpPath *wide_path; diff --git a/reactos/dll/win32/gdiplus/graphicspath.c b/reactos/dll/win32/gdiplus/graphicspath.c index 4982a0bfd32..507f77a9e2e 100644 --- a/reactos/dll/win32/gdiplus/graphicspath.c +++ b/reactos/dll/win32/gdiplus/graphicspath.c @@ -867,6 +867,7 @@ static GpStatus format_string_callback(HDC dc, start = (char *)ph; if (!ph || !lengthen_path(path, len / sizeof(POINTFX))) { + heap_free(ph); status = OutOfMemory; break; } diff --git a/reactos/dll/win32/gdiplus/image.c b/reactos/dll/win32/gdiplus/image.c index eab2f7fbbb2..c80e0cde4ff 100644 --- a/reactos/dll/win32/gdiplus/image.c +++ b/reactos/dll/win32/gdiplus/image.c @@ -38,13 +38,19 @@ static const struct { { &GUID_WICPixelFormatBlackWhite, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW }, { &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 }, { &GUID_WICPixelFormat32bppBGR, PixelFormat32bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, + { &GUID_WICPixelFormat48bppRGB, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 }, { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 }, + { &GUID_WICPixelFormat32bppCMYK, PixelFormat32bppCMYK, WICBitmapPaletteTypeFixedHalftone256 }, + { &GUID_WICPixelFormat64bppCMYK, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, + { &GUID_WICPixelFormat64bppRGBA, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 }, { NULL } }; @@ -1010,16 +1016,22 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, INT bitspp = PIXELFORMATBPP(format); GpRect act_rect; /* actual rect to be used */ GpStatus stat; + BOOL unlock; TRACE("%p %p %d 0x%x %p\n", bitmap, rect, flags, format, lockeddata); if(!lockeddata || !bitmap) return InvalidParameter; + if(!image_lock(&bitmap->image, &unlock)) + return ObjectBusy; if(rect){ if(rect->X < 0 || rect->Y < 0 || (rect->X + rect->Width > bitmap->width) || (rect->Y + rect->Height > bitmap->height) || !flags) + { + image_unlock(&bitmap->image, unlock); return InvalidParameter; + } act_rect = *rect; } @@ -1032,6 +1044,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, if(bitmap->lockmode) { WARN("bitmap is already locked and cannot be locked again\n"); + image_unlock(&bitmap->image, unlock); return WrongState; } @@ -1047,8 +1060,8 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, bitmap->stride * act_rect.Y; bitmap->lockmode = flags | ImageLockModeRead; - bitmap->numlocks++; + image_unlock(&bitmap->image, unlock); return Ok; } @@ -1059,6 +1072,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, if (stat == NotImplemented) { FIXME("cannot read bitmap from %x to %x\n", bitmap->format, format); + image_unlock(&bitmap->image, unlock); return NotImplemented; } } @@ -1071,6 +1085,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, if (stat == NotImplemented) { FIXME("cannot write bitmap from %x to %x\n", format, bitmap->format); + image_unlock(&bitmap->image, unlock); return NotImplemented; } } @@ -1086,7 +1101,11 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, bitmap->bitmapbits = heap_alloc_zero(lockeddata->Stride * act_rect.Height); - if (!bitmap->bitmapbits) return OutOfMemory; + if (!bitmap->bitmapbits) + { + image_unlock(&bitmap->image, unlock); + return OutOfMemory; + } lockeddata->Scan0 = bitmap->bitmapbits; } @@ -1111,15 +1130,16 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, { heap_free(bitmap->bitmapbits); bitmap->bitmapbits = NULL; + image_unlock(&bitmap->image, unlock); return stat; } } bitmap->lockmode = flags | ImageLockModeRead; - bitmap->numlocks++; bitmap->lockx = act_rect.X; bitmap->locky = act_rect.Y; + image_unlock(&bitmap->image, unlock); return Ok; } @@ -1141,21 +1161,26 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap, { GpStatus stat; static BOOL fixme = FALSE; + BOOL unlock; TRACE("(%p,%p)\n", bitmap, lockeddata); if(!bitmap || !lockeddata) return InvalidParameter; + if(!image_lock(&bitmap->image, &unlock)) + return ObjectBusy; if(!bitmap->lockmode) + { + image_unlock(&bitmap->image, unlock); return WrongState; + } if(!(lockeddata->Reserved & ImageLockModeWrite)){ - if(!(--bitmap->numlocks)) - bitmap->lockmode = 0; - + bitmap->lockmode = 0; heap_free(bitmap->bitmapbits); bitmap->bitmapbits = NULL; + image_unlock(&bitmap->image, unlock); return Ok; } @@ -1163,7 +1188,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap, { /* we passed a direct reference; no need to do anything */ bitmap->lockmode = 0; - bitmap->numlocks = 0; + image_unlock(&bitmap->image, unlock); return Ok; } @@ -1187,8 +1212,8 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap, heap_free(bitmap->bitmapbits); bitmap->bitmapbits = NULL; bitmap->lockmode = 0; - bitmap->numlocks = 0; + image_unlock(&bitmap->image, unlock); return stat; } @@ -1441,10 +1466,12 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap, UINT width, height; BITMAPINFOHEADER bih; LPBYTE bits; - BitmapData lockeddata; + BOOL unlock; + TRACE("(%p,%p,%x)\n", bitmap, hbmReturn, background); if (!bitmap || !hbmReturn) return InvalidParameter; + if (!image_lock(&bitmap->image, &unlock)) return ObjectBusy; GdipGetImageWidth(&bitmap->image, &width); GdipGetImageHeight(&bitmap->image, &height); @@ -1462,41 +1489,36 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap, bih.biClrImportant = 0; result = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&bits, NULL, 0); - - if (result) + if (!result) { - lockeddata.Stride = -width * 4; - lockeddata.Scan0 = bits + (width * 4 * (height - 1)); - - stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead|ImageLockModeUserInputBuf, - PixelFormat32bppPARGB, &lockeddata); - - if (stat == Ok) - stat = GdipBitmapUnlockBits(bitmap, &lockeddata); - - if (stat == Ok && (background & 0xffffff)) - { - DWORD *ptr; - UINT i; - for (ptr = (DWORD*)bits, i = 0; i < width * height; ptr++, i++) - { - if ((*ptr & 0xff000000) == 0xff000000) continue; - *ptr = blend_argb_no_bkgnd_alpha(*ptr, background); - } - } + image_unlock(&bitmap->image, unlock); + return GenericError; } - else - stat = GenericError; - if (stat != Ok && result) + stat = convert_pixels(width, height, -width*4, + bits + (width * 4 * (height - 1)), PixelFormat32bppPARGB, + bitmap->stride, bitmap->bits, bitmap->format, bitmap->image.palette); + if (stat != Ok) { DeleteObject(result); - result = NULL; + image_unlock(&bitmap->image, unlock); + return stat; + } + + if (background & 0xffffff) + { + DWORD *ptr; + UINT i; + for (ptr = (DWORD*)bits, i = 0; i < width * height; ptr++, i++) + { + if ((*ptr & 0xff000000) == 0xff000000) continue; + *ptr = blend_argb_no_bkgnd_alpha(*ptr, background); + } } *hbmReturn = result; - - return stat; + image_unlock(&bitmap->image, unlock); + return Ok; } GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT width, INT height, @@ -3736,6 +3758,7 @@ static GpStatus select_frame_wic(GpImage *image, UINT active_frame) if(status != Ok) return status; + new_image->busy = image->busy; memcpy(&new_image->format, &image->format, sizeof(GUID)); free_image_data(image); if (image->type == ImageTypeBitmap) @@ -4239,30 +4262,39 @@ GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, GDIPCONST GUID *d { GpStatus stat; const struct image_codec *codec = NULL; + BOOL unlock; TRACE("(%p,%s,%u)\n", image, debugstr_guid(dimensionID), frame); if (!image || !dimensionID) return InvalidParameter; + if(!image_lock(image, &unlock)) + return ObjectBusy; if (frame >= image->frame_count) { WARN("requested frame %u, but image has only %u\n", frame, image->frame_count); + image_unlock(image, unlock); return InvalidParameter; } if (image->type != ImageTypeBitmap && image->type != ImageTypeMetafile) { WARN("invalid image type %d\n", image->type); + image_unlock(image, unlock); return InvalidParameter; } if (image->current_frame == frame) + { + image_unlock(image, unlock); return Ok; + } if (!image->decoder) { TRACE("image doesn't have an associated decoder\n"); + image_unlock(image, unlock); return Ok; } @@ -4271,10 +4303,13 @@ GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, GDIPCONST GUID *d if (stat != Ok) { WARN("can't find decoder info\n"); + image_unlock(image, unlock); return stat; } - return codec->select_func(image, frame); + stat = codec->select_func(image, frame); + image_unlock(image, unlock); + return stat; } GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream *stream, GpImage **image) @@ -5284,11 +5319,14 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type) UINT x, y, width, height; BitmapData src_lock, dst_lock; GpStatus stat; + BOOL unlock; TRACE("(%p, %u)\n", image, type); if (!image) return InvalidParameter; + if (!image_lock(image, &unlock)) + return ObjectBusy; rotate_90 = type&1; flip_x = (type&6) == 2 || (type&6) == 4; @@ -5297,6 +5335,7 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type) if (image->type != ImageTypeBitmap) { FIXME("Not implemented for type %i\n", image->type); + image_unlock(image, unlock); return NotImplemented; } @@ -5306,6 +5345,7 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type) if (bpp < 8) { FIXME("Not implemented for %i bit images\n", bpp); + image_unlock(image, unlock); return NotImplemented; } @@ -5325,7 +5365,10 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type) stat = GdipCreateBitmapFromScan0(width, height, 0, bitmap->format, NULL, &new_bitmap); if (stat != Ok) + { + image_unlock(image, unlock); return stat; + } stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format, &src_lock); @@ -5385,6 +5428,7 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type) else GdipDisposeImage(&new_bitmap->image); + image_unlock(image, unlock); return stat; } diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 98d0ca4b295..61d60928cd1 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-1.9.23 +reactos/dll/win32/gdiplus # Synced to WineStaging-2.2 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