/* GTK - The GIMP Toolkit
* Copyright ( C ) 2011 Red Hat , Inc .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see < http : //www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkcsspalettevalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkprivate.h"
struct _GtkCssValue {
GTK_CSS_VALUE_BASE
guint n_colors;
char **color_names;
GtkCssValue **color_values;
};
static GtkCssValue *default_palette;
static GtkCssValue *gtk_css_palette_value_new_empty (void );
static GtkCssValue *gtk_css_palette_value_new_sized (guint size);
static void
gtk_css_palette_value_set_color (GtkCssValue *value,
guint i,
char *name,
GtkCssValue *color)
{
value->color_names[i] = name; /* No strdup */
value->color_values[i] = color;
}
static void
gtk_css_palette_value_sort_colors (GtkCssValue *value)
{
guint i, j;
/* Bubble sort. We're mostly talking about 3 elements here. */
for (i = 0 ; i < value->n_colors; i ++)
for (j = 0 ; j < value->n_colors; j ++)
{
if (strcmp (value->color_names[i], value->color_names[j]) < 0 )
{
char *tmp_name;
GtkCssValue *tmp_value;
tmp_name = value->color_names[i];
tmp_value = value->color_values[i];
value->color_names[i] = value->color_names[j];
value->color_values[i] = value->color_values[j];
value->color_names[j] = tmp_name;
value->color_values[j] = tmp_value;
}
}
}
static GtkCssValue *
gtk_css_palette_value_find_color (GtkCssValue *value,
const char *color_name)
{
guint i;
for (i = 0 ; i < value->n_colors; i ++)
{
if (strcmp (value->color_names[i], color_name) == 0 )
return value->color_values[i];
}
return NULL;
}
static void
gtk_css_value_palette_free (GtkCssValue *value)
{
guint i;
for (i = 0 ; i < value->n_colors; i ++)
{
g_free (value->color_names[i]);
gtk_css_value_unref (value->color_values[i]);
}
g_free (value->color_names);
g_free (value->color_values);
g_free (value);
}
static GtkCssValue *
gtk_css_value_palette_compute (GtkCssValue *specified,
guint property_id,
GtkCssComputeContext *context)
{
GtkCssValue *computed_color;
GtkCssValue *result;
gboolean changes = FALSE ;
guint i;
result = gtk_css_palette_value_new_sized (specified->n_colors);
for (i = 0 ; i < specified->n_colors; i ++)
{
GtkCssValue *value = specified->color_values[i];
computed_color = gtk_css_value_compute (value, property_id, context);
result->color_names[i] = g_strdup (specified->color_names[i]);
result->color_values[i] = computed_color;
changes |= computed_color != value;
}
if (!changes)
{
gtk_css_value_unref (result);
result = gtk_css_value_ref (specified);
}
return result;
}
static GtkCssValue *
gtk_css_value_palette_resolve (GtkCssValue *value,
GtkCssComputeContext *context,
GtkCssValue *current_color)
{
GtkCssValue *result;
if (!gtk_css_value_contains_current_color (value))
return gtk_css_value_ref (value);
result = gtk_css_palette_value_new_sized (value->n_colors);
for (guint i = 0 ; i < value->n_colors; i++)
{
result->color_names[i] = g_strdup (value->color_names[i]);
result->color_values[i] = gtk_css_value_resolve (value->color_values[i], context, current_color);
}
return result;
}
static gboolean
gtk_css_value_palette_equal (const GtkCssValue *value1,
const GtkCssValue *value2)
{
guint i;
if (value1->n_colors != value2->n_colors)
return FALSE ;
for (i = 0 ; i < value1->n_colors; i ++)
{
if (strcmp (value1->color_names[i], value2->color_names[i]) != 0 )
return FALSE ;
if (!gtk_css_value_equal (value1->color_values[i], value2->color_values[i]))
return FALSE ;
}
return TRUE ;
}
static GtkCssValue *
gtk_css_value_palette_transition (GtkCssValue *start,
GtkCssValue *end,
guint property_id,
double progress)
{
GtkCssValue *result, *transition;
GtkCssValue *start_color, *end_color;
const char *name;
guint i;
GPtrArray *new_names;
GPtrArray *new_values;
/* XXX: For colors that are only in start or end but not both,
* we don ' t transition but just keep the value .
* That causes an abrupt transition to currentColor at the end .
*/
result = gtk_css_palette_value_new_empty ();
new_names = g_ptr_array_new ();
new_values = g_ptr_array_new ();
for (i = 0 ; i < start->n_colors; i ++)
{
name = start->color_names[i];
start_color = start->color_values[i];
end_color = gtk_css_palette_value_find_color (end, name);
if (end_color == NULL)
transition = gtk_css_value_ref (start_color);
else
transition = gtk_css_value_transition (start_color, end_color, property_id, progress);
g_ptr_array_add (new_names, g_strdup (name));
g_ptr_array_add (new_values, transition);
}
for (i = 0 ; i < end->n_colors; i ++)
{
name = end->color_names[i];
end_color = end->color_values[i];
start_color = gtk_css_palette_value_find_color (start, name);
if (start_color != NULL)
continue ;
g_ptr_array_add (new_names, g_strdup (name));
g_ptr_array_add (new_values, gtk_css_value_ref (end_color));
}
result->n_colors = new_names->len;
result->color_names = (char **)g_ptr_array_free (new_names, FALSE );
result->color_values = (GtkCssValue **)g_ptr_array_free (new_values, FALSE );
gtk_css_palette_value_sort_colors (result);
return result;
}
static void
gtk_css_value_palette_print (const GtkCssValue *value,
GString *string)
{
gboolean first = TRUE ;
guint i;
if (value == default_palette)
{
g_string_append (string, "default" );
return ;
}
for (i = 0 ; i < value->n_colors; i ++)
{
if (first)
first = FALSE ;
else
g_string_append (string, ", " );
g_string_append (string, value->color_names[i]);
g_string_append_c (string, ' ' );
gtk_css_value_print (value->color_values[i], string);
}
}
static const GtkCssValueClass GTK_CSS_VALUE_PALETTE = {
"GtkCssPaletteValue" ,
gtk_css_value_palette_free,
gtk_css_value_palette_compute,
gtk_css_value_palette_resolve,
gtk_css_value_palette_equal,
gtk_css_value_palette_transition,
NULL,
NULL,
gtk_css_value_palette_print
};
static GtkCssValue *
gtk_css_palette_value_new_empty (void )
{
GtkCssValue *result;
result = gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_PALETTE);
return result;
}
static GtkCssValue *
gtk_css_palette_value_new_sized (guint size)
{
GtkCssValue *result;
result = gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_PALETTE);
result->n_colors = size;
result->color_names = g_malloc (sizeof (char *) * size);
result->color_values = g_malloc (sizeof (GtkCssValue *) * size);
return result;
}
GtkCssValue *
gtk_css_palette_value_new_default (void )
{
if (default_palette == NULL)
{
default_palette = gtk_css_palette_value_new_sized (4 );
gtk_css_palette_value_set_color (default_palette, 0 , g_strdup ("error" ),
gtk_css_color_value_new_name ("error_color" ));
gtk_css_palette_value_set_color (default_palette, 1 , g_strdup ("success" ),
gtk_css_color_value_new_name ("success_color" ));
gtk_css_palette_value_set_color (default_palette, 2 , g_strdup ("warning" ),
gtk_css_color_value_new_name ("warning_color" ));
gtk_css_palette_value_set_color (default_palette, 3 , g_strdup ("accent" ),
gtk_css_color_value_new_name ("accent_color" ));
/* Above is already sorted */
}
return gtk_css_value_ref (default_palette);
}
GtkCssValue *
gtk_css_palette_value_parse (GtkCssParser *parser)
{
GtkCssValue *result, *color;
GPtrArray *names;
GPtrArray *colors;
char *ident;
if (gtk_css_parser_try_ident (parser, "default" ))
return gtk_css_palette_value_new_default ();
result = gtk_css_palette_value_new_empty ();
names = g_ptr_array_new ();
colors = g_ptr_array_new ();
do {
ident = gtk_css_parser_consume_ident (parser);
if (ident == NULL)
{
gtk_css_value_unref (result);
return NULL;
}
color = gtk_css_color_value_parse (parser);
if (color == NULL)
{
g_free (ident);
gtk_css_value_unref (result);
return NULL;
}
result->is_computed = result->is_computed && gtk_css_value_is_computed (color);
result->contains_current_color = result->contains_current_color || gtk_css_value_contains_current_color (color);
g_ptr_array_add (names, ident);
g_ptr_array_add (colors, color);
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
result->n_colors = names->len;
result->color_names = (char **)g_ptr_array_free (names, FALSE );
result->color_values = (GtkCssValue **) g_ptr_array_free (colors, FALSE );
gtk_css_palette_value_sort_colors (result);
return result;
}
GtkCssValue *
gtk_css_palette_value_get_color (GtkCssValue *value,
const char *name)
{
guint i;
gtk_internal_return_val_if_fail (value->class == >K_CSS_VALUE_PALETTE, NULL);
for (i = 0 ; i < value->n_colors; i ++)
{
if (strcmp (value->color_names[i], name) == 0 )
return value->color_values[i];
}
return NULL;
}
Messung V0.5 in Prozent C=98 H=96 G=96
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-07-02)
¤
*© Formatika GbR, Deutschland