diff --git a/cache.c b/cache.c index 3eeea53..9e3fec2 100644 --- a/cache.c +++ b/cache.c @@ -430,3 +430,32 @@ cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor) error("put cursor %d\n", cache_idx); } } + +/* BRUSH CACHE */ +static BRUSHDATA g_brushcache[64]; + +/* Retrieve brush from cache */ +BRUSHDATA * +cache_get_brush_data(uint16 cache_idx) +{ + if (cache_idx < NUM_ELEMENTS(g_brushcache)) + { + return &g_brushcache[cache_idx]; + } + error("get brush %d\n", cache_idx); + return NULL; +} + +/* Store brush in cache */ +void +cache_put_brush_data(uint16 cache_idx, BRUSHDATA * brush_data) +{ + if (cache_idx < NUM_ELEMENTS(g_brushcache)) + { + memcpy(&g_brushcache[cache_idx], brush_data, sizeof(BRUSHDATA)); + } + else + { + error("put brush %d\n", cache_idx); + } +} diff --git a/constants.h b/constants.h index 074a378..b2a25d6 100644 --- a/constants.h +++ b/constants.h @@ -251,6 +251,9 @@ enum RDP_INPUT_DEVICE #define RDP_CAPSET_COLCACHE 10 #define RDP_CAPLEN_COLCACHE 0x08 +#define RDP_CAPSET_BRUSHCACHE 15 +#define RDP_CAPLEN_BRUSHCACHE 0x08 + #define RDP_CAPSET_BMPCACHE2 19 #define RDP_CAPLEN_BMPCACHE2 0x28 #define BMPCACHE2_FLAG_PERSIST ((uint32)1<<31) diff --git a/orders.c b/orders.c index 8225f99..2a9d4a0 100644 --- a/orders.c +++ b/orders.c @@ -148,6 +148,39 @@ rdp_parse_pen(STREAM s, PEN * pen, uint32 present) return s_check(s); } +static void +setup_brush(BRUSH * out_brush, BRUSH * in_brush) +{ + BRUSHDATA * brush_data; + uint16 cache_idx; + uint8 brush_bpp; + + memcpy(out_brush, in_brush, sizeof(BRUSH)); + if (out_brush->style & 0x80) + { + brush_bpp = out_brush->style & 0x0f; + if (brush_bpp == 1) /* 1 bpp */ + { + cache_idx = out_brush->pattern[0]; + brush_data = cache_get_brush_data(cache_idx); + if (brush_data == NULL) + { + error("error getting brush data, style %x\n", out_brush->style); + } + else + { + memcpy(out_brush->pattern, brush_data->pattern, + sizeof(out_brush->pattern)); + } + } + else + { + error("bad brush bpp %d\n", brush_bpp); + } + out_brush->style = 3; + } +} + /* Parse a brush */ static RD_BOOL rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present) @@ -199,6 +232,8 @@ process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, RD_BOOL delta) static void process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, RD_BOOL delta) { + BRUSH brush; + if (present & 0x0001) rdp_in_coord(s, &os->x, delta); @@ -225,8 +260,10 @@ process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, RD_BOOL delta) DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os->opcode, os->x, os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour)); + setup_brush(&brush, &os->brush); + ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy, - &os->brush, os->bgcolour, os->fgcolour); + &brush, os->bgcolour, os->fgcolour); } /* Process a screen blt order */ @@ -426,6 +463,7 @@ static void process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, RD_BOOL delta) { RD_HBITMAP bitmap; + BRUSH brush; if (present & 0x000001) { @@ -476,8 +514,10 @@ process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, RD_BOOL delta) if (bitmap == NULL) return; + setup_brush(&brush, &os->brush); + ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy, - bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour); + bitmap, os->srcx, os->srcy, &brush, os->bgcolour, os->fgcolour); } /* Process a polygon order */ @@ -566,6 +606,7 @@ process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, RD_BOOL delta) int index, data, next; uint8 flags = 0; RD_POINT *points; + BRUSH brush; if (present & 0x0001) rdp_in_coord(s, &os->x, delta); @@ -613,6 +654,8 @@ process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, RD_BOOL delta) return; } + setup_brush(&brush, &os->brush); + points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT)); memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT)); @@ -637,7 +680,7 @@ process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, RD_BOOL delta) if (next - 1 == os->npoints) ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1, - &os->brush, os->bgcolour, os->fgcolour); + &brush, os->bgcolour, os->fgcolour); else error("polygon2 parse error\n"); @@ -758,6 +801,8 @@ process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, RD_BOOL delta) static void process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, RD_BOOL delta) { + BRUSH brush; + if (present & 0x0001) rdp_in_coord(s, &os->left, delta); @@ -788,8 +833,10 @@ process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, RD_BOOL delta) os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style, os->bgcolour, os->fgcolour)); + setup_brush(&brush, &os->brush); + ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left, - os->bottom - os->top, &os->brush, os->bgcolour, os->fgcolour); + os->bottom - os->top, &brush, os->bgcolour, os->fgcolour); } /* Process a text order */ @@ -797,6 +844,7 @@ static void process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, RD_BOOL delta) { int i; + BRUSH brush; if (present & 0x000001) in_uint8(s, os->font); @@ -863,11 +911,13 @@ process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, RD_BOOL delta) DEBUG(("\n")); + setup_brush(&brush, &os->brush); + ui_draw_text(os->font, os->flags, os->opcode - 1, os->mixmode, os->x, os->y, os->clipleft, os->cliptop, os->clipright - os->clipleft, os->clipbottom - os->cliptop, os->boxleft, os->boxtop, os->boxright - os->boxleft, os->boxbottom - os->boxtop, - &os->brush, os->bgcolour, os->fgcolour, os->text, os->length); + &brush, os->bgcolour, os->fgcolour, os->text, os->length); } /* Process a raw bitmap cache order */ @@ -1104,6 +1154,34 @@ process_fontcache(STREAM s) } } +/* Process a brush cache order */ +static void +process_brushcache(STREAM s, uint16 flags) +{ + BRUSHDATA brush_data; + uint8 cache_idx, depth, width, height, size; + + in_uint8(s, cache_idx); + in_uint8(s, depth); + in_uint8(s, width); + in_uint8(s, height); + in_uint8s(s, 1); /* type, 0x80 = cached */ + in_uint8(s, size); + + DEBUG(("BRUSHCACHE(idx=%d,dp=%d,wd=%d,ht=%d,sz=%d)\n", cache_idx, depth, + width, height, size)); + + if ((depth == 1) && (width == 8) && (height == 8) && (size == 8)) + { + in_uint8a(s, brush_data.pattern, sizeof(brush_data.pattern)); + cache_put_brush_data(cache_idx, &brush_data); + } + else + { + warning("ignoring incompatible brush type. display may be incorrect\n"); + } +} + /* Process a secondary order */ static void process_secondary_order(STREAM s) @@ -1148,6 +1226,10 @@ process_secondary_order(STREAM s) process_bmpcache2(s, flags, True); /* compressed */ break; + case RDP_ORDER_BRUSHCACHE: + process_brushcache(s, flags); + break; + default: unimpl("secondary order %d\n", type); } diff --git a/proto.h b/proto.h index c277b49..70f2d5d 100644 --- a/proto.h +++ b/proto.h @@ -44,6 +44,8 @@ void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_pe uint8 * data); RD_HCURSOR cache_get_cursor(uint16 cache_idx); void cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor); +BRUSHDATA * cache_get_brush_data(uint16 cache_idx); +void cache_put_brush_data(uint16 cache_idx, BRUSHDATA * brush_data); /* channels.c */ VCHANNEL *channel_register(char *name, uint32 flags, void (*callback) (STREAM)); STREAM channel_init(VCHANNEL * channel, uint32 length); diff --git a/rdp.c b/rdp.c index 7809548..a21b27f 100644 --- a/rdp.c +++ b/rdp.c @@ -800,6 +800,15 @@ rdp_out_colcache_caps(STREAM s) out_uint16(s, 0); /* pad */ } +/* Output brush cache capability set */ +static void +rdp_out_brushcache_caps(STREAM s) +{ + out_uint16_le(s, RDP_CAPSET_BRUSHCACHE); + out_uint16_le(s, RDP_CAPLEN_BRUSHCACHE); + out_uint32_le(s, 1); /* cache type */ +} + static uint8 caps_0x0d[] = { 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -848,7 +857,7 @@ rdp_send_confirm_active(void) RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL + - RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_BRUSHCACHE + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ + 4 /* w2k fix, why? */ ; @@ -876,6 +885,7 @@ rdp_send_confirm_active(void) rdp_out_control_caps(s); rdp_out_pointer_caps(s); rdp_out_share_caps(s); + rdp_out_brushcache_caps(s); rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */ rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c); diff --git a/types.h b/types.h index 837f48d..d1dc2b1 100644 --- a/types.h +++ b/types.h @@ -79,6 +79,13 @@ typedef struct _PEN } PEN; +/* this is whats in the brush cache */ +typedef struct _BRUSHDATA +{ + uint8 pattern[8]; +} +BRUSHDATA; + typedef struct _BRUSH { uint8 xorigin;