851 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			851 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $Xorg: lbxgfx.c,v 1.3 2000/08/17 19:53:31 cpqbld Exp $ */
 | |
| /*
 | |
|  * Copyright 1993 Network Computing Devices, Inc.
 | |
|  *
 | |
|  * 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, and that the name Network Computing Devices, Inc. not be
 | |
|  * used in advertising or publicity pertaining to distribution of this
 | |
|  * software without specific, written prior permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED `AS-IS'.  NETWORK COMPUTING DEVICES, INC.,
 | |
|  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
 | |
|  * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 | |
|  * PARTICULAR PURPOSE, OR NONINFRINGEMENT.  IN NO EVENT SHALL NETWORK
 | |
|  * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
 | |
|  * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
 | |
|  * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
 | |
|  * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
 | |
|  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | |
|  *
 | |
|  */
 | |
| /* $XFree86: xc/programs/Xserver/lbx/lbxgfx.c,v 1.3 2001/01/17 22:36:59 dawes Exp $ */
 | |
| 
 | |
| /* various bits of DIX-level mangling */
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <stdio.h>
 | |
| #define NEED_REPLIES
 | |
| #define NEED_EVENTS
 | |
| #include <X11/X.h>
 | |
| #include <X11/Xproto.h>
 | |
| #include "misc.h"
 | |
| #include "os.h"
 | |
| #include "dixstruct.h"
 | |
| #include "resource.h"
 | |
| #include "servermd.h"
 | |
| #include "windowstr.h"
 | |
| #include "scrnintstr.h"
 | |
| #define _XLBX_SERVER_
 | |
| #include <X11/extensions/lbxstr.h>
 | |
| #include "lbxserve.h"
 | |
| #include "lbxtags.h"
 | |
| #include <X11/Xfuncproto.h>
 | |
| #include <X11/extensions/lbximage.h>
 | |
| #include "lbxsrvopts.h"
 | |
| 
 | |
| #define DrawableCache(client)	(LbxClient(client)->drawableCache)
 | |
| #define GContextCache(client)	(LbxClient(client)->gcontextCache)
 | |
| 
 | |
| static void
 | |
| push (XID	    cache[GFX_CACHE_SIZE],
 | |
|       XID	    xid)
 | |
| {
 | |
|     memmove (cache+1, cache, (GFX_CACHE_SIZE - 1) * sizeof (cache[0]));
 | |
|     cache[0] = xid;
 | |
| }
 | |
| 
 | |
| static XID
 | |
| use (XID	    cache[GFX_CACHE_SIZE],
 | |
|      int	    i)
 | |
| {
 | |
|     XID	tmp;
 | |
| 
 | |
|     tmp = cache[i];
 | |
|     if (i != 0)
 | |
|     {
 | |
| 	memmove (cache + 1, cache, i * sizeof (cache[0]));
 | |
| 	cache[0] = tmp;
 | |
|     }
 | |
|     return tmp;
 | |
| }
 | |
| 
 | |
| extern char *ConnectionInfo;
 | |
| 
 | |
| static int
 | |
| LbxDecodeGFXCache(ClientPtr	client,
 | |
| 		  CARD8		cacheEnts,
 | |
| 		  char		*after,
 | |
| 		  Drawable	*drawp,
 | |
| 		  GContext	*gcp)
 | |
| {
 | |
|     int	skip;
 | |
|     int	dcache, gcache;
 | |
|     
 | |
|     dcache = GFXdCacheEnt (cacheEnts);
 | |
|     gcache = GFXgCacheEnt (cacheEnts);
 | |
|     skip = 0;
 | |
|     if (dcache == GFXCacheNone)
 | |
|     {
 | |
| 	memcpy (drawp, after, sizeof (Drawable));
 | |
| 	push (DrawableCache(client), *drawp);
 | |
| 	after += sizeof (Drawable);
 | |
| 	skip += sizeof (Drawable);
 | |
|     }
 | |
|     else
 | |
| 	*drawp = use (DrawableCache(client), dcache);
 | |
|     if (gcache == GFXCacheNone)
 | |
|     {
 | |
| 	memcpy (gcp, after, sizeof (GContext));
 | |
| 	push (GContextCache(client), *gcp);
 | |
| 	skip += sizeof (GContext);
 | |
|     }
 | |
|     else
 | |
| 	*gcp = use (GContextCache(client), gcache);
 | |
|     return skip;
 | |
| }
 | |
| 
 | |
| static int
 | |
| LbxDecodeDrawableCache(ClientPtr	client,
 | |
| 		       CARD8		cacheEnts,
 | |
| 		       char		*after,
 | |
| 		       Drawable		*drawp)
 | |
| {
 | |
|     int	skip;
 | |
|     int	dcache;
 | |
|     
 | |
|     dcache = GFXdCacheEnt (cacheEnts);
 | |
|     skip = 0;
 | |
|     if (dcache == GFXCacheNone)
 | |
|     {
 | |
| 	memcpy (drawp, after, sizeof (Drawable));
 | |
| 	push (DrawableCache(client), *drawp);
 | |
| 	after += sizeof (Drawable);
 | |
| 	skip += sizeof (Drawable);
 | |
|     }
 | |
|     else
 | |
| 	*drawp = use (DrawableCache(client), dcache);
 | |
|     return skip;
 | |
| }
 | |
| 
 | |
| #ifdef notyet
 | |
| static int
 | |
| LbxDecodeGCCache(ClientPtr	client,
 | |
| 		 CARD8		cacheEnts,
 | |
| 		 char		*after,
 | |
| 		 GContext	*gcp)
 | |
| {
 | |
|     int	skip;
 | |
|     int	gcache;
 | |
|     
 | |
|     gcache = GFXgCacheEnt (cacheEnts);
 | |
|     skip = 0;
 | |
|     if (gcache == GFXCacheNone)
 | |
|     {
 | |
| 	memcpy (gcp, after, sizeof (GContext));
 | |
| 	push (GContextCache(client), *gcp);
 | |
| 	after += sizeof (GContext);
 | |
| 	skip += sizeof (GContext);
 | |
|     }
 | |
|     else
 | |
| 	*gcp = use (GContextCache(client), gcache);
 | |
|     return skip;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #define GFX_GET_DRAWABLE_AND_GC(type,in,len) {\
 | |
|     int	    skip;   \
 | |
|     len = (client->req_len << 2) - SIZEOF(type); \
 | |
|     in = ((char *) stuff) + SIZEOF(type);\
 | |
|     skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \
 | |
| 			     &drawable, &gc); \
 | |
|     in += skip; \
 | |
|     len -= skip; \
 | |
| }
 | |
|     
 | |
| #define GFX_GET_DST_DRAWABLE_AND_GC(type,in,len) {\
 | |
|     int	    skip;   \
 | |
|     len = (client->req_len << 2) - SIZEOF(type); \
 | |
|     in = ((char *) stuff) + SIZEOF(type);\
 | |
|     skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \
 | |
| 			     &dstDrawable, &gc); \
 | |
|     in += skip; \
 | |
|     len -= skip; \
 | |
| }
 | |
|     
 | |
| #define GFX_GET_SRC_DST_DRAWABLE_AND_GC(type, in, len) { \
 | |
|     int	    skip; \
 | |
|     len = (client->req_len << 2) - SIZEOF(type); \
 | |
|     in = ((char *) stuff) + SIZEOF(type); \
 | |
|     skip = LbxDecodeDrawableCache(client, stuff->srcCache, in, \
 | |
| 				  &srcDrawable); \
 | |
|     in += skip; \
 | |
|     len -= skip; \
 | |
|     skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \
 | |
| 			     &dstDrawable, &gc); \
 | |
|     in += skip; \
 | |
|     len -= skip; \
 | |
| }
 | |
| 
 | |
| #define GFX_GET_GC(type, in, len) { \
 | |
|     int	    skip; \
 | |
|     len = (client->req_len << 2) - SIZEOF(type); \
 | |
|     in = ((char *) stuff) + SIZEOF(type); \
 | |
|     skip = LbxDecodeGCCache(client, stuff->gcCache, in, &gc); \
 | |
|     in += skip; \
 | |
|     len -= skip; \
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodePoly(ClientPtr client,
 | |
| 	      CARD8	xreqtype,
 | |
| 	      int 	(*decode_rtn)(char *, char *, short *))
 | |
| {
 | |
|     REQUEST(xLbxPolyPointReq);
 | |
|     char		*in;
 | |
|     xPolyPointReq	*xreq;
 | |
|     int			len;
 | |
|     int			retval;
 | |
|     Drawable		drawable;
 | |
|     GContext		gc;
 | |
| 
 | |
|     GFX_GET_DRAWABLE_AND_GC(xLbxPolyPointReq, in, len);
 | |
|     if ((xreq = (xPolyPointReq *) 
 | |
| 	    xalloc(sizeof(xPolyPointReq) + (len << 1))) == NULL)
 | |
| 	return BadAlloc;
 | |
|     len = (*decode_rtn)(in, in + len - stuff->padBytes, (short *)(&xreq[1]));
 | |
|     xreq->reqType = xreqtype;
 | |
|     xreq->coordMode = 1;
 | |
|     xreq->drawable = drawable;
 | |
|     xreq->gc = gc;
 | |
|     xreq->length = client->req_len = (sizeof(xPolyPointReq) + len) >> 2;
 | |
|     client->requestBuffer = (pointer)xreq;
 | |
| 
 | |
|     retval = (*ProcVector[xreqtype])(client);
 | |
|     xfree(xreq);
 | |
|     return retval;
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodeFillPoly(ClientPtr  client)
 | |
| {
 | |
|     REQUEST(xLbxFillPolyReq);
 | |
|     char		*in;
 | |
|     xFillPolyReq	*xreq;
 | |
|     int			len;
 | |
|     int			retval;
 | |
|     Drawable		drawable;
 | |
|     GContext		gc;
 | |
|     
 | |
|     GFX_GET_DRAWABLE_AND_GC(xLbxFillPolyReq, in, len);
 | |
|     if ((xreq = (xFillPolyReq *) 
 | |
| 	    xalloc(sizeof(xFillPolyReq) + (len << 1))) == NULL)
 | |
| 	return BadAlloc;
 | |
|     len = LbxDecodePoints(in, in + len - stuff->padBytes, (short *) &xreq[1]);
 | |
|     xreq->reqType = X_FillPoly;
 | |
|     xreq->drawable = drawable;
 | |
|     xreq->gc = gc;
 | |
|     xreq->shape = stuff->shape;
 | |
|     xreq->coordMode = 1;
 | |
|     xreq->length = client->req_len = (sizeof(xFillPolyReq) + len) >> 2;
 | |
|     client->requestBuffer = (pointer)xreq;
 | |
| 
 | |
|     retval = (*ProcVector[X_FillPoly])(client);
 | |
|     xfree(xreq);
 | |
|     return retval;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Routines for decoding line drawing requests
 | |
|  */
 | |
| 
 | |
| #define DECODE_PSHORT(in, val) \
 | |
|     if ((*(in) & 0xf0) != 0xf0) \
 | |
| 	(val) = *(CARD8 *)(in)++; \
 | |
|     else { \
 | |
| 	(val) = ((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1); \
 | |
| 	if ((val) >= 0xe00) \
 | |
| 	    (val) -= 0x1000; \
 | |
| 	else \
 | |
| 	    (val) += 0xf0; \
 | |
| 	(in) += 2; \
 | |
|     }
 | |
| 
 | |
| #define DECODE_SHORT(in, val) \
 | |
|     if ((*(in) & 0xf0) != 0x80) \
 | |
|         (val) = *(INT8 *)(in)++; \
 | |
|     else { \
 | |
| 	(val) = ((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1); \
 | |
| 	if ((val) & 0x0800) \
 | |
| 	    (val) = ((val) | 0xf000) - 0x70; \
 | |
| 	else \
 | |
| 	    (val) += 0x80; \
 | |
| 	(in) += 2; \
 | |
|     }
 | |
| 
 | |
| #define DECODE_USHORT(in, val) \
 | |
|     if ((*(in) & 0xf0) != 0xf0) \
 | |
| 	(val) = *(CARD8 *)(in)++; \
 | |
|     else { \
 | |
| 	(val) = (((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1)) + 0xf0; \
 | |
| 	(in) += 2; \
 | |
|     }
 | |
| 
 | |
| #define DECODE_ANGLE(in, val) \
 | |
|     if (*(INT8 *)(in) >= 0x6e) \
 | |
| 	(val) = (*(INT8 *)(in)++ - 0x67) * (15 << 6); \
 | |
|     else if (*(INT8 *)(in) >= 0x5a) \
 | |
| 	(val) = (*(INT8 *)(in)++ - 0x5a) * (5 << 6); \
 | |
|     else if (*(INT8 *)(in) <= (INT8)0x91) \
 | |
| 	(val) = (*(INT8 *)(in)++ - (INT8)0x98) * (15 << 6); \
 | |
|     else if (*(INT8 *)(in) <= (INT8)0xa5) \
 | |
| 	(val) = (*(INT8 *)(in)++ - (INT8)0xa6) * (5 << 6); \
 | |
|     else { \
 | |
| 	(val) = (*(CARD8 *)(in) << 8) | *(CARD8 *)((in) + 1); \
 | |
| 	(in) += 2; \
 | |
|     }
 | |
| 
 | |
| int
 | |
| LbxDecodePoints(char  	*in,
 | |
| 		char	*inend,
 | |
| 		short 	*out)
 | |
| {
 | |
|     char	   *start_out = (char *)out;
 | |
| 
 | |
|     while (in < inend) {
 | |
| 	DECODE_SHORT(in, *out);
 | |
| 	out++;
 | |
| 	DECODE_SHORT(in, *out);
 | |
| 	out++;
 | |
|     }
 | |
|     return ((char *)out - start_out);
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodeSegment(char	*in,
 | |
| 		 char	*inend,
 | |
| 		 short	*out)
 | |
| {
 | |
|     short 	   diff;
 | |
|     short	   last_x = 0;
 | |
|     short	   last_y = 0;
 | |
|     char	   *start_out = (char *)out;
 | |
| 
 | |
|     while (in < inend) {
 | |
| 	DECODE_SHORT(in, diff);
 | |
| 	*out = last_x + diff;
 | |
| 	last_x += diff;
 | |
| 	out++;
 | |
| 	DECODE_SHORT(in, diff);
 | |
| 	*out = last_y + diff;
 | |
| 	last_y += diff;
 | |
| 	out++;
 | |
| 
 | |
| 	DECODE_SHORT(in, diff);
 | |
| 	*out = last_x + diff;
 | |
| 	out++;
 | |
| 	DECODE_SHORT(in, diff);
 | |
| 	*out = last_y + diff;
 | |
| 	out++;
 | |
|     }
 | |
|     return ((char *)out - start_out);
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodeRectangle(char	 *in,
 | |
| 		   char	 *inend,
 | |
| 		   short *out)
 | |
| {
 | |
|     short	   diff;
 | |
|     short	   last_x = 0;
 | |
|     short	   last_y = 0;
 | |
|     char	   *start_out = (char *)out;
 | |
| 
 | |
|     while (in < inend) {
 | |
| 	DECODE_SHORT(in, diff);
 | |
| 	*out = last_x + diff;
 | |
| 	last_x += diff;
 | |
| 	out++;
 | |
| 	DECODE_SHORT(in, diff);
 | |
| 	*out = last_y + diff;
 | |
| 	last_y += diff;
 | |
| 	out++;
 | |
| 
 | |
| 	DECODE_USHORT(in, *(unsigned short *)out);
 | |
| 	out++;
 | |
| 	DECODE_USHORT(in, *(unsigned short *)out);
 | |
| 	out++;
 | |
|     }
 | |
|     return ((char *)out - start_out);
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodeArc(char  *in,
 | |
| 	     char  *inend,
 | |
| 	     short *out)
 | |
| {
 | |
|     short 	   diff;
 | |
|     short	   last_x = 0;
 | |
|     short	   last_y = 0;
 | |
|     char	   *start_out = (char *)out;
 | |
| 
 | |
|     while (in < inend) {
 | |
| 	DECODE_SHORT(in, diff);
 | |
| 	*out = last_x + diff;
 | |
| 	last_x += diff;
 | |
| 	out++;
 | |
| 	DECODE_SHORT(in, diff);
 | |
| 	*out = last_y + diff;
 | |
| 	last_y += diff;
 | |
| 	out++;
 | |
| 
 | |
| 	DECODE_USHORT(in, *(unsigned short *)out);
 | |
| 	out++;
 | |
| 	DECODE_USHORT(in, *(unsigned short *)out);
 | |
| 	out++;
 | |
| 
 | |
| 	DECODE_ANGLE(in, *out);
 | |
| 	out++;
 | |
| 	DECODE_ANGLE(in, *out);
 | |
| 	out++;
 | |
|     }
 | |
|     return ((char *)out - start_out);
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodeCopyArea (ClientPtr	client)
 | |
| {
 | |
|     REQUEST(xLbxCopyAreaReq);
 | |
|     char		*in;
 | |
|     xCopyAreaReq    	req;
 | |
|     int			len;
 | |
|     Drawable		srcDrawable, dstDrawable;
 | |
|     GContext		gc;
 | |
|     
 | |
|     GFX_GET_SRC_DST_DRAWABLE_AND_GC(xLbxCopyAreaReq, in, len);
 | |
|     req.reqType = X_CopyArea;
 | |
|     req.length = client->req_len = SIZEOF(xCopyAreaReq) >> 2;
 | |
|     req.srcDrawable = srcDrawable;
 | |
|     req.dstDrawable = dstDrawable;
 | |
|     req.gc = gc;
 | |
|     DECODE_PSHORT (in, req.srcX);
 | |
|     DECODE_PSHORT (in, req.srcY);
 | |
|     DECODE_PSHORT (in, req.dstX);
 | |
|     DECODE_PSHORT (in, req.dstY);
 | |
|     DECODE_USHORT (in, req.width);
 | |
|     DECODE_USHORT (in, req.height);
 | |
|     client->requestBuffer = (pointer) &req;
 | |
|     return (*ProcVector[X_CopyArea])(client);
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodeCopyPlane (ClientPtr	client)
 | |
| {
 | |
|     REQUEST(xLbxCopyPlaneReq);
 | |
|     char		*in;
 | |
|     xCopyPlaneReq 	req;
 | |
|     int			len;
 | |
|     Drawable		srcDrawable, dstDrawable;
 | |
|     GContext		gc;
 | |
|     
 | |
|     GFX_GET_SRC_DST_DRAWABLE_AND_GC(xLbxCopyPlaneReq, in, len);
 | |
|     req.reqType = X_CopyPlane;
 | |
|     req.length = client->req_len = SIZEOF(xCopyPlaneReq) >> 2;
 | |
|     req.srcDrawable = srcDrawable;
 | |
|     req.dstDrawable = dstDrawable;
 | |
|     req.gc = gc;
 | |
|     DECODE_PSHORT (in, req.srcX);
 | |
|     DECODE_PSHORT (in, req.srcY);
 | |
|     DECODE_PSHORT (in, req.dstX);
 | |
|     DECODE_PSHORT (in, req.dstY);
 | |
|     DECODE_USHORT (in, req.width);
 | |
|     DECODE_USHORT (in, req.height);
 | |
|     req.bitPlane = stuff->bitPlane;
 | |
|     client->requestBuffer = (pointer) &req;
 | |
|     return (*ProcVector[X_CopyPlane])(client);
 | |
| }
 | |
| 
 | |
| static pointer
 | |
| get_gfx_buffer(ClientPtr	client,
 | |
| 	       int		len)
 | |
| {
 | |
|     LbxClientPtr    lbxClient = LbxClient(client);
 | |
|     pointer	tmp;
 | |
| 
 | |
|     /* XXX should probably shrink this sucker too */
 | |
|     if (len > lbxClient->gb_size) {
 | |
| 	tmp = (pointer) xrealloc(lbxClient->gfx_buffer, len);
 | |
| 	if (!tmp)
 | |
| 	    return (pointer) NULL;
 | |
| 	lbxClient->gfx_buffer = tmp;
 | |
| 	lbxClient->gb_size = len;
 | |
|     }
 | |
|     return lbxClient->gfx_buffer;
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodePolyText (ClientPtr	client)
 | |
| {
 | |
|     REQUEST(xLbxPolyTextReq);
 | |
|     char		*in, *pos;
 | |
|     xPolyTextReq	*xreq;
 | |
|     int			len;
 | |
|     Drawable		drawable;
 | |
|     GContext		gc;
 | |
|     
 | |
|     GFX_GET_DRAWABLE_AND_GC(xLbxPolyTextReq, in, len);
 | |
|     xreq = (xPolyTextReq *) get_gfx_buffer(client, sizeof (xPolyTextReq) + len);
 | |
|     if (!xreq)
 | |
| 	return BadAlloc;
 | |
|     xreq->reqType = stuff->lbxReqType == X_LbxPolyText8? X_PolyText8 : X_PolyText16;
 | |
|     xreq->drawable = drawable;
 | |
|     xreq->gc = gc;
 | |
|     pos = in;
 | |
|     DECODE_PSHORT(in, xreq->x);
 | |
|     DECODE_PSHORT(in, xreq->y);
 | |
|     len -= (in - pos);
 | |
|     memmove ((char *) (xreq + 1), in, len);
 | |
|     xreq->length = client->req_len = (sizeof (xPolyTextReq) + len) >> 2;
 | |
|     client->requestBuffer = (pointer) xreq;
 | |
|     return (*ProcVector[xreq->reqType])(client);
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodeImageText (ClientPtr	client)
 | |
| {
 | |
|     REQUEST(xLbxImageTextReq);
 | |
|     char		*in, *pos;
 | |
|     xImageTextReq	*xreq;
 | |
|     int			len;
 | |
|     Drawable		drawable;
 | |
|     GContext		gc;
 | |
| 
 | |
|     GFX_GET_DRAWABLE_AND_GC(xLbxImageTextReq, in, len);
 | |
|     xreq = (xImageTextReq *) get_gfx_buffer(client, sizeof (xImageTextReq) + len);
 | |
|     if (!xreq)
 | |
| 	return BadAlloc;
 | |
|     xreq->reqType = stuff->lbxReqType == X_LbxImageText8? X_ImageText8 : X_ImageText16;
 | |
|     xreq->drawable = drawable;
 | |
|     xreq->gc = gc;
 | |
|     xreq->nChars = stuff->nChars;
 | |
|     pos = in;
 | |
|     DECODE_PSHORT(in, xreq->x);
 | |
|     DECODE_PSHORT(in, xreq->y);
 | |
|     len -= (in - pos);
 | |
|     memmove ((char *) (xreq + 1), in, len);
 | |
|     xreq->length = client->req_len = (sizeof (xImageTextReq) + len) >> 2;
 | |
|     client->requestBuffer = (pointer) xreq;
 | |
|     return (*ProcVector[xreq->reqType])(client);
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodePutImage (ClientPtr  client)
 | |
| {
 | |
|     REQUEST		(xLbxPutImageReq);
 | |
|     char		*in, *data;
 | |
|     xPutImageReq	xreq;
 | |
|     int			ppl, bpl, nbytes;
 | |
|     int			retval;
 | |
|     int			n;
 | |
| 
 | |
|     xreq.reqType = X_PutImage;
 | |
| 
 | |
|     in = (char *) stuff + sz_xLbxPutImageReq;
 | |
| 
 | |
|     if (stuff->bitPacked & 0x80) {
 | |
| 	xreq.format = (stuff->bitPacked >> 5) & 0x3;
 | |
| 	xreq.depth = ((stuff->bitPacked >> 2) & 0x7) + 1;
 | |
| 	xreq.leftPad = 0;
 | |
|     } else {
 | |
| 	xreq.depth = (stuff->bitPacked >> 2) + 1;
 | |
| 	xreq.format = (*in >> 5) & 0x3;
 | |
| 	xreq.leftPad = *in++ & 0x1f;
 | |
|     }
 | |
|     DECODE_USHORT(in, xreq.width);
 | |
|     DECODE_USHORT(in, xreq.height);
 | |
|     DECODE_PSHORT(in, xreq.dstX);
 | |
|     DECODE_PSHORT(in, xreq.dstY);
 | |
|     if (client->swapped) {
 | |
| 	if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone ||
 | |
| 	    GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone)
 | |
| 	{
 | |
| 	    swapl (in, n);
 | |
| 	    if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone &&
 | |
| 		GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone)
 | |
| 		swapl (in + 4, n);
 | |
| 	}
 | |
|     }
 | |
|     in += LbxDecodeGFXCache(client, stuff->cacheEnts, in,
 | |
| 			    &xreq.drawable, &xreq.gc);
 | |
| 
 | |
|     ppl = xreq.width + xreq.leftPad;
 | |
|     if (xreq.format != ZPixmap ||
 | |
| 	(xreq.depth == 1 && screenInfo.formats->bitsPerPixel == 1)) {
 | |
| #ifdef INTERNAL_VS_EXTERNAL_PADDING
 | |
| 	bpl = BitmapBytePadProto(ppl);
 | |
| #else
 | |
| 	bpl = BitmapBytePad(ppl);
 | |
| #endif
 | |
| 	nbytes = bpl;
 | |
| 	if (xreq.format == XYPixmap)
 | |
| 	    nbytes *= xreq.depth;
 | |
|     } else {
 | |
| #ifdef INTERNAL_VS_EXTERNAL_PADDING
 | |
| 	bpl = PixmapBytePadProto(ppl, xreq.depth);
 | |
| #else
 | |
| 	bpl = PixmapBytePad(ppl, xreq.depth);
 | |
| #endif
 | |
| 	nbytes = bpl;
 | |
|     }
 | |
|     nbytes *= xreq.height;
 | |
|     xreq.length = ((nbytes + 3) >> 2) + (sz_xPutImageReq >> 2);
 | |
|     /* +1 is because fillspan in DecodeFaxG42D seems to go 1 byte too far,
 | |
|      * and I don't want to mess with that code */
 | |
|     if ((data = (char *) xalloc ((xreq.length << 2) + 1)) == NULL)
 | |
| 	return BadAlloc;
 | |
| 
 | |
|     *((xPutImageReq *)data) = xreq;
 | |
| 
 | |
|     if (!stuff->compressionMethod)
 | |
|     {
 | |
| 	memcpy(data + sz_xPutImageReq, in, nbytes);
 | |
|     }
 | |
|     else if (xreq.format != ZPixmap ||
 | |
| 	     (xreq.depth == 1 && screenInfo.formats->bitsPerPixel == 1))
 | |
|     {
 | |
| 	LbxBitmapCompMethod *compMethod;
 | |
| 
 | |
| 	compMethod = LbxSrvrLookupBitmapCompMethod (LbxProxy(client),
 | |
| 	    stuff->compressionMethod);
 | |
| 
 | |
| 	if (!compMethod)
 | |
| 	{
 | |
| 	    xfree (data);
 | |
| 	    return (BadValue);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    if (!compMethod->inited)
 | |
| 	    {
 | |
| 		if (compMethod->compInit)
 | |
| 		    (*compMethod->compInit)();
 | |
| 		compMethod->inited = 1;
 | |
| 	    }
 | |
| 
 | |
| 	    (*compMethod->decompFunc) (
 | |
| 	        (unsigned char *) in, (unsigned char *) data + sz_xPutImageReq,
 | |
| 	        nbytes,
 | |
| #if BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER
 | |
| 		(ppl + BITMAP_SCANLINE_UNIT - 1) & ~BITMAP_SCANLINE_UNIT,
 | |
| #else
 | |
| 	        ppl,
 | |
| #endif
 | |
| 		bpl,
 | |
| 	        ((xConnSetup *) ConnectionInfo)->bitmapBitOrder == LSBFirst);
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	LbxPixmapCompMethod *compMethod;
 | |
| 
 | |
| 	compMethod = LbxSrvrLookupPixmapCompMethod (LbxProxy(client),
 | |
| 	    stuff->compressionMethod);
 | |
| 
 | |
| 	if (!compMethod)
 | |
| 	{
 | |
| 	    xfree (data);
 | |
| 	    return (BadValue);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    if (!compMethod->inited)
 | |
| 	    {
 | |
| 		if (compMethod->compInit)
 | |
| 		    (*compMethod->compInit)();
 | |
| 		compMethod->inited = 1;
 | |
| 	    }
 | |
| 
 | |
| 	    (*compMethod->decompFunc) (
 | |
| 		in, (char *) data + sz_xPutImageReq,
 | |
| 		(int) xreq.height, bpl);
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     client->req_len = xreq.length;
 | |
|     client->requestBuffer = (pointer) data;
 | |
| 
 | |
|     retval = (*ProcVector[X_PutImage])(client);
 | |
|     xfree(data);
 | |
|     return retval;
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxDecodeGetImage (ClientPtr  client)
 | |
| {
 | |
|     REQUEST		(xLbxGetImageReq);
 | |
|     xLbxGetImageReply	*reply = NULL;
 | |
|     int			lbxLen, xLen, n;
 | |
|     int			method = 0, bytes, status;
 | |
|     xGetImageReply	*theImage;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xLbxGetImageReq);
 | |
| 
 | |
|     status = DoGetImage(client, stuff->format, stuff->drawable,
 | |
| 			stuff->x, stuff->y,
 | |
| 			(int)stuff->width, (int)stuff->height,
 | |
| 			stuff->planeMask, &theImage);
 | |
| 
 | |
|     if (status != Success)
 | |
| 	return (status);
 | |
| 
 | |
|     if ((reply = (xLbxGetImageReply *) xalloc (
 | |
| 	sz_xLbxGetImageReply + theImage->length)) == NULL)
 | |
|     {
 | |
| 	xfree(theImage);
 | |
| 	return (BadAlloc);
 | |
|     }
 | |
| 
 | |
|     if (stuff->format != ZPixmap ||
 | |
| 	(theImage->depth == 1 && screenInfo.formats->bitsPerPixel == 1))
 | |
|     {
 | |
| 	LbxBitmapCompMethod *compMethod;
 | |
| 
 | |
| 	compMethod = LbxSrvrFindPreferredBitmapCompMethod (LbxProxy(client));
 | |
| 
 | |
| 	if (!compMethod)
 | |
| 	    status = LBX_IMAGE_COMPRESS_NO_SUPPORT;
 | |
| 	else
 | |
| 	{
 | |
| 	    if (!compMethod->inited)
 | |
| 	    {
 | |
| 		if (compMethod->compInit)
 | |
| 		    (*compMethod->compInit)();
 | |
| 		compMethod->inited = 1;
 | |
| 	    }
 | |
| 
 | |
| 	    status = (*compMethod->compFunc) (
 | |
| 	        (unsigned char *) &theImage[1],
 | |
| 	        (unsigned char *) &reply[1],
 | |
| 	        theImage->length,
 | |
| 		theImage->length,
 | |
| #if BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER
 | |
| 		(int) (stuff->width + BITMAP_SCANLINE_UNIT - 1) &
 | |
| 		      ~BITMAP_SCANLINE_UNIT,
 | |
| #else
 | |
| 		(int) stuff->width,
 | |
| #endif
 | |
| #ifdef INTERNAL_VS_EXTERNAL_PADDING
 | |
| 		BitmapBytePadProto(stuff->width),
 | |
| #else
 | |
| 		BitmapBytePad(stuff->width),
 | |
| #endif
 | |
| 	        ((xConnSetup *) ConnectionInfo)->bitmapBitOrder == LSBFirst,
 | |
| 	        &bytes);
 | |
| 
 | |
| 	    method = compMethod->methodOpCode;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	LbxPixmapCompMethod *compMethod;
 | |
| 
 | |
| 	compMethod = LbxSrvrFindPreferredPixmapCompMethod (
 | |
| 	    LbxProxy(client), (int) stuff->format, theImage->depth);
 | |
| 
 | |
| 	if (!compMethod)
 | |
| 	    status = LBX_IMAGE_COMPRESS_NO_SUPPORT;
 | |
| 	else
 | |
| 	{
 | |
| 	    if (!compMethod->inited)
 | |
| 	    {
 | |
| 		if (compMethod->compInit)
 | |
| 		    (*compMethod->compInit)();
 | |
| 		compMethod->inited = 1;
 | |
| 	    }
 | |
| 
 | |
| 	    status = (*compMethod->compFunc) (
 | |
| 	        (char *) &theImage[1],
 | |
| 	        (char *) &reply[1],
 | |
| 	        theImage->length,
 | |
| 	        (int) stuff->format,
 | |
| 	        theImage->depth,
 | |
| 	        (int) stuff->height,
 | |
| #ifdef INTERNAL_VS_EXTERNAL_PADDING
 | |
| 		PixmapBytePadProto(stuff->width, theImage->depth),
 | |
| #else
 | |
| 		PixmapBytePad(stuff->width, theImage->depth),
 | |
| #endif
 | |
| 		&bytes);
 | |
| 
 | |
| 	    method = compMethod->methodOpCode;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     reply->type = X_Reply;
 | |
|     reply->depth = theImage->depth;
 | |
|     reply->sequenceNumber = client->sequence;
 | |
|     reply->visual = theImage->visual;
 | |
|     reply->pad1 = reply->pad2 = reply->pad3 = reply->pad4 = reply->pad5 = 0;
 | |
| 
 | |
|     if (status != LBX_IMAGE_COMPRESS_SUCCESS)
 | |
|     {
 | |
| 	reply->compressionMethod = LbxImageCompressNone;
 | |
| 	reply->lbxLength = reply->xLength = (theImage->length + 3) >> 2;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	reply->compressionMethod = method;
 | |
| 	reply->lbxLength = (bytes + 3) >> 2;
 | |
| 	reply->xLength = (theImage->length + 3) >> 2;
 | |
|     }
 | |
| 
 | |
|     lbxLen = reply->lbxLength;
 | |
|     xLen = reply->xLength;
 | |
| 
 | |
|     if (client->swapped)
 | |
|     {
 | |
| 	swaps (&reply->sequenceNumber, n);
 | |
| 	swapl (&reply->lbxLength, n);
 | |
| 	swapl (&reply->xLength, n);
 | |
| 	swapl (&reply->visual, n);
 | |
|     }
 | |
| 
 | |
|     if (reply->compressionMethod != LbxImageCompressNone)
 | |
|     {
 | |
| 	/*
 | |
| 	 * If the compressed image is greater that 25% of the original
 | |
| 	 * image, run the GetImage reply through the regular stream
 | |
| 	 * compressor.  Otherwise, just write the compressed image.
 | |
| 	 */
 | |
| 	
 | |
| 	if (lbxLen > (xLen / 4))
 | |
| 	{
 | |
| 	    WriteToClient (client,
 | |
| 	        sz_xLbxGetImageReply + (lbxLen << 2), (char *)reply);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    UncompressedWriteToClient (client,
 | |
| 	        sz_xLbxGetImageReply + (lbxLen << 2), (char *)reply);
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	/*
 | |
| 	 * Write back the original uncompressed image.
 | |
| 	 */
 | |
| 
 | |
| 	WriteToClient (client, sz_xLbxGetImageReply, (char *)reply);
 | |
| 	WriteToClient (client, lbxLen << 2, (char *)&theImage[1]);
 | |
|     }
 | |
| 
 | |
|     xfree (theImage);
 | |
| 
 | |
|     if (reply)
 | |
| 	xfree ((char *) reply);
 | |
| 
 | |
|     return (Success);
 | |
| }
 |