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