Glyph.c revision 6fae4e5d
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 = 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
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 = 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
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 = info->codes->major_opcode;
78    req->renderReqType = X_RenderFreeGlyphSet;
79    req->glyphset = 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 = 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
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 = 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
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 = 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}
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 = 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
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 = 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
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    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
497void
498XRenderCompositeText16 (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
608void
609XRenderCompositeText32 (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) / 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