From 5a6e6bdf2a4dc9b1f6bd83b413d281545dc678f6 Mon Sep 17 00:00:00 2001 From: Dmitry Chapyshev Date: Thu, 3 Sep 2009 15:07:25 +0000 Subject: [PATCH] - Sync gdiplus with Wine 1.1.29 svn path=/trunk/; revision=42989 --- reactos/dll/win32/gdiplus/brush.c | 51 +- reactos/dll/win32/gdiplus/gdiplus.c | 19 + reactos/dll/win32/gdiplus/gdiplus.rbuild | 1 + reactos/dll/win32/gdiplus/gdiplus.spec | 30 +- reactos/dll/win32/gdiplus/gdiplus_private.h | 22 + reactos/dll/win32/gdiplus/graphics.c | 723 ++++++++-- reactos/dll/win32/gdiplus/image.c | 1337 ++++++++++++++----- reactos/dll/win32/gdiplus/imageattributes.c | 11 +- reactos/dll/win32/gdiplus/region.c | 155 ++- reactos/include/psdk/gdiplusflat.h | 33 + 10 files changed, 1892 insertions(+), 490 deletions(-) diff --git a/reactos/dll/win32/gdiplus/brush.c b/reactos/dll/win32/gdiplus/brush.c index cdbc17ddf2a..6220443b04d 100644 --- a/reactos/dll/win32/gdiplus/brush.c +++ b/reactos/dll/win32/gdiplus/brush.c @@ -288,6 +288,17 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint, (*line)->rect.Width = fabs(startpoint->X - endpoint->X); (*line)->rect.Height = fabs(startpoint->Y - endpoint->Y); + if ((*line)->rect.Width == 0) + { + (*line)->rect.X -= (*line)->rect.Height / 2.0f; + (*line)->rect.Width = (*line)->rect.Height; + } + else if ((*line)->rect.Height == 0) + { + (*line)->rect.Y -= (*line)->rect.Width / 2.0f; + (*line)->rect.Height = (*line)->rect.Width; + } + (*line)->blendcount = 1; (*line)->blendfac = GdipAlloc(sizeof(REAL)); (*line)->blendpos = GdipAlloc(sizeof(REAL)); @@ -686,9 +697,9 @@ GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image, n_y + n_height > ((GpBitmap*)image)->height) return InvalidParameter; - IPicture_get_Handle(image->picture, (OLE_HANDLE*)&hbm); + hbm = ((GpBitmap*)image)->hbitmap; if(!hbm) return GenericError; - IPicture_get_CurDC(image->picture, &hdc); + hdc = ((GpBitmap*)image)->hdc; bm_is_selected = (hdc != 0); pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); @@ -1342,6 +1353,13 @@ GpStatus WINGDIPAPI GdipSetPathGradientBlend(GpPathGradient *brush, GDIPCONST RE return NotImplemented; } +GpStatus WINGDIPAPI GdipSetPathGradientPresetBlend(GpPathGradient *brush, + GDIPCONST ARGB *blend, GDIPCONST REAL *pos, INT count) +{ + FIXME("(%p,%p,%p,%i): stub\n", brush, blend, pos, count); + return NotImplemented; +} + GpStatus WINGDIPAPI GdipSetPathGradientCenterColor(GpPathGradient *grad, ARGB argb) { @@ -1551,12 +1569,33 @@ GpStatus WINGDIPAPI GdipRotateTextureTransform(GpTexture* brush, REAL angle, GpStatus WINGDIPAPI GdipSetLineLinearBlend(GpLineGradient *brush, REAL focus, REAL scale) { - static int calls; + REAL factors[3]; + REAL positions[3]; + int num_points = 0; - if(!(calls++)) - FIXME("not implemented\n"); + TRACE("(%p,%.2f,%.2f)\n", brush, focus, scale); - return NotImplemented; + if (!brush) return InvalidParameter; + + if (focus != 0.0) + { + factors[num_points] = 0.0; + positions[num_points] = 0.0; + num_points++; + } + + factors[num_points] = scale; + positions[num_points] = focus; + num_points++; + + if (focus != 1.0) + { + factors[num_points] = 0.0; + positions[num_points] = 1.0; + num_points++; + } + + return GdipSetLineBlend(brush, factors, positions, num_points); } GpStatus WINGDIPAPI GdipSetLinePresetBlend(GpLineGradient *brush, diff --git a/reactos/dll/win32/gdiplus/gdiplus.c b/reactos/dll/win32/gdiplus/gdiplus.c index 06019a24e35..ec956f34f57 100644 --- a/reactos/dll/win32/gdiplus/gdiplus.c +++ b/reactos/dll/win32/gdiplus/gdiplus.c @@ -399,6 +399,25 @@ BOOL lengthen_path(GpPath *path, INT len) return TRUE; } +void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height, + BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride) +{ + UINT x, y; + for (y=0; yuser32 gdi32 kernel32 + windowscodecs ntdll diff --git a/reactos/dll/win32/gdiplus/gdiplus.spec b/reactos/dll/win32/gdiplus/gdiplus.spec index c658e002dfc..bda241ed93b 100644 --- a/reactos/dll/win32/gdiplus/gdiplus.spec +++ b/reactos/dll/win32/gdiplus/gdiplus.spec @@ -165,11 +165,11 @@ @ stdcall GdipDrawClosedCurveI(ptr ptr ptr long) @ stdcall GdipDrawCurve2(ptr ptr ptr long long) @ stdcall GdipDrawCurve2I(ptr ptr ptr long long) -@ stub GdipDrawCurve3 -@ stub GdipDrawCurve3I +@ stdcall GdipDrawCurve3(ptr ptr ptr long long long long) +@ stdcall GdipDrawCurve3I(ptr ptr ptr long long long long) @ stdcall GdipDrawCurve(ptr ptr ptr long) @ stdcall GdipDrawCurveI(ptr ptr ptr long) -@ stub GdipDrawDriverString +@ stdcall GdipDrawDriverString(ptr ptr long ptr ptr ptr long ptr) @ stdcall GdipDrawEllipse(ptr ptr long long long long) @ stdcall GdipDrawEllipseI(ptr ptr long long long long) @ stdcall GdipDrawImage(ptr ptr long long) @@ -291,7 +291,7 @@ @ stdcall GdipGetImageHeight(ptr ptr) @ stdcall GdipGetImageHorizontalResolution(ptr ptr) @ stub GdipGetImageItemData -@ stub GdipGetImagePalette +@ stdcall GdipGetImagePalette(ptr ptr long) @ stdcall GdipGetImagePaletteSize(ptr ptr) @ stdcall GdipGetImagePixelFormat(ptr ptr) @ stdcall GdipGetImageRawFormat(ptr ptr) @@ -400,8 +400,8 @@ @ stub GdipGetTextureImage @ stdcall GdipGetTextureTransform(ptr ptr) @ stdcall GdipGetTextureWrapMode(ptr ptr) -@ stub GdipGetVisibleClipBounds -@ stub GdipGetVisibleClipBoundsI +@ stdcall GdipGetVisibleClipBounds(ptr ptr) +@ stdcall GdipGetVisibleClipBoundsI(ptr ptr) @ stdcall GdipGetWorldTransform(ptr ptr) @ stdcall GdipGraphicsClear(ptr long) @ stub GdipGraphicsSetAbort @@ -429,18 +429,18 @@ @ stdcall GdipIsVisiblePathPointI(ptr long long ptr ptr) @ stdcall GdipIsVisiblePoint(ptr long long ptr) @ stdcall GdipIsVisiblePointI(ptr long long ptr) -@ stub GdipIsVisibleRect -@ stub GdipIsVisibleRectI -@ stub GdipIsVisibleRegionPoint -@ stub GdipIsVisibleRegionPointI -@ stub GdipIsVisibleRegionRect -@ stub GdipIsVisibleRegionRectI +@ stdcall GdipIsVisibleRect(ptr long long long long ptr) +@ stdcall GdipIsVisibleRectI(ptr long long long long ptr) +@ stdcall GdipIsVisibleRegionPoint(ptr long long ptr ptr) +@ stdcall GdipIsVisibleRegionPointI(ptr long long ptr ptr) +@ stdcall GdipIsVisibleRegionRect(ptr long long long long ptr ptr) +@ stdcall GdipIsVisibleRegionRectI(ptr long long long long ptr ptr) @ stdcall GdipLoadImageFromFile(wstr ptr) @ stdcall GdipLoadImageFromFileICM(wstr ptr) @ stdcall GdipLoadImageFromStream(ptr ptr) @ stdcall GdipLoadImageFromStreamICM(ptr ptr) @ stdcall GdipMeasureCharacterRanges(ptr wstr long ptr ptr ptr long ptr) -@ stub GdipMeasureDriverString +@ stdcall GdipMeasureDriverString(ptr ptr long ptr ptr long ptr ptr) @ stdcall GdipMeasureString(ptr wstr long ptr ptr ptr ptr ptr ptr) @ stub GdipMultiplyLineTransform @ stdcall GdipMultiplyMatrix(ptr ptr long) @@ -469,7 +469,7 @@ @ stub GdipRecordMetafile @ stdcall GdipRecordMetafileFileName(wstr long long ptr long wstr ptr) @ stdcall GdipRecordMetafileFileNameI(wstr long long ptr long wstr ptr) -@ stub GdipRecordMetafileI +@ stdcall GdipRecordMetafileI(long long ptr long wstr ptr) @ stub GdipRecordMetafileStream @ stub GdipRecordMetafileStreamI @ stdcall GdipReleaseDC(ptr ptr) @@ -556,7 +556,7 @@ @ stdcall GdipSetPathGradientGammaCorrection(ptr long) @ stub GdipSetPathGradientLinearBlend @ stub GdipSetPathGradientPath -@ stub GdipSetPathGradientPresetBlend +@ stdcall GdipSetPathGradientPresetBlend(ptr ptr ptr long) @ stdcall GdipSetPathGradientSigmaBlend(ptr long long) @ stdcall GdipSetPathGradientSurroundColorsWithCount(ptr ptr ptr) @ stub GdipSetPathGradientTransform diff --git a/reactos/dll/win32/gdiplus/gdiplus_private.h b/reactos/dll/win32/gdiplus/gdiplus_private.h index 95133ca2d88..e87176e3064 100644 --- a/reactos/dll/win32/gdiplus/gdiplus_private.h +++ b/reactos/dll/win32/gdiplus/gdiplus_private.h @@ -29,6 +29,7 @@ #include "objbase.h" #include "ocidl.h" +#include "wine/list.h" #include "gdiplus.h" @@ -67,6 +68,11 @@ static inline INT roundr(REAL x) return (INT) floorf(x + 0.5); } +static inline INT ceilr(REAL x) +{ + return (INT) ceilf(x); +} + static inline REAL deg2rad(REAL degrees) { return M_PI * degrees / 180.0; @@ -74,6 +80,9 @@ static inline REAL deg2rad(REAL degrees) extern const char *debugstr_rectf(CONST RectF* rc); +extern void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height, + BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride); + struct GpPen{ UINT style; GpUnit unit; @@ -109,6 +118,8 @@ struct GpGraphics{ BOOL busy; /* hdc handle obtained by GdipGetDC */ GpRegion *clip; UINT textcontrast; /* not used yet. get/set only */ + struct list containers; + GraphicsContainer contid; /* last-issued container ID */ }; struct GpBrush{ @@ -214,14 +225,25 @@ struct GpBitmap{ ImageLockMode lockmode; INT numlocks; BYTE *bitmapbits; /* pointer to the buffer we passed in BitmapLockBits */ + HBITMAP hbitmap; + HDC hdc; + BYTE *bits; /* actual image bits if this is a DIB */ + INT stride; /* stride of bits if this is a DIB */ }; struct GpCachedBitmap{ GpImage *image; }; +struct color_key{ + BOOL enabled; + ARGB low; + ARGB high; +}; + struct GpImageAttributes{ WrapMode wrap; + struct color_key colorkeys[ColorAdjustTypeCount]; }; struct GpFont{ diff --git a/reactos/dll/win32/gdiplus/graphics.c b/reactos/dll/win32/gdiplus/graphics.c index 269815933f9..1df3eee4ba0 100644 --- a/reactos/dll/win32/gdiplus/graphics.c +++ b/reactos/dll/win32/gdiplus/graphics.c @@ -38,6 +38,7 @@ #include "gdiplus.h" #include "gdiplus_private.h" #include "wine/debug.h" +#include "wine/list.h" WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); @@ -941,6 +942,153 @@ GpStatus trace_path(GpGraphics *graphics, GpPath *path) return result; } +typedef struct _GraphicsContainerItem { + struct list entry; + GraphicsContainer contid; + + SmoothingMode smoothing; + CompositingQuality compqual; + InterpolationMode interpolation; + CompositingMode compmode; + TextRenderingHint texthint; + REAL scale; + GpUnit unit; + PixelOffsetMode pixeloffset; + UINT textcontrast; + GpMatrix* worldtrans; + GpRegion* clip; +} GraphicsContainerItem; + +static GpStatus init_container(GraphicsContainerItem** container, + GDIPCONST GpGraphics* graphics){ + GpStatus sts; + + *container = GdipAlloc(sizeof(GraphicsContainerItem)); + if(!(*container)) + return OutOfMemory; + + (*container)->contid = graphics->contid + 1; + + (*container)->smoothing = graphics->smoothing; + (*container)->compqual = graphics->compqual; + (*container)->interpolation = graphics->interpolation; + (*container)->compmode = graphics->compmode; + (*container)->texthint = graphics->texthint; + (*container)->scale = graphics->scale; + (*container)->unit = graphics->unit; + (*container)->textcontrast = graphics->textcontrast; + (*container)->pixeloffset = graphics->pixeloffset; + + sts = GdipCloneMatrix(graphics->worldtrans, &(*container)->worldtrans); + if(sts != Ok){ + GdipFree(*container); + *container = NULL; + return sts; + } + + sts = GdipCloneRegion(graphics->clip, &(*container)->clip); + if(sts != Ok){ + GdipDeleteMatrix((*container)->worldtrans); + GdipFree(*container); + *container = NULL; + return sts; + } + + return Ok; +} + +static void delete_container(GraphicsContainerItem* container){ + GdipDeleteMatrix(container->worldtrans); + GdipDeleteRegion(container->clip); + GdipFree(container); +} + +static GpStatus restore_container(GpGraphics* graphics, + GDIPCONST GraphicsContainerItem* container){ + GpStatus sts; + GpMatrix *newTrans; + GpRegion *newClip; + + sts = GdipCloneMatrix(container->worldtrans, &newTrans); + if(sts != Ok) + return sts; + + sts = GdipCloneRegion(container->clip, &newClip); + if(sts != Ok){ + GdipDeleteMatrix(newTrans); + return sts; + } + + GdipDeleteMatrix(graphics->worldtrans); + graphics->worldtrans = newTrans; + + GdipDeleteRegion(graphics->clip); + graphics->clip = newClip; + + graphics->contid = container->contid - 1; + + graphics->smoothing = container->smoothing; + graphics->compqual = container->compqual; + graphics->interpolation = container->interpolation; + graphics->compmode = container->compmode; + graphics->texthint = container->texthint; + graphics->scale = container->scale; + graphics->unit = container->unit; + graphics->textcontrast = container->textcontrast; + graphics->pixeloffset = container->pixeloffset; + + return Ok; +} + +static GpStatus get_graphics_bounds(GpGraphics* graphics, GpRectF* rect) +{ + RECT wnd_rect; + + if(graphics->hwnd) { + if(!GetClientRect(graphics->hwnd, &wnd_rect)) + return GenericError; + + rect->X = wnd_rect.left; + rect->Y = wnd_rect.top; + rect->Width = wnd_rect.right - wnd_rect.left; + rect->Height = wnd_rect.bottom - wnd_rect.top; + }else{ + rect->X = 0; + rect->Y = 0; + rect->Width = GetDeviceCaps(graphics->hdc, HORZRES); + rect->Height = GetDeviceCaps(graphics->hdc, VERTRES); + } + + return Ok; +} + +/* on success, rgn will contain the region of the graphics object which + * is visible after clipping has been applied */ +static GpStatus get_visible_clip_region(GpGraphics *graphics, GpRegion *rgn) +{ + GpStatus stat; + GpRectF rectf; + GpRegion* tmp; + + if((stat = get_graphics_bounds(graphics, &rectf)) != Ok) + return stat; + + if((stat = GdipCreateRegion(&tmp)) != Ok) + return stat; + + if((stat = GdipCombineRegionRect(tmp, &rectf, CombineModeReplace)) != Ok) + goto end; + + if((stat = GdipCombineRegionRegion(tmp, graphics->clip, CombineModeIntersect)) != Ok) + goto end; + + stat = GdipCombineRegionRegion(rgn, tmp, CombineModeReplace); + +end: + GdipDeleteRegion(tmp); + return stat; +} + GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics) { TRACE("(%p, %p)\n", hdc, graphics); @@ -955,7 +1103,7 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra TRACE("(%p, %p, %p)\n", hdc, hDevice, graphics); if(hDevice != NULL) { - FIXME("Don't know how to hadle parameter hDevice\n"); + FIXME("Don't know how to handle parameter hDevice\n"); return NotImplemented; } @@ -991,6 +1139,8 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra (*graphics)->scale = 1.0; (*graphics)->busy = FALSE; (*graphics)->textcontrast = 4; + list_init(&(*graphics)->containers); + (*graphics)->contid = 0; return Ok; } @@ -1155,6 +1305,7 @@ GpStatus WINGDIPAPI GdipCreateStreamOnFile(GDIPCONST WCHAR * filename, GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics) { + GraphicsContainerItem *cont, *next; TRACE("(%p)\n", graphics); if(!graphics) return InvalidParameter; @@ -1163,6 +1314,11 @@ GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics) if(graphics->owndc) ReleaseDC(graphics->hwnd, graphics->hdc); + LIST_FOR_EACH_ENTRY_SAFE(cont, next, &graphics->containers, GraphicsContainerItem, entry){ + list_remove(&cont->entry); + delete_container(cont); + } + GdipDeleteRegion(graphics->clip); GdipDeleteMatrix(graphics->worldtrans); GdipFree(graphics); @@ -1423,7 +1579,7 @@ GpStatus WINGDIPAPI GdipDrawCurveI(GpGraphics *graphics, GpPen *pen, TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count); - if(!points || count <= 0) + if(!points) return InvalidParameter; pointsF = GdipAlloc(sizeof(GpPointF)*count); @@ -1459,7 +1615,13 @@ GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics *graphics, GpPen *pen, if(graphics->busy) return ObjectBusy; + if(count < 2) + return InvalidParameter; + pt = GdipAlloc(len_pt * sizeof(GpPointF)); + if(!pt) + return OutOfMemory; + tension = tension * TENSION_CONST; calc_curve_bezier_endp(points[0].X, points[0].Y, points[1].X, points[1].Y, @@ -1508,7 +1670,7 @@ GpStatus WINGDIPAPI GdipDrawCurve2I(GpGraphics *graphics, GpPen *pen, TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension); - if(!points || count <= 0) + if(!points) return InvalidParameter; pointsF = GdipAlloc(sizeof(GpPointF)*count); @@ -1526,6 +1688,36 @@ GpStatus WINGDIPAPI GdipDrawCurve2I(GpGraphics *graphics, GpPen *pen, return ret; } +GpStatus WINGDIPAPI GdipDrawCurve3(GpGraphics *graphics, GpPen *pen, + GDIPCONST GpPointF *points, INT count, INT offset, INT numberOfSegments, + REAL tension) +{ + TRACE("(%p, %p, %p, %d, %d, %d, %.2f)\n", graphics, pen, points, count, offset, numberOfSegments, tension); + + if(offset >= count || numberOfSegments > count - offset - 1 || numberOfSegments <= 0){ + return InvalidParameter; + } + + return GdipDrawCurve2(graphics, pen, points + offset, numberOfSegments + 1, tension); +} + +GpStatus WINGDIPAPI GdipDrawCurve3I(GpGraphics *graphics, GpPen *pen, + GDIPCONST GpPoint *points, INT count, INT offset, INT numberOfSegments, + REAL tension) +{ + TRACE("(%p, %p, %p, %d, %d, %d, %.2f)\n", graphics, pen, points, count, offset, numberOfSegments, tension); + + if(count < 0){ + return OutOfMemory; + } + + if(offset >= count || numberOfSegments > count - offset - 1 || numberOfSegments <= 0){ + return InvalidParameter; + } + + return GdipDrawCurve2I(graphics, pen, points + offset, numberOfSegments + 1, tension); +} + GpStatus WINGDIPAPI GdipDrawEllipse(GpGraphics *graphics, GpPen *pen, REAL x, REAL y, REAL width, REAL height) { @@ -1569,18 +1761,10 @@ GpStatus WINGDIPAPI GdipDrawEllipseI(GpGraphics *graphics, GpPen *pen, INT x, GpStatus WINGDIPAPI GdipDrawImage(GpGraphics *graphics, GpImage *image, REAL x, REAL y) { - TRACE("(%p, %p, %.2f, %.2f)\n", graphics, image, x, y); - - /* IPicture::Render uses LONG coords */ - return GdipDrawImageI(graphics,image,roundr(x),roundr(y)); -} - -GpStatus WINGDIPAPI GdipDrawImageI(GpGraphics *graphics, GpImage *image, INT x, - INT y) -{ - UINT width, height, srcw, srch; + UINT width, height; + GpPointF points[3]; - TRACE("(%p, %p, %d, %d)\n", graphics, image, x, y); + TRACE("(%p, %p, %.2f, %.2f)\n", graphics, image, x, y); if(!graphics || !image) return InvalidParameter; @@ -1588,20 +1772,23 @@ GpStatus WINGDIPAPI GdipDrawImageI(GpGraphics *graphics, GpImage *image, INT x, GdipGetImageWidth(image, &width); GdipGetImageHeight(image, &height); - srcw = width * (((REAL) INCH_HIMETRIC) / - ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSX))); - srch = height * (((REAL) INCH_HIMETRIC) / - ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSY))); + /* FIXME: we should use the graphics and image dpi, somehow */ - if(image->type != ImageTypeMetafile){ - y += height; - height *= -1; - } + points[0].X = points[2].X = x; + points[0].Y = points[1].Y = y; + points[1].X = x + width; + points[2].Y = y + height; - IPicture_Render(image->picture, graphics->hdc, x, y, width, height, - 0, 0, srcw, srch, NULL); + return GdipDrawImagePointsRect(graphics, image, points, 3, 0, 0, width, height, + UnitPixel, NULL, NULL, NULL); +} - return Ok; +GpStatus WINGDIPAPI GdipDrawImageI(GpGraphics *graphics, GpImage *image, INT x, + INT y) +{ + TRACE("(%p, %p, %d, %d)\n", graphics, image, x, y); + + return GdipDrawImage(graphics, image, (REAL)x, (REAL)y); } GpStatus WINGDIPAPI GdipDrawImagePointRect(GpGraphics *graphics, GpImage *image, @@ -1651,37 +1838,127 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image if(!graphics || !image || !points || count != 3) return InvalidParameter; - if(srcUnit == UnitInch) - dx = dy = (REAL) INCH_HIMETRIC; - else if(srcUnit == UnitPixel){ - dx = ((REAL) INCH_HIMETRIC) / - ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSX)); - dy = ((REAL) INCH_HIMETRIC) / - ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSY)); - } - else - return NotImplemented; - memcpy(ptf, points, 3 * sizeof(GpPointF)); transform_and_round_points(graphics, pti, ptf, 3); - /* IPicture renders bitmaps with the y-axis reversed - * FIXME: flipping for unknown image type might not be correct. */ - if(image->type != ImageTypeMetafile){ - INT temp; - temp = pti[0].y; - pti[0].y = pti[2].y; - pti[2].y = temp; - } - - if(IPicture_Render(image->picture, graphics->hdc, - pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y, - srcx * dx, srcy * dy, - srcwidth * dx, srcheight * dy, - NULL) != S_OK){ - if(callback) - callback(callbackData); - return GenericError; + if (image->picture) + { + if(srcUnit == UnitInch) + dx = dy = (REAL) INCH_HIMETRIC; + else if(srcUnit == UnitPixel){ + dx = ((REAL) INCH_HIMETRIC) / + ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSX)); + dy = ((REAL) INCH_HIMETRIC) / + ((REAL) GetDeviceCaps(graphics->hdc, LOGPIXELSY)); + } + else + return NotImplemented; + + /* IPicture renders bitmaps with the y-axis reversed + * FIXME: flipping for unknown image type might not be correct. */ + if(image->type != ImageTypeMetafile){ + INT temp; + temp = pti[0].y; + pti[0].y = pti[2].y; + pti[2].y = temp; + } + + if(IPicture_Render(image->picture, graphics->hdc, + pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y, + srcx * dx, srcy * dy, + srcwidth * dx, srcheight * dy, + NULL) != S_OK){ + if(callback) + callback(callbackData); + return GenericError; + } + } + else if (image->type == ImageTypeBitmap && ((GpBitmap*)image)->hbitmap) + { + HDC hdc; + GpBitmap* bitmap = (GpBitmap*)image; + int temp_hdc=0, temp_bitmap=0; + HBITMAP hbitmap, old_hbm=NULL; + + if (srcUnit == UnitInch) + dx = dy = 96.0; /* FIXME: use the image resolution */ + else if (srcUnit == UnitPixel) + dx = dy = 1.0; + else + return NotImplemented; + + if (bitmap->format == PixelFormat32bppARGB) + { + BITMAPINFOHEADER bih; + BYTE *temp_bits; + + /* we need a bitmap with premultiplied alpha */ + hdc = CreateCompatibleDC(0); + temp_hdc = 1; + temp_bitmap = 1; + + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = bitmap->width; + bih.biHeight = -bitmap->height; + bih.biPlanes = 1; + bih.biBitCount = 32; + bih.biCompression = BI_RGB; + bih.biSizeImage = 0; + bih.biXPelsPerMeter = 0; + bih.biYPelsPerMeter = 0; + bih.biClrUsed = 0; + bih.biClrImportant = 0; + + hbitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_RGB_COLORS, + (void**)&temp_bits, NULL, 0); + + convert_32bppARGB_to_32bppPARGB(bitmap->width, bitmap->height, + temp_bits, bitmap->width*4, bitmap->bits, bitmap->stride); + } + else + { + hbitmap = bitmap->hbitmap; + hdc = bitmap->hdc; + temp_hdc = (hdc == 0); + } + + if (temp_hdc) + { + if (!hdc) hdc = CreateCompatibleDC(0); + old_hbm = SelectObject(hdc, hbitmap); + } + + if (bitmap->format == PixelFormat32bppARGB || bitmap->format == PixelFormat32bppPARGB) + { + BLENDFUNCTION bf; + + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + + GdiAlphaBlend(graphics->hdc, pti[0].x, pti[0].y, pti[1].x-pti[0].x, pti[2].y-pti[0].y, + hdc, srcx*dx, srcy*dy, srcwidth*dx, srcheight*dy, bf); + } + else + { + StretchBlt(graphics->hdc, pti[0].x, pti[0].y, pti[1].x-pti[0].x, pti[2].y-pti[0].y, + hdc, srcx*dx, srcy*dy, srcwidth*dx, srcheight*dy, SRCCOPY); + } + + if (temp_hdc) + { + SelectObject(hdc, old_hbm); + DeleteDC(hdc); + } + + if (temp_bitmap) + DeleteObject(hbitmap); + } + else + { + ERR("GpImage with no IPicture or HBITMAP?!\n"); + return NotImplemented; } return Ok; @@ -2090,8 +2367,10 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string WCHAR* stringdup; REAL angle, ang_cos, ang_sin, rel_width, rel_height; INT sum = 0, height = 0, offsety = 0, fit, fitcpy, save_state, i, j, lret, nwidth, - nheight; + nheight, lineend; SIZE size; + POINT drawbase; + UINT drawflags; RECT drawcoord; TRACE("(%p, %s, %i, %p, %s, %p, %p)\n", graphics, debugstr_wn(string, length), @@ -2183,10 +2462,10 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string pt[1].X = 1.0; pt[1].Y = 0.0; GdipTransformMatrixPoints(graphics->worldtrans, pt, 2); - angle = gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X)); + angle = -gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X)); ang_cos = cos(angle); ang_sin = sin(angle); - lfw.lfEscapement = lfw.lfOrientation = -roundr((angle / M_PI) * 1800.0); + lfw.lfEscapement = lfw.lfOrientation = roundr((angle / M_PI) * 1800.0); gdifont = CreateFontIndirectW(&lfw); DeleteObject(SelectObject(graphics->hdc, CreateFontIndirectW(&lfw))); @@ -2201,17 +2480,35 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string length = j; + if (!format || format->align == StringAlignmentNear) + { + drawbase.x = corners[0].x; + drawbase.y = corners[0].y; + drawflags = DT_NOCLIP | DT_EXPANDTABS; + } + else if (format->align == StringAlignmentCenter) + { + drawbase.x = (corners[0].x + corners[1].x)/2; + drawbase.y = (corners[0].y + corners[1].y)/2; + drawflags = DT_NOCLIP | DT_EXPANDTABS | DT_CENTER; + } + else /* (format->align == StringAlignmentFar) */ + { + drawbase.x = corners[1].x; + drawbase.y = corners[1].y; + drawflags = DT_NOCLIP | DT_EXPANDTABS | DT_RIGHT; + } + while(sum < length){ - drawcoord.left = corners[0].x + roundr(ang_sin * (REAL) height); - drawcoord.top = corners[0].y + roundr(ang_cos * (REAL) height); + drawcoord.left = drawcoord.right = drawbase.x + roundr(ang_sin * (REAL) height); + drawcoord.top = drawcoord.bottom = drawbase.y + roundr(ang_cos * (REAL) height); GetTextExtentExPointW(graphics->hdc, stringdup + sum, length - sum, nwidth, &fit, NULL, &size); fitcpy = fit; if(fit == 0){ - DrawTextW(graphics->hdc, stringdup + sum, 1, &drawcoord, DT_NOCLIP | - DT_EXPANDTABS); + DrawTextW(graphics->hdc, stringdup + sum, 1, &drawcoord, drawflags); break; } @@ -2221,7 +2518,7 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string /* Line break code (may look strange, but it imitates windows). */ if(lret < fit) - fit = lret; /* this is not an off-by-one error */ + lineend = fit = lret; /* this is not an off-by-one error */ else if(fit < (length - sum)){ if(*(stringdup + sum + fit) == ' ') while(*(stringdup + sum + fit) == ' ') @@ -2238,9 +2535,15 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string break; } } + lineend = fit; + while(*(stringdup + sum + lineend - 1) == ' ' || + *(stringdup + sum + lineend - 1) == '\t') + lineend--; } - DrawTextW(graphics->hdc, stringdup + sum, min(length - sum, fit), - &drawcoord, DT_NOCLIP | DT_EXPANDTABS); + else + lineend = fit; + DrawTextW(graphics->hdc, stringdup + sum, min(length - sum, lineend), + &drawcoord, drawflags); sum += fit + (lret < fitcpy ? 1 : 0); height += size.cy; @@ -2349,12 +2652,14 @@ GpStatus WINGDIPAPI GdipFillEllipse(GpGraphics *graphics, GpBrush *brush, REAL x save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); - SelectObject(graphics->hdc, brush->gdibrush); - SelectObject(graphics->hdc, GetStockObject(NULL_PEN)); transform_and_round_points(graphics, pti, ptf, 2); + BeginPath(graphics->hdc); Ellipse(graphics->hdc, pti[0].x, pti[0].y, pti[1].x, pti[1].y); + EndPath(graphics->hdc); + + brush_fill_path(graphics, brush); RestoreDC(graphics->hdc, save_state); @@ -2421,10 +2726,12 @@ GpStatus WINGDIPAPI GdipFillPie(GpGraphics *graphics, GpBrush *brush, REAL x, save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); - SelectObject(graphics->hdc, brush->gdibrush); - SelectObject(graphics->hdc, GetStockObject(NULL_PEN)); + BeginPath(graphics->hdc); draw_pie(graphics, x, y, width, height, startAngle, sweepAngle); + EndPath(graphics->hdc); + + brush_fill_path(graphics, brush); RestoreDC(graphics->hdc, save_state); @@ -2467,13 +2774,16 @@ GpStatus WINGDIPAPI GdipFillPolygon(GpGraphics *graphics, GpBrush *brush, save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); - SelectObject(graphics->hdc, brush->gdibrush); - SelectObject(graphics->hdc, GetStockObject(NULL_PEN)); SetPolyFillMode(graphics->hdc, (fillMode == FillModeAlternate ? ALTERNATE : WINDING)); transform_and_round_points(graphics, pti, ptf, count); + + BeginPath(graphics->hdc); Polygon(graphics->hdc, pti, count); + EndPath(graphics->hdc); + + brush_fill_path(graphics, brush); RestoreDC(graphics->hdc, save_state); @@ -2514,13 +2824,16 @@ GpStatus WINGDIPAPI GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush, save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); - SelectObject(graphics->hdc, brush->gdibrush); - SelectObject(graphics->hdc, GetStockObject(NULL_PEN)); SetPolyFillMode(graphics->hdc, (fillMode == FillModeAlternate ? ALTERNATE : WINDING)); transform_and_round_points(graphics, pti, ptf, count); + + BeginPath(graphics->hdc); Polygon(graphics->hdc, pti, count); + EndPath(graphics->hdc); + + brush_fill_path(graphics, brush); RestoreDC(graphics->hdc, save_state); @@ -2613,12 +2926,14 @@ GpStatus WINGDIPAPI GdipFillRectangleI(GpGraphics *graphics, GpBrush *brush, save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); - SelectObject(graphics->hdc, brush->gdibrush); - SelectObject(graphics->hdc, GetStockObject(NULL_PEN)); transform_and_round_points(graphics, pti, ptf, 4); + BeginPath(graphics->hdc); Polygon(graphics->hdc, pti, 4); + EndPath(graphics->hdc); + + brush_fill_path(graphics, brush); RestoreDC(graphics->hdc, save_state); @@ -2682,6 +2997,7 @@ GpStatus WINGDIPAPI GdipFillRegion(GpGraphics* graphics, GpBrush* brush, INT save_state; GpStatus status; HRGN hrgn; + RECT rc; TRACE("(%p, %p, %p)\n", graphics, brush, region); @@ -2697,9 +3013,17 @@ GpStatus WINGDIPAPI GdipFillRegion(GpGraphics* graphics, GpBrush* brush, save_state = SaveDC(graphics->hdc); EndPath(graphics->hdc); - SelectObject(graphics->hdc, GetStockObject(NULL_PEN)); - FillRgn(graphics->hdc, hrgn, brush->gdibrush); + ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); + + if (GetClipBox(graphics->hdc, &rc) != NULLREGION) + { + BeginPath(graphics->hdc); + Rectangle(graphics->hdc, rc.left, rc.top, rc.right, rc.bottom); + EndPath(graphics->hdc); + + brush_fill_path(graphics, brush); + } RestoreDC(graphics->hdc, save_state); @@ -2912,6 +3236,56 @@ GpStatus WINGDIPAPI GdipGetTextRenderingHint(GpGraphics *graphics, return Ok; } +GpStatus WINGDIPAPI GdipGetVisibleClipBounds(GpGraphics *graphics, GpRectF *rect) +{ + GpRegion *clip_rgn; + GpStatus stat; + + TRACE("(%p, %p)\n", graphics, rect); + + if(!graphics || !rect) + return InvalidParameter; + + if(graphics->busy) + return ObjectBusy; + + /* intersect window and graphics clipping regions */ + if((stat = GdipCreateRegion(&clip_rgn)) != Ok) + return stat; + + if((stat = get_visible_clip_region(graphics, clip_rgn)) != Ok) + goto cleanup; + + /* get bounds of the region */ + stat = GdipGetRegionBounds(clip_rgn, graphics, rect); + +cleanup: + GdipDeleteRegion(clip_rgn); + + return stat; +} + +GpStatus WINGDIPAPI GdipGetVisibleClipBoundsI(GpGraphics *graphics, GpRect *rect) +{ + GpRectF rectf; + GpStatus stat; + + TRACE("(%p, %p)\n", graphics, rect); + + if(!graphics || !rect) + return InvalidParameter; + + if((stat = GdipGetVisibleClipBounds(graphics, &rectf)) == Ok) + { + rect->X = roundr(rectf.X); + rect->Y = roundr(rectf.Y); + rect->Width = roundr(rectf.Width); + rect->Height = roundr(rectf.Height); + } + + return stat; +} + GpStatus WINGDIPAPI GdipGetWorldTransform(GpGraphics *graphics, GpMatrix *matrix) { TRACE("(%p, %p)\n", graphics, matrix); @@ -2930,7 +3304,7 @@ GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics *graphics, ARGB color) { GpSolidFill *brush; GpStatus stat; - RECT rect; + GpRectF wnd_rect; TRACE("(%p, %x)\n", graphics, color); @@ -2943,18 +3317,13 @@ GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics *graphics, ARGB color) if((stat = GdipCreateSolidFill(color, &brush)) != Ok) return stat; - if(graphics->hwnd){ - if(!GetWindowRect(graphics->hwnd, &rect)){ - GdipDeleteBrush((GpBrush*)brush); - return GenericError; - } - - GdipFillRectangle(graphics, (GpBrush*)brush, 0.0, 0.0, (REAL)(rect.right - rect.left), - (REAL)(rect.bottom - rect.top)); + if((stat = get_graphics_bounds(graphics, &wnd_rect)) != Ok){ + GdipDeleteBrush((GpBrush*)brush); + return stat; } - else - GdipFillRectangle(graphics, (GpBrush*)brush, 0.0, 0.0, (REAL)GetDeviceCaps(graphics->hdc, HORZRES), - (REAL)GetDeviceCaps(graphics->hdc, VERTRES)); + + GdipFillRectangle(graphics, (GpBrush*)brush, wnd_rect.X, wnd_rect.Y, + wnd_rect.Width, wnd_rect.Height); GdipDeleteBrush((GpBrush*)brush); @@ -2973,7 +3342,11 @@ GpStatus WINGDIPAPI GdipIsClipEmpty(GpGraphics *graphics, BOOL *res) GpStatus WINGDIPAPI GdipIsVisiblePoint(GpGraphics *graphics, REAL x, REAL y, BOOL *result) { - FIXME("(%p, %.2f, %.2f, %p) stub\n", graphics, x, y, result); + GpStatus stat; + GpRegion* rgn; + GpPointF pt; + + TRACE("(%p, %.2f, %.2f, %p)\n", graphics, x, y, result); if(!graphics || !result) return InvalidParameter; @@ -2981,12 +3354,37 @@ GpStatus WINGDIPAPI GdipIsVisiblePoint(GpGraphics *graphics, REAL x, REAL y, BOO if(graphics->busy) return ObjectBusy; - return NotImplemented; + pt.X = x; + pt.Y = y; + if((stat = GdipTransformPoints(graphics, CoordinateSpaceDevice, + CoordinateSpaceWorld, &pt, 1)) != Ok) + return stat; + + if((stat = GdipCreateRegion(&rgn)) != Ok) + return stat; + + if((stat = get_visible_clip_region(graphics, rgn)) != Ok) + goto cleanup; + + stat = GdipIsVisibleRegionPoint(rgn, pt.X, pt.Y, graphics, result); + +cleanup: + GdipDeleteRegion(rgn); + return stat; } GpStatus WINGDIPAPI GdipIsVisiblePointI(GpGraphics *graphics, INT x, INT y, BOOL *result) { - FIXME("(%p, %d, %d, %p) stub\n", graphics, x, y, result); + return GdipIsVisiblePoint(graphics, (REAL)x, (REAL)y, result); +} + +GpStatus WINGDIPAPI GdipIsVisibleRect(GpGraphics *graphics, REAL x, REAL y, REAL width, REAL height, BOOL *result) +{ + GpStatus stat; + GpRegion* rgn; + GpPointF pts[2]; + + TRACE("(%p %.2f %.2f %.2f %.2f %p)\n", graphics, x, y, width, height, result); if(!graphics || !result) return InvalidParameter; @@ -2994,7 +3392,34 @@ GpStatus WINGDIPAPI GdipIsVisiblePointI(GpGraphics *graphics, INT x, INT y, BOOL if(graphics->busy) return ObjectBusy; - return NotImplemented; + pts[0].X = x; + pts[0].Y = y; + pts[1].X = x + width; + pts[1].Y = y + height; + + if((stat = GdipTransformPoints(graphics, CoordinateSpaceDevice, + CoordinateSpaceWorld, pts, 2)) != Ok) + return stat; + + pts[1].X -= pts[0].X; + pts[1].Y -= pts[0].Y; + + if((stat = GdipCreateRegion(&rgn)) != Ok) + return stat; + + if((stat = get_visible_clip_region(graphics, rgn)) != Ok) + goto cleanup; + + stat = GdipIsVisibleRegionRect(rgn, pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, graphics, result); + +cleanup: + GdipDeleteRegion(rgn); + return stat; +} + +GpStatus WINGDIPAPI GdipIsVisibleRectI(GpGraphics *graphics, INT x, INT y, INT width, INT height, BOOL *result) +{ + return GdipIsVisibleRect(graphics, (REAL)x, (REAL)y, (REAL)width, (REAL)height, result); } GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics, @@ -3023,7 +3448,7 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, HFONT oldfont; WCHAR* stringdup; INT sum = 0, height = 0, fit, fitcpy, max_width = 0, i, j, lret, nwidth, - nheight; + nheight, lineend; SIZE size; TRACE("(%p, %s, %i, %p, %s, %p, %p, %p, %p)\n", graphics, @@ -3076,7 +3501,7 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, /* Line break code (may look strange, but it imitates windows). */ if(lret < fit) - fit = lret; /* this is not an off-by-one error */ + lineend = fit = lret; /* this is not an off-by-one error */ else if(fit < (length - sum)){ if(*(stringdup + sum + fit) == ' ') while(*(stringdup + sum + fit) == ' ') @@ -3093,9 +3518,15 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, break; } } + lineend = fit; + while(*(stringdup + sum + lineend - 1) == ' ' || + *(stringdup + sum + lineend - 1) == '\t') + lineend--; } + else + lineend = fit; - GetTextExtentExPointW(graphics->hdc, stringdup + sum, fit, + GetTextExtentExPointW(graphics->hdc, stringdup + sum, lineend, nwidth, &j, NULL, &size); sum += fit + (lret < fitcpy ? 1 : 0); @@ -3159,15 +3590,7 @@ GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics *graphics) GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics *graphics, GraphicsState state) { - static int calls; - - if(!graphics) - return InvalidParameter; - - if(!(calls++)) - FIXME("graphics state not implemented\n"); - - return Ok; + return GdipEndContainer(graphics, state); } GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics *graphics, REAL angle, @@ -3186,26 +3609,27 @@ GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics *graphics, REAL angle, GpStatus WINGDIPAPI GdipSaveGraphics(GpGraphics *graphics, GraphicsState *state) { - static int calls; - - if(!graphics || !state) - return InvalidParameter; - - if(!(calls++)) - FIXME("graphics state not implemented\n"); - - *state = 0xdeadbeef; - return Ok; + return GdipBeginContainer2(graphics, state); } -GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics, GraphicsContainer *state) +GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics, + GraphicsContainer *state) { - FIXME("(%p, %p)\n", graphics, state); + GraphicsContainerItem *container; + GpStatus sts; + + TRACE("(%p, %p)\n", graphics, state); if(!graphics || !state) return InvalidParameter; - *state = 0xdeadbeef; + sts = init_container(&container, graphics); + if(sts != Ok) + return sts; + + list_add_head(&graphics->containers, &container->entry); + *state = graphics->contid = container->contid; + return Ok; } @@ -3227,13 +3651,40 @@ GpStatus WINGDIPAPI GdipComment(GpGraphics *graphics, UINT sizeData, GDIPCONST B return NotImplemented; } -GpStatus WINGDIPAPI GdipEndContainer(GpGraphics *graphics, GraphicsState state) +GpStatus WINGDIPAPI GdipEndContainer(GpGraphics *graphics, GraphicsContainer state) { - FIXME("(%p, 0x%x)\n", graphics, state); + GpStatus sts; + GraphicsContainerItem *container, *container2; - if(!graphics || !state) + TRACE("(%p, %x)\n", graphics, state); + + if(!graphics) return InvalidParameter; + LIST_FOR_EACH_ENTRY(container, &graphics->containers, GraphicsContainerItem, entry){ + if(container->contid == state) + break; + } + + /* did not find a matching container */ + if(&container->entry == &graphics->containers) + return Ok; + + sts = restore_container(graphics, container); + if(sts != Ok) + return sts; + + /* remove all of the containers on top of the found container */ + LIST_FOR_EACH_ENTRY_SAFE(container, container2, &graphics->containers, GraphicsContainerItem, entry){ + if(container->contid == state) + break; + list_remove(&container->entry); + delete_container(container); + } + + list_remove(&container->entry); + delete_container(container); + return Ok; } @@ -3839,3 +4290,37 @@ GpStatus WINGDIPAPI GdipTranslateClipI(GpGraphics *graphics, INT dx, INT dy) return GdipTranslateRegion(graphics->clip, (REAL)dx, (REAL)dy); } + + +/***************************************************************************** + * GdipMeasureDriverString [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, + GDIPCONST GpFont *font, GDIPCONST PointF *positions, + INT flags, GDIPCONST GpMatrix *matrix, RectF *boundingBox) +{ + FIXME("(%p %p %d %p %p %d %p %p): stub\n", graphics, text, length, font, positions, flags, matrix, boundingBox); + return NotImplemented; +} + +/***************************************************************************** + * GdipDrawDriverString [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, + GDIPCONST GpFont *font, GDIPCONST GpBrush *brush, + GDIPCONST PointF *positions, INT flags, + GDIPCONST GpMatrix *matrix ) +{ + FIXME("(%p %p %d %p %p %p %d %p): stub\n", graphics, text, length, font, brush, positions, flags, matrix); + return NotImplemented; +} + +/***************************************************************************** + * GdipRecordMetafileI [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipRecordMetafileI(HDC hdc, EmfType type, GDIPCONST GpRect *frameRect, + MetafileFrameUnit frameUnit, GDIPCONST WCHAR *desc, GpMetafile **metafile) +{ + FIXME("(%p %d %p %d %p %p): stub\n", hdc, type, frameRect, frameUnit, desc, metafile); + return NotImplemented; +} diff --git a/reactos/dll/win32/gdiplus/image.c b/reactos/dll/win32/gdiplus/image.c index 6df104ec54f..b1e831fdf99 100644 --- a/reactos/dll/win32/gdiplus/image.c +++ b/reactos/dll/win32/gdiplus/image.c @@ -31,6 +31,7 @@ #include "ole2.h" #include "initguid.h" +#include "wincodec.h" #include "gdiplus.h" #include "gdiplus_private.h" #include "wine/debug.h" @@ -167,8 +168,25 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect, if(bitmap->lockmode) return WrongState; - IPicture_get_Handle(bitmap->image.picture, (OLE_HANDLE*)&hbm); - IPicture_get_CurDC(bitmap->image.picture, &hdc); + if (bitmap->bits && bitmap->format == format) + { + /* no conversion is necessary; just use the bits directly */ + lockeddata->Width = act_rect.Width; + lockeddata->Height = act_rect.Height; + lockeddata->PixelFormat = format; + lockeddata->Reserved = flags; + lockeddata->Stride = bitmap->stride; + lockeddata->Scan0 = bitmap->bits + (bitspp / 8) * act_rect.X + + bitmap->stride * act_rect.Y; + + bitmap->lockmode = flags; + bitmap->numlocks++; + + return Ok; + } + + hbm = bitmap->hbitmap; + hdc = bitmap->hdc; bm_is_selected = (hdc != 0); pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); @@ -263,8 +281,15 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap, return Ok; } - IPicture_get_Handle(bitmap->image.picture, (OLE_HANDLE*)&hbm); - IPicture_get_CurDC(bitmap->image.picture, &hdc); + if (!bitmap->bitmapbits) + { + /* we passed a direct reference; no need to do anything */ + bitmap->lockmode = 0; + return Ok; + } + + hbm = bitmap->hbitmap; + hdc = bitmap->hdc; bm_is_selected = (hdc != 0); pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); @@ -312,10 +337,6 @@ GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height, GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage) { - IStream* stream; - HRESULT hr; - INT size; - LARGE_INTEGER move; GpStatus stat = GenericError; TRACE("%p, %p\n", image, cloneImage); @@ -323,29 +344,82 @@ GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage) if (!image || !cloneImage) return InvalidParameter; - hr = CreateStreamOnHGlobal(0, TRUE, &stream); - if (FAILED(hr)) - return GenericError; - - hr = IPicture_SaveAsFile(image->picture, stream, FALSE, &size); - if(FAILED(hr)) + if (image->picture) { - WARN("Failed to save image on stream\n"); - goto out; - } + IStream* stream; + HRESULT hr; + INT size; + LARGE_INTEGER move; - /* Set seek pointer back to the beginning of the picture */ - move.QuadPart = 0; - hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL); - if (FAILED(hr)) - goto out; + hr = CreateStreamOnHGlobal(0, TRUE, &stream); + if (FAILED(hr)) + return GenericError; - stat = GdipLoadImageFromStream(stream, cloneImage); - if (stat != Ok) WARN("Failed to load image from stream\n"); + hr = IPicture_SaveAsFile(image->picture, stream, FALSE, &size); + if(FAILED(hr)) + { + WARN("Failed to save image on stream\n"); + goto out; + } -out: - IStream_Release(stream); - return stat; + /* Set seek pointer back to the beginning of the picture */ + move.QuadPart = 0; + hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) + goto out; + + stat = GdipLoadImageFromStream(stream, cloneImage); + if (stat != Ok) WARN("Failed to load image from stream\n"); + + out: + IStream_Release(stream); + return stat; + } + else if (image->type == ImageTypeBitmap) + { + GpBitmap *bitmap = (GpBitmap*)image; + BitmapData lockeddata_src, lockeddata_dst; + int i; + UINT row_size; + + stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format, + &lockeddata_src); + if (stat != Ok) return stat; + + stat = GdipCreateBitmapFromScan0(lockeddata_src.Width, lockeddata_src.Height, + 0, lockeddata_src.PixelFormat, NULL, (GpBitmap**)cloneImage); + if (stat == Ok) + { + stat = GdipBitmapLockBits((GpBitmap*)*cloneImage, NULL, ImageLockModeWrite, + lockeddata_src.PixelFormat, &lockeddata_dst); + + if (stat == Ok) + { + /* copy the image data */ + row_size = (lockeddata_src.Width * PIXELFORMATBPP(lockeddata_src.PixelFormat) +7)/8; + for (i=0; iimage.picture)) != S_OK){ - DestroyIcon(icon_copy); - GdipFree(*bitmap); - return GenericError; + rect.X = 0; + rect.Y = 0; + rect.Width = width; + rect.Height = height; + + stat = GdipBitmapLockBits(*bitmap, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &lockeddata); + if (stat != Ok) { + DeleteObject(iinfo.hbmColor); + DeleteObject(iinfo.hbmMask); + HeapFree(GetProcessHeap(), 0, bits); + GdipDisposeImage((GpImage*)*bitmap); + return stat; } - (*bitmap)->format = PixelFormat32bppARGB; - (*bitmap)->image.type = ImageTypeBitmap; - (*bitmap)->image.flags = ImageFlagsNone; - (*bitmap)->width = ipicture_pixel_width((*bitmap)->image.picture); - (*bitmap)->height = ipicture_pixel_height((*bitmap)->image.picture); + bih.biSize = sizeof(bih); + bih.biWidth = width; + bih.biHeight = -height; + bih.biPlanes = 1; + bih.biBitCount = 32; + bih.biCompression = BI_RGB; + bih.biSizeImage = 0; + bih.biXPelsPerMeter = 0; + bih.biYPelsPerMeter = 0; + bih.biClrUsed = 0; + bih.biClrImportant = 0; + + screendc = GetDC(0); + if (iinfo.hbmColor) + { + GetDIBits(screendc, iinfo.hbmColor, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS); + + if (bm.bmBitsPixel == 32) + { + has_alpha = FALSE; + + /* If any pixel has a non-zero alpha, ignore hbmMask */ + src = (DWORD*)bits; + for (x=0; xbfType = (((WORD)'M') << 8) + (WORD)'B'; - bmfh->bfSize = size; - bmfh->bfOffBits = size - datalen; + hbitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (void**)&bits, + NULL, 0); - bmih->biSize = sizeof(BITMAPINFOHEADER); - bmih->biWidth = width; - /* FIXME: use the rest of the data from format */ - bmih->biBitCount = PIXELFORMATBPP(format); - bmih->biCompression = BI_RGB; - bmih->biSizeImage = datalen; + DeleteDC(hdc); - if (scan0) - { - if (stride > 0) - { - bmih->biHeight = -height; - memcpy(bmih + 1, scan0, datalen); - } - else - { - bmih->biHeight = height; - memcpy(bmih + 1, scan0 + stride * (height - 1), datalen); - } - } - else - { - bmih->biHeight = height; - memset(bmih + 1, 0, datalen); - } + if (!hbitmap) return GenericError; - if(CreateStreamOnHGlobal(buff, TRUE, &stream) != S_OK){ - ERR("could not make stream\n"); - GdipFree(*bitmap); - GdipFree(buff); - *bitmap = NULL; - return GenericError; - } + /* copy bits to the dib if necessary */ + /* FIXME: should reference the bits instead of copying them */ + if (scan0) + for (i=0; iimage.picture)) != S_OK){ - TRACE("Could not load picture\n"); - IStream_Release(stream); - GdipFree(*bitmap); - GdipFree(buff); - *bitmap = NULL; - return GenericError; + *bitmap = GdipAlloc(sizeof(GpBitmap)); + if(!*bitmap) + { + DeleteObject(hbitmap); + return OutOfMemory; } (*bitmap)->image.type = ImageTypeBitmap; @@ -629,6 +862,11 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, (*bitmap)->width = width; (*bitmap)->height = height; (*bitmap)->format = format; + (*bitmap)->image.picture = NULL; + (*bitmap)->hbitmap = hbitmap; + (*bitmap)->hdc = NULL; + (*bitmap)->bits = bits; + (*bitmap)->stride = dib_stride; return Ok; } @@ -646,8 +884,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromStream(IStream* stream, return stat; if((*bitmap)->image.type != ImageTypeBitmap){ - IPicture_Release((*bitmap)->image.picture); - GdipFree(bitmap); + GdipDisposeImage(&(*bitmap)->image); + *bitmap = NULL; return GenericError; /* FIXME: what error to return? */ } @@ -726,18 +964,18 @@ GpStatus WINGDIPAPI GdipEmfToWmfBits(HENHMETAFILE hemf, UINT cbData16, GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) { - HDC hdc; - TRACE("%p\n", image); if(!image) return InvalidParameter; - IPicture_get_CurDC(image->picture, &hdc); - DeleteDC(hdc); - IPicture_Release(image->picture); + if (image->picture) + IPicture_Release(image->picture); if (image->type == ImageTypeBitmap) + { GdipFree(((GpBitmap*)image)->bitmapbits); + DeleteDC(((GpBitmap*)image)->hdc); + } GdipFree(image); return Ok; @@ -829,11 +1067,12 @@ GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage *image, return NotImplemented; } - IPicture_get_CurDC(image->picture, &hdc); + hdc = ((GpBitmap*)image)->hdc; if(!hdc){ hdc = CreateCompatibleDC(0); - IPicture_SelectPicture(image->picture, hdc, NULL, NULL); + SelectObject(hdc, ((GpBitmap*)image)->hbitmap); + ((GpBitmap*)image)->hdc = hdc; } return GdipCreateFromHDC(hdc, graphics); @@ -1143,10 +1382,148 @@ GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage * return GdipLoadImageFromFile(filename, image); } -GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream* stream, GpImage **image) +static const WICPixelFormatGUID *wic_pixel_formats[] = { + &GUID_WICPixelFormat16bppBGR555, + &GUID_WICPixelFormat24bppBGR, + &GUID_WICPixelFormat32bppBGR, + &GUID_WICPixelFormat32bppBGRA, + &GUID_WICPixelFormat32bppPBGRA, + NULL +}; + +static const PixelFormat wic_gdip_formats[] = { + PixelFormat16bppRGB555, + PixelFormat24bppRGB, + PixelFormat32bppRGB, + PixelFormat32bppARGB, + PixelFormat32bppPARGB, +}; + +static GpStatus decode_image_wic(IStream* stream, REFCLSID clsid, GpImage **image) +{ + GpStatus status=Ok; + GpBitmap *bitmap; + HRESULT hr; + IWICBitmapDecoder *decoder; + IWICBitmapFrameDecode *frame; + IWICBitmapSource *source=NULL; + WICPixelFormatGUID wic_format; + PixelFormat gdip_format=0; + int i; + UINT width, height; + BitmapData lockeddata; + WICRect wrc; + HRESULT initresult; + + initresult = CoInitialize(NULL); + + hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapDecoder, (void**)&decoder); + if (FAILED(hr)) goto end; + + hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad); + if (SUCCEEDED(hr)) + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); + + if (SUCCEEDED(hr)) /* got frame */ + { + hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &wic_format); + + if (SUCCEEDED(hr)) + { + for (i=0; wic_pixel_formats[i]; i++) + { + if (IsEqualGUID(&wic_format, wic_pixel_formats[i])) + { + source = (IWICBitmapSource*)frame; + IWICBitmapSource_AddRef(source); + gdip_format = wic_gdip_formats[i]; + break; + } + } + if (!source) + { + /* unknown format; fall back on 32bppARGB */ + hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, (IWICBitmapSource*)frame, &source); + gdip_format = PixelFormat32bppARGB; + } + } + + if (SUCCEEDED(hr)) /* got source */ + { + hr = IWICBitmapSource_GetSize(source, &width, &height); + + if (SUCCEEDED(hr)) + status = GdipCreateBitmapFromScan0(width, height, 0, gdip_format, + NULL, &bitmap); + + if (SUCCEEDED(hr) && status == Ok) /* created bitmap */ + { + status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeWrite, + gdip_format, &lockeddata); + if (status == Ok) /* locked bitmap */ + { + wrc.X = 0; + wrc.Width = width; + wrc.Height = 1; + for (i=0; itype = ImageTypeBitmap; - if(type == PICTYPE_BITMAP){ - BITMAPINFO *pbmi; - BITMAPCOREHEADER* bmch; - HBITMAP hbm; - HDC hdc; + (*((GpBitmap**) image))->width = ipicture_pixel_width(pic); + (*((GpBitmap**) image))->height = ipicture_pixel_height(pic); - pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); - if (!pbmi) - return OutOfMemory; - *image = GdipAlloc(sizeof(GpBitmap)); - if(!*image){ - GdipFree(pbmi); - return OutOfMemory; - } - (*image)->type = ImageTypeBitmap; + /* get the pixel format */ + IPicture_get_Handle(pic, (OLE_HANDLE*)&hbm); + IPicture_get_CurDC(pic, &hdc); - (*((GpBitmap**) image))->width = ipicture_pixel_width(pic); - (*((GpBitmap**) image))->height = ipicture_pixel_height(pic); + (*((GpBitmap**) image))->hbitmap = hbm; + (*((GpBitmap**) image))->hdc = hdc; + (*((GpBitmap**) image))->bits = NULL; - /* get the pixel format */ - IPicture_get_Handle(pic, (OLE_HANDLE*)&hbm); - IPicture_get_CurDC(pic, &hdc); + bmch = (BITMAPCOREHEADER*) (&pbmi->bmiHeader); + bmch->bcSize = sizeof(BITMAPCOREHEADER); - bmch = (BITMAPCOREHEADER*) (&pbmi->bmiHeader); - bmch->bcSize = sizeof(BITMAPCOREHEADER); + if(!hdc){ + HBITMAP old; + hdc = CreateCompatibleDC(0); + old = SelectObject(hdc, hbm); + GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS); + SelectObject(hdc, old); + DeleteDC(hdc); + } + else + GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS); - if(!hdc){ - HBITMAP old; - hdc = CreateCompatibleDC(0); - old = SelectObject(hdc, hbm); - GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS); - SelectObject(hdc, old); - DeleteDC(hdc); - } - else - GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS); + switch(bmch->bcBitCount) + { + case 1: + (*((GpBitmap**) image))->format = PixelFormat1bppIndexed; + break; + case 4: + (*((GpBitmap**) image))->format = PixelFormat4bppIndexed; + break; + case 8: + (*((GpBitmap**) image))->format = PixelFormat8bppIndexed; + break; + case 16: + (*((GpBitmap**) image))->format = PixelFormat16bppRGB565; + break; + case 24: + (*((GpBitmap**) image))->format = PixelFormat24bppRGB; + break; + case 32: + (*((GpBitmap**) image))->format = PixelFormat32bppRGB; + break; + case 48: + (*((GpBitmap**) image))->format = PixelFormat48bppRGB; + break; + default: + FIXME("Bit depth %d is not fully supported yet\n", bmch->bcBitCount); + (*((GpBitmap**) image))->format = (bmch->bcBitCount << 8) | PixelFormatGDI; + break; + } - switch(bmch->bcBitCount) - { - case 1: - (*((GpBitmap**) image))->format = PixelFormat1bppIndexed; - break; - case 4: - (*((GpBitmap**) image))->format = PixelFormat4bppIndexed; - break; - case 8: - (*((GpBitmap**) image))->format = PixelFormat8bppIndexed; - break; - case 16: - (*((GpBitmap**) image))->format = PixelFormat16bppRGB565; - break; - case 24: - (*((GpBitmap**) image))->format = PixelFormat24bppRGB; - break; - case 32: - (*((GpBitmap**) image))->format = PixelFormat32bppRGB; - break; - case 48: - (*((GpBitmap**) image))->format = PixelFormat48bppRGB; - break; - default: - FIXME("Bit depth %d is not fully supported yet\n", bmch->bcBitCount); - (*((GpBitmap**) image))->format = (bmch->bcBitCount << 8) | PixelFormatGDI; - break; - } + GdipFree(pbmi); - GdipFree(pbmi); - } - else if(type == PICTYPE_METAFILE || type == PICTYPE_ENHMETAFILE){ - /* FIXME: missing initialization code */ - *image = GdipAlloc(sizeof(GpMetafile)); - if(!*image) return OutOfMemory; - (*image)->type = ImageTypeMetafile; - } - else{ - *image = GdipAlloc(sizeof(GpImage)); - if(!*image) return OutOfMemory; - (*image)->type = ImageTypeUnknown; + (*image)->picture = pic; + (*image)->flags = ImageFlagsNone; + + return Ok; +} + +static GpStatus decode_image_olepicture_metafile(IStream* stream, REFCLSID clsid, GpImage **image) +{ + IPicture *pic; + + TRACE("%p %p\n", stream, image); + + if(!stream || !image) + return InvalidParameter; + + if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture, + (LPVOID*) &pic) != S_OK){ + TRACE("Could not load picture\n"); + return GenericError; } + /* FIXME: missing initialization code */ + *image = GdipAlloc(sizeof(GpMetafile)); + if(!*image) return OutOfMemory; + (*image)->type = ImageTypeMetafile; (*image)->picture = pic; (*image)->flags = ImageFlagsNone; return Ok; } +typedef GpStatus (*encode_image_func)(GpImage *image, IStream* stream, + GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params); + +typedef GpStatus (*decode_image_func)(IStream *stream, REFCLSID clsid, GpImage** image); + +typedef struct image_codec { + ImageCodecInfo info; + encode_image_func encode_func; + decode_image_func decode_func; +} image_codec; + +typedef enum { + BMP, + JPEG, + GIF, + EMF, + WMF, + PNG, + ICO, + NUM_CODECS +} ImageFormat; + +static const struct image_codec codecs[NUM_CODECS]; + +static GpStatus get_decoder_info(IStream* stream, const struct image_codec **result) +{ + BYTE signature[8]; + LARGE_INTEGER seek; + HRESULT hr; + UINT bytesread; + int i, j; + + /* seek to the start of the stream */ + seek.QuadPart = 0; + hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) return hresult_to_status(hr); + + /* read the first 8 bytes */ + /* FIXME: This assumes all codecs have one signature <= 8 bytes in length */ + hr = IStream_Read(stream, signature, 8, &bytesread); + if (FAILED(hr)) return hresult_to_status(hr); + if (hr == S_FALSE || bytesread == 0) return GenericError; + + for (i = 0; i < NUM_CODECS; i++) { + if ((codecs[i].info.Flags & ImageCodecFlagsDecoder) && + bytesread >= codecs[i].info.SigSize) + { + for (j=0; jdecode_func(stream, &codec->info.Clsid, image); +} + /* FIXME: no ICM */ GpStatus WINGDIPAPI GdipLoadImageFromStreamICM(IStream* stream, GpImage **image) { @@ -1290,9 +1761,6 @@ GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR* filenam if (!image || !filename|| !clsidEncoder) return InvalidParameter; - if (!(image->picture)) - return InvalidParameter; - stat = GdipCreateStreamOnFile(filename, GENERIC_WRITE, &stream); if (stat != Ok) return GenericError; @@ -1313,62 +1781,139 @@ GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR* filenam #define BITMAP_FORMAT_PNG 0x5089 #define BITMAP_FORMAT_APM 0xcdd7 -static GpStatus encode_image_BMP(LPVOID bitmap_bits, LPBITMAPINFO bitmap_info, - void **output, unsigned int *output_size) +static GpStatus encode_image_WIC(GpImage *image, IStream* stream, + GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) { - int num_palette_entries; - BITMAPFILEHEADER *bmp_file_hdr; - BITMAPINFO *bmp_info_hdr; + GpStatus stat; + GpBitmap *bitmap; + IWICBitmapEncoder *encoder; + IWICBitmapFrameEncode *frameencode; + IPropertyBag2 *encoderoptions; + HRESULT hr; + UINT width, height; + PixelFormat gdipformat=0; + WICPixelFormatGUID wicformat; + GpRect rc; + BitmapData lockeddata; + HRESULT initresult; + UINT i; + + if (image->type != ImageTypeBitmap) + return GenericError; - if (bitmap_info->bmiHeader.biClrUsed) { - num_palette_entries = bitmap_info->bmiHeader.biClrUsed; - if (num_palette_entries > 256) num_palette_entries = 256; - } else { - if (bitmap_info->bmiHeader.biBitCount <= 8) - num_palette_entries = 1 << bitmap_info->bmiHeader.biBitCount; - else - num_palette_entries = 0; + bitmap = (GpBitmap*)image; + + GdipGetImageWidth(image, &width); + GdipGetImageHeight(image, &height); + + rc.X = 0; + rc.Y = 0; + rc.Width = width; + rc.Height = height; + + initresult = CoInitialize(NULL); + + hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapEncoder, (void**)&encoder); + if (FAILED(hr)) + { + if (SUCCEEDED(initresult)) CoUninitialize(); + return hresult_to_status(hr); } - *output_size = - sizeof(BITMAPFILEHEADER) + - sizeof(BITMAPINFOHEADER) + - num_palette_entries * sizeof(RGBQUAD) + - bitmap_info->bmiHeader.biSizeImage; + hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache); - *output = GdipAlloc(*output_size); + if (SUCCEEDED(hr)) + { + hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &encoderoptions); + } - bmp_file_hdr = *output; - bmp_file_hdr->bfType = BITMAP_FORMAT_BMP; - bmp_file_hdr->bfSize = *output_size; - bmp_file_hdr->bfOffBits = - sizeof(BITMAPFILEHEADER) + - sizeof(BITMAPINFOHEADER) + - num_palette_entries * sizeof (RGBQUAD); + if (SUCCEEDED(hr)) /* created frame */ + { + hr = IWICBitmapFrameEncode_Initialize(frameencode, encoderoptions); - bmp_info_hdr = (BITMAPINFO*) ((unsigned char*)(*output) + sizeof(BITMAPFILEHEADER)); - memcpy(bmp_info_hdr, bitmap_info, sizeof(BITMAPINFOHEADER) + num_palette_entries * sizeof(RGBQUAD)); - memcpy((unsigned char *)(*output) + - sizeof(BITMAPFILEHEADER) + - sizeof(BITMAPINFOHEADER) + - num_palette_entries * sizeof(RGBQUAD), - bitmap_bits, bitmap_info->bmiHeader.biSizeImage); + if (SUCCEEDED(hr)) + hr = IWICBitmapFrameEncode_SetSize(frameencode, width, height); - return Ok; -} + if (SUCCEEDED(hr)) + /* FIXME: use the resolution from the image */ + hr = IWICBitmapFrameEncode_SetResolution(frameencode, 96.0, 96.0); -typedef GpStatus encode_image_func(LPVOID bitmap_bits, LPBITMAPINFO bitmap_info, - void **output, unsigned int *output_size); + if (SUCCEEDED(hr)) + { + for (i=0; wic_pixel_formats[i]; i++) + { + if (wic_gdip_formats[i] == bitmap->format) + break; + } + if (wic_pixel_formats[i]) + memcpy(&wicformat, wic_pixel_formats[i], sizeof(GUID)); + else + memcpy(&wicformat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID)); + + hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &wicformat); + + for (i=0; wic_pixel_formats[i]; i++) + { + if (IsEqualGUID(&wicformat, wic_pixel_formats[i])) + break; + } + if (wic_pixel_formats[i]) + gdipformat = wic_gdip_formats[i]; + else + { + ERR("cannot provide pixel format %s\n", debugstr_guid(&wicformat)); + hr = E_FAIL; + } + } -typedef enum { - BMP, - NUM_ENCODERS_SUPPORTED -} ImageFormat; + if (SUCCEEDED(hr)) + { + stat = GdipBitmapLockBits(bitmap, &rc, ImageLockModeRead, gdipformat, + &lockeddata); + + if (stat == Ok) + { + UINT row_size = (lockeddata.Width * PIXELFORMATBPP(gdipformat) + 7)/8; + BYTE *row; + + /* write one row at a time in case stride is negative */ + row = lockeddata.Scan0; + for (i=0; ipicture) - return GenericError; - - hr = IPicture_get_Type(image->picture, &type); - if (FAILED(hr) || type != PICTYPE_BITMAP) - return GenericError; - /* select correct encoder */ encode_image = NULL; - for (i = 0; i < NUM_ENCODERS_SUPPORTED; i++) { - if (IsEqualCLSID(clsid, &codecs[i].Clsid)) - encode_image = encode_image_funcs[i]; + for (i = 0; i < NUM_CODECS; i++) { + if ((codecs[i].info.Flags & ImageCodecFlagsEncoder) && + IsEqualCLSID(clsid, &codecs[i].info.Clsid)) + encode_image = codecs[i].encode_func; } if (encode_image == NULL) return UnknownImageFormat; - /* extract underlying hbitmap representation from the IPicture */ - hr = IPicture_get_Handle(image->picture, (OLE_HANDLE*)&hbmp); - if (FAILED(hr) || !hbmp) - return GenericError; - hr = IPicture_get_CurDC(image->picture, &hdc); - if (FAILED(hr)) - return GenericError; - bm_is_selected = (hdc != 0); - if (!bm_is_selected) { - hdc = CreateCompatibleDC(0); - old_hbmp = SelectObject(hdc, hbmp); - } - - /* get bits from HBITMAP */ - bmp_info.bmiHeader.biSize = sizeof(bmp_info.bmiHeader); - bmp_info.bmiHeader.biBitCount = 0; - GetDIBits(hdc, hbmp, 0, 0, NULL, &bmp_info, DIB_RGB_COLORS); - - bmp_bits = GdipAlloc(bmp_info.bmiHeader.biSizeImage); + stat = encode_image(image, stream, clsid, params); - if (bmp_bits) - GetDIBits(hdc, hbmp, 0, abs(bmp_info.bmiHeader.biHeight), bmp_bits, &bmp_info, DIB_RGB_COLORS); - - if (!bm_is_selected) { - SelectObject(hdc, old_hbmp); - DeleteDC(hdc); - } + return stat; +} - if (!bmp_bits) - return OutOfMemory; +/***************************************************************************** + * GdipGetImagePalette [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipGetImagePalette(GpImage *image, ColorPalette *palette, INT size) +{ + static int calls = 0; - stat = encode_image(bmp_bits, &bmp_info, &output, &output_size); - if (stat == Ok) - IStream_Write(stream, output, output_size, &dummy); + if(!image) + return InvalidParameter; - GdipFree(output); - GdipFree(bmp_bits); + if(!(calls++)) + FIXME("not implemented\n"); - return stat; + return NotImplemented; } /***************************************************************************** @@ -1487,7 +1991,49 @@ static const WCHAR bmp_format[] = {'B', 'M', 'P', 0}; /* BMP */ static const BYTE bmp_sig_pattern[] = { 0x42, 0x4D }; static const BYTE bmp_sig_mask[] = { 0xFF, 0xFF }; -static const ImageCodecInfo codecs[NUM_ENCODERS_SUPPORTED] = +static const WCHAR jpeg_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'J','P','E','G', 0}; +static const WCHAR jpeg_extension[] = {'*','.','J','P','G',';', '*','.','J','P','E','G',';', '*','.','J','P','E',';', '*','.','J','F','I','F',0}; +static const WCHAR jpeg_mimetype[] = {'i','m','a','g','e','/','j','p','e','g', 0}; +static const WCHAR jpeg_format[] = {'J','P','E','G',0}; +static const BYTE jpeg_sig_pattern[] = { 0xFF, 0xD8 }; +static const BYTE jpeg_sig_mask[] = { 0xFF, 0xFF }; + +static const WCHAR gif_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'G','I','F', 0}; +static const WCHAR gif_extension[] = {'*','.','G','I','F',0}; +static const WCHAR gif_mimetype[] = {'i','m','a','g','e','/','g','i','f', 0}; +static const WCHAR gif_format[] = {'G','I','F',0}; +static const BYTE gif_sig_pattern[4] = "GIF8"; +static const BYTE gif_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF }; + +static const WCHAR emf_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'E','M','F', 0}; +static const WCHAR emf_extension[] = {'*','.','E','M','F',0}; +static const WCHAR emf_mimetype[] = {'i','m','a','g','e','/','x','-','e','m','f', 0}; +static const WCHAR emf_format[] = {'E','M','F',0}; +static const BYTE emf_sig_pattern[] = { 0x01, 0x00, 0x00, 0x00 }; +static const BYTE emf_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF }; + +static const WCHAR wmf_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'W','M','F', 0}; +static const WCHAR wmf_extension[] = {'*','.','W','M','F',0}; +static const WCHAR wmf_mimetype[] = {'i','m','a','g','e','/','x','-','w','m','f', 0}; +static const WCHAR wmf_format[] = {'W','M','F',0}; +static const BYTE wmf_sig_pattern[] = { 0xd7, 0xcd }; +static const BYTE wmf_sig_mask[] = { 0xFF, 0xFF }; + +static const WCHAR png_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'P','N','G', 0}; +static const WCHAR png_extension[] = {'*','.','P','N','G',0}; +static const WCHAR png_mimetype[] = {'i','m','a','g','e','/','p','n','g', 0}; +static const WCHAR png_format[] = {'P','N','G',0}; +static const BYTE png_sig_pattern[] = { 137, 80, 78, 71, 13, 10, 26, 10, }; +static const BYTE png_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + +static const WCHAR ico_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'I','C','O', 0}; +static const WCHAR ico_extension[] = {'*','.','I','C','O',0}; +static const WCHAR ico_mimetype[] = {'i','m','a','g','e','/','x','-','i','c','o','n', 0}; +static const WCHAR ico_format[] = {'I','C','O',0}; +static const BYTE ico_sig_pattern[] = { 0x00, 0x00, 0x01, 0x00 }; +static const BYTE ico_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF }; + +static const struct image_codec codecs[NUM_CODECS] = { { { /* BMP */ /* Clsid */ { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, @@ -1504,20 +2050,145 @@ static const ImageCodecInfo codecs[NUM_ENCODERS_SUPPORTED] = /* SigPattern */ bmp_sig_pattern, /* SigMask */ bmp_sig_mask, }, - }; + encode_image_BMP, + decode_image_olepicture_bitmap + }, + { + { /* JPEG */ + /* Clsid */ { 0x557cf401, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, + /* FormatID */ { 0xb96b3caeU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, + /* CodecName */ jpeg_codecname, + /* DllName */ NULL, + /* FormatDescription */ jpeg_format, + /* FilenameExtension */ jpeg_extension, + /* MimeType */ jpeg_mimetype, + /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, + /* Version */ 1, + /* SigCount */ 1, + /* SigSize */ 2, + /* SigPattern */ jpeg_sig_pattern, + /* SigMask */ jpeg_sig_mask, + }, + NULL, + decode_image_jpeg + }, + { + { /* GIF */ + /* Clsid */ { 0x557cf402, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, + /* FormatID */ { 0xb96b3cb0U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, + /* CodecName */ gif_codecname, + /* DllName */ NULL, + /* FormatDescription */ gif_format, + /* FilenameExtension */ gif_extension, + /* MimeType */ gif_mimetype, + /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, + /* Version */ 1, + /* SigCount */ 1, + /* SigSize */ 4, + /* SigPattern */ gif_sig_pattern, + /* SigMask */ gif_sig_mask, + }, + NULL, + decode_image_gif + }, + { + { /* EMF */ + /* Clsid */ { 0x557cf403, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, + /* FormatID */ { 0xb96b3cacU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, + /* CodecName */ emf_codecname, + /* DllName */ NULL, + /* FormatDescription */ emf_format, + /* FilenameExtension */ emf_extension, + /* MimeType */ emf_mimetype, + /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportVector | ImageCodecFlagsBuiltin, + /* Version */ 1, + /* SigCount */ 1, + /* SigSize */ 4, + /* SigPattern */ emf_sig_pattern, + /* SigMask */ emf_sig_mask, + }, + NULL, + decode_image_olepicture_metafile + }, + { + { /* WMF */ + /* Clsid */ { 0x557cf404, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, + /* FormatID */ { 0xb96b3cadU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, + /* CodecName */ wmf_codecname, + /* DllName */ NULL, + /* FormatDescription */ wmf_format, + /* FilenameExtension */ wmf_extension, + /* MimeType */ wmf_mimetype, + /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportVector | ImageCodecFlagsBuiltin, + /* Version */ 1, + /* SigCount */ 1, + /* SigSize */ 2, + /* SigPattern */ wmf_sig_pattern, + /* SigMask */ wmf_sig_mask, + }, + NULL, + decode_image_olepicture_metafile + }, + { + { /* PNG */ + /* Clsid */ { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, + /* FormatID */ { 0xb96b3cafU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, + /* CodecName */ png_codecname, + /* DllName */ NULL, + /* FormatDescription */ png_format, + /* FilenameExtension */ png_extension, + /* MimeType */ png_mimetype, + /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, + /* Version */ 1, + /* SigCount */ 1, + /* SigSize */ 8, + /* SigPattern */ png_sig_pattern, + /* SigMask */ png_sig_mask, + }, + NULL, + decode_image_olepicture_bitmap + }, + { + { /* ICO */ + /* Clsid */ { 0x557cf407, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }, + /* FormatID */ { 0xb96b3cabU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} }, + /* CodecName */ ico_codecname, + /* DllName */ NULL, + /* FormatDescription */ ico_format, + /* FilenameExtension */ ico_extension, + /* MimeType */ ico_mimetype, + /* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin, + /* Version */ 1, + /* SigCount */ 1, + /* SigSize */ 4, + /* SigPattern */ ico_sig_pattern, + /* SigMask */ ico_sig_mask, + }, + NULL, + decode_image_icon + }, +}; /***************************************************************************** * GdipGetImageDecodersSize [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipGetImageDecodersSize(UINT *numDecoders, UINT *size) { - FIXME("%p %p stub!\n", numDecoders, size); + int decoder_count=0; + int i; + TRACE("%p %p\n", numDecoders, size); if (!numDecoders || !size) return InvalidParameter; - *numDecoders = 0; - *size = 0; + for (i=0; i= ColorAdjustTypeCount) return InvalidParameter; - if(!(calls++)) - FIXME("not implemented\n"); + imageattr->colorkeys[type].enabled = enableFlag; + imageattr->colorkeys[type].low = colorLow; + imageattr->colorkeys[type].high = colorHigh; - return NotImplemented; + return Ok; } GpStatus WINGDIPAPI GdipSetImageAttributesColorMatrix(GpImageAttributes *imageattr, diff --git a/reactos/dll/win32/gdiplus/region.c b/reactos/dll/win32/gdiplus/region.c index 8fe5e2694c4..197b68af4a8 100644 --- a/reactos/dll/win32/gdiplus/region.c +++ b/reactos/dll/win32/gdiplus/region.c @@ -579,51 +579,63 @@ GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRe */ GpStatus WINGDIPAPI GdipCreateRegionHrgn(HRGN hrgn, GpRegion **region) { - union { - RGNDATA data; - char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)]; - } rdata; DWORD size; - GpRectF rectf; - GpPath *path; + LPRGNDATA buf; + LPRECT rect; GpStatus stat; + GpPath* path; + GpRegion* local; + int i; TRACE("(%p, %p)\n", hrgn, region); if(!region || !(size = GetRegionData(hrgn, 0, NULL))) return InvalidParameter; - if(size > sizeof(RGNDATAHEADER) + sizeof(RECT)){ - FIXME("Only simple rect regions supported.\n"); - *region = NULL; - return NotImplemented; - } + buf = GdipAlloc(size); + if(!buf) + return OutOfMemory; - if(!GetRegionData(hrgn, sizeof(rdata), &rdata.data)) + if(!GetRegionData(hrgn, size, buf)){ + GdipFree(buf); return GenericError; - - /* return empty region */ - if(IsRectEmpty(&rdata.data.rdh.rcBound)){ - stat = GdipCreateRegion(region); - if(stat == Ok) - GdipSetEmpty(*region); - return stat; } - rectf.X = (REAL)rdata.data.rdh.rcBound.left; - rectf.Y = (REAL)rdata.data.rdh.rcBound.top; - rectf.Width = (REAL)rdata.data.rdh.rcBound.right - rectf.X; - rectf.Height = (REAL)rdata.data.rdh.rcBound.bottom - rectf.Y; + if(buf->rdh.nCount == 0){ + if((stat = GdipCreateRegion(&local)) != Ok){ + GdipFree(buf); + return stat; + } + if((stat = GdipSetEmpty(local)) != Ok){ + GdipFree(buf); + GdipDeleteRegion(local); + return stat; + } + *region = local; + GdipFree(buf); + return Ok; + } - stat = GdipCreatePath(FillModeAlternate, &path); - if(stat != Ok) + if((stat = GdipCreatePath(FillModeAlternate, &path)) != Ok){ + GdipFree(buf); return stat; + } - GdipAddPathRectangle(path, rectf.X, rectf.Y, rectf.Width, rectf.Height); + rect = (LPRECT)buf->Buffer; + for(i = 0; i < buf->rdh.nCount; i++){ + if((stat = GdipAddPathRectangle(path, (REAL)rect->left, (REAL)rect->top, + (REAL)(rect->right - rect->left), (REAL)(rect->bottom - rect->top))) != Ok){ + GdipFree(buf); + GdipDeletePath(path); + return stat; + } + rect++; + } stat = GdipCreateRegionPath(path, region); - GdipDeletePath(path); + GdipFree(buf); + GdipDeletePath(path); return stat; } @@ -657,7 +669,8 @@ GpStatus WINGDIPAPI GdipGetRegionBounds(GpRegion *region, GpGraphics *graphics, if(!region || !graphics || !rect) return InvalidParameter; - status = GdipGetRegionHRgn(region, graphics, &hrgn); + /* Contrary to MSDN, native ignores the graphics transform. */ + status = GdipGetRegionHRgn(region, NULL, &hrgn); if(status != Ok) return status; @@ -1114,6 +1127,92 @@ GpStatus WINGDIPAPI GdipIsInfiniteRegion(GpRegion *region, GpGraphics *graphics, return Ok; } +/***************************************************************************** + * GdipIsVisibleRegionRect [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipIsVisibleRegionRect(GpRegion* region, REAL x, REAL y, REAL w, REAL h, GpGraphics *graphics, BOOL *res) +{ + HRGN hrgn; + GpStatus stat; + RECT rect; + + TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %p, %p)\n", region, x, y, w, h, graphics, res); + + if(!region || !res) + return InvalidParameter; + + if((stat = GdipGetRegionHRgn(region, NULL, &hrgn)) != Ok) + return stat; + + /* infinite */ + if(!hrgn){ + *res = TRUE; + return Ok; + } + + rect.left = ceilr(x); + rect.top = ceilr(y); + rect.right = ceilr(x + w); + rect.bottom = ceilr(y + h); + + *res = RectInRegion(hrgn, &rect); + + DeleteObject(hrgn); + + return Ok; +} + +/***************************************************************************** + * GdipIsVisibleRegionRectI [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipIsVisibleRegionRectI(GpRegion* region, INT x, INT y, INT w, INT h, GpGraphics *graphics, BOOL *res) +{ + TRACE("(%p, %d, %d, %d, %d, %p, %p)\n", region, x, y, w, h, graphics, res); + if(!region || !res) + return InvalidParameter; + + return GdipIsVisibleRegionRect(region, (REAL)x, (REAL)y, (REAL)w, (REAL)h, graphics, res); +} + +/***************************************************************************** + * GdipIsVisibleRegionPoint [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipIsVisibleRegionPoint(GpRegion* region, REAL x, REAL y, GpGraphics *graphics, BOOL *res) +{ + HRGN hrgn; + GpStatus stat; + + TRACE("(%p, %.2f, %.2f, %p, %p)\n", region, x, y, graphics, res); + + if(!region || !res) + return InvalidParameter; + + if((stat = GdipGetRegionHRgn(region, NULL, &hrgn)) != Ok) + return stat; + + /* infinite */ + if(!hrgn){ + *res = TRUE; + return Ok; + } + + *res = PtInRegion(hrgn, roundr(x), roundr(y)); + + DeleteObject(hrgn); + + return Ok; +} + +/***************************************************************************** + * GdipIsVisibleRegionPointI [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipIsVisibleRegionPointI(GpRegion* region, INT x, INT y, GpGraphics *graphics, BOOL *res) +{ + TRACE("(%p, %d, %d, %p, %p)\n", region, x, y, graphics, res); + + return GdipIsVisibleRegionPoint(region, (REAL)x, (REAL)y, graphics, res); +} + /***************************************************************************** * GdipSetEmpty [GDIPLUS.@] */ diff --git a/reactos/include/psdk/gdiplusflat.h b/reactos/include/psdk/gdiplusflat.h index a7ee536e795..c06d951ed5b 100644 --- a/reactos/include/psdk/gdiplusflat.h +++ b/reactos/include/psdk/gdiplusflat.h @@ -39,11 +39,15 @@ GpStatus WINGDIPAPI GdipSetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap*,R GpStatus WINGDIPAPI GdipSetAdjustableArrowCapWidth(GpAdjustableArrowCap*,REAL); /* Bitmap */ +GpStatus WINGDIPAPI GdipBitmapApplyEffect(GpBitmap*,CGpEffect*,RECT*,BOOL,VOID**,INT*); +GpStatus WINGDIPAPI GdipBitmapCreateApplyEffect(GpBitmap**,INT,CGpEffect*,RECT*,RECT*,GpBitmap**,BOOL,VOID**,INT*); GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap*,INT,INT,ARGB*); GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap*,GDIPCONST GpRect*,UINT, PixelFormat,BitmapData*); GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap*,INT,INT,ARGB); GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap*,BitmapData*); +GpStatus WINGDIPAPI GdipCloneBitmapArea(REAL,REAL,REAL,REAL,PixelFormat,GpBitmap*,GpBitmap**); +GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT,INT,INT,INT,PixelFormat,GpBitmap*,GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromFile(GDIPCONST WCHAR*,GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromFileICM(GDIPCONST WCHAR*,GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromGdiDib(GDIPCONST BITMAPINFO*,VOID*,GpBitmap**); @@ -55,6 +59,9 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT,INT,INT,PixelFormat,BYTE*, GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromStream(IStream*,GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromStreamICM(IStream*,GpBitmap**); +GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap*,HBITMAP*,ARGB); +GpStatus WINGDIPAPI GdipCreateHICONFromBitmap(GpBitmap*,HICON*); +GpStatus WINGDIPAPI GdipDeleteEffect(CGpEffect*); /* Brush */ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush*,GpBrush**); @@ -118,6 +125,11 @@ GpStatus WINGDIPAPI GdipIsStyleAvailable(GDIPCONST GpFontFamily *, INT, BOOL*); /* Graphics */ GpStatus WINGDIPAPI GdipFlush(GpGraphics*, GpFlushIntention); +GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics*,GDIPCONST GpRectF*,GDIPCONST GpRectF*,GpUnit,GraphicsContainer*); +GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics*,GraphicsContainer*); +GpStatus WINGDIPAPI GdipBeginContainerI(GpGraphics*,GDIPCONST GpRect*,GDIPCONST GpRect*,GpUnit,GraphicsContainer*); +GpStatus WINGDIPAPI GdipEndContainer(GpGraphics*,GraphicsContainer); +GpStatus WINGDIPAPI GdipComment(GpGraphics*,UINT,GDIPCONST BYTE*); GpStatus WINGDIPAPI GdipCreateFromHDC(HDC,GpGraphics**); GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC,HANDLE,GpGraphics**); GpStatus WINGDIPAPI GdipCreateFromHWND(HWND,GpGraphics**); @@ -137,10 +149,16 @@ GpStatus WINGDIPAPI GdipDrawCurve(GpGraphics*,GpPen*,GDIPCONST GpPointF*,INT); GpStatus WINGDIPAPI GdipDrawCurveI(GpGraphics*,GpPen*,GDIPCONST GpPoint*,INT); GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics*,GpPen*,GDIPCONST GpPointF*,INT,REAL); GpStatus WINGDIPAPI GdipDrawCurve2I(GpGraphics*,GpPen*,GDIPCONST GpPoint*,INT,REAL); +GpStatus WINGDIPAPI GdipDrawCurve3(GpGraphics*,GpPen*,GDIPCONST GpPointF*,INT,INT,INT,REAL); +GpStatus WINGDIPAPI GdipDrawCurve3I(GpGraphics*,GpPen*,GDIPCONST GpPoint*,INT,INT,INT,REAL); GpStatus WINGDIPAPI GdipDrawEllipse(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL); GpStatus WINGDIPAPI GdipDrawEllipseI(GpGraphics*,GpPen*,INT,INT,INT,INT); GpStatus WINGDIPAPI GdipDrawImage(GpGraphics*,GpImage*,REAL,REAL); GpStatus WINGDIPAPI GdipDrawImageI(GpGraphics*,GpImage*,INT,INT); +GpStatus WINGDIPAPI GdipDrawImagePointRect(GpGraphics*,GpImage*,REAL,REAL,REAL,REAL,REAL,REAL,GpUnit); +GpStatus WINGDIPAPI GdipDrawImagePointRectI(GpGraphics*,GpImage*,INT,INT,INT,INT,INT,INT,GpUnit); +GpStatus WINGDIPAPI GdipDrawImagePoints(GpGraphics*,GpImage*,GDIPCONST GpPointF*,INT); +GpStatus WINGDIPAPI GdipDrawImagePointsI(GpGraphics*,GpImage*,GDIPCONST GpPoint*,INT); GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics*,GpImage*, GDIPCONST GpPointF*,INT,REAL,REAL,REAL,REAL,GpUnit, GDIPCONST GpImageAttributes*,DrawImageAbort,VOID*); @@ -210,9 +228,13 @@ GpStatus WINGDIPAPI GdipGetTextContrast(GpGraphics*,UINT*); GpStatus WINGDIPAPI GdipGetTextRenderingHint(GpGraphics*,TextRenderingHint*); GpStatus WINGDIPAPI GdipGetWorldTransform(GpGraphics*,GpMatrix*); GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics*,ARGB); +GpStatus WINGDIPAPI GdipGetVisibleClipBounds(GpGraphics*,GpRectF*); +GpStatus WINGDIPAPI GdipGetVisibleClipBoundsI(GpGraphics*,GpRect*); GpStatus WINGDIPAPI GdipIsClipEmpty(GpGraphics*, BOOL*); GpStatus WINGDIPAPI GdipIsVisiblePoint(GpGraphics*,REAL,REAL,BOOL*); GpStatus WINGDIPAPI GdipIsVisiblePointI(GpGraphics*,INT,INT,BOOL*); +GpStatus WINGDIPAPI GdipIsVisibleRect(GpGraphics*,REAL,REAL,REAL,REAL,BOOL*); +GpStatus WINGDIPAPI GdipIsVisibleRectI(GpGraphics*,INT,INT,INT,INT,BOOL*); GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics*, GDIPCONST WCHAR*, INT, GDIPCONST GpFont*, GDIPCONST RectF*, GDIPCONST GpStringFormat*, INT, GpRegion**); @@ -281,6 +303,8 @@ GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath*,REAL,REAL,REAL,REAL); GpStatus WINGDIPAPI GdipAddPathRectangleI(GpPath*,INT,INT,INT,INT); GpStatus WINGDIPAPI GdipAddPathRectangles(GpPath*,GDIPCONST GpRectF*,INT); GpStatus WINGDIPAPI GdipAddPathRectanglesI(GpPath*,GDIPCONST GpRect*,INT); +GpStatus WINGDIPAPI GdipAddPathString(GpPath*,GDIPCONST WCHAR*,INT,GDIPCONST GpFontFamily*,INT,REAL,GDIPCONST RectF*,GDIPCONST GpStringFormat*); +GpStatus WINGDIPAPI GdipAddPathStringI(GpPath*,GDIPCONST WCHAR*,INT,GDIPCONST GpFontFamily*,INT,REAL,GDIPCONST Rect*,GDIPCONST GpStringFormat*); GpStatus WINGDIPAPI GdipClearPathMarkers(GpPath*); GpStatus WINGDIPAPI GdipClonePath(GpPath*,GpPath**); GpStatus WINGDIPAPI GdipClosePathFigure(GpPath*); @@ -317,6 +341,7 @@ GpStatus WINGDIPAPI GdipTransformPath(GpPath*,GpMatrix*); GpStatus WINGDIPAPI GdipCloneImage(GpImage*, GpImage**); GpStatus WINGDIPAPI GdipCloneImageAttributes(GDIPCONST GpImageAttributes*,GpImageAttributes**); GpStatus WINGDIPAPI GdipDisposeImage(GpImage*); +GpStatus WINGDIPAPI GdipEmfToWmfBits(HENHMETAFILE,UINT,LPBYTE,INT,INT); GpStatus WINGDIPAPI GdipFindFirstImageItem(GpImage*,ImageItemData*); GpStatus WINGDIPAPI GdipFindNextImageItem(GpImage*,ImageItemData*); GpStatus WINGDIPAPI GdipGetAllPropertyItems(GpImage*,UINT,UINT,PropertyItem*); @@ -326,6 +351,7 @@ GpStatus WINGDIPAPI GdipGetImageFlags(GpImage*,UINT*); GpStatus WINGDIPAPI GdipGetImageHeight(GpImage*,UINT*); GpStatus WINGDIPAPI GdipGetImageHorizontalResolution(GpImage*,REAL*); GpStatus WINGDIPAPI GdipGetImageItemData(GpImage*,ImageItemData*); +GpStatus WINGDIPAPI GdipGetImagePalette(GpImage*,ColorPalette*,INT); GpStatus WINGDIPAPI GdipGetImagePixelFormat(GpImage*,PixelFormat*); GpStatus WINGDIPAPI GdipGetImageRawFormat(GpImage*,GUID*); GpStatus WINGDIPAPI GdipGetImageThumbnail(GpImage*,UINT,UINT,GpImage**,GetThumbnailImageAbort,VOID*); @@ -389,6 +415,7 @@ GpStatus WINGDIPAPI GdipGetLineBlendCount(GpLineGradient*,INT*); GpStatus WINGDIPAPI GdipSetLineColors(GpLineGradient*,ARGB,ARGB); GpStatus WINGDIPAPI GdipSetLineGammaCorrection(GpLineGradient*,BOOL); GpStatus WINGDIPAPI GdipSetLineSigmaBlend(GpLineGradient*,REAL,REAL); +GpStatus WINGDIPAPI GdipSetLineLinearBlend(GpLineGradient*,REAL,REAL); GpStatus WINGDIPAPI GdipSetLineWrapMode(GpLineGradient*,GpWrapMode); /* Matrix */ @@ -424,6 +451,8 @@ GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE,BOOL, GDIPCONST WmfPlaceableFileHeader*,GpMetafile**); GpStatus WINGDIPAPI GdipCreateMetafileFromWmfFile(GDIPCONST WCHAR*, GDIPCONST WmfPlaceableFileHeader*, GpMetafile**); +GpStatus WINGDIPAPI GdipCreateMetafileFromFile(GDIPCONST WCHAR*,GpMetafile**); +GpStatus WINGDIPAPI GdipCreateMetafileFromStream(IStream*,GpMetafile**); GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpMetafile*,UINT); /* MetafileHeader */ @@ -539,6 +568,10 @@ GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *, GpGraphics *, HRGN *); GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *, GpGraphics *, BOOL *); GpStatus WINGDIPAPI GdipIsEqualRegion(GpRegion *, GpRegion *, GpGraphics *, BOOL *); GpStatus WINGDIPAPI GdipIsInfiniteRegion(GpRegion *, GpGraphics *, BOOL *); +GpStatus WINGDIPAPI GdipIsVisibleRegionPoint(GpRegion *, REAL, REAL, GpGraphics *, BOOL *); +GpStatus WINGDIPAPI GdipIsVisibleRegionPointI(GpRegion *, INT, INT, GpGraphics *, BOOL *); +GpStatus WINGDIPAPI GdipIsVisibleRegionRect(GpRegion *, REAL, REAL, REAL, REAL, GpGraphics *, BOOL *); +GpStatus WINGDIPAPI GdipIsVisibleRegionRectI(GpRegion *, INT, INT, INT, INT, GpGraphics *, BOOL *); GpStatus WINGDIPAPI GdipSetEmpty(GpRegion *); GpStatus WINGDIPAPI GdipSetInfinite(GpRegion *); GpStatus WINGDIPAPI GdipTransformRegion(GpRegion *, GpMatrix *); -- 2.17.1