Index: app/core/gimpviewable.c =================================================================== --- app/core/gimpviewable.c (revision 24157) +++ app/core/gimpviewable.c (working copy) @@ -43,7 +43,8 @@ enum { PROP_0, - PROP_STOCK_ID + PROP_STOCK_ID, + PROP_FROZEN }; enum @@ -158,6 +159,12 @@ gimp_viewable_class_init (GimpViewableCl GIMP_CONFIG_INSTALL_PROP_STRING (object_class, PROP_STOCK_ID, "stock-id", NULL, NULL, GIMP_PARAM_STATIC_STRINGS); + + g_object_class_install_property (object_class, PROP_FROZEN, + g_param_spec_boolean ("frozen", + NULL, NULL, + FALSE, + GIMP_PARAM_READABLE)); } static void @@ -193,12 +200,16 @@ gimp_viewable_set_property (GObject const GValue *value, GParamSpec *pspec) { + GimpViewable *viewable = GIMP_VIEWABLE (object); + switch (property_id) { case PROP_STOCK_ID: - gimp_viewable_set_stock_id (GIMP_VIEWABLE (object), - g_value_get_string (value)); + gimp_viewable_set_stock_id (viewable, g_value_get_string (value)); break; + case PROP_FROZEN: + /* read-only, fall through */ + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -211,12 +222,17 @@ gimp_viewable_get_property (GObject * GValue *value, GParamSpec *pspec) { + GimpViewable *viewable = GIMP_VIEWABLE (object); + switch (property_id) { case PROP_STOCK_ID: - g_value_set_string (value, - gimp_viewable_get_stock_id (GIMP_VIEWABLE (object))); + g_value_set_string (value, gimp_viewable_get_stock_id (viewable)); + break; + case PROP_FROZEN: + g_value_set_boolean (value, gimp_viewable_preview_is_frozen (viewable)); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -1051,6 +1067,9 @@ gimp_viewable_preview_freeze (GimpViewab g_return_if_fail (GIMP_IS_VIEWABLE (viewable)); viewable->freeze_count++; + + if (viewable->freeze_count == 1) + g_object_notify (G_OBJECT (viewable), "frozen"); } void @@ -1062,5 +1081,16 @@ gimp_viewable_preview_thaw (GimpViewable viewable->freeze_count--; if (viewable->freeze_count == 0) - gimp_viewable_invalidate_preview (viewable); + { + gimp_viewable_invalidate_preview (viewable); + g_object_notify (G_OBJECT (viewable), "frozen"); + } +} + +gboolean +gimp_viewable_preview_is_frozen (GimpViewable *viewable) +{ + g_return_val_if_fail (GIMP_IS_VIEWABLE (viewable), FALSE); + + return viewable->freeze_count != 0; } Index: app/core/gimpviewable.h =================================================================== --- app/core/gimpviewable.h (revision 24157) +++ app/core/gimpviewable.h (working copy) @@ -172,6 +172,7 @@ void gimp_viewable_set_stock_id void gimp_viewable_preview_freeze (GimpViewable *viewable); void gimp_viewable_preview_thaw (GimpViewable *viewable); +gboolean gimp_viewable_preview_is_frozen (GimpViewable *viewable); #endif /* __GIMP_VIEWABLE_H__ */ Index: app/widgets/gimphistogramview.c =================================================================== --- app/widgets/gimphistogramview.c (revision 24157) +++ app/widgets/gimphistogramview.c (working copy) @@ -73,10 +73,12 @@ static gboolean gimp_histogram_view_moti static void gimp_histogram_view_draw_spike (GimpHistogramView *view, GimpHistogramChannel channel, GdkGC *gc, + GdkGC *bg_gc, gint x, gint i, gint j, gdouble max, + gdouble bg_max, gint height, gint border); @@ -150,9 +152,10 @@ gimp_histogram_view_class_init (GimpHist static void gimp_histogram_view_init (GimpHistogramView *view) { - view->histogram = NULL; - view->start = 0; - view->end = 255; + view->histogram = NULL; + view->bg_histogram = NULL; + view->start = 0; + view->end = 255; } static void @@ -227,9 +230,10 @@ gimp_histogram_view_size_request (GtkWid static gdouble gimp_histogram_view_get_maximum (GimpHistogramView *view, + GimpHistogram *histogram, GimpHistogramChannel channel) { - gdouble max = gimp_histogram_get_maximum (view->histogram, channel); + gdouble max = gimp_histogram_get_maximum (histogram, channel); switch (view->scale) { @@ -256,13 +260,16 @@ gimp_histogram_view_expose (GtkWidget gint x1, x2; gint border; gint width, height; - gdouble max; + gdouble max = 0.0; + gdouble bg_max = 0.0; gint xstop; GdkGC *gc_in; GdkGC *gc_out; + GdkGC *bg_gc_in; + GdkGC *bg_gc_out; GdkGC *rgb_gc[3] = { NULL, NULL, NULL }; - if (! view->histogram) + if (! view->histogram && ! view->bg_histogram) return FALSE; border = view->border_width; @@ -284,18 +291,19 @@ gimp_histogram_view_expose (GtkWidget border, border, width - 1, height - 1); - max = gimp_histogram_view_get_maximum (view, view->channel); + if (view->histogram) + max = gimp_histogram_view_get_maximum (view, view->histogram, + view->channel); + + if (view->bg_histogram) + bg_max = gimp_histogram_view_get_maximum (view, view->bg_histogram, + view->channel); - if (GIMP_HISTOGRAM_VIEW_GET_CLASS (view)->light_histogram) - { - gc_in = widget->style->mid_gc[GTK_STATE_SELECTED]; - gc_out = widget->style->mid_gc[GTK_STATE_NORMAL]; - } - else - { - gc_in = widget->style->text_gc[GTK_STATE_SELECTED]; - gc_out = widget->style->text_gc[GTK_STATE_NORMAL]; - } + gc_in = widget->style->text_gc[GTK_STATE_SELECTED]; + gc_out = widget->style->text_gc[GTK_STATE_NORMAL]; + + bg_gc_in = widget->style->mid_gc[GTK_STATE_SELECTED]; + bg_gc_out = widget->style->mid_gc[GTK_STATE_NORMAL]; if (view->channel == GIMP_HISTOGRAM_RGB) { @@ -357,17 +365,27 @@ gimp_histogram_view_expose (GtkWidget for (c = 0; c < 3; c++) gimp_histogram_view_draw_spike (view, GIMP_HISTOGRAM_RED + c, widget->style->black_gc, - x, i, j, max, height, border); + NULL, + x, i, j, max, bg_max, height, border); for (c = 0; c < 3; c++) gimp_histogram_view_draw_spike (view, GIMP_HISTOGRAM_RED + c, rgb_gc[c], - x, i, j, max, height, border); - } + NULL, + x, i, j, max, bg_max, height, border); - gimp_histogram_view_draw_spike (view, view->channel, - in_selection ? gc_in : gc_out, - x, i, j, max, height, border); + gimp_histogram_view_draw_spike (view, view->channel, + in_selection ? gc_in : gc_out, + NULL, + x, i, j, max, bg_max, height, border); + } + else + { + gimp_histogram_view_draw_spike (view, view->channel, + in_selection ? gc_in : gc_out, + in_selection ? bg_gc_in : bg_gc_out, + x, i, j, max, bg_max, height, border); + } } if (view->channel == GIMP_HISTOGRAM_RGB) @@ -383,43 +401,70 @@ static void gimp_histogram_view_draw_spike (GimpHistogramView *view, GimpHistogramChannel channel, GdkGC *gc, + GdkGC *bg_gc, gint x, gint i, gint j, gdouble max, + gdouble bg_max, gint height, gint border) { - gdouble value = 0.0; + gdouble value = 0.0; + gdouble bg_value = 0.0; gint y; + gint bg_y; - do + if (view->histogram) { - gdouble v = gimp_histogram_get_value (view->histogram, channel, i++); + do + { + gdouble v = gimp_histogram_get_value (view->histogram, channel, i++); - if (v > value) - value = v; + if (v > value) + value = v; + } + while (i < j); } - while (i < j); - if (value <= 0.0) + if (bg_gc && view->bg_histogram) + { + do + { + gdouble v = gimp_histogram_get_value (view->bg_histogram, channel, i++); + + if (v > bg_value) + bg_value = v; + } + while (i < j); + } + + if (value <= 0.0 && bg_value <= 0.0) return; switch (view->scale) { case GIMP_HISTOGRAM_SCALE_LINEAR: - y = (gint) (((height - 2) * value) / max); + y = (gint) (((height - 2) * value) / max); + bg_y = (gint) (((height - 2) * bg_value) / bg_max); break; case GIMP_HISTOGRAM_SCALE_LOGARITHMIC: - y = (gint) (((height - 2) * log (value)) / max); + y = (gint) (((height - 2) * log (value)) / max); + bg_y = (gint) (((height - 2) * log (bg_value)) / bg_max); break; default: - y = 0; + y = 0; + bg_y = 0; break; } + if (bg_gc) + gdk_draw_line (GTK_WIDGET (view)->window, bg_gc, + x + border, height + border - 1, + x + border, height + border - bg_y - 1); + gdk_draw_line (GTK_WIDGET (view)->window, gc, x + border, height + border - 1, x + border, height + border - y - 1); @@ -513,6 +558,12 @@ gimp_histogram_view_set_histogram (GimpH GimpHistogram *histogram) { g_return_if_fail (GIMP_IS_HISTOGRAM_VIEW (view)); +#if 0 + g_return_if_fail (histogram == NULL || + view->bg_histogram == NULL || + gimp_histogram_n_channels (view->bg_histogram) == + gimp_histogram_n_channels (histogram)); +#endif if (view->histogram != histogram) { @@ -534,6 +585,37 @@ gimp_histogram_view_get_histogram (GimpH } void +gimp_histogram_view_set_bg_histogram (GimpHistogramView *view, + GimpHistogram *histogram) +{ + g_return_if_fail (GIMP_IS_HISTOGRAM_VIEW (view)); +#if 0 + g_return_if_fail (histogram == NULL || + view->histogram == NULL || + gimp_histogram_n_channels (view->histogram) == + gimp_histogram_n_channels (histogram)); +#endif + + if (view->bg_histogram != histogram) + { + view->bg_histogram = histogram; + + if (histogram && view->channel >= gimp_histogram_n_channels (histogram)) + gimp_histogram_view_set_channel (view, GIMP_HISTOGRAM_VALUE); + } + + gtk_widget_queue_draw (GTK_WIDGET (view)); +} + +GimpHistogram * +gimp_histogram_view_get_bg_histogram (GimpHistogramView *view) +{ + g_return_val_if_fail (GIMP_IS_HISTOGRAM_VIEW (view), NULL); + + return view->bg_histogram; +} + +void gimp_histogram_view_set_channel (GimpHistogramView *view, GimpHistogramChannel channel) { Index: app/widgets/gimphistogramview.h =================================================================== --- app/widgets/gimphistogramview.h (revision 24157) +++ app/widgets/gimphistogramview.h (working copy) @@ -38,6 +38,7 @@ struct _GimpHistogramView GtkDrawingArea parent_instance; GimpHistogram *histogram; + GimpHistogram *bg_histogram; GimpHistogramChannel channel; GimpHistogramScale scale; gint start; @@ -51,8 +52,6 @@ struct _GimpHistogramViewClass { GtkDrawingAreaClass parent_class; - gboolean light_histogram; - void (* range_changed) (GimpHistogramView *view, gint start, gint end); @@ -67,13 +66,20 @@ void gimp_histogram_view_set_ GimpHistogram *histogram); GimpHistogram * gimp_histogram_view_get_histogram (GimpHistogramView *view); +void gimp_histogram_view_set_bg_histogram (GimpHistogramView *view, + GimpHistogram *histogram); +GimpHistogram * + gimp_histogram_view_get_bg_histogram (GimpHistogramView *view); + void gimp_histogram_view_set_channel (GimpHistogramView *view, GimpHistogramChannel channel); -GimpHistogramChannel gimp_histogram_view_get_channel (GimpHistogramView *view); +GimpHistogramChannel + gimp_histogram_view_get_channel (GimpHistogramView *view); void gimp_histogram_view_set_scale (GimpHistogramView *view, GimpHistogramScale scale); -GimpHistogramScale gimp_histogram_view_get_scale (GimpHistogramView *view); +GimpHistogramScale + gimp_histogram_view_get_scale (GimpHistogramView *view); void gimp_histogram_view_set_range (GimpHistogramView *view, gint start, Index: app/widgets/gimpcurveview.c =================================================================== --- app/widgets/gimpcurveview.c (revision 24157) +++ app/widgets/gimpcurveview.c (working copy) @@ -77,9 +77,8 @@ G_DEFINE_TYPE (GimpCurveView, gimp_curve static void gimp_curve_view_class_init (GimpCurveViewClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - GimpHistogramViewClass *hist_class = GIMP_HISTOGRAM_VIEW_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->finalize = gimp_curve_view_finalize; object_class->dispose = gimp_curve_view_dispose; @@ -94,8 +93,6 @@ gimp_curve_view_class_init (GimpCurveVie widget_class->leave_notify_event = gimp_curve_view_leave_notify; widget_class->key_press_event = gimp_curve_view_key_press; - hist_class->light_histogram = TRUE; - g_object_class_install_property (object_class, PROP_GRID_ROWS, g_param_spec_int ("grid-rows", NULL, NULL, 0, 100, 8, Index: app/widgets/gimphistogrameditor.c =================================================================== --- app/widgets/gimphistogrameditor.c (revision 24157) +++ app/widgets/gimphistogrameditor.c (working copy) @@ -53,6 +53,8 @@ static void gimp_histogram_editor_se GimpImage *image); static void gimp_histogram_editor_layer_changed (GimpImage *image, GimpHistogramEditor *editor); +static void gimp_histogram_editor_frozen_update (GimpHistogramEditor *editor, + const GParamSpec *pspec); static void gimp_histogram_editor_update (GimpHistogramEditor *editor); static gboolean gimp_histogram_editor_idle_update (GimpHistogramEditor *editor); @@ -103,11 +105,12 @@ gimp_histogram_editor_init (GimpHistogra N_("Percentile:") }; - editor->drawable = NULL; - editor->histogram = NULL; - editor->valid = FALSE; - editor->idle_id = 0; - editor->box = gimp_histogram_box_new (); + editor->drawable = NULL; + editor->histogram = NULL; + editor->bg_histogram = NULL; + editor->valid = FALSE; + editor->idle_id = 0; + editor->box = gimp_histogram_box_new (); gimp_editor_set_show_name (GIMP_EDITOR (editor), TRUE); @@ -259,9 +262,17 @@ gimp_histogram_editor_set_image (GimpIma { gimp_histogram_free (editor->histogram); editor->histogram = NULL; + + gimp_histogram_view_set_histogram (view, NULL); } - gimp_histogram_view_set_histogram (view, NULL); + if (editor->bg_histogram) + { + gimp_histogram_free (editor->bg_histogram); + editor->bg_histogram = NULL; + + gimp_histogram_view_set_bg_histogram (view, NULL); + } } GIMP_IMAGE_EDITOR_CLASS (parent_class)->set_image (image_editor, image); @@ -298,6 +309,16 @@ gimp_histogram_editor_layer_changed (Gim { if (editor->drawable) { + if (editor->bg_histogram) + { + GimpHistogramView *view = GIMP_HISTOGRAM_BOX (editor->box)->view; + + gimp_histogram_free (editor->bg_histogram); + editor->bg_histogram = NULL; + + gimp_histogram_view_set_bg_histogram (view, NULL); + } + g_signal_handlers_disconnect_by_func (editor->drawable, gimp_histogram_editor_name_update, editor); @@ -307,6 +328,9 @@ gimp_histogram_editor_layer_changed (Gim g_signal_handlers_disconnect_by_func (editor->drawable, gimp_histogram_editor_update, editor); + g_signal_handlers_disconnect_by_func (editor->drawable, + gimp_histogram_editor_frozen_update, + editor); editor->drawable = NULL; } @@ -317,6 +341,9 @@ gimp_histogram_editor_layer_changed (Gim if (editor->drawable) { + g_signal_connect_object (editor->drawable, "notify::frozen", + G_CALLBACK (gimp_histogram_editor_frozen_update), + editor, G_CONNECT_SWAPPED); g_signal_connect_object (editor->drawable, "update", G_CALLBACK (gimp_histogram_editor_update), editor, G_CONNECT_SWAPPED); @@ -340,6 +367,33 @@ gimp_histogram_editor_layer_changed (Gim } static void +gimp_histogram_editor_frozen_update (GimpHistogramEditor *editor, + const GParamSpec *pspec) +{ + GimpHistogramView *view = GIMP_HISTOGRAM_BOX (editor->box)->view; + + if (gimp_viewable_preview_is_frozen (GIMP_VIEWABLE (editor->drawable))) + { + if (! editor->bg_histogram) + { + editor->bg_histogram = gimp_histogram_new (); + + gimp_drawable_calculate_histogram (editor->drawable, + editor->bg_histogram); + + gimp_histogram_view_set_bg_histogram (view, editor->bg_histogram); + } + } + else if (editor->bg_histogram) + { + gimp_histogram_free (editor->bg_histogram); + editor->bg_histogram = NULL; + + gimp_histogram_view_set_bg_histogram (view, NULL); + } +} + +static void gimp_histogram_editor_update (GimpHistogramEditor *editor) { if (editor->idle_id) Index: app/widgets/gimphistogrameditor.h =================================================================== --- app/widgets/gimphistogrameditor.h (revision 24157) +++ app/widgets/gimphistogrameditor.h (working copy) @@ -39,6 +39,7 @@ struct _GimpHistogramEditor GimpDrawable *drawable; GimpHistogram *histogram; + GimpHistogram *bg_histogram; guint idle_id; gboolean valid;