libfreerdp-core: parsing of glyph fragments

This commit is contained in:
Marc-André Moreau 2011-09-04 16:49:22 -04:00
parent 65e0cc4eca
commit 08765a910d
3 changed files with 243 additions and 22 deletions

View File

@ -363,6 +363,23 @@ struct _SAVE_BITMAP_ORDER
};
typedef struct _SAVE_BITMAP_ORDER SAVE_BITMAP_ORDER;
struct _GLYPH_FRAGMENT_INDEX
{
uint8 index;
uint16 delta;
};
typedef struct _GLYPH_FRAGMENT_INDEX GLYPH_FRAGMENT_INDEX;
struct _GLYPH_FRAGMENT
{
uint8 operation;
uint8 index;
uint8 size;
uint8 nindices;
GLYPH_FRAGMENT_INDEX* indices;
};
typedef struct _GLYPH_FRAGMENT GLYPH_FRAGMENT;
struct _GLYPH_INDEX_ORDER
{
uint8 cacheId;
@ -382,8 +399,8 @@ struct _GLYPH_INDEX_ORDER
BRUSH brush;
sint16 x;
sint16 y;
uint8 cbData;
uint8* data;
uint8 cbFragments;
uint8* fragments;
};
typedef struct _GLYPH_INDEX_ORDER GLYPH_INDEX_ORDER;
@ -404,8 +421,8 @@ struct _FAST_INDEX_ORDER
sint16 opBottom;
sint16 x;
sint16 y;
uint8 cbData;
uint8* data;
uint16 nfragments;
GLYPH_FRAGMENT* fragments;
};
typedef struct _FAST_INDEX_ORDER FAST_INDEX_ORDER;
@ -898,6 +915,10 @@ typedef struct _SURFACE_BITS_COMMAND SURFACE_BITS_COMMAND;
#define SCREEN_BITMAP_SURFACE 0xFFFF
#define GLYPH_FRAGMENT_NOP 0x00
#define GLYPH_FRAGMENT_USE 0xFE
#define GLYPH_FRAGMENT_ADD 0xFF
/* Window Order Header Flags */
#define WINDOW_ORDER_TYPE_WINDOW 0x01000000
#define WINDOW_ORDER_TYPE_NOTIFY 0x02000000

View File

@ -268,10 +268,8 @@ boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s)
stream_seek(s, RDP_PACKET_HEADER_LENGTH);
if (rdp_recv_out_of_sequence_pdu(rdp, s) != True)
{
printf("Unexpected PDU when expecting Demand Active PDU\n");
return False;
}
return True;
}

View File

@ -18,6 +18,7 @@
*/
#include "window.h"
#include <freerdp/api.h>
#include "orders.h"
@ -131,7 +132,7 @@ uint8 BMF_BPP[] =
0, 1, 0, 8, 16, 24, 32
};
void update_read_coord(STREAM* s, sint16* coord, boolean delta)
INLINE void update_read_coord(STREAM* s, sint16* coord, boolean delta)
{
sint8 byte;
@ -146,7 +147,7 @@ void update_read_coord(STREAM* s, sint16* coord, boolean delta)
}
}
void update_read_color(STREAM* s, uint32* color)
INLINE void update_read_color(STREAM* s, uint32* color)
{
uint8 byte;
@ -158,7 +159,7 @@ void update_read_color(STREAM* s, uint32* color)
*color |= (byte << 16);
}
void update_read_colorref(STREAM* s, uint32* color)
INLINE void update_read_colorref(STREAM* s, uint32* color)
{
uint8 byte;
@ -171,7 +172,7 @@ void update_read_colorref(STREAM* s, uint32* color)
stream_seek_uint8(s);
}
void update_read_color_quad(STREAM* s, uint32* color)
INLINE void update_read_color_quad(STREAM* s, uint32* color)
{
uint8 byte;
@ -184,7 +185,7 @@ void update_read_color_quad(STREAM* s, uint32* color)
stream_seek_uint8(s);
}
void update_read_2byte_unsigned(STREAM* s, uint16* value)
INLINE void update_read_2byte_unsigned(STREAM* s, uint16* value)
{
uint8 byte;
@ -202,7 +203,7 @@ void update_read_2byte_unsigned(STREAM* s, uint16* value)
}
}
void update_read_2byte_signed(STREAM* s, sint16* value)
INLINE void update_read_2byte_signed(STREAM* s, sint16* value)
{
uint8 byte;
boolean negative;
@ -223,7 +224,7 @@ void update_read_2byte_signed(STREAM* s, sint16* value)
*value *= -1;
}
void update_read_4byte_unsigned(STREAM* s, uint32* value)
INLINE void update_read_4byte_unsigned(STREAM* s, uint32* value)
{
uint8 byte;
uint8 count;
@ -267,7 +268,7 @@ void update_read_4byte_unsigned(STREAM* s, uint32* value)
}
}
void update_read_delta(STREAM* s, sint16* value)
INLINE void update_read_delta(STREAM* s, sint16* value)
{
uint8 byte;
@ -285,7 +286,29 @@ void update_read_delta(STREAM* s, sint16* value)
}
}
void update_read_brush(STREAM* s, BRUSH* brush, uint8 fieldFlags)
INLINE void update_read_glyph_delta(STREAM* s, uint16* value)
{
uint8 byte;
stream_read_uint8(s, byte);
if (byte == 0x80)
stream_read_uint16(s, *value);
else
*value = (byte & 0x3F);
}
INLINE void update_seek_glyph_delta(STREAM* s)
{
uint8 byte;
stream_read_uint8(s, byte);
if (byte & 0x80)
stream_seek_uint8(s);
}
INLINE void update_read_brush(STREAM* s, BRUSH* brush, uint8 fieldFlags)
{
if (fieldFlags & ORDER_FIELD_01)
stream_read_uint8(s, brush->x);
@ -323,7 +346,7 @@ void update_read_brush(STREAM* s, BRUSH* brush, uint8 fieldFlags)
}
}
void update_read_delta_rects(STREAM* s, DELTA_RECT* rectangles, int number)
INLINE void update_read_delta_rects(STREAM* s, DELTA_RECT* rectangles, int number)
{
int i;
uint8 flags = 0;
@ -368,7 +391,7 @@ void update_read_delta_rects(STREAM* s, DELTA_RECT* rectangles, int number)
}
}
void update_read_delta_points(STREAM* s, DELTA_POINT* points, int number, sint16 x, sint16 y)
INLINE void update_read_delta_points(STREAM* s, DELTA_POINT* points, int number, sint16 x, sint16 y)
{
int i;
uint8 flags = 0;
@ -406,6 +429,174 @@ void update_read_delta_points(STREAM* s, DELTA_POINT* points, int number, sint16
points[i - 1].y += y;
}
INLINE uint16 update_read_glyph_fragments(STREAM* s, GLYPH_FRAGMENT** fragments, boolean delta, uint8 size)
{
int index;
uint8 byte;
uint16 count;
uint8** offsets;
uint16* lengths;
uint8* operations;
uint8* array_mark;
uint8* stream_end;
uint8* stream_start;
GLYPH_FRAGMENT* fragment;
count = 0;
fragment = NULL;
*fragments = NULL;
array_mark = NULL;
stream_end = s->p + size;
stream_get_mark(s, stream_start);
offsets = (uint8**) xmalloc(size / 2);
lengths = (uint16*) xmalloc(size / 2);
operations = (uint8*) xmalloc(size / 2);
while (s->p < stream_end)
{
stream_read_uint8(s, byte);
if (byte == GLYPH_FRAGMENT_USE)
{
if (array_mark != NULL)
{
offsets[count] = array_mark;
lengths[count] = array_mark - ((count < 1) ? stream_start : offsets[count - 1]);
operations[count] = GLYPH_FRAGMENT_NOP;
array_mark = NULL;
count++;
}
offsets[count] = (s->p - 1);
stream_seek_uint8(s);
if (delta)
update_seek_glyph_delta(s);
lengths[count] = (s->p - offsets[count]);
operations[count] = GLYPH_FRAGMENT_USE;
count++;
}
else if (byte == GLYPH_FRAGMENT_ADD)
{
stream_seek_uint8(s);
stream_read_uint8(s, byte);
if ((s->p - (byte + 3)) != array_mark)
{
offsets[count] = array_mark;
lengths[count] = (s->p - (byte + 3)) - array_mark;
array_mark = NULL;
count++;
}
offsets[count] = (s->p - (byte + 3));
lengths[count] = (s->p - offsets[count]);
operations[count] = GLYPH_FRAGMENT_ADD;
array_mark = NULL;
count++;
}
else
{
if (array_mark == NULL)
array_mark = (s->p - 1);
if (delta)
update_seek_glyph_delta(s);
}
}
if (array_mark != NULL)
{
lengths[count] = array_mark - ((count < 1) ? stream_start : offsets[count - 1]);
if (lengths[count] > 1)
{
offsets[count] = array_mark;
operations[count] = GLYPH_FRAGMENT_NOP;
array_mark = NULL;
count++;
}
}
index = 0;
stream_set_mark(s, stream_start);
*fragments = (GLYPH_FRAGMENT*) xmalloc(sizeof(GLYPH_FRAGMENT) * count);
for (index = 0; index < count; index++)
{
fragment = &(*fragments[index]);
stream_set_mark(s, offsets[index]);
if (operations[index] == GLYPH_FRAGMENT_USE)
{
stream_seek_uint8(s);
fragment->operation = GLYPH_FRAGMENT_USE;
stream_read_uint8(s, fragment->index);
}
else if (operations[index] == GLYPH_FRAGMENT_ADD)
{
uint16 icount;
fragment->operation = GLYPH_FRAGMENT_ADD;
fragment->nindices = 0;
icount = (lengths[index] - 3) / (delta) ? 2 : 1;
fragment->indices = (GLYPH_FRAGMENT_INDEX*) xmalloc(icount * sizeof(GLYPH_FRAGMENT_INDEX));
while (s->p < (offsets[index] + (lengths[index] - 3)))
{
if ((fragment->nindices + 1) > icount)
{
fragment->indices = (GLYPH_FRAGMENT_INDEX*) xrealloc(fragment->indices,
++icount * sizeof(GLYPH_FRAGMENT_INDEX));
}
stream_read_uint8(s, fragment->indices[fragment->nindices].index);
if (delta)
update_read_glyph_delta(s, &fragment->indices[fragment->nindices].delta);
fragment->nindices++;
}
stream_seek_uint8(s);
stream_read_uint8(s, fragment->index);
stream_read_uint8(s, fragment->size);
}
else
{
uint16 icount;
fragment->operation = GLYPH_FRAGMENT_NOP;
fragment->nindices = 0;
icount = lengths[index] / (delta) ? 2 : 1;
fragment->indices = (GLYPH_FRAGMENT_INDEX*) xmalloc(icount * sizeof(GLYPH_FRAGMENT_INDEX));
while (s->p < (offsets[index] + lengths[index]))
{
if ((fragment->nindices + 1) > icount)
{
fragment->indices = (GLYPH_FRAGMENT_INDEX*) xrealloc(fragment->indices,
++icount * sizeof(GLYPH_FRAGMENT_INDEX));
}
stream_read_uint8(s, fragment->indices[fragment->nindices].index);
if (delta)
update_read_glyph_delta(s, &fragment->indices[fragment->nindices].delta);
fragment->nindices++;
}
}
}
xfree(offsets);
xfree(lengths);
xfree(operations);
return count;
}
/* Primary Drawing Orders */
void update_read_dstblt_order(STREAM* s, ORDER_INFO* orderInfo, DSTBLT_ORDER* dstblt)
@ -904,8 +1095,8 @@ void update_read_glyph_index_order(STREAM* s, ORDER_INFO* orderInfo, GLYPH_INDEX
if (orderInfo->fieldFlags & ORDER_FIELD_22)
{
stream_read_uint8(s, glyph_index->cbData);
stream_seek(s, glyph_index->cbData);
stream_read_uint8(s, glyph_index->cbFragments);
stream_seek(s, glyph_index->cbFragments);
}
}
@ -958,8 +1149,19 @@ void update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_O
if (orderInfo->fieldFlags & ORDER_FIELD_15)
{
stream_read_uint8(s, fast_index->cbData);
stream_seek(s, fast_index->cbData);
uint8* mark;
uint8 cbData;
boolean delta = False;
stream_read_uint8(s, cbData);
stream_get_mark(s, mark);
if ((fast_index->ulCharInc == 0) && !(fast_index->flAccel & SO_CHAR_INC_EQUAL_BM_BASE))
delta = True;
fast_index->nfragments = update_read_glyph_fragments(s, &fast_index->fragments, delta, cbData);
stream_set_mark(s, mark);
}
}