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
XRenderCreateGlyphSet(Display * dpy,_Xconst XRenderPictFormat * format)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 = info->codes->major_opcode;
41     req->renderReqType = X_RenderCreateGlyphSet;
42     req->gsid = gsid = XAllocID(dpy);
43     req->format = format->id;
44     UnlockDisplay(dpy);
45     SyncHandle();
46     return gsid;
47 }
48 
49 GlyphSet
XRenderReferenceGlyphSet(Display * dpy,GlyphSet existing)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 = info->codes->major_opcode;
60     req->renderReqType = X_RenderReferenceGlyphSet;
61     req->gsid = gsid = XAllocID(dpy);
62     req->existing = existing;
63     UnlockDisplay(dpy);
64     SyncHandle();
65     return gsid;
66 }
67 
68 void
XRenderFreeGlyphSet(Display * dpy,GlyphSet glyphset)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 = info->codes->major_opcode;
78     req->renderReqType = X_RenderFreeGlyphSet;
79     req->glyphset = glyphset;
80     UnlockDisplay(dpy);
81     SyncHandle();
82 }
83 
84 void
XRenderAddGlyphs(Display * dpy,GlyphSet glyphset,_Xconst Glyph * gids,_Xconst XGlyphInfo * glyphs,int nglyphs,_Xconst char * images,int nbyte_images)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 = info->codes->major_opcode;
103     req->renderReqType = X_RenderAddGlyphs;
104     req->glyphset = glyphset;
105     req->nglyphs = nglyphs;
106     len = (nglyphs * (SIZEOF (xGlyphInfo) + 4) + nbyte_images) >> 2;
107     SetReqLen(req, len, len);
108     Data32 (dpy, (long *) gids, nglyphs * 4);
109     Data16 (dpy, (short *) glyphs, nglyphs * SIZEOF (xGlyphInfo));
110     Data (dpy, images, nbyte_images);
111     UnlockDisplay(dpy);
112     SyncHandle();
113 }
114 
115 void
XRenderFreeGlyphs(Display * dpy,GlyphSet glyphset,_Xconst Glyph * gids,int nglyphs)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 = info->codes->major_opcode;
129     req->renderReqType = X_RenderFreeGlyphs;
130     req->glyphset = glyphset;
131     len = nglyphs;
132     SetReqLen(req, len, len);
133     len <<= 2;
134     Data32 (dpy, (long *) gids, len);
135     UnlockDisplay(dpy);
136     SyncHandle();
137 }
138 
139 void
XRenderCompositeString8(Display * dpy,int op,Picture src,Picture dst,_Xconst XRenderPictFormat * maskFormat,GlyphSet glyphset,int xSrc,int ySrc,int xDst,int yDst,_Xconst char * string,int nchar)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 = info->codes->major_opcode;
167     req->renderReqType = X_RenderCompositeGlyphs8;
168     req->op = op;
169     req->src = src;
170     req->dst = dst;
171     req->maskFormat = maskFormat ? maskFormat->id : None;
172     req->glyphset = glyphset;
173     req->xSrc = xSrc;
174     req->ySrc = 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 += (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 = xDst;
202 	elt->deltay = 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 = nchar;
215 	elt->deltax = xDst;
216 	elt->deltay = yDst;
217 	memcpy ((char *) (elt + 1), string, nchar);
218     }
219 #undef MAX_8
220 
221     UnlockDisplay(dpy);
222     SyncHandle();
223 }
224 void
XRenderCompositeString16(Display * dpy,int op,Picture src,Picture dst,_Xconst XRenderPictFormat * maskFormat,GlyphSet glyphset,int xSrc,int ySrc,int xDst,int yDst,_Xconst unsigned short * string,int nchar)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 = info->codes->major_opcode;
252     req->renderReqType = X_RenderCompositeGlyphs16;
253     req->op = op;
254     req->src = src;
255     req->dst = dst;
256     req->maskFormat = maskFormat ? maskFormat->id : None;
257     req->glyphset = glyphset;
258     req->xSrc = xSrc;
259     req->ySrc = ySrc;
260 
261 #define MAX_16	254
262 
263     len = SIZEOF(xGlyphElt) * ((nchar + MAX_16-1) / MAX_16) + nchar * 2;
264 
265     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 = xDst;
281 	elt->deltay = yDst;
282 	xDst = 0;
283 	yDst = 0;
284 	memcpy ((char *) (elt + 1), (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 = nchar;
294 	elt->deltax = xDst;
295 	elt->deltay = yDst;
296 	memcpy ((char *) (elt + 1), (char *) string, nchar * 2);
297     }
298 #undef MAX_16
299 
300     UnlockDisplay(dpy);
301     SyncHandle();
302 }
303 
304 void
XRenderCompositeString32(Display * dpy,int op,Picture src,Picture dst,_Xconst XRenderPictFormat * maskFormat,GlyphSet glyphset,int xSrc,int ySrc,int xDst,int yDst,_Xconst unsigned int * string,int nchar)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 = info->codes->major_opcode;
332     req->renderReqType = X_RenderCompositeGlyphs32;
333     req->op = op;
334     req->src = src;
335     req->dst = dst;
336     req->maskFormat = maskFormat ? maskFormat->id : None;
337     req->glyphset = glyphset;
338     req->xSrc = xSrc;
339     req->ySrc = ySrc;
340 
341 #define MAX_32	254
342 
343     len = SIZEOF(xGlyphElt) * ((nchar + MAX_32-1) / MAX_32) + nchar * 4;
344 
345     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 = xDst;
361 	elt->deltay = yDst;
362 	xDst = 0;
363 	yDst = 0;
364 	memcpy ((char *) (elt + 1), (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 = nchar;
374 	elt->deltax = xDst;
375 	elt->deltay = yDst;
376 	memcpy ((char *) (elt + 1), (char *) string, nchar * 4);
377     }
378 #undef MAX_32
379 
380     UnlockDisplay(dpy);
381     SyncHandle();
382 }
383 
384 void
XRenderCompositeText8(Display * dpy,int op,Picture src,Picture dst,_Xconst XRenderPictFormat * maskFormat,int xSrc,int ySrc,int xDst,int yDst,_Xconst XGlyphElt8 * elts,int nelt)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     long			elen;
402     xGlyphElt			*elt;
403     int				i;
404     _Xconst char		*chars;
405     int				nchars;
406 
407     if (!nelt)
408 	return;
409 
410     RenderSimpleCheckExtension (dpy, info);
411     LockDisplay(dpy);
412 
413     GetReq(RenderCompositeGlyphs8, req);
414     req->reqType = info->codes->major_opcode;
415     req->renderReqType = X_RenderCompositeGlyphs8;
416     req->op = op;
417     req->src = src;
418     req->dst = dst;
419     req->maskFormat = maskFormat ? maskFormat->id : None;
420     req->glyphset = elts[0].glyphset;
421     req->xSrc = xSrc;
422     req->ySrc = ySrc;
423 
424     /*
425      * Compute the space necessary
426      */
427     len = 0;
428 
429 #define MAX_8 252
430 
431     glyphset = elts[0].glyphset;
432     for (i = 0; i < nelt; i++)
433     {
434 	/*
435 	 * Check for glyphset change
436 	 */
437 	if (elts[i].glyphset != glyphset)
438 	{
439 	    glyphset = elts[i].glyphset;
440 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
441 	}
442 	nchars = elts[i].nchars;
443 	/*
444 	 * xGlyphElt must be aligned on a 32-bit boundary; this is
445 	 * easily done by filling no more than 252 glyphs in each
446 	 * bucket
447 	 */
448 	elen = SIZEOF(xGlyphElt) * ((nchars + MAX_8-1) / MAX_8) + nchars;
449 	len += (elen + 3) >> 2;
450     }
451 
452     req->length += len;
453 
454     /*
455      * Send the glyphs
456      */
457     glyphset = elts[0].glyphset;
458     for (i = 0; i < nelt; i++)
459     {
460 	/*
461 	 * Switch glyphsets
462 	 */
463 	if (elts[i].glyphset != glyphset)
464 	{
465 	    glyphset = elts[i].glyphset;
466 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
467 	    elt->len = 0xff;
468 	    elt->deltax = 0;
469 	    elt->deltay = 0;
470 	    Data32(dpy, &glyphset, 4);
471 	}
472 	nchars = elts[i].nchars;
473 	xDst = elts[i].xOff;
474 	yDst = elts[i].yOff;
475 	chars = elts[i].chars;
476 	while (nchars)
477 	{
478 	    int this_chars = nchars > MAX_8 ? MAX_8 : nchars;
479 
480 	    BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
481 	    elt->len = this_chars;
482 	    elt->deltax = xDst;
483 	    elt->deltay = yDst;
484 	    xDst = 0;
485 	    yDst = 0;
486 	    Data (dpy, chars, this_chars);
487 	    nchars -= this_chars;
488 	    chars += this_chars;
489 	}
490     }
491 #undef MAX_8
492 
493     UnlockDisplay(dpy);
494     SyncHandle();
495 }
496 
497 void
XRenderCompositeText16(Display * dpy,int op,Picture src,Picture dst,_Xconst XRenderPictFormat * maskFormat,int xSrc,int ySrc,int xDst,int yDst,_Xconst XGlyphElt16 * elts,int nelt)498 XRenderCompositeText16 (Display			    *dpy,
499 			int			    op,
500 			Picture			    src,
501 			Picture			    dst,
502 			_Xconst XRenderPictFormat   *maskFormat,
503 			int			    xSrc,
504 			int			    ySrc,
505 			int			    xDst,
506 			int			    yDst,
507 			_Xconst XGlyphElt16	    *elts,
508 			int			    nelt)
509 {
510     XRenderExtDisplayInfo		*info = XRenderFindDisplay (dpy);
511     xRenderCompositeGlyphs16Req	*req;
512     GlyphSet			glyphset;
513     long			len;
514     long			elen;
515     xGlyphElt			*elt;
516     int				i;
517     _Xconst unsigned short    	*chars;
518     int				nchars;
519 
520     if (!nelt)
521 	return;
522 
523     RenderSimpleCheckExtension (dpy, info);
524     LockDisplay(dpy);
525 
526     GetReq(RenderCompositeGlyphs16, req);
527     req->reqType = info->codes->major_opcode;
528     req->renderReqType = X_RenderCompositeGlyphs16;
529     req->op = op;
530     req->src = src;
531     req->dst = dst;
532     req->maskFormat = maskFormat ? maskFormat->id : None;
533     req->glyphset = elts[0].glyphset;
534     req->xSrc = xSrc;
535     req->ySrc = ySrc;
536 
537     /*
538      * Compute the space necessary
539      */
540     len = 0;
541 
542 #define MAX_16	254
543 
544     glyphset = elts[0].glyphset;
545     for (i = 0; i < nelt; i++)
546     {
547 	/*
548 	 * Check for glyphset change
549 	 */
550 	if (elts[i].glyphset != glyphset)
551 	{
552 	    glyphset = elts[i].glyphset;
553 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
554 	}
555 	nchars = elts[i].nchars;
556 	/*
557 	 * xGlyphElt must be aligned on a 32-bit boundary; this is
558 	 * easily done by filling no more than 254 glyphs in each
559 	 * bucket
560 	 */
561 	elen = SIZEOF(xGlyphElt) * ((nchars + MAX_16-1) / MAX_16) + nchars * 2;
562 	len += (elen + 3) >> 2;
563     }
564 
565     req->length += len;
566 
567     glyphset = elts[0].glyphset;
568     for (i = 0; i < nelt; i++)
569     {
570 	/*
571 	 * Switch glyphsets
572 	 */
573 	if (elts[i].glyphset != glyphset)
574 	{
575 	    glyphset = elts[i].glyphset;
576 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
577 	    elt->len = 0xff;
578 	    elt->deltax = 0;
579 	    elt->deltay = 0;
580 	    Data32(dpy, &glyphset, 4);
581 	}
582 	nchars = elts[i].nchars;
583 	xDst = elts[i].xOff;
584 	yDst = elts[i].yOff;
585 	chars = elts[i].chars;
586 	while (nchars)
587 	{
588 	    int this_chars = nchars > MAX_16 ? MAX_16 : nchars;
589 	    int this_bytes = this_chars * 2;
590 
591 	    BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
592 	    elt->len = this_chars;
593 	    elt->deltax = xDst;
594 	    elt->deltay = yDst;
595 	    xDst = 0;
596 	    yDst = 0;
597 	    Data16 (dpy, chars, this_bytes);
598 	    nchars -= this_chars;
599 	    chars += this_chars;
600 	}
601     }
602 #undef MAX_16
603 
604     UnlockDisplay(dpy);
605     SyncHandle();
606 }
607 
608 void
XRenderCompositeText32(Display * dpy,int op,Picture src,Picture dst,_Xconst XRenderPictFormat * maskFormat,int xSrc,int ySrc,int xDst,int yDst,_Xconst XGlyphElt32 * elts,int nelt)609 XRenderCompositeText32 (Display			    *dpy,
610 			int			    op,
611 			Picture			    src,
612 			Picture			    dst,
613 			_Xconst XRenderPictFormat   *maskFormat,
614 			int			    xSrc,
615 			int			    ySrc,
616 			int			    xDst,
617 			int			    yDst,
618 			_Xconst XGlyphElt32	    *elts,
619 			int			    nelt)
620 {
621     XRenderExtDisplayInfo		*info = XRenderFindDisplay (dpy);
622     xRenderCompositeGlyphs32Req	*req;
623     GlyphSet			glyphset;
624     long			len;
625     long			elen;
626     xGlyphElt			*elt;
627     int				i;
628     _Xconst unsigned int    	*chars;
629     int				nchars;
630 
631     if (!nelt)
632 	return;
633 
634     RenderSimpleCheckExtension (dpy, info);
635     LockDisplay(dpy);
636 
637 
638     GetReq(RenderCompositeGlyphs32, req);
639     req->reqType = info->codes->major_opcode;
640     req->renderReqType = X_RenderCompositeGlyphs32;
641     req->op = op;
642     req->src = src;
643     req->dst = dst;
644     req->maskFormat = maskFormat ? maskFormat->id : None;
645     req->glyphset = elts[0].glyphset;
646     req->xSrc = xSrc;
647     req->ySrc = ySrc;
648 
649     /*
650      * Compute the space necessary
651      */
652     len = 0;
653 
654 #define MAX_32	254
655 
656     glyphset = elts[0].glyphset;
657     for (i = 0; i < nelt; i++)
658     {
659 	/*
660 	 * Check for glyphset change
661 	 */
662 	if (elts[i].glyphset != glyphset)
663 	{
664 	    glyphset = elts[i].glyphset;
665 	    len += (SIZEOF (xGlyphElt) + 4) >> 2;
666 	}
667 	nchars = elts[i].nchars;
668 	elen = SIZEOF(xGlyphElt) * ((nchars + MAX_32-1) / MAX_32) + nchars *4;
669 	len += (elen + 3) >> 2;
670     }
671 
672     req->length += len;
673 
674     glyphset = elts[0].glyphset;
675     for (i = 0; i < nelt; i++)
676     {
677 	/*
678 	 * Switch glyphsets
679 	 */
680 	if (elts[i].glyphset != glyphset)
681 	{
682 	    glyphset = elts[i].glyphset;
683 	    BufAlloc (xGlyphElt *, elt, SIZEOF (xGlyphElt));
684 	    elt->len = 0xff;
685 	    elt->deltax = 0;
686 	    elt->deltay = 0;
687 	    Data32(dpy, &glyphset, 4);
688 	}
689 	nchars = elts[i].nchars;
690 	xDst = elts[i].xOff;
691 	yDst = elts[i].yOff;
692 	chars = elts[i].chars;
693 	while (nchars)
694 	{
695 	    int this_chars = nchars > MAX_32 ? MAX_32 : nchars;
696 	    int this_bytes = this_chars * 4;
697 	    BufAlloc (xGlyphElt *, elt, SIZEOF(xGlyphElt))
698 	    elt->len = this_chars;
699 	    elt->deltax = xDst;
700 	    elt->deltay = yDst;
701 	    xDst = 0;
702 	    yDst = 0;
703 	    DataInt32 (dpy, chars, this_bytes);
704 	    nchars -= this_chars;
705 	    chars += this_chars;
706 	}
707     }
708 #undef MAX_32
709 
710     UnlockDisplay(dpy);
711     SyncHandle();
712 }
713