Add support for ellipse and polygon orders

git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@830 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Jeroen Meijer 2005-03-08 00:43:10 +00:00
parent a78d2b3ec9
commit f589939e23
7 changed files with 504 additions and 13 deletions

View File

@ -200,6 +200,9 @@ enum RDP_INPUT_DEVICE
#define TEXT2_VERTICAL 0x04
#define TEXT2_IMPLICIT_X 0x20
#define ALTERNATE 1
#define WINDING 2
/* RDP bitmap cache (version 2) constants */
#define BMPCACHE2_C0_CELLS 0x78
#define BMPCACHE2_C1_CELLS 0x78

274
orders.c
View File

@ -70,6 +70,24 @@ rdp_in_coord(STREAM s, sint16 * coord, BOOL delta)
}
}
/* Parse a delta co-ordinate in polyline/polygon order form */
static int
parse_delta(uint8 * buffer, int *offset)
{
int value = buffer[(*offset)++];
int two_byte = value & 0x80;
if (value & 0x40) /* sign bit */
value |= ~0x3f;
else
value &= 0x3f;
if (two_byte)
value = (value << 8) | buffer[(*offset)++];
return value;
}
/* Read a colour entry */
static void
rdp_in_colour(STREAM s, uint32 * colour)
@ -462,22 +480,168 @@ process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta)
bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour);
}
/* Parse a delta co-ordinate in polyline order form */
static int
parse_delta(uint8 * buffer, int *offset)
/* Process a polygon order */
static void
process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, BOOL delta)
{
int value = buffer[(*offset)++];
int two_byte = value & 0x80;
int index, data, next;
uint8 flags = 0;
POINT *points;
if (value & 0x40) /* sign bit */
value |= ~0x3f;
if (present & 0x01)
rdp_in_coord(s, &os->x, delta);
if (present & 0x02)
rdp_in_coord(s, &os->y, delta);
if (present & 0x04)
in_uint8(s, os->opcode);
if (present & 0x08)
in_uint8(s, os->fillmode);
if (present & 0x10)
rdp_in_colour(s, &os->fgcolour);
if (present & 0x20)
in_uint8(s, os->npoints);
if (present & 0x40)
{
in_uint8(s, os->datasize);
in_uint8a(s, os->data, os->datasize);
}
DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
os->x, os->y, os->opcode, os->fillmode, os->fgcolour, os->npoints, os->datasize));
DEBUG(("Data: "));
for (index = 0; index < os->datasize; index++)
DEBUG(("%02x ", os->data[index]));
DEBUG(("\n"));
if (os->opcode < 0x01 || os->opcode > 0x10)
{
error("bad ROP2 0x%x\n", os->opcode);
return;
}
points = (POINT *) xmalloc((os->npoints + 1) * sizeof(POINT));
memset(points, 0, (os->npoints + 1) * sizeof(POINT));
points[0].x = os->x;
points[0].y = os->y;
index = 0;
data = ((os->npoints - 1) / 4) + 1;
for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
{
if ((next - 1) % 4 == 0)
flags = os->data[index++];
if (~flags & 0x80)
points[next].x = parse_delta(os->data, &data);
if (~flags & 0x40)
points[next].y = parse_delta(os->data, &data);
flags <<= 2;
}
if (next - 1 == os->npoints)
ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1, NULL, 0,
os->fgcolour);
else
value &= 0x3f;
error("polygon parse error\n");
if (two_byte)
value = (value << 8) | buffer[(*offset)++];
xfree(points);
}
return value;
/* Process a polygon2 order */
static void
process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, BOOL delta)
{
int index, data, next;
uint8 flags = 0;
POINT *points;
if (present & 0x0001)
rdp_in_coord(s, &os->x, delta);
if (present & 0x0002)
rdp_in_coord(s, &os->y, delta);
if (present & 0x0004)
in_uint8(s, os->opcode);
if (present & 0x0008)
in_uint8(s, os->fillmode);
if (present & 0x0010)
rdp_in_colour(s, &os->bgcolour);
if (present & 0x0020)
rdp_in_colour(s, &os->fgcolour);
rdp_parse_brush(s, &os->brush, present >> 6);
if (present & 0x0800)
in_uint8(s, os->npoints);
if (present & 0x1000)
{
in_uint8(s, os->datasize);
in_uint8a(s, os->data, os->datasize);
}
DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
os->x, os->y, os->opcode, os->fillmode, os->brush.style, os->bgcolour, os->fgcolour,
os->npoints, os->datasize));
DEBUG(("Data: "));
for (index = 0; index < os->datasize; index++)
DEBUG(("%02x ", os->data[index]));
DEBUG(("\n"));
if (os->opcode < 0x01 || os->opcode > 0x10)
{
error("bad ROP2 0x%x\n", os->opcode);
return;
}
points = (POINT *) xmalloc((os->npoints + 1) * sizeof(POINT));
memset(points, 0, (os->npoints + 1) * sizeof(POINT));
points[0].x = os->x;
points[0].y = os->y;
index = 0;
data = ((os->npoints - 1) / 4) + 1;
for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
{
if ((next - 1) % 4 == 0)
flags = os->data[index++];
if (~flags & 0x80)
points[next].x = parse_delta(os->data, &data);
if (~flags & 0x40)
points[next].y = parse_delta(os->data, &data);
flags <<= 2;
}
if (next - 1 == os->npoints)
ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1,
&os->brush, os->bgcolour, os->fgcolour);
else
error("polygon2 parse error\n");
xfree(points);
}
/* Process a polyline order */
@ -558,6 +722,76 @@ process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
}
}
/* Process an ellipse order */
static void
process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, BOOL delta)
{
if (present & 0x01)
rdp_in_coord(s, &os->left, delta);
if (present & 0x02)
rdp_in_coord(s, &os->top, delta);
if (present & 0x04)
rdp_in_coord(s, &os->right, delta);
if (present & 0x08)
rdp_in_coord(s, &os->bottom, delta);
if (present & 0x10)
in_uint8(s, os->opcode);
if (present & 0x20)
in_uint8(s, os->fillmode);
if (present & 0x40)
rdp_in_colour(s, &os->fgcolour);
DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os->left, os->top,
os->right, os->bottom, os->opcode, os->fillmode, os->fgcolour));
ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
os->bottom - os->top, NULL, 0, os->fgcolour);
}
/* Process an ellipse2 order */
static void
process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, BOOL delta)
{
if (present & 0x0001)
rdp_in_coord(s, &os->left, delta);
if (present & 0x0002)
rdp_in_coord(s, &os->top, delta);
if (present & 0x0004)
rdp_in_coord(s, &os->right, delta);
if (present & 0x0008)
rdp_in_coord(s, &os->bottom, delta);
if (present & 0x0010)
in_uint8(s, os->opcode);
if (present & 0x0020)
in_uint8(s, os->fillmode);
if (present & 0x0040)
rdp_in_colour(s, &os->bgcolour);
if (present & 0x0080)
rdp_in_colour(s, &os->fgcolour);
rdp_parse_brush(s, &os->brush, present >> 8);
DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style,
os->bgcolour, os->fgcolour));
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);
}
/* Process a text order */
static void
process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta)
@ -982,6 +1216,8 @@ process_orders(STREAM s, uint16 num_orders)
case RDP_ORDER_PATBLT:
case RDP_ORDER_MEMBLT:
case RDP_ORDER_LINE:
case RDP_ORDER_POLYGON2:
case RDP_ORDER_ELLIPSE2:
size = 2;
break;
@ -1039,10 +1275,26 @@ process_orders(STREAM s, uint16 num_orders)
process_triblt(s, &os->triblt, present, delta);
break;
case RDP_ORDER_POLYGON:
process_polygon(s, &os->polygon, present, delta);
break;
case RDP_ORDER_POLYGON2:
process_polygon2(s, &os->polygon2, present, delta);
break;
case RDP_ORDER_POLYLINE:
process_polyline(s, &os->polyline, present, delta);
break;
case RDP_ORDER_ELLIPSE:
process_ellipse(s, &os->ellipse, present, delta);
break;
case RDP_ORDER_ELLIPSE2:
process_ellipse2(s, &os->ellipse2, present, delta);
break;
case RDP_ORDER_TEXT2:
process_text2(s, &os->text2, present, delta);
break;

View File

@ -37,7 +37,11 @@ enum RDP_ORDER_TYPE
RDP_ORDER_DESKSAVE = 11,
RDP_ORDER_MEMBLT = 13,
RDP_ORDER_TRIBLT = 14,
RDP_ORDER_POLYGON = 20,
RDP_ORDER_POLYGON2 = 21,
RDP_ORDER_POLYLINE = 22,
RDP_ORDER_ELLIPSE = 25,
RDP_ORDER_ELLIPSE2 = 26,
RDP_ORDER_TEXT2 = 27
};
@ -48,7 +52,8 @@ enum RDP_SECONDARY_ORDER_TYPE
RDP_ORDER_BMPCACHE = 2,
RDP_ORDER_FONTCACHE = 3,
RDP_ORDER_RAW_BMPCACHE2 = 4,
RDP_ORDER_BMPCACHE2 = 5
RDP_ORDER_BMPCACHE2 = 5,
RDP_ORDER_BRUSHCACHE = 7
};
typedef struct _DESTBLT_ORDER
@ -164,6 +169,36 @@ MEMBLT_ORDER;
#define MAX_DATA 256
typedef struct _POLYGON_ORDER
{
sint16 x;
sint16 y;
uint8 opcode;
uint8 fillmode;
uint32 fgcolour;
uint8 npoints;
uint8 datasize;
uint8 data[MAX_DATA];
}
POLYGON_ORDER;
typedef struct _POLYGON2_ORDER
{
sint16 x;
sint16 y;
uint8 opcode;
uint8 fillmode;
uint32 bgcolour;
uint32 fgcolour;
BRUSH brush;
uint8 npoints;
uint8 datasize;
uint8 data[MAX_DATA];
}
POLYGON2_ORDER;
typedef struct _POLYLINE_ORDER
{
sint16 x;
@ -177,6 +212,34 @@ typedef struct _POLYLINE_ORDER
}
POLYLINE_ORDER;
typedef struct _ELLIPSE_ORDER
{
sint16 left;
sint16 top;
sint16 right;
sint16 bottom;
uint8 opcode;
uint8 fillmode;
uint32 fgcolour;
}
ELLIPSE_ORDER;
typedef struct _ELLIPSE2_ORDER
{
sint16 left;
sint16 top;
sint16 right;
sint16 bottom;
uint8 opcode;
uint8 fillmode;
BRUSH brush;
uint32 bgcolour;
uint32 fgcolour;
}
ELLIPSE2_ORDER;
#define MAX_TEXT 256
typedef struct _TEXT2_ORDER
@ -216,7 +279,11 @@ typedef struct _RDP_ORDER_STATE
DESKSAVE_ORDER desksave;
MEMBLT_ORDER memblt;
TRIBLT_ORDER triblt;
POLYGON_ORDER polygon;
POLYGON2_ORDER polygon2;
POLYLINE_ORDER polyline;
ELLIPSE_ORDER ellipse;
ELLIPSE2_ORDER ellipse2;
TEXT2_ORDER text2;
}

View File

@ -211,6 +211,10 @@ void ui_triblt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx
BRUSH * brush, int bgcolour, int fgcolour);
void ui_line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen);
void ui_rect(int x, int y, int cx, int cy, int colour);
void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints, BRUSH * brush,
int bgcolour, int fgcolour);
void ui_ellipse(uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, BRUSH * brush,
int bgcolour, int fgcolour);
void ui_draw_glyph(int mixmode, int x, int y, int cx, int cy, HGLYPH glyph, int srcx, int srcy,
int bgcolour, int fgcolour);
void ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y, int clipx, int clipy,

6
rdp.c
View File

@ -495,19 +495,23 @@ rdp_out_order_caps(STREAM s)
{
uint8 order_caps[32];
memset(order_caps, 0, 32);
order_caps[0] = 1; /* dest blt */
order_caps[1] = 1; /* pat blt */
order_caps[2] = 1; /* screen blt */
order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */
order_caps[4] = 0; /* triblt */
order_caps[8] = 1; /* line */
order_caps[9] = 1; /* line */
order_caps[10] = 1; /* rect */
order_caps[11] = (g_desktop_save == False ? 0 : 1); /* desksave */
order_caps[13] = 1; /* memblt */
order_caps[14] = 1; /* triblt */
order_caps[20] = 1; /* polygon */
order_caps[21] = 1; /* polygon2 */
order_caps[22] = 1; /* polyline */
order_caps[25] = 1; /* ellipse */
order_caps[26] = 1; /* ellipse2 */
order_caps[27] = 1; /* text2 */
out_uint16_le(s, RDP_CAPSET_ORDER);
out_uint16_le(s, RDP_CAPLEN_ORDER);

View File

@ -37,6 +37,12 @@ typedef void *HGLYPH;
typedef void *HCOLOURMAP;
typedef void *HCURSOR;
typedef struct _POINT
{
sint16 x, y;
}
POINT;
typedef struct _COLOURENTRY
{
uint8 red;

155
xwin.c
View File

@ -119,6 +119,31 @@ PixelColour;
XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
}
#define FILL_POLYGON(p,np)\
{ \
XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
if (g_ownbackstore) \
XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
}
#define DRAW_ELLIPSE(x,y,cx,cy,m)\
{ \
switch (m) \
{ \
case 0: /* Outline */ \
XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
if (g_ownbackstore) \
XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
break; \
case 1: /* Filled */ \
XFillArc(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, \
cx, cy, 0, 360*64); \
if (g_ownbackstore) \
XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); \
break; \
} \
}
/* colour maps */
extern BOOL g_owncolmap;
static Colormap g_xcolmap;
@ -2166,6 +2191,136 @@ ui_rect(
FILL_RECTANGLE(x, y, cx, cy);
}
void
ui_polygon(uint8 opcode,
/* mode */ uint8 fillmode,
/* dest */ POINT * point, int npoints,
/* brush */ BRUSH * brush, int bgcolour, int fgcolour)
{
uint8 style, i, ipattern[8];
Pixmap fill;
SET_FUNCTION(opcode);
switch (fillmode)
{
case ALTERNATE:
XSetFillRule(g_display, g_gc, EvenOddRule);
break;
case WINDING:
XSetFillRule(g_display, g_gc, WindingRule);
break;
default:
unimpl("fill mode %d\n", fillmode);
}
if (brush)
style = brush->style;
else
style = 0;
switch (style)
{
case 0: /* Solid */
SET_FOREGROUND(fgcolour);
FILL_POLYGON((XPoint *) point, npoints);
break;
case 2: /* Hatch */
fill = (Pixmap) ui_create_glyph(8, 8,
hatch_patterns + brush->pattern[0] * 8);
SET_FOREGROUND(fgcolour);
SET_BACKGROUND(bgcolour);
XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
XSetStipple(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
FILL_POLYGON((XPoint *) point, npoints);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((HGLYPH) fill);
break;
case 3: /* Pattern */
for (i = 0; i != 8; i++)
ipattern[7 - i] = brush->pattern[i];
fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
SET_FOREGROUND(bgcolour);
SET_BACKGROUND(fgcolour);
XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
XSetStipple(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
FILL_POLYGON((XPoint *) point, npoints);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((HGLYPH) fill);
break;
default:
unimpl("brush %d\n", brush->style);
}
RESET_FUNCTION(opcode);
}
void
ui_ellipse(uint8 opcode,
/* mode */ uint8 fillmode,
/* dest */ int x, int y, int cx, int cy,
/* brush */ BRUSH * brush, int bgcolour, int fgcolour)
{
uint8 style, i, ipattern[8];
Pixmap fill;
SET_FUNCTION(opcode);
if (brush)
style = brush->style;
else
style = 0;
switch (style)
{
case 0: /* Solid */
SET_FOREGROUND(fgcolour);
DRAW_ELLIPSE(x, y, cx, cy, fillmode);
break;
case 2: /* Hatch */
fill = (Pixmap) ui_create_glyph(8, 8,
hatch_patterns + brush->pattern[0] * 8);
SET_FOREGROUND(fgcolour);
SET_BACKGROUND(bgcolour);
XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
XSetStipple(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
DRAW_ELLIPSE(x, y, cx, cy, fillmode);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((HGLYPH) fill);
break;
case 3: /* Pattern */
for (i = 0; i != 8; i++)
ipattern[7 - i] = brush->pattern[i];
fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
SET_FOREGROUND(bgcolour);
SET_BACKGROUND(fgcolour);
XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
XSetStipple(g_display, g_gc, fill);
XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
DRAW_ELLIPSE(x, y, cx, cy, fillmode);
XSetFillStyle(g_display, g_gc, FillSolid);
XSetTSOrigin(g_display, g_gc, 0, 0);
ui_destroy_glyph((HGLYPH) fill);
break;
default:
unimpl("brush %d\n", brush->style);
}
RESET_FUNCTION(opcode);
}
/* warning, this function only draws on wnd or backstore, not both */
void
ui_draw_glyph(int mixmode,