Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  *
      3  * Copyright  2000 SuSE, Inc.
      4  *
      5  * Permission to use, copy, modify, distribute, and sell this software and its
      6  * documentation for any purpose is hereby granted without fee, provided that
      7  * the above copyright notice appear in all copies and that both that
      8  * copyright notice and this permission notice appear in supporting
      9  * documentation, and that the name of SuSE not be used in advertising or
     10  * publicity pertaining to distribution of the software without specific,
     11  * written prior permission.  SuSE makes no representations about the
     12  * suitability of this software for any purpose.  It is provided "as is"
     13  * without express or implied warranty.
     14  *
     15  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
     17  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     19  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     21  *
     22  * Author:  Keith Packard, SuSE, Inc.
     23  */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include <config.h>
     27 #endif
     28 #include "Xrenderint.h"
     29 
     30 GlyphSet
     31 XRenderCreateGlyphSet (Display *dpy, _Xconst XRenderPictFormat *format)
     32 {
     33     XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
     34     GlyphSet			gsid;
     35     xRenderCreateGlyphSetReq	*req;
     36 
     37     RenderCheckExtension (dpy, info, 0);
     38     LockDisplay(dpy);
     39     GetReq(RenderCreateGlyphSet, req);
     40     req->reqType = (CARD8) info->codes->major_opcode;
     41     req->renderReqType = X_RenderCreateGlyphSet;
     42     req->gsid = (CARD32) (gsid = XAllocID(dpy));
     43     req->format = (CARD32) format->id;
     44     UnlockDisplay(dpy);
     45     SyncHandle();
     46     return gsid;
     47 }
     48 
     49 GlyphSet
     50 XRenderReferenceGlyphSet (Display *dpy, GlyphSet existing)
     51 {
     52     XRenderExtDisplayInfo       *info = XRenderFindDisplay (dpy);
     53     GlyphSet                    gsid;
     54     xRenderReferenceGlyphSetReq	*req;
     55 
     56     RenderCheckExtension (dpy, info, 0);
     57     LockDisplay(dpy);
     58     GetReq(RenderReferenceGlyphSet, req);
     59     req->reqType = (CARD8) info->codes->major_opcode;
     60     req->renderReqType = X_RenderReferenceGlyphSet;
     61     req->gsid = (CARD32) (gsid = XAllocID(dpy));
     62     req->existing = (CARD32) existing;
     63     UnlockDisplay(dpy);
     64     SyncHandle();
     65     return gsid;
     66 }
     67 
     68 void
     69 XRenderFreeGlyphSet (Display *dpy, GlyphSet glyphset)
     70 {
     71     XRenderExtDisplayInfo   *info = XRenderFindDisplay (dpy);
     72     xRenderFreeGlyphSetReq  *req;
     73 
     74     RenderSimpleCheckExtension (dpy, info);
     75     LockDisplay(dpy);
     76     GetReq(RenderFreeGlyphSet, req);
     77     req->reqType = (CARD8) info->codes->major_opcode;
     78     req->renderReqType = X_RenderFreeGlyphSet;
     79     req->glyphset = (CARD32) glyphset;
     80     UnlockDisplay(dpy);
     81     SyncHandle();
     82 }
     83 
     84 void
     85 XRenderAddGlyphs (Display	*dpy,
     86 		  GlyphSet	glyphset,
     87 		  _Xconst Glyph		*gids,
     88 		  _Xconst XGlyphInfo	*glyphs,
     89 		  int		nglyphs,
     90 		  _Xconst char		*images,
     91 		  int		nbyte_images)
     92 {
     93     XRenderExtDisplayInfo   *info = XRenderFindDisplay (dpy);
     94     xRenderAddGlyphsReq	    *req;
     95     long		    len;
     96 
     97     if (nbyte_images & 3)
     98 	nbyte_images += 4 - (nbyte_images & 3);
     99     RenderSimpleCheckExtension (dpy, info);
    100     LockDisplay(dpy);
    101     GetReq(RenderAddGlyphs, req);
    102     req->reqType = (CARD8) info->codes->major_opcode;
    103     req->renderReqType = X_RenderAddGlyphs;
    104     req->glyphset = (CARD32) glyphset;
    105     req->nglyphs = (CARD32) nglyphs;
    106     len = (nglyphs * (SIZEOF (xGlyphInfo) + 4) + nbyte_images) >> 2;
    107     SetReqLen(req, len, len);
    108     Data32 (dpy, (_Xconst long *) gids, nglyphs * 4);
    109     Data16 (dpy, (_Xconst short *) glyphs, nglyphs * SIZEOF (xGlyphInfo));
    110     Data (dpy, images, nbyte_images);
    111     UnlockDisplay(dpy);
    112     SyncHandle();
    113 }
    114 
    115 void
    116 XRenderFreeGlyphs (Display   *dpy,
    117 		   GlyphSet  glyphset,
    118 		   _Xconst Glyph     *gids,
    119 		   int       nglyphs)
    120 {
    121     XRenderExtDisplayInfo   *info = XRenderFindDisplay (dpy);
    122     xRenderFreeGlyphsReq    *req;
    123     long                    len;
    124 
    125     RenderSimpleCheckExtension (dpy, info);
    126     LockDisplay(dpy);
    127     GetReq(RenderFreeGlyphs, req);
    128     req->reqType = (CARD8) info->codes->major_opcode;
    129     req->renderReqType = X_RenderFreeGlyphs;
    130     req->glyphset = (CARD32) glyphset;
    131     len = nglyphs;
    132     SetReqLen(req, len, len);
    133     len <<= 2;
    134     Data32 (dpy, (_Xconst long *) gids, len);
    135     UnlockDisplay(dpy);
    136     SyncHandle();
    137 }
    138 
    139 void
    140 XRenderCompositeString8 (Display	    *dpy,
    141 			 int		    op,
    142 			 Picture	    src,
    143 			 Picture	    dst,
    144 			 _Xconst XRenderPictFormat  *maskFormat,
    145 			 GlyphSet	    glyphset,
    146 			 int		    xSrc,
    147 			 int		    ySrc,
    148 			 int		    xDst,
    149 			 int		    yDst,
    150 			 _Xconst char	    *string,
    151 			 int		    nchar)
    152 {
    153     XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
    154     xRenderCompositeGlyphs8Req	*req;
    155     long			len;
    156     xGlyphElt			*elt;
    157     int				nbytes;
    158 
    159     if (!nchar)
    160 	return;
    161 
    162     RenderSimpleCheckExtension (dpy, info);
    163     LockDisplay(dpy);
    164 
    165     GetReq(RenderCompositeGlyphs8, req);
    166     req->reqType = (CARD8) info->codes->major_opcode;
    167     req->renderReqType = X_RenderCompositeGlyphs8;
    168     req->op = (CARD8) op;
    169     req->src = (CARD32) src;
    170     req->dst = (CARD32) dst;
    171     req->maskFormat = (CARD32) (maskFormat ? maskFormat->id : None);
    172     req->glyphset = (CARD32) glyphset;
    173     req->xSrc = (INT16) xSrc;
    174     req->ySrc = (INT16) ySrc;
    175 
    176     /*
    177      * xGlyphElt must be aligned on a 32-bit boundary; this is
    178      * easily done by filling no more than 252 glyphs in each
    179      * bucket
    180      */
    181 
    182 #define MAX_8 252
    183 
    184     len = SIZEOF(xGlyphElt) * ((nchar + MAX_8-1) / MAX_8) + nchar;
    185 
    186     req->length = (CARD16) (req->length + ((len + 3)>>2));  /* convert to number of 32-bit words */
    187 
    188     /*
    189      * If the entire request does not fit into the remaining space in the
    190      * buffer, flush the buffer first.
    191      */
    192 
    193     if (dpy->bufptr + len > dpy->bufmax)
    194     	_XFlush (dpy);
    195 
    196     while(nchar > MAX_8)
    197     {
    198 	nbytes = MAX_8 + SIZEOF(xGlyphElt);
    199 	BufAlloc (xGlyphElt *, elt, nbytes);
    200 	elt->len = MAX_8;
    201 	elt->deltax = (INT16) xDst;
    202 	elt->deltay = (INT16) yDst;
    203 	xDst = 0;
    204 	yDst = 0;
    205 	memcpy ((char *) (elt + 1), string, MAX_8);
    206 	nchar = nchar - MAX_8;
    207 	string += MAX_8;
    208     }
    209 
    210     if (nchar)
    211     {
    212 	nbytes = (nchar + SIZEOF(xGlyphElt) + 3) & ~3;
    213 	BufAlloc (xGlyphElt *, elt, nbytes);
    214 	elt->len = (CARD8) nchar;
    215 	elt->deltax = (INT16) xDst;
    216 	elt->deltay = (INT16) yDst;
    217 	memcpy ((char *) (elt + 1), string, (size_t) nchar);
    218     }
    219 #undef MAX_8
    220 
    221     UnlockDisplay(dpy);
    222     SyncHandle();
    223 }
    224 void
    225 XRenderCompositeString16 (Display	    *dpy,
    226 			  int		    op,
    227 			  Picture	    src,
    228 			  Picture	    dst,
    229 			  _Xconst XRenderPictFormat *maskFormat,
    230 			  GlyphSet	    glyphset,
    231 			  int		    xSrc,
    232 			  int		    ySrc,
    233 			  int		    xDst,
    234 			  int		    yDst,
    235 			  _Xconst unsigned short    *string,
    236 			  int		    nchar)
    237 {
    238     XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
    239     xRenderCompositeGlyphs8Req	*req;
    240     long			len;
    241     xGlyphElt			*elt;
    242     int				nbytes;
    243 
    244     if (!nchar)
    245 	return;
    246 
    247     RenderSimpleCheckExtension (dpy, info);
    248     LockDisplay(dpy);
    249 
    250     GetReq(RenderCompositeGlyphs16, req);
    251     req->reqType = (CARD8) info->codes->major_opcode;
    252     req->renderReqType = X_RenderCompositeGlyphs16;
    253     req->op = (CARD8) op;
    254     req->src = (CARD32) src;
    255     req->dst = (CARD32) dst;
    256     req->maskFormat = (CARD32) (maskFormat ? maskFormat->id : None);
    257     req->glyphset = (CARD32) glyphset;
    258     req->xSrc = (INT16) xSrc;
    259     req->ySrc = (INT16) ySrc;
    260 
    261 #define MAX_16	254
    262 
    263     len = SIZEOF(xGlyphElt) * ((nchar + MAX_16-1) / MAX_16) + nchar * 2;
    264 
    265     req->length = (CARD16) (req->length + ((len + 3)>>2));  /* convert to number of 32-bit words */
    266 
    267     /*
    268      * If the entire request does not fit into the remaining space in the
    269      * buffer, flush the buffer first.
    270      */
    271 
    272     if (dpy->bufptr + len > dpy->bufmax)
    273     	_XFlush (dpy);
    274 
    275     while(nchar > MAX_16)
    276     {
    277 	nbytes = MAX_16 * 2 + SIZEOF(xGlyphElt);
    278 	BufAlloc (xGlyphElt *, elt, nbytes);
    279 	elt->len = MAX_16;
    280 	elt->deltax = (INT16) xDst;
    281 	elt->deltay = (INT16) yDst;
    282 	xDst = 0;
    283 	yDst = 0;
    284 	memcpy ((char *) (elt + 1), (_Xconst char *) string, MAX_16 * 2);
    285 	nchar = nchar - MAX_16;
    286 	string += MAX_16;
    287     }
    288 
    289     if (nchar)
    290     {
    291 	nbytes = (nchar * 2 + SIZEOF(xGlyphElt) + 3) & ~3;
    292 	BufAlloc (xGlyphElt *, elt, nbytes);
    293 	elt->len = (CARD8) nchar;
    294 	elt->deltax = (INT16) xDst;
    295 	elt->deltay = (INT16) yDst;
    296 	memcpy ((char *) (elt + 1), (_Xconst char *) string, (size_t) (nchar * 2));
    297     }
    298 #undef MAX_16
    299 
    300     UnlockDisplay(dpy);
    301     SyncHandle();
    302 }
    303 
    304 void
    305 XRenderCompositeString32 (Display	    *dpy,
    306 			  int		    op,
    307 			  Picture	    src,
    308 			  Picture	    dst,
    309 			  _Xconst XRenderPictFormat  *maskFormat,
    310 			  GlyphSet	    glyphset,
    311 			  int		    xSrc,
    312 			  int		    ySrc,
    313 			  int		    xDst,
    314 			  int		    yDst,
    315 			  _Xconst unsigned int	    *string,
    316 			  int		    nchar)
    317 {
    318     XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
    319     xRenderCompositeGlyphs8Req	*req;
    320     long			len;
    321     xGlyphElt			*elt;
    322     int				nbytes;
    323 
    324     if (!nchar)
    325 	return;
    326 
    327     RenderSimpleCheckExtension (dpy, info);
    328     LockDisplay(dpy);
    329 
    330     GetReq(RenderCompositeGlyphs32, req);
    331     req->reqType = (CARD8) info->codes->major_opcode;
    332     req->renderReqType = X_RenderCompositeGlyphs32;
    333     req->op = (CARD8) op;
    334     req->src = (CARD32) src;
    335     req->dst = (CARD32) dst;
    336     req->maskFormat = (CARD32) (maskFormat ? maskFormat->id : None);
    337     req->glyphset = (CARD32) glyphset;
    338     req->xSrc = (INT16) xSrc;
    339     req->ySrc = (INT16) ySrc;
    340 
    341 #define MAX_32	254
    342 
    343     len = SIZEOF(xGlyphElt) * ((nchar + MAX_32-1) / MAX_32) + nchar * 4;
    344 
    345     req->length = (CARD16) (req->length + ((len + 3)>>2));  /* convert to number of 32-bit words */
    346 
    347     /*
    348      * If the entire request does not fit into the remaining space in the
    349      * buffer, flush the buffer first.
    350      */
    351 
    352     if (dpy->bufptr + len > dpy->bufmax)
    353     	_XFlush (dpy);
    354 
    355     while(nchar > MAX_32)
    356     {
    357 	nbytes = MAX_32 * 4 + SIZEOF(xGlyphElt);
    358 	BufAlloc (xGlyphElt *, elt, nbytes);
    359 	elt->len = MAX_32;
    360 	elt->deltax = (INT16) xDst;
    361 	elt->deltay = (INT16) yDst;
    362 	xDst = 0;
    363 	yDst = 0;
    364 	memcpy ((char *) (elt + 1), (_Xconst char *) string, MAX_32 * 4);
    365 	nchar = nchar - MAX_32;
    366 	string += MAX_32;
    367     }
    368 
    369     if (nchar)
    370     {
    371 	nbytes = nchar * 4 + SIZEOF(xGlyphElt);
    372 	BufAlloc (xGlyphElt *, elt, nbytes);
    373 	elt->len = (CARD8) nchar;
    374 	elt->deltax = (INT16) xDst;
    375 	elt->deltay = (INT16) yDst;
    376 	memcpy ((char *) (elt + 1), (_Xconst char *) string, (size_t) (nchar * 4));
    377     }
    378 #undef MAX_32
    379 
    380     UnlockDisplay(dpy);
    381     SyncHandle();
    382 }
    383 
    384 void
    385 XRenderCompositeText8 (Display			    *dpy,
    386 		       int			    op,
    387 		       Picture			    src,
    388 		       Picture			    dst,
    389 		       _Xconst XRenderPictFormat    *maskFormat,
    390 		       int			    xSrc,
    391 		       int			    ySrc,
    392 		       int			    xDst,
    393 		       int			    yDst,
    394 		       _Xconst XGlyphElt8	    *elts,
    395 		       int			    nelt)
    396 {
    397     XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
    398     xRenderCompositeGlyphs8Req	*req;
    399     GlyphSet			glyphset;
    400     long			len;
    401     int				i;
    402 
    403     if (!nelt)
    404 	return;
    405 
    406     RenderSimpleCheckExtension (dpy, info);
    407     LockDisplay(dpy);
    408 
    409     GetReq(RenderCompositeGlyphs8, req);
    410     req->reqType = (CARD8) info->codes->major_opcode;
    411     req->renderReqType = X_RenderCompositeGlyphs8;
    412     req->op = (CARD8) op;
    413     req->src = (CARD32) src;
    414     req->dst = (CARD32) dst;
    415     req->maskFormat = (CARD32) (maskFormat ? maskFormat->id : None);
    416     req->glyphset = (CARD32) elts[0].glyphset;
    417     req->xSrc = (INT16) xSrc;
    418     req->ySrc = (INT16) ySrc;
    419 
    420     /*
    421      * Compute the space necessary
    422      */
    423     len = 0;
    424 
    425 #define MAX_8 252
    426 
    427     glyphset = elts[0].glyphset;
    428     for (i = 0; i < nelt; i++)
    429     {
    430 	long	elen;
    431 	int	nchars;
    432 
    433 	/*
    434 	 * Check for glyphset change
    435 	 */
    436 	if (elts[i].glyphset != glyphset)
    437 	{
    438 	    glyphset = elts[i].glyphset;
    439 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
    440 	}
    441 	nchars = elts[i].nchars;
    442 	/*
    443 	 * xGlyphElt must be aligned on a 32-bit boundary; this is
    444 	 * easily done by filling no more than 252 glyphs in each
    445 	 * bucket
    446 	 */
    447 	elen = SIZEOF(xGlyphElt) * ((nchars + MAX_8-1) / MAX_8) + nchars;
    448 	len += (elen + 3) >> 2;
    449     }
    450 
    451     req->length = (CARD16) (req->length + len);
    452 
    453     /*
    454      * Send the glyphs
    455      */
    456     glyphset = elts[0].glyphset;
    457     for (i = 0; i < nelt; i++)
    458     {
    459 	xGlyphElt	*elt;
    460 	_Xconst char	*chars;
    461 	int		nchars;
    462 
    463 	/*
    464 	 * Switch glyphsets
    465 	 */
    466 	if (elts[i].glyphset != glyphset)
    467 	{
    468 	    glyphset = elts[i].glyphset;
    469 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
    470 	    elt->len = 0xff;
    471 	    elt->deltax = 0;
    472 	    elt->deltay = 0;
    473 	    Data32(dpy, &glyphset, 4);
    474 	}
    475 	nchars = elts[i].nchars;
    476 	xDst = elts[i].xOff;
    477 	yDst = elts[i].yOff;
    478 	chars = elts[i].chars;
    479 	while (nchars)
    480 	{
    481 	    int this_chars = nchars > MAX_8 ? MAX_8 : nchars;
    482 
    483 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
    484 	    elt->len = (CARD8) this_chars;
    485 	    elt->deltax = (INT16) xDst;
    486 	    elt->deltay = (INT16) yDst;
    487 	    xDst = 0;
    488 	    yDst = 0;
    489 	    Data (dpy, chars, this_chars);
    490 	    nchars -= this_chars;
    491 	    chars += this_chars;
    492 	}
    493     }
    494 #undef MAX_8
    495 
    496     UnlockDisplay(dpy);
    497     SyncHandle();
    498 }
    499 
    500 void
    501 XRenderCompositeText16 (Display			    *dpy,
    502 			int			    op,
    503 			Picture			    src,
    504 			Picture			    dst,
    505 			_Xconst XRenderPictFormat   *maskFormat,
    506 			int			    xSrc,
    507 			int			    ySrc,
    508 			int			    xDst,
    509 			int			    yDst,
    510 			_Xconst XGlyphElt16	    *elts,
    511 			int			    nelt)
    512 {
    513     XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
    514     xRenderCompositeGlyphs16Req	*req;
    515     GlyphSet			glyphset;
    516     long			len;
    517     int				i;
    518 
    519     if (!nelt)
    520 	return;
    521 
    522     RenderSimpleCheckExtension (dpy, info);
    523     LockDisplay(dpy);
    524 
    525     GetReq(RenderCompositeGlyphs16, req);
    526     req->reqType = (CARD8) info->codes->major_opcode;
    527     req->renderReqType = X_RenderCompositeGlyphs16;
    528     req->op = (CARD8) op;
    529     req->src = (CARD32) src;
    530     req->dst = (CARD32) dst;
    531     req->maskFormat = (CARD32) (maskFormat ? maskFormat->id : None);
    532     req->glyphset = (CARD32) elts[0].glyphset;
    533     req->xSrc = (INT16) xSrc;
    534     req->ySrc = (INT16) ySrc;
    535 
    536     /*
    537      * Compute the space necessary
    538      */
    539     len = 0;
    540 
    541 #define MAX_16	254
    542 
    543     glyphset = elts[0].glyphset;
    544     for (i = 0; i < nelt; i++)
    545     {
    546 	int	nchars;
    547 	long	elen;
    548 
    549 	/*
    550 	 * Check for glyphset change
    551 	 */
    552 	if (elts[i].glyphset != glyphset)
    553 	{
    554 	    glyphset = elts[i].glyphset;
    555 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
    556 	}
    557 	nchars = elts[i].nchars;
    558 	/*
    559 	 * xGlyphElt must be aligned on a 32-bit boundary; this is
    560 	 * easily done by filling no more than 254 glyphs in each
    561 	 * bucket
    562 	 */
    563 	elen = SIZEOF(xGlyphElt) * ((nchars + MAX_16-1) / MAX_16) + nchars * 2;
    564 	len += (elen + 3) >> 2;
    565     }
    566 
    567     req->length = (CARD16) (req->length + len);
    568 
    569     glyphset = elts[0].glyphset;
    570     for (i = 0; i < nelt; i++)
    571     {
    572 	xGlyphElt		*elt;
    573 	_Xconst unsigned short	*chars;
    574 	int			nchars;
    575 
    576 	/*
    577 	 * Switch glyphsets
    578 	 */
    579 	if (elts[i].glyphset != glyphset)
    580 	{
    581 	    glyphset = elts[i].glyphset;
    582 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
    583 	    elt->len = 0xff;
    584 	    elt->deltax = 0;
    585 	    elt->deltay = 0;
    586 	    Data32(dpy, &glyphset, 4);
    587 	}
    588 	nchars = elts[i].nchars;
    589 	xDst = elts[i].xOff;
    590 	yDst = elts[i].yOff;
    591 	chars = elts[i].chars;
    592 	while (nchars)
    593 	{
    594 	    int this_chars = nchars > MAX_16 ? MAX_16 : nchars;
    595 	    int this_bytes = this_chars * 2;
    596 
    597 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
    598 	    elt->len = (CARD8) this_chars;
    599 	    elt->deltax = (INT16) xDst;
    600 	    elt->deltay = (INT16) yDst;
    601 	    xDst = 0;
    602 	    yDst = 0;
    603 	    Data16 (dpy, chars, this_bytes);
    604 	    nchars -= this_chars;
    605 	    chars += this_chars;
    606 	}
    607     }
    608 #undef MAX_16
    609 
    610     UnlockDisplay(dpy);
    611     SyncHandle();
    612 }
    613 
    614 void
    615 XRenderCompositeText32 (Display			    *dpy,
    616 			int			    op,
    617 			Picture			    src,
    618 			Picture			    dst,
    619 			_Xconst XRenderPictFormat   *maskFormat,
    620 			int			    xSrc,
    621 			int			    ySrc,
    622 			int			    xDst,
    623 			int			    yDst,
    624 			_Xconst XGlyphElt32	    *elts,
    625 			int			    nelt)
    626 {
    627     XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
    628     xRenderCompositeGlyphs32Req	*req;
    629     GlyphSet			glyphset;
    630     long			len;
    631     int				i;
    632 
    633     if (!nelt)
    634 	return;
    635 
    636     RenderSimpleCheckExtension (dpy, info);
    637     LockDisplay(dpy);
    638 
    639 
    640     GetReq(RenderCompositeGlyphs32, req);
    641     req->reqType = (CARD8) info->codes->major_opcode;
    642     req->renderReqType = X_RenderCompositeGlyphs32;
    643     req->op = (CARD8) op;
    644     req->src = (CARD32) src;
    645     req->dst = (CARD32) dst;
    646     req->maskFormat = (CARD32) (maskFormat ? maskFormat->id : None);
    647     req->glyphset = (CARD32) elts[0].glyphset;
    648     req->xSrc = (INT16) xSrc;
    649     req->ySrc = (INT16) ySrc;
    650 
    651     /*
    652      * Compute the space necessary
    653      */
    654     len = 0;
    655 
    656 #define MAX_32	254
    657 
    658     glyphset = elts[0].glyphset;
    659     for (i = 0; i < nelt; i++)
    660     {
    661 	int	nchars;
    662 	long	elen;
    663 
    664 	/*
    665 	 * Check for glyphset change
    666 	 */
    667 	if (elts[i].glyphset != glyphset)
    668 	{
    669 	    glyphset = elts[i].glyphset;
    670 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
    671 	}
    672 	nchars = elts[i].nchars;
    673 	elen = SIZEOF(xGlyphElt) * ((nchars + MAX_32-1) / MAX_32) + nchars *4;
    674 	len += (elen + 3) >> 2;
    675     }
    676 
    677     req->length = (CARD16) (req->length + len);
    678 
    679     glyphset = elts[0].glyphset;
    680     for (i = 0; i < nelt; i++)
    681     {
    682 	xGlyphElt		*elt;
    683 	_Xconst unsigned int	*chars;
    684 	int			nchars;
    685 
    686 	/*
    687 	 * Switch glyphsets
    688 	 */
    689 	if (elts[i].glyphset != glyphset)
    690 	{
    691 	    glyphset = elts[i].glyphset;
    692 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
    693 	    elt->len = 0xff;
    694 	    elt->deltax = 0;
    695 	    elt->deltay = 0;
    696 	    Data32(dpy, &glyphset, 4);
    697 	}
    698 	nchars = elts[i].nchars;
    699 	xDst = elts[i].xOff;
    700 	yDst = elts[i].yOff;
    701 	chars = elts[i].chars;
    702 	while (nchars)
    703 	{
    704 	    int this_chars = nchars > MAX_32 ? MAX_32 : nchars;
    705 	    int this_bytes = this_chars * 4;
    706 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
    707 	    elt->len = (CARD8) this_chars;
    708 	    elt->deltax = (INT16) xDst;
    709 	    elt->deltay = (INT16) yDst;
    710 	    xDst = 0;
    711 	    yDst = 0;
    712 	    DataInt32 (dpy, chars, this_bytes);
    713 	    nchars -= this_chars;
    714 	    chars += this_chars;
    715 	}
    716     }
    717 #undef MAX_32
    718 
    719     UnlockDisplay(dpy);
    720     SyncHandle();
    721 }
    722