"Fossies" - the Fresh Open Source Software Archive

Member "libcaca-0.99.beta20/caca/attr.c" (22 May 2018, 16837 Bytes) of package /linux/privat/libcaca-0.99.beta20.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  *  libcaca     Colour ASCII-Art library
    3  *  Copyright © 2002—2018 Sam Hocevar <sam@hocevar.net>
    4  *              All Rights Reserved
    5  *
    6  *  This library is free software. It comes without any warranty, to
    7  *  the extent permitted by applicable law. You can redistribute it
    8  *  and/or modify it under the terms of the Do What the Fuck You Want
    9  *  to Public License, Version 2, as published by Sam Hocevar. See
   10  *  http://www.wtfpl.net/ for more details.
   11  */
   12 
   13 /*
   14  *  This file contains functions for attribute management and colourspace
   15  *  conversions.
   16  */
   17 
   18 #include "config.h"
   19 
   20 #include "caca.h"
   21 #include "caca_internals.h"
   22 
   23 static uint8_t nearest_ansi(uint16_t);
   24 
   25 /* RGB colours for the ANSI palette. There is no real standard, so we
   26  * use the same values as gnome-terminal. The 7th colour (brown) is a bit
   27  * special: 0xfa50 instead of 0xfaa0. */
   28 static const uint16_t ansitab16[16] =
   29 {
   30     0xf000, 0xf00a, 0xf0a0, 0xf0aa, 0xfa00, 0xfa0a, 0xfa50, 0xfaaa,
   31     0xf555, 0xf55f, 0xf5f5, 0xf5ff, 0xff55, 0xff5f, 0xfff5, 0xffff,
   32 };
   33 
   34 /* Same table, except on 14 bits (3-4-4-3) */
   35 static const uint16_t ansitab14[16] =
   36 {
   37     0x3800, 0x3805, 0x3850, 0x3855, 0x3d00, 0x3d05, 0x3d28, 0x3d55,
   38     0x3aaa, 0x3aaf, 0x3afa, 0x3aff, 0x3faa, 0x3faf, 0x3ffa, 0x3fff,
   39 };
   40 
   41 /** \brief Get the text attribute at the given coordinates.
   42  *
   43  *  Get the internal \e libcaca attribute value of the character at the
   44  *  given coordinates. The attribute value has 32 significant bits,
   45  *  organised as follows from MSB to LSB:
   46  *  - 3 bits for the background alpha
   47  *  - 4 bits for the background red component
   48  *  - 4 bits for the background green component
   49  *  - 3 bits for the background blue component
   50  *  - 3 bits for the foreground alpha
   51  *  - 4 bits for the foreground red component
   52  *  - 4 bits for the foreground green component
   53  *  - 3 bits for the foreground blue component
   54  *  - 4 bits for the bold, italics, underline and blink flags
   55  *
   56  *  If the coordinates are outside the canvas boundaries, the current
   57  *  attribute is returned.
   58  *
   59  *  This function never fails.
   60  *
   61  *  \param cv A handle to the libcaca canvas.
   62  *  \param x X coordinate.
   63  *  \param y Y coordinate.
   64  *  \return The requested attribute.
   65  */
   66 uint32_t caca_get_attr(caca_canvas_t const *cv, int x, int y)
   67 {
   68     if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height)
   69         return cv->curattr;
   70 
   71     return cv->attrs[x + y * cv->width];
   72 }
   73 
   74 /** \brief Set the default character attribute.
   75  *
   76  *  Set the default character attribute for drawing. Attributes define
   77  *  foreground and background colour, transparency, bold, italics and
   78  *  underline styles, as well as blink. String functions such as
   79  *  caca_printf() and graphical primitive functions such as caca_draw_line()
   80  *  will use this attribute.
   81  *
   82  *  The value of \e attr is either:
   83  *  - a 32-bit integer as returned by caca_get_attr(), in which case it
   84  *    also contains colour information,
   85  *  - a combination (bitwise OR) of style values (\e CACA_UNDERLINE,
   86  *    \e CACA_BLINK, \e CACA_BOLD and \e CACA_ITALICS), in which case
   87  *    setting the attribute does not modify the current colour information.
   88  *
   89  *  To retrieve the current attribute value, use caca_get_attr(-1,-1).
   90  *
   91  *  This function never fails.
   92  *
   93  *  \param cv A handle to the libcaca canvas.
   94  *  \param attr The requested attribute value.
   95  *  \return This function always returns 0.
   96  */
   97 int caca_set_attr(caca_canvas_t *cv, uint32_t attr)
   98 {
   99     if(attr < 0x00000010)
  100         attr = (cv->curattr & 0xfffffff0) | attr;
  101 
  102     cv->curattr = attr;
  103 
  104     return 0;
  105 }
  106 
  107 /** \brief Unset flags in the default character attribute.
  108  *
  109  *  Unset flags in the default character attribute for drawing. Attributes
  110  *  define foreground and background colour, transparency, bold, italics and
  111  *  underline styles, as well as blink. String functions such as
  112  *  caca_printf() and graphical primitive functions such as caca_draw_line()
  113  *  will use this attribute.
  114  *
  115  *  The value of \e attr is a combination (bitwise OR) of style values
  116  *  (\e CACA_UNDERLINE, \e CACA_BLINK, \e CACA_BOLD and \e CACA_ITALICS).
  117  *  Unsetting these attributes does not modify the current colour information.
  118  *
  119  *  To retrieve the current attribute value, use caca_get_attr(-1,-1).
  120  *
  121  *  This function never fails.
  122  *
  123  *  \param cv A handle to the libcaca canvas.
  124  *  \param attr The requested attribute values to unset.
  125  *  \return This function always returns 0.
  126  */
  127 int caca_unset_attr(caca_canvas_t *cv, uint32_t attr)
  128 {
  129     cv->curattr &= ~(attr & 0x0000000f);
  130 
  131     return 0;
  132 }
  133 
  134 /** \brief Toggle flags in the default character attribute.
  135  *
  136  *  Toggle flags in the default character attribute for drawing. Attributes
  137  *  define foreground and background colour, transparency, bold, italics and
  138  *  underline styles, as well as blink. String functions such as
  139  *  caca_printf() and graphical primitive functions such as caca_draw_line()
  140  *  will use this attribute.
  141  *
  142  *  The value of \e attr is a combination (bitwise OR) of style values
  143  *  (\e CACA_UNDERLINE, \e CACA_BLINK, \e CACA_BOLD and \e CACA_ITALICS).
  144  *  Toggling these attributes does not modify the current colour information.
  145  *
  146  *  To retrieve the current attribute value, use caca_get_attr(-1,-1).
  147  *
  148  *  This function never fails.
  149  *
  150  *  \param cv A handle to the libcaca canvas.
  151  *  \param attr The requested attribute values to toggle.
  152  *  \return This function always returns 0.
  153  */
  154 int caca_toggle_attr(caca_canvas_t *cv, uint32_t attr)
  155 {
  156     cv->curattr ^= attr & 0x0000000f;
  157 
  158     return 0;
  159 }
  160 
  161 /** \brief Set the character attribute at the given coordinates.
  162  *
  163  *  Set the character attribute, without changing the character's value. If
  164  *  the character at the given coordinates is a fullwidth character, both
  165  *  cells' attributes are replaced.
  166  *
  167  *  The value of \e attr is either:
  168  *  - a 32-bit integer as returned by caca_get_attr(), in which case it
  169  *    also contains colour information,
  170  *  - a combination (bitwise OR) of style values (\e CACA_UNDERLINE,
  171  *    \e CACA_BLINK, \e CACA_BOLD and \e CACA_ITALICS), in which case
  172  *    setting the attribute does not modify the current colour information.
  173  *
  174  *  This function never fails.
  175  *
  176  *  \param cv A handle to the libcaca canvas.
  177  *  \param x X coordinate.
  178  *  \param y Y coordinate.
  179  *  \param attr The requested attribute value.
  180  *  \return This function always returns 0.
  181  */
  182 int caca_put_attr(caca_canvas_t *cv, int x, int y, uint32_t attr)
  183 {
  184     uint32_t *curattr, *curchar;
  185     int xmin, xmax;
  186 
  187     if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height)
  188         return 0;
  189 
  190     xmin = xmax = x;
  191 
  192     curchar = cv->chars + x + y * cv->width;
  193     curattr = cv->attrs + x + y * cv->width;
  194 
  195     if(attr < 0x00000010)
  196         curattr[0] = (curattr[0] & 0xfffffff0) | attr;
  197     else
  198         curattr[0] = attr;
  199 
  200     if(x && curchar[0] == CACA_MAGIC_FULLWIDTH)
  201     {
  202         curattr[-1] = curattr[0];
  203         xmin--;
  204     }
  205     else if(x + 1 < (int)cv->width && curchar[1] == CACA_MAGIC_FULLWIDTH)
  206     {
  207         curattr[1] = curattr[0];
  208         xmax++;
  209     }
  210 
  211     if(!cv->dirty_disabled)
  212         caca_add_dirty_rect(cv, xmin, y, xmax - xmin + 1, 1);
  213 
  214     return 0;
  215 }
  216 
  217 /** \brief Set the default colour pair for text (ANSI version).
  218  *
  219  *  Set the default ANSI colour pair for text drawing. String functions such
  220  *  as caca_printf() and graphical primitive functions such as caca_draw_line()
  221  *  will use these attributes.
  222  *
  223  *  Color values are those defined in caca.h, such as CACA_RED
  224  *  or CACA_TRANSPARENT.
  225  *
  226  *  If an error occurs, -1 is returned and \b errno is set accordingly:
  227  *  - \c EINVAL At least one of the colour values is invalid.
  228  *
  229  *  \param cv A handle to the libcaca canvas.
  230  *  \param fg The requested ANSI foreground colour.
  231  *  \param bg The requested ANSI background colour.
  232  *  \return 0 in case of success, -1 if an error occurred.
  233  */
  234 int caca_set_color_ansi(caca_canvas_t *cv, uint8_t fg, uint8_t bg)
  235 {
  236     uint32_t attr;
  237 
  238     if(fg > 0x20 || bg > 0x20)
  239     {
  240         seterrno(EINVAL);
  241         return -1;
  242     }
  243 
  244     attr = ((uint32_t)(bg | 0x40) << 18) | ((uint32_t)(fg | 0x40) << 4);
  245     cv->curattr = (cv->curattr & 0x0000000f) | attr;
  246 
  247     return 0;
  248 }
  249 
  250 /** \brief Set the default colour pair for text (truecolor version).
  251  *
  252  *  Set the default ARGB colour pair for text drawing. String functions such
  253  *  as caca_printf() and graphical primitive functions such as caca_draw_line()
  254  *  will use these attributes.
  255  *
  256  *  Colors are 16-bit ARGB values, each component being coded on 4 bits. For
  257  *  instance, 0xf088 is solid dark cyan (A=15 R=0 G=8 B=8), and 0x8fff is
  258  *  white with 50% alpha (A=8 R=15 G=15 B=15).
  259  *
  260  *  This function never fails.
  261  *
  262  *  \param cv A handle to the libcaca canvas.
  263  *  \param fg The requested ARGB foreground colour.
  264  *  \param bg The requested ARGB background colour.
  265  *  \return This function always returns 0.
  266  */
  267 int caca_set_color_argb(caca_canvas_t *cv, uint16_t fg, uint16_t bg)
  268 {
  269     uint32_t attr;
  270 
  271     if(fg < 0x100)
  272         fg += 0x100;
  273 
  274     if(bg < 0x100)
  275         bg += 0x100;
  276 
  277     fg = ((fg >> 1) & 0x7ff) | ((fg >> 13) << 11);
  278     bg = ((bg >> 1) & 0x7ff) | ((bg >> 13) << 11);
  279 
  280     attr = ((uint32_t)bg << 18) | ((uint32_t)fg << 4);
  281     cv->curattr = (cv->curattr & 0x0000000f) | attr;
  282 
  283     return 0;
  284 }
  285 
  286 /** \brief Get DOS ANSI information from attribute.
  287  *
  288  *  Get the ANSI colour pair for a given attribute. The returned value is
  289  *  an 8-bit value whose higher 4 bits are the background colour and lower
  290  *  4 bits are the foreground colour.
  291  *
  292  *  If the attribute has ARGB colours, the nearest colour is used. Special
  293  *  attributes such as \e CACA_DEFAULT and \e CACA_TRANSPARENT are not
  294  *  handled and are both replaced with \e CACA_LIGHTGRAY for the foreground
  295  *  colour and \e CACA_BLACK for the background colour.
  296  *
  297  *  This function never fails. If the attribute value is outside the expected
  298  *  32-bit range, higher order bits are simply ignored.
  299  *
  300  *  \param attr The requested attribute value.
  301  *  \return The corresponding DOS ANSI value.
  302  */
  303 uint8_t caca_attr_to_ansi(uint32_t attr)
  304 {
  305     uint8_t fg = nearest_ansi((attr >> 4) & 0x3fff);
  306     uint8_t bg = nearest_ansi(attr >> 18);
  307 
  308     return (fg < 0x10 ? fg : CACA_LIGHTGRAY)
  309             | ((bg < 0x10 ? bg : CACA_BLACK) << 4);
  310 }
  311 
  312 /** \brief Get ANSI foreground information from attribute.
  313  *
  314  *  Get the ANSI foreground colour value for a given attribute. The returned
  315  *  value is either one of the \e CACA_RED, \e CACA_BLACK etc. predefined
  316  *  colours, or the special value \e CACA_DEFAULT meaning the media's
  317  *  default foreground value, or the special value \e CACA_TRANSPARENT.
  318  *
  319  *  If the attribute has ARGB colours, the nearest colour is returned.
  320  *
  321  *  This function never fails. If the attribute value is outside the expected
  322  *  32-bit range, higher order bits are simply ignored.
  323  *
  324  *  \param attr The requested attribute value.
  325  *  \return The corresponding ANSI foreground value.
  326  */
  327 uint8_t caca_attr_to_ansi_fg(uint32_t attr)
  328 {
  329     return nearest_ansi((attr >> 4) & 0x3fff);
  330 }
  331 
  332 /** \brief Get ANSI background information from attribute.
  333  *
  334  *  Get the ANSI background colour value for a given attribute. The returned
  335  *  value is either one of the \e CACA_RED, \e CACA_BLACK etc. predefined
  336  *  colours, or the special value \e CACA_DEFAULT meaning the media's
  337  *  default background value, or the special value \e CACA_TRANSPARENT.
  338  *
  339  *  If the attribute has ARGB colours, the nearest colour is returned.
  340  *
  341  *  This function never fails. If the attribute value is outside the expected
  342  *  32-bit range, higher order bits are simply ignored.
  343  *
  344  *  \param attr The requested attribute value.
  345  *  \return The corresponding ANSI background value.
  346  */
  347 uint8_t caca_attr_to_ansi_bg(uint32_t attr)
  348 {
  349     return nearest_ansi(attr >> 18);
  350 }
  351 
  352 /** \brief Get 12-bit RGB foreground information from attribute.
  353  *
  354  *  Get the 12-bit foreground colour value for a given attribute. The returned
  355  *  value is a native-endian encoded integer with each red, green and blue
  356  *  values encoded on 8 bits in the following order:
  357  *   - 8-11 most significant bits: red
  358  *   - 4-7 most significant bits: green
  359  *   - least significant bits: blue
  360  *
  361  *  This function never fails. If the attribute value is outside the expected
  362  *  32-bit range, higher order bits are simply ignored.
  363  *
  364  *  \param attr The requested attribute value.
  365  *  \return The corresponding 12-bit RGB foreground value.
  366  */
  367 uint16_t caca_attr_to_rgb12_fg(uint32_t attr)
  368 {
  369     uint16_t fg = (attr >> 4) & 0x3fff;
  370 
  371     if(fg < (0x10 | 0x40))
  372         return ansitab16[fg ^ 0x40] & 0x0fff;
  373 
  374     if(fg == (CACA_DEFAULT | 0x40))
  375         return ansitab16[CACA_LIGHTGRAY] & 0x0fff;
  376 
  377     if(fg == (CACA_TRANSPARENT | 0x40))
  378         return ansitab16[CACA_LIGHTGRAY] & 0x0fff;
  379 
  380     return (fg << 1) & 0x0fff;
  381 }
  382 
  383 /** \brief Get 12-bit RGB background information from attribute.
  384  *
  385  *  Get the 12-bit background colour value for a given attribute. The returned
  386  *  value is a native-endian encoded integer with each red, green and blue
  387  *  values encoded on 8 bits in the following order:
  388  *   - 8-11 most significant bits: red
  389  *   - 4-7 most significant bits: green
  390  *   - least significant bits: blue
  391  *
  392  *  This function never fails. If the attribute value is outside the expected
  393  *  32-bit range, higher order bits are simply ignored.
  394  *
  395  *  \param attr The requested attribute value.
  396  *  \return The corresponding 12-bit RGB background value.
  397  */
  398 uint16_t caca_attr_to_rgb12_bg(uint32_t attr)
  399 {
  400     uint16_t bg = attr >> 18;
  401 
  402     if(bg < (0x10 | 0x40))
  403         return ansitab16[bg ^ 0x40] & 0x0fff;
  404 
  405     if(bg == (CACA_DEFAULT | 0x40))
  406         return ansitab16[CACA_BLACK] & 0x0fff;
  407 
  408     if(bg == (CACA_TRANSPARENT | 0x40))
  409         return ansitab16[CACA_BLACK] & 0x0fff;
  410 
  411     return (bg << 1) & 0x0fff;
  412 }
  413 
  414 /** \brief Get 64-bit ARGB information from attribute.
  415  *
  416  *  Get the 64-bit colour and alpha values for a given attribute. The values
  417  *  are written as 8-bit integers in the \e argb array in the following order:
  418  *   - \e argb[0]: background alpha value
  419  *   - \e argb[1]: background red value
  420  *   - \e argb[2]: background green value
  421  *   - \e argb[3]: background blue value
  422  *   - \e argb[4]: foreground alpha value
  423  *   - \e argb[5]: foreground red value
  424  *   - \e argb[6]: foreground green value
  425  *   - \e argb[7]: foreground blue value
  426  *
  427  *  This function never fails. If the attribute value is outside the expected
  428  *  32-bit range, higher order bits are simply ignored.
  429  *
  430  *  \param attr The requested attribute value.
  431  *  \param argb An array of 8-bit integers.
  432  */
  433 void caca_attr_to_argb64(uint32_t attr, uint8_t argb[8])
  434 {
  435     uint16_t fg = (attr >> 4) & 0x3fff;
  436     uint16_t bg = attr >> 18;
  437 
  438     if(bg < (0x10 | 0x40))
  439         bg = ansitab16[bg ^ 0x40];
  440     else if(bg == (CACA_DEFAULT | 0x40))
  441         bg = ansitab16[CACA_BLACK];
  442     else if(bg == (CACA_TRANSPARENT | 0x40))
  443         bg = 0x0fff;
  444     else
  445         bg = ((bg << 2) & 0xf000) | ((bg << 1) & 0x0fff);
  446 
  447     argb[0] = bg >> 12;
  448     argb[1] = (bg >> 8) & 0xf;
  449     argb[2] = (bg >> 4) & 0xf;
  450     argb[3] = bg & 0xf;
  451 
  452     if(fg < (0x10 | 0x40))
  453         fg = ansitab16[fg ^ 0x40];
  454     else if(fg == (CACA_DEFAULT | 0x40))
  455         fg = ansitab16[CACA_LIGHTGRAY];
  456     else if(fg == (CACA_TRANSPARENT | 0x40))
  457         fg = 0x0fff;
  458     else
  459         fg = ((fg << 2) & 0xf000) | ((fg << 1) & 0x0fff);
  460 
  461     argb[4] = fg >> 12;
  462     argb[5] = (fg >> 8) & 0xf;
  463     argb[6] = (fg >> 4) & 0xf;
  464     argb[7] = fg & 0xf;
  465 }
  466 
  467 /*
  468  * XXX: the following functions are local
  469  */
  470 
  471 static uint8_t nearest_ansi(uint16_t argb14)
  472 {
  473     unsigned int i, best, dist;
  474 
  475     if(argb14 < (0x10 | 0x40))
  476         return argb14 ^ 0x40;
  477 
  478     if(argb14 == (CACA_DEFAULT | 0x40) || argb14 == (CACA_TRANSPARENT | 0x40))
  479         return argb14 ^ 0x40;
  480 
  481     if(argb14 < 0x0fff) /* too transparent */
  482         return CACA_TRANSPARENT;
  483 
  484     best = CACA_DEFAULT;
  485     dist = 0x3fff;
  486     for(i = 0; i < 16; i++)
  487     {
  488         unsigned int d = 0;
  489         int a, b;
  490 
  491         a = (ansitab14[i] >> 7) & 0xf;
  492         b = (argb14 >> 7) & 0xf;
  493         d += (a - b) * (a - b);
  494 
  495         a = (ansitab14[i] >> 3) & 0xf;
  496         b = (argb14 >> 3) & 0xf;
  497         d += (a - b) * (a - b);
  498 
  499         a = (ansitab14[i] << 1) & 0xf;
  500         b = (argb14 << 1) & 0xf;
  501         d += (a - b) * (a - b);
  502 
  503         if(d < dist)
  504         {
  505             dist = d;
  506             best = i;
  507         }
  508     }
  509 
  510     return best;
  511 }
  512 
  513 #define RGB12TO24(i) \
  514    (((uint32_t)((i & 0xf00) >> 8) * 0x110000) \
  515   | ((uint32_t)((i & 0x0f0) >> 4) * 0x001100) \
  516   | ((uint32_t)(i & 0x00f) * 0x000011))
  517 
  518 uint32_t _caca_attr_to_rgb24fg(uint32_t attr)
  519 {
  520     return RGB12TO24(caca_attr_to_rgb12_fg(attr));
  521 }
  522 
  523 uint32_t _caca_attr_to_rgb24bg(uint32_t attr)
  524 {
  525     return RGB12TO24(caca_attr_to_rgb12_bg(attr));
  526 }
  527