Vincent Povirk : gdiplus: Create HBITMAP-less bitmap objects for exotic pixel formats.
Alexandre Julliard
julliard at winehq.org
Tue Aug 17 11:31:11 CDT 2010
Module: wine
Branch: master
Commit: 9a6eabf0b52e7d8f9728ba7a3afe2659a7ebed73
URL: http://source.winehq.org/git/wine.git/?a=commit;h=9a6eabf0b52e7d8f9728ba7a3afe2659a7ebed73
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Sun Aug 8 16:18:40 2010 -0500
gdiplus: Create HBITMAP-less bitmap objects for exotic pixel formats.
---
dlls/gdiplus/gdiplus_private.h | 3 +
dlls/gdiplus/graphics.c | 39 +++++++++++++++
dlls/gdiplus/image.c | 103 ++++++++++++++++++++++++++--------------
dlls/gdiplus/tests/graphics.c | 6 +-
4 files changed, 113 insertions(+), 38 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 908a1b7..f3393d4 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -49,6 +49,8 @@ extern REAL gdiplus_atan2(REAL dy, REAL dx);
extern GpStatus hresult_to_status(HRESULT res);
extern REAL convert_unit(REAL logpixels, GpUnit unit);
+extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics);
+
extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
REAL *y1, REAL *x2, REAL *y2);
extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
@@ -269,6 +271,7 @@ struct GpBitmap{
HDC hdc;
BYTE *bits; /* actual image bits if this is a DIB */
INT stride; /* stride of bits if this is a DIB */
+ BYTE *own_bits; /* image bits that need to be freed with this object */
};
struct GpCachedBitmap{
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 79290b5..e748477 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -1254,6 +1254,45 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra
return Ok;
}
+GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics)
+{
+ GpStatus retval;
+
+ *graphics = GdipAlloc(sizeof(GpGraphics));
+ if(!*graphics) return OutOfMemory;
+
+ if((retval = GdipCreateMatrix(&(*graphics)->worldtrans)) != Ok){
+ GdipFree(*graphics);
+ return retval;
+ }
+
+ if((retval = GdipCreateRegion(&(*graphics)->clip)) != Ok){
+ GdipFree((*graphics)->worldtrans);
+ GdipFree(*graphics);
+ return retval;
+ }
+
+ (*graphics)->hdc = NULL;
+ (*graphics)->hwnd = NULL;
+ (*graphics)->owndc = FALSE;
+ (*graphics)->image = image;
+ (*graphics)->smoothing = SmoothingModeDefault;
+ (*graphics)->compqual = CompositingQualityDefault;
+ (*graphics)->interpolation = InterpolationModeDefault;
+ (*graphics)->pixeloffset = PixelOffsetModeDefault;
+ (*graphics)->compmode = CompositingModeSourceOver;
+ (*graphics)->unit = UnitDisplay;
+ (*graphics)->scale = 1.0;
+ (*graphics)->busy = FALSE;
+ (*graphics)->textcontrast = 4;
+ list_init(&(*graphics)->containers);
+ (*graphics)->contid = 0;
+
+ TRACE("<-- %p\n", *graphics);
+
+ return Ok;
+}
+
GpStatus WINGDIPAPI GdipCreateFromHWND(HWND hwnd, GpGraphics **graphics)
{
GpStatus ret;
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index 57c9f83..536eebb 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -1626,10 +1626,10 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
PixelFormat format, BYTE* scan0, GpBitmap** bitmap)
{
BITMAPINFO* pbmi;
- HBITMAP hbitmap;
+ HBITMAP hbitmap=NULL;
INT row_size, dib_stride;
HDC hdc;
- BYTE *bits;
+ BYTE *bits=NULL, *own_bits=NULL;
int i;
REAL xres, yres;
GpStatus stat;
@@ -1655,39 +1655,63 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
if(stride == 0)
stride = dib_stride;
- pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
- if (!pbmi)
- return OutOfMemory;
+ if (format & PixelFormatGDI)
+ {
+ pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+ if (!pbmi)
+ return OutOfMemory;
- pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- pbmi->bmiHeader.biWidth = width;
- pbmi->bmiHeader.biHeight = -height;
- pbmi->bmiHeader.biPlanes = 1;
- /* FIXME: use the rest of the data from format */
- pbmi->bmiHeader.biBitCount = PIXELFORMATBPP(format);
- pbmi->bmiHeader.biCompression = BI_RGB;
- pbmi->bmiHeader.biSizeImage = 0;
- pbmi->bmiHeader.biXPelsPerMeter = 0;
- pbmi->bmiHeader.biYPelsPerMeter = 0;
- pbmi->bmiHeader.biClrUsed = 0;
- pbmi->bmiHeader.biClrImportant = 0;
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = width;
+ pbmi->bmiHeader.biHeight = -height;
+ pbmi->bmiHeader.biPlanes = 1;
+ /* FIXME: use the rest of the data from format */
+ pbmi->bmiHeader.biBitCount = PIXELFORMATBPP(format);
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ hdc = CreateCompatibleDC(NULL);
+ if (!hdc) {
+ GdipFree(pbmi);
+ return GenericError;
+ }
- hdc = CreateCompatibleDC(NULL);
- if (!hdc) {
+ hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+
+ DeleteDC(hdc);
GdipFree(pbmi);
- return GenericError;
- }
- hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+ if (!hbitmap) return GenericError;
+ }
+ else
+ {
+ /* Not a GDI format; don't try to make an HBITMAP. */
+ if (scan0)
+ {
+ /* FIXME: We should do this with GDI formats too when scan0 is
+ * provided, but for now we need the HDC for most drawing
+ * operations. */
+ bits = scan0;
+ }
+ else
+ {
+ INT size = abs(stride) * height;
- DeleteDC(hdc);
- GdipFree(pbmi);
+ own_bits = bits = GdipAlloc(size);
+ if (!own_bits) return OutOfMemory;
- if (!hbitmap) return GenericError;
+ if (stride < 0)
+ bits += stride * (1 - height);
+ }
+ }
/* copy bits to the dib if necessary */
/* FIXME: should reference the bits instead of copying them */
- if (scan0)
+ if (scan0 && bits != scan0)
for (i=0; i<height; i++)
memcpy(bits+i*dib_stride, scan0+i*stride, row_size);
@@ -1695,6 +1719,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
if(!*bitmap)
{
DeleteObject(hbitmap);
+ GdipFree(own_bits);
return OutOfMemory;
}
@@ -1715,6 +1740,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
(*bitmap)->hdc = NULL;
(*bitmap)->bits = bits;
(*bitmap)->stride = dib_stride;
+ (*bitmap)->own_bits = own_bits;
if (format == PixelFormat1bppIndexed ||
format == PixelFormat4bppIndexed ||
@@ -1916,6 +1942,7 @@ static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
dst->hdc = src->hdc;
dst->bits = src->bits;
dst->stride = src->stride;
+ dst->own_bits = src->own_bits;
GdipFree(src);
}
@@ -1932,6 +1959,7 @@ GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image)
if (image->type == ImageTypeBitmap)
{
GdipFree(((GpBitmap*)image)->bitmapbits);
+ GdipFree(((GpBitmap*)image)->own_bits);
DeleteDC(((GpBitmap*)image)->hdc);
DeleteObject(((GpBitmap*)image)->hbitmap);
}
@@ -2048,18 +2076,23 @@ GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage *image,
return NotImplemented;
}
- hdc = ((GpBitmap*)image)->hdc;
+ if (((GpBitmap*)image)->hbitmap)
+ {
+ hdc = ((GpBitmap*)image)->hdc;
- if(!hdc){
- hdc = CreateCompatibleDC(0);
- SelectObject(hdc, ((GpBitmap*)image)->hbitmap);
- ((GpBitmap*)image)->hdc = hdc;
- }
+ if(!hdc){
+ hdc = CreateCompatibleDC(0);
+ SelectObject(hdc, ((GpBitmap*)image)->hbitmap);
+ ((GpBitmap*)image)->hdc = hdc;
+ }
- stat = GdipCreateFromHDC(hdc, graphics);
+ stat = GdipCreateFromHDC(hdc, graphics);
- if (stat == Ok)
- (*graphics)->image = image;
+ if (stat == Ok)
+ (*graphics)->image = image;
+ }
+ else
+ stat = graphics_from_image(image, graphics);
return stat;
}
diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c
index 441367e..609f426 100644
--- a/dlls/gdiplus/tests/graphics.c
+++ b/dlls/gdiplus/tests/graphics.c
@@ -2616,7 +2616,7 @@ static void test_GdipGetNearestColor(void)
GdipDisposeImage((GpImage*)bitmap);
status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, &bitmap);
- todo_wine expect(Ok, status);
+ expect(Ok, status);
if (status == Ok)
{
status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
@@ -2629,7 +2629,7 @@ static void test_GdipGetNearestColor(void)
}
status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, &bitmap);
- todo_wine expect(Ok, status);
+ expect(Ok, status);
if (status == Ok)
{
status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
@@ -2642,7 +2642,7 @@ static void test_GdipGetNearestColor(void)
}
status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, &bitmap);
- todo_wine expect(Ok, status);
+ expect(Ok, status);
if (status == Ok)
{
status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
More information about the wine-cvs
mailing list