source: libcaca/trunk/cucul/colour.c @ 1092

Last change on this file since 1092 was 1092, checked in by Sam Hocevar, 13 years ago
  • Implemented cucul_get_color().
  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1/*
2 *  libcucul      Canvas for ultrafast compositing of Unicode letters
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: colour.c 1092 2006-09-23 01:28:49Z sam $
7 *
8 *  This library is free software; you can redistribute it and/or
9 *  modify it under the terms of the Do What The Fuck You Want To
10 *  Public License, Version 2, as published by Sam Hocevar. See
11 *  http://sam.zoy.org/wtfpl/COPYING for more details.
12 */
13
14/*
15 *  This file contains functions for converting colour values between
16 *  various colourspaces.
17 */
18
19#include "config.h"
20#include "common.h"
21
22#if defined(HAVE_ERRNO_H)
23#   include <errno.h>
24#endif
25
26#include "cucul.h"
27#include "cucul_internals.h"
28
29/* RGB colours for the ANSI palette. There is no real standard, so we
30 * use the same values as gnome-terminal. The 7th colour (brown) is a bit
31 * special. */
32static const uint16_t ansitab[16] =
33{
34    0xf000, 0xf00a, 0xf0a0, 0xf0aa, 0xfa00, 0xfa0a, 0xfa50, 0xfaaa,
35    0xf555, 0xf55f, 0xf5f5, 0xf5ff, 0xff55, 0xff5f, 0xfff5, 0xffff,
36};
37
38/** \brief Set the default colour pair.
39 *
40 *  This function sets the default ANSI colour pair. String functions such as
41 *  caca_printf() and graphical primitive functions such as caca_draw_line()
42 *  will use these colours.
43 *
44 *  Color values are those defined in cucul.h, such as CUCUL_COLOR_RED
45 *  or CUCUL_COLOR_TRANSPARENT.
46 *
47 *  If an error occurs, -1 is returned and \b errno is set accordingly:
48 *  - \c EINVAL At least one of the colour values is invalid.
49 *
50 *  \param cv A handle to the libcucul canvas.
51 *  \param fg The requested foreground colour.
52 *  \param bg The requested background colour.
53 *  \return 0 in case of success, -1 if an error occurred.
54 */
55int cucul_set_color(cucul_canvas_t *cv, unsigned char fg, unsigned char bg)
56{
57    if(fg > 0x20 || bg > 0x20)
58    {
59#if defined(HAVE_ERRNO_H)
60        errno = EINVAL;
61#endif
62        return -1;
63    }
64
65    cv->fgcolor = fg;
66    cv->bgcolor = bg;
67
68    return 0;
69}
70
71/** \brief Set the default colour pair (truecolor version).
72 *
73 *  This function sets the default colour pair. String functions such as
74 *  caca_printf() and graphical primitive functions such as caca_draw_line()
75 *  will use these colours.
76 *
77 *  Colors are 16-bit ARGB values, each component being coded on 4 bits. For
78 *  instance, 0xf088 is solid dark cyan (A=15 R=0 G=8 B=8), and 0x8fff is
79 *  white with 50% alpha (A=8 R=15 G=15 B=15).
80 *
81 *  If an error occurs, -1 is returned and \b errno is set accordingly:
82 *  - \c EINVAL At least one of the colour values is invalid.
83 *
84 *  \param cv A handle to the libcucul canvas.
85 *  \param fg The requested foreground colour.
86 *  \param bg The requested background colour.
87 *  \return 0 in case of success, -1 if an error occurred.
88 */
89int cucul_set_truecolor(cucul_canvas_t *cv, unsigned int fg, unsigned int bg)
90{
91    if(fg > 0xffff || bg > 0xffff)
92    {
93#if defined(HAVE_ERRNO_H)
94        errno = EINVAL;
95#endif
96        return -1;
97    }
98
99    if(fg < 0x100)
100        fg += 0x100;
101
102    if(bg < 0x100)
103        bg += 0x100;
104
105    cv->fgcolor = fg;
106    cv->bgcolor = bg;
107
108    return 0;
109}
110
111/** \brief Get the colour pair at the given coordinates.
112 *
113 *  This function gets the internal \e libcucul colour pair value of the
114 *  character at the given coordinates. The colour pair value has 32
115 *  significant bits: the lower 16 are for the foreground colour, the higher
116 *  16 are for the background.
117 *
118 *  If the coordinates are outside the canvas boundaries, the current colour
119 *  pair is returned.
120 *
121 *  This function never fails.
122 *
123 *  \param cv A handle to the libcucul canvas.
124 *  \param x X coordinate.
125 *  \param y Y coordinate.
126 *  \param ch The requested colour pair value.
127 *  \return The character always returns 0.
128 */
129unsigned long int cucul_get_color(cucul_canvas_t *cv, int x, int y)
130{
131    if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height)
132        return ((uint32_t)cv->bgcolor << 16) | (uint32_t)cv->fgcolor;
133
134    return (unsigned long int)cv->attr[x + y * cv->width];
135}
136
137
138/*
139 * XXX: the following functions are local
140 */
141
142static uint8_t nearest_ansi(uint16_t argb16, uint8_t def)
143{
144    unsigned int i, best, dist;
145
146    if(argb16 < CUCUL_COLOR_DEFAULT)
147        return argb16;
148
149    if(argb16 == CUCUL_COLOR_DEFAULT || argb16 == CUCUL_COLOR_TRANSPARENT)
150        return def;
151
152    if(argb16 < 0x5fff) /* too transparent, return default colour */
153        return def;
154
155    best = def;
156    dist = 0xffff;
157    for(i = 0; i < 16; i++)
158    {
159        unsigned int d = 0;
160        int a, b;
161
162        a = (ansitab[i] >> 8) & 0xf;
163        b = (argb16 >> 8) & 0xf;
164        d += (a - b) * (a - b);
165
166        a = (ansitab[i] >> 4) & 0xf;
167        b = (argb16 >> 4) & 0xf;
168        d += (a - b) * (a - b);
169
170        a = ansitab[i] & 0xf;
171        b = argb16 & 0xf;
172        d += (a - b) * (a - b);
173
174        if(d < dist)
175        {
176            dist = d;
177            best = i;
178        }
179    }
180
181    return best;
182}
183
184uint8_t _cucul_argb32_to_ansi8(uint32_t ch)
185{
186    uint16_t fg = ch & 0xffff;
187    uint16_t bg = ch >> 16;
188
189    return nearest_ansi(fg, CUCUL_COLOR_LIGHTGRAY)
190            | (nearest_ansi(bg, CUCUL_COLOR_BLACK) << 4);
191}
192
193uint8_t _cucul_argb32_to_ansi4fg(uint32_t ch)
194{
195    return nearest_ansi(ch & 0xffff, CUCUL_COLOR_LIGHTGRAY);
196}
197
198uint8_t _cucul_argb32_to_ansi4bg(uint32_t ch)
199{
200    return nearest_ansi(ch >> 16, CUCUL_COLOR_BLACK);
201}
202
203uint16_t _cucul_argb32_to_rgb12fg(uint32_t ch)
204{
205    uint16_t fg = ch & 0xffff;
206
207    if(fg < CUCUL_COLOR_DEFAULT)
208        return ansitab[fg] & 0x0fff;
209
210    if(fg == CUCUL_COLOR_DEFAULT)
211        return ansitab[CUCUL_COLOR_LIGHTGRAY] & 0x0fff;
212
213    if(fg == CUCUL_COLOR_TRANSPARENT)
214        return ansitab[CUCUL_COLOR_LIGHTGRAY] & 0x0fff;
215
216    return fg & 0x0fff;
217}
218
219uint16_t _cucul_argb32_to_rgb12bg(uint32_t ch)
220{
221    uint16_t bg = ch >> 16;
222
223    if(bg < CUCUL_COLOR_DEFAULT)
224        return ansitab[bg] & 0x0fff;
225
226    if(bg == CUCUL_COLOR_DEFAULT)
227        return ansitab[CUCUL_COLOR_BLACK] & 0x0fff;
228
229    if(bg == CUCUL_COLOR_TRANSPARENT)
230        return ansitab[CUCUL_COLOR_BLACK] & 0x0fff;
231
232    return bg & 0x0fff;
233}
234
235#define RGB12TO24(i) \
236   (((uint32_t)((i & 0xf00) >> 8) * 0x110000) \
237  | ((uint32_t)((i & 0x0f0) >> 4) * 0x001100) \
238  | ((uint32_t)(i & 0x00f) * 0x000011))
239
240uint32_t _cucul_argb32_to_rgb24fg(uint32_t ch)
241{
242    return RGB12TO24(_cucul_argb32_to_rgb12fg(ch));
243}
244
245uint32_t _cucul_argb32_to_rgb24bg(uint32_t ch)
246{
247    return RGB12TO24(_cucul_argb32_to_rgb12bg(ch));
248}
249
250void _cucul_argb32_to_argb4(uint32_t ch, uint8_t argb[8])
251{
252    uint16_t fg = ch & 0xffff;
253    uint16_t bg = ch >> 16;
254
255    if(fg < CUCUL_COLOR_DEFAULT)
256        fg = ansitab[fg];
257    else if(fg == CUCUL_COLOR_DEFAULT)
258        fg = ansitab[CUCUL_COLOR_LIGHTGRAY];
259    else if(fg == CUCUL_COLOR_TRANSPARENT)
260        fg = 0x0fff;
261
262    if(bg < CUCUL_COLOR_DEFAULT)
263        bg = ansitab[bg];
264    else if(bg == CUCUL_COLOR_DEFAULT)
265        bg = ansitab[CUCUL_COLOR_BLACK];
266    else if(bg == CUCUL_COLOR_TRANSPARENT)
267        bg = 0x0fff;
268
269    argb[0] = bg >> 12;
270    argb[1] = (bg >> 8) & 0xf;
271    argb[2] = (bg >> 4) & 0xf;
272    argb[3] = bg & 0xf;
273
274    argb[4] = fg >> 12;
275    argb[5] = (fg >> 8) & 0xf;
276    argb[6] = (fg >> 4) & 0xf;
277    argb[7] = fg & 0xf;
278}
279
Note: See TracBrowser for help on using the repository browser.