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