/* pango
* pango-color.c: Color handling
*
* Copyright (C) 2000 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pango-attributes.h"
#include "pango-impl-utils.h"
#include "pango-utils-internal.h"
G_DEFINE_BOXED_TYPE (PangoColor, pango_color,
pango_color_copy,
pango_color_free);
/**
* pango_color_copy:
* @src: (nullable): color to copy, may be %NULL
*
* Creates a copy of @src, which should be freed with
* pango_color_free(). Primarily used by language bindings,
* not that useful otherwise (since colors can just be copied
* by assignment in C).
*
* Return value: (nullable): the newly allocated #PangoColor, which
* should be freed with pango_color_free(), or %NULL if
* @src was %NULL.
**/
PangoColor*
pango_color_copy (const PangoColor *src)
{
PangoColor *ret;
if (src == NULL)
return NULL;
ret = g_slice_new (PangoColor);
*ret = *src;
return ret;
}
/**
* pango_color_free:
* @color: (nullable): an allocated #PangoColor, may be %NULL
*
* Frees a color allocated by pango_color_copy().
**/
void
pango_color_free (PangoColor *color)
{
if (color == NULL)
return;
g_slice_free (PangoColor, color);
}
/**
* pango_color_to_string:
* @color: a #PangoColor
*
* Returns a textual specification of @color in the hexadecimal form
* <literal>#rrrrggggbbbb</literal>, where <literal>r</literal>,
* <literal>g</literal> and <literal>b</literal> are hex digits representing
* the red, green, and blue components respectively.
*
* Return value: a newly-allocated text string that must be freed with g_free().
*
* Since: 1.16
**/
gchar *
pango_color_to_string (const PangoColor *color)
{
g_return_val_if_fail (color != NULL, NULL);
return g_strdup_printf ("#%04x%04x%04x", color->red, color->green, color->blue);
}
/* Color parsing
*/
/* The following 2 routines (parse_color, find_color) come from Tk, via the Win32
* port of GDK. The licensing terms on these (longer than the functions) is:
*
* This software is copyrighted by the Regents of the University of
* California, Sun Microsystems, Inc., and other parties. The following
* terms apply to all files associated with the software unless explicitly
* disclaimed in individual files.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*
* IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
* FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
* DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
* IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
* NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
* MODIFICATIONS.
*
* GOVERNMENT USE: If you are acquiring this software on behalf of the
* U.S. government, the Government shall have only "Restricted Rights"
* in the software and related documentation as defined in the Federal
* Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
* are acquiring the software on behalf of the Department of Defense, the
* software shall be classified as "Commercial Computer Software" and the
* Government shall have only "Restricted Rights" as defined in Clause
* 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
* authors grant the U.S. Government and others acting in its behalf
* permission to use and distribute the software in accordance with the
* terms specified in this license.
*/
#include "pango-color-table.h"
#define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z')
#define TOLOWER(c) (ISUPPER (c) ? (c) - 'A' + 'a' : (c))
static int
compare_xcolor_entries (const void *a, const void *b)
{
const guchar *s1 = (const guchar *) a;
const guchar *s2 = (const guchar *) (color_names + ((const ColorEntry *) b)->name_offset);
while (*s1 && *s2)
{
int c1, c2;
while (*s1 == ' ') s1++;
while (*s2 == ' ') s1++;
c1 = (gint)(guchar) TOLOWER (*s1);
c2 = (gint)(guchar) TOLOWER (*s2);
if (c1 != c2)
return (c1 - c2);
s1++; s2++;
}
return ((gint) *s1) - ((gint) *s2);
}
static gboolean
find_color(const char *name,
PangoColor *color)
{
ColorEntry *found;
found = bsearch (name, color_entries, G_N_ELEMENTS (color_entries),
sizeof (ColorEntry),
compare_xcolor_entries);
if (found == NULL)
return FALSE;
if (color)
{
color->red = (found->red * 65535) / 255;
color->green = (found->green * 65535) / 255;
color->blue = (found->blue * 65535) / 255;
}
return TRUE;
}
static gboolean
hex (const char *spec,
int len,
unsigned int *c)
{
const char *end;
*c = 0;
for (end = spec + len; spec != end; spec++)
if (g_ascii_isxdigit (*spec))
*c = (*c << 4) | g_ascii_xdigit_value (*spec);
else
return FALSE;
return TRUE;
}
/* Like pango_color_parse, but allow strings of the form
* '#rgba', '#rrggbbaa', '#rrrrggggbbbbaaaa',
* if alpha is not NULL. If no alpha component is found
* in the string, *alpha is set to 0.
*/
gboolean
_pango_color_parse_with_alpha (PangoColor *color,
guint16 *alpha,
const char *spec)
{
g_return_val_if_fail (spec != NULL, FALSE);
if (alpha)
*alpha = 0;
if (spec[0] == '#')
{
size_t len;
unsigned int r, g, b, a;
gboolean has_alpha;
spec++;
len = strlen (spec);
switch (len)
{
case 3:
case 6:
case 9:
case 12:
len /= 3;
has_alpha = FALSE;
break;
case 4:
case 8:
case 16:
if (!alpha)
return FALSE;
len /= 4;
has_alpha = TRUE;
break;
default:
return FALSE;
}
if (!hex (spec, len, &r) ||
!hex (spec + len, len, &g) ||
!hex (spec + len * 2, len, &b) ||
(has_alpha && !hex (spec + len * 3, len, &a)))
return FALSE;
if (color)
{
int bits = len * 4;
r <<= 16 - bits;
g <<= 16 - bits;
b <<= 16 - bits;
while (bits < 16)
{
r |= (r >> bits);
g |= (g >> bits);
b |= (b >> bits);
bits *= 2;
}
color->red = r;
color->green = g;
color->blue = b;
}
if (alpha && has_alpha)
{
int bits = len * 4;
a <<= 16 - bits;
while (bits < 16)
{
a |= (a >> bits);
bits *= 2;
}
*alpha = a;
}
}
else
{
if (!find_color (spec, color))
return FALSE;
}
return TRUE;
}
/**
* pango_color_parse:
* @color: (nullable): a #PangoColor structure in which to store the
* result, or %NULL
* @spec: a string specifying the new color
*
* Fill in the fields of a color from a string specification. The
* string can either one of a large set of standard names. (Taken
* from the CSS <ulink url="http://dev.w3.org/csswg/css-color/#named-colors">specification</ulink>), or it can be a hexadecimal
* value in the
* form '#rgb' '#rrggbb' '#rrrgggbbb' or '#rrrrggggbbbb' where
* 'r', 'g' and 'b' are hex digits of the red, green, and blue
* components of the color, respectively. (White in the four
* forms is '#fff' '#ffffff' '#fffffffff' and '#ffffffffffff')
*
* Return value: %TRUE if parsing of the specifier succeeded,
* otherwise false.
**/
gboolean
pango_color_parse (PangoColor *color,
const char *spec)
{
return _pango_color_parse_with_alpha (color, NULL, spec);
}