"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. For more information about "attr.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.99.beta19_vs_0.99.beta20.

    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