3 #include "xml/repr.h"
4 #include "color-profile.h"
5 #include "color-profile-fns.h"
6 #include "attributes.h"
7 #include "document.h"
9 using Inkscape::ColorProfile;
10 using Inkscape::ColorProfileClass;
12 namespace Inkscape
13 {
14 static void colorprofile_class_init( ColorProfileClass *klass );
15 static void colorprofile_init( ColorProfile *cprof );
17 static void colorprofile_release( SPObject *object );
18 static void colorprofile_build( SPObject *object, SPDocument *document, Inkscape::XML::Node *repr );
19 static void colorprofile_set( SPObject *object, unsigned key, gchar const *value );
20 static Inkscape::XML::Node *colorprofile_write( SPObject *object, Inkscape::XML::Node *repr, guint flags );
21 }
23 static SPObject *cprof_parent_class;
25 /**
26 * Register ColorProfile class and return its type.
27 */
28 GType Inkscape::colorprofile_get_type()
29 {
30 static GType type = 0;
31 if (!type) {
32 GTypeInfo info = {
33 sizeof(ColorProfileClass),
34 NULL, NULL,
35 (GClassInitFunc) colorprofile_class_init,
36 NULL, NULL,
37 sizeof(ColorProfile),
38 16,
39 (GInstanceInitFunc) colorprofile_init,
40 NULL, /* value_table */
41 };
42 type = g_type_register_static( SP_TYPE_OBJECT, "ColorProfile", &info, static_cast<GTypeFlags>(0) );
43 }
44 return type;
45 }
47 /**
48 * ColorProfile vtable initialization.
49 */
50 static void Inkscape::colorprofile_class_init( ColorProfileClass *klass )
51 {
52 SPObjectClass *sp_object_class = reinterpret_cast<SPObjectClass *>(klass);
54 cprof_parent_class = static_cast<SPObject*>(g_type_class_ref(SP_TYPE_OBJECT));
56 sp_object_class->release = colorprofile_release;
57 sp_object_class->build = colorprofile_build;
58 sp_object_class->set = colorprofile_set;
59 sp_object_class->write = colorprofile_write;
60 }
62 /**
63 * Callback for ColorProfile object initialization.
64 */
65 static void Inkscape::colorprofile_init( ColorProfile *cprof )
66 {
67 cprof->href = 0;
68 cprof->local = 0;
69 cprof->name = 0;
70 cprof->intentStr = 0;
71 cprof->rendering_intent = Inkscape::RENDERING_INTENT_UNKNOWN;
72 #if ENABLE_LCMS
73 cprof->profHandle = 0;
74 #endif // ENABLE_LCMS
75 }
77 /**
78 * Callback: free object
79 */
80 static void Inkscape::colorprofile_release( SPObject *object )
81 {
82 ColorProfile *cprof = COLORPROFILE(object);
83 if ( cprof->href ) {
84 g_free( cprof->href );
85 cprof->href = 0;
86 }
88 if ( cprof->local ) {
89 g_free( cprof->local );
90 cprof->local = 0;
91 }
93 if ( cprof->name ) {
94 g_free( cprof->name );
95 cprof->name = 0;
96 }
98 if ( cprof->intentStr ) {
99 g_free( cprof->intentStr );
100 cprof->intentStr = 0;
101 }
103 #if ENABLE_LCMS
104 if ( cprof->profHandle ) {
105 cmsCloseProfile( cprof->profHandle );
106 cprof->profHandle = 0;
107 }
108 #endif // ENABLE_LCMS
109 }
111 /**
112 * Callback: set attributes from associated repr.
113 */
114 static void Inkscape::colorprofile_build( SPObject *object, SPDocument *document, Inkscape::XML::Node *repr )
115 {
116 ColorProfile *cprof = COLORPROFILE(object);
117 g_assert(cprof->href == 0);
118 g_assert(cprof->local == 0);
119 g_assert(cprof->name == 0);
120 g_assert(cprof->intentStr == 0);
122 if (((SPObjectClass *) cprof_parent_class)->build) {
123 (* ((SPObjectClass *) cprof_parent_class)->build)(object, document, repr);
124 }
125 sp_object_read_attr( object, "xlink:href" );
126 sp_object_read_attr( object, "local" );
127 sp_object_read_attr( object, "name" );
128 sp_object_read_attr( object, "rendering-intent" );
129 }
131 /**
132 * Callback: set attribute.
133 */
134 static void Inkscape::colorprofile_set( SPObject *object, unsigned key, gchar const *value )
135 {
136 ColorProfile *cprof = COLORPROFILE(object);
138 switch (key) {
139 case SP_ATTR_XLINK_HREF:
140 if ( cprof->href ) {
141 g_free( cprof->href );
142 cprof->href = 0;
143 }
144 if ( value ) {
145 cprof->href = g_strdup( value );
146 if ( *cprof->href ) {
147 #if ENABLE_LCMS
148 cmsErrorAction( LCMS_ERROR_SHOW );
150 // TODO open filename and URIs properly
151 //FILE* fp = fopen_utf8name( filename, "r" );
152 //LCMSAPI cmsHPROFILE LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize);
154 if ( !g_path_is_absolute(cprof->href) ) {
155 // Try to open relative
156 gchar* docbase = SP_DOCUMENT_BASE( SP_OBJECT_DOCUMENT(object) );
157 gchar* fullname = g_build_filename( docbase ? docbase : ".", cprof->href, NULL );
159 cprof->profHandle = cmsOpenProfileFromFile( fullname, "r" );
161 g_free (fullname);
162 } else {
163 cprof->profHandle = cmsOpenProfileFromFile( cprof->href, "r" );
164 }
166 #endif // ENABLE_LCMS
167 }
168 }
169 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
170 break;
172 case SP_ATTR_LOCAL:
173 if ( cprof->local ) {
174 g_free( cprof->local );
175 cprof->local = 0;
176 }
177 cprof->local = g_strdup( value );
178 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
179 break;
181 case SP_ATTR_NAME:
182 if ( cprof->name ) {
183 g_free( cprof->name );
184 cprof->name = 0;
185 }
186 cprof->name = g_strdup( value );
187 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
188 break;
190 case SP_ATTR_RENDERING_INTENT:
191 if ( cprof->intentStr ) {
192 g_free( cprof->intentStr );
193 cprof->intentStr = 0;
194 }
195 cprof->intentStr = g_strdup( value );
197 if ( value ) {
198 if ( strcmp( value, "auto" ) == 0 ) {
199 cprof->rendering_intent = RENDERING_INTENT_AUTO;
200 } else if ( strcmp( value, "perceptual" ) == 0 ) {
201 cprof->rendering_intent = RENDERING_INTENT_PERCEPTUAL;
202 } else if ( strcmp( value, "relative-colorimetric" ) == 0 ) {
203 cprof->rendering_intent = RENDERING_INTENT_RELATIVE_COLORIMETRIC;
204 } else if ( strcmp( value, "saturation" ) == 0 ) {
205 cprof->rendering_intent = RENDERING_INTENT_SATURATION;
206 } else if ( strcmp( value, "absolute-colorimetric" ) == 0 ) {
207 cprof->rendering_intent = RENDERING_INTENT_ABSOLUTE_COLORIMETRIC;
208 } else {
209 cprof->rendering_intent = RENDERING_INTENT_UNKNOWN;
210 }
211 } else {
212 cprof->rendering_intent = RENDERING_INTENT_UNKNOWN;
213 }
215 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
216 break;
218 default:
219 if (((SPObjectClass *) cprof_parent_class)->set) {
220 (* ((SPObjectClass *) cprof_parent_class)->set)(object, key, value);
221 }
222 break;
223 }
225 }
227 /**
228 * Callback: write attributes to associated repr.
229 */
230 static Inkscape::XML::Node* Inkscape::colorprofile_write( SPObject *object, Inkscape::XML::Node *repr, guint flags )
231 {
232 ColorProfile *cprof = COLORPROFILE(object);
234 if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
235 repr = sp_repr_new("svg:color-profile");
236 }
238 if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->href ) {
239 repr->setAttribute( "xlink:href", cprof->href );
240 }
242 if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->local ) {
243 repr->setAttribute( "local", cprof->local );
244 }
246 if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->name ) {
247 repr->setAttribute( "name", cprof->name );
248 }
250 if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->intentStr ) {
251 repr->setAttribute( "rendering-intent", cprof->intentStr );
252 }
254 if (((SPObjectClass *) cprof_parent_class)->write) {
255 (* ((SPObjectClass *) cprof_parent_class)->write)(object, repr, flags);
256 }
258 return repr;
259 }
262 #if ENABLE_LCMS
265 static SPObject* bruteFind( SPObject* curr, gchar* const name )
266 {
267 SPObject* result = 0;
269 if ( curr ) {
270 if ( IS_COLORPROFILE(curr) ) {
271 ColorProfile* prof = COLORPROFILE(curr);
272 if ( prof ) {
273 if ( prof->name && (strcmp(prof->name, name) == 0) ) {
274 result = curr;
275 }
276 }
277 } else {
278 if ( curr->hasChildren() ) {
279 SPObject* child = curr->firstChild();
280 while ( child && !result ) {
281 result = bruteFind( child, name );
282 if ( !result ) {
283 child = child->next;
284 }
285 };
286 }
287 }
288 }
290 return result;
291 }
293 cmsHPROFILE Inkscape::colorprofile_get_handle( SPDocument* document, guint* intent, gchar* const name )
294 {
295 cmsHPROFILE prof = 0;
297 SPObject* root = SP_DOCUMENT_ROOT(document);
298 SPObject* thing = bruteFind( root, name );
299 if ( thing ) {
300 prof = COLORPROFILE(thing)->profHandle;
301 }
303 if ( intent ) {
304 *intent = thing ? COLORPROFILE(thing)->rendering_intent : (guint)RENDERING_INTENT_UNKNOWN;
305 }
307 return prof;
308 }
309 #endif // ENABLE_LCMS
311 /*
312 Local Variables:
313 mode:c++
314 c-file-style:"stroustrup"
315 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
316 indent-tabs-mode:nil
317 fill-column:99
318 End:
319 */
320 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :