1/* pango
2 * pango-color.c: Color handling
3 *
4 * Copyright (C) 2000 Red Hat Software
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include "config.h"
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "pango-attributes.h"
28#include "pango-impl-utils.h"
29#include "pango-utils-internal.h"
30
31G_DEFINE_BOXED_TYPE (PangoColor, pango_color,
32 pango_color_copy,
33 pango_color_free);
34
35/**
36 * pango_color_copy:
37 * @src: (nullable): color to copy
38 *
39 * Creates a copy of @src.
40 *
41 * The copy should be freed with [method@Pango.Color.free].
42 * Primarily used by language bindings, not that useful
43 * otherwise (since colors can just be copied by assignment
44 * in C).
45 *
46 * Return value: (nullable): the newly allocated `PangoColor`,
47 * which should be freed with [method@Pango.Color.free]
48 */
49PangoColor*
50pango_color_copy (const PangoColor *src)
51{
52 PangoColor *ret;
53
54 if (src == NULL)
55 return NULL;
56
57 ret = g_slice_new (PangoColor);
58
59 *ret = *src;
60
61 return ret;
62}
63
64/**
65 * pango_color_free:
66 * @color: (nullable): an allocated `PangoColor`
67 *
68 * Frees a color allocated by [method@Pango.Color.copy].
69 */
70void
71pango_color_free (PangoColor *color)
72{
73 if (color == NULL)
74 return;
75
76 g_slice_free (PangoColor, color);
77}
78
79/**
80 * pango_color_to_string:
81 * @color: a `PangoColor`
82 *
83 * Returns a textual specification of @color.
84 *
85 * The string is in the hexadecimal form `#rrrrggggbbbb`,
86 * where `r`, `g` and `b` are hex digits representing the
87 * red, green, and blue components respectively.
88 *
89 * Return value: a newly-allocated text string that must
90 * be freed with g_free().
91 *
92 * Since: 1.16
93 */
94gchar *
95pango_color_to_string (const PangoColor *color)
96{
97 g_return_val_if_fail (color != NULL, NULL);
98
99 return g_strdup_printf (format: "#%04x%04x%04x", color->red, color->green, color->blue);
100}
101
102/* Color parsing
103 */
104
105/* The following 2 routines (parse_color, find_color) come from Tk, via the Win32
106 * port of GDK. The licensing terms on these (longer than the functions) is:
107 *
108 * This software is copyrighted by the Regents of the University of
109 * California, Sun Microsystems, Inc., and other parties. The following
110 * terms apply to all files associated with the software unless explicitly
111 * disclaimed in individual files.
112 *
113 * The authors hereby grant permission to use, copy, modify, distribute,
114 * and license this software and its documentation for any purpose, provided
115 * that existing copyright notices are retained in all copies and that this
116 * notice is included verbatim in any distributions. No written agreement,
117 * license, or royalty fee is required for any of the authorized uses.
118 * Modifications to this software may be copyrighted by their authors
119 * and need not follow the licensing terms described here, provided that
120 * the new terms are clearly indicated on the first page of each file where
121 * they apply.
122 *
123 * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
124 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
125 * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
126 * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
127 * POSSIBILITY OF SUCH DAMAGE.
128 *
129 * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
130 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
131 * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
132 * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
133 * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
134 * MODIFICATIONS.
135 *
136 * GOVERNMENT USE: If you are acquiring this software on behalf of the
137 * U.S. government, the Government shall have only "Restricted Rights"
138 * in the software and related documentation as defined in the Federal
139 * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
140 * are acquiring the software on behalf of the Department of Defense, the
141 * software shall be classified as "Commercial Computer Software" and the
142 * Government shall have only "Restricted Rights" as defined in Clause
143 * 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
144 * authors grant the U.S. Government and others acting in its behalf
145 * permission to use and distribute the software in accordance with the
146 * terms specified in this license.
147 */
148
149#include "pango-color-table.h"
150
151#define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z')
152#define TOLOWER(c) (ISUPPER (c) ? (c) - 'A' + 'a' : (c))
153
154static int
155compare_xcolor_entries (const void *a, const void *b)
156{
157 const guchar *s1 = (const guchar *) a;
158 const guchar *s2 = (const guchar *) (color_names + ((const ColorEntry *) b)->name_offset);
159
160 while (*s1 && *s2)
161 {
162 int c1, c2;
163 while (*s1 == ' ') s1++;
164 while (*s2 == ' ') s1++;
165 c1 = (gint)(guchar) TOLOWER (*s1);
166 c2 = (gint)(guchar) TOLOWER (*s2);
167 if (c1 != c2)
168 return (c1 - c2);
169 s1++; s2++;
170 }
171
172 return ((gint) *s1) - ((gint) *s2);
173}
174
175static gboolean
176find_color(const char *name,
177 PangoColor *color)
178{
179 ColorEntry *found;
180
181 found = bsearch (key: name, base: color_entries, G_N_ELEMENTS (color_entries),
182 size: sizeof (ColorEntry),
183 compar: compare_xcolor_entries);
184 if (found == NULL)
185 return FALSE;
186
187 if (color)
188 {
189 color->red = (found->red * 65535) / 255;
190 color->green = (found->green * 65535) / 255;
191 color->blue = (found->blue * 65535) / 255;
192 }
193
194 return TRUE;
195}
196
197static gboolean
198hex (const char *spec,
199 int len,
200 unsigned int *c)
201{
202 const char *end;
203 *c = 0;
204 for (end = spec + len; spec != end; spec++)
205 if (g_ascii_isxdigit (*spec))
206 *c = (*c << 4) | g_ascii_xdigit_value (c: *spec);
207 else
208 return FALSE;
209 return TRUE;
210}
211
212
213/**
214 * pango_color_parse_with_alpha:
215 * @color: (nullable): a `PangoColor` structure in which
216 * to store the result
217 * @alpha: (out) (optional): return location for alpha
218 * @spec: a string specifying the new color
219 *
220 * Fill in the fields of a color from a string specification.
221 *
222 * The string can either one of a large set of standard names.
223 * (Taken from the CSS Color [specification](https://www.w3.org/TR/css-color-4/#named-colors),
224 * or it can be a hexadecimal value in the form `#rgb`,
225 * `#rrggbb`, `#rrrgggbbb` or `#rrrrggggbbbb` where `r`, `g`
226 * and `b` are hex digits of the red, green, and blue components
227 * of the color, respectively. (White in the four forms is
228 * `#fff`, `#ffffff`, `#fffffffff` and `#ffffffffffff`.)
229 *
230 * Additionally, parse strings of the form `#rgba`, `#rrggbbaa`,
231 * `#rrrrggggbbbbaaaa`, if @alpha is not %NULL, and set @alpha
232 * to the value specified by the hex digits for `a`. If no alpha
233 * component is found in @spec, @alpha is set to 0xffff (for a
234 * solid color).
235 *
236 * Return value: %TRUE if parsing of the specifier succeeded,
237 * otherwise %FALSE
238 *
239 * Since: 1.46
240 */
241gboolean
242pango_color_parse_with_alpha (PangoColor *color,
243 guint16 *alpha,
244 const char *spec)
245{
246 g_return_val_if_fail (spec != NULL, FALSE);
247
248 if (alpha)
249 *alpha = 0xffff;
250
251 if (spec[0] == '#')
252 {
253 size_t len;
254 unsigned int r, g, b, a;
255 gboolean has_alpha;
256
257 spec++;
258 len = strlen (s: spec);
259 switch (len)
260 {
261 case 3:
262 case 6:
263 case 9:
264 case 12:
265 len /= 3;
266 has_alpha = FALSE;
267 break;
268 case 4:
269 case 8:
270 case 16:
271 if (!alpha)
272 return FALSE;
273 len /= 4;
274 has_alpha = TRUE;
275 break;
276 default:
277 return FALSE;
278 }
279
280 if (!hex (spec, len, c: &r) ||
281 !hex (spec: spec + len, len, c: &g) ||
282 !hex (spec: spec + len * 2, len, c: &b) ||
283 (has_alpha && !hex (spec: spec + len * 3, len, c: &a)))
284 return FALSE;
285
286 if (color)
287 {
288 int bits = len * 4;
289 r <<= 16 - bits;
290 g <<= 16 - bits;
291 b <<= 16 - bits;
292 while (bits < 16)
293 {
294 r |= (r >> bits);
295 g |= (g >> bits);
296 b |= (b >> bits);
297 bits *= 2;
298 }
299 color->red = r;
300 color->green = g;
301 color->blue = b;
302 }
303
304 if (alpha && has_alpha)
305 {
306 int bits = len * 4;
307 a <<= 16 - bits;
308 while (bits < 16)
309 {
310 a |= (a >> bits);
311 bits *= 2;
312 }
313 *alpha = a;
314 }
315 }
316 else
317 {
318 if (!find_color (name: spec, color))
319 return FALSE;
320 }
321 return TRUE;
322}
323
324/**
325 * pango_color_parse:
326 * @color: (nullable): a `PangoColor` structure in which
327 * to store the result
328 * @spec: a string specifying the new color
329 *
330 * Fill in the fields of a color from a string specification.
331 *
332 * The string can either one of a large set of standard names.
333 * (Taken from the CSS Color [specification](https://www.w3.org/TR/css-color-4/#named-colors),
334 * or it can be a value in the form `#rgb`, `#rrggbb`,
335 * `#rrrgggbbb` or `#rrrrggggbbbb`, where `r`, `g` and `b`
336 * are hex digits of the red, green, and blue components
337 * of the color, respectively. (White in the four forms is
338 * `#fff`, `#ffffff`, `#fffffffff` and `#ffffffffffff`.)
339 *
340 * Return value: %TRUE if parsing of the specifier succeeded,
341 * otherwise %FALSE
342 */
343gboolean
344pango_color_parse (PangoColor *color,
345 const char *spec)
346{
347 return pango_color_parse_with_alpha (color, NULL, spec);
348}
349

source code of gtk/subprojects/pango/pango/pango-color.c