Example #1
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_surface_t        *surface;
    cairo_t                *cr2;
    cairo_rectangle_list_t *rectangle_list;
    const char             *phase;
    cairo_bool_t            uses_clip_rects;
    
    surface = cairo_surface_create_similar (cairo_get_group_target (cr),
                                            CAIRO_CONTENT_COLOR, 100, 100);
    /* don't use cr accidentally */
    cr = NULL;
    cr2 = cairo_create (surface);
    cairo_surface_destroy (surface);

    /* Check the surface type so we ignore cairo_copy_clip_rectangle_list failures
     * on surface types that don't use rectangle lists for clipping.
     * Default to FALSE for the internal surface types, (meta, test-fallback, etc.)
     */
    switch (cairo_surface_get_type (surface)) {
    case CAIRO_SURFACE_TYPE_IMAGE:
    case CAIRO_SURFACE_TYPE_XLIB:
    case CAIRO_SURFACE_TYPE_XCB:
    case CAIRO_SURFACE_TYPE_GLITZ:
    case CAIRO_SURFACE_TYPE_WIN32:
    case CAIRO_SURFACE_TYPE_BEOS:
    case CAIRO_SURFACE_TYPE_DIRECTFB:
        uses_clip_rects = TRUE;
	break;
    case CAIRO_SURFACE_TYPE_QUARTZ:
    case CAIRO_SURFACE_TYPE_PDF:
    case CAIRO_SURFACE_TYPE_PS:
    case CAIRO_SURFACE_TYPE_SVG:
    case CAIRO_SURFACE_TYPE_OS2:
    default:
        uses_clip_rects = FALSE;
        break;
    }

    /* first, test basic stuff. This should not be clipped, it should
       return the surface rectangle. */
    phase = "No clip set";
    rectangle_list = cairo_copy_clip_rectangle_list (cr2);
    if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) ||
        !check_clip_extents (ctx, phase, cr2, 0, 0, 100, 100) ||
        !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 0, 0, 100, 100)) {
        cairo_rectangle_list_destroy (rectangle_list);
	return CAIRO_TEST_FAILURE;
    }
    cairo_rectangle_list_destroy (rectangle_list);

    /* Test simple clip rect. */
    phase = "Simple clip rect";
    cairo_save (cr2);
    cairo_rectangle (cr2, 10, 10, 80, 80);
    cairo_clip (cr2);
    rectangle_list = cairo_copy_clip_rectangle_list (cr2);
    if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) ||
        !check_clip_extents (ctx, phase, cr2, 10, 10, 80, 80) ||
        !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) {
        cairo_rectangle_list_destroy (rectangle_list);
	return CAIRO_TEST_FAILURE;
    }
    cairo_rectangle_list_destroy (rectangle_list);
    cairo_restore (cr2);

    /* Test everything clipped out. */
    phase = "All clipped out";
    cairo_save (cr2);
    cairo_clip (cr2);
    rectangle_list = cairo_copy_clip_rectangle_list (cr2);
    if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 0)) {
        cairo_rectangle_list_destroy (rectangle_list);
	return CAIRO_TEST_FAILURE;
    }
    cairo_rectangle_list_destroy (rectangle_list);
    cairo_restore (cr2);
    
    /* test two clip rects */
    phase = "Two clip rects";
    cairo_save (cr2);
    cairo_rectangle (cr2, 10, 10, 10, 10);
    cairo_rectangle (cr2, 20, 20, 10, 10);
    cairo_clip (cr2);
    cairo_rectangle (cr2, 15, 15, 10, 10);
    cairo_clip (cr2);
    rectangle_list = cairo_copy_clip_rectangle_list (cr2);
    if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 2) ||
        !check_clip_extents (ctx, phase, cr2, 15, 15, 10, 10) ||
        !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 15, 15, 5, 5) ||
        !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 20, 20, 5, 5)) {
        cairo_rectangle_list_destroy (rectangle_list);
	return CAIRO_TEST_FAILURE;
    }
    cairo_rectangle_list_destroy (rectangle_list);
    cairo_restore (cr2);

    /* test non-rectangular clip */
    phase = "Nonrectangular clip";
    cairo_save (cr2);
    cairo_move_to (cr2, 0, 0);
    cairo_line_to (cr2, 100, 100);
    cairo_line_to (cr2, 100, 0);
    cairo_close_path (cr2);
    cairo_clip (cr2);
    rectangle_list = cairo_copy_clip_rectangle_list (cr2);
     /* can't get this in one tight user-space rectangle */
    if (!check_unrepresentable (ctx, phase, rectangle_list) ||
        !check_clip_extents (ctx, phase, cr2, 0, 0, 100, 100)) {
        cairo_rectangle_list_destroy (rectangle_list);
	return CAIRO_TEST_FAILURE;
    }
    cairo_rectangle_list_destroy (rectangle_list);
    cairo_restore (cr2);
    
    phase = "User space, simple scale, getting clip with same transform";
    cairo_save (cr2);
    cairo_scale (cr2, 2, 2);
    cairo_rectangle (cr2, 5, 5, 40, 40);
    cairo_clip (cr2);
    rectangle_list = cairo_copy_clip_rectangle_list (cr2);
    if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) ||
        !check_clip_extents (ctx, phase, cr2, 5, 5, 40, 40) ||
        !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 5, 5, 40, 40)) {
        cairo_rectangle_list_destroy (rectangle_list);
	return CAIRO_TEST_FAILURE;
    }
    cairo_rectangle_list_destroy (rectangle_list);
    cairo_restore (cr2);

    phase = "User space, simple scale, getting clip with no transform";
    cairo_save (cr2);
    cairo_save (cr2);
    cairo_scale (cr2, 2, 2);
    cairo_rectangle (cr2, 5, 5, 40, 40);
    cairo_restore (cr2);
    cairo_clip (cr2);
    rectangle_list = cairo_copy_clip_rectangle_list (cr2);
    if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) ||
        !check_clip_extents (ctx, phase, cr2, 10, 10, 80, 80) ||
        !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) {
        cairo_rectangle_list_destroy (rectangle_list);
	return CAIRO_TEST_FAILURE;
    }
    cairo_rectangle_list_destroy (rectangle_list);
    cairo_restore (cr2);

    phase = "User space, rotation, getting clip with no transform";
    cairo_save (cr2);
    cairo_save (cr2);
    cairo_rotate (cr2, 12);
    cairo_rectangle (cr2, 5, 5, 40, 40);
    cairo_restore (cr2);
    cairo_clip (cr2);
    rectangle_list = cairo_copy_clip_rectangle_list (cr2);
    if (!check_unrepresentable (ctx, phase, rectangle_list)) {
        cairo_rectangle_list_destroy (rectangle_list);
	return CAIRO_TEST_FAILURE;
    }
    cairo_rectangle_list_destroy (rectangle_list);
    cairo_restore (cr2);

    cairo_destroy (cr2);
    return CAIRO_TEST_SUCCESS;
}
Example #2
0
static void
gtk_css_image_radial_draw (GtkCssImage *image,
                           cairo_t     *cr,
                           double       width,
                           double       height)
{
  GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
  cairo_pattern_t *pattern;
  cairo_matrix_t matrix;
  double x, y;
  double radius, yscale;
  double start, end;
  double r1, r2, r3, r4, r;
  double offset;
  int i, last;

  x = _gtk_css_position_value_get_x (radial->position, width);
  y = _gtk_css_position_value_get_y (radial->position, height);

  if (radial->circle)
    {
      switch (radial->size)
        {
        case GTK_CSS_EXPLICIT_SIZE:
          radius = _gtk_css_number_value_get (radial->sizes[0], width);
          break;
        case GTK_CSS_CLOSEST_SIDE:
          radius = MIN (MIN (x, width - x), MIN (y, height - y));
          break;
        case GTK_CSS_FARTHEST_SIDE:
          radius = MAX (MAX (x, width - x), MAX (y, height - y));
          break;
        case GTK_CSS_CLOSEST_CORNER:
        case GTK_CSS_FARTHEST_CORNER:
          r1 = x*x + y*y;
          r2 = x*x + (height - y)*(height - y);
          r3 = (width - x)*(width - x) + y*y;
          r4 = (width - x)*(width - x) + (height - y)*(height - y);
          if (radial->size == GTK_CSS_CLOSEST_CORNER)
            r = MIN ( MIN (r1, r2), MIN (r3, r4));
          else
            r = MAX ( MAX (r1, r2), MAX (r3, r4));
          radius = sqrt (r);
          break;
        default:
          g_assert_not_reached ();
        }

      radius = MAX (1.0, radius);
      yscale = 1.0;
    }
  else
    {
      double hradius, vradius;

      switch (radial->size)
        {
        case GTK_CSS_EXPLICIT_SIZE:
          hradius = _gtk_css_number_value_get (radial->sizes[0], width);
          vradius = _gtk_css_number_value_get (radial->sizes[1], height);
          break;
        case GTK_CSS_CLOSEST_SIDE:
          hradius = MIN (x, width - x);
          vradius = MIN (y, height - y);
          break;
        case GTK_CSS_FARTHEST_SIDE:
          hradius = MAX (x, width - x);
          vradius = MAX (y, height - y);
          break;
        case GTK_CSS_CLOSEST_CORNER:
          hradius = M_SQRT2 * MIN (x, width - x);
          vradius = M_SQRT2 * MIN (y, height - y);
          break;
        case GTK_CSS_FARTHEST_CORNER:
          hradius = M_SQRT2 * MAX (x, width - x);
          vradius = M_SQRT2 * MAX (y, height - y);
          break;
        default:
          g_assert_not_reached ();
        }

      hradius = MAX (1.0, hradius);
      vradius = MAX (1.0, vradius);

      radius = hradius;
      yscale = vradius / hradius;
    }

  gtk_css_image_radial_get_start_end (radial, radius, &start, &end);

  pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, radius);
  if (yscale != 1.0)
    {
      cairo_matrix_init_scale (&matrix, 1.0, 1.0 / yscale);
      cairo_pattern_set_matrix (pattern, &matrix);
    }

 if (radial->repeating)
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
  else
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

  offset = start;
  last = -1;
  for (i = 0; i < radial->stops->len; i++)
    {
      GtkCssImageRadialColorStop *stop;
      double pos, step;

      stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, i);

      if (stop->offset == NULL)
        {
          if (i == 0)
            pos = 0.0;
          else if (i + 1 == radial->stops->len)
            pos = 1.0;
          else
            continue;
        }
      else
        pos = _gtk_css_number_value_get (stop->offset, radius) / radius;

      pos = MAX (pos, 0);
      step = pos / (i - last);
      for (last = last + 1; last <= i; last++)
        {
          const GdkRGBA *rgba;

          stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, last);

          rgba = _gtk_css_rgba_value_get_rgba (stop->color);
          offset += step;

          cairo_pattern_add_color_stop_rgba (pattern,
                                             (offset - start) / (end - start),
                                             rgba->red,
                                             rgba->green,
                                             rgba->blue,
                                             rgba->alpha);
        }

      offset = pos;
      last = i;
    }

  cairo_rectangle (cr, 0, 0, width, height);
  cairo_translate (cr, x, y);
  cairo_set_source (cr, pattern);
  cairo_fill (cr);

  cairo_pattern_destroy (pattern);
}
Example #3
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 #4
0
static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context,
					  gint page_nr, gpointer user_data)
{
	DocInfo *dinfo = user_data;
	GeanyEditor *editor;
	cairo_t *cr;
	gdouble width, height;
	gdouble x = 0.0, y = 0.0;
	/*gint layout_h;*/
	gint count;
	GString *str;

	if (dinfo == NULL || page_nr >= dinfo->n_pages)
		return;

	editor = dinfo->doc->editor;

	if (dinfo->n_pages > 0)
	{
		gdouble fraction = (page_nr + 1) / (gdouble) dinfo->n_pages;
		gchar *text = g_strdup_printf(_("Page %d of %d"), page_nr, dinfo->n_pages);
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(main_widgets.progressbar), fraction);
		gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets.progressbar), text);
		g_free(text);
	}

#ifdef GEANY_PRINT_DEBUG
	geany_debug("draw_page = %d, pages = %d, (real) lines_per_page = %d",
		page_nr, dinfo->n_pages, dinfo->lines_per_page);
#endif

	str = g_string_sized_new(256);
	cr = gtk_print_context_get_cairo_context(context);
	width = gtk_print_context_get_width(context);
	height = gtk_print_context_get_height(context);

	cairo_set_source_rgb(cr, 0, 0, 0);
#ifdef GEANY_PRINT_DEBUG
	cairo_set_line_width(cr, 0.2);
	cairo_rectangle(cr, 0, 0, width, height);
	cairo_stroke(cr);
#endif
	cairo_move_to(cr, 0, 0);

	pango_layout_set_width(dinfo->layout, width * PANGO_SCALE);
	pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_LEFT);
	pango_layout_set_ellipsize(dinfo->layout, FALSE);
	pango_layout_set_justify(dinfo->layout, FALSE);

	if (printing_prefs.print_page_header)
		add_page_header(dinfo, cr, width, page_nr);

	count = 0;	/* the actual line counter for the current page, might be different from
				 * dinfo->cur_line due to possible line breaks */
	while (count < dinfo->lines_per_page)
	{
		gchar c = 'a';
		gint style = -1;
		PangoAttrList *layout_attr;
		PangoAttribute *attr;
		gint colours[3] = { 0 };
		gboolean add_linenumber = TRUE;
		gboolean at_eol;

		while (count < dinfo->lines_per_page && c != '\0')
		{
			at_eol = FALSE;

			g_string_erase(str, 0, str->len); /* clear the string */

			/* line numbers */
			if (printing_prefs.print_line_numbers && add_linenumber)
			{
				/* if we had a wrapped line on the last page which needs to be continued, don't
				 * add a line number */
				if (dinfo->long_line)
				{
					add_linenumber = FALSE;
				}
				else
				{
					gchar *line_number = NULL;
					gint cur_line_number_margin = get_line_numbers_arity(dinfo->cur_line + 1);
					gchar *fill = g_strnfill(
						dinfo->max_line_number_margin - cur_line_number_margin - 1, ' ');

					line_number = g_strdup_printf("%s%d ", fill, dinfo->cur_line + 1);
					g_string_append(str, line_number);
					dinfo->cur_line++; /* increase document line */
					add_linenumber = FALSE;
					style = STYLE_LINENUMBER;
					c = 'a'; /* dummy value */
					g_free(fill);
					g_free(line_number);
				}
			}
			/* data */
			else
			{
				style = sci_get_style_at(dinfo->doc->editor->sci, dinfo->cur_pos);
				c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
				if (c == '\0' || style == -1)
				{	/* if c gets 0, we are probably out of document boundaries,
					 * so stop to break out of outer loop */
					count = dinfo->lines_per_page;
					break;
				}
				dinfo->cur_pos++;

				/* convert tabs to spaces which seems to be better than using Pango tabs */
				if (c == '\t')
				{
					gint tab_width = sci_get_tab_width(editor->sci);
					gchar *s = g_strnfill(tab_width, ' ');
					g_string_append(str, s);
					g_free(s);
				}
				/* don't add line breaks, they are handled manually below */
				else if (c == '\r' || c == '\n')
				{
					gchar c_next = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
					at_eol = TRUE;
					if (c == '\r' && c_next == '\n')
						dinfo->cur_pos++; /* skip LF part of CR/LF */
				}
				else
				{
					g_string_append_c(str, c); /* finally add the character */

					/* handle UTF-8: since we add char by char (better: byte by byte), we need to
					 * keep UTF-8 characters together(e.g. two bytes for one character)
					 * the input is always UTF-8 and c is signed, so all non-Ascii
					 * characters are less than 0 and consist of all bytes less than 0.
					 * style doesn't change since it is only one character with multiple bytes. */
					while (c < 0)
					{
						c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
						if (c < 0)
						{	/* only add the byte when it is part of the UTF-8 character
							 * otherwise we could add e.g. a '\n' and it won't be visible in the
							 * printed document */
							g_string_append_c(str, c);
							dinfo->cur_pos++;
						}
					}
				}
			}

			if (! at_eol)
			{
				/* set text */
				pango_layout_set_text(dinfo->layout, str->str, -1);
				/* attributes */
				layout_attr = pango_attr_list_new();
				/* foreground colour */
				get_rgb_values(dinfo->styles[style][FORE], &colours[0], &colours[1], &colours[2]);
				attr = pango_attr_foreground_new(colours[0], colours[1], colours[2]);
				ADD_ATTR(layout_attr, attr);
				/* background colour */
				get_rgb_values(dinfo->styles[style][BACK], &colours[0], &colours[1], &colours[2]);
				attr = pango_attr_background_new(colours[0], colours[1], colours[2]);
				ADD_ATTR(layout_attr, attr);
				/* bold text */
				if (dinfo->styles[style][BOLD])
				{
					attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
					ADD_ATTR(layout_attr, attr);
				}
				/* italic text */
				if (dinfo->styles[style][ITALIC])
				{
					attr = pango_attr_style_new(PANGO_STYLE_ITALIC);
					ADD_ATTR(layout_attr, attr);
				}
				pango_layout_set_attributes(dinfo->layout, layout_attr);
				pango_layout_context_changed(dinfo->layout);
				pango_attr_list_unref(layout_attr);
			}

			cairo_get_current_point(cr, &x, &y);


			/* normal line break at eol character in document */
			if (at_eol)
			{
				/*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/
				/*cairo_move_to(cr, 0, y + (gdouble)layout_h / PANGO_SCALE);*/
				cairo_move_to(cr, 0, y + dinfo->line_height);

				count++;
				/* we added a new document line so request a new line number */
				add_linenumber = TRUE;
			}
			else
			{
				gint x_offset = 0;
				/* maybe we need to force a line break because of too long line */
				if (x >= (width - dinfo->font_width))
				{
					/* don't start the line at horizontal origin because we need to skip the
					 * line number margin */
					if (printing_prefs.print_line_numbers)
					{
						x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width;
					}

					/*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/
					/*cairo_move_to(cr, x_offset, y + (gdouble)layout_h / PANGO_SCALE);*/
					/* this is faster but not exactly the same as above */
					cairo_move_to(cr, x_offset, y + dinfo->line_height);
					cairo_get_current_point(cr, &x, &y);
					count++;
				}
				if (count < dinfo->lines_per_page)
				{
					/* str->len is counted in bytes not characters, so use g_utf8_strlen() */
					x_offset = (g_utf8_strlen(str->str, -1) * dinfo->font_width);

					if (dinfo->long_line && count == 0)
					{
						x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width;
						dinfo->long_line = FALSE;
					}

					pango_cairo_show_layout(cr, dinfo->layout);
					cairo_move_to(cr, x + x_offset, y);
				}
				else
				/* we are on a wrapped line but we are out of lines on this page, so continue
				 * the current line on the next page and remember to continue in current line */
					dinfo->long_line = TRUE;
			}
		}
	}

	if (printing_prefs.print_line_numbers)
	{	/* print a thin line between the line number margin and the data */
		gint y_start = 0;

		if (printing_prefs.print_page_header)
			y_start = (dinfo->line_height * 3) - 2;	/* "- 2": to connect the line number line to
													 * the page header frame */

		cairo_set_line_width(cr, 0.3);
		cairo_move_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1, y_start);
		cairo_line_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1,
			y + dinfo->line_height); /* y is last added line, we reuse it */
		cairo_stroke(cr);
	}

	if (printing_prefs.print_page_numbers)
	{
		gchar *line = g_strdup_printf("<small>- %d -</small>", page_nr + 1);
		pango_layout_set_markup(dinfo->layout, line, -1);
		pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_CENTER);
		cairo_move_to(cr, 0, height - dinfo->line_height);
		pango_cairo_show_layout(cr, dinfo->layout);
		g_free(line);

#ifdef GEANY_PRINT_DEBUG
		cairo_set_line_width(cr, 0.3);
		cairo_move_to(cr, 0, height - (1.25 * dinfo->line_height));
		cairo_line_to(cr, width - 1, height - (1.25 * dinfo->line_height));
		cairo_stroke(cr);
#endif
	}
	g_string_free(str, TRUE);
}
Example #5
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 #6
0
static gboolean
gimp_fg_bg_view_expose (GtkWidget      *widget,
                        GdkEventExpose *eevent)
{
  GimpFgBgView *view   = GIMP_FG_BG_VIEW (widget);
  GtkStyle     *style  = gtk_widget_get_style (widget);
  GdkWindow    *window = gtk_widget_get_window (widget);
  cairo_t      *cr;
  GtkAllocation allocation;
  gint          rect_w, rect_h;
  GimpRGB       color;

  if (! gtk_widget_is_drawable (widget))
    return FALSE;

  cr = gdk_cairo_create (eevent->window);

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

  gtk_widget_get_allocation (widget, &allocation);

  cairo_translate (cr, allocation.x, allocation.y);

  rect_w = allocation.width  * 3 / 4;
  rect_h = allocation.height * 3 / 4;

  if (! view->transform)
    gimp_fg_bg_view_create_transform (view);

  /*  draw the background area  */

  if (view->context)
    {
      gimp_context_get_background (view->context, &color);

      if (view->transform)
        gimp_color_transform_process_pixels (view->transform,
                                             babl_format ("R'G'B'A double"),
                                             &color,
                                             babl_format ("R'G'B'A double"),
                                             &color,
                                             1);

      gimp_cairo_set_source_rgb (cr, &color);

      cairo_rectangle (cr,
                       allocation.width  - rect_w + 1,
                       allocation.height - rect_h + 1,
                       rect_w - 2,
                       rect_h - 2);
      cairo_fill (cr);
    }

  gtk_paint_shadow (style, window, GTK_STATE_NORMAL,
                    GTK_SHADOW_IN,
                    NULL, widget, NULL,
                    allocation.x + allocation.width  - rect_w,
                    allocation.y + allocation.height - rect_h,
                    rect_w, rect_h);

  /*  draw the foreground area  */

  if (view->context)
    {
      gimp_context_get_foreground (view->context, &color);

      if (view->transform)
        gimp_color_transform_process_pixels (view->transform,
                                             babl_format ("R'G'B'A double"),
                                             &color,
                                             babl_format ("R'G'B'A double"),
                                             &color,
                                             1);

      gimp_cairo_set_source_rgb (cr, &color);

      cairo_rectangle (cr, 1, 1, rect_w - 2, rect_h - 2);
      cairo_fill (cr);
    }

  gtk_paint_shadow (style, window, GTK_STATE_NORMAL,
                    GTK_SHADOW_OUT,
                    NULL, widget, NULL,
                    allocation.x, allocation.y, rect_w, rect_h);

  cairo_destroy (cr);

  return TRUE;
}
Example #7
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 / 255.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, sizeof(exifline));

  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 #8
0
static cairo_test_status_t
column_triangles (cairo_t *cr, int width, int height)
{
    int x, y, i, channel;

    state = 0x12345678;

    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
    cairo_paint (cr);

#if GENERATE_REFERENCE
    for (x = 0; x < WIDTH; x++) {
	cairo_set_source_rgba (cr, 1, 1, 1, x * 0.5 / WIDTH);
	cairo_rectangle (cr, x, 0, 1, HEIGHT);
	cairo_fill (cr);
    }
#else
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
    for (channel = 0; channel < 3; channel++) {
	switch (channel) {
	default:
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
	}

	for (x = 0; x < WIDTH; x++) {
	    double step = x / (double) (2 * WIDTH);
	    for (y = 0; y < HEIGHT; y++) {
		for (i = 0; i < PRECISION; i++) {
		    double dy = random_offset (WIDTH - x, FALSE);

		    /*
		     * We want to test some sharing of edges to further
		     * stress the rasterisers, so instead of using one
		     * tall triangle, it is split into two, with vertical
		     * edges on either side that may co-align with their
		     * neighbours:
		     *
		     *  s ---  .      ---
		     *  t  |   |\      |
		     *  e  |   | \     |
		     *  p ---  ....    |  2 * step = x / WIDTH
		     *          \ |    |
		     *           \|    |
		     *            .   ---
		     *        |---|
		     *     1 / PRECISION
		     *
		     * Each column contains two triangles of width one quantum and
		     * total height of (x / WIDTH), thus the total area covered by all
		     * columns in each pixel is .5 * (x / WIDTH).
		     */

		    cairo_move_to (cr, x + i / (double) PRECISION, y + dy);
		    cairo_rel_line_to (cr, 0, step);
		    cairo_rel_line_to (cr, 1 / (double) PRECISION, step);
		    cairo_rel_line_to (cr, 0, -step);
		    cairo_close_path (cr);
		}
		cairo_fill (cr); /* do these per-pixel due to the extra volume of edges */
	    }
	}
    }
#endif

    return CAIRO_TEST_SUCCESS;
}
static void
eom_print_preview_draw (EomPrintPreview *preview, cairo_t *cr)
{
	EomPrintPreviewPrivate *priv;
	GtkWidget *area;
	GtkAllocation allocation;
	gint x0, y0;
	GtkStyle *style;
	gboolean has_focus;

	priv = preview->priv;
	area = priv->area;

	has_focus = gtk_widget_has_focus (area);

	style = gtk_widget_get_style (area);

	gtk_widget_get_allocation (area, &allocation);

	/* draw the page */
 	gdk_cairo_set_source_color (cr, &style->white);
 	cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
 	cairo_fill (cr);

	/* draw the page margins */
	gdk_cairo_set_source_color (cr, &style->black);
	cairo_set_line_width (cr, 0.1);
	cairo_rectangle (cr,
			 priv->l_rmargin, priv->t_rmargin,
			 allocation.width - priv->l_rmargin - priv->r_rmargin,
			 allocation.height - priv->t_rmargin - priv->b_rmargin);
	cairo_stroke (cr);

	get_current_image_coordinates (preview, &x0, &y0);

	if (priv->flag_create_surface) {
		create_surface (preview);
	}

	if (priv->surface) {
		cairo_set_source_surface (cr, priv->surface, x0, y0);
		cairo_paint (cr);
	} else if (priv->image_scaled) {
		/* just in the remote case we don't have the surface */

		/* adjust (x0, y0) to the new scale */
		gdouble scale = priv->i_scale * priv->p_scale *
			gdk_pixbuf_get_width (priv->image) / gdk_pixbuf_get_width (priv->image_scaled);
		x0 /= scale;
		y0 /= scale;

		cairo_scale (cr, scale, scale);
		gdk_cairo_set_source_pixbuf (cr, priv->image_scaled, x0, y0);
		cairo_paint (cr);
	} else if (priv->image) {
		/* just in the remote case we don't have the surface */

		/* adjust (x0, y0) to the new scale */
		x0 /=  priv->i_scale * priv->p_scale;
		y0 /=  priv->i_scale * priv->p_scale;

		cairo_scale (cr, priv->i_scale*priv->p_scale, priv->i_scale*priv->p_scale);
		gdk_cairo_set_source_pixbuf (cr, priv->image, x0, y0);
		cairo_paint (cr);
	}

	if (has_focus) {
		gtk_paint_focus (style, gtk_widget_get_window (area),
				 GTK_STATE_NORMAL, NULL, NULL, NULL,
				 0, 0, allocation.width, allocation.height);
	}
}
Example #10
0
/**
 * ags_note_edit_draw_position:
 * @note_edit: the #AgsNoteEdit
 * @cr: the #cairo_t surface
 *
 * Draws the cursor.
 *
 * Since: 0.4
 */
void
ags_note_edit_draw_position(AgsNoteEdit *note_edit, cairo_t *cr)
{
  guint selected_x, selected_y;
  guint x_offset[2], y_offset[2];
  guint x, y, width, height;
  gint size_width, size_height;

  selected_x = note_edit->selected_x * note_edit->control_unit.control_width;
  selected_y = note_edit->selected_y * note_edit->control_height;

  size_width = GTK_WIDGET(note_edit->drawing_area)->allocation.width;
  size_height = GTK_WIDGET(note_edit->drawing_area)->allocation.height;

  x_offset[0] = (guint) gtk_range_get_value(GTK_RANGE(note_edit->hscrollbar));
  x_offset[1] = x_offset[0] + (guint) size_width;

  y_offset[0] = (guint) gtk_range_get_value(GTK_RANGE(note_edit->vscrollbar));
  y_offset[1] = y_offset[0] + (guint) size_height;

  /* calculate horizontally values */
  if(selected_x < x_offset[0]){
    if(selected_x + note_edit->control_current.control_width > x_offset[0]){
      x = 0;
      width = selected_x + note_edit->control_current.control_width - x_offset[0];
    }else{
      return;
    }
  }else if(selected_x > x_offset[1]){
    return;
  }else{
    x = selected_x - x_offset[0];

    if(selected_x + note_edit->control_current.control_width < x_offset[1]){
      width = note_edit->control_current.control_width;
    }else{
      width = x_offset[1] - (selected_x + note_edit->control_current.control_width);
    }
  }

  /* calculate vertically values */
  if(selected_y < y_offset[0]){
    if(selected_y + note_edit->control_height > y_offset[0]){
      y = 0;
      height = selected_y + note_edit->control_height - y_offset[0];
    }else{
      return;
    }
  }else if(selected_y > y_offset[1]){
    return;
  }else{
    y = selected_y - y_offset[0];

    if(selected_y + note_edit->control_height < y_offset[1]){
      height = note_edit->control_height;
    }else{
      height = y_offset[1] - (selected_y + note_edit->control_height);
    }
  }

  /* draw */
  cairo_set_source_rgba(cr, 0.25, 0.5, 1.0, 0.5);
  cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
  cairo_fill(cr);
}
Example #11
0
/**
 * ags_note_edit_draw_notation:
 * @note_edit: the #AgsNoteEdit
 * @cr: the #cairo_t surface
 *
 * Draw the #AgsNotation of selected #AgsMachine on @note_edit.
 *
 * Since: 0.4
 */
void
ags_note_edit_draw_notation(AgsNoteEdit *note_edit, cairo_t *cr)
{
  AgsMachine *machine;
  AgsEditor *editor;
  GtkWidget *widget;
  AgsNote *note;
  GList *list_notation, *list_note;
  guint x_offset;
  guint control_height;
  guint x, y, width, height;
  gint selected_channel;
  gint i;

  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit),
						 AGS_TYPE_EDITOR);

  if(editor->selected_machine == NULL ||
     (machine = editor->selected_machine) == NULL ||
     machine->audio->notation == NULL)
    return;

  widget = (GtkWidget *) note_edit->drawing_area;

  cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);

  i = 0;

  while((selected_channel = ags_notebook_next_active_tab(editor->notebook,
							 i)) != -1){
    list_notation = g_list_nth(machine->audio->notation,
			       selected_channel);
    list_note = AGS_NOTATION(list_notation->data)->notes;

    control_height = note_edit->control_height - 2 * note_edit->control_margin_y;

    x_offset = (guint) GTK_RANGE(note_edit->hscrollbar)->adjustment->value;

    /* draw controls smaller than note_edit->nth_x */
    while(list_note != NULL && (note = (AgsNote *) list_note->data)->x[0] < note_edit->control_unit.nth_x){
      if(note->x[1] >= note_edit->control_unit.nth_x){
	if(note->y >= note_edit->nth_y && note->y <= note_edit->stop_y){
	  x = 0;
	  y = (note->y - note_edit->nth_y) * note_edit->control_height + note_edit->y0 + note_edit->control_margin_y;

	  width = (guint) ((double) note->x[1] * note_edit->control_unit.control_width - (double) x_offset);

	  if(width > widget->allocation.width)
	    width = widget->allocation.width;

	  height = control_height;

	  /* draw note */
	  cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	  cairo_fill(cr);

	  /* check if note is selected */
	  if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){
	    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7);

	    cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	    cairo_stroke(cr);

	    cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	  }
	}else if(note->y == (note_edit->nth_y - 1) && note_edit->y0 != 0){
	  if(note_edit->y0 > note_edit->control_margin_y){
	    x = 0;
	    width = (guint) ((double) note->x[1] * (double) note_edit->control_unit.control_width - x_offset);

	    if(width > widget->allocation.width)
	      width = widget->allocation.width;

	    if(note_edit->y0 > control_height + note_edit->control_margin_y){
	      y = note_edit->y0 - (control_height + note_edit->control_margin_y);
	      height = control_height;
	    }else{
	      y = 0;
	      height = note_edit->y0 - note_edit->control_margin_y;
	    }

	    /* draw note */
	    cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	    cairo_fill(cr);

	    /* check if note is selected */
	    if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){
	      cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7);
	    
	      cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	      cairo_stroke(cr);
	    
	      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	    }
	  }
	}else if(note->y == (note_edit->stop_y + 1) && note_edit->y1 != 0){
	  if(note_edit->y1 > note_edit->control_margin_y){
	    x = 0;
	    width = note->x[1] * note_edit->control_unit.control_width - x_offset;

	    if(width > widget->allocation.width)
	      width = widget->allocation.width;

	    y = (note->y - note_edit->nth_y) * note_edit->control_height + note_edit->control_margin_y;

	    if(note_edit->y1 > control_height + note_edit->control_margin_y){
	      height = control_height;
	    }else{
	      height = note_edit->y1 - note_edit->control_margin_y;
	    }

	    /* draw note */
	    cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	    cairo_fill(cr);
	  
	    /* check if note is selected */
	    if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){
	      cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7);
	    
	      cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	      cairo_stroke(cr);
	    
	      cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	    }
	  }
	}
      }

      list_note = list_note->next;
    }

    /* draw controls equal or greater than note_edit->nth_x */
    while(list_note != NULL && (note = (AgsNote *) list_note->data)->x[0] <= note_edit->control_unit.stop_x){
      if(note->y >= note_edit->nth_y && note->y <= note_edit->stop_y){
	x = (guint) note->x[0] * note_edit->control_unit.control_width;
	y = (note->y - note_edit->nth_y) * note_edit->control_height +
	  note_edit->y0 +
	  note_edit->control_margin_y;

	width = note->x[1] * note_edit->control_unit.control_width - x;
	x -= x_offset;

	if(x + width > widget->allocation.width)
	  width = widget->allocation.width - x;

	height = control_height;

	/* draw note*/
	cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	cairo_fill(cr);

	/* check if note is selected */
	if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){
	  cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7);
	
	  cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	  cairo_stroke(cr);
	
	  cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	}
      }else if(note->y == (note_edit->nth_y - 1) && note_edit->y0 != 0){
	if(note_edit->y0 > note_edit->control_margin_y){
	  x = note->x[0] * note_edit->control_unit.control_width - x_offset;
	  width = note->x[1] * note_edit->control_unit.control_width - x_offset - x;
      
	  if(x + width > widget->allocation.width)
	    width = widget->allocation.width - x;

	  if(note_edit->y0 > control_height + note_edit->control_margin_y){
	    y = note_edit->y0 - (control_height + note_edit->control_margin_y);
	    height = control_height;
	  }else{
	    y = 0;
	    height = note_edit->y0 - note_edit->control_margin_y;
	  }

	  /* draw note */
	  cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	  cairo_fill(cr);

	  /* check if note is selected */
	  if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){
	    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7);

	    cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	    cairo_stroke(cr);

	    cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	  }
	}
      }else if(note->y == (note_edit->stop_y + 1) && note_edit->y1 != 0){
	if(note_edit->y1 > note_edit->control_margin_y){
	  x = note->x[0] * note_edit->control_unit.control_width - x_offset;
	  width = note->x[1] * note_edit->control_unit.control_width - x_offset - x;
      
	  if(x + width > widget->allocation.width)
	    width = widget->allocation.width - x;

	  y = (note->y - note_edit->nth_y) * note_edit->control_height + note_edit->control_margin_y;

	  if(note_edit->y1 > control_height + note_edit->control_margin_y){
	    height = control_height;
	  }else{
	    height = note_edit->y1 - note_edit->control_margin_y;
	  }

	  /* draw note */
	  cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	  cairo_fill(cr);

	  /* check if note is selected */
	  if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){
	    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7);

	    cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height);
	    cairo_stroke(cr);

	    cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	  }
	}
      }

      list_note = list_note->next;
    }

    i++;
  }
}
Example #12
0
/**
 * ags_note_edit_draw_segment:
 * @note_edit: the #AgsNoteEdit
 * @cr: the #cairo_t surface
 *
 * Draws horizontal and vertical lines.
 *
 * Since: 0.4
 */
void
ags_note_edit_draw_segment(AgsNoteEdit *note_edit, cairo_t *cr)
{
  AgsEditor *editor;
  GtkWidget *widget;

  double tact;
  guint i, j;
  guint j_set;

  widget = (GtkWidget *) note_edit->drawing_area;

  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit),
						 AGS_TYPE_EDITOR);

  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
  cairo_rectangle(cr, 0.0, 0.0, (double) widget->allocation.width, (double) widget->allocation.height);
  cairo_fill(cr);

  cairo_set_line_width(cr, 1.0);

  cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);

  for(i = note_edit->y0 ; i < note_edit->height;){
    cairo_move_to(cr, 0.0, (double) i);
    cairo_line_to(cr, (double) note_edit->width, (double) i);
    cairo_stroke(cr);

    i += note_edit->control_height;
  }

  cairo_move_to(cr, 0.0, (double) i);
  cairo_line_to(cr, (double) note_edit->width, (double) i);
  cairo_stroke(cr);

  tact = exp2((double) gtk_combo_box_get_active(editor->toolbar->zoom) - 4.0);

  i = note_edit->control_current.x0;
  
  if(i < note_edit->width &&
     tact > 1.0 ){
    j_set = note_edit->control_current.nth_x % ((guint) tact);
    cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);

    if(j_set != 0){
      j = j_set;
      goto ags_note_edit_draw_segment0;
    }
  }

  for(; i < note_edit->width; ){
    cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
    
    cairo_move_to(cr, (double) i, 0.0);
    cairo_line_to(cr, (double) i, (double) note_edit->height);
    cairo_stroke(cr);
    
    i += note_edit->control_current.control_width;
    
    cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
    
    for(j = 1; i < note_edit->width && j < tact; j++){
    ags_note_edit_draw_segment0:
      cairo_move_to(cr, (double) i, 0.0);
      cairo_line_to(cr, (double) i, (double) note_edit->height);
      cairo_stroke(cr);
      
      i += note_edit->control_current.control_width;
    }
  }
}
Example #13
0
static gboolean
dt_iop_basecurve_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
  dt_iop_module_t *self = (dt_iop_module_t *)user_data;
  dt_iop_basecurve_gui_data_t *c = (dt_iop_basecurve_gui_data_t *)self->gui_data;
  dt_iop_basecurve_params_t *p = (dt_iop_basecurve_params_t *)self->params;

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

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

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

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

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

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

  cairo_translate(cr, 0, height);
  cairo_scale(cr, 1.0f, -1.0f);

  // draw grid
  cairo_set_line_width(cr, .4);
  cairo_set_source_rgb (cr, .1, .1, .1);
  if(c->loglogscale)
    dt_draw_loglog_grid(cr, 4, 0, 0, width, height, c->loglogscale);
  else
    dt_draw_grid(cr, 4, 0, 0, width, height);

  // draw nodes positions
  cairo_set_line_width(cr, 1.);
  cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
  for(int k=0; k<nodes; k++)
  {
    const float x = to_log(basecurve[k].x, c->loglogscale), y = to_log(basecurve[k].y, c->loglogscale);
    cairo_arc(cr, x*width, y*height, 3, 0, 2.*M_PI);
    cairo_stroke(cr);
  }

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

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

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

  cairo_destroy(cr);
  cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget));
  cairo_set_source_surface (cr_pixmap, cst, 0, 0);
  cairo_paint(cr_pixmap);
  cairo_destroy(cr_pixmap);
  cairo_surface_destroy(cst);
  return TRUE;
}
Example #14
0
/* 
 * render functions 
 */ 
static void
begin_render(DiaRenderer *self, const Rectangle *update)
{
  DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self);
  real onedu = 0.0;
  real lmargin = 0.0, tmargin = 0.0;
  gboolean paginated = renderer->surface && /* only with our own pagination, not GtkPrint */
    cairo_surface_get_type (renderer->surface) == CAIRO_SURFACE_TYPE_PDF && !renderer->skip_show_page;

  if (renderer->surface && !renderer->cr)
    renderer->cr = cairo_create (renderer->surface);
  else
    g_assert (renderer->cr);

  /* remember current state, so we can start from new with every page */
  cairo_save (renderer->cr);

  if (paginated && renderer->dia) {
    DiagramData *data = renderer->dia;
    /* Dia's paper.width already contains the scale, cairo needs it without 
     * Similar for margins, Dia's without, but cairo wants them?
     */
    real width = (data->paper.lmargin + data->paper.width * data->paper.scaling + data->paper.rmargin)
          * (72.0 / 2.54) + 0.5;
    real height = (data->paper.tmargin + data->paper.height * data->paper.scaling + data->paper.bmargin)
           * (72.0 / 2.54) + 0.5;
    /* "Changes the size of a PDF surface for the current (and
     * subsequent) pages." Pagination setup? */
    cairo_pdf_surface_set_size (renderer->surface, width, height);
    lmargin = data->paper.lmargin / data->paper.scaling;
    tmargin = data->paper.tmargin / data->paper.scaling;
  }

  cairo_scale (renderer->cr, renderer->scale, renderer->scale);
  /* to ensure no clipping at top/left we need some extra gymnastics,
   * otherwise a box with a line witdh one one pixel might loose the
   * top/left border as in bug #147386 */
  ensure_minimum_one_device_unit (renderer, &onedu);

  if (update && paginated) {
    cairo_rectangle (renderer->cr, lmargin, tmargin,
                     update->right - update->left, update->bottom - update->top);
    cairo_clip (renderer->cr);
    cairo_translate (renderer->cr, -update->left + lmargin, -update->top + tmargin);
  } else
    cairo_translate (renderer->cr, -renderer->dia->extents.left + onedu, -renderer->dia->extents.top + onedu);
  /* no more blurred UML diagrams */
  cairo_set_antialias (renderer->cr, CAIRO_ANTIALIAS_NONE);

  /* clear background */
  if (renderer->with_alpha)
    {
      cairo_set_operator (renderer->cr, CAIRO_OPERATOR_SOURCE);
      cairo_set_source_rgba (renderer->cr,
                             renderer->dia->bg_color.red, 
                             renderer->dia->bg_color.green, 
                             renderer->dia->bg_color.blue,
                             0.0);
    }
  else
    {
      cairo_set_source_rgba (renderer->cr,
                             renderer->dia->bg_color.red, 
                             renderer->dia->bg_color.green, 
                             renderer->dia->bg_color.blue,
                             1.0);
    }
  cairo_paint (renderer->cr);
  if (renderer->with_alpha)
    {
      /* restore to default drawing */
      cairo_set_operator (renderer->cr, CAIRO_OPERATOR_OVER);
      cairo_set_source_rgba (renderer->cr,
                             renderer->dia->bg_color.red, 
                             renderer->dia->bg_color.green, 
                             renderer->dia->bg_color.blue,
                             1.0);
    }
#ifdef HAVE_PANGOCAIRO_H
  if (!renderer->layout)
    renderer->layout = pango_cairo_create_layout (renderer->cr);
#endif

  cairo_set_fill_rule (renderer->cr, CAIRO_FILL_RULE_EVEN_ODD);

#if 0 /* try to work around bug #341481 - no luck */
  {
    cairo_font_options_t *fo = cairo_font_options_create ();
    cairo_get_font_options (renderer->cr, fo);
    /* try to switch off kerning */
    cairo_font_options_set_hint_style (fo, CAIRO_HINT_STYLE_NONE);
    cairo_font_options_set_hint_metrics (fo, CAIRO_HINT_METRICS_OFF);

    cairo_set_font_options (renderer->cr, fo);
    cairo_font_options_destroy (fo);
#ifdef HAVE_PANGOCAIRO_H
    pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout));
    pango_layout_context_changed (renderer->layout);
#endif
  }
#endif
  
  DIAG_STATE(renderer->cr)
}
void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
{
    if (context->paintingDisabled())
        return;

    if (!m_visible)
        return;
    if (!m_buffer)
        return;

    int width = 0, height = 0;
    int pixelAspectRatioNumerator = 0;
    int pixelAspectRatioDenominator = 0;
    double doublePixelAspectRatioNumerator = 0;
    double doublePixelAspectRatioDenominator = 0;
    double displayWidth;
    double displayHeight;
    double scale, gapHeight, gapWidth;

    GstCaps *caps = gst_buffer_get_caps(m_buffer);

    if (!gst_video_format_parse_caps(caps, NULL, &width, &height) ||
        !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator)) {
      gst_caps_unref(caps);
      return;
    }

    displayWidth = width;
    displayHeight = height;
    doublePixelAspectRatioNumerator = pixelAspectRatioNumerator;
    doublePixelAspectRatioDenominator = pixelAspectRatioDenominator;

    cairo_t* cr = context->platformContext();
    cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(m_buffer),
                                                               CAIRO_FORMAT_RGB24,
                                                               width, height,
                                                               4 * width);

    cairo_save(cr);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);

    displayWidth *= doublePixelAspectRatioNumerator / doublePixelAspectRatioDenominator;
    displayHeight *= doublePixelAspectRatioDenominator / doublePixelAspectRatioNumerator;

    scale = MIN (rect.width () / displayWidth, rect.height () / displayHeight);
    displayWidth *= scale;
    displayHeight *= scale;

    // Calculate gap between border an picture
    gapWidth = (rect.width() - displayWidth) / 2.0;
    gapHeight = (rect.height() - displayHeight) / 2.0;

    // paint the rectangle on the context and draw the surface inside.
    cairo_translate(cr, rect.x() + gapWidth, rect.y() + gapHeight);
    cairo_rectangle(cr, 0, 0, rect.width(), rect.height());
    cairo_scale(cr, doublePixelAspectRatioNumerator / doublePixelAspectRatioDenominator,
                doublePixelAspectRatioDenominator / doublePixelAspectRatioNumerator);
    cairo_scale(cr, scale, scale);
    cairo_set_source_surface(cr, src, 0, 0);
    cairo_fill(cr);
    cairo_restore(cr);

    cairo_surface_destroy(src);
    gst_caps_unref(caps);
}
static gboolean
gstyle_color_widget_draw (GtkWidget *widget,
                          cairo_t   *cr)
{
  GstyleColorWidget *self = (GstyleColorWidget *)widget;
  GtkStyleContext *style_context;
  GdkRectangle margin_box;
  GdkRectangle border_box;
  cairo_matrix_t matrix;
  GdkRGBA bg_color = {0};
  gint radius;

  g_assert (GSTYLE_IS_COLOR_WIDGET (self));
  g_assert (cr != NULL);

  style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
  gtk_widget_get_allocation (widget, &margin_box);
  margin_box.x = margin_box.y = 0;

  gstyle_utils_get_rect_resized_box (margin_box, &margin_box, &self->cached_margin);
  gstyle_utils_get_rect_resized_box (margin_box, &border_box, &self->cached_border);
  cairo_save (cr);

  if (self->color != NULL)
    {
      gtk_style_context_get (style_context,
                            gtk_style_context_get_state (style_context),
                            "border-radius", &radius,
                            NULL);

      gstyle_color_fill_rgba (self->color, &bg_color);
      if (self->filter_func != NULL)
        self->filter_func (&bg_color, &bg_color, self->filter_user_data);

      cairo_new_path (cr);
      draw_cairo_round_box (cr, border_box, radius, radius, radius, radius);
    }
  else
    cairo_rectangle (cr, border_box.x, border_box.y, border_box.width, border_box.height);

  cairo_clip_preserve (cr);

  cairo_set_source_rgb (cr, 0.20, 0.20, 0.20);
  cairo_paint (cr);
  cairo_set_source_rgb (cr, 0.80, 0.80, 0.80);

  cairo_matrix_init_scale (&matrix, 0.1, 0.1);
  cairo_matrix_translate (&matrix, -border_box.x, -border_box.y);
  cairo_pattern_set_matrix (self->checkered_pattern, &matrix);
  cairo_mask (cr, self->checkered_pattern);

  if (self->color != NULL)
    {
      gdk_cairo_set_source_rgba (cr, &bg_color);
      cairo_fill (cr);
    }
  else
    gtk_render_background (style_context, cr, border_box.x, border_box.y, border_box.width, border_box.height);

  cairo_restore (cr);
  gtk_render_frame (gtk_widget_get_style_context (widget), cr,
                    margin_box.x, margin_box.y, margin_box.width, margin_box.height);

  return GTK_WIDGET_CLASS (gstyle_color_widget_parent_class)->draw (widget, cr);
}
static gboolean _lib_navigation_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{

  const int inset = DT_NAVIGATION_INSET;
  int width = widget->allocation.width, height = widget->allocation.height;

  dt_develop_t *dev = darktable.develop;

  if (dev->preview_dirty) 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_dirty)
  {
    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;
    int closeup;
    float zoom_x, zoom_y;
    DT_CTL_GET_GLOBAL(zoom, dev_zoom);
    DT_CTL_GET_GLOBAL(closeup, dev_closeup);
    DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x);
    DT_CTL_GET_GLOBAL(zoom_y, 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:
    if(cur_scale > min_scale+0.001)
    {
      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);
    }
  }

  /* 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 #18
0
int main(int argc, char **argv)
{
  cairo_surface_t *surface;
  cairo_t *context;
  int x, y, i,
      width, height, depth,
      screen, pressed_key,
      png;
  double r, b, v;
  QTnode *tree;
  bool rendering;
  struct XWin **xwin;

  /* Get the arguments */
  if(argc != 3) {
    printf("Usage: nbody rendering resultsdir\n");
    exit(1);
  }
  if(*argv[1] == '0') {
    rendering = false;
  } else {
    rendering = true;
  }
  char buf[strlen(argv[2]) + 10];

  /* Set window size */
  width = 1024;
  height = 1024;
  depth = 32;

  tree = init_tree(10, NULL);
  for (i = 0; i < 100000; i++) {
    tree->insert(phys_gen_particle());
    if (i % 10000 == 0)
      printf("%d\n", i);
  }

  /* Create the drawing surface */
  if(rendering) {
    /* Create the X11 window */
    xwin = (struct XWin **)calloc(sizeof(struct XWin *), 1);
    xwindow_init(width, height, depth, xwin);
    surface = cairo_xlib_surface_create((*xwin)->dsp, (*xwin)->win, DefaultVisual((*xwin)->dsp, screen), width, height);
    cairo_xlib_surface_set_size(surface, width, height);
  } else {
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); 
  }
  context = cairo_create(surface);
  cairo_scale(context, width, height);

  png = 0;
  while(1) {
    if(rendering) {
      if((*xwin)->should_close) {
        break;
      }
      /* Wait on the input (also sync up to disable flickering) */
      if(input_ready(xwin)) {
        pressed_key = get_key(xwin);
      }
    }

    /* Clear the surface with black */
    cairo_set_source_rgb(context, 0.0, 0.0, 0.0);
    cairo_paint(context);

    std::queue <QTnode *> nodes;
    QTnode *t;

    nodes.push(tree);

    while (!nodes.empty()) {
      t = nodes.front();
      nodes.pop();

      if (!t->children.empty()) {
        for (i = 0; i < t->children.size(); i++) {
          nodes.push(t->children[i]);
        }
      } else {
        for (std::list <Particle>::iterator p = t->particles.begin(); p != t->particles.end(); p++) {

          v = f2_norm((*p).vel);
          if(v >= 0.4) {
            r = 1.0; b = 0.0;
          } else if(v < 0.5) {
            b = 1.0; r = 0.0;
          }
          cairo_set_source_rgba(context, (double)r, 0.0, (double)b, 1.0);
          cairo_rectangle(context, (*p).pos.x,
              (*p).pos.y, 2e-3, 2e-3);
          cairo_fill(context);
          cairo_set_source_rgba(context, (double)r, 0.0, (double)b, 0.2);
          cairo_rectangle(context, (*p).pos.x - 1e-3,
              (*p).pos.y - 1e-3, 4e-3, 4e-3);
          cairo_fill(context);
        }
      }
    }

    if(rendering) {
      /* Flush the X window */
      flush_input(xwin);
      update_screen(xwin);
    } else {
      mkdir(argv[2], S_IRWXU | S_IRWXG);
      sprintf(buf, "%s/%05d.png", argv[2], png++);
      printf("Making %s\n", buf);
      cairo_surface_write_to_png (surface, buf);
    }

    /* Get the new particles */
    timing(
        tree->calc_global_accel();
        tree->move_shit();
        );
  }
Example #19
0
static void _draw_mode_toggle(cairo_t *cr, float x, float y, float width, float height, int type)
{
  cairo_save(cr);
  cairo_translate(cr, x, y);

  // border
  float border = MIN(width * .1, height * .1);
  cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.4);
  cairo_rectangle(cr, border, border, width - 2.0 * border, height - 2.0 * border);
  cairo_fill_preserve(cr);
  cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.5);
  cairo_set_line_width(cr, border);
  cairo_stroke(cr);

  // icon
  cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.5);
  cairo_move_to(cr, 2.0 * border, height - 2.0 * border);
  switch(type)
  {
    case DT_DEV_HISTOGRAM_LINEAR:
      cairo_line_to(cr, width - 2.0 * border, 2.0 * border);
      cairo_stroke(cr);
      break;
    case DT_DEV_HISTOGRAM_LOGARITHMIC:
      cairo_curve_to(cr, 2.0 * border, 0.33 * height, 0.66 * width, 2.0 * border, width - 2.0 * border,
                     2.0 * border);
      cairo_stroke(cr);
      break;
    case DT_DEV_HISTOGRAM_WAVEFORM:
    {
      cairo_pattern_t *pattern;
      pattern = cairo_pattern_create_linear(0.0, 1.5 * border, 0.0, height - 3.0 * border);

      cairo_pattern_add_color_stop_rgba(pattern, 0.0, 0.0, 0.0, 0.0, 0.5);
      cairo_pattern_add_color_stop_rgba(pattern, 0.2, 0.2, 0.2, 0.2, 0.5);
      cairo_pattern_add_color_stop_rgba(pattern, 0.5, 1.0, 1.0, 1.0, 0.5);
      cairo_pattern_add_color_stop_rgba(pattern, 0.6, 1.0, 1.0, 1.0, 0.5);
      cairo_pattern_add_color_stop_rgba(pattern, 1.0, 0.2, 0.2, 0.2, 0.5);

      cairo_rectangle(cr, 1.5 * border, 1.5 * border, (width - 3.0 * border) * 0.3, height - 3.0 * border);
      cairo_set_source(cr, pattern);
      cairo_fill(cr);

      cairo_save(cr);
      cairo_scale(cr, 1, -1);
      cairo_translate(cr, 0, -height);
      cairo_rectangle(cr, 1.5 * border + (width - 3.0 * border) * 0.2, 1.5 * border,
                      (width - 3.0 * border) * 0.6, height - 3.0 * border);
      cairo_set_source(cr, pattern);
      cairo_fill(cr);
      cairo_restore(cr);

      cairo_rectangle(cr, 1.5 * border + (width - 3.0 * border) * 0.7, 1.5 * border,
                      (width - 3.0 * border) * 0.3, height - 3.0 * border);
      cairo_set_source(cr, pattern);
      cairo_fill(cr);

      cairo_pattern_destroy(pattern);
      break;
    }
  }
  cairo_restore(cr);
}
Example #20
0
/*
 * Draws global image with fill color onto a pixmap with the given
 * resolution and returns it.
 *
 */
xcb_pixmap_t draw_image(uint32_t *resolution) {
    xcb_pixmap_t bg_pixmap = XCB_NONE;
    int button_diameter_physical = ceil(scaling_factor() * BUTTON_DIAMETER);
    DEBUG("scaling_factor is %.f, physical diameter is %d px\n",
          scaling_factor(), button_diameter_physical);

    if (!vistype)
        vistype = get_root_visual_type(screen);
    bg_pixmap = create_bg_pixmap(conn, screen, resolution, color);
    /* Initialize cairo: Create one in-memory surface to render the unlock
     * indicator on, create one XCB surface to actually draw (one or more,
     * depending on the amount of screens) unlock indicators on. */
    cairo_surface_t *output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, button_diameter_physical, button_diameter_physical);
    cairo_t *ctx = cairo_create(output);

    cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]);
    cairo_t *xcb_ctx = cairo_create(xcb_output);

    if (img) {
        if (!tile) {
            cairo_set_source_surface(xcb_ctx, img, 0, 0);
            cairo_paint(xcb_ctx);
        } else {
            /* create a pattern and fill a rectangle as big as the screen */
            cairo_pattern_t *pattern;
            pattern = cairo_pattern_create_for_surface(img);
            cairo_set_source(xcb_ctx, pattern);
            cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
            cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]);
            cairo_fill(xcb_ctx);
            cairo_pattern_destroy(pattern);
        }
    } else {
        char strgroups[3][3] = {{color[0], color[1], '\0'},
            {color[2], color[3], '\0'},
            {color[4], color[5], '\0'}
        };
        uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)),
                             (strtol(strgroups[1], NULL, 16)),
                             (strtol(strgroups[2], NULL, 16))
                            };
        cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0);
        cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]);
        cairo_fill(xcb_ctx);
    }

    if (unlock_indicator) {
        cairo_scale(ctx, scaling_factor(), scaling_factor());
        /* Draw a (centered) circle with transparent background. */
        cairo_set_line_width(ctx, 3.0);
        cairo_arc(ctx,
                  BUTTON_CENTER /* x */,
                  BUTTON_CENTER /* y */,
                  BUTTON_RADIUS /* radius */,
                  0 /* start */,
                  2 * M_PI /* end */);

        /* Use the appropriate color for the different PAM states
         * (currently verifying, wrong password, or default)
         * Basic function so we don't have to use this code
         * repeatedly for objects of the same color */

        void get_color(void) {
            switch (pam_state) {
            case STATE_PAM_VERIFY:
                cairo_set_source_rgba(ctx, 68.0/255, 80.0/255, 41.0/255, 0.8);
                break;
            case STATE_PAM_WRONG:
                cairo_set_source_rgba(ctx, 143.0/255, 53.0/255, 53.0/255, 0.8);
                break;
            case STATE_PAM_IDLE:
                if (unlock_state == STATE_BACKSPACE_ACTIVE) {
                    cairo_set_source_rgba(ctx, 143.0/255, 53.0/255, 53.0/255, 0.8);
                }
                else {
                    cairo_set_source_rgba(ctx, 1, 1, 1, 0.8);
                }
                break;
            }
        }

        /* Circle fill */
        switch (pam_state) {
        case STATE_PAM_VERIFY:
            cairo_set_source_rgba(ctx, 144.0/255, 169.0/255, 89.0/255, 0.2);
            break;
        case STATE_PAM_WRONG:
            cairo_set_source_rgba(ctx, 172.0/255, 65.0/255, 66.0/255, 0.2);
            break;
        default:
            cairo_set_source_rgba(ctx, 0, 0, 0, 0);
            break;
        }
        cairo_fill_preserve(ctx);

        /* Circle border */
        get_color();
        cairo_stroke(ctx);

        /* Display (centered) Time */
        char *timetext = malloc(6);

        time_t curtime = time(NULL);
        struct tm *tm = localtime(&curtime);
        strftime(timetext, 100, TIME_FORMAT, tm);

        /* Color text, same as border */
        get_color();

        cairo_set_font_size(ctx, 32.0);

        cairo_text_extents_t time_extents;
        double time_x, time_y;

        cairo_text_extents(ctx, timetext, &time_extents);
        time_x = BUTTON_CENTER - ((time_extents.width / 2) + time_extents.x_bearing);
        time_y = BUTTON_CENTER - ((time_extents.height / 2) + time_extents.y_bearing);

        cairo_move_to(ctx, time_x, time_y);
        cairo_show_text(ctx, timetext);
        cairo_close_path(ctx);

        free(timetext);

        /* After the user pressed any valid key or the backspace key, we
         * highlight a random part of the unlock indicator to confirm this
         * keypress. */
        if (unlock_state == STATE_KEY_ACTIVE ||
                unlock_state == STATE_BACKSPACE_ACTIVE) {
            cairo_set_line_width(ctx, 4);
            cairo_new_sub_path(ctx);
            double highlight_start = (rand() % (int)(2 * M_PI * 100)) / 100.0;
            cairo_arc(ctx,
                      BUTTON_CENTER /* x */,
                      BUTTON_CENTER /* y */,
                      BUTTON_RADIUS /* radius */,
                      highlight_start,
                      highlight_start + (M_PI / 2.5));
            cairo_set_operator(ctx,CAIRO_OPERATOR_CLEAR); /* Set newly drawn lines to erase what they're drawn over*/
            cairo_stroke(ctx);

            /* Draw two little separators for the highlighted part of the
            * unlock indicator. */
            cairo_set_operator(ctx,CAIRO_OPERATOR_OVER); /* back to normal operator */
            cairo_set_line_width(ctx, 10);

            /* Change color of separators based on backspace/active keypress */
            get_color();

            /* separator 1 */
            cairo_arc(ctx,
                      BUTTON_CENTER /* x */,
                      BUTTON_CENTER /* y */,
                      BUTTON_RADIUS /* radius */,
                      highlight_start /* start */,
                      highlight_start + (M_PI / 128.0) /* end */);
            cairo_stroke(ctx);

            /* separator 2 */
            cairo_arc(ctx,
                      BUTTON_CENTER /* x */,
                      BUTTON_CENTER /* y */,
                      BUTTON_RADIUS /* radius */,
                      highlight_start + (M_PI / 2.5) /* start */,
                      (highlight_start + (M_PI / 2.5)) + (M_PI / 128.0) /* end */);
            cairo_stroke(ctx);
        }
    }

    if (xr_screens > 0) {
        /* Composite the unlock indicator in the middle of each screen. */
        for (int screen = 0; screen < xr_screens; screen++) {
            int x = (xr_resolutions[screen].x + ((xr_resolutions[screen].width / 2) - (button_diameter_physical / 2)));
            int y = (xr_resolutions[screen].y + ((xr_resolutions[screen].height / 2) - (button_diameter_physical / 2)));
            cairo_set_source_surface(xcb_ctx, output, x, y);
            cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical);
            cairo_fill(xcb_ctx);
        }
    } else {
        /* We have no information about the screen sizes/positions, so we just
         * place the unlock indicator in the middle of the X root window and
         * hope for the best. */
        int x = (last_resolution[0] / 2) - (button_diameter_physical / 2);
        int y = (last_resolution[1] / 2) - (button_diameter_physical / 2);
        cairo_set_source_surface(xcb_ctx, output, x, y);
        cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical);
        cairo_fill(xcb_ctx);
    }

    cairo_surface_destroy(xcb_output);
    cairo_surface_destroy(output);
    cairo_destroy(ctx);
    cairo_destroy(xcb_ctx);
    return bg_pixmap;
}
Example #21
0
static void sctp_graph_draw(struct sctp_udata *u_data)
{
	int length, lwidth;
	guint32 distance=5, i, e, sec, w, start, a, j, b;
	gint label_width, label_height;
	char label_string[15];
	gfloat dis;
	gboolean write_label = FALSE;
	PangoLayout  *layout;
	GtkAllocation widget_alloc;
	cairo_t *cr;

	if (u_data->io->x1_tmp_sec == 0 && u_data->io->x1_tmp_usec == 0)
		u_data->io->offset = 0;
	else
		u_data->io->offset = 5;

	if (u_data->io->x2_tmp_sec - u_data->io->x1_tmp_sec > 1500)
	{
		u_data->io->min_x=u_data->io->x1_tmp_sec;
		u_data->io->max_x=u_data->io->x2_tmp_sec;
		u_data->io->uoff = TRUE;
	}
	else
	{
		u_data->io->min_x=((guint32) (u_data->io->x1_tmp_sec*1000000.0))+u_data->io->x1_tmp_usec;
		u_data->io->max_x=((guint32) (u_data->io->x2_tmp_sec*1000000.0))+u_data->io->x2_tmp_usec;
		u_data->io->uoff = FALSE;
	}

	u_data->io->tmp_width = u_data->io->max_x - u_data->io->min_x;

	if (u_data->dir == 1)
	{
		if (u_data->io->tmp == FALSE)
		{
			if (u_data->assoc->sort_tsn1 != NULL)
				u_data->io->max_y = u_data->io->tmp_max_tsn1 - u_data->io->tmp_min_tsn1;
			else
				u_data->io->max_y = 0;
			u_data->io->min_y = 0;
		}
		else
		{
			u_data->io->max_y = u_data->io->tmp_max_tsn1;
			u_data->io->min_y = u_data->io->tmp_min_tsn1;
		}
	}
	else if (u_data->dir == 2)
	{
		if (u_data->io->tmp == FALSE)
		{
			if (u_data->assoc->tsn2 != NULL)
				u_data->io->max_y = u_data->io->tmp_max_tsn2 - u_data->io->tmp_min_tsn2;
			else
				u_data->io->max_y = 0;
			u_data->io->min_y = 0;
		}
		else
		{
			u_data->io->max_y = u_data->io->tmp_max_tsn2;
			u_data->io->min_y = u_data->io->tmp_min_tsn2;
		}
	}

#if GTK_CHECK_VERSION(2,22,0)
	cr = cairo_create (u_data->io->surface);
#else
	cr = gdk_cairo_create (u_data->io->pixmap);
#endif
	cairo_set_source_rgb (cr, 1, 1, 1);
	gtk_widget_get_allocation(u_data->io->draw_area, &widget_alloc);
	cairo_rectangle (cr,
		0,
		0,
		widget_alloc.width,
		widget_alloc.height);
	cairo_fill (cr);
	cairo_destroy (cr);

	/* x_axis */
#if GTK_CHECK_VERSION(2,22,0)
	cr = cairo_create (u_data->io->surface);
#else
	cr = gdk_cairo_create (u_data->io->pixmap);
#endif
	cairo_set_line_width (cr, 1.0);
	cairo_move_to(cr, LEFT_BORDER+u_data->io->offset+0.5, u_data->io->surface_height - BOTTOM_BORDER+0.5);
	cairo_line_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset+0.5, u_data->io->surface_height - BOTTOM_BORDER+0.5);

	cairo_move_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset+0.5, u_data->io->surface_height - BOTTOM_BORDER+0.5);
	cairo_line_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset - 5+0.5, u_data->io->surface_height - BOTTOM_BORDER - 5+0.5);

	cairo_move_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset + 0.5, u_data->io->surface_height - BOTTOM_BORDER + 0.5);
	cairo_line_to(cr, u_data->io->surface_width - RIGHT_BORDER + u_data->io->offset - 5.5, u_data->io->surface_height - BOTTOM_BORDER + 5.5);
	cairo_stroke(cr);
	cairo_destroy(cr);
	
	u_data->io->axis_width = u_data->io->surface_width - LEFT_BORDER - RIGHT_BORDER - u_data->io->offset;

	if(u_data->io->tmp_width>0){
		u_data->io->x_interval = (float)((u_data->io->axis_width*1.0)/u_data->io->tmp_width); /*distance in pixels between 2 data points*/
	} else {
		u_data->io->x_interval = (float)(u_data->io->axis_width);
	}

	e=0;
	if (u_data->io->x_interval < 1)
	{
		dis = 1 / u_data->io->x_interval;
		while (dis >1)
		{
			dis /= 10;
			e++;
		}
		distance = 1;
			for (i=0; i<=e+1; i++)
			distance *= 10;
	}
	else
		distance = 5;

	g_snprintf(label_string, sizeof(label_string), "%d", 0);
	memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
	layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
	pango_layout_get_pixel_size(layout, &label_width, &label_height);

	if (u_data->io->x1_tmp_usec == 0)
		sec = u_data->io->x1_tmp_sec;
	else
		sec = u_data->io->x1_tmp_sec+1;

	if (u_data->io->offset != 0)
	{
		g_snprintf(label_string, sizeof(label_string), "%u", u_data->io->x1_tmp_sec);
		memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
		pango_layout_set_text(layout, label_string, -1);
		pango_layout_get_pixel_size(layout, &lwidth, NULL);

#if GTK_CHECK_VERSION(2,22,0)
		cr = cairo_create (u_data->io->surface);
#else
		cr = gdk_cairo_create (u_data->io->pixmap);
#endif
		cairo_move_to (cr, LEFT_BORDER - 25, u_data->io->surface_height - BOTTOM_BORDER + 20);
		pango_cairo_show_layout (cr, layout);
		cairo_destroy (cr);
		cr = NULL;

	}
	w = (guint32)(500 / (guint32)(distance * u_data->io->x_interval));
	if (w == 0)
		w = 1;
	if (w == 4 || w==3 || w==2)
	{
		w = 5;
		a = distance / 10;
		b = (guint32)((u_data->io->min_x/100000))%10; /* start for labels*/
	}
	else
	{
		a = distance / 5;
		b = 0;
	}

	if (!u_data->io->uoff)
	{
		if (a>=1000000)
		{
			start=u_data->io->min_x/1000000*1000000;
			if (a==1000000)
				b = 0;
		}
		else
		{
			start=u_data->io->min_x/100000;
			if (start%2!=0)
				start--;
			start*=100000;
			b = (guint32)((start/100000))%10;
		}
	}
	else
	{
		start = u_data->io->min_x;
		if (start%2!=0)
			start--;
		b = 0;

	}

	for (i=start, j=b; i<=u_data->io->max_x; i+=a, j++)
	{
		if (!u_data->io->uoff)
		if (i >= u_data->io->min_x && i % 1000000 != 0)
		{
			length = 5;
			g_snprintf(label_string, sizeof(label_string), "%d", i%1000000);

			if (j % w == 0)
			{
				length = 10;

				memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
				pango_layout_set_text(layout, label_string, -1);
				pango_layout_get_pixel_size(layout, &lwidth, NULL);
#if GTK_CHECK_VERSION(2,22,0)
				cr = cairo_create (u_data->io->surface);
#else
				cr = gdk_cairo_create (u_data->io->pixmap);
#endif
				cairo_move_to (cr,
					LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval - lwidth / 2,
					u_data->io->surface_height - BOTTOM_BORDER + 10);
				pango_cairo_show_layout (cr, layout);
				cairo_destroy (cr);
				cr = NULL;
			}
#if GTK_CHECK_VERSION(2,22,0)
			cr = cairo_create (u_data->io->surface);
#else
			cr = gdk_cairo_create (u_data->io->pixmap);
#endif
			cairo_set_line_width (cr, 1.0);
			cairo_move_to(cr,
				LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval + 0.5,
				u_data->io->surface_height - BOTTOM_BORDER + 0.5);
			cairo_line_to(cr,
				LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval + 0.5,
				u_data->io->surface_height - BOTTOM_BORDER + length + 0.5);
			cairo_stroke(cr);
			cairo_destroy(cr);
		}

		if (!u_data->io->uoff)
		{
			if (i%1000000==0 && j%w==0)
			{
				sec=i/1000000;
				write_label = TRUE;
			}
		}
		else
		{
			if (j%w == 0)
			{
				sec = i;
				write_label = TRUE;
			}
		}
		if (write_label)
		{
#if GTK_CHECK_VERSION(2,22,0)
			cr = cairo_create (u_data->io->surface);
#else
			cr = gdk_cairo_create (u_data->io->pixmap);
#endif
			cairo_set_line_width (cr, 1.0);
			cairo_move_to(cr,
				LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval + 0.5,
				u_data->io->surface_height - BOTTOM_BORDER + 0.5);
			cairo_line_to(cr,
				LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval + 0.5,
				u_data->io->surface_height - BOTTOM_BORDER + 10 + 0.5);
			cairo_stroke(cr);
			cairo_destroy(cr);

			g_snprintf(label_string, sizeof(label_string), "%d", sec);
			memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
			pango_layout_set_text(layout, label_string, -1);
			pango_layout_get_pixel_size(layout, &lwidth, NULL);
#if GTK_CHECK_VERSION(2,22,0)
			cr = cairo_create (u_data->io->surface);
#else
			cr = gdk_cairo_create (u_data->io->pixmap);
#endif
			cairo_move_to (cr,
				(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval-10),
				u_data->io->surface_height - BOTTOM_BORDER + 20);
			pango_cairo_show_layout (cr, layout);
			cairo_destroy (cr);
			cr = NULL;

			write_label = FALSE;
		}
	}

	g_strlcpy(label_string, "sec", sizeof(label_string));

	memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
	pango_layout_set_text(layout, label_string, -1);
	pango_layout_get_pixel_size(layout, &lwidth, NULL);
#if GTK_CHECK_VERSION(2,22,0)
	cr = cairo_create (u_data->io->surface);
#else
	cr = gdk_cairo_create (u_data->io->pixmap);
#endif
	cairo_move_to (cr,
		u_data->io->surface_width - RIGHT_BORDER - 10,
		u_data->io->surface_height - BOTTOM_BORDER + 30);
	pango_cairo_show_layout (cr, layout);
	cairo_destroy (cr);
	cr = NULL;

	distance = 5;

	/* y-axis */
#if GTK_CHECK_VERSION(2,22,0)
	cr = cairo_create (u_data->io->surface);
#else
	cr = gdk_cairo_create (u_data->io->pixmap);
#endif
	cairo_set_line_width (cr, 1.0);
	cairo_move_to(cr, LEFT_BORDER + 0.5, TOP_BORDER - u_data->io->offset + 0.5);
	cairo_line_to(cr, LEFT_BORDER + 0.5, u_data->io->surface_height - BOTTOM_BORDER - u_data->io->offset + 0.5);

	cairo_move_to(cr, LEFT_BORDER + 0.5, TOP_BORDER - u_data->io->offset + 0.5);
	cairo_line_to(cr, LEFT_BORDER - 5 + 0.5, TOP_BORDER - u_data->io->offset + 5 + 0.5);

	cairo_move_to(cr, LEFT_BORDER + 0.5, TOP_BORDER - u_data->io->offset + 0.5);
	cairo_line_to(cr, LEFT_BORDER +5 + 0.5, TOP_BORDER - u_data->io->offset + 5 + 0.5);
	cairo_stroke(cr);
	cairo_destroy(cr);

	u_data->io->y_interval = (float)(((u_data->io->surface_height - TOP_BORDER - BOTTOM_BORDER) * 1.0)/(u_data->io->max_y - u_data->io->min_y));

	e = 0;
	if (u_data->io->y_interval < 1)
	{
		dis = 1 / u_data->io->y_interval;
		while (dis > 1)
		{
			dis /= 10;
			e++;
		}
		distance = 1;
		for (i=0; i<=e; i++)
			distance = distance * 10;
	}
	else if (u_data->io->y_interval<2)
		distance = 10;

	if (u_data->io->max_y > 0)
	{
		for (i=u_data->io->min_y/distance*distance; i<=u_data->io->max_y; i+=distance/5)
		{
			if (i >= u_data->io->min_y)
			{
				length = 5;
				g_snprintf(label_string, sizeof(label_string), "%d", i);

				if (i%distance == 0 || (distance <= 5 && u_data->io->y_interval > 10))
				{
					length = 10;

					memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), sizeof(label_string));
					pango_layout_set_text(layout, label_string, -1);
					pango_layout_get_pixel_size(layout, &lwidth, NULL);
#if GTK_CHECK_VERSION(2,22,0)
					cr = cairo_create (u_data->io->surface);
#else
					cr = gdk_cairo_create (u_data->io->pixmap);
#endif
					cairo_move_to (cr,
						LEFT_BORDER - length - lwidth - 5,
						u_data->io->surface_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval - 3);
					pango_cairo_show_layout (cr, layout);
					cairo_destroy (cr);
					cr = NULL;
				}
#if GTK_CHECK_VERSION(2,22,0)
				cr = cairo_create (u_data->io->surface);
#else
				cr = gdk_cairo_create (u_data->io->pixmap);
#endif
				cairo_set_line_width (cr, 1.0);
				cairo_move_to(cr,
					LEFT_BORDER - length + 0.5,
					u_data->io->surface_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval + 0.5);
				cairo_line_to(cr,
					LEFT_BORDER + 0.5,
					u_data->io->surface_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval + 0.5);
				cairo_stroke(cr);
				cairo_destroy(cr);
			}
		}
	}
	else
		simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");

	g_object_unref(G_OBJECT(layout));
}
Example #22
0
static gboolean
gimp_color_bar_expose (GtkWidget      *widget,
                       GdkEventExpose *event)
{
  GimpColorBar    *bar = GIMP_COLOR_BAR (widget);
  cairo_t         *cr;
  GtkAllocation    allocation;
  cairo_surface_t *surface;
  cairo_pattern_t *pattern;
  guchar          *src;
  guchar          *dest;
  gint             x, y;
  gint             width, height;
  gint             i;

  cr = gdk_cairo_create (event->window);

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

  gtk_widget_get_allocation (widget, &allocation);

  x = y = gtk_container_get_border_width (GTK_CONTAINER (bar));

  width  = allocation.width  - 2 * x;
  height = allocation.height - 2 * y;

  if (width < 1 || height < 1)
    return TRUE;

  cairo_translate (cr, allocation.x + x, allocation.y + y);
  cairo_rectangle (cr, 0, 0, width, height);
  cairo_clip (cr);

  surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 256, 1);

  for (i = 0, src = bar->buf, dest = cairo_image_surface_get_data (surface);
       i < 256;
       i++, src += 3, dest += 4)
    {
      GIMP_CAIRO_RGB24_SET_PIXEL(dest, src[0], src[1], src[2]);
    }

  cairo_surface_mark_dirty (surface);

  pattern = cairo_pattern_create_for_surface (surface);
  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT);
  cairo_surface_destroy (surface);

  if (bar->orientation == GTK_ORIENTATION_HORIZONTAL)
    {
      cairo_scale (cr, (gdouble) width / 256.0, 1.0);
    }
  else
    {
      cairo_translate (cr, 0, height);
      cairo_scale (cr, 1.0, (gdouble) height / 256.0);
      cairo_rotate (cr, - G_PI / 2);
    }

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

  cairo_paint (cr);

  cairo_destroy (cr);

  return TRUE;
}
Example #23
0
void CairoDrawer::drawRect(const GraphRect &rect)
    {
    cairo_rectangle(cr, rect.start.x, rect.start.y, rect.size.x, rect.size.y);
    setFillAndLine(cr, mFillColor, mLineColor);
    }
Example #24
0
static void
draw_page (GtkPrintOperation *operation,
           GtkPrintContext   *context,
           gint               page_nr,
           gpointer           user_data)
{
    PrintData *data = (PrintData *)user_data;
    cairo_t *cr;
    PangoLayout *layout;
    gint text_width, text_height;
    gdouble width;
    gint line, i;
    PangoFontDescription *desc;
    gchar *page_str;

    (void) operation; /* avoid unused parameter compiler warning */

    cr = gtk_print_context_get_cairo_context (context);

    width = gtk_print_context_get_width (context);

    cairo_rectangle (cr, 0, 0, width, HEADER_HEIGHT);

    cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
    cairo_fill_preserve (cr);

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


    layout = gtk_print_context_create_pango_layout (context);

    desc = pango_font_description_from_string ("sans 14");
    pango_layout_set_font_description (layout, desc);
    pango_font_description_free (desc);

    pango_layout_set_text (layout, data->pgheader, -1);
    pango_layout_get_pixel_size (layout, &text_width, &text_height);

    if (text_width > width) {
        pango_layout_set_width (layout, width);
        pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_START);
        pango_layout_get_pixel_size (layout, &text_width, &text_height);
    }

    cairo_move_to (cr, (width - text_width) / 2,  (HEADER_HEIGHT - text_height) / 2);
    pango_cairo_show_layout (cr, layout);

    page_str = g_strdup_printf ("%d/%d", page_nr + 1, data->num_pages);
    pango_layout_set_text (layout, page_str, -1);
    g_free (page_str);

    pango_layout_set_width (layout, -1);
    pango_layout_get_pixel_size (layout, &text_width, &text_height);
    cairo_move_to (cr, width - text_width - 4, (HEADER_HEIGHT - text_height) / 2);
    pango_cairo_show_layout (cr, layout);

    g_object_unref (layout);

    layout = gtk_print_context_create_pango_layout (context);

    desc = pango_font_description_from_string ("monospace");
    pango_font_description_set_size (desc, data->font_size * PANGO_SCALE);
    pango_layout_set_font_description (layout, desc);
    pango_font_description_free (desc);

    cairo_move_to (cr, 0, HEADER_HEIGHT + HEADER_GAP);
    line = page_nr * data->lines_per_page;
    for (i = 0; i < data->lines_per_page && line < data->num_lines; i++) {
        pango_layout_set_text (layout, data->lines[line], -1);
        pango_cairo_show_layout (cr, layout);
        cairo_rel_move_to (cr, 0, data->font_size);
        line++;
    }

    g_object_unref (layout);
}
Example #25
0
   // ----------------------------------------------------------------------
   void
   RefreshLiveviewEvent::
   write_frame()
      throw( std::runtime_error )
   {
      double t = 0.0;
      unsigned char* texture_ = getTexture();
      const Camera& cam = visualization().camera();
      bool freezed = cam.cam_properties().freeze(t)>.5;
      cairo_surface_t* surface_;

      if( (!freezed) )
         {
            int w = int(ceil(cam.width(t)));
            int h = int(ceil(cam.height(t)));

            if( (w<5) || (h<5) )
               {
                  std::ostringstream oss;
                  oss << "Picture dimension too small: "
                      << w << "x" << h;
                  throw std::runtime_error(oss.str());
               }

            double scale = cam.scale(t);
            if( scale < EPSILON )
               {
                  std::ostringstream oss;
                  oss << "Scale too small: " << scale;
                  throw std::runtime_error(oss.str());
               }

            shawn::Vec cam_pos = cam.position(t);
            shawn::Vec cam_pos_shift = cam.position_shift(t);

            // ALLOC SURFACE
            // make_surface(w,h);
            surface_ =
               cairo_image_surface_create_for_data ( texture_,
                                                     CAIRO_FORMAT_ARGB32,
                                                     w,h,
                                                      w*4);


            // CLEAR
            shawn::Vec cam_bg = cam.background(t);
            cairo_t* cr = cairo_create(surface_);
            cairo_rectangle (cr, 0, 0, w, h);
            cairo_set_source_rgb (cr,cam_bg.x(),cam_bg.y(),cam_bg.z());
            cairo_fill (cr);

            shawn::Vec trans( (-cam_pos.x()*scale) + (double(w)/2.0) + cam_pos_shift.x(),
                              (-cam_pos.y()*scale) - (double(h)/2.0) - cam_pos_shift.y() );

            Context C(trans/scale,scale,w,h, 0);

            cairo_save(cr);
            // TRANSFORMATION
            cairo_translate( cr, trans.x(), -trans.y() );
            cairo_scale(cr,scale,-scale);

            //
            visualization().draw(cr,t,C);

            cairo_restore(cr);

            cairo_destroy (cr);
      }
   }
Example #26
0
static void draw_stripe(GtkWidget* widget, WindowData* windata, cairo_t* cr)
{
	GtkStyle*        style;
	GdkColor         color;
	int              stripe_x;
	int              stripe_y;
	int              stripe_height;
	#ifdef ENABLE_GRADIENT_LOOK
		cairo_pattern_t* gradient;
		double           r, g, b;
	#endif

	style = gtk_widget_get_style(widget);

	GtkAllocation alloc;
	gtk_widget_get_allocation(windata->main_hbox, &alloc);

	stripe_x = alloc.x + 1;

	if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)
	{
		stripe_x = windata->width - STRIPE_WIDTH - stripe_x;
	}

	stripe_y = alloc.y + 1;
	stripe_height = alloc.height - 2;

	switch (windata->urgency)
	{
		case URGENCY_LOW: // LOW
			color = style->bg[GTK_STATE_NORMAL];
			break;

		case URGENCY_CRITICAL: // CRITICAL
			gdk_color_parse("#CC0000", &color);
			break;

		case URGENCY_NORMAL: // NORMAL
		default:
			color = style->bg[GTK_STATE_SELECTED];
			break;
	}

	cairo_rectangle(cr, stripe_x, stripe_y, STRIPE_WIDTH, stripe_height);

	#ifdef ENABLE_GRADIENT_LOOK
		r = color.red / 65535.0;
		g = color.green / 65535.0;
		b = color.blue / 65535.0;

		gradient = cairo_pattern_create_linear(stripe_x, 0, STRIPE_WIDTH, 0);
		cairo_pattern_add_color_stop_rgba(gradient, 0, r, g, b, 1);
		cairo_pattern_add_color_stop_rgba(gradient, 1, r, g, b, 0);
		cairo_set_source(cr, gradient);
		cairo_fill(cr);
		cairo_pattern_destroy(gradient);
	#else
		gdk_cairo_set_source_color(cr, &color);
		cairo_fill(cr);
	#endif
}
Example #27
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 #28
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    /* Paint background white, then draw in black. */
    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
    cairo_paint (cr);
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */

    cairo_set_line_width (cr, 1.0);
    cairo_translate (cr, 1, 1);

    /* Draw everything first with square caps. */
    cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);

    /* Draw horizontal and vertical segments, each in both
     * directions. */
    cairo_move_to     (cr,  4.5,  0.5);
    cairo_rel_line_to (cr,  2.0,  0.0);

    cairo_move_to     (cr, 10.5,  4.5);
    cairo_rel_line_to (cr,  0.0,  2.0);

    cairo_move_to     (cr,  6.5, 10.5);
    cairo_rel_line_to (cr, -2.0,  0.0);

    cairo_move_to     (cr,  0.5,  6.5);
    cairo_rel_line_to (cr,  0.0, -2.0);

    /* Draw right angle turns in four directions. */
    cairo_move_to     (cr,  0.5,  2.5);
    cairo_rel_line_to (cr,  0.0, -2.0);
    cairo_rel_line_to (cr,  2.0,  0.0);

    cairo_move_to     (cr,  8.5,  0.5);
    cairo_rel_line_to (cr,  2.0,  0.0);
    cairo_rel_line_to (cr,  0.0,  2.0);

    cairo_move_to     (cr, 10.5,  8.5);
    cairo_rel_line_to (cr,  0.0,  2.0);
    cairo_rel_line_to (cr, -2.0,  0.0);

    cairo_move_to     (cr,  2.5, 10.5);
    cairo_rel_line_to (cr, -2.0,  0.0);
    cairo_rel_line_to (cr,  0.0, -2.0);

    /* Draw a closed-path rectangle */
    cairo_rectangle   (cr, 0.5, 12.5, 10.0, 10.0);

    cairo_stroke (cr);

    cairo_translate (cr, 12, 0);

    /* Now draw the same results, but with butt caps. */
    cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);

    /* Draw horizontal and vertical segments, each in both
     * directions. */
    cairo_move_to     (cr,  4.0,  0.5);
    cairo_rel_line_to (cr,  3.0,  0.0);

    cairo_move_to     (cr, 10.5,  4.0);
    cairo_rel_line_to (cr,  0.0,  3.0);

    cairo_move_to     (cr,  7.0, 10.5);
    cairo_rel_line_to (cr, -3.0,  0.0);

    cairo_move_to     (cr,  0.5,  7.0);
    cairo_rel_line_to (cr,  0.0, -3.0);

    /* Draw right angle turns in four directions. */
    cairo_move_to     (cr,  0.5,  3.0);
    cairo_rel_line_to (cr,  0.0, -2.5);
    cairo_rel_line_to (cr,  2.5,  0.0);

    cairo_move_to     (cr,  8.0,  0.5);
    cairo_rel_line_to (cr,  2.5,  0.0);
    cairo_rel_line_to (cr,  0.0,  2.5);

    cairo_move_to     (cr, 10.5,  8.0);
    cairo_rel_line_to (cr,  0.0,  2.5);
    cairo_rel_line_to (cr, -2.5,  0.0);

    cairo_move_to     (cr,  3.0, 10.5);
    cairo_rel_line_to (cr, -2.5,  0.0);
    cairo_rel_line_to (cr,  0.0, -2.5);

    /* Draw a closed-path rectangle */
    cairo_rectangle   (cr, 0.5, 12.5, 10.0, 10.0);

    /* Draw a path that is rectilinear initially, but not completely */
    /* We draw this out of the target window.  The bug that caused this
     * addition was leaks if part of the path was rectilinear but not
     * completely */
    cairo_move_to     (cr,  3.0, 30.5);
    cairo_rel_line_to (cr, -2.5,  0.0);
    cairo_rel_line_to (cr, +2.5, +2.5);

    cairo_stroke (cr);

    return CAIRO_TEST_SUCCESS;
}
Example #29
0
void
HippoCanvas::onPaint(WPARAM wParam, LPARAM lParam)
{
    RECT region;
    if (GetUpdateRect(window_, &region, true)) {

        int regionWidth = region.right - region.left;
        int regionHeight = region.bottom - region.top;

#if 0
        g_debug("SIZING: %p paint region %d,%d %dx%d",
                window_, region.left, region.top,
                regionWidth, regionHeight);
#endif

        // go ahead and request/resize if necessary, so we paint the right thing
        ensureRequestAndAllocation();

        PAINTSTRUCT paint;
        HDC hdc = BeginPaint(window_, &paint);

        //g_debug("paint.fErase=%d", paint.fErase);

        cairo_surface_t *surface = cairo_win32_surface_create(hdc);
        cairo_surface_t *buffer = cairo_surface_create_similar(surface,
            CAIRO_CONTENT_COLOR, regionWidth, regionHeight);
        cairo_t *cr = cairo_create(buffer);
        hippo_canvas_context_win_update_pango(context_, cr);

        // make the buffer's coordinates look like the real coordinates
        cairo_translate(cr, - region.left, - region.top);

        // Paint a background rectangle to the buffer
        cairo_rectangle(cr, region.left, region.top, regionWidth, regionHeight);
        cairo_clip(cr);
        
        // FIXME not the right background color (on linux it's the default gtk background)
        // should use system color, maybe GetThemeSysColorBrush is right. Note that 
        // this rectangle draws the little corner between the scrollbars in 
        // addition to the viewport background.
        hippo_cairo_set_source_rgba32(cr, 0xffffffff);
        cairo_paint(cr);

        // Draw canvas item to the buffer
        if (root_ != (HippoCanvasItem*) NULL) {
            RECT viewport;
            HippoRectangle viewport_hippo;
            HippoRectangle region_hippo;

            getViewport(&viewport);
            
            hippo_rectangle_from_rect(&viewport_hippo, &viewport);
            hippo_rectangle_from_rect(&region_hippo, &region);

            if (hippo_rectangle_intersect(&viewport_hippo, &region_hippo, &region_hippo)) {
                // we have to clip so we don't draw outside the viewport - the canvas
                // doesn't have its own window
                cairo_save(cr);
                cairo_rectangle(cr, region_hippo.x, region_hippo.y, region_hippo.width, region_hippo.height);
                cairo_clip(cr);

                int x, y;
                getCanvasOrigin(&x, &y);
                hippo_canvas_item_process_paint(root_, cr, &region_hippo, x, y);

                cairo_restore(cr);
            }
        }
        
        // pop the update region clip and the translation off the buffer
        cairo_destroy(cr);

        // Copy the buffer to the window
        cairo_t *window_cr = cairo_create(surface);
        cairo_rectangle(window_cr, region.left, region.top, regionWidth, regionHeight);
        cairo_clip(window_cr);
        cairo_set_source_surface(window_cr, buffer, region.left, region.top);
        cairo_paint(window_cr);
        cairo_destroy(window_cr);

        cairo_surface_destroy(buffer);
        cairo_surface_destroy(surface);

        EndPaint(window_, &paint);
    }
}
Example #30
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);
}