gdi32: Add support for arbitrary DIB bitfields for 16-bpp conversions.

This commit is contained in:
Alexandre Julliard 2011-10-13 00:12:04 +02:00
parent b084e52bf6
commit 587f492fdf
2 changed files with 156 additions and 61 deletions

View File

@ -1294,8 +1294,21 @@ static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_
} }
else else
{ {
FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8888\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = (get_field( src_val, src->red_shift, src->red_len ) << 16 |
get_field( src_val, src->green_shift, src->green_len ) << 8 |
get_field( src_val, src->blue_shift, src->blue_len ));
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 4;
src_start += src->stride / 2;
}
} }
break; break;
} }
@ -1547,8 +1560,21 @@ static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_re
} }
else else
{ {
FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 32\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 4;
src_start += src->stride / 2;
}
} }
break; break;
} }
@ -1783,8 +1809,21 @@ static BOOL convert_to_24(dib_info *dst, const dib_info *src, const RECT *src_re
} }
else else
{ {
FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 24\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = get_field(src_val, src->blue_shift, src->blue_len );
*dst_pixel++ = get_field(src_val, src->green_shift, src->green_len );
*dst_pixel++ = get_field(src_val, src->red_shift, src->red_len );
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride;
src_start += src->stride / 2;
}
} }
break; break;
} }
@ -2018,8 +2057,21 @@ static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_r
} }
else else
{ {
FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 555\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = (((get_field(src_val, src->red_shift, src->red_len) << 7) & 0x7c00) |
((get_field(src_val, src->green_shift, src->green_len) << 2) & 0x03e0) |
( get_field(src_val, src->blue_shift, src->blue_len) >> 3));
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 2;
src_start += src->stride / 2;
}
} }
break; break;
} }
@ -2277,9 +2329,21 @@ static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_re
} }
else else
{ {
FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 16 (%08x, %08x, %08x)\n", for(y = src_rect->top; y < src_rect->bottom; y++)
src->red_mask, src->green_mask, src->blue_mask, dst->red_mask, dst->green_mask, dst->blue_mask); {
return FALSE; dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = put_field(get_field(src_val, src->red_shift, src->red_len ), dst->red_shift, dst->red_len) |
put_field(get_field(src_val, src->green_shift, src->green_len ), dst->green_shift, dst->green_len) |
put_field(get_field(src_val, src->blue_shift, src->blue_len ), dst->blue_shift, dst->blue_len);
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride / 2;
src_start += src->stride / 2;
}
} }
break; break;
} }
@ -2530,8 +2594,21 @@ static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rec
} }
else else
{ {
FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 8\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = colorref_to_pixel_colortable(dst, (get_field(src_val, src->red_shift, src->red_len) |
get_field(src_val, src->green_shift, src->green_len) << 8 |
get_field(src_val, src->blue_shift, src->blue_len) << 16));
}
if(pad_size) memset(dst_pixel, 0, pad_size);
dst_start += dst->stride;
src_start += src->stride / 2;
}
} }
break; break;
} }
@ -2865,8 +2942,32 @@ static BOOL convert_to_4(dib_info *dst, const dib_info *src, const RECT *src_rec
} }
else else
{ {
FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 4\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
dst_val = colorref_to_pixel_colortable(dst, (get_field(src_val, src->red_shift, src->red_len) |
get_field(src_val, src->green_shift, src->green_len) << 8 |
get_field(src_val, src->blue_shift, src->blue_len) << 16));
if((x - src_rect->left) & 1)
{
*dst_pixel = (dst_val & 0x0f) | (*dst_pixel & 0xf0);
dst_pixel++;
}
else
*dst_pixel = (dst_val << 4) & 0xf0;
}
if(pad_size)
{
if((x - src_rect->left) & 1) dst_pixel++;
memset(dst_pixel, 0, pad_size);
}
dst_start += dst->stride;
src_start += src->stride / 2;
}
} }
break; break;
} }
@ -3228,7 +3329,7 @@ static BOOL convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
(((src_val >> src->green_shift) << 10) & 0x00fc00) | (((src_val >> src->green_shift) << 10) & 0x00fc00) |
(((src_val >> src->green_shift) << 4) & 0x000300) | (((src_val >> src->green_shift) << 4) & 0x000300) |
(((src_val >> src->blue_shift) << 19) & 0xf80000) | (((src_val >> src->blue_shift) << 19) & 0xf80000) |
(((src_val >> src->blue_shift) << 14) & 0x070000) ); (((src_val >> src->blue_shift) << 14) & 0x070000) ) ? 0xff : 0;
if(bit_pos == 0) *dst_pixel = 0; if(bit_pos == 0) *dst_pixel = 0;
*dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]); *dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
@ -3249,8 +3350,33 @@ static BOOL convert_to_1(dib_info *dst, const dib_info *src, const RECT *src_rec
} }
else else
{ {
FIXME("Unsupported conversion: 16 (%08x, %08x, %08x) -> 1\n", src->red_mask, src->green_mask, src->blue_mask); for(y = src_rect->top; y < src_rect->bottom; y++)
return FALSE; {
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left, bit_pos = 0; x < src_rect->right; x++)
{
src_val = *src_pixel++;
dst_val = colorref_to_pixel_colortable(dst, (get_field(src_val, src->red_shift, src->red_len) |
get_field(src_val, src->green_shift, src->green_len) << 8 |
get_field(src_val, src->blue_shift, src->blue_len) << 16)) ? 0xff : 0;
if(bit_pos == 0) *dst_pixel = 0;
*dst_pixel = (*dst_pixel & ~pixel_masks_1[bit_pos]) | (dst_val & pixel_masks_1[bit_pos]);
if(++bit_pos == 8)
{
dst_pixel++;
bit_pos = 0;
}
}
if(pad_size)
{
if(bit_pos != 0) dst_pixel++;
memset(dst_pixel, 0, pad_size);
}
dst_start += dst->stride;
src_start += src->stride / 2;
}
} }
break; break;
} }

View File

@ -821,7 +821,7 @@ static void test_dib_formats(void)
HBITMAP hdib, hbmp; HBITMAP hdib, hbmp;
HDC hdc, memdc; HDC hdc, memdc;
UINT ret; UINT ret;
BOOL expect_ok, todo; BOOL expect_ok;
bi = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ) ); bi = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ) );
hdc = GetDC( 0 ); hdc = GetDC( 0 );
@ -846,7 +846,6 @@ static void test_dib_formats(void)
case 32: expect_ok = (compr == BI_RGB || compr == BI_BITFIELDS); break; case 32: expect_ok = (compr == BI_RGB || compr == BI_BITFIELDS); break;
default: expect_ok = FALSE; break; default: expect_ok = FALSE; break;
} }
todo = (compr == BI_BITFIELDS) && bpp == 16; /* wine doesn't like strange bitfields */
memset( bi, 0, sizeof(bi->bmiHeader) ); memset( bi, 0, sizeof(bi->bmiHeader) );
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
@ -897,36 +896,21 @@ static void test_dib_formats(void)
bi->bmiHeader.biSizeImage = 0; bi->bmiHeader.biSizeImage = 0;
ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS); ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS);
if (expect_ok) if (expect_ok)
{ ok( ret, "SetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
if (todo)
todo_wine ok( ret, "SetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( ret, "SetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
}
else else
ok( !ret || ok( !ret ||
broken((bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8)), /* nt4 */ broken((bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8)), /* nt4 */
"SetDIBits succeeded for %u/%u/%u\n", bpp, planes, compr ); "SetDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
ret = SetDIBitsToDevice( memdc, 0, 0, 1, 1, 0, 0, 0, 1, data, bi, DIB_RGB_COLORS ); ret = SetDIBitsToDevice( memdc, 0, 0, 1, 1, 0, 0, 0, 1, data, bi, DIB_RGB_COLORS );
if (expect_ok) if (expect_ok)
{ ok( ret, "SetDIBitsToDevice failed for %u/%u/%u\n", bpp, planes, compr );
if (todo)
todo_wine ok( ret, "SetDIBitsToDevice failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( ret, "SetDIBitsToDevice failed for %u/%u/%u\n", bpp, planes, compr );
}
else else
ok( !ret || ok( !ret ||
broken((bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8)), /* nt4 */ broken((bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8)), /* nt4 */
"SetDIBitsToDevice succeeded for %u/%u/%u\n", bpp, planes, compr ); "SetDIBitsToDevice succeeded for %u/%u/%u\n", bpp, planes, compr );
ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY ); ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY );
if (expect_ok) if (expect_ok)
{ ok( ret, "StretchDIBits failed for %u/%u/%u\n", bpp, planes, compr );
if (todo)
todo_wine ok( ret, "StretchDIBits failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( ret, "StretchDIBits failed for %u/%u/%u\n", bpp, planes, compr );
}
else else
ok( !ret || ok( !ret ||
broken((bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8)), /* nt4 */ broken((bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8)), /* nt4 */
@ -953,32 +937,17 @@ static void test_dib_formats(void)
ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS); ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS);
if (expect_ok) if (expect_ok)
{ ok( ret, "SetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
if (todo)
todo_wine ok( ret, "SetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( ret, "SetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
}
else else
ok( !ret, "SetDIBits succeeded for %u/%u/%u\n", bpp, planes, compr ); ok( !ret, "SetDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
ret = SetDIBitsToDevice( memdc, 0, 0, 1, 1, 0, 0, 0, 1, data, bi, DIB_RGB_COLORS ); ret = SetDIBitsToDevice( memdc, 0, 0, 1, 1, 0, 0, 0, 1, data, bi, DIB_RGB_COLORS );
if (expect_ok) if (expect_ok)
{ ok( ret, "SetDIBitsToDevice failed for %u/%u/%u\n", bpp, planes, compr );
if (todo)
todo_wine ok( ret, "SetDIBitsToDevice failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( ret, "SetDIBitsToDevice failed for %u/%u/%u\n", bpp, planes, compr );
}
else else
ok( !ret, "SetDIBitsToDevice succeeded for %u/%u/%u\n", bpp, planes, compr ); ok( !ret, "SetDIBitsToDevice succeeded for %u/%u/%u\n", bpp, planes, compr );
ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY ); ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY );
if (expect_ok) if (expect_ok)
{ ok( ret, "StretchDIBits failed for %u/%u/%u\n", bpp, planes, compr );
if (todo)
todo_wine ok( ret, "StretchDIBits failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( ret, "StretchDIBits failed for %u/%u/%u\n", bpp, planes, compr );
}
else else
ok( !ret, "StretchDIBits succeeded for %u/%u/%u\n", bpp, planes, compr ); ok( !ret, "StretchDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
@ -1007,15 +976,15 @@ static void test_dib_formats(void)
hdib = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0); hdib = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
ok( hdib == NULL, "CreateDIBSection succeeded with null bitfields\n" ); ok( hdib == NULL, "CreateDIBSection succeeded with null bitfields\n" );
ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS); ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS);
ok( !ret, "SetDIBits succeeded with null bitfields\n" ); todo_wine ok( !ret, "SetDIBits succeeded with null bitfields\n" );
/* other functions don't check */ /* other functions don't check */
hdib = CreateDIBitmap( hdc, &bi->bmiHeader, 0, bits, bi, DIB_RGB_COLORS ); hdib = CreateDIBitmap( hdc, &bi->bmiHeader, 0, bits, bi, DIB_RGB_COLORS );
ok( hdib != NULL, "CreateDIBitmap failed with null bitfields\n" ); ok( hdib != NULL, "CreateDIBitmap failed with null bitfields\n" );
DeleteObject( hdib ); DeleteObject( hdib );
ret = SetDIBitsToDevice( memdc, 0, 0, 1, 1, 0, 0, 0, 1, data, bi, DIB_RGB_COLORS ); ret = SetDIBitsToDevice( memdc, 0, 0, 1, 1, 0, 0, 0, 1, data, bi, DIB_RGB_COLORS );
todo_wine ok( ret, "SetDIBitsToDevice failed with null bitfields\n" ); ok( ret, "SetDIBitsToDevice failed with null bitfields\n" );
ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY ); ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY );
todo_wine ok( ret, "StretchDIBits failed with null bitfields\n" ); ok( ret, "StretchDIBits failed with null bitfields\n" );
ret = GetDIBits(hdc, hbmp, 0, 2, data, bi, DIB_RGB_COLORS); ret = GetDIBits(hdc, hbmp, 0, 2, data, bi, DIB_RGB_COLORS);
ok( ret, "GetDIBits failed with null bitfields\n" ); ok( ret, "GetDIBits failed with null bitfields\n" );
bi->bmiHeader.biPlanes = 1; bi->bmiHeader.biPlanes = 1;
@ -1035,7 +1004,7 @@ static void test_dib_formats(void)
hdib = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0); hdib = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
ok( hdib == NULL, "CreateDIBSection succeeded with null bitfields\n" ); ok( hdib == NULL, "CreateDIBSection succeeded with null bitfields\n" );
ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS); ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS);
ok( !ret, "SetDIBits succeeded with null bitfields\n" ); todo_wine ok( !ret, "SetDIBits succeeded with null bitfields\n" );
/* garbage is ok though */ /* garbage is ok though */
*(DWORD *)&bi->bmiColors[0] = 0x55; *(DWORD *)&bi->bmiColors[0] = 0x55;
@ -1045,7 +1014,7 @@ static void test_dib_formats(void)
ok( hdib != NULL, "CreateDIBSection failed with bad bitfields\n" ); ok( hdib != NULL, "CreateDIBSection failed with bad bitfields\n" );
if (hdib) DeleteObject( hdib ); if (hdib) DeleteObject( hdib );
ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS); ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS);
todo_wine ok( ret, "SetDIBits failed with bad bitfields\n" ); ok( ret, "SetDIBits failed with bad bitfields\n" );
bi->bmiHeader.biWidth = -2; bi->bmiHeader.biWidth = -2;
bi->bmiHeader.biHeight = 2; bi->bmiHeader.biHeight = 2;