gdi32: Add conversion routines to the primitive functions.

This commit is contained in:
Huw Davies 2011-05-27 13:41:32 +01:00 committed by Alexandre Julliard
parent 18a96edf69
commit 0a9eae97d2
4 changed files with 315 additions and 56 deletions

View File

@ -178,25 +178,6 @@ void copy_dib_color_info(dib_info *dst, const dib_info *src)
dst->funcs = src->funcs;
}
static BOOL dib_formats_match(const dib_info *d1, const dib_info *d2)
{
if(d1->bit_count != d2->bit_count) return FALSE;
switch(d1->bit_count)
{
case 24: return TRUE;
case 32:
case 16:
return (d1->red_mask == d2->red_mask) && (d1->green_mask == d2->green_mask) &&
(d1->blue_mask == d2->blue_mask);
default:
ERR("Unexpected depth %d\n", d1->bit_count);
return FALSE;
}
}
/**************************************************************
* convert_dib
*
@ -207,34 +188,22 @@ static BOOL dib_formats_match(const dib_info *d1, const dib_info *d2)
*/
BOOL convert_dib(dib_info *dst, const dib_info *src)
{
INT y;
BOOL ret;
RECT src_rect;
dst->height = src->height;
dst->width = src->width;
dst->stride = ((dst->width * dst->bit_count + 31) >> 3) & ~3;
dst->bits = NULL;
dst->bits = HeapAlloc(GetProcessHeap(), 0, dst->height * dst->stride);
if(dib_formats_match(src, dst))
{
dst->bits = HeapAlloc(GetProcessHeap(), 0, dst->height * dst->stride);
src_rect.left = src_rect.top = 0;
src_rect.right = src->width;
src_rect.bottom = src->height;
if(src->stride > 0)
memcpy(dst->bits, src->bits, dst->height * dst->stride);
else
{
BYTE *src_bits = src->bits;
BYTE *dst_bits = dst->bits;
for(y = 0; y < dst->height; y++)
{
memcpy(dst_bits, src_bits, dst->stride);
dst_bits += dst->stride;
src_bits += src->stride;
}
}
return TRUE;
}
FIXME("Format conversion not implemented\n");
return FALSE;
ret = dst->funcs->convert_to(dst, src, &src_rect);
if(!ret) free_dib_info(dst, TRUE);
return ret;
}
/***********************************************************************

View File

@ -42,6 +42,7 @@ typedef struct primitive_funcs
void (* solid_rects)(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor);
void (* pattern_rects)(const dib_info *dib, int num, const RECT *rc, const POINT *orign, const dib_info *brush, void *and_bits, void *xor_bits);
DWORD (* colorref_to_pixel)(const dib_info *dib, COLORREF color);
BOOL (* convert_to)(dib_info *dst, const dib_info *src, const RECT *src_rect);
} primitive_funcs;
extern const primitive_funcs funcs_8888 DECLSPEC_HIDDEN;

View File

@ -992,6 +992,8 @@ static BOOL create_pattern_brush_bits(dibdrv_physdev *pdev)
assert(pdev->brush_and_bits == NULL);
assert(pdev->brush_xor_bits == NULL);
assert(pdev->brush_dib.stride > 0);
and_bits = pdev->brush_and_bits = HeapAlloc(GetProcessHeap(), 0, size);
xor_bits = pdev->brush_xor_bits = HeapAlloc(GetProcessHeap(), 0, size);
@ -1002,22 +1004,12 @@ static BOOL create_pattern_brush_bits(dibdrv_physdev *pdev)
return FALSE;
}
if(pdev->brush_dib.stride < 0)
brush_bits = (DWORD*)((BYTE*)brush_bits + (pdev->brush_dib.height - 1) * pdev->brush_dib.stride);
while(size)
{
calc_and_xor_masks(pdev->brush_rop, *brush_bits++, and_bits++, xor_bits++);
size -= 4;
}
if(pdev->brush_dib.stride < 0)
{
/* Update the bits ptrs if the dib is bottom up. The subtraction is because stride is -ve */
pdev->brush_and_bits = (BYTE*)pdev->brush_and_bits - (pdev->brush_dib.height - 1) * pdev->brush_dib.stride;
pdev->brush_xor_bits = (BYTE*)pdev->brush_xor_bits - (pdev->brush_dib.height - 1) * pdev->brush_dib.stride;
}
return TRUE;
}

View File

@ -21,6 +21,10 @@
#include "gdi_private.h"
#include "dibdrv.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dib);
static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y)
{
return (DWORD *)((BYTE*)dib->bits + y * dib->stride + x * 4);
@ -237,37 +241,330 @@ static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
return 0;
}
static BOOL convert_to_8888(dib_info *dst, const dib_info *src, const RECT *src_rect)
{
DWORD *dst_start = dst->bits, *dst_pixel, src_val;
int x, y;
switch(src->bit_count)
{
case 32:
{
DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top);
if(src->funcs == &funcs_8888)
{
if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
else
{
for(y = src_rect->top; y < src_rect->bottom; y++)
{
memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 4);
dst_start += dst->stride / 4;
src_start += src->stride / 4;
}
}
}
else
{
FIXME("Unsupported conversion: 32 -> 8888\n");
return FALSE;
}
break;
}
case 16:
{
WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
if(src->funcs == &funcs_555)
{
for(y = src_rect->top; y < src_rect->bottom; y++)
{
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = ((src_val << 9) & 0xf80000) | ((src_val << 4) & 0x070000) |
((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) |
((src_val << 3) & 0x0000f8) | ((src_val >> 2) & 0x000007);
}
dst_start += dst->stride / 4;
src_start += src->stride / 2;
}
}
else
{
FIXME("Unsupported conversion: 16 -> 8888\n");
return FALSE;
}
break;
}
default:
FIXME("Unsupported conversion: %d -> 8888\n", src->bit_count);
return FALSE;
}
return TRUE;
}
static BOOL convert_to_32(dib_info *dst, const dib_info *src, const RECT *src_rect)
{
DWORD *dst_start = dst->bits, *dst_pixel, src_val;
int x, y;
switch(src->bit_count)
{
case 32:
{
DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
if(src->funcs == &funcs_8888)
{
for(y = src_rect->top; y < src_rect->bottom; y++)
{
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((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
}
dst_start += dst->stride / 4;
src_start += src->stride / 4;
}
}
else
{
FIXME("Unsupported conversion: 32 -> 32\n");
return FALSE;
}
break;
}
case 16:
{
WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
if(src->funcs == &funcs_555)
{
for(y = src_rect->top; y < src_rect->bottom; y++)
{
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(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
}
dst_start += dst->stride / 4;
src_start += src->stride / 2;
}
}
else
{
FIXME("Unsupported conversion: 16 -> 8888\n");
return FALSE;
}
break;
}
default:
FIXME("Unsupported conversion: %d -> 32\n", src->bit_count);
return FALSE;
}
return TRUE;
}
static BOOL convert_to_555(dib_info *dst, const dib_info *src, const RECT *src_rect)
{
WORD *dst_start = dst->bits, *dst_pixel;
INT x, y;
DWORD src_val;
switch(src->bit_count)
{
case 32:
{
DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
if(src->funcs == &funcs_8888)
{
for(y = src_rect->top; y < src_rect->bottom; y++)
{
dst_pixel = dst_start;
src_pixel = src_start;
for(x = src_rect->left; x < src_rect->right; x++)
{
src_val = *src_pixel++;
*dst_pixel++ = ((src_val >> 9) & 0x7c00) |
((src_val >> 6) & 0x03e0) |
((src_val >> 3) & 0x001e);
}
dst_start += dst->stride / 2;
src_start += src->stride / 4;
}
}
else
{
FIXME("Unsupported conversion: 32 -> 555\n");
return FALSE;
}
break;
}
case 16:
{
WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top);
if(src->funcs == &funcs_555)
{
if(src->stride > 0 && dst->stride > 0 && src_rect->left == 0 && src_rect->right == src->width)
memcpy(dst->bits, src_start, (src_rect->bottom - src_rect->top) * src->stride);
else
{
for(y = src_rect->top; y < src_rect->bottom; y++)
{
memcpy(dst_start, src_start, (src_rect->right - src_rect->left) * 2);
dst_start += dst->stride / 2;
src_start += src->stride / 2;
}
}
}
else
{
FIXME("Unsupported conversion: 16 -> 555\n");
return FALSE;
}
break;
}
default:
FIXME("Unsupported conversion: %d -> 555\n", src->bit_count);
return FALSE;
}
return TRUE;
}
static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_rect)
{
WORD *dst_start = dst->bits, *dst_pixel;
INT x, y;
DWORD src_val;
switch(src->bit_count)
{
case 32:
{
DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
if(src->funcs == &funcs_8888)
{
for(y = src_rect->top; y < src_rect->bottom; y++)
{
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((src_val >> 16) & 0xff, dst->red_shift, dst->red_len) |
put_field((src_val >> 8) & 0xff, dst->green_shift, dst->green_len) |
put_field( src_val & 0xff, dst->blue_shift, dst->blue_len);
}
dst_start += dst->stride / 2;
src_start += src->stride / 4;
}
}
else
{
FIXME("Unsupported conversion: 32 -> 16\n");
return FALSE;
}
break;
}
case 16:
{
WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
if(src->funcs == &funcs_555)
{
for(y = src_rect->top; y < src_rect->bottom; y++)
{
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(((src_val >> 7) & 0xf8) | ((src_val >> 12) & 0x07), dst->red_shift, dst->red_len) |
put_field(((src_val >> 2) & 0xf8) | ((src_val >> 7) & 0x07), dst->green_shift, dst->green_len) |
put_field(((src_val << 3) & 0xf8) | ((src_val >> 2) & 0x07), dst->blue_shift, dst->blue_len);
}
dst_start += dst->stride / 2;
src_start += src->stride / 2;
}
}
else
{
FIXME("Unsupported conversion: 16 -> 16\n");
return FALSE;
}
break;
}
default:
FIXME("Unsupported conversion: %d -> 16\n", src->bit_count);
return FALSE;
}
return TRUE;
}
static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
{
return TRUE;
}
const primitive_funcs funcs_8888 =
{
solid_rects_32,
pattern_rects_32,
colorref_to_pixel_888
colorref_to_pixel_888,
convert_to_8888
};
const primitive_funcs funcs_32 =
{
solid_rects_32,
pattern_rects_32,
colorref_to_pixel_masks
colorref_to_pixel_masks,
convert_to_32
};
const primitive_funcs funcs_555 =
{
solid_rects_16,
pattern_rects_16,
colorref_to_pixel_555
colorref_to_pixel_555,
convert_to_555
};
const primitive_funcs funcs_16 =
{
solid_rects_16,
pattern_rects_16,
colorref_to_pixel_masks
colorref_to_pixel_masks,
convert_to_16
};
const primitive_funcs funcs_null =
{
solid_rects_null,
pattern_rects_null,
colorref_to_pixel_null
colorref_to_pixel_null,
convert_to_null
};