Example #1
0
gboolean
update_window_decoration_size (WnckWindow *win)
{
    decor_t           *d;
    GdkPixmap         *pixmap, *buffer_pixmap = NULL;
    Picture           picture;
    Display           *xdisplay;
    XRenderPictFormat *format;

    if (win == NULL)
	return FALSE;

    d = g_object_get_data (G_OBJECT (win), "decor");

    if (!d->decorated)
	return FALSE;

    xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());

    gdk_error_trap_push ();

    /* Get the correct depth for the frame window in reparenting mode, otherwise
     * enforce 32 */
    if (d->frame_window)
	pixmap = create_native_pixmap_and_wrap (d->width, d->height, d->frame->style_window_rgb);
    else
	pixmap = create_native_pixmap_and_wrap (d->width, d->height, d->frame->style_window_rgba);

    gdk_flush ();

    /* Handle failure */
    if (!pixmap || gdk_error_trap_pop ())
    {
	memset (pixmap, 0, sizeof (*pixmap));
	return FALSE;
    }

    gdk_error_trap_push ();

    if (d->frame_window)
	buffer_pixmap = create_pixmap (d->width, d->height, d->frame->style_window_rgb);
    else
	buffer_pixmap = create_pixmap (d->width, d->height, d->frame->style_window_rgba);

    gdk_flush ();

    /* Handle failure */
    if (!buffer_pixmap || gdk_error_trap_pop ())
    {
	memset (buffer_pixmap, 0, sizeof (*buffer_pixmap));
	g_object_unref (G_OBJECT (pixmap));
	return FALSE;
    }

    /* Create XRender context */
    format = get_format_for_drawable (d, GDK_DRAWABLE (buffer_pixmap));
    picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (buffer_pixmap),
				    format, 0, NULL);

    /* Destroy the old pixmaps and pictures */
    if (d->pixmap)
	g_object_unref (d->pixmap);

    if (d->x11Pixmap)
	decor_post_delete_pixmap (xdisplay,
				  wnck_window_get_xid (d->win),
				  d->x11Pixmap);

    if (d->buffer_pixmap)
	g_object_unref (G_OBJECT (d->buffer_pixmap));

    if (d->picture)
	XRenderFreePicture (xdisplay, d->picture);

    if (d->cr)
	cairo_destroy (d->cr);

    /* Assign new pixmaps and pictures */
    d->pixmap	     = pixmap;
    d->x11Pixmap     = GDK_PIXMAP_XID (d->pixmap);
    d->buffer_pixmap = buffer_pixmap;
    d->cr	     = gdk_cairo_create (pixmap);

    d->picture = picture;

    d->prop_xid = wnck_window_get_xid (win);

    update_window_decoration_name (win);

    /* Redraw decoration on idle */
    queue_decor_draw (d);

    return TRUE;
}
Example #2
0
/*!
 \brief draws the static elements of the gauge (only on resize), This includes
 the border, units and name strings,  tick marks and warning regions
 This is the cairo version.
 \param widget (MtxPieGauge *) pointer to the gauge object
 */
void generate_pie_gauge_background(MtxPieGauge *gauge)
{
	cairo_t *cr = NULL;
	gint w = 0;
	gint h = 0;
	MtxPieGaugePrivate *priv = MTX_PIE_GAUGE_GET_PRIVATE(gauge);

	w = GTK_WIDGET(gauge)->allocation.width;
	h = GTK_WIDGET(gauge)->allocation.height;

	if (!priv->bg_pixmap)
		return;
	/* get a cairo_t */
	cr = gdk_cairo_create (priv->bg_pixmap);
	cairo_set_font_options(cr,priv->font_options);
	cairo_set_source_rgb (cr, 
			priv->colors[COL_BG].red/65535.0,
			priv->colors[COL_BG].green/65535.0,
			priv->colors[COL_BG].blue/65535.0);
	/* Background Rectangle */
	cairo_rectangle (cr,
			0,0,w,h);
	cairo_fill(cr);
	/* first one big yellow, with the green and red on top
	 * This prevents seeing BG pixels due to antialiasing errors */
	cairo_move_to(cr,priv->pie_xc,priv->pie_yc);
	cairo_set_source_rgb (cr, 
			priv->colors[COL_MID].red/65535.0,
			priv->colors[COL_MID].green/65535.0,
			priv->colors[COL_MID].blue/65535.0);
	cairo_arc(cr, priv->pie_xc, priv->pie_yc, priv->pie_radius, 
			priv->start_angle*(M_PI/180.0), 
			(priv->start_angle+priv->sweep_angle)*(M_PI/180.0));
	cairo_fill(cr);
	/* Low green Arc (*/
	cairo_move_to(cr,priv->pie_xc,priv->pie_yc);
	cairo_set_source_rgb (cr, 
			priv->colors[COL_LOW].red/65535.0,
			priv->colors[COL_LOW].green/65535.0,
			priv->colors[COL_LOW].blue/65535.0);
	cairo_arc(cr, priv->pie_xc, priv->pie_yc, priv->pie_radius, 
			priv->start_angle*(M_PI/180.0), 
			(priv->start_angle+45)*(M_PI/180.0));
	cairo_fill(cr);
	/* High red Arc */
	cairo_move_to(cr,priv->pie_xc,priv->pie_yc);
	cairo_set_source_rgb (cr, 
			priv->colors[COL_HIGH].red/65535.0,
			priv->colors[COL_HIGH].green/65535.0,
			priv->colors[COL_HIGH].blue/65535.0);
	cairo_arc(cr, priv->pie_xc, priv->pie_yc, priv->pie_radius, 
			(priv->start_angle+135)*(M_PI/180.0), 
			(priv->start_angle+180)*(M_PI/180.0));
	cairo_fill(cr);
	/* Pie Gauge Arcs */
	cairo_set_line_width (cr, 1.0);
	cairo_set_source_rgb (cr, 
			priv->colors[COL_NEEDLE].red/65535.0,
			priv->colors[COL_NEEDLE].green/65535.0,
			priv->colors[COL_NEEDLE].blue/65535.0);
	cairo_arc(cr, priv->pie_xc, priv->pie_yc, priv->pie_radius, 
			priv->start_angle*(M_PI/180.0), 
			(priv->start_angle+priv->sweep_angle)*(M_PI/180.0));
	cairo_stroke(cr);
	cairo_destroy (cr);
}
Example #3
0
static gboolean
gimp_tag_popup_list_expose (GtkWidget      *widget,
                            GdkEventExpose *event,
                            GimpTagPopup   *popup)
{
  GdkWindow      *window = gtk_widget_get_window (widget);
  GtkStyle       *style  = gtk_widget_get_style (widget);
  cairo_t        *cr;
  PangoAttribute *attribute;
  PangoAttrList  *attributes;
  gint            i;

  cr = gdk_cairo_create (event->window);

  gdk_cairo_region (cr, event->region);
  cairo_clip (cr);

  cairo_set_line_width (cr, 1.0);
  cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);

  for (i = 0; i < popup->tag_count; i++)
    {
      PopupTagData *tag_data = &popup->tag_data[i];

      pango_layout_set_text (popup->layout,
                             gimp_tag_get_name (tag_data->tag), -1);

      switch (tag_data->state)
        {
        case GTK_STATE_SELECTED:
          attributes = pango_attr_list_copy (popup->combo_entry->selected_item_attr);
          break;

        case GTK_STATE_INSENSITIVE:
          attributes = pango_attr_list_copy (popup->combo_entry->insensitive_item_attr);
          break;

        default:
          attributes = pango_attr_list_copy (popup->combo_entry->normal_item_attr);
          break;
        }

      if (tag_data == popup->prelight &&
          tag_data->state != GTK_STATE_INSENSITIVE)
        {
          attribute = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
          pango_attr_list_insert (attributes, attribute);
        }

      pango_layout_set_attributes (popup->layout, attributes);
      pango_attr_list_unref (attributes);

      if (tag_data->state == GTK_STATE_SELECTED)
        {
          gdk_cairo_set_source_color (cr,
                                      &popup->combo_entry->selected_item_color);

          cairo_rectangle (cr,
                           tag_data->bounds.x - 1,
                           tag_data->bounds.y - popup->scroll_y,
                           tag_data->bounds.width + 2,
                           tag_data->bounds.height);
          cairo_fill (cr);

          cairo_translate (cr, 0.5, 0.5);

          cairo_move_to (cr,
                         tag_data->bounds.x,
                         tag_data->bounds.y - popup->scroll_y - 1);
          cairo_line_to (cr,
                         tag_data->bounds.x + tag_data->bounds.width - 1,
                         tag_data->bounds.y - popup->scroll_y - 1);

          cairo_move_to (cr,
                         tag_data->bounds.x,
                         tag_data->bounds.y - popup->scroll_y + tag_data->bounds.height);
          cairo_line_to (cr,
                         tag_data->bounds.x + tag_data->bounds.width - 1,
                         tag_data->bounds.y - popup->scroll_y + tag_data->bounds.height);

          cairo_stroke (cr);

          cairo_translate (cr, -0.5, -0.5);
        }

      cairo_move_to (cr,
                     (tag_data->bounds.x +
                      GIMP_TAG_POPUP_PADDING),
                     (tag_data->bounds.y -
                      popup->scroll_y +
                      GIMP_TAG_POPUP_PADDING));

      pango_cairo_show_layout (cr, popup->layout);

      if (tag_data == popup->prelight              &&
          tag_data->state != GTK_STATE_INSENSITIVE &&
          ! popup->single_select_disabled)
        {
          gtk_paint_focus (style, window,
                           tag_data->state,
                           &event->area, widget, NULL,
                           tag_data->bounds.x,
                           tag_data->bounds.y - popup->scroll_y,
                           tag_data->bounds.width,
                           tag_data->bounds.height);
        }
    }

  cairo_destroy (cr);

  return FALSE;
}
/*!
 \brief updates the chart position,  This is the CAIRO implementation
 \param chart is the pointer to the chart object
 */
void update_stripchart_position (MtxStripChart *chart)
{
	GtkWidget * widget = NULL;
	cairo_font_weight_t weight;
	cairo_font_slant_t slant;
	gfloat tmpf = 0.0;
	gfloat needle_pos = 0.0;
	gchar * tmpbuf = NULL;
	gchar * message = NULL;
	gint shift = 0;
	gfloat start_x = 0.0;
	gfloat start_y = 0.0;
	gfloat buffer = 0.0;
	gboolean draw_quarters = TRUE;
	gint i = 0;
	gint j = 0;
	gfloat x = 0.0;
	gfloat y = 0.0;
	gfloat text_offset[NUM_TXTS] = {0.0,0.0,0.0,0.0,0.0};
	GdkPoint tip;
	cairo_t *cr = NULL;
	cairo_t *cr2 = NULL;
	cairo_text_extents_t extents;
	MtxStripChartTrace *trace = NULL;
	MtxStripChartPrivate *priv = MTX_STRIPCHART_GET_PRIVATE(chart);

	widget = GTK_WIDGET(chart);
	shift = priv->newsamples;

	/* Draw new data to trace pixmap */

	/* Scroll trace pixmap */

	cr = gdk_cairo_create(priv->trace_pixmap);
	gdk_cairo_set_source_pixmap(cr,priv->trace_pixmap,-shift,0);
	cairo_rectangle(cr,0,0,priv->w,priv->h);
	cairo_fill(cr);
	cairo_set_source_rgb(cr,0,0,0);
	cairo_rectangle(cr,priv->w-shift,0,shift,priv->h);
	cairo_fill(cr);
	/* Render new data */

	for (i=0;i<priv->num_traces;i++)
	{
		trace = g_array_index(priv->traces,MtxStripChartTrace *,i);

		cairo_set_line_width(cr,trace->lwidth);
		cairo_set_source_rgb (cr, 
				trace->color.red/65535.0,
				trace->color.green/65535.0,
				trace->color.blue/65535.0);
		for(j=shift;j>0;j--)
		{
			if (trace->history->len > 1)
			{
				start_x = priv->w - j;
				start_y = priv->h - (((g_array_index(trace->history,gfloat,trace->history->len-j-1)-trace->min) / (trace->max - trace->min))*priv->h);
				cairo_move_to(cr,start_x,start_y);
				x = priv->w-j+1;
				y = priv->h - (((g_array_index(trace->history,gfloat,trace->history->len-j)-trace->min) / (trace->max - trace->min))*priv->h);
				cairo_line_to(cr,x,y);
				cairo_stroke(cr);
			}
		}
	}
	cairo_destroy(cr);

	/* Copy background trace pixmap to grat for grat rendering */

	cr = gdk_cairo_create(priv->grat_pixmap);
	gdk_cairo_set_source_pixmap(cr,priv->trace_pixmap,0,0);
	cairo_rectangle(cr,0,0,priv->w,priv->h);
	cairo_fill(cr);

	/* Render the graticule lines */

	cairo_set_source_rgba (cr, 
			priv->colors[COL_GRAT].red/65535.0,
			priv->colors[COL_GRAT].green/65535.0,
			priv->colors[COL_GRAT].blue/65535.0,
			0.5);
	cairo_move_to(cr,0,priv->h/4);
	cairo_line_to(cr,priv->w,priv->h/4);
	cairo_stroke(cr);
	cairo_move_to(cr,0,priv->h/2);
	cairo_line_to(cr,priv->w,priv->h/2);
	cairo_stroke(cr);
	cairo_move_to(cr,0,priv->h*3/4);
	cairo_line_to(cr,priv->w,priv->h*3/4);
	cairo_stroke(cr);

	cairo_set_font_options(cr,priv->font_options);
	tmpbuf = g_utf8_strup(priv->font,-1);
	if (g_strrstr(tmpbuf,"BOLD"))
		weight = CAIRO_FONT_WEIGHT_BOLD;
	else
		weight = CAIRO_FONT_WEIGHT_NORMAL;
	if (g_strrstr(tmpbuf,"OBLIQUE"))
		slant = CAIRO_FONT_SLANT_OBLIQUE;
	else if (g_strrstr(tmpbuf,"ITALIC"))
		slant = CAIRO_FONT_SLANT_ITALIC;
	else
		slant = CAIRO_FONT_SLANT_NORMAL;
	g_free(tmpbuf);
	cairo_select_font_face (cr, priv->font,  slant, weight);

	cairo_set_font_size (cr, 12);

	cairo_set_antialias(cr,CAIRO_ANTIALIAS_DEFAULT);
	buffer = 0;
	text_offset[BOTTOM] = 0.0;
	message = g_strdup_printf("123");
	cairo_text_extents(cr,message,&extents);
	if ((extents.height * 4) > (priv->h/4))
		draw_quarters = FALSE;
	else
		draw_quarters = TRUE;
	g_free(message);
	/* render the new data */

	cr2 = gdk_cairo_create(priv->grat_pixmap);
	cairo_set_source_rgba(cr2,0.13,0.13,0.13,0.75);

	for (i=0;i<priv->num_traces;i++)
	{
		trace = g_array_index(priv->traces,MtxStripChartTrace *,i);
		cairo_set_source_rgb (cr, 
				trace->color.red/65535.0,
				trace->color.green/65535.0,
				trace->color.blue/65535.0
				);
		message = g_strdup_printf("%1$.*2$f", trace->min,trace->precision);
		cairo_text_extents (cr, message, &extents);
		cairo_rectangle(cr2,2.0+text_offset[BOTTOM],priv->h-2.0,extents.width,-extents.height);
		cairo_fill(cr2);
		cairo_move_to(cr,2.0+text_offset[BOTTOM],priv->h-2.0);

		cairo_show_text (cr, message);
		g_free(message);
		text_offset[BOTTOM] += extents.width + 7;

		if (draw_quarters)
		{
			message = g_strdup_printf("%1$.*2$f", trace->min+((trace->max-trace->min)/4),trace->precision);
			cairo_text_extents (cr, message, &extents);
			cairo_rectangle(cr2,2.0+text_offset[QUARTER],priv->h*3/4-2.0,extents.width,-extents.height);
			cairo_fill(cr2);
			cairo_move_to(cr,2.0+text_offset[QUARTER],(priv->h*3/4)-2.0);
			cairo_show_text (cr, message);
			g_free(message);
			text_offset[QUARTER] += extents.width + 7;
		}

		message = g_strdup_printf("%1$.*2$f", trace->min+((trace->max-trace->min)/2),trace->precision);
		cairo_text_extents (cr, message, &extents);
		cairo_rectangle(cr2,2.0+text_offset[HALF],(priv->h/2.0)-2.0,extents.width,-extents.height);
		cairo_fill(cr2);
		cairo_move_to(cr,2.0+text_offset[HALF],(priv->h/2.0)-2.0);
		cairo_show_text (cr, message);
		g_free(message);
		text_offset[HALF] += extents.width + 7;

		if (draw_quarters)
		{
			message = g_strdup_printf("%1$.*2$f", trace->min+((trace->max-trace->min)*3/4),trace->precision);
			cairo_text_extents (cr, message, &extents);
			cairo_rectangle(cr2,2.0+text_offset[THREEQUARTER],priv->h/4-2.0,extents.width,-extents.height);
			cairo_fill(cr2);
			cairo_move_to(cr,2.0+text_offset[THREEQUARTER],(priv->h/4)-2.0);
			cairo_show_text (cr, message);
			g_free(message);
			text_offset[THREEQUARTER] += extents.width + 7;
		}

		message = g_strdup_printf("%1$.*2$f", trace->max,trace->precision);
		cairo_text_extents (cr, message, &extents);
		cairo_rectangle(cr2,2.0+text_offset[TOP],2.0,extents.width,extents.height);
		cairo_fill(cr2);
		cairo_move_to(cr,2.0+text_offset[TOP],extents.height+2.0);
		cairo_show_text (cr, message);
		g_free(message);
		text_offset[TOP] += extents.width + 7;

		/* Trace names */

		message = g_strdup_printf("%s", trace->name);
		cairo_text_extents (cr, message, &extents);
		cairo_rectangle(cr2,priv->w-extents.width - 20, 2.0+buffer +extents.height,extents.width,-extents.height);
		cairo_fill(cr2);
		cairo_move_to(cr,priv->w-extents.width - 20, 2.0 + buffer + extents.height);
		cairo_show_text (cr, message);
		g_free(message);
		buffer += (extents.height + 3);

	}
	cairo_destroy(cr);
	cairo_destroy(cr2);
}
Example #5
0
/*!
 \brief updates the gauge position,  This is the CAIRO implementation that
 looks a bit nicer, though is a little bit slower
 \param widget (MtxPieGauge *) pointer to the gauge object
 */
void update_pie_gauge_position (MtxPieGauge *gauge)
{
	GtkWidget * widget = NULL;
	cairo_font_weight_t weight;
	cairo_font_slant_t slant;
	gfloat tmpf = 0.0;
	gfloat needle_pos = 0.0;
	gchar * tmpbuf = NULL;
	gchar * message = NULL;
	GdkPoint tip;
	cairo_t *cr = NULL;
	cairo_text_extents_t extents;
	MtxPieGaugePrivate *priv = MTX_PIE_GAUGE_GET_PRIVATE(gauge);

	widget = GTK_WIDGET(gauge);

	/* Copy background pixmap to intermediary for final rendering */
	gdk_draw_drawable(priv->pixmap,
			widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
			priv->bg_pixmap,
			0,0,
			0,0,
			widget->allocation.width,widget->allocation.height);

	cr = gdk_cairo_create (priv->pixmap);
	cairo_set_font_options(cr,priv->font_options);

	cairo_set_antialias(cr,CAIRO_ANTIALIAS_DEFAULT);
	/* Update the VALUE text */
	cairo_set_source_rgb (cr, 
			priv->colors[COL_VALUE_FONT].red/65535.0,
			priv->colors[COL_VALUE_FONT].green/65535.0,
			priv->colors[COL_VALUE_FONT].blue/65535.0);
	tmpbuf = g_utf8_strup(priv->value_font,-1);
	if (g_strrstr(tmpbuf,"BOLD"))
		weight = CAIRO_FONT_WEIGHT_BOLD;
	else
		weight = CAIRO_FONT_WEIGHT_NORMAL;
	if (g_strrstr(tmpbuf,"OBLIQUE"))
		slant = CAIRO_FONT_SLANT_OBLIQUE;
	else if (g_strrstr(tmpbuf,"ITALIC"))
		slant = CAIRO_FONT_SLANT_ITALIC;
	else
		slant = CAIRO_FONT_SLANT_NORMAL;
	g_free(tmpbuf);
	cairo_select_font_face (cr, priv->value_font,  slant, weight);

	cairo_set_font_size (cr, 11);

	if (priv->valname)
		message = g_strdup_printf("%s:%.*f", priv->valname,priv->precision,priv->value);
	else
		message = g_strdup_printf("%.*f", priv->precision,priv->value);

	cairo_text_extents (cr, message, &extents);

	cairo_move_to (cr, 
			((priv->w-(priv->pie_radius*2.0 + 5)-extents.width)/2.0) +priv->pie_radius*2.0,
			priv->pie_yc - (extents.height/4.0));
	cairo_show_text (cr, message);
	g_free(message);

	cairo_stroke (cr);

	/* gauge hands */
	tmpf = (priv->value-priv->min)/(priv->max-priv->min);
	needle_pos = (priv->start_angle+(tmpf*priv->sweep_angle))*(M_PI/180);


	cairo_set_source_rgb (cr, priv->colors[COL_NEEDLE].red/65535.0,
			priv->colors[COL_NEEDLE].green/65535.0,
			priv->colors[COL_NEEDLE].blue/65535.0);
	cairo_set_line_width (cr, 1.5);


	tip.x = priv->pie_xc + (priv->pie_radius * cos (needle_pos));
	tip.y = priv->pie_yc + (priv->pie_radius * sin (needle_pos));

	cairo_move_to (cr, priv->pie_xc,priv->pie_yc);
	cairo_line_to (cr, tip.x,tip.y);
	cairo_stroke(cr);
	cairo_destroy(cr);
}
void
html_engine_draw_cursor_in_area (HTMLEngine *engine,
                                 gint x,
                                 gint y,
                                 gint width,
                                 gint height)
{
	HTMLObject *obj;
	guint offset;
	gint x1, y1, x2, y2, sc_x, sc_y;
	GdkRectangle pos;
	GtkAdjustment *hadj, *vadj;

	if ((engine->editable || engine->caret_mode) && (engine->cursor_hide_count <= 0 && !engine->thaw_idle_id)) {
		html_engine_draw_table_cursor (engine);
		html_engine_draw_cell_cursor (engine);
		html_engine_draw_image_cursor (engine);
	}

	if (!cursor_enabled || engine->cursor_hide_count > 0 || !(engine->editable || engine->caret_mode) || engine->thaw_idle_id)
		return;

	obj = engine->cursor->object;
	if (obj == NULL || engine->window == NULL)
		return;

	offset = engine->cursor->offset;

	if (width < 0 || height < 0) {
		width = html_engine_get_doc_width (engine);
		height = html_engine_get_doc_height (engine);
		x = 0;
		y = 0;
	}

	html_object_get_cursor (obj, engine->painter, offset, &x1, &y1, &x2, &y2);
	while (obj) {
		if (html_object_is_frame (obj)) {
			x1 -= HTML_EMBEDDED (obj)->abs_x;
			x2 -= HTML_EMBEDDED (obj)->abs_x;
			y1 -= HTML_EMBEDDED (obj)->abs_y;
			y2 -= HTML_EMBEDDED (obj)->abs_y;
			break;
		}
		obj = obj->parent;
	}

	/* get scroll offset */
	hadj = gtk_layout_get_hadjustment (GTK_LAYOUT (engine->widget));
	vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (engine->widget));
	sc_x = (gint) gtk_adjustment_get_value (hadj);
	sc_y = (gint) gtk_adjustment_get_value (vadj);

	pos.x = x1 - sc_x;
	pos.y = y1 - sc_y;
	pos.width = x2 - x1;
	pos.height = y2 - y1;

	gtk_im_context_set_cursor_location (GTK_HTML (engine->widget)->priv->im_context, &pos);

	if (clip_cursor (engine, x, y, width, height, &x1, &y1, &x2, &y2)) {
		cairo_t *cr;
		gboolean using_painter_cr;

		using_painter_cr = engine->painter &&
		    HTML_IS_GDK_PAINTER (engine->painter) &&
		    HTML_GDK_PAINTER (engine->painter)->cr != NULL;

		if (using_painter_cr) {
			HTMLGdkPainter *gdk_painter = HTML_GDK_PAINTER (engine->painter);

			cr = gdk_painter->cr;
			cairo_save (cr);

			x1 -= gdk_painter->x1;
			y1 -= gdk_painter->y1;
			x2 -= gdk_painter->x1;
			y2 -= gdk_painter->y1;
		} else {
			cr = gdk_cairo_create (engine->window);
		}

		cairo_set_source_rgb (cr, 1, 1, 1);
		cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
		cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
		cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
		cairo_line_to (cr, x2 + 0.5, y2 - 0.5);
		cairo_set_line_width (cr, 1);
		cairo_stroke (cr);

		if (using_painter_cr)
			cairo_restore (cr);
		else
			cairo_destroy (cr);
	}
}
static gboolean
load_graph_expose (GtkWidget *widget,
		   GdkEventExpose *event,
		   gpointer data_ptr)
{
	LoadGraph * const g = static_cast<LoadGraph*>(data_ptr);

	guint i, j;
	gdouble sample_width, x_offset;

	if (g->background == NULL) {
		draw_background(g);
	}
	gdk_draw_drawable (g->disp->window,
			   g->gc,
			   g->background,
			   0, 0, 0, 0, 
			   g->disp->allocation.width, 
			   g->disp->allocation.height);

	/* Number of pixels wide for one graph point */
	sample_width = (float)(g->draw_width - g->rmargin - g->indent) / (float)LoadGraph::NUM_POINTS;
	/* General offset */
	x_offset = g->draw_width - g->rmargin + (sample_width*2);

	/* Subframe offset */
	x_offset += g->rmargin - ((sample_width / g->frames_per_unit) * g->render_counter);

	/* draw the graph */
	cairo_t* cr;

	cr = gdk_cairo_create (g->disp->window);

	cairo_set_line_width (cr, 1);
	cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
	cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
	cairo_rectangle (cr, g->rmargin + g->indent + FRAME_WIDTH + 1, FRAME_WIDTH - 1,
			 g->draw_width - g->rmargin - g->indent - 1, g->real_draw_height + FRAME_WIDTH - 1);
	cairo_clip(cr);

	for (j = 0; j < g->n; ++j) {
		cairo_move_to (cr, x_offset, (1.0f - g->data[0][j]) * g->real_draw_height);
		gdk_cairo_set_source_color (cr, &(g->colors [j]));

		for (i = 1; i < LoadGraph::NUM_POINTS; ++i) {
			if (g->data[i][j] == -1.0f)
				continue;
			cairo_curve_to (cr, 
				       x_offset - ((i - 0.5f) * g->graph_delx),
				       (1.0f - g->data[i-1][j]) * g->real_draw_height + 3.5f,
				       x_offset - ((i - 0.5f) * g->graph_delx),
				       (1.0f - g->data[i][j]) * g->real_draw_height + 3.5f,
				       x_offset - (i * g->graph_delx),
				       (1.0f - g->data[i][j]) * g->real_draw_height + 3.5f);
		}
		cairo_stroke (cr);

	}

	cairo_destroy (cr);

	return TRUE;
}
Example #8
0
static void
draw_window (GtkWidget                   *widget,
             #if GTK_CHECK_VERSION(3, 0, 0)
             cairo_t                     *cr,
             #else
             GdkDrawable                 *drawable,
             #endif
             const WnckWindowDisplayInfo *win,
             const GdkRectangle          *winrect,
             GtkStateType                state)
{
  #if !GTK_CHECK_VERSION(3, 0, 0)
  cairo_t *cr;
  #endif

  GdkPixbuf *icon;
  int icon_x, icon_y, icon_w, icon_h;
  gboolean is_active;
  GdkColor *color;
  GtkStyle *style;

  is_active = win->is_active;

  #if GTK_CHECK_VERSION(3, 0, 0)
  cairo_save(cr);
  #else
  cr = gdk_cairo_create (drawable);
  #endif

  cairo_rectangle (cr, winrect->x, winrect->y, winrect->width, winrect->height);
  cairo_clip (cr);

  style = gtk_widget_get_style (widget);
  if (is_active)
    color = &style->light[state];
  else
    color = &style->bg[state];
  cairo_set_source_rgb (cr,
                        color->red / 65535.,
                        color->green / 65535.,
                        color->blue / 65535.);

  cairo_rectangle (cr,
                   winrect->x + 1, winrect->y + 1,
                   MAX (0, winrect->width - 2), MAX (0, winrect->height - 2));
  cairo_fill (cr);


  icon = win->icon;

  icon_w = icon_h = 0;

  if (icon)
    {
      icon_w = gdk_pixbuf_get_width (icon);
      icon_h = gdk_pixbuf_get_height (icon);

      /* If the icon is too big, fall back to mini icon.
       * We don't arbitrarily scale the icon, because it's
       * just too slow on my Athlon 850.
       */
      if (icon_w > (winrect->width - 2) ||
          icon_h > (winrect->height - 2))
        {
          icon = win->mini_icon;
          if (icon)
            {
              icon_w = gdk_pixbuf_get_width (icon);
              icon_h = gdk_pixbuf_get_height (icon);

              /* Give up. */
              if (icon_w > (winrect->width - 2) ||
                  icon_h > (winrect->height - 2))
                icon = NULL;
            }
        }
    }

  if (icon)
    {
      icon_x = winrect->x + (winrect->width - icon_w) / 2;
      icon_y = winrect->y + (winrect->height - icon_h) / 2;

      cairo_save (cr);
      gdk_cairo_set_source_pixbuf (cr, icon, icon_x, icon_y);
      cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h);
      cairo_clip (cr);
      cairo_paint (cr);
      cairo_restore (cr);
    }

  if (is_active)
    color = &style->fg[state];
  else
    color = &style->fg[state];

  cairo_set_source_rgb (cr,
                        color->red / 65535.,
                        color->green / 65535.,
                        color->blue / 65535.);
  cairo_set_line_width (cr, 1.0);
  cairo_rectangle (cr,
                   winrect->x + 0.5, winrect->y + 0.5,
                   MAX (0, winrect->width - 1), MAX (0, winrect->height - 1));
  cairo_stroke (cr);

  #if GTK_CHECK_VERSION(3, 0, 0)
  cairo_restore(cr);
  #else
  cairo_destroy (cr);
  #endif
}
Example #9
0
static void gtk_attractor_view_paint(GtkWidget *widget)
{
    GtkAttractor_View *attractor_view = GTK_ATTRACTOR_VIEW(widget);






    int width, height;
    PangoLayout *layout;
    CairoxTextParameters text_p;
    char buffer[64];
    cairo_t *cr;
    int p, c;

    width = widget->allocation.width;
    height = widget->allocation.height;

    cr = gdk_cairo_create(widget->window);

    /* Transparent background */
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0);
    cairo_paint(cr);
    //int current_attractor_i = ((iterations_so_far) && (iterations_so_far < C_MAX)) ? (iterations_so_far) : (0);
    layout = pango_cairo_create_layout(cr);
// 	if (!training) {
//         g_snprintf(buffer, 64, "Step: %d", step_number);
//         cairox_text_parameters_set(&text_p, 20, height-20, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0);
//         cairox_paint_pango_text(cr, &text_p, layout, buffer);

    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_set_line_width(cr, 1);

// 	  cairo_rectangle(cr, 20, 20, 120, 80);
    cairo_rectangle(cr, X_MARGIN, Y_MARGIN, width - (2.0 * X_MARGIN), height - (2.0 * Y_MARGIN));
    cairo_stroke_preserve(cr);
    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_fill(cr);

    double n_rows = (double) (P + 6);
    double row_height = (height - (Y_MARGIN*2)) / n_rows;

    double n_columns = ATTRACTOR_LESION_LEVEL + 1.0;
    double column_width = (width - (X_MARGIN*2)) / n_columns;

    int smaller_font_size = 14, bigger_font_size = 16;
    if (n_rows > 36) {
        smaller_font_size = 12;
        bigger_font_size = 15;
    }

    pangox_layout_set_font_size(layout, bigger_font_size);
    g_snprintf(buffer, 64, "Pattern Name");
    cairox_text_parameters_set(&text_p, X_MARGIN*2, row_height*2, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0);
    cairox_paint_pango_text(cr, &text_p, layout, buffer);

    for (c = 0; c < ATTRACTOR_LESION_LEVEL; c++) {
        g_snprintf(buffer, 64, "%1.1f%% Lesioned", c * 100.0 / (double) ATTRACTOR_LESION_LEVEL);
        cairox_text_parameters_set(&text_p, column_width*(c+1), row_height*2, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0);
        cairox_paint_pango_text(cr, &text_p, layout, buffer);
    }


    pangox_layout_set_font_size(layout, smaller_font_size);

    for (p = 0; p < P; p++) {
        g_snprintf(buffer, 64, "%s", get_name_string(p));
        cairox_text_parameters_set(&text_p, X_MARGIN*2, (p+4)* row_height, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0);
        cairox_paint_pango_text(cr, &text_p, layout, buffer);
    }

    if (attractor_view->response[0][0][0] != -1) {

        for (c = 0; c < ATTRACTOR_LESION_LEVEL; c++) {

            for (p = 0; p < P; p++) {
                g_snprintf(buffer, 64, "%s", get_name_string(attractor_view->response[c][attractor_view->type][p]));
                cairox_text_parameters_set(&text_p, column_width*(c+1), (p+4)* row_height, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0);
                cairox_paint_pango_text(cr, &text_p, layout, buffer);
            }
        }
    }





    g_object_unref(layout);

    cairo_destroy(cr);

}
Example #10
0
File: tray.c Project: b4283/hime
static void draw_icon()
{
  gboolean tsin_pho_mode();
//  dbg("draw_icon\n");

  if (!da)
    return;

  GdkPixbuf *pix =  ((! current_CS) ||
                     (current_CS->im_state != HIME_STATE_CHINESE)) ?
                    pixbuf : pixbuf_ch;

#if GTK_CHECK_VERSION(2,17,7)
  GtkAllocation dwdh;
  gtk_widget_get_allocation(da, &dwdh);
  int dw = dwdh.width, dh = dwdh.height;
#else
  int dw = da->allocation.width, dh = da->allocation.height;
#endif
  int w, h;

  GdkColor color_fg;


//  dbg("wh %d,%d\n", dw,dh);

  gdk_color_parse("black", &color_fg);
#if !GTK_CHECK_VERSION(2,90,6)
  gdk_gc_set_rgb_fg_color(gc, &color_fg);
#else
  gc = gdk_cairo_create (tray_da_win);
  gdk_cairo_set_source_color (gc, &color_fg);
#endif

  if (pix) {
    int ofs = (dh - gdk_pixbuf_get_height (pix))/2;
#if !GTK_CHECK_VERSION(2,90,6)
    gdk_draw_pixbuf(tray_da_win, NULL, pix, 0, 0, 0, ofs, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0);
#else
    gdk_cairo_set_source_pixbuf (gc, pix, 0, ofs);
    cairo_paint (gc);
    cairo_destroy (gc);
#endif
  } else {
    get_text_w_h(inmd[current_CS->in_method].cname, &w, &h);
#if !GTK_CHECK_VERSION(2,90,6)
    gdk_draw_layout(tray_da_win, gc, 0, 0, pango);
#else
    cairo_move_to (gc, 0, 0);
    pango_cairo_show_layout (gc, pango);
    cairo_destroy (gc);
#endif
  }

  if (current_CS) {
    if (current_CS->b_half_full_char || (
#if USE_TSIN
        current_method_type()==method_type_TSIN && tss.tsin_half_full &&
#endif
        current_CS->im_state == HIME_STATE_CHINESE)) {
      static char full[] = N_("全");
      get_text_w_h(full,  &w, &h);
#if !GTK_CHECK_VERSION(2,90,6)
      gdk_draw_layout(tray_da_win, gc, dw - w, dh - h, pango);
#else
      cairo_move_to (gc, dw - w, dh - h);
      pango_cairo_show_layout (gc, pango);
      cairo_destroy (gc);
#endif
    }

    if (current_CS->im_state == HIME_STATE_ENG_FULL) {
      static char efull[] = N_("A全");
      get_text_w_h(efull,  &w, &h);
#if !GTK_CHECK_VERSION(2,90,6)
      gdk_draw_layout(tray_da_win, gc, 0, 0, pango);
#else
      cairo_move_to (gc, 0, 0);
      pango_cairo_show_layout (gc, pango);
      cairo_destroy (gc);
#endif
    }
#if USE_TSIN
    if (((current_method_type()==method_type_TSIN) || (current_method_type()==method_type_MODULE)) &&
        (current_CS->im_state == HIME_STATE_CHINESE) &&
	 (! tsin_pho_mode())) {
      static char efull[] = "ABC";
      gdk_color_parse("blue", &color_fg);
#if !GTK_CHECK_VERSION(2,90,6)
      gdk_gc_set_rgb_fg_color(gc, &color_fg);
#else
      gc = gdk_cairo_create (tray_da_win);
      gdk_cairo_set_source_color (gc, &color_fg);
#endif

      get_text_w_h(efull,  &w, &h);
#if !GTK_CHECK_VERSION(2,90,6)
      gdk_draw_layout(tray_da_win, gc, 0, 0, pango);
#else
      cairo_move_to (gc, 0, 0);
      pango_cairo_show_layout (gc, pango);
      cairo_destroy (gc);
#endif
    }
#endif
  }

  gdk_color_parse("red", &color_fg);
#if !GTK_CHECK_VERSION(2,90,6)
  gdk_gc_set_rgb_fg_color(gc, &color_fg);
#else
  gc = gdk_cairo_create (tray_da_win);
  gdk_cairo_set_source_color (gc, &color_fg);
#endif

  if (gb_output) {
    static char sim[] = "简";
    get_text_w_h(sim,  &w, &h);
#if !GTK_CHECK_VERSION(2,90,6)
    gdk_draw_layout(tray_da_win, gc, 0, dh - h, pango);
#else
    cairo_move_to (gc, 0, dh - h);
    pango_cairo_show_layout (gc, pango);
    cairo_destroy (gc);
#endif
  }

}
Example #11
0
void
wnck_draw_workspace (GtkWidget                   *widget,
                     #if GTK_CHECK_VERSION(3, 0, 0)
                     cairo_t                     *cr,
                     #else
                     GdkDrawable                 *drawable,
                     #endif
                     int                          x,
                     int                          y,
                     int                          width,
                     int                          height,
                     int                          screen_width,
                     int                          screen_height,
                     GdkPixbuf                   *workspace_background,
                     gboolean                     is_active,
                     const WnckWindowDisplayInfo *windows,
                     int                          n_windows)
{
  int i;
  GdkRectangle workspace_rect;
  GtkStateType state;
  #if !GTK_CHECK_VERSION(3, 0, 0)
  cairo_t *cr;
  #endif

  workspace_rect.x = x;
  workspace_rect.y = y;
  workspace_rect.width = width;
  workspace_rect.height = height;

  if (is_active)
    state = GTK_STATE_SELECTED;
  else if (workspace_background)
    state = GTK_STATE_PRELIGHT;
  else
    state = GTK_STATE_NORMAL;

  #if GTK_CHECK_VERSION(3, 0, 0)
  cairo_save(cr);
  #else
  cr = gdk_cairo_create (drawable);
  #endif

  if (workspace_background)
    {
      gdk_cairo_set_source_pixbuf (cr, workspace_background, x, y);
      cairo_paint (cr);
    }
  else
    {
      gdk_cairo_set_source_color (cr, &gtk_widget_get_style (widget)->dark[state]);
      cairo_rectangle (cr, x, y, width, height);
      cairo_fill (cr);
    }

  #if !GTK_CHECK_VERSION(3, 0, 0)
  cairo_destroy (cr);
  #endif

  i = 0;
  while (i < n_windows)
    {
      const WnckWindowDisplayInfo *win = &windows[i];
      GdkRectangle winrect;

      get_window_rect (win, screen_width,
                       screen_height, &workspace_rect, &winrect);

      draw_window (widget,
                   #if GTK_CHECK_VERSION(3, 0, 0)
                   cr,
                   #else
                   drawable,
                   #endif
                   win,
                   &winrect,
                   state);

      ++i;
    }

  #if GTK_CHECK_VERSION(3, 0, 0)
  cairo_restore(cr);
  #endif
}
Example #12
0
static gboolean _gradient_slider_expose(GtkWidget *widget, GdkEventExpose *event)
{
  GtkDarktableGradientSlider *gslider=DTGTK_GRADIENT_SLIDER(widget);

  assert(gslider->position > 0);

  g_return_val_if_fail(widget != NULL, FALSE);
  g_return_val_if_fail(DTGTK_IS_GRADIENT_SLIDER(widget), FALSE);
  g_return_val_if_fail(event != NULL, FALSE);
  GtkStyle *style=gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL,"GtkButton", GTK_TYPE_BUTTON);
  if(!style) style = gtk_rc_get_style(widget);
  int state = gtk_widget_get_state(widget);

  GtkAllocation allocation;
  gtk_widget_get_allocation(widget, &allocation);
  /*int x = allocation.x;
  int y = allocation.y;*/
  int width = allocation.width;
  int height = allocation.height;
  int margins = gslider->margins;

  // Begin cairo drawing
  cairo_t *cr;
  cr = gdk_cairo_create(gtk_widget_get_window(widget));

  // First build the cairo gradient and then fill the gradient
  float gheight=height/2.0;
  float gwidth=width-2*margins;
  GList *current=NULL;
  cairo_pattern_t *gradient=NULL;
  if((current=g_list_first(gslider->colors)) != NULL)
  {
    gradient=cairo_pattern_create_linear(0,0,gwidth,gheight);
    do
    {
      _gradient_slider_stop_t *stop=(_gradient_slider_stop_t *)current->data;
      cairo_pattern_add_color_stop_rgb(gradient,stop->position,stop->color.red/65535.0,stop->color.green/65535.0,stop->color.blue/65535.0);
    }
    while((current=g_list_next(current))!=NULL);
  }

  if(gradient!=NULL) // Do we got a gradient, lets draw it
  {
    cairo_set_line_width(cr,0.1);
    cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND);
    cairo_set_source(cr,gradient);
    cairo_rectangle(cr,margins,(height-gheight)/2.0,gwidth,gheight);
    cairo_fill(cr);
    cairo_stroke(cr);
  }



  // Lets draw position arrows

  cairo_set_source_rgba(cr,
                        style->fg[state].red/65535.0,
                        style->fg[state].green/65535.0,
                        style->fg[state].blue/65535.0,
                        1.0
                       );


  // do we have a picker value to draw?
  gdouble *picker = gslider->picker;
  if(picker[0] >= 0.0 && picker[0] <= 1.0)
  {
    int vx_min=_scale_to_screen(widget, picker[1]);
    int vx_max=_scale_to_screen(widget, picker[2]);
    int vx_avg=_scale_to_screen(widget, picker[0]);

    cairo_set_source_rgba(cr,
                          style->fg[state].red/65535.0,
                          style->fg[state].green/65535.0,
                          style->fg[state].blue/65535.0,
                          0.33
                         );

    cairo_rectangle(cr,vx_min,(height-gheight)/2.0,fmax((float)vx_max-vx_min, 0.0f),gheight);
    cairo_fill(cr);

    cairo_set_source_rgba(cr,
                          style->fg[state].red/65535.0,
                          style->fg[state].green/65535.0,
                          style->fg[state].blue/65535.0,
                          1.0
                         );

    cairo_move_to(cr,vx_avg,(height-gheight)/2.0);
    cairo_line_to(cr,vx_avg,(height+gheight)/2.0);
    cairo_set_antialias(cr,CAIRO_ANTIALIAS_NONE);
    cairo_set_line_width(cr,1.0);
    cairo_stroke(cr);
  }

  int indirect[GRADIENT_SLIDER_MAX_POSITIONS];
  for(int k=0; k<gslider->positions; k++)
    indirect[k] = gslider->selected == -1 ? k : (gslider->selected + 1 + k) % gslider->positions;


  for(int k=0; k<gslider->positions; k++)
  {
    int l = indirect[k];
    int vx=_scale_to_screen(widget, gslider->position[l]);
    int mk=gslider->marker[l];
    int sz=(mk & (1<<3)) ? 13 : 10;  // big or small marker?

    if(l == gslider->selected && (gslider->is_entered == TRUE || gslider->is_dragging == TRUE))
    {
      cairo_set_source_rgba(cr,
                            style->fg[state].red/65535.0,
                            style->fg[state].green/65535.0,
                            style->fg[state].blue/65535.0 * 0.5,
                            1.0
                           );

    }
    else
    {
      cairo_set_source_rgba(cr,
                            style->fg[state].red/65535.0*0.8,
                            style->fg[state].green/65535.0*0.8,
                            style->fg[state].blue/65535.0*0.8,
                            1.0
                           );
    }


    cairo_set_antialias(cr,CAIRO_ANTIALIAS_DEFAULT);

    if(mk & 0x04) /* upper arrow */
    {
      if (mk & 0x01) /* filled */
        dtgtk_cairo_paint_solid_triangle(cr, vx-sz/2, sz < 10 ? 1 : -2,sz,sz,CPF_DIRECTION_DOWN);
      else
        dtgtk_cairo_paint_triangle(cr, vx-sz/2, sz < 10 ? 1 : -2,sz,sz,CPF_DIRECTION_DOWN);
    }

    if(mk & 0x02) /* lower arrow */
    {
      if (mk & 0x01) /* filled */
        dtgtk_cairo_paint_solid_triangle(cr, vx-sz/2,sz < 10 ? height-6 : height-11,sz,sz,CPF_DIRECTION_UP);
      else
        dtgtk_cairo_paint_triangle(cr, vx-sz/2,sz < 10 ? height-6 : height-11,sz,sz,CPF_DIRECTION_UP);
    }
  }

  cairo_destroy(cr);
  return FALSE;
}
Example #13
0
/*!
 \brief draws the static part of the stripchart,  i.e. this is only the 
 history of the trace, as there's no point to re-render the whole f*****g thing
 every damn time when only 1 datapoint is being appended,  This writes to a
 pixmap, which is shifted and new trace data rendered, before graticaule/text
 overlay is added on.
 \param chart is the pointer to the chart object
 */
void generate_stripchart_static_traces(MtxStripChart *chart)
{
	cairo_t *cr = NULL;
	gint w = 0;
	gint h = 0;
	gint i = 0;
	gint j = 0;
	gfloat x = 0.0;
	gfloat y = 0.0;
	gfloat start_x = 0.0;
	gfloat start_y = 0.0;
	gint points = 0;
	MtxStripChartTrace *trace = NULL;
	MtxStripChartPrivate *priv = MTX_STRIPCHART_GET_PRIVATE(chart);
	GtkAllocation allocation;

	gtk_widget_get_allocation(GTK_WIDGET(chart),&allocation);

	w = allocation.width;
	h = allocation.height;

	if (!priv->trace_pixmap)
		return;
	/* get a cairo_t */

	cr = gdk_cairo_create (priv->trace_pixmap);
	cairo_set_font_options(cr,priv->font_options);
	cairo_set_source_rgb (cr, 
			priv->colors[COL_BG].red/65535.0,
			priv->colors[COL_BG].green/65535.0,
			priv->colors[COL_BG].blue/65535.0);
	/* Background Rectangle */

	cairo_rectangle (cr,
			0,0,w,h);
	cairo_fill(cr);

	for (i=0;i<priv->num_traces;i++)
	{
		trace = g_array_index(priv->traces,MtxStripChartTrace *,i);
		if (!trace)
			continue;


		cairo_set_line_width(cr,trace->lwidth);
		cairo_set_source_rgb (cr, 
				trace->color.red/65535.0,
				trace->color.green/65535.0,
				trace->color.blue/65535.0);
		points = trace->history->len < priv->w ? trace->history->len-1:priv->w;
		if (points < 1)
			continue;
		start_x = priv->w - points;
		start_y = priv->h - (((g_array_index(trace->history,gfloat,trace->history->len - points)-trace->min) / (trace->max - trace->min))*priv->h);
		cairo_move_to(cr,start_x,start_y);
		for (j=0;j<points;j++)
		{
			x = priv->w - points + j;
			y = priv->h - (((g_array_index(trace->history,gfloat,trace->history->len - points + j)-trace->min) / (trace->max - trace->min))*priv->h);
			cairo_line_to(cr,x,y);
		}
		cairo_stroke(cr);
	}
	cairo_destroy (cr);
}
Example #14
0
/*!
 \brief handles configure events when the chart gets created or resized.
 Takes care of creating/destroying graphics contexts, backing pixmaps (two 
 levels are used to split the rendering for speed reasons) colormaps are 
 also created here as well
 \param widget is the pointer to the chart object
 \param event is the pointer to the GdkEventConfigure structure that
 encodes important info like window dimensions and depth.
 \returns TRUE on success, FALSE otherwise
 */
gboolean mtx_stripchart_configure (GtkWidget *widget, GdkEventConfigure *event)
{
	MtxStripChart * chart = MTX_STRIPCHART(widget);
	MtxStripChartPrivate *priv = NULL;
	cairo_t *cr = NULL;
	GtkAllocation allocation;
	GdkWindow *window = gtk_widget_get_window(widget);

	g_return_val_if_fail(MTX_IS_STRIPCHART(widget),FALSE);
	gtk_widget_get_allocation(widget,&allocation);
	priv = MTX_STRIPCHART_GET_PRIVATE(chart);

	priv->w = allocation.width;
	priv->h = allocation.height;

	/* Backing pixmap (copy of window) */

	if (priv->bg_pixmap)
		g_object_unref(priv->bg_pixmap);
	priv->bg_pixmap=gdk_pixmap_new(window,
			priv->w,priv->h,
			gtk_widget_get_visual(widget)->depth);
	cr = gdk_cairo_create(priv->bg_pixmap);
	cairo_set_operator(cr,CAIRO_OPERATOR_DEST_OUT);
	cairo_paint(cr);
	cairo_destroy(cr);
	/* Trace pixmap */

	if (priv->trace_pixmap)
		g_object_unref(priv->trace_pixmap);
	priv->trace_pixmap=gdk_pixmap_new(window,
			priv->w,priv->h,
			gtk_widget_get_visual(widget)->depth);
	cr = gdk_cairo_create(priv->trace_pixmap);
	cairo_set_operator(cr,CAIRO_OPERATOR_DEST_OUT);
	cairo_paint(cr);
	cairo_destroy(cr);
	/* Grat pixmap */

	if (priv->grat_pixmap)
		g_object_unref(priv->grat_pixmap);
	priv->grat_pixmap=gdk_pixmap_new(window,
			priv->w,priv->h,
			gtk_widget_get_visual(widget)->depth);
	cr = gdk_cairo_create(priv->grat_pixmap);
	cairo_set_operator(cr,CAIRO_OPERATOR_DEST_OUT);
	cairo_paint(cr);
	cairo_destroy(cr);

	gdk_window_set_back_pixmap(window,priv->bg_pixmap,0);

	if (priv->font_options)
		cairo_font_options_destroy(priv->font_options);
	priv->font_options = cairo_font_options_create();
	cairo_font_options_set_antialias(priv->font_options,
			CAIRO_ANTIALIAS_GRAY);

	generate_stripchart_static_traces(chart);
	render_marker (chart);

	return TRUE;
}
inf_text_gtk_viewport_scrollbar_expose_event_cb(GtkWidget* scrollbar,
                                                GdkEventExpose* event,
                                                gpointer user_data)
#endif
{
  InfTextGtkViewport* viewport;
  InfTextGtkViewportPrivate* priv;
  InfTextGtkViewportUser* viewport_user;
  GdkRectangle* rectangle;
  GdkColor* color;
  double h,s,v;
  double r,g,b;
  GSList* item;
  double line_width;

#if GTK_CHECK_VERSION(2, 91, 0)
  GdkRectangle clip_area;
#else
  cairo_t* cr;
#endif

  viewport = INF_TEXT_GTK_VIEWPORT(user_data);
  priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport);

  /* Can this happen? */
#if GTK_CHECK_VERSION(2, 91, 0)
  if(!gtk_cairo_should_draw_window(cr, gtk_widget_get_window(scrollbar)))
#elif GTK_CHECK_VERSION(2,14,0)
  if(event->window != gtk_widget_get_window(scrollbar))
#else
  if(event->window != GTK_WIDGET(scrollbar)->window)
#endif
    return FALSE;

  if(priv->show_user_markers)
  {
    color = &gtk_widget_get_style(scrollbar)->bg[GTK_STATE_NORMAL];
    h = color->red / 65535.0;
    s = color->green / 65535.0;
    v = color->blue / 65535.0;
    rgb_to_hsv(&h, &s, &v);
    s = MIN(MAX(s, 0.5), 0.8);
    v = MAX(v, 0.5);

#if GTK_CHECK_VERSION(2, 91, 0)
    gtk_cairo_transform_to_window(
      cr,
      GTK_WIDGET(scrollbar),
      gtk_widget_get_window(scrollbar)
    );

    gdk_cairo_get_clip_rectangle(cr, &clip_area);
#else
    cr = gdk_cairo_create(event->window);
#endif

    line_width = cairo_get_line_width(cr);
    for(item = priv->users; item != NULL; item = item->next)
    {
      viewport_user = (InfTextGtkViewportUser*)item->data;
      rectangle = &viewport_user->rectangle;

#if GTK_CHECK_VERSION(2, 91, 0)
      if(gdk_rectangle_intersect(&clip_area, rectangle, NULL))
#elif GTK_CHECK_VERSION(2,90,5)
      if(cairo_region_contains_rectangle(event->region, rectangle) !=
         CAIRO_REGION_OVERLAP_OUT)
#else
      if(gdk_region_rect_in(event->region, rectangle) !=
         GDK_OVERLAP_RECTANGLE_OUT)
#endif
      {
        h = inf_text_user_get_hue(viewport_user->user);

        cairo_rectangle(
          cr,
          rectangle->x + line_width/2,
          rectangle->y + line_width/2,
          rectangle->width - line_width,
          rectangle->height - line_width
        );

        r = h; g = s; b = v/2.0;
        hsv_to_rgb(&r, &g, &b);
        cairo_set_source_rgba(cr, r, g, b, 0.6);
        cairo_stroke_preserve(cr);

        r = h; g = s; b = v;
        hsv_to_rgb(&r, &g, &b);
        cairo_set_source_rgba(cr, r, g, b, 0.6);
        cairo_fill(cr);
      }
    }

#if ! GTK_CHECK_VERSION(2, 91, 0)
    cairo_destroy(cr);
#endif
  }

  return FALSE;
}
Example #16
0
static gboolean
calf_vumeter_expose (GtkWidget *widget, GdkEventExpose *event)
{
    g_assert(CALF_IS_VUMETER(widget));

    CalfVUMeter *vu = CALF_VUMETER(widget);
    cairo_t *c = gdk_cairo_create(GDK_DRAWABLE(widget->window));

    float r, g, b;

    int x = widget->allocation.x;
    int y = widget->allocation.y;
    int width = widget->allocation.width;
    int height = widget->allocation.height;
    int border_x = widget->style->xthickness;
    int border_y = widget->style->ythickness;
    int space_x = 1;
    int space_y = 1; // inner border around led bar
    int led = 2; // single LED size
    int led_m = 1; // margin between LED
    int led_s = led + led_m; // size of LED with margin
    int led_x = widget->style->xthickness;
    int led_y = widget->style->ythickness; // position of first LED
    int led_w = width - 2 * led_x + led_m; // width of LED bar w/o text calc (additional led margin, is removed later; used for filling the led bar completely w/o margin gap)
    int led_h = height - 2 * led_y; // height of LED bar w/o text calc
    int text_x = 0;
    int text_y = 0;
    int text_w = 0;
    int text_h = 0;

    // only valid if vumeter is enabled
    cairo_text_extents_t extents;

    if(vu->vumeter_position) {
        cairo_select_font_face(c, "cairo:sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
        cairo_set_font_size(c, 8);

        cairo_text_extents(c, "-88.88", &extents);
        text_w = extents.width;
        text_h = extents.height;
        switch(vu->vumeter_position) {
        case 1:
            text_x = width / 2 - text_w / 2;
            text_y = border_y + led_y - extents.y_bearing;
            led_y += text_h + led_y;
            led_h -= text_h + led_y;
            break;
        case 2:
            text_x = width - border_x - led_x - text_w;
            text_y = height / 2 - text_h / 2 - extents.y_bearing;
            led_w -= led_x + text_w;
            break;
        case 3:
            text_x = width / 2 - text_w / 2;
            text_y = height - border_y - led_y - text_h - extents.y_bearing;
            led_h -= led_y + text_h;
            break;
        case 4:
            text_x = border_x + led_x;
            text_y = height / 2 - text_h / 2 - extents.y_bearing;
            led_x += led_x + text_w;
            led_w -= led_x + text_w;
            break;
        }
    }

    led_w -= led_w % led_s + led_m; //round LED width to LED size and remove margin gap, width is filled with LED without margin gap now

    if( vu->cache_surface == NULL ) {
        // looks like its either first call or the widget has been resized.
        // create the cache_surface.
        vu->cache_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height );
        cairo_t *cache_cr = cairo_create( vu->cache_surface );

        float radius, bevel;
        get_bg_color(widget, NULL, &r, &g, &b);
        gtk_widget_style_get(widget, "border-radius", &radius, "bevel",  &bevel, NULL);
        create_rectangle(cache_cr, 0, 0, width, height, radius);
        cairo_set_source_rgb(cache_cr, r, g, b);
        cairo_fill(cache_cr);
        draw_bevel(cache_cr, 0, 0, width, height, radius, bevel);

        // border around LED
        cairo_rectangle(cache_cr, led_x, led_y, led_w, led_h);
        cairo_set_source_rgb (cache_cr, 0, 0, 0);
        cairo_fill(cache_cr);

        led_x += space_x;
        led_y += space_y;
        led_w -= 2 * space_x;
        led_h -= 2 * space_y;

        // LED bases
        cairo_set_line_width(cache_cr, 1);
        for (int x = led_x; x + led <= led_x + led_w; x += led_s)
        {
            float ts = (x - led_x) * 1.0 / led_w;
            float r = 0.f, g = 0.f, b = 0.f;
            switch(vu->mode)
            {
            case VU_STANDARD:
            default:
                if (ts < 0.75)
                    r = ts / 0.75, g = 0.5 + ts * 0.66, b = 1 - ts / 0.75;
                else
                    r = 1, g = 1 - (ts - 0.75) / 0.25, b = 0;
                //                if (vu->value < ts || vu->value <= 0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            case VU_STANDARD_CENTER:
                if (ts < 0.25)
                    // 0.0 -> 0.25
                    // green: 0.f -> 1.f
                    r = 1, g = (ts) / 0.25, b = 0;
                else if (ts > 0.75)
                    // 0.75 -> 1.0
                    // green: 1.f -> 0.f
                    r = 1, g = 1 - (ts - 0.75) / 0.25, b = 0;
                else if (ts > 0.5)
                    // 0.5 -> 0.75
                    // red: 0.f -> 1.f
                    // green: 0.5 -> 1.f
                    // blue: 1.f -> 0.f
                    r = (ts - 0.5) / 0.25, g = 0.5 + (ts - 0.5) * 2.f, b = 1 - (ts - 0.5) / 0.25;
                else
                    // 0.25 -> 0.5
                    // red: 1.f -> 0.f
                    // green: 1.f -> 0.5
                    // blue: 0.f -> 1.f
                    r = 1 - (ts - 0.25) / 0.25, g = 1.f - (ts * 2.f - .5f), b = (ts - 0.25) / 0.25;
                //                if (vu->value < ts || vu->value <= 0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            case VU_MONOCHROME_REVERSE:
                r = 0, g = 170.0 / 255.0, b = 1;
                //                if (!(vu->value < ts) || vu->value >= 1.0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            case VU_MONOCHROME:
                r = 0, g = 170.0 / 255.0, b = 1;
                //                if (vu->value < ts || vu->value <= 0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            case VU_MONOCHROME_CENTER:
                r = 0, g = 170.0 / 255.0, b = 1;
                //                if (vu->value < ts || vu->value <= 0)
                //                    r *= 0.5, g *= 0.5, b *= 0.5;
                break;
            }
            GdkColor sc2 = { 0, (guint16)(65535 * r + 0.2), (guint16)(65535 * g), (guint16)(65535 * b) };
            GdkColor sc3 = { 0, (guint16)(65535 * r * 0.7), (guint16)(65535 * g * 0.7), (guint16)(65535 * b * 0.7) };
            gdk_cairo_set_source_color(cache_cr, &sc2);
            cairo_move_to(cache_cr, x + 0.5, led_y);
            cairo_line_to(cache_cr, x + 0.5, led_y + led_h);
            cairo_stroke(cache_cr);
            gdk_cairo_set_source_color(cache_cr, &sc3);
            cairo_move_to(cache_cr, x + 1.5, led_y + led_h);
            cairo_line_to(cache_cr, x + 1.5, led_y);
            cairo_stroke(cache_cr);
        }
        // create blinder pattern
        cairo_pattern_t *pat = cairo_pattern_create_linear (led_x, led_y, led_x, led_y + led_h);
        cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 0.25);
        cairo_pattern_add_color_stop_rgba (pat, 0.5, 0.5, 0.5, 0.5, 0.0);
        cairo_pattern_add_color_stop_rgba (pat, 1, 0.0, 0.0, 0.0, 0.25);
        cairo_rectangle(cache_cr, led_x, led_y, led_w, led_h);
        cairo_set_source(cache_cr, pat);
        cairo_fill(cache_cr);

        // create overlay
        vu->cache_overlay = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
        cairo_t *over_cr = cairo_create(vu->cache_overlay);

        // copy surface to overlay
        cairo_set_source_surface(over_cr, vu->cache_surface, 0, 0);
        cairo_rectangle(over_cr, 0, 0, width, height);
        cairo_fill(over_cr);

        // create blinder pattern
        pat = cairo_pattern_create_linear (led_x, led_y, led_x, led_y + led_h);
        cairo_pattern_add_color_stop_rgba (pat, 0, 0.2, 0.2, 0.2, 0.7);
        cairo_pattern_add_color_stop_rgba (pat, 0.4, 0.05, 0.05, 0.05, 0.7);
        cairo_pattern_add_color_stop_rgba (pat, 0.401, 0.05, 0.05, 0.05, 0.9);
        cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.05, 0.05, 0.75);

        // draw on top of overlay
        cairo_set_source(over_cr, pat);
        cairo_rectangle(over_cr, 0, 0, width, height);
        cairo_paint(over_cr);

        // clean up
        cairo_destroy(cache_cr);
        cairo_destroy(over_cr);
    } else {
        led_x += space_x;
        led_y += space_y;
        led_w -= 2 * space_x;
        led_h -= 2 * space_y;
    }
    led_x += x;
    led_y += y;
    text_x += x;
    text_y += y;
    // draw LED blinder
    cairo_set_source_surface( c, vu->cache_surface, x, y );
    cairo_paint( c );
    cairo_set_source_surface( c, vu->cache_overlay, x, y );

    // get microseconds
    timeval tv;
    gettimeofday(&tv, 0);
    long time = tv.tv_sec * 1000 * 1000 + tv.tv_usec;

    // limit to 1.f
    float value_orig = std::max(std::min(vu->value, 1.f), 0.f);
    float value = 0.f;

    // falloff?
    if(vu->vumeter_falloff > 0.f and vu->mode != VU_MONOCHROME_REVERSE) {
        // fall off a bit
        float s = ((float)(time - vu->last_falltime) / 1000000.0);
        float m = vu->last_falloff * s * vu->vumeter_falloff;
        vu->last_falloff -= m;
        // new max value?
        if(value_orig > vu->last_falloff) {
            vu->last_falloff = value_orig;
        }
        value = vu->last_falloff;
        vu->last_falltime = time;
        vu->falling = vu->last_falloff > 0.00000001;
    } else {
        // falloff disabled
        vu->last_falloff = 0.f;
        vu->last_falltime = 0.f;
        value = value_orig;
        vu->falling = false;
    }

    float draw = 0.f;
    float draw_last = 0.f;

    if(vu->vumeter_hold > 0.0) {
        // peak hold timer
        if(time - (long)(vu->vumeter_hold * 1000 * 1000) > vu->last_hold) {
            // time's up, reset
            vu->last_value = value;
            vu->last_hold = time;
            vu->holding = false;
            vu->disp_value = value_orig;
        }
        if( vu->mode == VU_MONOCHROME_REVERSE ) {
            if(value < vu->last_value) {
                // value is above peak hold
                vu->last_value = value;
                vu->last_hold = time;
                vu->holding = true;
            }
            draw = log10(1 + value * 9);
            draw_last = log10(1 + vu->last_value * 9);

            // blinder left -> hold LED
            int hold_x = round((draw_last) * (led_w + led_m)); // add last led_m removed earlier
            hold_x -= hold_x % led_s + led_m;
            hold_x = std::max(0, hold_x);
            cairo_rectangle( c, led_x, led_y, hold_x, led_h);

            // blinder hold LED -> value
            int val_x = round((1 - draw) * (led_w + led_m)); // add last led_m removed earlier
            val_x -= val_x % led_s;
            int blind_x = std::min(hold_x + led_s, led_w);
            int blind_w = std::min(std::max(led_w - val_x - hold_x - led_s, 0), led_w);
            cairo_rectangle(c, led_x + blind_x, led_y, blind_w, led_h);
        } else  if( vu->mode == VU_STANDARD_CENTER ) {
            if(value > vu->last_value) {
                // value is above peak hold
                vu->last_value = value;
                vu->last_hold = time;
                vu->holding = true;
            }
            draw = log10(1 + value * 9);
            int val_x = round((1 - draw) / 2.f * (led_w + led_m)); // add last led_m removed earlier
            cairo_rectangle(c, led_x, led_y, val_x, led_h);
            cairo_rectangle(c, led_x + led_w - val_x, led_y, val_x, led_h);

        } else {
            if(value > vu->last_value) {
                // value is above peak hold
                vu->last_value = value;
                vu->last_hold = time;
                vu->holding = true;
            }
            draw = log10(1 + value * 9);
            draw_last = log10(1 + vu->last_value * 9);

            int hold_x = round((1 - draw_last) * (led_w + led_m)); // add last led_m removed earlier
            hold_x -= hold_x % led_s;
            int val_x = round(draw * (led_w + led_m)); // add last led_m removed earlier
            val_x -= val_x % led_s;
            int blind_w = led_w - hold_x - led_s - val_x;
            blind_w = std::min(std::max(blind_w, 0), led_w);
            cairo_rectangle(c, led_x + val_x, led_y, blind_w, led_h);
            cairo_rectangle( c, led_x + led_w - hold_x, led_y, hold_x, led_h);
        }
    } else {
        // darken normally
        float draw = log10(1 + value * 9);
        if( vu->mode == VU_MONOCHROME_REVERSE )
            cairo_rectangle( c, led_x, led_y, draw * led_w, led_h);
        else if( vu->mode == VU_STANDARD_CENTER ) {
            int val_x = round((1 - draw) / 2.f * (led_w + led_m)); // add last led_m removed earlier
            cairo_rectangle(c, led_x, led_y, val_x, led_h);
            cairo_rectangle(c, led_x + led_w - val_x, led_y, val_x, led_h);
        } else
            cairo_rectangle( c, led_x + draw * led_w, led_y, led_w * (1 - draw), led_h);
    }
    cairo_fill( c );

    if (vu->vumeter_position)
    {
        char str[32];
        if((vu->value > vu->disp_value and vu->mode != VU_MONOCHROME_REVERSE)
                or (vu->value < vu->disp_value and vu->mode == VU_MONOCHROME_REVERSE))
            vu->disp_value = vu->value;
        if (vu->disp_value < 1.0 / 32768.0)
            snprintf(str, sizeof(str), "-inf");
        else
            snprintf(str, sizeof(str), "%0.2f", dsp::amp2dB(vu->disp_value));
        // draw value as number
        cairo_text_extents(c, str, &extents);
        cairo_move_to(c, text_x + (text_w - extents.width) / 2.0, text_y);
        GtkStateType state;
        if(vu->disp_value > 1.f and vu->mode != VU_MONOCHROME_REVERSE)
            state = GTK_STATE_ACTIVE;
        else
            state = GTK_STATE_NORMAL;
        get_fg_color(widget, &state, &r, &g, &b);
        cairo_set_source_rgba (c, r, g, b, 1);
        cairo_show_text(c, str);
        cairo_fill(c);
    }
    cairo_destroy(c);
    //gtk_paint_shadow(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, widget, NULL, ox - 2, oy - 2, sx + 4, sy + 4);
    //printf("exposed %p %d+%d\n", widget->window, widget->allocation.x, widget->allocation.y);

    return TRUE;
}
Example #17
0
static gboolean _lib_filmstrip_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
  dt_lib_module_t *self = (dt_lib_module_t *)user_data;
  dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data;

  int32_t width = widget->allocation.width;
  int32_t height = widget->allocation.height;

  gdouble pointerx = strip->pointerx;
  gdouble pointery = strip->pointery;

  if(darktable.gui->center_tooltip == 1)
    darktable.gui->center_tooltip++;

  strip->image_over = DT_VIEW_DESERT;
  DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1);

  /* create cairo surface */
  cairo_t *cr = gdk_cairo_create(widget->window);

  /* fill background */
  cairo_set_source_rgb (cr, .2, .2, .2);
  cairo_paint(cr);

  int offset = strip->offset;

  const float wd = height;
  const float ht = height;

  int max_cols = (int)(width/(float)wd) + 2;
  if (max_cols%2 == 0)
    max_cols += 1;

  const int col_start = max_cols/2 - strip->offset;
  const int empty_edge = (width - (max_cols * wd))/2;
  int step_res = SQLITE_ROW;

  sqlite3_stmt *stmt = NULL;

  /* mouse over image position in filmstrip */
  pointerx -= empty_edge;
  const int seli = (pointery > 0 && pointery <= ht) ? pointerx / (float)wd : -1;
  const int img_pointerx = (int)fmodf(pointerx, wd);
  const int img_pointery = (int)pointery;


  /* get the count of current collection */
  strip->collection_count = dt_collection_get_count (darktable.collection);

  /* get the collection query */
  const gchar *query=dt_collection_get_query (darktable.collection);
  if(!query)
    return FALSE;

  if(offset < 0)
    strip->offset = offset = 0;
  if(offset > strip->collection_count-1)
    strip->offset = offset = strip->collection_count-1;

  // dt_view_set_scrollbar(self, offset, count, max_cols, 0, 1, 1);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, offset - max_cols/2);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, max_cols);


  cairo_save(cr);
  cairo_translate(cr, empty_edge, 0.0f);
  for(int col = 0; col < max_cols; col++)
  {
    if(col < col_start)
    {
      cairo_translate(cr, wd, 0.0f);
      continue;
    }

    if(step_res != SQLITE_DONE)
    {
      step_res = sqlite3_step(stmt);
    }

    if(step_res == SQLITE_ROW)
    {
      int id = sqlite3_column_int(stmt, 0);
      // set mouse over id
      if(seli == col)
      {
        strip->mouse_over_id = id;
        DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, strip->mouse_over_id);
      }
      cairo_save(cr);
      // FIXME find out where the y translation is done, how big the value is and use it directly instead of getting it from the matrix ...
      cairo_matrix_t m;
      cairo_get_matrix(cr, &m);
      dt_view_image_expose(&(strip->image_over), id, cr, wd, ht, max_cols, img_pointerx, img_pointery, FALSE);
      cairo_restore(cr);
    }
    else if (step_res == SQLITE_DONE)
    {
      /* do nothing, just add some empty thumb frames */
    }
    else goto failure;
    cairo_translate(cr, wd, 0.0f);
  }
failure:
  cairo_restore(cr);
  sqlite3_finalize(stmt);

  if(darktable.gui->center_tooltip == 1) // set in this round
  {
    char* tooltip = dt_history_get_items_as_string(strip->mouse_over_id);
    if(tooltip != NULL)
    {
      g_object_set(G_OBJECT(strip->filmstrip), "tooltip-text", tooltip, (char *)NULL);
      g_free(tooltip);
    }
  }
  else if(darktable.gui->center_tooltip == 2)   // not set in this round
  {
    darktable.gui->center_tooltip = 0;
    g_object_set(G_OBJECT(strip->filmstrip), "tooltip-text", "", (char *)NULL);
  }

#ifdef _DEBUG
  if(darktable.unmuted & DT_DEBUG_CACHE)
    dt_mipmap_cache_print(darktable.mipmap_cache);
#endif

  /* cleanup */
  cairo_destroy(cr);

  return TRUE;
}
Example #18
0
gboolean draw_callback
(GtkWidget *widget, GdkEventExpose *event, UNUSED gpointer data)
{
	guint width, height;
	cairo_pattern_t *color;
	cairo_path_t *bolt, *fill, *text;

	// Grab our widget size
	width = widget->allocation.width;
	height = widget->allocation.height;

	// Set up Cairo
	cairo_t *cr = gdk_cairo_create(widget->window);

	cairo_set_antialias(cr, CAIRO_ANTIALIAS_BEST);

	// Clear canvas
	#ifdef BACKGROUND_FILL_ENTIRE_WIDGET
	cairo_rectangle(cr, 0, 0, width, height);
	#else
	cairo_rectangle(cr, (MARGIN / 2) + STROKE_WIDTH, (MARGIN / 2) + STROKE_WIDTH, BATTERY_WIDTH, BATTERY_HEIGHT);
	#endif
	cairo_set_source_rgba(cr, COLOR_BACKGROUND, OPACITY_BACKGROUND);
	cairo_fill(cr);

	// Decide on a color
	color = cairo_pattern_create_rgb(COLOR_DEFAULT);
	if (battery_get_charging())
		color = cairo_pattern_create_rgb(COLOR_CHARGING);
	if (battery_get_critical())
		color = cairo_pattern_create_rgb(COLOR_CRITICAL);

	battery_border_draw(cr, color, (int)CENTERED(width, BATTERY_WIDTH),
	                               (int)CENTERED(height, BATTERY_HEIGHT),
	                               BATTERY_WIDTH,
	                               BATTERY_HEIGHT,
	                               STROKE_WIDTH,
	                               PEG_WIDTH,
	                               PEG_HEIGHT);


	int fill_x = CENTERED(width, BATTERY_WIDTH);
	int fill_y = CENTERED(height, BATTERY_HEIGHT);

	// Set fill style
	cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);

	// Generate battery fill
	fill = battery_fill_generate(BATTERY_WIDTH, BATTERY_HEIGHT, battery_get_percent());
	cairo_translate(cr, fill_x, fill_y);
	cairo_append_path(cr, fill);

	if (battery_get_charging()) {
		int bolt_x = CENTERED(BATTERY_WIDTH, BOLT_WIDTH);
		int bolt_y = CENTERED(BATTERY_HEIGHT, BOLT_HEIGHT);

		cairo_translate(cr, bolt_x, bolt_y);
		bolt = battery_bolt_generate(BOLT_WIDTH, BOLT_HEIGHT);
		cairo_append_path(cr, bolt);
		cairo_translate(cr, bolt_x, bolt_y);
	} else {
		cairo_text_extents_t extents;
		char strpercent[5];
		snprintf(strpercent, 5, "%i%%", (int)(battery_get_percent() * 100));

		cairo_select_font_face(cr, FONT_FACE, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
		cairo_set_font_size(cr, FONT_SIZE);
		cairo_text_extents(cr, strpercent, &extents);

		int text_x = CENTERED(BATTERY_WIDTH, extents.width);
		int text_y = CENTERED(BATTERY_HEIGHT,  extents.height + extents.y_bearing*2);

		text = battery_text_generate(strpercent, FONT_FACE, FONT_SIZE);

		cairo_translate(cr, text_x, text_y);
		cairo_append_path(cr, text);
		cairo_translate(cr, -text_x, -text_y);
	}
	cairo_translate(cr, -fill_x, -fill_y);

	cairo_set_source(cr, color);
	cairo_fill(cr);

	return FALSE;
}
Example #19
0
static gboolean gx_selector_expose (GtkWidget *widget, GdkEventExpose *event)
{
	g_assert(GX_IS_SELECTOR(widget));
	GxSelector *selector = GX_SELECTOR(widget);
	GxSelectorPrivate *priv = selector->priv;
	int selectorstate = get_selector_state(selector);
    
    gx_selector_create_icon(selector);
    
	PangoLayout *layout = gtk_widget_create_pango_layout(widget, NULL);
	GdkRectangle arrow, text;
	gint off_x, off_y;
	gx_selector_get_positions(widget, &arrow, &text, &off_x, &off_y);
    gint rad;
    float bevel;
    gtk_widget_style_get(widget, "border-radius", &rad, "bevel", &bevel, NULL);
    if (!rad)
        rad = 0;
    if (!bevel)
        bevel = 0;
    cairo_t * cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
    GdkRegion *reg = gdk_region_rectangle(&widget->allocation);
    if (event->region)
        gdk_region_intersect(reg, event->region);
    gdk_cairo_region(cr, reg);
    cairo_clip (cr);
   
    gx_draw_rect(widget, "bg", NULL, widget->allocation.x,
        widget->allocation.y + (widget->allocation.height - widget->requisition.height) / 2,
        widget->allocation.width,
        widget->requisition.height,
        rad,
        bevel);
    
    if (widget->style->ythickness >= 3)
        gx_draw_inset(widget, text.x, text.y, text.width, text.height,
            std::max(rad - std::max(widget->style->ythickness, widget->style->ythickness), 0), 1);
        
    gx_draw_rect(widget, "base", NULL, text.x,
        text.y,
        text.width,
        text.height,
        std::max(rad - std::max(widget->style->ythickness, widget->style->ythickness), 0),
        0);
    
    gx_draw_glass(widget, text.x, text.y, text.width, text.height,
        std::max(rad - std::max(widget->style->ythickness, widget->style->ythickness), 0));
    
    gdk_cairo_set_source_pixbuf(cr, selector->icon, arrow.x, arrow.y);
    cairo_rectangle(cr, arrow.x, arrow.y, arrow.width, arrow.height);
    cairo_fill(cr);
    
	cairo_destroy(cr);
    
	if (selector->model) {
		gint x, y;
		PangoRectangle logical;
		char *s;
		GtkTreeIter iter;
		gtk_tree_model_iter_nth_child(selector->model, &iter, NULL, selectorstate);
		gtk_tree_model_get(selector->model, &iter, 0, &s, -1);
		pango_layout_set_text(layout, s, -1);
		pango_layout_get_pixel_extents(layout, NULL, &logical);
		x = text.x + (text.width - logical.width) / 2;
		y = text.y + off_y + (priv->textsize.height - logical.height)/ 2;
		gtk_paint_layout(widget->style, widget->window, gtk_widget_get_state(widget),
		                 FALSE, NULL, widget, "label", x, y, layout);
		g_free(s);
	}
	g_object_unref(layout);
	gdk_region_destroy(reg);
	return TRUE;
}
Example #20
0
static gboolean dt_iop_tonecurve_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
  dt_iop_module_t *self = (dt_iop_module_t *)user_data;
  dt_iop_tonecurve_gui_data_t *c = (dt_iop_tonecurve_gui_data_t *)self->gui_data;
  dt_iop_tonecurve_params_t *p = (dt_iop_tonecurve_params_t *)self->params;
  dt_develop_t *dev = darktable.develop;

  const float color_labels_left[3][3] = { { 0.3f, 0.3f,  0.3f  },
    { 0.0f, 0.34f, 0.27f },
    { 0.0f, 0.27f, 0.58f }
  };

  const float color_labels_right[3][3] = {{ 0.3f, 0.3f, 0.3f   },
    { 0.53f, 0.08f, 0.28f},
    { 0.81f, 0.66f, 0.0f }
  };

  int ch = c->channel;
  int nodes = p->tonecurve_nodes[ch];
  dt_iop_tonecurve_node_t *tonecurve = p->tonecurve[ch];
  int autoscale_ab = p->tonecurve_autoscale_ab;
  if(c->minmax_curve_type[ch] != p->tonecurve_type[ch] || c->minmax_curve_nodes[ch] != p->tonecurve_nodes[ch])
  {
    dt_draw_curve_destroy(c->minmax_curve[ch]);
    c->minmax_curve[ch] = dt_draw_curve_new(0.0, 1.0, p->tonecurve_type[ch]);
    c->minmax_curve_nodes[ch] = p->tonecurve_nodes[ch];
    c->minmax_curve_type[ch] = p->tonecurve_type[ch];
    for(int k=0; k<p->tonecurve_nodes[ch]; k++)
      (void)dt_draw_curve_add_point(c->minmax_curve[ch], p->tonecurve[ch][k].x, p->tonecurve[ch][k].y);
  }
  else
  {
    for(int k=0; k<p->tonecurve_nodes[ch]; k++)
      dt_draw_curve_set_point(c->minmax_curve[ch], k, p->tonecurve[ch][k].x, p->tonecurve[ch][k].y);
  }
  dt_draw_curve_t *minmax_curve = c->minmax_curve[ch];
  dt_draw_curve_calc_values(minmax_curve, 0.0, 1.0, DT_IOP_TONECURVE_RES, c->draw_xs, c->draw_ys);

  const float xm = tonecurve[nodes-1].x;
  const float x[4] = {0.7f*xm, 0.8f*xm, 0.9f*xm, 1.0f*xm};
  const float y[4] = {c->draw_ys[CLAMP((int)(x[0]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)],
                      c->draw_ys[CLAMP((int)(x[1]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)],
                      c->draw_ys[CLAMP((int)(x[2]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)],
                      c->draw_ys[CLAMP((int)(x[3]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)]
                     };
  float unbounded_coeffs[3];
  dt_iop_estimate_exp(x, y, 4, unbounded_coeffs);

  const int inset = DT_GUI_CURVE_EDITOR_INSET;
  int width = widget->allocation.width, height = widget->allocation.height;
  cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  cairo_t *cr = cairo_create(cst);
  // clear bg
  cairo_set_source_rgb (cr, .2, .2, .2);
  cairo_paint(cr);

  cairo_translate(cr, inset, inset);
  width -= 2*inset;
  height -= 2*inset;

#if 0
  // draw shadow around
  float alpha = 1.0f;
  for(int k=0; k<inset; k++)
  {
    cairo_rectangle(cr, -k, -k, width + 2*k, height + 2*k);
    cairo_set_source_rgba(cr, 0, 0, 0, alpha);
    alpha *= 0.6f;
    cairo_fill(cr);
  }
#else
  cairo_set_line_width(cr, 1.0);
  cairo_set_source_rgb (cr, .1, .1, .1);
  cairo_rectangle(cr, 0, 0, width, height);
  cairo_stroke(cr);
#endif

  cairo_set_source_rgb (cr, .3, .3, .3);
  cairo_rectangle(cr, 0, 0, width, height);
  cairo_fill(cr);

  // draw color labels
  const int cells = 8;
  for(int j=0; j<cells; j++)
  {
    for(int i=0; i<cells; i++)
    {
      const float f = (cells-1-j+i)/(2.0f*cells-2.0f);
      cairo_set_source_rgba (cr,
                             (1.0f-f)*color_labels_left[ch][0] + f*color_labels_right[ch][0],
                             (1.0f-f)*color_labels_left[ch][1] + f*color_labels_right[ch][1],
                             (1.0f-f)*color_labels_left[ch][2] + f*color_labels_right[ch][2],
                             .5f); // blend over to make colors darker, so the overlay is more visible
      cairo_rectangle(cr, width*i/(float)cells, height*j/(float)cells, width/(float)cells, height/(float)cells);
      cairo_fill(cr);
    }
  }

  // draw grid
  cairo_set_line_width(cr, .4);
  cairo_set_source_rgb (cr, .1, .1, .1);
  if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM)
    dt_draw_waveform_lines(cr, 0, 0, width, height);
  else
  dt_draw_grid(cr, 4, 0, 0, width, height);

  // if autoscale_ab is on: do not display a and b curves
  if (autoscale_ab && ch != ch_L) goto finally;

  // draw nodes positions
  cairo_set_line_width(cr, 1.);
  cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
  cairo_translate(cr, 0, height);

  for(int k=0; k<nodes; k++)
  {
    cairo_arc(cr, tonecurve[k].x*width, -tonecurve[k].y*height, 3, 0, 2.*M_PI);
    cairo_stroke(cr);
  }

  // draw selected cursor
  cairo_set_line_width(cr, 1.);

  // draw histogram in background
  // only if module is enabled
  if (self->enabled)
  {
    float *hist, hist_max;
    float *raw_mean, *raw_min, *raw_max;
    float *raw_mean_output;
    float picker_mean[3], picker_min[3], picker_max[3];
    char text[256];

    raw_mean = self->picked_color;
    raw_min = self->picked_color_min;
    raw_max = self->picked_color_max;
    raw_mean_output = self->picked_output_color;

    hist = self->histogram;
    hist_max = dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR?self->histogram_max[ch]:logf(1.0 + self->histogram_max[ch]);
    if(hist && hist_max > 0)
    {
      cairo_save(cr);
      cairo_scale(cr, width/63.0, -(height-5)/(float)hist_max);
      cairo_set_source_rgba(cr, .2, .2, .2, 0.5);
      dt_draw_histogram_8(cr, hist, ch, dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM?DT_DEV_HISTOGRAM_LOGARITHMIC:dev->histogram_type); // TODO: make draw handle waveform histograms
      cairo_restore(cr);
    }

    if(self->request_color_pick)
    {
      // the global live samples ...
      GSList *samples = darktable.lib->proxy.colorpicker.live_samples;
      dt_colorpicker_sample_t *sample = NULL;
      while(samples)
      {
        sample = samples->data;

        picker_scale(sample->picked_color_lab_mean, picker_mean);
        picker_scale(sample->picked_color_lab_min, picker_min);
        picker_scale(sample->picked_color_lab_max, picker_max);

        cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.15);
        cairo_rectangle(cr, width*picker_min[ch], 0, width*fmax(picker_max[ch]-picker_min[ch], 0.0f), -height);
        cairo_fill(cr);
        cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.5);
        cairo_move_to(cr, width*picker_mean[ch], 0);
        cairo_line_to(cr, width*picker_mean[ch], -height);
        cairo_stroke(cr);

        samples = g_slist_next(samples);
      }

      // ... and the local sample
      if(raw_max[0] >= 0.0f)
      {
        picker_scale(raw_mean, picker_mean);
        picker_scale(raw_min, picker_min);
        picker_scale(raw_max, picker_max);

        cairo_set_source_rgba(cr, 0.7, 0.5, 0.5, 0.33);
        cairo_rectangle(cr, width*picker_min[ch], 0, width*fmax(picker_max[ch]-picker_min[ch], 0.0f), -height);
        cairo_fill(cr);
        cairo_set_source_rgba(cr, 0.9, 0.7, 0.7, 0.5);
        cairo_move_to(cr, width*picker_mean[ch], 0);
        cairo_line_to(cr, width*picker_mean[ch], -height);
        cairo_stroke(cr);

        snprintf(text, 256, "%.1f → %.1f", raw_mean[ch], raw_mean_output[ch]);

        cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
        cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size (cr, 0.06*height);
        cairo_move_to (cr, 0.02f*width, -0.94*height);
        cairo_show_text(cr, text);
        cairo_stroke(cr);
      }
    }
  }

  if(c->selected >= 0)
  {
    cairo_set_source_rgb(cr, .9, .9, .9);
    cairo_arc(cr, tonecurve[c->selected].x*width, -tonecurve[c->selected].y*height, 4, 0, 2.*M_PI);
    cairo_stroke(cr);
  }

  // draw curve
  cairo_set_line_width(cr, 2.);
  cairo_set_source_rgb(cr, .9, .9, .9);
  // cairo_set_line_cap  (cr, CAIRO_LINE_CAP_SQUARE);
  cairo_move_to(cr, 0, -height*c->draw_ys[0]);
  for(int k=1; k<DT_IOP_TONECURVE_RES; k++)
  {
    const float xx = k/(DT_IOP_TONECURVE_RES-1.0);
    if(xx > xm)
    {
      const float yy = dt_iop_eval_exp(unbounded_coeffs, xx);
      cairo_line_to(cr, xx*width, - height*yy);
    }
    else
    {
      cairo_line_to(cr, xx*width, - height*c->draw_ys[k]);
    }
  }
  cairo_stroke(cr);

finally:
  cairo_destroy(cr);
  cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget));
  cairo_set_source_surface (cr_pixmap, cst, 0, 0);
  cairo_paint(cr_pixmap);
  cairo_destroy(cr_pixmap);
  cairo_surface_destroy(cst);
  return TRUE;
}
void draw_background(LoadGraph *g) {
	double dash[2] = { 1.0, 2.0 };
	cairo_t *cr;
	guint i;
	unsigned num_bars;
	char *caption;
	cairo_text_extents_t extents;

	num_bars = g->num_bars();
	g->graph_dely = (g->draw_height - 15) / num_bars; /* round to int to avoid AA blur */
	g->real_draw_height = g->graph_dely * num_bars;
	g->graph_delx = (g->draw_width - 2.0 - g->rmargin - g->indent) / (LoadGraph::NUM_POINTS - 3);
	g->graph_buffer_offset = (int) (1.5 * g->graph_delx) + FRAME_WIDTH ;

	g->background = gdk_pixmap_new (GDK_DRAWABLE (g->disp->window),
					g->disp->allocation.width,
					g->disp->allocation.height,
					-1);
	cr = gdk_cairo_create (g->background);
	
	// set the background colour
	GtkStyle *style = gtk_widget_get_style (ProcData::get_instance()->notebook);
	gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
	cairo_paint (cr);

	/* draw frame */
	cairo_translate (cr, FRAME_WIDTH, FRAME_WIDTH);
	
	/* Draw background rectangle */
	cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
	cairo_rectangle (cr, g->rmargin + g->indent, 0,
			 g->draw_width - g->rmargin - g->indent, g->real_draw_height);
	cairo_fill(cr);
	
	cairo_set_line_width (cr, 1.0);
	cairo_set_dash (cr, dash, 2, 0);
	cairo_set_font_size (cr, g->fontsize);

	for (i = 0; i <= num_bars; ++i) {
		double y;

		if (i == 0)
			y = 0.5 + g->fontsize / 2.0;
		else if (i == num_bars)
			y = i * g->graph_dely + 0.5;
		else
			y = i * g->graph_dely + g->fontsize / 2.0;

		gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]);
		if (g->type == LOAD_GRAPH_NET) {
			// operation orders matters so it's 0 if i == num_bars
			unsigned rate = g->net.max - (i * g->net.max / num_bars);
			const std::string caption(procman::format_rate(rate, g->net.max));
			cairo_text_extents (cr, caption.c_str(), &extents);
			cairo_move_to (cr, g->indent - extents.width + 20, y);
			cairo_show_text (cr, caption.c_str());
		} else {
			// operation orders matters so it's 0 if i == num_bars
			caption = g_strdup_printf("%d %%", 100 - i * (100 / num_bars));
			cairo_text_extents (cr, caption, &extents);
			cairo_move_to (cr, g->indent - extents.width + 20, y);
			cairo_show_text (cr, caption);
			g_free (caption);
		}

		cairo_set_source_rgba (cr, 0, 0, 0, 0.75);
		cairo_move_to (cr, g->rmargin + g->indent - 3, i * g->graph_dely + 0.5);
		cairo_line_to (cr, g->draw_width - 0.5, i * g->graph_dely + 0.5);
	}
	cairo_stroke (cr);

	cairo_set_dash (cr, dash, 2, 1.5);

	const unsigned total_seconds = g->speed * (LoadGraph::NUM_POINTS - 2) / 1000;

	for (unsigned int i = 0; i < 7; i++) {
		double x = (i) * (g->draw_width - g->rmargin - g->indent) / 6;
		cairo_set_source_rgba (cr, 0, 0, 0, 0.75);
		cairo_move_to (cr, (ceil(x) + 0.5) + g->rmargin + g->indent, 0.5);
		cairo_line_to (cr, (ceil(x) + 0.5) + g->rmargin + g->indent, g->real_draw_height + 4.5);
		cairo_stroke(cr);
		unsigned seconds = total_seconds - i * total_seconds / 6;
		const char* format;
		if (i == 0)
			format = dngettext(GETTEXT_PACKAGE, "%u second", "%u seconds", seconds);
		else
			format = "%u";
		caption = g_strdup_printf(format, seconds);
		cairo_text_extents (cr, caption, &extents);
		cairo_move_to (cr, ((ceil(x) + 0.5) + g->rmargin + g->indent) - (extents.width/2), g->draw_height);
		gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]);
		cairo_show_text (cr, caption);
		g_free (caption);
	}

	cairo_stroke (cr);
	cairo_destroy (cr);
}
Example #22
0
static gboolean
dt_iop_basecurve_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
  dt_iop_module_t *self = (dt_iop_module_t *)user_data;
  dt_iop_basecurve_gui_data_t *c = (dt_iop_basecurve_gui_data_t *)self->gui_data;
  dt_iop_basecurve_params_t *p = (dt_iop_basecurve_params_t *)self->params;

  int nodes = p->basecurve_nodes[0];
  dt_iop_basecurve_node_t *basecurve = p->basecurve[0];
  if(c->minmax_curve_type != p->basecurve_type[0] || c->minmax_curve_nodes != p->basecurve_nodes[0])
  {
    dt_draw_curve_destroy(c->minmax_curve);
    c->minmax_curve = dt_draw_curve_new(0.0, 1.0, p->basecurve_type[0]);
    c->minmax_curve_nodes = p->basecurve_nodes[0];
    c->minmax_curve_type = p->basecurve_type[0];
    for(int k=0; k<p->basecurve_nodes[0]; k++)
      (void)dt_draw_curve_add_point(c->minmax_curve, p->basecurve[0][k].x, p->basecurve[0][k].y);
  }
  else
  {
    for(int k=0; k<p->basecurve_nodes[0]; k++)
      dt_draw_curve_set_point(c->minmax_curve, k, p->basecurve[0][k].x, p->basecurve[0][k].y);
  }
  dt_draw_curve_t *minmax_curve = c->minmax_curve;
  dt_draw_curve_calc_values(minmax_curve, 0.0, 1.0, DT_IOP_TONECURVE_RES, c->draw_xs, c->draw_ys);

  const float xm = basecurve[nodes-1].x;
  const float x[4] = {0.7f*xm, 0.8f*xm, 0.9f*xm, 1.0f*xm};
  const float y[4] = {c->draw_ys[CLAMP((int)(x[0]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)],
                      c->draw_ys[CLAMP((int)(x[1]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)],
                      c->draw_ys[CLAMP((int)(x[2]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)],
                      c->draw_ys[CLAMP((int)(x[3]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)]
                     };
  float unbounded_coeffs[3];
  dt_iop_estimate_exp(x, y, 4, unbounded_coeffs);

  const int inset = DT_GUI_CURVE_EDITOR_INSET;
  int width = widget->allocation.width, height = widget->allocation.height;
  cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  cairo_t *cr = cairo_create(cst);
  // clear bg
  cairo_set_source_rgb (cr, .2, .2, .2);
  cairo_paint(cr);

  cairo_translate(cr, inset, inset);
  width -= 2*inset;
  height -= 2*inset;

#if 0
  // draw shadow around
  float alpha = 1.0f;
  for(int k=0; k<inset; k++)
  {
    cairo_rectangle(cr, -k, -k, width + 2*k, height + 2*k);
    cairo_set_source_rgba(cr, 0, 0, 0, alpha);
    alpha *= 0.6f;
    cairo_fill(cr);
  }
#else
  cairo_set_line_width(cr, 1.0);
  cairo_set_source_rgb (cr, .1, .1, .1);
  cairo_rectangle(cr, 0, 0, width, height);
  cairo_stroke(cr);
#endif

  cairo_set_source_rgb (cr, .3, .3, .3);
  cairo_rectangle(cr, 0, 0, width, height);
  cairo_fill(cr);

#if 1
  // draw grid
  cairo_set_line_width(cr, .4);
  cairo_set_source_rgb (cr, .1, .1, .1);
  dt_draw_grid(cr, 4, 0, 0, width, height);

  // draw nodes positions
  cairo_set_line_width(cr, 1.);
  cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
  cairo_translate(cr, 0, height);

  for(int k=0; k<nodes; k++)
  {
    cairo_arc(cr, basecurve[k].x*width, -basecurve[k].y*height, 3, 0, 2.*M_PI);
    cairo_stroke(cr);
  }

  // draw selected cursor
  cairo_set_line_width(cr, 1.);

  if(c->selected >= 0)
  {
    cairo_set_source_rgb(cr, .9, .9, .9);
    cairo_arc(cr, basecurve[c->selected].x*width, -basecurve[c->selected].y*height, 4, 0, 2.*M_PI);
    cairo_stroke(cr);
  }

  // draw curve
  cairo_set_line_width(cr, 2.);
  cairo_set_source_rgb(cr, .9, .9, .9);
  // cairo_set_line_cap  (cr, CAIRO_LINE_CAP_SQUARE);
  cairo_move_to(cr, 0, -height*c->draw_ys[0]);
  for(int k=1; k<DT_IOP_TONECURVE_RES; k++)
  {
    const float xx = k/(DT_IOP_TONECURVE_RES-1.0);
    if(xx > xm)
    {
      const float yy = dt_iop_eval_exp(unbounded_coeffs, xx);
      cairo_line_to(cr, xx*width, - height*yy);
    }
    else
    {
      cairo_line_to(cr, xx*width, - height*c->draw_ys[k]);
    }
  }
  cairo_stroke(cr);

  cairo_destroy(cr);
  cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget));
  cairo_set_source_surface (cr_pixmap, cst, 0, 0);
  cairo_paint(cr_pixmap);
  cairo_destroy(cr_pixmap);
  cairo_surface_destroy(cst);
  return TRUE;
#endif
}