diff --git a/CMakeLists.txt b/CMakeLists.txt index 215139a26..668fc3b0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,8 +58,7 @@ endif() # Compiler-specific flags if(CMAKE_COMPILER_IS_GNUCC) - #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-unused-but-set-variable") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -lncurses") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-unused-but-set-variable") if(CMAKE_BUILD_TYPE STREQUAL "Release") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") endif() diff --git a/client/DirectFB/CMakeLists.txt b/client/DirectFB/CMakeLists.txt index d0ef4b302..5ae3d2fd0 100644 --- a/client/DirectFB/CMakeLists.txt +++ b/client/DirectFB/CMakeLists.txt @@ -31,3 +31,5 @@ target_link_libraries(dfreerdp freerdp-kbd) target_link_libraries(dfreerdp freerdp-chanman) target_link_libraries(dfreerdp freerdp-utils) target_link_libraries(dfreerdp ${DIRECTFB_LIBRARIES}) + +install(TARGETS dfreerdp DESTINATION bin) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index f7f3c227c..fd948edbf 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -232,6 +232,29 @@ Pixmap xf_mono_bitmap_new(xfInfo* xfi, int width, int height, uint8* data) return bitmap; } +Pixmap xf_glyph_new(xfInfo* xfi, int width, int height, uint8* data) +{ + int scanline; + Pixmap bitmap; + XImage* image; + + scanline = (width + 7) / 8; + + bitmap = XCreatePixmap(xfi->display, xfi->window->handle, width, height, 1); + + image = XCreateImage(xfi->display, xfi->visual, 1, + ZPixmap, 0, (char*) data, width, height, 8, scanline); + + image->byte_order = MSBFirst; + image->bitmap_bit_order = MSBFirst; + + XInitImage(image); + XPutImage(xfi->display, bitmap, xfi->gc_mono, image, 0, 0, 0, 0, width, height); + XFree(image); + + return bitmap; +} + void xf_gdi_bitmap_update(rdpUpdate* update, BITMAP_UPDATE* bitmap) { int i; @@ -319,7 +342,6 @@ void xf_gdi_patblt(rdpUpdate* update, PATBLT_ORDER* patblt) if (brush->style & CACHED_BRUSH) { - printf("cached brush bpp:%d\n", brush->bpp); brush->data = brush_get(xfi->cache->brush, brush->index, &brush->bpp); brush->style = GDI_BS_PATTERN; } @@ -505,7 +527,117 @@ void xf_gdi_polyline(rdpUpdate* update, POLYLINE_ORDER* polyline) void xf_gdi_fast_index(rdpUpdate* update, FAST_INDEX_ORDER* fast_index) { + int i, j; + int x, y; + Pixmap bmp; + Pixmap* bmps; + uint32 fg_color; + uint32 bg_color; + GLYPH_DATA* glyph; + GLYPH_DATA** glyphs; + GLYPH_FRAGMENT* fragment; + xfInfo* xfi = GET_XFI(update); + x = fast_index->bkLeft; + y = fast_index->y; + + fg_color = freerdp_color_convert(fast_index->foreColor, 32, xfi->bpp, xfi->clrconv); + bg_color = freerdp_color_convert(fast_index->backColor, 32, xfi->bpp, xfi->clrconv); + + XSetFunction(xfi->display, xfi->gc, GXcopy); + XSetForeground(xfi->display, xfi->gc, bg_color); + XSetBackground(xfi->display, xfi->gc, fg_color); + +#if 0 + if (fast_index->opaqueRect) + { + XSetFillStyle(xfi->display, xfi->gc, FillSolid); + + XFillRectangle(xfi->display, xfi->drawing, xfi->gc, fast_index->opLeft, fast_index->opTop, + fast_index->opRight - fast_index->opLeft + 1, fast_index->opBottom - fast_index->opTop + 1); + + if (xfi->drawing == xfi->primary) + { + XFillRectangle(xfi->display, xfi->window->handle, xfi->gc, fast_index->opLeft, fast_index->opTop, + fast_index->opRight - fast_index->opLeft + 1, fast_index->opBottom - fast_index->opTop + 1); + } + } +#endif + + XSetFillStyle(xfi->display, xfi->gc, FillStippled); + + for (i = 0; i < fast_index->nfragments; i++) + { + fragment = &fast_index->fragments[i]; + + if (fragment->operation == GLYPH_FRAGMENT_USE) + { + fragment->indices = (GLYPH_FRAGMENT_INDEX*) glyph_fragment_get(xfi->cache->glyph, + fragment->index, &fragment->nindices, (void**) &bmps); + + glyphs = (GLYPH_DATA**) xmalloc(sizeof(GLYPH_DATA*) * fragment->nindices); + + for (j = 0; j < fragment->nindices; j++) + { + glyphs[j] = glyph_get(xfi->cache->glyph, fast_index->cacheId, fragment->indices[j].index, (void**) &bmps[j]); + } + } + else + { + bmps = (Pixmap*) xmalloc(sizeof(Pixmap*) * fragment->nindices); + glyphs = (GLYPH_DATA**) xmalloc(sizeof(GLYPH_DATA*) * fragment->nindices); + + for (j = 0; j < fragment->nindices; j++) + { + glyphs[j] = glyph_get(xfi->cache->glyph, fast_index->cacheId, fragment->indices[j].index, (void**) &bmps[j]); + } + } + + for (j = 0; j < fragment->nindices; j++) + { + bmp = bmps[j]; + glyph = glyphs[j]; + + XSetStipple(xfi->display, xfi->gc, bmp); + XSetTSOrigin(xfi->display, xfi->gc, glyph->x + x, glyph->y + y); + XFillRectangle(xfi->display, xfi->drawing, xfi->gc, glyph->x + x, glyph->y + y, glyph->cx, glyph->cy); + XSetStipple(xfi->display, xfi->gc, xfi->bitmap_mono); + + if ((j + 1) < fragment->nindices) + { + if (!(fast_index->flAccel & SO_CHAR_INC_EQUAL_BM_BASE)) + { + if (fast_index->flAccel & SO_VERTICAL) + { + y += fragment->indices[j + 1].delta; + } + else + { + x += fragment->indices[j + 1].delta; + } + } + else + { + x += glyph->cx; + } + } + } + + if (fragment->operation == GLYPH_FRAGMENT_ADD) + { + glyph_fragment_put(xfi->cache->glyph, fragment->index, + fragment->nindices, (void*) fragment->indices, (void*) bmps); + } + } + + if (xfi->drawing == xfi->primary) + { + XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, + fast_index->bkLeft, fast_index->bkTop, + fast_index->bkRight - fast_index->bkLeft + 1, + fast_index->bkBottom - fast_index->bkTop + 1, + fast_index->bkLeft, fast_index->bkTop); + } } void xf_gdi_create_offscreen_bitmap(rdpUpdate* update, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap) @@ -549,7 +681,17 @@ void xf_gdi_cache_color_table(rdpUpdate* update, CACHE_COLOR_TABLE_ORDER* cache_ void xf_gdi_cache_glyph(rdpUpdate* update, CACHE_GLYPH_ORDER* cache_glyph) { + int i; + Pixmap bitmap; + GLYPH_DATA* glyph; + xfInfo* xfi = GET_XFI(update); + for (i = 0; i < cache_glyph->cGlyphs; i++) + { + glyph = cache_glyph->glyphData[i]; + bitmap = xf_glyph_new(xfi, glyph->cx, glyph->cy, glyph->aj); + glyph_put(xfi->cache->glyph, cache_glyph->cacheId, glyph->cacheIndex, glyph, (void*) bitmap); + } } void xf_gdi_cache_glyph_v2(rdpUpdate* update, CACHE_GLYPH_V2_ORDER* cache_glyph_v2) @@ -565,19 +707,15 @@ void xf_gdi_cache_brush(rdpUpdate* update, CACHE_BRUSH_ORDER* cache_brush) void xf_gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command) { - STREAM* s; - XImage* image; int i, tx, ty; + XImage* image; RFX_MESSAGE* message; xfInfo* xfi = GET_XFI(update); RFX_CONTEXT* context = (RFX_CONTEXT*) xfi->rfx_context; if (surface_bits_command->codecID == CODEC_ID_REMOTEFX) { - s = stream_new(0); - stream_attach(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); - - message = rfx_process_message(context, s); + message = rfx_process_message(context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); @@ -611,8 +749,6 @@ void xf_gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_c XSetClipMask(xfi->display, xfi->gc, None); rfx_message_free(context, message); - stream_detach(s); - stream_free(s); } else if (surface_bits_command->codecID == CODEC_ID_NONE) { diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index a7a4234bc..a572b28f3 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -24,18 +24,23 @@ #include #endif +#include #include #include -#include -#include #include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include #include #include -#include #include #include @@ -742,6 +747,67 @@ int main(int argc, char* argv[]) xf_process_plugin_args, chanman, xf_process_ui_args, NULL) < 0) return 1; + if (instance->settings->password == NULL) + { + int status; + char* password; + int pipe_ends[2]; + struct termios term_flags; + const int password_size = 512; + + password = xmalloc(password_size * sizeof(char)); + + printf("Password: "); + + /* Turn off ECHO on stdin, but still echo newlines */ + if (tcgetattr(fileno(stdin), &term_flags) != 0) + { + perror(strerror(errno)); + exit(errno); + } + + if (pipe(pipe_ends) != 0) + { + perror(strerror(errno)); + exit(errno); + } + + switch (fork()) + { + case -1: + perror(strerror(errno)); + exit(errno); + + case 0: + close(pipe_ends[0]); + term_flags.c_lflag &= ~ECHO; + term_flags.c_lflag |= ECHONL; + tcsetattr(fileno(stdin), TCSAFLUSH, &term_flags); + fgets(password, password_size - 1, stdin); + write(pipe_ends[1], password, strlen(password)); + close(pipe_ends[1]); + exit(EXIT_SUCCESS); + + default: + wait(&status); + if (tcsetattr(fileno(stdin), TCSADRAIN, &term_flags) != 0) + { + tcsetattr(fileno(stdin), TCSANOW, &term_flags); + perror(strerror(errno)); + exit(errno); + } + break; + } + + close(pipe_ends[1]); + read(pipe_ends[0], password, password_size); + close(pipe_ends[0]); + + *(password + strlen(password) - 1) = '\0'; + xfree(instance->settings->password); + instance->settings->password = password; + } + data = (struct thread_data*) xzalloc(sizeof(struct thread_data)); data->instance = instance; diff --git a/cunit/test_color.c b/cunit/test_color.c index 16214809e..e29776e14 100644 --- a/cunit/test_color.c +++ b/cunit/test_color.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "test_color.h" int init_color_suite(void) diff --git a/cunit/test_librfx.c b/cunit/test_librfx.c index 0719ffe98..bc1df676d 100644 --- a/cunit/test_librfx.c +++ b/cunit/test_librfx.c @@ -393,7 +393,7 @@ void test_message(void) stream_seal(s); /*hexdump(buffer, size);*/ stream_set_pos(s, 0); - message = rfx_process_message(context, s); + message = rfx_process_message(context, s->p, s->size); if (i == 0) { for (j = 0; j < message->num_tiles; j++) diff --git a/include/freerdp/cache/glyph.h b/include/freerdp/cache/glyph.h index 88ee83d64..b16a82b3f 100644 --- a/include/freerdp/cache/glyph.h +++ b/include/freerdp/cache/glyph.h @@ -39,17 +39,34 @@ struct _GLYPH_CACHE }; typedef struct _GLYPH_CACHE GLYPH_CACHE; +struct _FRAGMENT_CACHE_ENTRY +{ + void* entry; + void* extra; + uint16 count; +}; +typedef struct _FRAGMENT_CACHE_ENTRY FRAGMENT_CACHE_ENTRY; + +struct _FRAGMENT_CACHE +{ + FRAGMENT_CACHE_ENTRY* entries; +}; +typedef struct _FRAGMENT_CACHE FRAGMENT_CACHE; + struct rdp_glyph { rdpSettings* settings; GLYPH_CACHE glyphCache[10]; - GLYPH_CACHE fragCache; + FRAGMENT_CACHE fragCache; }; typedef struct rdp_glyph rdpGlyph; FREERDP_API void* glyph_get(rdpGlyph* glyph, uint8 id, uint16 index, void** extra); FREERDP_API void glyph_put(rdpGlyph* glyph, uint8 id, uint16 index, void* entry, void* extra); +FREERDP_API void* glyph_fragment_get(rdpGlyph* glyph, uint8 index, uint8* count, void** extra); +FREERDP_API void glyph_fragment_put(rdpGlyph* glyph, uint8 index, uint8 count, void* entry, void* extra); + FREERDP_API rdpGlyph* glyph_new(rdpSettings* settings); FREERDP_API void glyph_free(rdpGlyph* glyph); diff --git a/include/freerdp/rfx/rfx.h b/include/freerdp/rfx/rfx.h index 50eac7b0f..9be66b53b 100644 --- a/include/freerdp/rfx/rfx.h +++ b/include/freerdp/rfx/rfx.h @@ -130,11 +130,15 @@ FREERDP_API void rfx_context_free(RFX_CONTEXT* context); FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, RFX_PIXEL_FORMAT pixel_format); FREERDP_API void rfx_context_reset(RFX_CONTEXT* context); -FREERDP_API RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, STREAM* data_in); +FREERDP_API RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, uint8* data, uint32 length); +FREERDP_API uint16 rfx_message_get_tile_count(RFX_MESSAGE* message); +FREERDP_API RFX_TILE* rfx_message_get_tile(RFX_MESSAGE* message, int index); +FREERDP_API uint16 rfx_message_get_rect_count(RFX_MESSAGE* message); +FREERDP_API RFX_RECT* rfx_message_get_rect(RFX_MESSAGE* message, int index); FREERDP_API void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message); -FREERDP_API void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* data_out); -FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, STREAM* data_out, +FREERDP_API void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* s); +FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, STREAM* s, const RFX_RECT* rects, int num_rects, uint8* image_data, int width, int height, int rowstride); #ifdef __cplusplus diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 82afa1282..c58bd35ef 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -419,6 +419,7 @@ struct _FAST_INDEX_ORDER sint16 opTop; sint16 opRight; sint16 opBottom; + boolean opaqueRect; sint16 x; sint16 y; uint16 nfragments; @@ -900,6 +901,14 @@ typedef struct _SURFACE_BITS_COMMAND SURFACE_BITS_COMMAND; #define HS_CROSS 0x04 #define HS_DIAGCROSS 0x05 +#define SO_FLAG_DEFAULT_PLACEMENT 0x01 +#define SO_HORIZONTAL 0x02 +#define SO_VERTICAL 0x04 +#define SO_REVERSED 0x08 +#define SO_ZERO_BEARINGS 0x10 +#define SO_CHAR_INC_EQUAL_BM_BASE 0x20 +#define SO_MAXEXT_EQUAL_BM_SIDE 0x40 + #define DSDNG_STRETCH 0x00000001 #define DSDNG_TILE 0x00000002 #define DSDNG_PERPIXELALPHA 0x00000004 diff --git a/libfreerdp-cache/glyph.c b/libfreerdp-cache/glyph.c index dc63502ae..1607404a4 100644 --- a/libfreerdp-cache/glyph.c +++ b/libfreerdp-cache/glyph.c @@ -66,6 +66,26 @@ void glyph_put(rdpGlyph* glyph, uint8 id, uint16 index, void* entry, void* extra glyph->glyphCache[id].entries[index].extra = extra; } +void* glyph_fragment_get(rdpGlyph* glyph, uint8 index, uint8* count, void** extra) +{ + void* entry; + + entry = glyph->fragCache.entries[index].entry; + *count = glyph->fragCache.entries[index].count; + + if (extra != NULL) + *extra = glyph->fragCache.entries[index].extra; + + return entry; +} + +void glyph_fragment_put(rdpGlyph* glyph, uint8 index, uint8 count, void* entry, void* extra) +{ + glyph->fragCache.entries[index].entry = entry; + glyph->fragCache.entries[index].count = count; + glyph->fragCache.entries[index].extra = extra; +} + rdpGlyph* glyph_new(rdpSettings* settings) { rdpGlyph* glyph; @@ -78,7 +98,7 @@ rdpGlyph* glyph_new(rdpSettings* settings) glyph->settings = settings; - //settings->glyphSupportLevel = GLYPH_SUPPORT_FULL; + settings->glyphSupportLevel = GLYPH_SUPPORT_FULL; for (i = 0; i < 10; i++) { @@ -87,9 +107,7 @@ rdpGlyph* glyph_new(rdpSettings* settings) glyph->glyphCache[i].entries = xzalloc(sizeof(GLYPH_CACHE) * glyph->glyphCache[i].number); } - glyph->fragCache.number = settings->fragCache.cacheEntries; - glyph->fragCache.maxCellSize = settings->fragCache.cacheMaximumCellSize; - glyph->fragCache.entries = xzalloc(sizeof(GLYPH_CACHE) * glyph->fragCache.number); + glyph->fragCache.entries = xzalloc(sizeof(FRAGMENT_CACHE_ENTRY) * 256); } return glyph; diff --git a/libfreerdp-core/certificate.c b/libfreerdp-core/certificate.c index 78f172333..0095c0c09 100644 --- a/libfreerdp-core/certificate.c +++ b/libfreerdp-core/certificate.c @@ -280,8 +280,6 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific uint32 wSignatureBlobType; uint32 wSignatureBlobLen; - printf("Server Proprietary Certificate\n"); - stream_read_uint32(s, dwSigAlgId); stream_read_uint32(s, dwKeyAlgId); if (!(dwSigAlgId == 1 && dwKeyAlgId == 1)) diff --git a/libfreerdp-core/orders.c b/libfreerdp-core/orders.c index a6833c9b0..079c8f1a3 100644 --- a/libfreerdp-core/orders.c +++ b/libfreerdp-core/orders.c @@ -535,7 +535,7 @@ INLINE uint16 update_read_glyph_fragments(STREAM* s, GLYPH_FRAGMENT** fragments, fragment->operation = GLYPH_FRAGMENT_ADD; fragment->nindices = 0; - icount = (lengths[index] - 3) / (delta) ? 2 : 1; + 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))) @@ -550,6 +550,8 @@ INLINE uint16 update_read_glyph_fragments(STREAM* s, GLYPH_FRAGMENT** fragments, if (delta) update_read_glyph_delta(s, &fragment->indices[fragment->nindices].delta); + else + fragment->indices[fragment->nindices].delta = 0; fragment->nindices++; } @@ -564,7 +566,7 @@ INLINE uint16 update_read_glyph_fragments(STREAM* s, GLYPH_FRAGMENT** fragments, fragment->operation = GLYPH_FRAGMENT_NOP; fragment->nindices = 0; - icount = lengths[index] / (delta) ? 2 : 1; + icount = lengths[index] / ((delta) ? 2 : 1); fragment->indices = (GLYPH_FRAGMENT_INDEX*) xmalloc(icount * sizeof(GLYPH_FRAGMENT_INDEX)); while (s->p < (offsets[index] + lengths[index])) @@ -579,6 +581,8 @@ INLINE uint16 update_read_glyph_fragments(STREAM* s, GLYPH_FRAGMENT** fragments, if (delta) update_read_glyph_delta(s, &fragment->indices[fragment->nindices].delta); + else + fragment->indices[fragment->nindices].delta = 0; fragment->nindices++; } @@ -1097,6 +1101,8 @@ void update_read_glyph_index_order(STREAM* s, ORDER_INFO* orderInfo, GLYPH_INDEX void update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_ORDER* fast_index) { + fast_index->opaqueRect = False; + if (orderInfo->fieldFlags & ORDER_FIELD_01) stream_read_uint8(s, fast_index->cacheId); @@ -1125,7 +1131,10 @@ void update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_O update_read_coord(s, &fast_index->bkBottom, orderInfo->deltaCoordinates); if (orderInfo->fieldFlags & ORDER_FIELD_09) + { update_read_coord(s, &fast_index->opLeft, orderInfo->deltaCoordinates); + fast_index->opaqueRect = True; + } if (orderInfo->fieldFlags & ORDER_FIELD_10) update_read_coord(s, &fast_index->opTop, orderInfo->deltaCoordinates); @@ -1142,6 +1151,37 @@ void update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_O if (orderInfo->fieldFlags & ORDER_FIELD_14) update_read_coord(s, &fast_index->y, orderInfo->deltaCoordinates); + if (fast_index->opRight == 0) + fast_index->opRight = fast_index->bkRight; + + if (fast_index->opBottom == -32768) + { + if ((fast_index->opTop & 0x0F) == 0x0F) + { + fast_index->opLeft = fast_index->bkLeft; + fast_index->opTop = fast_index->bkTop; + fast_index->opRight = fast_index->bkRight; + fast_index->opBottom = fast_index->bkBottom; + fast_index->opaqueRect = True; + } + else if ((fast_index->opTop & 0x0F) == 0x0D) + { + fast_index->opLeft = fast_index->bkLeft; + fast_index->opTop = fast_index->bkTop; + fast_index->opBottom = fast_index->bkBottom; + fast_index->opaqueRect = True; + } + } + + if (fast_index->opRight - fast_index->opLeft > 1) + fast_index->opaqueRect = True; + + if (fast_index->x == -32768) + fast_index->x = fast_index->bkLeft; + + if (fast_index->y == -32768) + fast_index->y = fast_index->bkTop; + if (orderInfo->fieldFlags & ORDER_FIELD_15) { uint8* mark; diff --git a/libfreerdp-core/orders.h b/libfreerdp-core/orders.h index c7462c050..6604055bd 100644 --- a/libfreerdp-core/orders.h +++ b/libfreerdp-core/orders.h @@ -89,14 +89,6 @@ #define CBR3_IGNORABLE_FLAG 0x08 #define CBR3_DO_NOT_CACHE 0x10 -#define SO_FLAG_DEFAULT_PLACEMENT 0x01 -#define SO_HORIZONTAL 0x02 -#define SO_VERTICAL 0x04 -#define SO_REVERSED 0x08 -#define SO_ZERO_BEARINGS 0x10 -#define SO_CHAR_INC_EQUAL_BM_BASE 0x20 -#define SO_MAXEXT_EQUAL_BM_SIDE 0x40 - #define COMPRESSED_BRUSH_LENGTH 20 /* Primary Drawing Orders */ diff --git a/libfreerdp-core/tcp.c b/libfreerdp-core/tcp.c index 542206b5d..2bdd616be 100644 --- a/libfreerdp-core/tcp.c +++ b/libfreerdp-core/tcp.c @@ -199,6 +199,7 @@ boolean tcp_disconnect(rdpTcp * tcp) { if (tcp->sockfd != -1) { + shutdown(tcp->sockfd, SHUT_RDWR); close(tcp->sockfd); tcp->sockfd = -1; } diff --git a/libfreerdp-gdi/gdi.c b/libfreerdp-gdi/gdi.c index 61c111f02..39c121ab4 100644 --- a/libfreerdp-gdi/gdi.c +++ b/libfreerdp-gdi/gdi.c @@ -402,7 +402,7 @@ HGDI_BITMAP gdi_create_bitmap(GDI* gdi, int width, int height, int bpp, uint8* d return bitmap; } -GDI_IMAGE* gdi_bitmap_new(GDI *gdi, int width, int height, int bpp, uint8* data) +GDI_IMAGE* gdi_bitmap_new(GDI* gdi, int width, int height, int bpp, uint8* data) { GDI_IMAGE *gdi_bmp; @@ -437,6 +437,39 @@ void gdi_bitmap_free(GDI_IMAGE *gdi_bmp) } } +GDI_IMAGE* gdi_glyph_new(GDI* gdi, GLYPH_DATA* glyph) +{ + uint8* extra; + GDI_IMAGE* gdi_bmp; + + gdi_bmp = (GDI_IMAGE*) malloc(sizeof(GDI_IMAGE)); + + gdi_bmp->hdc = gdi_GetDC(); + gdi_bmp->hdc->bytesPerPixel = 1; + gdi_bmp->hdc->bitsPerPixel = 1; + + extra = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj); + gdi_bmp->bitmap = gdi_CreateBitmap(glyph->cx, glyph->cy, 1, extra); + gdi_bmp->bitmap->bytesPerPixel = 1; + gdi_bmp->bitmap->bitsPerPixel = 1; + + gdi_SelectObject(gdi_bmp->hdc, (HGDIOBJECT) gdi_bmp->bitmap); + gdi_bmp->org_bitmap = NULL; + + return gdi_bmp; +} + +void gdi_glyph_free(GDI_IMAGE *gdi_bmp) +{ + if (gdi_bmp != 0) + { + gdi_SelectObject(gdi_bmp->hdc, (HGDIOBJECT) gdi_bmp->org_bitmap); + gdi_DeleteObject((HGDIOBJECT) gdi_bmp->bitmap); + gdi_DeleteDC(gdi_bmp->hdc); + free(gdi_bmp); + } +} + void gdi_bitmap_update(rdpUpdate* update, BITMAP_UPDATE* bitmap) { int i; @@ -642,13 +675,84 @@ void gdi_polyline(rdpUpdate* update, POLYLINE_ORDER* polyline) void gdi_fast_index(rdpUpdate* update, FAST_INDEX_ORDER* fast_index) { + int i, j; + int x, y; uint32 color; + GDI_IMAGE* bmp; + GDI_IMAGE** bmps; + GLYPH_DATA* glyph; + GLYPH_DATA** glyphs; + GLYPH_FRAGMENT* fragment; GDI* gdi = GET_GDI(update); - color = freerdp_color_convert(fast_index->foreColor, gdi->srcBpp, 32, gdi->clrconv); + x = fast_index->bkLeft; + y = fast_index->y; + + color = freerdp_color_convert(fast_index->backColor, gdi->srcBpp, 32, gdi->clrconv); gdi->textColor = gdi_SetTextColor(gdi->drawing->hdc, color); + gdi_SetNullClipRgn(gdi->drawing->hdc); + for (i = 0; i < fast_index->nfragments; i++) + { + fragment = &fast_index->fragments[i]; + if (fragment->operation == GLYPH_FRAGMENT_USE) + { + fragment->indices = (GLYPH_FRAGMENT_INDEX*) glyph_fragment_get(gdi->cache->glyph, + fragment->index, &fragment->nindices, (void**) &bmps); + + glyphs = (GLYPH_DATA**) xmalloc(sizeof(GLYPH_DATA*) * fragment->nindices); + + for (j = 0; j < fragment->nindices; j++) + { + glyphs[j] = glyph_get(gdi->cache->glyph, fast_index->cacheId, fragment->indices[j].index, (void**) &bmps[j]); + } + } + else + { + bmps = (GDI_IMAGE**) xmalloc(sizeof(GDI_IMAGE*) * fragment->nindices); + glyphs = (GLYPH_DATA**) xmalloc(sizeof(GLYPH_DATA*) * fragment->nindices); + + for (j = 0; j < fragment->nindices; j++) + { + glyphs[j] = glyph_get(gdi->cache->glyph, fast_index->cacheId, fragment->indices[j].index, (void**) &bmps[j]); + } + } + + for (j = 0; j < fragment->nindices; j++) + { + bmp = bmps[j]; + glyph = glyphs[j]; + + gdi_BitBlt(gdi->drawing->hdc, glyph->x + x, glyph->y + y, bmp->bitmap->width, + bmp->bitmap->height, bmp->hdc, 0, 0, GDI_DSPDxax); + + if ((j + 1) < fragment->nindices) + { + if (!(fast_index->flAccel & SO_CHAR_INC_EQUAL_BM_BASE)) + { + if (fast_index->flAccel & SO_VERTICAL) + { + y += fragment->indices[j + 1].delta; + } + else + { + x += fragment->indices[j + 1].delta; + } + } + else + { + x += glyph->cx; + } + } + } + + if (fragment->operation == GLYPH_FRAGMENT_ADD) + { + glyph_fragment_put(gdi->cache->glyph, fragment->index, + fragment->nindices, (void*) fragment->indices, (void*) bmps); + } + } gdi_SetTextColor(gdi->drawing->hdc, gdi->textColor); } @@ -696,7 +800,6 @@ void gdi_cache_color_table(rdpUpdate* update, CACHE_COLOR_TABLE_ORDER* cache_col void gdi_cache_glyph(rdpUpdate* update, CACHE_GLYPH_ORDER* cache_glyph) { int i; - uint8* extra; GLYPH_DATA* glyph; GDI_IMAGE* gdi_bmp; GDI* gdi = GET_GDI(update); @@ -704,20 +807,7 @@ void gdi_cache_glyph(rdpUpdate* update, CACHE_GLYPH_ORDER* cache_glyph) for (i = 0; i < cache_glyph->cGlyphs; i++) { glyph = cache_glyph->glyphData[i]; - gdi_bmp = (GDI_IMAGE*) malloc(sizeof(GDI_IMAGE)); - - gdi_bmp->hdc = gdi_GetDC(); - gdi_bmp->hdc->bytesPerPixel = 1; - gdi_bmp->hdc->bitsPerPixel = 1; - - extra = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj); - gdi_bmp->bitmap = gdi_CreateBitmap(glyph->cx, glyph->cy, 1, extra); - gdi_bmp->bitmap->bytesPerPixel = 1; - gdi_bmp->bitmap->bitsPerPixel = 1; - - gdi_SelectObject(gdi_bmp->hdc, (HGDIOBJECT) gdi_bmp->bitmap); - gdi_bmp->org_bitmap = NULL; - + gdi_bmp = gdi_glyph_new(gdi, glyph); glyph_put(gdi->cache->glyph, cache_glyph->cacheId, glyph->cacheIndex, glyph, (void*) gdi_bmp); } } @@ -763,7 +853,6 @@ void gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_comm { int i, j; int tx, ty; - STREAM* s; char* tile_bitmap; RFX_MESSAGE* message; GDI* gdi = GET_GDI(update); @@ -781,10 +870,7 @@ void gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_comm if (surface_bits_command->codecID == CODEC_ID_REMOTEFX) { - s = stream_new(0); - stream_attach(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); - - message = rfx_process_message(context, s); + message = rfx_process_message(context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); DEBUG_GDI("num_rects %d num_tiles %d", message->num_rects, message->num_tiles); @@ -814,9 +900,6 @@ void gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_comm gdi_SetNullClipRgn(gdi->primary->hdc); rfx_message_free(context, message); - - stream_detach(s); - stream_free(s); } else if (surface_bits_command->codecID == CODEC_ID_NONE) { diff --git a/libfreerdp-rfx/librfx.c b/libfreerdp-rfx/librfx.c index 56471f09a..9c0f26343 100644 --- a/libfreerdp-rfx/librfx.c +++ b/libfreerdp-rfx/librfx.c @@ -211,12 +211,12 @@ void rfx_context_reset(RFX_CONTEXT* context) context->frame_idx = 0; } -static void rfx_process_message_sync(RFX_CONTEXT* context, STREAM* data_in) +static void rfx_process_message_sync(RFX_CONTEXT* context, STREAM* s) { uint32 magic; /* RFX_SYNC */ - stream_read_uint32(data_in, magic); /* magic (4 bytes), 0xCACCACCA */ + stream_read_uint32(s, magic); /* magic (4 bytes), 0xCACCACCA */ if (magic != WF_MAGIC) { @@ -224,7 +224,7 @@ static void rfx_process_message_sync(RFX_CONTEXT* context, STREAM* data_in) return; } - stream_read_uint16(data_in, context->version); /* version (2 bytes), WF_VERSION_1_0 (0x0100) */ + stream_read_uint16(s, context->version); /* version (2 bytes), WF_VERSION_1_0 (0x0100) */ if (context->version != WF_VERSION_1_0) { @@ -235,11 +235,11 @@ static void rfx_process_message_sync(RFX_CONTEXT* context, STREAM* data_in) DEBUG_RFX("version 0x%X", context->version); } -static void rfx_process_message_codec_versions(RFX_CONTEXT* context, STREAM* data_in) +static void rfx_process_message_codec_versions(RFX_CONTEXT* context, STREAM* s) { uint8 numCodecs; - stream_read_uint8(data_in, numCodecs); /* numCodecs (1 byte), must be set to 0x01 */ + stream_read_uint8(s, numCodecs); /* numCodecs (1 byte), must be set to 0x01 */ if (numCodecs != 1) { @@ -248,18 +248,18 @@ static void rfx_process_message_codec_versions(RFX_CONTEXT* context, STREAM* dat } /* RFX_CODEC_VERSIONT */ - stream_read_uint8(data_in, context->codec_id); /* codecId (1 byte) */ - stream_read_uint8(data_in, context->codec_version); /* version (2 bytes) */ + stream_read_uint8(s, context->codec_id); /* codecId (1 byte) */ + stream_read_uint8(s, context->codec_version); /* version (2 bytes) */ DEBUG_RFX("id %d version 0x%X.", context->codec_id, context->codec_version); } -static void rfx_process_message_channels(RFX_CONTEXT* context, STREAM* data_in) +static void rfx_process_message_channels(RFX_CONTEXT* context, STREAM* s) { uint8 channelId; uint8 numChannels; - stream_read_uint8(data_in, numChannels); /* numChannels (1 byte), must bet set to 0x01 */ + stream_read_uint8(s, numChannels); /* numChannels (1 byte), must bet set to 0x01 */ if (numChannels != 1) { @@ -268,23 +268,23 @@ static void rfx_process_message_channels(RFX_CONTEXT* context, STREAM* data_in) } /* RFX_CHANNELT */ - stream_read_uint8(data_in, channelId); /* channelId (1 byte) */ - stream_read_uint16(data_in, context->width); /* width (2 bytes) */ - stream_read_uint16(data_in, context->height); /* height (2 bytes) */ + stream_read_uint8(s, channelId); /* channelId (1 byte) */ + stream_read_uint16(s, context->width); /* width (2 bytes) */ + stream_read_uint16(s, context->height); /* height (2 bytes) */ DEBUG_RFX("numChannels %d id %d, %dx%d.", numChannels, channelId, context->width, context->height); } -static void rfx_process_message_context(RFX_CONTEXT* context, STREAM* data_in) +static void rfx_process_message_context(RFX_CONTEXT* context, STREAM* s) { uint8 ctxId; uint16 tileSize; uint16 properties; - stream_read_uint8(data_in, ctxId); /* ctxId (1 byte), must be set to 0x00 */ - stream_read_uint16(data_in, tileSize); /* tileSize (2 bytes), must be set to CT_TILE_64x64 (0x0040) */ - stream_read_uint16(data_in, properties); /* properties (2 bytes) */ + stream_read_uint8(s, ctxId); /* ctxId (1 byte), must be set to 0x00 */ + stream_read_uint16(s, tileSize); /* tileSize (2 bytes), must be set to CT_TILE_64x64 (0x0040) */ + stream_read_uint16(s, properties); /* properties (2 bytes) */ DEBUG_RFX("ctxId %d tileSize %d properties 0x%X.", ctxId, tileSize, properties); @@ -314,28 +314,28 @@ static void rfx_process_message_context(RFX_CONTEXT* context, STREAM* data_in) } } -static void rfx_process_message_frame_begin(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* data_in) +static void rfx_process_message_frame_begin(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { uint32 frameIdx; uint16 numRegions; - stream_read_uint32(data_in, frameIdx); /* frameIdx (4 bytes), if codec is in video mode, must be ignored */ - stream_read_uint16(data_in, numRegions); /* numRegions (2 bytes) */ + stream_read_uint32(s, frameIdx); /* frameIdx (4 bytes), if codec is in video mode, must be ignored */ + stream_read_uint16(s, numRegions); /* numRegions (2 bytes) */ DEBUG_RFX("RFX_FRAME_BEGIN: frameIdx:%d numRegions:%d", frameIdx, numRegions); } -static void rfx_process_message_frame_end(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* data_in) +static void rfx_process_message_frame_end(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { DEBUG_RFX("RFX_FRAME_END"); } -static void rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* data_in) +static void rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; - stream_seek_uint8(data_in); /* regionFlags (1 byte) */ - stream_read_uint16(data_in, message->num_rects); /* numRects (2 bytes) */ + stream_seek_uint8(s); /* regionFlags (1 byte) */ + stream_read_uint16(s, message->num_rects); /* numRects (2 bytes) */ if (message->num_rects < 1) { @@ -352,17 +352,17 @@ static void rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag for (i = 0; i < message->num_rects; i++) { /* RFX_RECT */ - stream_read_uint16(data_in, message->rects[i].x); /* x (2 bytes) */ - stream_read_uint16(data_in, message->rects[i].y); /* y (2 bytes) */ - stream_read_uint16(data_in, message->rects[i].width); /* width (2 bytes) */ - stream_read_uint16(data_in, message->rects[i].height); /* height (2 bytes) */ + stream_read_uint16(s, message->rects[i].x); /* x (2 bytes) */ + stream_read_uint16(s, message->rects[i].y); /* y (2 bytes) */ + stream_read_uint16(s, message->rects[i].width); /* width (2 bytes) */ + stream_read_uint16(s, message->rects[i].height); /* height (2 bytes) */ DEBUG_RFX("rect %d (%d %d %d %d).", i, message->rects[i].x, message->rects[i].y, message->rects[i].width, message->rects[i].height); } } -static void rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREAM* data_in) +static void rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREAM* s) { uint8 quantIdxY; uint8 quantIdxCb; @@ -371,14 +371,14 @@ static void rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREA uint16 YLen, CbLen, CrLen; /* RFX_TILE */ - stream_read_uint8(data_in, quantIdxY); /* quantIdxY (1 byte) */ - stream_read_uint8(data_in, quantIdxCb); /* quantIdxCb (1 byte) */ - stream_read_uint8(data_in, quantIdxCr); /* quantIdxCr (1 byte) */ - stream_read_uint16(data_in, xIdx); /* xIdx (2 bytes) */ - stream_read_uint16(data_in, yIdx); /* yIdx (2 bytes) */ - stream_read_uint16(data_in, YLen); /* YLen (2 bytes) */ - stream_read_uint16(data_in, CbLen); /* CbLen (2 bytes) */ - stream_read_uint16(data_in, CrLen); /* CrLen (2 bytes) */ + stream_read_uint8(s, quantIdxY); /* quantIdxY (1 byte) */ + stream_read_uint8(s, quantIdxCb); /* quantIdxCb (1 byte) */ + stream_read_uint8(s, quantIdxCr); /* quantIdxCr (1 byte) */ + stream_read_uint16(s, xIdx); /* xIdx (2 bytes) */ + stream_read_uint16(s, yIdx); /* yIdx (2 bytes) */ + stream_read_uint16(s, YLen); /* YLen (2 bytes) */ + stream_read_uint16(s, CbLen); /* CbLen (2 bytes) */ + stream_read_uint16(s, CrLen); /* CrLen (2 bytes) */ DEBUG_RFX("quantIdxY:%d quantIdxCb:%d quantIdxCr:%d xIdx:%d yIdx:%d YLen:%d CbLen:%d CrLen:%d", quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx, YLen, CbLen, CrLen); @@ -386,14 +386,14 @@ static void rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREA tile->x = xIdx * 64; tile->y = yIdx * 64; - rfx_decode_rgb(context, data_in, + rfx_decode_rgb(context, s, YLen, context->quants + (quantIdxY * 10), CbLen, context->quants + (quantIdxCb * 10), CrLen, context->quants + (quantIdxCr * 10), tile->data); } -static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* data_in) +static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; uint16 subtype; @@ -404,7 +404,7 @@ static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa uint8 quant; int pos; - stream_read_uint16(data_in, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */ + stream_read_uint16(s, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */ if (subtype != CBT_TILESET) { @@ -412,11 +412,11 @@ static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa return; } - stream_seek_uint16(data_in); /* idx (2 bytes), must be set to 0x0000 */ - stream_seek_uint16(data_in); /* properties (2 bytes) */ + stream_seek_uint16(s); /* idx (2 bytes), must be set to 0x0000 */ + stream_seek_uint16(s); /* properties (2 bytes) */ - stream_read_uint8(data_in, context->num_quants); /* numQuant (1 byte) */ - stream_seek_uint8(data_in); /* tileSize (1 byte), must be set to 0x40 */ + stream_read_uint8(s, context->num_quants); /* numQuant (1 byte) */ + stream_seek_uint8(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->num_quants < 1) { @@ -424,7 +424,7 @@ static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa return; } - stream_read_uint16(data_in, message->num_tiles); /* numTiles (2 bytes) */ + stream_read_uint16(s, message->num_tiles); /* numTiles (2 bytes) */ if (message->num_tiles < 1) { @@ -432,7 +432,7 @@ static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa return; } - stream_read_uint32(data_in, tilesDataSize); /* tilesDataSize (4 bytes) */ + stream_read_uint32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (context->quants != NULL) context->quants = (uint32*) xrealloc((void*) context->quants, context->num_quants * 10 * sizeof(uint32)); @@ -444,19 +444,19 @@ static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa for (i = 0; i < context->num_quants; i++) { /* RFX_CODEC_QUANT */ - stream_read_uint8(data_in, quant); + stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); - stream_read_uint8(data_in, quant); + stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); - stream_read_uint8(data_in, quant); + stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); - stream_read_uint8(data_in, quant); + stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); - stream_read_uint8(data_in, quant); + stream_read_uint8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); @@ -474,10 +474,10 @@ static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa for (i = 0; i < message->num_tiles; i++) { /* RFX_TILE */ - stream_read_uint16(data_in, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ - stream_read_uint32(data_in, blockLen); /* blockLen (4 bytes) */ + stream_read_uint16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ + stream_read_uint32(s, blockLen); /* blockLen (4 bytes) */ - pos = stream_get_pos(data_in) - 6 + blockLen; + pos = stream_get_pos(s) - 6 + blockLen; if (blockType != CBT_TILE) { @@ -485,26 +485,29 @@ static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa break; } - rfx_process_message_tile(context, message->tiles[i], data_in); + rfx_process_message_tile(context, message->tiles[i], s); - stream_set_pos(data_in, pos); + stream_set_pos(s, pos); } } -RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, STREAM* data_in) +RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, uint8* data, uint32 length) { + int pos; + STREAM* s; uint32 blockLen; uint32 blockType; RFX_MESSAGE* message; - int pos; + s = stream_new(0); message = xnew(RFX_MESSAGE); + stream_attach(s, data, length); - while (stream_get_left(data_in) > 6) + while (stream_get_left(s) > 6) { /* RFX_BLOCKT */ - stream_read_uint16(data_in, blockType); /* blockType (2 bytes) */ - stream_read_uint32(data_in, blockLen); /* blockLen (4 bytes) */ + stream_read_uint16(s, blockType); /* blockType (2 bytes) */ + stream_read_uint32(s, blockLen); /* blockLen (4 bytes) */ DEBUG_RFX("blockType 0x%X blockLen %d", blockType, blockLen); @@ -514,48 +517,48 @@ RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, STREAM* data_in) break; } - pos = stream_get_pos(data_in) - 6 + blockLen; + pos = stream_get_pos(s) - 6 + blockLen; if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION) { /* RFX_CODEC_CHANNELT */ /* codecId (1 byte) must be set to 0x01 */ /* channelId (1 byte) must be set to 0x00 */ - stream_seek(data_in, 2); + stream_seek(s, 2); } switch (blockType) { case WBT_SYNC: - rfx_process_message_sync(context, data_in); + rfx_process_message_sync(context, s); break; case WBT_CODEC_VERSIONS: - rfx_process_message_codec_versions(context, data_in); + rfx_process_message_codec_versions(context, s); break; case WBT_CHANNELS: - rfx_process_message_channels(context, data_in); + rfx_process_message_channels(context, s); break; case WBT_CONTEXT: - rfx_process_message_context(context, data_in); + rfx_process_message_context(context, s); break; case WBT_FRAME_BEGIN: - rfx_process_message_frame_begin(context, message, data_in); + rfx_process_message_frame_begin(context, message, s); break; case WBT_FRAME_END: - rfx_process_message_frame_end(context, message, data_in); + rfx_process_message_frame_end(context, message, s); break; case WBT_REGION: - rfx_process_message_region(context, message, data_in); + rfx_process_message_region(context, message, s); break; case WBT_EXTENSION: - rfx_process_message_tileset(context, message, data_in); + rfx_process_message_tileset(context, message, s); break; default: @@ -563,12 +566,35 @@ RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, STREAM* data_in) break; } - stream_set_pos(data_in, pos); + stream_set_pos(s, pos); } + stream_detach(s); + stream_free(s); + return message; } +uint16 rfx_message_get_tile_count(RFX_MESSAGE* message) +{ + return message->num_tiles; +} + +RFX_TILE* rfx_message_get_tile(RFX_MESSAGE* message, int index) +{ + return message->tiles[index]; +} + +uint16 rfx_message_get_rect_count(RFX_MESSAGE* message) +{ + return message->num_rects; +} + +RFX_RECT* rfx_message_get_rect(RFX_MESSAGE* message, int index) +{ + return &message->rects[index]; +} + void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) { if (message != NULL) @@ -585,43 +611,43 @@ void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) } } -static void rfx_compose_message_sync(RFX_CONTEXT* context, STREAM* data_out) +static void rfx_compose_message_sync(RFX_CONTEXT* context, STREAM* s) { - stream_write_uint16(data_out, WBT_SYNC); /* BlockT.blockType */ - stream_write_uint32(data_out, 12); /* BlockT.blockLen */ - stream_write_uint32(data_out, WF_MAGIC); /* magic */ - stream_write_uint16(data_out, WF_VERSION_1_0); /* version */ + stream_write_uint16(s, WBT_SYNC); /* BlockT.blockType */ + stream_write_uint32(s, 12); /* BlockT.blockLen */ + stream_write_uint32(s, WF_MAGIC); /* magic */ + stream_write_uint16(s, WF_VERSION_1_0); /* version */ } -static void rfx_compose_message_codec_versions(RFX_CONTEXT* context, STREAM* data_out) +static void rfx_compose_message_codec_versions(RFX_CONTEXT* context, STREAM* s) { - stream_write_uint16(data_out, WBT_CODEC_VERSIONS); /* BlockT.blockType */ - stream_write_uint32(data_out, 10); /* BlockT.blockLen */ - stream_write_uint8(data_out, 1); /* numCodecs */ - stream_write_uint8(data_out, 1); /* codecs.codecId */ - stream_write_uint16(data_out, WF_VERSION_1_0); /* codecs.version */ + stream_write_uint16(s, WBT_CODEC_VERSIONS); /* BlockT.blockType */ + stream_write_uint32(s, 10); /* BlockT.blockLen */ + stream_write_uint8(s, 1); /* numCodecs */ + stream_write_uint8(s, 1); /* codecs.codecId */ + stream_write_uint16(s, WF_VERSION_1_0); /* codecs.version */ } -static void rfx_compose_message_channels(RFX_CONTEXT* context, STREAM* data_out) +static void rfx_compose_message_channels(RFX_CONTEXT* context, STREAM* s) { - stream_write_uint16(data_out, WBT_CHANNELS); /* BlockT.blockType */ - stream_write_uint32(data_out, 12); /* BlockT.blockLen */ - stream_write_uint8(data_out, 1); /* numChannels */ - stream_write_uint8(data_out, 0); /* Channel.channelId */ - stream_write_uint16(data_out, context->width); /* Channel.width */ - stream_write_uint16(data_out, context->height); /* Channel.height */ + stream_write_uint16(s, WBT_CHANNELS); /* BlockT.blockType */ + stream_write_uint32(s, 12); /* BlockT.blockLen */ + stream_write_uint8(s, 1); /* numChannels */ + stream_write_uint8(s, 0); /* Channel.channelId */ + stream_write_uint16(s, context->width); /* Channel.width */ + stream_write_uint16(s, context->height); /* Channel.height */ } -static void rfx_compose_message_context(RFX_CONTEXT* context, STREAM* data_out) +static void rfx_compose_message_context(RFX_CONTEXT* context, STREAM* s) { uint16 properties; - stream_write_uint16(data_out, WBT_CONTEXT); /* CodecChannelT.blockType */ - stream_write_uint32(data_out, 13); /* CodecChannelT.blockLen */ - stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */ - stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */ - stream_write_uint8(data_out, 0); /* ctxId */ - stream_write_uint16(data_out, CT_TILE_64x64); /* tileSize */ + stream_write_uint16(s, WBT_CONTEXT); /* CodecChannelT.blockType */ + stream_write_uint32(s, 13); /* CodecChannelT.blockLen */ + stream_write_uint8(s, 1); /* CodecChannelT.codecId */ + stream_write_uint8(s, 0); /* CodecChannelT.channelId */ + stream_write_uint8(s, 0); /* ctxId */ + stream_write_uint16(s, CT_TILE_64x64); /* tileSize */ /* properties */ properties = context->flags; /* flags */ @@ -629,7 +655,7 @@ static void rfx_compose_message_context(RFX_CONTEXT* context, STREAM* data_out) properties |= (CLW_XFORM_DWT_53_A << 5); /* xft */ properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 9); /* et */ properties |= (SCALAR_QUANTIZATION << 13); /* qt */ - stream_write_uint16(data_out, properties); + stream_write_uint16(s, properties); /* properties in tilesets: note that this has different format from the one in TS_RFX_CONTEXT */ properties = 1; /* lt */ @@ -641,61 +667,61 @@ static void rfx_compose_message_context(RFX_CONTEXT* context, STREAM* data_out) context->properties = properties; } -void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* data_out) +void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* s) { - stream_check_size(data_out, 12 + 10 + 12 + 13); + stream_check_size(s, 12 + 10 + 12 + 13); - rfx_compose_message_sync(context, data_out); - rfx_compose_message_context(context, data_out); - rfx_compose_message_codec_versions(context, data_out); - rfx_compose_message_channels(context, data_out); + rfx_compose_message_sync(context, s); + rfx_compose_message_context(context, s); + rfx_compose_message_codec_versions(context, s); + rfx_compose_message_channels(context, s); context->header_processed = True; } -static void rfx_compose_message_frame_begin(RFX_CONTEXT* context, STREAM* data_out) +static void rfx_compose_message_frame_begin(RFX_CONTEXT* context, STREAM* s) { - stream_check_size(data_out, 14); + stream_check_size(s, 14); - stream_write_uint16(data_out, WBT_FRAME_BEGIN); /* CodecChannelT.blockType */ - stream_write_uint32(data_out, 14); /* CodecChannelT.blockLen */ - stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */ - stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */ - stream_write_uint32(data_out, context->frame_idx); /* frameIdx */ - stream_write_uint16(data_out, 1); /* numRegions */ + stream_write_uint16(s, WBT_FRAME_BEGIN); /* CodecChannelT.blockType */ + stream_write_uint32(s, 14); /* CodecChannelT.blockLen */ + stream_write_uint8(s, 1); /* CodecChannelT.codecId */ + stream_write_uint8(s, 0); /* CodecChannelT.channelId */ + stream_write_uint32(s, context->frame_idx); /* frameIdx */ + stream_write_uint16(s, 1); /* numRegions */ context->frame_idx++; } -static void rfx_compose_message_region(RFX_CONTEXT* context, STREAM* data_out, +static void rfx_compose_message_region(RFX_CONTEXT* context, STREAM* s, const RFX_RECT* rects, int num_rects) { int size; int i; size = 15 + num_rects * 8; - stream_check_size(data_out, size); + stream_check_size(s, size); - stream_write_uint16(data_out, WBT_REGION); /* CodecChannelT.blockType */ - stream_write_uint32(data_out, size); /* set CodecChannelT.blockLen later */ - stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */ - stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */ - stream_write_uint8(data_out, 1); /* regionFlags */ - stream_write_uint16(data_out, num_rects); /* numRects */ + stream_write_uint16(s, WBT_REGION); /* CodecChannelT.blockType */ + stream_write_uint32(s, size); /* set CodecChannelT.blockLen later */ + stream_write_uint8(s, 1); /* CodecChannelT.codecId */ + stream_write_uint8(s, 0); /* CodecChannelT.channelId */ + stream_write_uint8(s, 1); /* regionFlags */ + stream_write_uint16(s, num_rects); /* numRects */ for (i = 0; i < num_rects; i++) { - stream_write_uint16(data_out, rects[i].x); - stream_write_uint16(data_out, rects[i].y); - stream_write_uint16(data_out, rects[i].width); - stream_write_uint16(data_out, rects[i].height); + stream_write_uint16(s, rects[i].x); + stream_write_uint16(s, rects[i].y); + stream_write_uint16(s, rects[i].width); + stream_write_uint16(s, rects[i].height); } - stream_write_uint16(data_out, CBT_REGION); /* regionType */ - stream_write_uint16(data_out, 1); /* numTilesets */ + stream_write_uint16(s, CBT_REGION); /* regionType */ + stream_write_uint16(s, 1); /* numTilesets */ } -static void rfx_compose_message_tile(RFX_CONTEXT* context, STREAM* data_out, +static void rfx_compose_message_tile(RFX_CONTEXT* context, STREAM* s, uint8* tile_data, int tile_width, int tile_height, int rowstride, const uint32* quantVals, int quantIdxY, int quantIdxCb, int quantIdxCr, int xIdx, int yIdx) @@ -705,39 +731,39 @@ static void rfx_compose_message_tile(RFX_CONTEXT* context, STREAM* data_out, int CrLen = 0; int start_pos, end_pos; - stream_check_size(data_out, 19); - start_pos = stream_get_pos(data_out); + stream_check_size(s, 19); + start_pos = stream_get_pos(s); - stream_write_uint16(data_out, CBT_TILE); /* BlockT.blockType */ - stream_seek_uint32(data_out); /* set BlockT.blockLen later */ - stream_write_uint8(data_out, quantIdxY); - stream_write_uint8(data_out, quantIdxCb); - stream_write_uint8(data_out, quantIdxCr); - stream_write_uint16(data_out, xIdx); - stream_write_uint16(data_out, yIdx); + stream_write_uint16(s, CBT_TILE); /* BlockT.blockType */ + stream_seek_uint32(s); /* set BlockT.blockLen later */ + stream_write_uint8(s, quantIdxY); + stream_write_uint8(s, quantIdxCb); + stream_write_uint8(s, quantIdxCr); + stream_write_uint16(s, xIdx); + stream_write_uint16(s, yIdx); - stream_seek(data_out, 6); /* YLen, CbLen, CrLen */ + stream_seek(s, 6); /* YLen, CbLen, CrLen */ rfx_encode_rgb(context, tile_data, tile_width, tile_height, rowstride, quantVals + quantIdxY * 10, quantVals + quantIdxCb * 10, quantVals + quantIdxCr * 10, - data_out, &YLen, &CbLen, &CrLen); + s, &YLen, &CbLen, &CrLen); DEBUG_RFX("xIdx=%d yIdx=%d width=%d height=%d YLen=%d CbLen=%d CrLen=%d", xIdx, yIdx, tile_width, tile_height, YLen, CbLen, CrLen); - end_pos = stream_get_pos(data_out); + end_pos = stream_get_pos(s); - stream_set_pos(data_out, start_pos + 2); - stream_write_uint32(data_out, 19 + YLen + CbLen + CrLen); /* BlockT.blockLen */ - stream_set_pos(data_out, start_pos + 13); - stream_write_uint16(data_out, YLen); - stream_write_uint16(data_out, CbLen); - stream_write_uint16(data_out, CrLen); + stream_set_pos(s, start_pos + 2); + stream_write_uint32(s, 19 + YLen + CbLen + CrLen); /* BlockT.blockLen */ + stream_set_pos(s, start_pos + 13); + stream_write_uint16(s, YLen); + stream_write_uint16(s, CbLen); + stream_write_uint16(s, CrLen); - stream_set_pos(data_out, end_pos); + stream_set_pos(s, end_pos); } -static void rfx_compose_message_tileset(RFX_CONTEXT* context, STREAM* data_out, +static void rfx_compose_message_tileset(RFX_CONTEXT* context, STREAM* s, uint8* image_data, int width, int height, int rowstride) { int size; @@ -778,80 +804,80 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, STREAM* data_out, numTiles = numTilesX * numTilesY; size = 22 + numQuants * 5; - stream_check_size(data_out, size); - start_pos = stream_get_pos(data_out); + stream_check_size(s, size); + start_pos = stream_get_pos(s); - stream_write_uint16(data_out, WBT_EXTENSION); /* CodecChannelT.blockType */ - stream_seek_uint32(data_out); /* set CodecChannelT.blockLen later */ - stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */ - stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */ - stream_write_uint16(data_out, CBT_TILESET); /* subtype */ - stream_write_uint16(data_out, 0); /* idx */ - stream_write_uint16(data_out, context->properties); /* properties */ - stream_write_uint8(data_out, numQuants); /* numQuants */ - stream_write_uint8(data_out, 0x40); /* tileSize */ - stream_write_uint16(data_out, numTiles); /* numTiles */ - stream_seek_uint32(data_out); /* set tilesDataSize later */ + stream_write_uint16(s, WBT_EXTENSION); /* CodecChannelT.blockType */ + stream_seek_uint32(s); /* set CodecChannelT.blockLen later */ + stream_write_uint8(s, 1); /* CodecChannelT.codecId */ + stream_write_uint8(s, 0); /* CodecChannelT.channelId */ + stream_write_uint16(s, CBT_TILESET); /* subtype */ + stream_write_uint16(s, 0); /* idx */ + stream_write_uint16(s, context->properties); /* properties */ + stream_write_uint8(s, numQuants); /* numQuants */ + stream_write_uint8(s, 0x40); /* tileSize */ + stream_write_uint16(s, numTiles); /* numTiles */ + stream_seek_uint32(s); /* set tilesDataSize later */ quantValsPtr = quantVals; for (i = 0; i < numQuants * 5; i++) { - stream_write_uint8(data_out, quantValsPtr[0] + (quantValsPtr[1] << 4)); + stream_write_uint8(s, quantValsPtr[0] + (quantValsPtr[1] << 4)); quantValsPtr += 2; } DEBUG_RFX("width:%d height:%d rowstride:%d", width, height, rowstride); - end_pos = stream_get_pos(data_out); + end_pos = stream_get_pos(s); for (yIdx = 0; yIdx < numTilesY; yIdx++) { for (xIdx = 0; xIdx < numTilesX; xIdx++) { - rfx_compose_message_tile(context, data_out, + rfx_compose_message_tile(context, s, image_data + yIdx * 64 * rowstride + xIdx * 8 * context->bits_per_pixel, xIdx < numTilesX - 1 ? 64 : width - xIdx * 64, yIdx < numTilesY - 1 ? 64 : height - yIdx * 64, rowstride, quantVals, quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx); } } - tilesDataSize = stream_get_pos(data_out) - end_pos; + tilesDataSize = stream_get_pos(s) - end_pos; size += tilesDataSize; - end_pos = stream_get_pos(data_out); + end_pos = stream_get_pos(s); - stream_set_pos(data_out, start_pos + 2); - stream_write_uint32(data_out, size); /* CodecChannelT.blockLen */ - stream_set_pos(data_out, start_pos + 18); - stream_write_uint32(data_out, tilesDataSize); + stream_set_pos(s, start_pos + 2); + stream_write_uint32(s, size); /* CodecChannelT.blockLen */ + stream_set_pos(s, start_pos + 18); + stream_write_uint32(s, tilesDataSize); - stream_set_pos(data_out, end_pos); + stream_set_pos(s, end_pos); } -static void rfx_compose_message_frame_end(RFX_CONTEXT* context, STREAM* data_out) +static void rfx_compose_message_frame_end(RFX_CONTEXT* context, STREAM* s) { - stream_check_size(data_out, 8); + stream_check_size(s, 8); - stream_write_uint16(data_out, WBT_FRAME_END); /* CodecChannelT.blockType */ - stream_write_uint32(data_out, 8); /* CodecChannelT.blockLen */ - stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */ - stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */ + stream_write_uint16(s, WBT_FRAME_END); /* CodecChannelT.blockType */ + stream_write_uint32(s, 8); /* CodecChannelT.blockLen */ + stream_write_uint8(s, 1); /* CodecChannelT.codecId */ + stream_write_uint8(s, 0); /* CodecChannelT.channelId */ } -static void rfx_compose_message_data(RFX_CONTEXT* context, STREAM* data_out, +static void rfx_compose_message_data(RFX_CONTEXT* context, STREAM* s, const RFX_RECT* rects, int num_rects, uint8* image_data, int width, int height, int rowstride) { - rfx_compose_message_frame_begin(context, data_out); - rfx_compose_message_region(context, data_out, rects, num_rects); - rfx_compose_message_tileset(context, data_out, image_data, width, height, rowstride); - rfx_compose_message_frame_end(context, data_out); + rfx_compose_message_frame_begin(context, s); + rfx_compose_message_region(context, s, rects, num_rects); + rfx_compose_message_tileset(context, s, image_data, width, height, rowstride); + rfx_compose_message_frame_end(context, s); } -FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, STREAM* data_out, +FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, STREAM* s, const RFX_RECT* rects, int num_rects, uint8* image_data, int width, int height, int rowstride) { /* Only the first frame should send the RemoteFX header */ if (context->frame_idx == 0 && !context->header_processed) - rfx_compose_message_header(context, data_out); + rfx_compose_message_header(context, s); - rfx_compose_message_data(context, data_out, rects, num_rects, image_data, width, height, rowstride); + rfx_compose_message_data(context, s, rects, num_rects, image_data, width, height, rowstride); }