diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index 98463b7f2f6..07227a1e64b 100644 --- a/dlls/gdi32/dibdrv/dc.c +++ b/dlls/gdi32/dibdrv/dc.c @@ -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; } /*********************************************************************** diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index 0b5dba313e8..a8e1dd95d33 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -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; diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index 30be49666e5..ebe94c079da 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -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; } diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c index c1d159712a8..8ff95fa1401 100644 --- a/dlls/gdi32/dibdrv/primitives.c +++ b/dlls/gdi32/dibdrv/primitives.c @@ -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 };