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 26XftRectCore (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 45static 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, (unsigned)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 */ 118static 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, (unsigned)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 174static 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, (unsigned)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 230typedef void (*XftSharpGlyph) (XftDraw *draw, 231 XftGlyph *glyph, 232 int x, 233 int y); 234 235static XftSharpGlyph 236_XftSharpGlyphFind (XftDraw *draw _X_UNUSED, 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 261static 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 282static CARD32 283_XftGetField (unsigned long l_pixel, int shift, int len) 284{ 285 CARD32 pixel = (CARD32) l_pixel; 286 287 pixel = pixel & (CARD32)(((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 297static 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 = l_pixel & (unsigned long)(((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 */ 317static 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) (CARD16)((((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) (CARD16)((((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,cast) \ 394 ( ((t) = (cast)((a) * (b) + 0x80)), \ 395 ( ( ( (t) >> 8 ) + (t) ) >> 8 ) ) 396 397#define XftIntDiv(a,b) (((CARD16) (a) * 255) / (b)) 398 399#define XftGet8(v,i) ((CARD16) (CARD8) ((v) >> i)) 400 401/* 402 * There are two ways of handling alpha -- either as a single unified value or 403 * a separate value for each component, hence each macro must have two 404 * versions. The unified alpha version has a 'U' at the end of the name, 405 * the component version has a 'C'. Similarly, functions which deal with 406 * this difference will have two versions using the same convention. 407 */ 408 409#define XftOverU(x,y,i,a,t) \ 410 ((t) = (CARD16) XftIntMult(XftGet8(y,i),(a),(t),CARD16) + \ 411 XftGet8(x,i),\ 412 (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) 413 414#define XftOverC(x,y,i,a,t) \ 415 ((t) = (CARD16) XftIntMult(XftGet8(y,i),XftGet8(a,i),(t),CARD16) + \ 416 XftGet8(x,i),\ 417 (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) 418 419#define XftInU(x,i,a,t) \ 420 ((CARD32) XftIntMult(XftGet8(x,i),(a),(t),CARD16) << (i)) 421 422#define XftInC(x,i,a,t) \ 423 ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t),CARD32) << (i)) 424 425#define XftGen(x,y,i,ax,ay,t,u,v) \ 426 ((t) = (XftIntMult(XftGet8(y,i),ay,(u),CARD32) + \ 427 XftIntMult(XftGet8(x,i),ax,(v),CARD32)),\ 428 (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) 429 430#define XftAdd(x,y,i,t) \ 431 ((t) = XftGet8(x,i) + XftGet8(y,i), \ 432 (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) 433 434 435static CARD32 436fbOver24 (CARD32 x, CARD32 y) 437{ 438 CARD16 a = (CARD16)(~x >> 24); 439 CARD16 t = 0; 440 CARD32 m,n,o; 441 442 m = XftOverU(x,y,0,a,t); 443 n = XftOverU(x,y,8,a,t); 444 o = XftOverU(x,y,16,a,t); 445 return m|n|o; 446} 447 448static CARD32 449fbIn (CARD32 x, CARD8 y) 450{ 451 CARD16 a = y; 452 CARD16 t; 453 CARD32 m,n,o,p; 454 455 m = XftInU(x,0,a,t); 456 n = XftInU(x,8,a,t); 457 o = XftInU(x,16,a,t); 458 p = XftInU(x,24,a,t); 459 return m|n|o|p; 460} 461 462static void 463_XftSmoothGlyphGray8888 (XImage *image, 464 _Xconst XftGlyph *xftg, 465 int x, 466 int y, 467 _Xconst XftColor *color) 468{ 469 CARD32 src, srca; 470 CARD32 r, g, b; 471 CARD32 *dstLine, *dst, d; 472 CARD8 *maskLine, *mask, m; 473 int dstStride, maskStride; 474 int width, height; 475 int w; 476 477 srca = color->color.alpha >> 8; 478 479 /* This handles only RGB and BGR */ 480 g = (color->color.green & 0xff00); 481 if (image->red_mask == 0xff0000) 482 { 483 r = (color->color.red & 0xff00) << 8; 484 b = color->color.blue >> 8; 485 } 486 else 487 { 488 r = color->color.red >> 8; 489 b = (color->color.blue & 0xff00) << 8; 490 } 491 src = (srca << 24) | r | g | b; 492 493 width = xftg->metrics.width; 494 height = xftg->metrics.height; 495 496 x -= xftg->metrics.x; 497 y -= xftg->metrics.y; 498 499 dstLine = (CARD32 *) (image->data + image->bytes_per_line * y + (x << 2)); 500 dstStride = image->bytes_per_line >> 2; 501 maskLine = (unsigned char *) xftg->bitmap; 502 maskStride = (width + 3) & ~3; 503 504 while (height--) 505 { 506 dst = dstLine; 507 dstLine += dstStride; 508 mask = maskLine; 509 maskLine += maskStride; 510 w = width; 511 512 while (w--) 513 { 514 m = *mask++; 515 if (m == 0xff) 516 { 517 if (srca == 0xff) 518 *dst = src; 519 else 520 *dst = fbOver24 (src, *dst); 521 } 522 else if (m) 523 { 524 d = fbIn (src, m); 525 *dst = fbOver24 (d, *dst); 526 } 527 dst++; 528 } 529 } 530} 531 532static void 533_XftSmoothGlyphGray565 (XImage *image, 534 _Xconst XftGlyph *xftg, 535 int x, 536 int y, 537 _Xconst XftColor *color) 538{ 539 CARD32 src, srca; 540 CARD32 r, g, b; 541 CARD32 d; 542 CARD16 *dstLine, *dst; 543 CARD8 *maskLine, *mask, m; 544 int dstStride, maskStride; 545 int width, height; 546 int w; 547 548 srca = color->color.alpha >> 8; 549 550 /* This handles only RGB and BGR */ 551 g = (color->color.green & 0xff00); 552 if (image->red_mask == 0xf800) 553 { 554 r = (color->color.red & 0xff00) << 8; 555 b = color->color.blue >> 8; 556 } 557 else 558 { 559 r = color->color.red >> 8; 560 b = (color->color.blue & 0xff00) << 8; 561 } 562 src = (srca << 24) | r | g | b; 563 564 width = xftg->metrics.width; 565 height = xftg->metrics.height; 566 567 x -= xftg->metrics.x; 568 y -= xftg->metrics.y; 569 570 dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1)); 571 dstStride = image->bytes_per_line >> 1; 572 maskLine = (unsigned char *) xftg->bitmap; 573 maskStride = (width + 3) & ~3; 574 575 while (height--) 576 { 577 dst = dstLine; 578 dstLine += dstStride; 579 mask = maskLine; 580 maskLine += maskStride; 581 w = width; 582 583 while (w--) 584 { 585 m = *mask++; 586 if (m == 0xff) 587 { 588 if (srca == 0xff) 589 d = src; 590 else 591 { 592 d = *dst; 593 d = fbOver24 (src, cvt0565to8888(d)); 594 } 595 *dst = cvt8888to0565(d); 596 } 597 else if (m) 598 { 599 d = *dst; 600 d = fbOver24 (fbIn(src,m), cvt0565to8888(d)); 601 *dst = cvt8888to0565(d); 602 } 603 dst++; 604 } 605 } 606} 607 608static void 609_XftSmoothGlyphGray555 (XImage *image, 610 _Xconst XftGlyph *xftg, 611 int x, 612 int y, 613 _Xconst XftColor *color) 614{ 615 CARD32 src, srca; 616 CARD32 r, g, b; 617 CARD32 d; 618 CARD16 *dstLine, *dst; 619 CARD8 *maskLine, *mask, m; 620 int dstStride, maskStride; 621 int width, height; 622 int w; 623 624 srca = color->color.alpha >> 8; 625 626 /* This handles only RGB and BGR */ 627 g = (color->color.green & 0xff00); 628 if (image->red_mask == 0xf800) 629 { 630 r = (color->color.red & 0xff00) << 8; 631 b = color->color.blue >> 8; 632 } 633 else 634 { 635 r = color->color.red >> 8; 636 b = (color->color.blue & 0xff00) << 8; 637 } 638 src = (srca << 24) | r | g | b; 639 640 width = xftg->metrics.width; 641 height = xftg->metrics.height; 642 643 x -= xftg->metrics.x; 644 y -= xftg->metrics.y; 645 646 dstLine = (CARD16 *) (image->data + image->bytes_per_line * y + (x << 1)); 647 dstStride = image->bytes_per_line >> 1; 648 maskLine = (unsigned char *) xftg->bitmap; 649 maskStride = (width + 3) & ~3; 650 651 while (height--) 652 { 653 dst = dstLine; 654 dstLine += dstStride; 655 mask = maskLine; 656 maskLine += maskStride; 657 w = width; 658 659 while (w--) 660 { 661 m = *mask++; 662 if (m == 0xff) 663 { 664 if (srca == 0xff) 665 d = src; 666 else 667 { 668 d = *dst; 669 d = fbOver24 (src, cvt0555to8888(d)); 670 } 671 *dst = cvt8888to0555(d); 672 } 673 else if (m) 674 { 675 d = *dst; 676 d = fbOver24 (fbIn(src,m), cvt0555to8888(d)); 677 *dst = cvt8888to0555(d); 678 } 679 dst++; 680 } 681 } 682} 683 684static void 685_XftSmoothGlyphGray (XImage *image, 686 _Xconst XftGlyph *xftg, 687 int x, 688 int y, 689 _Xconst XftColor *color) 690{ 691 CARD32 src, srca; 692 int r_shift, r_len; 693 int g_shift, g_len; 694 int b_shift, b_len; 695 CARD8 *maskLine, *mask, m; 696 int maskStride; 697 CARD32 d; 698 unsigned long pixel; 699 int width, height; 700 int w, tx; 701 702 srca = color->color.alpha >> 8; 703 src = (srca << 24 | 704 (CARD32)((color->color.red & 0xff00) << 8) | 705 (color->color.green & 0xff00) | 706 (color->color.blue) >> 8); 707 x -= xftg->metrics.x; 708 y -= xftg->metrics.y; 709 width = xftg->metrics.width; 710 height = xftg->metrics.height; 711 712 maskLine = (unsigned char *) xftg->bitmap; 713 maskStride = (width + 3) & ~3; 714 715 _XftExamineBitfield (image->red_mask, &r_shift, &r_len); 716 _XftExamineBitfield (image->green_mask, &g_shift, &g_len); 717 _XftExamineBitfield (image->blue_mask, &b_shift, &b_len); 718 while (height--) 719 { 720 mask = maskLine; 721 maskLine += maskStride; 722 w = width; 723 tx = x; 724 725 while (w--) 726 { 727 m = *mask++; 728 if (m == 0xff) 729 { 730 if (srca == 0xff) 731 d = src; 732 else 733 { 734 pixel = XGetPixel (image, tx, y); 735 d = (_XftGetField (pixel, r_shift, r_len) << 16 | 736 _XftGetField (pixel, g_shift, g_len) << 8 | 737 _XftGetField (pixel, b_shift, b_len)); 738 d = fbOver24 (src, d); 739 } 740 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | 741 _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | 742 _XftPutField ((d ) & 0xff, b_shift, b_len)); 743 XPutPixel (image, tx, y, pixel); 744 } 745 else if (m) 746 { 747 pixel = XGetPixel (image, tx, y); 748 d = (_XftGetField (pixel, r_shift, r_len) << 16 | 749 _XftGetField (pixel, g_shift, g_len) << 8 | 750 _XftGetField (pixel, b_shift, b_len)); 751 d = fbOver24 (fbIn(src,m), d); 752 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | 753 _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | 754 _XftPutField ((d ) & 0xff, b_shift, b_len)); 755 XPutPixel (image, tx, y, pixel); 756 } 757 tx++; 758 } 759 y++; 760 } 761} 762 763static void 764_XftSmoothGlyphRgba (XImage *image, 765 _Xconst XftGlyph *xftg, 766 int x, 767 int y, 768 _Xconst XftColor *color) 769{ 770 CARD32 src, srca; 771 int r_shift, r_len; 772 int g_shift, g_len; 773 int b_shift, b_len; 774 CARD32 *mask, ma; 775 CARD32 d; 776 unsigned long pixel; 777 int width, height; 778 int w, tx; 779 780 srca = color->color.alpha >> 8; 781 src = (srca << 24 | 782 (CARD32)((color->color.red & 0xff00) << 8) | 783 (color->color.green & 0xff00) | 784 (color->color.blue) >> 8); 785 x -= xftg->metrics.x; 786 y -= xftg->metrics.y; 787 width = xftg->metrics.width; 788 height = xftg->metrics.height; 789 790 mask = (CARD32 *) xftg->bitmap; 791 792 _XftExamineBitfield (image->red_mask, &r_shift, &r_len); 793 _XftExamineBitfield (image->green_mask, &g_shift, &g_len); 794 _XftExamineBitfield (image->blue_mask, &b_shift, &b_len); 795 while (height--) 796 { 797 w = width; 798 tx = x; 799 800 while (w--) 801 { 802 ma = *mask++; 803 if (ma == 0xffffffff) 804 { 805 if (srca == 0xff) 806 d = src; 807 else 808 { 809 pixel = XGetPixel (image, tx, y); 810 d = (_XftGetField (pixel, r_shift, r_len) << 16 | 811 _XftGetField (pixel, g_shift, g_len) << 8 | 812 _XftGetField (pixel, b_shift, b_len)); 813 d = fbOver24 (src, d); 814 } 815 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | 816 _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | 817 _XftPutField ((d ) & 0xff, b_shift, b_len)); 818 XPutPixel (image, tx, y, pixel); 819 } 820 else if (ma) 821 { 822 CARD32 m,n,o; 823 pixel = XGetPixel (image, tx, y); 824 d = (_XftGetField (pixel, r_shift, r_len) << 16 | 825 _XftGetField (pixel, g_shift, g_len) << 8 | 826 _XftGetField (pixel, b_shift, b_len)); 827#define XftInOverC(src,srca,msk,dst,i,result) { \ 828 CARD16 __a = XftGet8(msk,i); \ 829 CARD32 __t, __ta; \ 830 CARD32 __i; \ 831 __t = XftIntMult (XftGet8(src,i), __a,__i,CARD32); \ 832 __ta = (CARD8) ~XftIntMult (srca, __a,__i,CARD32); \ 833 __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i,CARD32); \ 834 __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \ 835 result = __t << (i); \ 836} 837 XftInOverC(src,srca,ma,d,0,m); 838 XftInOverC(src,srca,ma,d,8,n); 839 XftInOverC(src,srca,ma,d,16,o); 840 d = m | n | o; 841 pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) | 842 _XftPutField ((d >> 8) & 0xff, g_shift, g_len) | 843 _XftPutField ((d ) & 0xff, b_shift, b_len)); 844 XPutPixel (image, tx, y, pixel); 845 } 846 tx++; 847 } 848 y++; 849 } 850} 851 852static FcBool 853_XftSmoothGlyphPossible (XftDraw *draw) 854{ 855 if (!draw->visual) 856 return FcFalse; 857 if (draw->visual->class != TrueColor) 858 return FcFalse; 859 return FcTrue; 860} 861 862typedef void (*XftSmoothGlyph) (XImage *image, 863 _Xconst XftGlyph *xftg, 864 int x, 865 int y, 866 _Xconst XftColor *color); 867 868static XftSmoothGlyph 869_XftSmoothGlyphFind (XftDraw *draw, XftFont *public) 870{ 871 XftFontInt *font = (XftFontInt *) public; 872 873 if (!font->info.antialias) 874 return _XftSmoothGlyphMono; 875 else switch (font->info.rgba) { 876 case FC_RGBA_RGB: 877 case FC_RGBA_BGR: 878 case FC_RGBA_VRGB: 879 case FC_RGBA_VBGR: 880 return _XftSmoothGlyphRgba; 881 default: 882 switch (XftDrawBitsPerPixel (draw)) { 883 case 32: 884 if ((draw->visual->red_mask == 0xff0000 && 885 draw->visual->green_mask == 0x00ff00 && 886 draw->visual->blue_mask == 0x0000ff) || 887 (draw->visual->red_mask == 0x0000ff && 888 draw->visual->green_mask == 0x00ff00 && 889 draw->visual->blue_mask == 0xff0000)) 890 { 891 return _XftSmoothGlyphGray8888; 892 } 893 break; 894 case 16: 895 if ((draw->visual->red_mask == 0xf800 && 896 draw->visual->green_mask == 0x07e0 && 897 draw->visual->blue_mask == 0x001f) || 898 (draw->visual->red_mask == 0x001f && 899 draw->visual->green_mask == 0x07e0 && 900 draw->visual->blue_mask == 0xf800)) 901 { 902 return _XftSmoothGlyphGray565; 903 } 904 if ((draw->visual->red_mask == 0x7c00 && 905 draw->visual->green_mask == 0x03e0 && 906 draw->visual->blue_mask == 0x001f) || 907 (draw->visual->red_mask == 0x001f && 908 draw->visual->green_mask == 0x03e0 && 909 draw->visual->blue_mask == 0x7c00)) 910 { 911 return _XftSmoothGlyphGray555; 912 } 913 break; 914 default: 915 break; 916 } 917 return _XftSmoothGlyphGray; 918 } 919} 920 921static XftGlyph * 922_XftGlyphDefault (Display *dpy, XftFont *public) 923{ 924 XftFontInt *font = (XftFontInt *) public; 925 FT_UInt missing[XFT_NMISSING]; 926 int nmissing = 0; 927 FcBool glyphs_loaded = FcFalse; 928 929 if (XftFontCheckGlyph (dpy, public, FcTrue, 0, missing, &nmissing)) 930 glyphs_loaded = FcTrue; 931 if (nmissing) 932 XftFontLoadGlyphs (dpy, public, glyphs_loaded, missing, nmissing); 933 return font->glyphs[0]; 934} 935 936static int XftGetImageErrorHandler (Display *dpy _X_UNUSED, XErrorEvent *error_event _X_UNUSED) 937{ 938 return 0; 939} 940 941_X_HIDDEN void 942XftGlyphCore (XftDraw *draw, 943 _Xconst XftColor *color, 944 XftFont *public, 945 int x, 946 int y, 947 _Xconst FT_UInt *glyphs, 948 int nglyphs) 949{ 950 Display *dpy = draw->dpy; 951 XftFontInt *font = (XftFontInt *) public; 952 XftGlyph *xftg; 953 FT_UInt glyph; 954 _Xconst FT_UInt *g; 955 FT_UInt missing[XFT_NMISSING]; 956 FcBool glyphs_loaded; 957 int nmissing; 958 int n; 959 XErrorHandler prev_error; 960 961 /* 962 * Load missing glyphs 963 */ 964 g = glyphs; 965 n = nglyphs; 966 nmissing = 0; 967 glyphs_loaded = FcFalse; 968 while (n--) 969 if (XftFontCheckGlyph (dpy, public, FcTrue, *g++, missing, &nmissing)) 970 glyphs_loaded = FcTrue; 971 if (nmissing) 972 XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); 973 974 g = glyphs; 975 n = nglyphs; 976 if ((font->info.antialias || color->color.alpha != 0xffff) && 977 _XftSmoothGlyphPossible (draw)) 978 { 979 XGlyphInfo gi; 980 XImage *image; 981 unsigned int depth; 982 int ox, oy; 983 XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); 984 985 XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi); 986 if (!gi.width || !gi.height) 987 goto bail1; 988 ox = x - gi.x; 989 oy = y - gi.y; 990 /* 991 * Try to get bits directly from the drawable; if that fails, 992 * use a temporary pixmap. When it does fail, assume it 993 * will probably fail for a while and keep using temporary 994 * pixmaps for a while to avoid double round trips. 995 */ 996 if (draw->core.use_pixmap == 0) 997 { 998 prev_error = XSetErrorHandler (XftGetImageErrorHandler); 999 image = XGetImage (dpy, draw->drawable, 1000 ox, oy, 1001 gi.width, gi.height, AllPlanes, 1002 ZPixmap); 1003 XSetErrorHandler (prev_error); 1004 if (!image) 1005 draw->core.use_pixmap = XFT_ASSUME_PIXMAP; 1006 } 1007 else 1008 { 1009 draw->core.use_pixmap--; 1010 image = NULL; 1011 } 1012 if (!image && (depth = XftDrawDepth (draw))) 1013 { 1014 Pixmap pix; 1015 GC gc; 1016 XGCValues gcv; 1017 1018 pix = XCreatePixmap (dpy, draw->drawable, 1019 gi.width, gi.height, depth); 1020 gcv.graphics_exposures = False; 1021 gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); 1022 XCopyArea (dpy, draw->drawable, pix, gc, ox, oy, 1023 gi.width, gi.height, 0, 0); 1024 XFreeGC (dpy, gc); 1025 image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes, 1026 ZPixmap); 1027 XFreePixmap (dpy, pix); 1028 } 1029 if (!image) 1030 goto bail1; 1031 image->red_mask = draw->visual->red_mask; 1032 image->green_mask = draw->visual->green_mask; 1033 image->blue_mask = draw->visual->blue_mask; 1034 if (image->byte_order != XftNativeByteOrder ()) 1035 XftSwapImage (image); 1036 while (n--) 1037 { 1038 glyph = *g++; 1039 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) 1040 xftg = _XftGlyphDefault (dpy, public); 1041 if (xftg) 1042 { 1043 (*smooth) (image, xftg, x - ox, y - oy, color); 1044 x += xftg->metrics.xOff; 1045 y += xftg->metrics.yOff; 1046 } 1047 } 1048 if (image->byte_order != XftNativeByteOrder ()) 1049 XftSwapImage (image); 1050 XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy, 1051 gi.width, gi.height); 1052 XDestroyImage (image); 1053 } 1054 else 1055 { 1056 XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); 1057 while (n--) 1058 { 1059 glyph = *g++; 1060 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) 1061 xftg = _XftGlyphDefault (dpy, public); 1062 if (xftg) 1063 { 1064 (*sharp) (draw, xftg, x, y); 1065 x += xftg->metrics.xOff; 1066 y += xftg->metrics.yOff; 1067 } 1068 } 1069 } 1070bail1: 1071 if (glyphs_loaded) 1072 _XftFontManageMemory (dpy, public); 1073} 1074 1075#define NUM_LOCAL 1024 1076 1077_X_HIDDEN void 1078XftGlyphSpecCore (XftDraw *draw, 1079 _Xconst XftColor *color, 1080 XftFont *public, 1081 _Xconst XftGlyphSpec *glyphs, 1082 int nglyphs) 1083{ 1084 Display *dpy = draw->dpy; 1085 XftFontInt *font = (XftFontInt *) public; 1086 XftGlyph *xftg; 1087 FT_UInt missing[XFT_NMISSING]; 1088 FcBool glyphs_loaded; 1089 int nmissing; 1090 int i; 1091 XErrorHandler prev_error; 1092 int x1, y1, x2, y2; 1093 1094 /* 1095 * Load missing glyphs 1096 */ 1097 glyphs_loaded = FcFalse; 1098 x1 = y1 = x2 = y2 = 0; 1099 for (i = 0; i < nglyphs; i++) 1100 { 1101 XGlyphInfo gi; 1102 int g_x1, g_x2, g_y1, g_y2; 1103 1104 nmissing = 0; 1105 if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing)) 1106 glyphs_loaded = FcTrue; 1107 if (nmissing) 1108 XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); 1109 1110 XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi); 1111 g_x1 = glyphs[i].x - gi.x; 1112 g_y1 = glyphs[i].y - gi.y; 1113 g_x2 = g_x1 + gi.width; 1114 g_y2 = g_y1 + gi.height; 1115 if (i) 1116 { 1117 if (g_x1 < x1) 1118 x1 = g_x1; 1119 if (g_y1 < y1) 1120 y1 = g_y1; 1121 if (g_x2 > x2) 1122 x2 = g_x2; 1123 if (g_y2 > y2) 1124 y2 = g_y2; 1125 } 1126 else 1127 { 1128 x1 = g_x1; 1129 y1 = g_y1; 1130 x2 = g_x2; 1131 y2 = g_y2; 1132 } 1133 } 1134 1135 if (x1 == x2 || y1 == y2) 1136 goto bail1; 1137 1138 if ((font->info.antialias || color->color.alpha != 0xffff) && 1139 _XftSmoothGlyphPossible (draw)) 1140 { 1141 XImage *image; 1142 unsigned int depth; 1143 int width = x2 - x1, height = y2 - y1; 1144 XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); 1145 1146 /* 1147 * Try to get bits directly from the drawable; if that fails, 1148 * use a temporary pixmap. When it does fail, assume it 1149 * will probably fail for a while and keep using temporary 1150 * pixmaps for a while to avoid double round trips. 1151 */ 1152 if (draw->core.use_pixmap == 0) 1153 { 1154 prev_error = XSetErrorHandler (XftGetImageErrorHandler); 1155 image = XGetImage (dpy, draw->drawable, 1156 x1, y1, 1157 (unsigned)width, (unsigned)height, AllPlanes, 1158 ZPixmap); 1159 XSetErrorHandler (prev_error); 1160 if (!image) 1161 draw->core.use_pixmap = XFT_ASSUME_PIXMAP; 1162 } 1163 else 1164 { 1165 draw->core.use_pixmap--; 1166 image = NULL; 1167 } 1168 if (!image && (depth = XftDrawDepth (draw))) 1169 { 1170 Pixmap pix; 1171 GC gc; 1172 XGCValues gcv; 1173 1174 pix = XCreatePixmap (dpy, draw->drawable, 1175 (unsigned)width, (unsigned)height, depth); 1176 gcv.graphics_exposures = False; 1177 gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); 1178 XCopyArea (dpy, draw->drawable, pix, gc, x1, y1, 1179 (unsigned)width, (unsigned)height, 0, 0); 1180 XFreeGC (dpy, gc); 1181 image = XGetImage (dpy, pix, 0, 0, (unsigned)width, (unsigned)height, AllPlanes, 1182 ZPixmap); 1183 XFreePixmap (dpy, pix); 1184 } 1185 if (!image) 1186 goto bail1; 1187 image->red_mask = draw->visual->red_mask; 1188 image->green_mask = draw->visual->green_mask; 1189 image->blue_mask = draw->visual->blue_mask; 1190 if (image->byte_order != XftNativeByteOrder ()) 1191 XftSwapImage (image); 1192 for (i = 0; i < nglyphs; i++) 1193 { 1194 FT_UInt glyph = glyphs[i].glyph; 1195 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) 1196 xftg = _XftGlyphDefault (dpy, public); 1197 if (xftg) 1198 { 1199 (*smooth) (image, xftg, glyphs[i].x - x1, 1200 glyphs[i].y - y1, color); 1201 } 1202 } 1203 if (image->byte_order != XftNativeByteOrder ()) 1204 XftSwapImage (image); 1205 XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1, 1206 (unsigned)width, (unsigned)height); 1207 XDestroyImage (image); 1208 } 1209 else 1210 { 1211 XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); 1212 for (i = 0; i < nglyphs; i++) 1213 { 1214 FT_UInt glyph = glyphs[i].glyph; 1215 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) 1216 xftg = _XftGlyphDefault (dpy, public); 1217 if (xftg) 1218 (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y); 1219 } 1220 } 1221bail1: 1222 if (glyphs_loaded) 1223 _XftFontManageMemory (dpy, public); 1224} 1225 1226_X_HIDDEN void 1227XftGlyphFontSpecCore (XftDraw *draw, 1228 _Xconst XftColor *color, 1229 _Xconst XftGlyphFontSpec *glyphs, 1230 int nglyphs) 1231{ 1232 Display *dpy = draw->dpy; 1233 XftGlyph *xftg; 1234 FT_UInt missing[XFT_NMISSING]; 1235 FcBool glyphs_loaded; 1236 int nmissing; 1237 int i; 1238 XErrorHandler prev_error; 1239 int x1, y1, x2, y2; 1240 1241 /* 1242 * Load missing glyphs 1243 */ 1244 glyphs_loaded = FcFalse; 1245 x1 = y1 = x2 = y2 = 0; 1246 for (i = 0; i < nglyphs; i++) 1247 { 1248 XftFont *public = glyphs[i].font; 1249 XGlyphInfo gi; 1250 int g_x1, g_x2, g_y1, g_y2; 1251 1252 nmissing = 0; 1253 if (XftFontCheckGlyph (dpy, public, FcTrue, glyphs[i].glyph, missing, &nmissing)) 1254 glyphs_loaded = FcTrue; 1255 if (nmissing) 1256 XftFontLoadGlyphs (dpy, public, FcTrue, missing, nmissing); 1257 1258 XftGlyphExtents (dpy, public, &glyphs[i].glyph, 1, &gi); 1259 g_x1 = glyphs[i].x - gi.x; 1260 g_y1 = glyphs[i].y - gi.y; 1261 g_x2 = g_x1 + gi.width; 1262 g_y2 = g_y1 + gi.height; 1263 if (i) 1264 { 1265 if (g_x1 < x1) 1266 { 1267 if (g_x1 < 0) 1268 { 1269 /* do nothing if the given glyphs are out of range */ 1270 short t = (short)(glyphs[i-1].font->max_advance_width 1271 + glyphs[i-1].x); 1272 if (t < 0 && glyphs[i-1].x > 0) 1273 goto bail1; 1274 } 1275 x1 = g_x1; 1276 } 1277 if (g_y1 < y1) 1278 y1 = g_y1; 1279 if (g_x2 > x2) 1280 x2 = g_x2; 1281 if (g_y2 > y2) 1282 y2 = g_y2; 1283 } 1284 else 1285 { 1286 x1 = g_x1; 1287 y1 = g_y1; 1288 x2 = g_x2; 1289 y2 = g_y2; 1290 } 1291 } 1292 1293 if (x1 == x2 || y1 == y2) 1294 goto bail1; 1295 1296 for (i = 0; i < nglyphs; i++) 1297 if (((XftFontInt *) glyphs[i].font)->info.antialias) 1298 break; 1299 1300 if ((i != nglyphs || color->color.alpha != 0xffff) && 1301 _XftSmoothGlyphPossible (draw)) 1302 { 1303 XImage *image; 1304 unsigned int depth; 1305 int width = x2 - x1, height = y2 - y1; 1306 1307 /* 1308 * Try to get bits directly from the drawable; if that fails, 1309 * use a temporary pixmap. When it does fail, assume it 1310 * will probably fail for a while and keep using temporary 1311 * pixmaps for a while to avoid double round trips. 1312 */ 1313 if (draw->core.use_pixmap == 0) 1314 { 1315 prev_error = XSetErrorHandler (XftGetImageErrorHandler); 1316 image = XGetImage (dpy, draw->drawable, 1317 x1, y1, 1318 (unsigned)width, (unsigned)height, AllPlanes, 1319 ZPixmap); 1320 XSetErrorHandler (prev_error); 1321 if (!image) 1322 draw->core.use_pixmap = XFT_ASSUME_PIXMAP; 1323 } 1324 else 1325 { 1326 draw->core.use_pixmap--; 1327 image = NULL; 1328 } 1329 if (!image && (depth = XftDrawDepth (draw))) 1330 { 1331 Pixmap pix; 1332 GC gc; 1333 XGCValues gcv; 1334 1335 pix = XCreatePixmap (dpy, draw->drawable, 1336 (unsigned)width, (unsigned)height, depth); 1337 gcv.graphics_exposures = False; 1338 gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv); 1339 XCopyArea (dpy, draw->drawable, pix, gc, x1, y1, 1340 (unsigned)width, (unsigned)height, 0, 0); 1341 XFreeGC (dpy, gc); 1342 image = XGetImage (dpy, pix, 0, 0, (unsigned)width, (unsigned)height, AllPlanes, 1343 ZPixmap); 1344 XFreePixmap (dpy, pix); 1345 } 1346 if (!image) 1347 goto bail1; 1348 image->red_mask = draw->visual->red_mask; 1349 image->green_mask = draw->visual->green_mask; 1350 image->blue_mask = draw->visual->blue_mask; 1351 if (image->byte_order != XftNativeByteOrder ()) 1352 XftSwapImage (image); 1353 for (i = 0; i < nglyphs; i++) 1354 { 1355 XftFont *public = glyphs[i].font; 1356 XftFontInt *font = (XftFontInt *) public; 1357 XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public); 1358 FT_UInt glyph = glyphs[i].glyph; 1359 1360 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) 1361 xftg = _XftGlyphDefault (dpy, public); 1362 if (xftg) 1363 { 1364 (*smooth) (image, xftg, glyphs[i].x - x1, 1365 glyphs[i].y - y1, color); 1366 } 1367 } 1368 if (image->byte_order != XftNativeByteOrder ()) 1369 XftSwapImage (image); 1370 XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1, 1371 (unsigned)width, (unsigned)height); 1372 XDestroyImage (image); 1373 } 1374 else 1375 { 1376 for (i = 0; i < nglyphs; i++) 1377 { 1378 XftFont *public = glyphs[i].font; 1379 XftFontInt *font = (XftFontInt *) public; 1380 XftSharpGlyph sharp = _XftSharpGlyphFind (draw, public); 1381 FT_UInt glyph = glyphs[i].glyph; 1382 1383 if (glyph >= font->num_glyphs || !(xftg = font->glyphs[glyph])) 1384 xftg = _XftGlyphDefault (dpy, public); 1385 if (xftg) 1386 (*sharp) (draw, xftg, glyphs[i].x, glyphs[i].y); 1387 } 1388 } 1389bail1: 1390 if (glyphs_loaded) 1391 for (i = 0; i < nglyphs; i++) 1392 _XftFontManageMemory (dpy, glyphs[i].font); 1393} 1394