Commit b26a0a12 authored by Ell's avatar Ell

app: various improvements to GimpMeter

Allow controlling the gauge/history visibility, and the history
interpolation method, of individual values.

Improve redraw elision when some values are hidden.
parent c548d5d3
...@@ -64,8 +64,11 @@ enum ...@@ -64,8 +64,11 @@ enum
typedef struct typedef struct
{ {
gboolean active; gboolean active;
GimpRGB color; gboolean show_in_gauge;
gboolean show_in_history;
GimpRGB color;
GimpInterpolationType interpolation;
} Value; } Value;
struct _GimpMeterPrivate struct _GimpMeterPrivate
...@@ -120,6 +123,10 @@ static void gimp_meter_clear_history_unlocked (GimpMeter *meter); ...@@ -120,6 +123,10 @@ static void gimp_meter_clear_history_unlocked (GimpMeter *meter);
static void gimp_meter_update_samples (GimpMeter *meter); static void gimp_meter_update_samples (GimpMeter *meter);
static void gimp_meter_shift_samples (GimpMeter *meter); static void gimp_meter_shift_samples (GimpMeter *meter);
static void gimp_meter_mask_sample (GimpMeter *meter,
const gdouble *sample,
gdouble *result);
G_DEFINE_TYPE (GimpMeter, gimp_meter, GTK_TYPE_WIDGET) G_DEFINE_TYPE (GimpMeter, gimp_meter, GTK_TYPE_WIDGET)
...@@ -505,8 +512,11 @@ gimp_meter_expose_event (GtkWidget *widget, ...@@ -505,8 +512,11 @@ gimp_meter_expose_event (GtkWidget *widget,
{ {
gdouble v = VALUE (0, i); gdouble v = VALUE (0, i);
if (! meter->priv->values[i].active) if (! meter->priv->values[i].active ||
continue; ! meter->priv->values[i].show_in_gauge)
{
continue;
}
gimp_cairo_set_source_rgba (cr, &meter->priv->values[i].color); gimp_cairo_set_source_rgba (cr, &meter->priv->values[i].color);
cairo_move_to (cr, 0.0, 0.0); cairo_move_to (cr, 0.0, 0.0);
...@@ -599,48 +609,85 @@ gimp_meter_expose_event (GtkWidget *widget, ...@@ -599,48 +609,85 @@ gimp_meter_expose_event (GtkWidget *widget,
2.0, 2.0,
0.0); 0.0);
/* paint history graph for each value, with cubic interpolation */ /* paint history graph for each value */
for (i = 0; i < meter->priv->n_values; i++) for (i = 0; i < meter->priv->n_values; i++)
{ {
gdouble y[4]; gdouble y;
gdouble t[2];
gdouble c[4];
gdouble x;
if (! meter->priv->values[i].active) if (! meter->priv->values[i].active ||
continue; ! meter->priv->values[i].show_in_history)
{
continue;
}
gimp_cairo_set_source_rgba (cr, &meter->priv->values[i].color); gimp_cairo_set_source_rgba (cr, &meter->priv->values[i].color);
cairo_move_to (cr, 0.0, 0.0); cairo_move_to (cr, 0.0, 0.0);
for (j = 1; j < meter->priv->n_samples - 2; j++) switch (meter->priv->values[i].interpolation)
{ {
for (k = 0; k < 4; k++) case GIMP_INTERPOLATION_NONE:
y[k] = VALUE (j + k - 1, i); {
for (j = 1; j < meter->priv->n_samples - 2; j++)
for (k = 0; k < 2; k++) {
{ gdouble y0 = VALUE (j - 1, i);
t[k] = (y[k + 2] - y[k]) / 2.0; gdouble y1 = VALUE (j, i);
t[k] = CLAMP (t[k], y[k + 1] - 1.0, y[k + 1]);
t[k] = CLAMP (t[k], -y[k + 1], 1.0 - y[k + 1]); cairo_line_to (cr, j, y0);
} cairo_line_to (cr, j, y1);
}
c[0] = y[1]; }
c[1] = t[0]; break;
c[2] = 3 * (y[2] - y[1]) - 2 * t[0] - t[1];
c[3] = t[0] + t[1] - 2 * (y[2] - y[1]); case GIMP_INTERPOLATION_LINEAR:
{
for (x = 0.0; x < 1.0; x += dx) for (j = 1; j < meter->priv->n_samples - 2; j++)
{ {
gdouble y = ((c[3] * x + c[2]) * x + c[1]) * x + c[0]; gdouble y = VALUE (j, i);
cairo_line_to (cr, j + x, y); cairo_line_to (cr, j, y);
} }
}
break;
case GIMP_INTERPOLATION_CUBIC:
default:
{
for (j = 1; j < meter->priv->n_samples - 2; j++)
{
gdouble y[4];
gdouble t[2];
gdouble c[4];
gdouble x;
for (k = 0; k < 4; k++)
y[k] = VALUE (j + k - 1, i);
for (k = 0; k < 2; k++)
{
t[k] = (y[k + 2] - y[k]) / 2.0;
t[k] = CLAMP (t[k], y[k + 1] - 1.0, y[k + 1]);
t[k] = CLAMP (t[k], -y[k + 1], 1.0 - y[k + 1]);
}
c[0] = y[1];
c[1] = t[0];
c[2] = 3 * (y[2] - y[1]) - 2 * t[0] - t[1];
c[3] = t[0] + t[1] - 2 * (y[2] - y[1]);
for (x = 0.0; x < 1.0; x += dx)
{
gdouble y = ((c[3] * x + c[2]) * x + c[1]) * x + c[0];
cairo_line_to (cr, j + x, y);
}
}
}
break;
} }
y[1] = VALUE (j, i); y = VALUE (j, i);
cairo_line_to (cr, meter->priv->n_samples - 2, y[1]); cairo_line_to (cr, meter->priv->n_samples - 2, y);
cairo_line_to (cr, meter->priv->n_samples - 2, 0.0); cairo_line_to (cr, meter->priv->n_samples - 2, 0.0);
cairo_close_path (cr); cairo_close_path (cr);
cairo_fill (cr); cairo_fill (cr);
...@@ -705,34 +752,38 @@ gimp_meter_expose_event (GtkWidget *widget, ...@@ -705,34 +752,38 @@ gimp_meter_expose_event (GtkWidget *widget,
static gboolean static gboolean
gimp_meter_timeout (GimpMeter *meter) gimp_meter_timeout (GimpMeter *meter)
{ {
gboolean uniform; gboolean uniform = TRUE;
gboolean redraw; gboolean redraw = TRUE;
gdouble sample0[meter->priv->n_values];
gint i;
g_mutex_lock (&meter->priv->mutex); g_mutex_lock (&meter->priv->mutex);
gimp_meter_shift_samples (meter); gimp_meter_shift_samples (meter);
gimp_meter_mask_sample (meter, SAMPLE (0), sample0);
if (meter->priv->history_visible) if (meter->priv->history_visible)
{ {
uniform = ! memcmp (SAMPLE (0), SAMPLE (1), for (i = 1; uniform && i < meter->priv->n_samples; i++)
(meter->priv->n_samples - 1) * SAMPLE_SIZE); {
} gdouble sample[meter->priv->n_values];
else
{ gimp_meter_mask_sample (meter, SAMPLE (i), sample);
uniform = TRUE;
uniform = ! memcmp (sample0, sample, SAMPLE_SIZE);
}
} }
if (uniform && meter->priv->uniform_sample) if (uniform && meter->priv->uniform_sample)
redraw = memcmp (SAMPLE (0), meter->priv->uniform_sample, SAMPLE_SIZE); redraw = memcmp (sample0, meter->priv->uniform_sample, SAMPLE_SIZE);
else
redraw = TRUE;
if (uniform) if (uniform)
{ {
if (! meter->priv->uniform_sample) if (! meter->priv->uniform_sample)
meter->priv->uniform_sample = g_malloc (SAMPLE_SIZE); meter->priv->uniform_sample = g_malloc (SAMPLE_SIZE);
memcpy (meter->priv->uniform_sample, SAMPLE (0), SAMPLE_SIZE); memcpy (meter->priv->uniform_sample, sample0, SAMPLE_SIZE);
} }
else else
{ {
...@@ -796,6 +847,28 @@ gimp_meter_shift_samples (GimpMeter *meter) ...@@ -796,6 +847,28 @@ gimp_meter_shift_samples (GimpMeter *meter)
meter->priv->last_sample_time = time; meter->priv->last_sample_time = time;
} }
static void
gimp_meter_mask_sample (GimpMeter *meter,
const gdouble *sample,
gdouble *result)
{
gint i;
for (i = 0; i < meter->priv->n_values; i++)
{
if (meter->priv->values[i].active &&
(meter->priv->values[i].show_in_gauge ||
meter->priv->values[i].show_in_history))
{
result[i] = sample[i];
}
else
{
result[i] = 0.0;
}
}
}
/* public functions */ /* public functions */
...@@ -934,7 +1007,11 @@ gimp_meter_set_n_values (GimpMeter *meter, ...@@ -934,7 +1007,11 @@ gimp_meter_set_n_values (GimpMeter *meter,
if (n_values > meter->priv->n_values) if (n_values > meter->priv->n_values)
{ {
gegl_memset_pattern (meter->priv->values, gegl_memset_pattern (meter->priv->values,
&(Value) { .active = TRUE }, sizeof (Value), &(Value) { .active = TRUE,
.show_in_gauge = TRUE,
.show_in_history = TRUE,
.interpolation = GIMP_INTERPOLATION_CUBIC},
sizeof (Value),
n_values - meter->priv->n_values); n_values - meter->priv->n_values);
} }
...@@ -1012,6 +1089,85 @@ gimp_meter_get_value_color (GimpMeter *meter, ...@@ -1012,6 +1089,85 @@ gimp_meter_get_value_color (GimpMeter *meter,
return &meter->priv->values[value].color; return &meter->priv->values[value].color;
} }
void
gimp_meter_set_value_interpolation (GimpMeter *meter,
gint value,
GimpInterpolationType interpolation)
{
g_return_if_fail (GIMP_IS_METER (meter));
g_return_if_fail (value >= 0 && value < meter->priv->n_values);
if (meter->priv->values[value].interpolation != interpolation)
{
meter->priv->values[value].interpolation = interpolation;
gtk_widget_queue_draw (GTK_WIDGET (meter));
}
}
GimpInterpolationType
gimp_meter_get_value_interpolation (GimpMeter *meter,
gint value)
{
g_return_val_if_fail (GIMP_IS_METER (meter), GIMP_INTERPOLATION_NONE);
g_return_val_if_fail (value >= 0 && value < meter->priv->n_values,
GIMP_INTERPOLATION_NONE);
return meter->priv->values[value].interpolation;
}
void
gimp_meter_set_value_show_in_gauge (GimpMeter *meter,
gint value,
gboolean show)
{
g_return_if_fail (GIMP_IS_METER (meter));
g_return_if_fail (value >= 0 && value < meter->priv->n_values);
if (meter->priv->values[value].show_in_gauge != show)
{
meter->priv->values[value].show_in_gauge = show;
gtk_widget_queue_draw (GTK_WIDGET (meter));
}
}
gboolean
gimp_meter_get_value_show_in_gauge (GimpMeter *meter,
gint value)
{
g_return_val_if_fail (GIMP_IS_METER (meter), FALSE);
g_return_val_if_fail (value >= 0 && value < meter->priv->n_values, FALSE);
return meter->priv->values[value].show_in_gauge;
}
void
gimp_meter_set_value_show_in_history (GimpMeter *meter,
gint value,
gboolean show)
{
g_return_if_fail (GIMP_IS_METER (meter));
g_return_if_fail (value >= 0 && value < meter->priv->n_values);
if (meter->priv->values[value].show_in_history != show)
{
meter->priv->values[value].show_in_history = show;
gtk_widget_queue_draw (GTK_WIDGET (meter));
}
}
gboolean
gimp_meter_get_value_show_in_history (GimpMeter *meter,
gint value)
{
g_return_val_if_fail (GIMP_IS_METER (meter), FALSE);
g_return_val_if_fail (value >= 0 && value < meter->priv->n_values, FALSE);
return meter->priv->values[value].show_in_history;
}
void void
gimp_meter_set_history_visible (GimpMeter *meter, gimp_meter_set_history_visible (GimpMeter *meter,
gboolean visible) gboolean visible)
......
...@@ -46,64 +46,82 @@ struct _GimpMeterClass ...@@ -46,64 +46,82 @@ struct _GimpMeterClass
}; };
GType gimp_meter_get_type (void) G_GNUC_CONST; GType gimp_meter_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_meter_new (gint n_values); GtkWidget * gimp_meter_new (gint n_values);
void gimp_meter_set_size (GimpMeter *meter, void gimp_meter_set_size (GimpMeter *meter,
gint size); gint size);
gint gimp_meter_get_size (GimpMeter *meter); gint gimp_meter_get_size (GimpMeter *meter);
void gimp_meter_set_refresh_rate (GimpMeter *meter, void gimp_meter_set_refresh_rate (GimpMeter *meter,
gdouble rate); gdouble rate);
gdouble gimp_meter_get_refresh_rate (GimpMeter *meter); gdouble gimp_meter_get_refresh_rate (GimpMeter *meter);
void gimp_meter_set_range (GimpMeter *meter, void gimp_meter_set_range (GimpMeter *meter,
gdouble min, gdouble min,
gdouble max); gdouble max);
gdouble gimp_meter_get_range_min (GimpMeter *meter); gdouble gimp_meter_get_range_min (GimpMeter *meter);
gdouble gimp_meter_get_range_max (GimpMeter *meter); gdouble gimp_meter_get_range_max (GimpMeter *meter);
void gimp_meter_set_n_values (GimpMeter *meter, void gimp_meter_set_n_values (GimpMeter *meter,
gint n_values); gint n_values);
gint gimp_meter_get_n_values (GimpMeter *meter); gint gimp_meter_get_n_values (GimpMeter *meter);
void gimp_meter_set_value_active (GimpMeter *meter, void gimp_meter_set_value_active (GimpMeter *meter,
gint value, gint value,
gboolean active); gboolean active);
gboolean gimp_meter_get_value_active (GimpMeter *meter, gboolean gimp_meter_get_value_active (GimpMeter *meter,
gint value); gint value);
void gimp_meter_set_value_color (GimpMeter *meter, void gimp_meter_set_value_show_in_gauge (GimpMeter *meter,
gint value, gint value,
const GimpRGB *color); gboolean show);
const GimpRGB * gimp_meter_get_value_color (GimpMeter *meter, gboolean gimp_meter_get_value_show_in_gauge (GimpMeter *meter,
gint value); gint value);
void gimp_meter_set_history_visible (GimpMeter *meter, void gimp_meter_set_value_show_in_history (GimpMeter *meter,
gboolean visible); gint value,
gboolean gimp_meter_get_history_visible (GimpMeter *meter); gboolean show);
gboolean gimp_meter_get_value_show_in_history (GimpMeter *meter,
void gimp_meter_set_history_duration (GimpMeter *meter, gint value);
gdouble duration);
gdouble gimp_meter_get_history_duration (GimpMeter *meter); void gimp_meter_set_value_color (GimpMeter *meter,
gint value,
void gimp_meter_set_history_resolution (GimpMeter *meter, const GimpRGB *color);
gdouble resolution); const GimpRGB * gimp_meter_get_value_color (GimpMeter *meter,
gdouble gimp_meter_get_history_resolution (GimpMeter *meter); gint value);
void gimp_meter_clear_history (GimpMeter *meter); void gimp_meter_set_value_interpolation (GimpMeter *meter,
gint value,
void gimp_meter_add_sample (GimpMeter *meter, GimpInterpolationType interpolation);
const gdouble *sample); GimpInterpolationType gimp_meter_get_value_interpolation (GimpMeter *meter,
gint value);
void gimp_meter_set_led_active (GimpMeter *meter,
gboolean active); void gimp_meter_set_history_visible (GimpMeter *meter,
gboolean gimp_meter_get_led_active (GimpMeter *meter); gboolean visible);
gboolean gimp_meter_get_history_visible (GimpMeter *meter);
void gimp_meter_set_led_color (GimpMeter *meter,
const GimpRGB *color); void gimp_meter_set_history_duration (GimpMeter *meter,
const GimpRGB * gimp_meter_get_led_color (GimpMeter *meter); gdouble duration);
gdouble gimp_meter_get_history_duration (GimpMeter *meter);
void gimp_meter_set_history_resolution (GimpMeter *meter,
gdouble resolution);
gdouble gimp_meter_get_history_resolution (GimpMeter *meter);
void gimp_meter_clear_history (GimpMeter *meter);
void gimp_meter_add_sample (GimpMeter *meter,
const gdouble *sample);
void gimp_meter_set_led_active (GimpMeter *meter,
gboolean active);
gboolean gimp_meter_get_led_active (GimpMeter *meter);
void gimp_meter_set_led_color (GimpMeter *meter,
const GimpRGB *color);
const GimpRGB * gimp_meter_get_led_color (GimpMeter *meter);
#endif /* __GIMP_METER_H__ */ #endif /* __GIMP_METER_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment