Changeset 1775 for libcaca/trunk/caca/driver_x11.c
- Timestamp:
- Jun 27, 2007, 7:40:14 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcaca/trunk/caca/driver_x11.c
r1462 r1775 1 1 /* 2 2 * libcaca Colour ASCII-Art library 3 * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org> 3 * Copyright (c) 2002-2007 Sam Hocevar <sam@zoy.org> 4 * 2007 Ben Wiley Sittler <bsittler@gmail.com> 4 5 * All Rights Reserved 5 6 * … … 31 32 #include <stdio.h> /* BUFSIZ */ 32 33 #include <stdlib.h> 34 #include <string.h> 33 35 34 36 #include "caca.h" … … 41 43 */ 42 44 static int x11_error_handler(Display *, XErrorEvent *); 45 static void x11_put_glyph(caca_display_t *, int, int, int, int, int, 46 uint32_t, uint32_t); 43 47 44 48 struct driver_private … … 60 64 Bool autorepeat; 61 65 #endif 66 uint32_t max_char; 62 67 }; 68 69 #define UNICODE_XLFD_SUFFIX "-iso10646-1" 70 #define LATIN_1_XLFD_SUFFIX "-iso8859-1" 63 71 64 72 static int x11_init_graphics(caca_display_t *dp) … … 100 108 for( ; ; parser++) 101 109 { 110 unsigned int font_max_char; 111 102 112 if(!*parser) 103 113 { … … 118 128 } 119 129 130 if((strlen(*parser) > sizeof(UNICODE_XLFD_SUFFIX)) 131 && !strcasecmp(*parser + strlen(*parser) 132 - strlen(UNICODE_XLFD_SUFFIX), UNICODE_XLFD_SUFFIX)) 133 dp->drv.p->max_char = 0xffff; 134 else if((strlen(*parser) > sizeof(LATIN_1_XLFD_SUFFIX)) 135 && !strcasecmp(*parser + strlen(*parser) 136 - strlen(LATIN_1_XLFD_SUFFIX), LATIN_1_XLFD_SUFFIX)) 137 dp->drv.p->max_char = 0xff; 138 else 139 dp->drv.p->max_char = 0x7f; 140 141 font_max_char = 142 (((unsigned int)dp->drv.p->font_struct->max_byte1) << 8) 143 | dp->drv.p->font_struct->max_char_or_byte2; 144 if(font_max_char && (font_max_char < dp->drv.p->max_char)) 145 dp->drv.p->max_char = font_max_char; 146 120 147 break; 121 148 } … … 123 150 /* Reset the default X11 error handler */ 124 151 XSetErrorHandler(old_error_handler); 125 126 dp->drv.p->font_width = dp->drv.p->font_struct->max_bounds.width; 152 153 dp->drv.p->font_width = 0; 154 if(dp->drv.p->font_struct->per_char 155 && !dp->drv.p->font_struct->min_byte1 156 && dp->drv.p->font_struct->min_char_or_byte2 <= 0x21 157 && dp->drv.p->font_struct->max_char_or_byte2 >= 0x7e) 158 { 159 for(i = 0x21; i < 0x7f; i++) 160 { 161 int cw = dp->drv.p->font_struct->per_char[i 162 - dp->drv.p->font_struct->min_char_or_byte2].width; 163 if(cw > dp->drv.p->font_width) 164 dp->drv.p->font_width = cw; 165 } 166 } 167 168 if(!dp->drv.p->font_width) 169 dp->drv.p->font_width = dp->drv.p->font_struct->max_bounds.width; 170 127 171 dp->drv.p->font_height = dp->drv.p->font_struct->max_bounds.ascent 128 172 + dp->drv.p->font_struct->max_bounds.descent; … … 174 218 XEvent xevent; 175 219 XNextEvent(dp->drv.p->dpy, &xevent); 176 if 220 if(xevent.type == MapNotify) 177 221 break; 178 222 } … … 259 303 dp->drv.p->colors[bg]); 260 304 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, dp->drv.p->gc, 261 x * dp->drv.p->font_width, y * dp->drv.p->font_height, 262 len * dp->drv.p->font_width, dp->drv.p->font_height); 305 x * dp->drv.p->font_width, 306 y * dp->drv.p->font_height, 307 len * dp->drv.p->font_width, 308 dp->drv.p->font_height); 263 309 } 264 310 } … … 270 316 - dp->drv.p->font_offset; 271 317 uint32_t *chars = dp->cv->chars + y * dp->cv->width; 272 273 for(x = 0; x < dp->cv->width; x++, chars++) 274 { 275 uint32_t *attrs = dp->cv->attrs + x + y * dp->cv->width; 276 277 /* Underline */ 278 if(*attrs & CUCUL_UNDERLINE) 279 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 280 dp->drv.p->gc, 281 x * dp->drv.p->font_width, 282 (y + 1) * dp->drv.p->font_height - 1, 283 dp->drv.p->font_width, 1); 284 285 /* Skip spaces */ 286 if(*chars <= 0x00000020) 287 continue; 288 289 if(*chars == CUCUL_MAGIC_FULLWIDTH) 290 continue; 291 318 uint32_t *attrs = dp->cv->attrs + y * dp->cv->width; 319 320 for(x = 0; x < dp->cv->width; x++, chars++, attrs++) 321 { 292 322 XSetForeground(dp->drv.p->dpy, dp->drv.p->gc, 293 323 dp->drv.p->colors[_cucul_attr_to_rgb12fg(*attrs)]); 294 324 295 /* Plain ASCII, no problem. */ 296 if(*chars > 0x00000020 && *chars < 0x00000080) 297 { 298 char ch = (uint8_t)*chars; 299 XDrawString(dp->drv.p->dpy, dp->drv.p->pixmap, dp->drv.p->gc, 300 x * dp->drv.p->font_width, yoff, &ch, 1); 301 continue; 302 } 303 304 /* We want to be able to print a few special Unicode characters 305 * such as the CP437 gradients and half blocks. For unknown 306 * characters, just print '?'. */ 307 switch(*chars) 308 { 309 case 0x000000b7: /* · */ 310 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 311 dp->drv.p->gc, 312 x * dp->drv.p->font_width 313 + dp->drv.p->font_width / 2, 314 y * dp->drv.p->font_height 315 + dp->drv.p->font_height / 2, 2, 2); 316 break; 317 case 0x00002500: /* ─ */ 318 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 319 dp->drv.p->gc, 320 x * dp->drv.p->font_width, 321 y * dp->drv.p->font_height 322 + dp->drv.p->font_height / 2 + 1, 323 dp->drv.p->font_width, 1); 324 break; 325 case 0x00002580: /* ▀ */ 326 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 327 dp->drv.p->gc, 328 x * dp->drv.p->font_width, 329 y * dp->drv.p->font_height, 330 dp->drv.p->font_width, 331 dp->drv.p->font_height / 2); 332 break; 333 case 0x00002584: /* ▄ */ 334 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 335 dp->drv.p->gc, 336 x * dp->drv.p->font_width, 337 (y + 1) * dp->drv.p->font_height 338 - dp->drv.p->font_height / 2, 339 dp->drv.p->font_width, 340 dp->drv.p->font_height / 2); 341 break; 342 case 0x00002588: /* █ */ 343 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 344 dp->drv.p->gc, 345 x * dp->drv.p->font_width, 346 y * dp->drv.p->font_height, 347 dp->drv.p->font_width, 348 dp->drv.p->font_height); 349 break; 350 case 0x0000258c: /* ▌ */ 351 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 352 dp->drv.p->gc, 353 x * dp->drv.p->font_width, 354 y * dp->drv.p->font_height, 355 dp->drv.p->font_width / 2, 356 dp->drv.p->font_height); 357 break; 358 case 0x00002590: /* ▐ */ 359 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 360 dp->drv.p->gc, 361 (x + 1) * dp->drv.p->font_width 362 - dp->drv.p->font_width / 2, 363 y * dp->drv.p->font_height, 364 dp->drv.p->font_width / 2, 365 dp->drv.p->font_height); 366 break; 367 case 0x000025a0: /* ■ */ 368 XFillRectangle(dp->drv.p->dpy, dp->drv.p->pixmap, 369 dp->drv.p->gc, 370 x * dp->drv.p->font_width, 371 y * dp->drv.p->font_height 372 + dp->drv.p->font_height / 4, 373 dp->drv.p->font_width, 374 dp->drv.p->font_height / 2); 375 break; 376 case 0x00002593: /* ▓ */ 377 case 0x00002592: /* ▒ */ 378 case 0x00002591: /* ░ */ 379 { 380 /* FIXME: this sucks utterly */ 381 int i, j, k = *chars - 0x00002591; 382 for(j = dp->drv.p->font_height; j--; ) 383 for(i = dp->drv.p->font_width; i--; ) 384 { 385 if(((i + 2 * (j & 1)) & 3) > k) 386 continue; 387 388 XDrawPoint(dp->drv.p->dpy, dp->drv.p->pixmap, 389 dp->drv.p->gc, 390 x * dp->drv.p->font_width + i, 391 y * dp->drv.p->font_height + j); 392 } 393 break; 394 } 395 default: 396 { 397 char ch; 398 ch = '?'; 399 XDrawString(dp->drv.p->dpy, dp->drv.p->pixmap, 400 dp->drv.p->gc, 401 x * dp->drv.p->font_width, yoff, &ch, 1); 402 break; 403 } 404 } 325 x11_put_glyph(dp, x * dp->drv.p->font_width, 326 y * dp->drv.p->font_height, yoff, 327 dp->drv.p->font_width, dp->drv.p->font_height, 328 *attrs, *chars); 405 329 } 406 330 } … … 623 547 } 624 548 549 static void x11_put_glyph(caca_display_t *dp, int x, int y, int yoff, 550 int w, int h, uint32_t attr, uint32_t ch) 551 { 552 Display *dpy = dp->drv.p->dpy; 553 Pixmap px = dp->drv.p->pixmap; 554 GC gc = dp->drv.p->gc; 555 int fw; 556 XChar2b ch16; 557 558 /* Underline */ 559 if(attr & CUCUL_UNDERLINE) 560 XFillRectangle(dpy, px, gc, x, y + h - 1, w, 1); 561 562 /* Skip spaces and magic stuff */ 563 if(ch <= 0x00000020) 564 return; 565 566 if(ch == CUCUL_MAGIC_FULLWIDTH) 567 return; 568 569 fw = w; 570 if(cucul_utf32_is_fullwidth(ch)) 571 fw *= 2; 572 573 /* We want to be able to print a few special Unicode characters 574 * such as the CP437 gradients and half blocks. For unknown 575 * characters, print what cucul_utf32_to_ascii() returns. */ 576 577 if(ch >= 0x2500 && ch <= 0x256c) 578 { 579 static uint8_t const udlr[] = 580 { 581 /* 0x2500 - 0x250f: ─ . │ . . . . . . . . . ┌ . . . */ 582 0x05, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 583 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 584 /* 0x2510 - 0x251f: ┐ . . . └ . . . ┘ . . . ├ . . . */ 585 0x14, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 586 0x44, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 587 /* 0x2520 - 0x252f: . . . . ┤ . . . . . . . ┬ . . . */ 588 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 589 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 590 /* 0x2530 - 0x253f: . . . . ┴ . . . . . . . ┼ . . . */ 591 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 592 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 593 /* 0x2540 - 0x254f: . . . . . . . . . . . . . . . . */ 594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 596 /* 0x2550 - 0x255f: ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ */ 597 0x0a, 0xa0, 0x12, 0x21, 0x22, 0x18, 0x24, 0x28, 598 0x42, 0x81, 0x82, 0x48, 0x84, 0x88, 0x52, 0xa1, 599 /* 0x2560 - 0x256c: ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ */ 600 0xa2, 0x58, 0xa4, 0xa8, 0x1a, 0x25, 0x2a, 0x4a, 601 0x85, 0x8a, 0x5a, 0xa5, 0xaa, 602 }; 603 604 uint16_t D = udlr[ch - 0x2500]; 605 606 if(!D) 607 goto next_try; 608 609 if(D & 0x04) 610 XFillRectangle(dpy, px, gc, x, y + h / 2, fw / 2 + 1, 1); 611 612 if(D & 0x01) 613 XFillRectangle(dpy, px, gc, 614 x + fw / 2, y + h / 2, (fw + 1) / 2, 1); 615 616 if(D & 0x40) 617 XFillRectangle(dpy, px, gc, x + fw / 2, y, 1, h / 2 + 1); 618 619 if(D & 0x10) 620 XFillRectangle(dpy, px, gc, x + fw / 2, y + h / 2, 1, (h + 1) / 2); 621 622 #define STEPIF(a,b) (D&(a)?-1:(D&(b))?1:0) 623 624 if(D & 0x08) 625 { 626 XFillRectangle(dpy, px, gc, x, y - 1 + h / 2, 627 fw / 2 + 1 + STEPIF(0xc0,0x20), 1); 628 XFillRectangle(dpy, px, gc, x, y + 1 + h / 2, 629 fw / 2 + 1 + STEPIF(0x30,0x80), 1); 630 } 631 632 if(D & 0x02) 633 { 634 XFillRectangle(dpy, px, gc, x - STEPIF(0xc0,0x20) + fw / 2, 635 y - 1 + h / 2, (fw + 1) / 2 + STEPIF(0xc0,0x20), 1); 636 XFillRectangle(dpy, px, gc, x - STEPIF(0x30,0x80) + fw / 2, 637 y + 1 + h / 2, (fw + 1) / 2 + STEPIF(0x30,0x80), 1); 638 } 639 640 if(D & 0x80) 641 { 642 XFillRectangle(dpy, px, gc, x - 1 + fw / 2, y, 643 1, h / 2 + 1 + STEPIF(0x0c,0x02)); 644 XFillRectangle(dpy, px, gc, x + 1 + fw / 2, y, 645 1, h / 2 + 1 + STEPIF(0x03,0x08)); 646 } 647 648 if(D & 0x20) 649 { 650 XFillRectangle(dpy, px, gc, x - 1 + fw / 2, 651 y - STEPIF(0x0c,0x02) + h / 2, 652 1, (h + 1) / 2 + STEPIF(0x0c,0x02)); 653 XFillRectangle(dpy, px, gc, x + 1 + fw / 2, 654 y - STEPIF(0x03,0x08) + h / 2, 655 1, (h + 1) / 2 + STEPIF(0x03,0x08)); 656 } 657 658 return; 659 } 660 next_try: 661 662 switch(ch) 663 { 664 case 0x000000b7: /* · */ 665 case 0x00002219: /* ∙ */ 666 case 0x000030fb: /* ・ */ 667 XFillRectangle(dpy, px, gc, x + fw / 2 - 1, y + h / 2 - 1, 2, 2); 668 return; 669 670 case 0x00002261: /* ≡ */ 671 XFillRectangle(dpy, px, gc, x + 1, y - 2 + h / 2, fw - 1, 1); 672 XFillRectangle(dpy, px, gc, x + 1, y + h / 2, fw - 1, 1); 673 XFillRectangle(dpy, px, gc, x + 1, y + 2 + h / 2, fw - 1, 1); 674 return; 675 676 case 0x00002580: /* ▀ */ 677 XFillRectangle(dpy, px, gc, x, y, fw, h / 2); 678 return; 679 680 case 0x00002584: /* ▄ */ 681 XFillRectangle(dpy, px, gc, x, y + h - h / 2, fw, h / 2); 682 return; 683 684 case 0x00002588: /* █ */ 685 case 0x000025ae: /* ▮ */ 686 XFillRectangle(dpy, px, gc, x, y, fw, h); 687 return; 688 689 case 0x0000258c: /* ▌ */ 690 XFillRectangle(dpy, px, gc, x, y, fw / 2, h); 691 return; 692 693 case 0x00002590: /* ▐ */ 694 XFillRectangle(dpy, px, gc, x + fw - fw / 2, y, fw / 2, h); 695 return; 696 697 case 0x000025a0: /* ■ */ 698 case 0x000025ac: /* ▬ */ 699 XFillRectangle(dpy, px, gc, x, y + h / 4, fw, h / 2); 700 return; 701 702 case 0x00002593: /* ▓ */ 703 case 0x00002592: /* ▒ */ 704 case 0x00002591: /* ░ */ 705 { 706 /* FIXME: this sucks utterly */ 707 int i, j, k = ch - 0x00002591; 708 for(j = h; j--; ) 709 for(i = fw; i--; ) 710 { 711 if(((i + 2 * (j & 1)) & 3) > k) 712 continue; 713 714 XDrawPoint(dpy, px, gc, x + i, y + j); 715 } 716 return; 717 } 718 719 case 0x000025cb: /* ○ */ 720 case 0x00002022: /* • */ 721 case 0x000025cf: /* ● */ 722 { 723 int d, xo, yo; 724 725 d = fw; 726 if(h < fw) 727 d = h; 728 if(d < 1) 729 d = 1; 730 xo = (fw - d) / 2; 731 yo = (h - d) / 2; 732 if(ch == 0x000025cb) 733 XDrawArc(dpy, px, gc, x + xo, y + yo, d, d, 0, 64 * 360); 734 else 735 XFillArc(dpy, px, gc, x + xo, y + yo, d, d, 0, 64 * 360); 736 return; 737 } 738 } 739 740 if(ch >= 0x00000020 && ch <= dp->drv.p->max_char) 741 { 742 /* ascii, latin-1 or unicode font (might draw a blank square) */ 743 ch16.byte1 = (ch) >> 8; 744 ch16.byte2 = (ch) & 0xff; 745 } 746 else 747 { 748 ch16.byte1 = 0; 749 ch16.byte2 = cucul_utf32_to_ascii(ch); 750 } 751 752 XDrawString16(dpy, px, gc, x + (ch16.byte1 ? 0 : (fw - w) / 2), yoff, &ch16, 1); 753 } 754 625 755 /* 626 756 * Driver initialisation
Note: See TracChangeset
for help on using the changeset viewer.