Code

Adding rendering-intent to <color-profile>
authorjoncruz <joncruz@users.sourceforge.net>
Thu, 6 Apr 2006 07:20:13 +0000 (07:20 +0000)
committerjoncruz <joncruz@users.sourceforge.net>
Thu, 6 Apr 2006 07:20:13 +0000 (07:20 +0000)
ChangeLog
src/Makefile.am
src/Makefile_insert
src/color-profile-fns.h
src/color-profile-test.h [new file with mode: 0644]
src/color-profile.cpp
src/color-profile.h
src/sp-image.cpp

index f57923f4f4381b61132ab2b52de2d264675094d2..07fdbfb2269783826d5ada960027ee6c11df85ef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2006-04-06  Jon A. Cruz  <jon@joncruz.org>
+
+       * src/Makefile_insert, src/Makefile.am, src/color-profile.cpp
+         src/color-profile.h, src/color-profile-fns.h,
+         src/color-profile-test.h, src/sp-image.cpp:
+
+         Adding rendering-intent to <color-profile>.
+
 2006-04-05  MenTaLguY  <mental@rydia.net>
 
        * configure.ac, share/keyboards/.cvsignore, share/keyboards/Makefile.am,
index cf10338813673c594eb7d96d6af4e325a415427c..23aa417af003d2ed047ac54aa4e62c223ac8d4e8 100644 (file)
@@ -235,19 +235,20 @@ test-all.cpp: \
                $(libnr_test_nr_includes)       \
                $(svg_test_svg_includes)        \
                $(xml_test_xml_includes)        \
-               attributes-test.h
+               $(test_all_includes)
        $(top_srcdir)/cxxtest/cxxtestgen.pl --error-printer -root -o test-all.cpp       \
                $(libnr_test_nr_includes)       \
                $(svg_test_svg_includes)        \
                $(xml_test_xml_includes)        \
-               attributes-test.h
+               $(test_all_includes)
 
 test_all_SOURCES = \
        test-all.cpp
 
 
 test_all_LDADD =       \
-       libinkpre.a     \
+       $(all_libs)     \
+       io/libio.a      \
        $(libnr_test_nr_LDADD)  \
        $(svg_test_svg_LDADD)   \
        $(xml_test_xml_LDADD)
index e09b69ffc69e3ed88bc79515144a5255c3901d80..43d85e62e6279c1e62c837f60814b1770b7caebc 100644 (file)
@@ -339,3 +339,7 @@ style_test_LDADD = $(all_libs)
 
 inkscape_version.h: ../configure.ac
        echo '#define INKSCAPE_VERSION "$(VERSION)"' > inkscape_version.h
+
+test_all_includes = \
+               attributes-test.h       \
+               color-profile-test.h
index 96a7410a9de0fe7c4f8d697467a45d98eece9b0e..d7342b09dff020048b24e3a90a9d62c0bd470cfd 100644 (file)
@@ -25,7 +25,7 @@ GType colorprofile_get_type();
 
 #if ENABLE_LCMS
 
-cmsHPROFILE colorprofile_get_handle( SPDocument* document, gchar* const name );
+cmsHPROFILE colorprofile_get_handle( SPDocument* document, guint* intent, gchar* const name );
 
 #endif
 
diff --git a/src/color-profile-test.h b/src/color-profile-test.h
new file mode 100644 (file)
index 0000000..56134ef
--- /dev/null
@@ -0,0 +1,159 @@
+
+
+#include <cxxtest/TestSuite.h>
+#include <cassert>
+
+#include "inkscape-private.h"
+#include "sp-object.h"
+#include "document.h"
+
+#include "color-profile.h"
+#include "color-profile-fns.h"
+
+using Inkscape::ColorProfile;
+
+/// Dummy functions to keep linker happy
+#if !defined(DUMMY_MAIN_TEST_CALLS_SEEN)
+#define DUMMY_MAIN_TEST_CALLS_SEEN
+int sp_main_gui (int, char const**) { return 0; }
+int sp_main_console (int, char const**) { return 0; }
+#endif // DUMMY_MAIN_TEST_CALLS_SEEN
+
+class ColorProfileTest : public CxxTest::TestSuite
+{
+public:
+
+    ColorProfileTest() :
+        TestSuite(),
+        _doc(0)
+    {
+    }
+    virtual ~ColorProfileTest() {}
+
+// createSuite and destroySuite get us per-suite setup and teardown
+// without us having to worry about static initialization order, etc.
+    static ColorProfileTest *createSuite()
+    {
+        ColorProfileTest* suite = 0;
+        bool canRun = false;
+
+        g_type_init();
+        Inkscape::GC::init();
+
+        ColorProfile *prof = static_cast<ColorProfile *>(g_object_new(COLORPROFILE_TYPE, NULL));
+        canRun = prof;
+        canRun &= prof->rendering_intent == (guint)Inkscape::RENDERING_INTENT_UNKNOWN;
+        TS_ASSERT_EQUALS( prof->rendering_intent, (guint)Inkscape::RENDERING_INTENT_UNKNOWN );
+        g_object_unref(prof);
+
+        if ( canRun ) {
+            // Create the global inkscape object.
+            static_cast<void>(g_object_new(inkscape_get_type(), NULL));
+            SPDocument* tmp = sp_document_new_dummy();
+            if ( tmp ) {
+                suite = new ColorProfileTest();
+                suite->_doc = tmp;
+            }
+        }
+
+        return suite;
+    }
+
+    static void destroySuite( ColorProfileTest *suite )
+    {
+        delete suite; 
+    }
+
+
+    SPDocument* _doc;
+
+    // ---------------------------------------------------------------
+
+    void testSetRenderingIntent()
+    {
+        struct {
+            gchar const *attr;
+            guint intVal;
+        }
+        const cases[] = {
+            {"auto", (guint)Inkscape::RENDERING_INTENT_AUTO},
+            {"perceptual", (guint)Inkscape::RENDERING_INTENT_PERCEPTUAL},
+            {"relative-colorimetric", (guint)Inkscape::RENDERING_INTENT_RELATIVE_COLORIMETRIC},
+            {"saturation", (guint)Inkscape::RENDERING_INTENT_SATURATION},
+            {"absolute-colorimetric", (guint)Inkscape::RENDERING_INTENT_ABSOLUTE_COLORIMETRIC},
+            {"something-else", (guint)Inkscape::RENDERING_INTENT_UNKNOWN},
+            {"auto2", (guint)Inkscape::RENDERING_INTENT_UNKNOWN},
+        };
+
+        ColorProfile *prof = static_cast<ColorProfile *>(g_object_new(COLORPROFILE_TYPE, NULL));
+        TS_ASSERT( prof );
+        SP_OBJECT(prof)->document = _doc;
+
+        for ( size_t i = 0; i < G_N_ELEMENTS( cases ); i++ ) {
+            std::string descr(cases[i].attr);
+            sp_object_set(SP_OBJECT(prof), SP_ATTR_RENDERING_INTENT, cases[i].attr);
+            TSM_ASSERT_EQUALS( descr, prof->rendering_intent, (guint)cases[i].intVal );
+        }
+
+        g_object_unref(prof);
+    }
+
+    void testSetLocal()
+    {
+        gchar const* cases[] = {
+            "local",
+            "something",
+        };
+
+        ColorProfile *prof = static_cast<ColorProfile *>(g_object_new(COLORPROFILE_TYPE, NULL));
+        TS_ASSERT( prof );
+        SP_OBJECT(prof)->document = _doc;
+
+        for ( size_t i = 0; i < G_N_ELEMENTS( cases ); i++ ) {
+            sp_object_set(SP_OBJECT(prof), SP_ATTR_LOCAL, cases[i]);
+            TS_ASSERT( prof->local );
+            if ( prof->local ) {
+                TS_ASSERT_EQUALS( std::string(prof->local), std::string(cases[i]) );
+            }
+        }
+        sp_object_set(SP_OBJECT(prof), SP_ATTR_LOCAL, NULL);
+        TS_ASSERT_EQUALS( prof->local, (gchar*)0 );
+
+        g_object_unref(prof);
+    }
+
+    void testSetName()
+    {
+        gchar const* cases[] = {
+            "name",
+            "something",
+        };
+
+        ColorProfile *prof = static_cast<ColorProfile *>(g_object_new(COLORPROFILE_TYPE, NULL));
+        TS_ASSERT( prof );
+        SP_OBJECT(prof)->document = _doc;
+
+        for ( size_t i = 0; i < G_N_ELEMENTS( cases ); i++ ) {
+            sp_object_set(SP_OBJECT(prof), SP_ATTR_NAME, cases[i]);
+            TS_ASSERT( prof->name );
+            if ( prof->name ) {
+                TS_ASSERT_EQUALS( std::string(prof->name), std::string(cases[i]) );
+            }
+        }
+        sp_object_set(SP_OBJECT(prof), SP_ATTR_NAME, NULL);
+        TS_ASSERT_EQUALS( prof->name, (gchar*)0 );
+
+        g_object_unref(prof);
+    }
+};
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index b9e42ccbdde34a3634e37034d727aa7ed81b240d..7b03c77736d7ea540c088e034a1c4d77ff836496 100644 (file)
@@ -9,6 +9,8 @@
 using Inkscape::ColorProfile;
 using Inkscape::ColorProfileClass;
 
+namespace Inkscape
+{
 static void colorprofile_class_init( ColorProfileClass *klass );
 static void colorprofile_init( ColorProfile *cprof );
 
@@ -16,6 +18,7 @@ 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 );
+}
 
 static SPObject *cprof_parent_class;
 
@@ -44,7 +47,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 +62,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 +77,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 +95,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 +111,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 +131,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 );
@@ -153,28 +166,53 @@ static void colorprofile_set( SPObject *object, unsigned key, gchar const *value
 #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 );
+            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:
@@ -183,12 +221,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);
 
@@ -197,19 +236,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) {
@@ -251,7 +290,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;
 
@@ -261,6 +300,10 @@ 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;
+    }
+
     return prof;
 }
 #endif // ENABLE_LCMS
index a6a83ccb57d77664ef77764cac57766ef2e81299..76e25d0655085c8946b6420d3ae13d7a6f734613 100644 (file)
 
 namespace Inkscape {
 
+enum {
+    RENDERING_INTENT_UNKNOWN = 0,
+    RENDERING_INTENT_AUTO = 1,
+    RENDERING_INTENT_PERCEPTUAL = 2,
+    RENDERING_INTENT_RELATIVE_COLORIMETRIC = 3,
+    RENDERING_INTENT_SATURATION = 4,
+    RENDERING_INTENT_ABSOLUTE_COLORIMETRIC = 5
+};
+
 /** Color Profile. */
 struct ColorProfile : public SPObject {
     gchar* href;
     gchar* local;
     gchar* name;
+    gchar* intentStr;
     guint rendering_intent;
 #if ENABLE_LCMS
     cmsHPROFILE profHandle;
index 6a848c1bccb7cf5a6450661739ff0901a885cb82..83b623dbc80f4f7b1248f10bdeec569236cf9abc 100644 (file)
@@ -38,6 +38,7 @@
 #include <png.h>
 #if ENABLE_LCMS
 #include "color-profile-fns.h"
+#include "color-profile.h"
 #endif // ENABLE_LCMS
 /*
  * SPImage
@@ -665,16 +666,36 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
                                     guchar* px = gdk_pixbuf_get_pixels( pixbuf );
 
                                     if ( px ) {
-                                        cmsHPROFILE prof = Inkscape::colorprofile_get_handle( SP_OBJECT_DOCUMENT( object ), image->color_profile );
+                                        guint profIntent = Inkscape::RENDERING_INTENT_UNKNOWN;
+                                        cmsHPROFILE prof = Inkscape::colorprofile_get_handle( SP_OBJECT_DOCUMENT( object ),
+                                                                                              &profIntent,
+                                                                                              image->color_profile );
                                         if ( prof ) {
                                             icProfileClassSignature profileClass = cmsGetDeviceClass( prof );
                                             if ( profileClass != icSigNamedColorClass ) {
+                                                int intent = INTENT_PERCEPTUAL;
+                                                switch ( profIntent ) {
+                                                    case Inkscape::RENDERING_INTENT_RELATIVE_COLORIMETRIC:
+                                                        intent = INTENT_RELATIVE_COLORIMETRIC;
+                                                        break;
+                                                    case Inkscape::RENDERING_INTENT_SATURATION:
+                                                        intent = INTENT_SATURATION;
+                                                        break;
+                                                    case Inkscape::RENDERING_INTENT_ABSOLUTE_COLORIMETRIC:
+                                                        intent = INTENT_ABSOLUTE_COLORIMETRIC;
+                                                        break;
+                                                    case Inkscape::RENDERING_INTENT_PERCEPTUAL:
+                                                    case Inkscape::RENDERING_INTENT_UNKNOWN:
+                                                    case Inkscape::RENDERING_INTENT_AUTO:
+                                                    default:
+                                                        intent = INTENT_PERCEPTUAL;
+                                                }
                                                 cmsHPROFILE destProf = cmsCreate_sRGBProfile();
                                                 cmsHTRANSFORM transf = cmsCreateTransform( prof, 
                                                                                            TYPE_RGBA_8,
                                                                                            destProf,
                                                                                            TYPE_RGBA_8,
-                                                                                           INTENT_PERCEPTUAL, 0 );
+                                                                                           intent, 0 );
                                                 if ( transf ) {
                                                     guchar* currLine = px;
                                                     for ( int y = 0; y < imageheight; y++ ) {