Changeset 711 for libcaca/trunk
- Timestamp:
- Apr 1, 2006, 5:02:05 PM (15 years ago)
- Location:
- libcaca/trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
libcaca/trunk/caca/caca.h
r710 r711 31 31 * ncurses (through Cygwin emulation) or conio. There is also a native X11 32 32 * driver, and an OpenGL driver (through freeglut) that does not require a 33 * text terminal. For machines without a screen, and with a valid tcp stack,34 * t he network driver (BSD sockets) should perfectly fit your needs.33 * text terminal. For machines without a screen, the raw driver can be used 34 * to send the output to another machine, using for instance cacaserver. 35 35 * 36 36 * \e libcaca is free software, released under the Do What The Fuck You … … 52 52 * 53 53 * Some environment variables can be used to change the behaviour of 54 * \e libcaca or \e libcucul without having to modify the program which55 * uses them. Thesevariables are:54 * \e libcaca without having to modify the program which uses them. These 55 * variables are: 56 56 * 57 57 * \li \b CACA_DRIVER: set the backend video driver. In order of preference: … … 61 61 * - \c x11 uses the native X11 driver. 62 62 * - \c gl uses freeglut and opengl libraries. 63 * - \c network uses BSD sockets calls. 64 * 65 * \li \b CUCUL_BACKGROUND: set the background type. 66 * - \c solid uses solid coloured backgrounds for all characters. This 67 * feature does not work with all terminal emulators. This is the 68 * default choice. 69 * - \c black uses only black backgrounds to render characters. 70 * 71 * \li \b CUCUL_ANTIALIASING: set the antialiasing mode. Antialiasing 72 * smoothens the rendered image and avoids the commonly seen staircase 73 * effect. 74 * - \c none disables antialiasing. 75 * - \c prefilter uses a simple prefilter antialiasing method. This is 76 * the default choice. 77 * 78 * \li \b CUCUL_DITHERING: set the dithering mode. Dithering is necessary 79 * when rendering a picture that has more colours than the usually 80 * available palette. 81 * - \c none disables dithering. 82 * - \c ordered2 uses a 2x2 Bayer matrix for dithering. 83 * - \c ordered4 uses a 4x4 Bayer matrix for dithering. This is the 84 * default choice. 85 * - \c ordered8 uses a 8x8 Bayer matrix for dithering. 86 * - \c random uses random dithering. 63 * - \c raw outputs to the standard output instead of rendering the 64 * canvas. This is can be used together with cacaserver. 87 65 * 88 66 * \li \b CACA_GEOMETRY: set the video display size. The format of this -
libcaca/trunk/cucul/bitmap.c
r691 r711 86 86 }; 87 87 88 /* List of glyphs */ 89 static char const * ascii_glyphs[] = 90 { 91 " ", ".", ":", ";", "t", "%", "S", "X", "@", "8", "?" 92 }; 93 94 static char const * shades_glyphs[] = 95 { 96 " ", ":", "░", "▒", "?" 97 }; 98 99 static char const * blocks_glyphs[] = 100 { 101 " ", "▘", "▚", "?" 102 }; 103 88 104 #if !defined(_DOXYGEN_SKIP_ME) 105 enum color_mode 106 { 107 COLOR_MODE_MONO, 108 COLOR_MODE_GRAY, 109 COLOR_MODE_8, 110 COLOR_MODE_16, 111 COLOR_MODE_FULLGRAY, 112 COLOR_MODE_FULL8, 113 COLOR_MODE_FULL16, 114 }; 115 116 struct cucul_bitmap 117 { 118 int bpp, has_palette, has_alpha; 119 int w, h, pitch; 120 int rmask, gmask, bmask, amask; 121 int rright, gright, bright, aright; 122 int rleft, gleft, bleft, aleft; 123 void (*get_hsv)(struct cucul_bitmap *, char *, int, int); 124 int red[256], green[256], blue[256], alpha[256]; 125 float gamma; 126 int gammatab[4097]; 127 128 /* Bitmap features */ 129 int invert, antialias; 130 131 /* Colour mode used for rendering */ 132 enum color_mode color_mode; 133 134 /* Glyphs used for rendering */ 135 char const * const * glyphs; 136 unsigned glyph_count; 137 138 /* Current dithering method */ 139 void (*init_dither) (int); 140 unsigned int (*get_dither) (void); 141 void (*increment_dither) (void); 142 }; 143 89 144 #define HSV_XRATIO 6 90 145 #define HSV_YRATIO 3 … … 112 167 113 168 static void get_rgba_default(struct cucul_bitmap const *, uint8_t *, int, int, 114 unsigned int *, unsigned int *, unsigned int *,115 169 unsigned int *); 116 static inline void rgb2hsv_default(int, int, int, int *, int *, int *);117 static inline int sq(int);118 170 119 171 /* Dithering methods */ … … 122 174 static void increment_no_dither(void); 123 175 176 static void init_fstein_dither(int); 177 static unsigned int get_fstein_dither(void); 178 static void increment_fstein_dither(void); 179 124 180 static void init_ordered2_dither(int); 125 181 static unsigned int get_ordered2_dither(void); … … 138 194 static void increment_random_dither(void); 139 195 140 #if !defined(_DOXYGEN_SKIP_ME) 141 struct cucul_bitmap 142 { 143 int bpp, has_palette, has_alpha; 144 int w, h, pitch; 145 int rmask, gmask, bmask, amask; 146 int rright, gright, bright, aright; 147 int rleft, gleft, bleft, aleft; 148 void (*get_hsv)(struct cucul_bitmap *, char *, int, int); 149 int red[256], green[256], blue[256], alpha[256]; 150 float gamma; 151 int gammatab[4097]; 152 unsigned char invert; 153 }; 154 #endif 155 196 static inline int sq(int x) 197 { 198 return x * x; 199 } 200 201 static inline void rgb2hsv_default(int r, int g, int b, 202 int *hue, int *sat, int *val) 203 { 204 int min, max, delta; 205 206 min = r; max = r; 207 if(min > g) min = g; if(max < g) max = g; 208 if(min > b) min = b; if(max < b) max = b; 209 210 delta = max - min; /* 0 - 0xfff */ 211 *val = max; /* 0 - 0xfff */ 212 213 if(delta) 214 { 215 *sat = 0xfff * delta / max; /* 0 - 0xfff */ 216 217 /* Generate *hue between 0 and 0x5fff */ 218 if( r == max ) 219 *hue = 0x1000 + 0x1000 * (g - b) / delta; 220 else if( g == max ) 221 *hue = 0x3000 + 0x1000 * (b - r) / delta; 222 else 223 *hue = 0x5000 + 0x1000 * (r - g) / delta; 224 } 225 else 226 { 227 *sat = 0; 228 *hue = 0; 229 } 230 } 231 232 /** 233 * \brief Create an internal bitmap object. 234 * 235 * Create a bitmap structure from its coordinates (depth, width, height and 236 * pitch) and pixel mask values. If the depth is 8 bits per pixel, the mask 237 * values are ignored and the colour palette should be set using the 238 * cucul_set_bitmap_palette() function. For depths greater than 8 bits per 239 * pixel, a zero alpha mask causes the alpha values to be ignored. 240 * 241 * \param bpp Bitmap depth in bits per pixel. 242 * \param w Bitmap width in pixels. 243 * \param h Bitmap height in pixels. 244 * \param pitch Bitmap pitch in bytes. 245 * \param rmask Bitmask for red values. 246 * \param gmask Bitmask for green values. 247 * \param bmask Bitmask for blue values. 248 * \param amask Bitmask for alpha values. 249 * \return Bitmap object, or NULL upon error. 250 */ 251 struct cucul_bitmap *cucul_create_bitmap(unsigned int bpp, unsigned int w, 252 unsigned int h, unsigned int pitch, 253 unsigned int rmask, unsigned int gmask, 254 unsigned int bmask, unsigned int amask) 255 { 256 struct cucul_bitmap *bitmap; 257 int i; 258 259 /* Minor sanity test */ 260 if(!w || !h || !pitch || bpp > 32 || bpp < 8) 261 return NULL; 262 263 bitmap = malloc(sizeof(struct cucul_bitmap)); 264 if(!bitmap) 265 return NULL; 266 267 bitmap->bpp = bpp; 268 bitmap->has_palette = 0; 269 bitmap->has_alpha = amask ? 1 : 0; 270 271 bitmap->w = w; 272 bitmap->h = h; 273 bitmap->pitch = pitch; 274 275 bitmap->rmask = rmask; 276 bitmap->gmask = gmask; 277 bitmap->bmask = bmask; 278 bitmap->amask = amask; 279 280 /* Load bitmasks */ 281 if(rmask || gmask || bmask || amask) 282 { 283 mask2shift(rmask, &bitmap->rright, &bitmap->rleft); 284 mask2shift(gmask, &bitmap->gright, &bitmap->gleft); 285 mask2shift(bmask, &bitmap->bright, &bitmap->bleft); 286 mask2shift(amask, &bitmap->aright, &bitmap->aleft); 287 } 288 289 /* In 8 bpp mode, default to a grayscale palette */ 290 if(bpp == 8) 291 { 292 bitmap->has_palette = 1; 293 bitmap->has_alpha = 0; 294 for(i = 0; i < 256; i++) 295 { 296 bitmap->red[i] = i * 0xfff / 256; 297 bitmap->green[i] = i * 0xfff / 256; 298 bitmap->blue[i] = i * 0xfff / 256; 299 } 300 } 301 302 /* Default features */ 303 bitmap->invert = 0; 304 bitmap->antialias = 1; 305 306 /* Default gamma value */ 307 for(i = 0; i < 4096; i++) 308 bitmap->gammatab[i] = i; 309 310 /* Default colour mode */ 311 bitmap->color_mode = COLOR_MODE_FULL16; 312 313 /* Default character set */ 314 bitmap->glyphs = ascii_glyphs; 315 bitmap->glyph_count = sizeof(ascii_glyphs) / sizeof(*ascii_glyphs); 316 317 return bitmap; 318 } 319 320 /** 321 * \brief Set the palette of an 8bpp bitmap object. 322 * 323 * Set the palette of an 8 bits per pixel bitmap. Values should be between 324 * 0 and 4095 (0xfff). 325 * 326 * \param bitmap Bitmap object. 327 * \param red Array of 256 red values. 328 * \param green Array of 256 green values. 329 * \param blue Array of 256 blue values. 330 * \param alpha Array of 256 alpha values. 331 */ 332 void cucul_set_bitmap_palette(struct cucul_bitmap *bitmap, 333 unsigned int red[], unsigned int green[], 334 unsigned int blue[], unsigned int alpha[]) 335 { 336 int i, has_alpha = 0; 337 338 if(bitmap->bpp != 8) 339 return; 340 341 for(i = 0; i < 256; i++) 342 { 343 if(red[i] >= 0 && red[i] < 0x1000 && 344 green[i] >= 0 && green[i] < 0x1000 && 345 blue[i] >= 0 && blue[i] < 0x1000 && 346 alpha[i] >= 0 && alpha[i] < 0x1000) 347 { 348 bitmap->red[i] = red[i]; 349 bitmap->green[i] = green[i]; 350 bitmap->blue[i] = blue[i]; 351 if(alpha[i]) 352 { 353 bitmap->alpha[i] = alpha[i]; 354 has_alpha = 1; 355 } 356 } 357 } 358 359 bitmap->has_alpha = has_alpha; 360 } 361 362 /** 363 * \brief Set the brightness of a bitmap object. 364 * 365 * Set the brightness of bitmap. 366 * 367 * \param bitmap Bitmap object. 368 * \param brightness brightness value. 369 */ 370 void cucul_set_bitmap_brightness(struct cucul_bitmap *bitmap, float brightness) 371 { 372 /* FIXME */ 373 } 374 375 /** 376 * \brief Set the gamma of a bitmap object. 377 * 378 * Set the gamma of bitmap. 379 * 380 * \param bitmap Bitmap object. 381 * \param gamma Gamma value. 382 */ 383 void cucul_set_bitmap_gamma(struct cucul_bitmap *bitmap, float gamma) 384 { 385 /* FIXME: we don't need 4096 calls to gammapow(), we can just compute 386 * 128 of them and do linear interpolation for the rest. This will 387 * probably speed up things a lot. */ 388 int i; 389 390 if(gamma <= 0.0) 391 return; 392 393 bitmap->gamma = gamma; 394 395 for(i = 0; i < 4096; i++) 396 bitmap->gammatab[i] = 4096.0 * gammapow((float)i / 4096.0, 1.0 / gamma); 397 } 398 399 /** 400 * \brief Set the contrast of a bitmap object. 401 * 402 * Set the contrast of bitmap. 403 * 404 * \param bitmap Bitmap object. 405 * \param contrast contrast value. 406 */ 407 void cucul_set_bitmap_contrast(struct cucul_bitmap *bitmap, float contrast) 408 { 409 /* FIXME */ 410 } 411 412 /** 413 * \brief Set bitmap antialiasing 414 * 415 * Tell the renderer whether to antialias the bitmap. Antialiasing smoothen 416 * the rendered image and avoids the commonly seen staircase effect. The 417 * method used is a simple prefilter antialiasing. 418 * 419 * \param bitmap Bitmap object. 420 * \param value 0 to disable antialiasing, 1 to activate it. 421 */ 422 void cucul_set_bitmap_antialias(struct cucul_bitmap *bitmap, int value) 423 { 424 bitmap->antialias = value ? 1 : 0; 425 } 426 427 /** 428 * \brief Invert colors of bitmap 429 * 430 * Invert colors of bitmap 431 * 432 * \param bitmap Bitmap object. 433 * \param value 0 for normal behaviour, 1 for invert 434 */ 435 void cucul_set_bitmap_invert(struct cucul_bitmap *bitmap, int value) 436 { 437 bitmap->invert = value ? 1 : 0; 438 } 439 440 /** 441 * \brief Choose colours used for bitmap rendering 442 * 443 * Tell the renderer which colours should be used to render the 444 * bitmap. Valid values for \e str are: 445 * 446 * \li \e "mono": use light gray on a black background. 447 * 448 * \li \e "gray": use white and two shades of gray on a black background. 449 * 450 * \li \e "8": use the 8 ANSI colours on a black background. 451 * 452 * \li \e "16": use the 16 ANSI colours on a black background. 453 * 454 * \li \e "fullgray": use black, white and two shades of gray for both the 455 * characters and the background. 456 * 457 * \li \e "full8": use the 8 ANSI colours for both the characters and the 458 * background. 459 * 460 * \li \e "full16": use the 16 ANSI colours for both the characters and the 461 * background. This is the default value. 462 * 463 * \param bitmap Bitmap object. 464 * \param str A string describing the colour set that will be used 465 * for the bitmap rendering. 466 */ 467 void cucul_set_bitmap_color(struct cucul_bitmap *bitmap, char const *str) 468 { 469 if(!strcasecmp(str, "mono")) 470 bitmap->color_mode = COLOR_MODE_MONO; 471 else if(!strcasecmp(str, "gray")) 472 bitmap->color_mode = COLOR_MODE_GRAY; 473 else if(!strcasecmp(str, "8")) 474 bitmap->color_mode = COLOR_MODE_8; 475 else if(!strcasecmp(str, "16")) 476 bitmap->color_mode = COLOR_MODE_16; 477 else if(!strcasecmp(str, "fullgray")) 478 bitmap->color_mode = COLOR_MODE_FULLGRAY; 479 else if(!strcasecmp(str, "full8")) 480 bitmap->color_mode = COLOR_MODE_FULL8; 481 else /* "full16" is the default */ 482 bitmap->color_mode = COLOR_MODE_FULL16; 483 } 484 485 /** 486 * \brief Get available colour modes 487 * 488 * Return a list of available colour modes for a given bitmap. The list 489 * is a NULL-terminated array of strings, interleaving a string containing 490 * the internal value for the colour mode, to be used with 491 * \e cucul_set_bitmap_color(), and a string containing the natural 492 * language description for that colour mode. 493 * 494 * \param bitmap Bitmap object. 495 * \return An array of strings. 496 */ 497 char const * const * 498 cucul_get_bitmap_color_list(struct cucul_bitmap const *bitmap) 499 { 500 static char const * const list[] = 501 { 502 "mono", "white on black", 503 "gray", "grayscale on black", 504 "8", "8 colours on black", 505 "16", "16 colours on black", 506 "fullgray", "full grayscale", 507 "full8", "full 8 colours", 508 "full16", "full 16 colours", 509 NULL, NULL 510 }; 511 512 return list; 513 } 514 515 /** 516 * \brief Choose characters used for bitmap rendering 517 * 518 * Tell the renderer which characters should be used to render the 519 * bitmap. Valid values for \e str are: 520 * 521 * \li \e "ascii": use only ASCII characters. This is the default value. 522 * 523 * \li \e "shades": use Unicode characters "U+2591 LIGHT SHADE", "U+2592 524 * MEDIUM SHADE" and "U+2593 DARK SHADE". These characters are also 525 * present in the CP437 codepage available on DOS and VGA. 526 * 527 * \li \e "blocks": use Unicode quarter-cell block combinations. These 528 * characters are only found in the Unicode set. 529 * 530 * \param bitmap Bitmap object. 531 * \param str A string describing the characters that need to be used 532 * for the bitmap rendering. 533 */ 534 void cucul_set_bitmap_charset(struct cucul_bitmap *bitmap, char const *str) 535 { 536 if(!strcasecmp(str, "shades")) 537 { 538 bitmap->glyphs = shades_glyphs; 539 bitmap->glyph_count = sizeof(shades_glyphs) / sizeof(*shades_glyphs); 540 } 541 else if(!strcasecmp(str, "blocks")) 542 { 543 bitmap->glyphs = blocks_glyphs; 544 bitmap->glyph_count = sizeof(blocks_glyphs) / sizeof(*blocks_glyphs); 545 } 546 else /* "ascii" is the default */ 547 { 548 bitmap->glyphs = ascii_glyphs; 549 bitmap->glyph_count = sizeof(ascii_glyphs) / sizeof(*ascii_glyphs); 550 } 551 } 552 553 /** 554 * \brief Get available bitmap character sets 555 * 556 * Return a list of available character sets for a given bitmap. The list 557 * is a NULL-terminated array of strings, interleaving a string containing 558 * the internal value for the character set, to be used with 559 * \e cucul_set_bitmap_charset(), and a string containing the natural 560 * language description for that character set. 561 * 562 * \param bitmap Bitmap object. 563 * \return An array of strings. 564 */ 565 char const * const * 566 cucul_get_bitmap_charset_list(struct cucul_bitmap const *bitmap) 567 { 568 static char const * const list[] = 569 { 570 "ascii", "plain ASCII", 571 "shades", "CP437 shades", 572 "blocks", "Unicode blocks", 573 NULL, NULL 574 }; 575 576 return list; 577 } 578 579 /** 580 * \brief Set bitmap dithering method 581 * 582 * Tell the renderer which dithering method should be used to render the 583 * bitmap. Dithering is necessary because the picture being rendered has 584 * usually far more colours than the available palette. Valid values for 585 * \e str are: 586 * 587 * \li \e "none": no dithering is used, the nearest matching colour is used. 588 * 589 * \li \e "ordered2": use a 2x2 Bayer matrix for dithering. 590 * 591 * \li \e "ordered4": use a 4x4 Bayer matrix for dithering. 592 * 593 * \li \e "ordered8": use a 8x8 Bayer matrix for dithering. 594 * 595 * \li \e "random": use random dithering. 596 * 597 * \li \e "fstein": use Floyd-Steinberg dithering. This is the default value. 598 * 599 * \param bitmap Bitmap object. 600 * \param str A string describing the dithering method that needs to be used 601 * for the bitmap rendering. 602 */ 603 void cucul_set_bitmap_dithering(struct cucul_bitmap *bitmap, char const *str) 604 { 605 if(!strcasecmp(str, "none")) 606 { 607 bitmap->init_dither = init_no_dither; 608 bitmap->get_dither = get_no_dither; 609 bitmap->increment_dither = increment_no_dither; 610 } 611 else if(!strcasecmp(str, "ordered2")) 612 { 613 bitmap->init_dither = init_ordered2_dither; 614 bitmap->get_dither = get_ordered2_dither; 615 bitmap->increment_dither = increment_ordered2_dither; 616 } 617 else if(!strcasecmp(str, "ordered4")) 618 { 619 bitmap->init_dither = init_ordered4_dither; 620 bitmap->get_dither = get_ordered4_dither; 621 bitmap->increment_dither = increment_ordered4_dither; 622 } 623 else if(!strcasecmp(str, "ordered4")) 624 { 625 bitmap->init_dither = init_ordered8_dither; 626 bitmap->get_dither = get_ordered8_dither; 627 bitmap->increment_dither = increment_ordered8_dither; 628 } 629 else if(!strcasecmp(str, "random")) 630 { 631 bitmap->init_dither = init_random_dither; 632 bitmap->get_dither = get_random_dither; 633 bitmap->increment_dither = increment_random_dither; 634 } 635 else /* "fstein" is the default */ 636 { 637 bitmap->init_dither = init_fstein_dither; 638 bitmap->get_dither = get_fstein_dither; 639 bitmap->increment_dither = increment_fstein_dither; 640 } 641 } 642 643 /** 644 * \brief Get bitmap dithering methods 645 * 646 * Return a list of available dithering methods for a given bitmap. The list 647 * is a NULL-terminated array of strings, interleaving a string containing 648 * the internal value for the dithering method, to be used with 649 * \e cucul_set_bitmap_dithering(), and a string containing the natural 650 * language description for that dithering method. 651 * 652 * \param bitmap Bitmap object. 653 * \return An array of strings. 654 */ 655 char const * const * 656 cucul_get_bitmap_dithering_list(struct cucul_bitmap const *bitmap) 657 { 658 static char const * const list[] = 659 { 660 "none", "no dithering", 661 "ordered2", "2x2 ordered dithering", 662 "ordered2", "2x2 ordered dithering", 663 "ordered2", "2x2 ordered dithering", 664 "random", "random dithering", 665 "fstein", "Floyd-Steinberg dithering", 666 NULL, NULL 667 }; 668 669 return list; 670 } 671 672 /** 673 * \brief Draw a bitmap on the screen. 674 * 675 * Draw a bitmap at the given coordinates. The bitmap can be of any size and 676 * will be stretched to the text area. 677 * 678 * \param x1 X coordinate of the upper-left corner of the drawing area. 679 * \param y1 Y coordinate of the upper-left corner of the drawing area. 680 * \param x2 X coordinate of the lower-right corner of the drawing area. 681 * \param y2 Y coordinate of the lower-right corner of the drawing area. 682 * \param bitmap Bitmap object to be drawn. 683 * \param pixels Bitmap's pixels. 684 */ 685 void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, 686 struct cucul_bitmap const *bitmap, void *pixels) 687 { 688 int *floyd_steinberg, *fs_r, *fs_g, *fs_b; 689 int fs_length; 690 int x, y, w, h, pitch, deltax, deltay; 691 unsigned int dchmax; 692 693 if(!bitmap || !pixels) 694 return; 695 696 w = bitmap->w; 697 h = bitmap->h; 698 pitch = bitmap->pitch; 699 700 if(x1 > x2) 701 { 702 int tmp = x2; x2 = x1; x1 = tmp; 703 } 704 705 if(y1 > y2) 706 { 707 int tmp = y2; y2 = y1; y1 = tmp; 708 } 709 710 deltax = x2 - x1 + 1; 711 deltay = y2 - y1 + 1; 712 dchmax = bitmap->glyph_count; 713 714 fs_length = ((int)qq->width <= x2 ? (int)qq->width : x2) + 1; 715 floyd_steinberg = malloc(3 * (fs_length + 2) * sizeof(int)); 716 memset(floyd_steinberg, 0, 3 * (fs_length + 2) * sizeof(int)); 717 fs_r = floyd_steinberg + 1; 718 fs_g = fs_r + fs_length + 2; 719 fs_b = fs_g + fs_length + 2; 720 721 for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)qq->height; y++) 722 { 723 int remain_r = 0, remain_g = 0, remain_b = 0; 724 725 for(x = x1 > 0 ? x1 : 0, bitmap->init_dither(y); 726 x <= x2 && x <= (int)qq->width; 727 x++) 728 { 729 unsigned int i; 730 int ch = 0, distmin; 731 unsigned int rgba[4]; 732 int fg_r = 0, fg_g = 0, fg_b = 0, bg_r, bg_g, bg_b; 733 int fromx, fromy, tox, toy, myx, myy, dots, dist; 734 int error[3]; 735 736 enum cucul_color outfg = 0, outbg = 0; 737 char const *outch; 738 739 rgba[0] = rgba[1] = rgba[2] = rgba[3] = 0; 740 741 /* First get RGB */ 742 if(bitmap->antialias) 743 { 744 fromx = (x - x1) * w / deltax; 745 fromy = (y - y1) * h / deltay; 746 tox = (x - x1 + 1) * w / deltax; 747 toy = (y - y1 + 1) * h / deltay; 748 749 /* We want at least one pixel */ 750 if(tox == fromx) tox++; 751 if(toy == fromy) toy++; 752 753 dots = 0; 754 755 for(myx = fromx; myx < tox; myx++) 756 for(myy = fromy; myy < toy; myy++) 757 { 758 dots++; 759 get_rgba_default(bitmap, pixels, myx, myy, rgba); 760 } 761 762 /* Normalize */ 763 rgba[0] /= dots; 764 rgba[1] /= dots; 765 rgba[2] /= dots; 766 rgba[3] /= dots; 767 } 768 else 769 { 770 fromx = (x - x1) * w / deltax; 771 fromy = (y - y1) * h / deltay; 772 tox = (x - x1 + 1) * w / deltax; 773 toy = (y - y1 + 1) * h / deltay; 774 775 /* tox and toy can overflow the screen, but they cannot overflow 776 * when averaged with fromx and fromy because these are guaranteed 777 * to be within the pixel boundaries. */ 778 myx = (fromx + tox) / 2; 779 myy = (fromy + toy) / 2; 780 781 get_rgba_default(bitmap, pixels, myx, myy, rgba); 782 } 783 784 if(bitmap->has_alpha && rgba[3] < 0x800) 785 { 786 remain_r = remain_g = remain_b = 0; 787 fs_r[x] = 0; 788 fs_g[x] = 0; 789 fs_b[x] = 0; 790 continue; 791 } 792 793 /* XXX: OMG HAX */ 794 if(bitmap->init_dither == init_fstein_dither) 795 { 796 rgba[0] += remain_r; 797 rgba[1] += remain_g; 798 rgba[2] += remain_b; 799 } 800 else 801 { 802 rgba[0] += (bitmap->get_dither() - 0x80) * 4; 803 rgba[1] += (bitmap->get_dither() - 0x80) * 4; 804 rgba[2] += (bitmap->get_dither() - 0x80) * 4; 805 } 806 807 distmin = INT_MAX; 808 for(i = 0; i < 16; i++) 809 { 810 dist = sq(rgba[0] - rgb_palette[i * 3]) 811 + sq(rgba[1] - rgb_palette[i * 3 + 1]) 812 + sq(rgba[2] - rgb_palette[i * 3 + 2]); 813 dist *= rgb_weight[i]; 814 if(dist < distmin) 815 { 816 outbg = i; 817 distmin = dist; 818 } 819 } 820 bg_r = rgb_palette[outbg * 3]; 821 bg_g = rgb_palette[outbg * 3 + 1]; 822 bg_b = rgb_palette[outbg * 3 + 2]; 823 824 /* FIXME: we currently only honour "full16" */ 825 if(bitmap->color_mode == COLOR_MODE_FULL16) 826 { 827 distmin = INT_MAX; 828 for(i = 0; i < 16; i++) 829 { 830 if(i == outbg) 831 continue; 832 dist = sq(rgba[0] - rgb_palette[i * 3]) 833 + sq(rgba[1] - rgb_palette[i * 3 + 1]) 834 + sq(rgba[2] - rgb_palette[i * 3 + 2]); 835 dist *= rgb_weight[i]; 836 if(dist < distmin) 837 { 838 outfg = i; 839 distmin = dist; 840 } 841 } 842 fg_r = rgb_palette[outfg * 3]; 843 fg_g = rgb_palette[outfg * 3 + 1]; 844 fg_b = rgb_palette[outfg * 3 + 2]; 845 846 distmin = INT_MAX; 847 for(i = 0; i < dchmax - 1; i++) 848 { 849 int newr = i * fg_r + ((2*dchmax-1) - i) * bg_r; 850 int newg = i * fg_g + ((2*dchmax-1) - i) * bg_g; 851 int newb = i * fg_b + ((2*dchmax-1) - i) * bg_b; 852 dist = abs(rgba[0] * (2*dchmax-1) - newr) 853 + abs(rgba[1] * (2*dchmax-1) - newg) 854 + abs(rgba[2] * (2*dchmax-1) - newb); 855 856 if(dist < distmin) 857 { 858 ch = i; 859 distmin = dist; 860 } 861 } 862 outch = bitmap->glyphs[ch]; 863 864 /* XXX: OMG HAX */ 865 if(bitmap->init_dither == init_fstein_dither) 866 { 867 error[0] = rgba[0] - (fg_r * ch + bg_r * ((2*dchmax-1) - ch)) / (2*dchmax-1); 868 error[1] = rgba[1] - (fg_g * ch + bg_g * ((2*dchmax-1) - ch)) / (2*dchmax-1); 869 error[2] = rgba[2] - (fg_b * ch + bg_b * ((2*dchmax-1) - ch)) / (2*dchmax-1); 870 } 871 } 872 else 873 { 874 unsigned int lum = rgba[0]; 875 if(rgba[1] > lum) lum = rgba[1]; 876 if(rgba[2] > lum) lum = rgba[2]; 877 outfg = outbg; 878 outbg = CUCUL_COLOR_BLACK; 879 880 ch = lum * dchmax / 0x1000; 881 if(ch < 0) 882 ch = 0; 883 else if(ch > (int)(dchmax - 1)) 884 ch = dchmax - 1; 885 outch = bitmap->glyphs[ch]; 886 887 /* XXX: OMG HAX */ 888 if(bitmap->init_dither == init_fstein_dither) 889 { 890 error[0] = rgba[0] - bg_r * ch / (dchmax-1); 891 error[1] = rgba[1] - bg_g * ch / (dchmax-1); 892 error[2] = rgba[2] - bg_b * ch / (dchmax-1); 893 } 894 } 895 896 /* XXX: OMG HAX */ 897 if(bitmap->init_dither == init_fstein_dither) 898 { 899 remain_r = fs_r[x+1] + 7 * error[0] / 16; 900 remain_g = fs_g[x+1] + 7 * error[1] / 16; 901 remain_b = fs_b[x+1] + 7 * error[2] / 16; 902 fs_r[x-1] += 3 * error[0] / 16; 903 fs_g[x-1] += 3 * error[1] / 16; 904 fs_b[x-1] += 3 * error[2] / 16; 905 fs_r[x] = 5 * error[0] / 16; 906 fs_g[x] = 5 * error[1] / 16; 907 fs_b[x] = 5 * error[2] / 16; 908 fs_r[x+1] = 1 * error[0] / 16; 909 fs_g[x+1] = 1 * error[1] / 16; 910 fs_b[x+1] = 1 * error[2] / 16; 911 } 912 913 if(bitmap->invert) 914 { 915 outfg = 15 - outfg; 916 outbg = 15 - outbg; 917 } 918 919 /* Now output the character */ 920 cucul_set_color(qq, outfg, outbg); 921 cucul_putstr(qq, x, y, outch); 922 923 bitmap->increment_dither(); 924 } 925 /* end loop */ 926 } 927 928 free(floyd_steinberg); 929 } 930 931 /** 932 * \brief Free the memory associated with a bitmap. 933 * 934 * Free the memory allocated by cucul_create_bitmap(). 935 * 936 * \param bitmap Bitmap object. 937 */ 938 void cucul_free_bitmap(struct cucul_bitmap *bitmap) 939 { 940 if(!bitmap) 941 return; 942 943 free(bitmap); 944 } 945 946 /* 947 * XXX: The following functions are local. 948 */ 949 950 /* Convert a mask, eg. 0x0000ff00, to shift values, eg. 8 and -4. */ 156 951 static void mask2shift(unsigned int mask, int *right, int *left) 157 952 { … … 179 974 } 180 975 976 /* Compute x^y without relying on the math library */ 181 977 static float gammapow(float x, float y) 182 978 { … … 241 1037 } 242 1038 243 /**244 * \brief Create an internal bitmap object.245 *246 * Create a bitmap structure from its coordinates (depth, width, height and247 * pitch) and pixel mask values. If the depth is 8 bits per pixel, the mask248 * values are ignored and the colour palette should be set using the249 * cucul_set_bitmap_palette() function. For depths greater than 8 bits per250 * pixel, a zero alpha mask causes the alpha values to be ignored.251 *252 * \param bpp Bitmap depth in bits per pixel.253 * \param w Bitmap width in pixels.254 * \param h Bitmap height in pixels.255 * \param pitch Bitmap pitch in bytes.256 * \param rmask Bitmask for red values.257 * \param gmask Bitmask for green values.258 * \param bmask Bitmask for blue values.259 * \param amask Bitmask for alpha values.260 * \return Bitmap object, or NULL upon error.261 */262 struct cucul_bitmap *cucul_create_bitmap(unsigned int bpp, unsigned int w,263 unsigned int h, unsigned int pitch,264 unsigned int rmask, unsigned int gmask,265 unsigned int bmask, unsigned int amask)266 {267 struct cucul_bitmap *bitmap;268 int i;269 270 /* Minor sanity test */271 if(!w || !h || !pitch || bpp > 32 || bpp < 8)272 return NULL;273 274 bitmap = malloc(sizeof(struct cucul_bitmap));275 if(!bitmap)276 return NULL;277 278 bitmap->bpp = bpp;279 bitmap->has_palette = 0;280 bitmap->has_alpha = amask ? 1 : 0;281 282 bitmap->w = w;283 bitmap->h = h;284 bitmap->pitch = pitch;285 286 bitmap->rmask = rmask;287 bitmap->gmask = gmask;288 bitmap->bmask = bmask;289 bitmap->amask = amask;290 291 /* Load bitmasks */292 if(rmask || gmask || bmask || amask)293 {294 mask2shift(rmask, &bitmap->rright, &bitmap->rleft);295 mask2shift(gmask, &bitmap->gright, &bitmap->gleft);296 mask2shift(bmask, &bitmap->bright, &bitmap->bleft);297 mask2shift(amask, &bitmap->aright, &bitmap->aleft);298 }299 300 /* In 8 bpp mode, default to a grayscale palette */301 if(bpp == 8)302 {303 bitmap->has_palette = 1;304 bitmap->has_alpha = 0;305 for(i = 0; i < 256; i++)306 {307 bitmap->red[i] = i * 0xfff / 256;308 bitmap->green[i] = i * 0xfff / 256;309 bitmap->blue[i] = i * 0xfff / 256;310 }311 }312 313 /* Default gamma value */314 for(i = 0; i < 4096; i++)315 bitmap->gammatab[i] = i;316 317 /* No color inversion by default */318 bitmap->invert = 0;319 320 return bitmap;321 }322 323 /**324 * \brief Set the palette of an 8bpp bitmap object.325 *326 * Set the palette of an 8 bits per pixel bitmap. Values should be between327 * 0 and 4095 (0xfff).328 *329 * \param bitmap Bitmap object.330 * \param red Array of 256 red values.331 * \param green Array of 256 green values.332 * \param blue Array of 256 blue values.333 * \param alpha Array of 256 alpha values.334 */335 void cucul_set_bitmap_palette(struct cucul_bitmap *bitmap,336 unsigned int red[], unsigned int green[],337 unsigned int blue[], unsigned int alpha[])338 {339 int i, has_alpha = 0;340 341 if(bitmap->bpp != 8)342 return;343 344 for(i = 0; i < 256; i++)345 {346 if(red[i] >= 0 && red[i] < 0x1000 &&347 green[i] >= 0 && green[i] < 0x1000 &&348 blue[i] >= 0 && blue[i] < 0x1000 &&349 alpha[i] >= 0 && alpha[i] < 0x1000)350 {351 bitmap->red[i] = red[i];352 bitmap->green[i] = green[i];353 bitmap->blue[i] = blue[i];354 if(alpha[i])355 {356 bitmap->alpha[i] = alpha[i];357 has_alpha = 1;358 }359 }360 }361 362 bitmap->has_alpha = has_alpha;363 }364 365 /**366 * \brief Set the gamma of a bitmap object.367 *368 * Set the gamma of bitmap.369 *370 * \param bitmap Bitmap object.371 * \param gamma Gamma value.372 */373 void cucul_set_bitmap_gamma(struct cucul_bitmap *bitmap, float gamma)374 {375 int i;376 377 if(gamma <= 0.0)378 return;379 380 bitmap->gamma = gamma;381 382 for(i = 0; i < 4096; i++)383 bitmap->gammatab[i] = 4096.0 * gammapow((float)i / 4096.0, 1.0 / gamma);384 }385 386 387 /**388 * \brief Invert colors of bitmap389 *390 * Invert colors of bitmap391 *392 * \param bitmap Bitmap object.393 * \param value 0 for normal behaviour, 1 for invert394 */395 void cucul_set_bitmap_invert(struct cucul_bitmap *bitmap, unsigned char value)396 {397 bitmap->invert = (value==0)?0:1;398 }399 400 401 402 /**403 * \brief Free the memory associated with a bitmap.404 *405 * Free the memory allocated by cucul_create_bitmap().406 *407 * \param bitmap Bitmap object.408 */409 void cucul_free_bitmap(struct cucul_bitmap *bitmap)410 {411 if(!bitmap)412 return;413 414 free(bitmap);415 }416 417 1039 static void get_rgba_default(struct cucul_bitmap const *bitmap, uint8_t *pixels, 418 int x, int y, unsigned int *r, unsigned int *g, 419 unsigned int *b, unsigned int *a) 1040 int x, int y, unsigned int *rgba) 420 1041 { 421 1042 uint32_t bits; … … 457 1078 if(bitmap->has_palette) 458 1079 { 459 *r+= bitmap->gammatab[bitmap->red[bits]];460 *g+= bitmap->gammatab[bitmap->green[bits]];461 *b+= bitmap->gammatab[bitmap->blue[bits]];462 *a+= bitmap->alpha[bits];1080 rgba[0] += bitmap->gammatab[bitmap->red[bits]]; 1081 rgba[1] += bitmap->gammatab[bitmap->green[bits]]; 1082 rgba[2] += bitmap->gammatab[bitmap->blue[bits]]; 1083 rgba[3] += bitmap->alpha[bits]; 463 1084 } 464 1085 else 465 1086 { 466 *r += bitmap->gammatab[((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft]; 467 *g += bitmap->gammatab[((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft]; 468 *b += bitmap->gammatab[((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft]; 469 *a += ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft; 470 } 471 } 472 473 static inline void rgb2hsv_default(int r, int g, int b, 474 int *hue, int *sat, int *val) 475 { 476 int min, max, delta; 477 478 min = r; max = r; 479 if(min > g) min = g; if(max < g) max = g; 480 if(min > b) min = b; if(max < b) max = b; 481 482 delta = max - min; /* 0 - 0xfff */ 483 *val = max; /* 0 - 0xfff */ 484 485 if(delta) 486 { 487 *sat = 0xfff * delta / max; /* 0 - 0xfff */ 488 489 /* Generate *hue between 0 and 0x5fff */ 490 if( r == max ) 491 *hue = 0x1000 + 0x1000 * (g - b) / delta; 492 else if( g == max ) 493 *hue = 0x3000 + 0x1000 * (b - r) / delta; 494 else 495 *hue = 0x5000 + 0x1000 * (r - g) / delta; 496 } 497 else 498 { 499 *sat = 0; 500 *hue = 0; 501 } 502 } 503 504 static inline int sq(int x) 505 { 506 return x * x; 507 } 508 509 /** 510 * \brief Draw a bitmap on the screen. 511 * 512 * Draw a bitmap at the given coordinates. The bitmap can be of any size and 513 * will be stretched to the text area. 514 * 515 * \param x1 X coordinate of the upper-left corner of the drawing area. 516 * \param y1 Y coordinate of the upper-left corner of the drawing area. 517 * \param x2 X coordinate of the lower-right corner of the drawing area. 518 * \param y2 Y coordinate of the lower-right corner of the drawing area. 519 * \param bitmap Bitmap object to be drawn. 520 * \param pixels Bitmap's pixels. 521 */ 522 void cucul_draw_bitmap(cucul_t *qq, int x1, int y1, int x2, int y2, 523 struct cucul_bitmap const *bitmap, void *pixels) 524 { 525 /* Current dithering method */ 526 void (*_init_dither) (int); 527 unsigned int (*_get_dither) (void); 528 void (*_increment_dither) (void); 529 530 int *floyd_steinberg, *fs_r, *fs_g, *fs_b; 531 int fs_length; 532 533 /* FIXME: choose better characters! */ 534 #if !defined(_DOXYGEN_SKIP_ME) 535 # define DCHMAX ((sizeof(density_chars)/sizeof(*density_chars))) 536 #endif 537 static char const * density_chars[] = 538 { 539 #if CP437 540 " ", ":", "░", "▒", "?" 541 /* "0", "1", "2", "3", "?" */ 542 #else 543 " ", ".", ":", ";", "t", "%", "S", "X", "@", "8", "?" 544 #endif 1087 rgba[0] += bitmap->gammatab[((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft]; 1088 rgba[1] += bitmap->gammatab[((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft]; 1089 rgba[2] += bitmap->gammatab[((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft]; 1090 rgba[3] += ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft; 1091 } 1092 } 1093 1094 /* 1095 * No dithering 1096 */ 1097 static void init_no_dither(int line) 1098 { 1099 ; 1100 } 1101 1102 static unsigned int get_no_dither(void) 1103 { 1104 return 0x80; 1105 } 1106 1107 static void increment_no_dither(void) 1108 { 1109 return; 1110 } 1111 1112 /* 1113 * Floyd-Steinberg dithering 1114 */ 1115 static void init_fstein_dither(int line) 1116 { 1117 ; 1118 } 1119 1120 static unsigned int get_fstein_dither(void) 1121 { 1122 return 0x80; 1123 } 1124 1125 static void increment_fstein_dither(void) 1126 { 1127 return; 1128 } 1129 1130 /* 1131 * Ordered 2 dithering 1132 */ 1133 static unsigned int const *ordered2_table; 1134 static unsigned int ordered2_index; 1135 1136 static void init_ordered2_dither(int line) 1137 { 1138 static unsigned int const dither2x2[] = 1139 { 1140 0x00, 0x80, 1141 0xc0, 0x40, 545 1142 }; 546 1143 547 int x, y, w, h, pitch, deltax, deltay; 548 549 if(!bitmap || !pixels) 550 return; 551 552 w = bitmap->w; 553 h = bitmap->h; 554 pitch = bitmap->pitch; 555 556 if(x1 > x2) 557 { 558 int tmp = x2; x2 = x1; x1 = tmp; 559 } 560 561 if(y1 > y2) 562 { 563 int tmp = y2; y2 = y1; y1 = tmp; 564 } 565 566 deltax = x2 - x1 + 1; 567 deltay = y2 - y1 + 1; 568 569 switch(qq->dithering) 570 { 571 case CUCUL_DITHERING_NONE: 572 _init_dither = init_no_dither; 573 _get_dither = get_no_dither; 574 _increment_dither = increment_no_dither; 575 break; 576 577 case CUCUL_DITHERING_ORDERED2: 578 _init_dither = init_ordered2_dither; 579 _get_dither = get_ordered2_dither; 580 _increment_dither = increment_ordered2_dither; 581 break; 582 583 case CUCUL_DITHERING_ORDERED4: 584 _init_dither = init_ordered4_dither; 585 _get_dither = get_ordered4_dither; 586 _increment_dither = increment_ordered4_dither; 587 break; 588 589 case CUCUL_DITHERING_ORDERED8: 590 _init_dither = init_ordered8_dither; 591 _get_dither = get_ordered8_dither; 592 _increment_dither = increment_ordered8_dither; 593 break; 594 595 case CUCUL_DITHERING_RANDOM: 596 _init_dither = init_random_dither; 597 _get_dither = get_random_dither; 598 _increment_dither = increment_random_dither; 599 break; 600 601 case CUCUL_DITHERING_FSTEIN: 602 _init_dither = init_no_dither; 603 _get_dither = get_no_dither; 604 _increment_dither = increment_no_dither; 605 break; 606 607 default: 608 /* Something wicked happened! */ 609 return; 610 } 611 612 fs_length = ((int)qq->width <= x2 ? (int)qq->width : x2) + 1; 613 floyd_steinberg = malloc(3 * (fs_length + 2) * sizeof(int)); 614 memset(floyd_steinberg, 0, 3 * (fs_length + 2) * sizeof(int)); 615 fs_r = floyd_steinberg + 1; 616 fs_g = fs_r + fs_length + 2; 617 fs_b = fs_g + fs_length + 2; 618 619 for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)qq->height; y++) 620 { 621 int remain_r = 0, remain_g = 0, remain_b = 0; 622 623 for(x = x1 > 0 ? x1 : 0, _init_dither(y); 624 x <= x2 && x <= (int)qq->width; 625 x++) 626 { 627 unsigned int i; 628 int ch = 0, distmin; 629 unsigned int r, g, b, a; 630 int fg_r = 0, fg_g = 0, fg_b = 0, bg_r, bg_g, bg_b; 631 int fromx, fromy, tox, toy, myx, myy, dots, dist; 632 int error[3]; 633 634 enum cucul_color outfg = 0, outbg = 0; 635 char const *outch; 636 637 r = g = b = a = 0; 638 639 /* First get RGB */ 640 if(qq->antialiasing == CUCUL_ANTIALIASING_PREFILTER) 641 { 642 fromx = (x - x1) * w / deltax; 643 fromy = (y - y1) * h / deltay; 644 tox = (x - x1 + 1) * w / deltax; 645 toy = (y - y1 + 1) * h / deltay; 646 647 /* We want at least one pixel */ 648 if(tox == fromx) tox++; 649 if(toy == fromy) toy++; 650 651 dots = 0; 652 653 for(myx = fromx; myx < tox; myx++) 654 for(myy = fromy; myy < toy; myy++) 655 { 656 dots++; 657 get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a); 658 } 659 660 /* Normalize */ 661 r /= dots; 662 g /= dots; 663 b /= dots; 664 a /= dots; 665 } 666 else 667 { 668 fromx = (x - x1) * w / deltax; 669 fromy = (y - y1) * h / deltay; 670 tox = (x - x1 + 1) * w / deltax; 671 toy = (y - y1 + 1) * h / deltay; 672 673 /* tox and toy can overflow the screen, but they cannot overflow 674 * when averaged with fromx and fromy because these are guaranteed 675 * to be within the pixel boundaries. */ 676 myx = (fromx + tox) / 2; 677 myy = (fromy + toy) / 2; 678 679 get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a); 680 } 681 682 if(bitmap->has_alpha && a < 0x800) 683 { 684 remain_r = remain_g = remain_b = 0; 685 fs_r[x] = 0; 686 fs_g[x] = 0; 687 fs_b[x] = 0; 688 continue; 689 } 690 691 if(qq->dithering == CUCUL_DITHERING_FSTEIN) 692 { 693 r += remain_r; 694 g += remain_g; 695 b += remain_b; 696 } 697 else 698 { 699 r += (_get_dither() - 0x80) * 4; 700 g += (_get_dither() - 0x80) * 4; 701 b += (_get_dither() - 0x80) * 4; 702 } 703 704 distmin = INT_MAX; 705 for(i = 0; i < 16; i++) 706 { 707 dist = sq(r - rgb_palette[i * 3]) 708 + sq(g - rgb_palette[i * 3 + 1]) 709 + sq(b - rgb_palette[i * 3 + 2]); 710 dist *= rgb_weight[i]; 711 if(dist < distmin) 712 { 713 outbg = i; 714 distmin = dist; 715 } 716 } 717 bg_r = rgb_palette[outbg * 3]; 718 bg_g = rgb_palette[outbg * 3 + 1]; 719 bg_b = rgb_palette[outbg * 3 + 2]; 720 721 if(qq->background == CUCUL_BACKGROUND_SOLID) 722 { 723 distmin = INT_MAX; 724 for(i = 0; i < 16; i++) 725 { 726 if(i == outbg) 727 continue; 728 dist = sq(r - rgb_palette[i * 3]) 729 + sq(g - rgb_palette[i * 3 + 1]) 730 + sq(b - rgb_palette[i * 3 + 2]); 731 dist *= rgb_weight[i]; 732 if(dist < distmin) 733 { 734 outfg = i; 735 distmin = dist; 736 } 737 } 738 fg_r = rgb_palette[outfg * 3]; 739 fg_g = rgb_palette[outfg * 3 + 1]; 740 fg_b = rgb_palette[outfg * 3 + 2]; 741 742 distmin = INT_MAX; 743 for(i = 0; i < DCHMAX - 1; i++) 744 { 745 int newr = i * fg_r + ((2*DCHMAX-1) - i) * bg_r; 746 int newg = i * fg_g + ((2*DCHMAX-1) - i) * bg_g; 747 int newb = i * fg_b + ((2*DCHMAX-1) - i) * bg_b; 748 dist = abs(r * (2*DCHMAX-1) - newr) 749 + abs(g * (2*DCHMAX-1) - newg) 750 + abs(b * (2*DCHMAX-1) - newb); 751 752 if(dist < distmin) 753 { 754 ch = i; 755 distmin = dist; 756 } 757 } 758 outch = density_chars[ch]; 759 760 if(qq->dithering == CUCUL_DITHERING_FSTEIN) 761 { 762 error[0] = r - (fg_r * ch + bg_r * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); 763 error[1] = g - (fg_g * ch + bg_g * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); 764 error[2] = b - (fg_b * ch + bg_b * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); 765 } 766 } 767 else 768 { 769 unsigned int lum = r; if(g > lum) lum = g; if(b > lum) lum = b; 770 outfg = outbg; 771 outbg = CUCUL_COLOR_BLACK; 772 773 ch = lum * DCHMAX / 0x1000; 774 if(ch < 0) 775 ch = 0; 776 else if(ch > (int)(DCHMAX - 1)) 777 ch = DCHMAX - 1; 778 outch = density_chars[ch]; 779 780 if(qq->dithering == CUCUL_DITHERING_FSTEIN) 781 { 782 error[0] = r - bg_r * ch / (DCHMAX-1); 783 error[1] = g - bg_g * ch / (DCHMAX-1); 784 error[2] = b - bg_b * ch / (DCHMAX-1); 785 } 786 } 787 788 if(qq->dithering == CUCUL_DITHERING_FSTEIN) 789 { 790 remain_r = fs_r[x+1] + 7 * error[0] / 16; 791 remain_g = fs_g[x+1] + 7 * error[1] / 16; 792 remain_b = fs_b[x+1] + 7 * error[2] / 16; 793 fs_r[x-1] += 3 * error[0] / 16; 794 fs_g[x-1] += 3 * error[1] / 16; 795 fs_b[x-1] += 3 * error[2] / 16; 796 fs_r[x] = 5 * error[0] / 16; 797 fs_g[x] = 5 * error[1] / 16; 798 fs_b[x] = 5 * error[2] / 16; 799 fs_r[x+1] = 1 * error[0] / 16; 800 fs_g[x+1] = 1 * error[1] / 16; 801 fs_b[x+1] = 1 * error[2] / 16; 802 } 803 804 if(bitmap->invert) { 805 outfg = 15-outfg; 806 outbg = 15-outbg; 807 } 808 809 /* Now output the character */ 810 cucul_set_color(qq, outfg, outbg); 811 cucul_putstr(qq, x, y, outch); 812 813 _increment_dither(); 814 } 815 /* end loop */ 816 } 817 818 free(floyd_steinberg); 1144 ordered2_table = dither2x2 + (line % 2) * 2; 1145 ordered2_index = 0; 1146 } 1147 1148 static unsigned int get_ordered2_dither(void) 1149 { 1150 return ordered2_table[ordered2_index]; 1151 } 1152 1153 static void increment_ordered2_dither(void) 1154 { 1155 ordered2_index = (ordered2_index + 1) % 2; 1156 } 1157 1158 /* 1159 * Ordered 4 dithering 1160 */ 1161 /*static int dither4x4[] = { 5, 0, 1, 6, 1162 -1, -6, -5, 2, 1163 -2, -7, -8, 3, 1164 4, -3, -4, -7};*/ 1165 static unsigned int const *ordered4_table; 1166 static unsigned int ordered4_index; 1167 1168 static void init_ordered4_dither(int line) 1169 { 1170 static unsigned int const dither4x4[] = 1171 { 1172 0x00, 0x80, 0x20, 0xa0, 1173 0xc0, 0x40, 0xe0, 0x60, 1174 0x30, 0xb0, 0x10, 0x90, 1175 0xf0, 0x70, 0xd0, 0x50 1176 }; 1177 1178 ordered4_table = dither4x4 + (line % 4) * 4; 1179 ordered4_index = 0; 1180 } 1181 1182 static unsigned int get_ordered4_dither(void) 1183 { 1184 return ordered4_table[ordered4_index]; 1185 } 1186 1187 static void increment_ordered4_dither(void) 1188 { 1189 ordered4_index = (ordered4_index + 1) % 4; 1190 } 1191 1192 /* 1193 * Ordered 8 dithering 1194 */ 1195 static unsigned int const *ordered8_table; 1196 static unsigned int ordered8_index; 1197 1198 static void init_ordered8_dither(int line) 1199 { 1200 static unsigned int const dither8x8[] = 1201 { 1202 0x00, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8, 1203 0xc0, 0x40, 0xe0, 0x60, 0xc8, 0x48, 0xe8, 0x68, 1204 0x30, 0xb0, 0x10, 0x90, 0x38, 0xb8, 0x18, 0x98, 1205 0xf0, 0x70, 0xd0, 0x50, 0xf8, 0x78, 0xd8, 0x58, 1206 0x0c, 0x8c, 0x2c, 0xac, 0x04, 0x84, 0x24, 0xa4, 1207 0xcc, 0x4c, 0xec, 0x6c, 0xc4, 0x44, 0xe4, 0x64, 1208 0x3c, 0xbc, 0x1c, 0x9c, 0x34, 0xb4, 0x14, 0x94, 1209 0xfc, 0x7c, 0xdc, 0x5c, 0xf4, 0x74, 0xd4, 0x54, 1210 }; 1211 1212 ordered8_table = dither8x8 + (line % 8) * 8; 1213 ordered8_index = 0; 1214 } 1215 1216 static unsigned int get_ordered8_dither(void) 1217 { 1218 return ordered8_table[ordered8_index]; 1219 } 1220 1221 static void increment_ordered8_dither(void) 1222 { 1223 ordered8_index = (ordered8_index + 1) % 8; 1224 } 1225 1226 /* 1227 * Random dithering 1228 */ 1229 static void init_random_dither(int line) 1230 { 1231 ; 1232 } 1233 1234 static unsigned int get_random_dither(void) 1235 { 1236 return cucul_rand(0x00, 0xff); 1237 } 1238 1239 static void increment_random_dither(void) 1240 { 1241 return; 819 1242 } 820 1243 … … 884 1307 #endif /* _DOXYGEN_SKIP_ME */ 885 1308 886 /* 887 * XXX: The following functions are local. 888 */ 889 890 /* 891 * No dithering 892 */ 893 static void init_no_dither(int line) 894 { 895 ; 896 } 897 898 static unsigned int get_no_dither(void) 899 { 900 return 0x80; 901 } 902 903 static void increment_no_dither(void) 904 { 905 return; 906 } 907 908 /* 909 * Ordered 2 dithering 910 */ 911 static unsigned int const *ordered2_table; 912 static unsigned int ordered2_index; 913 914 static void init_ordered2_dither(int line) 915 { 916 static unsigned int const dither2x2[] = 917 { 918 0x00, 0x80, 919 0xc0, 0x40, 920 }; 921 922 ordered2_table = dither2x2 + (line % 2) * 2; 923 ordered2_index = 0; 924 } 925 926 static unsigned int get_ordered2_dither(void) 927 { 928 return ordered2_table[ordered2_index]; 929 } 930 931 static void increment_ordered2_dither(void) 932 { 933 ordered2_index = (ordered2_index + 1) % 2; 934 } 935 936 /* 937 * Ordered 4 dithering 938 */ 939 /*static int dither4x4[] = { 5, 0, 1, 6, 940 -1, -6, -5, 2, 941 -2, -7, -8, 3, 942 4, -3, -4, -7};*/ 943 static unsigned int const *ordered4_table; 944 static unsigned int ordered4_index; 945 946 static void init_ordered4_dither(int line) 947 { 948 static unsigned int const dither4x4[] = 949 { 950 0x00, 0x80, 0x20, 0xa0, 951 0xc0, 0x40, 0xe0, 0x60, 952 0x30, 0xb0, 0x10, 0x90, 953 0xf0, 0x70, 0xd0, 0x50 954 }; 955 956 ordered4_table = dither4x4 + (line % 4) * 4; 957 ordered4_index = 0; 958 } 959 960 static unsigned int get_ordered4_dither(void) 961 { 962 return ordered4_table[ordered4_index]; 963 } 964 965 static void increment_ordered4_dither(void) 966 { 967 ordered4_index = (ordered4_index + 1) % 4; 968 } 969 970 /* 971 * Ordered 8 dithering 972 */ 973 static unsigned int const *ordered8_table; 974 static unsigned int ordered8_index; 975 976 static void init_ordered8_dither(int line) 977 { 978 static unsigned int const dither8x8[] = 979 { 980 0x00, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8, 981 0xc0, 0x40, 0xe0, 0x60, 0xc8, 0x48, 0xe8, 0x68, 982 0x30, 0xb0, 0x10, 0x90, 0x38, 0xb8, 0x18, 0x98, 983 0xf0, 0x70, 0xd0, 0x50, 0xf8, 0x78, 0xd8, 0x58, 984 0x0c, 0x8c, 0x2c, 0xac, 0x04, 0x84, 0x24, 0xa4, 985 0xcc, 0x4c, 0xec, 0x6c, 0xc4, 0x44, 0xe4, 0x64, 986 0x3c, 0xbc, 0x1c, 0x9c, 0x34, 0xb4, 0x14, 0x94, 987 0xfc, 0x7c, 0xdc, 0x5c, 0xf4, 0x74, 0xd4, 0x54, 988 }; 989 990 ordered8_table = dither8x8 + (line % 8) * 8; 991 ordered8_index = 0; 992 } 993 994 static unsigned int get_ordered8_dither(void) 995 { 996 return ordered8_table[ordered8_index]; 997 } 998 999 static void increment_ordered8_dither(void) 1000 { 1001 ordered8_index = (ordered8_index + 1) % 8; 1002 } 1003 1004 /* 1005 * Random dithering 1006 */ 1007 static void init_random_dither(int line) 1008 { 1009 ; 1010 } 1011 1012 static unsigned int get_random_dither(void) 1013 { 1014 return cucul_rand(0x00, 0xff); 1015 } 1016 1017 static void increment_random_dither(void) 1018 { 1019 return; 1020 } 1021 1309 -
libcaca/trunk/cucul/cucul.c
r708 r711 29 29 #include "cucul_internals.h" 30 30 31 static void cucul_read_environment(cucul_t *);32 33 31 /** \brief Initialise a \e libcucul canvas. 34 32 * … … 48 46 { 49 47 cucul_t *qq = malloc(sizeof(cucul_t)); 50 51 cucul_read_environment(qq);52 48 53 49 qq->refcount = 0; … … 202 198 } 203 199 204 /** \brief Get the current value of a feature.205 *206 * This function retrieves the value of an internal \e libcucul feature. A207 * generic feature value is expected, such as CUCUL_ANTIALIASING.208 *209 * \param feature The requested feature.210 * \return The current value of the feature or CUCUL_FEATURE_UNKNOWN if an211 * error occurred..212 */213 enum cucul_feature cucul_get_feature(cucul_t *qq, enum cucul_feature feature)214 {215 switch(feature)216 {217 case CUCUL_BACKGROUND:218 return qq->background;219 case CUCUL_ANTIALIASING:220 return qq->antialiasing;221 case CUCUL_DITHERING:222 return qq->dithering;223 224 default:225 return CUCUL_FEATURE_UNKNOWN;226 }227 }228 229 /** \brief Set a feature.230 *231 * This function sets an internal \e libcucul feature such as the antialiasing232 * or dithering modes. If a specific feature such as CUCUL_DITHERING_RANDOM,233 * cucul_set_feature() will set it immediately. If a generic feature is given234 * instead, such as CUCUL_DITHERING, the default value will be used instead.235 *236 * \param feature The requested feature.237 */238 void cucul_set_feature(cucul_t *qq, enum cucul_feature feature)239 {240 switch(feature)241 {242 case CUCUL_BACKGROUND:243 feature = CUCUL_BACKGROUND_SOLID;244 case CUCUL_BACKGROUND_BLACK:245 case CUCUL_BACKGROUND_SOLID:246 qq->background = feature;247 break;248 249 case CUCUL_ANTIALIASING:250 feature = CUCUL_ANTIALIASING_PREFILTER;251 case CUCUL_ANTIALIASING_NONE:252 case CUCUL_ANTIALIASING_PREFILTER:253 qq->antialiasing = feature;254 break;255 256 case CUCUL_DITHERING:257 feature = CUCUL_DITHERING_FSTEIN;258 case CUCUL_DITHERING_NONE:259 case CUCUL_DITHERING_ORDERED2:260 case CUCUL_DITHERING_ORDERED4:261 case CUCUL_DITHERING_ORDERED8:262 case CUCUL_DITHERING_RANDOM:263 case CUCUL_DITHERING_FSTEIN:264 qq->dithering = feature;265 break;266 267 case CUCUL_FEATURE_UNKNOWN:268 break;269 }270 }271 272 /** \brief Translate a feature value into the feature's name.273 *274 * This function translates a cucul_feature enum into a human-readable275 * description string of the associated feature.276 *277 * \param feature The feature value.278 * \return A static string containing the feature's name.279 */280 char const *cucul_get_feature_name(enum cucul_feature feature)281 {282 switch(feature)283 {284 case CUCUL_BACKGROUND_BLACK: return "black background";285 case CUCUL_BACKGROUND_SOLID: return "solid background";286 287 case CUCUL_ANTIALIASING_NONE: return "no antialiasing";288 case CUCUL_ANTIALIASING_PREFILTER: return "prefilter antialiasing";289 290 case CUCUL_DITHERING_NONE: return "no dithering";291 case CUCUL_DITHERING_ORDERED2: return "2x2 ordered dithering";292 case CUCUL_DITHERING_ORDERED4: return "4x4 ordered dithering";293 case CUCUL_DITHERING_ORDERED8: return "8x8 ordered dithering";294 case CUCUL_DITHERING_RANDOM: return "random dithering";295 case CUCUL_DITHERING_FSTEIN: return "Floyd-Steinberg dithering";296 297 default: return "unknown";298 }299 }300 301 200 /** \brief Uninitialise \e libcucul. 302 201 * … … 381 280 */ 382 281 383 static void cucul_read_environment(cucul_t * qq)384 {385 /* FIXME: if strcasecmp isn't available, use strcmp */386 #if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)387 char *var;388 #endif389 390 cucul_set_feature(qq, CUCUL_BACKGROUND);391 cucul_set_feature(qq, CUCUL_ANTIALIASING);392 cucul_set_feature(qq, CUCUL_DITHERING);393 394 #if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)395 if((var = getenv("CUCUL_BACKGROUND")) && *var)396 {397 if(!strcasecmp("black", var))398 cucul_set_feature(qq, CUCUL_BACKGROUND_BLACK);399 else if(!strcasecmp("solid", var))400 cucul_set_feature(qq, CUCUL_BACKGROUND_SOLID);401 }402 403 if((var = getenv("CUCUL_ANTIALIASING")) && *var)404 {405 if(!strcasecmp("none", var))406 cucul_set_feature(qq, CUCUL_ANTIALIASING_NONE);407 else if(!strcasecmp("prefilter", var))408 cucul_set_feature(qq, CUCUL_ANTIALIASING_PREFILTER);409 }410 411 if((var = getenv("CUCUL_DITHERING")) && *var)412 {413 if(!strcasecmp("none", var))414 cucul_set_feature(qq, CUCUL_DITHERING_NONE);415 else if(!strcasecmp("ordered2", var))416 cucul_set_feature(qq, CUCUL_DITHERING_ORDERED2);417 else if(!strcasecmp("ordered4", var))418 cucul_set_feature(qq, CUCUL_DITHERING_ORDERED4);419 else if(!strcasecmp("ordered8", var))420 cucul_set_feature(qq, CUCUL_DITHERING_ORDERED8);421 else if(!strcasecmp("random", var))422 cucul_set_feature(qq, CUCUL_DITHERING_RANDOM);423 else if(!strcasecmp("fstein", var))424 cucul_set_feature(qq, CUCUL_DITHERING_FSTEIN);425 }426 #endif427 }428 429 282 void _cucul_set_size(cucul_t *qq, unsigned int width, unsigned int height) 430 283 { -
libcaca/trunk/cucul/cucul.h
r708 r711 35 35 enum cucul_color 36 36 { 37 CUCUL_COLOR_BLACK = 0, /**< The colour index for black. */ 38 CUCUL_COLOR_BLUE = 1, /**< The colour index for blue. */ 39 CUCUL_COLOR_GREEN = 2, /**< The colour index for green. */ 40 CUCUL_COLOR_CYAN = 3, /**< The colour index for cyan. */ 41 CUCUL_COLOR_RED = 4, /**< The colour index for red. */ 42 CUCUL_COLOR_MAGENTA = 5, /**< The colour index for magenta. */ 43 CUCUL_COLOR_BROWN = 6, /**< The colour index for brown. */ 44 CUCUL_COLOR_LIGHTGRAY = 7, /**< The colour index for light gray. */ 45 CUCUL_COLOR_DARKGRAY = 8, /**< The colour index for dark gray. */ 46 CUCUL_COLOR_LIGHTBLUE = 9, /**< The colour index for blue. */ 47 CUCUL_COLOR_LIGHTGREEN = 10, /**< The colour index for light green. */ 48 CUCUL_COLOR_LIGHTCYAN = 11, /**< The colour index for light cyan. */ 49 CUCUL_COLOR_LIGHTRED = 12, /**< The colour index for light red. */ 50 CUCUL_COLOR_LIGHTMAGENTA = 13, /**< The colour index for light magenta. */ 51 CUCUL_COLOR_YELLOW = 14, /**< The colour index for yellow. */ 52 CUCUL_COLOR_WHITE = 15 /**< The colour index for white. */ 37 CUCUL_COLOR_BLACK = 0x0, /**< The colour index for black. */ 38 CUCUL_COLOR_BLUE = 0x1, /**< The colour index for blue. */ 39 CUCUL_COLOR_GREEN = 0x2, /**< The colour index for green. */ 40 CUCUL_COLOR_CYAN = 0x3, /**< The colour index for cyan. */ 41 CUCUL_COLOR_RED = 0x4, /**< The colour index for red. */ 42 CUCUL_COLOR_MAGENTA = 0x5, /**< The colour index for magenta. */ 43 CUCUL_COLOR_BROWN = 0x6, /**< The colour index for brown. */ 44 CUCUL_COLOR_LIGHTGRAY = 0x7, /**< The colour index for light gray. */ 45 CUCUL_COLOR_DARKGRAY = 0x8, /**< The colour index for dark gray. */ 46 CUCUL_COLOR_LIGHTBLUE = 0x9, /**< The colour index for blue. */ 47 CUCUL_COLOR_LIGHTGREEN = 0xa, /**< The colour index for light green. */ 48 CUCUL_COLOR_LIGHTCYAN = 0xb, /**< The colour index for light cyan. */ 49 CUCUL_COLOR_LIGHTRED = 0xc, /**< The colour index for light red. */ 50 CUCUL_COLOR_LIGHTMAGENTA = 0xd, /**< The colour index for light magenta. */ 51 CUCUL_COLOR_YELLOW = 0xe, /**< The colour index for yellow. */ 52 CUCUL_COLOR_WHITE = 0xf, /**< The colour index for white. */ 53 54 CUCUL_COLOR_TRANSPARENT = 0xfe, /**< The transparent colour. */ 55 CUCUL_COLOR_DEFAULT = 0xff, /**< The output driver's default colour. */ 53 56 }; 54 55 /** \brief Internal features.56 *57 * Internal libcaca features such as the rendering method or the dithering58 * mode.59 */60 enum cucul_feature61 {62 CUCUL_BACKGROUND = 0x10, /**< Properties of background characters. */63 CUCUL_BACKGROUND_BLACK = 0x11, /**< Draw only black backgrounds. */64 CUCUL_BACKGROUND_SOLID = 0x12, /**< Draw coloured solid backgorunds. */65 #define CUCUL_BACKGROUND_MIN 0x11 /**< First background property */66 #define CUCUL_BACKGROUND_MAX 0x12 /**< Last background property */67 68 CUCUL_ANTIALIASING = 0x20, /**< Antialiasing features. */69 CUCUL_ANTIALIASING_NONE = 0x21, /**< No antialiasing. */70 CUCUL_ANTIALIASING_PREFILTER = 0x22, /**< Prefilter antialiasing. */71 #define CUCUL_ANTIALIASING_MIN 0x21 /**< First antialiasing feature. */72 #define CUCUL_ANTIALIASING_MAX 0x22 /**< Last antialiasing feature. */73 74 CUCUL_DITHERING = 0x30, /**< Dithering methods */75 CUCUL_DITHERING_NONE = 0x31, /**< No dithering. */76 CUCUL_DITHERING_ORDERED2 = 0x32, /**< Ordered 2x2 Bayer dithering. */77 CUCUL_DITHERING_ORDERED4 = 0x33, /**< Ordered 4x4 Bayer dithering. */78 CUCUL_DITHERING_ORDERED8 = 0x34, /**< Ordered 8x8 Bayer dithering. */79 CUCUL_DITHERING_RANDOM = 0x35, /**< Random dithering. */80 CUCUL_DITHERING_FSTEIN = 0x36, /**< Floyd-Steinberg dithering. */81 #define CUCUL_DITHERING_MIN 0x31 /**< First dithering feature. */82 #define CUCUL_DITHERING_MAX 0x36 /**< Last dithering feature. */83 84 CUCUL_FEATURE_UNKNOWN = 0xffff /**< Unknown feature. */85 };86 87 /*88 * Backwards compatibility macros89 */90 #if !defined(_DOXYGEN_SKIP_ME)91 #define caca_dithering cucul_feature92 #define caca_set_dithering caca_set_feature93 #define caca_get_dithering_name caca_get_feature_name94 #define CACA_DITHER_NONE CUCUL_DITHERING_NONE95 #define CACA_DITHER_ORDERED CUCUL_DITHERING_ORDERED896 #define CACA_DITHER_RANDOM CUCUL_DITHERING_RANDOM97 #endif98 57 99 58 typedef struct cucul_context cucul_t; … … 110 69 unsigned int cucul_get_width(cucul_t *); 111 70 unsigned int cucul_get_height(cucul_t *); 112 enum cucul_feature cucul_get_feature(cucul_t *, enum cucul_feature);113 void cucul_set_feature(cucul_t *, enum cucul_feature);114 char const *cucul_get_feature_name(enum cucul_feature);115 71 void cucul_free(cucul_t *); 116 72 /* @} */ … … 210 166 unsigned int r[], unsigned int g[], 211 167 unsigned int b[], unsigned int a[]); 168 void cucul_set_bitmap_brightness(struct cucul_bitmap *, float); 212 169 void cucul_set_bitmap_gamma(struct cucul_bitmap *, float); 213 void cucul_draw_bitmap(cucul_t *, int, int, int, int, struct cucul_bitmap const *, void *); 214 void cucul_set_bitmap_invert(struct cucul_bitmap *, unsigned char); 170 void cucul_set_bitmap_contrast(struct cucul_bitmap *, float); 171 void cucul_set_bitmap_invert(struct cucul_bitmap *, int); 172 void cucul_set_bitmap_antialias(struct cucul_bitmap *, int); 173 void cucul_set_bitmap_color(struct cucul_bitmap *, char const *); 174 char const * const * cucul_get_bitmap_color_list(struct cucul_bitmap const *); 175 void cucul_set_bitmap_charset(struct cucul_bitmap *, char const *); 176 char const * const * cucul_get_bitmap_charset_list(struct cucul_bitmap 177 const *); 178 void cucul_set_bitmap_dithering(struct cucul_bitmap *, char const *); 179 char const * const * cucul_get_bitmap_dithering_list(struct cucul_bitmap 180 const *); 181 void cucul_draw_bitmap(cucul_t *, int, int, int, int, 182 struct cucul_bitmap const *, void *); 215 183 void cucul_free_bitmap(struct cucul_bitmap *); 216 184 /* @} */ -
libcaca/trunk/cucul/cucul_internals.h
r678 r711 44 44 enum cucul_color bgcolor; 45 45 46 /* Internal libcucul features */47 enum cucul_feature background, antialiasing, dithering;48 49 46 unsigned int refcount; 50 47 }; -
libcaca/trunk/test/demo.c
r710 r711 101 101 display_menu(); 102 102 break; 103 #if 0 103 104 case 'd': 104 105 case 'D': … … 107 108 display_menu(); 108 109 break; 110 #endif 109 111 case 'c': 110 112 demo = demo_color; … … 218 220 cucul_printf(qq, 4, 18, "'b': drawing boundaries: %s", 219 221 bounds == 0 ? "screen" : "infinite"); 220 cucul_printf(qq, 4, 19, "'d': dithering (%s)",221 cucul_get_feature_name(dithering));222 //cucul_printf(qq, 4, 19, "'d': dithering (%s)", 223 // cucul_get_feature_name(dithering)); 222 224 223 225 cucul_putstr(qq, 4, yo - 2, "'q': quit");
Note: See TracChangeset
for help on using the changeset viewer.