mirror of
https://github.com/reactos/reactos.git
synced 2025-02-20 15:35:04 +00:00
[GDIPLUS] Sync with Wine Staging 1.7.47. CORE-9924
svn path=/trunk/; revision=68437
This commit is contained in:
parent
1174b60215
commit
373482cc7d
10 changed files with 877 additions and 436 deletions
|
@ -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)
|
||||
|
|
|
@ -20,3 +20,6 @@
|
|||
|
||||
/* @makedep: gdiplus.manifest */
|
||||
WINE_MANIFEST 24 gdiplus.manifest
|
||||
|
||||
/* @makedep: gdiplus11.manifest */
|
||||
WINE_MANIFEST11 24 gdiplus11.manifest
|
||||
|
|
|
@ -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)
|
||||
|
|
5
reactos/dll/win32/gdiplus/gdiplus11.manifest
Normal file
5
reactos/dll/win32/gdiplus/gdiplus11.manifest
Normal file
|
@ -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>
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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++))
|
||||
|
|
|
@ -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(®ion->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(®ion->node, graphics, hrgn);
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue