git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@308 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Jay Sorg 2003-02-04 05:32:13 +00:00
parent b417d5ed8a
commit 4b26f4fc6b
9 changed files with 310 additions and 30 deletions

221
bitmap.c
View File

@ -21,6 +21,7 @@
#include "rdesktop.h"
#define CVAL(p) (*(p++))
#define CVAL16(p) (*(((uint16*)p)++))
#define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
@ -43,7 +44,7 @@
}
BOOL
bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size)
bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *input, int size)
{
unsigned char *end = input + size;
unsigned char *prevline = NULL, *line = NULL;
@ -246,3 +247,221 @@ bitmap_decompress(unsigned char *output, int width, int height, unsigned char *i
return True;
}
BOOL
bitmap_decompress16(unsigned char *output, int width, int height, unsigned char *input, int size)
{
unsigned char *end = input + size;
uint16 *prevline = NULL, *line = NULL;
int opcode, count, offset, isfillormix, x = width;
int lastopcode = -1, insertmix = False, bicolour = False;
uint8 code;
uint16 colour1 = 0, colour2 = 0;
uint8 mixmask, mask = 0;
uint16 mix = 0xffff;
int fom_mask = 0;
while (input < end)
{
fom_mask = 0;
code = CVAL(input);
opcode = code >> 4;
/* Handle different opcode forms */
switch (opcode)
{
case 0xc:
case 0xd:
case 0xe:
opcode -= 6;
count = code & 0xf;
offset = 16;
break;
case 0xf:
opcode = code & 0xf;
if (opcode < 9)
{
count = CVAL(input);
count |= CVAL(input) << 8;
}
else
{
count = (opcode < 0xd) ? 8 : 1; // was 0xb in 8 bit
}
offset = 0;
break;
default:
opcode >>= 1;
count = code & 0x1f;
offset = 32;
break;
}
/* Handle strange cases for counts */
if (offset != 0)
{
isfillormix = ((opcode == 2) || (opcode == 7));
if (count == 0)
{
if (isfillormix)
count = CVAL(input) + 1;
else
count = CVAL(input) + offset;
}
else if (isfillormix)
{
count <<= 3;
}
}
/* Read preliminary data */
switch (opcode)
{
case 0: /* Fill */
if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
insertmix = True;
break;
case 8: /* Bicolour */
colour1 = CVAL16(input);
case 3: /* Colour */
colour2 = CVAL16(input);
break;
case 6: /* SetMix/Mix */
case 7: /* SetMix/FillOrMix */
mix = CVAL16(input);
opcode -= 5;
break;
case 9: /* FillOrMix_1 */
mask = 0x03;
opcode = 0x02;
fom_mask = 3;
break;
case 0x0a: /* FillOrMix_2 */
mask = 0x05;
opcode = 0x02;
fom_mask = 5;
break;
}
lastopcode = opcode;
mixmask = 0;
/* Output body */
while (count > 0)
{
if (x >= width)
{
if (height <= 0)
return False;
x = 0;
height--;
prevline = line;
line = (uint16*)output + height * width;
}
switch (opcode)
{
case 0: /* Fill */
if (insertmix)
{
if (prevline == NULL)
line[x] = mix;
else
line[x] = prevline[x] ^ mix;
insertmix = False;
count--;
x++;
}
if (prevline == NULL)
{
REPEAT(line[x] = 0);
}
else
{
REPEAT(line[x] = prevline[x]);
}
break;
case 1: /* Mix */
if (prevline == NULL)
{
REPEAT(line[x] = mix);
}
else
{
REPEAT(line[x] = prevline[x] ^ mix);
}
break;
case 2: /* Fill or Mix */
if (prevline == NULL)
{
REPEAT(MASK_UPDATE();
if (mask & mixmask) line[x] = mix;
else
line[x] = 0;);
}
else
{
REPEAT(MASK_UPDATE();
if (mask & mixmask)
line[x] = prevline[x] ^ mix;
else
line[x] = prevline[x];);
}
break;
case 3: /* Colour */
REPEAT(line[x] = colour2);
break;
case 4: /* Copy */
REPEAT(line[x] = CVAL16(input));
break;
case 8: /* Bicolour */
REPEAT(if (bicolour)
{
line[x] = colour2; bicolour = False;}
else
{
line[x] = colour1; bicolour = True; count++;}
);
break;
case 0xd: /* White */
REPEAT(line[x] = 0xffff);
break;
case 0xe: /* Black */
REPEAT(line[x] = 0x00);
break;
default:
unimpl("bitmap opcode 0x%x\n", opcode);
return False;
}
}
}
return True;
}
BOOL
bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, int bpp)
{
if (bpp == 8)
return bitmap_decompress8(output, width, height, input, size);
else if (bpp == 16)
return bitmap_decompress16(output, width, height, input, size);
else
return False;
}

View File

@ -71,10 +71,15 @@ rdp_in_coord(STREAM s, uint16 * coord, BOOL delta)
/* Read a colour entry */
static void
rdp_in_colour(STREAM s, uint8 * colour)
rdp_in_colour(STREAM s, uint32 * colour)
{
in_uint8(s, *colour);
s->p += 2;
uint32 i;
in_uint8(s, i);
*colour = i;
in_uint8(s, i);
*colour |= i << 8;
in_uint8(s, i);
*colour |= i << 16;
}
/* Parse bounds information */
@ -279,6 +284,7 @@ process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta)
static void
process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta)
{
uint32 i;
if (present & 0x01)
rdp_in_coord(s, &os->x, delta);
@ -292,7 +298,22 @@ process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta)
rdp_in_coord(s, &os->cy, delta);
if (present & 0x10)
in_uint8(s, os->colour);
{
in_uint8(s, i);
os->colour = (os->colour & 0xffffff00) | i;
}
if (present & 0x20)
{
in_uint8(s, i);
os->colour = (os->colour & 0xffff00ff) | (i << 8);
}
if (present & 0x40)
{
in_uint8(s, i);
os->colour = (os->colour & 0xff00ffff) | (i << 16);
}
DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour));
@ -632,6 +653,8 @@ process_raw_bmpcache(STREAM s)
in_uint16_le(s, bufsize);
in_uint16_le(s, cache_idx);
in_uint8p(s, data, bufsize);
if (bpp != 8) /* todo */
return;
DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
inverted = xmalloc(width * height);
@ -665,12 +688,14 @@ process_bmpcache(STREAM s)
in_uint16_le(s, size);
in_uint8s(s, 4); /* row_size, final_size */
in_uint8p(s, data, size);
if (bpp != 8) /* todo */
return;
DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
bmpdata = xmalloc(width * height);
if (bitmap_decompress(bmpdata, width, height, data, size))
if (bitmap_decompress(bmpdata, width, height, data, size, bpp))
{
bitmap = ui_create_bitmap(width, height, bmpdata);
cache_put_bitmap(cache_id, cache_idx, bitmap);

View File

@ -67,8 +67,8 @@ typedef struct _PATBLT_ORDER
uint16 cx;
uint16 cy;
uint8 opcode;
uint8 bgcolour;
uint8 fgcolour;
uint32 bgcolour;
uint32 fgcolour;
BRUSH brush;
}
@ -94,7 +94,7 @@ typedef struct _LINE_ORDER
uint16 starty;
uint16 endx;
uint16 endy;
uint8 bgcolour;
uint32 bgcolour;
uint8 opcode;
PEN pen;
@ -107,7 +107,7 @@ typedef struct _RECT_ORDER
uint16 y;
uint16 cx;
uint16 cy;
uint8 colour;
uint32 colour;
}
RECT_ORDER;
@ -135,8 +135,8 @@ typedef struct _TRIBLT_ORDER
uint8 opcode;
uint16 srcx;
uint16 srcy;
uint8 bgcolour;
uint8 fgcolour;
uint32 bgcolour;
uint32 fgcolour;
BRUSH brush;
uint16 cache_idx;
uint16 unknown;
@ -167,7 +167,7 @@ typedef struct _POLYLINE_ORDER
uint16 x;
uint16 y;
uint8 opcode;
uint8 fgcolour;
uint32 fgcolour;
uint8 lines;
uint8 datasize;
uint8 data[MAX_DATA];
@ -183,8 +183,8 @@ typedef struct _TEXT2_ORDER
uint8 flags;
uint8 mixmode;
uint8 unknown;
uint8 fgcolour;
uint8 bgcolour;
uint32 fgcolour;
uint32 bgcolour;
uint16 clipleft;
uint16 cliptop;
uint16 clipright;

View File

@ -1,6 +1,6 @@
/* bitmap.c */
BOOL bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input,
int size);
int size, int bpp);
/* cache.c */
HBITMAP cache_get_bitmap(uint8 cache_id, uint16 cache_idx);
void cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap);

View File

@ -49,6 +49,7 @@ int width = 800; /* If width or height are reset to zero, the geometry will
be fetched from _NET_WORKAREA */
int height = 600;
int tcp_port_rdp = TCP_PORT_RDP;
int server_bpp = 8;
BOOL bitmap_compression = True;
BOOL sendmotion = True;
BOOL orders = True;
@ -84,6 +85,7 @@ usage(char *program)
fprintf(stderr, " -K: keep window manager key bindings\n");
fprintf(stderr, " -T: window title\n");
fprintf(stderr, " -D: hide window manager decorations\n");
fprintf(stderr, " -a: server bpp\n");
}
static BOOL
@ -144,7 +146,7 @@ main(int argc, char *argv[])
domain[0] = password[0] = shell[0] = directory[0] = 0;
strcpy(keymapname, "en-us");
while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:fbemCKT:Dh?")) != -1)
while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:a:fbemCKT:Dh?")) != -1)
{
switch (c)
{
@ -239,6 +241,15 @@ main(int argc, char *argv[])
hide_decorations = True;
break;
case 'a':
server_bpp = strtol(optarg, NULL, 10);
if (server_bpp != 8 && server_bpp != 16)
{
error("invalid server bpp\n");
return 1;
}
break;
case 'h':
case '?':
default:

10
rdp.c
View File

@ -579,10 +579,10 @@ process_bitmap_updates(STREAM s)
if (!compress)
{
int y;
bmpdata = xmalloc(width * height);
bmpdata = xmalloc(width * height * (bpp / 8));
for (y = 0; y < height; y++)
{
in_uint8a(s, &bmpdata[(height - y - 1) * width], width);
in_uint8a(s, &bmpdata[(height - y - 1) * (width * (bpp / 8))], width * (bpp / 8));
}
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
xfree(bmpdata);
@ -593,13 +593,11 @@ process_bitmap_updates(STREAM s)
in_uint16_le(s, size);
in_uint8s(s, 4); /* line_size, final_size */
in_uint8p(s, data, size);
bmpdata = xmalloc(width * height);
if (bitmap_decompress(bmpdata, width, height, data, size))
bmpdata = xmalloc(width * height * (bpp / 8));
if (bitmap_decompress(bmpdata, width, height, data, size, bpp))
{
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
}
xfree(bmpdata);
}
}

View File

@ -38,6 +38,7 @@ extern int height;
extern int keylayout;
extern BOOL encryption;
extern BOOL licence_issued;
extern int server_bpp;
static int rc4_key_len;
static RC4_KEY rc4_decrypt_key;
@ -425,7 +426,14 @@ sec_out_mcs_data(STREAM s)
out_uint32_le(s, 12);
out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
out_uint16_le(s, 0xca01);
if (server_bpp == 16)
{
out_uint16_le(s, 0xca03); /* 16 bit */
}
else
{
out_uint16_le(s, 0xca01); /* 8 bit */
}
out_uint16(s, 0);
/* Client encryption settings */

View File

@ -68,7 +68,7 @@ typedef struct _PEN
{
uint8 style;
uint8 width;
uint8 colour;
uint32 colour;
}
PEN;

21
xwin.c
View File

@ -31,6 +31,7 @@ extern BOOL fullscreen;
extern BOOL grab_keyboard;
extern BOOL hide_decorations;
extern char title[];
extern int server_bpp;
BOOL enable_compose = False;
BOOL focused;
BOOL mouse_in_wnd;
@ -88,7 +89,7 @@ BOOL owncolmap = False;
static Colormap xcolmap;
static uint32 *colmap;
#define TRANSLATE(col) ( owncolmap ? col : translate_colour(colmap[col]) )
#define TRANSLATE(col) ( server_bpp != 8 ? col : owncolmap ? col : translate_colour(colmap[col]) )
#define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
#define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
@ -749,6 +750,24 @@ ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * dat
XImage *image;
uint8 *tdata;
if (server_bpp == 16)
{
image = XCreateImage(display, visual, depth, ZPixmap, 0,
(char *) data, width, height, 16, 0);
if (ownbackstore)
{
XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
}
else
{
XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
}
XFree(image);
return;
}
tdata = (owncolmap ? data : translate_image(width, height, data));
image = XCreateImage(display, visual, depth, ZPixmap, 0,
(char *) tdata, width, height, 8, 0);