ac3b807d14411dcf5120c3e7aa735a0bffbacf18
1 /** \file
2 * Inkscape::Extension::Internal::GimpGrad implementation
3 */
5 /*
6 * Authors:
7 * Ted Gould <ted@gould.cx>
8 *
9 * Copyright (C) 2004-2005 Authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
18 #include <color-rgba.h>
19 #include "io/sys.h"
20 #include "extension/system.h"
22 #include "gimpgrad.h"
24 namespace Inkscape {
25 namespace Extension {
26 namespace Internal {
28 /**
29 \brief A function to allocated anything -- just an example here
30 \param module Unused
31 \return Whether the load was sucessful
32 */
33 bool
34 GimpGrad::load (Inkscape::Extension::Extension *module)
35 {
36 // std::cout << "Hey, I'm loading!\n" << std::endl;
37 return TRUE;
38 }
40 /**
41 \brief A function to remove what was allocated
42 \param module Unused
43 \return None
44 */
45 void
46 GimpGrad::unload (Inkscape::Extension::Extension *module)
47 {
48 // std::cout << "Nooo! I'm being unloaded!" << std::endl;
49 return;
50 }
52 /**
53 \brief A function to turn a color into a gradient stop
54 \param in_color The color for the stop
55 \param location Where the stop is placed in the gradient
56 \return The text that is the stop. Full SVG containing the element.
58 This function encapsulates all of the translation of the ColorRGBA
59 and the location into the gradient. It is really pretty simple except
60 that the ColorRGBA is in floats that are 0 to 1 and the SVG wants
61 hex values from 0 to 255 for color. Otherwise mostly this is just
62 turning the values into strings and returning it.
63 */
64 Glib::ustring
65 GimpGrad::new_stop (ColorRGBA in_color, float location)
66 {
67 char temp_string[25];
68 Glib::ustring mystring("<stop style=\"stop-color:#");
70 for (int i = 0; i < 3; i++) {
71 unsigned char temp;
73 temp = (unsigned char)(in_color[i] * 255.0);
75 sprintf(temp_string, "%2.2X", temp);
76 mystring += temp_string;
77 }
79 mystring += ";stop-opacity:";
80 sprintf(temp_string, "%1.8f", in_color[3]);
81 mystring += temp_string;
82 mystring += ";\" offset=\"";
83 sprintf(temp_string, "%1.8f", location);
84 mystring += temp_string;
85 mystring += "\"/>\n";
86 return mystring;
87 }
89 /**
90 \brief Actually open the gradient and turn it into an SPDocument
91 \param module The input module being used
92 \param filename The filename of the gradient to be opened
93 \return A Document with the gradient in it.
95 GIMP gradients are pretty simple (atleast the newer format, this
96 function does not handle the old one yet). They start out with
97 the like "GIMP Gradient", then name it, and tell how many entries
98 there are. This function currently ignores the name and the number
99 of entries just reading until it fails.
101 The other small piece of trickery here is that GIMP gradients define
102 a left possition, right possition and middle possition. SVG gradients
103 have no middle possition in them. In order to handle this case the
104 left and right colors are averaged in a linear manner and the middle
105 possition is used for that color.
107 That is another point, the GIMP gradients support many different types
108 of gradients -- linear being the most simple. This plugin assumes
109 that they are all linear. Most GIMP gradients are done this way,
110 but it is possible to encounter more complex ones -- which won't be
111 handled correctly.
113 The one optimization that this plugin makes that if the right side
114 of the previous segment is the same color as the left side of the
115 current segment, then the second one is dropped. This is often
116 done in GIMP gradients and they are not necissary in SVG.
118 What this function does is build up an SVG document with a single
119 linear gradient in it with all the stops of the colors in the GIMP
120 gradient that is passed in. This document is then turned into a
121 document using the \c sp_document_from_mem. That is then returned
122 to Inkscape.
123 */
124 SPDocument *
125 GimpGrad::open (Inkscape::Extension::Input *module, gchar const *filename)
126 {
127 FILE * gradient;
128 // std::cout << "Open filename: " << filename << std::endl;
130 Inkscape::IO::dump_fopen_call(filename, "I");
131 gradient = Inkscape::IO::fopen_utf8name(filename, "r");
132 if (gradient == NULL) return NULL;
134 char tempstr[1024];
135 if (fgets(tempstr, 1024, gradient) == 0) {
136 // std::cout << "Seems that the read failed" << std::endl;
137 fclose(gradient);
138 return NULL;
139 }
141 if (!strcmp(tempstr, "GIMP Gradient")) {
142 // std::cout << "This doesn't appear to be a GIMP gradient" << std::endl;
143 fclose(gradient);
144 return NULL;
145 }
147 if (fgets(tempstr, 1024, gradient) == 0) {
148 // std::cout << "Seems that the second read failed" << std::endl;
149 fclose(gradient);
150 return NULL;
151 }
153 if (fgets(tempstr, 1024, gradient) == 0) {
154 // std::cout << "Seems that the third read failed" << std::endl;
155 fclose(gradient);
156 return NULL;
157 }
159 ColorRGBA last_color(-1.0, -1.0, -1.0, -1.0);
160 float lastlocation = -1.0;
161 Glib::ustring outsvg("<svg><defs><linearGradient>\n");
162 while (fgets(tempstr, 1024, gradient) != 0) {
163 float left, middle, right;
164 float temp_color[4];
165 int type;
166 int color;
167 gchar * end;
169 left = g_ascii_strtod(tempstr, &end);
170 middle = g_ascii_strtod(end, &end);
171 right = g_ascii_strtod(end, &end);
173 for (int i = 0; i < 4; i++) {
174 temp_color[i] = g_ascii_strtod(end, &end);
175 }
176 ColorRGBA leftcolor(temp_color[0], temp_color[1], temp_color[2], temp_color[3]);
178 for (int i = 0; i < 4; i++) {
179 temp_color[i] = g_ascii_strtod(end, &end);
180 }
181 ColorRGBA rightcolor(temp_color[0], temp_color[1], temp_color[2], temp_color[3]);
183 sscanf(end, "%d %d", &type, &color);
185 if (!(last_color == leftcolor) || left != lastlocation) {
186 outsvg += new_stop(leftcolor, left);
187 }
188 outsvg += new_stop(leftcolor.average(rightcolor), middle);
189 outsvg += new_stop(rightcolor, right);
191 last_color = rightcolor;
192 lastlocation = right;
193 }
195 outsvg += "</linearGradient></defs></svg>";
197 // std::cout << "SVG Output: " << outsvg << std::endl;
199 fclose(gradient);
201 return sp_document_new_from_mem(outsvg.c_str(), outsvg.length(), TRUE);
202 }
204 #include "clear-n_.h"
206 void
207 GimpGrad::init (void)
208 {
209 Inkscape::Extension::build_from_mem(
210 "<inkscape-extension>\n"
211 "<name>" N_("GIMP Gradients") "</name>\n"
212 "<id>org.inkscape.input.gimpgrad</id>\n"
213 "<input>\n"
214 "<extension>.ggr</extension>\n"
215 "<mimetype>application/x-gimp-gradient</mimetype>\n"
216 "<filetypename>" N_("GIMP Gradient (*.ggr)") "</filetypename>\n"
217 "<filetypetooltip>" N_("Gradients used in GIMP") "</filetypetooltip>\n"
218 "</input>\n"
219 "</inkscape-extension>\n", new GimpGrad());
220 return;
221 }
223 } } } /* namespace Internal; Extension; Inkscape */
225 /*
226 Local Variables:
227 mode:c++
228 c-file-style:"stroustrup"
229 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
230 indent-tabs-mode:nil
231 fill-column:99
232 End:
233 */
234 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :