Commit c8f3fed5 authored by Alexandre Julliard's avatar Alexandre Julliard

Ignore RLE data that goes past the line end (found by Uwe Bonnes).

General cleanup of the RLE routines.
parent 76598823
...@@ -67,6 +67,13 @@ typedef struct ...@@ -67,6 +67,13 @@ typedef struct
} X11DRV_DIB_IMAGEBITS_DESCR; } X11DRV_DIB_IMAGEBITS_DESCR;
enum Rle_EscapeCodes
{
RLE_EOL = 0, /* End of line */
RLE_END = 1, /* End of bitmap */
RLE_DELTA = 2 /* Delta */
};
/*********************************************************************** /***********************************************************************
* X11DRV_DIB_GetXImageWidthBytes * X11DRV_DIB_GetXImageWidthBytes
* *
...@@ -855,70 +862,44 @@ static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits, ...@@ -855,70 +862,44 @@ static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
int left, int *colors, int left, int *colors,
XImage *bmpImage ) XImage *bmpImage )
{ {
int x = 0, c, length; int x = 0, y = lines - 1, c, length;
const BYTE *begin = bits; const BYTE *begin = bits;
lines--; while (y >= 0)
{
while ((int)lines >= 0) {
length = *bits++; length = *bits++;
if (length) { /* encoded */ if (length) { /* encoded */
c = *bits++; c = *bits++;
while (length--) { while (length--) {
if(x >= width) { if (x >= width) break;
x = 0; XPutPixel(bmpImage, x++, y, colors[c >> 4]);
if(--lines < 0) if (!length--) break;
return; if (x >= width) break;
} XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
XPutPixel(bmpImage, x++, lines, colors[c >>4]);
if (length) {
length--;
if(x >= width) {
x = 0;
if(--lines < 0)
return;
}
XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
}
} }
} else { } else {
length = *bits++; length = *bits++;
switch (length) { switch (length)
case 0: /* eol */ {
x = 0; case RLE_EOL:
lines--; x = 0;
continue; y--;
break;
case 1: /* eopicture */ case RLE_END:
return; return;
case 2: /* delta */ case RLE_DELTA:
x += *bits++; x += *bits++;
if(x >= width) { y -= *bits++;
FIXME_(x11drv)("x-delta is too large?\n"); break;
return;
}
lines -= *bits++;
continue;
default: /* absolute */ default: /* absolute */
while (length--) { while (length--) {
c = *bits++; c = *bits++;
if(x >= width) { if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
x = 0; if (!length--) break;
if(--lines < 0) if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
return;
}
XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
if (length) {
length--;
if(x >= width) {
x = 0;
if(--lines < 0)
return;
}
XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
}
} }
if ((bits - begin) & 1) if ((bits - begin) & 1)
bits++; bits++;
...@@ -1272,172 +1253,99 @@ static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits, ...@@ -1272,172 +1253,99 @@ static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
* James A. Youngman <mbcstjy@afs.man.ac.uk> * James A. Youngman <mbcstjy@afs.man.ac.uk>
* [JAY] * [JAY]
*/ */
enum Rle8_EscapeCodes
{
/*
* Apologies for polluting your file's namespace...
*/
RleEol = 0, /* End of line */
RleEnd = 1, /* End of bitmap */
RleDelta = 2 /* Delta */
};
static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits, static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
DWORD width, DWORD dstwidth, DWORD width, DWORD dstwidth,
int left, int *colors, int left, int *colors,
XImage *bmpImage ) XImage *bmpImage )
{ {
int x; /* X-positon on each line. Increases. */ int x; /* X-positon on each line. Increases. */
int line; /* Line #. Starts at lines-1, decreases */ int y; /* Line #. Starts at lines-1, decreases */
const BYTE *pIn = bits; /* Pointer to current position in bits */ const BYTE *pIn = bits; /* Pointer to current position in bits */
BYTE length; /* The length pf a run */ BYTE length; /* The length pf a run */
BYTE color_index; /* index into colors[] as read from bits */
BYTE escape_code; /* See enum Rle8_EscapeCodes.*/ BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
int color; /* value of colour[color_index] */
if (lines == 0) /* Let's hope this doesn't happen. */
return;
/* /*
* Note that the bitmap data is stored by Windows starting at the * Note that the bitmap data is stored by Windows starting at the
* bottom line of the bitmap and going upwards. Within each line, * bottom line of the bitmap and going upwards. Within each line,
* the data is stored left-to-right. That's the reason why line * the data is stored left-to-right. That's the reason why line
* goes from lines-1 to 0. [JAY] * goes from lines-1 to 0. [JAY]
*/ */
x = 0; x = 0;
line = lines-1; y = lines - 1;
do while (y >= 0)
{ {
length = *pIn++; length = *pIn++;
/* /*
* If the length byte is not zero (which is the escape value), * If the length byte is not zero (which is the escape value),
* We have a run of length pixels all the same colour. The colour * We have a run of length pixels all the same colour. The colour
* index is stored next. * index is stored next.
* *
* If the length byte is zero, we need to read the next byte to * If the length byte is zero, we need to read the next byte to
* know what to do. [JAY] * know what to do. [JAY]
*/ */
if (length != 0) if (length != 0)
{ {
/* /*
* [Run-Length] Encoded mode * [Run-Length] Encoded mode
*/ */
color_index = (*pIn++); /* Get the colour index. */ int color = colors[*pIn++];
color = colors[color_index]; while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
}
while(length--) else
{ {
if (x>=dstwidth) /*
{ * Escape codes (may be an absolute sequence though)
x=0; */
line--; escape_code = (*pIn++);
} switch(escape_code)
XPutPixel(bmpImage, x++, line, color); {
} case RLE_EOL:
} x = 0;
else y--;
{ break;
/*
* Escape codes (may be an absolute sequence though) case RLE_END:
*/ /* Not all RLE8 bitmaps end with this code. For
escape_code = (*pIn++); * example, Paint Shop Pro produces some that don't.
switch(escape_code) * That's (I think) what caused the previous
{ * implementation to fail. [JAY]
case RleEol: /* =0, end of line */ */
{ return;
x = 0;
line--; case RLE_DELTA:
break; x += (*pIn++);
} y -= (*pIn++);
break;
case RleEnd: /* =1, end of bitmap */
{ default: /* switch to absolute mode */
/* length = escape_code;
* Not all RLE8 bitmaps end with this while (length--)
* code. For example, Paint Shop Pro {
* produces some that don't. That's (I think) int color = colors[*pIn++];
* what caused the previous implementation to if (x >= dstwidth)
* fail. [JAY] {
*/ pIn += length;
line=-1; /* Cause exit from do loop. */ break;
break; }
} XPutPixel(bmpImage, x++, y, color);
}
case RleDelta: /* =2, a delta */ /*
{ * If you think for a moment you'll realise that the
/* * only time we could ever possibly read an odd
* Note that deltaing to line 0 * number of bytes is when there is a 0x00 (escape),
* will cause an exit from the loop, * a value >0x02 (absolute mode) and then an odd-
* which may not be what is intended. * length run. Therefore this is the only place we
* The fact that there is a delta in the bits * need to worry about it. Everywhere else the
* almost certainly implies that there is data * bytes are always read in pairs. [JAY]
* to follow. You may feel that we should */
* jump to the top of the loop to avoid exiting if (escape_code & 1) pIn++; /* Throw away the pad byte. */
* in this case. break;
* } /* switch (escape_code) : Escape sequence */
* TODO: Decide what to do here in that case. [JAY] }
*/ }
x += (*pIn++); }
line -= (*pIn++);
if (line == 0)
{
TRACE("Delta to last line of bitmap "
"(wrongly?) causes loop exit\n");
}
break;
}
default: /* >2, switch to absolute mode */
{
/*
* Absolute Mode
*/
length = escape_code;
while(length--)
{
color_index = (*pIn++);
if (x>=dstwidth)
{
x=0;
line--;
}
XPutPixel(bmpImage, x++, line,
colors[color_index]);
}
/*
* If you think for a moment you'll realise that the
* only time we could ever possibly read an odd
* number of bytes is when there is a 0x00 (escape),
* a value >0x02 (absolute mode) and then an odd-
* length run. Therefore this is the only place we
* need to worry about it. Everywhere else the
* bytes are always read in pairs. [JAY]
*/
if (escape_code & 1)
pIn++; /* Throw away the pad byte. */
break;
}
} /* switch (escape_code) : Escape sequence */
} /* process either an encoded sequence or an escape sequence */
/* We expect to come here more than once per line. */
} while (line >= 0); /* Do this until the bitmap is filled */
/*
* Everybody comes here at the end.
* Check how we exited the loop and print a message if it's a bit odd.
* [JAY]
*/
if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
{
TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
"bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
}
}
/*********************************************************************** /***********************************************************************
......
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