43a2a3cbe7ef7a573aef17ab06cb22e5442976b3
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 #ifdef DEBUG_LCMS
27 #include "prefs-utils.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 gint dump = prefs_get_int_attribute_limited("options.scislac", #key, 0, 0, 1);\
38 gint dumpD = prefs_get_int_attribute_limited("options.scislac", #key"D", 0, 0, 1);\
39 gint dumpD2 = prefs_get_int_attribute_limited("options.scislac", #key"D2", 0, 0, 1);\
40 dumpD &= ( (update_in_progress == 0) || dumpD2 );\
41 if ( dump )\
42 {\
43 g_message( __VA_ARGS__ );\
44 \
45 }\
46 if ( dumpD )\
47 {\
48 GtkWidget *dialog = gtk_message_dialog_new(NULL,\
49 GTK_DIALOG_DESTROY_WITH_PARENT, \
50 GTK_MESSAGE_INFO, \
51 GTK_BUTTONS_OK, \
52 __VA_ARGS__ \
53 );\
54 g_signal_connect_swapped(dialog, "response",\
55 G_CALLBACK(gtk_widget_destroy), \
56 dialog); \
57 gtk_widget_show_all( dialog );\
58 }\
59 }
60 #endif // DEBUG_LCMS
64 G_BEGIN_DECLS
66 static void sp_color_icc_selector_class_init (SPColorICCSelectorClass *klass);
67 static void sp_color_icc_selector_init (SPColorICCSelector *cs);
68 static void sp_color_icc_selector_destroy (GtkObject *object);
70 static void sp_color_icc_selector_show_all (GtkWidget *widget);
71 static void sp_color_icc_selector_hide_all (GtkWidget *widget);
74 G_END_DECLS
76 static SPColorSelectorClass *parent_class;
78 #define XPAD 4
79 #define YPAD 1
81 GType
82 sp_color_icc_selector_get_type (void)
83 {
84 static GType type = 0;
85 if (!type) {
86 static const GTypeInfo info = {
87 sizeof (SPColorICCSelectorClass),
88 NULL, /* base_init */
89 NULL, /* base_finalize */
90 (GClassInitFunc) sp_color_icc_selector_class_init,
91 NULL, /* class_finalize */
92 NULL, /* class_data */
93 sizeof (SPColorICCSelector),
94 0, /* n_preallocs */
95 (GInstanceInitFunc) sp_color_icc_selector_init,
96 0, /* value_table */
97 };
99 type = g_type_register_static (SP_TYPE_COLOR_SELECTOR,
100 "SPColorICCSelector",
101 &info,
102 static_cast< GTypeFlags > (0) );
103 }
104 return type;
105 }
107 static void
108 sp_color_icc_selector_class_init (SPColorICCSelectorClass *klass)
109 {
110 static const gchar* nameset[] = {N_("CMS"), 0};
111 GtkObjectClass *object_class;
112 GtkWidgetClass *widget_class;
113 SPColorSelectorClass *selector_class;
115 object_class = (GtkObjectClass *) klass;
116 widget_class = (GtkWidgetClass *) klass;
117 selector_class = SP_COLOR_SELECTOR_CLASS (klass);
119 parent_class = SP_COLOR_SELECTOR_CLASS (g_type_class_peek_parent (klass));
121 selector_class->name = nameset;
122 selector_class->submode_count = 1;
124 object_class->destroy = sp_color_icc_selector_destroy;
126 widget_class->show_all = sp_color_icc_selector_show_all;
127 widget_class->hide_all = sp_color_icc_selector_hide_all;
128 }
131 ColorICCSelector::ColorICCSelector( SPColorSelector* csel )
132 : ColorSelector( csel ),
133 _updating( FALSE ),
134 _dragging( FALSE ),
135 _fixupNeeded(0),
136 _fooCount(0),
137 _fooScales(0),
138 _fooAdj(0),
139 _fooSlider(0),
140 _fooBtn(0),
141 _fooLabel(0),
142 _fooMap(0),
143 _adj(0),
144 _sbtn(0),
145 _label(0),
146 _tt(0)
147 #if ENABLE_LCMS
148 ,
149 _profileName(""),
150 _prof(),
151 _profChannelCount(0),
152 _profChangedID(0)
153 #endif // ENABLE_LCMS
154 {
155 }
157 ColorICCSelector::~ColorICCSelector()
158 {
159 _adj = 0;
160 _sbtn = 0;
161 _label = 0;
162 }
164 void sp_color_icc_selector_init (SPColorICCSelector *cs)
165 {
166 SP_COLOR_SELECTOR(cs)->base = new ColorICCSelector( SP_COLOR_SELECTOR(cs) );
168 if ( SP_COLOR_SELECTOR(cs)->base )
169 {
170 SP_COLOR_SELECTOR(cs)->base->init();
171 }
172 }
175 /*
176 icSigRgbData
177 icSigCmykData
178 icSigCmyData
179 */
180 #define SPACE_ID_RGB 0
181 #define SPACE_ID_CMY 1
182 #define SPACE_ID_CMYK 2
185 #if ENABLE_LCMS
186 static icUInt16Number* getScratch() {
187 // bytes per pixel * input channels * width
188 static icUInt16Number* scritch = static_cast<icUInt16Number*>(g_new(icUInt16Number, 4 * 1024));
190 return scritch;
191 }
193 struct MapMap {
194 DWORD space;
195 DWORD inForm;
196 };
198 void getThings( DWORD space, gchar const**& namers, gchar const**& tippies, guint const*& scalies ) {
199 MapMap possible[] = {
200 {icSigXYZData, TYPE_XYZ_16},
201 {icSigLabData, TYPE_Lab_16},
202 //icSigLuvData
203 {icSigYCbCrData, TYPE_YCbCr_16},
204 {icSigYxyData, TYPE_Yxy_16},
205 {icSigRgbData, TYPE_RGB_16},
206 {icSigGrayData, TYPE_GRAY_16},
207 {icSigHsvData, TYPE_HSV_16},
208 {icSigHlsData, TYPE_HLS_16},
209 {icSigCmykData, TYPE_CMYK_16},
210 {icSigCmyData, TYPE_CMY_16},
211 };
213 static gchar const *names[][6] = {
214 {"_X", "_Y", "_Z", "", "", ""},
215 {"_L", "_a", "_b", "", "", ""},
216 //
217 {"_Y", "C_b", "C_r", "", "", ""},
218 {"_Y", "_x", "y", "", "", ""},
219 {_("_R"), _("_G"), _("_B"), "", "", ""},
220 {_("_G"), "", "", "", "", ""},
221 {_("_H"), _("_S"), "_V", "", "", ""},
222 {_("_H"), _("_L"), _("_S"), "", "", ""},
223 {_("_C"), _("_M"), _("_Y"), _("_K"), "", ""},
224 {_("_C"), _("_M"), _("_Y"), "", "", ""},
225 };
227 static gchar const *tips[][6] = {
228 {"X", "Y", "Z", "", "", ""},
229 {"L", "a", "b", "", "", ""},
230 //
231 {"Y", "Cb", "Cr", "", "", ""},
232 {"Y", "x", "y", "", "", ""},
233 {_("Red"), _("Green"), _("Blue"), "", "", ""},
234 {_("Gray"), "", "", "", "", ""},
235 {_("Hue"), _("Saturation"), "Value", "", "", ""},
236 {_("Hue"), _("Lightness"), _("Saturation"), "", "", ""},
237 {_("Cyan"), _("Magenta"), _("Yellow"), _("Black"), "", ""},
238 {_("Cyan"), _("Magenta"), _("Yellow"), "", "", ""},
239 };
241 static guint scales[][6] = {
242 {2, 1, 2, 1, 1, 1},
243 {100, 256, 256, 1, 1, 1},
244 //
245 {1, 1, 1, 1, 1, 1},
246 {1, 1, 1, 1, 1, 1},
247 {1, 1, 1, 1, 1, 1},
248 {1, 1, 1, 1, 1, 1},
249 {360, 1, 1, 1, 1, 1},
250 {360, 1, 1, 1, 1, 1},
251 {1, 1, 1, 1, 1, 1},
252 {1, 1, 1, 1, 1, 1},
253 };
255 int index = 0;
256 for ( guint i = 0; i < G_N_ELEMENTS(possible); i++ ) {
257 if ( possible[i].space == space ) {
258 index = i;
259 break;
260 }
261 }
263 namers = names[index];
264 tippies = tips[index];
265 scalies = scales[index];
266 }
267 #endif // ENABLE_LCMS
270 void ColorICCSelector::init()
271 {
272 GtkWidget *t;
273 gint row = 0;
275 _updating = FALSE;
276 _dragging = FALSE;
278 _tt = gtk_tooltips_new();
280 t = gtk_table_new (5, 3, FALSE);
281 gtk_widget_show (t);
282 gtk_box_pack_start (GTK_BOX (_csel), t, TRUE, TRUE, 0);
284 #if ENABLE_LCMS
285 //guint partCount = _cmsChannelsOf( icSigRgbData );
286 gchar const** names = 0;
287 gchar const** tips = 0;
288 getThings( icSigRgbData, names, tips, _fooScales );
289 #endif // ENABLE_LCMS
291 /* Create components */
292 row = 0;
295 _fixupBtn = gtk_button_new_with_label(_("Fix"));
296 g_signal_connect( G_OBJECT(_fixupBtn), "clicked", G_CALLBACK(_fixupHit), (gpointer)this );
297 gtk_widget_set_sensitive( _fixupBtn, FALSE );
298 gtk_tooltips_set_tip( _tt, _fixupBtn, _("Fix RGB fallback to match icc-color() value."), NULL );
299 //gtk_misc_set_alignment( GTK_MISC (_fixupBtn), 1.0, 0.5 );
300 gtk_widget_show( _fixupBtn );
301 gtk_table_attach( GTK_TABLE (t), _fixupBtn, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD );
304 _profileSel = gtk_combo_box_new_text();
305 gtk_combo_box_append_text( GTK_COMBO_BOX(_profileSel), "<none>" );
306 gtk_widget_show( _profileSel );
307 gtk_combo_box_set_active( GTK_COMBO_BOX(_profileSel), 0 );
308 gtk_table_attach( GTK_TABLE(t), _profileSel, 1, 2, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD );
310 #if ENABLE_LCMS
311 _profChangedID = g_signal_connect( G_OBJECT(_profileSel), "changed", G_CALLBACK(_profileSelected), (gpointer)this );
312 #else
313 gtk_widget_set_sensitive( _profileSel, false );
314 #endif // ENABLE_LCMS
317 row++;
319 _fooCount = 4;
320 _fooAdj = new GtkAdjustment*[_fooCount];
321 _fooSlider = new GtkWidget*[_fooCount];
322 _fooBtn = new GtkWidget*[_fooCount];
323 _fooLabel = new GtkWidget*[_fooCount];
324 _fooMap = new guchar*[_fooCount];
326 for ( guint i = 0; i < _fooCount; i++ ) {
327 /* Label */
328 #if ENABLE_LCMS
329 _fooLabel[i] = gtk_label_new_with_mnemonic( names[i] );
330 #else
331 _fooLabel[i] = gtk_label_new_with_mnemonic( "." );
332 #endif // ENABLE_LCMS
333 gtk_misc_set_alignment( GTK_MISC (_fooLabel[i]), 1.0, 0.5 );
334 gtk_widget_show( _fooLabel[i] );
335 gtk_table_attach( GTK_TABLE (t), _fooLabel[i], 0, 1, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD );
337 /* Adjustment */
338 gdouble step = static_cast<gdouble>(_fooScales[i]) / 100.0;
339 gdouble page = static_cast<gdouble>(_fooScales[i]) / 10.0;
340 gint digits = (step > 0.9) ? 0 : 2;
341 _fooAdj[i] = GTK_ADJUSTMENT( gtk_adjustment_new( 0.0, 0.0, _fooScales[i], step, page, page ) );
343 /* Slider */
344 _fooSlider[i] = sp_color_slider_new( _fooAdj[i] );
345 #if ENABLE_LCMS
346 gtk_tooltips_set_tip( _tt, _fooSlider[i], tips[i], NULL );
347 #else
348 gtk_tooltips_set_tip( _tt, _fooSlider[i], ".", NULL );
349 #endif // ENABLE_LCMS
350 gtk_widget_show( _fooSlider[i] );
351 gtk_table_attach( GTK_TABLE (t), _fooSlider[i], 1, 2, row, row + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)GTK_FILL, XPAD, YPAD );
353 _fooBtn[i] = gtk_spin_button_new( _fooAdj[i], step, digits );
354 #if ENABLE_LCMS
355 gtk_tooltips_set_tip( _tt, _fooBtn[i], tips[i], NULL );
356 #else
357 gtk_tooltips_set_tip( _tt, _fooBtn[i], ".", NULL );
358 #endif // ENABLE_LCMS
359 sp_dialog_defocus_on_enter( _fooBtn[i] );
360 gtk_label_set_mnemonic_widget( GTK_LABEL(_fooLabel[i]), _fooBtn[i] );
361 gtk_widget_show( _fooBtn[i] );
362 gtk_table_attach( GTK_TABLE (t), _fooBtn[i], 2, 3, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, XPAD, YPAD );
364 _fooMap[i] = g_new( guchar, 4 * 1024 );
365 memset( _fooMap[i], 0x0ff, 1024 * 4 );
368 /* Signals */
369 gtk_signal_connect( GTK_OBJECT( _fooAdj[i] ), "value_changed", GTK_SIGNAL_FUNC( _adjustmentChanged ), _csel );
371 gtk_signal_connect( GTK_OBJECT( _fooSlider[i] ), "grabbed", GTK_SIGNAL_FUNC( _sliderGrabbed ), _csel );
372 gtk_signal_connect( GTK_OBJECT( _fooSlider[i] ), "released", GTK_SIGNAL_FUNC( _sliderReleased ), _csel );
373 gtk_signal_connect( GTK_OBJECT( _fooSlider[i] ), "changed", GTK_SIGNAL_FUNC( _sliderChanged ), _csel );
375 row++;
376 }
378 /* Label */
379 _label = gtk_label_new_with_mnemonic (_("_A"));
380 gtk_misc_set_alignment (GTK_MISC (_label), 1.0, 0.5);
381 gtk_widget_show (_label);
382 gtk_table_attach (GTK_TABLE (t), _label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, XPAD, YPAD);
384 /* Adjustment */
385 _adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 10.0, 10.0);
387 /* Slider */
388 _slider = sp_color_slider_new (_adj);
389 gtk_tooltips_set_tip (_tt, _slider, _("Alpha (opacity)"), NULL);
390 gtk_widget_show (_slider);
391 gtk_table_attach (GTK_TABLE (t), _slider, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)GTK_FILL, XPAD, YPAD);
393 sp_color_slider_set_colors( SP_COLOR_SLIDER( _slider ),
394 SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 0.0 ),
395 SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 0.5 ),
396 SP_RGBA32_F_COMPOSE( 1.0, 1.0, 1.0, 1.0 ) );
399 /* Spinbutton */
400 _sbtn = gtk_spin_button_new (GTK_ADJUSTMENT (_adj), 1.0, 0);
401 gtk_tooltips_set_tip (_tt, _sbtn, _("Alpha (opacity)"), NULL);
402 sp_dialog_defocus_on_enter (_sbtn);
403 gtk_label_set_mnemonic_widget (GTK_LABEL(_label), _sbtn);
404 gtk_widget_show (_sbtn);
405 gtk_table_attach (GTK_TABLE (t), _sbtn, 2, 3, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, XPAD, YPAD);
407 /* Signals */
408 gtk_signal_connect (GTK_OBJECT (_adj), "value_changed",
409 GTK_SIGNAL_FUNC (_adjustmentChanged), _csel);
411 gtk_signal_connect (GTK_OBJECT (_slider), "grabbed",
412 GTK_SIGNAL_FUNC (_sliderGrabbed), _csel);
413 gtk_signal_connect (GTK_OBJECT (_slider), "released",
414 GTK_SIGNAL_FUNC (_sliderReleased), _csel);
415 gtk_signal_connect (GTK_OBJECT (_slider), "changed",
416 GTK_SIGNAL_FUNC (_sliderChanged), _csel);
417 }
419 static void
420 sp_color_icc_selector_destroy (GtkObject *object)
421 {
422 if (((GtkObjectClass *) (parent_class))->destroy)
423 (* ((GtkObjectClass *) (parent_class))->destroy) (object);
424 }
426 static void
427 sp_color_icc_selector_show_all (GtkWidget *widget)
428 {
429 gtk_widget_show (widget);
430 }
432 static void
433 sp_color_icc_selector_hide_all (GtkWidget *widget)
434 {
435 gtk_widget_hide (widget);
436 }
438 GtkWidget *
439 sp_color_icc_selector_new (void)
440 {
441 SPColorICCSelector *csel;
443 csel = (SPColorICCSelector*)gtk_type_new (SP_TYPE_COLOR_ICC_SELECTOR);
445 return GTK_WIDGET (csel);
446 }
449 void ColorICCSelector::_fixupHit( GtkWidget* /*src*/, gpointer data )
450 {
451 ColorICCSelector* self = reinterpret_cast<ColorICCSelector*>(data);
452 gtk_widget_set_sensitive( self->_fixupBtn, FALSE );
453 self->_adjustmentChanged( self->_fooAdj[0], SP_COLOR_ICC_SELECTOR(self->_csel) );
454 }
456 #if ENABLE_LCMS
457 void ColorICCSelector::_profileSelected( GtkWidget* /*src*/, gpointer data )
458 {
459 ColorICCSelector* self = reinterpret_cast<ColorICCSelector*>(data);
460 gint activeIndex = gtk_combo_box_get_active( GTK_COMBO_BOX(self->_profileSel) );
461 gchar* name = (activeIndex != 0) ? gtk_combo_box_get_active_text( GTK_COMBO_BOX(self->_profileSel) ) : 0;
462 self->_switchToProfile( name );
463 if ( name ) {
464 g_free( name );
465 }
466 }
467 #endif // ENABLE_LCMS
469 #ifdef ENABLE_LCMS
470 void ColorICCSelector::_switchToProfile( gchar const* name )
471 {
472 bool dirty = false;
473 SPColor tmp( _color );
475 if ( name ) {
476 if ( tmp.icc && tmp.icc->colorProfile == name ) {
477 #ifdef DEBUG_LCMS
478 g_message("Already at name [%s]", name );
479 #endif // DEBUG_LCMS
480 } else {
481 #ifdef DEBUG_LCMS
482 g_message("Need to switch to profile [%s]", name );
483 #endif // DEBUG_LCMS
484 if ( tmp.icc ) {
485 tmp.icc->colors.clear();
486 } else {
487 tmp.icc = new SVGICCColor();
488 }
489 tmp.icc->colorProfile = name;
490 Inkscape::ColorProfile* newProf = SP_ACTIVE_DOCUMENT->profileManager->find(name);
491 if ( newProf ) {
492 cmsHTRANSFORM trans = newProf->getTransfFromSRGB8();
493 if ( trans ) {
494 guint32 val = _color.toRGBA32(0);
495 guchar pre[4] = {
496 SP_RGBA32_R_U(val),
497 SP_RGBA32_G_U(val),
498 SP_RGBA32_B_U(val),
499 255};
500 #ifdef DEBUG_LCMS
501 g_message("Shoving in [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]);
502 #endif // DEBUG_LCMS
503 icUInt16Number post[4] = {0,0,0,0};
504 cmsDoTransform( trans, pre, post, 1 );
505 #ifdef DEBUG_LCMS
506 g_message("got on out [%04x] [%04x] [%04x] [%04x]", post[0], post[1], post[2], post[3]);
507 #endif // DEBUG_LCMS
508 guint count = _cmsChannelsOf( newProf->getColorSpace() );
510 gchar const** names = 0;
511 gchar const** tips = 0;
512 guint const* scales = 0;
513 getThings( newProf->getColorSpace(), names, tips, scales );
515 for ( guint i = 0; i < count; i++ ) {
516 gdouble val = (((gdouble)post[i])/65535.0) * (gdouble)scales[i];
517 #ifdef DEBUG_LCMS
518 g_message(" scaled %d by %d to be %f", i, scales[i], val);
519 #endif // DEBUG_LCMS
520 tmp.icc->colors.push_back(val);
521 }
522 cmsHTRANSFORM retrans = newProf->getTransfToSRGB8();
523 if ( retrans ) {
524 cmsDoTransform( retrans, post, pre, 1 );
525 #ifdef DEBUG_LCMS
526 g_message(" back out [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]);
527 #endif // DEBUG_LCMS
528 tmp.set(SP_RGBA32_U_COMPOSE(pre[0], pre[1], pre[2], 0xff));
529 }
530 }
531 }
532 dirty = true;
533 }
534 } else {
535 #ifdef DEBUG_LCMS
536 g_message("NUKE THE ICC");
537 #endif // DEBUG_LCMS
538 if ( tmp.icc ) {
539 delete tmp.icc;
540 tmp.icc = 0;
541 dirty = true;
542 _fixupHit( 0, this );
543 } else {
544 #ifdef DEBUG_LCMS
545 g_message("No icc to nuke");
546 #endif // DEBUG_LCMS
547 }
548 }
550 if ( dirty ) {
551 #ifdef DEBUG_LCMS
552 g_message("+----------------");
553 g_message("+ new color is [%s]", tmp.toString().c_str());
554 #endif // DEBUG_LCMS
555 _setProfile( tmp.icc );
556 //_adjustmentChanged( _fooAdj[0], SP_COLOR_ICC_SELECTOR(_csel) );
557 setColorAlpha( tmp, _alpha, true );
558 #ifdef DEBUG_LCMS
559 g_message("+_________________");
560 #endif // DEBUG_LCMS
561 }
562 }
563 #endif // ENABLE_LCMS
565 void ColorICCSelector::_profilesChanged( std::string const & name )
566 {
567 #ifdef ENABLE_LCMS
568 GtkComboBox* combo = GTK_COMBO_BOX(_profileSel);
570 g_signal_handler_block( G_OBJECT(_profileSel), _profChangedID );
572 GtkTreeModel* model = gtk_combo_box_get_model( combo );
573 GtkTreeIter iter;
574 while ( gtk_tree_model_get_iter_first( model, &iter ) ) {
575 gtk_combo_box_remove_text( combo, 0 );
576 }
578 gtk_combo_box_append_text( combo, "<none>");
580 gtk_combo_box_set_active( combo, 0 );
582 int index = 1;
583 const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "iccprofile" );
584 while ( current ) {
585 SPObject* obj = SP_OBJECT(current->data);
586 Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj);
587 gtk_combo_box_append_text( combo, prof->name );
588 if ( name == prof->name ) {
589 gtk_combo_box_set_active( combo, index );
590 }
592 index++;
593 current = g_slist_next(current);
594 }
596 g_signal_handler_unblock( G_OBJECT(_profileSel), _profChangedID );
597 #endif // ENABLE_LCMS
598 }
600 /* Helpers for setting color value */
602 void ColorICCSelector::_colorChanged()
603 {
604 _updating = TRUE;
605 // sp_color_icc_set_color( SP_COLOR_ICC( _icc ), &color );
607 #ifdef DEBUG_LCMS
608 g_message( "/^^^^^^^^^ %p::_colorChanged(%08x:%s)", this,
609 _color.toRGBA32(_alpha), ( (_color.icc) ? _color.icc->colorProfile.c_str(): "<null>" )
610 );
611 #endif // DEBUG_LCMS
613 #ifdef DEBUG_LCMS
614 g_message("FLIPPIES!!!! %p '%s'", _color.icc, (_color.icc ? _color.icc->colorProfile.c_str():"<null>"));
615 #endif // DEBUG_LCMS
617 _profilesChanged( (_color.icc) ? _color.icc->colorProfile : std::string("") );
618 ColorScales::setScaled( _adj, _alpha );
620 #if ENABLE_LCMS
621 _setProfile( _color.icc );
622 _fixupNeeded = 0;
623 gtk_widget_set_sensitive( _fixupBtn, FALSE );
625 if ( _prof && _prof->getTransfToSRGB8() ) {
626 icUInt16Number tmp[4];
627 for ( guint i = 0; i < _profChannelCount; i++ ) {
628 gdouble val = 0.0;
629 if ( _color.icc->colors.size() > i ) {
630 if ( _fooScales[i] == 256 ) {
631 val = (_color.icc->colors[i] + 128.0) / static_cast<gdouble>(_fooScales[i]);
632 } else {
633 val = _color.icc->colors[i] / static_cast<gdouble>(_fooScales[i]);
634 }
635 }
636 tmp[i] = val * 0x0ffff;
637 }
638 guchar post[4] = {0,0,0,0};
639 cmsDoTransform( _prof->getTransfToSRGB8(), tmp, post, 1 );
640 guint32 other = SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255 );
641 if ( other != _color.toRGBA32(255) ) {
642 _fixupNeeded = other;
643 gtk_widget_set_sensitive( _fixupBtn, TRUE );
644 #ifdef DEBUG_LCMS
645 g_message("Color needs to change 0x%06x to 0x%06x", _color.toRGBA32(255) >> 8, other >> 8 );
646 #endif // DEBUG_LCMS
647 }
648 }
649 #else
650 //(void)color;
651 #endif // ENABLE_LCMS
652 _updateSliders( -1 );
655 _updating = FALSE;
656 #ifdef DEBUG_LCMS
657 g_message( "\\_________ %p::_colorChanged()", this );
658 #endif // DEBUG_LCMS
659 }
661 #if ENABLE_LCMS
662 void ColorICCSelector::_setProfile( SVGICCColor* profile )
663 {
664 #ifdef DEBUG_LCMS
665 g_message( "/^^^^^^^^^ %p::_setProfile(%s)", this,
666 ( (profile) ? profile->colorProfile.c_str() : "<null>")
667 );
668 #endif // DEBUG_LCMS
669 bool profChanged = false;
670 if ( _prof && (!profile || (_profileName != profile->colorProfile) ) ) {
671 // Need to clear out the prior one
672 profChanged = true;
673 _profileName.clear();
674 _prof = 0;
675 _profChannelCount = 0;
676 } else if ( profile && !_prof ) {
677 profChanged = true;
678 }
680 for ( guint i = 0; i < _fooCount; i++ ) {
681 gtk_widget_hide( _fooLabel[i] );
682 gtk_widget_hide( _fooSlider[i] );
683 gtk_widget_hide( _fooBtn[i] );
684 }
686 if ( profile ) {
687 _prof = SP_ACTIVE_DOCUMENT->profileManager->find(profile->colorProfile.c_str());
688 if ( _prof && _prof->getProfileClass() != icSigNamedColorClass ) {
689 _profChannelCount = _cmsChannelsOf( _prof->getColorSpace() );
691 gchar const** names = 0;
692 gchar const** tips = 0;
693 getThings( _prof->getColorSpace(), names, tips, _fooScales );
695 if ( profChanged ) {
696 for ( guint i = 0; i < _profChannelCount; i++ ) {
697 gtk_label_set_text_with_mnemonic( GTK_LABEL(_fooLabel[i]), names[i]);
699 gtk_tooltips_set_tip( _tt, _fooSlider[i], tips[i], NULL );
700 gtk_tooltips_set_tip( _tt, _fooBtn[i], tips[i], NULL );
702 sp_color_slider_set_colors( SP_COLOR_SLIDER(_fooSlider[i]),
703 SPColor(0.0, 0.0, 0.0).toRGBA32(0xff),
704 SPColor(0.5, 0.5, 0.5).toRGBA32(0xff),
705 SPColor(1.0, 1.0, 1.0).toRGBA32(0xff) );
706 /*
707 _fooAdj[i] = GTK_ADJUSTMENT( gtk_adjustment_new( val, 0.0, _fooScales[i], step, page, page ) );
708 gtk_signal_connect( GTK_OBJECT( _fooAdj[i] ), "value_changed", GTK_SIGNAL_FUNC( _adjustmentChanged ), _csel );
710 sp_color_slider_set_adjustment( SP_COLOR_SLIDER(_fooSlider[i]), _fooAdj[i] );
711 gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(_fooBtn[i]), _fooAdj[i] );
712 gtk_spin_button_set_digits( GTK_SPIN_BUTTON(_fooBtn[i]), digits );
713 */
714 gtk_widget_show( _fooLabel[i] );
715 gtk_widget_show( _fooSlider[i] );
716 gtk_widget_show( _fooBtn[i] );
717 //gtk_adjustment_set_value( _fooAdj[i], 0.0 );
718 //gtk_adjustment_set_value( _fooAdj[i], val );
719 }
720 for ( guint i = _profChannelCount; i < _fooCount; i++ ) {
721 gtk_widget_hide( _fooLabel[i] );
722 gtk_widget_hide( _fooSlider[i] );
723 gtk_widget_hide( _fooBtn[i] );
724 }
725 }
726 } else {
727 // Give up for now on named colors
728 _prof = 0;
729 }
730 }
732 #ifdef DEBUG_LCMS
733 g_message( "\\_________ %p::_setProfile()", this );
734 #endif // DEBUG_LCMS
735 }
736 #endif // ENABLE_LCMS
738 void ColorICCSelector::_updateSliders( gint ignore )
739 {
740 #ifdef ENABLE_LCMS
741 if ( _color.icc )
742 {
743 for ( guint i = 0; i < _profChannelCount; i++ ) {
744 gdouble val = 0.0;
745 if ( _color.icc->colors.size() > i ) {
746 if ( _fooScales[i] == 256 ) {
747 val = (_color.icc->colors[i] + 128.0) / static_cast<gdouble>(_fooScales[i]);
748 } else {
749 val = _color.icc->colors[i] / static_cast<gdouble>(_fooScales[i]);
750 }
751 }
752 gtk_adjustment_set_value( _fooAdj[i], val );
753 }
755 if ( _prof->getTransfToSRGB8() ) {
756 for ( guint i = 0; i < _profChannelCount; i++ ) {
757 if ( static_cast<gint>(i) != ignore ) {
758 icUInt16Number* scratch = getScratch();
759 icUInt16Number filler[4] = {0, 0, 0, 0};
760 for ( guint j = 0; j < _profChannelCount; j++ ) {
761 filler[j] = 0x0ffff * ColorScales::getScaled( _fooAdj[j] );
762 }
764 icUInt16Number* p = scratch;
765 for ( guint x = 0; x < 1024; x++ ) {
766 for ( guint j = 0; j < _profChannelCount; j++ ) {
767 if ( j == i ) {
768 *p++ = x * 0x0ffff / 1024;
769 } else {
770 *p++ = filler[j];
771 }
772 }
773 }
775 cmsDoTransform( _prof->getTransfToSRGB8(), scratch, _fooMap[i], 1024 );
776 sp_color_slider_set_map( SP_COLOR_SLIDER(_fooSlider[i]), _fooMap[i] );
777 }
778 }
779 }
780 }
781 #else
782 (void)ignore;
783 #endif // ENABLE_LCMS
785 guint32 start = _color.toRGBA32( 0x00 );
786 guint32 mid = _color.toRGBA32( 0x7f );
787 guint32 end = _color.toRGBA32( 0xff );
789 sp_color_slider_set_colors( SP_COLOR_SLIDER(_slider), start, mid, end );
791 }
794 void ColorICCSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICCSelector *cs )
795 {
796 // // TODO check this. It looks questionable:
797 // // if a value is entered between 0 and 1 exclusive, normalize it to (int) 0..255 or 0..100
798 // if (adjustment->value > 0.0 && adjustment->value < 1.0) {
799 // gtk_adjustment_set_value( adjustment, floor ((adjustment->value) * adjustment->upper + 0.5) );
800 // }
802 #ifdef DEBUG_LCMS
803 g_message( "/^^^^^^^^^ %p::_adjustmentChanged()", cs );
804 #endif // DEBUG_LCMS
806 ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
807 if (iccSelector->_updating) {
808 return;
809 }
811 iccSelector->_updating = TRUE;
813 gint match = -1;
815 SPColor newColor( iccSelector->_color );
816 gfloat scaled = ColorScales::getScaled( iccSelector->_adj );
817 if ( iccSelector->_adj == adjustment ) {
818 #ifdef DEBUG_LCMS
819 g_message("ALPHA");
820 #endif // DEBUG_LCMS
821 } else {
822 #if ENABLE_LCMS
823 for ( guint i = 0; i < iccSelector->_fooCount; i++ ) {
824 if ( iccSelector->_fooAdj[i] == adjustment ) {
825 match = i;
826 break;
827 }
828 }
829 if ( match >= 0 ) {
830 #ifdef DEBUG_LCMS
831 g_message(" channel %d", match );
832 #endif // DEBUG_LCMS
833 }
836 icUInt16Number tmp[4];
837 for ( guint i = 0; i < 4; i++ ) {
838 tmp[i] = ColorScales::getScaled( iccSelector->_fooAdj[i] ) * 0x0ffff;
839 }
840 guchar post[4] = {0,0,0,0};
842 cmsDoTransform( iccSelector->_prof->getTransfToSRGB8(), tmp, post, 1 );
844 SPColor other( SP_RGBA32_U_COMPOSE(post[0], post[1], post[2], 255) );
845 other.icc = new SVGICCColor();
846 if ( iccSelector->_color.icc ) {
847 other.icc->colorProfile = iccSelector->_color.icc->colorProfile;
848 }
850 guint32 prior = iccSelector->_color.toRGBA32(255);
851 guint32 newer = other.toRGBA32(255);
853 if ( prior != newer ) {
854 #ifdef DEBUG_LCMS
855 g_message("Transformed color from 0x%08x to 0x%08x", prior, newer );
856 g_message(" ~~~~ FLIP");
857 #endif // DEBUG_LCMS
858 newColor = other;
859 newColor.icc->colors.clear();
860 for ( guint i = 0; i < iccSelector->_profChannelCount; i++ ) {
861 gdouble val = ColorScales::getScaled( iccSelector->_fooAdj[i] );
862 if ( iccSelector->_fooScales ) {
863 val *= iccSelector->_fooScales[i];
864 if ( iccSelector->_fooScales[i] == 256 ) {
865 val -= 128;
866 }
867 }
868 newColor.icc->colors.push_back( val );
869 }
870 }
871 #endif // ENABLE_LCMS
872 }
873 iccSelector->_updateInternals( newColor, scaled, iccSelector->_dragging );
874 iccSelector->_updateSliders( match );
876 iccSelector->_updating = FALSE;
877 #ifdef DEBUG_LCMS
878 g_message( "\\_________ %p::_adjustmentChanged()", cs );
879 #endif // DEBUG_LCMS
880 }
882 void ColorICCSelector::_sliderGrabbed( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
883 {
884 // ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
885 // if (!iccSelector->_dragging) {
886 // iccSelector->_dragging = TRUE;
887 // iccSelector->_grabbed();
888 // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
889 // }
890 }
892 void ColorICCSelector::_sliderReleased( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
893 {
894 // ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
895 // if (iccSelector->_dragging) {
896 // iccSelector->_dragging = FALSE;
897 // iccSelector->_released();
898 // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
899 // }
900 }
902 #ifdef DEBUG_LCMS
903 void ColorICCSelector::_sliderChanged( SPColorSlider *slider, SPColorICCSelector *cs )
904 #else
905 void ColorICCSelector::_sliderChanged( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ )
906 #endif // DEBUG_LCMS
907 {
908 #ifdef DEBUG_LCMS
909 g_message("Changed %p and %p", slider, cs );
910 #endif // DEBUG_LCMS
911 // ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base);
913 // iccSelector->_updateInternals( iccSelector->_color, ColorScales::getScaled( iccSelector->_adj ), iccSelector->_dragging );
914 }
917 /*
918 Local Variables:
919 mode:c++
920 c-file-style:"stroustrup"
921 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
922 indent-tabs-mode:nil
923 fill-column:99
924 End:
925 */
926 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :