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