1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <math.h>
5 #include <gtk/gtkbutton.h>
6 #include <gtk/gtk.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 DEBUG_LCMS
22 #if ENABLE_LCMS
23 #include "color-profile-fns.h"
24 #include "color-profile.h"
26 #ifdef DEBUG_LCMS
27 #include "preferences.h"
28 #include <gtk/gtkmessagedialog.h>
29 #endif // DEBUG_LCMS
30 #endif // ENABLE_LCMS
33 #ifdef 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;
106 }
108 static void
109 sp_color_icc_selector_class_init (SPColorICCSelectorClass *klass)
110 {
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;
129 }
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
155 {
156 }
158 ColorICCSelector::~ColorICCSelector()
159 {
160 _adj = 0;
161 _sbtn = 0;
162 _label = 0;
163 }
165 void sp_color_icc_selector_init (SPColorICCSelector *cs)
166 {
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 }
173 }
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;
192 }
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];
267 }
268 #endif // ENABLE_LCMS
271 void ColorICCSelector::init()
272 {
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);
418 }
420 static void
421 sp_color_icc_selector_destroy (GtkObject *object)
422 {
423 if (((GtkObjectClass *) (parent_class))->destroy)
424 (* ((GtkObjectClass *) (parent_class))->destroy) (object);
425 }
427 static void
428 sp_color_icc_selector_show_all (GtkWidget *widget)
429 {
430 gtk_widget_show (widget);
431 }
433 static void
434 sp_color_icc_selector_hide_all (GtkWidget *widget)
435 {
436 gtk_widget_hide (widget);
437 }
439 GtkWidget *
440 sp_color_icc_selector_new (void)
441 {
442 SPColorICCSelector *csel;
444 csel = (SPColorICCSelector*)gtk_type_new (SP_TYPE_COLOR_ICC_SELECTOR);
446 return GTK_WIDGET (csel);
447 }
450 void ColorICCSelector::_fixupHit( GtkWidget* /*src*/, gpointer data )
451 {
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) );
455 }
457 #if ENABLE_LCMS
458 void ColorICCSelector::_profileSelected( GtkWidget* /*src*/, gpointer data )
459 {
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 }
467 }
468 #endif // ENABLE_LCMS
470 #ifdef ENABLE_LCMS
471 void ColorICCSelector::_switchToProfile( gchar const* name )
472 {
473 bool dirty = false;
474 SPColor tmp( _color );
476 if ( name ) {
477 if ( tmp.icc && tmp.icc->colorProfile == name ) {
478 #ifdef DEBUG_LCMS
479 g_message("Already at name [%s]", name );
480 #endif // DEBUG_LCMS
481 } else {
482 #ifdef 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 #ifdef 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 #ifdef 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 #ifdef 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 #ifdef 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 #ifdef 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 #ifdef DEBUG_LCMS
546 g_message("No icc to nuke");
547 #endif // DEBUG_LCMS
548 }
549 }
551 if ( dirty ) {
552 #ifdef 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 #ifdef DEBUG_LCMS
560 g_message("+_________________");
561 #endif // DEBUG_LCMS
562 }
563 }
564 #endif // ENABLE_LCMS
566 void ColorICCSelector::_profilesChanged( std::string const & name )
567 {
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
599 }
601 /* Helpers for setting color value */
603 void ColorICCSelector::_colorChanged()
604 {
605 _updating = TRUE;
606 //sp_color_icc_set_color( SP_COLOR_ICC( _icc ), &color );
608 #ifdef 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 #ifdef 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 cmsHTRANSFORM trans = _prof->getTransfToSRGB8();
641 if ( trans ) {
642 cmsDoTransform( trans, tmp, post, 1 );
643 guint32 other = SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255 );
644 if ( other != _color.toRGBA32(255) ) {
645 _fixupNeeded = other;
646 gtk_widget_set_sensitive( _fixupBtn, TRUE );
647 #ifdef DEBUG_LCMS
648 g_message("Color needs to change 0x%06x to 0x%06x", _color.toRGBA32(255) >> 8, other >> 8 );
649 #endif // DEBUG_LCMS
650 }
651 }
652 }
653 #else
654 //(void)color;
655 #endif // ENABLE_LCMS
656 _updateSliders( -1 );
659 _updating = FALSE;
660 #ifdef DEBUG_LCMS
661 g_message( "\\_________ %p::_colorChanged()", this );
662 #endif // DEBUG_LCMS
663 }
665 #if ENABLE_LCMS
666 void ColorICCSelector::_setProfile( SVGICCColor* profile )
667 {
668 #ifdef DEBUG_LCMS
669 g_message( "/^^^^^^^^^ %p::_setProfile(%s)", this,
670 ( (profile) ? profile->colorProfile.c_str() : "<null>")
671 );
672 #endif // DEBUG_LCMS
673 bool profChanged = false;
674 if ( _prof && (!profile || (_profileName != profile->colorProfile) ) ) {
675 // Need to clear out the prior one
676 profChanged = true;
677 _profileName.clear();
678 _prof = 0;
679 _profChannelCount = 0;
680 } else if ( profile && !_prof ) {
681 profChanged = true;
682 }
684 for ( guint i = 0; i < _fooCount; i++ ) {
685 gtk_widget_hide( _fooLabel[i] );
686 gtk_widget_hide( _fooSlider[i] );
687 gtk_widget_hide( _fooBtn[i] );
688 }
690 if ( profile ) {
691 _prof = SP_ACTIVE_DOCUMENT->profileManager->find(profile->colorProfile.c_str());
692 if ( _prof && _prof->getProfileClass() != icSigNamedColorClass ) {
693 _profChannelCount = _cmsChannelsOf( _prof->getColorSpace() );
695 gchar const** names = 0;
696 gchar const** tips = 0;
697 getThings( _prof->getColorSpace(), names, tips, _fooScales );
699 if ( profChanged ) {
700 for ( guint i = 0; i < _profChannelCount; i++ ) {
701 gtk_label_set_text_with_mnemonic( GTK_LABEL(_fooLabel[i]), names[i]);
703 gtk_tooltips_set_tip( _tt, _fooSlider[i], tips[i], NULL );
704 gtk_tooltips_set_tip( _tt, _fooBtn[i], tips[i], NULL );
706 sp_color_slider_set_colors( SP_COLOR_SLIDER(_fooSlider[i]),
707 SPColor(0.0, 0.0, 0.0).toRGBA32(0xff),
708 SPColor(0.5, 0.5, 0.5).toRGBA32(0xff),
709 SPColor(1.0, 1.0, 1.0).toRGBA32(0xff) );
710 /*
711 _fooAdj[i] = GTK_ADJUSTMENT( gtk_adjustment_new( val, 0.0, _fooScales[i], step, page, page ) );
712 gtk_signal_connect( GTK_OBJECT( _fooAdj[i] ), "value_changed", GTK_SIGNAL_FUNC( _adjustmentChanged ), _csel );
714 sp_color_slider_set_adjustment( SP_COLOR_SLIDER(_fooSlider[i]), _fooAdj[i] );
715 gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(_fooBtn[i]), _fooAdj[i] );
716 gtk_spin_button_set_digits( GTK_SPIN_BUTTON(_fooBtn[i]), digits );
717 */
718 gtk_widget_show( _fooLabel[i] );
719 gtk_widget_show( _fooSlider[i] );
720 gtk_widget_show( _fooBtn[i] );
721 //gtk_adjustment_set_value( _fooAdj[i], 0.0 );
722 //gtk_adjustment_set_value( _fooAdj[i], val );
723 }
724 for ( guint i = _profChannelCount; i < _fooCount; i++ ) {
725 gtk_widget_hide( _fooLabel[i] );
726 gtk_widget_hide( _fooSlider[i] );
727 gtk_widget_hide( _fooBtn[i] );
728 }
729 }
730 } else {
731 // Give up for now on named colors
732 _prof = 0;
733 }
734 }
736 #ifdef DEBUG_LCMS
737 g_message( "\\_________ %p::_setProfile()", this );
738 #endif // DEBUG_LCMS
739 }
740 #endif // ENABLE_LCMS
742 void ColorICCSelector::_updateSliders( gint ignore )
743 {
744 #ifdef ENABLE_LCMS
745 if ( _color.icc )
746 {
747 for ( guint i = 0; i < _profChannelCount; i++ ) {
748 gdouble val = 0.0;
749 if ( _color.icc->colors.size() > i ) {
750 if ( _fooScales[i] == 256 ) {
751 val = (_color.icc->colors[i] + 128.0) / static_cast<gdouble>(_fooScales[i]);
752 } else {
753 val = _color.icc->colors[i] / static_cast<gdouble>(_fooScales[i]);
754 }
755 }
756 gtk_adjustment_set_value( _fooAdj[i], val );
757 }
759 if ( _prof && _prof->getTransfToSRGB8() ) {
760 for ( guint i = 0; i < _profChannelCount; i++ ) {
761 if ( static_cast<gint>(i) != ignore ) {
762 icUInt16Number* scratch = getScratch();
763 icUInt16Number filler[4] = {0, 0, 0, 0};
764 for ( guint j = 0; j < _profChannelCount; j++ ) {
765 filler[j] = 0x0ffff * ColorScales::getScaled( _fooAdj[j] );
766 }
768 icUInt16Number* p = scratch;
769 for ( guint x = 0; x < 1024; x++ ) {
770 for ( guint j = 0; j < _profChannelCount; j++ ) {
771 if ( j == i ) {
772 *p++ = x * 0x0ffff / 1024;
773 } else {
774 *p++ = filler[j];
775 }
776 }
777 }
779 cmsHTRANSFORM trans = _prof->getTransfToSRGB8();
780 if ( trans ) {
781 cmsDoTransform( trans, scratch, _fooMap[i], 1024 );
782 sp_color_slider_set_map( SP_COLOR_SLIDER(_fooSlider[i]), _fooMap[i] );
783 }
784 }
785 }
786 }
787 }
788 #else
789 (void)ignore;
790 #endif // ENABLE_LCMS
792 guint32 start = _color.toRGBA32( 0x00 );
793 guint32 mid = _color.toRGBA32( 0x7f );
794 guint32 end = _color.toRGBA32( 0xff );
796 sp_color_slider_set_colors( SP_COLOR_SLIDER(_slider), start, mid, end );
798 }
801 void ColorICCSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICCSelector *cs )
802 {
803 // // TODO check this. It looks questionable:
804 // // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255 or 0..100
805 // if (adjustment->value > 0.0 && adjustment->value < 1.0) {
806 // gtk_adjustment_set_value( adjustment, floor ((adjustment->value) * adjustment->upper + 0.5) );
807 // }
809 #ifdef DEBUG_LCMS
810 g_message( "/^^^^^^^^^ %p::_adjustmentChanged()", cs );
811 #endif // DEBUG_LCMS
813 ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
814 if (iccSelector->_updating) {
815 return;
816 }
818 iccSelector->_updating = TRUE;
820 gint match = -1;
822 SPColor newColor( iccSelector->_color );
823 gfloat scaled = ColorScales::getScaled( iccSelector->_adj );
824 if ( iccSelector->_adj == adjustment ) {
825 #ifdef DEBUG_LCMS
826 g_message("ALPHA");
827 #endif // DEBUG_LCMS
828 } else {
829 #if ENABLE_LCMS
830 for ( guint i = 0; i < iccSelector->_fooCount; i++ ) {
831 if ( iccSelector->_fooAdj[i] == adjustment ) {
832 match = i;
833 break;
834 }
835 }
836 if ( match >= 0 ) {
837 #ifdef DEBUG_LCMS
838 g_message(" channel %d", match );
839 #endif // DEBUG_LCMS
840 }
843 icUInt16Number tmp[4];
844 for ( guint i = 0; i < 4; i++ ) {
845 tmp[i] = ColorScales::getScaled( iccSelector->_fooAdj[i] ) * 0x0ffff;
846 }
847 guchar post[4] = {0,0,0,0};
849 cmsHTRANSFORM trans = iccSelector->_prof->getTransfToSRGB8();
850 if ( trans ) {
851 cmsDoTransform( trans, tmp, post, 1 );
852 }
854 SPColor other( SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255) );
855 other.icc = new SVGICCColor();
856 if ( iccSelector->_color.icc ) {
857 other.icc->colorProfile = iccSelector->_color.icc->colorProfile;
858 }
860 guint32 prior = iccSelector->_color.toRGBA32(255);
861 guint32 newer = other.toRGBA32(255);
863 if ( prior != newer ) {
864 #ifdef DEBUG_LCMS
865 g_message("Transformed color from 0x%08x to 0x%08x", prior, newer );
866 g_message(" ~~~~ FLIP");
867 #endif // DEBUG_LCMS
868 newColor = other;
869 newColor.icc->colors.clear();
870 for ( guint i = 0; i < iccSelector->_profChannelCount; i++ ) {
871 gdouble val = ColorScales::getScaled( iccSelector->_fooAdj[i] );
872 if ( iccSelector->_fooScales ) {
873 val *= iccSelector->_fooScales[i];
874 if ( iccSelector->_fooScales[i] == 256 ) {
875 val -= 128;
876 }
877 }
878 newColor.icc->colors.push_back( val );
879 }
880 }
881 #endif // ENABLE_LCMS
882 }
883 iccSelector->_updateInternals( newColor, scaled, iccSelector->_dragging );
884 iccSelector->_updateSliders( match );
886 iccSelector->_updating = FALSE;
887 #ifdef DEBUG_LCMS
888 g_message( "\\_________ %p::_adjustmentChanged()", cs );
889 #endif // DEBUG_LCMS
890 }
892 void ColorICCSelector::_sliderGrabbed( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
893 {
894 // ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
895 // if (!iccSelector->_dragging) {
896 // iccSelector->_dragging = TRUE;
897 // iccSelector->_grabbed();
898 // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
899 // }
900 }
902 void ColorICCSelector::_sliderReleased( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
903 {
904 // ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
905 // if (iccSelector->_dragging) {
906 // iccSelector->_dragging = FALSE;
907 // iccSelector->_released();
908 // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
909 // }
910 }
912 #ifdef DEBUG_LCMS
913 void ColorICCSelector::_sliderChanged( SPColorSlider *slider, SPColorICCSelector *cs )
914 #else
915 void ColorICCSelector::_sliderChanged( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
916 #endif // DEBUG_LCMS
917 {
918 #ifdef DEBUG_LCMS
919 g_message("Changed %p and %p", slider, cs );
920 #endif // DEBUG_LCMS
921 // ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
923 // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
924 }
927 /*
928 Local Variables:
929 mode:c++
930 c-file-style:"stroustrup"
931 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
932 indent-tabs-mode:nil
933 fill-column:99
934 End:
935 */
936 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :