mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 02:34:53 +00:00
[GDIPLUS] Sync with Wine Staging 1.7.37. CORE-9246
svn path=/trunk/; revision=66857
This commit is contained in:
parent
89656789aa
commit
5478176ded
|
@ -823,6 +823,10 @@ static void get_bitmap_sample_size(InterpolationMode interpolation, WrapMode wra
|
||||||
right = bitmap->width-1;
|
right = bitmap->width-1;
|
||||||
if (bottom >= bitmap->height)
|
if (bottom >= bitmap->height)
|
||||||
bottom = bitmap->height-1;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1775,7 +1779,7 @@ static GpStatus draw_poly(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *
|
||||||
for(i = 1; i < count; i++){
|
for(i = 1; i < count; i++){
|
||||||
if((types[i] & PathPointTypePathTypeMask) == PathPointTypeBezier){
|
if((types[i] & PathPointTypePathTypeMask) == PathPointTypeBezier){
|
||||||
if((i + 2 >= count) || !(types[i + 1] & PathPointTypeBezier)
|
if((i + 2 >= count) || !(types[i + 1] & PathPointTypeBezier)
|
||||||
|| !(types[i + 1] & PathPointTypeBezier)){
|
|| !(types[i + 2] & PathPointTypeBezier)){
|
||||||
ERR("Bad bezier points\n");
|
ERR("Bad bezier points\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -2021,8 +2025,7 @@ static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect)
|
||||||
rect->Height = GetDeviceCaps(graphics->hdc, VERTRES);
|
rect->Height = GetDeviceCaps(graphics->hdc, VERTRES);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (graphics->hdc &&
|
if (graphics->hdc)
|
||||||
(GetMapMode(graphics->hdc) != MM_TEXT || GetGraphicsMode(graphics->hdc) != GM_COMPATIBLE))
|
|
||||||
{
|
{
|
||||||
POINT points[2];
|
POINT points[2];
|
||||||
|
|
||||||
|
|
|
@ -565,8 +565,8 @@ GpStatus convert_pixels(INT width, INT height,
|
||||||
}
|
}
|
||||||
|
|
||||||
#define convert_indexed_to_rgb(getpixel_function, setpixel_function) do { \
|
#define convert_indexed_to_rgb(getpixel_function, setpixel_function) do { \
|
||||||
for (x=0; x<width; x++) \
|
for (y=0; y<height; y++) \
|
||||||
for (y=0; y<height; y++) { \
|
for (x=0; x<width; x++) { \
|
||||||
BYTE index; \
|
BYTE index; \
|
||||||
ARGB argb; \
|
ARGB argb; \
|
||||||
BYTE *color = (BYTE *)&argb; \
|
BYTE *color = (BYTE *)&argb; \
|
||||||
|
@ -578,8 +578,8 @@ GpStatus convert_pixels(INT width, INT height,
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
#define convert_rgb_to_rgb(getpixel_function, setpixel_function) do { \
|
#define convert_rgb_to_rgb(getpixel_function, setpixel_function) do { \
|
||||||
for (x=0; x<width; x++) \
|
for (y=0; y<height; y++) \
|
||||||
for (y=0; y<height; y++) { \
|
for (x=0; x<width; x++) { \
|
||||||
BYTE r, g, b, a; \
|
BYTE r, g, b, a; \
|
||||||
getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \
|
getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \
|
||||||
setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x); \
|
setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x); \
|
||||||
|
@ -588,8 +588,8 @@ GpStatus convert_pixels(INT width, INT height,
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
#define convert_rgb_to_indexed(getpixel_function, setpixel_function) do { \
|
#define convert_rgb_to_indexed(getpixel_function, setpixel_function) do { \
|
||||||
for (x=0; x<width; x++) \
|
for (y=0; y<height; y++) \
|
||||||
for (y=0; y<height; y++) { \
|
for (x=0; x<width; x++) { \
|
||||||
BYTE r, g, b, a; \
|
BYTE r, g, b, a; \
|
||||||
getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \
|
getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \
|
||||||
setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x, palette); \
|
setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x, palette); \
|
||||||
|
@ -1466,6 +1466,18 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromResource(HINSTANCE hInstance,
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline DWORD blend_argb_no_bkgnd_alpha(DWORD src, DWORD bkgnd)
|
||||||
|
{
|
||||||
|
BYTE b = (BYTE)src;
|
||||||
|
BYTE g = (BYTE)(src >> 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,
|
GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
||||||
HBITMAP* hbmReturn, ARGB background)
|
HBITMAP* hbmReturn, ARGB background)
|
||||||
{
|
{
|
||||||
|
@ -1506,6 +1518,17 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
||||||
|
|
||||||
if (stat == Ok)
|
if (stat == Ok)
|
||||||
stat = GdipBitmapUnlockBits(bitmap, &lockeddata);
|
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
|
else
|
||||||
stat = GenericError;
|
stat = GenericError;
|
||||||
|
@ -3836,11 +3859,6 @@ GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR* filenam
|
||||||
* Encoding functions -
|
* Encoding functions -
|
||||||
* These functions encode an image in different image file formats.
|
* 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,
|
static GpStatus encode_image_WIC(GpImage *image, IStream* stream,
|
||||||
GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params)
|
GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google (Lei Zhang)
|
* Copyright (C) 2008 Google (Lei Zhang)
|
||||||
|
* Copyright (C) 2013 Dmitry Timoshkov
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -64,6 +65,28 @@
|
||||||
#define FLAGS_NOFLAGS 0x0
|
#define FLAGS_NOFLAGS 0x0
|
||||||
#define FLAGS_INTPATH 0x4000
|
#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 as far as header->size is concerned. This doesn't include
|
||||||
* header->size or header->checksum
|
* header->size or header->checksum
|
||||||
*/
|
*/
|
||||||
|
@ -510,12 +533,221 @@ GpStatus WINGDIPAPI GdipCreateRegionRectI(GDIPCONST GpRect *rect,
|
||||||
return GdipCreateRegionRect(&rectf, region);
|
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)
|
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;
|
if (!data || !size) return InvalidParameter;
|
||||||
return NotImplemented;
|
|
||||||
|
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;
|
INT i;
|
||||||
const GpPath* path = element->elementdata.path;
|
const GpPath* path = element->elementdata.path;
|
||||||
struct _pathheader
|
struct path_header *pathheader;
|
||||||
{
|
|
||||||
DWORD size;
|
|
||||||
DWORD magic;
|
|
||||||
DWORD count;
|
|
||||||
DWORD flags;
|
|
||||||
} *pathheader;
|
|
||||||
|
|
||||||
pathheader = (struct _pathheader *)(buffer + *filled);
|
pathheader = (struct path_header *)(buffer + *filled);
|
||||||
|
|
||||||
pathheader->flags = is_integer_path(path) ? FLAGS_INTPATH : FLAGS_NOFLAGS;
|
pathheader->flags = is_integer_path(path) ? FLAGS_INTPATH : FLAGS_NOFLAGS;
|
||||||
/* 3 for headers, once again size doesn't count itself */
|
/* 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,
|
GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
|
||||||
UINT *needed)
|
UINT *needed)
|
||||||
{
|
{
|
||||||
struct _region_header
|
struct region_header *region_header;
|
||||||
{
|
|
||||||
DWORD size;
|
|
||||||
DWORD checksum;
|
|
||||||
DWORD magic;
|
|
||||||
DWORD num_children;
|
|
||||||
} *region_header;
|
|
||||||
INT filled = 0;
|
INT filled = 0;
|
||||||
UINT required;
|
UINT required;
|
||||||
GpStatus status;
|
GpStatus status;
|
||||||
|
@ -835,7 +1055,7 @@ GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
|
||||||
return InsufficientBuffer;
|
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->size = sizeheader_size + get_element_size(®ion->node);
|
||||||
region_header->checksum = 0;
|
region_header->checksum = 0;
|
||||||
region_header->magic = VERSION_MAGIC;
|
region_header->magic = VERSION_MAGIC;
|
||||||
|
|
|
@ -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/faultrep # Synced to Wine-1.7.27
|
||||||
reactos/dll/win32/fltlib # 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/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/hhctrl.ocx # Synced to Wine-1.7.27
|
||||||
reactos/dll/win32/hlink # 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
|
reactos/dll/win32/hnetcfg # Synced to Wine-1.7.27
|
||||||
|
|
Loading…
Reference in a new issue