Commit 219e2a35 authored by Alexandre Julliard's avatar Alexandre Julliard

winex11: Split copy_image_bits into a couple of helper functions.

parent 8f8212b8
...@@ -1036,113 +1036,86 @@ static inline BOOL is_r8g8b8( const XVisualInfo *vis ) ...@@ -1036,113 +1036,86 @@ static inline BOOL is_r8g8b8( const XVisualInfo *vis )
return vis->depth == 24 && vis->red_mask == 0xff0000 && vis->blue_mask == 0x0000ff; return vis->depth == 24 && vis->red_mask == 0xff0000 && vis->blue_mask == 0x0000ff;
} }
/* copy the image bits, fixing up alignment and byte swapping as necessary */ static inline BOOL image_needs_byteswap( XImage *image, BOOL is_r8g8b8, int bit_count )
DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
{ {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
static const int client_byte_order = MSBFirst; static const int client_byte_order = MSBFirst;
#else #else
static const int client_byte_order = LSBFirst; static const int client_byte_order = LSBFirst;
#endif #endif
BOOL need_byteswap;
int x, y, height = coords->visrect.bottom - coords->visrect.top;
int width_bytes = image->bytes_per_line;
int padding_pos;
unsigned char *src, *dst;
switch (info->bmiHeader.biBitCount) switch (bit_count)
{ {
case 1: case 1: return image->bitmap_bit_order != MSBFirst;
need_byteswap = (image->bitmap_bit_order != MSBFirst); case 4: return image->byte_order != MSBFirst;
break;
case 4:
need_byteswap = (image->byte_order != MSBFirst);
break;
case 16: case 16:
case 32: case 32: return image->byte_order != client_byte_order;
need_byteswap = (image->byte_order != client_byte_order); case 24: return (image->byte_order == MSBFirst) ^ !is_r8g8b8;
break; default: return FALSE;
case 24:
need_byteswap = (image->byte_order == MSBFirst) ^ !is_r8g8b8;
break;
default:
need_byteswap = FALSE;
break;
} }
}
src = src_bits->ptr; /* copy image bits with byte swapping and/or pixel mapping */
if (info->bmiHeader.biHeight > 0) static void copy_image_byteswap( BITMAPINFO *info, const unsigned char *src, unsigned char *dst,
src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes; int src_stride, int dst_stride, int height,
else BOOL byteswap, const int *mapping, unsigned int zeropad_mask )
src += coords->visrect.top * width_bytes; {
int x, y, padding_pos = abs(dst_stride) / sizeof(unsigned int) - 1;
if ((need_byteswap && !src_bits->is_copy) || /* need to swap bytes */ if (!byteswap && !mapping) /* simply copy */
(zeropad_mask != ~0u && !src_bits->is_copy) || /* need to clear padding bytes */
(mapping && !src_bits->is_copy) || /* need to remap pixels */
(width_bytes & 3) || /* need to fixup line alignment */
(info->bmiHeader.biHeight > 0)) /* need to flip vertically */
{ {
width_bytes = (width_bytes + 3) & ~3; if (src != dst)
info->bmiHeader.biSizeImage = height * width_bytes;
if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
return ERROR_OUTOFMEMORY;
dst_bits->is_copy = TRUE;
dst_bits->free = free_heap_bits;
}
else
{ {
/* swap bits in place */ for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
dst_bits->ptr = src; {
dst_bits->is_copy = src_bits->is_copy; memcpy( dst, src, src_stride );
dst_bits->free = NULL; ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS; /* nothing to do */
} }
}
dst = dst_bits->ptr; else if (zeropad_mask != ~0u) /* only need to clear the padding */
padding_pos = width_bytes/sizeof(unsigned int) - 1;
if (info->bmiHeader.biHeight > 0)
{ {
dst += (height - 1) * width_bytes; for (y = 0; y < height; y++, dst += dst_stride)
width_bytes = -width_bytes; ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
}
return;
} }
if (need_byteswap || mapping)
{
switch (info->bmiHeader.biBitCount) switch (info->bmiHeader.biBitCount)
{ {
case 1: case 1:
for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes) for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
{ {
for (x = 0; x < image->bytes_per_line; x++) for (x = 0; x < src_stride; x++) dst[x] = bit_swap[src[x]];
dst[x] = bit_swap[src[x]];
((unsigned int *)dst)[padding_pos] &= zeropad_mask; ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
} }
break; break;
case 4: case 4:
for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes) for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
{ {
if (mapping) if (mapping)
for (x = 0; x < image->bytes_per_line; x++) {
if (byteswap)
for (x = 0; x < src_stride; x++)
dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4]; dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
else else
for (x = 0; x < image->bytes_per_line; x++) for (x = 0; x < src_stride; x++)
dst[x] = mapping[src[x] & 0x0f] | (mapping[src[x] >> 4] << 4);
}
else
for (x = 0; x < src_stride; x++)
dst[x] = (src[x] << 4) | (src[x] >> 4); dst[x] = (src[x] << 4) | (src[x] >> 4);
((unsigned int *)dst)[padding_pos] &= zeropad_mask; ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
} }
break; break;
case 8: case 8:
for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes) for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
{ {
for (x = 0; x < image->bytes_per_line; x++) for (x = 0; x < src_stride; x++) dst[x] = mapping[src[x]];
dst[x] = mapping[src[x]];
((unsigned int *)dst)[padding_pos] &= zeropad_mask; ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
} }
break; break;
case 16: case 16:
for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes) for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
{ {
for (x = 0; x < info->bmiHeader.biWidth; x++) for (x = 0; x < info->bmiHeader.biWidth; x++)
((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] ); ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
...@@ -1150,7 +1123,7 @@ DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, ...@@ -1150,7 +1123,7 @@ DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
} }
break; break;
case 24: case 24:
for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes) for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
{ {
for (x = 0; x < info->bmiHeader.biWidth; x++) for (x = 0; x < info->bmiHeader.biWidth; x++)
{ {
...@@ -1163,25 +1136,61 @@ DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, ...@@ -1163,25 +1136,61 @@ DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
} }
break; break;
case 32: case 32:
for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes) for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
for (x = 0; x < info->bmiHeader.biWidth; x++) for (x = 0; x < info->bmiHeader.biWidth; x++)
((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] ); ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
break; break;
} }
} }
else if (src != dst)
{ /* copy the image bits, fixing up alignment and byte swapping as necessary */
for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes) DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
{
BOOL need_byteswap = image_needs_byteswap( image, is_r8g8b8, info->bmiHeader.biBitCount );
int height = coords->visrect.bottom - coords->visrect.top;
int width_bytes = image->bytes_per_line;
unsigned char *src, *dst;
src = src_bits->ptr;
if (info->bmiHeader.biHeight > 0)
src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
else
src += coords->visrect.top * width_bytes;
if ((need_byteswap && !src_bits->is_copy) || /* need to swap bytes */
(zeropad_mask != ~0u && !src_bits->is_copy) || /* need to clear padding bytes */
(mapping && !src_bits->is_copy) || /* need to remap pixels */
(width_bytes & 3) || /* need to fixup line alignment */
(info->bmiHeader.biHeight > 0)) /* need to flip vertically */
{ {
memcpy( dst, src, image->bytes_per_line ); width_bytes = (width_bytes + 3) & ~3;
((unsigned int *)dst)[padding_pos] &= zeropad_mask; info->bmiHeader.biSizeImage = height * width_bytes;
if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
return ERROR_OUTOFMEMORY;
dst_bits->is_copy = TRUE;
dst_bits->free = free_heap_bits;
} }
else
{
/* swap bits in place */
dst_bits->ptr = src;
dst_bits->is_copy = src_bits->is_copy;
dst_bits->free = NULL;
if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS; /* nothing to do */
} }
else /* only need to clear the padding */
dst = dst_bits->ptr;
if (info->bmiHeader.biHeight > 0)
{ {
for (y = 0; y < height; y++, dst += width_bytes) dst += (height - 1) * width_bytes;
((unsigned int *)dst)[padding_pos] &= zeropad_mask; width_bytes = -width_bytes;
} }
copy_image_byteswap( info, src, dst, image->bytes_per_line, width_bytes, height,
need_byteswap, mapping, zeropad_mask );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment