}
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;
}
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;
}
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;
}
#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)))
{
}
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;
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;
rdpGraphics* graphics;
rdpGlyphCache* glyph_cache;
rdpGlyph* glyph;
+ RDP_RECT bound;
if (!context || !data || !context->graphics || !context->cache
|| !context->cache->glyph)
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)
{
/**
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)
{
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;
}
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;
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;
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];
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];
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;
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;
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;
{
rdpGlyph* glyph;
WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCacheGet: id: %d index: %d", id,
- index);
+ index);
if (id > 9)
{
}
BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index,
- rdpGlyph* glyph)
+ rdpGlyph* glyph)
{
rdpGlyph* prevGlyph;
}
WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCachePut: id: %d index: %d", id,
- index);
+ index);
prevGlyph = glyphCache->glyphCache[id].entries[index];
if (prevGlyph)
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;
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);
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)
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));