Example #1
0
void application_draw(cairo_t *cr, int width, int height)
// draw onto the main window using cairo
// width is the actual width of the main window
// height is the actual height of the main window

#define FIELD_SIZE		20
#define CIRCLE_RADIUS	6

{	
	int i,x, y, pin, xNum, xLabel, xWiringPi;
	char str[16];
	
	// printf("application_draw called\n");
	
	// set the backgrond color
	cairo_rectangle(cr, 0.0, 0.0, width, height);
	cairo_set_source_rgb(cr, 0.93, 0.93, 0.93);
	cairo_fill(cr);
	
	cairo_set_font_size(cr, 11);
	cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
	
	cairo_set_line_width (cr, 1);
	cairo_rectangle (cr, width / 2 - (9 * FIELD_SIZE),
		12, 18 * FIELD_SIZE, 22 * FIELD_SIZE);
		
	y = 26;
	x = (width / 2) - ((3 * FIELD_SIZE) / 2);
	cairo_move_to(cr, x, y);
	cairo_show_text(cr, "pi-gpio");
	
	x = (width / 2) - ((18 * FIELD_SIZE) / 2) + 6;
	cairo_move_to(cr, x, y);
	cairo_show_text(cr, "wirPi");

	x = (width / 2) - ((11 * FIELD_SIZE) / 2) - 6;
	cairo_move_to(cr, x, y);
	cairo_show_text(cr, "pin name");
	
	x = (width / 2) + ((7 * FIELD_SIZE) / 2) - 6;
	cairo_move_to(cr, x, y);
	cairo_show_text(cr, "pin name");
	
	x = (width / 2) + ((14 * FIELD_SIZE) / 2) + 4;
	cairo_move_to(cr, x, y);
	cairo_show_text(cr, "wirPi");
		
	cairo_move_to(cr, width / 2 - (9 * FIELD_SIZE), 12 + FIELD_SIZE);
	cairo_line_to(cr, width / 2 + (9 * FIELD_SIZE), 12 + FIELD_SIZE);
	
	cairo_move_to(cr, width / 2 - (7 * FIELD_SIZE), 12);
	cairo_line_to(cr, width / 2 - (7 * FIELD_SIZE), 12 + (22 * FIELD_SIZE));
	
	cairo_move_to(cr, width / 2 - (2 * FIELD_SIZE), 12);
	cairo_line_to(cr, width / 2 - (2 * FIELD_SIZE), 12 + (22 * FIELD_SIZE));
	
	cairo_move_to(cr, width / 2 + (2 * FIELD_SIZE), 12);
	cairo_line_to(cr, width / 2 + (2 * FIELD_SIZE), 12 + (22 * FIELD_SIZE));
	
	cairo_move_to(cr, width / 2 + (7 * FIELD_SIZE), 12);
	cairo_line_to(cr, width / 2 + (7 * FIELD_SIZE), 12 + (22 * FIELD_SIZE));
		
	for (pin = 1; pin <= 40; pin++) {
		
		if (pin % 2) {
			x = (width / 2) - (FIELD_SIZE / 2);
			xNum = x - FIELD_SIZE - 6;
			xLabel = x - (6 * FIELD_SIZE) - 6;
			xWiringPi = (width / 2) - ((18 * FIELD_SIZE) / 2) + 12;
		}
		else {
			x = (width / 2) + (FIELD_SIZE / 2);
			xNum = x + FIELD_SIZE - 8;
			xLabel = x + (2 * FIELD_SIZE) - 2;
			xWiringPi = (width / 2) + ((14 * FIELD_SIZE) / 2) + 12;
		}
		
		y = FIELD_SIZE + 12 + (((pin + 1) / 2) * FIELD_SIZE);
		cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
		cairo_move_to(cr, xNum, y + 4);
		sprintf(str, "%2d", pin);
		cairo_show_text(cr, str);
		
		cairo_stroke (cr);
		
		cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);    // black
		cairo_move_to(cr, x + CIRCLE_RADIUS, y);
		cairo_arc(cr, x, y, CIRCLE_RADIUS, 0, 2 * M_PI);
		if (pinConfig[pin].value) {
			cairo_stroke_preserve(cr);
			cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);    // fill red
			cairo_fill(cr);
		}
		else if (pinConfig[pin].wiringPiPin >= 0) {
			cairo_stroke_preserve(cr);
			cairo_set_source_rgb(cr, 0.5, 0.0, 0.0);    // fill dark red
			cairo_fill(cr);
		}
		cairo_stroke (cr);
		
		
		if (pinConfig[pin].wiringPiPin >= 0)
			cairo_set_source_rgb(cr, 0.0, 0.5, 0.0);    // dark green
		else
			cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);    // black
		
		cairo_move_to(cr, xLabel, y + 4);
		cairo_show_text(cr, pinConfig[pin].name);
		if (pinConfig[pin].wiringPiPin >= 0) {
			sprintf(str, "%2d", pinConfig[pin].wiringPiPin);
			cairo_move_to(cr, xWiringPi, y + 4);
		    cairo_show_text(cr, str);
		}
	}
	cairo_stroke (cr);

}
Example #2
0
static gboolean _lib_histogram_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data)
{
  dt_lib_module_t *self = (dt_lib_module_t *)user_data;
  dt_lib_histogram_t *d = (dt_lib_histogram_t *)self->data;

  dt_develop_t *dev = darktable.develop;
  uint32_t *hist = dev->histogram;
  float hist_max = dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR ? dev->histogram_max
                                                                  : logf(1.0 + dev->histogram_max);
  const int inset = DT_HIST_INSET;
  GtkAllocation allocation;
  gtk_widget_get_allocation(widget, &allocation);
  int width = allocation.width, height = allocation.height;
  cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  cairo_t *cr = cairo_create(cst);

  gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0, allocation.width, allocation.height);

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

  if(d->mode_x == 0)
  {
    d->color_w = 0.06 * width;
    d->button_spacing = 0.01 * width;
    d->button_h = 0.06 * width;
    d->button_y = d->button_spacing;
    d->mode_w = d->color_w;
    d->mode_x = width - 3 * (d->color_w + d->button_spacing) - (d->mode_w + d->button_spacing);
    d->red_x = width - 3 * (d->color_w + d->button_spacing);
    d->green_x = width - 2 * (d->color_w + d->button_spacing);
    d->blue_x = width - (d->color_w + d->button_spacing);
  }

  // TODO: probably this should move to the configure-event callback! That would be future proof if we ever
  // (again) allow to resize the side panels.
  const gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);

  // this code assumes that the first expose comes before the first (preview) pipe is processed and that the
  // size of the widget doesn't change!
  if(dev->histogram_waveform_width == 0)
  {
    dev->histogram_waveform = (uint32_t *)calloc(height * stride / 4, sizeof(uint32_t));
    dev->histogram_waveform_stride = stride;
    dev->histogram_waveform_height = height;
    dev->histogram_waveform_width = width;
    //     return TRUE; // there are enough expose events following ...
  }

#if 1
  // draw shadow around
  float alpha = 1.0f;
  cairo_set_line_width(cr, 0.2);
  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.5f;
    cairo_fill(cr);
  }
  cairo_set_line_width(cr, 1.0);
#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_rectangle(cr, 0, 0, width, height);
  cairo_clip(cr);

  cairo_set_source_rgb(cr, .3, .3, .3);
  cairo_rectangle(cr, 0, 0, width, height);
  cairo_fill(cr);
  if(d->highlight == 1)
  {
    cairo_set_source_rgb(cr, .5, .5, .5);
    cairo_rectangle(cr, 0, 0, .2 * width, height);
    cairo_fill(cr);
  }
  else if(d->highlight == 2)
  {
    cairo_set_source_rgb(cr, .5, .5, .5);
    cairo_rectangle(cr, 0.2 * width, 0, width, height);
    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(hist_max > 0.0f)
  {
    cairo_save(cr);
    if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM)
    {
      // make the color channel selector work:
      uint8_t *buf = (uint8_t *)malloc(sizeof(uint8_t) * height * stride);
      uint8_t mask[3] = { d->blue, d->green, d->red };
      memcpy(buf, dev->histogram_waveform, sizeof(uint8_t) * height * stride);
      for(int y = 0; y < height; y++)
        for(int x = 0; x < width; x++)
          for(int k = 0; k < 3; k++)
          {
            buf[y * stride + x * 4 + k] *= mask[k];
          }

      cairo_surface_t *source
          = cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32, width, height, stride);

      cairo_set_source_surface(cr, source, 0.0, 0.0);
      cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
      cairo_paint(cr);
      cairo_surface_destroy(source);
      free(buf);
    }
    else
    {
      // cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
      cairo_translate(cr, 0, height);
      cairo_scale(cr, width / 63.0, -(height - 10) / hist_max);
      cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
      // cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
      cairo_set_line_width(cr, 1.);
      if(d->red)
      {
        cairo_set_source_rgba(cr, 1., 0., 0., 0.2);
        dt_draw_histogram_8(cr, hist, 0, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR);
      }
      if(d->green)
      {
        cairo_set_source_rgba(cr, 0., 1., 0., 0.2);
        dt_draw_histogram_8(cr, hist, 1, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR);
      }
      if(d->blue)
      {
        cairo_set_source_rgba(cr, 0., 0., 1., 0.2);
        dt_draw_histogram_8(cr, hist, 2, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR);
      }
      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
      // cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
    }
    cairo_restore(cr);
  }

  cairo_set_source_rgb(cr, .25, .25, .25);
  cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
  PangoLayout *layout;
  PangoRectangle ink;
  PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc);
  pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
  layout = pango_cairo_create_layout(cr);
  pango_font_description_set_absolute_size(desc, .1 * height * PANGO_SCALE);
  pango_layout_set_font_description(layout, desc);

  char exifline[50];
  dt_image_print_exif(&dev->image_storage, exifline, 50);
  pango_layout_set_text(layout, exifline, -1);
  pango_layout_get_pixel_extents(layout, &ink, NULL);
  cairo_move_to(cr, .02 * width, .98 * height - ink.height - ink.y);
  cairo_save(cr);
  cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0));
  cairo_set_source_rgba(cr, 1, 1, 1, 0.3);
  pango_cairo_layout_path(cr, layout);
  cairo_stroke_preserve(cr);
  cairo_set_source_rgb(cr, .25, .25, .25);
  cairo_fill(cr);
  cairo_restore(cr);

  // buttons to control the display of the histogram: linear/log, r, g, b
  if(d->highlight != 0)
  {
    _draw_mode_toggle(cr, d->mode_x, d->button_y, d->mode_w, d->button_h, dev->histogram_type);
    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.4);
    _draw_color_toggle(cr, d->red_x, d->button_y, d->color_w, d->button_h, d->red);
    cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.4);
    _draw_color_toggle(cr, d->green_x, d->button_y, d->color_w, d->button_h, d->green);
    cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.4);
    _draw_color_toggle(cr, d->blue_x, d->button_y, d->color_w, d->button_h, d->blue);
  }

  cairo_destroy(cr);
  cairo_set_source_surface(crf, cst, 0, 0);
  cairo_paint(crf);
  cairo_surface_destroy(cst);
  pango_font_description_free(desc);
  g_object_unref(layout);
  return TRUE;
}
Example #3
0
static gboolean _lib_navigation_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
  dt_lib_module_t *self = (dt_lib_module_t *)user_data;
  dt_lib_navigation_t *d = (dt_lib_navigation_t *)self->data;

  const int inset = DT_NAVIGATION_INSET;
  GtkAllocation allocation;
  gtk_widget_get_allocation(widget, &allocation);
  int width = allocation.width, height = allocation.height;

  dt_develop_t *dev = darktable.develop;

  if(dev->preview_status != DT_DEV_PIXELPIPE_VALID) return FALSE;

  /* get the current style */
  GtkStyle *style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL, "GtkWidget", GTK_TYPE_WIDGET);
  if(!style) style = gtk_rc_get_style(widget);
  cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  cairo_t *cr = cairo_create(cst);

  /* fill background */
  cairo_set_source_rgb(cr, style->bg[0].red / 65535.0, style->bg[0].green / 65535.0,
                       style->bg[0].blue / 65535.0);
  cairo_paint(cr);

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

  /* draw navigation image if available */
  if(dev->preview_pipe->backbuf && (dev->preview_status == DT_DEV_PIXELPIPE_VALID))
  {
    dt_pthread_mutex_t *mutex = &dev->preview_pipe->backbuf_mutex;
    dt_pthread_mutex_lock(mutex);
    const int wd = dev->preview_pipe->backbuf_width;
    const int ht = dev->preview_pipe->backbuf_height;
    const float scale = fminf(width / (float)wd, height / (float)ht);

    const int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wd);
    cairo_surface_t *surface
        = cairo_image_surface_create_for_data(dev->preview_pipe->backbuf, CAIRO_FORMAT_RGB24, wd, ht, stride);
    cairo_translate(cr, width / 2.0, height / 2.0f);
    cairo_scale(cr, scale, scale);
    cairo_translate(cr, -.5f * wd, -.5f * ht);

    // draw shadow around
    float alpha = 1.0f;
    for(int k = 0; k < 4; k++)
    {
      cairo_rectangle(cr, -k / scale, -k / scale, wd + 2 * k / scale, ht + 2 * k / scale);
      cairo_set_source_rgba(cr, 0, 0, 0, alpha);
      alpha *= 0.6f;
      cairo_fill(cr);
    }

    cairo_rectangle(cr, 0, 0, wd - 2, ht - 1);
    cairo_set_source_surface(cr, surface, 0, 0);
    cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST);
    cairo_fill(cr);
    cairo_surface_destroy(surface);

    dt_pthread_mutex_unlock(mutex);

    // draw box where we are
    dt_dev_zoom_t zoom = dt_control_get_dev_zoom();
    int closeup = dt_control_get_dev_closeup();
    float zoom_x = dt_control_get_dev_zoom_x();
    float zoom_y = dt_control_get_dev_zoom_y();
    const float min_scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, closeup ? 2.0 : 1.0, 0);
    const float cur_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0);
    // avoid numerical instability for small resolutions:
    double h, w;
    if(cur_scale > min_scale)
    {
      float boxw = 1, boxh = 1;
      dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, &boxw, &boxh);

      cairo_translate(cr, wd * (.5f + zoom_x), ht * (.5f + zoom_y));
      cairo_set_source_rgb(cr, 0., 0., 0.);
      cairo_set_line_width(cr, 1.f / scale);
      boxw *= wd;
      boxh *= ht;
      cairo_rectangle(cr, -boxw / 2 - 1, -boxh / 2 - 1, boxw + 2, boxh + 2);
      cairo_stroke(cr);
      cairo_set_source_rgb(cr, 1., 1., 1.);
      cairo_rectangle(cr, -boxw / 2, -boxh / 2, boxw, boxh);
      cairo_stroke(cr);
    }
    if(fabsf(cur_scale - min_scale) > 0.001f)
    {
      /* Zoom % */
      cairo_identity_matrix(cr);
      cairo_translate(cr, 0, height);
      cairo_set_source_rgba(cr, 1., 1., 1., 0.5);
      cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
      cairo_set_font_size(cr, DT_PIXEL_APPLY_DPI(11));

      char zoomline[5];
      snprintf(zoomline, sizeof(zoomline), "%.0f%%", cur_scale * 100);

      cairo_text_extents_t ext;
      cairo_text_extents(cr, zoomline, &ext);
      h = d->zoom_h = ext.height;
      w = d->zoom_w = ext.width;

      cairo_move_to(cr, width - w - h * 1.1, 0);

      cairo_save(cr);
      cairo_set_line_width(cr, 2.0);
      cairo_set_source_rgb(cr, style->bg[0].red / 65535.0, style->bg[0].green / 65535.0,
                           style->bg[0].blue / 65535.0);
      cairo_text_path(cr, zoomline);
      cairo_stroke_preserve(cr);
      cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
      cairo_fill(cr);
      cairo_restore(cr);
    }
    else
    {
      // draw the zoom-to-fit icon
      cairo_identity_matrix(cr);
      cairo_translate(cr, 0, height);
      cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
      cairo_text_extents_t ext;
      cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
      cairo_set_font_size(cr, DT_PIXEL_APPLY_DPI(11));
      cairo_text_extents(cr, "100%", &ext); // dummy text, just to get the height
      h = d->zoom_h = ext.height;
      w = h * 1.5;
      float sp = h * 0.6;
      d->zoom_w = w + sp;

      cairo_move_to(cr, width - w - h - sp, -1.0 * h);
      cairo_rectangle(cr, width - w - h - sp, -1.0 * h, w, h);
      cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
      cairo_fill(cr);

      cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
      cairo_move_to(cr, width - w * 0.8 - h - sp, -1.0 * h);
      cairo_line_to(cr, width - w - h - sp, -1.0 * h);
      cairo_line_to(cr, width - w - h - sp, -0.7 * h);
      cairo_stroke(cr);
      cairo_move_to(cr, width - w - h - sp, -0.3 * h);
      cairo_line_to(cr, width - w - h - sp, 0);
      cairo_line_to(cr, width - w * 0.8 - h - sp, 0);
      cairo_stroke(cr);
      cairo_move_to(cr, width - w * 0.2 - h - sp, 0);
      cairo_line_to(cr, width - h - sp, 0);
      cairo_line_to(cr, width - h - sp, -0.3 * h);
      cairo_stroke(cr);
      cairo_move_to(cr, width - h - sp, -0.7 * h);
      cairo_line_to(cr, width - h - sp, -1.0 * h);
      cairo_line_to(cr, width - w * 0.2 - h - sp, -1.0 * h);
      cairo_stroke(cr);
    }

    cairo_move_to(cr, width - 0.95 * h, -0.9 * h);
    cairo_line_to(cr, width - 0.05 * h, -0.9 * h);
    cairo_line_to(cr, width - 0.5 * h, -0.1 * h);
    cairo_fill(cr);
  }

  /* blit memsurface into widget */
  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;
}
Example #4
0
static void
polygon_view_draw (PolygonView *self, cairo_t *cr)
{
    polygon_t *polygon;
    gdouble sf_x, sf_y, sf;
    gdouble mid, dim;
    gdouble x0,  y0;
    box_t extents;

    extents = self->extents;

    mid = (extents.p2.x + extents.p1.x) / 2.;
    dim = (extents.p2.x - extents.p1.x) / 2. * 1.25;
    sf_x = self->widget.allocation.width / dim / 2;

    mid = (extents.p2.y + extents.p1.y) / 2.;
    dim = (extents.p2.y - extents.p1.y) / 2. * 1.25;
    sf_y = self->widget.allocation.height / dim / 2;

    sf = MIN (sf_x, sf_y);

    mid = (extents.p2.x + extents.p1.x) / 2.;
    dim = sf_x / sf * (extents.p2.x - extents.p1.x) / 2. * 1.25;
    x0 = mid - dim;
    mid = (extents.p2.y + extents.p1.y) / 2.;
    dim = sf_y / sf * (extents.p2.y - extents.p1.y) / 2. * 1.25;
    y0 = mid - dim;

    if (self->pixmap_width != self->widget.allocation.width ||
	self->pixmap_height != self->widget.allocation.height)
    {
	cairo_surface_destroy (self->pixmap);
	self->pixmap = pixmap_create (self, cairo_get_target (cr));
	self->pixmap_width = self->widget.allocation.width;
	self->pixmap_height = self->widget.allocation.height;
    }

    cairo_set_source_surface (cr, self->pixmap, 0, 0);
    cairo_paint (cr);

    if (self->polygons == NULL)
	return;

    /* draw a zoom view of the area around the mouse */
    if (1) {
	double zoom = self->mag_zoom;
	int size = self->mag_size;
	int mag_x = self->mag_x;
	int mag_y = self->mag_y;

	if (1) {
	    if (self->px + size < self->widget.allocation.width/2)
		mag_x = self->px + size/4;
	    else
		mag_x = self->px - size/4 - size;
	    mag_y = self->py - size/2;
	    if (mag_y < 0)
		mag_y = 0;
	    if (mag_y + size > self->widget.allocation.height)
		mag_y = self->widget.allocation.height - size;
	}

	cairo_save (cr); {
	    /* bottom right */
	    cairo_rectangle (cr, mag_x, mag_y, size, size);
	    cairo_stroke_preserve (cr);
	    cairo_set_source_rgb (cr, 1, 1, 1);
	    cairo_fill_preserve (cr);
	    cairo_clip (cr);

	    /* compute roi in extents */
	    cairo_translate (cr, mag_x + size/2, mag_y + size/2);

	    cairo_save (cr); {
		cairo_scale (cr, zoom, zoom);
		cairo_translate (cr, -(self->px / sf + x0), -(self->py /sf + y0));
		for (polygon = self->polygons; polygon; polygon = polygon->next) {
		    if (polygon->num_edges == 0)
			continue;

		    draw_polygon (cr, polygon, zoom);
		}

		if (highlight != -1) {
		    cairo_move_to (cr, extents.p1.x, highlight);
		    cairo_line_to (cr, extents.p2.x, highlight);
		    cairo_set_source_rgb (cr, 0, .7, 0);
		    cairo_save (cr);
		    cairo_identity_matrix (cr);
		    cairo_set_line_width (cr, 1.);
		    cairo_stroke (cr);
		    cairo_restore (cr);
		}
	    } cairo_restore (cr);

	    /* grid */
	    cairo_save (cr); {
		int i;

		cairo_translate (cr,
				 -zoom*fmod (self->px/sf + x0, 1.),
				 -zoom*fmod (self->py/sf + y0, 1.));
		zoom /= 2;
		for (i = -size/2/zoom; i <= size/2/zoom + 1; i+=2) {
		    cairo_move_to (cr, zoom*i, -size/2);
		    cairo_line_to (cr, zoom*i, size/2 + zoom);
		    cairo_move_to (cr, -size/2, zoom*i);
		    cairo_line_to (cr, size/2 + zoom, zoom*i);
		}
		zoom *= 2;
		cairo_set_source_rgba (cr, .7, .7, .7, .5);
		cairo_set_line_width (cr, 1.);
		cairo_stroke (cr);

		for (i = -size/2/zoom - 1; i <= size/2/zoom + 1; i++) {
		    cairo_move_to (cr, zoom*i, -size/2);
		    cairo_line_to (cr, zoom*i, size/2 + zoom);
		    cairo_move_to (cr, -size/2, zoom*i);
		    cairo_line_to (cr, size/2 + zoom, zoom*i);
		}
		cairo_set_source_rgba (cr, .1, .1, .1, .5);
		cairo_set_line_width (cr, 2.);
		cairo_stroke (cr);
	    } cairo_restore (cr);

	} cairo_restore (cr);
    }
}
Example #5
0
void gfxContext::Stroke()
{
    cairo_stroke_preserve(mCairo);
}
Example #6
0
/*
    This file is part of darktable,
    copyright (c) 2009--2011 johannes hanika.
    copyright (c) 2012 tobias ellinghaus.
    copyright (c) 2014 henrik andersson.

    darktable is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    darktable is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with darktable.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "bauhaus/bauhaus.h"
#include "common/camera_control.h"
#include "common/darktable.h"
#include "common/image_cache.h"
#include "common/mipmap_cache.h"
#include "control/conf.h"
#include "control/control.h"
#include "control/jobs.h"
#include "dtgtk/button.h"
#include "gui/accelerators.h"
#include "gui/gtk.h"
#include "gui/guides.h"
#include "libs/lib.h"
#include "libs/lib_api.h"
#include <gdk/gdkkeysyms.h>

typedef enum dt_lib_live_view_flip_t
{
  FLAG_FLIP_NONE = 0,
  FLAG_FLIP_HORIZONTAL = 1<<0,
  FLAG_FLIP_VERTICAL = 1<<1,
  FLAG_FLIP_BOTH = FLAG_FLIP_HORIZONTAL|FLAG_FLIP_VERTICAL
} dt_lib_live_view_flip_t;

typedef enum dt_lib_live_view_overlay_t
{
  OVERLAY_NONE = 0,
  OVERLAY_SELECTED,
  OVERLAY_ID
} dt_lib_live_view_overlay_t;

#define HANDLE_SIZE 0.02

static const cairo_operator_t _overlay_modes[] = {
  CAIRO_OPERATOR_OVER, CAIRO_OPERATOR_XOR, CAIRO_OPERATOR_ADD, CAIRO_OPERATOR_SATURATE
#if(CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0))
  ,
  CAIRO_OPERATOR_MULTIPLY, CAIRO_OPERATOR_SCREEN, CAIRO_OPERATOR_OVERLAY, CAIRO_OPERATOR_DARKEN,
  CAIRO_OPERATOR_LIGHTEN, CAIRO_OPERATOR_COLOR_DODGE, CAIRO_OPERATOR_COLOR_BURN, CAIRO_OPERATOR_HARD_LIGHT,
  CAIRO_OPERATOR_SOFT_LIGHT, CAIRO_OPERATOR_DIFFERENCE, CAIRO_OPERATOR_EXCLUSION, CAIRO_OPERATOR_HSL_HUE,
  CAIRO_OPERATOR_HSL_SATURATION, CAIRO_OPERATOR_HSL_COLOR, CAIRO_OPERATOR_HSL_LUMINOSITY
#endif
};

DT_MODULE(1)

typedef struct dt_lib_live_view_t
{
  int imgid;
  int splitline_rotation;
  double overlay_x0, overlay_x1, overlay_y0, overlay_y1;
  double splitline_x, splitline_y; // 0..1
  gboolean splitline_dragging;

  GtkWidget *live_view, *live_view_zoom, *rotate_ccw, *rotate_cw, *flip;
  GtkWidget *focus_out_small, *focus_out_big, *focus_in_small, *focus_in_big;
  GtkWidget *guide_selector, *flip_guides, *guides_widgets;
  GList *guides_widgets_list;
  GtkWidget *overlay, *overlay_id_box, *overlay_id, *overlay_mode, *overlay_splitline;
} dt_lib_live_view_t;

static void guides_presets_set_visibility(dt_lib_live_view_t *lib, int which)
{
  if(which == 0)
  {
    gtk_widget_set_no_show_all(lib->guides_widgets, TRUE);
    gtk_widget_hide(lib->guides_widgets);
    gtk_widget_set_no_show_all(lib->flip_guides, TRUE);
    gtk_widget_hide(lib->flip_guides);
  }
  else
  {
    GtkWidget *widget = g_list_nth_data(lib->guides_widgets_list, which - 1);
    if(widget)
    {
      gtk_widget_set_no_show_all(lib->guides_widgets, FALSE);
      gtk_widget_show_all(lib->guides_widgets);
      gtk_stack_set_visible_child(GTK_STACK(lib->guides_widgets), widget);
    }
    else
    {
      gtk_widget_set_no_show_all(lib->guides_widgets, TRUE);
      gtk_widget_hide(lib->guides_widgets);
    }
    gtk_widget_set_no_show_all(lib->flip_guides, FALSE);
    gtk_widget_show_all(lib->flip_guides);
  }

  // TODO: add a support_flip flag to guides to hide the flip gui?
}

static void guides_presets_changed(GtkWidget *combo, dt_lib_live_view_t *lib)
{
  int which = dt_bauhaus_combobox_get(combo);
  guides_presets_set_visibility(lib, which);
}

static void overlay_changed(GtkWidget *combo, dt_lib_live_view_t *lib)
{
  int which = dt_bauhaus_combobox_get(combo);
  if(which == OVERLAY_NONE)
  {
    gtk_widget_set_visible(GTK_WIDGET(lib->overlay_mode), FALSE);
    gtk_widget_set_visible(GTK_WIDGET(lib->overlay_splitline), FALSE);
  }
  else
  {
    gtk_widget_set_visible(GTK_WIDGET(lib->overlay_mode), TRUE);
    gtk_widget_set_visible(GTK_WIDGET(lib->overlay_splitline), TRUE);
  }

  if(which == OVERLAY_ID)
    gtk_widget_set_visible(GTK_WIDGET(lib->overlay_id_box), TRUE);
  else
    gtk_widget_set_visible(GTK_WIDGET(lib->overlay_id_box), FALSE);
}


const char *name(dt_lib_module_t *self)
{
  return _("live view");
}

const char **views(dt_lib_module_t *self)
{
  static const char *v[] = {"tethering", NULL};
  return v;
}

uint32_t container(dt_lib_module_t *self)
{
  return DT_UI_CONTAINER_PANEL_RIGHT_CENTER;
}


void gui_reset(dt_lib_module_t *self)
{
}

int position()
{
  return 998;
}

void init_key_accels(dt_lib_module_t *self)
{
  dt_accel_register_lib(self, NC_("accel", "toggle live view"), GDK_KEY_v, 0);
  dt_accel_register_lib(self, NC_("accel", "zoom live view"), GDK_KEY_z, 0);
  dt_accel_register_lib(self, NC_("accel", "rotate 90 degrees CCW"), 0, 0);
  dt_accel_register_lib(self, NC_("accel", "rotate 90 degrees CW"), 0, 0);
  dt_accel_register_lib(self, NC_("accel", "flip horizontally"), 0, 0);
  dt_accel_register_lib(self, NC_("accel", "move focus point in (big steps)"), 0, 0);
  dt_accel_register_lib(self, NC_("accel", "move focus point in (small steps)"), 0, 0);
  dt_accel_register_lib(self, NC_("accel", "move focus point out (small steps)"), 0, 0);
  dt_accel_register_lib(self, NC_("accel", "move focus point out (big steps)"), 0, 0);
}

void connect_key_accels(dt_lib_module_t *self)
{
  dt_lib_live_view_t *lib = (dt_lib_live_view_t *)self->data;

  dt_accel_connect_button_lib(self, "toggle live view", GTK_WIDGET(lib->live_view));
  dt_accel_connect_button_lib(self, "zoom live view", GTK_WIDGET(lib->live_view_zoom));
  dt_accel_connect_button_lib(self, "rotate 90 degrees CCW", GTK_WIDGET(lib->rotate_ccw));
  dt_accel_connect_button_lib(self, "rotate 90 degrees CW", GTK_WIDGET(lib->rotate_cw));
  dt_accel_connect_button_lib(self, "flip horizontally", GTK_WIDGET(lib->flip));
  dt_accel_connect_button_lib(self, "move focus point in (big steps)", GTK_WIDGET(lib->focus_in_big));
  dt_accel_connect_button_lib(self, "move focus point in (small steps)", GTK_WIDGET(lib->focus_in_small));
  dt_accel_connect_button_lib(self, "move focus point out (small steps)", GTK_WIDGET(lib->focus_out_small));
  dt_accel_connect_button_lib(self, "move focus point out (big steps)", GTK_WIDGET(lib->focus_out_big));
}

static void _rotate_ccw(GtkWidget *widget, gpointer user_data)
{
  dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera;
  cam->live_view_rotation = (cam->live_view_rotation + 1) % 4; // 0 -> 1 -> 2 -> 3 -> 0 -> ...
}

static void _rotate_cw(GtkWidget *widget, gpointer user_data)
{
  dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera;
  cam->live_view_rotation = (cam->live_view_rotation + 3) % 4; // 0 -> 3 -> 2 -> 1 -> 0 -> ...
}

// Congratulations to Simon for being the first one recognizing live view in a screen shot ^^
static void _toggle_live_view_clicked(GtkWidget *widget, gpointer user_data)
{
  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) == TRUE)
  {
    if(dt_camctl_camera_start_live_view(darktable.camctl) == FALSE)
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
  }
  else
  {
    dt_camctl_camera_stop_live_view(darktable.camctl);
  }
}

// TODO: using a toggle button would be better, but this setting can also be changed by right clicking on the
// canvas (src/views/capture.c).
//       maybe using a signal would work? i have no idea.
static void _zoom_live_view_clicked(GtkWidget *widget, gpointer user_data)
{
  dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera;
  if(cam->is_live_viewing)
  {
    cam->live_view_zoom = !cam->live_view_zoom;
    if(cam->live_view_zoom == TRUE)
      dt_camctl_camera_set_property_string(darktable.camctl, NULL, "eoszoom", "5");
    else
      dt_camctl_camera_set_property_string(darktable.camctl, NULL, "eoszoom", "1");
  }
}

static void _focus_button_clicked(GtkWidget *widget, gpointer user_data)
{
  int focus = GPOINTER_TO_INT(user_data);
  dt_camctl_camera_set_property_choice(darktable.camctl, NULL, "manualfocusdrive", focus);
}

static void _toggle_flip_clicked(GtkWidget *widget, gpointer user_data)
{
  dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera;
  cam->live_view_flip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
}

static void _overlay_id_changed(GtkWidget *widget, gpointer user_data)
{
  dt_lib_live_view_t *lib = (dt_lib_live_view_t *)user_data;
  lib->imgid = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
  dt_conf_set_int("plugins/lighttable/live_view/overlay_imgid", lib->imgid);
}

static void _overlay_mode_changed(GtkWidget *combo, gpointer user_data)
{
  dt_conf_set_int("plugins/lighttable/live_view/overlay_mode", dt_bauhaus_combobox_get(combo));
}

static void _overlay_splitline_changed(GtkWidget *combo, gpointer user_data)
{
  dt_conf_set_int("plugins/lighttable/live_view/splitline", dt_bauhaus_combobox_get(combo));
}

void gui_init(dt_lib_module_t *self)
{
  self->data = calloc(1, sizeof(dt_lib_live_view_t));

  // Setup lib data
  dt_lib_live_view_t *lib = self->data;
  lib->splitline_x = lib->splitline_y = 0.5;

  // Setup gui
  self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
  dt_gui_add_help_link(self->widget, "live_view.html#live_view");
  GtkWidget *box;

  box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), box, TRUE, TRUE, 0);
  lib->live_view = dtgtk_togglebutton_new(dtgtk_cairo_paint_eye, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER, NULL);
  lib->live_view_zoom = dtgtk_button_new(
      dtgtk_cairo_paint_zoom, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER, NULL); // TODO: see _zoom_live_view_clicked
  lib->rotate_ccw = dtgtk_button_new(dtgtk_cairo_paint_refresh, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER, NULL);
  lib->rotate_cw = dtgtk_button_new(dtgtk_cairo_paint_refresh,
                                    CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_UP, NULL);
  lib->flip = dtgtk_togglebutton_new(dtgtk_cairo_paint_flip,
                                     CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_UP, NULL);

  gtk_box_pack_start(GTK_BOX(box), lib->live_view, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), lib->live_view_zoom, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), lib->rotate_ccw, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), lib->rotate_cw, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), lib->flip, TRUE, TRUE, 0);

  gtk_widget_set_tooltip_text(lib->live_view, _("toggle live view"));
  gtk_widget_set_tooltip_text(lib->live_view_zoom, _("zoom live view"));
  gtk_widget_set_tooltip_text(lib->rotate_ccw, _("rotate 90 degrees ccw"));
  gtk_widget_set_tooltip_text(lib->rotate_cw, _("rotate 90 degrees cw"));
  gtk_widget_set_tooltip_text(lib->flip, _("flip live view horizontally"));

  g_signal_connect(G_OBJECT(lib->live_view), "clicked", G_CALLBACK(_toggle_live_view_clicked), lib);
  g_signal_connect(G_OBJECT(lib->live_view_zoom), "clicked", G_CALLBACK(_zoom_live_view_clicked), lib);
  g_signal_connect(G_OBJECT(lib->rotate_ccw), "clicked", G_CALLBACK(_rotate_ccw), lib);
  g_signal_connect(G_OBJECT(lib->rotate_cw), "clicked", G_CALLBACK(_rotate_cw), lib);
  g_signal_connect(G_OBJECT(lib->flip), "clicked", G_CALLBACK(_toggle_flip_clicked), lib);

  // focus buttons
  box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), box, TRUE, TRUE, 0);
  lib->focus_in_big = dtgtk_button_new(dtgtk_cairo_paint_solid_triangle,
                                       CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_LEFT, NULL);
  lib->focus_in_small
      = dtgtk_button_new(dtgtk_cairo_paint_arrow, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER
                                                  | CPF_DIRECTION_LEFT, NULL); // TODO icon not centered
  lib->focus_out_small = dtgtk_button_new(dtgtk_cairo_paint_arrow, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER
                                                                   | CPF_DIRECTION_RIGHT, NULL); // TODO same here
  lib->focus_out_big = dtgtk_button_new(dtgtk_cairo_paint_solid_triangle,
                                        CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_RIGHT, NULL);

  gtk_box_pack_start(GTK_BOX(box), lib->focus_in_big, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), lib->focus_in_small, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), lib->focus_out_small, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), lib->focus_out_big, TRUE, TRUE, 0);

  gtk_widget_set_tooltip_text(lib->focus_in_big, _("move focus point in (big steps)"));
  gtk_widget_set_tooltip_text(lib->focus_in_small, _("move focus point in (small steps)"));
  gtk_widget_set_tooltip_text(lib->focus_out_small, _("move focus point out (small steps)"));
  gtk_widget_set_tooltip_text(lib->focus_out_big, _("move focus point out (big steps)"));

  // Near 3
  g_signal_connect(G_OBJECT(lib->focus_in_big), "clicked", G_CALLBACK(_focus_button_clicked),
                   GINT_TO_POINTER(2));
  // Near 1
  g_signal_connect(G_OBJECT(lib->focus_in_small), "clicked", G_CALLBACK(_focus_button_clicked),
                   GINT_TO_POINTER(0));
  // Far 1
  g_signal_connect(G_OBJECT(lib->focus_out_small), "clicked", G_CALLBACK(_focus_button_clicked),
                   GINT_TO_POINTER(4));
  // Far 3
  g_signal_connect(G_OBJECT(lib->focus_out_big), "clicked", G_CALLBACK(_focus_button_clicked),
                   GINT_TO_POINTER(6));

  // Guides
  lib->guide_selector = dt_bauhaus_combobox_new(NULL);
  dt_bauhaus_widget_set_label(lib->guide_selector, NULL, _("guides"));
  gtk_box_pack_start(GTK_BOX(self->widget), lib->guide_selector, TRUE, TRUE, 0);

  lib->guides_widgets = gtk_stack_new();
  gtk_stack_set_homogeneous(GTK_STACK(lib->guides_widgets), FALSE);
  gtk_box_pack_start(GTK_BOX(self->widget), lib->guides_widgets, TRUE, TRUE, 0);

  dt_bauhaus_combobox_add(lib->guide_selector, _("none"));
  int i = 0;
  for(GList *iter = darktable.guides; iter; iter = g_list_next(iter), i++)
  {
    GtkWidget *widget = NULL;
    dt_guides_t *guide = (dt_guides_t *)iter->data;
    dt_bauhaus_combobox_add(lib->guide_selector, _(guide->name));
    if(guide->widget)
    {
      // generate some unique name so that we can have the same name several times
      char name[5];
      snprintf(name, sizeof(name), "%d", i);
      widget = guide->widget(NULL, guide->user_data);
      gtk_widget_show_all(widget);
      gtk_stack_add_named(GTK_STACK(lib->guides_widgets), widget, name);
    }
    lib->guides_widgets_list = g_list_append(lib->guides_widgets_list, widget);
  }
  gtk_widget_set_no_show_all(lib->guides_widgets, TRUE);

  gtk_widget_set_tooltip_text(lib->guide_selector, _("display guide lines to help compose your photograph"));
  g_signal_connect(G_OBJECT(lib->guide_selector), "value-changed", G_CALLBACK(guides_presets_changed), lib);

  lib->flip_guides = dt_bauhaus_combobox_new(NULL);
  dt_bauhaus_widget_set_label(lib->flip_guides, NULL, _("flip"));
  dt_bauhaus_combobox_add(lib->flip_guides, _("none"));
  dt_bauhaus_combobox_add(lib->flip_guides, _("horizontally"));
  dt_bauhaus_combobox_add(lib->flip_guides, _("vertically"));
  dt_bauhaus_combobox_add(lib->flip_guides, _("both"));
  gtk_widget_set_tooltip_text(lib->flip_guides, _("flip guides"));
  gtk_box_pack_start(GTK_BOX(self->widget), lib->flip_guides, TRUE, TRUE, 0);

  lib->overlay = dt_bauhaus_combobox_new(NULL);
  dt_bauhaus_widget_set_label(lib->overlay, NULL, _("overlay"));
  dt_bauhaus_combobox_add(lib->overlay, _("none"));
  dt_bauhaus_combobox_add(lib->overlay, _("selected image"));
  dt_bauhaus_combobox_add(lib->overlay, _("id"));
  gtk_widget_set_tooltip_text(lib->overlay, _("overlay another image over the live view"));
  g_signal_connect(G_OBJECT(lib->overlay), "value-changed", G_CALLBACK(overlay_changed), lib);
  gtk_box_pack_start(GTK_BOX(self->widget), lib->overlay, TRUE, TRUE, 0);

  lib->overlay_id_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
  GtkWidget *label = gtk_label_new(_("image id"));
  gtk_widget_set_halign(label, GTK_ALIGN_START);
  lib->overlay_id = gtk_spin_button_new_with_range(0, 1000000000, 1);
  gtk_spin_button_set_digits(GTK_SPIN_BUTTON(lib->overlay_id), 0);
  gtk_widget_set_tooltip_text(lib->overlay_id, _("enter image id of the overlay manually"));
  g_signal_connect(G_OBJECT(lib->overlay_id), "value-changed", G_CALLBACK(_overlay_id_changed), lib);
  gtk_spin_button_set_value(GTK_SPIN_BUTTON(lib->overlay_id),
                            dt_conf_get_int("plugins/lighttable/live_view/overlay_imgid"));
  gtk_box_pack_start(GTK_BOX(lib->overlay_id_box), label, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(lib->overlay_id_box), lib->overlay_id, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), lib->overlay_id_box, TRUE, TRUE, 0);
  gtk_widget_show(lib->overlay_id);
  gtk_widget_show(label);

  lib->overlay_mode = dt_bauhaus_combobox_new(NULL);
  dt_bauhaus_widget_set_label(lib->overlay_mode, NULL, _("overlay mode"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "normal"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "xor"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "add"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "saturate"));
#if(CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0))
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "multiply"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "screen"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "overlay"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "darken"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "lighten"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "color dodge"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "color burn"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "hard light"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "soft light"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "difference"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "exclusion"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "HSL hue"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "HSL saturation"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "HSL color"));
  dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "HSL luminosity"));
#endif
  gtk_widget_set_tooltip_text(lib->overlay_mode, _("mode of the overlay"));
  dt_bauhaus_combobox_set(lib->overlay_mode, dt_conf_get_int("plugins/lighttable/live_view/overlay_mode"));
  g_signal_connect(G_OBJECT(lib->overlay_mode), "value-changed", G_CALLBACK(_overlay_mode_changed), lib);
  gtk_box_pack_start(GTK_BOX(self->widget), lib->overlay_mode, TRUE, TRUE, 0);

  lib->overlay_splitline = dt_bauhaus_combobox_new(NULL);
  dt_bauhaus_widget_set_label(lib->overlay_splitline, NULL, _("split line"));
  dt_bauhaus_combobox_add(lib->overlay_splitline, _("off"));
  dt_bauhaus_combobox_add(lib->overlay_splitline, _("on"));
  gtk_widget_set_tooltip_text(lib->overlay_splitline, _("only draw part of the overlay"));
  dt_bauhaus_combobox_set(lib->overlay_splitline, dt_conf_get_int("plugins/lighttable/live_view/splitline"));
  g_signal_connect(G_OBJECT(lib->overlay_splitline), "value-changed", G_CALLBACK(_overlay_splitline_changed),
                   lib);
  gtk_box_pack_start(GTK_BOX(self->widget), lib->overlay_splitline, TRUE, TRUE, 0);

  gtk_widget_set_visible(GTK_WIDGET(lib->overlay_mode), FALSE);
  gtk_widget_set_visible(GTK_WIDGET(lib->overlay_id_box), FALSE);
  gtk_widget_set_visible(GTK_WIDGET(lib->overlay_splitline), FALSE);

  gtk_widget_set_no_show_all(GTK_WIDGET(lib->overlay_mode), TRUE);
  gtk_widget_set_no_show_all(GTK_WIDGET(lib->overlay_id_box), TRUE);
  gtk_widget_set_no_show_all(GTK_WIDGET(lib->overlay_splitline), TRUE);

  guides_presets_set_visibility(lib, 0);
}

void gui_cleanup(dt_lib_module_t *self)
{
  // dt_lib_live_view_t *lib = self->data;

  // g_list_free(lib->guides_widgets_list);
  // INTENTIONAL. it's supposed to be leaky until lua is fixed.

  free(self->data);
  self->data = NULL;
}

void view_enter(struct dt_lib_module_t *self,struct dt_view_t *old_view,struct dt_view_t *new_view)
{
  // disable buttons that won't work with this camera
  // TODO: initialize tethering mode outside of libs/camera.s so we can use darktable.camctl->active_camera
  // here
  dt_lib_live_view_t *lib = self->data;
  const dt_camera_t *cam = darktable.camctl->active_camera;
  if(cam == NULL) cam = darktable.camctl->wanted_camera;

  gboolean sensitive = cam && cam->can_live_view_advanced;

  gtk_widget_set_sensitive(lib->live_view_zoom, sensitive);
  gtk_widget_set_sensitive(lib->focus_in_big, sensitive);
  gtk_widget_set_sensitive(lib->focus_in_small, sensitive);
  gtk_widget_set_sensitive(lib->focus_out_big, sensitive);
  gtk_widget_set_sensitive(lib->focus_out_small, sensitive);
}

// TODO: find out where the zoom window is and draw overlay + grid accordingly
#define MARGIN 20
#define BAR_HEIGHT 18 /* see libs/camera.c */
void gui_post_expose(dt_lib_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx,
                     int32_t pointery)
{
  dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera;
  dt_lib_live_view_t *lib = self->data;

  if(cam->is_live_viewing == FALSE || cam->live_view_zoom == TRUE) return;

  dt_pthread_mutex_lock(&cam->live_view_pixbuf_mutex);
  if(GDK_IS_PIXBUF(cam->live_view_pixbuf) == FALSE)
  {
    dt_pthread_mutex_unlock(&cam->live_view_pixbuf_mutex);
    return;
  }
  double w = width - (MARGIN * 2.0f);
  double h = height - (MARGIN * 2.0f) - BAR_HEIGHT;
  gint pw = gdk_pixbuf_get_width(cam->live_view_pixbuf);
  gint ph = gdk_pixbuf_get_height(cam->live_view_pixbuf);
  lib->overlay_x0 = lib->overlay_x1 = lib->overlay_y0 = lib->overlay_y1 = 0.0;

  gboolean use_splitline = (dt_bauhaus_combobox_get(lib->overlay_splitline) == 1);

  // OVERLAY
  int imgid = 0;
  switch(dt_bauhaus_combobox_get(lib->overlay))
  {
    case OVERLAY_SELECTED:
      imgid = dt_view_tethering_get_selected_imgid(darktable.view_manager);
      break;
    case OVERLAY_ID:
      imgid = lib->imgid;
      break;
  }
  if(imgid > 0)
  {
    cairo_save(cr);
    const dt_image_t *img = dt_image_cache_testget(darktable.image_cache, imgid, 'r');
    // if the user points at this image, we really want it:
    if(!img) img = dt_image_cache_get(darktable.image_cache, imgid, 'r');

    const float imgwd = 0.97f;
    dt_mipmap_buffer_t buf;
    dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size(darktable.mipmap_cache, imgwd * w, imgwd * h);
    dt_mipmap_cache_get(darktable.mipmap_cache, &buf, imgid, mip, 0, 'r');

    float scale = 1.0;
    cairo_surface_t *surface = NULL;
    if(buf.buf)
    {
      const int32_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, buf.width);
      surface = cairo_image_surface_create_for_data(buf.buf, CAIRO_FORMAT_RGB24, buf.width,
                                                    buf.height, stride);
      scale = fminf(fminf(w, pw) / (float)buf.width, fminf(h, ph) / (float)buf.height);
    }

    // draw centered and fitted:
    cairo_translate(cr, width / 2.0, (height + BAR_HEIGHT) / 2.0f);
    cairo_scale(cr, scale, scale);

    if(buf.buf)
    {
      cairo_translate(cr, -.5f * buf.width, -.5f * buf.height);

      if(use_splitline)
      {
        double x0, y0, x1, y1;
        switch(lib->splitline_rotation)
        {
          case 0:
            x0 = 0.0;
            y0 = 0.0;
            x1 = buf.width * lib->splitline_x;
            y1 = buf.height;
            break;
          case 1:
            x0 = 0.0;
            y0 = 0.0;
            x1 = buf.width;
            y1 = buf.height * lib->splitline_y;
            break;
          case 2:
            x0 = buf.width * lib->splitline_x;
            y0 = 0.0;
            x1 = buf.width;
            y1 = buf.height;
            break;
          case 3:
            x0 = 0.0;
            y0 = buf.height * lib->splitline_y;
            x1 = buf.width;
            y1 = buf.height;
            break;
          default:
            fprintf(stderr, "OMFG, the world will collapse, this shouldn't be reachable!\n");
            dt_pthread_mutex_unlock(&cam->live_view_pixbuf_mutex);
            return;
        }

        cairo_rectangle(cr, x0, y0, x1, y1);
        cairo_clip(cr);
      }

      cairo_set_source_surface(cr, surface, 0, 0);
      // set filter no nearest:
      // in skull mode, we want to see big pixels.
      // in 1 iir mode for the right mip, we want to see exactly what the pipe gave us, 1:1 pixel for pixel.
      // in between, filtering just makes stuff go unsharp.
      if((buf.width <= 8 && buf.height <= 8) || fabsf(scale - 1.0f) < 0.01f)
        cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
      cairo_rectangle(cr, 0, 0, buf.width, buf.height);
      int overlay_modes_index = dt_bauhaus_combobox_get(lib->overlay_mode);
      if(overlay_modes_index >= 0)
      {
        cairo_operator_t mode = _overlay_modes[overlay_modes_index];
        cairo_set_operator(cr, mode);
      }
      cairo_fill(cr);
      cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
      cairo_surface_destroy(surface);
    }
    cairo_restore(cr);
    if(buf.buf) dt_mipmap_cache_release(darktable.mipmap_cache, &buf);
    if(img) dt_image_cache_read_release(darktable.image_cache, img);

    // ON CANVAS CONTROLS
    if(use_splitline)
    {
      scale = fminf(1.0, fminf(w / pw, h / ph));

      // image coordinates
      lib->overlay_x0 = 0.5 * (width - pw * scale);
      lib->overlay_y0 = 0.5 * (height - ph * scale + BAR_HEIGHT);
      lib->overlay_x1 = lib->overlay_x0 + pw * scale;
      lib->overlay_y1 = lib->overlay_y0 + ph * scale;

      // splitline position to absolute coords:
      double sl_x = lib->overlay_x0 + lib->splitline_x * pw * scale;
      double sl_y = lib->overlay_y0 + lib->splitline_y * ph * scale;

      int x0 = sl_x, y0 = 0.0, x1 = x0, y1 = height;
      if(lib->splitline_rotation % 2 != 0)
      {
        x0 = 0.0;
        y0 = sl_y;
        x1 = width;
        y1 = y0;
      }
      gboolean mouse_over_control = (lib->splitline_rotation % 2 == 0) ? (fabs(sl_x - pointerx) < 5)
                                                                       : (fabs(sl_y - pointery) < 5);
      cairo_save(cr);
      cairo_set_source_rgb(cr, .7, .7, .7);
      cairo_set_line_width(cr, (mouse_over_control ? 2.0 : 0.5));

      cairo_move_to(cr, x0, y0);
      cairo_line_to(cr, x1, y1);
      cairo_stroke(cr);

      /* if mouse over control lets draw center rotate control, hide if split is dragged */
      if(!lib->splitline_dragging && mouse_over_control)
      {
        cairo_set_line_width(cr, 0.5);
        double s = width * HANDLE_SIZE;
        dtgtk_cairo_paint_refresh(cr, sl_x - (s * 0.5), sl_y - (s * 0.5), s, s, 1, NULL);
      }

      cairo_restore(cr);
    }
  }

  // GUIDES
  if(cam->live_view_rotation % 2 == 1)
  {
    gint tmp = pw;
    pw = ph;
    ph = tmp;
  }
  float scale = 1.0;
  //   if(cam->live_view_zoom == FALSE)
  //   {
  if(pw > w) scale = w / pw;
  if(ph > h) scale = fminf(scale, h / ph);
  //   }
  double sw = scale * pw;
  double sh = scale * ph;

  // draw guides
  int guide_flip = dt_bauhaus_combobox_get(lib->flip_guides);
  double left = (width - sw) * 0.5;
  double top = (height + BAR_HEIGHT - sh) * 0.5;

  double dashes = 5.0;

  cairo_save(cr);
  cairo_rectangle(cr, left, top, sw, sh);
  cairo_clip(cr);
  cairo_set_dash(cr, &dashes, 1, 0);

  // Move coordinates to local center selection.
  cairo_translate(cr, (sw / 2 + left), (sh / 2 + top));

  // Flip horizontal.
  if(guide_flip & FLAG_FLIP_HORIZONTAL) cairo_scale(cr, -1, 1);
  // Flip vertical.
  if(guide_flip & FLAG_FLIP_VERTICAL) cairo_scale(cr, 1, -1);

  int which = dt_bauhaus_combobox_get(lib->guide_selector);
  dt_guides_t *guide = (dt_guides_t *)g_list_nth_data(darktable.guides, which - 1);
  if(guide)
  {
    guide->draw(cr, -sw / 2, -sh / 2, sw, sh, 1.0, guide->user_data);
    cairo_stroke_preserve(cr);
    cairo_set_dash(cr, &dashes, 0, 0);
    cairo_set_source_rgba(cr, .3, .3, .3, .8);
    cairo_stroke(cr);
  }
  cairo_restore(cr);
  dt_pthread_mutex_unlock(&cam->live_view_pixbuf_mutex);
}
Example #7
0
/*
 * BackgroundLayer::render
 *
 * Render the background to the tab bar, also render the tab bar animation
 *
 */
void
BackgroundLayer::render ()
{
    cairo_t         *cr;
    int             twidth, theight, radius;
    int             borderWidth;
    float           r, g, b, a;
    double          x0, y0, x1, y1;

    GROUP_SCREEN (screen);

    if (!HAS_TOP_WIN (mGroup) || !mCairo)
	return;

    /* Dimentions are the tab bar's region */
    twidth = mGroup->mTabBar->mRegion.boundingRect ().width ();
    theight = mGroup->mTabBar->mRegion.boundingRect ().height ();
    radius = gs->optionGetBorderRadius ();

    /* Do not draw more than the tab bar width */
    if (twidth > width ())
	twidth = width ();

    /* Border radius should not exceed
     * half of the tab bar height */
    if (radius > twidth / 2)
	radius = twidth / 2;

    cr = mCairo;

    /* Clear the layer */
    clear ();

    /* Draw the border around the tab bar */

    borderWidth = gs->optionGetBorderWidth ();
    cairo_set_line_width (cr, borderWidth);

    cairo_save (cr);

    /* Move to the center of where we want to draw the line */
    x0 = borderWidth / 2.0f;
    y0 = borderWidth / 2.0f;
    /* The center of where we want to draw the opposite line */
    x1 = twidth  - borderWidth / 2.0f;
    y1 = theight - borderWidth / 2.0f;
    cairo_move_to (cr, x0 + radius, y0);

    /* Arc the top right corner */
    cairo_arc (cr, x1 - radius, y0 + radius, radius, M_PI * 1.5, M_PI * 2.0);
    /* Arc the bottom right corner */
    cairo_arc (cr, x1 - radius, y1 - radius, radius, 0.0, M_PI * 0.5);
    /* Arc the bottom left corner */
    cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI * 0.5, M_PI);
    /* Arc the top left corner */
    cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI, M_PI * 1.5);

    cairo_close_path  (cr);

    /* There are 5 different tab styles here:
     * Simple: draws a simple filled rect
     * Gradient: left to right gradient between base and highlight
     * Glass: left to right gradient, stopping at 60% and drawing a shadow
     * Metal: base -> highlight -> base gradient
     * Murrina: draws an arc between the two corners blending base and highlight
     */
    switch (gs->optionGetTabStyle ()) {
    case GroupOptions::TabStyleSimple:
	{
	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_set_source_rgba (cr, r, g, b, a);

    	    cairo_fill_preserve (cr);
	    break;
	}

    case GroupOptions::TabStyleGradient:
	{
	    /* fill */
	    cairo_pattern_t *pattern;
	    pattern = cairo_pattern_create_linear (0, 0, twidth, theight);

	    /* highlight color */
	    r = gs->optionGetTabHighlightColorRed () / 65535.0f;
	    g = gs->optionGetTabHighlightColorGreen () / 65535.0f;
	    b = gs->optionGetTabHighlightColorBlue () / 65535.0f;
	    a = gs->optionGetTabHighlightColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill_preserve (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case GroupOptions::TabStyleGlass:
	{
	    cairo_pattern_t *pattern;

	    cairo_save (cr);

	    /* clip width rounded rectangle */
	    cairo_clip (cr);

	    /* ===== HIGHLIGHT ===== */

	    /* make draw the shape for the highlight and
	       create a pattern for it */
	    cairo_rectangle (cr, 0, 0, twidth, theight / 2);
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* highlight color */
	    r = gs->optionGetTabHighlightColorRed () / 65535.0f;
	    g = gs->optionGetTabHighlightColorGreen () / 65535.0f;
	    b = gs->optionGetTabHighlightColorBlue () / 65535.0f;
	    a = gs->optionGetTabHighlightColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.6f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    /* ==== SHADOW ===== */

	    /* make draw the shape for the show and create a pattern for it */
	    cairo_rectangle (cr, 0, theight / 2, twidth, theight);
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (gs->optionGetTabHighlightColorRed () +
		 gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f);
	    g = (gs->optionGetTabHighlightColorGreen () +
		 gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f);
	    b = (gs->optionGetTabHighlightColorBlue () +
		 gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f);
	    a = (gs->optionGetTabHighlightColorAlpha () +
		 gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.5f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    cairo_restore (cr);

	    /* draw shape again for the outline */
	    cairo_move_to (cr, x0 + radius, y0);
	    cairo_arc (cr, x1 - radius, y0 + radius,
		       radius, M_PI * 1.5, M_PI * 2.0);
	    cairo_arc (cr, x1 - radius, y1 - radius,
		       radius, 0.0, M_PI * 0.5);
	    cairo_arc (cr, x0 + radius, y1 - radius,
		       radius, M_PI * 0.5, M_PI);
	    cairo_arc (cr, x0 + radius, y0 + radius,
		       radius, M_PI, M_PI * 1.5);

	    break;
	}

    case GroupOptions::TabStyleMetal:
	{
	    /* fill */
	    cairo_pattern_t *pattern;
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* base color #1 */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* highlight color */
	    r = gs->optionGetTabHighlightColorRed () / 65535.0f;
	    g = gs->optionGetTabHighlightColorGreen () / 65535.0f;
	    b = gs->optionGetTabHighlightColorBlue () / 65535.0f;
	    a = gs->optionGetTabHighlightColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.55f, r, g, b, a);

	    /* base color #2 */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);
	    cairo_fill_preserve (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case GroupOptions::TabStyleMurrina:
	{
	    double          ratio, transX;
	    cairo_pattern_t *pattern;

	    cairo_save (cr);

	    /* clip width rounded rectangle */
	    cairo_clip_preserve (cr);

	    /* ==== TOP ==== */

	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = twidth  - borderWidth / 2.0;
	    y1 = theight - borderWidth / 2.0;
	    radius = (y1 - y0) / 2;

	    /* setup pattern */
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (gs->optionGetTabHighlightColorRed () +
		 gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f);
	    g = (gs->optionGetTabHighlightColorGreen () +
		 gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f);
	    b = (gs->optionGetTabHighlightColorBlue () +
		 gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f);
	    a = (gs->optionGetTabHighlightColorAlpha () +
		 gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* highlight color */
	    r = gs->optionGetTabHighlightColorRed () / 65535.0f;
	    g = gs->optionGetTabHighlightColorGreen () / 65535.0f;
	    b = gs->optionGetTabHighlightColorBlue () / 65535.0f;
	    a = gs->optionGetTabHighlightColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_source (cr, pattern);

	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);

	    /* ==== BOTTOM ===== */

	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = twidth  - borderWidth / 2.0;
	    y1 = theight - borderWidth / 2.0;
	    radius = (y1 - y0) / 2;

	    ratio = (double)twidth / (double)theight;
	    transX = twidth - (twidth * ratio);

	    cairo_move_to (cr, x1, y1);
	    cairo_line_to (cr, x1, y0);
	    if (twidth < theight)
	    {
		cairo_translate (cr, transX, 0);
		cairo_scale (cr, ratio, 1.0);
	    }
	    cairo_arc (cr, x1 - radius, y0, radius, 0.0, M_PI * 0.5);
	    if (twidth < theight)
	    {
		cairo_scale (cr, 1.0 / ratio, 1.0);
		cairo_translate (cr, -transX, 0);
		cairo_scale (cr, ratio, 1.0);
	    }
	    cairo_arc_negative (cr, x0 + radius, y1,
				radius, M_PI * 1.5, M_PI);
	    cairo_close_path (cr);

	    /* setup pattern */
	    pattern = cairo_pattern_create_linear (0, 0, 0, theight);

	    /* base color */
	    r = gs->optionGetTabBaseColorRed () / 65535.0f;
	    g = gs->optionGetTabBaseColorGreen () / 65535.0f;
	    b = gs->optionGetTabBaseColorBlue () / 65535.0f;
	    a = gs->optionGetTabBaseColorAlpha () / 65535.0f;
	    cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);

	    /* we don't want to use a full highlight here
	       so we mix the colors */
	    r = (gs->optionGetTabHighlightColorRed () +
		 gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f);
	    g = (gs->optionGetTabHighlightColorGreen () +
		 gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f);
	    b = (gs->optionGetTabHighlightColorBlue () +
		 gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f);
	    a = (gs->optionGetTabHighlightColorAlpha () +
		 gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f);
	    cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);

	    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_pattern_destroy (pattern);
	    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);

	    cairo_restore (cr);

	    /* draw shape again for the outline */
	    x0 = borderWidth / 2.0;
	    y0 = borderWidth / 2.0;
	    x1 = twidth  - borderWidth / 2.0;
	    y1 = theight - borderWidth / 2.0;
	    radius = gs->optionGetBorderRadius ();

	    cairo_move_to (cr, x0 + radius, y0);
	    cairo_arc (cr, x1 - radius, y0 + radius,
		       radius, M_PI * 1.5, M_PI * 2.0);
	    cairo_arc (cr, x1 - radius, y1 - radius,
		       radius, 0.0, M_PI * 0.5);
	    cairo_arc (cr, x0 + radius, y1 - radius,
		       radius, M_PI * 0.5, M_PI);
	    cairo_arc (cr, x0 + radius, y0 + radius,
		       radius, M_PI, M_PI * 1.5);

    	    break;
	}

    default:
	break;
    }

    /* outline */
    r = gs->optionGetTabBorderColorRed () / 65535.0f;
    g = gs->optionGetTabBorderColorGreen () / 65535.0f;
    b = gs->optionGetTabBorderColorBlue () / 65535.0f;
    a = gs->optionGetTabBorderColorAlpha () / 65535.0f;
    cairo_set_source_rgba (cr, r, g, b, a);

    /* If there is an animation running, stroke preserved
     * so that we can paint directly on top (and blend!)
     * the new animation with the existing tab bar.
     * Otherwise just stroke normally, this is less expensive
     */
    if (mBgAnimation != AnimationNone)
	cairo_stroke_preserve (cr);
    else
	cairo_stroke (cr);

    /* There are two animations here:
     * Pulse: Highlight tab bar in and out (used for tab hover)
     * Reflex: Paint a diagonal gradient moving from right to left
     *         on the tab bar when it appears
     */
    switch (mBgAnimation) {
    case AnimationPulse:
	{
	    double animationProgress;
	    double alpha;

	    /* Progress here is measured in the current time */
	    animationProgress = mBgAnimationTime /
		                (gs->optionGetPulseTime () * 1000.0);
	    /* The highlight pulsates in and out, so the alpha here should run
	     * on a sine wave */
	    alpha = sin ((2 * PI * animationProgress) - 1.55)*0.5 + 0.5;

	    /* If the alpha of the animation is < 0, don't bother painting */
	    if (alpha <= 0)
		break;

	    cairo_save (cr);
	    cairo_clip (cr);
	    /* Paint highlight over the tab bar */
	    cairo_set_operator (cr, CAIRO_OPERATOR_XOR);
	    cairo_rectangle (cr, 0.0, 0.0, twidth, theight);
	    cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha);
	    cairo_fill (cr);
	    cairo_restore (cr);
	    break;
	}

    case AnimationReflex:
	{
	    double          animationProgress;
	    double          reflexWidth;
	    double          posX, alpha;
	    cairo_pattern_t *pattern;

	    /* Progress is measured in current time */
	    animationProgress = mBgAnimationTime /
		                (gs->optionGetReflexTime () * 1000.0);
	    /* Position here is the tab bar width plus the reflection width * 2 */
	    reflexWidth = (mGroup->mTabBar->mSlots.size () / 2.0) * 30;
	    posX = (twidth + reflexWidth * 2.0) * animationProgress;
	    alpha = sin (PI * animationProgress) * 0.55;
	    if (alpha <= 0)
		break;

	    cairo_save (cr);
	    cairo_clip (cr);
	    pattern = cairo_pattern_create_linear (posX - reflexWidth,
						   0.0, posX, theight);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       0.0f, 1.0, 1.0, 1.0, 0.0);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       0.5f, 1.0, 1.0, 1.0, alpha);
	    cairo_pattern_add_color_stop_rgba (pattern,
					       1.0f, 1.0, 1.0, 1.0, 0.0);
	    cairo_rectangle (cr, 0.0, 0.0, twidth, theight);
	    cairo_set_source (cr, pattern);
	    cairo_fill (cr);
	    cairo_restore (cr);
	    cairo_pattern_destroy (pattern);
	    break;
	}

    case AnimationNone:
    default:
	break;
    }

    /* draw inner outline */
    cairo_move_to (cr, x0 + radius + 1.0, y0 + 1.0);
    cairo_arc (cr, x1 - radius - 1.0, y0 + radius + 1.0,
		radius, M_PI * 1.5, M_PI * 2.0);
    cairo_arc (cr, x1 - radius - 1.0, y1 - radius - 1.0,
		radius, 0.0, M_PI * 0.5);
    cairo_arc (cr, x0 + radius + 1.0, y1 - radius - 1.0,
		radius, M_PI * 0.5, M_PI);
    cairo_arc (cr, x0 + radius + 1.0, y0 + radius + 1.0,
		radius, M_PI, M_PI * 1.5);

    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.3);
    cairo_stroke(cr);

    cairo_restore (cr);

    mTexture = GLTexture::imageBufferToTexture ((char*) mBuffer,
			  		  (CompSize &) *this);
}
Example #8
0
void drawPie(cairo_t* c, int w, int h) {
	double w2  = w / 2.0f;
	double h2  = h / 2.0f;
	double r   = h2 * 0.8f;
	double seg = (2.0f * osg::PI) / 8.0f;
	double top = osg::PI + (osg::PI / 2.0f);

	// each "tier" or level or an arc
	double lvl[] = { 0.0f, 0.25f, 0.50f, 0.75f, 1.0f };

	const char* atts[] = {
		"Milk",
		"Horns",
		"Beefiness",
		"Moo/HR",
		"Grazing",
		"Sleeping",
		"Cowpower!",
		"s p o t s"
	};

	double attl[] = {
		0.25f,
		0.0f,
		0.50f,
		1.0f,
		0.0f,
		0.25f,
		0.75f,
		1.0f
	};

	cairo_set_line_width(c, ((w + h) / 2.0f) * 0.003f);
	cairo_select_font_face(c, "SegoeUI", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
	cairo_set_font_size(c, ((w + h) / 2.0f) * 0.05f);

	cairo_translate(c, w2, h2);
	cairo_rotate(c, -seg / 2.0f);
	cairo_set_source_rgba(c, 1.0f, 1.0f, 1.0f, 1.0f);

	for(unsigned int i = 0; i < 8; i++) {
		// Pick a random level...
		cairo_move_to(c, 0.0f, 0.0f);
		cairo_line_to(c, 0.0f, -r);
        	cairo_arc(c, 0.0f, 0.0f, attl[i] * r, top, top + seg);
		cairo_line_to(c, 0.0f, 0.0f);
		cairo_set_source_rgba(c, 0.2f, 0.8f, 0.2f, 0.5f);
		cairo_fill(c);
		cairo_set_source_rgba(c, 1.0f, 1.0f, 1.0f, 1.0f);

        	// Do the various levels...
		cairo_move_to(c, 0.0f, 0.0f);
		cairo_line_to(c, 0.0f, -r);
		cairo_stroke(c);

		for(unsigned int l = 0; l < 5; l++) {
			cairo_arc(c, 0.0f, 0.0f, lvl[l] * r, top, top + seg);
			cairo_stroke(c);
		}

		cairo_text_extents_t extents;

		cairo_text_extents(c, atts[i], &extents);

		double arcsize = r * seg;

		// ------------------------------------
		cairo_save(c);

		double tr = extents.width / r;
		double aa = ((arcsize - extents.width) / 2.0f) / r;

		cairo_arc(c, 0.0f, 0.0f, h2 * 0.85f, top + aa, top + aa + tr);
		cairo_set_tolerance(c, 0.01f);

		cairo_path_t* path = cairo_copy_path_flat(c);

		cairo_new_path(c);
		cairo_text_path(c, atts[i]);

		osgCairo::mapPathOnto(c, path);

		cairo_path_destroy(path);

		cairo_set_source_rgba(c, 1.0f, 1.0f, 1.0f, 1.0f);
		cairo_set_line_width(c, 1.0f);
        	cairo_stroke_preserve(c);
		cairo_set_source_rgba(c, 0.8f, 0.5f, 0.1f, 0.7f);
		cairo_fill(c);

		cairo_restore(c);
		// ------------------------------------

        	// Pick a random level...
		cairo_move_to(c, 0.0f, 0.0f);
		cairo_line_to(c, 0.0f, -r);
		cairo_arc(c, 0.0f, 0.0f, r, top, top + seg);
		cairo_line_to(c, 0.0f, 0.0f);
		cairo_set_source_rgba(c, 1.0f, 1.0f, 1.0f, 1.0f);
		cairo_stroke(c);

		cairo_rotate(c, seg);
	}
}
Example #9
0
void
dt_view_image_expose(
    dt_view_image_over_t *image_over,
    uint32_t imgid,
    cairo_t *cr,
    int32_t width,
    int32_t height,
    int32_t zoom,
    int32_t px,
    int32_t py)
{
  cairo_save (cr);
  float bgcol = 0.4, fontcol = 0.425, bordercol = 0.1, outlinecol = 0.2;
  int selected = 0, altered = 0, imgsel;
  DT_CTL_GET_GLOBAL(imgsel, lib_image_mouse_over_id);
  // if(img->flags & DT_IMAGE_SELECTED) selected = 1;

  /* clear and reset statements */
  DT_DEBUG_SQLITE3_CLEAR_BINDINGS(darktable.view_manager->statements.is_selected);
  DT_DEBUG_SQLITE3_CLEAR_BINDINGS(darktable.view_manager->statements.have_history);
  DT_DEBUG_SQLITE3_RESET(darktable.view_manager->statements.is_selected);
  DT_DEBUG_SQLITE3_RESET(darktable.view_manager->statements.have_history);

  /* bind imgid to prepared statments */
  DT_DEBUG_SQLITE3_BIND_INT(darktable.view_manager->statements.is_selected, 1, imgid);
  DT_DEBUG_SQLITE3_BIND_INT(darktable.view_manager->statements.have_history, 1, imgid); 

  /* lets check if imgid is selected */
  if(sqlite3_step(darktable.view_manager->statements.is_selected) == SQLITE_ROW) 
    selected = 1;

  /* lets check if imgid has history */
  if(sqlite3_step(darktable.view_manager->statements.have_history) == SQLITE_ROW) 
    altered = 1;
  
  const dt_image_t *img = dt_image_cache_read_testget(darktable.image_cache, imgid);
  if(selected == 1)
  {
    outlinecol = 0.4;
    bgcol = 0.6;
    fontcol = 0.5;
  }
  if(imgsel == imgid)
  {
    bgcol = 0.8;  // mouse over
    fontcol = 0.7;
    outlinecol = 0.6;
    // if the user points at this image, we really want it:
    if(!img)
      img = dt_image_cache_read_get(darktable.image_cache, imgid);
  }
  float imgwd = 0.90f;
  if(zoom == 1)
  {
    imgwd = .97f;
    // cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
  }
  else
  {
    double x0 = 1, y0 = 1, rect_width = width-2, rect_height = height-2, radius = 5;
    double x1, y1, off, off1;

    x1=x0+rect_width;
    y1=y0+rect_height;
    off=radius*0.666;
    off1 = radius-off;
    cairo_move_to  (cr, x0, y0 + radius);
    cairo_curve_to (cr, x0, y0+off1, x0+off1 , y0, x0 + radius, y0);
    cairo_line_to (cr, x1 - radius, y0);
    cairo_curve_to (cr, x1-off1, y0, x1, y0+off1, x1, y0 + radius);
    cairo_line_to (cr, x1 , y1 - radius);
    cairo_curve_to (cr, x1, y1-off1, x1-off1, y1, x1 - radius, y1);
    cairo_line_to (cr, x0 + radius, y1);
    cairo_curve_to (cr, x0+off1, y1, x0, y1-off1, x0, y1- radius);
    cairo_close_path (cr);
    cairo_set_source_rgb(cr, bgcol, bgcol, bgcol);
    cairo_fill_preserve(cr);
    cairo_set_line_width(cr, 0.005*width);
    cairo_set_source_rgb(cr, outlinecol, outlinecol, outlinecol);
    cairo_stroke(cr);

    if(img)
    {
      const char *ext = img->filename + strlen(img->filename);
      while(ext > img->filename && *ext != '.') ext--;
      ext++;
      cairo_set_source_rgb(cr, fontcol, fontcol, fontcol);
      cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
      cairo_set_font_size (cr, .25*width);

      cairo_move_to (cr, .01*width, .24*height);
      cairo_show_text (cr, ext);
    }
  }

  float scale = 1.0;
  dt_mipmap_buffer_t buf;
  dt_mipmap_size_t mip = 
    dt_mipmap_cache_get_matching_size(
      darktable.mipmap_cache,
      imgwd*width, imgwd*height);
  dt_mipmap_cache_read_get(
      darktable.mipmap_cache,
      &buf,
      imgid,
      mip,
      0);
  cairo_surface_t *surface = NULL;
  if(buf.buf)
  {
    const int32_t stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, buf.width);
    surface = cairo_image_surface_create_for_data (buf.buf, CAIRO_FORMAT_RGB24, buf.width, buf.height, stride);
    if(zoom == 1)
    {
      scale = fminf(
			 fminf(darktable.thumbnail_width, width) / (float)buf.width, 
			 fminf(darktable.thumbnail_height, height) / (float)buf.height
			 );
    }
    else scale = fminf(width*imgwd/(float)buf.width, height*imgwd/(float)buf.height);
  }

  // draw centered and fitted:
  cairo_save(cr);
  cairo_translate(cr, width/2.0, height/2.0f);
  cairo_scale(cr, scale, scale);

  if(buf.buf)
  {
    cairo_translate(cr, -.5f*buf.width, -.5f*buf.height);
    cairo_set_source_surface (cr, surface, 0, 0);
    if(buf.width <= 8 && buf.height <= 8)
      cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
    cairo_rectangle(cr, 0, 0, buf.width, buf.height);
    cairo_fill(cr);
    cairo_surface_destroy (surface);

    if(zoom == 1) cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BEST);
    cairo_rectangle(cr, 0, 0, buf.width, buf.height);
  }

  // border around image
  const float border = zoom == 1 ? 16/scale : 2/scale;
  cairo_set_source_rgb(cr, bordercol, bordercol, bordercol);
  if(buf.buf && selected)
  {
    cairo_set_line_width(cr, 1./scale);
    if(zoom == 1)
    {
      // draw shadow around border
      cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
      cairo_stroke(cr);
      // cairo_new_path(cr);
      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
      float alpha = 1.0f;
      for(int k=0; k<16; k++)
      {
        cairo_rectangle(cr, 0, 0, buf.width, buf.height);
        cairo_new_sub_path(cr);
        cairo_rectangle(cr, -k/scale, -k/scale, buf.width+2.*k/scale, buf.height+2.*k/scale);
        cairo_set_source_rgba(cr, 0, 0, 0, alpha);
        alpha *= 0.6f;
        cairo_fill(cr);
      }
    }
    else
    {
      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
      cairo_new_sub_path(cr);
      cairo_rectangle(cr, -border, -border, buf.width+2.*border, buf.height+2.*border);
      cairo_stroke_preserve(cr);
      cairo_set_source_rgb(cr, 1.0-bordercol, 1.0-bordercol, 1.0-bordercol);
      cairo_fill(cr);
    }
  }
  else if(buf.buf)
  {
    cairo_set_line_width(cr, 1);
    cairo_stroke(cr);
  }
  cairo_restore(cr);
  if(buf.buf)
    dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf);

  const float fscale = fminf(width, height);
  if(imgsel == imgid)
  {
    // draw mouseover hover effects, set event hook for mouse button down!
    *image_over = DT_VIEW_DESERT;
    cairo_set_line_width(cr, 1.5);
    cairo_set_source_rgb(cr, outlinecol, outlinecol, outlinecol);
    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
    float r1, r2;
    if(zoom != 1)
    {
      r1 = 0.05*width;
      r2 = 0.022*width;
    }
    else
    {
      r1 = 0.015*fscale;
      r2 = 0.007*fscale;
    }

    float x, y;
    if(zoom != 1) y = 0.90*height;
    else y = .12*fscale;

    if(img) for(int k=0; k<5; k++)
      {
        if(zoom != 1) x = (0.41+k*0.12)*width;
        else x = (.08+k*0.04)*fscale;

        if((img->flags & 0x7) != 6) //if rejected: draw no stars
        {
          dt_view_star(cr, x, y, r1, r2);
          if((px - x)*(px - x) + (py - y)*(py - y) < r1*r1)
          {
            *image_over = DT_VIEW_STAR_1 + k;
            cairo_fill(cr);
          }
          else if((img->flags & 0x7) > k)
          {
            cairo_fill_preserve(cr);
            cairo_set_source_rgb(cr, 1.0-bordercol, 1.0-bordercol, 1.0-bordercol);
            cairo_stroke(cr);
            cairo_set_source_rgb(cr, outlinecol, outlinecol, outlinecol);
          }
          else cairo_stroke(cr);
        }
      }

    //Image rejected?
    if(zoom !=1) x = 0.11*width;
    else x = .04*fscale;

    if((px - x)*(px - x) + (py - y)*(py - y) < r1*r1)
    {
      *image_over = DT_VIEW_REJECT; //mouse sensitive
      cairo_new_sub_path(cr);
      cairo_arc(cr, x, y, (r1+r2)*.5, 0, 2.0f*M_PI);
      cairo_stroke(cr);
    }
    else if (img && ((img->flags & 0x7) == 6))
    {
      cairo_set_source_rgb(cr, 1., 0., 0.);
      cairo_new_sub_path(cr);
      cairo_arc(cr, x, y, (r1+r2)*.5, 0, 2.0f*M_PI);
      cairo_stroke(cr);
      cairo_set_line_width(cr, 2.5);
    }

    //reject cross:
    cairo_move_to(cr, x-r2, y-r2);
    cairo_line_to(cr, x+r2, y+r2);
    cairo_move_to(cr, x+r2, y-r2);
    cairo_line_to(cr, x-r2, y+r2);
    cairo_close_path(cr);
    cairo_stroke(cr);
    cairo_set_source_rgb(cr, outlinecol, outlinecol, outlinecol);
    cairo_set_line_width(cr, 1.5);

    // image altered?
    if(altered)
    {
      // align to right
      float s = (r1+r2)*.5;
      if(zoom != 1)
      {
        x = width*0.9;
        y = height*0.1;
      }
      else x = (.04+7*0.04)*fscale;
      dt_view_draw_altered(cr, x, y, s);
      //g_print("px = %d, x = %.4f, py = %d, y = %.4f\n", px, x, py, y);
      if(img && abs(px-x) <= 1.2*s && abs(py-y) <= 1.2*s) // mouse hovers over the altered-icon -> history tooltip!
      {
        darktable.gui->center_tooltip = 1;
      }
    }
  }

  // kill all paths, in case img was not loaded yet, or is blocked:
  cairo_new_path(cr);

  // TODO: make mouse sensitive, just as stars!
  // TODO: cache in image struct!
  {
    // color labels:
    const float x = zoom == 1 ? (0.07)*fscale : .21*width;
    const float y = zoom == 1 ? 0.17*fscale: 0.1*height;
    const float r = zoom == 1 ? 0.01*fscale : 0.03*width;

    /* clear and reset prepared statement */
    DT_DEBUG_SQLITE3_CLEAR_BINDINGS(darktable.view_manager->statements.get_color);
    DT_DEBUG_SQLITE3_RESET(darktable.view_manager->statements.get_color); 

    /* setup statement and iterate rows */
    DT_DEBUG_SQLITE3_BIND_INT(darktable.view_manager->statements.get_color, 1, imgid);
    while(sqlite3_step(darktable.view_manager->statements.get_color) == SQLITE_ROW)
    {
      cairo_save(cr);
      int col = sqlite3_column_int(darktable.view_manager->statements.get_color, 0);
      // see src/dtgtk/paint.c
      dtgtk_cairo_paint_label(cr, x+(3*r*col)-5*r, y-r, r*2, r*2, col);
      cairo_restore(cr);
    }
  }

  if(img && (zoom == 1))
  {
    // some exif data
    cairo_set_source_rgb(cr, .7, .7, .7);
    cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
    cairo_set_font_size (cr, .025*fscale);

    cairo_move_to (cr, .02*fscale, .04*fscale);
    // cairo_show_text(cr, img->filename);
    cairo_text_path(cr, img->filename);
    char exifline[50];
    cairo_move_to (cr, .02*fscale, .08*fscale);
    dt_image_print_exif(img, exifline, 50);
    cairo_text_path(cr, exifline);
    cairo_fill_preserve(cr);
    cairo_set_line_width(cr, 1.0);
    cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
    cairo_stroke(cr);
  }

  if(img) dt_image_cache_read_release(darktable.image_cache, img);
  cairo_restore(cr);
  // if(zoom == 1) cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
}
Example #10
0
static void dt_ellipse_events_post_expose(cairo_t *cr, float zoom_scale, dt_masks_form_gui_t *gui, int index)
{
  double dashed[] = { 4.0, 4.0 };
  dashed[0] /= zoom_scale;
  dashed[1] /= zoom_scale;
  int len = sizeof(dashed) / sizeof(dashed[0]);
  dt_masks_form_gui_points_t *gpt = (dt_masks_form_gui_points_t *)g_list_nth_data(gui->points, index);
  if(!gpt) return;

  const float r = atan2(gpt->points[3] - gpt->points[1], gpt->points[2] - gpt->points[0]);
  const float sinr = sin(r);
  const float cosr = cos(r);

  float dx = 0.0f, dy = 0.0f, xref = gpt->points[0], yref = gpt->points[1];
  float dxs = 0.0f, dys = 0.0f, xrefs = 0.0f, yrefs = 0.0f;
  float sinv = 0.0f, cosv = 1.0f;
  float scalea = 1.0f, scaleb = 1.0f, scaleab = 1.0f, scalebb = 1.0f;

  if(gpt->source_count > 10)
  {
    xrefs = gpt->source[0];
    yrefs = gpt->source[1];
  }
  if((gui->group_selected == index) && gui->form_dragging)
  {
    dx = gui->posx + gui->dx - xref;
    dy = gui->posy + gui->dy - yref;
  }
  else if((gui->group_selected == index) && gui->source_dragging)
  {
    xrefs = gpt->source[0], yrefs = gpt->source[1];
    dxs = gui->posx + gui->dx - xrefs;
    dys = gui->posy + gui->dy - yrefs;
  }
  else if((gui->group_selected == index) && gui->form_rotating)
  {
    const float v = atan2(gui->posy - yref, gui->posx - xref) - atan2(-gui->dy, -gui->dx);
    sinv = sin(v);
    cosv = cos(v);
  }
  else if((gui->group_selected == index) && (gui->point_dragging >= 1))
  {
    const int k = gui->point_dragging;
    const float rx = gpt->points[k * 2] - xref;
    const float ry = gpt->points[k * 2 + 1] - yref;
    const float bx = gpt->border[k * 2] - xref;
    const float by = gpt->border[k * 2 + 1] - yref;
    const float deltax = gui->posx + gui->dx - xref;
    const float deltay = gui->posy + gui->dy - yref;

    const float r = sqrtf(rx * rx + ry * ry);
    const float b = sqrtf(bx * bx + by * by);
    float d = (rx * deltax + ry * deltay) / r;
    if(r + d < 0) d = -r;

    if(k == 1 || k == 2)
    {
      scalea = r > 0 ? (r + d) / r : 0;
      scaleab = b > 0 ? (b + d) / b : 0;
    }
    else
    {
      scaleb = r > 0 ? (r + d) / r : 0;
      scalebb = b > 0 ? (b + d) / b : 0;
    }
  }

  float x, y;

  // draw shape
  if(gpt->points_count > 10)
  {
    cairo_set_dash(cr, dashed, 0, 0);
    if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging))
      cairo_set_line_width(cr, 5.0 / zoom_scale);
    else
      cairo_set_line_width(cr, 3.0 / zoom_scale);
    cairo_set_source_rgba(cr, .3, .3, .3, .8);

    _ellipse_point_transform(xref, yref, gpt->points[10] + dx, gpt->points[11] + dy, sinr, cosr, scalea,
                             scaleb, sinv, cosv, &x, &y);
    cairo_move_to(cr, x, y);
    for(int i = 6; i < gpt->points_count; i++)
    {
      _ellipse_point_transform(xref, yref, gpt->points[i * 2] + dx, gpt->points[i * 2 + 1] + dy, sinr, cosr,
                               scalea, scaleb, sinv, cosv, &x, &y);
      cairo_line_to(cr, x, y);
    }
    _ellipse_point_transform(xref, yref, gpt->points[10] + dx, gpt->points[11] + dy, sinr, cosr, scalea,
                             scaleb, sinv, cosv, &x, &y);
    cairo_line_to(cr, x, y);
    cairo_stroke_preserve(cr);
    if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging))
      cairo_set_line_width(cr, 2.0 / zoom_scale);
    else
      cairo_set_line_width(cr, 1.0 / zoom_scale);
    cairo_set_source_rgba(cr, .8, .8, .8, .8);
    cairo_stroke(cr);
  }

  // draw anchor points
  if(TRUE)
  {
    cairo_set_dash(cr, dashed, 0, 0);
    float anchor_size; // = (gui->form_dragging || gui->form_selected) ? 7.0f / zoom_scale : 5.0f /
                       // zoom_scale;

    for(int i = 1; i < 5; i++)
    {
      cairo_set_source_rgba(cr, .8, .8, .8, .8);

      if(i == gui->point_dragging || i == gui->point_selected)
        anchor_size = 7.0f / zoom_scale;
      else
        anchor_size = 5.0f / zoom_scale;

      _ellipse_point_transform(xref, yref, gpt->points[i * 2] + dx, gpt->points[i * 2 + 1] + dy, sinr, cosr,
                               scalea, scaleb, sinv, cosv, &x, &y);
      cairo_rectangle(cr, x - (anchor_size * 0.5), y - (anchor_size * 0.5), anchor_size, anchor_size);
      cairo_fill_preserve(cr);
      if((gui->group_selected == index) && (i == gui->point_dragging || i == gui->point_selected))
        cairo_set_line_width(cr, 2.0 / zoom_scale);
      if((gui->group_selected == index) && (gui->form_dragging || gui->form_selected))
        cairo_set_line_width(cr, 2.0 / zoom_scale);
      else
        cairo_set_line_width(cr, 1.0 / zoom_scale);
      cairo_set_source_rgba(cr, .3, .3, .3, .8);
      cairo_stroke(cr);
    }
  }

  // draw border
  if((gui->group_selected == index) && gpt->border_count > 10)
  {
    cairo_set_dash(cr, dashed, len, 0);
    if((gui->group_selected == index) && (gui->border_selected))
      cairo_set_line_width(cr, 2.0 / zoom_scale);
    else
      cairo_set_line_width(cr, 1.0 / zoom_scale);
    cairo_set_source_rgba(cr, .3, .3, .3, .8);

    _ellipse_point_transform(xref, yref, gpt->border[10] + dx, gpt->border[11] + dy, sinr, cosr, scaleab,
                             scalebb, sinv, cosv, &x, &y);
    cairo_move_to(cr, x, y);
    for(int i = 6; i < gpt->border_count; i++)
    {
      _ellipse_point_transform(xref, yref, gpt->border[i * 2] + dx, gpt->border[i * 2 + 1] + dy, sinr, cosr,
                               scaleab, scalebb, sinv, cosv, &x, &y);
      cairo_line_to(cr, x, y);
    }
    _ellipse_point_transform(xref, yref, gpt->border[10] + dx, gpt->border[11] + dy, sinr, cosr, scaleab,
                             scalebb, sinv, cosv, &x, &y);
    cairo_line_to(cr, x, y);

    cairo_stroke_preserve(cr);
    if((gui->group_selected == index) && (gui->border_selected))
      cairo_set_line_width(cr, 2.0 / zoom_scale);
    else
      cairo_set_line_width(cr, 1.0 / zoom_scale);
    cairo_set_source_rgba(cr, .8, .8, .8, .8);
    cairo_set_dash(cr, dashed, len, 4);
    cairo_stroke(cr);
  }

  // draw the source if any
  if(gpt->source_count > 10)
  {
    // compute the dest inner ellipse intersection with the line from source center to dest center.
    float cdx = gpt->source[0] + dxs - gpt->points[0] - dx;
    float cdy = gpt->source[1] + dys - gpt->points[1] - dy;

    // we don't draw the line if source==point
    if(cdx != 0.0 && cdy != 0.0)
    {
      cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
      float cangle = atan(cdx / cdy);

      if(cdy > 0)
        cangle = (M_PI / 2) - cangle;
      else
        cangle = -(M_PI / 2) - cangle;

      float arrowx = gpt->points[0] + dx;
      float arrowy = gpt->points[1] + dy;

      cairo_move_to(cr, gpt->source[0] + dxs, gpt->source[1] + dys); // source center
      cairo_line_to(cr, arrowx, arrowy);                             // dest border
      // then draw to line for the arrow itself
      const float arrow_scale = 8.0;
      cairo_move_to(cr, arrowx + arrow_scale * cos(cangle + (0.4)),
                    arrowy + arrow_scale * sin(cangle + (0.4)));
      cairo_line_to(cr, arrowx, arrowy);
      cairo_line_to(cr, arrowx + arrow_scale * cos(cangle - (0.4)),
                    arrowy + arrow_scale * sin(cangle - (0.4)));

      cairo_set_dash(cr, dashed, 0, 0);
      if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging))
        cairo_set_line_width(cr, 2.5 / zoom_scale);
      else
        cairo_set_line_width(cr, 1.5 / zoom_scale);
      cairo_set_source_rgba(cr, .3, .3, .3, .8);
      cairo_stroke_preserve(cr);
      if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging))
        cairo_set_line_width(cr, 1.0 / zoom_scale);
      else
        cairo_set_line_width(cr, 0.5 / zoom_scale);
      cairo_set_source_rgba(cr, .8, .8, .8, .8);
      cairo_stroke(cr);
    }

    // we draw the source
    cairo_set_dash(cr, dashed, 0, 0);
    if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging))
      cairo_set_line_width(cr, 2.5 / zoom_scale);
    else
      cairo_set_line_width(cr, 1.5 / zoom_scale);
    cairo_set_source_rgba(cr, .3, .3, .3, .8);
    _ellipse_point_transform(xrefs, yrefs, gpt->source[10] + dxs, gpt->source[11] + dys, sinr, cosr, scalea,
                             scaleb, sinv, cosv, &x, &y);
    cairo_move_to(cr, x, y);
    for(int i = 6; i < gpt->source_count; i++)
    {
      _ellipse_point_transform(xrefs, yrefs, gpt->source[i * 2] + dxs, gpt->source[i * 2 + 1] + dys, sinr,
                               cosr, scalea, scaleb, sinv, cosv, &x, &y);
      cairo_line_to(cr, x, y);
    }
    _ellipse_point_transform(xrefs, yrefs, gpt->source[10] + dxs, gpt->source[11] + dys, sinr, cosr, scalea,
                             scaleb, sinv, cosv, &x, &y);
    cairo_line_to(cr, x, y);
    cairo_stroke_preserve(cr);
    if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging))
      cairo_set_line_width(cr, 1.0 / zoom_scale);
    else
      cairo_set_line_width(cr, 0.5 / zoom_scale);
    cairo_set_source_rgba(cr, .8, .8, .8, .8);
    cairo_stroke(cr);
  }
}
Example #11
0
static int
cr_stroke_preserve (lua_State *L) {
    cairo_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_CONTEXT);
    cairo_stroke_preserve(*obj);
    return 0;
}
Example #12
0
static void
gimp_cell_renderer_color_render (GtkCellRenderer      *cell,
                                 GdkWindow            *window,
                                 GtkWidget            *widget,
                                 GdkRectangle         *background_area,
                                 GdkRectangle         *cell_area,
                                 GdkRectangle         *expose_area,
                                 GtkCellRendererState  flags)
{
  GimpCellRendererColor *color = GIMP_CELL_RENDERER_COLOR (cell);
  GdkRectangle           rect;

  gimp_cell_renderer_color_get_size (cell, widget, cell_area,
                                     &rect.x,
                                     &rect.y,
                                     &rect.width,
                                     &rect.height);

  rect.x      += cell_area->x + cell->xpad;
  rect.y      += cell_area->y + cell->ypad;
  rect.width  -= 2 * cell->xpad;
  rect.height -= 2 * cell->ypad;

  if (rect.width > 2 && rect.height > 2)
    {
      cairo_t      *cr    = gdk_cairo_create (window);
      GtkStyle     *style = gtk_widget_get_style (widget);
      GtkStateType  state;

      cairo_rectangle (cr,
                       rect.x + 1, rect.y + 1,
                       rect.width - 2, rect.height - 2);

      gimp_cairo_set_source_rgb (cr, &color->color);
      cairo_fill (cr);

      if (! color->opaque && color->color.a < 1.0)
        {
          cairo_pattern_t *pattern;

          cairo_move_to (cr, rect.x + 1,              rect.y + rect.height - 1);
          cairo_line_to (cr, rect.x + rect.width - 1, rect.y + rect.height - 1);
          cairo_line_to (cr, rect.x + rect.width - 1, rect.y + 1);
          cairo_close_path (cr);

          pattern = gimp_cairo_checkerboard_create (cr,
                                                    GIMP_CHECK_SIZE_SM,
                                                    NULL, NULL);
          cairo_set_source (cr, pattern);
          cairo_pattern_destroy (pattern);

          cairo_fill_preserve (cr);

          gimp_cairo_set_source_rgba (cr, &color->color);
          cairo_fill (cr);
        }

      /* draw border */
      cairo_rectangle (cr,
                       rect.x + 0.5, rect.y + 0.5,
                       rect.width - 1, rect.height - 1);

      if (! cell->sensitive ||
          GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE)
        {
          state = GTK_STATE_INSENSITIVE;
        }
      else
        {
          state = (flags & GTK_CELL_RENDERER_SELECTED ?
                   GTK_STATE_SELECTED : GTK_STATE_NORMAL);
        }

      cairo_set_line_width (cr, 1);
      gdk_cairo_set_source_color (cr, &style->fg[state]);
      cairo_stroke_preserve (cr);

      if (state == GTK_STATE_SELECTED &&
          gimp_cairo_set_focus_line_pattern (cr, widget))
        {
          gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]);
          cairo_stroke (cr);
        }

      cairo_destroy (cr);
    }
}
Example #13
0
void
gimp_display_shell_render (GimpDisplayShell *shell,
                           cairo_t          *cr,
                           gint              x,
                           gint              y,
                           gint              w,
                           gint              h)
{
  GimpImage       *image;
  GimpProjection  *projection;
  GeglBuffer      *buffer;
  gdouble          scale_x      = 1.0;
  gdouble          scale_y      = 1.0;
  gdouble          buffer_scale = 1.0;
  gint             viewport_offset_x;
  gint             viewport_offset_y;
  gint             viewport_width;
  gint             viewport_height;
  gint             scaled_x;
  gint             scaled_y;
  gint             scaled_width;
  gint             scaled_height;
  cairo_surface_t *xfer;
  gint             xfer_src_x;
  gint             xfer_src_y;
  gint             mask_src_x = 0;
  gint             mask_src_y = 0;
  gint             stride;
  guchar          *data;

  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
  g_return_if_fail (cr != NULL);
  g_return_if_fail (w > 0 && h > 0);

  image      = gimp_display_get_image (shell->display);
  projection = gimp_image_get_projection (image);
  buffer     = gimp_pickable_get_buffer (GIMP_PICKABLE (projection));

#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
  /* if we had this future API, things would look pretty on hires (retina) */
  scale_x = gdk_window_get_scale_factor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell))));
#endif

  scale_x = MIN (scale_x, GIMP_DISPLAY_RENDER_MAX_SCALE);
  scale_y = scale_x;

  if (shell->scale_x > shell->scale_y)
    {
      scale_y *= (shell->scale_x / shell->scale_y);

      buffer_scale = shell->scale_y * scale_y;
    }
  else if (shell->scale_y > shell->scale_x)
    {
      scale_x *= (shell->scale_y / shell->scale_x);

      buffer_scale = shell->scale_x * scale_x;
    }
  else
    {
      buffer_scale = shell->scale_x * scale_x;
    }

  gimp_display_shell_scroll_get_scaled_viewport (shell,
                                                 &viewport_offset_x,
                                                 &viewport_offset_y,
                                                 &viewport_width,
                                                 &viewport_height);

  scaled_x      = floor ((x + viewport_offset_x) * scale_x);
  scaled_y      = floor ((y + viewport_offset_y) * scale_y);
  scaled_width  = ceil (w * scale_x);
  scaled_height = ceil (h * scale_y);

  if (shell->rotate_transform)
    {
      xfer = cairo_surface_create_similar_image (cairo_get_target (cr),
                                                 CAIRO_FORMAT_ARGB32,
                                                 scaled_width,
                                                 scaled_height);
      cairo_surface_mark_dirty (xfer);
      xfer_src_x = 0;
      xfer_src_y = 0;
    }
  else
    {
      xfer = gimp_display_xfer_get_surface (shell->xfer,
                                            scaled_width,
                                            scaled_height,
                                            &xfer_src_x,
                                            &xfer_src_y);
    }

  stride = cairo_image_surface_get_stride (xfer);
  data = cairo_image_surface_get_data (xfer);
  data += xfer_src_y * stride + xfer_src_x * 4;

  /*  apply filters to the rendered projection  */
  if (shell->filter_stack)
    {
      const Babl *filter_format = babl_format ("R'G'B'A float");

      if (! shell->filter_buffer)
        {
          gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
          gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;

          shell->filter_data =
            gegl_malloc (w * h * babl_format_get_bytes_per_pixel (filter_format));

          shell->filter_stride = w * babl_format_get_bytes_per_pixel (filter_format);

          shell->filter_buffer =
            gegl_buffer_linear_new_from_data (shell->filter_data,
                                              filter_format,
                                              GEGL_RECTANGLE (0, 0, w, h),
                                              GEGL_AUTO_ROWSTRIDE,
                                              (GDestroyNotify) gegl_free,
                                              shell->filter_data);
        }

      gegl_buffer_get (buffer,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       filter_format, shell->filter_data,
                       shell->filter_stride, GEGL_ABYSS_CLAMP);


      gimp_color_display_stack_convert_buffer (shell->filter_stack,
                                               shell->filter_buffer,
                                               GEGL_RECTANGLE (0, 0,
                                                               scaled_width,
                                                               scaled_height));

      gegl_buffer_get (shell->filter_buffer,
                       GEGL_RECTANGLE (0, 0,
                                       scaled_width,
                                       scaled_height),
                       1.0,
                       babl_format ("cairo-ARGB32"),
                       data, stride,
                       GEGL_ABYSS_CLAMP);
    }
  else
    {
      gegl_buffer_get (buffer,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("cairo-ARGB32"),
                       data, stride,
                       GEGL_ABYSS_CLAMP);
    }

  if (shell->mask)
    {
      gint mask_height;

      if (! shell->mask_surface)
        {
          shell->mask_surface =
            cairo_image_surface_create (CAIRO_FORMAT_A8,
                                        GIMP_DISPLAY_RENDER_BUF_WIDTH  *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE,
                                        GIMP_DISPLAY_RENDER_BUF_HEIGHT *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE);
        }

      cairo_surface_mark_dirty (shell->mask_surface);

      stride = cairo_image_surface_get_stride (shell->mask_surface);
      data = cairo_image_surface_get_data (shell->mask_surface);
      data += mask_src_y * stride + mask_src_x * 4;

      gegl_buffer_get (shell->mask,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("Y u8"),
                       data, stride,
                       GEGL_ABYSS_CLAMP);

      /* invert the mask so what is *not* the foreground object is masked */
      mask_height = scaled_height;
      while (mask_height--)
        {
          gint    mask_width = scaled_width;
          guchar *d          = data;

          while (mask_width--)
            {
              guchar inv = 255 - *d;

              *d++ = inv;
            }

          data += stride;
        }
    }

  /*  put it to the screen  */
  cairo_save (cr);

  cairo_rectangle (cr, x, y, w, h);

  cairo_scale (cr, 1.0 / scale_x, 1.0 / scale_y);

  cairo_set_source_surface (cr, xfer,
                            x * scale_x - xfer_src_x,
                            y * scale_y - xfer_src_y);

  if (shell->rotate_transform)
    {
      cairo_pattern_t *pattern;

      pattern = cairo_get_source (cr);
      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

      cairo_set_line_width (cr, 1.0);
      cairo_stroke_preserve (cr);

      cairo_surface_destroy (xfer);
    }

  cairo_clip (cr);
  cairo_paint (cr);

  if (shell->mask)
    {
      gimp_cairo_set_source_rgba (cr, &shell->mask_color);
      cairo_mask_surface (cr, shell->mask_surface,
                          (x - mask_src_x) * scale_x,
                          (y - mask_src_y) * scale_y);
    }

  cairo_restore (cr);
}
Example #14
0
static void dt_circle_events_post_expose(cairo_t *cr,float zoom_scale,dt_masks_form_gui_t *gui,int index)
{
  double dashed[] = {4.0, 4.0};
  dashed[0] /= zoom_scale;
  dashed[1] /= zoom_scale;
  int len  = sizeof(dashed) / sizeof(dashed[0]);
  dt_masks_form_gui_points_t *gpt = (dt_masks_form_gui_points_t *) g_list_nth_data(gui->points,index);
  if (!gpt) return;
  float dx=0, dy=0, dxs=0, dys=0;
  if ((gui->group_selected == index) && gui->form_dragging)
  {
    dx = gui->posx + gui->dx - gpt->points[0];
    dy = gui->posy + gui->dy - gpt->points[1];
  }
  if ((gui->group_selected == index) && gui->source_dragging)
  {
    dxs = gui->posx + gui->dx - gpt->source[0];
    dys = gui->posy + gui->dy - gpt->source[1];
  }

  if (gpt->points_count > 6)
  {
    cairo_set_dash(cr, dashed, 0, 0);
    if ((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 5.0/zoom_scale);
    else                                     cairo_set_line_width(cr, 3.0/zoom_scale);
    cairo_set_source_rgba(cr, .3, .3, .3, .8);
    cairo_move_to(cr,gpt->points[2]+dx,gpt->points[3]+dy);
    for (int i=2; i<gpt->points_count; i++)
    {
      cairo_line_to(cr,gpt->points[i*2]+dx,gpt->points[i*2+1]+dy);
    }
    cairo_line_to(cr,gpt->points[2]+dx,gpt->points[3]+dy);
    cairo_stroke_preserve(cr);
    if ((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 2.0/zoom_scale);
    else                                     cairo_set_line_width(cr, 1.0/zoom_scale);
    cairo_set_source_rgba(cr, .8, .8, .8, .8);
    cairo_stroke(cr);
  }

  //draw border
  if ((gui->group_selected == index) && gpt->border_count > 6)
  {
    cairo_set_dash(cr, dashed, len, 0);
    if ((gui->group_selected == index) && (gui->border_selected)) cairo_set_line_width(cr, 2.0/zoom_scale);
    else                     cairo_set_line_width(cr, 1.0/zoom_scale);
    cairo_set_source_rgba(cr, .3, .3, .3, .8);

    cairo_move_to(cr,gpt->border[2]+dx,gpt->border[3]+dy);
    for (int i=2; i<gpt->border_count; i++)
    {
      cairo_line_to(cr,gpt->border[i*2]+dx,gpt->border[i*2+1]+dy);
    }
    cairo_line_to(cr,gpt->border[2]+dx,gpt->border[3]+dy);

    cairo_stroke_preserve(cr);
    if ((gui->group_selected == index) && (gui->border_selected)) cairo_set_line_width(cr, 2.0/zoom_scale);
    else                     cairo_set_line_width(cr, 1.0/zoom_scale);
    cairo_set_source_rgba(cr, .8, .8, .8, .8);
    cairo_set_dash(cr, dashed, len, 4);
    cairo_stroke(cr);
  }

  //draw the source if any
  if (gpt->source_count>6)
  {
    const float radius = fabs(gpt->points[3] - gpt->points[1]);


    
    // compute the dest inner circle intersection with the line from source center to dest center.
    float cdx = gpt->source[0] + dxs - gpt->points[0] - dx;
    float cdy = gpt->source[1] + dys - gpt->points[1] - dy;

    //we don't draw the line if source==point
    if (cdx != 0.0 && cdy != 0.0)
    { 
      cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND);
      float cangle = atan(cdx / cdy);
  
      if (cdy>0) cangle = (M_PI/2) - cangle;
      else cangle = -(M_PI/2) - cangle;
  
      // (arrowx,arrowy) is the point of intersection, we move it (factor 1.11) a bit farther than the
      // inner circle to avoid superposition.
      float arrowx = gpt->points[0] + 1.11 * radius * cos (cangle) + dx;
      float arrowy = gpt->points[1] + 1.11 * radius * sin (cangle) + dy;
  
      cairo_move_to(cr,gpt->source[0]+dxs,gpt->source[1]+dys); // source center
      cairo_line_to(cr,arrowx,arrowy); // dest border
      // then draw to line for the arrow itself
      const float arrow_scale = 8.0;
      cairo_move_to(cr,arrowx + arrow_scale * cos (cangle+(0.4)),
                    arrowy + arrow_scale * sin (cangle+(0.4)));
      cairo_line_to(cr,arrowx,arrowy);
      cairo_line_to(cr,arrowx + arrow_scale * cos (cangle-(0.4)),
                    arrowy + arrow_scale * sin (cangle-(0.4)));
  
      cairo_set_dash(cr, dashed, 0, 0);
      if ((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 2.5/zoom_scale);
      else                                     cairo_set_line_width(cr, 1.5/zoom_scale);
      cairo_set_source_rgba(cr, .3, .3, .3, .8);
      cairo_stroke_preserve(cr);
      if ((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 1.0/zoom_scale);
      else                                     cairo_set_line_width(cr, 0.5/zoom_scale);
      cairo_set_source_rgba(cr, .8, .8, .8, .8);
      cairo_stroke(cr);
    }
    
    //we draw the source
    cairo_set_dash(cr, dashed, 0, 0);
    if ((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 2.5/zoom_scale);
    else                                     cairo_set_line_width(cr, 1.5/zoom_scale);
    cairo_set_source_rgba(cr, .3, .3, .3, .8);
    cairo_move_to(cr,gpt->source[2]+dxs,gpt->source[3]+dys);
    for (int i=2; i<gpt->source_count; i++)
    {
      cairo_line_to(cr,gpt->source[i*2]+dxs,gpt->source[i*2+1]+dys);
    }
    cairo_line_to(cr,gpt->source[2]+dxs,gpt->source[3]+dys);
    cairo_stroke_preserve(cr);
    if ((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 1.0/zoom_scale);
    else                                     cairo_set_line_width(cr, 0.5/zoom_scale);
    cairo_set_source_rgba(cr, .8, .8, .8, .8);
    cairo_stroke(cr);
  }
}
void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int /* offset */, const Color& color)
{
    if (paintingDisabled())
        return;

    unsigned rectCount = rects.size();

    cairo_t* cr = platformContext()->cr();
    cairo_save(cr);
    cairo_push_group(cr);
    cairo_new_path(cr);

#if PLATFORM(GTK)
#ifdef GTK_API_VERSION_2
    GdkRegion* reg = gdk_region_new();
#else
    cairo_region_t* reg = cairo_region_create();
#endif

    for (unsigned i = 0; i < rectCount; i++) {
#ifdef GTK_API_VERSION_2
        GdkRectangle rect = rects[i];
        gdk_region_union_with_rect(reg, &rect);
#else
        cairo_rectangle_int_t rect = rects[i];
        cairo_region_union_rectangle(reg, &rect);
#endif
    }
    gdk_cairo_region(cr, reg);
#ifdef GTK_API_VERSION_2
    gdk_region_destroy(reg);
#else
    cairo_region_destroy(reg);
#endif
#else
    int radius = (width - 1) / 2;
    Path path;
    for (unsigned i = 0; i < rectCount; ++i) {
        if (i > 0)
            path.clear();
        path.addRoundedRect(rects[i], FloatSize(radius, radius));
        appendWebCorePathToCairoContext(cr, path);
    }
#endif
    Color ringColor = color;
    adjustFocusRingColor(ringColor);
    adjustFocusRingLineWidth(width);
    setSourceRGBAFromColor(cr, ringColor);
    cairo_set_line_width(cr, width);
    setPlatformStrokeStyle(focusRingStrokeStyle());

    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
    cairo_stroke_preserve(cr);

    cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
    cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
    cairo_fill(cr);

    cairo_pop_group_to_source(cr);
    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
    cairo_paint(cr);
    cairo_restore(cr);
}
Example #16
0
static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event,  gpointer data)
{
//ifff a====0
         cairo_t *cr;
          cr = gdk_cairo_create(widget->window);
                
        if(a==0)
        {
                 cairo_set_source_rgb(cr, 0, 0, 0);
                  cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
             CAIRO_FONT_WEIGHT_NORMAL);
                  cairo_set_font_size(cr, 40.0);

                  cairo_move_to(cr, 70, 100);
                  cairo_show_text(cr, buf);

        }
//iffff a===1
        if(a==1)
        {
        int i;

        cairo_set_source_rgb(cr, 0 , 0 , 0 );
        cairo_set_line_width(cr, 6 );
        cairo_arc(cr, 150, 100, 75, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        /*cairo_set_source_rgb(cr, 0.3, 0.4, 0.6); 
        cairo_fill(cr);        */

        for(i=0;i<12;i++)
        {
                cairo_set_source_rgb(cr, 0, 0, 0);
                  cairo_set_line_width(cr, 4 );
                cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); 

                cairo_move_to(cr,150 + 66.5 * cos(i * M_PI / 6),100 + 66.5 * sin(i * M_PI / 6 ));
                cairo_line_to(cr,150 + 75 * cos(i * M_PI / 6),100 + 75 * sin(i * M_PI / 6 ));
                cairo_stroke(cr);
        }

        for(i=0;i<12;i+=3)
        {
                cairo_set_source_rgb(cr, 0, 0, 0);
                  cairo_set_line_width(cr, 7 );
                cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); 

                cairo_move_to(cr,150 + 65.5 * cos(i * M_PI / 6),100 + 65.5 * sin(i * M_PI / 6 ));
                cairo_line_to(cr,150 + 75 * cos(i * M_PI / 6),100 + 75 * sin(i * M_PI / 6 ));
                cairo_stroke(cr);
        }


         minutes = minutes * M_PI / 30;
          hours = hours * M_PI / 6;
          seconds=seconds * M_PI / 30;

        cairo_set_source_rgb(cr,0.3,0.6,0.2);
        cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); 
        cairo_set_line_width(cr, 8  );
        cairo_move_to(cr,150 ,100);
        cairo_line_to(cr,150 + 30 * sin(hours + minutes / 12.0),100 + 40 * -1*cos(hours + minutes / 12.0));
        cairo_stroke(cr);        

        cairo_set_source_rgb(cr, 0.3, 0.4, 0.6);
        cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); 
        cairo_set_line_width(cr, 6 );
        cairo_move_to(cr,150 ,100);
        cairo_line_to(cr,150 + 60 * sin(minutes + seconds / 60),100 + 60 * -1*cos(minutes + seconds / 60));
        cairo_stroke(cr);

        cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
        cairo_set_line_width(cr, 2.5 );
        cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); 
        cairo_move_to(cr,150 ,100);
        cairo_line_to(cr,150 + 70 * sin(seconds),100 + 60*-1 * cos(seconds));
        cairo_stroke(cr);

        cairo_set_source_rgb(cr, 0 , 0 , 0 );
        cairo_set_line_width(cr, 2 );
        cairo_arc(cr, 150, 100, 1.5, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        }

        if (a==2)
        {
        

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 50, 120);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(hour_arr[2]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(hour_arr[2]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, 35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(hour_arr[3]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(hour_arr[3]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr); 

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 35, 0);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(hour_brr[3]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(hour_brr[3]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr); 

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(hour_brr[2]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(hour_brr[2]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(hour_brr[1]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(hour_brr[1]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(hour_brr[0]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);  
        else if(hour_brr[0]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 50, 35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(min_arr[1]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(min_arr[1]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, 35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(min_arr[2]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(min_arr[2]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, 35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(min_arr[3]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(min_arr[3]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 35,0 );
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(min_brr[3]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(min_brr[3]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(min_brr[2]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(min_brr[2]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(min_brr[1]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);  
        else if(min_brr[1]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(min_brr[0]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);  
        else if(min_brr[0]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 50, 35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(sec_arr[1]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);  
        else if(sec_arr[1]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, 35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(sec_arr[2]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);  
        else if(sec_arr[2]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, 35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(sec_arr[3]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(sec_arr[3]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 35,0 );
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(sec_brr[3]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(sec_brr[3]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(sec_brr[2]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(sec_brr[2]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(sec_brr[1]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);  
        else if(sec_brr[1]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);

        cairo_set_line_width(cr, 4);  
        cairo_set_source_rgb(cr, 0.69, 0.19, 0);
        cairo_translate(cr, 0, -35);
        cairo_arc(cr, 0, 0, 10, 0, 2 * M_PI);
        cairo_stroke_preserve(cr);
        if(sec_brr[0]==0)
        cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); 
        else if(sec_brr[0]==1)
        cairo_set_source_rgb(cr, 0, 0, 0); 
        cairo_fill(cr);
        
        }
}
Example #17
0
static gboolean _lib_histogram_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
  dt_lib_module_t *self = (dt_lib_module_t *)user_data;
  dt_lib_histogram_t *d = (dt_lib_histogram_t *)self->data;

  dt_develop_t *dev = darktable.develop;
  float *hist = dev->histogram;
  float hist_max = dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR?dev->histogram_max:logf(1.0 + dev->histogram_max);
  const int inset = DT_HIST_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);
  GtkStyle *style=gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL,"GtkWidget", GTK_TYPE_WIDGET);
  if(!style) style = gtk_rc_get_style(widget);
  cairo_set_source_rgb(cr, style->bg[0].red/65535.0, style->bg[0].green/65535.0, style->bg[0].blue/65535.0);
  cairo_paint(cr);

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

  if(d->mode_x == 0)
  {
    d->color_w = 0.06*width;
    d->button_spacing = 0.01*width;
    d->button_h = 0.06*width;
    d->button_y = d->button_spacing;
    d->mode_w = d->color_w;
    d->mode_x = width - 3*(d->color_w+d->button_spacing) - (d->mode_w+d->button_spacing);
    d->red_x = width - 3*(d->color_w+d->button_spacing);
    d->green_x = width - 2*(d->color_w+d->button_spacing);
    d->blue_x = width - (d->color_w+d->button_spacing);
  }

  // TODO: probably this should move to the configure-event callback! That would be future proof if we ever (again) allow to resize the side panels.
  const gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);

  // this code assumes that the first expose comes before the first (preview) pipe is processed and that the size of the widget doesn't change!
  if(dev->histogram_waveform_width == 0)
  {
    dev->histogram_waveform = (uint32_t*)calloc(height * stride / 4, sizeof(uint32_t));
    dev->histogram_waveform_stride = stride;
    dev->histogram_waveform_height = height;
    dev->histogram_waveform_width = width;
//     return TRUE; // there are enough expose events following ...
  }

#if 1
  // draw shadow around
  float alpha = 1.0f;
  cairo_set_line_width(cr, 0.2);
  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.5f;
    cairo_fill(cr);
  }
  cairo_set_line_width(cr, 1.0);
#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_rectangle(cr, 0, 0, width, height);
  cairo_clip(cr);

  cairo_set_source_rgb (cr, .3, .3, .3);
  cairo_rectangle(cr, 0, 0, width, height);
  cairo_fill(cr);
  if(d->highlight == 1)
  {
    cairo_set_source_rgb (cr, .5, .5, .5);
    cairo_rectangle(cr, 0, 0, .2*width, height);
    cairo_fill(cr);
  }
  else if(d->highlight == 2)
  {
    cairo_set_source_rgb (cr, .5, .5, .5);
    cairo_rectangle(cr, 0.2*width, 0, width, height);
    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(hist_max > 0)
  {
    cairo_save(cr);
    if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM)
    {
      // make the color channel selector work:
      uint8_t *buf = (uint8_t*)malloc(sizeof(uint8_t) * height * stride);
      uint8_t mask[3] = {d->blue, d->green, d->red};
      memcpy(buf, dev->histogram_waveform, sizeof(uint8_t) * height * stride);
      for(int y = 0; y < height; y++)
        for(int x = 0; x < width; x++)
          for(int k = 0; k < 3; k++)
          {
            buf[y * stride + x * 4 + k] *= mask[k];
          }

      cairo_surface_t *source = cairo_image_surface_create_for_data(buf,
                                                CAIRO_FORMAT_ARGB32,
                                                width, height, stride);

      cairo_set_source_surface(cr, source, 0.0, 0.0);
      cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
      cairo_paint(cr);
      cairo_surface_destroy(source);
      free(buf);
    }
    else
    {
      // cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
      cairo_translate(cr, 0, height);
      cairo_scale(cr, width/63.0, -(height-10)/hist_max);
      cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
      // cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
      cairo_set_line_width(cr, 1.);
      if(d->red)
      {
        cairo_set_source_rgba(cr, 1., 0., 0., 0.2);
        dt_draw_histogram_8(cr, hist, 0, dev->histogram_type);
      }
      if(d->green)
      {
        cairo_set_source_rgba(cr, 0., 1., 0., 0.2);
        dt_draw_histogram_8(cr, hist, 1, dev->histogram_type);
      }
      if(d->blue)
      {
        cairo_set_source_rgba(cr, 0., 0., 1., 0.2);
        dt_draw_histogram_8(cr, hist, 2, dev->histogram_type);
      }
      cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
      // cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
    }
    cairo_restore(cr);
  }

  cairo_set_source_rgb(cr, .25, .25, .25);
  cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
  cairo_set_font_size (cr, .1*height);

  char exifline[50];
  cairo_move_to (cr, .02*width, .98*height);
  dt_image_print_exif(&dev->image_storage, exifline, 50);
  cairo_save(cr);
  //   cairo_show_text(cr, exifline);
  cairo_set_line_width(cr, 2.0);
  cairo_set_source_rgba(cr, 1, 1, 1, 0.3);
  cairo_text_path(cr, exifline);
  cairo_stroke_preserve(cr);
  cairo_set_source_rgb(cr, .25, .25, .25);
  cairo_fill(cr);
  cairo_restore(cr);

  // buttons to control the display of the histogram: linear/log, r, g, b
  if(d->highlight != 0)
  {
    _draw_mode_toggle(cr, d->mode_x, d->button_y, d->mode_w, d->button_h, dev->histogram_type);
    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.4);
    _draw_color_toggle(cr, d->red_x, d->button_y, d->color_w, d->button_h, d->red);
    cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.4);
    _draw_color_toggle(cr, d->green_x, d->button_y, d->color_w, d->button_h, d->green);
    cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.4);
    _draw_color_toggle(cr, d->blue_x, d->button_y, d->color_w, d->button_h, d->blue);
  }

  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;
}
static GdkPixbuf *
create_gallery (ThumbApp *app)
{
	GdkPixbuf *screenshot, *pixbuf = NULL;
	cairo_t *cr;
	cairo_surface_t *surface;
	PangoLayout *layout;
	PangoFontDescription *font_desc;
	gint64 stream_length, screenshot_interval, pos;
	guint columns = 3, rows, current_column, current_row, x, y;
	gint screenshot_width = 0, screenshot_height = 0, x_padding = 0, y_padding = 0;
	gfloat scale = 1.0;
	gchar *header_text, *duration_text, *filename;

	/* Calculate how many screenshots we're going to take */
	stream_length = app->duration;

	/* As a default, we have one screenshot per minute of stream,
	 * but adjusted so we don't have any gaps in the resulting gallery. */
	if (gallery == 0) {
		gallery = stream_length / 60000;

		while (gallery % 3 != 0 &&
		       gallery % 4 != 0 &&
		       gallery % 5 != 0) {
			gallery++;
		}
	}

	if (gallery < GALLERY_MIN)
		gallery = GALLERY_MIN;
	if (gallery > GALLERY_MAX)
		gallery = GALLERY_MAX;
	screenshot_interval = stream_length / gallery;

	/* Put a lower bound on the screenshot interval so we can't enter an infinite loop below */
	if (screenshot_interval == 0)
		screenshot_interval = 1;

	PROGRESS_DEBUG ("Producing gallery of %u screenshots, taken at %" G_GINT64_FORMAT " millisecond intervals throughout a %" G_GINT64_FORMAT " millisecond-long stream.",
			gallery, screenshot_interval, stream_length);

	/* Calculate how to arrange the screenshots so we don't get ones orphaned on the last row.
	 * At this point, only deal with arrangements of 3, 4 or 5 columns. */
	y = G_MAXUINT;
	for (x = 3; x <= 5; x++) {
		if (gallery % x == 0 || x - gallery % x < y) {
			y = x - gallery % x;
			columns = x;

			/* Have we found an optimal solution already? */
			if (y == x)
				break;
		}
	}

	rows = ceil ((gfloat) gallery / (gfloat) columns);

	PROGRESS_DEBUG ("Outputting as %u rows and %u columns.", rows, columns);

	/* Take the screenshots and composite them into a pixbuf */
	current_column = current_row = x = y = 0;
	for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) {
		if (pos == stream_length)
			screenshot = capture_frame_at_time (app, pos - 1);
		else
			screenshot = capture_frame_at_time (app, pos);

		if (pixbuf == NULL) {
			screenshot_width = gdk_pixbuf_get_width (screenshot);
			screenshot_height = gdk_pixbuf_get_height (screenshot);

			/* Calculate a scaling factor so that screenshot_width -> output_size */
			scale = (float) output_size / (float) screenshot_width;

			x_padding = x = MAX (output_size * 0.05, 1);
			y_padding = y = MAX (scale * screenshot_height * 0.05, 1);

			PROGRESS_DEBUG ("Scaling each screenshot by %f.", scale);

			/* Create our massive pixbuf */
			pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
						 columns * output_size + (columns + 1) * x_padding,
						 (guint) (rows * scale * screenshot_height + (rows + 1) * y_padding));
			gdk_pixbuf_fill (pixbuf, 0x000000ff);

			PROGRESS_DEBUG ("Created output pixbuf (%ux%u).", gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf));
		}

		/* Composite the screenshot into our gallery */
		gdk_pixbuf_composite (screenshot, pixbuf,
				      x, y, output_size, scale * screenshot_height,
				      (gdouble) x, (gdouble) y, scale, scale,
				      GDK_INTERP_BILINEAR, 255);
		g_object_unref (screenshot);

		PROGRESS_DEBUG ("Composited screenshot from %" G_GINT64_FORMAT " milliseconds (address %u) at (%u,%u).",
				pos, GPOINTER_TO_UINT (screenshot), x, y);

		/* We print progress in the range 10% (MIN_PROGRESS) to 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0 */
		PRINT_PROGRESS (MIN_PROGRESS + (current_row * columns + current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0));

		current_column = (current_column + 1) % columns;
		x += output_size + x_padding;
		if (current_column == 0) {
			x = x_padding;
			y += scale * screenshot_height + y_padding;
			current_row++;
		}
	}

	PROGRESS_DEBUG ("Converting pixbuf to a Cairo surface.");

	/* Load the pixbuf into a Cairo surface and overlay the text. The height is the height of
	 * the gallery plus the necessary height for 3 lines of header (at ~18px each), plus some
	 * extra padding. */
	surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, gdk_pixbuf_get_width (pixbuf),
					      gdk_pixbuf_get_height (pixbuf) + GALLERY_HEADER_HEIGHT + y_padding);
	cr = cairo_create (surface);
	cairo_surface_destroy (surface);

	/* First, copy across the gallery pixbuf */
	gdk_cairo_set_source_pixbuf (cr, pixbuf, 0.0, GALLERY_HEADER_HEIGHT + y_padding);
	cairo_rectangle (cr, 0.0, GALLERY_HEADER_HEIGHT + y_padding, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf));
	cairo_fill (cr);
	g_object_unref (pixbuf);

	/* Build the header information */
	duration_text = xplayer_time_to_string (stream_length);
	filename = NULL;
	if (strstr (app->input, "://")) {
		char *local;
		local = g_filename_from_uri (app->input, NULL, NULL);
		filename = g_path_get_basename (local);
		g_free (local);
	}
	if (filename == NULL)
		filename = g_path_get_basename (app->input);

	/* Translators: The first string is "Filename" (as translated); the second is an actual filename.
			The third string is "Resolution" (as translated); the fourth and fifth are screenshot height and width, respectively.
			The sixth string is "Duration" (as translated); the seventh is the movie duration in words. */
	header_text = g_markup_printf_escaped (_("<b>%s</b>: %s\n<b>%s</b>: %d\303\227%d\n<b>%s</b>: %s"),
					       _("Filename"),
					       filename,
					       _("Resolution"),
					       screenshot_width,
					       screenshot_height,
					       _("Duration"),
					       duration_text);
	g_free (duration_text);
	g_free (filename);

	PROGRESS_DEBUG ("Writing header text with Pango.");

	/* Write out some header information */
	layout = pango_cairo_create_layout (cr);
	font_desc = pango_font_description_from_string ("Sans 18px");
	pango_layout_set_font_description (layout, font_desc);
	pango_font_description_free (font_desc);

	pango_layout_set_markup (layout, header_text, -1);
	g_free (header_text);

	cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
	cairo_move_to (cr, (gdouble) x_padding, (gdouble) y_padding);
	pango_cairo_show_layout (cr, layout);

	/* Go through each screenshot and write its timestamp */
	current_column = current_row = 0;
	x = x_padding + output_size;
	y = y_padding * 2 + GALLERY_HEADER_HEIGHT + scale * screenshot_height;

	font_desc = pango_font_description_from_string ("Sans 10px");
	pango_layout_set_font_description (layout, font_desc);
	pango_font_description_free (font_desc);

	PROGRESS_DEBUG ("Writing screenshot timestamps with Pango.");

	for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) {
		gchar *timestamp_text;
		gint layout_width, layout_height;

		timestamp_text = xplayer_time_to_string (pos);

		pango_layout_set_text (layout, timestamp_text, -1);
		pango_layout_get_pixel_size (layout, &layout_width, &layout_height);

		/* Display the timestamp in the bottom-right corner of the current screenshot */
		cairo_move_to (cr, x - layout_width - 0.02 * output_size, y - layout_height - 0.02 * scale * screenshot_height);

		/* We have to stroke the text so it's visible against screenshots of the same
		 * foreground color. */
		pango_cairo_layout_path (cr, layout);
		cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
		cairo_stroke_preserve (cr);
		cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
		cairo_fill (cr);

		PROGRESS_DEBUG ("Writing timestamp \"%s\" at (%f,%f).", timestamp_text,
				x - layout_width - 0.02 * output_size,
				y - layout_height - 0.02 * scale * screenshot_height);

		/* We print progress in the range 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0) to 90% (MAX_PROGRESS) */
		PRINT_PROGRESS (MIN_PROGRESS + (MAX_PROGRESS - MIN_PROGRESS) / 2.0 + (current_row * columns + current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0));

		g_free (timestamp_text);

		current_column = (current_column + 1) % columns;
		x += output_size + x_padding;
		if (current_column == 0) {
			x = x_padding + output_size;
			y += scale * screenshot_height + y_padding;
			current_row++;
		}
	}

	g_object_unref (layout);

	PROGRESS_DEBUG ("Converting Cairo surface back to pixbuf.");

	/* Create a new pixbuf from the Cairo context */
	pixbuf = cairo_surface_to_pixbuf (cairo_get_target (cr));
	cairo_destroy (cr);

	return pixbuf;
}
Example #19
0
void Context::strokePreserve()
{
	cairo_stroke_preserve( mCairo );
}
Example #20
0
void draw_single_road(struct ScreenContext *screenContext, cairo_t *cr, struct Road *aRoad, struct RGBO *fillColor)
{
	struct Item *p;
	struct Point point, mp;
	double width, wRoad;
	struct Color lineColor;
	double dist, d, angle;

	width = aRoad->width/screenContext->meterperpixel;
	if(width < 1) 
		wRoad =1;
	else 
		wRoad = width;
	/* draw a road */
	lineColor.red = 179.0/255;
	lineColor.green = 166.0/255;
	lineColor.blue = 147.0/255;
	// for test, draw origpoints
	if (screenContext->debug) {
		p = aRoad->origPoints.head;
		gps_to_canvas(&screenContext->awin, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y, &point.x, &point.y);
		cairo_move_to(cr, point.x-screenContext->scr_x, point.y-screenContext->scr_y);
		p = p->next;
		while(p!=NULL) {
			gps_to_canvas(&screenContext->awin, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y, &point.x, &point.y);
			cairo_line_to(cr, point.x-screenContext->scr_x, point.y-screenContext->scr_y);
			p = p->next;
		}
		cairo_set_line_width(cr, wRoad+1);
		cairo_set_source_rgb(cr, lineColor.red, lineColor.green, lineColor.blue);
		cairo_stroke_preserve(cr);
		cairo_set_line_width(cr, wRoad);
		cairo_set_source_rgba(cr, fillColor->red/255.0, fillColor->green/255.0, fillColor->blue/255.0, fillColor->opacity/255.0);
		cairo_stroke(cr);
				
		p = aRoad->origPoints.head;
		gps_to_canvas(&screenContext->awin, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y, &point.x, &point.y);
		cairo_arc(cr,  (int)point.x-screenContext->scr_x, (int)point.y-screenContext->scr_y, 2, 0, 2*M_PI) ;
		cairo_set_source_rgb(cr, 0.2, 0.2, 0.8);
		cairo_fill(cr);
		p = p->next;
		while(p!=NULL) {
			gps_to_canvas(&screenContext->awin, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y, &point.x, &point.y);
			cairo_arc(cr,  (int)point.x-screenContext->scr_x, (int)point.y-screenContext->scr_y, 2, 0, 2*M_PI) ;
			cairo_set_source_rgb(cr, 0.2, 0.2, 0.8);
			cairo_fill(cr);
			p = p->next;
		}
	}
	// draw points on the road
	p = aRoad->points.head;
	gps_to_canvas(&screenContext->awin, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y, &point.x, &point.y);
	cairo_move_to(cr, point.x-screenContext->scr_x, point.y-screenContext->scr_y);
	dist = 0;
	p = p->next;
	while(p!=NULL) {
		gps_to_canvas(&screenContext->awin, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y, &point.x, &point.y);
		cairo_line_to(cr, point.x-screenContext->scr_x, point.y-screenContext->scr_y);
		d = distance_in_meter(((struct Point*)p->prev->datap)->x, ((struct Point*)p->prev->datap)->y, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y);
		if (dist < aRoad->length/2 && dist + d > aRoad->length/2) {
			gps_to_canvas(&screenContext->awin, (((struct Point*)p->prev->datap)->x+((struct Point*)p->datap)->x)/2, (((struct Point*)p->prev->datap)->y+((struct Point*)p->datap)->y)/2, &mp.x, &mp.y);
			angle = angle_between(((struct Point*)p->prev->datap)->x, ((struct Point*)p->prev->datap)->y, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y);
		} 
		dist += d;
		p = p->next;
	}
	cairo_set_line_width(cr, wRoad+1);
	cairo_set_source_rgb(cr, lineColor.red, lineColor.green, lineColor.blue);
	cairo_stroke_preserve(cr);
	cairo_set_line_width(cr, wRoad);
	cairo_set_source_rgba(cr, fillColor->red/255.0, fillColor->green/255.0, fillColor->blue/255.0, fillColor->opacity/255.0);
	cairo_stroke(cr);
			
	if (screenContext->debug) {
		p = aRoad->points.head;
		gps_to_canvas(&screenContext->awin, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y, &point.x, &point.y);
		cairo_arc(cr,  (int)point.x-screenContext->scr_x, (int)point.y-screenContext->scr_y, 2, 0, 2*M_PI) ;
		cairo_set_source_rgb(cr, 0.2, 0.2, 0.8);
		cairo_fill(cr);
		p = p->next;
		while(p!=NULL) {
			gps_to_canvas(&screenContext->awin, ((struct Point*)p->datap)->x, ((struct Point*)p->datap)->y, &point.x, &point.y);
			cairo_arc(cr,  (int)point.x-screenContext->scr_x, (int)point.y-screenContext->scr_y, 2, 0, 2*M_PI) ;
			cairo_set_source_rgb(cr, 0.2, 0.2, 0.8);
			cairo_fill(cr);
			p = p->next;
		}
	}
        // draw arrow
        if(screenContext->meterperpixel < 2.5) {
		cairo_set_line_width(cr, 1);
		cairo_set_source_rgb(cr, lineColor.red, lineColor.green, lineColor.blue);
		cairo_move_to(cr, mp.x+cos(M_PI*(90+angle)/180)*MARK_LENGTH/4-screenContext->scr_x, mp.y-sin(M_PI*(90+angle)/180)*MARK_LENGTH/4-screenContext->scr_y);
		cairo_line_to(cr, mp.x+cos(M_PI*angle/180)*MARK_LENGTH/2-screenContext->scr_x, mp.y-sin(M_PI*angle/180)*MARK_LENGTH/2-screenContext->scr_y);
		cairo_line_to(cr, mp.x+cos(M_PI*(270+angle)/180)*MARK_LENGTH/4-screenContext->scr_x, mp.y-sin(M_PI*(270+angle)/180)*MARK_LENGTH/4-screenContext->scr_y);
		cairo_stroke(cr);
		cairo_move_to(cr, mp.x+cos(M_PI*angle/180)*MARK_LENGTH/2-screenContext->scr_x, mp.y-sin(M_PI*angle/180)*MARK_LENGTH/2-screenContext->scr_y);
		cairo_line_to(cr, mp.x-cos(M_PI*angle/180)*MARK_LENGTH/2-screenContext->scr_x, mp.y+sin(M_PI*angle/180)*MARK_LENGTH/2-screenContext->scr_y);
		cairo_stroke(cr);
	}
}
Example #21
0
void Circle::draw() const {
    cairo_scale(cairoHandle_, 1, 0.7);
    cairo_arc(cairoHandle_,  center_.getX(), center_.getY(), radius_, 0, 2*M_PI);
    cairo_stroke_preserve(cairoHandle_);
}
Example #22
0
	void lime_cairo_stroke_preserve (value handle) {
		
		cairo_stroke_preserve ((cairo_t*)val_data (handle));
		
	}
Example #23
0
void draw_cells(struct ScreenContext *screenContext, cairo_t *cr)
{
	char buf[128];
	double transparent;
	struct Item *aItem;
	struct Point p1, p2;
	double cellsize, fontSize, fsize, fontX, fontY;
	cairo_text_extents_t extents;
  	struct Color fillColor, lineColor, fontColor;

	fillColor.red = 175.0/255;
	fillColor.green = 210.0/255;
	fillColor.blue = 235.0/255;

	lineColor.red = 140.0/255;
	lineColor.green = 145.0/255;
	lineColor.blue = 135.0/255;

	fontColor.red = 0/255;
	fontColor.green = 0/255;
	fontColor.blue = 0/255;

	transparent = 0.3;

	aItem = screenContext->surroundings.head;
	gps_to_canvas(&screenContext->awin, ((struct Cell*)aItem->datap)->box.xmin, ((struct Cell*)aItem->datap)->box.ymin, &p1.x, &p1.y);
	gps_to_canvas(&screenContext->awin, ((struct Cell*)aItem->datap)->box.xmax, ((struct Cell*)aItem->datap)->box.ymax, &p2.x, &p2.y);
	cellsize = p2.x - p1.x;
	while(aItem!=NULL) {
		gps_to_canvas(&screenContext->awin, ((struct Cell*)aItem->datap)->box.xmin, ((struct Cell*)aItem->datap)->box.ymin, &p1.x, &p1.y);
		fontX = p1.x-screenContext->scr_x, fontY = p1.y-screenContext->scr_y;
		cairo_move_to(cr, p1.x-screenContext->scr_x, p1.y-screenContext->scr_y);
		gps_to_canvas(&screenContext->awin, ((struct Cell*)aItem->datap)->box.xmin, ((struct Cell*)aItem->datap)->box.ymax, &p1.x, &p1.y);
		cairo_line_to(cr, p1.x-screenContext->scr_x, p1.y-screenContext->scr_y);
		gps_to_canvas(&screenContext->awin, ((struct Cell*)aItem->datap)->box.xmax, ((struct Cell*)aItem->datap)->box.ymax, &p1.x, &p1.y);
		cairo_line_to(cr, p1.x-screenContext->scr_x, p1.y-screenContext->scr_y);
		gps_to_canvas(&screenContext->awin, ((struct Cell*)aItem->datap)->box.xmax, ((struct Cell*)aItem->datap)->box.ymin, &p1.x, &p1.y);
		cairo_line_to(cr, p1.x-screenContext->scr_x, p1.y-screenContext->scr_y);
		cairo_close_path(cr);
		cairo_set_line_width(cr, 1);
		cairo_set_source_rgba(cr, lineColor.red, lineColor.green, lineColor.blue, transparent);
		cairo_stroke_preserve(cr);
		cairo_set_source_rgba(cr, fillColor.red, fillColor.green, fillColor.blue, transparent);
		cairo_fill(cr);

		sprintf(buf, "(%d, %d)", ((struct Cell*)aItem->datap)->xNumber, ((struct Cell*)aItem->datap)->yNumber);
		if (aItem == screenContext->surroundings.head) {
			fsize = 2*cellsize/(strlen(buf)+2);
			if (fsize > 25) fsize = 15;
			fontSize = fsize;
		} else
			fontSize = 0.75*fsize;

		if(fsize > 5) {
			fontX = fontX + fontSize*0.5;
			fontY = fontY + fontSize*0.5;
			cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
			cairo_set_font_size(cr, (int)fontSize);
			cairo_text_extents(cr, buf, &extents);
			cairo_set_source_rgba(cr, fontColor.red, fontColor.green, fontColor.blue, transparent);
			cairo_move_to(cr, fontX, fontY-extents.height);
			cairo_show_text(cr, buf);
		}
		aItem=aItem->next;
	}
}
static void render (cairo_t *pCairoContext, CairoDesklet *pDesklet)
{
	CDPanelParameters *pPanel = (CDPanelParameters *) pDesklet->pRendererData;
	//g_print ("%s(%x)\n", __func__, pPanel);
	if (pPanel == NULL)
		return ;
	
	double fRadius = pPanel->iRadius;
	double fLineWidth = pPanel->iLineWidth;
	double fOffsetX = fRadius + fLineWidth/2;
	double fOffsetY = fLineWidth/2;
	double fFrameWidth = pDesklet->container.iWidth - 2 * fRadius - fLineWidth;
	double fFrameHeight = pDesklet->container.iHeight - fLineWidth;
	// le cadre.
	cairo_set_line_width (pCairoContext, pPanel->iLineWidth);
	
	cairo_move_to (pCairoContext, fOffsetX, fOffsetY);
	
	cairo_rel_curve_to (pCairoContext,
		fFrameWidth/2, 0,
		fFrameWidth/2, pPanel->iMainIconSize,
		fFrameWidth, pPanel->iMainIconSize);
	
	//\_________________ Coin haut droit.
	cairo_rel_curve_to (pCairoContext,
		0, 0,
		fRadius, 0,
		fRadius, fRadius);
	cairo_rel_line_to (pCairoContext, 0, fFrameHeight - fRadius * 2 - pPanel->iMainIconSize);
	//\_________________ Coin bas droit.
	cairo_rel_curve_to (pCairoContext,
		0, 0,
		0, fRadius,
		-fRadius, fRadius);

	cairo_rel_line_to (pCairoContext, - fFrameWidth, 0);
	//\_________________ Coin bas gauche.
	cairo_rel_curve_to (pCairoContext,
		0, 0,
		-fRadius, 0,
		-fRadius, - fRadius);
	cairo_rel_line_to (pCairoContext, 0, - (fFrameHeight - fRadius * 2));
	//\_________________ Coin haut gauche.
	cairo_rel_curve_to (pCairoContext,
		0, 0,
		0, -fRadius,
		fRadius, -fRadius);
	
	cairo_set_source_rgba (pCairoContext, pPanel->fBgColor[0], pPanel->fBgColor[1], pPanel->fBgColor[2], 1.);
	cairo_stroke_preserve (pCairoContext);
	
	cairo_set_source_rgba (pCairoContext, pPanel->fBgColor[0], pPanel->fBgColor[1], pPanel->fBgColor[2], pPanel->fBgColor[3]);
	cairo_fill (pCairoContext);
	
	// les icones.
	Icon *pIcon;
	GList *ic;
	
	pIcon = pDesklet->pIcon;
	if (pIcon && pIcon->image.pSurface != NULL)
	{
		cairo_save (pCairoContext);
		
		cairo_translate (pCairoContext, pIcon->fDrawX, pIcon->fDrawY);
		
		cairo_dock_apply_image_buffer_surface_with_offset (&pIcon->image, pCairoContext, 0, 0, pIcon->fAlpha);
		
		cairo_dock_draw_icon_overlays_cairo (pIcon, pDesklet->container.fRatio, pCairoContext);
		
		cairo_restore (pCairoContext);
	}
	
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDesklet->icons);
	if (pFirstDrawnElement == NULL)
		return;
	ic = pFirstDrawnElement;
	do
	{
		pIcon = ic->data;
		if (pIcon->image.pSurface != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
		{
			cairo_save (pCairoContext);
			
			cairo_translate (pCairoContext, pIcon->fDrawX, pIcon->fDrawY);
			
			cairo_dock_apply_image_buffer_surface_with_offset (&pIcon->image, pCairoContext, 0, 0, pIcon->fAlpha);
			
			if (pIcon->label.pSurface != NULL)
			{
				cairo_save (pCairoContext);
				
				double fOffsetX = 0., fAlpha;
				if (pIcon->bPointed)
				{
					fAlpha = 1.;
					/**if (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2 > pDesklet->container.iWidth)
						fOffsetX = pDesklet->container.iWidth - (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2);
					if (pIcon->fDrawX + pIcon->fWidth/2 - pIcon->label.iWidth/2 < 0)
						fOffsetX = pIcon->label.iWidth/2 - (pIcon->fDrawX + pIcon->fWidth/2);
					cairo_set_source_surface (pCairoContext,
						pIcon->label.pSurface,
						fOffsetX + pIcon->fWidth/2 - pIcon->label.iWidth/2,
						-myIconsParam.iLabelSize);*/
					cairo_set_source_surface (pCairoContext,
						pIcon->label.pSurface,
						0.,
						-myIconsParam.iLabelSize);
					cairo_paint_with_alpha (pCairoContext, fAlpha);
				}
				else
				{
					fAlpha = .6;
					if (pIcon->label.iWidth > 2*pIcon->fWidth + 0 * myIconsParam.iLabelSize)
					{
						///fOffsetX = - myIconsParam.iLabelSize;
						cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (fOffsetX,
							0.,
							fOffsetX + 2*pIcon->fWidth + 0*myIconsParam.iLabelSize,
							0.);
						cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							0.,
							0.,
							0.,
							0.,
							fAlpha);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							0.75,
							0.,
							0.,
							0.,
							fAlpha);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							1.,
							0.,
							0.,
							0.,
							0.);
						cairo_set_source_surface (pCairoContext,
							pIcon->label.pSurface,
							fOffsetX,
							-myIconsParam.iLabelSize);
						cairo_mask (pCairoContext, pGradationPattern);
						cairo_pattern_destroy (pGradationPattern);
					}
					else
					{
						///fOffsetX = pIcon->fWidth/2 - pIcon->label.iWidth/2;
						cairo_set_source_surface (pCairoContext,
							pIcon->label.pSurface,
							fOffsetX,
							-myIconsParam.iLabelSize);
						cairo_paint_with_alpha (pCairoContext, fAlpha);
					}
				}
				
				cairo_restore (pCairoContext);
			}
			
			cairo_translate (pCairoContext,
				pIcon->fWidth,
				- pIcon->fHeight/2);  // not ideal, it should be vertically centered.
			cairo_dock_draw_icon_overlays_cairo (pIcon, pDesklet->container.fRatio, pCairoContext);
			
			cairo_restore (pCairoContext);
		}
		ic = cairo_dock_get_next_element (ic, pDesklet->icons);
	}
	while (ic != pFirstDrawnElement);
}
Example #25
0
int renderGlyphsCairo(imageObj *img,double x, double y, labelStyleObj *style, char *text) {
    cairo_renderer *r = CAIRO_RENDERER(img);
    cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img);
    faceCacheObj *face = getFontFace(cache,style->font);

    char *utfptr=text;
    int i,has_kerning,unicode;
    unsigned long previdx=0;
    int numglyphs = msGetNumGlyphs(text);
    cairo_glyph_t glyph;
    cairo_text_extents_t extents;
    double px=0,py=0;

    if(face == NULL) {
        return MS_FAILURE;
    }

    cairo_set_font_face(r->cr,face->face);
    cairo_set_font_size(r->cr,style->size*96/72.0);

    cairo_save(r->cr);
    cairo_translate(r->cr,MS_NINT(x),MS_NINT(y));
    if(style->rotation != 0.0)
       cairo_rotate(r->cr, -style->rotation);

    has_kerning = FT_HAS_KERNING((face->ftface));
    for(i=0;i<numglyphs;i++) {
        utfptr+=msUTF8ToUniChar(utfptr, &unicode);
        glyph.x=px;
        glyph.y=py;
        if(unicode=='\n') {
            py += ceil(style->size*CAIROLINESPACE);
            px = 0;
            previdx=0;
            continue;
        }
        glyph.index = FT_Get_Char_Index(face->ftface, unicode);
        if( has_kerning && previdx ) {
            FT_Vector delta;
            FT_Get_Kerning( face->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta );
            px += delta.x / 64.;
        }
        cairo_glyph_extents(r->cr,&glyph,1,&extents);
        cairo_glyph_path(r->cr,&glyph,1);
        px += extents.x_advance;
        previdx=glyph.index;
    }

    if (style->outlinewidth > 0) {
        cairo_save(r->cr);
        msCairoSetSourceColor(r->cr, style->outlinecolor);
        cairo_set_line_width(r->cr, style->outlinewidth + 1);
        cairo_stroke_preserve(r->cr);
        cairo_restore(r->cr);
    }
    if(style->color) {
        msCairoSetSourceColor(r->cr, style->color);
        cairo_fill(r->cr);
    }
    cairo_new_path(r->cr);
    cairo_restore(r->cr);
    return MS_SUCCESS;
}
Example #26
0
void
gimp_display_shell_render (GimpDisplayShell *shell,
                           cairo_t          *cr,
                           gint              x,
                           gint              y,
                           gint              w,
                           gint              h)
{
  GimpImage       *image;
  GeglBuffer      *buffer;
#ifdef USE_NODE_BLIT
  GeglNode        *node;
#endif
  gdouble          scale_x       = 1.0;
  gdouble          scale_y       = 1.0;
  gdouble          buffer_scale  = 1.0;
  gint             viewport_offset_x;
  gint             viewport_offset_y;
  gint             viewport_width;
  gint             viewport_height;
  gint             scaled_x;
  gint             scaled_y;
  gint             scaled_width;
  gint             scaled_height;
  cairo_surface_t *xfer;
  gint             xfer_src_x;
  gint             xfer_src_y;
  gint             mask_src_x = 0;
  gint             mask_src_y = 0;
  gint             cairo_stride;
  guchar          *cairo_data;
  GeglBuffer      *cairo_buffer;

  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
  g_return_if_fail (cr != NULL);
  g_return_if_fail (w > 0 && h > 0);

  image  = gimp_display_get_image (shell->display);
  buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image));
#ifdef USE_NODE_BLIT
  node   = gimp_projectable_get_graph (GIMP_PROJECTABLE (image));
#endif

#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
  /* if we had this future API, things would look pretty on hires (retina) */
  scale_x = gdk_window_get_scale_factor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell))));
#endif

  scale_x = MIN (scale_x, GIMP_DISPLAY_RENDER_MAX_SCALE);
  scale_y = scale_x;

  if (shell->scale_x > shell->scale_y)
    {
      scale_y *= (shell->scale_x / shell->scale_y);

      buffer_scale = shell->scale_y * scale_y;
    }
  else if (shell->scale_y > shell->scale_x)
    {
      scale_x *= (shell->scale_y / shell->scale_x);

      buffer_scale = shell->scale_x * scale_x;
    }
  else
    {
      buffer_scale = shell->scale_x * scale_x;
    }

  gimp_display_shell_scroll_get_scaled_viewport (shell,
                                                 &viewport_offset_x,
                                                 &viewport_offset_y,
                                                 &viewport_width,
                                                 &viewport_height);

  scaled_x      = floor ((x + viewport_offset_x) * scale_x);
  scaled_y      = floor ((y + viewport_offset_y) * scale_y);
  scaled_width  = ceil (w * scale_x);
  scaled_height = ceil (h * scale_y);

  if (shell->rotate_transform)
    {
      xfer = cairo_surface_create_similar_image (cairo_get_target (cr),
                                                 CAIRO_FORMAT_ARGB32,
                                                 scaled_width,
                                                 scaled_height);
      cairo_surface_mark_dirty (xfer);
      xfer_src_x = 0;
      xfer_src_y = 0;
    }
  else
    {
      xfer = gimp_display_xfer_get_surface (shell->xfer,
                                            scaled_width,
                                            scaled_height,
                                            &xfer_src_x,
                                            &xfer_src_y);
    }

  cairo_stride = cairo_image_surface_get_stride (xfer);
  cairo_data   = cairo_image_surface_get_data (xfer) +
                 xfer_src_y * cairo_stride + xfer_src_x * 4;

  cairo_buffer = gegl_buffer_linear_new_from_data (cairo_data,
                                                   babl_format ("cairo-ARGB32"),
                                                   GEGL_RECTANGLE (0, 0,
                                                                   scaled_width,
                                                                   scaled_height),
                                                   cairo_stride,
                                                   NULL, NULL);

  if (shell->profile_transform ||
      gimp_display_shell_has_filter (shell))
    {
      gboolean can_convert_to_u8;

      /*  if there is a profile transform or a display filter, we need
       *  to use temp buffers
       */

      can_convert_to_u8 = gimp_display_shell_profile_can_convert_to_u8 (shell);

      /*  create the filter buffer if we have filters
       */
      if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
          ! shell->filter_buffer)
        {
          gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
          gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;

          shell->filter_data =
            gegl_malloc (w * h * babl_format_get_bytes_per_pixel (shell->filter_format));

          shell->filter_stride =
            w * babl_format_get_bytes_per_pixel (shell->filter_format);

          shell->filter_buffer =
            gegl_buffer_linear_new_from_data (shell->filter_data,
                                              shell->filter_format,
                                              GEGL_RECTANGLE (0, 0, w, h),
                                              GEGL_AUTO_ROWSTRIDE,
                                              (GDestroyNotify) gegl_free,
                                              shell->filter_data);
        }

      if (shell->profile_transform)
        {
          /*  if there is a profile transform, load the projection
           *  pixels into the profile_buffer
           */
#ifndef USE_NODE_BLIT
          gegl_buffer_get (buffer,
                           GEGL_RECTANGLE (scaled_x, scaled_y,
                                           scaled_width, scaled_height),
                           buffer_scale,
                           gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
                           shell->profile_data, shell->profile_stride,
                           GEGL_ABYSS_CLAMP);
#else
          gegl_node_blit (node,
                          buffer_scale,
                          GEGL_RECTANGLE (scaled_x, scaled_y,
                                          scaled_width, scaled_height),
                          gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
                          shell->profile_data, shell->profile_stride,
                          GEGL_BLIT_CACHE);
#endif

          if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
            {
              /*  if there are filters, convert the pixels from the
               *  profile_buffer to the filter_buffer
               */
              gimp_display_shell_profile_convert_buffer (shell,
                                                         shell->profile_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height),
                                                         shell->filter_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height));
            }
          else
            {
              /*  otherwise, convert the profile_buffer directly into
               *  the cairo_buffer
               */
              gimp_display_shell_profile_convert_buffer (shell,
                                                         shell->profile_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height),
                                                         cairo_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height));
            }
        }
      else
        {
          /*  otherwise, load the projection pixels directly into the
           *  filter_buffer
           */
#ifndef USE_NODE_BLIT
          gegl_buffer_get (buffer,
                           GEGL_RECTANGLE (scaled_x, scaled_y,
                                           scaled_width, scaled_height),
                           buffer_scale,
                           shell->filter_format,
                           shell->filter_data, shell->filter_stride,
                           GEGL_ABYSS_CLAMP);
#else
          gegl_node_blit (node,
                          buffer_scale,
                          GEGL_RECTANGLE (scaled_x, scaled_y,
                                          scaled_width, scaled_height),
                          shell->filter_format,
                          shell->filter_data, shell->filter_stride,
                          GEGL_BLIT_CACHE);
#endif
        }

      if (gimp_display_shell_has_filter (shell))
        {
          /*  convert the filter_buffer in place
           */
          gimp_color_display_stack_convert_buffer (shell->filter_stack,
                                                   shell->filter_buffer,
                                                   GEGL_RECTANGLE (0, 0,
                                                                   scaled_width,
                                                                   scaled_height));
        }

      if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
        {
          /*  finally, copy the filter buffer to the cairo-ARGB32 buffer
           */
          gegl_buffer_get (shell->filter_buffer,
                           GEGL_RECTANGLE (0, 0,
                                           scaled_width,
                                           scaled_height),
                           1.0,
                           babl_format ("cairo-ARGB32"),
                           cairo_data, cairo_stride,
                           GEGL_ABYSS_CLAMP);
        }
    }
  else
    {
      /*  otherwise we can copy the projection pixels straight to the
       *  cairo-ARGB32 buffer
       */
#ifndef USE_NODE_BLIT
      gegl_buffer_get (buffer,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("cairo-ARGB32"),
                       cairo_data, cairo_stride,
                       GEGL_ABYSS_CLAMP);
#else
      gegl_node_blit (node,
                      buffer_scale,
                      GEGL_RECTANGLE (scaled_x, scaled_y,
                                      scaled_width, scaled_height),
                      babl_format ("cairo-ARGB32"),
                      cairo_data, cairo_stride,
                      GEGL_BLIT_CACHE);
#endif
    }

  g_object_unref (cairo_buffer);

  if (shell->mask)
    {
      if (! shell->mask_surface)
        {
          shell->mask_surface =
            cairo_image_surface_create (CAIRO_FORMAT_A8,
                                        GIMP_DISPLAY_RENDER_BUF_WIDTH  *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE,
                                        GIMP_DISPLAY_RENDER_BUF_HEIGHT *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE);
        }

      cairo_surface_mark_dirty (shell->mask_surface);

      cairo_stride = cairo_image_surface_get_stride (shell->mask_surface);
      cairo_data   = cairo_image_surface_get_data (shell->mask_surface) +
                     mask_src_y * cairo_stride + mask_src_x * 4;

      gegl_buffer_get (shell->mask,
                       GEGL_RECTANGLE (scaled_x - shell->mask_offset_x,
                                       scaled_y - shell->mask_offset_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("Y u8"),
                       cairo_data, cairo_stride,
                       GEGL_ABYSS_NONE);

      if (shell->mask_inverted)
        {
          gint mask_height = scaled_height;

          while (mask_height--)
            {
              gint    mask_width = scaled_width;
              guchar *d          = cairo_data;

              while (mask_width--)
                {
                  guchar inv = 255 - *d;

                  *d++ = inv;
                }

              cairo_data += cairo_stride;
            }
        }
    }

  /*  put it to the screen  */
  cairo_save (cr);

  cairo_rectangle (cr, x, y, w, h);

  cairo_scale (cr, 1.0 / scale_x, 1.0 / scale_y);

  cairo_set_source_surface (cr, xfer,
                            x * scale_x - xfer_src_x,
                            y * scale_y - xfer_src_y);

  if (shell->rotate_transform)
    {
      cairo_pattern_t *pattern;

      pattern = cairo_get_source (cr);
      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

      cairo_set_line_width (cr, 1.0);
      cairo_stroke_preserve (cr);

      cairo_surface_destroy (xfer);
    }

  cairo_clip (cr);
  cairo_paint (cr);

  if (shell->mask)
    {
      gimp_cairo_set_source_rgba (cr, &shell->mask_color);
      cairo_mask_surface (cr, shell->mask_surface,
                          (x - mask_src_x) * scale_x,
                          (y - mask_src_y) * scale_y);
    }

  cairo_restore (cr);
}
Example #27
0
EXPORT void stroke_preserve(cairo_t *context)
{
    cairo_stroke_preserve(context);
}
/*Function executes only if there is button press event*/
static gboolean button_press_event( GtkWidget      *widget,
                                    GdkEventButton *event )
{	
	int i;
	if (( event->button == 1) && SPLINE==0 && FILL==0 && line==0 && complete==0 && CENTER!=1 && RADIUS!=1&&CIRCLE==0)
	{
	    draw_brush (widget, event->x, event->y); 
	    return TRUE;
  	}
  
	if(SPLINE==1)
  	{
    	get_points_spline(widget, event);
    	return TRUE;
  	}
  
    if(CENTER==1)
    {
  		get_center(widget,event);
  		return TRUE;
    }
  
    if(RADIUS==1)
    {
  		get_radius(widget,event);
  		return TRUE;
    }
  
  	if(FILL==1)
  	{
    	floodfill_select(widget,event);
    	return TRUE;
  	}
  
  	if( complete == 1 )
  	{
    	if (event->button == 1 ) 
    	{
        	glob.coordx[glob.count] = event->x;         //stores the coordinates of present point
        	glob.coordy[glob.count] = event->y;
        	draw_brush (widget, event->x, event->y);
        	if(glob.count>0)
        	{
          		cr = gdk_cairo_create(widget->window);
	      		cairo_set_source_rgb(cr,red,green,blue);
          		cairo_set_line_width(cr, rec1);  
          			//moves to present point  
          			for( i = 0; i<=glob.count-1; i++ )                     
          			{ 
					   cairo_move_to(cr, glob.coordx[glob.count], glob.coordy[glob.count]);
         			   //line is made to previous point.
          			   cairo_line_to(cr, glob.coordx[i], glob.coordy[i]);
					   int end_x = glob.coordx[glob.count];
					   //present point coordinates stored in end_x.
					   int end_y = glob.coordy[glob.count];
					   int start_x = glob.coordx[i];
					   //coordinates of previously selected points.
					   int start_y = glob.coordy[i]; 
					   pixels[start_x][start_y]=1;
					   R[start_x][start_y]=red;
					   G[start_x][start_y]=green;
					   B[start_x][start_y]=blue;
					   int distance = sqrt(pow((end_x - start_x),2) + pow((end_y - start_y),2)); 
					   double slope = ((double)(end_y-start_y)/(double)(end_x-start_x));
					   int i,j;
					   for(i=start_x;i<=end_x;i++)
					   {
					  		j=(slope*i)-(slope*start_x)+(start_y);
					  		pixels[i][j]=1;
						  	pixels[i+1][j]=1;
						  	pixels[i-1][j]=1;
						  	pixels[i][j+1]=1;
						  	pixels[i][j-1]=1;
						  	pixels[i+2][j]=1;
						  	pixels[i-2][j]=1;
						  	pixels[i][j+2]=1;
						  	pixels[i][j-2]=1;
						  	R[i][j]=red;
						  	G[i][j]=green;
						  	B[i][j]=blue;
					  }
					  cairo_stroke(cr); 
          			}
          		} glob.count++;
          }
     }

  if( line == 1 )
  {
    if (event->button == 1 ) 
    {
        glob.coordx[glob.count] = event->x;
        glob.coordy[glob.count] = event->y;
        int end_x = event->x;
        // coordinates of present points
        int end_y = event->y;
        pixels[end_x][end_y]=1;
        R[end_x][end_y]=1;
		G[end_x][end_y]=1;
		B[end_x][end_y]=1;
        // this function shows the presently selected point.
        draw_brush (widget, event->x, event->y);
        if(glob.count>0)
        {
          cr = gdk_cairo_create(widget->window);
	      cairo_set_source_rgb(cr,red,green,blue);
	      //line colour is set
          cairo_set_line_width(cr, rec1);
          // line width is set rec1 is global variable
          // moved to present point
          cairo_move_to(cr, glob.coordx[glob.count], glob.coordy[glob.count]);
          // line is made to previous point
          cairo_line_to(cr, glob.coordx[glob.count-1], glob.coordy[glob.count-1]);
          line=0;
          gtk_label_set_text (GTK_LABEL(butlabel),"Pencil");
          int start_x = glob.coordx[glob.count-1];
          int start_y = glob.coordy[glob.count-1]; 
		  pixels[start_x][start_y]=1;
          R[start_x][start_y]=red;
		  G[start_x][start_y]=green;
		  B[start_x][start_y]=blue;
		  int distance = sqrt(pow((end_x - start_x),2) + pow((end_y - start_y),2)); 
		  double slope = ((double)(end_y-start_y)/(double)(end_x-start_x));
		  int i,j;
		  for(i=start_x;i<=end_x;i++)
		  {
		  	j=(slope*i)-(slope*start_x)+(start_y);
		  	pixels[i][j]=1;
		  	pixels[i+1][j]=1;
		  	pixels[i-1][j]=1;
		  	pixels[i][j+1]=1;
		  	pixels[i][j-1]=1;
		  	pixels[i+2][j]=1;
		  	pixels[i-2][j]=1;
		  	pixels[i][j+2]=1;
		  	pixels[i][j-2]=1;
		  	R[i][j]=red;
		  	G[i][j]=green;
		  	B[i][j]=blue;
		  }
		  cairo_stroke_preserve(cr);
          cairo_stroke(cr);
        }
        glob.count++;   
     }
     
    }
    
    if(CIRCLE==1)
    {
		cr=gdk_cairo_create(widget->window);
		cairo_set_source_rgb(cr, red, green, blue);
		cairo_set_line_width(cr,1);
		cairo_rectangle(cr, event->x,event->y, rec1, rec2);
		int X=event->x;
		int Y=event->y;
		R[X][Y]=red;
		B[X][Y]=blue;
		G[X][Y]=green;
		cairo_stroke_preserve(cr);
		cairo_fill(cr);
		return TRUE;
    }
    
}
Example #29
0
void
eda_cairo_stroke (cairo_t *cr, int flags, int line_type, int line_end,
                  double wwidth, double wlength, double wspace)
{
  double offset = 0;
  double dashes[4];
  double dummy = 0;
  cairo_line_cap_t cap;
  cairo_line_cap_t round_cap_if_legible = CAIRO_LINE_CAP_ROUND;
  int num_dashes;
  int iwidth;
  double width = wwidth, length = wlength, space = wspace;

  if (flags & EDA_CAIRO_ENABLE_HINTS) {
    width  = iwidth = screen_width (cr, wwidth);
    length = screen_width (cr, wlength);
    space  = screen_width (cr, wspace);
    cairo_device_to_user_distance (cr, &width, &dummy);
    cairo_device_to_user_distance (cr, &length, &dummy);
    cairo_device_to_user_distance (cr, &space, &dummy);

    offset = ((iwidth % 2) == 0) ? 0 : 0.5;

    round_cap_if_legible =
      (iwidth <= 1) ? CAIRO_LINE_CAP_SQUARE : CAIRO_LINE_CAP_ROUND;
  }

  cairo_set_line_width (cr, width);
  cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);

  switch (line_end) {
    case END_NONE:   cap = CAIRO_LINE_CAP_BUTT;   break;
    case END_SQUARE: cap = CAIRO_LINE_CAP_SQUARE; break;
    case END_ROUND:  cap = round_cap_if_legible;  break;
    default:
      g_warn_if_reached ();
      cap = CAIRO_LINE_CAP_BUTT;
    break;
  }

  switch (line_type) {

    default:
      g_warn_if_reached ();
      /* Fall through */

    case TYPE_SOLID:
      num_dashes = 0;

      cairo_set_dash (cr, dashes, num_dashes, 0.);
      cairo_set_line_cap (cr, cap);
      cairo_stroke (cr);
      break;

    case TYPE_DOTTED:
      dashes[0] = 0;                    /* DOT */
      dashes[1] = space;
      num_dashes = 2;

      cairo_set_dash (cr, dashes, num_dashes, offset);
      cairo_set_line_cap (cr, round_cap_if_legible);
      cairo_stroke (cr);
      break;

    case TYPE_DASHED:
      dashes[0] = length;               /* DASH */
      dashes[1] = space;
      num_dashes = 2;

      cairo_set_dash (cr, dashes, num_dashes, 0.);
      cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
      cairo_stroke (cr);
      break;

    case TYPE_CENTER:
      dashes[0] = length;               /* DASH */
      dashes[1] = 2 * space;
      num_dashes = 2;

      cairo_set_dash (cr, dashes, num_dashes, 0.);
      cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
      cairo_stroke_preserve (cr);

      dashes[0] = 0;                    /* DOT */
      dashes[1] = 2 * space + length;
      num_dashes = 2;

      cairo_set_dash (cr, dashes, num_dashes, -length - space + offset);
      cairo_set_line_cap (cr, round_cap_if_legible);
      cairo_stroke (cr);
      break;

    case TYPE_PHANTOM:
      dashes[0] = length;               /* DASH */
      dashes[1] = 3 * space;
      num_dashes = 2;

      cairo_set_dash (cr, dashes, num_dashes, 0.);
      cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
      cairo_stroke_preserve (cr);

      dashes[0] = 0;                    /* DOT */
      dashes[1] = space;
      dashes[2] = 0;                    /* DOT */
      dashes[3] = 2 * space + length;
      num_dashes = 4;

      cairo_set_dash (cr, dashes, num_dashes, -length - space + offset);
      cairo_set_line_cap (cr, round_cap_if_legible);
      cairo_stroke (cr);
      break;
  }

  cairo_set_dash (cr, NULL, 0, 0.);
}
Example #30
-1
static gboolean _lib_navigation_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data)
{
  dt_lib_module_t *self = (dt_lib_module_t *)user_data;
  dt_lib_navigation_t *d = (dt_lib_navigation_t *)self->data;

  const int inset = DT_NAVIGATION_INSET;
  GtkAllocation allocation;
  gtk_widget_get_allocation(widget, &allocation);
  int width = allocation.width, height = allocation.height;

  dt_develop_t *dev = darktable.develop;

  /* double buffering of image data: only take new data if valid */
  if(dev->preview_pipe->backbuf && dev->preview_status == DT_DEV_PIXELPIPE_VALID)
  {
    /* re-allocate in case of changed image dimensions */
    if(d->buffer == NULL || dev->preview_pipe->backbuf_width != d->wd || dev->preview_pipe->backbuf_height != d->ht)
    {
      g_free(d->buffer);
      d->wd = dev->preview_pipe->backbuf_width;
      d->ht = dev->preview_pipe->backbuf_height;
      d->buffer = g_malloc0((size_t)d->wd * d->ht * 4 * sizeof(unsigned char));
    }

    /* update buffer if new data is available */
    if(d->buffer && dev->preview_pipe->input_timestamp > d->timestamp)
    {
      dt_pthread_mutex_t *mutex = &dev->preview_pipe->backbuf_mutex;
      dt_pthread_mutex_lock(mutex);
      memcpy(d->buffer, dev->preview_pipe->backbuf, (size_t)d->wd * d->ht * 4 * sizeof(unsigned char));
      d->timestamp = dev->preview_pipe->input_timestamp;
      dt_pthread_mutex_unlock(mutex);
    }
  }

  /* get the current style */
  cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  cairo_t *cr = cairo_create(cst);

  GtkStyleContext *context = gtk_widget_get_style_context(widget);
  gtk_render_background(context, cr, 0, 0, allocation.width, allocation.height);

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

  /* draw navigation image if available */
  if(d->buffer)
  {
    cairo_save(cr);
    const int wd = d->wd;
    const int ht = d->ht;
    const float scale = fminf(width / (float)wd, height / (float)ht);

    const int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wd);
    cairo_surface_t *surface
        = cairo_image_surface_create_for_data(d->buffer, CAIRO_FORMAT_RGB24, wd, ht, stride);
    cairo_translate(cr, width / 2.0, height / 2.0f);
    cairo_scale(cr, scale, scale);
    cairo_translate(cr, -.5f * wd, -.5f * ht);

    // draw shadow around
    float alpha = 1.0f;
    for(int k = 0; k < 4; k++)
    {
      cairo_rectangle(cr, -k / scale, -k / scale, wd + 2 * k / scale, ht + 2 * k / scale);
      cairo_set_source_rgba(cr, 0, 0, 0, alpha);
      alpha *= 0.6f;
      cairo_fill(cr);
    }

    cairo_rectangle(cr, 0, 0, wd - 2, ht - 1);
    cairo_set_source_surface(cr, surface, 0, 0);
    cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST);
    cairo_fill(cr);
    cairo_surface_destroy(surface);

    // draw box where we are
    dt_dev_zoom_t zoom = dt_control_get_dev_zoom();
    int closeup = dt_control_get_dev_closeup();
    float zoom_x = dt_control_get_dev_zoom_x();
    float zoom_y = dt_control_get_dev_zoom_y();
    const float min_scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, closeup ? 2.0 : 1.0, 0);
    const float cur_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0);
    // avoid numerical instability for small resolutions:
    double h, w;
    if(cur_scale > min_scale)
    {
      float boxw = 1, boxh = 1;
      dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, &boxw, &boxh);
      cairo_translate(cr, wd * (.5f + zoom_x), ht * (.5f + zoom_y));
      cairo_set_source_rgb(cr, 0., 0., 0.);
      cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.f / scale));
      boxw *= wd;
      boxh *= ht;
      cairo_rectangle(cr, -boxw / 2 - 1, -boxh / 2 - 1, boxw + 2, boxh + 2);
      cairo_stroke(cr);
      cairo_set_source_rgb(cr, 1., 1., 1.);
      cairo_rectangle(cr, -boxw / 2, -boxh / 2, boxw, boxh);
      cairo_stroke(cr);
    }
    cairo_restore(cr);
    if(fabsf(cur_scale - min_scale) > 0.001f)
    {
      /* Zoom % */
      PangoLayout *layout;
      PangoRectangle ink;
      PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc);
      pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
      layout = pango_cairo_create_layout(cr);
      const float fontsize = DT_PIXEL_APPLY_DPI(11);
      pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE);
      pango_layout_set_font_description(layout, desc);
      cairo_translate(cr, 0, height);
      cairo_set_source_rgba(cr, 1., 1., 1., 0.5);
      cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);

      char zoomline[5];
      snprintf(zoomline, sizeof(zoomline), "%.0f%%", cur_scale * 100);

      pango_layout_set_text(layout, zoomline, -1);
      pango_layout_get_pixel_extents(layout, &ink, NULL);
      h = d->zoom_h = ink.height;
      w = d->zoom_w = ink.width;

      cairo_move_to(cr, width - w - h * 1.1 - ink.x, - fontsize);

      cairo_save(cr);
      cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0));

      GdkRGBA *color;
      gtk_style_context_get(context, gtk_widget_get_state_flags(widget), "background-color", &color, NULL);

      gdk_cairo_set_source_rgba(cr, color);
      pango_cairo_layout_path(cr, layout);
      cairo_stroke_preserve(cr);
      cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
      cairo_fill(cr);
      cairo_restore(cr);

      gdk_rgba_free(color);
      pango_font_description_free(desc);
      g_object_unref(layout);

    }
    else
    {
      // draw the zoom-to-fit icon
      cairo_translate(cr, 0, height);
      cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

      static int height = -1;
      if(height == -1)
      {
        PangoLayout *layout;
        PangoRectangle ink;
        PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc);
        pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
        layout = pango_cairo_create_layout(cr);
        pango_font_description_set_absolute_size(desc, DT_PIXEL_APPLY_DPI(11) * PANGO_SCALE);
        pango_layout_set_font_description(layout, desc);
        pango_layout_set_text(layout, "100%", -1); // dummy text, just to get the height
        pango_layout_get_pixel_extents(layout, &ink, NULL);
        height = ink.height;
        pango_font_description_free(desc);
        g_object_unref(layout);
      }

      h = d->zoom_h = height;
      w = h * 1.5;
      float sp = h * 0.6;
      d->zoom_w = w + sp;

      cairo_move_to(cr, width - w - h - sp, -1.0 * h);
      cairo_rectangle(cr, width - w - h - sp, -1.0 * h, w, h);
      cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
      cairo_fill(cr);

      cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0));

      cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
      cairo_move_to(cr, width - w * 0.8 - h - sp, -1.0 * h);
      cairo_line_to(cr, width - w - h - sp, -1.0 * h);
      cairo_line_to(cr, width - w - h - sp, -0.7 * h);
      cairo_stroke(cr);
      cairo_move_to(cr, width - w - h - sp, -0.3 * h);
      cairo_line_to(cr, width - w - h - sp, 0);
      cairo_line_to(cr, width - w * 0.8 - h - sp, 0);
      cairo_stroke(cr);
      cairo_move_to(cr, width - w * 0.2 - h - sp, 0);
      cairo_line_to(cr, width - h - sp, 0);
      cairo_line_to(cr, width - h - sp, -0.3 * h);
      cairo_stroke(cr);
      cairo_move_to(cr, width - h - sp, -0.7 * h);
      cairo_line_to(cr, width - h - sp, -1.0 * h);
      cairo_line_to(cr, width - w * 0.2 - h - sp, -1.0 * h);
      cairo_stroke(cr);
    }

    cairo_move_to(cr, width - 0.95 * h, -0.9 * h);
    cairo_line_to(cr, width - 0.05 * h, -0.9 * h);
    cairo_line_to(cr, width - 0.5 * h, -0.1 * h);
    cairo_fill(cr);
  }

  /* blit memsurface into widget */
  cairo_destroy(cr);
  cairo_set_source_surface(crf, cst, 0, 0);
  cairo_paint(crf);
  cairo_surface_destroy(cst);

  return TRUE;
}