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