Fixed some more glyph chache bugs.
authorArmin Novak <armin.novak@thincast.com>
Wed, 17 Aug 2016 07:26:59 +0000 (09:26 +0200)
committerArmin Novak <armin.novak@thincast.com>
Thu, 6 Oct 2016 11:43:11 +0000 (13:43 +0200)
client/X11/xf_graphics.c
include/freerdp/graphics.h
libfreerdp/cache/glyph.c
libfreerdp/gdi/graphics.c

index ce63207..0e162dc 100644 (file)
@@ -355,15 +355,29 @@ static void xf_Glyph_Free(rdpContext* context, rdpGlyph* glyph)
 }
 
 static BOOL xf_Glyph_Draw(rdpContext* context, const rdpGlyph* glyph, UINT32 x,
-                          UINT32 y, BOOL fOpRedundant)
+                          UINT32 y, UINT32 w, UINT32 h, UINT32 sx, UINT32 sy,
+                          BOOL fOpRedundant)
 {
        xfGlyph* xf_glyph;
        xfContext* xfc = (xfContext*) context;
        xf_glyph = (xfGlyph*) glyph;
        xf_lock_x11(xfc, FALSE);
+
+       if (!fOpRedundant)
+       {
+               XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
+               XFillRectangle(xfc->display, xfc->drawable, xfc->gc, x, y, w, h);
+       }
+
+       XSetFillStyle(xfc->display, xfc->gc, FillStippled);
        XSetStipple(xfc->display, xfc->gc, xf_glyph->pixmap);
+
+       if (sx || sy)
+               WLog_ERR(TAG, "");
+
+       //XSetClipOrigin(xfc->display, xfc->gc, sx, sy);
        XSetTSOrigin(xfc->display, xfc->gc, x, y);
-       XFillRectangle(xfc->display, xfc->drawing, xfc->gc, x, y, glyph->cx, glyph->cy);
+       XFillRectangle(xfc->display, xfc->drawing, xfc->gc, x, y, w, h);
        xf_unlock_x11(xfc, FALSE);
        return TRUE;
 }
@@ -386,11 +400,18 @@ static BOOL xf_Glyph_BeginDraw(rdpContext* context, UINT32 x, UINT32 y,
        rect.width = width;
        rect.height = height;
        xf_lock_x11(xfc, FALSE);
+
+       if (!fOpRedundant)
+       {
+               XSetForeground(xfc->display, xfc->gc, fgcolor);
+               XSetBackground(xfc->display, xfc->gc, fgcolor);
+               XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
+               XClearArea(xfc->display, xfc->drawable, xfc->gc, x, y, width, height);
+               XFillRectangle(xfc->display, xfc->drawable, xfc->gc, x, y, width, height);
+       }
+
        XSetForeground(xfc->display, xfc->gc, bgcolor);
        XSetBackground(xfc->display, xfc->gc, fgcolor);
-       XSetFillStyle(xfc->display, xfc->gc,
-                     fOpRedundant ? FillOpaqueStippled : FillStippled);
-       XFillRectangle(xfc->display, xfc->drawable, xfc->gc, x, y, width, height);
        xf_unlock_x11(xfc, FALSE);
        return TRUE;
 }
@@ -408,16 +429,9 @@ static BOOL xf_Glyph_EndDraw(rdpContext* context, UINT32 x, UINT32 y,
        if (!xf_decode_color(context->gdi, fgcolor, &fgcolor, NULL))
                return FALSE;
 
-       xf_lock_x11(xfc, FALSE);
-       XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
-       XSetForeground(xfc->display, xfc->gc, fgcolor);
-       XSetBackground(xfc->display, xfc->gc, bgcolor);
-       XFillRectangle(xfc->display, xfc->drawable, xfc->gc, x, y, width, height);
-
        if (xfc->drawing == xfc->primary)
                ret = gdi_InvalidateRegion(xfc->hdc, x, y, width, height);
 
-       xf_unlock_x11(xfc, FALSE);
        return ret;
 }
 
index a4d1b74..6bf534c 100644 (file)
@@ -119,7 +119,8 @@ FREERDP_API rdpPointer* Pointer_Alloc(rdpContext* context);
 typedef BOOL (*pGlyph_New)(rdpContext* context, const rdpGlyph* glyph);
 typedef void (*pGlyph_Free)(rdpContext* context, rdpGlyph* glyph);
 typedef BOOL (*pGlyph_Draw)(rdpContext* context, const rdpGlyph* glyph,
-                            UINT32 x, UINT32 y, BOOL fOpRedundant);
+                            UINT32 x, UINT32 y, UINT32 w, UINT32 h,
+                            UINT32 sx, UINT32 sy, BOOL fOpRedundant);
 typedef BOOL (*pGlyph_BeginDraw)(rdpContext* context, UINT32 x, UINT32 y,
                                  UINT32 width, UINT32 height, UINT32 bgcolor,
                                  UINT32 fgcolor, BOOL fOpRedundant);
index 11fadce..5a90515 100644 (file)
 #define TAG FREERDP_TAG("cache.glyph")
 
 static rdpGlyph* glyph_cache_get(rdpGlyphCache* glyph_cache, UINT32 id,
-                                 UINT32 index);
+                                UINT32 index);
 static BOOL glyph_cache_put(rdpGlyphCache* glyph_cache, UINT32 id, UINT32 index,
-                            rdpGlyph* entry);
+                           rdpGlyph* entry);
 
-static void* glyph_cache_fragment_get(rdpGlyphCache* glyph, UINT32 index,
-                                      UINT32* count);
-static void glyph_cache_fragment_put(rdpGlyphCache* glyph, UINT32 index,
-                                     UINT32 count, void* entry);
+static const void* glyph_cache_fragment_get(rdpGlyphCache* glyph, UINT32 index,
+       UINT32* count);
+static BOOL glyph_cache_fragment_put(rdpGlyphCache* glyph, UINT32 index,
+                                    UINT32 count, const void* entry);
 
 static UINT32 update_glyph_offset(const BYTE* data, UINT32 index, INT32* x,
-                                  INT32* y, UINT32 ulCharInc, UINT32 flAccel)
+                                 INT32* y, UINT32 ulCharInc, UINT32 flAccel)
 {
        if ((ulCharInc == 0) && (!(flAccel & SO_CHAR_INC_EQUAL_BM_BASE)))
        {
@@ -67,9 +67,12 @@ static UINT32 update_glyph_offset(const BYTE* data, UINT32 index, INT32* x,
 }
 
 static BOOL update_process_glyph(rdpContext* context, const BYTE* data,
-                                 UINT32 cacheIndex, INT32* x, INT32* y,
-                                 UINT32 cacheId, UINT32 flAccel, BOOL fOpRedundant)
+                                UINT32 cacheIndex, INT32* x, INT32* y,
+                                UINT32 cacheId, UINT32 flAccel, BOOL fOpRedundant,
+                                const RDP_RECT* bound)
 {
+       INT32 sx = 0, sy = 0;
+       INT32 dx, dy;
        rdpGlyph* glyph;
        rdpGraphics* graphics;
        rdpGlyphCache* glyph_cache;
@@ -85,29 +88,56 @@ static BOOL update_process_glyph(rdpContext* context, const BYTE* data,
        if (!glyph)
                return FALSE;
 
-       if (glyph != NULL)
+       dx = glyph->x + *x;
+       dy = glyph->y + *y;
+
+       if (dx < bound->x)
        {
-               if (!glyph->Draw(context, glyph, glyph->x + *x, glyph->y + *y, fOpRedundant))
-                       return FALSE;
+               sx = bound->x - dx;
+               dx = bound->x;
+       }
 
-               if (flAccel & SO_CHAR_INC_EQUAL_BM_BASE)
-                       *x += glyph->cx;
+       if (dy < bound->y)
+       {
+               sy = bound->y - dy;
+               dy = bound->y;
        }
 
+       if ((dx <= (bound->x + bound->width)) && (dy <= (bound->y + bound->height)))
+       {
+               INT32 dw = glyph->cx - sx;
+               INT32 dh = glyph->cy - sy;
+
+               if ((dw + dx) > (bound->x + bound->width))
+                       dw = (bound->x + bound->width) - (dw + dx);
+
+               if ((dh + dy) > (bound->y + bound->height))
+                       dh = (bound->y + bound->height) - (dh + dy);
+
+               if ((dh > 0) && (dw > 0))
+               {
+                       if (!glyph->Draw(context, glyph, dx, dy, dw, dh, sx, sy, fOpRedundant))
+                               return FALSE;
+               }
+       }
+
+       if (flAccel & SO_CHAR_INC_EQUAL_BM_BASE)
+               *x += glyph->cx;
+
        return TRUE;
 }
 
 static BOOL update_process_glyph_fragments(rdpContext* context,
-        const BYTE* data,
-        UINT32 length, UINT32 cacheId,
-        UINT32 ulCharInc, UINT32 flAccel,
-        UINT32 bgcolor, UINT32 fgcolor,
-        INT32 x, INT32 y,
-        INT32 bkX, INT32 bkY,
-        INT32 bkWidth, INT32 bkHeight,
-        INT32 opX, INT32 opY,
-        INT32 opWidth, INT32 opHeight,
-        BOOL fOpRedundant)
+       const BYTE* data,
+       UINT32 length, UINT32 cacheId,
+       UINT32 ulCharInc, UINT32 flAccel,
+       UINT32 bgcolor, UINT32 fgcolor,
+       INT32 x, INT32 y,
+       INT32 bkX, INT32 bkY,
+       INT32 bkWidth, INT32 bkHeight,
+       INT32 opX, INT32 opY,
+       INT32 opWidth, INT32 opHeight,
+       BOOL fOpRedundant)
 {
        UINT32 n;
        UINT32 id;
@@ -117,6 +147,7 @@ static BOOL update_process_glyph_fragments(rdpContext* context,
        rdpGraphics* graphics;
        rdpGlyphCache* glyph_cache;
        rdpGlyph* glyph;
+       RDP_RECT bound;
 
        if (!context || !data || !context->graphics || !context->cache
            || !context->cache->glyph)
@@ -129,6 +160,44 @@ static BOOL update_process_glyph_fragments(rdpContext* context,
        if (!glyph)
                return FALSE;
 
+       /* Limit op rectangle to vislble screen. */
+       if (opX < 0)
+       {
+               opWidth += opX;
+               opX = 0;
+       }
+
+       if (opY < 0)
+       {
+               opHeight += opY;
+               opY = 0;
+       }
+
+       if (opWidth < 0)
+               opWidth = 0;
+
+       if (opHeight < 0)
+               opHeight = 0;
+
+       /* Limit bk rectangle to vislble screen. */
+       if (bkX < 0)
+       {
+               bkWidth += bkX;
+               bkX = 0;
+       }
+
+       if (bkY < 0)
+       {
+               bkHeight += bkY;
+               bkY = 0;
+       }
+
+       if (bkWidth < 0)
+               bkWidth = 0;
+
+       if (bkHeight < 0)
+               bkHeight = 0;
+
        if (opX + opWidth > context->settings->DesktopWidth)
        {
                /**
@@ -143,8 +212,27 @@ static BOOL update_process_glyph_fragments(rdpContext* context,
                opWidth = context->settings->DesktopWidth - opX;
        }
 
+       if (bkX + bkWidth > context->settings->DesktopWidth)
+       {
+               /**
+                * Some Microsoft servers send erroneous high values close to the
+                * sint16 maximum in the OpRight field of the GlyphIndex, FastIndex and
+                * FastGlyph drawing orders, probably a result of applications trying to
+                * clear the text line to the very right end.
+                * One example where this can be seen is typing in notepad.exe within
+                * a RDP session to Windows XP Professional SP3.
+                * This workaround prevents resulting problems in the UI callbacks.
+                */
+               bkWidth = context->settings->DesktopWidth - bkX;
+       }
+
+       bound.x = bkX;
+       bound.y = bkY;
+       bound.width = bkWidth;
+       bound.height = bkHeight;
+
        if (!glyph->BeginDraw(context, opX, opY, opWidth, opHeight, bgcolor, fgcolor,
-                             fOpRedundant))
+                             fOpRedundant))
                return FALSE;
 
        while (index < length)
@@ -155,54 +243,40 @@ static BOOL update_process_glyph_fragments(rdpContext* context,
                {
                        case GLYPH_FRAGMENT_USE:
                                if (index + 1 > length)
-                               {
-                                       /* at least one byte need to follow */
-                                       index = length = 0;
-                                       break;
-                               }
+                                       return FALSE;
 
                                id = data[index++];
                                fragments = (BYTE*) glyph_cache_fragment_get(glyph_cache, id, &size);
 
-                               if (fragments != NULL)
+                               if (fragments == NULL)
+                                       return FALSE;
+
+                               for (n = 0; n < size;)
                                {
-                                       for (n = 0; n < size;)
-                                       {
-                                               const UINT32 fop = fragments[n++];
-                                               n = update_glyph_offset(fragments, n, &x, &y, ulCharInc, flAccel);
-
-                                               if (!update_process_glyph(context, fragments, fop, &x, &y, cacheId,
-                                                                         flAccel, fOpRedundant))
-                                                       return FALSE;
-                                       }
+                                       const UINT32 fop = fragments[n++];
+                                       n = update_glyph_offset(fragments, n, &x, &y, ulCharInc, flAccel);
+
+                                       if (!update_process_glyph(context, fragments, fop, &x, &y, cacheId,
+                                                                 flAccel, fOpRedundant, &bound))
+                                               return FALSE;
                                }
 
                                break;
 
                        case GLYPH_FRAGMENT_ADD:
                                if (index + 2 > length)
-                               {
-                                       /* at least two bytes need to follow */
-                                       index = length = 0;
-                                       break;
-                               }
+                                       return FALSE;
 
                                id = data[index++];
                                size = data[index++];
-                               fragments = (BYTE*) malloc(size);
-
-                               if (!fragments)
-                                       return FALSE;
-
-                               CopyMemory(fragments, data, size);
-                               glyph_cache_fragment_put(glyph_cache, id, size, fragments);
+                               glyph_cache_fragment_put(glyph_cache, id, size, data);
                                break;
 
                        default:
                                index = update_glyph_offset(data, index, &x, &y, ulCharInc, flAccel);
 
                                if (!update_process_glyph(context, data, op, &x, &y, cacheId, flAccel,
-                                                         fOpRedundant))
+                                                         fOpRedundant, &bound))
                                        return FALSE;
 
                                break;
@@ -213,7 +287,7 @@ static BOOL update_process_glyph_fragments(rdpContext* context,
 }
 
 static BOOL update_gdi_glyph_index(rdpContext* context,
-                                   GLYPH_INDEX_ORDER* glyphIndex)
+                                  GLYPH_INDEX_ORDER* glyphIndex)
 {
        rdpGlyphCache* glyph_cache;
        INT32 bkWidth = 0, bkHeight = 0, opWidth = 0, opHeight = 0;
@@ -236,16 +310,16 @@ static BOOL update_gdi_glyph_index(rdpContext* context,
                opHeight = glyphIndex->opBottom - glyphIndex->opTop + 1;
 
        return update_process_glyph_fragments(context, glyphIndex->data,
-                                             glyphIndex->cbData,
-                                             glyphIndex->cacheId, glyphIndex->ulCharInc, glyphIndex->flAccel,
-                                             glyphIndex->backColor, glyphIndex->foreColor, glyphIndex->x, glyphIndex->y,
-                                             glyphIndex->bkLeft, glyphIndex->bkTop, bkWidth, bkHeight,
-                                             glyphIndex->opLeft, glyphIndex->opTop, opWidth, opHeight,
-                                             glyphIndex->fOpRedundant);
+                                             glyphIndex->cbData,
+                                             glyphIndex->cacheId, glyphIndex->ulCharInc, glyphIndex->flAccel,
+                                             glyphIndex->backColor, glyphIndex->foreColor, glyphIndex->x, glyphIndex->y,
+                                             glyphIndex->bkLeft, glyphIndex->bkTop, bkWidth, bkHeight,
+                                             glyphIndex->opLeft, glyphIndex->opTop, opWidth, opHeight,
+                                             glyphIndex->fOpRedundant);
 }
 
 static BOOL update_gdi_fast_index(rdpContext* context,
-                                  const FAST_INDEX_ORDER* fastIndex)
+                                 const FAST_INDEX_ORDER* fastIndex)
 {
        INT32 x, y;
        INT32 opLeft, opTop;
@@ -313,15 +387,15 @@ static BOOL update_gdi_fast_index(rdpContext* context,
                opHeight = opBottom - opTop + 1;
 
        return update_process_glyph_fragments(context, fastIndex->data,
-                                             fastIndex->cbData,
-                                             fastIndex->cacheId, fastIndex->ulCharInc, fastIndex->flAccel,
-                                             fastIndex->backColor, fastIndex->foreColor, x, y,
-                                             fastIndex->bkLeft, fastIndex->bkTop, bkWidth, bkHeight,
-                                             opLeft, opTop, opWidth, opHeight, FALSE);
+                                             fastIndex->cbData,
+                                             fastIndex->cacheId, fastIndex->ulCharInc, fastIndex->flAccel,
+                                             fastIndex->backColor, fastIndex->foreColor, x, y,
+                                             fastIndex->bkLeft, fastIndex->bkTop, bkWidth, bkHeight,
+                                             opLeft, opTop, opWidth, opHeight, FALSE);
 }
 
 static BOOL update_gdi_fast_glyph(rdpContext* context,
-                                  const FAST_GLYPH_ORDER* fastGlyph)
+                                 const FAST_GLYPH_ORDER* fastGlyph)
 {
        INT32 x, y;
        BYTE text_data[2];
@@ -385,13 +459,18 @@ static BOOL update_gdi_fast_glyph(rdpContext* context,
                        return FALSE;
 
                glyph = Glyph_Alloc(context, glyphData->x, glyphData->y, glyphData->cx,
-                                   glyphData->cy,
-                                   glyphData->cb, glyphData->aj);
+                                   glyphData->cy,
+                                   glyphData->cb, glyphData->aj);
 
                if (!glyph)
                        return FALSE;
 
-               glyph_cache_put(cache->glyph, fastGlyph->cacheId, fastGlyph->data[0], glyph);
+               if (!glyph_cache_put(cache->glyph, fastGlyph->cacheId, fastGlyph->data[0],
+                                    glyph))
+               {
+                       glyph->Free(context, glyph);
+                       return FALSE;
+               }
        }
 
        text_data[0] = fastGlyph->data[0];
@@ -410,15 +489,15 @@ static BOOL update_gdi_fast_glyph(rdpContext* context,
                opHeight = opBottom - opTop + 1;
 
        return update_process_glyph_fragments(context, text_data, 1,
-                                             fastGlyph->cacheId, fastGlyph->ulCharInc, fastGlyph->flAccel,
-                                             fastGlyph->backColor, fastGlyph->foreColor, x, y,
-                                             fastGlyph->bkLeft, fastGlyph->bkTop,
-                                             bkWidth, bkHeight, opLeft, opTop,
-                                             opWidth, opHeight, FALSE);
+                                             fastGlyph->cacheId, fastGlyph->ulCharInc, fastGlyph->flAccel,
+                                             fastGlyph->backColor, fastGlyph->foreColor, x, y,
+                                             fastGlyph->bkLeft, fastGlyph->bkTop,
+                                             bkWidth, bkHeight, opLeft, opTop,
+                                             opWidth, opHeight, FALSE);
 }
 
 static BOOL update_gdi_cache_glyph(rdpContext* context,
-                                   const CACHE_GLYPH_ORDER* cacheGlyph)
+                                  const CACHE_GLYPH_ORDER* cacheGlyph)
 {
        UINT32 i;
        rdpCache* cache;
@@ -437,22 +516,26 @@ static BOOL update_gdi_cache_glyph(rdpContext* context,
                        return FALSE;
 
                if (!(glyph = Glyph_Alloc(context, glyph_data->x,
-                                         glyph_data->y,
-                                         glyph_data->cx,
-                                         glyph_data->cy,
-                                         glyph_data->cb,
-                                         glyph_data->aj)))
+                                         glyph_data->y,
+                                         glyph_data->cx,
+                                         glyph_data->cy,
+                                         glyph_data->cb,
+                                         glyph_data->aj)))
                        return FALSE;
 
-               glyph_cache_put(cache->glyph, cacheGlyph->cacheId, glyph_data->cacheIndex,
-                               glyph);
+               if (!glyph_cache_put(cache->glyph, cacheGlyph->cacheId, glyph_data->cacheIndex,
+                                    glyph))
+               {
+                       glyph->Free(context, glyph);
+                       return FALSE;
+               }
        }
 
        return TRUE;
 }
 
 static BOOL update_gdi_cache_glyph_v2(rdpContext* context,
-                                      const CACHE_GLYPH_V2_ORDER* cacheGlyphV2)
+                                     const CACHE_GLYPH_V2_ORDER* cacheGlyphV2)
 {
        UINT32 i;
        rdpCache* cache;
@@ -471,17 +554,21 @@ static BOOL update_gdi_cache_glyph_v2(rdpContext* context,
                        return FALSE;
 
                glyph = Glyph_Alloc(context, glyphData->x,
-                                   glyphData->y,
-                                   glyphData->cx,
-                                   glyphData->cy,
-                                   glyphData->cb,
-                                   glyphData->aj);
+                                   glyphData->y,
+                                   glyphData->cx,
+                                   glyphData->cy,
+                                   glyphData->cb,
+                                   glyphData->aj);
 
                if (!glyph)
                        return FALSE;
 
-               glyph_cache_put(cache->glyph, cacheGlyphV2->cacheId, glyphData->cacheIndex,
-                               glyph);
+               if (!glyph_cache_put(cache->glyph, cacheGlyphV2->cacheId, glyphData->cacheIndex,
+                                    glyph))
+               {
+                       glyph->Free(context, glyph);
+                       return FALSE;
+               }
        }
 
        return TRUE;
@@ -491,7 +578,7 @@ rdpGlyph* glyph_cache_get(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index)
 {
        rdpGlyph* glyph;
        WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCacheGet: id: %d index: %d", id,
-                  index);
+                  index);
 
        if (id > 9)
        {
@@ -514,7 +601,7 @@ rdpGlyph* glyph_cache_get(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index)
 }
 
 BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index,
-                     rdpGlyph* glyph)
+                    rdpGlyph* glyph)
 {
        rdpGlyph* prevGlyph;
 
@@ -531,7 +618,7 @@ BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index,
        }
 
        WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCachePut: id: %d index: %d", id,
-                  index);
+                  index);
        prevGlyph = glyphCache->glyphCache[id].entries[index];
 
        if (prevGlyph)
@@ -541,8 +628,8 @@ BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index,
        return TRUE;
 }
 
-void* glyph_cache_fragment_get(rdpGlyphCache* glyphCache, UINT32 index,
-                               UINT32* size)
+const void* glyph_cache_fragment_get(rdpGlyphCache* glyphCache, UINT32 index,
+                                    UINT32* size)
 {
        void* fragment;
 
@@ -555,7 +642,7 @@ void* glyph_cache_fragment_get(rdpGlyphCache* glyphCache, UINT32 index,
        fragment = glyphCache->fragCache.entries[index].fragment;
        *size = (BYTE) glyphCache->fragCache.entries[index].size;
        WLog_Print(glyphCache->log, WLOG_DEBUG,
-                  "GlyphCacheFragmentGet: index: %d size: %d", index, *size);
+                  "GlyphCacheFragmentGet: index: %d size: %d", index, *size);
 
        if (!fragment)
                WLog_ERR(TAG, "invalid glyph fragment at index:%d", index);
@@ -563,23 +650,31 @@ void* glyph_cache_fragment_get(rdpGlyphCache* glyphCache, UINT32 index,
        return fragment;
 }
 
-void glyph_cache_fragment_put(rdpGlyphCache* glyphCache, UINT32 index,
-                              UINT32 size, void* fragment)
+BOOL glyph_cache_fragment_put(rdpGlyphCache* glyphCache, UINT32 index,
+                             UINT32 size, const void* fragment)
 {
        void* prevFragment;
+       void* copy;
 
        if (index > 255)
        {
                WLog_ERR(TAG, "invalid glyph cache fragment index: %d", index);
-               return;
+               return FALSE;
        }
 
+       copy = malloc(size);
+
+       if (!copy)
+               return FALSE;
+
        WLog_Print(glyphCache->log, WLOG_DEBUG,
-                  "GlyphCacheFragmentPut: index: %d size: %d", index, size);
+                  "GlyphCacheFragmentPut: index: %d size: %d", index, size);
+       CopyMemory(copy, fragment, size);
        prevFragment = glyphCache->fragCache.entries[index].fragment;
-       glyphCache->fragCache.entries[index].fragment = fragment;
+       glyphCache->fragCache.entries[index].fragment = copy;
        glyphCache->fragCache.entries[index].size = size;
        free(prevFragment);
+       return TRUE;
 }
 
 void glyph_cache_register_callbacks(rdpUpdate* update)
@@ -610,7 +705,7 @@ rdpGlyphCache* glyph_cache_new(rdpSettings* settings)
                        glyphCache->glyphCache[i].maxCellSize =
                            settings->GlyphCache[i].cacheMaximumCellSize;
                        glyphCache->glyphCache[i].entries = (rdpGlyph**) calloc(
-                                                               glyphCache->glyphCache[i].number, sizeof(rdpGlyph*));
+                                                               glyphCache->glyphCache[i].number, sizeof(rdpGlyph*));
                }
 
                glyphCache->fragCache.entries = calloc(256, sizeof(FRAGMENT_CACHE_ENTRY));
index 0bc4070..c4333fd 100644 (file)
@@ -255,7 +255,7 @@ static void gdi_Glyph_Free(rdpContext* context, rdpGlyph* glyph)
 }
 
 static BOOL gdi_Glyph_Draw(rdpContext* context, const rdpGlyph* glyph, UINT32 x,
-                           UINT32 y, BOOL fOpRedundant)
+                           UINT32 y, UINT32 w, UINT32 h, UINT32 sx, UINT32 sy, BOOL fOpRedundant)
 {
        gdiGlyph* gdi_glyph;
        rdpGdi* gdi;
@@ -267,14 +267,42 @@ static BOOL gdi_Glyph_Draw(rdpContext* context, const rdpGlyph* glyph, UINT32 x,
 
        gdi = context->gdi;
        gdi_glyph = (gdiGlyph*) glyph;
+
+       if (!fOpRedundant && 0)
+       {
+               GDI_RECT rect = { 0 };
+
+               if (x > 0)
+                       rect.left = x;
+
+               if (y > 0)
+                       rect.top = y;
+
+               if (x + w > 0)
+                       rect.right = x + w - 1;
+
+               if (y + h > 0)
+                       rect.bottom = y + h - 1;
+
+               if ((rect.left < rect.right) && (rect.top < rect.bottom))
+               {
+                       brush = gdi_CreateSolidBrush(gdi->drawing->hdc->bkColor);
+
+                       if (!brush)
+                               return FALSE;
+
+                       gdi_FillRect(gdi->drawing->hdc, &rect, brush);
+                       gdi_DeleteObject((HGDIOBJECT)brush);
+               }
+       }
+
        brush = gdi_CreateSolidBrush(gdi->drawing->hdc->textColor);
 
        if (!brush)
                return FALSE;
 
        gdi_SelectObject(gdi->drawing->hdc, (HGDIOBJECT)brush);
-       rc = gdi_BitBlt(gdi->drawing->hdc, x, y, gdi_glyph->bitmap->width,
-                       gdi_glyph->bitmap->height, gdi_glyph->hdc, 0, 0,
+       rc = gdi_BitBlt(gdi->drawing->hdc, x, y, w, h, gdi_glyph->hdc, sx, sy,
                        GDI_GLYPH_ORDER, &context->gdi->palette);
        gdi_DeleteObject((HGDIOBJECT)brush);
        return rc;
@@ -303,7 +331,7 @@ static BOOL gdi_Glyph_BeginDraw(rdpContext* context, UINT32 x, UINT32 y,
        gdi_SetTextColor(gdi->drawing->hdc, bgcolor);
        gdi_SetBkColor(gdi->drawing->hdc, fgcolor);
 
-       if (!fOpRedundant)
+       if (1)
        {
                GDI_RECT rect = { 0 };
                HGDI_BRUSH brush = gdi_CreateSolidBrush(fgcolor);
@@ -317,13 +345,12 @@ static BOOL gdi_Glyph_BeginDraw(rdpContext* context, UINT32 x, UINT32 y,
                if (y > 0)
                        rect.top = y;
 
-               if (x + width > 0)
-                       rect.right = x + width - 1;
+               rect.right = x + width - 1;
+               rect.bottom = y + height - 1;
 
-               if (y + height > 0)
-                       rect.bottom = y + height - 1;
+               if ((x + width > rect.left) && (y + height > rect.top))
+                       gdi_FillRect(gdi->drawing->hdc, &rect, brush);
 
-               gdi_FillRect(gdi->drawing->hdc, &rect, brush);
                gdi_DeleteObject((HGDIOBJECT)brush);
        }