Hand-apply patches (glyph cache) from Authentic8 branch: 653869c 30f23d4 74b015d 4e51e6d 2829087

ulab-next
Jim Grandy 11 years ago
parent 1ae9a7f2b6
commit 45b0bc9f17

@ -40,13 +40,15 @@ struct xrdp_pen
int color;
};
/* 2.2.2.2.1.2.5.1 Cache Glyph Data (TS_CACHE_GLYPH_DATA) */
struct xrdp_font_char
{
int offset;
int baseline;
int width;
int height;
int offset; /* x */
int baseline; /* y */
int width; /* cx */
int height; /* cy */
int incby;
int bpp;
char* data;
};

@ -2020,15 +2020,25 @@ xrdp_orders_send_font(struct xrdp_orders *self,
int order_flags = 0;
int datasize = 0;
int len = 0;
int flags;
datasize = FONT_DATASIZE(font_char);
if (font_char->bpp == 8) /* alpha font */
{
datasize = ((font_char->width + 3) & ~3) * font_char->height;
flags = 8 | 0x4000;
}
else
{
datasize = FONT_DATASIZE(font_char);
flags = 8;
}
xrdp_orders_check(self, datasize + 18);
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
len = (datasize + 12) - 7; /* length after type minus 7 */
out_uint16_le(self->out_s, len);
out_uint16_le(self->out_s, 8); /* flags */
out_uint16_le(self->out_s, flags);
out_uint8(self->out_s, RDP_ORDER_FONTCACHE); /* type */
out_uint8(self->out_s, font_index);
out_uint8(self->out_s, 1); /* num of chars */

@ -13,7 +13,7 @@ rdpPolylines.o rdpPolySegment.o rdpFillSpans.o rdpSetSpans.o \
rdpCopyPlane.o rdpPolyPoint.o rdpPolyArc.o rdpFillPolygon.o \
rdpPolyFillArc.o rdpPolyText8.o rdpPolyText16.o \
rdpImageText8.o rdpImageText16.o rdpImageGlyphBlt.o rdpPolyGlyphBlt.o \
rdpPushPixels.o rdpxv.o \
rdpPushPixels.o rdpxv.o rdpglyph.o \
miinitext.o \
fbcmap_mi.o

@ -95,6 +95,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define PixelDPI 100
#define PixelToMM(_size) (((_size) * 254 + (PixelDPI) * 5) / ((PixelDPI) * 10))
#define TAG_COMPOSITE 0
#define TAG_COPYAREA 1
#define TAG_POLYFILLRECT 2
#define TAG_PUTIMAGE 3
#define TAG_POLYRECTANGLE 4
#define TAG_COPYPLANE 5
#define TAG_POLYARC 6
#define TAG_FILLPOLYGON 7
#define TAG_POLYFILLARC 8
#define TAG_IMAGETEXT8 9
#define TAG_POLYTEXT8 10
#define TAG_POLYTEXT16 11
#define TAG_IMAGETEXT16 12
#define TAG_IMAGEGLYPHBLT 13
#define TAG_POLYGLYPHBLT 14
#define TAG_PUSHPIXELS 15
struct image_data
{
int width;
@ -144,6 +161,8 @@ struct _rdpScreenInfoRec
CopyWindowProcPtr CopyWindow;
ClearToBackgroundProcPtr ClearToBackground;
ScreenWakeupHandlerProcPtr WakeupHandler;
CreatePictureProcPtr CreatePicture;
DestroyPictureProcPtr DestroyPicture;
CompositeProcPtr Composite;
GlyphsProcPtr Glyphs;
/* Backing store procedures */
@ -200,6 +219,7 @@ typedef rdpWindowRec* rdpWindowPtr;
#define RDI_IMGLY 3 /* lossy */
#define RDI_LINE 4
#define RDI_SCRBLT 5
define RDI_TEXT 6
struct urdp_draw_item_fill
{
@ -236,6 +256,13 @@ struct urdp_draw_item_scrblt
int cy;
};
struct urdp_draw_item_text
{
int opcode;
int fg_color;
struct rdp_text* rtext; /* in rdpglyph.h */
};
union urdp_draw_item
{
struct urdp_draw_item_fill fill;
@ -246,7 +273,7 @@ union urdp_draw_item
struct rdp_draw_item
{
int type;
int type; /* RDI_FILL, RDI_IMGLL, ... */
int flags;
struct rdp_draw_item* prev;
struct rdp_draw_item* next;
@ -327,6 +354,8 @@ void
hexdump(unsigned char *p, unsigned int len);
void
RegionAroundSegs(RegionPtr reg, xSegment* segs, int nseg);
int
get_crc(char* data, int data_bytes);
/* rdpdraw.c */
Bool
@ -355,6 +384,9 @@ int
draw_item_add_srcblt_region(rdpPixmapRec* priv, RegionPtr reg,
int srcx, int srcy, int dstx, int dsty,
int cx, int cy);
int
draw_item_add_text_region(rdpPixmapRec* priv, RegionPtr reg, int color,
int opcode, struct rdp_text* rtext);
PixmapPtr
rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
@ -413,6 +445,10 @@ rdpDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
void
rdpRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor,
Bool displayed);
int
rdpCreatePicture(PicturePtr pPicture);
void
rdpDestroyPicture(PicturePtr pPicture);
void
rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
@ -523,6 +559,19 @@ int
rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec* pDirtyPriv);
int
rdpup_check_dirty_screen(rdpPixmapRec* pDirtyPriv);
int
rdpup_add_char(int font, int charactor, short x, short y, int cx, int cy,
char* bmpdata, int bmpdata_bytes);
int
rdpup_add_char_alpha(int font, int charactor, short x, short y, int cx, int cy,
char* bmpdata, int bmpdata_bytes);
int
rdpup_draw_text(int font, int flags, int mixmode,
short clip_left, short clip_top,
short clip_right, short clip_bottom,
short box_left, short box_top,
short box_right, short box_bottom, short x, short y,
char* data, int data_bytes);
void
rdpScheduleDeferredUpdate(void);

@ -472,6 +472,8 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
}
}
LLOGLN(10, ("rdpCopyArea: fallback"));
/* do original call */
rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
@ -553,7 +555,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 1);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COPYAREA);
RegionUninit(&reg1);
}
else if (got_id)
@ -577,7 +579,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
box.y2 = box.y1 + h;
RegionInit(&box_reg, &box, 0);
RegionIntersect(&clip_reg, &clip_reg, &box_reg);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 1);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, TAG_COPYAREA);
RegionUninit(&box_reg);
}
else if (got_id)

@ -168,7 +168,7 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 5);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COPYPLANE);
RegionUninit(&reg1);
}
else if (got_id)
@ -194,7 +194,7 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
RegionInit(&reg2, NullBox, 0);
RegionCopy(&reg2, &clip_reg);
RegionIntersect(&reg1, &reg1, &reg2);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 5);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COPYPLANE);
RegionUninit(&reg1);
RegionUninit(&reg2);
}

@ -203,7 +203,7 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 7);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_FILLPOLYGON);
RegionUninit(&reg1);
}
else if (got_id)
@ -223,7 +223,7 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 7);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, TAG_FILLPOLYGON);
}
else if (got_id)
{

@ -169,7 +169,7 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 13);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_IMAGEGLYPHBLT);
RegionUninit(&reg1);
}
else if (got_id)
@ -189,7 +189,7 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 13);
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_IMAGEGLYPHBLT);
}
else if (got_id)
{

@ -167,7 +167,7 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 12);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_IMAGETEXT16);
RegionUninit(&reg1);
}
else if (got_id)
@ -187,7 +187,7 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 12);
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_IMAGETEXT16);
}
else if (got_id)
{

@ -167,7 +167,7 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 9);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_IMAGETEXT8);
RegionUninit(&reg1);
}
else if (got_id)
@ -187,7 +187,7 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 9);
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_IMAGETEXT8);
}
else if (got_id)
{

@ -185,7 +185,7 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, 6);
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYARC);
}
else if (got_id)
{
@ -217,7 +217,7 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, 6);
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYARC);
}
else if (got_id)
{

@ -185,7 +185,7 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, 8);
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYFILLARC);
}
else if (got_id)
{
@ -217,7 +217,7 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, 8);
draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYFILLARC);
}
else if (got_id)
{

@ -192,7 +192,7 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
}
else
{
draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, RDI_IMGLL, 2);
draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, RDI_IMGLL, TAG_POLYFILLRECT);
}
}
else if (got_id)
@ -256,8 +256,7 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
}
else
{
LLOGLN(10, ("rdpPolyFillRect: 4"));
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, RDI_IMGLL, 2);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, RDI_IMGLL, TAG_POLYFILLRECT);
}
}
else if (got_id)

@ -169,7 +169,7 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 14);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_POLYGLYPHBLT);
RegionUninit(&reg1);
}
else if (got_id)
@ -189,7 +189,7 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 14);
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_POLYGLYPHBLT);
}
else if (got_id)
{

@ -221,7 +221,7 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
}
else
{
draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, dirty_type, 4);
draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, dirty_type, TAG_POLYRECTANGLE);
}
RegionDestroy(fill_reg);
@ -275,7 +275,7 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
}
else
{
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 4);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, TAG_POLYRECTANGLE);
}
}
else if (got_id)

@ -170,7 +170,7 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 11);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_POLYTEXT16);
RegionUninit(&reg1);
}
else if (got_id)
@ -190,7 +190,7 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 11);
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_POLYTEXT16);
}
else if (got_id)
{

@ -170,7 +170,7 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 10);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_POLYTEXT8);
RegionUninit(&reg1);
}
else if (got_id)
@ -190,7 +190,7 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 10);
draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_POLYTEXT8);
}
else if (got_id)
{

@ -160,7 +160,7 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 15);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_PUSHPIXELS);
RegionUninit(&reg1);
}
else if (got_id)
@ -185,7 +185,7 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 15);
draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, TAG_PUSHPIXELS);
RegionUninit(&reg1);
}
else if (got_id)

@ -163,7 +163,7 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 3);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_PUTIMAGE);
RegionUninit(&reg1);
}
else if (got_id)
@ -185,7 +185,7 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
RegionInit(&reg2, NullBox, 0);
RegionCopy(&reg2, &clip_reg);
RegionIntersect(&reg1, &reg1, &reg2);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 3);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_PUTIMAGE);
RegionUninit(&reg1);
RegionUninit(&reg2);
}

@ -45,6 +45,7 @@ Xserver drawing ops and funcs
#include "rdpImageGlyphBlt.h"
#include "rdpPolyGlyphBlt.h"
#include "rdpPushPixels.h"
#include "rdpglyph.h"
#define LOG_LEVEL 1
#define LLOG(_level, _args) \
@ -65,6 +66,7 @@ extern int g_do_dirty_os; /* in rdpmain.c */
extern int g_do_dirty_ons; /* in rdpmain.c */
extern rdpPixmapRec g_screenPriv; /* in rdpmain.c */
extern int g_con_number; /* in rdpmain.c */
extern int g_do_glyph_cache; /* in rdpmain.c */
ColormapPtr g_rdpInstalledColormap;
@ -458,6 +460,11 @@ draw_item_remove(rdpPixmapRec *priv, struct rdp_draw_item *di)
g_free(di->u.line.segs);
}
}
if (di->type == RDI_TEXT)
{
delete_rdp_text(di->u.text.rtext);
}
RegionDestroy(di->reg);
g_free(di);
@ -481,6 +488,51 @@ draw_item_remove_all(rdpPixmapRec *priv)
return 0;
}
/******************************************************************************/
int
region_get_pixel_count(RegionPtr reg)
{
int index;
int count;
int pixels;
int width;
int height;
BoxRec box;
pixels = 0;
count = REGION_NUM_RECTS(reg);
for (index = 0; index < count; index++)
{
box = REGION_RECTS(reg)[index];
width = box.x2 - box.x1;
height = box.y2 - box.y1;
pixels += width * height;
}
return pixels;
}
/******************************************************************************/
int
region_in_region(RegionPtr reg_small, int sreg_pcount, RegionPtr reg_big)
{
int rv;
RegionRec reg;
rv = 0;
RegionInit(&reg, NullBox, 0);
RegionIntersect(&reg, reg_small, reg_big);
if (sreg_pcount == -1)
{
sreg_pcount = region_get_pixel_count(reg_small);
}
if (region_get_pixel_count(&reg) == sreg_pcount)
{
rv = 1;
}
RegionUninit(&reg);
return rv;
}
/******************************************************************************/
int
draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
@ -488,7 +540,25 @@ draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
struct rdp_draw_item *di;
struct rdp_draw_item *di_prev;
RegionRec treg;
BoxRec box;
#if 1
box.x1 = 0;
box.x2 = pix->drawable.width;
box.y1 = 0;
box.y2 = pix->drawable.height;
RegionInit(&treg, &box, 0);
di = priv->draw_item_head;
di_prev = 0;
while (di != 0)
{
RegionIntersect(di->reg, di->reg, &treg);
di_prev = di;
di = di->next;
}
RegionUninit(&treg);
#endif
#if 1
/* look for repeating draw types */
@ -501,17 +571,19 @@ draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
while (di != 0)
{
if ((di_prev->type == RDI_IMGLL || di_prev->type == RDI_IMGLY ||
di_prev->type == RDI_FILL) &&
(di->type == RDI_IMGLL || di->type == RDI_IMGLY ||
di->type == RDI_FILL))
if ((di_prev->type == RDI_IMGLL) && (di->type == RDI_IMGLL))
{
LLOGLN(10, ("draw_item_pack: packing RDI_IMGLL / RDI_IMGLY / "
"RDI_FILL"));
LLOGLN(10, ("draw_item_pack: packing RDI_IMGLL"));
RegionUnion(di_prev->reg, di_prev->reg, di->reg);
draw_item_remove(priv, di);
di = di_prev->next;
}
else if ((di_prev->type == RDI_IMGLY) && (di->type == RDI_IMGLY))
{
LLOGLN(10, ("draw_item_pack: packing RDI_IMGLY"));
RegionUnion(di_prev->reg, di_prev->reg, di->reg);
draw_item_remove(priv, di);
di = di_prev->next;
di_prev->type = RDI_IMGLL;
}
else
{
@ -545,15 +617,11 @@ draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
while (di_prev != 0)
{
/* D = M - S */
RegionInit(&treg, NullBox, 0);
RegionSubtract(&treg, di_prev->reg, di->reg);
if (!RegionNotEmpty(&treg))
if (region_in_region(di_prev->reg, -1, di->reg))
{
/* copy empty region so this draw item will get removed below */
RegionCopy(di_prev->reg, &treg);
/* empty region so this draw item will get removed below */
RegionEmpty(di_prev->reg);
}
RegionUninit(&treg);
di_prev = di_prev->prev;
}
}
@ -698,6 +766,25 @@ draw_item_add_srcblt_region(rdpPixmapRec *priv, RegionPtr reg,
return 0;
}
/******************************************************************************/
int
draw_item_add_text_region(rdpPixmapRec* priv, RegionPtr reg, int color,
int opcode, struct rdp_text* rtext)
{
struct rdp_draw_item* di;
LLOGLN(10, ("draw_item_add_text_region:"));
di = (struct rdp_draw_item*)g_malloc(sizeof(struct rdp_draw_item), 1);
di->type = RDI_TEXT;
di->u.text.fg_color = color;
di->u.text.opcode = opcode;
di->u.text.rtext = rtext;
di->reg = RegionCreate(NullBox, 0);
RegionCopy(di->reg, reg);
draw_item_add(priv, di);
return 0;
}
/******************************************************************************/
PixmapPtr
rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
@ -1299,7 +1386,57 @@ rdpSaveScreen(ScreenPtr pScreen, int on)
}
/******************************************************************************/
/* it looks like all the antialias draws go through here */
int
rdpCreatePicture(PicturePtr pPicture)
{
PictureScreenPtr ps;
int rv;
LLOGLN(10, ("rdpCreatePicture:"));
ps = GetPictureScreen(g_pScreen);
ps->CreatePicture = g_rdpScreen.CreatePicture;
rv = ps->CreatePicture(pPicture);
ps->CreatePicture = rdpCreatePicture;
return rv;
}
/******************************************************************************/
void
rdpDestroyPicture(PicturePtr pPicture)
{
PictureScreenPtr ps;
LLOGLN(10, ("rdpDestroyPicture:"));
ps = GetPictureScreen(g_pScreen);
ps->DestroyPicture = g_rdpScreen.DestroyPicture;
ps->DestroyPicture(pPicture);
ps->DestroyPicture = rdpDestroyPicture;
}
/******************************************************************************/
/* it looks like all the antialias draws go through here
op is one of the following
#define PictOpMinimum 0
#define PictOpClear 0
#define PictOpSrc 1
#define PictOpDst 2
#define PictOpOver 3
#define PictOpOverReverse 4
#define PictOpIn 5
#define PictOpInReverse 6
#define PictOpOut 7
#define PictOpOutReverse 8
#define PictOpAtop 9
#define PictOpAtopReverse 10
#define PictOpXor 11
#define PictOpAdd 12
#define PictOpSaturate 13
#define PictOpMaximum 13
see for porter duff
http://www.svgopen.org/2005/papers/abstractsvgopen/
*/
void
rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
@ -1323,12 +1460,20 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
struct image_data id;
LLOGLN(10, ("rdpComposite:"));
ps = GetPictureScreen(g_pScreen);
ps->Composite = g_rdpScreen.Composite;
ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc,
xMask, yMask, xDst, yDst, width, height);
ps->Composite = rdpComposite;
if (g_doing_font == 2)
{
return;
}
LLOGLN(10, ("rdpComposite: op %d %p %p %p w %d h %d", op, pSrc, pMask, pDst, width, height));
p = pDst->pDrawable;
dirty_type = 0;
@ -1409,7 +1554,7 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
if (dirty_type != 0)
{
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COMPOSITE);
}
else if (got_id)
{
@ -1442,7 +1587,7 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 0);
draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COMPOSITE);
RegionUninit(&reg1);
}
else if (got_id)
@ -1467,26 +1612,31 @@ rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
GlyphPtr *glyphs)
{
PictureScreenPtr ps;
int index;
LLOGLN(10, ("rdpGlyphs:"));
LLOGLN(10, ("rdpGlyphs: nlists %d len %d", nlists, lists->len));
rdpup_set_hints(1, 1);
g_doing_font = 1;
LLOGLN(10, ("rdpGlyphs: op %d xSrc %d ySrc %d", op, xSrc, ySrc));
for (index = 0; index < lists->len; index++)
if (g_do_glyph_cache)
{
LLOGLN(10, (" index %d size %d refcnt %d width %d height %d",
index, (int)(glyphs[index]->size), (int)(glyphs[index]->refcnt),
glyphs[index]->info.width, glyphs[index]->info.height));
g_doing_font = 2;
ps = GetPictureScreen(g_pScreen);
ps->Glyphs = g_rdpScreen.Glyphs;
ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc,
nlists, lists, glyphs);
ps->Glyphs = rdpGlyphs;
rdpGlypht(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlists, lists, glyphs);
}
else
{
g_doing_font = 1;
rdpup_set_hints(1, 1);
ps = GetPictureScreen(g_pScreen);
ps->Glyphs = g_rdpScreen.Glyphs;
ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc,
nlists, lists, glyphs);
ps->Glyphs = rdpGlyphs;
rdpup_set_hints(0, 1);
}
ps = GetPictureScreen(g_pScreen);
ps->Glyphs = g_rdpScreen.Glyphs;
ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc,
nlists, lists, glyphs);
ps->Glyphs = rdpGlyphs;
rdpup_set_hints(0, 1);
g_doing_font = 0;
LLOGLN(10, ("rdpGlyphs: out"));
}

@ -0,0 +1,773 @@
/*
Copyright 2012 Jay Sorg
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
http://msdn.microsoft.com/en-us/library/cc241863(v=prot.20).aspx
4.6.1 "d" Character
This topic has not yet been rated - Rate this topic
The following shows glyph image data (1 bpp format) for character
"d" extracted from a Cache Glyph (Revision 2) (section 2.2.2.2.1.2.6)
Secondary Drawing Order.
Glyph width = 5 pixels
Glyph height = 9 pixels
Glyph origin = (0, -9), marked with an "X" on the image grid
Bitmap = { 0x08, 0x08, 0x08, 0x78, 0x88, 0x88, 0x88, 0x88, 0x78 }
http://msdn.microsoft.com/en-us/library/cc241864(v=prot.20).aspx
4.6.2 "p" Character
This topic has not yet been rated - Rate this topic
The following shows glyph image data (1 bpp format) for character
"p" extracted from a Cache Glyph (Revision 2) (section 2.2.2.2.1.2.6)
Secondary Drawing Order.
Glyph width = 5 pixels
Glyph height = 8 pixels
Glyph origin = (0, -6), marked with an "X" on the image grid
Bitmap = { 0xF0, 0x88, 0x88, 0x88, 0x88, 0xF0, 0x80, 0x80 }
*/
#include "rdp.h"
#include "rdpdraw.h"
#include "rdpglyph.h"
extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
extern int g_do_alpha_glyphs; /* in rdpmain.c */
#define LOG_LEVEL 1
#define LLOG(_level, _args) \
do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0)
#define LLOGLN(_level, _args) \
do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
struct font_cache
{
int offset;
int baseline;
int width;
int height;
int crc;
int stamp;
};
static struct font_cache g_font_cache[12][256];
static int g_stamp = 0;
/*****************************************************************************/
static void
set_mono_pixel(char* data, int x, int y, int width, int pixel)
{
int start;
int shift;
width = (width + 7) / 8;
start = (y * width) + x / 8;
shift = x % 8;
if (pixel != 0)
{
data[start] = data[start] | (0x80 >> shift);
}
else
{
data[start] = data[start] & ~(0x80 >> shift);
}
}
/******************************************************************************/
static int
glyph_get_data(ScreenPtr pScreen, GlyphPtr glyph, struct rdp_font_char* rfd)
{
int i;
int j;
int src_xoff;
int src_yoff;
int stride_bytes;
int hh;
int ww;
int ss;
int depth;
unsigned char pixel;
PicturePtr pPicture;
pixman_image_t *src;
uint32_t* pi32;
char* pi8;
pPicture = GlyphPicture(glyph)[pScreen->myNum];
if (pPicture == 0)
{
return 0;
}
src = image_from_pict(pPicture, FALSE, &src_xoff, &src_yoff);
if (src == 0)
{
return 0;
}
depth = pixman_image_get_depth(src);
stride_bytes = pixman_image_get_stride(src);
ww = pixman_image_get_width(src);
hh = pixman_image_get_height(src);
ss = (glyph->info.width + 3) & ~3;
if ((ww != glyph->info.width) || (hh != glyph->info.height) ||
(depth != 8) || (stride_bytes != ss))
{
LLOGLN(10, ("glyph_get_data: error w %d w %d h %d h %d "
"stride %d stride %d depth %d", ww,
glyph->info.width, hh, glyph->info.height,
stride_bytes, ss, depth));
free_pixman_pict(pPicture, src);
return 0;
}
if (g_do_alpha_glyphs)
{
rfd->data_bytes = glyph->info.height * stride_bytes;
rfd->bpp = 8;
}
else
{
rfd->data_bytes = (((glyph->info.height *
((glyph->info.width + 7) / 8)) + 3) & ~3);
rfd->bpp = 1;
}
rfd->data = (char*)g_malloc(rfd->data_bytes, 1);
rfd->offset = -glyph->info.x;
rfd->baseline = -glyph->info.y;
rfd->width = glyph->info.width;
rfd->height = glyph->info.height;
pi32 = pixman_image_get_data(src);
pi8 = (char*)pi32;
for (j = 0; j < rfd->height; j++)
{
for (i = 0; i < rfd->width; i++)
{
pixel = pi8[j * stride_bytes + i];
if (g_do_alpha_glyphs)
{
rfd->data[j * stride_bytes + i] = pixel;
}
else
{
if (pixel > 0x7f)
{
set_mono_pixel(rfd->data, i, j, rfd->width, 1);
}
else
{
set_mono_pixel(rfd->data, i, j, rfd->width, 0);
}
}
}
}
free_pixman_pict(pPicture, src);
return 0;
}
/******************************************************************************/
struct rdp_text*
create_rdp_text(ScreenPtr pScreen, int nlists, GlyphListPtr lists,
GlyphPtr* glyphs)
{
struct rdp_text* rv;
struct rdp_text* rtext;
struct rdp_text* last_rtext;
BoxRec box;
RegionRec reg1;
int n;
int lxoff;
int lyoff;
int count;
int lx;
int ly;
int font_index;
int max_height;
int min_height;
int force_new;
GlyphPtr glyph;
struct rdp_font_char* rfd;
LLOGLN(10, ("create_rdp_text: nlists %d", nlists));
max_height = 0;
min_height = 0x7fffffff;
lx = lists->xOff;
ly = lists->yOff;
lxoff = 0;
lyoff = 0;
force_new = 0;
rtext = (struct rdp_text*)g_malloc(sizeof(struct rdp_text), 1);
rtext->reg = RegionCreate(NullBox, 0);
rtext->flags = 3;
rtext->mixmode = 0;
rtext->x = lx;
rtext->y = ly;
rv = rtext;
last_rtext = rtext;
count = 0;
while (nlists--)
{
LLOGLN(10, ("lists->xOff %d lists->yOff %d", lists->xOff, lists->yOff));
if (count != 0)
{
lx += lists->xOff;
ly += lists->yOff;
force_new = 1;
}
count++;
n = lists->len;
lists++;
while (n--)
{
glyph = *glyphs++;
/* process glyph here */
if ((glyph->info.width > 0) && (glyph->info.height > 0))
{
if (force_new)
{
LLOGLN(10, ("create_rdp_text: too many chars"));
force_new = 0;
rtext = (struct rdp_text*)g_malloc(sizeof(struct rdp_text), 1);
rtext->reg = RegionCreate(NullBox, 0);
rtext->flags = 3;
rtext->mixmode = 0;
rtext->x = lx;
rtext->y = ly;
last_rtext->next = rtext;
last_rtext = rtext;
lxoff = 0;
lyoff = 0;
}
LLOGLN(10, ("x %d y %d width %d height %d xOff %d yOff %d "
"num_chars %d lxoff %d lyoff %d lx %d ly %d",
glyph->info.x, glyph->info.y,
glyph->info.width, glyph->info.height,
glyph->info.xOff, glyph->info.yOff, rtext->num_chars,
lxoff, lyoff, lx, ly));
rfd = (struct rdp_font_char*)g_malloc(sizeof(struct rdp_font_char), 1);
rtext->chars[rtext->num_chars] = rfd;
box.x1 = lx - glyph->info.x;
box.y1 = ly - glyph->info.y;
box.x2 = box.x1 + glyph->info.width;
box.y2 = box.y1 + glyph->info.height;
if (glyph->info.height > max_height)
{
max_height = glyph->info.height;
}
if (glyph->info.height < min_height)
{
min_height = glyph->info.height;
}
RegionInit(&reg1, &box, 0);
RegionUnion(rtext->reg, &reg1, rtext->reg);
RegionUninit(&reg1);
glyph_get_data(pScreen, glyph, rfd);
rfd->incby = lxoff;
lxoff = glyph->info.xOff;
lyoff = glyph->info.yOff;
rtext->num_chars++;
if (rtext->num_chars > 63)
{
force_new = 1;
}
}
else
{
lxoff += glyph->info.xOff;
lyoff += glyph->info.yOff;
}
lx += glyph->info.xOff;
ly += glyph->info.yOff;
}
}
if (max_height > 10)
{
font_index = 8;
}
else if (max_height < 7)
{
font_index = 6;
}
else
{
font_index = 7;
}
LLOGLN(10, ("create_rdp_text: min_height %d max_height %d font_index %d",
min_height, max_height, font_index));
rtext = rv;
while (rtext != 0)
{
rtext->font = font_index;
rtext = rtext->next;
}
return rv;
}
/******************************************************************************/
int
delete_rdp_text(struct rdp_text* rtext)
{
int index;
if (rtext == 0)
{
return 0;
}
for (index = 0; index < rtext->num_chars; index++)
{
if (rtext->chars[index] != 0)
{
g_free(rtext->chars[index]->data);
g_free(rtext->chars[index]);
}
}
RegionDestroy(rtext->reg);
delete_rdp_text(rtext->next);
g_free(rtext);
return 0;
}
/******************************************************************************/
static int
get_color(PicturePtr pPicture)
{
int src_xoff;
int src_yoff;
int rv;
uint32_t* pi32;
pixman_image_t *src;
src = image_from_pict(pPicture, FALSE, &src_xoff, &src_yoff);
if (src == 0)
{
return 0;
}
pi32 = pixman_image_get_data(src);
rv = *pi32;
LLOGLN(10, ("get_color: 0x%8.8x width %d height %d ", rv,
pixman_image_get_width(src),
pixman_image_get_height(src)));
free_pixman_pict(pPicture, src);
return rv;
}
/******************************************************************************/
static int
find_or_add_char(int font, struct rdp_font_char* rfd)
{
int crc;
int index;
int char_index;
int oldest;
crc = get_crc(rfd->data, rfd->data_bytes);
LLOGLN(10, ("find_or_add_char: crc 0x%8.8x", crc));
char_index = 0;
oldest = 0x7fffffff;
for (index = 0; index < 250; index++)
{
if ((g_font_cache[font][index].crc == crc) &&
(g_font_cache[font][index].width == rfd->width) &&
(g_font_cache[font][index].height == rfd->height) &&
(g_font_cache[font][index].offset == rfd->offset) &&
(g_font_cache[font][index].baseline == rfd->baseline))
{
g_stamp++;
g_font_cache[font][index].stamp = g_stamp;
LLOGLN(10, ("find_or_add_char: found char at %d %d", font, index));
return index;
}
if (g_font_cache[font][index].stamp < oldest)
{
oldest = g_font_cache[font][index].stamp;
char_index = index;
}
}
g_stamp++;
g_font_cache[font][char_index].stamp = g_stamp;
g_font_cache[font][char_index].crc = crc;
g_font_cache[font][char_index].width = rfd->width;
g_font_cache[font][char_index].height = rfd->height;
g_font_cache[font][char_index].offset = rfd->offset;
g_font_cache[font][char_index].baseline = rfd->baseline;
LLOGLN(10, ("find_or_add_char: adding char at %d %d", font, char_index));
if (rfd->bpp == 8)
{
rdpup_add_char_alpha(font, char_index, rfd->offset, rfd->baseline,
rfd->width, rfd->height,
rfd->data, rfd->data_bytes);
}
else
{
rdpup_add_char(font, char_index, rfd->offset, rfd->baseline,
rfd->width, rfd->height,
rfd->data, rfd->data_bytes);
}
return char_index;
}
/******************************************************************************/
int
rdp_text_chars_to_data(struct rdp_text* rtext)
{
int index;
int data_bytes;
int char_index;
struct rdp_font_char* rfd;
LLOGLN(10, ("rdp_text_chars_to_data: rtext->num_chars %d", rtext->num_chars));
data_bytes = 0;
for (index = 0; index < rtext->num_chars; index++)
{
rfd = rtext->chars[index];
if (rfd == 0)
{
LLOGLN(0, ("rdp_text_chars_to_data: error rfd is nil"));
continue;
}
char_index = find_or_add_char(rtext->font, rfd);
rtext->data[data_bytes] = char_index;
data_bytes++;
if (rfd->incby > 127)
{
rtext->data[data_bytes] = 0x80;
data_bytes++;
rtext->data[data_bytes] = (rfd->incby >> 0) & 0xff;
data_bytes++;
rtext->data[data_bytes] = (rfd->incby >> 8) & 0xff;
data_bytes++;
}
else
{
rtext->data[data_bytes] = rfd->incby;
data_bytes++;
}
}
rtext->data_bytes = data_bytes;
return 0;
}
/******************************************************************************/
/*
typedef struct _GlyphList {
INT16 xOff;
INT16 yOff;
CARD8 len;
PictFormatPtr format;
} GlyphListRec, *GlyphListPtr;
*/
/* see ghyphstr.h but the follow is not in there
typedef struct _XGlyphInfo {
unsigned short width;
unsigned short height;
short x;
short y;
short xOff;
short yOff;
} XGlyphInfo;
*/
static void
rdpGlyphu(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int nlists, GlyphListPtr lists, GlyphPtr* glyphs,
BoxPtr extents)
{
BoxRec box;
RegionRec reg1;
RegionRec reg2;
DrawablePtr p;
int dirty_type;
int j;
int num_clips;
int post_process;
int reset_surface;
int got_id;
int fg_color;
WindowPtr pDstWnd;
PixmapPtr pDstPixmap;
rdpPixmapRec* pDstPriv;
rdpPixmapRec* pDirtyPriv;
struct image_data id;
struct rdp_text* rtext;
struct rdp_text* trtext;
LLOGLN(10, ("rdpGlyphu: xSrc %d ySrc %d", xSrc, ySrc));
p = pDst->pDrawable;
dirty_type = 0;
pDirtyPriv = 0;
post_process = 0;
reset_surface = 0;
got_id = 0;
if (p->type == DRAWABLE_PIXMAP)
{
pDstPixmap = (PixmapPtr)p;
pDstPriv = GETPIXPRIV(pDstPixmap);
if (XRDP_IS_OS(pDstPriv))
{
post_process = 1;
if (g_do_dirty_os)
{
LLOGLN(10, ("rdpGlyphu: gettig dirty"));
pDstPriv->is_dirty = 1;
dirty_type = RDI_IMGLL;
pDirtyPriv = pDstPriv;
}
else
{
rdpup_switch_os_surface(pDstPriv->rdpindex);
reset_surface = 1;
rdpup_get_pixmap_image_rect(pDstPixmap, &id);
got_id = 1;
LLOGLN(10, ("rdpGlyphu: offscreen"));
}
}
}
else
{
if (p->type == DRAWABLE_WINDOW)
{
pDstWnd = (WindowPtr)p;
if (pDstWnd->viewable)
{
post_process = 1;
rdpup_get_screen_image_rect(&id);
got_id = 1;
LLOGLN(10, ("rdpGlyphu: screen"));
}
}
}
if (!post_process)
{
return;
}
rtext = create_rdp_text(pDst->pDrawable->pScreen, nlists, lists, glyphs);
if (rtext == 0)
{
LLOGLN(0, ("rdpGlyphu: create_rdp_text failed"));
return;
}
fg_color = get_color(pSrc);
LLOGLN(10, ("rdpGlyphu: pDst->clientClipType %d pCompositeClip %p",
pDst->clientClipType, pDst->pCompositeClip));
if (pDst->pCompositeClip != 0)
{
box.x1 = p->x + extents->x1;
box.y1 = p->y + extents->y1;
box.x2 = p->x + extents->x2;
box.y2 = p->y + extents->y2;
RegionInit(&reg1, &box, 0);
RegionInit(&reg2, NullBox, 0);
RegionCopy(&reg2, pDst->pCompositeClip);
RegionIntersect(&reg1, &reg1, &reg2);
if (dirty_type != 0)
{
LLOGLN(10, ("1"));
draw_item_add_text_region(pDirtyPriv, &reg1, fg_color, GXcopy, rtext);
rtext = 0;
}
else if (got_id)
{
num_clips = REGION_NUM_RECTS(&reg1);
if (num_clips > 0)
{
LLOGLN(10, (" num_clips %d", num_clips));
rdpup_begin_update();
rdpup_set_fgcolor(fg_color);
trtext = rtext;
while (trtext != 0)
{
rdp_text_chars_to_data(trtext);
for (j = num_clips - 1; j >= 0; j--)
{
box = REGION_RECTS(&reg1)[j];
LLOGLN(10, ("2"));
rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
LLOGLN(10, ("rdpGlyphu: rdpup_draw_text"));
box = RegionExtents(trtext->reg)[0];
rdpup_draw_text(trtext->font, trtext->flags, trtext->mixmode,
box.x1 + p->x, box.y1 + p->y,
box.x2 + p->x, box.y2 + p->y,
//box.x1 + p->x, box.y1 + p->y,
//box.x2 + p->x, box.y2 + p->y,
0, 0, 0, 0,
trtext->x + p->x, trtext->y + p->y,
trtext->data, trtext->data_bytes);
}
trtext = trtext->next;
}
rdpup_reset_clip();
rdpup_end_update();
}
}
RegionUninit(&reg1);
RegionUninit(&reg2);
}
else
{
box.x1 = p->x + extents->x1;
box.y1 = p->y + extents->y1;
box.x2 = p->x + extents->x2;
box.y2 = p->y + extents->y2;
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
LLOGLN(10, ("3"));
draw_item_add_text_region(pDirtyPriv, &reg1, fg_color, GXcopy, rtext);
rtext = 0;
RegionUninit(&reg1);
}
else if (got_id)
{
rdpup_begin_update();
LLOGLN(10, ("4"));
rdpup_set_fgcolor(fg_color);
trtext = rtext;
while (trtext != 0)
{
LLOGLN(10, ("rdpGlyphu: rdpup_draw_text"));
rdp_text_chars_to_data(trtext);
box = RegionExtents(trtext->reg)[0];
rdpup_draw_text(trtext->font, trtext->flags, trtext->mixmode,
box.x1 + p->x, box.y1 + p->y,
box.x2 + p->x, box.y2 + p->y,
//box.x1 + p->x, box.y1 + p->y,
//box.x2 + p->x, box.y2 + p->y,
0, 0, 0, 0,
trtext->x + p->x, trtext->y + p->y,
trtext->data, trtext->data_bytes);
trtext = trtext->next;
}
rdpup_end_update();
}
}
if (reset_surface)
{
rdpup_switch_os_surface(-1);
}
delete_rdp_text(rtext);
}
/******************************************************************************/
static void
GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr* glyphs, BoxPtr extents)
{
int x1;
int x2;
int y1;
int y2;
int n;
int x;
int y;
GlyphPtr glyph;
x = 0;
y = 0;
extents->x1 = MAXSHORT;
extents->x2 = MINSHORT;
extents->y1 = MAXSHORT;
extents->y2 = MINSHORT;
while (nlist--)
{
x += list->xOff;
y += list->yOff;
n = list->len;
list++;
while (n--)
{
glyph = *glyphs++;
x1 = x - glyph->info.x;
if (x1 < MINSHORT)
{
x1 = MINSHORT;
}
y1 = y - glyph->info.y;
if (y1 < MINSHORT)
{
y1 = MINSHORT;
}
x2 = x1 + glyph->info.width;
if (x2 > MAXSHORT)
{
x2 = MAXSHORT;
}
y2 = y1 + glyph->info.height;
if (y2 > MAXSHORT)
{
y2 = MAXSHORT;
}
if (x1 < extents->x1)
{
extents->x1 = x1;
}
if (x2 > extents->x2)
{
extents->x2 = x2;
}
if (y1 < extents->y1)
{
extents->y1 = y1;
}
if (y2 > extents->y2)
{
extents->y2 = y2;
}
x += glyph->info.xOff;
y += glyph->info.yOff;
}
}
}
/******************************************************************************/
void
rdpGlypht(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int nlists, GlyphListPtr lists, GlyphPtr* glyphs)
{
BoxRec extents;
GlyphExtents(nlists, lists, glyphs, &extents);
if ((extents.x2 <= extents.x1) || (extents.y2 <= extents.y1))
{
return;
}
rdpGlyphu(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlists, lists,
glyphs, &extents);
}
/******************************************************************************/
int
rdpGlyphInit(void)
{
memset(&g_font_cache, 0, sizeof(g_font_cache));
return 0;
}

@ -0,0 +1,64 @@
/*
Copyright 2012 Jay Sorg
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __RDPGLYPH_H
#define __RDPGLYPH_H
struct rdp_font_char
{
int offset; /* x */
int baseline; /* y */
int width; /* cx */
int height; /* cy */
int incby;
int bpp;
char* data;
int data_bytes;
};
struct rdp_text
{
RegionPtr reg;
int font;
int x;
int y;
int flags;
int mixmode;
char data[256];
int data_bytes;
struct rdp_font_char* chars[256];
int num_chars;
struct rdp_text* next;
};
int
delete_rdp_text(struct rdp_text* rtext);
int
rdp_text_chars_to_data(struct rdp_text* rtext);
void
rdpGlypht(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int nlists, GlyphListPtr lists, GlyphPtr* glyphs);
int
rdpGlyphInit(void);
#endif

@ -24,6 +24,7 @@ Sets up the functions
#include "rdp.h"
#include "rdprandr.h"
#include "rdpglyph.h"
#if 1
#define DEBUG_OUT(arg)
@ -46,7 +47,9 @@ DeviceIntPtr g_keyboard = 0;
int g_can_do_pix_to_pix = 0;
int g_do_dirty_os = 1; /* delay remoting off screen bitmaps */
int g_do_dirty_ons = 1; /* delay remoting screen */
int g_do_dirty_ons = 0; /* delay remoting screen */
int g_do_glyph_cache = 1;
int g_do_alpha_glyphs = 1;
Bool g_wrapWindow = 1;
Bool g_wrapPixmap = 1;
@ -398,6 +401,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
if (ps)
{
g_rdpScreen.CreatePicture = ps->CreatePicture;
g_rdpScreen.DestroyPicture = ps->DestroyPicture;
g_rdpScreen.Composite = ps->Composite;
g_rdpScreen.Glyphs = ps->Glyphs;
@ -411,6 +416,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
if (ps)
{
ps->CreatePicture = rdpCreatePicture;
ps->DestroyPicture = rdpDestroyPicture;
ps->Composite = rdpComposite;
ps->Glyphs = rdpGlyphs;
}
@ -530,6 +537,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
}
rdpGlyphInit();
//rdpXvInit(pScreen);
ErrorF("rdpScreenInit: ret %d\n", ret);

@ -27,6 +27,59 @@ the rest
Bool noFontCacheExtension = 1;
static int g_crc_seed = 0xffffffff;
static int g_crc_table[256] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
#define CRC_START(in_crc) (in_crc) = g_crc_seed
#define CRC_PASS(in_pixel, in_crc) \
(in_crc) = g_crc_table[((in_crc) ^ (in_pixel)) & 0xff] ^ ((in_crc) >> 8)
#define CRC_END(in_crc) (in_crc) = ((in_crc) ^ g_crc_seed)
/******************************************************************************/
/* print a time-stamped message to the log file (stderr). */
void
@ -599,3 +652,19 @@ RegionAroundSegs(RegionPtr reg, xSegment *segs, int nseg)
index++;
}
}
/******************************************************************************/
int
get_crc(char* data, int data_bytes)
{
int crc;
int index;
CRC_START(crc);
for (index = 0; index < data_bytes; index++)
{
CRC_PASS(data[index], crc);
}
CRC_END(crc);
return crc;
}

@ -21,6 +21,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "rdp.h"
#include "xrdp_rail.h"
#include "rdpglyph.h"
#define LOG_LEVEL 1
#define LLOG(_level, _args) \
@ -941,6 +942,7 @@ rdpup_check(void)
g_sck_closed = 0;
g_begin = 0;
g_con_number++;
rdpGlyphInit();
AddEnabledDevice(g_sck);
}
}
@ -1877,6 +1879,8 @@ rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec *pDirtyPriv)
xSegment *seg;
struct image_data id;
struct rdp_draw_item *di;
struct rdp_text* rtext;
struct rdp_text* trtext;
if (pDirtyPriv == 0)
{
@ -1983,6 +1987,37 @@ rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec *pDirtyPriv)
case RDI_SCRBLT:
LLOGLN(10, (" RDI_SCRBLT"));
break;
case RDI_TEXT:
LLOGLN(10, (" RDI_TEXT"));
num_clips = REGION_NUM_RECTS(di->reg);
if (num_clips > 0)
{
LLOGLN(10, (" num_clips %d", num_clips));
rdpup_set_fgcolor(di->u.text.fg_color);
rdpup_set_opcode(di->u.text.opcode);
rtext = di->u.text.rtext;
trtext = rtext;
while (trtext != 0)
{
rdp_text_chars_to_data(trtext);
for (clip_index = num_clips - 1; clip_index >= 0; clip_index--)
{
box = REGION_RECTS(di->reg)[clip_index];
rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
LLOGLN(10, (" %d %d %d %d", box.x1, box.y1, box.x2, box.y2));
box = RegionExtents(trtext->reg)[0];
rdpup_draw_text(trtext->font, trtext->flags, trtext->mixmode,
box.x1, box.y1, box.x2, box.y2,
//box.x1, box.y1, box.x2, box.y2,
0, 0, 0, 0,
trtext->x, trtext->y, trtext->data, trtext->data_bytes);
}
trtext = trtext->next;
}
}
rdpup_reset_clip();
rdpup_set_opcode(GXcopy);
break;
}
di = di->next;
@ -2118,3 +2153,87 @@ rdpup_check_dirty_screen(rdpPixmapRec *pDirtyPriv)
pDirtyPriv->is_dirty = 0;
return 0;
}
/******************************************************************************/
int
rdpup_add_char(int font, int charactor, short x, short y, int cx, int cy,
char* bmpdata, int bmpdata_bytes)
{
if (g_connected)
{
LLOGLN(10, (" rdpup_add_char"));
rdpup_pre_check(18 + bmpdata_bytes);
out_uint16_le(g_out_s, 28); /* add char */
out_uint16_le(g_out_s, 18 + bmpdata_bytes); /* size */
g_count++;
out_uint16_le(g_out_s, font);
out_uint16_le(g_out_s, charactor);
out_uint16_le(g_out_s, x);
out_uint16_le(g_out_s, y);
out_uint16_le(g_out_s, cx);
out_uint16_le(g_out_s, cy);
out_uint16_le(g_out_s, bmpdata_bytes);
out_uint8a(g_out_s, bmpdata, bmpdata_bytes);
}
return 0;
}
/******************************************************************************/
int
rdpup_add_char_alpha(int font, int charactor, short x, short y, int cx, int cy,
char* bmpdata, int bmpdata_bytes)
{
if (g_connected)
{
LLOGLN(10, (" rdpup_add_char_alpha"));
rdpup_pre_check(18 + bmpdata_bytes);
out_uint16_le(g_out_s, 29); /* add char alpha */
out_uint16_le(g_out_s, 18 + bmpdata_bytes); /* size */
g_count++;
out_uint16_le(g_out_s, font);
out_uint16_le(g_out_s, charactor);
out_uint16_le(g_out_s, x);
out_uint16_le(g_out_s, y);
out_uint16_le(g_out_s, cx);
out_uint16_le(g_out_s, cy);
out_uint16_le(g_out_s, bmpdata_bytes);
out_uint8a(g_out_s, bmpdata, bmpdata_bytes);
}
return 0;
}
/******************************************************************************/
int
rdpup_draw_text(int font, int flags, int mixmode,
short clip_left, short clip_top,
short clip_right, short clip_bottom,
short box_left, short box_top,
short box_right, short box_bottom, short x, short y,
char* data, int data_bytes)
{
if (g_connected)
{
LLOGLN(10, (" rdpup_draw_text"));
rdpup_pre_check(32 + data_bytes);
out_uint16_le(g_out_s, 30); /* draw text */
out_uint16_le(g_out_s, 32 + data_bytes); /* size */
g_count++;
out_uint16_le(g_out_s, font);
out_uint16_le(g_out_s, flags);
out_uint16_le(g_out_s, mixmode);
out_uint16_le(g_out_s, clip_left);
out_uint16_le(g_out_s, clip_top);
out_uint16_le(g_out_s, clip_right);
out_uint16_le(g_out_s, clip_bottom);
out_uint16_le(g_out_s, box_left);
out_uint16_le(g_out_s, box_top);
out_uint16_le(g_out_s, box_right);
out_uint16_le(g_out_s, box_bottom);
out_uint16_le(g_out_s, x);
out_uint16_le(g_out_s, y);
out_uint16_le(g_out_s, data_bytes);
out_uint8a(g_out_s, data, data_bytes);
}
return 0;
}

@ -468,3 +468,7 @@ int DEFAULT_CC
server_monitored_desktop(struct xrdp_mod* mod,
struct rail_monitored_desktop_order* mdo,
int flags);
int DEFAULT_CC
server_add_char_alpha(struct xrdp_mod* mod, int font, int charactor,
int offset, int baseline,
int width, int height, char* data);

@ -413,6 +413,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self)
self->mod->server_notify_new_update = server_notify_new_update;
self->mod->server_notify_delete = server_notify_delete;
self->mod->server_monitored_desktop = server_monitored_desktop;
self->mod->server_add_char_alpha = server_add_char_alpha;
}
}
@ -2293,6 +2294,7 @@ server_add_char(struct xrdp_mod *mod, int font, int charactor,
fi.height = height;
fi.incby = 0;
fi.data = data;
fi.bpp = 1;
return libxrdp_orders_send_font(((struct xrdp_wm *)mod->wm)->session,
&fi, font, charactor);
}
@ -2890,3 +2892,23 @@ server_monitored_desktop(struct xrdp_mod *mod,
wm = (struct xrdp_wm *)(mod->wm);
return libxrdp_monitored_desktop(wm->session, mdo, flags);
}
/*****************************************************************************/
int DEFAULT_CC
server_add_char_alpha(struct xrdp_mod* mod, int font, int charactor,
int offset, int baseline,
int width, int height, char* data)
{
struct xrdp_font_char fi;
fi.offset = offset;
fi.baseline = baseline;
fi.width = width;
fi.height = height;
fi.incby = 0;
fi.data = data;
fi.bpp = 8;
return libxrdp_orders_send_font(((struct xrdp_wm*)mod->wm)->session,
&fi, font, charactor);
}

@ -118,8 +118,11 @@ struct xrdp_mod
int flags);
int (*server_set_pointer_ex)(struct xrdp_mod* v, int x, int y, char* data,
char* mask, int bpp);
int (*server_add_char_alpha)(struct xrdp_mod* mod, int font, int charactor,
int offset, int baseline,
int width, int height, char* data);
long server_dumby[100 - 38]; /* align, 100 minus the number of server
long server_dumby[100 - 39]; /* align, 100 minus the number of server
functions above */
/* common */
long handle; /* pointer to self as int */

@ -555,6 +555,18 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
int fgcolor;
int bgcolor;
int opcode;
int charactor;
int font;
int flags;
int mixmode;
int clip_left;
int clip_top;
int clip_right;
int clip_bottom;
int box_left;
int box_top;
int box_right;
int box_bottom;
char *bmpdata;
char cur_data[32 * (32 * 3)];
char cur_mask[32 * (32 / 8)];
@ -680,6 +692,48 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
case 27: /* server_window_new_update - show */
rv = process_server_window_show(mod, s);
break;
case 28: /* server_add_char */
in_uint16_le(s, font);
in_uint16_le(s, charactor);
in_sint16_le(s, x);
in_sint16_le(s, y);
in_uint16_le(s, cx);
in_uint16_le(s, cy);
in_uint16_le(s, len_bmpdata);
in_uint8p(s, bmpdata, len_bmpdata);
rv = mod->server_add_char(mod, font, charactor, x, y, cx, cy, bmpdata);
break;
case 29: /* server_add_char_alpha */
in_uint16_le(s, font);
in_uint16_le(s, charactor);
in_sint16_le(s, x);
in_sint16_le(s, y);
in_uint16_le(s, cx);
in_uint16_le(s, cy);
in_uint16_le(s, len_bmpdata);
in_uint8p(s, bmpdata, len_bmpdata);
rv = mod->server_add_char_alpha(mod, font, charactor, x, y, cx, cy, bmpdata);
break;
case 30: /* server_draw_text */
in_uint16_le(s, font);
in_uint16_le(s, flags);
in_uint16_le(s, mixmode);
in_sint16_le(s, clip_left);
in_sint16_le(s, clip_top);
in_sint16_le(s, clip_right);
in_sint16_le(s, clip_bottom);
in_sint16_le(s, box_left);
in_sint16_le(s, box_top);
in_sint16_le(s, box_right);
in_sint16_le(s, box_bottom);
in_sint16_le(s, x);
in_sint16_le(s, y);
in_uint16_le(s, len_bmpdata);
in_uint8p(s, bmpdata, len_bmpdata);
rv = mod->server_draw_text(mod, font, flags, mixmode, clip_left, clip_top,
clip_right, clip_bottom, box_left, box_top,
box_right, box_bottom, x, y, bmpdata, len_bmpdata);
break;
case 51: /* server_set_pointer_ex */
rv = process_server_set_pointer_ex(mod, s);
break;

@ -119,8 +119,11 @@ struct mod
int flags);
int (*server_set_cursor_ex)(struct mod* v, int x, int y, char* data,
char* mask, int bpp);
int (*server_add_char_alpha)(struct mod* v, int font, int charactor,
int offset, int baseline,
int width, int height, char* data);
tbus server_dumby[100 - 38]; /* align, 100 minus the number of server
tbus server_dumby[100 - 39]; /* align, 100 minus the number of server
functions above */
/* common */
tbus handle; /* pointer to self as long */

Loading…
Cancel
Save