Code

Initial cut of softproofing
authorjoncruz <joncruz@users.sourceforge.net>
Wed, 3 Oct 2007 01:47:41 +0000 (01:47 +0000)
committerjoncruz <joncruz@users.sourceforge.net>
Wed, 3 Oct 2007 01:47:41 +0000 (01:47 +0000)
src/color-profile-fns.h
src/color-profile.cpp
src/display/sp-canvas.cpp
src/preferences-skeleton.h
src/ui/dialog/inkscape-preferences.cpp
src/ui/dialog/inkscape-preferences.h

index 93d327f423c159d68292cdaf9fe3566555b137b2..24044ddce27dc4d23b688cedebf796d9393e25e8 100644 (file)
@@ -28,10 +28,10 @@ GType colorprofile_get_type();
 #if ENABLE_LCMS
 
 cmsHPROFILE colorprofile_get_handle( SPDocument* document, guint* intent, gchar const* name );
-
-cmsHPROFILE colorprofile_get_system_profile_handle();
+cmsHTRANSFORM colorprofile_get_display_transform();
 
 std::vector<Glib::ustring> colorprofile_get_display_names();
+std::vector<Glib::ustring> colorprofile_get_softproof_names();
 
 Glib::ustring get_path_for_profile(Glib::ustring const& name);
 
index bdfa694f022e4901beea11074f95e9e9aae77609..7cd4df5986ef4cf216759b5a68344772de084913 100644 (file)
@@ -31,6 +31,9 @@ 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 cmsHPROFILE colorprofile_get_system_profile_handle();
+static cmsHPROFILE colorprofile_get_proof_profile_handle();
 }
 
 #ifdef DEBUG_LCMS
@@ -417,6 +420,19 @@ std::vector<Glib::ustring> Inkscape::colorprofile_get_display_names()
     return result;
 }
 
+std::vector<Glib::ustring> Inkscape::colorprofile_get_softproof_names()
+{
+    std::vector<Glib::ustring> result;
+
+    for ( std::vector<ProfileInfo>::iterator it = knownProfiles.begin(); it != knownProfiles.end(); ++it ) {
+        if ( it->getClass() == icSigOutputClass ) {
+            result.push_back( it->getName() );
+        }
+    }
+
+    return result;
+}
+
 Glib::ustring Inkscape::get_path_for_profile(Glib::ustring const& name)
 {
     Glib::ustring result;
@@ -529,6 +545,9 @@ int errorHandlerCB(int ErrorCode, const char *ErrorText)
     return 1;
 }
 
+static bool gamutWarn = false;
+static cmsHTRANSFORM transf = 0;
+static cmsHPROFILE srcprof = 0;
 
 cmsHPROFILE Inkscape::colorprofile_get_system_profile_handle()
 {
@@ -552,12 +571,76 @@ cmsHPROFILE Inkscape::colorprofile_get_system_profile_handle()
             if ( theOne ) {
                 cmsCloseProfile( theOne );
             }
+            if ( transf ) {
+                cmsDeleteTransform( transf );
+                transf = 0;
+            }
+            theOne = cmsOpenProfileFromFile( uri, "r" );
+            if ( theOne ) {
+                // a display profile must have the proper stuff
+                icColorSpaceSignature space = cmsGetColorSpace(theOne);
+                icProfileClassSignature profClass = cmsGetDeviceClass(theOne);
+
+                if ( profClass != icSigDisplayClass ) {
+                    g_warning("Not a display profile");
+                    cmsCloseProfile( theOne );
+                    theOne = 0;
+                } else if ( space != icSigRgbData ) {
+                    g_warning("Not an RGB profile");
+                    cmsCloseProfile( theOne );
+                    theOne = 0;
+                } else {
+                    lastURI = uri;
+                }
+            }
+        }
+    } else if ( theOne ) {
+        cmsCloseProfile( theOne );
+        theOne = 0;
+        lastURI.clear();
+        if ( transf ) {
+            cmsDeleteTransform( transf );
+            transf = 0;
+        }
+    }
+
+    return theOne;
+}
+
+
+cmsHPROFILE Inkscape::colorprofile_get_proof_profile_handle()
+{
+    static cmsHPROFILE theOne = 0;
+    static std::string lastURI;
+
+    static bool init = false;
+    if ( !init ) {
+        cmsSetErrorHandler(errorHandlerCB);
+
+        findThings();
+        init = true;
+    }
+
+    long long int which = prefs_get_int_attribute_limited( "options.softproof", "enable", 0, 0, 1 );
+    gchar const * uri = prefs_get_string_attribute("options.softproof", "uri");
+
+    if ( which && uri && *uri ) {
+        if ( lastURI != std::string(uri) ) {
+            lastURI.clear();
+            if ( theOne ) {
+                cmsCloseProfile( theOne );
+            }
+            if ( transf ) {
+                cmsDeleteTransform( transf );
+                transf = 0;
+            }
             theOne = cmsOpenProfileFromFile( uri, "r" );
             if ( theOne ) {
                 // a display profile must have the proper stuff
                 icColorSpaceSignature space = cmsGetColorSpace(theOne);
                 icProfileClassSignature profClass = cmsGetDeviceClass(theOne);
 
+/*
                 if ( profClass != icSigDisplayClass ) {
                     g_warning("Not a display profile");
                     cmsCloseProfile( theOne );
@@ -567,19 +650,60 @@ cmsHPROFILE Inkscape::colorprofile_get_system_profile_handle()
                     cmsCloseProfile( theOne );
                     theOne = 0;
                 } else {
+*/
                     lastURI = uri;
+/*
                 }
+*/
             }
         }
     } else if ( theOne ) {
         cmsCloseProfile( theOne );
         theOne = 0;
         lastURI.clear();
+        if ( transf ) {
+            cmsDeleteTransform( transf );
+            transf = 0;
+        }
     }
 
     return theOne;
 }
 
+cmsHTRANSFORM Inkscape::colorprofile_get_display_transform()
+{
+    bool warn = prefs_get_int_attribute_limited( "options.softproof", "gamutwarn", 0, 0, 1 );
+    if ( (warn != gamutWarn) ) {
+        gamutWarn = warn;
+        if ( transf ) {
+            cmsDeleteTransform(transf);
+            transf = 0;
+        }
+    }
+
+    // Fecth these now, as they might clear the transform as a side effect.
+    cmsHPROFILE hprof = Inkscape::colorprofile_get_system_profile_handle();
+    cmsHPROFILE proofProf = hprof ? Inkscape::colorprofile_get_proof_profile_handle() : 0;
+
+    if ( !transf ) {
+        if ( !srcprof ) {
+            srcprof = cmsCreate_sRGBProfile();
+        }
+        if ( hprof && proofProf ) {
+            DWORD dwFlags = cmsFLAGS_SOFTPROOFING;
+            if ( gamutWarn ) {
+                dwFlags |= cmsFLAGS_GAMUTCHECK;
+            }
+            cmsSetAlarmCodes(0, 255, 0);
+            transf = cmsCreateProofingTransform( srcprof, TYPE_RGB_8, hprof, TYPE_RGB_8, proofProf, INTENT_PERCEPTUAL, INTENT_PERCEPTUAL, dwFlags );
+        } else if ( hprof ) {
+            transf = cmsCreateTransform( srcprof, TYPE_RGB_8, hprof, TYPE_RGB_8, INTENT_PERCEPTUAL, 0 );
+        }
+    }
+
+    return transf;
+}
+
 #endif // ENABLE_LCMS
 
 /*
index 3c647aa1c3d4e08f17769694806f1fe6f70b4810..efd2628903d45237a82a79479ed37c07271e81f3 100644 (file)
@@ -1588,9 +1588,7 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
     }
 
 #if ENABLE_LCMS
-        cmsHPROFILE hprof = Inkscape::colorprofile_get_system_profile_handle();
-        cmsHPROFILE srcprof = hprof ? cmsCreate_sRGBProfile() : 0;
-        cmsHTRANSFORM transf = hprof ? cmsCreateTransform( srcprof, TYPE_RGB_8, hprof, TYPE_RGB_8, INTENT_PERCEPTUAL, 0 ) : 0;
+    cmsHTRANSFORM transf = Inkscape::colorprofile_get_display_transform();
 #endif // ENABLE_LCMS
 
     if (buf.is_empty) {
@@ -1647,14 +1645,6 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
                                       x0 - canvas->x0, y0 - canvas->y0);
     }
 
-#if ENABLE_LCMS
-    if ( transf ) {
-        cmsDeleteTransform( transf );
-        transf = 0;
-    }
-#endif // ENABLE_LCMS
-
-
     if (canvas->rendermode != RENDERMODE_OUTLINE) {
         nr_pixelstore_256K_free (buf.buf);
     } else {
index 16e1bc76e145a765cb996a4d76dae14d18e63e0a..3733230975508d5b11f8161cf8e75fc02862c774 100644 (file)
@@ -185,6 +185,11 @@ static char const preferences_skeleton[] =
 "       id=\"displayprofile\""
 "       enable=\"0\"\n"
 "       uri=\"\" />\n"
+"    <group\n"
+"       id=\"softproof\""
+"       enable=\"0\"\n"
+"       gamutwarn=\"0\"\n"
+"       uri=\"\" />\n"
 "    <group id=\"savewindowgeometry\" value=\"1\"/>\n"
 "    <group id=\"defaultoffsetwidth\" value=\"2\"/>\n"
 "    <group id=\"defaultscale\" value=\"2\"/>\n"
index 59132349f423f6e8c4efff6233768bcbb759804d..0e83addec8e0096282efd8ed67a7a6a205ed0043 100644 (file)
@@ -644,6 +644,17 @@ static void profileComboChanged( Gtk::ComboBoxText* combo )
         forceUpdates();
     }
 }
+
+static void proofComboChanged( Gtk::ComboBoxText* combo )
+{
+    Glib::ustring active = combo->get_active_text();
+
+    Glib::ustring path = get_path_for_profile(active);
+    if ( !path.empty() ) {
+        prefs_set_string_attribute( "options.softproof", "uri", path.c_str() );
+        forceUpdates();
+    }
+}
 #endif // ENABLE_LCMS
 
 
@@ -663,6 +674,19 @@ void InkscapePreferences::initPageMisc()
 
     _page_misc.add_line( false, _("Display profile:"), _misc_cms_display_profile, "",
                          _("The ICC profile to use to calibrate display output."), true);
+
+
+    _misc_cms_softproof.init( _("Simulate output on screen."), "options.softproof", "enable", false);
+    _page_misc.add_line( false, "", _misc_cms_softproof, "",
+                           _("Simulates output of target device."), true);
+
+    _misc_cms_gamutwarn.init( _("Mark out of gamut colors."), "options.softproof", "gamutwarn", false);
+    _page_misc.add_line( false, "", _misc_cms_gamutwarn, "",
+                           _("Highlights colors that are out of gamut for the target device."), true);
+
+    _page_misc.add_line( false, _("Device profile:"), _misc_cms_proof_profile, "",
+                         _("The ICC profile to use to simulate device output."), true);
+
 #if ENABLE_LCMS
     {
         std::vector<Glib::ustring> names = ::Inkscape::colorprofile_get_display_names();
@@ -677,15 +701,34 @@ void InkscapePreferences::initPageMisc()
             }
             index++;
         }
+
+        names = ::Inkscape::colorprofile_get_softproof_names();
+        const gchar * tmp = prefs_get_string_attribute( "options.softproof", "uri" );
+        current = tmp ? tmp : "";
+        index = 0;
+        for ( std::vector<Glib::ustring>::iterator it = names.begin(); it != names.end(); ++it ) {
+            _misc_cms_proof_profile.append_text( *it );
+            Glib::ustring path = get_path_for_profile(*it);
+            if ( !path.empty() && path == current ) {
+                _misc_cms_proof_profile.set_active(index);
+            }
+            index++;
+        }
     }
 
     _misc_cms_display.signal_toggled().connect( sigc::ptr_fun(forceUpdates) );
+    _misc_cms_softproof.signal_toggled().connect( sigc::ptr_fun(forceUpdates) );
+    _misc_cms_gamutwarn.signal_toggled().connect( sigc::ptr_fun(forceUpdates) );
 
     _misc_cms_display_profile.signal_changed().connect( sigc::bind( sigc::ptr_fun(profileComboChanged), &_misc_cms_display_profile) );
+    _misc_cms_proof_profile.signal_changed().connect( sigc::bind( sigc::ptr_fun(proofComboChanged), &_misc_cms_proof_profile) );
 #else
     // disable it, but leave it visible
     _misc_cms_display.set_sensitive( false );
     _misc_cms_display_profile.set_sensitive( false );
+    _misc_cms_softproof.set_sensitive( false );
+    _misc_cms_gamutwarn.set_sensitive( false );
+    _misc_cms_proof_profile.set_sensitive( false );
 #endif // ENABLE_LCMS
 
     _misc_recent.init("options.maxrecentdocuments", "value", 0.0, 1000.0, 1.0, 1.0, 1.0, true, false);
index 5dafd40516722e9d1d366820897d35fda74bb2bb..58c908a9acc08b17f42def05e4d4357a452e785a 100644 (file)
@@ -165,6 +165,10 @@ protected:
     PrefCheckButton     _misc_cms_display;
     Gtk::ComboBoxText   _misc_cms_display_profile;
 
+    PrefCheckButton     _misc_cms_softproof;
+    PrefCheckButton     _misc_cms_gamutwarn;
+    Gtk::ComboBoxText   _misc_cms_proof_profile;
+
     PrefEntryButtonHBox _importexport_ocal_url;
     PrefEntry       _importexport_ocal_username;
     PrefEntry       _importexport_ocal_password;