diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index d6023b0632b..850fbc354b2 100644 --- a/dlls/gdi32/dibdrv/dc.c +++ b/dlls/gdi32/dibdrv/dc.c @@ -114,6 +114,10 @@ static BOOL init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD dib->funcs = &funcs_16; break; + case 8: + dib->funcs = &funcs_8; + break; + default: TRACE("bpp %d not supported, will forward to graphics driver.\n", dib->bit_count); return FALSE; diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index a330d0acf3f..56d08b33719 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -49,6 +49,7 @@ extern const primitive_funcs funcs_8888 DECLSPEC_HIDDEN; extern const primitive_funcs funcs_32 DECLSPEC_HIDDEN; extern const primitive_funcs funcs_555 DECLSPEC_HIDDEN; extern const primitive_funcs funcs_16 DECLSPEC_HIDDEN; +extern const primitive_funcs funcs_8 DECLSPEC_HIDDEN; extern const primitive_funcs funcs_null DECLSPEC_HIDDEN; extern void calc_and_xor_masks(INT rop, DWORD color, DWORD *and, DWORD *xor) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c index 8ff95fa1401..9622098a4eb 100644 --- a/dlls/gdi32/dibdrv/primitives.c +++ b/dlls/gdi32/dibdrv/primitives.c @@ -35,6 +35,11 @@ static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y) return (WORD *)((BYTE*)dib->bits + y * dib->stride + x * 2); } +static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y) +{ + return (BYTE*)dib->bits + y * dib->stride + x; +} + static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor) { *ptr = (*ptr & and) ^ xor; @@ -45,6 +50,11 @@ static inline void do_rop_16(WORD *ptr, WORD and, WORD xor) *ptr = (*ptr & and) ^ xor; } +static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor) +{ + *ptr = (*ptr & and) ^ xor; +} + static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor) { DWORD *ptr, *start; @@ -73,6 +83,20 @@ static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD a } } +static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor) +{ + BYTE *ptr, *start; + int x, y, i; + + for(i = 0; i < num; i++, rc++) + { + start = get_pixel_ptr_8(dib, rc->left, rc->top); + for(y = rc->top; y < rc->bottom; y++, start += dib->stride) + for(x = rc->left, ptr = start; x < rc->right; x++) + do_rop_8(ptr++, and, xor); + } +} + static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor) { return; @@ -194,6 +218,52 @@ static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const } } +static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin, + const dib_info *brush, void *and_bits, void *xor_bits) +{ + BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr; + int x, y, i; + POINT offset; + + for(i = 0; i < num; i++, rc++) + { + offset = calc_brush_offset(rc, brush, origin); + + start = get_pixel_ptr_8(dib, rc->left, rc->top); + start_and = (BYTE*)and_bits + offset.y * brush->stride; + start_xor = (BYTE*)xor_bits + offset.y * brush->stride; + + for(y = rc->top; y < rc->bottom; y++, start += dib->stride) + { + and_ptr = start_and + offset.x; + xor_ptr = start_xor + offset.x; + + for(x = rc->left, ptr = start; x < rc->right; x++) + { + do_rop_8(ptr++, *and_ptr++, *xor_ptr++); + if(and_ptr == start_and + brush->width) + { + and_ptr = start_and; + xor_ptr = start_xor; + } + } + + offset.y++; + if(offset.y == brush->height) + { + start_and = and_bits; + start_xor = xor_bits; + offset.y = 0; + } + else + { + start_and += brush->stride; + start_xor += brush->stride; + } + } + } +} + static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin, const dib_info *brush, void *and_bits, void *xor_bits) { @@ -235,6 +305,37 @@ static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color) return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) ); } +static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color) +{ + int i, best_index = 0; + RGBQUAD rgb; + DWORD diff, best_diff = 0xffffffff; + + rgb.rgbRed = GetRValue(color); + rgb.rgbGreen = GetGValue(color); + rgb.rgbBlue = GetBValue(color); + + for(i = 0; i < dib->color_table_size; i++) + { + RGBQUAD *cur = dib->color_table + i; + diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed) + + (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen) + + (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue); + + if(diff == 0) + { + best_index = i; + break; + } + + if(diff < best_diff) + { + best_diff = diff; + best_index = i; + } + } + return best_index; +} static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color) { @@ -524,6 +625,79 @@ static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_re return TRUE; } +static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect) +{ + BYTE *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++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) | + ( src_val & 0x00ff00) | + ((src_val << 16) & 0xff0000) ); + } + dst_start += dst->stride; + src_start += src->stride / 4; + } + } + else + { + FIXME("Unsupported conversion: 32 -> 8\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++ = colorref_to_pixel_colortable(dst, ((src_val >> 7) & 0x0000f8) | ((src_val >> 12) & 0x000007) | + ((src_val << 6) & 0x00f800) | ((src_val << 1) & 0x000700) | + ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) ); + } + dst_start += dst->stride; + src_start += src->stride / 2; + } + } + else + { + FIXME("Unsupported conversion: 16 -> 8\n"); + return FALSE; + } + break; + } + + default: + FIXME("Unsupported conversion: %d -> 8\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; @@ -561,6 +735,14 @@ const primitive_funcs funcs_16 = convert_to_16 }; +const primitive_funcs funcs_8 = +{ + solid_rects_8, + pattern_rects_8, + colorref_to_pixel_colortable, + convert_to_8 +}; + const primitive_funcs funcs_null = { solid_rects_null,