diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index f7f3c227c..a13e8f2b5 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) 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/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/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 49fcdf789..0fb7f6968 100644 --- a/libfreerdp-core/certificate.c +++ b/libfreerdp-core/certificate.c @@ -278,8 +278,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-gdi/gdi.c b/libfreerdp-gdi/gdi.c index 61c111f02..341b15e8f 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); } }