style-color.c 4.88 KB
Newer Older
Jody Goldberg's avatar
Jody Goldberg committed
1
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
Arturo Espinosa's avatar
Arturo Espinosa committed
2 3 4 5 6 7 8
/*
 * color.c: Color allocation on the Gnumeric spreadsheet
 *
 * Author:
 *  Miguel de Icaza (miguel@kernel.org)
 *
 */
9 10
#include <gnumeric-config.h>
#include "gnumeric.h"
11
#include "style-color.h"
12
#include "style-border.h"
13
#include <gtk/gtk.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
14

15
/* Public _unallocated_ colours, i.e., no valid .pixel.  */
16 17 18 19 20 21
GdkRGBA gs_black      = { 0, 0, 0, 1 };    /* "Black" */
GdkRGBA gs_white      = { 1, 1, 1, 1 };    /* "White" */
GdkRGBA gs_yellow     = { 1, 1, .88, 1 };    /* "LightYellow" */
GdkRGBA gs_lavender   = { .9, .9, .98, 1 };    /* "lavender" */
GdkRGBA gs_dark_gray  = { .2, .2, .2, 1 };    /* "gray20" */
GdkRGBA gs_light_gray = { .78, .78, .78, 1 };    /* "gray78" */
22

23
static GHashTable *style_color_hash;
Morten Welinder's avatar
Morten Welinder committed
24 25 26
static GnmColor *sc_black;
static GnmColor *sc_white;
static GnmColor *sc_grid;
27

Morten Welinder's avatar
Morten Welinder committed
28
GnmColor *
29 30
style_color_new_name (char const *name)
{
31 32
	GdkRGBA c;
	gdk_rgba_parse (&c, name);
33
	return style_color_new_gdk (&c);
34 35
}

Morten Welinder's avatar
Morten Welinder committed
36
static GnmColor *
37
style_color_new_uninterned (GOColor c, gboolean is_auto)
38
{
Morten Welinder's avatar
Morten Welinder committed
39
	GnmColor *sc = g_new (GnmColor, 1);
40

41 42
	sc->go_color = c;
	sc->is_auto = !!is_auto;
43
	sc->ref_count = 1;
44 45 46 47

	return sc;
}

Morten Welinder's avatar
Morten Welinder committed
48
GnmColor *
49
style_color_new_i16 (gushort red, gushort green, gushort blue)
50
{
51
	return style_color_new_i8 (red >> 8, green >> 8, blue >> 8);
52 53
}

Jody Goldberg's avatar
Jody Goldberg committed
54
GnmColor *
55 56
style_color_new_pango (PangoColor const *c)
{
57
	return style_color_new_i16 (c->red, c->green, c->blue);
58
}
59

60
GnmColor *
61
style_color_new_gdk (GdkRGBA const *c)
Jody Goldberg's avatar
Jody Goldberg committed
62
{
63
	return style_color_new_i8 (c->red * 255, c->green * 255, c->blue * 255);
Jody Goldberg's avatar
Jody Goldberg committed
64 65
}

Morten Welinder's avatar
Morten Welinder committed
66
GnmColor *
67 68
style_color_new_i8 (guint8 red, guint8 green, guint8 blue)
{
Jean Bréfort's avatar
Jean Bréfort committed
69
	return style_color_new_go (GO_COLOR_FROM_RGBA (red, green, blue, 0xff));
70
}
71

72 73 74
GnmColor *
style_color_new_go (GOColor c)
{
75 76 77 78 79 80 81 82 83 84 85 86 87 88
	GnmColor *sc;
	GnmColor key;

	key.go_color = c;
	key.is_auto = FALSE;

	sc = g_hash_table_lookup (style_color_hash, &key);
	if (!sc) {
		sc = style_color_new_uninterned (c, FALSE);
		g_hash_table_insert (style_color_hash, sc, sc);
	} else
		sc->ref_count++;

	return sc;
89
}
90

Morten Welinder's avatar
Morten Welinder committed
91
GnmColor *
92 93
style_color_black (void)
{
94
	if (!sc_black)
95
		sc_black = style_color_new_i8 (0, 0, 0);
96
	return style_color_ref (sc_black);
97 98
}

Morten Welinder's avatar
Morten Welinder committed
99
GnmColor *
100 101
style_color_white (void)
{
102
	if (!sc_white)
103
		sc_white = style_color_new_i8 (0xff, 0xff, 0xff);
104
	return style_color_ref (sc_white);
105 106
}

Morten Welinder's avatar
Morten Welinder committed
107
GnmColor *
108 109
style_color_grid (void)
{
110
	if (!sc_grid)
111
		sc_grid = style_color_new_i8 (0xc7, 0xc7, 0xc7);
112
	return style_color_ref (sc_grid);
113
}
114 115 116 117 118 119 120 121

/**
 * Support for Excel auto-colors.
 */

/**
 * Always black, as far as we know.
 */
Morten Welinder's avatar
Morten Welinder committed
122
GnmColor *
123 124
style_color_auto_font (void)
{
Morten Welinder's avatar
Morten Welinder committed
125
	static GnmColor *color = NULL;
126 127

	if (!color)
Jean Bréfort's avatar
Jean Bréfort committed
128
		color = style_color_new_uninterned (GO_COLOR_BLACK, TRUE);
129 130 131 132 133 134
	return style_color_ref (color);
}

/**
 * Always white, as far as we know.
 */
Morten Welinder's avatar
Morten Welinder committed
135
GnmColor *
136 137
style_color_auto_back (void)
{
Morten Welinder's avatar
Morten Welinder committed
138
	static GnmColor *color = NULL;
139 140

	if (!color)
Jean Bréfort's avatar
Jean Bréfort committed
141
		color = style_color_new_uninterned (GO_COLOR_WHITE, TRUE);
142 143 144 145 146 147
	return style_color_ref (color);
}

/**
 * Normally black, but follows grid color if so told.
 */
Morten Welinder's avatar
Morten Welinder committed
148
GnmColor *
149 150
style_color_auto_pattern (void)
{
Morten Welinder's avatar
Morten Welinder committed
151
	static GnmColor *color = NULL;
152 153

	if (!color)
Jean Bréfort's avatar
Jean Bréfort committed
154
		color = style_color_new_uninterned (GO_COLOR_BLACK, TRUE);
155 156 157
	return style_color_ref (color);
}

Morten Welinder's avatar
Morten Welinder committed
158 159
GnmColor *
style_color_ref (GnmColor *sc)
160
{
161 162
	if (sc != NULL)
		sc->ref_count++;
163 164 165 166 167

	return sc;
}

void
Morten Welinder's avatar
Morten Welinder committed
168
style_color_unref (GnmColor *sc)
169
{
170 171 172
	if (sc == NULL)
		return;

173 174 175 176 177 178 179 180 181 182
	g_return_if_fail (sc->ref_count > 0);

	sc->ref_count--;
	if (sc->ref_count != 0)
		return;

	g_hash_table_remove (style_color_hash, sc);
	g_free (sc);
}

183
gint
184
style_color_equal (GnmColor const *k1, GnmColor const *k2)
185
{
186 187
	return (k1->go_color == k2->go_color &&
		k1->is_auto == k2->is_auto);
188 189 190 191 192
}

static guint
color_hash (gconstpointer v)
{
193
	GnmColor const *k = (GnmColor const *)v;
194
	return k->go_color ^ k->is_auto;
195
}
Arturo Espinosa's avatar
Arturo Espinosa committed
196 197

void
198
gnm_color_init (void)
Arturo Espinosa's avatar
Arturo Espinosa committed
199
{
Morten Welinder's avatar
Morten Welinder committed
200
	style_color_hash = g_hash_table_new (color_hash,
201
					     (GEqualFunc)style_color_equal);
202 203
}

204 205 206
static void
cb_color_leak (gpointer key, gpointer value, gpointer user_data)
{
Morten Welinder's avatar
Morten Welinder committed
207
	GnmColor *color = value;
208

209
	g_printerr ("Leaking style-color at %p [%08x].\n",
Jody Goldberg's avatar
Jody Goldberg committed
210
		    (void *)color,
211
		    color->go_color);
212 213
}

214
void
215
gnm_color_shutdown (void)
216
{
217 218 219
	/*
	 * FIXME: this doesn't really belong here, but style-border.c isn't
	 * able to clean itself up yet.
220
	 */
Morten Welinder's avatar
Morten Welinder committed
221
	GnmBorder *none = gnm_style_border_none ();
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
	style_color_unref (none->color);
	none->color = NULL;

	if (sc_black) {
		style_color_unref (sc_black);
		sc_black = NULL;
	}

	if (sc_white) {
		style_color_unref (sc_white);
		sc_white = NULL;
	}

	if (sc_grid) {
		style_color_unref (sc_grid);
		sc_grid = NULL;
	}

	g_hash_table_foreach (style_color_hash, cb_color_leak, NULL);
241 242
	g_hash_table_destroy (style_color_hash);
	style_color_hash = NULL;
Arturo Espinosa's avatar
Arturo Espinosa committed
243
}
244 245 246 247 248

GType
gnm_style_color_get_type (void)
{
	static GType our_type = 0;
249

250 251 252 253 254 255 256
	if (our_type == 0)
		our_type = g_boxed_type_register_static
			("GnmStyleColor",
			 (GBoxedCopyFunc)style_color_ref,
			 (GBoxedFreeFunc)style_color_unref);
	return our_type;
}