Changeset 711


Ignore:
Timestamp:
Apr 1, 2006, 5:02:05 PM (15 years ago)
Author:
Sam Hocevar
Message:
  • Removed CUCUL_BACKGROUND, CUCUL_ANTIALIASING and CUCUL_DITHERING environment variables handling. Replaced that with three per-bitmap functions: cucul_set_bitmap_antialias(), cucul_set_bitmap_color() and cucul_set_bitmap_dithering().
  • Added cucul_set_bitmap_brightness() and cucul_set_bitmap_contrast() prototypes (but did not implement them yet).
  • Added cucul_set_bitmap_charset() to choose what characters are going to be used for the bitmap rendering.
  • Removed the now useless cucul_get_feature(), cucul_set_feature() etc.
Location:
libcaca/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/caca/caca.h

    r710 r711  
    3131 *  ncurses (through Cygwin emulation) or conio. There is also a native X11
    3232 *  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  *  the 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.
    3535 *
    3636 *  \e libcaca is free software, released under the Do What The Fuck You
     
    5252 *
    5353 *  Some environment variables can be used to change the behaviour of
    54  *  \e libcaca or \e libcucul without having to modify the program which
    55  *  uses them. These variables are:
     54 *  \e libcaca without having to modify the program which uses them. These
     55 *  variables are:
    5656 *
    5757 *  \li \b CACA_DRIVER: set the backend video driver. In order of preference:
     
    6161 *      - \c x11 uses the native X11 driver.
    6262 *      - \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.
    8765 *
    8866 *  \li \b CACA_GEOMETRY: set the video display size. The format of this
  • libcaca/trunk/cucul/bitmap.c

    r691 r711  
    8686};
    8787
     88/* List of glyphs */
     89static char const * ascii_glyphs[] =
     90{
     91    " ", ".", ":", ";", "t", "%", "S", "X", "@", "8", "?"
     92};
     93
     94static char const * shades_glyphs[] =
     95{
     96    " ", ":", "░", "▒", "?"
     97};
     98
     99static char const * blocks_glyphs[] =
     100{
     101    " ", "▘", "▚", "?"
     102};
     103
    88104#if !defined(_DOXYGEN_SKIP_ME)
     105enum 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
     116struct 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
    89144#define HSV_XRATIO 6
    90145#define HSV_YRATIO 3
     
    112167
    113168static void get_rgba_default(struct cucul_bitmap const *, uint8_t *, int, int,
    114                              unsigned int *, unsigned int *, unsigned int *,
    115169                             unsigned int *);
    116 static inline void rgb2hsv_default(int, int, int, int *, int *, int *);
    117 static inline int sq(int);
    118170
    119171/* Dithering methods */
     
    122174static void increment_no_dither(void);
    123175
     176static void init_fstein_dither(int);
     177static unsigned int get_fstein_dither(void);
     178static void increment_fstein_dither(void);
     179
    124180static void init_ordered2_dither(int);
    125181static unsigned int get_ordered2_dither(void);
     
    138194static void increment_random_dither(void);
    139195
    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 
     196static inline int sq(int x)
     197{
     198    return x * x;
     199}
     200
     201static 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 */
     251struct 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 */
     332void 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 */
     370void 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 */
     383void 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 */
     407void 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 */
     422void 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 */
     435void 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 */
     467void 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 */
     497char 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 */
     534void 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 */
     565char 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 */
     603void 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 */
     655char 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 */
     685void 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 */
     938void 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. */
    156951static void mask2shift(unsigned int mask, int *right, int *left)
    157952{
     
    179974}
    180975
     976/* Compute x^y without relying on the math library */
    181977static float gammapow(float x, float y)
    182978{
     
    2411037}
    2421038
    243 /**
    244  * \brief Create an internal bitmap object.
    245  *
    246  * Create a bitmap structure from its coordinates (depth, width, height and
    247  * pitch) and pixel mask values. If the depth is 8 bits per pixel, the mask
    248  * values are ignored and the colour palette should be set using the
    249  * cucul_set_bitmap_palette() function. For depths greater than 8 bits per
    250  * 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 between
    327  * 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 bitmap
    389  *
    390  * Invert colors of bitmap
    391  *
    392  * \param bitmap Bitmap object.
    393  * \param value 0 for normal behaviour, 1 for invert
    394  */
    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 
    4171039static 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)
    4201041{
    4211042    uint32_t bits;
     
    4571078    if(bitmap->has_palette)
    4581079    {
    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];
    4631084    }
    4641085    else
    4651086    {
    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 */
     1097static void init_no_dither(int line)
     1098{
     1099    ;
     1100}
     1101
     1102static unsigned int get_no_dither(void)
     1103{
     1104    return 0x80;
     1105}
     1106
     1107static void increment_no_dither(void)
     1108{
     1109    return;
     1110}
     1111
     1112/*
     1113 * Floyd-Steinberg dithering
     1114 */
     1115static void init_fstein_dither(int line)
     1116{
     1117    ;
     1118}
     1119
     1120static unsigned int get_fstein_dither(void)
     1121{
     1122    return 0x80;
     1123}
     1124
     1125static void increment_fstein_dither(void)
     1126{
     1127    return;
     1128}
     1129
     1130/*
     1131 * Ordered 2 dithering
     1132 */
     1133static unsigned int const *ordered2_table;
     1134static unsigned int ordered2_index;
     1135
     1136static void init_ordered2_dither(int line)
     1137{
     1138    static unsigned int const dither2x2[] =
     1139    {
     1140        0x00, 0x80,
     1141        0xc0, 0x40,
    5451142    };
    5461143
    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
     1148static unsigned int get_ordered2_dither(void)
     1149{
     1150    return ordered2_table[ordered2_index];
     1151}
     1152
     1153static 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};*/
     1165static unsigned int const *ordered4_table;
     1166static unsigned int ordered4_index;
     1167
     1168static 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
     1182static unsigned int get_ordered4_dither(void)
     1183{
     1184    return ordered4_table[ordered4_index];
     1185}
     1186
     1187static void increment_ordered4_dither(void)
     1188{
     1189    ordered4_index = (ordered4_index + 1) % 4;
     1190}
     1191
     1192/*
     1193 * Ordered 8 dithering
     1194 */
     1195static unsigned int const *ordered8_table;
     1196static unsigned int ordered8_index;
     1197
     1198static 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
     1216static unsigned int get_ordered8_dither(void)
     1217{
     1218    return ordered8_table[ordered8_index];
     1219}
     1220
     1221static void increment_ordered8_dither(void)
     1222{
     1223    ordered8_index = (ordered8_index + 1) % 8;
     1224}
     1225
     1226/*
     1227 * Random dithering
     1228 */
     1229static void init_random_dither(int line)
     1230{
     1231    ;
     1232}
     1233
     1234static unsigned int get_random_dither(void)
     1235{
     1236    return cucul_rand(0x00, 0xff);
     1237}
     1238
     1239static void increment_random_dither(void)
     1240{
     1241    return;
    8191242}
    8201243
     
    8841307#endif /* _DOXYGEN_SKIP_ME */
    8851308
    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  
    2929#include "cucul_internals.h"
    3030
    31 static void cucul_read_environment(cucul_t *);
    32 
    3331/** \brief Initialise a \e libcucul canvas.
    3432 *
     
    4846{
    4947    cucul_t *qq = malloc(sizeof(cucul_t));
    50 
    51     cucul_read_environment(qq);
    5248
    5349    qq->refcount = 0;
     
    202198}
    203199
    204 /** \brief Get the current value of a feature.
    205  *
    206  *  This function retrieves the value of an internal \e libcucul feature. A
    207  *  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 an
    211  *          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 antialiasing
    232  *  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 given
    234  *  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-readable
    275  *  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 
    301200/** \brief Uninitialise \e libcucul.
    302201 *
     
    381280 */
    382281
    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 #endif
    389 
    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 #endif
    427 }
    428 
    429282void _cucul_set_size(cucul_t *qq, unsigned int width, unsigned int height)
    430283{
  • libcaca/trunk/cucul/cucul.h

    r708 r711  
    3535enum cucul_color
    3636{
    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. */
    5356};
    54 
    55 /** \brief Internal features.
    56  *
    57  *  Internal libcaca features such as the rendering method or the dithering
    58  *  mode.
    59  */
    60 enum cucul_feature
    61 {
    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 macros
    89  */
    90 #if !defined(_DOXYGEN_SKIP_ME)
    91 #define caca_dithering cucul_feature
    92 #define caca_set_dithering caca_set_feature
    93 #define caca_get_dithering_name caca_get_feature_name
    94 #define CACA_DITHER_NONE    CUCUL_DITHERING_NONE
    95 #define CACA_DITHER_ORDERED CUCUL_DITHERING_ORDERED8
    96 #define CACA_DITHER_RANDOM  CUCUL_DITHERING_RANDOM
    97 #endif
    9857
    9958typedef struct cucul_context cucul_t;
     
    11069unsigned int cucul_get_width(cucul_t *);
    11170unsigned 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);
    11571void cucul_free(cucul_t *);
    11672/*  @} */
     
    210166                              unsigned int r[], unsigned int g[],
    211167                              unsigned int b[], unsigned int a[]);
     168void cucul_set_bitmap_brightness(struct cucul_bitmap *, float);
    212169void 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);
     170void cucul_set_bitmap_contrast(struct cucul_bitmap *, float);
     171void cucul_set_bitmap_invert(struct cucul_bitmap *, int);
     172void cucul_set_bitmap_antialias(struct cucul_bitmap *, int);
     173void cucul_set_bitmap_color(struct cucul_bitmap *, char const *);
     174char const * const * cucul_get_bitmap_color_list(struct cucul_bitmap const *);
     175void cucul_set_bitmap_charset(struct cucul_bitmap *, char const *);
     176char const * const * cucul_get_bitmap_charset_list(struct cucul_bitmap
     177                                                   const *);
     178void cucul_set_bitmap_dithering(struct cucul_bitmap *, char const *);
     179char const * const * cucul_get_bitmap_dithering_list(struct cucul_bitmap
     180                                                     const *);
     181void cucul_draw_bitmap(cucul_t *, int, int, int, int,
     182                       struct cucul_bitmap const *, void *);
    215183void cucul_free_bitmap(struct cucul_bitmap *);
    216184/*  @} */
  • libcaca/trunk/cucul/cucul_internals.h

    r678 r711  
    4444    enum cucul_color bgcolor;
    4545
    46     /* Internal libcucul features */
    47     enum cucul_feature background, antialiasing, dithering;
    48 
    4946    unsigned int refcount;
    5047};
  • libcaca/trunk/test/demo.c

    r710 r711  
    101101                    display_menu();
    102102                    break;
     103#if 0
    103104                case 'd':
    104105                case 'D':
     
    107108                    display_menu();
    108109                    break;
     110#endif
    109111                case 'c':
    110112                    demo = demo_color;
     
    218220    cucul_printf(qq, 4, 18, "'b': drawing boundaries: %s",
    219221                 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));
    222224
    223225    cucul_putstr(qq, 4, yo - 2, "'q': quit");
Note: See TracChangeset for help on using the changeset viewer.