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
30GlyphSet
31XRenderCreateGlyphSet (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
49GlyphSet
50XRenderReferenceGlyphSet (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
68void
69XRenderFreeGlyphSet (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
84void
85XRenderAddGlyphs (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
115void
116XRenderFreeGlyphs (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
139void
140XRenderCompositeString8 (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}
224void
225XRenderCompositeString16 (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
304void
305XRenderCompositeString32 (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
384void
385XRenderCompositeText8 (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
500void
501XRenderCompositeText16 (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
614void
615XRenderCompositeText32 (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