From 5478176dedb48eba9c52e63bc1e86d598dfe80f0 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 22 Mar 2015 18:33:30 +0000 Subject: [PATCH] [GDIPLUS] Sync with Wine Staging 1.7.37. CORE-9246 svn path=/trunk/; revision=66857 --- reactos/dll/win32/gdiplus/graphics.c | 9 +- reactos/dll/win32/gdiplus/image.c | 40 +++-- reactos/dll/win32/gdiplus/region.c | 258 +++++++++++++++++++++++++-- reactos/media/doc/README.WINE | 2 +- 4 files changed, 275 insertions(+), 34 deletions(-) diff --git a/reactos/dll/win32/gdiplus/graphics.c b/reactos/dll/win32/gdiplus/graphics.c index 3270c89c821..0e796abcbe5 100644 --- a/reactos/dll/win32/gdiplus/graphics.c +++ b/reactos/dll/win32/gdiplus/graphics.c @@ -823,6 +823,10 @@ static void get_bitmap_sample_size(InterpolationMode interpolation, WrapMode wra right = bitmap->width-1; if (bottom >= bitmap->height) bottom = bitmap->height-1; + if (bottom < top || right < left) + /* entirely outside image, just sample a pixel so we don't have to + * special-case this later */ + left = top = right = bottom = 0; } else { @@ -1775,7 +1779,7 @@ static GpStatus draw_poly(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF * for(i = 1; i < count; i++){ if((types[i] & PathPointTypePathTypeMask) == PathPointTypeBezier){ if((i + 2 >= count) || !(types[i + 1] & PathPointTypeBezier) - || !(types[i + 1] & PathPointTypeBezier)){ + || !(types[i + 2] & PathPointTypeBezier)){ ERR("Bad bezier points\n"); goto end; } @@ -2021,8 +2025,7 @@ static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect) rect->Height = GetDeviceCaps(graphics->hdc, VERTRES); } - if (graphics->hdc && - (GetMapMode(graphics->hdc) != MM_TEXT || GetGraphicsMode(graphics->hdc) != GM_COMPATIBLE)) + if (graphics->hdc) { POINT points[2]; diff --git a/reactos/dll/win32/gdiplus/image.c b/reactos/dll/win32/gdiplus/image.c index ebbfa4cbf40..795bdf088cb 100644 --- a/reactos/dll/win32/gdiplus/image.c +++ b/reactos/dll/win32/gdiplus/image.c @@ -565,8 +565,8 @@ GpStatus convert_pixels(INT width, INT height, } #define convert_indexed_to_rgb(getpixel_function, setpixel_function) do { \ - for (x=0; x> 8); + BYTE r = (BYTE)(src >> 16); + DWORD alpha = (BYTE)(src >> 24); + return ((b + ((BYTE)bkgnd * (255 - alpha) + 127) / 255) | + (g + ((BYTE)(bkgnd >> 8) * (255 - alpha) + 127) / 255) << 8 | + (r + ((BYTE)(bkgnd >> 16) * (255 - alpha) + 127) / 255) << 16 | + (alpha << 24)); +} + GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap, HBITMAP* hbmReturn, ARGB background) { @@ -1506,6 +1518,17 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap, 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); + } + } } else stat = GenericError; @@ -3836,11 +3859,6 @@ GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR* filenam * Encoding functions - * These functions encode an image in different image file formats. */ -#define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */ -#define BITMAP_FORMAT_JPEG 0xd8ff -#define BITMAP_FORMAT_GIF 0x4947 -#define BITMAP_FORMAT_PNG 0x5089 -#define BITMAP_FORMAT_APM 0xcdd7 static GpStatus encode_image_WIC(GpImage *image, IStream* stream, GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) diff --git a/reactos/dll/win32/gdiplus/region.c b/reactos/dll/win32/gdiplus/region.c index 37cb45f860d..132903f6a83 100644 --- a/reactos/dll/win32/gdiplus/region.c +++ b/reactos/dll/win32/gdiplus/region.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Google (Lei Zhang) + * Copyright (C) 2013 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -64,6 +65,28 @@ #define FLAGS_NOFLAGS 0x0 #define FLAGS_INTPATH 0x4000 +struct memory_buffer +{ + const BYTE *buffer; + INT size, pos; +}; + +struct region_header +{ + DWORD size; + DWORD checksum; + DWORD magic; + DWORD num_children; +}; + +struct path_header +{ + DWORD size; + DWORD magic; + DWORD count; + DWORD flags; +}; + /* Header size as far as header->size is concerned. This doesn't include * header->size or header->checksum */ @@ -510,12 +533,221 @@ GpStatus WINGDIPAPI GdipCreateRegionRectI(GDIPCONST GpRect *rect, return GdipCreateRegionRect(&rectf, region); } +static inline void init_memory_buffer(struct memory_buffer *mbuf, const BYTE *buffer, INT size) +{ + mbuf->buffer = buffer; + mbuf->size = size; + mbuf->pos = 0; +} + +static inline const void *buffer_read(struct memory_buffer *mbuf, INT size) +{ + if (mbuf->size - mbuf->pos >= size) + { + const void *data = mbuf->buffer + mbuf->pos; + mbuf->pos += size; + return data; + } + return NULL; +} + +static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, region_element *node, INT *count) +{ + GpStatus status; + const DWORD *type; + + type = buffer_read(mbuf, sizeof(DWORD)); + if (!type) return Ok; + + TRACE("type %#x\n", *type); + + node->type = *type; + + switch (node->type) + { + case CombineModeReplace: + case CombineModeIntersect: + case CombineModeUnion: + case CombineModeXor: + case CombineModeExclude: + case CombineModeComplement: + { + region_element *left, *right; + + left = GdipAlloc(sizeof(region_element)); + if (!left) return OutOfMemory; + right = GdipAlloc(sizeof(region_element)); + if (!right) + { + GdipFree(left); + return OutOfMemory; + } + + status = read_element(mbuf, region, left, count); + if (status == Ok) + { + status = read_element(mbuf, region, right, count); + if (status == Ok) + { + node->elementdata.combine.left = left; + node->elementdata.combine.right = right; + region->num_children += 2; + return Ok; + } + } + + GdipFree(left); + GdipFree(right); + return status; + } + + case RegionDataRect: + { + const GpRectF *rc; + + rc = buffer_read(mbuf, sizeof(GpRectF)); + if (!rc) + { + ERR("failed to read rect data\n"); + return InvalidParameter; + } + + node->elementdata.rect = *rc; + *count += 1; + return Ok; + } + + case RegionDataPath: + { + GpPath *path; + const struct path_header *path_header; + const BYTE *types; + + path_header = buffer_read(mbuf, sizeof(struct path_header)); + if (!path_header) + { + ERR("failed to read path header\n"); + return InvalidParameter; + } + if (path_header->magic != VERSION_MAGIC) + { + ERR("invalid path header magic %#x\n", path_header->magic); + return InvalidParameter; + } + + /* Windows always fails to create an empty path in a region */ + if (!path_header->count) + { + TRACE("refusing to create an empty path in a region\n"); + return GenericError; + } + + status = GdipCreatePath(FillModeAlternate, &path); + if (status) return status; + + node->elementdata.path = path; + + if (!lengthen_path(path, path_header->count)) + return OutOfMemory; + + path->pathdata.Count = path_header->count; + + if (path_header->flags & ~FLAGS_INTPATH) + FIXME("unhandled path flags %#x\n", path_header->flags); + + if (path_header->flags & FLAGS_INTPATH) + { + const packed_point *pt; + DWORD i; + + pt = buffer_read(mbuf, sizeof(packed_point) * path_header->count); + if (!pt) + { + ERR("failed to read packed %u path points\n", path_header->count); + return InvalidParameter; + } + + for (i = 0; i < path_header->count; i++) + { + path->pathdata.Points[i].X = (REAL)pt[i].X; + path->pathdata.Points[i].Y = (REAL)pt[i].Y; + } + } + else + { + const GpPointF *ptf; + + ptf = buffer_read(mbuf, sizeof(GpPointF) * path_header->count); + if (!ptf) + { + ERR("failed to read %u path points\n", path_header->count); + return InvalidParameter; + } + memcpy(path->pathdata.Points, ptf, sizeof(GpPointF) * path_header->count); + } + + types = buffer_read(mbuf, path_header->count); + if (!types) + { + ERR("failed to read %u path types\n", path_header->count); + return InvalidParameter; + } + memcpy(path->pathdata.Types, types, path_header->count); + if (path_header->count & 3) + { + if (!buffer_read(mbuf, 4 - (path_header->count & 3))) + { + ERR("failed to read rounding %u bytes\n", 4 - (path_header->count & 3)); + return InvalidParameter; + } + } + + *count += 1; + return Ok; + } + + case RegionDataEmptyRect: + case RegionDataInfiniteRect: + *count += 1; + return Ok; + + default: + FIXME("element type %#x is not supported\n", *type); + break; + } + + return InvalidParameter; +} + GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRegion **region) { - FIXME("(%p, %d, %p): stub\n", data, size, region); + GpStatus status; + struct memory_buffer mbuf; + const struct region_header *region_header; + INT count; - *region = NULL; - return NotImplemented; + if (!data || !size) return InvalidParameter; + + TRACE("%p, %d, %p\n", data, size, region); + + init_memory_buffer(&mbuf, data, size); + + region_header = buffer_read(&mbuf, sizeof(struct region_header)); + if (!region_header || region_header->magic != VERSION_MAGIC) + return InvalidParameter; + + status = GdipCreateRegion(region); + if (status != Ok) return status; + + count = 0; + status = read_element(&mbuf, *region, &(*region)->node, &count); + if (status == Ok && !count) + status = InvalidParameter; + + if (status != Ok) + GdipDeleteRegion(*region); + + return status; } @@ -726,15 +958,9 @@ static void write_element(const region_element* element, DWORD *buffer, { INT i; const GpPath* path = element->elementdata.path; - struct _pathheader - { - DWORD size; - DWORD magic; - DWORD count; - DWORD flags; - } *pathheader; + struct path_header *pathheader; - pathheader = (struct _pathheader *)(buffer + *filled); + pathheader = (struct path_header *)(buffer + *filled); pathheader->flags = is_integer_path(path) ? FLAGS_INTPATH : FLAGS_NOFLAGS; /* 3 for headers, once again size doesn't count itself */ @@ -811,13 +1037,7 @@ static void write_element(const region_element* element, DWORD *buffer, GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, UINT *needed) { - struct _region_header - { - DWORD size; - DWORD checksum; - DWORD magic; - DWORD num_children; - } *region_header; + struct region_header *region_header; INT filled = 0; UINT required; GpStatus status; @@ -835,7 +1055,7 @@ GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, return InsufficientBuffer; } - region_header = (struct _region_header *)buffer; + region_header = (struct region_header *)buffer; region_header->size = sizeheader_size + get_element_size(®ion->node); region_header->checksum = 0; region_header->magic = VERSION_MAGIC; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index bffff1211d4..4faf733a73b 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -76,7 +76,7 @@ reactos/dll/win32/dwmapi # Synced to WineStaging-1.7.37 reactos/dll/win32/faultrep # Synced to Wine-1.7.27 reactos/dll/win32/fltlib # Synced to Wine-1.7.27 reactos/dll/win32/fusion # Synced to WineStaging-1.7.37 -reactos/dll/win32/gdiplus # Synced to Wine-1.7.27 +reactos/dll/win32/gdiplus # Synced to WineStaging-1.7.37 reactos/dll/win32/hhctrl.ocx # Synced to Wine-1.7.27 reactos/dll/win32/hlink # Synced to Wine-1.7.27 reactos/dll/win32/hnetcfg # Synced to Wine-1.7.27