1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Luc BILLARD et Damien
3 CALISTE, laboratoire L_Sim, (2001-2005)
4
5 Adresse mèl :
6 BILLARD, non joignable par mèl ;
7 CALISTE, damien P caliste AT cea P fr.
8
9 Ce logiciel est un programme informatique servant à visualiser des
10 structures atomiques dans un rendu pseudo-3D.
11
12 Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 respectant les principes de diffusion des logiciels libres. Vous pouvez
14 utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 sur le site "http://www.cecill.info".
17
18 Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22
23 /* LICENCE SUM UP
24 Copyright CEA, contributors : Luc BILLARD et Damien
25 CALISTE, laboratoire L_Sim, (2001-2005)
26
27 E-mail address:
28 BILLARD, not reachable any more ;
29 CALISTE, damien P caliste AT cea P fr.
30
31 This software is a computer program whose purpose is to visualize atomic
32 configurations in 3D.
33
34 This software is governed by the CeCILL license under French law and
35 abiding by the rules of distribution of free software. You can use,
36 modify and/ or redistribute the software under the terms of the CeCILL
37 license as circulated by CEA, CNRS and INRIA at the following URL
38 "http://www.cecill.info".
39
40 The fact that you are presently reading this means that you have had
41 knowledge of the CeCILL license and that you accept its terms. You can
42 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44
45 #include "toolShade.h"
46
47 #include <errno.h>
48 #include <string.h>
49
50 #include <pango/pango.h>
51
52 #include <visu_configFile.h>
53 #include "toolConfigFile.h"
54 #include "toolColor.h"
55
56 /**
57 * SECTION:toolShade
58 * @short_description: ToolShades are color gradients.
59 *
60 * <para>This module allow V_Sim to deal with color gradients. Such a
61 * gradient is defined by a linear transformation of color space. This
62 * space can be RBG or HSV (see the enum #ToolShadeColorMode). This linear
63 * transformation can be written [resulting color vector] = [vectB] +
64 * lambda.[vectA], where lambda denotes the input variable of the
65 * gradient (ranging from 0 to 1). Resulting color vector are clamped
66 * to [0;1] if needed.</para>
67 * <para>Use tool_shade_new() to create a new shade, giving the arguments as
68 * defined above.</para>
69 * <para>To share color gradients between modules in V_Sim, you can
70 * find a global list of stored shades with tool_shade_getStorage().
71 * This is a #ToolPool object. Use tool_pool_add() to add a new shade
72 * to it.</para>
73 */
74
75
76 #define SHADE_LEGEND_WIDTH 0.05
77 #define SHADE_LEGEND_HEIGHT 0.3
78 #define SHADE_LEGEND_N_QUADS 20
79
80 #define FLAG_SHADE "shade_palette"
81 #define DESC_SHADE "Define a new shade by giving colours to points ; label (val [name|#rgb|#rrggbb|...], ...)"
82 static void exportParameters(GString *data, VisuData *dataObj);
83 static gboolean readShade(VisuConfigFileEntry *entry _U_, gchar **lines, int nbLines,int position,
84 GError **error);
85 static gboolean parseValue(gchar *line, float *index, float rgb[3], GError **error);
86 static void _buildPresetList(void);
87
88 struct _ToolShade
89 {
90 gchar* labelUTF8;
91 ToolShadeColorMode colorMode;
92 ToolShadeMode mode;
93
94 /* The linear storage. */
95 float vectA[3], vectB[3];
96 /* The array storage. */
97 float *index;
98 float *vectCh[3];
99 guint nVals;
100
101 /* Some user defined values. */
102 gboolean userDefined;
103 gchar *steps;
104 };
105
106 static ToolPool *shadePool = NULL;
107
108 /**
109 * tool_shade_get_type:
110 *
111 * Create and retrieve a #GType for a #ToolShade object.
112 *
113 * Since: 3.7
114 *
115 * Returns: a new type for #ToolShade structures.
116 */
tool_shade_get_type(void)117 GType tool_shade_get_type(void)
118 {
119 static GType g_define_type_id = 0;
120 VisuConfigFileEntry *entry;
121
122 if (g_define_type_id == 0)
123 {
124 g_define_type_id = g_boxed_type_register_static("ToolShade",
125 (GBoxedCopyFunc)tool_shade_copy,
126 (GBoxedFreeFunc)tool_shade_free);
127
128 /* Set private variables. */
129 entry = visu_config_file_addEntry(VISU_CONFIG_FILE_RESOURCE,
130 FLAG_SHADE, DESC_SHADE,
131 1, readShade);
132 visu_config_file_entry_setVersion(entry, 3.7f);
133 visu_config_file_addExportFunction(VISU_CONFIG_FILE_RESOURCE,
134 exportParameters);
135 }
136
137 return g_define_type_id;
138 }
139
140 /**
141 * tool_shade_getById:
142 * @id: an id.
143 *
144 * Convenience function calling tool_pool_getById() on the default
145 * #ToolShade storage.
146 *
147 * Since: 3.8
148 *
149 * Returns: a #ToolShade from the pool.
150 **/
tool_shade_getById(guint id)151 const ToolShade* tool_shade_getById(guint id)
152 {
153 return tool_pool_getById(tool_shade_getStorage(), id);
154 }
155
156 /**
157 * tool_shade_new:
158 * @labelUTF8: a UTF8 string that shortly named this new shade ;
159 * @vectA: an array of three floating point values ;
160 * @vectB: an array of three floating point values ;
161 * @colorMode: an integer that describes the color code (see #ToolShadeColorMode enumeration).
162 *
163 * Create a linear shade. Its profile is given by an AX+B formula,
164 * dealing on three channels. These channels are defined by the
165 * @colorMode parameter. All given values are copied when the new
166 * shade is created.
167 *
168 * Returns: the newly created ToolShade.
169 */
tool_shade_new(const gchar * labelUTF8,float vectA[3],float vectB[3],ToolShadeColorMode colorMode)170 ToolShade* tool_shade_new(const gchar* labelUTF8, float vectA[3], float vectB[3],
171 ToolShadeColorMode colorMode)
172 {
173 ToolShade *shade;
174 int i;
175
176 g_return_val_if_fail(labelUTF8 && vectA && vectB &&
177 colorMode < TOOL_SHADE_COLOR_MODE_N_VALUES, (ToolShade*)0);
178
179 DBG_fprintf(stderr, "Tool ToolShade: create a new ToolShade object (linear):");
180 shade = g_malloc(sizeof(ToolShade));
181 shade->labelUTF8 = g_strdup(labelUTF8);
182 for (i = 0; i < 3; i++)
183 {
184 shade->vectA[i] = vectA[i];
185 shade->vectB[i] = vectB[i];
186 }
187 shade->index = (float*)0;
188 shade->vectCh[0] = (float*)0;
189 shade->vectCh[1] = (float*)0;
190 shade->vectCh[2] = (float*)0;
191 shade->colorMode = colorMode;
192 shade->mode = TOOL_SHADE_MODE_LINEAR;
193 shade->userDefined = TRUE;
194 shade->steps = (gchar*)0;
195
196 DBG_fprintf(stderr, " %p.\n", (gpointer)shade);
197 return shade;
198 }
199 /**
200 * tool_shade_newFromData:
201 * @labelUTF8: a UTF8 string that shortly named this new shade ;
202 * @len: the size of arguments @vectCh1, @vectCh2 and @vectCh3 ;
203 * @vectCh1: an array of floating point values for the first channel ;
204 * @vectCh2: an array of floating point values for the second channel ;
205 * @vectCh3: an array of floating point values for the third channel ;
206 * @colorMode: an integer that describes the color code (see
207 * #ToolShadeColorMode enumeration).
208 *
209 * Create a #ToolShade from direct data for three channels. These channels
210 * are defined by the @colorMode parameter. All given values are
211 * copied when the new shade is created.
212 *
213 * Returns: the newly created ToolShade.
214 */
tool_shade_newFromData(const gchar * labelUTF8,guint len,float * vectCh1,float * vectCh2,float * vectCh3,ToolShadeColorMode colorMode)215 ToolShade* tool_shade_newFromData(const gchar* labelUTF8, guint len, float *vectCh1,
216 float *vectCh2, float *vectCh3, ToolShadeColorMode colorMode)
217 {
218 ToolShade *shade;
219 guint i;
220
221 g_return_val_if_fail(labelUTF8 && vectCh1 && vectCh2 && vectCh3 &&
222 colorMode < TOOL_SHADE_COLOR_MODE_N_VALUES && len > 0, (ToolShade*)0);
223
224 DBG_fprintf(stderr, "Tool ToolShade: create a new ToolShade object (array):");
225 shade = g_malloc(sizeof(ToolShade));
226 shade->labelUTF8 = g_strdup(labelUTF8);
227 shade->colorMode = colorMode;
228 shade->mode = TOOL_SHADE_MODE_ARRAY;
229 shade->nVals = len;
230 shade->index = g_malloc(sizeof(float) * len);
231 shade->vectCh[0] = g_malloc(sizeof(float) * len);
232 shade->vectCh[1] = g_malloc(sizeof(float) * len);
233 shade->vectCh[2] = g_malloc(sizeof(float) * len);
234 for (i = 0; i < len; i++)
235 shade->index[i] = (float)i / (float)(len - 1);
236 memcpy(shade->vectCh[0], vectCh1, sizeof(float) * len);
237 memcpy(shade->vectCh[1], vectCh2, sizeof(float) * len);
238 memcpy(shade->vectCh[2], vectCh3, sizeof(float) * len);
239 shade->userDefined = TRUE;
240 shade->steps = (gchar*)0;
241
242 DBG_fprintf(stderr, " %p.\n", (gpointer)shade);
243 return shade;
244 }
245 /**
246 * tool_shade_newFromSteps:
247 * @labelUTF8: a UTF8 string that shortly named this new shade ;
248 * @lst: (transfer none) (element-type ToolShadeStep*): a list of
249 * color steps.
250 * @colorMode: a #ToolShadeColorMode mode.
251 *
252 * Create a #ToolShade from a set of steps defining colours at given
253 * indexes. These channels are defined by the @colorMode
254 * parameter. All given values are copied when the new shade is
255 * created. The values of indexes will be normalised by this call to
256 * range in [0;1]. Colour channel values must be in [0;1] for each step.
257 *
258 * Since: 3.7
259 *
260 * Returns: (transfer full): the newly created ToolShade.
261 */
tool_shade_newFromSteps(const gchar * labelUTF8,GList * lst,ToolShadeColorMode colorMode)262 ToolShade* tool_shade_newFromSteps(const gchar* labelUTF8, GList *lst,
263 ToolShadeColorMode colorMode)
264 {
265 ToolShade *shade;
266 float minVal, maxVal, f;
267 GList *tmp;
268 ToolShadeStep *step;
269 guint i;
270
271 g_return_val_if_fail(labelUTF8 && lst && (g_list_length(lst) > 1), (ToolShade*)0);
272
273 DBG_fprintf(stderr, "Tool ToolShade: create a new ToolShade object (array):\n");
274 shade = g_malloc(sizeof(ToolShade));
275 shade->labelUTF8 = g_strdup(labelUTF8);
276 shade->nVals = g_list_length(lst);
277 shade->index = g_malloc(sizeof(float) * shade->nVals);
278 shade->vectCh[0] = g_malloc(sizeof(float) * shade->nVals);
279 shade->vectCh[1] = g_malloc(sizeof(float) * shade->nVals);
280 shade->vectCh[2] = g_malloc(sizeof(float) * shade->nVals);
281 shade->colorMode = colorMode;
282 shade->mode = TOOL_SHADE_MODE_ARRAY;
283 shade->userDefined = TRUE;
284 shade->steps = (gchar*)0;
285
286 /* Normalise entry. */
287 minVal = G_MAXFLOAT;
288 maxVal = -G_MAXFLOAT;
289 for (tmp = lst; tmp; tmp = g_list_next(tmp))
290 {
291 minVal = MIN(minVal, ((ToolShadeStep*)tmp->data)->index);
292 maxVal = MAX(maxVal, ((ToolShadeStep*)tmp->data)->index);
293 }
294 f = 1.f / (maxVal - minVal);
295 DBG_fprintf(stderr, " | applying factor %g to index\n", f);
296
297 for (tmp = lst, i = 0; tmp; tmp = g_list_next(tmp), i++)
298 {
299 step = (ToolShadeStep*)tmp->data;
300 shade->index[i] = (step->index - minVal) * f;
301 shade->vectCh[0][i] = CLAMP(step->channels[0], 0.f, 1.f);
302 shade->vectCh[1][i] = CLAMP(step->channels[1], 0.f, 1.f);
303 shade->vectCh[2][i] = CLAMP(step->channels[2], 0.f, 1.f);
304 }
305
306 DBG_fprintf(stderr, " | done %p.\n", (gpointer)shade);
307 return shade;
308 }
309 /**
310 * tool_shade_newFromString:
311 * @labelUTF8: a UTF8 string that shortly named this new shade ;
312 * @descr: a string with the shade description.
313 * @colorMode: a #ToolShadeColorMode mode.
314 * @error: (allow-none): a location for an error.
315 *
316 * As tool_shade_newFromSteps() routine, but it takes an unparsed
317 * string describing the steps in @descr.
318 *
319 * Since: 3.7
320 *
321 * Returns: (transfer full): the newly created ToolShade.
322 */
tool_shade_newFromString(const gchar * labelUTF8,const gchar * descr,ToolShadeColorMode colorMode,GError ** error)323 ToolShade* tool_shade_newFromString(const gchar* labelUTF8, const gchar *descr,
324 ToolShadeColorMode colorMode, GError **error)
325 {
326 ToolShade *shade;
327 gchar **tokens;
328 guint i;
329 GList *lst;
330 ToolShadeStep *step;
331
332 g_return_val_if_fail(labelUTF8 && descr && error, (ToolShade*)0);
333
334 DBG_fprintf(stderr, "Tool ToolShade: create a new ToolShade object (string): %s\n", descr);
335
336 /* Read @size boolean values from @line. */
337 lst = (GList*)0;
338 tokens = g_strsplit_set(descr, ",", TOOL_MAX_LINE_LENGTH);
339 for (i = 0; tokens[i]; i++)
340 if (tokens[i][0])
341 {
342 step = g_malloc(sizeof(ToolShadeStep));
343 lst = g_list_append(lst, step);
344 if (!parseValue(tokens[i], &(step->index), step->channels, error))
345 {
346 g_strfreev(tokens);
347 g_list_free_full(lst, g_free);
348 return FALSE;
349 }
350 }
351
352 shade = tool_shade_newFromSteps(labelUTF8, lst, colorMode);
353 if (shade)
354 shade->steps = g_strdup(descr);
355
356 g_strfreev(tokens);
357 g_list_free_full(lst, g_free);
358
359 return shade;
360 }
361 /**
362 * tool_shade_free:
363 * @shade: a #ToolShade.
364 *
365 * Free all dynamic memory from @shade and free @shade itself.
366 */
tool_shade_free(ToolShade * shade)367 void tool_shade_free(ToolShade *shade)
368 {
369 if (shade)
370 {
371 DBG_fprintf(stderr, "Tool Shade: freeing %p.\n", (gpointer)shade);
372 g_free(shade->labelUTF8);
373 g_free(shade->index);
374 g_free(shade->vectCh[0]);
375 g_free(shade->vectCh[1]);
376 g_free(shade->vectCh[2]);
377 g_free(shade->steps);
378 g_free(shade);
379 }
380 }
381 /**
382 * tool_shade_copy:
383 * @shade: a #ToolShade.
384 *
385 * Create a new shade deep copy of the first.
386 *
387 * Returns: a newly created shade.
388 */
tool_shade_copy(const ToolShade * shade)389 ToolShade* tool_shade_copy(const ToolShade *shade)
390 {
391 ToolShade *out;
392
393 if (!shade)
394 return (ToolShade*)0;
395
396 out = g_malloc(sizeof(ToolShade));
397 out->labelUTF8 = g_strdup(shade->labelUTF8);
398 out->colorMode = shade->colorMode;
399 out->mode = shade->mode;
400 out->nVals = shade->nVals;
401 out->vectA[0] = shade->vectA[0];
402 out->vectA[1] = shade->vectA[1];
403 out->vectA[2] = shade->vectA[2];
404 out->vectB[0] = shade->vectB[0];
405 out->vectB[1] = shade->vectB[1];
406 out->vectB[2] = shade->vectB[2];
407 out->index = g_memdup(shade->index, sizeof(float) * out->nVals);
408 out->vectCh[0] = g_memdup(shade->vectCh[0], sizeof(float) * out->nVals);
409 out->vectCh[1] = g_memdup(shade->vectCh[1], sizeof(float) * out->nVals);
410 out->vectCh[2] = g_memdup(shade->vectCh[2], sizeof(float) * out->nVals);
411 out->userDefined = shade->userDefined;
412 out->steps = g_strdup(shade->steps);
413
414 return out;
415 }
_compare(const ToolShade * sh1,const ToolShade * sh2)416 static gint _compare(const ToolShade* sh1, const ToolShade *sh2)
417 {
418 guint i;
419 gboolean equal;
420
421 if (!sh1 && !sh2)
422 return 0;
423 if (!sh1)
424 return -1;
425 if (!sh2)
426 return +1;
427
428 if (sh1->mode != sh2->mode)
429 return (sh2 - sh1);
430 if (sh1->colorMode != sh2->colorMode)
431 return (sh2 - sh1);
432
433 if (sh1->mode == TOOL_SHADE_MODE_LINEAR)
434 return (sh1->vectA[0] == sh2->vectA[0] &&
435 sh1->vectA[1] == sh2->vectA[1] &&
436 sh1->vectA[2] == sh2->vectA[2] &&
437 sh1->vectB[0] == sh2->vectB[0] &&
438 sh1->vectB[1] == sh2->vectB[1] &&
439 sh1->vectB[2] == sh2->vectB[2]) ? 0 : (sh2 - sh1);
440 else
441 {
442 if (sh1->nVals != sh2->nVals)
443 return (sh2 - sh1);
444 equal = TRUE;
445 for (i = 0; i < sh1->nVals && equal; i++)
446 equal = equal && (sh1->index[i] == sh2->index[i]) &&
447 (sh1->vectCh[0][i] == sh2->vectCh[0][i]) &&
448 (sh1->vectCh[1][i] == sh2->vectCh[1][i]) &&
449 (sh1->vectCh[2][i] == sh2->vectCh[2][i]);
450 return equal ? 0 : (sh2 - sh1);
451 }
452 }
453 /**
454 * tool_shade_compare:
455 * @sh1: a #ToolShade ;
456 * @sh2: a #ToolShade.
457 *
458 * Compare if the two shade are identical (first, smae mode, then same
459 * values).
460 *
461 * Returns: TRUE if @shade1 is equivalent to @shade2.
462 */
tool_shade_compare(const ToolShade * sh1,const ToolShade * sh2)463 gboolean tool_shade_compare(const ToolShade* sh1, const ToolShade *sh2)
464 {
465 return (_compare(sh1, sh2) == 0);
466 }
467 /**
468 * tool_shade_getLabel:
469 * @shade: a valid #ToolShade object.
470 *
471 * Get the name (in UTF8) of the shade.
472 *
473 * Returns: a string naming the shade.
474 */
tool_shade_getLabel(ToolShade * shade)475 gchar* tool_shade_getLabel(ToolShade *shade)
476 {
477 g_return_val_if_fail(shade, (gchar*)0);
478 return shade->labelUTF8;
479 }
480 /**
481 * tool_shade_getColorMode:
482 * @shade: a valid #ToolShade object.
483 *
484 * Get the color mode of the shade (RGB or HSV).
485 *
486 * Returns: the color mode.
487 */
tool_shade_getColorMode(ToolShade * shade)488 ToolShadeColorMode tool_shade_getColorMode(ToolShade *shade)
489 {
490 g_return_val_if_fail(shade, (int)0);
491 return shade->colorMode;
492 }
493 /**
494 * tool_shade_getMode:
495 * @shade: a valid #ToolShade object.
496 *
497 * Get the mode of the shade (linear, array...).
498 *
499 * Returns: the mode.
500 */
tool_shade_getMode(const ToolShade * shade)501 ToolShadeMode tool_shade_getMode(const ToolShade *shade)
502 {
503 g_return_val_if_fail(shade, (int)0);
504 return shade->mode;
505 }
506 /**
507 * tool_shade_setColorMode:
508 * @shade: a #ToolShade ;
509 * @mode: a new mode for the shade.
510 *
511 * Change the mode of the shade, see #ToolShadeColorMode.
512 *
513 * Returns: TRUE if @mode is different from previous @shade mode.
514 */
tool_shade_setColorMode(ToolShade * shade,ToolShadeColorMode mode)515 gboolean tool_shade_setColorMode(ToolShade *shade, ToolShadeColorMode mode)
516 {
517 g_return_val_if_fail(shade, FALSE);
518
519 if (shade->colorMode == mode)
520 return FALSE;
521
522 shade->colorMode = mode;
523 return TRUE;
524 }
525 /**
526 * tool_shade_getLinearCoeff:
527 * @shade: a valid #ToolShade object ;
528 * @vectA: a pointer to a floating point values array to store vect in AX+B ;
529 * @vectB: a pointer to a floating point values array to store vect in AX+B.
530 *
531 * This methods can get the linear color transformation. The given
532 * arrays (@vectA, @vectB) are read-only. This method return
533 * FALSE if the @shade is not in a #TOOL_SHADE_MODE_LINEAR state.
534 *
535 * Returns: TRUE if @vectA, @vectB and @vectX have been set correctly.
536 */
tool_shade_getLinearCoeff(const ToolShade * shade,const float ** vectA,const float ** vectB)537 gboolean tool_shade_getLinearCoeff(const ToolShade *shade,
538 const float **vectA, const float **vectB)
539 {
540 g_return_val_if_fail(shade, FALSE);
541 g_return_val_if_fail(shade->mode == TOOL_SHADE_MODE_LINEAR, FALSE);
542 g_return_val_if_fail(vectA && vectB, FALSE);
543
544 *vectA = shade->vectA;
545 *vectB = shade->vectB;
546 return TRUE;
547 }
548 /**
549 * tool_shade_setLinearCoeff:
550 * @shade: a #ToolShade ;
551 * @coeff: a new value ;
552 * @channel: either RGBA (from 0 to 3) ;
553 * @order: the order in the linear approx (0 means constant and 1 is
554 * the linear coeeficient).
555 *
556 * Change one value @coeff of the linear mode for the given @shade.
557 *
558 * Returns: TRUE if the new value changes anything.
559 */
tool_shade_setLinearCoeff(ToolShade * shade,float coeff,int channel,int order)560 gboolean tool_shade_setLinearCoeff(ToolShade *shade, float coeff, int channel, int order)
561 {
562 float *pt;
563
564 g_return_val_if_fail(shade, FALSE);
565 g_return_val_if_fail(channel >= 0 && channel < 3 && order >= 0 && order < 2, FALSE);
566
567 if (order == 0)
568 pt = shade->vectB + channel;
569 else
570 pt = shade->vectA + channel;
571
572 DBG_fprintf(stderr, "Tool ToolShade: set the %d value of vect[%d]"
573 " to %f (previuosly %f).\n", channel, order, coeff, *pt);
574
575 if (*pt == coeff)
576 return FALSE;
577
578 *pt = coeff;
579 return TRUE;
580 }
581 /**
582 * tool_shade_channelToRGB:
583 * @shade: a #ToolShade ;
584 * @rgba: a location to store the result of the colour transformation ;
585 * @values: inout values.
586 *
587 * Like tool_shade_valueToRGB() but here, the three values
588 * are applied respectivly for the Red, the Green and the Blue
589 * channel.
590 */
tool_shade_channelToRGB(const ToolShade * shade,float rgba[4],float values[3])591 void tool_shade_channelToRGB(const ToolShade *shade, float rgba[4], float values[3])
592 {
593 guint i;
594
595 g_return_if_fail(shade);
596
597 /* DBG_fprintf(stderr, "Tool Shade: get RGB from (%g ; %g ; %g).\n", */
598 /* values[0], values[1], values[2]); */
599 if (shade->mode == TOOL_SHADE_MODE_LINEAR)
600 {
601 rgba[0] = CLAMP(shade->vectA[0] * values[0] + shade->vectB[0], 0.f, 1.f);
602 rgba[1] = CLAMP(shade->vectA[1] * values[1] + shade->vectB[1], 0.f, 1.f);
603 rgba[2] = CLAMP(shade->vectA[2] * values[2] + shade->vectB[2], 0.f, 1.f);
604 }
605 else
606 {
607 for (i = 1; i < shade->nVals - 1; i++)
608 if (values[0] < shade->index[i])
609 break;
610 rgba[0] = CLAMP(shade->vectCh[0][i - 1] +
611 (shade->vectCh[0][i] - shade->vectCh[0][i - 1]) *
612 (values[0] - shade->index[i - 1]) /
613 (shade->index[i] - shade->index[i - 1]), 0.f, 1.f);
614 for (i = 1; i < shade->nVals - 1; i++)
615 if (values[1] < shade->index[i])
616 break;
617 rgba[1] = CLAMP(shade->vectCh[1][i - 1] +
618 (shade->vectCh[1][i] - shade->vectCh[1][i - 1]) *
619 (values[1] - shade->index[i - 1]) /
620 (shade->index[i] - shade->index[i - 1]), 0.f, 1.f);
621 for (i = 1; i < shade->nVals - 1; i++)
622 if (values[2] < shade->index[i])
623 break;
624 rgba[2] = CLAMP(shade->vectCh[2][i - 1] +
625 (shade->vectCh[2][i] - shade->vectCh[2][i - 1]) *
626 (values[2] - shade->index[i - 1]) /
627 (shade->index[i] - shade->index[i - 1]), 0.f, 1.f);
628 }
629 /* Don't use alpha channel at present time. */
630 rgba[3] = 1.;
631 /* Transform if required. */
632 if (shade->colorMode == TOOL_SHADE_COLOR_MODE_HSV)
633 tool_color_convertHSVtoRGB(rgba, rgba);
634 }
635 /**
636 * tool_shade_valueToRGB:
637 * @shade: a valid #ToolShade object ;
638 * @rgba: an array of size [4] ;
639 * @value: the value ranged in [0;1].
640 *
641 * Give a RGBA vector for the given value.
642 */
tool_shade_valueToRGB(const ToolShade * shade,float rgba[4],float value)643 void tool_shade_valueToRGB(const ToolShade *shade, float rgba[4], float value)
644 {
645 float vals[3];
646
647 vals[0] = value;
648 vals[1] = value;
649 vals[2] = value;
650 tool_shade_channelToRGB(shade, rgba, vals);
651 }
652
653 /*********************************************/
654 /* Methods to deal with internal shade list. */
655 /*********************************************/
656 /**
657 * tool_shade_getStorage:
658 *
659 * It returns a read-only pointer to the internal shade list. Use tool_shade_appendList()
660 * to add new shades to this list.
661 *
662 * Since: 3.8
663 *
664 * Returns: (transfer none): a pointer to the internal shade list.
665 */
tool_shade_getStorage(void)666 ToolPool* tool_shade_getStorage(void)
667 {
668 if (!shadePool)
669 _buildPresetList();
670
671 return shadePool;
672 }
_buildPresetList(void)673 static void _buildPresetList(void)
674 {
675 ToolShade *shade;
676 float vectA[3], vectB[3];
677
678 /* Zero Centred Colored. */
679 #define zccLn 3
680 float zccH[zccLn] = {0.f, 0.333f, 0.667f};
681 float zccS[zccLn] = {1.0f, 0.0f, 1.0f};
682 float zccV[zccLn] = {1.f, 1.f, 1.f};
683
684 /* Zero Centred Light. */
685 #define zclLn 3
686 float zclR[zclLn] = {1.f, 1.f, 0.f};
687 float zclG[zclLn] = {0.0f, 1.0f, 0.0f};
688 float zclB[zclLn] = {0.f, 1.f, 1.f};
689
690 /* Jet colour shade. */
691 #define jetn 9
692 float jetR[jetn] = {0.f, 0.f, 0.f, 0.f, 0.5f, 1.f, 1.f, 1.f, 0.5f};
693 float jetG[jetn] = {0.f, 0.f, 0.5f, 1.f, 1.f, 1.f, 0.5f, 0.f, 0.f};
694 float jetB[jetn] = {0.5f, 1.f, 1.f, 1.f, 0.5f, 0.f, 0.f, 0.f, 0.f};
695
696 shadePool = tool_pool_new(TOOL_TYPE_SHADE, (GCompareFunc)_compare);
697
698 /* Create a blue to red color range. */
699 vectA[0] = -0.66667;
700 vectA[1] = 0.;
701 vectA[2] = 0.;
702 vectB[0] = 0.66667;
703 vectB[1] = 1.;
704 vectB[2] = 1.;
705 shade = tool_shade_new(_("blue to red"), vectA, vectB, TOOL_SHADE_COLOR_MODE_HSV);
706 shade->userDefined = FALSE;
707 tool_pool_take(shadePool, shade);
708
709 /* Create a black to white (through yellow and red) color range. */
710 vectA[0] = 2.66667;
711 vectA[1] = 2.66667;
712 vectA[2] = 4.;
713 vectB[0] = 0.;
714 vectB[1] = -1.;
715 vectB[2] = -3.;
716 shade = tool_shade_new(_("hot color"), vectA, vectB, TOOL_SHADE_COLOR_MODE_RGB);
717 shade->userDefined = FALSE;
718 tool_pool_take(shadePool, shade);
719
720 /* Create a blue to yellow (through dark purple) color range. */
721 vectA[0] = 1.33333;
722 vectA[1] = 2.;
723 vectA[2] = -2;
724 vectB[0] = 0.;
725 vectB[1] = -1.;
726 vectB[2] = 1.;
727 shade = tool_shade_new(_("blue to yellow"), vectA, vectB, TOOL_SHADE_COLOR_MODE_RGB);
728 shade->userDefined = FALSE;
729 tool_pool_take(shadePool, shade);
730
731 /* Create a blue and red shade with black zero centred. */
732 vectA[0] = -2.;
733 vectA[1] = 0.;
734 vectA[2] = 2.;
735 vectB[0] = 1.;
736 vectB[1] = 0.;
737 vectB[2] = -1.;
738 shade = tool_shade_new(_("zero centred dark"), vectA, vectB, TOOL_SHADE_COLOR_MODE_RGB);
739 shade->userDefined = FALSE;
740 tool_pool_take(shadePool, shade);
741
742 /* Create a blue and red shade with withe zero centred. */
743 shade = tool_shade_newFromData(_("zero centred light"), zclLn,
744 zclR, zclG, zclB, TOOL_SHADE_COLOR_MODE_RGB);
745 shade->userDefined = FALSE;
746 tool_pool_take(shadePool, shade);
747
748 shade = tool_shade_newFromData(_("zero centred coloured"), zccLn,
749 zccH, zccS, zccV, TOOL_SHADE_COLOR_MODE_HSV);
750 shade->userDefined = FALSE;
751 tool_pool_take(shadePool, shade);
752
753 /* Create a green to red color range. */
754 vectA[0] = -.3333;
755 vectA[1] = 0.;
756 vectA[2] = 0.;
757 vectB[0] = 0.3333;
758 vectB[1] = 1.;
759 vectB[2] = 1.;
760 shade = tool_shade_new(_("green to red"), vectA, vectB, TOOL_SHADE_COLOR_MODE_HSV);
761 shade->userDefined = FALSE;
762 tool_pool_take(shadePool, shade);
763
764 /* Create a white to red color range. */
765 vectA[0] = -.3333;
766 vectA[1] = 0.8;
767 vectA[2] = 0.;
768 vectB[0] = 0.3333;
769 vectB[1] = 0.1;
770 vectB[2] = 1.;
771 shade = tool_shade_new(_("light green to red"), vectA, vectB, TOOL_SHADE_COLOR_MODE_HSV);
772 shade->userDefined = FALSE;
773 tool_pool_take(shadePool, shade);
774
775 /* Create a black to white color range. */
776 vectA[0] = 0.;
777 vectA[1] = 0.;
778 vectA[2] = 1.;
779 vectB[0] = 0.;
780 vectB[1] = 0.;
781 vectB[2] = 0.;
782 shade = tool_shade_new(_("black to white"), vectA, vectB, TOOL_SHADE_COLOR_MODE_HSV);
783 shade->userDefined = FALSE;
784 tool_pool_take(shadePool, shade);
785
786 /* Create a black to white color range. */
787 vectA[0] = 0.;
788 vectA[1] = 0.;
789 vectA[2] = -1.;
790 vectB[0] = 0.;
791 vectB[1] = 0.;
792 vectB[2] = 1.;
793 shade = tool_shade_new(_("white to black"), vectA, vectB, TOOL_SHADE_COLOR_MODE_HSV);
794 shade->userDefined = FALSE;
795 tool_pool_take(shadePool, shade);
796
797 /* Create a black to red (through purple) color range. */
798 vectA[0] = 1.;
799 vectA[1] = 1.;
800 vectA[2] = 1.;
801 vectB[0] = 0.;
802 vectB[1] = 0.;
803 vectB[2] = 0.;
804 shade = tool_shade_new(_("purple color"), vectA, vectB, TOOL_SHADE_COLOR_MODE_HSV);
805 shade->userDefined = FALSE;
806 tool_pool_take(shadePool, shade);
807
808 /* Create the so-called Jet colour map. */
809 shade = tool_shade_newFromData(_("Jet map"), jetn,
810 jetR, jetG, jetB, TOOL_SHADE_COLOR_MODE_RGB);
811 shade->userDefined = FALSE;
812 tool_pool_take(shadePool, shade);
813 }
814
parseValue(gchar * line,float * index,float rgb[3],GError ** error)815 static gboolean parseValue(gchar *line, float *index, float rgb[3], GError **error)
816 {
817 gchar *name;
818 PangoColor color;
819 double index_;
820
821 DBG_fprintf(stderr, "Tool Shade: parse step from '%s'\n", line);
822 index_ = g_ascii_strtod(line, &name);
823 if (errno != 0 || name == line)
824 {
825 *error = g_error_new(TOOL_CONFIG_FILE_ERROR, TOOL_CONFIG_FILE_ERROR_READ,
826 _("1 floating point value should start a step '%s'.\n"), line);
827 return FALSE;
828 }
829 *index = (float)index_;
830 DBG_fprintf(stderr, " | index %g\n", *index);
831
832 name += 1;
833 g_strdelimit(name, "\"'", ' ');
834 g_strstrip(name);
835 if (!pango_color_parse(&color, name))
836 {
837 *error = g_error_new(TOOL_CONFIG_FILE_ERROR, TOOL_CONFIG_FILE_ERROR_READ,
838 _("cannot read a color from '%s' (name, #rgb, #rrggbb ... awaited).\n"),
839 name);
840 return FALSE;
841 }
842 rgb[0] = (float)color.red / (float)G_MAXUINT16;
843 rgb[1] = (float)color.green / (float)G_MAXUINT16;
844 rgb[2] = (float)color.blue / (float)G_MAXUINT16;
845 DBG_fprintf(stderr, " | color %fx%fx%f\n", rgb[0], rgb[1], rgb[2]);
846
847 return TRUE;
848 }
exportParameters(GString * data,VisuData * dataObj _U_)849 static void exportParameters(GString *data, VisuData *dataObj _U_)
850 {
851 GList *lst;
852 ToolShade *shade;
853 guint i;
854 PangoColor pcolor;
855 gchar *color;
856 GString *buf;
857
858 visu_config_file_exportComment(data, DESC_SHADE);
859 for (lst = tool_pool_asList(shadePool); lst; lst = g_list_next(lst))
860 if (((ToolShade*)lst->data)->userDefined)
861 {
862 shade = (ToolShade*)lst->data;
863 buf = g_string_new("");
864 if (shade->userDefined)
865 g_string_append(buf, shade->steps);
866 else
867 for (i = 0; i < shade->nVals ; i++)
868 {
869 if (i != 0)
870 g_string_append_printf(buf, ", ");
871 pcolor.red = (guint16)(shade->vectCh[0][i] * (gfloat)G_MAXUINT16);
872 pcolor.green = (guint16)(shade->vectCh[1][i] * (gfloat)G_MAXUINT16);
873 pcolor.blue = (guint16)(shade->vectCh[2][i] * (gfloat)G_MAXUINT16);
874 color = pango_color_to_string(&pcolor);
875 g_string_append_printf(buf, "%g %s", shade->index[i], color);
876 g_free(color);
877 }
878 visu_config_file_exportEntry(data, FLAG_SHADE, shade->labelUTF8,
879 "%s", buf->str);
880 g_string_free(buf, TRUE);
881 }
882 visu_config_file_exportComment(data, "");
883 }
readShade(VisuConfigFileEntry * entry,gchar ** lines,int nbLines _U_,int position _U_,GError ** error)884 static gboolean readShade(VisuConfigFileEntry *entry, gchar **lines, int nbLines _U_, int position _U_,
885 GError **error)
886 {
887 gchar *name, *descr;
888 char *startDef, *endDef;
889 ToolShade *shade;
890 ToolPool *pool;
891
892 name = g_strdup(visu_config_file_entry_getLabel(entry));
893
894 startDef = strchr(lines[0], '(');
895 if (!startDef)
896 startDef = lines[0];
897 else
898 startDef += 1;
899 endDef = strchr(startDef, ')');
900 if (endDef)
901 descr = g_strndup(startDef, endDef - startDef);
902 else
903 descr = g_strdup(startDef);
904
905 shade = tool_shade_newFromString(g_strstrip(name), descr,
906 TOOL_SHADE_COLOR_MODE_RGB, error);
907 g_free(name);
908 g_free(descr);
909
910 if (!shade)
911 return FALSE;
912 pool = tool_shade_getStorage();
913 tool_pool_take(pool, shade);
914
915 return TRUE;
916 }
917