Code

handle the case of no filter primitives
[inkscape.git] / src / color-profile.cpp
index 049bd14ecf7791cfc8bbb7474cecc3d279f96fc5..7423f93a1e8d17ebeb631c46c9e579d82525e5b5 100644 (file)
@@ -4,11 +4,23 @@
 #include "color-profile.h"
 #include "color-profile-fns.h"
 #include "attributes.h"
+#include "inkscape.h"
 #include "document.h"
 
+#include "dom/uri.h"
+
+//#define DEBUG_LCMS
+
+#ifdef DEBUG_LCMS
+#include "prefs-utils.h"
+#include <gtk/gtkmessagedialog.h>
+#endif // DEBUG_LCMS
+
 using Inkscape::ColorProfile;
 using Inkscape::ColorProfileClass;
 
+namespace Inkscape
+{
 static void colorprofile_class_init( ColorProfileClass *klass );
 static void colorprofile_init( ColorProfile *cprof );
 
@@ -16,6 +28,36 @@ static void colorprofile_release( SPObject *object );
 static void colorprofile_build( SPObject *object, SPDocument *document, Inkscape::XML::Node *repr );
 static void colorprofile_set( SPObject *object, unsigned key, gchar const *value );
 static Inkscape::XML::Node *colorprofile_write( SPObject *object, Inkscape::XML::Node *repr, guint flags );
+}
+
+#ifdef DEBUG_LCMS
+extern guint update_in_progress;
+#define DEBUG_MESSAGE(key, ...) \
+{\
+    gint dump = prefs_get_int_attribute_limited("options.scislac", #key, 0, 0, 1);\
+    gint dumpD = prefs_get_int_attribute_limited("options.scislac", #key"D", 0, 0, 1);\
+    gint dumpD2 = prefs_get_int_attribute_limited("options.scislac", #key"D2", 0, 0, 1);\
+    dumpD &= ( (update_in_progress == 0) || dumpD2 );\
+    if ( dump )\
+    {\
+        g_message( __VA_ARGS__ );\
+\
+    }\
+    if ( dumpD )\
+    {\
+        GtkWidget *dialog = gtk_message_dialog_new(NULL,\
+                                                   GTK_DIALOG_DESTROY_WITH_PARENT, \
+                                                   GTK_MESSAGE_INFO,    \
+                                                   GTK_BUTTONS_OK,      \
+                                                   __VA_ARGS__          \
+                                                   );\
+        g_signal_connect_swapped(dialog, "response",\
+                                 G_CALLBACK(gtk_widget_destroy),        \
+                                 dialog);                               \
+        gtk_widget_show_all( dialog );\
+    }\
+}
+#endif // DEBUG_LCMS
 
 static SPObject *cprof_parent_class;
 
@@ -44,7 +86,7 @@ GType Inkscape::colorprofile_get_type()
 /**
  * ColorProfile vtable initialization.
  */
-static void colorprofile_class_init( ColorProfileClass *klass )
+static void Inkscape::colorprofile_class_init( ColorProfileClass *klass )
 {
     SPObjectClass *sp_object_class = reinterpret_cast<SPObjectClass *>(klass);
 
@@ -59,12 +101,13 @@ static void colorprofile_class_init( ColorProfileClass *klass )
 /**
  * Callback for ColorProfile object initialization.
  */
-static void colorprofile_init( ColorProfile *cprof )
+static void Inkscape::colorprofile_init( ColorProfile *cprof )
 {
     cprof->href = 0;
     cprof->local = 0;
     cprof->name = 0;
-    cprof->rendering_intent = 0;
+    cprof->intentStr = 0;
+    cprof->rendering_intent = Inkscape::RENDERING_INTENT_UNKNOWN;
 #if ENABLE_LCMS
     cprof->profHandle = 0;
 #endif // ENABLE_LCMS
@@ -73,7 +116,7 @@ static void colorprofile_init( ColorProfile *cprof )
 /**
  * Callback: free object
  */
-static void colorprofile_release( SPObject *object )
+static void Inkscape::colorprofile_release( SPObject *object )
 {
     ColorProfile *cprof = COLORPROFILE(object);
     if ( cprof->href ) {
@@ -91,6 +134,11 @@ static void colorprofile_release( SPObject *object )
         cprof->name = 0;
     }
 
+    if ( cprof->intentStr ) {
+        g_free( cprof->intentStr );
+        cprof->intentStr = 0;
+    }
+
 #if ENABLE_LCMS
     if ( cprof->profHandle ) {
         cmsCloseProfile( cprof->profHandle );
@@ -102,12 +150,13 @@ static void colorprofile_release( SPObject *object )
 /**
  * Callback: set attributes from associated repr.
  */
-static void colorprofile_build( SPObject *object, SPDocument *document, Inkscape::XML::Node *repr )
+static void Inkscape::colorprofile_build( SPObject *object, SPDocument *document, Inkscape::XML::Node *repr )
 {
     ColorProfile *cprof = COLORPROFILE(object);
     g_assert(cprof->href == 0);
     g_assert(cprof->local == 0);
     g_assert(cprof->name == 0);
+    g_assert(cprof->intentStr == 0);
 
     if (((SPObjectClass *) cprof_parent_class)->build) {
         (* ((SPObjectClass *) cprof_parent_class)->build)(object, document, repr);
@@ -121,15 +170,18 @@ static void colorprofile_build( SPObject *object, SPDocument *document, Inkscape
 /**
  * Callback: set attribute.
  */
-static void colorprofile_set( SPObject *object, unsigned key, gchar const *value )
+static void Inkscape::colorprofile_set( SPObject *object, unsigned key, gchar const *value )
 {
     ColorProfile *cprof = COLORPROFILE(object);
 
     switch (key) {
         case SP_ATTR_XLINK_HREF:
+            if ( cprof->href ) {
+                g_free( cprof->href );
+                cprof->href = 0;
+            }
             if ( value ) {
                 cprof->href = g_strdup( value );
-                object->requestModified(SP_OBJECT_MODIFIED_FLAG);
                 if ( *cprof->href ) {
 #if ENABLE_LCMS
                     cmsErrorAction( LCMS_ERROR_SHOW );
@@ -137,32 +189,86 @@ static void colorprofile_set( SPObject *object, unsigned key, gchar const *value
                     // TODO open filename and URIs properly
                     //FILE* fp = fopen_utf8name( filename, "r" );
                     //LCMSAPI cmsHPROFILE   LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize);
-                    cprof->profHandle = cmsOpenProfileFromFile( value, "r" );
+
+                    // Try to open relative
+                    SPDocument *doc = SP_OBJECT_DOCUMENT(object);
+                    if (!doc) {
+                        doc = SP_ACTIVE_DOCUMENT;
+                        g_warning("object has no document.  using active");
+                    }
+                    //# 1.  Get complete URI of document
+                    gchar* docbase = SP_DOCUMENT_URI( doc );
+                    if (!docbase)
+                        {
+                        g_warning("null docbase");
+                        docbase = "";
+                        }
+                    //g_message("docbase:%s\n", docbase);
+                    org::w3c::dom::URI docUri(docbase);
+                    //# 2. Get href of icc file.  we don't care if it's rel or abs
+                    org::w3c::dom::URI hrefUri(cprof->href);
+                    //# 3.  Resolve the href according the docBase.  This follows
+                    //      the w3c specs.  All absolute and relative issues are considered
+                    org::w3c::dom::URI cprofUri = docUri.resolve(hrefUri);
+                    gchar* fullname = (gchar *)cprofUri.getNativePath().c_str();
+                    cprof->profHandle = cmsOpenProfileFromFile( fullname, "r" );
+#ifdef DEBUG_LCMS
+                    DEBUG_MESSAGE( lcmsOne, "cmsOpenProfileFromFile( '%s'...) = %p", fullname, (void*)cprof->profHandle );
+#endif // DEBUG_LCMS
+
 #endif // ENABLE_LCMS
                 }
             }
+            object->requestModified(SP_OBJECT_MODIFIED_FLAG);
             break;
 
         case SP_ATTR_LOCAL:
-            if ( value ) {
-                cprof->local = g_strdup( value );
-                object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            if ( cprof->local ) {
+                g_free( cprof->local );
+                cprof->local = 0;
             }
+            cprof->local = g_strdup( value );
+            object->requestModified(SP_OBJECT_MODIFIED_FLAG);
             break;
 
         case SP_ATTR_NAME:
-            if ( value ) {
-                cprof->name = g_strdup( value );
-                object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            if ( cprof->name ) {
+                g_free( cprof->name );
+                cprof->name = 0;
             }
+            cprof->name = g_strdup( value );
+#ifdef DEBUG_LCMS
+            DEBUG_MESSAGE( lcmsTwo, "<color-profile> name set to '%s'", cprof->name );
+#endif // DEBUG_LCMS
+            object->requestModified(SP_OBJECT_MODIFIED_FLAG);
             break;
 
         case SP_ATTR_RENDERING_INTENT:
+            if ( cprof->intentStr ) {
+                g_free( cprof->intentStr );
+                cprof->intentStr = 0;
+            }
+            cprof->intentStr = g_strdup( value );
+
             if ( value ) {
-// auto | perceptual | relative-colorimetric | saturation | absolute-colorimetric
-                //cprof->name = g_strdup( value );
-                //object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+                if ( strcmp( value, "auto" ) == 0 ) {
+                    cprof->rendering_intent = RENDERING_INTENT_AUTO;
+                } else if ( strcmp( value, "perceptual" ) == 0 ) {
+                    cprof->rendering_intent = RENDERING_INTENT_PERCEPTUAL;
+                } else if ( strcmp( value, "relative-colorimetric" ) == 0 ) {
+                    cprof->rendering_intent = RENDERING_INTENT_RELATIVE_COLORIMETRIC;
+                } else if ( strcmp( value, "saturation" ) == 0 ) {
+                    cprof->rendering_intent = RENDERING_INTENT_SATURATION;
+                } else if ( strcmp( value, "absolute-colorimetric" ) == 0 ) {
+                    cprof->rendering_intent = RENDERING_INTENT_ABSOLUTE_COLORIMETRIC;
+                } else {
+                    cprof->rendering_intent = RENDERING_INTENT_UNKNOWN;
+                }
+            } else {
+                cprof->rendering_intent = RENDERING_INTENT_UNKNOWN;
             }
+
+            object->requestModified(SP_OBJECT_MODIFIED_FLAG);
             break;
 
         default:
@@ -171,12 +277,13 @@ static void colorprofile_set( SPObject *object, unsigned key, gchar const *value
             }
             break;
     }
+
 }
 
 /**
  * Callback: write attributes to associated repr.
  */
-static Inkscape::XML::Node* colorprofile_write( SPObject *object, Inkscape::XML::Node *repr, guint flags )
+static Inkscape::XML::Node* Inkscape::colorprofile_write( SPObject *object, Inkscape::XML::Node *repr, guint flags )
 {
     ColorProfile *cprof = COLORPROFILE(object);
 
@@ -185,19 +292,19 @@ static Inkscape::XML::Node* colorprofile_write( SPObject *object, Inkscape::XML:
     }
 
     if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->href ) {
-        repr->setAttribute( "xlink:href", cprof->name );
+        repr->setAttribute( "xlink:href", cprof->href );
     }
 
-    if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->href ) {
-        repr->setAttribute( "local", cprof->name );
+    if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->local ) {
+        repr->setAttribute( "local", cprof->local );
     }
 
-    if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->href ) {
+    if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->name ) {
         repr->setAttribute( "name", cprof->name );
     }
 
-    if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->href ) {
-//        repr->setAttribute( "rendering-intent", cprof->name );
+    if ( (flags & SP_OBJECT_WRITE_ALL) || cprof->intentStr ) {
+        repr->setAttribute( "rendering-intent", cprof->intentStr );
     }
 
     if (((SPObjectClass *) cprof_parent_class)->write) {
@@ -239,7 +346,7 @@ static SPObject* bruteFind( SPObject* curr, gchar* const name )
     return result;
 }
 
-cmsHPROFILE Inkscape::colorprofile_get_handle( SPDocument* document, gchar* const name )
+cmsHPROFILE Inkscape::colorprofile_get_handle( SPDocument* document, guint* intent, gchar* const name )
 {
     cmsHPROFILE prof = 0;
 
@@ -249,6 +356,14 @@ cmsHPROFILE Inkscape::colorprofile_get_handle( SPDocument* document, gchar* cons
         prof = COLORPROFILE(thing)->profHandle;
     }
 
+    if ( intent ) {
+        *intent = thing ? COLORPROFILE(thing)->rendering_intent : (guint)RENDERING_INTENT_UNKNOWN;
+    }
+
+#ifdef DEBUG_LCMS
+    DEBUG_MESSAGE( lcmsThree, "<color-profile> queried for profile of '%s'. Returning %p with intent of %d", name, prof, (intent? *intent:0) );
+#endif // DEBUG_LCMS
+
     return prof;
 }
 #endif // ENABLE_LCMS