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

This commit is contained in:
Vincent Povirk 2010-08-08 16:18:40 -05:00 committed by Alexandre Julliard
parent 963c7090d5
commit 9a6eabf0b5
4 changed files with 114 additions and 39 deletions

View File

@ -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{

View File

@ -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;

View File

@ -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) {
hdc = CreateCompatibleDC(NULL);
if (!hdc) {
GdipFree(pbmi);
return GenericError;
}
hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
DeleteDC(hdc);
GdipFree(pbmi);
return GenericError;
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;
hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
own_bits = bits = GdipAlloc(size);
if (!own_bits) return OutOfMemory;
DeleteDC(hdc);
GdipFree(pbmi);
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);
if (stat == Ok)
(*graphics)->image = image;
}
stat = GdipCreateFromHDC(hdc, graphics);
if (stat == Ok)
(*graphics)->image = image;
else
stat = graphics_from_image(image, graphics);
return stat;
}

View File

@ -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);