[GDIPLUS] Sync with Wine Staging 1.7.47. CORE-9924

svn path=/trunk/; revision=68437
This commit is contained in:
Amine Khaldi
2015-07-19 13:31:15 +00:00
parent 1174b60215
commit 373482cc7d
10 changed files with 877 additions and 436 deletions
+1 -1
View File
@@ -450,7 +450,7 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW
matrix = graphics->worldtrans;
if (font->unit == UnitPixel)
if (font->unit == UnitPixel || font->unit == UnitWorld)
{
height = units_to_pixels(font->emSize, graphics->unit, graphics->yres);
if (graphics->unit != UnitDisplay)
+3
View File
@@ -20,3 +20,6 @@
/* @makedep: gdiplus.manifest */
WINE_MANIFEST 24 gdiplus.manifest
/* @makedep: gdiplus11.manifest */
WINE_MANIFEST11 24 gdiplus11.manifest
+2 -2
View File
@@ -610,7 +610,7 @@
610 stdcall GdipFindFirstImageItem(ptr ptr)
611 stub GdipFindNextImageItem
612 stdcall GdipGetImageItemData(ptr ptr)
613 stub GdipCreateEffect
613 stdcall -stub GdipCreateEffect(ptr ptr)
614 stdcall GdipDeleteEffect(ptr)
615 stub GdipGetEffectParameterSize
616 stub GdipGetEffectParameters
@@ -621,7 +621,7 @@
621 stub GdipBitmapGetHistogram
622 stub GdipBitmapGetHistogramSize
623 stub GdipBitmapConvertFormat
624 stub GdipImageSetAbort
624 stdcall GdipImageSetAbort(ptr ptr)
625 stub GdipGraphicsSetAbort
626 stub GdipDrawImageFX
627 stdcall GdipConvertToEmfPlus(ptr ptr ptr long ptr ptr)
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="Microsoft.Windows.GdiPlus" version="1.1.7601.23038" processorArchitecture="" publicKeyToken="6595b64144ccf1df"/>
<file name="gdiplus.dll"/>
</assembly>
+28 -2
View File
@@ -47,9 +47,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
#define MAX_DASHLEN (16) /* this is a limitation of gdi */
#define INCH_HIMETRIC (2540)
#define VERSION_MAGIC 0xdbc01001
#define VERSION_MAGIC 0xdbc01001
#define VERSION_MAGIC2 0xdbc01002
#define TENSION_CONST (0.3)
#define GIF_DISPOSE_UNSPECIFIED 0
#define GIF_DISPOSE_DO_NOT_DISPOSE 1
#define GIF_DISPOSE_RESTORE_TO_BKGND 2
#define GIF_DISPOSE_RESTORE_TO_PREV 3
COLORREF ARGB2COLORREF(ARGB color) DECLSPEC_HIDDEN;
HBITMAP ARGB2BMP(ARGB color) DECLSPEC_HIDDEN;
extern INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2,
@@ -124,6 +130,26 @@ static inline ARGB color_over(ARGB bg, ARGB fg)
return (a<<24)|(r<<16)|(g<<8)|b;
}
/* fg is premult, bg and return value are not */
static inline ARGB color_over_fgpremult(ARGB bg, ARGB fg)
{
BYTE b, g, r, a;
BYTE bg_alpha, fg_alpha;
fg_alpha = (fg>>24)&0xff;
if (fg_alpha == 0) return bg;
bg_alpha = (((bg>>24)&0xff) * (0xff-fg_alpha)) / 0xff;
a = bg_alpha + fg_alpha;
b = ((bg&0xff)*bg_alpha + (fg&0xff)*0xff)/a;
g = (((bg>>8)&0xff)*bg_alpha + ((fg>>8)&0xff)*0xff)/a;
r = (((bg>>16)&0xff)*bg_alpha + ((fg>>16)&0xff)*0xff)/a;
return (a<<24)|(r<<16)|(g<<8)|b;
}
extern const char *debugstr_rectf(const RectF* rc) DECLSPEC_HIDDEN;
extern const char *debugstr_pointf(const PointF* pt) DECLSPEC_HIDDEN;
@@ -278,7 +304,7 @@ struct GpAdustableArrowCap{
struct GpImage{
IPicture *picture;
IStream *stream; /* source stream */
IWICBitmapDecoder *decoder;
ImageType type;
GUID format;
UINT flags;
+72 -38
View File
@@ -247,6 +247,7 @@ static INT prepare_dc(GpGraphics *graphics, GpPen *pen)
(pt[1].Y - pt[0].Y) * (pt[1].Y - pt[0].Y)) / sqrt(2.0);
width *= units_to_pixels(pen->width, pen->unit == UnitWorld ? graphics->unit : pen->unit, graphics->xres);
width *= graphics->scale;
}
if(pen->dash == DashStyleCustom){
@@ -349,21 +350,28 @@ static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn)
return GdipGetRegionHRgn(graphics->clip, NULL, hrgn);
}
/* Draw non-premultiplied ARGB data to the given graphics object */
/* Draw ARGB data to the given graphics object */
static GpStatus alpha_blend_bmp_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
const BYTE *src, INT src_width, INT src_height, INT src_stride)
const BYTE *src, INT src_width, INT src_height, INT src_stride, const PixelFormat fmt)
{
GpBitmap *dst_bitmap = (GpBitmap*)graphics->image;
INT x, y;
for (x=0; x<src_width; x++)
for (y=0; y<src_height; y++)
{
for (y=0; y<src_height; y++)
for (x=0; x<src_width; x++)
{
ARGB dst_color, src_color;
GdipBitmapGetPixel(dst_bitmap, x+dst_x, y+dst_y, &dst_color);
src_color = ((ARGB*)(src + src_stride * y))[x];
GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over(dst_color, src_color));
if (!(src_color & 0xff000000))
continue;
GdipBitmapGetPixel(dst_bitmap, x+dst_x, y+dst_y, &dst_color);
if (fmt & PixelFormatPAlpha)
GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over_fgpremult(dst_color, src_color));
else
GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over(dst_color, src_color));
}
}
@@ -371,7 +379,7 @@ static GpStatus alpha_blend_bmp_pixels(GpGraphics *graphics, INT dst_x, INT dst_
}
static GpStatus alpha_blend_hdc_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
const BYTE *src, INT src_width, INT src_height, INT src_stride)
const BYTE *src, INT src_width, INT src_height, INT src_stride, PixelFormat fmt)
{
HDC hdc;
HBITMAP hbitmap;
@@ -395,7 +403,8 @@ static GpStatus alpha_blend_hdc_pixels(GpGraphics *graphics, INT dst_x, INT dst_
hbitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_RGB_COLORS,
(void**)&temp_bits, NULL, 0);
if (GetDeviceCaps(graphics->hdc, SHADEBLENDCAPS) == SB_NONE)
if (GetDeviceCaps(graphics->hdc, SHADEBLENDCAPS) == SB_NONE ||
fmt & PixelFormatPAlpha)
memcpy(temp_bits, src, src_width * src_height * 4);
else
convert_32bppARGB_to_32bppPARGB(src_width, src_height, temp_bits,
@@ -411,7 +420,7 @@ static GpStatus alpha_blend_hdc_pixels(GpGraphics *graphics, INT dst_x, INT dst_
}
static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst_y,
const BYTE *src, INT src_width, INT src_height, INT src_stride, HRGN hregion)
const BYTE *src, INT src_width, INT src_height, INT src_stride, HRGN hregion, PixelFormat fmt)
{
GpStatus stat=Ok;
@@ -461,7 +470,7 @@ static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst
stat = alpha_blend_bmp_pixels(graphics, rects[i].left, rects[i].top,
&src[(rects[i].left - dst_x) * 4 + (rects[i].top - dst_y) * src_stride],
rects[i].right - rects[i].left, rects[i].bottom - rects[i].top,
src_stride);
src_stride, fmt);
}
GdipFree(rgndata);
@@ -494,7 +503,7 @@ static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst
ExtSelectClipRgn(graphics->hdc, hregion, RGN_AND);
stat = alpha_blend_hdc_pixels(graphics, dst_x, dst_y, src, src_width,
src_height, src_stride);
src_height, src_stride, fmt);
RestoreDC(graphics->hdc, save);
@@ -505,27 +514,29 @@ static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst
}
static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
const BYTE *src, INT src_width, INT src_height, INT src_stride)
const BYTE *src, INT src_width, INT src_height, INT src_stride, PixelFormat fmt)
{
return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL);
return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL, fmt);
}
static ARGB blend_colors(ARGB start, ARGB end, REAL position)
{
ARGB result=0;
ARGB i;
INT a1, a2, a3;
INT start_a, end_a, final_a;
INT pos;
a1 = (start >> 24) & 0xff;
a2 = (end >> 24) & 0xff;
pos = gdip_round(position * 0xff);
a3 = (int)(a1*(1.0f - position)+a2*(position));
start_a = ((start >> 24) & 0xff) * (pos ^ 0xff);
end_a = ((end >> 24) & 0xff) * pos;
result |= a3 << 24;
final_a = start_a + end_a;
for (i=0xff; i<=0xff0000; i = i << 8)
result |= (int)((start&i)*(1.0f - position)+(end&i)*(position))&i;
return result;
if (final_a < 0xff) return 0;
return (final_a / 0xff) << 24 |
((((start >> 16) & 0xff) * start_a + (((end >> 16) & 0xff) * end_a)) / final_a) << 16 |
((((start >> 8) & 0xff) * start_a + (((end >> 8) & 0xff) * end_a)) / final_a) << 8 |
(((start & 0xff) * start_a + ((end & 0xff) * end_a)) / final_a);
}
static ARGB blend_line_gradient(GpLineGradient* brush, REAL position)
@@ -645,8 +656,9 @@ static BOOL color_is_gray(ARGB color)
return (r == g) && (g == b);
}
static void apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data,
UINT width, UINT height, INT stride, ColorAdjustType type)
/* returns preferred pixel format for the applied attributes */
static PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data,
UINT width, UINT height, INT stride, ColorAdjustType type, PixelFormat fmt)
{
UINT x, y;
INT i;
@@ -658,6 +670,9 @@ static void apply_image_attributes(const GpImageAttributes *attributes, LPBYTE d
BYTE min_blue, min_green, min_red;
BYTE max_blue, max_green, max_red;
if (!data || fmt != PixelFormat32bppARGB)
return PixelFormat32bppARGB;
if (attributes->colorkeys[type].enabled)
key = &attributes->colorkeys[type];
else
@@ -691,6 +706,9 @@ static void apply_image_attributes(const GpImageAttributes *attributes, LPBYTE d
{
const struct color_remap_table *table;
if (!data || fmt != PixelFormat32bppARGB)
return PixelFormat32bppARGB;
if (attributes->colorremaptables[type].enabled)
table = &attributes->colorremaptables[type];
else
@@ -720,6 +738,9 @@ static void apply_image_attributes(const GpImageAttributes *attributes, LPBYTE d
int gray_matrix[5][5];
BOOL identity;
if (!data || fmt != PixelFormat32bppARGB)
return PixelFormat32bppARGB;
if (attributes->colormatrices[type].enabled)
colormatrices = &attributes->colormatrices[type];
else
@@ -758,6 +779,9 @@ static void apply_image_attributes(const GpImageAttributes *attributes, LPBYTE d
{
REAL gamma;
if (!data || fmt != PixelFormat32bppARGB)
return PixelFormat32bppARGB;
if (attributes->gamma_enabled[type])
gamma = attributes->gamma[type];
else
@@ -782,6 +806,8 @@ static void apply_image_attributes(const GpImageAttributes *attributes, LPBYTE d
*src_color = (*src_color & 0xff000000) | (red << 16) | (green << 8) | blue;
}
}
return fmt;
}
/* Given a bitmap and its source rectangle, find the smallest rectangle in the
@@ -1226,7 +1252,7 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
if (stat == Ok)
apply_image_attributes(fill->imageattributes, fill->bitmap_bits,
bitmap->width, bitmap->height,
src_stride, ColorAdjustTypeBitmap);
src_stride, ColorAdjustTypeBitmap, lockeddata.PixelFormat);
if (stat != Ok)
{
@@ -2115,7 +2141,7 @@ static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font,
HFONT unscaled_font;
TEXTMETRICW textmet;
if (font->unit == UnitPixel)
if (font->unit == UnitPixel || font->unit == UnitWorld)
font_height = font->emSize;
else
{
@@ -2138,8 +2164,8 @@ static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font,
GpMatrix xform = *matrix;
GdipTransformMatrixPoints(&xform, pt, 3);
}
if (graphics)
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 3);
GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 3);
angle = -gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X));
rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
(pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
@@ -2979,15 +3005,18 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
return OutOfMemory;
src_stride = sizeof(ARGB) * src_area.Width;
/* Read the bits we need from the source bitmap into an ARGB buffer. */
/* Read the bits we need from the source bitmap into a compatible buffer. */
lockeddata.Width = src_area.Width;
lockeddata.Height = src_area.Height;
lockeddata.Stride = src_stride;
lockeddata.PixelFormat = PixelFormat32bppARGB;
lockeddata.Scan0 = src_data;
if (!do_resampling && bitmap->format == PixelFormat32bppPARGB)
lockeddata.PixelFormat = apply_image_attributes(imageAttributes, NULL, 0, 0, 0, ColorAdjustTypeBitmap, bitmap->format);
else
lockeddata.PixelFormat = PixelFormat32bppARGB;
stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf,
PixelFormat32bppARGB, &lockeddata);
lockeddata.PixelFormat, &lockeddata);
if (stat == Ok)
stat = GdipBitmapUnlockBits(bitmap, &lockeddata);
@@ -3000,7 +3029,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
apply_image_attributes(imageAttributes, src_data,
src_area.Width, src_area.Height,
src_stride, ColorAdjustTypeBitmap);
src_stride, ColorAdjustTypeBitmap, lockeddata.PixelFormat);
if (do_resampling)
{
@@ -3048,7 +3077,8 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
}
stat = alpha_blend_pixels(graphics, dst_area.left, dst_area.top,
dst_data, dst_area.right - dst_area.left, dst_area.bottom - dst_area.top, dst_stride);
dst_data, dst_area.right - dst_area.left, dst_area.bottom - dst_area.top, dst_stride,
lockeddata.PixelFormat);
GdipFree(src_data);
@@ -3998,7 +4028,8 @@ static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush,
if (stat == Ok)
stat = alpha_blend_pixels_hrgn(graphics, gp_bound_rect.X,
gp_bound_rect.Y, (BYTE*)pixel_data, gp_bound_rect.Width,
gp_bound_rect.Height, gp_bound_rect.Width * 4, hregion);
gp_bound_rect.Height, gp_bound_rect.Width * 4, hregion,
PixelFormat32bppARGB);
GdipFree(pixel_data);
}
@@ -4730,6 +4761,9 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
scaled_rect.Width = layoutRect->Width * args.rel_width;
scaled_rect.Height = layoutRect->Height * args.rel_height;
if (scaled_rect.Width >= 1 << 23) scaled_rect.Width = 1 << 23;
if (scaled_rect.Height >= 1 << 23) scaled_rect.Height = 1 << 23;
get_font_hfont(graphics, font, stringFormat, &gdifont, NULL);
oldfont = SelectObject(hdc, gdifont);
@@ -5705,7 +5739,7 @@ GpStatus WINGDIPAPI GdipGetDC(GpGraphics *graphics, HDC *hdc)
{
stat = METAFILE_GetDC((GpMetafile*)graphics->image, hdc);
}
else if (!graphics->hdc || graphics->alpha_hdc ||
else if (!graphics->hdc ||
(graphics->image && graphics->image->type == ImageTypeBitmap && ((GpBitmap*)graphics->image)->format & PixelFormatAlpha))
{
/* Create a fake HDC and fill it with a constant color. */
@@ -5797,7 +5831,7 @@ GpStatus WINGDIPAPI GdipReleaseDC(GpGraphics *graphics, HDC hdc)
/* Write the changed pixels to the real target. */
alpha_blend_pixels(graphics, 0, 0, graphics->temp_bits,
graphics->temp_hbitmap_width, graphics->temp_hbitmap_height,
graphics->temp_hbitmap_width * 4);
graphics->temp_hbitmap_width * 4, PixelFormat32bppARGB);
/* Clean up. */
DeleteDC(graphics->temp_hdc);
@@ -6352,7 +6386,7 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
/* draw the result */
stat = alpha_blend_pixels(graphics, min_x, min_y, pixel_data, pixel_area.Width,
pixel_area.Height, pixel_data_stride);
pixel_area.Height, pixel_data_stride, PixelFormat32bppARGB);
GdipFree(pixel_data);
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -1105,10 +1105,11 @@ GpStatus WINGDIPAPI GdipConvertToEmfPlus(const GpGraphics* ref,
TRACE("(%p,%p,%p,%u,%s,%p)\n", ref, metafile, succ, emfType,
debugstr_w(description), out_metafile);
if(!ref || !metafile || !out_metafile)
if(!ref || !metafile || !out_metafile || emfType < EmfTypeEmfOnly || emfType > EmfTypeEmfPlusDual)
return InvalidParameter;
*succ = FALSE;
if(succ)
*succ = FALSE;
*out_metafile = NULL;
if(!(calls++))
+229 -249
View File
@@ -533,224 +533,6 @@ 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)
{
GpStatus status;
struct memory_buffer mbuf;
const struct region_header *region_header;
INT count;
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;
}
/******************************************************************************
* GdipCreateRegionHrgn [GDIPLUS.@]
*/
@@ -1071,6 +853,232 @@ GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
return Ok;
}
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(*type));
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(*rc));
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(*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(*pt) * 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(*ptf) * path_header->count);
if (!ptf)
{
ERR("failed to read %u path points\n", path_header->count);
return InvalidParameter;
}
memcpy(path->pathdata.Points, ptf, sizeof(*ptf) * 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;
}
/*****************************************************************************
* GdipCreateRegionRgnData [GDIPLUS.@]
*/
GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRegion **region)
{
const struct region_header *region_header;
struct memory_buffer mbuf;
GpStatus status;
INT count;
TRACE("(%p, %d, %p)\n", data, size, region);
if (!data || !size)
return InvalidParameter;
init_memory_buffer(&mbuf, data, size);
region_header = buffer_read(&mbuf, sizeof(*region_header));
if (!region_header || (region_header->magic != VERSION_MAGIC &&
region_header->magic != VERSION_MAGIC2))
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);
*region = NULL;
}
return status;
}
/*****************************************************************************
* GdipGetRegionDataSize [GDIPLUS.@]
*/
@@ -1098,16 +1106,12 @@ static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn)
{
new_hdc = CreateCompatibleDC(0);
if (!new_hdc)
{
ERR("CreateCompatibleDC failed\n");
return OutOfMemory;
}
stat = GdipCreateFromHDC(new_hdc, &new_graphics);
graphics = new_graphics;
if (stat != Ok)
{
ERR("GdipCreateFromHDC failed: 0x%x\n", stat);
DeleteDC(new_hdc);
return stat;
}
@@ -1116,10 +1120,7 @@ static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn)
{
graphics->hdc = new_hdc = CreateCompatibleDC(0);
if (!new_hdc)
{
ERR("CreateCompatibleDC failed\n");
return OutOfMemory;
}
}
save_state = SaveDC(graphics->hdc);
@@ -1132,16 +1133,8 @@ static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn)
if (stat == Ok)
{
*hrgn = PathToRegion(graphics->hdc);
if (*hrgn == NULL)
{
ERR("PathToRegion failed\n");
}
stat = *hrgn ? Ok : OutOfMemory;
}
else
{
ERR("trace_path failed: 0x%x\n", stat);
}
RestoreDC(graphics->hdc, save_state);
if (new_hdc)
@@ -1176,18 +1169,11 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
stat = GdipCreatePath(FillModeAlternate, &path);
if (stat != Ok)
{
ERR("GdipCreatePath failed: 0x%x\n", stat);
return stat;
}
stat = GdipAddPathRectangle(path, rc->X, rc->Y, rc->Width, rc->Height);
if (stat == Ok)
stat = get_path_hrgn(path, graphics, hrgn);
else
{
ERR("GdipAddPathRectangle failed: 0x%x\n", stat);
}
GdipDeletePath(path);
@@ -1218,7 +1204,7 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
case CombineModeIntersect:
return get_region_hrgn(element->elementdata.combine.right, graphics, hrgn);
case CombineModeXor: case CombineModeExclude:
left = CreateRectRgn(-4194304, -4194304, 4194304, 4194304);
left = CreateRectRgn(-(1 << 22), -(1 << 22), 1 << 22, 1 << 22);
break;
case CombineModeUnion: case CombineModeComplement:
*hrgn = NULL;
@@ -1243,7 +1229,7 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
*hrgn = left;
return Ok;
case CombineModeXor: case CombineModeComplement:
right = CreateRectRgn(-4194304, -4194304, 4194304, 4194304);
right = CreateRectRgn(-(1 << 22), -(1 << 22), 1 << 22, 1 << 22);
break;
case CombineModeUnion: case CombineModeExclude:
DeleteObject(left);
@@ -1297,18 +1283,12 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
*/
GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *region, GpGraphics *graphics, HRGN *hrgn)
{
GpStatus status;
TRACE("(%p, %p, %p)\n", region, graphics, hrgn);
if (!region || !hrgn)
return InvalidParameter;
status = get_region_hrgn(&region->node, graphics, hrgn);
if (status != Ok)
{
ERR("get_region_hrgn() failed. region->node.type = 0x%x\n", region->node.type);
}
return status;
return get_region_hrgn(&region->node, graphics, hrgn);
}
GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
+1 -1
View File
@@ -70,7 +70,7 @@ reactos/dll/win32/dwmapi # Synced to WineStaging-1.7.37
reactos/dll/win32/faultrep # Synced to WineStaging-1.7.37
reactos/dll/win32/fltlib # Synced to WineStaging-1.7.47
reactos/dll/win32/fusion # Synced to WineStaging-1.7.47
reactos/dll/win32/gdiplus # Synced to WineStaging-1.7.37
reactos/dll/win32/gdiplus # Synced to WineStaging-1.7.47
reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-1.7.47
reactos/dll/win32/hlink # Synced to WineStaging-1.7.37
reactos/dll/win32/hnetcfg # Synced to WineStaging-1.7.37