Commit 9a6eabf0 authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Create HBITMAP-less bitmap objects for exotic pixel formats.

parent 963c7090
...@@ -49,6 +49,8 @@ extern REAL gdiplus_atan2(REAL dy, REAL dx); ...@@ -49,6 +49,8 @@ extern REAL gdiplus_atan2(REAL dy, REAL dx);
extern GpStatus hresult_to_status(HRESULT res); extern GpStatus hresult_to_status(HRESULT res);
extern REAL convert_unit(REAL logpixels, GpUnit unit); 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, extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
REAL *y1, REAL *x2, REAL *y2); REAL *y1, REAL *x2, REAL *y2);
extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
...@@ -269,6 +271,7 @@ struct GpBitmap{ ...@@ -269,6 +271,7 @@ struct GpBitmap{
HDC hdc; HDC hdc;
BYTE *bits; /* actual image bits if this is a DIB */ BYTE *bits; /* actual image bits if this is a DIB */
INT stride; /* stride of 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{ struct GpCachedBitmap{
......
...@@ -1254,6 +1254,45 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra ...@@ -1254,6 +1254,45 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra
return Ok; 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 WINGDIPAPI GdipCreateFromHWND(HWND hwnd, GpGraphics **graphics)
{ {
GpStatus ret; GpStatus ret;
......
...@@ -1626,10 +1626,10 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, ...@@ -1626,10 +1626,10 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
PixelFormat format, BYTE* scan0, GpBitmap** bitmap) PixelFormat format, BYTE* scan0, GpBitmap** bitmap)
{ {
BITMAPINFO* pbmi; BITMAPINFO* pbmi;
HBITMAP hbitmap; HBITMAP hbitmap=NULL;
INT row_size, dib_stride; INT row_size, dib_stride;
HDC hdc; HDC hdc;
BYTE *bits; BYTE *bits=NULL, *own_bits=NULL;
int i; int i;
REAL xres, yres; REAL xres, yres;
GpStatus stat; GpStatus stat;
...@@ -1655,39 +1655,63 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, ...@@ -1655,39 +1655,63 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
if(stride == 0) if(stride == 0)
stride = dib_stride; stride = dib_stride;
pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); if (format & PixelFormatGDI)
if (!pbmi) {
return OutOfMemory; pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
if (!pbmi)
return OutOfMemory;
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = width; pbmi->bmiHeader.biWidth = width;
pbmi->bmiHeader.biHeight = -height; pbmi->bmiHeader.biHeight = -height;
pbmi->bmiHeader.biPlanes = 1; pbmi->bmiHeader.biPlanes = 1;
/* FIXME: use the rest of the data from format */ /* FIXME: use the rest of the data from format */
pbmi->bmiHeader.biBitCount = PIXELFORMATBPP(format); pbmi->bmiHeader.biBitCount = PIXELFORMATBPP(format);
pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 0; pbmi->bmiHeader.biSizeImage = 0;
pbmi->bmiHeader.biXPelsPerMeter = 0; pbmi->bmiHeader.biXPelsPerMeter = 0;
pbmi->bmiHeader.biYPelsPerMeter = 0; pbmi->bmiHeader.biYPelsPerMeter = 0;
pbmi->bmiHeader.biClrUsed = 0; pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biClrImportant = 0; pbmi->bmiHeader.biClrImportant = 0;
hdc = CreateCompatibleDC(NULL);
if (!hdc) {
GdipFree(pbmi);
return GenericError;
}
hdc = CreateCompatibleDC(NULL); hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
if (!hdc) {
DeleteDC(hdc);
GdipFree(pbmi); 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); own_bits = bits = GdipAlloc(size);
GdipFree(pbmi); if (!own_bits) return OutOfMemory;
if (!hbitmap) return GenericError; if (stride < 0)
bits += stride * (1 - height);
}
}
/* copy bits to the dib if necessary */ /* copy bits to the dib if necessary */
/* FIXME: should reference the bits instead of copying them */ /* FIXME: should reference the bits instead of copying them */
if (scan0) if (scan0 && bits != scan0)
for (i=0; i<height; i++) for (i=0; i<height; i++)
memcpy(bits+i*dib_stride, scan0+i*stride, row_size); memcpy(bits+i*dib_stride, scan0+i*stride, row_size);
...@@ -1695,6 +1719,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, ...@@ -1695,6 +1719,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
if(!*bitmap) if(!*bitmap)
{ {
DeleteObject(hbitmap); DeleteObject(hbitmap);
GdipFree(own_bits);
return OutOfMemory; return OutOfMemory;
} }
...@@ -1715,6 +1740,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, ...@@ -1715,6 +1740,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
(*bitmap)->hdc = NULL; (*bitmap)->hdc = NULL;
(*bitmap)->bits = bits; (*bitmap)->bits = bits;
(*bitmap)->stride = dib_stride; (*bitmap)->stride = dib_stride;
(*bitmap)->own_bits = own_bits;
if (format == PixelFormat1bppIndexed || if (format == PixelFormat1bppIndexed ||
format == PixelFormat4bppIndexed || format == PixelFormat4bppIndexed ||
...@@ -1916,6 +1942,7 @@ static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette) ...@@ -1916,6 +1942,7 @@ static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
dst->hdc = src->hdc; dst->hdc = src->hdc;
dst->bits = src->bits; dst->bits = src->bits;
dst->stride = src->stride; dst->stride = src->stride;
dst->own_bits = src->own_bits;
GdipFree(src); GdipFree(src);
} }
...@@ -1932,6 +1959,7 @@ GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) ...@@ -1932,6 +1959,7 @@ GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image)
if (image->type == ImageTypeBitmap) if (image->type == ImageTypeBitmap)
{ {
GdipFree(((GpBitmap*)image)->bitmapbits); GdipFree(((GpBitmap*)image)->bitmapbits);
GdipFree(((GpBitmap*)image)->own_bits);
DeleteDC(((GpBitmap*)image)->hdc); DeleteDC(((GpBitmap*)image)->hdc);
DeleteObject(((GpBitmap*)image)->hbitmap); DeleteObject(((GpBitmap*)image)->hbitmap);
} }
...@@ -2048,18 +2076,23 @@ GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage *image, ...@@ -2048,18 +2076,23 @@ GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage *image,
return NotImplemented; return NotImplemented;
} }
hdc = ((GpBitmap*)image)->hdc; if (((GpBitmap*)image)->hbitmap)
{
hdc = ((GpBitmap*)image)->hdc;
if(!hdc){ if(!hdc){
hdc = CreateCompatibleDC(0); hdc = CreateCompatibleDC(0);
SelectObject(hdc, ((GpBitmap*)image)->hbitmap); SelectObject(hdc, ((GpBitmap*)image)->hbitmap);
((GpBitmap*)image)->hdc = hdc; ((GpBitmap*)image)->hdc = hdc;
} }
stat = GdipCreateFromHDC(hdc, graphics); stat = GdipCreateFromHDC(hdc, graphics);
if (stat == Ok) if (stat == Ok)
(*graphics)->image = image; (*graphics)->image = image;
}
else
stat = graphics_from_image(image, graphics);
return stat; return stat;
} }
......
...@@ -2616,7 +2616,7 @@ static void test_GdipGetNearestColor(void) ...@@ -2616,7 +2616,7 @@ static void test_GdipGetNearestColor(void)
GdipDisposeImage((GpImage*)bitmap); GdipDisposeImage((GpImage*)bitmap);
status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, &bitmap); status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, &bitmap);
todo_wine expect(Ok, status); expect(Ok, status);
if (status == Ok) if (status == Ok)
{ {
status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
...@@ -2629,7 +2629,7 @@ static void test_GdipGetNearestColor(void) ...@@ -2629,7 +2629,7 @@ static void test_GdipGetNearestColor(void)
} }
status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, &bitmap); status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, &bitmap);
todo_wine expect(Ok, status); expect(Ok, status);
if (status == Ok) if (status == Ok)
{ {
status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
...@@ -2642,7 +2642,7 @@ static void test_GdipGetNearestColor(void) ...@@ -2642,7 +2642,7 @@ static void test_GdipGetNearestColor(void)
} }
status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, &bitmap); status = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, &bitmap);
todo_wine expect(Ok, status); expect(Ok, status);
if (status == Ok) if (status == Ok)
{ {
status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); status = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment