Code

144e42aa2a194d60a2df07774cbf21d0de9be796
[inkscape.git] / src / widgets / sp-color-icc-selector.cpp
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <math.h>
5 #include <gtk/gtkbutton.h>
6 #include <gtk/gtkcombobox.h>
7 #include <gtk/gtksignal.h>
8 #include <gtk/gtklabel.h>
9 #include <gtk/gtktable.h>
10 #include <gtk/gtkspinbutton.h>
11 #include <glibmm/i18n.h>
12 #include "../dialogs/dialog-events.h"
13 #include "sp-color-icc-selector.h"
14 #include "sp-color-scales.h"
15 #include "svg/svg-icc-color.h"
16 #include "document.h"
17 #include "inkscape.h"
18 #include "profile-manager.h"
20 #define noDEBUG_LCMS
22 #if ENABLE_LCMS
23 #include "color-profile-fns.h"
24 #include "color-profile.h"
25 //#define DEBUG_LCMS
26 #if 1 //DEBUG_LCMS
27 #include "preferences.h"
28 #include <gtk/gtkmessagedialog.h>
29 #endif // DEBUG_LCMS
30 #endif // ENABLE_LCMS
33 #if 1 //DEBUG_LCMS
34 extern guint update_in_progress;
35 #define DEBUG_MESSAGE(key, ...) \
36 {\
37     Inkscape::Preferences *prefs = Inkscape::Preferences::get();\
38     bool dump = prefs->getBool("/options/scislac/" #key);\
39     bool dumpD = prefs->getBool("/options/scislac/" #key "D");\
40     bool dumpD2 = prefs->getBool("/options/scislac/" #key "D2");\
41     dumpD &&= ( (update_in_progress == 0) || dumpD2 );\
42     if ( dump )\
43     {\
44         g_message( __VA_ARGS__ );\
45 \
46     }\
47     if ( dumpD )\
48     {\
49         GtkWidget *dialog = gtk_message_dialog_new(NULL,\
50                                                    GTK_DIALOG_DESTROY_WITH_PARENT, \
51                                                    GTK_MESSAGE_INFO,    \
52                                                    GTK_BUTTONS_OK,      \
53                                                    __VA_ARGS__          \
54                                                    );\
55         g_signal_connect_swapped(dialog, "response",\
56                                  G_CALLBACK(gtk_widget_destroy),        \
57                                  dialog);                               \
58         gtk_widget_show_all( dialog );\
59     }\
60 }
61 #endif // DEBUG_LCMS
65 G_BEGIN_DECLS
67 static void sp_color_icc_selector_class_init (SPColorICCSelectorClass *klass);
68 static void sp_color_icc_selector_init (SPColorICCSelector *cs);
69 static void sp_color_icc_selector_destroy (GtkObject *object);
71 static void sp_color_icc_selector_show_all (GtkWidget *widget);
72 static void sp_color_icc_selector_hide_all (GtkWidget *widget);
75 G_END_DECLS
77 static SPColorSelectorClass *parent_class;
79 #define XPAD 4
80 #define YPAD 1
82 GType
83 sp_color_icc_selector_get_type (void)
84 {
85     static GType type = 0;
86     if (!type) {
87         static const GTypeInfo info = {
88             sizeof (SPColorICCSelectorClass),
89             NULL, /* base_init */
90             NULL, /* base_finalize */
91             (GClassInitFunc) sp_color_icc_selector_class_init,
92             NULL, /* class_finalize */
93             NULL, /* class_data */
94             sizeof (SPColorICCSelector),
95             0,    /* n_preallocs */
96             (GInstanceInitFunc) sp_color_icc_selector_init,
97             0,    /* value_table */
98         };
100         type = g_type_register_static (SP_TYPE_COLOR_SELECTOR,
101                                        "SPColorICCSelector",
102                                        &info,
103                                        static_cast< GTypeFlags > (0) );
104     }
105     return type;
108 static void
109 sp_color_icc_selector_class_init (SPColorICCSelectorClass *klass)
111     static const gchar* nameset[] = {N_("CMS"), 0};
112     GtkObjectClass *object_class;
113     GtkWidgetClass *widget_class;
114     SPColorSelectorClass *selector_class;
116     object_class = (GtkObjectClass *) klass;
117     widget_class = (GtkWidgetClass *) klass;
118     selector_class = SP_COLOR_SELECTOR_CLASS (klass);
120     parent_class = SP_COLOR_SELECTOR_CLASS (g_type_class_peek_parent (klass));
122     selector_class->name = nameset;
123     selector_class->submode_count = 1;
125     object_class->destroy = sp_color_icc_selector_destroy;
127     widget_class->show_all = sp_color_icc_selector_show_all;
128     widget_class->hide_all = sp_color_icc_selector_hide_all;
132 ColorICCSelector::ColorICCSelector( SPColorSelector* csel )
133     : ColorSelector( csel ),
134       _updating( FALSE ),
135       _dragging( FALSE ),
136       _fixupNeeded(0),
137       _fooCount(0),
138       _fooScales(0),
139       _fooAdj(0),
140       _fooSlider(0),
141       _fooBtn(0),
142       _fooLabel(0),
143       _fooMap(0),
144       _adj(0),
145       _sbtn(0),
146       _label(0),
147       _tt(0)
148 #if ENABLE_LCMS
149     ,
150       _profileName(""),
151       _prof(),
152       _profChannelCount(0),
153       _profChangedID(0)
154 #endif // ENABLE_LCMS
158 ColorICCSelector::~ColorICCSelector()
160     _adj = 0;
161     _sbtn = 0;
162     _label = 0;
165 void sp_color_icc_selector_init (SPColorICCSelector *cs)
167     SP_COLOR_SELECTOR(cs)->base = new ColorICCSelector( SP_COLOR_SELECTOR(cs) );
169     if ( SP_COLOR_SELECTOR(cs)->base )
170     {
171         SP_COLOR_SELECTOR(cs)->base->init();
172     }
176 /*
177 icSigRgbData
178 icSigCmykData
179 icSigCmyData
180 */
181 #define SPACE_ID_RGB 0
182 #define SPACE_ID_CMY 1
183 #define SPACE_ID_CMYK 2
186 #if ENABLE_LCMS
187 static icUInt16Number* getScratch() {
188     // bytes per pixel * input channels * width
189     static icUInt16Number* scritch = static_cast<icUInt16Number*>(g_new(icUInt16Number, 4 * 1024));
191     return scritch;
194 struct MapMap {
195     DWORD space;
196     DWORD inForm;
197 };
199 void getThings( DWORD space, gchar const**& namers, gchar const**& tippies, guint const*& scalies ) {
200     MapMap possible[] = {
201         {icSigXYZData,   TYPE_XYZ_16},
202         {icSigLabData,   TYPE_Lab_16},
203         //icSigLuvData
204         {icSigYCbCrData, TYPE_YCbCr_16},
205         {icSigYxyData,   TYPE_Yxy_16},
206         {icSigRgbData,   TYPE_RGB_16},
207         {icSigGrayData,  TYPE_GRAY_16},
208         {icSigHsvData,   TYPE_HSV_16},
209         {icSigHlsData,   TYPE_HLS_16},
210         {icSigCmykData,  TYPE_CMYK_16},
211         {icSigCmyData,   TYPE_CMY_16},
212     };
214     static gchar const *names[][6] = {
215         {"_X", "_Y", "_Z", "", "", ""},
216         {"_L", "_a", "_b", "", "", ""},
217         //
218         {"_Y", "C_b", "C_r", "", "", ""},
219         {"_Y", "_x", "y", "", "", ""},
220         {_("_R"), _("_G"), _("_B"), "", "", ""},
221         {_("_G"), "", "", "", "", ""},
222         {_("_H"), _("_S"), "_V", "", "", ""},
223         {_("_H"), _("_L"), _("_S"), "", "", ""},
224         {_("_C"), _("_M"), _("_Y"), _("_K"), "", ""},
225         {_("_C"), _("_M"), _("_Y"), "", "", ""},
226     };
228     static gchar const *tips[][6] = {
229         {"X", "Y", "Z", "", "", ""},
230         {"L", "a", "b", "", "", ""},
231         //
232         {"Y", "Cb", "Cr", "", "", ""},
233         {"Y", "x", "y", "", "", ""},
234         {_("Red"), _("Green"), _("Blue"), "", "", ""},
235         {_("Gray"), "", "", "", "", ""},
236         {_("Hue"), _("Saturation"), "Value", "", "", ""},
237         {_("Hue"), _("Lightness"), _("Saturation"), "", "", ""},
238         {_("Cyan"), _("Magenta"), _("Yellow"), _("Black"), "", ""},
239         {_("Cyan"), _("Magenta"), _("Yellow"), "", "", ""},
240     };
242     static guint scales[][6] = {
243         {2, 1, 2, 1, 1, 1},
244         {100, 256, 256, 1, 1, 1},
245         //
246         {1, 1, 1, 1, 1, 1},
247         {1, 1, 1, 1, 1, 1},
248         {1, 1, 1, 1, 1, 1},
249         {1, 1, 1, 1, 1, 1},
250         {360, 1, 1, 1, 1, 1},
251         {360, 1, 1, 1, 1, 1},
252         {1, 1, 1, 1, 1, 1},
253         {1, 1, 1, 1, 1, 1},
254     };
256     int index = 0;
257     for ( guint i = 0; i < G_N_ELEMENTS(possible); i++ ) {
258         if ( possible[i].space == space ) {
259             index = i;
260             break;
261         }
262     }
264     namers = names[index];
265     tippies = tips[index];
266     scalies = scales[index];
268 #endif // ENABLE_LCMS
271 void ColorICCSelector::init()
273     GtkWidget *t;
274     gint row = 0;
276     _updating = FALSE;
277     _dragging = FALSE;
279     _tt = gtk_tooltips_new();
281     t = gtk_table_new (5, 3, FALSE);
282     gtk_widget_show (t);
283     gtk_box_pack_start (GTK_BOX (_csel), t, TRUE, TRUE, 0);
285 #if ENABLE_LCMS
286     //guint partCount = _cmsChannelsOf( icSigRgbData );
287     gchar const** names = 0;
288     gchar const** tips = 0;
289     getThings( icSigRgbData, names, tips, _fooScales );
290 #endif // ENABLE_LCMS
292     /* Create components */
293     row = 0;
296     _fixupBtn = gtk_button_new_with_label(_("Fix"));
297     g_signal_connect( G_OBJECT(_fixupBtn), "clicked", G_CALLBACK(_fixupHit), (gpointer)this );
298     gtk_widget_set_sensitive( _fixupBtn, FALSE );
299     gtk_tooltips_set_tip( _tt, _fixupBtn, _("Fix RGB fallback to match icc-color() value."), NULL );
300     //gtk_misc_set_alignment( GTK_MISC (_fixupBtn), 1.0, 0.5 );
301     gtk_widget_show( _fixupBtn );
302     gtk_table_attach( GTK_TABLE (t), _fixupBtn, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD );
305     _profileSel = gtk_combo_box_new_text();
306     gtk_combo_box_append_text( GTK_COMBO_BOX(_profileSel), "<none>" );
307     gtk_widget_show( _profileSel );
308     gtk_combo_box_set_active( GTK_COMBO_BOX(_profileSel), 0 );
309     gtk_table_attach( GTK_TABLE(t), _profileSel, 1, 2, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD );
311 #if ENABLE_LCMS
312     _profChangedID = g_signal_connect( G_OBJECT(_profileSel), "changed", G_CALLBACK(_profileSelected), (gpointer)this );
313 #else
314     gtk_widget_set_sensitive( _profileSel, false );
315 #endif // ENABLE_LCMS
318     row++;
320     _fooCount = 4;
321     _fooAdj = new GtkAdjustment*[_fooCount];
322     _fooSlider = new GtkWidget*[_fooCount];
323     _fooBtn = new GtkWidget*[_fooCount];
324     _fooLabel = new GtkWidget*[_fooCount];
325     _fooMap = new guchar*[_fooCount];
327     for ( guint i = 0; i < _fooCount; i++ ) {
328         /* Label */
329 #if ENABLE_LCMS
330         _fooLabel[i] = gtk_label_new_with_mnemonic( names[i] );
331 #else
332         _fooLabel[i] = gtk_label_new_with_mnemonic( "." );
333 #endif // ENABLE_LCMS
334         gtk_misc_set_alignment( GTK_MISC (_fooLabel[i]), 1.0, 0.5 );
335         gtk_widget_show( _fooLabel[i] );
336         gtk_table_attach( GTK_TABLE (t), _fooLabel[i], 0, 1, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD );
338         /* Adjustment */
339         gdouble step = static_cast<gdouble>(_fooScales[i]) / 100.0;
340         gdouble page = static_cast<gdouble>(_fooScales[i]) / 10.0;
341         gint digits = (step > 0.9) ? 0 : 2;
342         _fooAdj[i] = GTK_ADJUSTMENT( gtk_adjustment_new( 0.0, 0.0, _fooScales[i],  step, page, page ) );
344         /* Slider */
345         _fooSlider[i] = sp_color_slider_new( _fooAdj[i] );
346 #if ENABLE_LCMS
347         gtk_tooltips_set_tip( _tt, _fooSlider[i], tips[i], NULL );
348 #else
349         gtk_tooltips_set_tip( _tt, _fooSlider[i], ".", NULL );
350 #endif // ENABLE_LCMS
351         gtk_widget_show( _fooSlider[i] );
352         gtk_table_attach( GTK_TABLE (t), _fooSlider[i], 1, 2, row, row + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)GTK_FILL, XPAD, YPAD );
354         _fooBtn[i] = gtk_spin_button_new( _fooAdj[i], step, digits );
355 #if ENABLE_LCMS
356         gtk_tooltips_set_tip( _tt, _fooBtn[i], tips[i], NULL );
357 #else
358         gtk_tooltips_set_tip( _tt, _fooBtn[i], ".", NULL );
359 #endif // ENABLE_LCMS
360         sp_dialog_defocus_on_enter( _fooBtn[i] );
361         gtk_label_set_mnemonic_widget( GTK_LABEL(_fooLabel[i]), _fooBtn[i] );
362         gtk_widget_show( _fooBtn[i] );
363         gtk_table_attach( GTK_TABLE (t), _fooBtn[i], 2, 3, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, XPAD, YPAD );
365         _fooMap[i] = g_new( guchar, 4 * 1024 );
366         memset( _fooMap[i], 0x0ff, 1024 * 4 );
369         /* Signals */
370         gtk_signal_connect( GTK_OBJECT( _fooAdj[i] ), "value_changed", GTK_SIGNAL_FUNC( _adjustmentChanged ), _csel );
372         gtk_signal_connect( GTK_OBJECT( _fooSlider[i] ), "grabbed", GTK_SIGNAL_FUNC( _sliderGrabbed ), _csel );
373         gtk_signal_connect( GTK_OBJECT( _fooSlider[i] ), "released", GTK_SIGNAL_FUNC( _sliderReleased ), _csel );
374         gtk_signal_connect( GTK_OBJECT( _fooSlider[i] ), "changed", GTK_SIGNAL_FUNC( _sliderChanged ), _csel );
376         row++;
377     }
379     /* Label */
380     _label = gtk_label_new_with_mnemonic (_("_A"));
381     gtk_misc_set_alignment (GTK_MISC (_label), 1.0, 0.5);
382     gtk_widget_show (_label);
383     gtk_table_attach (GTK_TABLE (t), _label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD);
385     /* Adjustment */
386     _adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 10.0, 10.0);
388     /* Slider */
389     _slider = sp_color_slider_new (_adj);
390     gtk_tooltips_set_tip (_tt, _slider, _("Alpha (opacity)"), NULL);
391     gtk_widget_show (_slider);
392     gtk_table_attach (GTK_TABLE (t), _slider, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)GTK_FILL, XPAD, YPAD);
394     sp_color_slider_set_colors( SP_COLOR_SLIDER( _slider ),
395                                 SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 0.0 ),
396                                 SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 0.5 ),
397                                 SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 1.0 ) );
400     /* Spinbutton */
401     _sbtn = gtk_spin_button_new (GTK_ADJUSTMENT (_adj), 1.0, 0);
402     gtk_tooltips_set_tip (_tt, _sbtn, _("Alpha (opacity)"), NULL);
403     sp_dialog_defocus_on_enter (_sbtn);
404     gtk_label_set_mnemonic_widget (GTK_LABEL(_label), _sbtn);
405     gtk_widget_show (_sbtn);
406     gtk_table_attach (GTK_TABLE (t), _sbtn, 2, 3, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, XPAD, YPAD);
408     /* Signals */
409     gtk_signal_connect (GTK_OBJECT (_adj), "value_changed",
410                         GTK_SIGNAL_FUNC (_adjustmentChanged), _csel);
412     gtk_signal_connect (GTK_OBJECT (_slider), "grabbed",
413                         GTK_SIGNAL_FUNC (_sliderGrabbed), _csel);
414     gtk_signal_connect (GTK_OBJECT (_slider), "released",
415                         GTK_SIGNAL_FUNC (_sliderReleased), _csel);
416     gtk_signal_connect (GTK_OBJECT (_slider), "changed",
417                         GTK_SIGNAL_FUNC (_sliderChanged), _csel);
420 static void
421 sp_color_icc_selector_destroy (GtkObject *object)
423     if (((GtkObjectClass *) (parent_class))->destroy)
424         (* ((GtkObjectClass *) (parent_class))->destroy) (object);
427 static void
428 sp_color_icc_selector_show_all (GtkWidget *widget)
430     gtk_widget_show (widget);
433 static void
434 sp_color_icc_selector_hide_all (GtkWidget *widget)
436     gtk_widget_hide (widget);
439 GtkWidget *
440 sp_color_icc_selector_new (void)
442     SPColorICCSelector *csel;
444     csel = (SPColorICCSelector*)gtk_type_new (SP_TYPE_COLOR_ICC_SELECTOR);
446     return GTK_WIDGET (csel);
450 void ColorICCSelector::_fixupHit( GtkWidget* /*src*/, gpointer data )
452     ColorICCSelector* self = reinterpret_cast<ColorICCSelector*>(data);
453     gtk_widget_set_sensitive( self->_fixupBtn, FALSE );
454     self->_adjustmentChanged( self->_fooAdj[0], SP_COLOR_ICC_SELECTOR(self->_csel) );
457 #if ENABLE_LCMS
458 void ColorICCSelector::_profileSelected( GtkWidget* /*src*/, gpointer data )
460     ColorICCSelector* self = reinterpret_cast<ColorICCSelector*>(data);
461     gint activeIndex = gtk_combo_box_get_active( GTK_COMBO_BOX(self->_profileSel) );
462     gchar* name = (activeIndex != 0) ? gtk_combo_box_get_active_text( GTK_COMBO_BOX(self->_profileSel) ) : 0;
463     self->_switchToProfile( name );
464     if ( name ) {
465         g_free( name );
466     }
468 #endif // ENABLE_LCMS
470 #ifdef ENABLE_LCMS
471 void ColorICCSelector::_switchToProfile( gchar const* name )
473     bool dirty = false;
474     SPColor tmp( _color );
476     if ( name ) {
477         if ( tmp.icc && tmp.icc->colorProfile == name ) {
478 #if 1 //DEBUG_LCMS
479              g_message("Already at name [%s]", name );
480 #endif // DEBUG_LCMS
481         } else {
482 #if 1 //DEBUG_LCMS
483              g_message("Need to switch to profile [%s]", name );
484 #endif // DEBUG_LCMS
485             if ( tmp.icc ) {
486                 tmp.icc->colors.clear();
487             } else {
488                 tmp.icc = new SVGICCColor();
489             }
490             tmp.icc->colorProfile = name;
491             Inkscape::ColorProfile* newProf = SP_ACTIVE_DOCUMENT->profileManager->find(name);
492             if ( newProf ) {
493                 cmsHTRANSFORM trans = newProf->getTransfFromSRGB8();
494                 if ( trans ) {
495                     guint32 val = _color.toRGBA32(0);
496                     guchar pre[4] = {
497                         SP_RGBA32_R_U(val),
498                         SP_RGBA32_G_U(val),
499                         SP_RGBA32_B_U(val),
500                         255};
501 #if 1 //DEBUG_LCMS
502                     g_message("Shoving in [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]);
503 #endif // DEBUG_LCMS
504                     icUInt16Number post[4] = {0,0,0,0};
505                     cmsDoTransform( trans, pre, post, 1 );
506 #if 1 //DEBUG_LCMS
507                     g_message("got on out [%04x] [%04x] [%04x] [%04x]", post[0], post[1], post[2], post[3]);
508 #endif // DEBUG_LCMS
509                     guint count = _cmsChannelsOf( newProf->getColorSpace() );
511                     gchar const** names = 0;
512                     gchar const** tips = 0;
513                     guint const* scales = 0;
514                     getThings( newProf->getColorSpace(), names, tips, scales );
516                     for ( guint i = 0; i < count; i++ ) {
517                         gdouble val = (((gdouble)post[i])/65535.0) * (gdouble)scales[i];
518 #if 1 //DEBUG_LCMS
519                         g_message("     scaled %d by %d to be %f", i, scales[i], val);
520 #endif // DEBUG_LCMS
521                         tmp.icc->colors.push_back(val);
522                     }
523                     cmsHTRANSFORM retrans = newProf->getTransfToSRGB8();
524                     if ( retrans ) {
525                         cmsDoTransform( retrans, post, pre, 1 );
526 #if 1 //DEBUG_LCMS
527                         g_message("  back out [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]);
528 #endif // DEBUG_LCMS
529                         tmp.set(SP_RGBA32_U_COMPOSE(pre[0], pre[1], pre[2], 0xff));
530                     }
531                 }
532             }
533             dirty = true;
534         }
535     } else {
536 #if 1 //DEBUG_LCMS
537          g_message("NUKE THE ICC");
538 #endif // DEBUG_LCMS
539         if ( tmp.icc ) {
540             delete tmp.icc;
541             tmp.icc = 0;
542             dirty = true;
543             _fixupHit( 0, this );
544         } else {
545 #if 1 //DEBUG_LCMS
546              g_message("No icc to nuke");
547 #endif // DEBUG_LCMS
548         }
549     }
551     if ( dirty ) {
552 #if 1 //DEBUG_LCMS
553         g_message("+----------------");
554         g_message("+   new color is [%s]", tmp.toString().c_str());
555 #endif // DEBUG_LCMS
556         _setProfile( tmp.icc );
557         //_adjustmentChanged( _fooAdj[0], SP_COLOR_ICC_SELECTOR(_csel) );
558         setColorAlpha( tmp, _alpha, true );
559 #if 1 //DEBUG_LCMS
560         g_message("+_________________");
561 #endif // DEBUG_LCMS
562     }
564 #endif // ENABLE_LCMS
566 void ColorICCSelector::_profilesChanged( std::string const & name )
568 #ifdef ENABLE_LCMS
569     GtkComboBox* combo = GTK_COMBO_BOX(_profileSel);
571     g_signal_handler_block( G_OBJECT(_profileSel), _profChangedID );
573     GtkTreeModel* model = gtk_combo_box_get_model( combo );
574     GtkTreeIter iter;
575     while ( gtk_tree_model_get_iter_first( model, &iter ) ) {
576         gtk_combo_box_remove_text( combo, 0 );
577     }
579     gtk_combo_box_append_text( combo, "<none>");
581     gtk_combo_box_set_active( combo, 0 );
583     int index = 1;
584     const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "iccprofile" );
585     while ( current ) {
586         SPObject* obj = SP_OBJECT(current->data);
587         Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj);
588         gtk_combo_box_append_text( combo, prof->name );
589         if ( name == prof->name ) {
590             gtk_combo_box_set_active( combo, index );
591         }
593         index++;
594         current = g_slist_next(current);
595     }
597     g_signal_handler_unblock( G_OBJECT(_profileSel), _profChangedID );
598 #endif // ENABLE_LCMS
601 /* Helpers for setting color value */
603 void ColorICCSelector::_colorChanged()
605     _updating = TRUE;
606      //sp_color_icc_set_color( SP_COLOR_ICC( _icc ), &color );
608 #if 1 //DEBUG_LCMS
609     g_message( "/^^^^^^^^^  %p::_colorChanged(%08x:%s)", this,
610                _color.toRGBA32(_alpha), ( (_color.icc) ? _color.icc->colorProfile.c_str(): "<null>" )
611                );
612 #endif // DEBUG_LCMS
614 #if 1 //DEBUG_LCMS
615     g_message("FLIPPIES!!!!     %p   '%s'", _color.icc, (_color.icc ? _color.icc->colorProfile.c_str():"<null>"));
616 #endif // DEBUG_LCMS
618     _profilesChanged( (_color.icc) ? _color.icc->colorProfile : std::string("") );
619     ColorScales::setScaled( _adj, _alpha );
621 #if ENABLE_LCMS
622     _setProfile( _color.icc );
623     _fixupNeeded = 0;
624     gtk_widget_set_sensitive( _fixupBtn, FALSE );
626     if ( _prof && _prof->getTransfToSRGB8() ) {
627         icUInt16Number tmp[4];
628         for ( guint i = 0; i < _profChannelCount; i++ ) {
629             gdouble val = 0.0;
630             if ( _color.icc->colors.size() > i ) {
631                 if ( _fooScales[i] == 256 ) {
632                     val = (_color.icc->colors[i] + 128.0) / static_cast<gdouble>(_fooScales[i]);
633                 } else {
634                     val = _color.icc->colors[i] / static_cast<gdouble>(_fooScales[i]);
635                 }
636             }
637             tmp[i] = val * 0x0ffff;
638         }
639         guchar post[4] = {0,0,0,0};
640         cmsDoTransform( _prof->getTransfToSRGB8(), tmp, post, 1 );
641         guint32 other = SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255 );
642         if ( other != _color.toRGBA32(255) ) {
643             _fixupNeeded = other;
644             gtk_widget_set_sensitive( _fixupBtn, TRUE );
645 #if 1 //DEBUG_LCMS
646             g_message("Color needs to change 0x%06x to 0x%06x", _color.toRGBA32(255) >> 8, other >> 8 );
647 #endif // DEBUG_LCMS
648         }
649     }
650 #else
651     //(void)color;
652 #endif // ENABLE_LCMS
653     _updateSliders( -1 );
656     _updating = FALSE;
657 #if 1 //DEBUG_LCMS
658     g_message( "\\_________  %p::_colorChanged()", this );
659 #endif // DEBUG_LCMS
662 #if ENABLE_LCMS
663 void ColorICCSelector::_setProfile( SVGICCColor* profile )
665 #if 1 //DEBUG_LCMS
666     g_message( "/^^^^^^^^^  %p::_setProfile(%s)", this,
667                ( (profile) ? profile->colorProfile.c_str() : "<null>")
668                );
669 #endif // DEBUG_LCMS
670     bool profChanged = false;
671     if ( _prof && (!profile || (_profileName != profile->colorProfile) ) ) {
672         // Need to clear out the prior one
673         profChanged = true;
674         _profileName.clear();
675         _prof = 0;
676         _profChannelCount = 0;
677     } else if ( profile && !_prof ) {
678         profChanged = true;
679     }
681     for ( guint i = 0; i < _fooCount; i++ ) {
682         gtk_widget_hide( _fooLabel[i] );
683         gtk_widget_hide( _fooSlider[i] );
684         gtk_widget_hide( _fooBtn[i] );
685     }
687     if ( profile ) {
688         _prof = SP_ACTIVE_DOCUMENT->profileManager->find(profile->colorProfile.c_str());
689         if ( _prof && _prof->getProfileClass() != icSigNamedColorClass ) {
690             _profChannelCount = _cmsChannelsOf( _prof->getColorSpace() );
692             gchar const** names = 0;
693             gchar const** tips = 0;
694             getThings( _prof->getColorSpace(), names, tips, _fooScales );
696             if ( profChanged ) {
697                 for ( guint i = 0; i < _profChannelCount; i++ ) {
698                     gtk_label_set_text_with_mnemonic( GTK_LABEL(_fooLabel[i]), names[i]);
700                     gtk_tooltips_set_tip( _tt, _fooSlider[i], tips[i], NULL );
701                     gtk_tooltips_set_tip( _tt, _fooBtn[i], tips[i], NULL );
703                     sp_color_slider_set_colors( SP_COLOR_SLIDER(_fooSlider[i]),
704                                                 SPColor(0.0, 0.0, 0.0).toRGBA32(0xff),
705                                                 SPColor(0.5, 0.5, 0.5).toRGBA32(0xff),
706                                                 SPColor(1.0, 1.0, 1.0).toRGBA32(0xff) );
707 /*
708                     _fooAdj[i] = GTK_ADJUSTMENT( gtk_adjustment_new( val, 0.0, _fooScales[i],  step, page, page ) );
709                     gtk_signal_connect( GTK_OBJECT( _fooAdj[i] ), "value_changed", GTK_SIGNAL_FUNC( _adjustmentChanged ), _csel );
711                     sp_color_slider_set_adjustment( SP_COLOR_SLIDER(_fooSlider[i]), _fooAdj[i] );
712                     gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(_fooBtn[i]), _fooAdj[i] );
713                     gtk_spin_button_set_digits( GTK_SPIN_BUTTON(_fooBtn[i]), digits );
714 */
715                     gtk_widget_show( _fooLabel[i] );
716                     gtk_widget_show( _fooSlider[i] );
717                     gtk_widget_show( _fooBtn[i] );
718                     //gtk_adjustment_set_value( _fooAdj[i], 0.0 );
719                     //gtk_adjustment_set_value( _fooAdj[i], val );
720                 }
721                 for ( guint i = _profChannelCount; i < _fooCount; i++ ) {
722                     gtk_widget_hide( _fooLabel[i] );
723                     gtk_widget_hide( _fooSlider[i] );
724                     gtk_widget_hide( _fooBtn[i] );
725                 }
726             }
727         } else {
728             // Give up for now on named colors
729             _prof = 0;
730         }
731     }
733 #if 1 //DEBUG_LCMS
734     g_message( "\\_________  %p::_setProfile()", this );
735 #endif // DEBUG_LCMS
737 #endif // ENABLE_LCMS
739 void ColorICCSelector::_updateSliders( gint ignore )
741 #ifdef ENABLE_LCMS
742     if ( _color.icc )
743     {
744         for ( guint i = 0; i < _profChannelCount; i++ ) {
745             gdouble val = 0.0;
746             if ( _color.icc->colors.size() > i ) {
747                 if ( _fooScales[i] == 256 ) {
748                     val = (_color.icc->colors[i] + 128.0) / static_cast<gdouble>(_fooScales[i]);
749                 } else {
750                     val = _color.icc->colors[i] / static_cast<gdouble>(_fooScales[i]);
751                 }
752             }
753             gtk_adjustment_set_value( _fooAdj[i], val );
754         }
756         if ( _prof->getTransfToSRGB8() ) {
757             for ( guint i = 0; i < _profChannelCount; i++ ) {
758                 if ( static_cast<gint>(i) != ignore ) {
759                     icUInt16Number* scratch = getScratch();
760                     icUInt16Number filler[4] = {0, 0, 0, 0};
761                     for ( guint j = 0; j < _profChannelCount; j++ ) {
762                         filler[j] = 0x0ffff * ColorScales::getScaled( _fooAdj[j] );
763                     }
765                     icUInt16Number* p = scratch;
766                     for ( guint x = 0; x < 1024; x++ ) {
767                         for ( guint j = 0; j < _profChannelCount; j++ ) {
768                             if ( j == i ) {
769                                 *p++ = x * 0x0ffff / 1024;
770                             } else {
771                                 *p++ = filler[j];
772                             }
773                         }
774                     }
776                     cmsDoTransform( _prof->getTransfToSRGB8(), scratch, _fooMap[i], 1024 );
777                     sp_color_slider_set_map( SP_COLOR_SLIDER(_fooSlider[i]), _fooMap[i] );
778                 }
779             }
780         }
781     }
782 #else
783     (void)ignore;
784 #endif // ENABLE_LCMS
786     guint32 start = _color.toRGBA32( 0x00 );
787     guint32 mid = _color.toRGBA32( 0x7f );
788     guint32 end = _color.toRGBA32( 0xff );
790     sp_color_slider_set_colors( SP_COLOR_SLIDER(_slider), start, mid, end );
795 void ColorICCSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICCSelector *cs )
797 // // TODO check this. It looks questionable:
798 //     // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255  or 0..100
799 //     if (adjustment->value > 0.0 && adjustment->value < 1.0) {
800 //         gtk_adjustment_set_value( adjustment, floor ((adjustment->value) * adjustment->upper + 0.5) );
801 //     }
803 #if 1 //DEBUG_LCMS
804     g_message( "/^^^^^^^^^  %p::_adjustmentChanged()", cs );
805 #endif // DEBUG_LCMS
807      ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
808      if (iccSelector->_updating) {
809          return;
810      }
812      iccSelector->_updating = TRUE;
814      gint match = -1;
816      SPColor newColor( iccSelector->_color );
817      gfloat scaled = ColorScales::getScaled( iccSelector->_adj );
818      if ( iccSelector->_adj == adjustment ) {
819 #if 1 //DEBUG_LCMS
820          g_message("ALPHA");
821 #endif // DEBUG_LCMS
822      } else {
823 #if ENABLE_LCMS
824          for ( guint i = 0; i < iccSelector->_fooCount; i++ ) {
825              if ( iccSelector->_fooAdj[i] == adjustment ) {
826                  match = i;
827                  break;
828              }
829          }
830          if ( match >= 0 ) {
831 #if 1 //DEBUG_LCMS
832              g_message(" channel %d", match );
833 #endif // DEBUG_LCMS
834          }
837          icUInt16Number tmp[4];
838          for ( guint i = 0; i < 4; i++ ) {
839              tmp[i] = ColorScales::getScaled( iccSelector->_fooAdj[i] ) * 0x0ffff;
840          }
841          guchar post[4] = {0,0,0,0};
843          cmsDoTransform( iccSelector->_prof->getTransfToSRGB8(), tmp, post, 1 );
845          SPColor other( SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255) );
846          other.icc = new SVGICCColor();
847          if ( iccSelector->_color.icc ) {
848              other.icc->colorProfile = iccSelector->_color.icc->colorProfile;
849          }
851          guint32 prior = iccSelector->_color.toRGBA32(255);
852          guint32 newer = other.toRGBA32(255);
854          if ( prior != newer ) {
855 #if 1 //DEBUG_LCMS
856              g_message("Transformed color from 0x%08x to 0x%08x", prior, newer );
857              g_message("      ~~~~ FLIP");
858 #endif // DEBUG_LCMS
859              newColor = other;
860              newColor.icc->colors.clear();
861              for ( guint i = 0; i < iccSelector->_profChannelCount; i++ ) {
862                  gdouble val = ColorScales::getScaled( iccSelector->_fooAdj[i] );
863                  if ( iccSelector->_fooScales ) {
864                      val *= iccSelector->_fooScales[i];
865                      if ( iccSelector->_fooScales[i] == 256 ) {
866                          val -= 128;
867                      }
868                  }
869                  newColor.icc->colors.push_back( val );
870              }
871          }
872 #endif // ENABLE_LCMS
873      }
874      iccSelector->_updateInternals( newColor, scaled, iccSelector->_dragging );
875      iccSelector->_updateSliders( match );
877      iccSelector->_updating = FALSE;
878 #if 1 //DEBUG_LCMS
879      g_message( "\\_________  %p::_adjustmentChanged()", cs );
880 #endif // DEBUG_LCMS
883 void ColorICCSelector::_sliderGrabbed( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
885 //    ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
886 //     if (!iccSelector->_dragging) {
887 //         iccSelector->_dragging = TRUE;
888 //         iccSelector->_grabbed();
889 //         iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
890 //     }
893 void ColorICCSelector::_sliderReleased( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
895 //     ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
896 //     if (iccSelector->_dragging) {
897 //         iccSelector->_dragging = FALSE;
898 //         iccSelector->_released();
899 //         iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
900 //     }
903 #if 1 //DEBUG_LCMS
904 void ColorICCSelector::_sliderChanged( SPColorSlider *slider, SPColorICCSelector *cs )
905 #else
906 void ColorICCSelector::_sliderChanged( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
907 #endif // DEBUG_LCMS
909 #if 1 //DEBUG_LCMS
910     g_message("Changed  %p and %p", slider, cs );
911 #endif // DEBUG_LCMS
912 //     ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
914 //     iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
918 /*
919   Local Variables:
920   mode:c++
921   c-file-style:"stroustrup"
922   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
923   indent-tabs-mode:nil
924   fill-column:99
925   End:
926 */
927 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :