3f8710929a0cdda610e208cda0a1656500ffa273
[framework/uifw/xorg/lib/libxft.git] / src / xftcore.c
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 _X_HIDDEN void
26 XftRectCore (XftDraw            *draw,
27              _Xconst XftColor   *color,
28              int                x, 
29              int                y,
30              unsigned int       width,
31              unsigned int       height)
32 {
33     if (color->color.alpha >= 0x8000)
34     {
35         XSetForeground (draw->dpy, draw->core.gc, color->pixel);
36         XFillRectangle (draw->dpy, draw->drawable, draw->core.gc,
37                         x, y, width, height);
38     }
39 }
40
41 /*
42  * Use the core protocol to draw the glyphs
43  */
44
45 static void
46 _XftSharpGlyphMono (XftDraw     *draw,
47                     XftGlyph    *glyph,
48                     int         x,
49                     int         y)
50 {
51     unsigned char   *srcLine = glyph->bitmap, *src;
52     unsigned char   bits, bitsMask;
53     int             width = glyph->metrics.width;
54     int             stride = ((width + 31) & ~31) >> 3;
55     int             height = glyph->metrics.height;
56     int             w;
57     int             xspan, lenspan;
58
59     x -= glyph->metrics.x;
60     y -= glyph->metrics.y;
61     while (height--)
62     {
63         src = srcLine;
64         srcLine += stride;
65         w = width;
66         
67         bitsMask = 0x80;    /* FreeType is always MSB first */
68         bits = *src++;
69         
70         xspan = x;
71         while (w)
72         {
73             if (bits & bitsMask)
74             {
75                 lenspan = 0;
76                 do
77                 {
78                     lenspan++;
79                     if (lenspan == w)
80                         break;
81                     bitsMask = bitsMask >> 1;
82                     if (!bitsMask)
83                     {
84                         bits = *src++;
85                         bitsMask = 0x80;
86                     }
87                 } while (bits & bitsMask);
88                 XFillRectangle (draw->dpy, draw->drawable, 
89                                 draw->core.gc, xspan, y, lenspan, 1);
90                 xspan += lenspan;
91                 w -= lenspan;
92             }
93             else
94             {
95                 do
96                 {
97                     w--;
98                     xspan++;
99                     if (!w)
100                         break;
101                     bitsMask = bitsMask >> 1;
102                     if (!bitsMask)
103                     {
104                         bits = *src++;
105                         bitsMask = 0x80;
106                     }
107                 } while (!(bits & bitsMask));
108             }
109         }
110         y++;
111     }
112 }
113
114 /*
115  * Draw solid color text from an anti-aliased bitmap.  This is a
116  * fallback for cases where a particular drawable has no AA code
117  */
118 static void
119 _XftSharpGlyphGray (XftDraw     *draw,
120                     XftGlyph    *glyph,
121                     int         x,
122                     int         y)
123 {
124     unsigned char   *srcLine = glyph->bitmap, *src, bits;
125     int             width = glyph->metrics.width;
126     int             stride = ((width + 3) & ~3);
127     int             height = glyph->metrics.height;
128     int             w;
129     int             xspan, lenspan;
130
131     x -= glyph->metrics.x;
132     y -= glyph->metrics.y;
133     while (height--)
134     {
135         src = srcLine;
136         srcLine += stride;
137         w = width;
138         
139         bits = *src++;
140         xspan = x;
141         while (w)
142         {
143             if (bits >= 0x80)
144             {
145                 lenspan = 0;
146                 do
147                 {
148                     lenspan++;
149                     if (lenspan == w)
150                         break;
151                     bits = *src++;
152                 } while (bits >= 0x80);
153                 XFillRectangle (draw->dpy, draw->drawable, 
154                                 draw->core.gc, xspan, y, lenspan, 1);
155                 xspan += lenspan;
156                 w -= lenspan;
157             }
158             else
159             {
160                 do
161                 {
162                     w--;
163                     xspan++;
164                     if (!w)
165                         break;
166                     bits = *src++;
167                 } while (bits < 0x80);
168             }
169         }
170         y++;
171     }
172 }
173
174 static void
175 _XftSharpGlyphRgba (XftDraw     *draw,
176                     XftGlyph    *glyph,
177                     int         x,
178                     int         y)
179 {
180     CARD32          *srcLine = glyph->bitmap, *src, bits;
181     int             width = glyph->metrics.width;
182     int             stride = ((width + 3) & ~3);
183     int             height = glyph->metrics.height;
184     int             w;
185     int             xspan, lenspan;
186
187     x -= glyph->metrics.x;
188     y -= glyph->metrics.y;
189     while (height--)
190     {
191         src = srcLine;
192         srcLine += stride;
193         w = width;
194         
195         bits = *src++;
196         xspan = x;
197         while (w)
198         {
199             if (bits >= 0x80000000)
200             {
201                 lenspan = 0;
202                 do
203                 {
204                     lenspan++;
205                     if (lenspan == w)
206                         break;
207                     bits = *src++;
208                 } while (bits >= 0x80000000);
209                 XFillRectangle (draw->dpy, draw->drawable, 
210                                 draw->core.gc, xspan, y, lenspan, 1);
211                 xspan += lenspan;
212                 w -= lenspan;
213             }
214             else
215             {
216                 do
217                 {
218                     w--;
219                     xspan++;
220                     if (!w)
221                         break;
222                     bits = *src++;
223                 } while (bits < 0x80000000);
224             }
225         }
226         y++;
227     }
228 }
229
230 typedef void (*XftSharpGlyph) (XftDraw  *draw,
231                                XftGlyph *glyph,
232                                int      x,
233                                int      y);
234
235 static XftSharpGlyph
236 _XftSharpGlyphFind (XftDraw *draw, XftFont *public)
237 {
238     XftFontInt *font = (XftFontInt *) public;
239
240     if (!font->info.antialias)
241         return _XftSharpGlyphMono;
242     else switch (font->info.rgba) {
243     case FC_RGBA_RGB:
244     case FC_RGBA_BGR:
245     case FC_RGBA_VRGB:
246     case FC_RGBA_VBGR:
247         return _XftSharpGlyphRgba;
248     default:
249         return _XftSharpGlyphGray;
250     }
251 }
252
253 /*
254  * Draw glyphs to a target that supports anti-aliasing
255  */
256
257 /*
258  * Primitives for converting between RGB values and TrueColor pixels
259  */
260  
261 static void
262 _XftExamineBitfield (unsigned long mask, int *shift, int *len)
263 {
264     int s, l;
265
266     s = 0;
267     while ((mask & 1) == 0)
268     {
269         mask >>= 1;
270         s++;
271     }
272     l = 0;
273     while ((mask & 1) == 1)
274     {
275         mask >>= 1;
276         l++;
277     }
278     *shift = s;
279     *len = l;
280 }
281
282 static CARD32
283 _XftGetField (unsigned long l_pixel, int shift, int len)
284 {
285     CARD32  pixel = (CARD32) l_pixel;
286     
287     pixel = pixel & (((1 << (len)) - 1) << shift);
288     pixel = pixel << (32 - (shift + len)) >> 24;
289     while (len < 8)
290     {
291         pixel |= (pixel >> len);
292         len <<= 1;
293     }
294     return pixel;
295 }
296
297 static unsigned long
298 _XftPutField (CARD32 pixel, int shift, int len)
299 {
300     unsigned long   l_pixel = (unsigned long) pixel;
301
302     shift = shift - (8 - len);
303     if (len <= 8)
304         l_pixel &= (((1 << len) - 1) << (8 - len));
305     if (shift < 0)
306         l_pixel >>= -shift;
307     else
308         l_pixel <<= shift;
309     return l_pixel;
310 }
311
312 /*
313  * This is used when doing XftCharFontSpec/XftGlyphFontSpec where
314  * some of the fonts are bitmaps and some are anti-aliased to handle
315  * the bitmap portions
316  */
317 static void
318 _XftSmoothGlyphMono (XImage             *image,
319                      _Xconst XftGlyph   *xftg,
320                      int                x,
321                      int                y,
322                      _Xconst XftColor   *color)
323 {
324     unsigned char   *srcLine = xftg->bitmap, *src;
325     unsigned char   bits, bitsMask;
326     int             width = xftg->metrics.width;
327     int             stride = ((width + 31) & ~31) >> 3;
328     int             height = xftg->metrics.height;
329     int             w;
330     int             xspan;
331     int             r_shift, r_len;
332     int             g_shift, g_len;
333     int             b_shift, b_len;
334     unsigned long   pixel;
335
336     _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
337     _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
338     _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
339     pixel = (_XftPutField (color->color.red >> 8, r_shift, r_len) |
340              _XftPutField (color->color.green >> 8, g_shift, g_len) |
341              _XftPutField (color->color.blue >> 8, b_shift, b_len));
342     x -= xftg->metrics.x;
343     y -= xftg->metrics.y;
344     while (height--)
345     {
346         src = srcLine;
347         srcLine += stride;
348         w = width;
349         
350         bitsMask = 0x80;    /* FreeType is always MSB first */
351         bits = *src++;
352         
353         xspan = x;
354         while (w--)
355         {
356             if (bits & bitsMask)
357                 XPutPixel (image, xspan, y, pixel);
358             bitsMask = bitsMask >> 1;
359             if (!bitsMask)
360             {
361                 bits = *src++;
362                 bitsMask = 0x80;
363             }
364             xspan++;
365         }
366         y++;
367     }
368 }
369
370 /*
371  * As simple anti-aliasing is likely to be common, there are three
372  * optimized versions for the usual true color pixel formats (888, 565, 555).
373  * Other formats are handled by the general case
374  */
375
376 #define cvt8888to0565(s)    ((((s) >> 3) & 0x001f) | \
377                              (((s) >> 5) & 0x07e0) | \
378                              (((s) >> 8) & 0xf800))
379
380 #define cvt0565to8888(s)    (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
381                              ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
382                              ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)))
383
384 #define cvt8888to0555(s)    ((((s) >> 3) & 0x001f) | \
385                              (((s) >> 6) & 0x03e0) | \
386                              (((s) >> 7) & 0x7c00))
387
388 #define cvt0555to8888(s)    (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
389                              ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \
390                              ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000)))
391
392
393 #define XftIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) )
394 #define XftIntDiv(a,b)   (((CARD16) (a) * 255) / (b))
395
396 #define XftGet8(v,i)   ((CARD16) (CARD8) ((v) >> i))
397
398 /*
399  * There are two ways of handling alpha -- either as a single unified value or
400  * a separate value for each component, hence each macro must have two
401  * versions.  The unified alpha version has a 'U' at the end of the name,
402  * the component version has a 'C'.  Similarly, functions which deal with
403  * this difference will have two versions using the same convention.
404  */
405
406 #define XftOverU(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),(a),(t)) + XftGet8(x,i),\
407                            (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
408
409 #define XftOverC(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),XftGet8(a,i),(t)) + XftGet8(x,i),\
410                             (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
411
412 #define XftInU(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),(a),(t)) << (i))
413
414 #define XftInC(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t)) << (i))
415
416 #define XftGen(x,y,i,ax,ay,t,u,v) ((t) = (XftIntMult(XftGet8(y,i),ay,(u)) + \
417                                          XftIntMult(XftGet8(x,i),ax,(v))),\
418                                   (CARD32) ((CARD8) ((t) | \
419                                                      (0 - ((t) >> 8)))) << (i))
420
421 #define XftAdd(x,y,i,t) ((t) = XftGet8(x,i) + XftGet8(y,i), \
422                          (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
423
424
425 static CARD32
426 fbOver24 (CARD32 x, CARD32 y)
427 {
428     CARD16  a = ~x >> 24;
429     CARD16  t;
430     CARD32  m,n,o;
431
432     m = XftOverU(x,y,0,a,t);
433     n = XftOverU(x,y,8,a,t);
434     o = XftOverU(x,y,16,a,t);
435     return m|n|o;
436 }
437
438 static CARD32
439 fbIn (CARD32 x, CARD8 y)
440 {
441     CARD16  a = y;
442     CARD16  t;
443     CARD32  m,n,o,p;
444
445     m = XftInU(x,0,a,t);
446     n = XftInU(x,8,a,t);
447     o = XftInU(x,16,a,t);
448     p = XftInU(x,24,a,t);
449     return m|n|o|p;
450 }
451
452 static void
453 _XftSmoothGlyphGray8888 (XImage             *image,
454                          _Xconst XftGlyph   *xftg,
455                          int                x,
456                          int                y,
457                          _Xconst XftColor   *color)
458 {
459     CARD32      src, srca;
460     CARD32      r, g, b;
461     CARD32      *dstLine, *dst, d;
462     CARD8       *maskLine, *mask, m;
463     int         dstStride, maskStride;
464     int         width, height;
465     int         w;
466
467     srca = color->color.alpha >> 8;
468     
469     /* This handles only RGB and BGR */
470     g = (color->color.green & 0xff00);
471     if (image->red_mask == 0xff0000)
472     {
473         r = (color->color.red & 0xff00) << 8;
474         b = color->color.blue >> 8;
475     }
476     else
477     {
478         r = color->color.red >> 8;
479         b = (color->color.blue & 0xff00) << 8;
480     }
481     src = (srca << 24) | r | g | b;
482     
483     width = xftg->metrics.width;
484     height = xftg->metrics.height;
485     
486     x -= xftg->metrics.x;
487     y -= xftg->metrics.y;
488
489     dstLine = (CARD32 *) (image->data + image->bytes_per_line * y + (x << 2));
490     dstStride = image->bytes_per_line >> 2;
491     maskLine = (unsigned char *) xftg->bitmap;
492     maskStride = (width + 3) & ~3;
493     
494     while (height--)
495     {
496         dst = dstLine;
497         dstLine += dstStride;
498         mask = maskLine;
499         maskLine += maskStride;
500         w = width;
501
502         while (w--)
503         {
504             m = *mask++;
505             if (m == 0xff)
506             {
507                 if (srca == 0xff)
508                     *dst = src;
509                 else
510                     *dst = fbOver24 (src, *dst);
511             }
512             else if (m)
513             {
514                 d = fbIn (src, m);
515                 *dst = fbOver24 (d, *dst);
516             }
517             dst++;
518         }
519     }
520 }
521
522 static void
523 _XftSmoothGlyphGray565 (XImage              *image,
524                         _Xconst XftGlyph    *xftg,
525                         int                 x,
526                         int                 y,
527                         _Xconst XftColor    *color)
528 {
529     CARD32      src, srca;
530     CARD32      r, g, b;
531     CARD32      d;
532     CARD16      *dstLine, *dst;
533     CARD8       *maskLine, *mask, m;
534     int         dstStride, maskStride;
535     int         width, height;
536     int         w;
537
538     srca = color->color.alpha >> 8;
539     
540     /* This handles only RGB and BGR */
541     g = (color->color.green & 0xff00);
542     if (image->red_mask == 0xf800)
543     {
544         r = (color->color.red & 0xff00) << 8;
545         b = color->color.blue >> 8;
546     }
547     else
548     {
549         r = color->color.red >> 8;
550         b = (color->color.blue & 0xff00) << 8;
551     }
552     src = (srca << 24) | r | g | b;
553     
554     width = xftg->metrics.width;
555     height = xftg->metrics.height;
556     
557     x -= xftg->metrics.x;
558     y -= xftg->metrics.y;
559
560     dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
561     dstStride = image->bytes_per_line >> 1;
562     maskLine = (unsigned char *) xftg->bitmap;
563     maskStride = (width + 3) & ~3;
564     
565     while (height--)
566     {
567         dst = dstLine;
568         dstLine += dstStride;
569         mask = maskLine;
570         maskLine += maskStride;
571         w = width;
572
573         while (w--)
574         {
575             m = *mask++;
576             if (m == 0xff)
577             {
578                 if (srca == 0xff)
579                     d = src;
580                 else
581                 {
582                     d = *dst;
583                     d = fbOver24 (src, cvt0565to8888(d));
584                 }
585                 *dst = cvt8888to0565(d);
586             }
587             else if (m)
588             {
589                 d = *dst;
590                 d = fbOver24 (fbIn(src,m), cvt0565to8888(d));
591                 *dst = cvt8888to0565(d);
592             }
593             dst++;
594         }
595     }
596 }
597
598 static void
599 _XftSmoothGlyphGray555 (XImage              *image,
600                         _Xconst XftGlyph    *xftg,
601                         int                 x,
602                         int                 y,
603                         _Xconst XftColor    *color)
604 {
605     CARD32      src, srca;
606     CARD32      r, g, b;
607     CARD32      d;
608     CARD16      *dstLine, *dst;
609     CARD8       *maskLine, *mask, m;
610     int         dstStride, maskStride;
611     int         width, height;
612     int         w;
613
614     srca = color->color.alpha >> 8;
615     
616     /* This handles only RGB and BGR */
617     g = (color->color.green & 0xff00);
618     if (image->red_mask == 0xf800)
619     {
620         r = (color->color.red & 0xff00) << 8;
621         b = color->color.blue >> 8;
622     }
623     else
624     {
625         r = color->color.red >> 8;
626         b = (color->color.blue & 0xff00) << 8;
627     }
628     src = (srca << 24) | r | g | b;
629     
630     width = xftg->metrics.width;
631     height = xftg->metrics.height;
632     
633     x -= xftg->metrics.x;
634     y -= xftg->metrics.y;
635
636     dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1));
637     dstStride = image->bytes_per_line >> 1;
638     maskLine = (unsigned char *) xftg->bitmap;
639     maskStride = (width + 3) & ~3;
640     
641     while (height--)
642     {
643         dst = dstLine;
644         dstLine += dstStride;
645         mask = maskLine;
646         maskLine += maskStride;
647         w = width;
648
649         while (w--)
650         {
651             m = *mask++;
652             if (m == 0xff)
653             {
654                 if (srca == 0xff)
655                     d = src;
656                 else
657                 {
658                     d = *dst;
659                     d = fbOver24 (src, cvt0555to8888(d));
660                 }
661                 *dst = cvt8888to0555(d);
662             }
663             else if (m)
664             {
665                 d = *dst;
666                 d = fbOver24 (fbIn(src,m), cvt0555to8888(d));
667                 *dst = cvt8888to0555(d);
668             }
669             dst++;
670         }
671     }
672 }
673
674 static void
675 _XftSmoothGlyphGray (XImage             *image,
676                      _Xconst XftGlyph   *xftg,
677                      int                x,
678                      int                y,
679                      _Xconst XftColor   *color)
680 {
681     CARD32          src, srca;
682     int             r_shift, r_len;
683     int             g_shift, g_len;
684     int             b_shift, b_len;
685     CARD8           *maskLine, *mask, m;
686     int             maskStride;
687     CARD32          d;
688     unsigned long   pixel;
689     int             width, height;
690     int             w, tx;
691     
692     srca = color->color.alpha >> 8;
693     src = (srca << 24 |
694            (color->color.red & 0xff00) << 8 |
695            (color->color.green & 0xff00) |
696            (color->color.blue) >> 8);
697     x -= xftg->metrics.x;
698     y -= xftg->metrics.y;
699     width = xftg->metrics.width;
700     height = xftg->metrics.height;
701     
702     maskLine = (unsigned char *) xftg->bitmap;
703     maskStride = (width + 3) & ~3;
704
705     _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
706     _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
707     _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
708     while (height--)
709     {
710         mask = maskLine;
711         maskLine += maskStride;
712         w = width;
713         tx = x;
714         
715         while (w--)
716         {
717             m = *mask++;
718             if (m == 0xff)
719             {
720                 if (srca == 0xff)
721                     d = src;
722                 else
723                 {
724                     pixel = XGetPixel (image, tx, y);
725                     d = (_XftGetField (pixel, r_shift, r_len) << 16 |
726                          _XftGetField (pixel, g_shift, g_len) << 8 |
727                          _XftGetField (pixel, b_shift, b_len));
728                     d = fbOver24 (src, d);
729                 }
730                 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
731                          _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
732                          _XftPutField ((d      ) & 0xff, b_shift, b_len));
733                 XPutPixel (image, tx, y, pixel);
734             }
735             else if (m)
736             {
737                 pixel = XGetPixel (image, tx, y);
738                 d = (_XftGetField (pixel, r_shift, r_len) << 16 |
739                      _XftGetField (pixel, g_shift, g_len) << 8 |
740                      _XftGetField (pixel, b_shift, b_len));
741                 d = fbOver24 (fbIn(src,m), d);
742                 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
743                          _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
744                          _XftPutField ((d      ) & 0xff, b_shift, b_len));
745                 XPutPixel (image, tx, y, pixel);
746             }
747             tx++;
748         }
749         y++;
750     }
751 }
752
753 static void
754 _XftSmoothGlyphRgba (XImage             *image,
755                      _Xconst XftGlyph   *xftg,
756                      int                x,
757                      int                y,
758                      _Xconst XftColor   *color)
759 {
760     CARD32          src, srca;
761     int             r_shift, r_len;
762     int             g_shift, g_len;
763     int             b_shift, b_len;
764     CARD32          *mask, ma;
765     CARD32          d;
766     unsigned long   pixel;
767     int             width, height;
768     int             w, tx;
769     
770     srca = color->color.alpha >> 8;
771     src = (srca << 24 |
772            (color->color.red & 0xff00) << 8 |
773            (color->color.green & 0xff00) |
774            (color->color.blue) >> 8);
775     x -= xftg->metrics.x;
776     y -= xftg->metrics.y;
777     width = xftg->metrics.width;
778     height = xftg->metrics.height;
779     
780     mask = (CARD32 *) xftg->bitmap;
781
782     _XftExamineBitfield (image->red_mask, &r_shift, &r_len);
783     _XftExamineBitfield (image->green_mask, &g_shift, &g_len);
784     _XftExamineBitfield (image->blue_mask, &b_shift, &b_len);
785     while (height--)
786     {
787         w = width;
788         tx = x;
789         
790         while (w--)
791         {
792             ma = *mask++;
793             if (ma == 0xffffffff)
794             {
795                 if (srca == 0xff)
796                     d = src;
797                 else
798                 {
799                     pixel = XGetPixel (image, tx, y);
800                     d = (_XftGetField (pixel, r_shift, r_len) << 16 |
801                          _XftGetField (pixel, g_shift, g_len) << 8 |
802                          _XftGetField (pixel, b_shift, b_len));
803                     d = fbOver24 (src, d);
804                 }
805                 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
806                          _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
807                          _XftPutField ((d      ) & 0xff, b_shift, b_len));
808                 XPutPixel (image, tx, y, pixel);
809             }
810             else if (ma)
811             {
812                 CARD32  m,n,o;
813                 pixel = XGetPixel (image, tx, y);
814                 d = (_XftGetField (pixel, r_shift, r_len) << 16 |
815                      _XftGetField (pixel, g_shift, g_len) << 8 |
816                      _XftGetField (pixel, b_shift, b_len));
817 #define XftInOverC(src,srca,msk,dst,i,result) { \
818     CARD16  __a = XftGet8(msk,i); \
819     CARD32  __t, __ta; \
820     CARD32  __i; \
821     __t = XftIntMult (XftGet8(src,i), __a,__i); \
822     __ta = (CARD8) ~XftIntMult (srca, __a,__i); \
823     __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i); \
824     __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \
825     result = __t << (i); \
826 }
827                 XftInOverC(src,srca,ma,d,0,m);
828                 XftInOverC(src,srca,ma,d,8,n);
829                 XftInOverC(src,srca,ma,d,16,o);
830                 d = m | n | o;
831                 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
832                          _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
833                          _XftPutField ((d      ) & 0xff, b_shift, b_len));
834                 XPutPixel (image, tx, y, pixel);
835             }
836             tx++;
837         }
838         y++;
839     }
840 }
841
842 static FcBool
843 _XftSmoothGlyphPossible (XftDraw *draw)
844 {
845     if (!draw->visual)
846         return FcFalse;
847     if (draw->visual->class != TrueColor)
848         return FcFalse;
849     return FcTrue;
850 }
851
852 typedef void (*XftSmoothGlyph) (XImage              *image, 
853                                 _Xconst XftGlyph    *xftg,
854                                 int                 x,
855                                 int                 y,
856                                 _Xconst XftColor    *color);
857
858 static XftSmoothGlyph
859 _XftSmoothGlyphFind (XftDraw *draw, XftFont *public)
860 {
861     XftFontInt *font = (XftFontInt *) public;
862
863     if (!font->info.antialias)
864         return _XftSmoothGlyphMono;
865     else switch (font->info.rgba) {
866     case FC_RGBA_RGB:
867     case FC_RGBA_BGR:
868     case FC_RGBA_VRGB:
869     case FC_RGBA_VBGR:
870         return _XftSmoothGlyphRgba;
871     default:
872         switch (XftDrawBitsPerPixel (draw)) {
873         case 32:
874             if ((draw->visual->red_mask   == 0xff0000 &&
875                  draw->visual->green_mask == 0x00ff00 &&
876                  draw->visual->blue_mask  == 0x0000ff) ||
877                 (draw->visual->red_mask   == 0x0000ff &&
878                  draw->visual->green_mask == 0x00ff00 &&
879                  draw->visual->blue_mask  == 0xff0000))
880             {
881                 return _XftSmoothGlyphGray8888;
882             }
883             break;
884         case 16:
885             if ((draw->visual->red_mask   == 0xf800 &&
886                  draw->visual->green_mask == 0x07e0 &&
887                  draw->visual->blue_mask  == 0x001f) ||
888                 (draw->visual->red_mask   == 0x001f &&
889                  draw->visual->green_mask == 0x07e0 &&
890                  draw->visual->blue_mask  == 0xf800))
891             {
892                 return _XftSmoothGlyphGray565;
893             }
894             if ((draw->visual->red_mask   == 0x7c00 &&
895                  draw->visual->green_mask == 0x03e0 &&
896                  draw->visual->blue_mask  == 0x001f) ||
897                 (draw->visual->red_mask   == 0x001f &&
898                  draw->visual->green_mask == 0x03e0 &&
899                  draw->visual->blue_mask  == 0x7c00))
900             {
901                 return _XftSmoothGlyphGray555;
902             }
903             break;
904         default:
905             break;
906         }
907         return _XftSmoothGlyphGray;
908     }
909 }
910
911 static XftGlyph *
912 _XftGlyphDefault (Display *dpy, XftFont   *public)
913 {
914     XftFontInt      *font = (XftFontInt *) public;
915     FT_UInt         missing[XFT_NMISSING];
916     int             nmissing;
917     FcBool          glyphs_loaded = FcFalse;
918
919     if (XftFontCheckGlyph (dpy, public, FcTrue, 0, missing, &nmissing))
920         glyphs_loaded = FcTrue;
921     if (nmissing)
922         XftFontLoadGlyphs (dpy, public, glyphs_loaded, missing, nmissing);
923     return font->glyphs[0];
924 }
925
926 static int XftGetImageErrorHandler (Display *dpy, XErrorEvent *error_event)
927 {
928     return 0;
929 }
930
931 _X_HIDDEN void
932 XftGlyphCore (XftDraw           *draw,
933               _Xconst XftColor  *color,
934               XftFont           *public,
935               int               x,
936               int               y,
937               _Xconst FT_UInt   *glyphs,
938               int               nglyphs)
939 {
940     Display         *dpy = draw->dpy;
941     XftFontInt      *font = (XftFontInt *) public;
942     XftGlyph        *xftg;
943     FT_UInt         glyph;
944     _Xconst FT_UInt *g;
945     FT_UInt         missing[XFT_NMISSING];
946     FcBool          glyphs_loaded;
947     int             nmissing;
948     int             n;
949     XErrorHandler   prev_error;
950
951     /*
952      * Load missing glyphs
953      */
954     g = glyphs;
955     n = nglyphs;
956     nmissing = 0;
957     glyphs_loaded = FcFalse;
958     while (n--)
959         if (XftFontCheckGlyph (dpy, public, FcTrue, *g++, missing, &nmissing))
960             glyphs_loaded = FcTrue;
961     if (nmissing)
962         XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
963     
964     g = glyphs;
965     n = nglyphs;
966     if ((font->info.antialias || color->color.alpha != 0xffff) &&
967         _XftSmoothGlyphPossible (draw))
968     {
969         XGlyphInfo      gi;
970         XImage          *image;
971         unsigned int    depth;
972         int             ox, oy;
973         XftSmoothGlyph  smooth = _XftSmoothGlyphFind (draw, public);
974         
975         XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi);
976         if (!gi.width || !gi.height)
977             goto bail1;
978         ox = x - gi.x;
979         oy = y - gi.y;
980         /*
981          * Try to get bits directly from the drawable; if that fails,
982          * use a temporary pixmap.  When it does fail, assume it
983          * will probably fail for a while and keep using temporary
984          * pixmaps for a while to avoid double round trips.
985          */
986         if (draw->core.use_pixmap == 0)
987         {
988             prev_error = XSetErrorHandler (XftGetImageErrorHandler);
989             image = XGetImage (dpy, draw->drawable,
990                                ox, oy,
991                                gi.width, gi.height, AllPlanes,
992                                ZPixmap);
993             XSetErrorHandler (prev_error);
994             if (!image)
995                 draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
996         }
997         else
998         {
999             draw->core.use_pixmap--;
1000             image = NULL;
1001         }
1002         if (!image && (depth = XftDrawDepth (draw)))
1003         {
1004             Pixmap      pix;
1005             GC          gc;
1006             XGCValues   gcv;
1007
1008             pix = XCreatePixmap (dpy, draw->drawable,
1009                                  gi.width, gi.height, depth);
1010             gcv.graphics_exposures = False;
1011             gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
1012             XCopyArea (dpy, draw->drawable, pix, gc, ox, oy,
1013                        gi.width, gi.height, 0, 0);
1014             XFreeGC (dpy, gc);
1015             image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes,
1016                                ZPixmap);
1017             XFreePixmap (dpy, pix);
1018         }
1019         if (!image)
1020             goto bail1;
1021         image->red_mask = draw->visual->red_mask;
1022         image->green_mask = draw->visual->green_mask;
1023         image->blue_mask = draw->visual->blue_mask;
1024         if (image->byte_order != XftNativeByteOrder ())
1025             XftSwapImage (image);
1026         while (n--)
1027         {
1028             glyph = *g++;
1029             if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1030                 xftg = _XftGlyphDefault (dpy, public);
1031             if (xftg)
1032             {
1033                 (*smooth) (image, xftg, x - ox, y - oy, color);
1034                 x += xftg->metrics.xOff;
1035                 y += xftg->metrics.yOff;
1036             }
1037         }
1038         if (image->byte_order != XftNativeByteOrder ())
1039             XftSwapImage (image);
1040         XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy,
1041                    gi.width, gi.height);
1042         XDestroyImage (image);
1043     }
1044     else
1045     {
1046         XftSharpGlyph   sharp = _XftSharpGlyphFind (draw, public);
1047         while (n--)
1048         {
1049             glyph = *g++;
1050             if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1051                 xftg = _XftGlyphDefault (dpy, public);
1052             if (xftg)
1053             {
1054                 (*sharp) (draw, xftg, x, y);
1055                 x += xftg->metrics.xOff;
1056                 y += xftg->metrics.yOff;
1057             }
1058         }
1059     }
1060 bail1:
1061     if (glyphs_loaded)
1062         _XftFontManageMemory (dpy, public);
1063 }
1064
1065 #define NUM_LOCAL   1024
1066
1067 _X_HIDDEN void
1068 XftGlyphSpecCore (XftDraw               *draw,
1069                   _Xconst XftColor      *color,
1070                   XftFont               *public,
1071                   _Xconst XftGlyphSpec  *glyphs,
1072                   int                   nglyphs)
1073 {
1074     Display         *dpy = draw->dpy;
1075     XftFontInt      *font = (XftFontInt *) public;
1076     XftGlyph        *xftg;
1077     FT_UInt         missing[XFT_NMISSING];
1078     FcBool          glyphs_loaded;
1079     int             nmissing;
1080     int             i;
1081     XErrorHandler   prev_error;
1082     int             x1, y1, x2, y2;
1083
1084     /*
1085      * Load missing glyphs
1086      */
1087     glyphs_loaded = FcFalse;
1088     x1 = y1 = x2 = y2 = 0;
1089     for (i = 0; i < nglyphs; i++)
1090     {
1091         XGlyphInfo      gi;
1092         int             g_x1, g_x2, g_y1, g_y2;
1093         
1094         nmissing = 0;
1095         if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
1096             glyphs_loaded = FcTrue;
1097         if (nmissing)
1098             XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
1099
1100         XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
1101         g_x1 = glyphs[i].x - gi.x;
1102         g_y1 = glyphs[i].y - gi.y;
1103         g_x2 = g_x1 + gi.width;
1104         g_y2 = g_y1 + gi.height;
1105         if (i)
1106         {
1107             if (g_x1 < x1)
1108                 x1 = g_x1;
1109             if (g_y1 < y1)
1110                 y1 = g_y1;
1111             if (g_x2 > x2)
1112                 x2 = g_x2;
1113             if (g_y2 > y2)
1114                 y2 = g_y2;
1115         }
1116         else
1117         {
1118             x1 = g_x1;
1119             y1 = g_y1;
1120             x2 = g_x2;
1121             y2 = g_y2;
1122         }
1123     }
1124     
1125     if (x1 == x2 || y1 == y2)
1126         goto bail1;
1127
1128     if ((font->info.antialias || color->color.alpha != 0xffff) &&
1129         _XftSmoothGlyphPossible (draw))
1130     {
1131         XImage          *image;
1132         unsigned int    depth;
1133         int             width = x2 - x1, height = y2 - y1;
1134         XftSmoothGlyph  smooth = _XftSmoothGlyphFind (draw, public);
1135
1136         /*
1137          * Try to get bits directly from the drawable; if that fails,
1138          * use a temporary pixmap.  When it does fail, assume it
1139          * will probably fail for a while and keep using temporary
1140          * pixmaps for a while to avoid double round trips.
1141          */
1142         if (draw->core.use_pixmap == 0)
1143         {
1144             prev_error = XSetErrorHandler (XftGetImageErrorHandler);
1145             image = XGetImage (dpy, draw->drawable,
1146                                x1, y1,
1147                                width, height, AllPlanes,
1148                                ZPixmap);
1149             XSetErrorHandler (prev_error);
1150             if (!image)
1151                 draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
1152         }
1153         else
1154         {
1155             draw->core.use_pixmap--;
1156             image = NULL;
1157         }
1158         if (!image && (depth = XftDrawDepth (draw)))
1159         {
1160             Pixmap      pix;
1161             GC          gc;
1162             XGCValues   gcv;
1163
1164             pix = XCreatePixmap (dpy, draw->drawable,
1165                                  width, height, depth);
1166             gcv.graphics_exposures = False;
1167             gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
1168             XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
1169                        width, height, 0, 0);
1170             XFreeGC (dpy, gc);
1171             image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
1172                                ZPixmap);
1173             XFreePixmap (dpy, pix);
1174         }
1175         if (!image)
1176             goto bail1;
1177         image->red_mask = draw->visual->red_mask;
1178         image->green_mask = draw->visual->green_mask;
1179         image->blue_mask = draw->visual->blue_mask;
1180         if (image->byte_order != XftNativeByteOrder ())
1181             XftSwapImage (image);
1182         for (i = 0; i < nglyphs; i++)
1183         {
1184             FT_UInt glyph = glyphs[i].glyph;
1185             if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1186                 xftg = _XftGlyphDefault (dpy, public);
1187             if (xftg)
1188             {
1189                 (*smooth) (image, xftg, glyphs[i].x - x1, 
1190                            glyphs[i].y - y1, color);
1191             }
1192         }
1193         if (image->byte_order != XftNativeByteOrder ())
1194             XftSwapImage (image);
1195         XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
1196                    width, height);
1197         XDestroyImage (image);
1198     }
1199     else
1200     {
1201         XftSharpGlyph   sharp = _XftSharpGlyphFind (draw, public);
1202         for (i = 0; i < nglyphs; i++)
1203         {
1204             FT_UInt glyph = glyphs[i].glyph;
1205             if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1206                 xftg = _XftGlyphDefault (dpy, public);
1207             if (xftg)
1208                 (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
1209         }
1210     }
1211 bail1:
1212     if (glyphs_loaded)
1213         _XftFontManageMemory (dpy, public);
1214 }
1215
1216 _X_HIDDEN void
1217 XftGlyphFontSpecCore (XftDraw                   *draw,
1218                       _Xconst XftColor          *color,
1219                       _Xconst XftGlyphFontSpec  *glyphs,
1220                       int                       nglyphs)
1221 {
1222     Display         *dpy = draw->dpy;
1223     XftGlyph        *xftg;
1224     FT_UInt         missing[XFT_NMISSING];
1225     FcBool          glyphs_loaded;
1226     int             nmissing;
1227     int             i;
1228     XErrorHandler   prev_error;
1229     int             x1, y1, x2, y2;
1230
1231     /*
1232      * Load missing glyphs
1233      */
1234     glyphs_loaded = FcFalse;
1235     x1 = y1 = x2 = y2 = 0;
1236     for (i = 0; i < nglyphs; i++)
1237     {
1238         XftFont         *public = glyphs[i].font;
1239         XGlyphInfo      gi;
1240         int             g_x1, g_x2, g_y1, g_y2;
1241         
1242         nmissing = 0;
1243         if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing))
1244             glyphs_loaded = FcTrue;
1245         if (nmissing)
1246             XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing);
1247         
1248         XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi);
1249         g_x1 = glyphs[i].x - gi.x;
1250         g_y1 = glyphs[i].y - gi.y;
1251         g_x2 = g_x1 + gi.width;
1252         g_y2 = g_y1 + gi.height;
1253         if (i)
1254         {
1255             if (g_x1 < x1)
1256                 x1 = g_x1;
1257             if (g_y1 < y1)
1258                 y1 = g_y1;
1259             if (g_x2 > x2)
1260                 x2 = g_x2;
1261             if (g_y2 > y2)
1262                 y2 = g_y2;
1263         }
1264         else
1265         {
1266             x1 = g_x1;
1267             y1 = g_y1;
1268             x2 = g_x2;
1269             y2 = g_y2;
1270         }
1271     }
1272     
1273     if (x1 == x2 || y1 == y2)
1274         goto bail1;
1275
1276     for (i = 0; i < nglyphs; i++)
1277         if (((XftFontInt *) glyphs[i].font)->info.antialias)
1278             break;
1279     
1280     if ((i != nglyphs || color->color.alpha != 0xffff) &&
1281         _XftSmoothGlyphPossible (draw))
1282     {
1283         XImage          *image;
1284         unsigned int    depth;
1285         int             width = x2 - x1, height = y2 - y1;
1286
1287         /*
1288          * Try to get bits directly from the drawable; if that fails,
1289          * use a temporary pixmap.  When it does fail, assume it
1290          * will probably fail for a while and keep using temporary
1291          * pixmaps for a while to avoid double round trips.
1292          */
1293         if (draw->core.use_pixmap == 0)
1294         {
1295             prev_error = XSetErrorHandler (XftGetImageErrorHandler);
1296             image = XGetImage (dpy, draw->drawable,
1297                                x1, y1,
1298                                width, height, AllPlanes,
1299                                ZPixmap);
1300             XSetErrorHandler (prev_error);
1301             if (!image)
1302                 draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
1303         }
1304         else
1305         {
1306             draw->core.use_pixmap--;
1307             image = NULL;
1308         }
1309         if (!image && (depth = XftDrawDepth (draw)))
1310         {
1311             Pixmap      pix;
1312             GC          gc;
1313             XGCValues   gcv;
1314
1315             pix = XCreatePixmap (dpy, draw->drawable,
1316                                  width, height, depth);
1317             gcv.graphics_exposures = False;
1318             gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
1319             XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
1320                        width, height, 0, 0);
1321             XFreeGC (dpy, gc);
1322             image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
1323                                ZPixmap);
1324             XFreePixmap (dpy, pix);
1325         }
1326         if (!image)
1327             goto bail1;
1328         image->red_mask = draw->visual->red_mask;
1329         image->green_mask = draw->visual->green_mask;
1330         image->blue_mask = draw->visual->blue_mask;
1331         if (image->byte_order != XftNativeByteOrder ())
1332             XftSwapImage (image);
1333         for (i = 0; i < nglyphs; i++)
1334         {
1335             XftFont         *public = glyphs[i].font;
1336             XftFontInt      *font = (XftFontInt *) public;
1337             XftSmoothGlyph  smooth = _XftSmoothGlyphFind (draw, public);
1338             FT_UInt         glyph = glyphs[i].glyph;
1339             
1340             if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1341                 xftg = _XftGlyphDefault (dpy, public);
1342             if (xftg)
1343             {
1344                 (*smooth) (image, xftg, glyphs[i].x - x1, 
1345                            glyphs[i].y - y1, color);
1346             }
1347         }
1348         if (image->byte_order != XftNativeByteOrder ())
1349             XftSwapImage (image);
1350         XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
1351                    width, height);
1352         XDestroyImage (image);
1353     }
1354     else
1355     {
1356         for (i = 0; i < nglyphs; i++)
1357         {
1358             XftFont             *public = glyphs[i].font;
1359             XftFontInt          *font = (XftFontInt *) public;
1360             XftSharpGlyph       sharp = _XftSharpGlyphFind (draw, public);
1361             FT_UInt             glyph = glyphs[i].glyph;
1362             
1363             if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph]))
1364                 xftg = _XftGlyphDefault (dpy, public);
1365             if (xftg)
1366                 (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y);
1367         }
1368     }
1369 bail1:
1370     if (glyphs_loaded)
1371         for (i = 0; i < nglyphs; i++)
1372             _XftFontManageMemory (dpy, glyphs[i].font);
1373 }