File: script-fu-color.c

package info (click to toggle)
gimp 3.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 222,880 kB
  • sloc: ansic: 870,914; python: 10,965; lisp: 10,857; cpp: 7,355; perl: 4,536; sh: 1,753; xml: 972; yacc: 609; lex: 348; javascript: 150; makefile: 42
file content (226 lines) | stat: -rw-r--r-- 6,829 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <libgimp/gimp.h>

#include "script-fu-color.h"
#include "script-fu-types.h"


/* This encapsulates the implementation of the SFColorType.
 * It knows how to manipulate a SFArg of that type.
 * SFArg is the original abstraction
 * that in other parts of Gimp is a property and its metadata GParamSpec.
 *
 * Separate because it is likely to change and is slightly complex.
 *
 * Likely to change:
 *  - recently changed to use GeglColor in the PDB and GUI
 *  - planned change is to eliminate the duplicate old-style interface.
 *  - New-style ScriptFu scripts may not need to keep actual values
 *    and default values, only the declarations of defaults etc.
 *    Since a GimpProcedureConfig carries the values
 *    and GParamSpec carries the defaults.
 *  - ScriptFu might support other formats
 *
 * Complex:
 * PDB and widgets traffic in GeglColor but SF dumbs it down to a Scheme list
 * e.g. (r g b) (r g b a) or (y) or (y a)
 *
 * More SF code deals with GeglColor:
 * see scheme_marshall.c we marshall from GeglColor to/from Scheme lists of numbers.
 */


/* Return the Scheme representation.
 * Caller owns returned string.
 *
 * An alias: knows SFColorType is GeglColor
 */
gchar*
sf_color_get_repr (SFColorType arg_value)
{
  return sf_color_get_repr_from_gegl_color (arg_value);
}

/* Returns GeglColor from arg of type SFColorType.
 * When arg is NULL, returns GeglColor transparent.
 *
 * Returned GeglColor is owned by caller.
 */
GeglColor *
sf_color_get_gegl_color (SFColorType arg_value)
{
  return arg_value ? gegl_color_duplicate (arg_value) : gegl_color_new ("transparent");
}

/* Set an SFArg of type SFColorType from a GeglColor.
 * color is owned by caller.
 */
void
sf_color_set_from_gegl_color (SFColorType *arg_value,
                              GeglColor   *color)
{
  if (*arg_value)
    {
      /* Arg is already a GeglColor, change its color. */
      const Babl *format = gegl_color_get_format (color);
      guint8      pixel[48];

      gegl_color_get_pixel (color, format, pixel);
      gegl_color_set_pixel (*arg_value, format, pixel);
    }
  else
    {
      /* Arg is NULL.  Duplicate given color. */
      *arg_value = gegl_color_duplicate (color);
    }
}

/* Set the default for an arg of type SFColorType from a string name.
 *
 * The default value is later put in default of param spec when creating procedure.
 *
 * Also, the old-style dialog resets from the kept default value.
 * Versus new-style dialog, using ProcedureConfig, which resets from a paramspec.
 *
 * Called at registration time.
 *
 * Returns FALSE when name_of_default is not the name of a color,
 * and then the default is not set properly.
 */
gboolean
sf_color_arg_set_default_by_name (SFArg *arg,
                                  gchar *name_of_default)
{
  gboolean   result = TRUE;
  GeglColor *color;

  /* Create a default value for the old-style interface.
   */
  if (! (color = gimp_color_parse_css (name_of_default)))
    {
      result = FALSE;
    }
  else
    {
      /* css named colors are in sRGB.
       * You cannot name a grayscale color.
       * However, "transparent" is also a css named color.
       */
      /* We don't override alpha:
       * Not calling: gimp_color_set_alpha (color, 1.0);
       */

      /* Expect the default is NULL, but call the setter anyway,
       * which sets it when not already NULL.
       */
      sf_color_set_from_gegl_color (&arg->default_value.sfa_color, color);

      g_object_unref (color);
    }
  return result;
}

/* Set the default for an arg of type SFColorType from a GeglColor.
 *
 * This knows the proper field of the arg.
 */
void
sf_color_arg_set_default_by_color (SFArg     *arg,
                                   GeglColor *color)
{
  sf_color_set_from_gegl_color (&arg->default_value.sfa_color, color);
}

/* Return the color of the default.
 *
 * Agnostic whether the default was declared by name or color (list of numbers.)
 *
 * The returned color is owned by the caller and must be freed.
 */
GeglColor*
sf_color_arg_get_default_color (SFArg *arg)
{
  /* require the default was set earlier.
   * No easy way to assert it was set.
   */
  return sf_color_get_gegl_color (arg->default_value.sfa_color);
}


/* Methods for conversion GeglColor to/from Scheme representation. */

/* Convert GeglColor to scheme representation as list of numeric.
 * List is length in [0,4].
 * Caller owns returned string.
 * Length depends on format: GRAY, GRAYA, RGB, or RGBA.
 * Returns literal for empty list when color is NULL.
 */
gchar*
sf_color_get_repr_from_gegl_color (GeglColor *color)
{
  gchar *result;

  if (color == NULL)
    {
      result = g_strdup_printf ("'()");
    }
  else
    {
      guint  count_components = babl_format_get_n_components (gegl_color_get_format (color));
      guchar rgba[4] = { 0 };

      /* Dispatch on count of components. */
      switch (count_components)
      {
      case 1:
        gegl_color_get_pixel (color, babl_format ("Y' u8"), rgba);
        result = g_strdup_printf ("'(%d)", (gint) rgba[0]);
        break;
      case 2:
        gegl_color_get_pixel (color, babl_format ("Y'A u8"), rgba);
        result = g_strdup_printf ("'(%d %d)", (gint) rgba[0], (gint) rgba[1]);
        break;
      case 3:
        gegl_color_get_pixel (color, babl_format ("R'G'B' u8"), rgba);
        result = g_strdup_printf ("'(%d %d %d)", (gint) rgba[0], (gint) rgba[1], (gint) rgba[2]);
        break;
      case 4:
        gegl_color_get_pixel (color, babl_format ("R'G'B'A u8"), rgba);
        result = g_strdup_printf ("'(%d %d %d %d)",
                                  (gint) rgba[0], (gint) rgba[1], (gint) rgba[2], (gint) rgba[3]);
        break;
      default:
          g_warning ("%s unhandled count of color components", G_STRFUNC);
          result = g_strdup_printf ("'()");
      }
    }

  return result;
}

/* Caller owns the returned GeglColor.
 * Returns NULL when name is not of a color.
 */
GeglColor *
sf_color_get_color_from_name (gchar *color_name)
{
  return gimp_color_parse_css (color_name);
}