1 /*
2  * Copyright © 2000 Keith Packard
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Keith Packard not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  Keith Packard makes no
11  * representations about the suitability of this software for any purpose.  It
12  * is provided "as is" without express or implied warranty.
13  *
14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  */
22 
23 #include "xftint.h"
24 
25 #define NUM_LOCAL	1024
26 #define NUM_ELT_LOCAL	128
27 
28 /*
29  * Use the Render extension to draw the glyphs
30  */
31 
32 _X_EXPORT void
XftGlyphRender(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FT_UInt * glyphs,int nglyphs)33 XftGlyphRender (Display		*dpy,
34 		int		op,
35 		Picture		src,
36 		XftFont		*pub,
37 		Picture		dst,
38 		int		srcx,
39 		int		srcy,
40 		int		x,
41 		int		y,
42 		_Xconst FT_UInt	*glyphs,
43 		int		nglyphs)
44 {
45     XftFontInt	    *font = (XftFontInt *) pub;
46     int		    i;
47     FT_UInt	    missing[XFT_NMISSING];
48     int		    nmissing;
49     FT_UInt	    g, max;
50     int		    size, width;
51     Glyph	    wire;
52     char	    *char8;
53     unsigned short  *char16;
54     unsigned int    *char32;
55     unsigned int    char_local[NUM_LOCAL];
56     unsigned int    *chars;
57     FcBool	    glyphs_loaded;
58 
59     if (!font->format)
60 	return;
61 
62     /*
63      * Load missing glyphs
64      */
65     nmissing = 0;
66     max = 0;
67     glyphs_loaded = FcFalse;
68     for (i = 0; i < nglyphs; i++)
69     {
70 	g = glyphs[i];
71 	if (g > max)
72 	    max = g;
73 	if (XftFontCheckGlyph (dpy, pub, FcTrue, g, missing, &nmissing))
74 	    glyphs_loaded = FcTrue;
75     }
76     if (nmissing)
77 	XftFontLoadGlyphs (dpy, pub, FcTrue, missing, nmissing);
78 
79     if (!font->glyphset)
80 	goto bail1;
81     if (max < 0x100)
82     {
83 	width = 1;
84 	size = sizeof (char);
85     }
86     else if (max < 0x10000)
87     {
88 	width = 2;
89 	size = sizeof (unsigned short);
90     }
91     else
92     {
93 	width = 4;
94 	size = sizeof (unsigned int);
95     }
96     chars = char_local;
97     if (nglyphs * size > sizeof (char_local))
98     {
99 	chars = malloc ((size_t)(nglyphs * size));
100 	if (!chars)
101 	    goto bail1;
102     }
103     char8 = (char *) chars;
104     char16 = (unsigned short *) chars;
105     char32 = (unsigned int *) chars;
106     for (i = 0; i < nglyphs; i++)
107     {
108 	wire = (Glyph) glyphs[i];
109 	if (wire >= font->num_glyphs || !font->glyphs[wire])
110 	    wire = 0;
111 	switch (width) {
112 	case 1: char8[i] = (char) wire; break;
113 	case 2: char16[i] = (unsigned short) wire; break;
114 	case 4: char32[i] = (unsigned int) wire; break;
115 	}
116     }
117     switch (width) {
118     case 1:
119     default:
120 	XRenderCompositeString8 (dpy, op,
121 				 src, dst, font->format, font->glyphset,
122 				 srcx, srcy, x, y, char8, nglyphs);
123 	break;
124     case 2:
125 	XRenderCompositeString16(dpy, op,
126 				 src, dst, font->format, font->glyphset,
127 				 srcx, srcy, x, y, char16, nglyphs);
128 	break;
129     case 4:
130 	XRenderCompositeString32(dpy, op,
131 				 src, dst, font->format, font->glyphset,
132 				 srcx, srcy, x, y, char32, nglyphs);
133 	break;
134     }
135     if (chars != char_local)
136 	free (chars);
137 bail1:
138     if (glyphs_loaded)
139 	_XftFontManageMemory (dpy, pub);
140 }
141 
142 _X_EXPORT void
XftGlyphSpecRender(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,_Xconst XftGlyphSpec * glyphs,int nglyphs)143 XftGlyphSpecRender (Display		    *dpy,
144 		    int			    op,
145 		    Picture		    src,
146 		    XftFont		    *pub,
147 		    Picture		    dst,
148 		    int			    srcx,
149 		    int			    srcy,
150 		    _Xconst XftGlyphSpec    *glyphs,
151 		    int			    nglyphs)
152 {
153     XftFontInt	    *font = (XftFontInt *) pub;
154     int		    i, j;
155     FT_UInt	    missing[XFT_NMISSING];
156     int		    nmissing;
157     int		    n;
158     FT_UInt	    g;
159     XftGlyph	    *glyph;
160     FT_UInt	    max;
161     int		    size, width;
162     char	    *char8;
163     unsigned short  *char16;
164     unsigned int    *char32;
165     unsigned int    char_local[NUM_LOCAL];
166     unsigned int    *chars;
167     XGlyphElt8	    *elts;
168     XGlyphElt8	    elts_local[NUM_ELT_LOCAL];
169     FcBool	    glyphs_loaded;
170     int		    nelt;
171     int		    x, y;
172 
173     if (!font->format)
174 	return;
175     if (!nglyphs)
176 	return;
177 
178     /*
179      * Load missing glyphs
180      */
181     max = 0;
182     nmissing = 0;
183     glyphs_loaded = FcFalse;
184     g = glyphs[0].glyph;
185     for (i = 0; i < nglyphs; i++)
186     {
187 	g = glyphs[i].glyph;
188 	if (g > max)
189 	    max = g;
190 	if (XftFontCheckGlyph (dpy, pub, FcTrue, g, missing, &nmissing))
191 	    glyphs_loaded = FcTrue;
192     }
193     if (nmissing)
194 	XftFontLoadGlyphs (dpy, pub, FcTrue, missing, nmissing);
195 
196     if (!font->glyphset)
197 	goto bail1;
198 
199     /*
200      * See what encoding size is needed
201      */
202     if (max < 0x100)
203     {
204 	size = sizeof (char);
205 	width = 1;
206     }
207     else if (max < 0x10000)
208     {
209 	size = sizeof (unsigned short);
210 	width = 2;
211     }
212     else
213     {
214 	size = sizeof (unsigned int);
215 	width = 4;
216     }
217     chars = char_local;
218     if (nglyphs * size > NUM_LOCAL)
219     {
220 	chars = malloc ((size_t)(nglyphs * size));
221 	if (!chars)
222 	    goto bail1;
223     }
224     char8 = (char *) chars;
225     char16 = (unsigned short *) chars;
226     char32 = (unsigned int *) chars;
227 
228     /*
229      * Compute the number of glyph elts needed
230      */
231     nelt = 1;
232     for (i = 0; i < nglyphs; i++)
233     {
234 	g = glyphs[i].glyph;
235 	/* Substitute default for non-existant glyphs */
236 	if (g >= font->num_glyphs || !font->glyphs[g])
237 	    g = 0;
238 	if (font->glyphs[g])
239 	     break;
240     }
241     if (i == nglyphs)
242 	goto bail2;
243     glyph = font->glyphs[g];
244     x = glyphs[i].x + glyph->metrics.xOff;
245     y = glyphs[i].y + glyph->metrics.yOff;
246     while (++i < nglyphs)
247     {
248 	g = glyphs[i].glyph;
249 	/* Substitute default for non-existant glyphs */
250 	if (g >= font->num_glyphs || !font->glyphs[g])
251 	    g = 0;
252 	/*
253 	 * check to see if the glyph is placed where it would
254 	 * fall using the normal spacing
255 	 */
256 	if ((glyph = font->glyphs[g]))
257 	{
258 	    if (x != glyphs[i].x || y != glyphs[i].y)
259 	    {
260 		x = glyphs[i].x;
261 		y = glyphs[i].y;
262 		++nelt;
263 	    }
264 	    x += glyph->metrics.xOff;
265 	    y += glyph->metrics.yOff;
266 	}
267     }
268 
269     elts = elts_local;
270     if (nelt > NUM_ELT_LOCAL)
271     {
272 	elts = malloc ((size_t)nelt * sizeof (XGlyphElt8));
273 	if (!elts)
274 	    goto bail2;
275     }
276 
277     /*
278      * Generate the list of glyph elts
279      */
280     nelt = 0;
281     x = y = 0;
282     n = 0;
283     j = 0;
284     for (i = 0; i < nglyphs; i++)
285     {
286 	g = glyphs[i].glyph;
287 	/* Substitute default for non-existant glyphs */
288 	if (g >= font->num_glyphs || !font->glyphs[g])
289 	    g = 0;
290 	if ((glyph = font->glyphs[g]))
291 	{
292 	    if (!i || x != glyphs[i].x || y != glyphs[i].y)
293 	    {
294 		if (n)
295 		{
296 		    elts[nelt].nchars = n;
297 		    nelt++;
298 		}
299 		elts[nelt].glyphset = font->glyphset;
300 		elts[nelt].chars = char8 + size * j;
301 		elts[nelt].xOff = glyphs[i].x - x;
302 		elts[nelt].yOff = glyphs[i].y - y;
303 		x = glyphs[i].x;
304 		y = glyphs[i].y;
305 		n = 0;
306 	    }
307 	    switch (width) {
308 	    case 1: char8[j] = (char) g; break;
309 	    case 2: char16[j] = (unsigned short) g; break;
310 	    case 4: char32[j] = (unsigned int) g; break;
311 	    }
312 	    x += glyph->metrics.xOff;
313 	    y += glyph->metrics.yOff;
314 	    j++;
315 	    n++;
316 	}
317     }
318     if (n)
319     {
320 	elts[nelt].nchars = n;
321 	nelt++;
322     }
323     switch (width) {
324     case 1:
325 	XRenderCompositeText8 (dpy, op, src, dst, font->format,
326 			       srcx, srcy, glyphs[0].x, glyphs[0].y,
327 			       elts, nelt);
328 	break;
329     case 2:
330 	XRenderCompositeText16 (dpy, op, src, dst, font->format,
331 				srcx, srcy, glyphs[0].x, glyphs[0].y,
332 				(XGlyphElt16 *) elts, nelt);
333 	break;
334     case 4:
335 	XRenderCompositeText32 (dpy, op, src, dst, font->format,
336 				srcx, srcy, glyphs[0].x, glyphs[0].y,
337 				(XGlyphElt32 *) elts, nelt);
338 	break;
339     }
340 
341     if (elts != elts_local)
342 	free (elts);
343 bail2:
344     if (chars != char_local)
345 	free (chars);
346 bail1:
347     if (glyphs_loaded)
348 	_XftFontManageMemory (dpy, pub);
349 }
350 
351 _X_EXPORT void
XftCharSpecRender(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,_Xconst XftCharSpec * chars,int len)352 XftCharSpecRender (Display		*dpy,
353 		   int			op,
354 		   Picture		src,
355 		   XftFont		*pub,
356 		   Picture		dst,
357 		   int			srcx,
358 		   int			srcy,
359 		   _Xconst XftCharSpec	*chars,
360 		   int			len)
361 {
362     XftGlyphSpec    *glyphs, glyphs_local[NUM_LOCAL];
363     int		    i;
364 
365     if (len <= NUM_LOCAL)
366 	glyphs = glyphs_local;
367     else
368     {
369 	glyphs = malloc ((size_t)len * sizeof (XftGlyphSpec));
370 	if (!glyphs)
371 	    return;
372     }
373     for (i = 0; i < len; i++)
374     {
375 	glyphs[i].glyph = XftCharIndex(dpy, pub, chars[i].ucs4);
376 	glyphs[i].x = chars[i].x;
377 	glyphs[i].y = chars[i].y;
378     }
379 
380     XftGlyphSpecRender (dpy, op, src, pub, dst, srcx, srcy, glyphs, len);
381 
382     if (glyphs != glyphs_local)
383 	free (glyphs);
384 }
385 
386 /*
387  * Choose which format to draw text in when drawing with fonts
388  * of different formats.  The trick is that ARGB formats aren't
389  * compatible with A formats as PictOpAdd does the wrong thing, so
390  * fall back to an A format when presented with an ARGB and A format
391  */
392 
393 #define XftIsARGBFormat(a)  ((a)->depth == 32)
394 
395 static XRenderPictFormat *
XftPreferFormat(Display * dpy,XRenderPictFormat * a,XRenderPictFormat * b)396 XftPreferFormat (Display *dpy, XRenderPictFormat *a, XRenderPictFormat *b)
397 {
398     XRenderPictFormat	*prefer = NULL;
399 
400     if (a == b)
401 	prefer = a;
402     else if (XftIsARGBFormat(a) != XftIsARGBFormat(b))
403 	prefer = XRenderFindStandardFormat (dpy, PictStandardA8);
404     else if (a->depth > b->depth)
405 	prefer = a;
406     else
407 	prefer = b;
408     return prefer;
409 }
410 
411 _X_EXPORT void
XftGlyphFontSpecRender(Display * dpy,int op,Picture src,Picture dst,int srcx,int srcy,_Xconst XftGlyphFontSpec * glyphs,int nglyphs)412 XftGlyphFontSpecRender (Display			    *dpy,
413 			int			    op,
414 			Picture			    src,
415 			Picture			    dst,
416 			int			    srcx,
417 			int			    srcy,
418 			_Xconst XftGlyphFontSpec    *glyphs,
419 			int			    nglyphs)
420 {
421     int		    i, j;
422     XftFont	    *prevPublic;
423     XftFontInt	    *firstFont;
424     XRenderPictFormat	*format;
425     FT_UInt	    missing[XFT_NMISSING];
426     int		    nmissing;
427     int		    n;
428     FT_UInt	    g;
429     XftGlyph	    *glyph;
430     FT_UInt	    max;
431     int		    size, width;
432     char	    *char8;
433     unsigned short  *char16;
434     unsigned int    *char32;
435     unsigned int    char_local[NUM_LOCAL];
436     unsigned int    *chars;
437     XGlyphElt8	    *elts;
438     XGlyphElt8	    elts_local[NUM_ELT_LOCAL];
439     FcBool	    glyphs_loaded;
440     int		    nelt;
441     int		    x, y;
442 
443     if (!nglyphs)
444 	return;
445 
446     /*
447      * Load missing glyphs.  Have to load them
448      * one at a time in case the font changes
449      */
450     max = 0;
451     glyphs_loaded = FcFalse;
452     g = glyphs[0].glyph;
453     for (i = 0; i < nglyphs; i++)
454     {
455 	XftFont	    *pub = glyphs[i].font;
456 	XftFontInt  *font = (XftFontInt *) pub;
457 	g = glyphs[i].glyph;
458 	if (g > max)
459 	    max = g;
460 	nmissing = 0;
461 	if (XftFontCheckGlyph (dpy, pub, FcTrue, g, missing, &nmissing))
462 	    glyphs_loaded = FcTrue;
463 	if (nmissing)
464 	    XftFontLoadGlyphs (dpy, pub, FcTrue, missing, nmissing);
465 	if (!font->format)
466 	    goto bail1;
467 	if (!font->glyphset)
468 	    goto bail1;
469     }
470 
471     /*
472      * See what encoding size is needed
473      */
474     if (max < 0x100)
475     {
476 	size = sizeof (char);
477 	width = 1;
478     }
479     else if (max < 0x10000)
480     {
481 	size = sizeof (unsigned short);
482 	width = 2;
483     }
484     else
485     {
486 	size = sizeof (unsigned int);
487 	width = 4;
488     }
489     chars = char_local;
490     if (nglyphs * size > NUM_LOCAL)
491     {
492 	chars = malloc ((size_t)(nglyphs * size));
493 	if (!chars)
494 	    goto bail1;
495     }
496     char8 = (char *) chars;
497     char16 = (unsigned short *) chars;
498     char32 = (unsigned int *) chars;
499 
500     /*
501      * Compute the number of glyph elts needed
502      */
503     nelt = 1;
504     firstFont = NULL;
505     for (i = 0; i < nglyphs; i++)
506     {
507 	XftFont	    *pub = glyphs[i].font;
508 	XftFontInt  *font = (XftFontInt *) pub;
509 	g = glyphs[i].glyph;
510 	/* Substitute default for non-existant glyphs */
511 	if (g >= font->num_glyphs || !font->glyphs[g])
512 	    g = 0;
513 	if (font->glyphs[g])
514 	{
515 	    firstFont = font;
516 	    break;
517 	}
518     }
519     if (i == nglyphs || !firstFont)
520 	goto bail2;
521     glyph = firstFont->glyphs[g];
522     format = firstFont->format;
523     x = glyphs[i].x + glyph->metrics.xOff;
524     y = glyphs[i].y + glyph->metrics.yOff;
525     prevPublic = NULL;
526     while (++i < nglyphs)
527     {
528 	XftFont	    *pub = glyphs[i].font;
529 	XftFontInt  *font = (XftFontInt *) pub;
530 	g = glyphs[i].glyph;
531 	/* Substitute default for non-existant glyphs */
532 	if (g >= font->num_glyphs || !font->glyphs[g])
533 	    g = 0;
534 	/*
535 	 * check to see if the glyph is placed where it would
536 	 * fall using the normal spacing
537 	 */
538 	if ((glyph = font->glyphs[g]))
539 	{
540 	    if (pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y)
541 	    {
542 		prevPublic = pub;
543 		if (font->format != format)
544 		    format = XftPreferFormat (dpy, font->format, format);
545 		x = glyphs[i].x;
546 		y = glyphs[i].y;
547 		++nelt;
548 	    }
549 	    x += glyph->metrics.xOff;
550 	    y += glyph->metrics.yOff;
551 	}
552     }
553 
554     elts = elts_local;
555     if (nelt > NUM_ELT_LOCAL)
556     {
557 	elts = malloc ((size_t)nelt * sizeof (XGlyphElt8));
558 	if (!elts)
559 	    goto bail2;
560     }
561 
562     /*
563      * Generate the list of glyph elts
564      */
565     nelt = 0;
566     x = y = 0;
567     n = 0;
568     j = 0;
569     prevPublic = NULL;
570     for (i = 0; i < nglyphs; i++)
571     {
572 	XftFont	    *pub = glyphs[i].font;
573 	XftFontInt  *font = (XftFontInt *) pub;
574 
575 	g = glyphs[i].glyph;
576 	/* Substitute default for non-existant glyphs */
577 	if (g >= font->num_glyphs || !font->glyphs[g])
578 	    g = 0;
579 	if ((glyph = font->glyphs[g]))
580 	{
581 	    if (!i || pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y)
582 	    {
583 		if (n)
584 		{
585 		    elts[nelt].nchars = n;
586 		    nelt++;
587 		}
588 		elts[nelt].glyphset = font->glyphset;
589 		elts[nelt].chars = char8 + size * j;
590 		elts[nelt].xOff = glyphs[i].x - x;
591 		elts[nelt].yOff = glyphs[i].y - y;
592 		prevPublic = pub;
593 		x = glyphs[i].x;
594 		y = glyphs[i].y;
595 		n = 0;
596 	    }
597 	    switch (width) {
598 	    case 1: char8[j] = (char) g; break;
599 	    case 2: char16[j] = (unsigned short) g; break;
600 	    case 4: char32[j] = (unsigned int) g; break;
601 	    }
602 	    x += glyph->metrics.xOff;
603 	    y += glyph->metrics.yOff;
604 	    j++;
605 	    n++;
606 	}
607     }
608     if (n)
609     {
610 	elts[nelt].nchars = n;
611 	nelt++;
612     }
613     switch (width) {
614     case 1:
615 	XRenderCompositeText8 (dpy, op, src, dst, format,
616 			       srcx, srcy, glyphs[0].x, glyphs[0].y,
617 			       elts, nelt);
618 	break;
619     case 2:
620 	XRenderCompositeText16 (dpy, op, src, dst, format,
621 				srcx, srcy, glyphs[0].x, glyphs[0].y,
622 				(XGlyphElt16 *) elts, nelt);
623 	break;
624     case 4:
625 	XRenderCompositeText32 (dpy, op, src, dst, format,
626 				srcx, srcy, glyphs[0].x, glyphs[0].y,
627 				(XGlyphElt32 *) elts, nelt);
628 	break;
629     }
630 
631     if (elts != elts_local)
632 	free (elts);
633 bail2:
634     if (chars != char_local)
635 	free (chars);
636 bail1:
637     if (glyphs_loaded)
638 	for (i = 0; i < nglyphs; i++)
639 	    _XftFontManageMemory (dpy, glyphs[i].font);
640 }
641 
642 _X_EXPORT void
XftCharFontSpecRender(Display * dpy,int op,Picture src,Picture dst,int srcx,int srcy,_Xconst XftCharFontSpec * chars,int len)643 XftCharFontSpecRender (Display			*dpy,
644 		       int			op,
645 		       Picture			src,
646 		       Picture			dst,
647 		       int			srcx,
648 		       int			srcy,
649 		       _Xconst XftCharFontSpec	*chars,
650 		       int			len)
651 {
652     XftGlyphFontSpec	*glyphs, glyphs_local[NUM_LOCAL];
653     int			i;
654 
655     if (len <= NUM_LOCAL)
656 	glyphs = glyphs_local;
657     else
658     {
659 	glyphs = malloc ((size_t)len * sizeof (XftGlyphFontSpec));
660 	if (!glyphs)
661 	    return;
662     }
663     for (i = 0; i < len; i++)
664     {
665 	glyphs[i].font = chars[i].font;
666 	glyphs[i].glyph = XftCharIndex(dpy, glyphs[i].font, chars[i].ucs4);
667 	glyphs[i].x = chars[i].x;
668 	glyphs[i].y = chars[i].y;
669     }
670 
671     XftGlyphFontSpecRender (dpy, op, src, dst, srcx, srcy, glyphs, len);
672     if (glyphs != glyphs_local)
673 	free (glyphs);
674 }
675 
676 _X_EXPORT void
XftTextRender8(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar8 * string,int len)677 XftTextRender8 (Display		*dpy,
678 		int		op,
679 		Picture		src,
680 		XftFont		*pub,
681 		Picture		dst,
682 		int		srcx,
683 		int		srcy,
684 		int		x,
685 		int		y,
686 		_Xconst FcChar8	*string,
687 		int		len)
688 {
689     FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
690     int		    i;
691 
692     if (len <= NUM_LOCAL)
693 	glyphs = glyphs_local;
694     else
695     {
696 	glyphs = malloc ((size_t)len * sizeof (FT_UInt));
697 	if (!glyphs)
698 	    return;
699     }
700     for (i = 0; i < len; i++)
701 	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
702     XftGlyphRender (dpy, op, src, pub, dst,
703 		     srcx, srcy, x, y, glyphs, len);
704     if (glyphs != glyphs_local)
705 	free (glyphs);
706 }
707 
708 _X_EXPORT void
XftTextRender16(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar16 * string,int len)709 XftTextRender16 (Display	    *dpy,
710 		 int		    op,
711 		 Picture	    src,
712 		 XftFont	    *pub,
713 		 Picture	    dst,
714 		 int		    srcx,
715 		 int		    srcy,
716 		 int		    x,
717 		 int		    y,
718 		 _Xconst FcChar16   *string,
719 		 int		    len)
720 {
721     FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
722     int		    i;
723 
724     if (len <= NUM_LOCAL)
725 	glyphs = glyphs_local;
726     else
727     {
728 	glyphs = malloc ((size_t)len * sizeof (FT_UInt));
729 	if (!glyphs)
730 	    return;
731     }
732     for (i = 0; i < len; i++)
733 	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
734     XftGlyphRender (dpy, op, src, pub, dst,
735 		     srcx, srcy, x, y, glyphs, len);
736     if (glyphs != glyphs_local)
737 	free (glyphs);
738 }
739 
740 _X_EXPORT void
XftTextRender16BE(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar8 * string,int len)741 XftTextRender16BE (Display	    *dpy,
742 		   int		    op,
743 		   Picture	    src,
744 		   XftFont	    *pub,
745 		   Picture	    dst,
746 		   int		    srcx,
747 		   int		    srcy,
748 		   int		    x,
749 		   int		    y,
750 		   _Xconst FcChar8  *string,
751 		   int		    len)
752 {
753     FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
754     int		    i;
755 
756     if (len <= NUM_LOCAL)
757 	glyphs = glyphs_local;
758     else
759     {
760 	glyphs = malloc ((size_t)len * sizeof (FT_UInt));
761 	if (!glyphs)
762 	    return;
763     }
764     for (i = 0; i < len; i++)
765 	glyphs[i] = XftCharIndex (dpy, pub,
766 				  (FcChar32)((string[i*2]<<8) | string[i*2+1]));
767     XftGlyphRender (dpy, op, src, pub, dst,
768 		     srcx, srcy, x, y, glyphs, len);
769     if (glyphs != glyphs_local)
770 	free (glyphs);
771 }
772 
773 _X_EXPORT void
XftTextRender16LE(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar8 * string,int len)774 XftTextRender16LE (Display	    *dpy,
775 		   int		    op,
776 		   Picture	    src,
777 		   XftFont	    *pub,
778 		   Picture	    dst,
779 		   int		    srcx,
780 		   int		    srcy,
781 		   int		    x,
782 		   int		    y,
783 		   _Xconst FcChar8  *string,
784 		   int		    len)
785 {
786     FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
787     int		    i;
788 
789     if (len <= NUM_LOCAL)
790 	glyphs = glyphs_local;
791     else
792     {
793 	glyphs = malloc ((size_t)len * sizeof (FT_UInt));
794 	if (!glyphs)
795 	    return;
796     }
797     for (i = 0; i < len; i++)
798 	glyphs[i] = XftCharIndex (dpy, pub,
799 				  (FcChar32)(string[i*2] | (string[i*2+1]<<8)));
800     XftGlyphRender (dpy, op, src, pub, dst,
801 		     srcx, srcy, x, y, glyphs, len);
802     if (glyphs != glyphs_local)
803 	free (glyphs);
804 }
805 
806 _X_EXPORT void
XftTextRender32(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar32 * string,int len)807 XftTextRender32 (Display	    *dpy,
808 		 int		    op,
809 		 Picture	    src,
810 		 XftFont	    *pub,
811 		 Picture	    dst,
812 		 int		    srcx,
813 		 int		    srcy,
814 		 int		    x,
815 		 int		    y,
816 		 _Xconst FcChar32   *string,
817 		 int		    len)
818 {
819     FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
820     int		    i;
821 
822     if (len <= NUM_LOCAL)
823 	glyphs = glyphs_local;
824     else
825     {
826 	glyphs = malloc ((size_t)len * sizeof (FT_UInt));
827 	if (!glyphs)
828 	    return;
829     }
830     for (i = 0; i < len; i++)
831 	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
832     XftGlyphRender (dpy, op, src, pub, dst,
833 		     srcx, srcy, x, y, glyphs, len);
834     if (glyphs != glyphs_local)
835 	free (glyphs);
836 }
837 
838 _X_EXPORT void
XftTextRender32BE(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar8 * string,int len)839 XftTextRender32BE (Display	    *dpy,
840 		   int		    op,
841 		   Picture	    src,
842 		   XftFont	    *pub,
843 		   Picture	    dst,
844 		   int		    srcx,
845 		   int		    srcy,
846 		   int		    x,
847 		   int		    y,
848 		   _Xconst FcChar8  *string,
849 		   int		    len)
850 {
851     FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
852     int		    i;
853 
854     if (len <= NUM_LOCAL)
855 	glyphs = glyphs_local;
856     else
857     {
858 	glyphs = malloc ((size_t)len * sizeof (FT_UInt));
859 	if (!glyphs)
860 	    return;
861     }
862     for (i = 0; i < len; i++)
863 	glyphs[i] = XftCharIndex (dpy, pub,
864 				  (FcChar32)((string[i*4] << 24) |
865 					     (string[i*4+1] << 16) |
866 					     (string[i*4+2] << 8) |
867 					     (string[i*4+3])));
868     XftGlyphRender (dpy, op, src, pub, dst,
869 		     srcx, srcy, x, y, glyphs, len);
870     if (glyphs != glyphs_local)
871 	free (glyphs);
872 }
873 
874 _X_EXPORT void
XftTextRender32LE(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar8 * string,int len)875 XftTextRender32LE (Display	    *dpy,
876 		   int		    op,
877 		   Picture	    src,
878 		   XftFont	    *pub,
879 		   Picture	    dst,
880 		   int		    srcx,
881 		   int		    srcy,
882 		   int		    x,
883 		   int		    y,
884 		   _Xconst FcChar8  *string,
885 		   int		    len)
886 {
887     FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
888     int		    i;
889 
890     if (len <= NUM_LOCAL)
891 	glyphs = glyphs_local;
892     else
893     {
894 	glyphs = malloc ((size_t)len * sizeof (FT_UInt));
895 	if (!glyphs)
896 	    return;
897     }
898     for (i = 0; i < len; i++)
899 	glyphs[i] = XftCharIndex (dpy, pub,
900 				  (FcChar32)((string[i*4]) |
901 					     (string[i*4+1] << 8) |
902 					     (string[i*4+2] << 16) |
903 					     (string[i*4+3] << 24)));
904     XftGlyphRender (dpy, op, src, pub, dst,
905 		     srcx, srcy, x, y, glyphs, len);
906     if (glyphs != glyphs_local)
907 	free (glyphs);
908 }
909 
910 _X_EXPORT void
XftTextRenderUtf8(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar8 * string,int len)911 XftTextRenderUtf8 (Display	    *dpy,
912 		   int		    op,
913 		   Picture	    src,
914 		   XftFont	    *pub,
915 		   Picture	    dst,
916 		   int		    srcx,
917 		   int		    srcy,
918 		   int		    x,
919 		   int		    y,
920 		   _Xconst FcChar8  *string,
921 		   int		    len)
922 {
923     FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
924     FcChar32	    ucs4;
925     int		    i;
926     int		    l;
927     int		    size;
928 
929     i = 0;
930     glyphs = glyphs_local;
931     size = NUM_LOCAL;
932     while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
933     {
934 	if (i == size)
935 	{
936 	    glyphs_new = malloc ((size_t)size * 2 * sizeof (FT_UInt));
937 	    if (!glyphs_new)
938 	    {
939 		if (glyphs != glyphs_local)
940 		    free (glyphs);
941 		return;
942 	    }
943 	    memcpy (glyphs_new, glyphs, (size_t)size * sizeof (FT_UInt));
944 	    size *= 2;
945 	    if (glyphs != glyphs_local)
946 		free (glyphs);
947 	    glyphs = glyphs_new;
948 	}
949 	glyphs[i++] = XftCharIndex (dpy, pub, ucs4);
950 	string += l;
951 	len -= l;
952     }
953     XftGlyphRender (dpy, op, src, pub, dst,
954 		     srcx, srcy, x, y, glyphs, i);
955     if (glyphs != glyphs_local)
956 	free (glyphs);
957 }
958 
959 _X_EXPORT void
XftTextRenderUtf16(Display * dpy,int op,Picture src,XftFont * pub,Picture dst,int srcx,int srcy,int x,int y,_Xconst FcChar8 * string,FcEndian endian,int len)960 XftTextRenderUtf16 (Display	    *dpy,
961 		    int		    op,
962 		    Picture	    src,
963 		    XftFont	    *pub,
964 		    Picture	    dst,
965 		    int		    srcx,
966 		    int		    srcy,
967 		    int		    x,
968 		    int		    y,
969 		    _Xconst FcChar8 *string,
970 		    FcEndian	    endian,
971 		    int		    len)
972 {
973     FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
974     FcChar32	    ucs4;
975     int		    i;
976     int		    l;
977     int		    size;
978 
979     i = 0;
980     glyphs = glyphs_local;
981     size = NUM_LOCAL;
982     while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
983     {
984 	if (i == size)
985 	{
986 	    glyphs_new = malloc ((size_t)size * 2 * sizeof (FT_UInt));
987 	    if (!glyphs_new)
988 	    {
989 		if (glyphs != glyphs_local)
990 		    free (glyphs);
991 		return;
992 	    }
993 	    memcpy (glyphs_new, glyphs, (size_t)size * sizeof (FT_UInt));
994 	    size *= 2;
995 	    if (glyphs != glyphs_local)
996 		free (glyphs);
997 	    glyphs = glyphs_new;
998 	}
999 	glyphs[i++] = XftCharIndex (dpy, pub, ucs4);
1000 	string += l;
1001 	len -= l;
1002     }
1003     XftGlyphRender (dpy, PictOpOver, src, pub, dst,
1004 		     srcx, srcy, x, y, glyphs, i);
1005     if (glyphs != glyphs_local)
1006 	free (glyphs);
1007 }
1008