コード例 #1
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;
    }
  }
}
コード例 #2
0
ファイル: ogra2cairo.c プロジェクト: htrb/ngraph-gtk
static int
gra2cairo_output(struct objlist *obj, N_VALUE *inst, N_VALUE *rval,
                 int argc, char **argv)
{
  char code, *cstr, *tmp;
  int *cpar, i, r, font_style;
  double x, y, w, h, fontsize,
    fontspace, fontdir, fontsin, fontcos, a1, a2;
  cairo_line_join_t join;
  cairo_line_cap_t cap;
  double *dashlist = NULL;
  struct gra2cairo_local *local;

  local = (struct gra2cairo_local *)argv[2];
  code = *(char *)(argv[3]);
  cpar = (int *)argv[4];
  cstr = argv[5];

  if (local->cairo == NULL)
    return -1;

  if (code != 'T') {
    gra2cairo_draw_path(local);
  }
  switch (code) {
  case 'I':
    gra2cairo_set_antialias(local, local->antialias);
    local->linetonum = 0;
    r = check_cairo_status(local->cairo);
    if (r) {
      error(obj, r);
      return 1;
    }
  case '%': case 'X':
    break;
  case 'E':
    r = check_cairo_status(local->cairo);
    if (r) {
      error(obj, r);
      return 1;
    }
    break;
  case 'V':
    local->offsetx = mxd2pw(local, cpar[1]);
    local->offsety = mxd2ph(local, cpar[2]);
    cairo_new_path(local->cairo);
    if (cpar[5]) {
      x = mxd2pw(local, cpar[1]);
      y = mxd2ph(local, cpar[2]);
      w = mxd2pw(local, cpar[3]) - x;
      h = mxd2ph(local, cpar[4]) - y;

      cairo_reset_clip(local->cairo);
      cairo_rectangle(local->cairo, x, y, w, h);
      cairo_clip(local->cairo);
    } else {
      cairo_reset_clip(local->cairo);
    }

    if (local->region) {
      gra2cairo_clip_region(local, local->region);
    }
    break;
  case 'A':
    if (cpar[1] == 0) {
      cairo_set_dash(local->cairo, NULL, 0, 0);
    } else {
      dashlist = g_malloc(sizeof(* dashlist) * cpar[1]);
      if (dashlist == NULL)
	break;
      for (i = 0; i < cpar[1]; i++) {
	dashlist[i] = mxd2pw(local, cpar[6 + i]);
        if (dashlist[i] <= 0) {
	  dashlist[i] = 1;
	}
      }
      cairo_set_dash(local->cairo, dashlist, cpar[1], 0);
      g_free(dashlist);
    }

    cairo_set_line_width(local->cairo, mxd2pw(local, cpar[2]));

    if (cpar[3] == 2) {
      cap = CAIRO_LINE_CAP_SQUARE;
    } else if (cpar[3] == 1) {
      cap = CAIRO_LINE_CAP_ROUND;
    } else {
      cap = CAIRO_LINE_CAP_BUTT;
    }
    cairo_set_line_cap(local->cairo, cap);

    if (cpar[4] == 2) {
      join = CAIRO_LINE_JOIN_BEVEL;
    } else if (cpar[4] == 1) {
      join = CAIRO_LINE_JOIN_ROUND;
    } else {
      join = CAIRO_LINE_JOIN_MITER;
    }
    cairo_set_line_join(local->cairo, join);
    break;
  case 'G':
    if (local->use_opacity && cpar[0] > 3 && cpar[4] < 255) {
      cairo_set_source_rgba(local->cairo,
			    cpar[1] / 255.0,
			    cpar[2] / 255.0,
			    cpar[3] / 255.0,
			    cpar[4] / 255.0);
    } else {
      cairo_set_source_rgb(local->cairo,
			   cpar[1] / 255.0,
			   cpar[2] / 255.0,
			   cpar[3] / 255.0);
    }
    break;
  case 'M':
    cairo_move_to(local->cairo, mxd2px(local, cpar[1]), mxd2py(local, cpar[2]));
    break;
  case 'N':
    relative_move(local->cairo, mxd2pw(local, cpar[1]), mxd2ph(local, cpar[2]));
    break;
  case 'L':
    cairo_new_path(local->cairo);
    cairo_move_to(local->cairo, mxd2px(local, cpar[1]), mxd2py(local, cpar[2]));
    cairo_line_to(local->cairo, mxd2px(local, cpar[3]), mxd2py(local, cpar[4]));
    cairo_stroke(local->cairo);
    break;
  case 'T':
    cairo_line_to(local->cairo, mxd2px(local, cpar[1]), mxd2py(local, cpar[2]));
    local->linetonum++;
    break;
  case 'C':
    x = mxd2px(local, cpar[1] - cpar[3]);
    y = mxd2py(local, cpar[2] - cpar[4]);
    w = mxd2pw(local, cpar[3]);
    h = mxd2ph(local, cpar[4]);
    a1 = cpar[5] * (M_PI / 18000.0);
    a2 = cpar[6] * (M_PI / 18000.0) + a1;

    if (w == 0 || h == 0 || a1 == a2)
      break;

    cairo_new_path(local->cairo);
    cairo_save(local->cairo);
    cairo_translate(local->cairo, x + w, y + h);
    cairo_scale(local->cairo, w, h);
    cairo_arc_negative(local->cairo, 0., 0., 1., -a1, -a2);
    cairo_restore (local->cairo);
    switch (cpar[7]) {
    case 1:
      cairo_line_to(local->cairo, x + w, y + h);
      /* fall through */
    case 2:
      cairo_close_path(local->cairo);
      cairo_fill(local->cairo);
      break;
    case 3:
      cairo_line_to(local->cairo, x + w, y + h);
      /* fall through */
    case 4:
      cairo_close_path(local->cairo);
      cairo_stroke(local->cairo);
      break;
    default:
      cairo_stroke(local->cairo);
    }
    break;
  case 'B':
    cairo_new_path(local->cairo);
    if (cpar[1] <= cpar[3]) {
      x = mxd2px(local, cpar[1]);
      w = mxd2pw(local, cpar[3] - cpar[1]);
    } else {
      x = mxd2px(local, cpar[3]);
      w = mxd2pw(local, cpar[1] - cpar[3]);
    }

    if (cpar[2] <= cpar[4]) {
      y = mxd2py(local, cpar[2]);
      h = mxd2ph(local, cpar[4] - cpar[2]);
    } else {
      y = mxd2py(local, cpar[4]);
      h = mxd2ph(local, cpar[2] - cpar[4]);
    }
    cairo_rectangle(local->cairo, x, y, w, h);
    if (cpar[5] == 0) {
      cairo_stroke(local->cairo);
    } else {
      cairo_fill(local->cairo);
    }
    break;
  case 'P':
    cairo_new_path(local->cairo);
    cairo_arc(local->cairo, mxd2px(local, cpar[1]), mxd2py(local, cpar[2]), mxd2pw(local, 1), 0, 2 * M_PI);
    cairo_fill(local->cairo);
    break;
  case 'R':
    cairo_new_path(local->cairo);
    if (cpar[1] == 0)
      break;

    for (i = 0; i < cpar[1]; i++) {
      cairo_line_to(local->cairo,
		    mxd2px(local, cpar[i * 2 + 2]),
		    mxd2py(local, cpar[i * 2 + 3]));
    }
    cairo_stroke(local->cairo);
    break;
  case 'D':
    cairo_new_path(local->cairo);

    if (cpar[1] == 0)
      break;

    for (i = 0; i < cpar[1]; i++) {
      cairo_line_to(local->cairo,
		    mxd2px(local, cpar[i * 2 + 3]),
		    mxd2py(local, cpar[i * 2 + 4]));
    }
    cairo_close_path(local->cairo);

    switch (cpar[2]) {
    case 0:
      cairo_stroke(local->cairo);
      break;
    case 1:
      cairo_set_fill_rule(local->cairo, CAIRO_FILL_RULE_EVEN_ODD);
      cairo_fill(local->cairo);
      break;
    case 2:
      cairo_set_fill_rule(local->cairo, CAIRO_FILL_RULE_WINDING);
      cairo_fill(local->cairo);
      break;
    }
    break;
  case 'F':
    g_free(local->fontalias);
    local->fontalias = g_strdup(cstr);
    break;
  case 'H':
    fontspace = cpar[2] / 72.0 * 25.4;
    local->fontspace = fontspace;
    fontsize = cpar[1] / 72.0 * 25.4;
    local->fontsize = fontsize;
    fontdir = cpar[3] * MPI / 18000.0;
    fontsin = sin(fontdir);
    fontcos = cos(fontdir);
    local->fontdir = (cpar[3] % 36000) / 100.0;
    if (local->fontdir < 0) {
      local->fontdir += 360;
    }
    local->fontsin = fontsin;
    local->fontcos = fontcos;
    font_style = (cpar[0] > 3) ? cpar[4] : -1;
    local->loadfont = loadfont(local->fontalias, font_style, &local->symbol);
    break;
  case 'S':
    if (local->loadfont == NULL)
      break;

    tmp = gra2cairo_get_utf8_str(cstr, local->symbol);
    if (tmp) {
      draw_str(local, TRUE, tmp, local->loadfont, local->fontsize, local->fontspace, NULL, NULL, NULL);
      g_free(tmp);
    }
    break;
  case 'K':
    if (local->loadfont == NULL)
      break;

    tmp = sjis_to_utf8(cstr);
    if (tmp) {
      draw_str(local, TRUE, tmp, local->loadfont, local->fontsize, local->fontspace, NULL, NULL, NULL);
      g_free(tmp);
    }
    break;
  default:
    break;
  }
  return 0;
}
コード例 #3
0
ファイル: broadway-demo.c プロジェクト: simokivimaki/gtk
static void
snippet(cairo_t *cr, int i)
{
  if (1)
    {
      cairo_save(cr);
      cairo_rotate (cr, i * 0.002);
      /* a custom shape that could be wrapped in a function */
      double x0      = 25.6,   /* parameters like cairo_rectangle */
	y0      = 25.6,
	rect_width  = 204.8,
	rect_height = 204.8,
	radius = 102.4;   /* and an approximate curvature radius */

      double x1,y1;

      x1=x0+rect_width;
      y1=y0+rect_height;
      if (rect_width/2<radius) {
	if (rect_height/2<radius) {
	  cairo_move_to  (cr, x0, (y0 + y1)/2);
	  cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
	  cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
	  cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
	  cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
	} else {
	  cairo_move_to  (cr, x0, y0 + radius);
	  cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
	  cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
	  cairo_line_to (cr, x1 , y1 - radius);
	  cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
	  cairo_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
	}
      } else {
	if (rect_height/2<radius) {
	  cairo_move_to  (cr, x0, (y0 + y1)/2);
	  cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
	  cairo_line_to (cr, x1 - radius, y0);
	  cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
	  cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
	  cairo_line_to (cr, x0 + radius, y1);
	  cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
	} else {
	  cairo_move_to  (cr, x0, y0 + radius);
	  cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
	  cairo_line_to (cr, x1 - radius, y0);
	  cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
	  cairo_line_to (cr, x1 , y1 - radius);
	  cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
	  cairo_line_to (cr, x0 + radius, y1);
	  cairo_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
	}
      }
      cairo_close_path (cr);

      cairo_set_source_rgb (cr, 0.5, 0.5, 1);
      cairo_fill_preserve (cr);
      cairo_set_source_rgba (cr, 0.5, 0, 0, 0.5);
      cairo_set_line_width (cr, 10.0);
      cairo_stroke (cr);
      cairo_restore(cr);
    }
  if (1)
    {
      double xc = 128.0;
      double yc = 128.0;
      double radius = 100.0;
      double angle1 = (45.0 + i * 5)  * (M_PI/180.0);  /* angles are specified */
      double angle2 = (180.0 + i * 5) * (M_PI/180.0);  /* in radians           */

      cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);

      cairo_set_line_width (cr, 10.0);
      cairo_arc (cr, xc, yc, radius, angle1, angle2);
      cairo_stroke (cr);

      /* draw helping lines */
      cairo_set_source_rgba (cr, 1, 0.2, 0.2, 0.6);
      cairo_set_line_width (cr, 6.0);

      cairo_arc (cr, xc, yc, 10.0, 0, 2*M_PI);
      cairo_fill (cr);

      cairo_arc (cr, xc, yc, radius, angle1, angle1);
      cairo_line_to (cr, xc, yc);
      cairo_arc (cr, xc, yc, radius, angle2, angle2);
      cairo_line_to (cr, xc, yc);
      cairo_stroke (cr);
    }
}
コード例 #4
0
ファイル: plot_view.cpp プロジェクト: constcast/tcpflow
void plot_view::render(cairo_t *cr, const plot_view::bounds_t &bounds) {
    cairo_matrix_t original_matrix;
    cairo_get_matrix(cr, &original_matrix);

    // purple background for padding checking
    //cairo_set_source_rgb(cr, 0.50, 0.00, 0.50);
    //cairo_rectangle(cr, bounds.x, bounds.y, bounds.width, bounds.height);
    //cairo_fill(cr);

    double pad_left = width * pad_left_factor;
    double pad_top = height * pad_top_factor;
    double pad_bottom = height * pad_bottom_factor;
    double pad_right = width * pad_right_factor;

    // compute bounds for subclasses to render content into
    bounds_t content_bounds;

    content_bounds.x = bounds.x + pad_left;
    content_bounds.y = bounds.y + pad_top;
    content_bounds.width = bounds.width - pad_right - pad_left;
    content_bounds.height = bounds.height - pad_bottom - pad_top;

    cairo_text_extents_t title_extents;
    cairo_text_extents_t subtitle_extents;
    double font_size_title = title_font_size;

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

    double title_base_y = 0.0;
    if(title_on_bottom) {
        title_base_y = bounds.height - pad_bottom;
    }

    cairo_select_font_face(cr, "Sans",
               CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(cr, font_size_title);
    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_text_extents(cr, title.c_str(), &title_extents);
    // Is the title too wide?
    double title_max_width = bounds.width * title_max_width_ratio;
    if(title_extents.width > title_max_width) {
        // scale the font size accordingly
        font_size_title *= title_max_width / title_extents.width;
        cairo_set_font_size(cr, font_size_title);
        cairo_text_extents(cr, title.c_str(), &title_extents);
    }
    // derive subtitle size and measure
    double font_size_subtitle = font_size_title *
        subtitle_font_size_factor;
    cairo_set_font_size(cr, font_size_subtitle);
    cairo_text_extents(cr, subtitle.c_str(), &subtitle_extents);
    double intertitle_padding = subtitle_extents.height *
        subtitle_y_pad_factor;
    cairo_set_font_size(cr, font_size_title);
    double title_padded_height = title_extents.height *
        title_y_pad_factor;
    // render title text
    cairo_move_to(cr, (bounds.width - title_extents.width) / 2.0,
          title_base_y + title_extents.height +
          (title_padded_height - title_extents.height) / 2);
    cairo_show_text(cr, title.c_str());
    // render subtitle text
    cairo_set_font_size(cr, font_size_subtitle);
    cairo_move_to(cr, (bounds.width - subtitle_extents.width) / 2.0,
          title_base_y + ((title_padded_height - title_extents.height) / 2) +
          title_extents.height + intertitle_padding +
          subtitle_extents.height);
    cairo_show_text(cr, subtitle.c_str());

    // render axis labels

    cairo_matrix_t unrotated_matrix;
    cairo_get_matrix(cr, &unrotated_matrix);
    cairo_text_extents_t axis_label_extents;
    cairo_set_font_size(cr, y_axis_font_size);
    cairo_text_extents(cr, y_label.c_str(), &axis_label_extents);
    double y_label_x = 0.0 + axis_label_extents.height;
    double y_label_centering_pad = ((content_bounds.height - axis_label_extents.width) / 2.0);
    double y_label_y = pad_top + y_label_centering_pad + axis_label_extents.width;
    cairo_move_to(cr, y_label_x, y_label_y);
    cairo_rotate(cr, -M_PI / 2.0);
    cairo_show_text(cr, y_label.c_str());
    cairo_set_matrix(cr, &unrotated_matrix);
    // add y axis decoration
    // TODO not implemented for brevity

    cairo_set_font_size(cr, x_axis_font_size);
    cairo_text_extents(cr, x_label.c_str(), &axis_label_extents);
    double x_label_centering_pad = (content_bounds.width - axis_label_extents.width) / 2.0;
    double x_label_x = pad_left + x_label_centering_pad;
    double x_label_y = bounds.height;
    cairo_move_to(cr, x_label_x, x_label_y);
    cairo_show_text(cr, x_label.c_str());

    // add x axis decoration
    if(x_axis_decoration == AXIS_SPAN_ARROW || x_axis_decoration == AXIS_SPAN_STOP) {
        double angle = span_arrow_angle;
        double line_width = x_axis_font_size * text_line_base_width;
        double tip_length = line_width * 10.0;
        if(x_axis_decoration == AXIS_SPAN_STOP) {
            angle = span_stop_angle;
            tip_length = line_width * 5.0;
        }
        double gap = line_width * 10.0;
        double x = x_label_x - gap;
        double y = x_label_y - axis_label_extents.height / 3.0;
        double pr_x, pr_y; // previous x and y positions
        // left of label
        cairo_move_to(cr, x, y);
        pr_x = x;
        pr_y = y;
        x = pr_x - (x_label_centering_pad - gap);
        y = pr_y;
        cairo_line_to(cr, x, y);
        pr_x = x;
        pr_y = y;
        x = pr_x + tip_length * sin(angle + M_PI / 2.0);
        y = pr_y + tip_length * cos(angle + M_PI / 2.0);
        cairo_line_to(cr, x, y);
        cairo_move_to(cr, pr_x, pr_y);
        x = pr_x + tip_length * sin(-angle + M_PI / 2.0);
        y = pr_y + tip_length * cos(-angle + M_PI / 2.0);
        cairo_line_to(cr, x, y);
        // right of label
        x = x_label_x + axis_label_extents.width + gap;
        y = x_label_y - axis_label_extents.height / 3.0;
        cairo_move_to(cr, x, y);
        pr_x = x;
        pr_y = y;
        x = pr_x + (x_label_centering_pad - gap);
        y = pr_y;
        cairo_line_to(cr, x, y);
        pr_x = x;
        pr_y = y;
        x = pr_x + tip_length * sin(angle - M_PI / 2.0);
        y = pr_y - tip_length * cos(angle - M_PI / 2.0);
        cairo_line_to(cr, x, y);
        cairo_move_to(cr, pr_x, pr_y);
        x = pr_x + tip_length * sin(-angle - M_PI / 2.0);
        y = pr_y - tip_length * cos(-angle - M_PI / 2.0);
        cairo_line_to(cr, x, y);
        cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
        cairo_set_line_width(cr, line_width);
        cairo_stroke(cr);
    }

    // render ticks

    double tick_length = bounds.width * tick_length_factor;
    double tick_width = bounds.height * tick_width_factor;

    // y ticks (packet counts)

    cairo_set_font_size(cr, y_tick_font_size);

    // translate down so the top of the window aligns with the top of
    // the graph itself
    cairo_translate(cr, 0, pad_top);

    double y_height = bounds.height - pad_bottom - pad_top;
    double y_tick_spacing = 0.0;
    if(y_tick_labels.size() > 1) {
        y_tick_spacing = y_height / (double) (y_tick_labels.size() - 1);
    }
    for(size_t ii = 0; ii < y_tick_labels.size(); ii++) {
        cairo_text_extents_t label_extents;
        double yy = y_height - (((double) ii) * y_tick_spacing);
        string label = y_tick_labels.at(ii);

        cairo_text_extents(cr, label.c_str(),
               &label_extents);
        cairo_move_to(cr, (pad_left - tick_length - label_extents.width),
          yy + (label_extents.height / 2));
        cairo_show_text(cr, label.c_str());

        // tick mark
        cairo_rectangle(cr, pad_left - tick_length, yy - (tick_width / 2),
                tick_length, tick_width);
        cairo_fill(cr);
    }

    // right ticks (packet counts)

    cairo_set_font_size(cr, right_tick_font_size);

    if(right_tick_labels.size() > 1) {
        y_tick_spacing = y_height / (double) (right_tick_labels.size() - 1);
    }
    for(size_t ii = 0; ii < right_tick_labels.size(); ii++) {
        cairo_text_extents_t label_extents;
        double yy = y_height - (((double) ii) * y_tick_spacing);
        string label = right_tick_labels.at(ii);

        cairo_text_extents(cr, label.c_str(),
               &label_extents);
        cairo_move_to(cr, (bounds.width - pad_right + tick_length),
          yy + (label_extents.height / 2));
        cairo_show_text(cr, label.c_str());

        // tick mark
        cairo_rectangle(cr, bounds.width - pad_right, yy - (tick_width / 2),
                tick_length, tick_width);
        cairo_fill(cr);
    }
    cairo_set_matrix(cr, &original_matrix);
    cairo_translate(cr, bounds.x, bounds.y);

    // x ticks (time)
    // TODO prevent overlap

    cairo_set_font_size(cr, x_tick_font_size);

    cairo_translate(cr, pad_left, bounds.height - pad_bottom);

    double x_width = bounds.width - (pad_right + pad_left);
    double x_tick_spacing = x_width / (x_tick_labels.size() - 1);

    for(size_t ii = 0; ii < x_tick_labels.size(); ii++) {
        cairo_text_extents_t label_extents;
        double xx = ii * x_tick_spacing;

        const char *label = x_tick_labels.at(ii).c_str();

        cairo_text_extents(cr, label, &label_extents);
        double pad = ((label_extents.height * x_tick_label_pad_factor) -
                label_extents.height) / 2;

        // prevent labels from running off the edge of the image
        double label_x = xx - (label_extents.width / 2.0);
        label_x = max(label_x, - pad_left);
        label_x = min(bounds.width - label_extents.width, label_x);

        cairo_move_to(cr, label_x, label_extents.height + pad);
        cairo_show_text(cr, label);
    }

    cairo_set_matrix(cr, &original_matrix);
    cairo_translate(cr, bounds.x, bounds.y);

    // render legend

    cairo_text_extents_t legend_label_extents;
    double chip_length = 0.0;

    // derive color chip size from largest label height
    for(size_t ii = 0; ii < legend.size(); ii++) {
        const legend_entry_t &entry = legend.at(ii);
        cairo_text_extents(cr, entry.label.c_str(), &legend_label_extents);

        chip_length = max(chip_length, legend_label_extents.height);
    }
    chip_length *= legend_chip_factor;

    cairo_translate(cr, bounds.width - (pad_right * 0.9),
        pad_top);

    cairo_set_font_size(cr, legend_font_size);

    for(size_t ii = 0; ii < legend.size(); ii++) {
        const legend_entry_t &entry = legend.at(ii);

        // chip
        cairo_set_source_rgb(cr, entry.color.r, entry.color.g,
             entry.color.b);
        cairo_rectangle(cr, 0, 0, chip_length, chip_length);
        cairo_fill(cr);

        // label
        cairo_set_source_rgb(cr, 0, 0, 0);
        cairo_text_extents(cr, entry.label.c_str(),
               &legend_label_extents);
        cairo_move_to(cr, chip_length * 1.2, (chip_length / 2.0) +
                (legend_label_extents.height / 2.0));
        cairo_show_text(cr, entry.label.c_str());

        // translate down for the next legend entry
        cairo_translate(cr, 0, chip_length);
    }

    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_set_matrix(cr, &original_matrix);

    // render axes and update content bounds
    double axis_width = bounds.height * axis_thickness_factor;

    cairo_rectangle(cr, content_bounds.x, content_bounds.y, axis_width,
            content_bounds.height);
    cairo_rectangle(cr, content_bounds.x,
            content_bounds.y + (content_bounds.height - axis_width),
            content_bounds.width, axis_width);
    // if there are right hand ticks, draw a right-hand axis
    if(right_tick_labels.size() > 0) {
        cairo_rectangle(cr, content_bounds.x + content_bounds.width - axis_width, content_bounds.y, axis_width,
                content_bounds.height);
    }
    cairo_fill(cr);

    content_bounds.x += axis_width;
    content_bounds.width -= axis_width;
    if(right_tick_labels.size() > 0) {
        content_bounds.width -= axis_width;
    }
    content_bounds.height -= axis_width;

    // render data!

    render_data(cr, content_bounds);
}
コード例 #5
0
ファイル: ppg-ruler.c プロジェクト: chergert/perfkit
/**
 * ppg_ruler_draw_ruler:
 * @ruler: (in): A #PpgRuler.
 *
 * Draws the background of the ruler containing the time values and ticks
 * to an offscreen pixmap that can be blitted to the widget during
 * "expose-event".
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_draw_ruler (PpgRuler *ruler)
{
	PpgRulerPrivate *priv;
	GtkAllocation alloc;
	PangoLayout *layout;
	cairo_t *cr;
	GtkStyle *style;
	GdkColor text_color;
	gint text_width;
	gint text_height;
	gdouble every = 1.0;
	gdouble n_seconds;
	gdouble v;
	gdouble p;
	gint pw;
	gint ph;
	gint x;
	gint xx;
	gint n;
	gint z = 0;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	gtk_widget_get_allocation(GTK_WIDGET(ruler), &alloc);
	style = gtk_widget_get_style(GTK_WIDGET(ruler));
	cr = cairo_create(priv->ruler);

	cairo_save(cr);
	cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
	cairo_rectangle(cr, 0, 0, alloc.width, alloc.height);
	cairo_fill(cr);
	cairo_restore(cr);

	text_color = style->text[GTK_STATE_NORMAL];
	cairo_set_line_width(cr, 1.0);
	gdk_cairo_set_source_color(cr, &text_color);

	layout = pango_cairo_create_layout(cr);
	pango_layout_set_font_description(layout, priv->font_desc);
	pango_layout_set_markup(layout, "00:00:00.000", -1);
	pango_layout_get_pixel_size(layout, &text_width, &text_height);
	text_width += 5;

	n_seconds = priv->upper - priv->lower;
	if ((alloc.width / n_seconds) < text_width) {
		every = ceil(text_width / (alloc.width / n_seconds));
	}

	for (v = floor(priv->lower); v < priv->upper; v += every) {
		gdk_cairo_set_source_color(cr, &text_color);
		x = get_x_offset(priv, &alloc, v);
		cairo_move_to(cr, x + 0.5, alloc.height - 1.5);
		cairo_line_to(cr, x + 0.5, 0.5);

		/*
		 * Mini lines.
		 */
		for (p = v, n = 0, z = 0;
		     p < v + every;
		     p += (every / 10), n++, z++)
		{
			if (n == 0 || n == 10) {
				continue;
			}

			xx = get_x_offset(priv, &alloc, p);
			cairo_move_to(cr, xx + 0.5, alloc.height - 1.5);
			if (z % 2 == 0) {
				cairo_line_to(cr, xx + 0.5, text_height + 8.5);
			} else {
				cairo_line_to(cr, xx + 0.5, text_height + 5.5);
			}
		}

		cairo_stroke(cr);

		cairo_move_to(cr, x + 1.5, 1.5);
		ppg_ruler_update_layout_text(ruler, layout,
		                             CLAMP(v, priv->lower, priv->upper));

		/*
		 * If there is enough room to draw this layout before we get to the
		 * next layout, then draw it.
		 */
		pango_layout_get_pixel_size(layout, &pw, &ph);
		if ((x + pw) < get_x_offset(priv, &alloc, floor(v) + every)) {
			pango_cairo_show_layout(cr, layout);
		}
	}

	g_object_unref(layout);
	cairo_destroy(cr);
}
コード例 #6
0
ファイル: control.c プロジェクト: fhrtms/darktable
void *dt_control_expose(void *voidptr)
{
  int width, height, pointerx, pointery;
  if(!darktable.gui->surface) return NULL;
  width = dt_cairo_image_surface_get_width(darktable.gui->surface);
  height = dt_cairo_image_surface_get_height(darktable.gui->surface);
  GtkWidget *widget = dt_ui_center(darktable.gui->ui);
#if GTK_CHECK_VERSION(3, 20, 0)
  gdk_window_get_device_position(gtk_widget_get_window(widget),
      gdk_seat_get_pointer(gdk_display_get_default_seat(gtk_widget_get_display(widget))),
      &pointerx, &pointery, NULL);
#else
  GdkDevice *device
      = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(widget)));
  gdk_window_get_device_position(gtk_widget_get_window(widget), device, &pointerx, &pointery, NULL);
#endif

  // create a gtk-independent surface to draw on
  cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  cairo_t *cr = cairo_create(cst);

  // TODO: control_expose: only redraw the part not overlapped by temporary control panel show!
  //
  float tb = 8; // fmaxf(10, width/100.0);
  darktable.control->tabborder = tb;
  darktable.control->width = width;
  darktable.control->height = height;

  GdkRGBA color;
  GtkStyleContext *context = gtk_widget_get_style_context(widget);
  gboolean color_found = gtk_style_context_lookup_color (context, "bg_color", &color);
  if(!color_found)
  {
    color.red = 1.0;
    color.green = 0.0;
    color.blue = 0.0;
    color.alpha = 1.0;
  }
  gdk_cairo_set_source_rgba(cr, &color);

  cairo_set_line_width(cr, tb);
  cairo_rectangle(cr, tb / 2., tb / 2., width - tb, height - tb);
  cairo_stroke(cr);
  cairo_set_line_width(cr, 1.5);
  color_found = gtk_style_context_lookup_color (context, "really_dark_bg_color", &color);
  if(!color_found)
  {
    color.red = 1.0;
    color.green = 0.0;
    color.blue = 0.0;
    color.alpha = 1.0;
  }
  gdk_cairo_set_source_rgba(cr, &color);
  cairo_rectangle(cr, tb, tb, width - 2 * tb, height - 2 * tb);
  cairo_stroke(cr);

  cairo_save(cr);
  cairo_translate(cr, tb, tb);
  cairo_rectangle(cr, 0, 0, width - 2 * tb, height - 2 * tb);
  cairo_clip(cr);
  cairo_new_path(cr);
  // draw view
  dt_view_manager_expose(darktable.view_manager, cr, width - 2 * tb, height - 2 * tb, pointerx - tb,
                         pointery - tb);
  cairo_restore(cr);

  // draw log message, if any
  dt_pthread_mutex_lock(&darktable.control->log_mutex);
  if(darktable.control->log_ack != darktable.control->log_pos)
  {
    PangoRectangle ink;
    PangoLayout *layout;
    PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc);
    const float fontsize = DT_PIXEL_APPLY_DPI(14);
    pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE);
    pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
    layout = pango_cairo_create_layout(cr);
    pango_layout_set_font_description(layout, desc);
    pango_layout_set_text(layout, darktable.control->log_message[darktable.control->log_ack], -1);
    pango_layout_get_pixel_extents(layout, &ink, NULL);
    const float pad = DT_PIXEL_APPLY_DPI(20.0f), xc = width / 2.0;
    const float yc = height * 0.85 + DT_PIXEL_APPLY_DPI(10), wd = pad + ink.width * .5f;
    float rad = DT_PIXEL_APPLY_DPI(14);
    cairo_set_line_width(cr, 1.);
    cairo_move_to(cr, xc - wd, yc + rad);
    for(int k = 0; k < 5; k++)
    {
      cairo_arc(cr, xc - wd, yc, rad, M_PI / 2.0, 3.0 / 2.0 * M_PI);
      cairo_line_to(cr, xc + wd, yc - rad);
      cairo_arc(cr, xc + wd, yc, rad, 3.0 * M_PI / 2.0, M_PI / 2.0);
      cairo_line_to(cr, xc - wd, yc + rad);
      if(k == 0)
      {
        color_found = gtk_style_context_lookup_color (context, "selected_bg_color", &color);
        if(!color_found)
        {
          color.red = 1.0;
          color.green = 0.0;
          color.blue = 0.0;
          color.alpha = 1.0;
        }
        gdk_cairo_set_source_rgba(cr, &color);
        cairo_fill_preserve(cr);
      }
      cairo_set_source_rgba(cr, 0., 0., 0., 1.0 / (1 + k));
      cairo_stroke(cr);
      rad += .5f;
    }
    color_found = gtk_style_context_lookup_color (context, "fg_color", &color);
    if(!color_found)
    {
      color.red = 1.0;
      color.green = 0.0;
      color.blue = 0.0;
      color.alpha = 1.0;
    }
    gdk_cairo_set_source_rgba(cr, &color);
    cairo_move_to(cr, xc - wd + .5f * pad, (yc + 1. / 3. * fontsize) - fontsize);
    pango_cairo_show_layout(cr, layout);
    pango_font_description_free(desc);
    g_object_unref(layout);
  }
  // draw busy indicator
  if(darktable.control->log_busy > 0)
  {
    PangoRectangle ink;
    PangoLayout *layout;
    PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc);
    const float fontsize = DT_PIXEL_APPLY_DPI(14);
    pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE);
    pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
    layout = pango_cairo_create_layout(cr);
    pango_layout_set_font_description(layout, desc);
    pango_layout_set_text(layout, _("working.."), -1);
    pango_layout_get_pixel_extents(layout, &ink, NULL);
    const float xc = width / 2.0, yc = height * 0.85 - DT_PIXEL_APPLY_DPI(30), wd = ink.width * .5f;
    cairo_move_to(cr, xc - wd, yc + 1. / 3. * fontsize - fontsize);
    pango_cairo_layout_path(cr, layout);
    cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
    cairo_fill_preserve(cr);
    cairo_set_line_width(cr, 0.7);
    cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
    cairo_stroke(cr);
    pango_font_description_free(desc);
    g_object_unref(layout);
  }
  dt_pthread_mutex_unlock(&darktable.control->log_mutex);

  cairo_destroy(cr);

  cairo_t *cr_pixmap = cairo_create(darktable.gui->surface);
  cairo_set_source_surface(cr_pixmap, cst, 0, 0);
  cairo_paint(cr_pixmap);
  cairo_destroy(cr_pixmap);

  cairo_surface_destroy(cst);
  return NULL;
}
コード例 #7
0
ファイル: result.cpp プロジェクト: joeedh/psa
void SaveSummary(const std::string &fname, Result &result, Config &config)
{
#if 0
    const float fnorm = 2.f / sqrtf(result.npoints);
    const float rnorm = 1.f / sqrtf(2.f / (SQRT3 * result.npoints));
    
    const int csize = 512;  // Composition cell size
    const double dashes[] = { 6.0, 3.0 };
    
    cairo_surface_t *surface =
    cairo_pdf_surface_create(fname.c_str(), 2*csize, 1.5*csize);
    cairo_pdf_surface_restrict_to_version(surface, CAIRO_PDF_VERSION_1_4);
    
    cairo_t *cr = cairo_create(surface);
    unsigned char *imgdata = NULL;
    cairo_surface_t *image = NULL;
    
    // Draw points
    const float radius = 2.0;
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    for (int i = 0; i < result.points.size(); ++i) {
        float x = result.points[i].x * csize;
        float y = (1.f - result.points[i].y) * csize;
        cairo_arc(cr, x, y, radius, 0, TWOPI);
        cairo_fill(cr);
    }
    
    // Draw radial power reference level
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1);
    cairo_set_line_width(cr, 1.0);
    cairo_set_dash(cr, dashes, 2, 0);
    const float rpref = 1.f - (1.f - config.fymin) / (config.fymax - config.fymin);
    cairo_move_to(cr,   csize, csize + rpref*csize/2);
    cairo_line_to(cr, 2*csize, csize + rpref*csize/2);
    cairo_stroke(cr);
    
    // Draw radial power
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    cairo_set_line_width(cr, 1.0);
    cairo_set_dash(cr, NULL, 0, 0);
    for (int i = 0; i < result.rp.size(); ++i) {
        float x = i / (float) result.rp.size();
        float y = 1.f - (result.rp[i] - config.fymin) / (config.fymax - config.fymin);
        Clamp01(y);
        if (i == 0)
            cairo_move_to(cr, csize + x*csize, csize + y*csize/2);
        else
            cairo_line_to(cr, csize + x*csize, csize + y*csize/2);
    }
    cairo_stroke(cr);
    
    // Draw spectrum
    int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,
                                               result.spectrum.width);
    result.spectrum.GetRGBA(imgdata);
    image = cairo_image_surface_create_for_data(imgdata, CAIRO_FORMAT_RGB24,
                                                result.spectrum.width,
                                                result.spectrum.height,
                                                stride);
    cairo_identity_matrix(cr);
    cairo_translate(cr, csize, 0);
    cairo_scale(cr, csize / (float) result.spectrum.width,
                    csize / (float) result.spectrum.height);
    cairo_set_source_surface(cr, image, 0, 0);
    cairo_paint(cr);
    
    // Draw RDF reference level
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1);
    cairo_set_line_width(cr, 1.0);
    cairo_set_dash(cr, dashes, 2, 0);
    const float rdfref = 1.f - (1.f - config.rymin) / (config.rymax - config.rymin);
    cairo_move_to(cr, 0, csize + rdfref*csize/2);
    cairo_line_to(cr, csize, csize + rdfref*csize/2);
    cairo_stroke(cr);
    
    // Draw RDF
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    cairo_set_line_width(cr, 1.0);
    cairo_set_dash(cr, NULL, 0, 0);
    for (int i = 0; i < result.rdf.size(); ++i) {
        float x = i / (float) result.rdf.size();
        float y = 1.f - (result.rdf[i] - config.rymin) / (config.rymax - config.rymin);
        Clamp01(y);
        if (i == 0)
            cairo_move_to(cr, x*csize, csize + y*csize/2);
        else
            cairo_line_to(cr, x*csize, csize + y*csize/2);
    }
    cairo_stroke(cr);
    
    // Draw separators
    cairo_identity_matrix(cr);
    cairo_set_line_width(cr, 1.0);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    cairo_move_to(cr, 0, csize);
    cairo_line_to(cr, 2*csize, csize);
    cairo_stroke(cr);
    cairo_move_to(cr, csize, 0);
    cairo_line_to(cr, csize, 1.5*csize);
    cairo_stroke(cr);
    
    // Draw labels
    cairo_identity_matrix(cr);
    cairo_set_font_size(cr, 12.0);
    cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
                           CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    cairo_move_to(cr, 0.0125 * csize, 1.025 * csize);
    cairo_show_text(cr, "RDF");
    cairo_stroke(cr);
    cairo_move_to(cr, 1.0125 * csize, 1.025 * csize);
    cairo_show_text(cr, "Power Spectrum");
    cairo_stroke(cr);
    
    // Draw stats box
#ifdef PSA_HAS_CGAL
    int nlines = 5;
#else
    int nlines = 4;
#endif
    nlines += (result.nsets > 1);
    double offset = 0.03;
    double bsize[] = { 0.33 * csize, (nlines * offset + 0.01) * csize };
    double banchor = 0.0125 * csize;
    cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.7);
    cairo_rectangle(cr, banchor, banchor, bsize[0], bsize[1]);
    cairo_fill(cr);
    
    // Draw stats and corresponding labels
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    cairo_set_font_size(cr, 12.0);
    cairo_select_font_face(cr, "monospace", CAIRO_FONT_SLANT_NORMAL,
                           CAIRO_FONT_WEIGHT_NORMAL);
    const int len = 128;
    char label[len];
    double tanchor[2] = { 1.75 * banchor, 0.9 * banchor };
    
    int i = 1;
    if (result.nsets > 1) {
        snprintf(label, len, "Averaged over %d sets", result.nsets);
        cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize);
        cairo_show_text(cr, label);
        ++i;
    }
    snprintf(label, len, "Gbl. Mindist   %.5f", result.stats.mindist * rnorm);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);
    snprintf(label, len, "Avg. Mindist   %.5f", result.stats.avgmindist * rnorm);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);
#ifdef PSA_HAS_CGAL
    snprintf(label, len, "Orient. order  %.5f", result.stats.orientorder);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);
#endif
    snprintf(label, len, "Eff. Nyquist   %.5f", result.stats.effnyquist * fnorm);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);
    snprintf(label, len, "Oscillations   %.5f", result.stats.oscillations);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);

    cairo_stroke(cr);
    
    // Save and clean up
    cairo_show_page(cr);
    cairo_surface_destroy(image);
    if (imgdata) delete[] imgdata;
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
#endif
}
コード例 #8
0
ファイル: label.c プロジェクト: joninvski/darktable-old
static gboolean _label_expose(GtkWidget *widget, GdkEventExpose *event)
{
  g_return_val_if_fail(widget != NULL, FALSE);
  g_return_val_if_fail(DTGTK_IS_LABEL(widget), FALSE);
  g_return_val_if_fail(event != NULL, FALSE);
  GtkStyle *style=gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL,"GtkButton", GTK_TYPE_BUTTON);
  // uninitialized?
  if(style->depth == -1) return FALSE;
  int state = gtk_widget_get_state(widget);

  int x = widget->allocation.x;
  int y = widget->allocation.y;
  int width = widget->allocation.width;
  int height = widget->allocation.height;

  // Formating the display of text and draw it...
  PangoLayout *layout;
  layout = gtk_widget_create_pango_layout(widget,NULL);
  pango_layout_set_font_description(layout,style->font_desc);
  const gchar *text=gtk_label_get_text(GTK_LABEL(widget));
  pango_layout_set_text(layout,text,-1);
  GdkRectangle t= {x,y,x+width,y+height};
  int pw,ph;
  pango_layout_get_pixel_size(layout,&pw,&ph);


  // Begin cairo drawing

  cairo_t *cr;
  cr = gdk_cairo_create(widget->window);

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

  cairo_set_antialias(cr,CAIRO_ANTIALIAS_NONE);

  cairo_set_line_width(cr,1.0);
  cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND);
  if( DTGTK_LABEL(widget)->flags&DARKTABLE_LABEL_UNDERLINED )
  {
    cairo_move_to(cr,x,y+height-2);
    cairo_line_to(cr,x+width,y+height-2);
    cairo_stroke(cr);
  }
  else if( DTGTK_LABEL(widget)->flags&DARKTABLE_LABEL_BACKFILLED )
  {
    cairo_rectangle(cr,x,y,width,height);
    cairo_fill(cr);
  }
  else if( DTGTK_LABEL(widget)->flags&DARKTABLE_LABEL_TAB )
  {
    int rx=x,rw=pw+2;
    if( DTGTK_LABEL(widget)->flags&DARKTABLE_LABEL_ALIGN_RIGHT ) rx=x+width-pw-8;
    cairo_rectangle(cr,rx,y,rw+4,height-1);
    cairo_fill(cr);

    if( DTGTK_LABEL(widget)->flags&DARKTABLE_LABEL_ALIGN_RIGHT )
    {
      // /|
      cairo_move_to(cr,x+width-rw-6,y);
      cairo_line_to(cr,x+width-rw-6-15,y+height-2);
      cairo_line_to(cr,x+width-rw-6,y+height-2);
      cairo_fill(cr);

      // hline
      cairo_move_to(cr,x,y+height-1);
      cairo_line_to(cr,x+width-rw-6,y+height-1);
      cairo_stroke(cr);
    }
    else
    {
      // |
      cairo_move_to(cr,x+rw+4,y);
      cairo_line_to(cr,x+rw+4+15,y+height-2);
      cairo_line_to(cr,x+rw+4,y+height-2);
      cairo_fill(cr);

      // hline
      cairo_move_to(cr,x+rw+4,y+height-1);
      cairo_line_to(cr,x+width,y+height-1);
      cairo_stroke(cr);
    }
  }
  cairo_set_antialias(cr,CAIRO_ANTIALIAS_DEFAULT);
  cairo_destroy(cr);

  // draw text
  int lx=x+4, ly=y+((height/2.0)-(ph/2.0));
  if( DTGTK_LABEL(widget)->flags&DARKTABLE_LABEL_ALIGN_RIGHT ) lx=x+width-pw-6;
  else if( DTGTK_LABEL(widget)->flags&DARKTABLE_LABEL_ALIGN_CENTER ) lx=(width/2.0)-(pw/2.0);
  gtk_paint_layout(style,widget->window, state,TRUE,&t,widget,"label",lx,ly,layout);

  return FALSE;
}
コード例 #9
0
	WindowPanel::WindowPanel()
		: auto_hide_(false) {
		ClutterLayoutManager * main_layout = clutter_bin_layout_new(CLUTTER_BIN_ALIGNMENT_FIXED,
		                                                            CLUTTER_BIN_ALIGNMENT_FIXED);
		actor_ = clutter_box_new(main_layout);

		ClutterActor * menu = clutter_cairo_texture_new(110, 22);
		clutter_actor_set_position(menu, 10.0f, 0.0f);

		cairo_t * context = clutter_cairo_texture_create(CLUTTER_CAIRO_TEXTURE(menu));

		cairo_move_to(context, 0.0, 0.0);
		cairo_line_to(context, 0.0, 19.0);
		cairo_curve_to(context, 1.0, 21.0, 2.0, 22.0, 3.0, 22.0);
		cairo_line_to(context, 107.0, 22.0);
		cairo_curve_to(context, 108.0, 22.0, 109.0, 21.0, 110.0, 19.0);
		cairo_line_to(context, 110.0, 0.0);
		cairo_close_path(context);
		cairo_set_source_rgb(context, 0.8, 0.8, 0.8);
		cairo_fill_preserve(context);
		cairo_set_line_width(context, 1.0);
		cairo_set_source_rgb(context, 0.0, 0.0, 0.0);
		cairo_stroke(context);

		cairo_select_font_face(context, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
		cairo_set_font_size(context, 12.0);

		cairo_text_extents_t extents;
		cairo_text_extents(context, DISPLAY_NAME, &extents);
		cairo_move_to(context, 55.0 - ((extents.width / 2.0) + extents.x_bearing),
		              11.0 - ((extents.height / 2.0) + extents.y_bearing));

		cairo_text_path(context, DISPLAY_NAME);
		cairo_set_source_rgb(context, 0.0, 0.0, 0.0);
		cairo_fill(context);

		cairo_destroy(context);

		clutter_box_pack(CLUTTER_BOX(actor_), menu, NULL, NULL);

		ClutterLayoutManager * controls_layout = clutter_box_layout_new();
		clutter_box_layout_set_spacing(CLUTTER_BOX_LAYOUT(controls_layout), 10u);
		ClutterActor * controls = clutter_box_new(controls_layout);
		clutter_actor_add_constraint(controls, clutter_align_constraint_new(clutter_stage_get_default(),
		                             CLUTTER_ALIGN_X_AXIS, 0.95f));
		clutter_actor_add_constraint(controls, clutter_bind_constraint_new(clutter_stage_get_default(),
		                             CLUTTER_BIND_Y, 5.0f));

		fullscreen_button_ = clutter_cairo_texture_new(18, 16);
		clutter_actor_set_reactive(fullscreen_button_, TRUE);
		g_signal_connect(fullscreen_button_, "button-press-event", G_CALLBACK(fullscreen_clicked_cb), this);
		g_signal_connect(fullscreen_button_, "enter-event", G_CALLBACK(actor_highlight_on_cb), fullscreen_button_);
		g_signal_connect(fullscreen_button_, "leave-event", G_CALLBACK(actor_highlight_off_cb), fullscreen_button_);
		clutter_box_pack(CLUTTER_BOX(controls), fullscreen_button_, NULL, NULL);

		close_button_ = clutter_cairo_texture_new(15, 15);

		context = clutter_cairo_texture_create(CLUTTER_CAIRO_TEXTURE(close_button_));

		cairo_move_to(context, 1.0, 3.0);
		cairo_line_to(context, 3.0, 1.0);
		cairo_line_to(context, 8.0, 6.0);
		cairo_line_to(context, 13.0, 1.0);
		cairo_line_to(context, 15.0, 3.0);
		cairo_line_to(context, 10.0, 8.0);
		cairo_line_to(context, 15.0, 13.0);
		cairo_line_to(context, 13.0, 15.0);
		cairo_line_to(context, 8.0, 10.0);
		cairo_line_to(context, 3.0, 15.0);
		cairo_line_to(context, 1.0, 13.0);
		cairo_line_to(context, 6.0, 8.0);
		cairo_close_path(context);
		cairo_set_source_rgb(context, 1.0, 1.0, 1.0);
		cairo_fill_preserve(context);
		cairo_set_line_width(context, 1.0);
		cairo_set_source_rgb(context, 0.0, 0.0, 0.0);
		cairo_stroke(context);

		cairo_destroy(context);

		clutter_actor_set_reactive(close_button_, TRUE);
		g_signal_connect(close_button_, "button-press-event", G_CALLBACK(close_clicked_cb), NULL);
		g_signal_connect(close_button_, "enter-event", G_CALLBACK(actor_highlight_on_cb), close_button_);
		g_signal_connect(close_button_, "leave-event", G_CALLBACK(actor_highlight_off_cb), close_button_);
		clutter_box_pack(CLUTTER_BOX(controls), close_button_, NULL, NULL);

		draw_window_controls();

		clutter_box_pack(CLUTTER_BOX(actor_), controls, NULL, NULL);

		g_signal_connect(clutter_stage_get_default(), "fullscreen", G_CALLBACK(fullscreen_status_changed_cb), this);
		g_signal_connect(clutter_stage_get_default(), "unfullscreen", G_CALLBACK(fullscreen_status_changed_cb), this);
		g_signal_connect(clutter_stage_get_default(), "motion-event", G_CALLBACK(show_panel_cb), this);
	}
コード例 #10
0
int main(int argc, char *argv[]) {
    int pid = fork();
    if (!pid) {

      drawing_information dinformation;
      drawing_information* di = &dinformation;

      di->ball_x = 360;
      di->ball_y = 240;
      di->paddle_one_y = 0;
      di->paddle_two_y = 0;
      di->score_one = 0;
      di->score_two = 0;
      di->ball_speed = 1;

      int shmid;
      key_t key = 25568;

      if ((shmid = shmget(key, sizeof(drawing_information), IPC_CREAT | 0666)) < 0) {
	printf("Error shmgetting...\n");
	exit(1);
      }
      
      int width = 720;
      int height = 520;
      int videoFlags = SDL_SWSURFACE | SDL_RESIZABLE | SDL_DOUBLEBUF;
      int bpp = 32;
      
      if (SDL_Init(SDL_INIT_VIDEO) < 0) {
	return -1;
      }
      
      SDL_WM_SetCaption("Pong", "Pong");
      
      SDL_Surface *screen;
      screen = SDL_SetVideoMode(width, height, bpp, videoFlags);
      
      SDL_EnableKeyRepeat(300, 130);
      SDL_EnableUNICODE(1);
      
      SDL_Surface *sdl_surface = SDL_CreateRGBSurface ( 
						       videoFlags, width, height, 32, 
						       0x00ff0000, 
						       0x0000ff00, 
						       0x000000ff, 
						       0
							);
      
      int done = 0;
      
      while (!done) {
	di = (drawing_information *)shmat(shmid, NULL, 0);
	
	SDL_FillRect(sdl_surface, NULL, 0);
	
	cairo_surface_t *cairo_surface = cairo_image_surface_create_for_data((unsigned char *)sdl_surface->pixels, CAIRO_FORMAT_RGB24, sdl_surface->w, sdl_surface->h, sdl_surface->pitch);
	
	cairo_t *cr = cairo_create(cairo_surface);
	
	//do_drawing(cr);
	cairo_set_source_rgb(cr,255,255,255);
	cairo_rectangle(cr, 20, di->paddle_one_y, 7, 40);
	cairo_fill(cr);
	
	cairo_rectangle(cr, 693, di->paddle_two_y, 7, 40);
	cairo_fill(cr);
	
	cairo_arc(cr, di->ball_x, di->ball_y, 5, 0, 2*M_PI);
	cairo_fill(cr);

	cairo_move_to(cr, 0, 480);
	cairo_line_to(cr, 720, 480);

	cairo_stroke(cr);
	
	cairo_select_font_face(cr, "Courier",
			       CAIRO_FONT_SLANT_NORMAL,
			       CAIRO_FONT_WEIGHT_BOLD);

	cairo_set_font_size(cr, 38);

	cairo_move_to(cr, 20, 510);
	char *to_send = (char *)malloc(100);
	sprintf(to_send,
	  "%d",
	  di->score_one);

	cairo_show_text(cr, to_send);

	cairo_move_to(cr, 693, 510);
	sprintf(to_send,
		"%d",
		di->score_two);

	cairo_show_text(cr, to_send); 
		
	SDL_BlitSurface(sdl_surface, NULL, screen, NULL);
	SDL_Flip(screen);
	
	//dont with cairo surface
	cairo_surface_destroy(cairo_surface);
	cairo_destroy(cr);
	
	//Event handling
	SDL_Event event;
	while (SDL_PollEvent(&event)) {
	  switch(event.type) {
	  case SDL_KEYDOWN:
	    if (event.key.keysym.sym == SDLK_ESCAPE) {
	      done = 1;
	    }
	    else if (event.key.keysym.sym == SDLK_w) {
	      if (di->paddle_one_y > 15) {
		di->paddle_one_y -= 15;
	      }
	    }
	    else if (event.key.keysym.sym == SDLK_s) {
	      if (di->paddle_one_y < 410) {
		di->paddle_one_y += 15;
	      }
	    }
	    else if (event.key.keysym.sym == SDLK_UP) {
	      if (di->paddle_two_y > 15) {
		di->paddle_two_y -= 15;
	      }
	    }
	    else if (event.key.keysym.sym == SDLK_DOWN) {
	      if (di->paddle_two_y < 410) {
		di->paddle_two_y += 15;
	      }
	    }
	    break;
	  case SDL_QUIT:
	    done = 1;
	    break;
	  }
	}
	
	SDL_Delay(1);
	
      }
      
      //cleanup
      SDL_FreeSurface(sdl_surface);
      SDL_Quit();
      
      return 0;
      
    }
    else {
      drawing_information dinformation;
      drawing_information* di = &dinformation;

      di->ball_x = 360;
      di->ball_y = 240;
      di->paddle_one_y = 0;
      di->paddle_two_y = 0;
      di->score_one = 0;
      di->score_two = 0;

      int to_server;
      int from_server;
      char buffer[100];
      
      to_server = client_handshake(&from_server);
      
      while (1) {
	// Reading loop
	
	// Take input from user
	
	// Write to server
	
	// If the message is exit, then shut down
	// write(to_server, buffer, sizeof(buffer));
	
	// Get message from server
	read(from_server, buffer, sizeof(buffer));
	// Print confirmation
	char *to_send = parse_input(buffer, di);
	write(to_server, to_send, 100);
      }
    }
}
コード例 #11
0
ファイル: stats_graph.c プロジェクト: Prince781/gtorrent
gboolean
gt_gui_stats_graph_draw(GtkWidget *canvas, cairo_t *cr, gpointer data) {
	int width, height;
	double x, y;
	double largest = 1.0;
	double damp = 0.7;	// damp height factor
	char buf[50];
	cairo_text_extents_t te;
	uint64_t rate;
	int t;			// time
	struct sess_stat *p, *pb;

	if ((p = gt_gui_get_stat()) == NULL)
		return FALSE;

	width = gtk_widget_get_allocated_width(canvas);
	height = gtk_widget_get_allocated_height(canvas);

	cairo_set_line_width(cr, 0.3);

	// draw grid first
	cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
	cairo_rectangle(cr, 15, 15, width-30, height-30);
	cairo_stroke(cr);

	for (y = 15 + (height-30)/4; y < height-15; y += (height-30)/4) {
		cairo_move_to(cr, 15, y);
		cairo_line_to(cr, width-15, y);
		cairo_stroke(cr);
	}

	// draw chart
	cairo_set_line_width(cr, 1.3);
	cairo_set_source_rgb(cr, 0.7, 0.1, 0.3);
	largest = 0;
	for (pb = p; ; p = p->next) {
		if (p->val > largest)
			largest = p->val;
		if (p->next == pb)
			break;
	}
	p = pb;
	x = 15;
	for (pb = p; ; p = p->next) {
		if (x == 15)
			cairo_move_to(cr, x, 
				height-15-damp*(height-30)*(p->val/largest));
		else
			cairo_line_to(cr, x,
				height-15-damp*(height-30)*(p->val/largest));
		x += width / (STATSIZE-1);
		if (p->next == pb)
			break;
	}

	cairo_stroke(cr);

	// draw labels
	cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
	cairo_select_font_face(cr, "Cantarell", CAIRO_FONT_SLANT_NORMAL,
				CAIRO_FONT_WEIGHT_NORMAL);
	cairo_set_font_size(cr, 12);
	for (y = height-15; y >= 15; y -= (height-30)/4) {
		rate = (uint64_t)(largest/damp*(height-15-y)/(height-30));
		gt_trnt_getratep(rate, 2, buf);
		cairo_text_extents(cr, buf, &te);
		cairo_move_to(cr, 15.5, y - te.height/2);
		cairo_show_text(cr, buf);
	}
	for (x = 15.5, t = STATSIZE/2; x <= width-15; x += (width-30)/ 4) {
		snprintf(buf, 50, "%d", t);
		cairo_text_extents(cr, buf, &te);
		cairo_move_to(cr, x - te.width/2, height-14.5 + te.height);
		cairo_show_text(cr, buf);
		t -= STATSIZE/8;
	}

	return FALSE;
}
コード例 #12
0
//-----------------------------------------------------------------------------------
void ofxCairoTexture::draw(ofSubPath & path){
	if(!surface || !cr) return;
	const vector<ofSubPath::Command> & commands = path.getCommands();
	cairo_new_sub_path(cr);
	for(int i=0; i<(int)commands.size(); i++){
		switch(commands[i].type){
			case ofSubPath::Command::lineTo:
				curvePoints.clear();
				cairo_line_to(cr,commands[i].to.x,commands[i].to.y);
				break;
				
				
			case ofSubPath::Command::curveTo:
				curvePoints.push_back(commands[i].to);
				
				//code adapted from ofxVectorGraphics to convert catmull rom to bezier
				if(curvePoints.size()==4){
					ofPoint p1=curvePoints[0];
					ofPoint p2=curvePoints[1];
					ofPoint p3=curvePoints[2];
					ofPoint p4=curvePoints[3];
					
					//SUPER WEIRD MAGIC CONSTANT = 1/6 (this works 100% can someone explain it?)
					ofPoint cp1 = p2 + ( p3 - p1 ) * (1.0/6);
					ofPoint cp2 = p3 + ( p2 - p4 ) * (1.0/6);
					
					cairo_curve_to( cr, cp1.x, cp1.y, cp2.x, cp2.y, p3.x, p3.y );
					curvePoints.pop_front();
				}
				break;
				
				
			case ofSubPath::Command::bezierTo:
				curvePoints.clear();
				cairo_curve_to(cr,commands[i].cp1.x,commands[i].cp1.y,commands[i].cp2.x,commands[i].cp2.y,commands[i].to.x,commands[i].to.y);
				break;
				
			case ofSubPath::Command::quadBezierTo:
				curvePoints.clear();
				cairo_curve_to(cr,commands[i].cp1.x,commands[i].cp1.y,commands[i].cp2.x,commands[i].cp2.y,commands[i].to.x,commands[i].to.y);
				break;
				
				
			case ofSubPath::Command::arc:
				curvePoints.clear();
				// elliptic arcs not directly supported in cairo, lets scale y
				if(commands[i].radiusX!=commands[i].radiusY){
					float ellipse_ratio = commands[i].radiusY/commands[i].radiusX;
					pushMatrix();
					translate(0,-commands[i].to.y*ellipse_ratio);
					scale(1,ellipse_ratio);
					translate(0,commands[i].to.y/ellipse_ratio);
					cairo_arc(cr,commands[i].to.x,commands[i].to.y,commands[i].radiusX,commands[i].angleBegin*DEG_TO_RAD,commands[i].angleEnd*DEG_TO_RAD);
					//cairo_set_matrix(cr,&stored_matrix);
					popMatrix();
				}else{
					cairo_arc(cr,commands[i].to.x,commands[i].to.y,commands[i].radiusX,commands[i].angleBegin*DEG_TO_RAD,commands[i].angleEnd*DEG_TO_RAD);
				}
				break;
		}
	}
	
	if(path.isClosed()){
		cairo_close_path(cr);
	}
	
	
}
コード例 #13
0
//-----------------------------------------------------------------------------------
void ofxCairoTexture::draw(ofMesh & primitive){
	if(primitive.getNumVertices()==0) return;
	pushMatrix();
	cairo_matrix_init_identity(getCairoMatrix());
	cairo_new_path(cr);
	//if(indices.getNumIndices()){
	
	int i = 1;
	ofVec3f v = transform(primitive.getVertex(primitive.getIndex(0)));
	ofVec3f v2;
	cairo_move_to(cr,v.x,v.y);
	if(primitive.getMode()==OF_PRIMITIVE_TRIANGLE_STRIP){
		v = transform(primitive.getVertex(primitive.getIndex(1)));
		cairo_line_to(cr,v.x,v.y);
		v = transform(primitive.getVertex(primitive.getIndex(2)));
		cairo_line_to(cr,v.x,v.y);
		i=2;
	}
	for(; i<primitive.getNumIndices(); i++){
		v = transform(primitive.getVertex(primitive.getIndex(i)));
		switch(primitive.getMode()){
			case(OF_PRIMITIVE_TRIANGLES):
				if((i+1)%3==0){
					cairo_line_to(cr,v.x,v.y);
					v2 = transform(primitive.getVertex(primitive.getIndex(i-2)));
					cairo_line_to(cr,v2.x,v2.y);
					cairo_move_to(cr,v.x,v.y);
				}else if((i+3)%3==0){
					cairo_move_to(cr,v.x,v.y);
				}else{
					cairo_line_to(cr,v.x,v.y);
				}
				
				break;
			case(OF_PRIMITIVE_TRIANGLE_STRIP):
				v2 = transform(primitive.getVertex(primitive.getIndex(i-2)));
				cairo_line_to(cr,v.x,v.y);
				cairo_line_to(cr,v2.x,v2.y);
				cairo_move_to(cr,v.x,v.y);
				break;
			case(OF_PRIMITIVE_TRIANGLE_FAN):
				//triangles.addIndex((GLuint)0);
				 //triangles.addIndex((GLuint)1);
				 //triangles.addIndex((GLuint)2);
				 //for(int i = 2; i < primitive.getNumVertices()-1;i++){
				 //triangles.addIndex((GLuint)0);
				 //triangles.addIndex((GLuint)i);
				 //triangles.addIndex((GLuint)i+1);
				 //}
				break;
			default:break;
		}
	}
	
	cairo_move_to(cr,primitive.getVertex(primitive.getIndex(primitive.getNumIndices()-1)).x,primitive.getVertex(primitive.getIndex(primitive.getNumIndices()-1)).y);
	
	if(ofGetStyle().lineWidth>0){
		
		cairo_stroke( cr );
	}
	popMatrix();
}
コード例 #14
0
ファイル: paint.c プロジェクト: andyTsing/darktable
void dtgtk_cairo_paint_modulegroup_effect(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags)
{
  gint s = w < h ? w : h;
  cairo_translate(cr, x + (w / 2.) - (s / 2.), y + (h / 2.) - (s / 2.));
  cairo_scale(cr, s, s);
  cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
  cairo_set_line_width(cr, 0.1);

  /* draw circle */
  cairo_arc(cr, 0.5, 0.5, 0.40, -M_PI, M_PI);
  cairo_stroke(cr);

  /* sparkles */
  cairo_set_line_width(cr, 0.06);

  cairo_move_to(cr, 0.378, 0.502);
  cairo_line_to(cr, 0.522, 0.549);
  cairo_line_to(cr, 0.564, 0.693);
  cairo_line_to(cr, 0.653, 0.569);
  cairo_line_to(cr, 0.802, 0.573);
  cairo_line_to(cr, 0.712, 0.449);
  cairo_line_to(cr, 0.762, 0.308);
  cairo_line_to(cr, 0.618, 0.356);
  cairo_line_to(cr, 0.500, 0.264);
  cairo_line_to(cr, 0.500, 0.417);
  cairo_close_path(cr);

  cairo_move_to(cr, 0.269, 0.717);
  cairo_line_to(cr, 0.322, 0.735);
  cairo_line_to(cr, 0.337, 0.787);
  cairo_line_to(cr, 0.370, 0.742);
  cairo_line_to(cr, 0.424, 0.743);
  cairo_line_to(cr, 0.391, 0.698);
  cairo_line_to(cr, 0.409, 0.646);
  cairo_line_to(cr, 0.357, 0.664);
  cairo_line_to(cr, 0.314, 0.630);
  cairo_line_to(cr, 0.314, 0.686);

  cairo_move_to(cr, 0.217, 0.366);
  cairo_line_to(cr, 0.271, 0.384);
  cairo_line_to(cr, 0.286, 0.437);
  cairo_line_to(cr, 0.319, 0.391);
  cairo_line_to(cr, 0.374, 0.393);
  cairo_line_to(cr, 0.341, 0.347);
  cairo_line_to(cr, 0.360, 0.295);
  cairo_line_to(cr, 0.306, 0.312);
  cairo_line_to(cr, 0.263, 0.279);
  cairo_line_to(cr, 0.263, 0.335);

  cairo_close_path(cr);

  cairo_stroke(cr);
}
コード例 #15
0
ファイル: live_view.c プロジェクト: CarVac/darktable
/*
    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");
}

uint32_t views(dt_lib_module_t *self)
{
  return DT_VIEW_TETHERING;
}

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, 5);
  GtkWidget *box;

  box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
  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);
  lib->live_view_zoom = dtgtk_button_new(
      dtgtk_cairo_paint_zoom, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER); // TODO: see _zoom_live_view_clicked
  lib->rotate_ccw = dtgtk_button_new(dtgtk_cairo_paint_refresh, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER);
  lib->rotate_cw = dtgtk_button_new(dtgtk_cairo_paint_refresh,
                                    CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_UP);
  lib->flip = dtgtk_togglebutton_new(dtgtk_cairo_paint_flip,
                                     CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_UP);

  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, 5);
  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);
  lib->focus_in_small
      = dtgtk_button_new(dtgtk_cairo_paint_arrow, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER
                                                  | CPF_DIRECTION_LEFT); // 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); // 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);

  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, 5);
  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');

    int zoom = 1;
    float imgwd = 0.90f;
    if(zoom == 1)
    {
      imgwd = .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);
      if(zoom == 1)
      {
        scale = fminf(fminf(w, pw) / (float)buf.width, fminf(h, ph) / (float)buf.height);
      }
      else
        scale = fminf(w * imgwd / (float)buf.width, h * imgwd / (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");
            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)
    {
      float 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);
      }

      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);
}
コード例 #16
0
ファイル: cairo.c プロジェクト: initlove/wechat
static void do_drawing(cairo_t *cr)
{
	double angle[TC + 1];
	double X[TC + 1];
	double Y[TC + 1];
	int i;
	
	double degree;
	for (i = 0; i < TC; i++) {
		degree = 360/TC * i;
		angle[i] = 1.0*(270 + degree) * (M_PI)/180.0;
		X[i] = MID_X + sin(degree * M_PI /180.0) * MID_R;
		Y[i] = MID_Y - cos(degree * M_PI /180.0) * MID_R;
	}

	for (i = 0; i < TC; i++) {
		float red, green;
		if (counts[i] > 2500) {
			red = 1.0;
			green = 1.0*(5000-counts[i]) /2500;
		} else {
			green = 1.0;
			red = 1.0*(counts[i]) / 2500;
		}
		cairo_set_source_rgba (cr, red, green, 0, 1);

		cairo_move_to (cr, MID_X, MID_Y);
		cairo_line_to (cr, X[i], Y[i]);
		cairo_arc (cr, MID_X, MID_Y, MID_R, angle[i], angle[(i+1)%TC]);
		cairo_line_to (cr, MID_X, MID_Y);
		cairo_fill (cr);
	}
	
	cairo_set_source_rgba (cr, 0, 0, 0, 1);
	cairo_set_line_width (cr, 1.0);
	for (i = 0; i < TC; i++) {
		cairo_move_to (cr, MID_X, MID_Y);
		cairo_line_to (cr, X[i], Y[i]);
		cairo_arc (cr, MID_X, MID_Y, MID_R, angle[i], angle[(i+1)%TC]);
		cairo_line_to (cr, MID_X, MID_Y);
		cairo_stroke (cr);
	}

	cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
                               CAIRO_FONT_WEIGHT_BOLD);
	cairo_set_font_size (cr, 20.0);

	for (i = 0; i < TC; i++) {
		float x, y;
		gchar *hour;

		degree = 360/TC * i;
		x = MID_X + sin(degree * M_PI /180.0) * MID_R * 1.2 - 5;
		y = MID_Y - cos(degree * M_PI /180.0) * MID_R * 1.2 + 5;
		
		cairo_set_font_size (cr, 20.0);
		cairo_set_source_rgba (cr, 0, 0, 0, 1);
		cairo_move_to (cr, x, y);
		hour = g_strdup_printf ("%d", i);
		cairo_show_text (cr, hour);

		if (i == 8) {
			cairo_set_source_rgba (cr, 1, 0, 0, 1);
			cairo_set_font_size (cr, 15.0);
			cairo_move_to (cr, x + 20, y);
			cairo_show_text (cr, "开始上班");
		} else if (i == 13) {
			cairo_set_source_rgba (cr, 1, 0, 0, 1);
			cairo_set_font_size (cr, 15.0);
			cairo_move_to (cr, x + 5, y + 20);
			cairo_show_text (cr, "午饭时间");
		} else if (i == 19) {
			cairo_set_source_rgba (cr, 1, 0, 0, 1);
			cairo_set_font_size (cr, 15.0);
			cairo_move_to (cr, x - 10, y - 20);
			cairo_show_text (cr, "回家晚饭");
		}
	}

	gchar *note[6] = {"微信群统计", "数据来源:", "真实群一年来", "4万多条聊天记录", "绿色表示发言较少", "红色表示发言较多"};
	cairo_set_font_size (cr, 20);
	cairo_move_to (cr,  700, 180);
	cairo_show_text (cr, note[0]);
	for (i = 1; i < 6; i++) {
		cairo_move_to (cr,  700, 200 + i * 30);
		cairo_show_text (cr, note[i]);
	}
}
コード例 #17
0
ファイル: circle.c プロジェクト: CarVac/darktable
static void dt_circle_events_post_expose(cairo_t *cr, float zoom_scale, dt_masks_form_gui_t *gui, int index)
{
  double dashed[] = { 4.0, 4.0 };
  dashed[0] /= zoom_scale;
  dashed[1] /= zoom_scale;
  int len = sizeof(dashed) / sizeof(dashed[0]);
  dt_masks_form_gui_points_t *gpt = (dt_masks_form_gui_points_t *)g_list_nth_data(gui->points, index);
  if(!gpt) return;
  float dx = 0, dy = 0, dxs = 0, dys = 0;
  if((gui->group_selected == index) && gui->form_dragging)
  {
    dx = gui->posx + gui->dx - gpt->points[0];
    dy = gui->posy + gui->dy - gpt->points[1];
  }
  if((gui->group_selected == index) && gui->source_dragging)
  {
    dxs = gui->posx + gui->dx - gpt->source[0];
    dys = gui->posy + gui->dy - gpt->source[1];
  }

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

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

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

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

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



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

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

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

      // (arrowx,arrowy) is the point of intersection, we move it (factor 1.11) a bit farther than the
      // inner circle to avoid superposition.
      float arrowx = gpt->points[0] + 1.11 * radius * cos(cangle) + dx;
      float arrowy = gpt->points[1] + 1.11 * radius * sin(cangle) + dy;

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

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

    // we draw the source
    cairo_set_dash(cr, dashed, 0, 0);
    if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging))
      cairo_set_line_width(cr, 2.5 / zoom_scale);
    else
      cairo_set_line_width(cr, 1.5 / zoom_scale);
    cairo_set_source_rgba(cr, .3, .3, .3, .8);
    cairo_move_to(cr, gpt->source[2] + dxs, gpt->source[3] + dys);
    for(int i = 2; i < gpt->source_count; i++)
    {
      cairo_line_to(cr, gpt->source[i * 2] + dxs, gpt->source[i * 2 + 1] + dys);
    }
    cairo_line_to(cr, gpt->source[2] + dxs, gpt->source[3] + dys);
    cairo_stroke_preserve(cr);
    if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging))
      cairo_set_line_width(cr, 1.0 / zoom_scale);
    else
      cairo_set_line_width(cr, 0.5 / zoom_scale);
    cairo_set_source_rgba(cr, .8, .8, .8, .8);
    cairo_stroke(cr);
  }
}
コード例 #18
0
void Path::addLineTo(const FloatPoint& p)
{
    cairo_t* cr = platformPath()->context();
    cairo_line_to(cr, p.x(), p.y());
}
コード例 #19
0
static cairo_status_t
twin_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
			       unsigned long         glyph,
			       cairo_t              *cr,
			       cairo_text_extents_t *metrics)
{
    double x1, y1, x2, y2, x3, y3;
    double marginl;
    twin_scaled_properties_t *props;
    twin_snap_info_t info;
    const int8_t *b;
    const int8_t *g;
    int8_t w;
    double gw;

    props = cairo_scaled_font_get_user_data (scaled_font, &twin_properties_key);

    /* Save glyph space, we need it when stroking */
    cairo_save (cr);

    /* center the pen */
    cairo_translate (cr, props->penx * .5, -props->peny * .5);

    /* small-caps */
    if (props->face_props->smallcaps && glyph >= 'a' && glyph <= 'z') {
	glyph += 'A' - 'a';
	/* 28 and 42 are small and capital letter heights of the glyph data */
	cairo_scale (cr, 1, 28. / 42);
    }

    /* slant */
    if (props->face_props->slant != CAIRO_FONT_SLANT_NORMAL) {
	cairo_matrix_t shear = { 1, 0, -.2, 1, 0, 0};
	cairo_transform (cr, &shear);
    }

    b = _cairo_twin_outlines +
	_cairo_twin_charmap[unlikely (glyph >= ARRAY_LENGTH (_cairo_twin_charmap)) ? 0 : glyph];
    g = twin_glyph_draw(b);
    w = twin_glyph_right(b);
    gw = F(w);

    marginl = props->marginl;

    /* monospace */
    if (props->face_props->monospace) {
	double monow = F(24);
	double extra =  props->penx + props->marginl + props->marginr;
	cairo_scale (cr, (monow + extra) / (gw + extra), 1);
	gw = monow;

	/* resnap margin for new transform */
	{
	    double x, y, x_scale, x_scale_inv;
	    x = 1; y = 0;
	    compute_hinting_scale (cr, x, y, &x_scale, &x_scale_inv);
	    marginl = SNAPXI (marginl);
	}
    }

    cairo_translate (cr, marginl, 0);

    /* stretch */
    cairo_scale (cr, props->stretch, 1);

    if (props->snap)
	twin_compute_snap (cr, &info, b);
    else
	info.n_snap_x = info.n_snap_y = 0;

    /* advance width */
    metrics->x_advance = gw * props->stretch + props->penx + props->marginl + props->marginr;

    /* glyph shape */
    for (;;) {
	switch (*g++) {
	case 'M':
	    cairo_close_path (cr);
	    /* fall through */
	case 'm':
	    x1 = SNAPX(*g++);
	    y1 = SNAPY(*g++);
	    cairo_move_to (cr, x1, y1);
	    continue;
	case 'L':
	    cairo_close_path (cr);
	    /* fall through */
	case 'l':
	    x1 = SNAPX(*g++);
	    y1 = SNAPY(*g++);
	    cairo_line_to (cr, x1, y1);
	    continue;
	case 'C':
	    cairo_close_path (cr);
	    /* fall through */
	case 'c':
	    x1 = SNAPX(*g++);
	    y1 = SNAPY(*g++);
	    x2 = SNAPX(*g++);
	    y2 = SNAPY(*g++);
	    x3 = SNAPX(*g++);
	    y3 = SNAPY(*g++);
	    cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
	    continue;
	case 'E':
	    cairo_close_path (cr);
	    /* fall through */
	case 'e':
	    cairo_restore (cr); /* restore glyph space */
	    cairo_set_tolerance (cr, 0.01);
	    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
	    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
	    cairo_set_line_width (cr, 1);
	    cairo_scale (cr, props->penx, props->peny);
	    cairo_stroke (cr);
	    break;
	case 'X':
	    /* filler */
	    continue;
	}
	break;
    }

    return CAIRO_STATUS_SUCCESS;
}
コード例 #20
0
void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
{
    if (isEmpty())
        return;

    cairo_t* cr = platformPath()->context();

    double x0, y0;
    cairo_get_current_point(cr, &x0, &y0);
    FloatPoint p0(x0, y0);

    // Draw only a straight line to p1 if any of the points are equal or the radius is zero
    // or the points are collinear (triangle that the points form has area of zero value).
    if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() == p2.y()) || !radius
        || !areaOfTriangleFormedByPoints(p0, p1, p2)) {
        cairo_line_to(cr, p1.x(), p1.y());
        return;
    }

    FloatPoint p1p0((p0.x() - p1.x()),(p0.y() - p1.y()));
    FloatPoint p1p2((p2.x() - p1.x()),(p2.y() - p1.y()));
    float p1p0_length = sqrtf(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y());
    float p1p2_length = sqrtf(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y());

    double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length);
    // all points on a line logic
    if (cos_phi == -1) {
        cairo_line_to(cr, p1.x(), p1.y());
        return;
    }
    if (cos_phi == 1) {
        // add infinite far away point
        unsigned int max_length = 65535;
        double factor_max = max_length / p1p0_length;
        FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * p1p0.y()));
        cairo_line_to(cr, ep.x(), ep.y());
        return;
    }

    float tangent = radius / tan(acos(cos_phi) / 2);
    float factor_p1p0 = tangent / p1p0_length;
    FloatPoint t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 * p1p0.y()));

    FloatPoint orth_p1p0(p1p0.y(), -p1p0.x());
    float orth_p1p0_length = sqrt(orth_p1p0.x() * orth_p1p0.x() + orth_p1p0.y() * orth_p1p0.y());
    float factor_ra = radius / orth_p1p0_length;

    // angle between orth_p1p0 and p1p2 to get the right vector orthographic to p1p0
    double cos_alpha = (orth_p1p0.x() * p1p2.x() + orth_p1p0.y() * p1p2.y()) / (orth_p1p0_length * p1p2_length);
    if (cos_alpha < 0.f)
        orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y());

    FloatPoint p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + factor_ra * orth_p1p0.y()));

    // calculate angles for addArc
    orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y());
    float sa = acos(orth_p1p0.x() / orth_p1p0_length);
    if (orth_p1p0.y() < 0.f)
        sa = 2 * piDouble - sa;

    // anticlockwise logic
    bool anticlockwise = false;

    float factor_p1p2 = tangent / p1p2_length;
    FloatPoint t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 * p1p2.y()));
    FloatPoint orth_p1p2((t_p1p2.x() - p.x()),(t_p1p2.y() - p.y()));
    float orth_p1p2_length = sqrtf(orth_p1p2.x() * orth_p1p2.x() + orth_p1p2.y() * orth_p1p2.y());
    float ea = acos(orth_p1p2.x() / orth_p1p2_length);
    if (orth_p1p2.y() < 0)
        ea = 2 * piDouble - ea;
    if ((sa > ea) && ((sa - ea) < piDouble))
        anticlockwise = true;
    if ((sa < ea) && ((ea - sa) > piDouble))
        anticlockwise = true;

    cairo_line_to(cr, t_p1p0.x(), t_p1p0.y());

    addArc(p, radius, sa, ea, anticlockwise);
}
コード例 #21
0
ファイル: ms2_tlogger.c プロジェクト: BMWPower/MegaTunix
/*!
  \brief renders the new TTM data to the screen
  */
void ms2_update_trigtooth_display()
{
	gint w = 0;
	gint h = 0;
	gint i = 0;
	cairo_t *cr = NULL;
	gfloat tmpf = 0;
	gint space = 0;
	gfloat tmpx = 0.0;
	gfloat ctr = 0.0;
	gfloat cur_pos = 0.0;
	gfloat y_shift = 0.0;
	gushort val = 0;
	gchar * message = NULL;
	cairo_text_extents_t extents;
	extern gconstpointer *global_data;
	Firmware_Details *firmware;
	GtkAllocation allocation;
	GdkWindow *window = gtk_widget_get_window(ttm_data->darea);

	ENTER();
	gtk_widget_get_allocation(ttm_data->darea,&allocation);
	
	firmware = (Firmware_Details *)DATA_GET(global_data,"firmware");

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

	cr = gdk_cairo_create(ttm_data->pixmap);
	cairo_set_source_rgb(cr,1.0,1.0,1.0);
	cairo_paint(cr);

	cairo_set_source_rgb(cr,0.0,0.0,0.0);
	/* get our font */
	cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL);
	cairo_set_font_size(cr,h/30);
	cairo_set_line_width(cr,1);

	/* Get width of largest value and save it */
	message = g_strdup_printf("%i",(GINT)(ttm_data->peak));
	cairo_text_extents (cr, message, &extents);
	tmpx = extents.x_advance;
	y_shift = extents.height;
	ttm_data->font_height=extents.height;
	g_free(message);

	cairo_set_line_width(cr,1);
	/* Draw left side axis scale */
	for (ctr=0.0;ctr < ttm_data->peak;ctr+=ttm_data->vdivisor)
	{
		message = g_strdup_printf("%i",(GINT)ctr);
		/*g_printf("marker \"%s\"\n",message);*/
		cairo_text_extents (cr, message, &extents);
		cur_pos = (h-y_shift)*(1-(ctr/ttm_data->peak))+y_shift;
		cairo_move_to(cr,tmpx-extents.x_advance,cur_pos);
		cairo_show_text(cr,message);
		g_free(message);
	}
	/* Horizontal Axis lines */
	cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 1.0); /* grey */

	for (ctr=0.0;ctr < ttm_data->peak;ctr+=ttm_data->vdivisor)
	{
		cur_pos = (h-y_shift)*(1-(ctr/ttm_data->peak))+(y_shift/2);
		cairo_move_to(cr,extents.x_advance+3,cur_pos);
		cairo_line_to(cr,w,cur_pos);
	}
	ttm_data->usable_begin=extents.x_advance+9;
	/* Left Side vertical axis line */
	cairo_move_to(cr,extents.x_advance+7,0);
	cairo_line_to(cr,extents.x_advance+7,h);
	cairo_stroke(cr);

	cairo_set_source_rgba (cr, 0, 0, 0, 1.0); /* black */
	w = allocation.width-ttm_data->usable_begin;
	h = allocation.height;
	y_shift=ttm_data->font_height;
	tmpf = w/(682.0/ttm_data->zoom) >= 2.0 ? 2.0 : w/(682.0/ttm_data->zoom);
	cairo_set_line_width(cr,tmpf);
	
	/*g_printf("ttm_data->peak is %f line width %f\n",ttm_data->peak,w/186.0);*/
	/* Draw the bars, left to right */
	for (i=0;i<(GINT)(341.0/ttm_data->zoom);i++)
	{
		/*g_printf("moved to %f %i\n",ttm_data->usable_begin+(i*w/341.0),0);*/
		cairo_move_to(cr,ttm_data->usable_begin+(i*w/(341.0/ttm_data->zoom)),h-(y_shift/2));
		val = ttm_data->current[i];
		cur_pos = (h-y_shift)*(1.0-(val/ttm_data->peak))+(y_shift/2);
		cairo_line_to(cr,ttm_data->usable_begin+(i*w/(341.0/ttm_data->zoom)),cur_pos);
	}
	cairo_set_font_size(cr,h/20);
	if (ttm_data->page == firmware->toothmon_page)
		message = g_strdup("Tooth times in microseconds.");
	else if (ttm_data->page == firmware->trigmon_page)
		message = g_strdup("Trigger times in microseconds.");
	else
		message = g_strdup("Composite, not sure yet..");

	cairo_text_extents (cr, message, &extents);
	cairo_move_to(cr,ttm_data->usable_begin+((w)/2)-(extents.width/2),extents.height*1.125);
	space = extents.height*1.25;
	cairo_show_text(cr,message);
	g_free(message);

	cairo_set_font_size(cr,11);
	message = g_strdup_printf(_("Engine RPM:  %.1f"),ttm_data->rpm);
	cairo_text_extents (cr, message, &extents);
	space +=extents.height;
	cairo_move_to(cr,ttm_data->usable_begin+5,space+extents.height/8);
	cairo_show_text(cr,message);
	g_free(message);

	message = g_strdup_printf(_("Sample Time: %i ms."),ttm_data->sample_time);
	cairo_text_extents (cr, message, &extents);
	space +=extents.height;
	cairo_move_to(cr,ttm_data->usable_begin+5,space+extents.height/8);
	cairo_show_text(cr,message);
	g_free(message);

	cairo_stroke(cr);
	cairo_destroy(cr);

	/* Trigger redraw to main screen */
	if (!window) 
	{
		EXIT();
		return;
	}
	gdk_window_clear(window);
	EXIT();
	return;
}
コード例 #22
0
ファイル: gdkdrawing.c プロジェクト: bro1/deadbeef
void
draw_line (drawctx_t *ctx, float x1, float y1, float x2, float y2) {
    cairo_move_to (ctx->drawable, x1, y1);
    cairo_line_to (ctx->drawable, x2, y2);
    cairo_stroke (ctx->drawable);
}
コード例 #23
0
ファイル: ppg-ruler.c プロジェクト: chergert/perfkit
/**
 * ppg_ruler_draw_arrow:
 * @ruler: (in): A #PpgRuler.
 *
 * Draw the arrow to a pixmap for rendering on top of the background.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_draw_arrow (PpgRuler *ruler)
{
	PpgRulerPrivate *priv;
	GtkStyle *style;
	GdkColor base_light;
	GdkColor base_dark;
	GdkColor hl_light;
	cairo_t *cr;
	gint half;
	gint line_width;
	gint center;
	gint middle;
	gdouble top;
	gdouble bottom;
	gdouble left;
	gdouble right;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;
	style = gtk_widget_get_style(GTK_WIDGET(ruler));

	cr = cairo_create(priv->arrow);

	cairo_save(cr);
	cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
	cairo_rectangle(cr, 0, 0, ARROW_SIZE, ARROW_SIZE);
	cairo_fill(cr);
	cairo_restore(cr);

	center = middle = half = ARROW_SIZE / 2;
	line_width = half / 6;

	base_light = style->light[GTK_STATE_SELECTED];
	base_dark = style->dark[GTK_STATE_SELECTED];
	hl_light = style->light[GTK_STATE_SELECTED];

	top = middle - half + line_width + 0.5;
	bottom = middle + half - line_width + 0.5;
	left = center - half + line_width + 0.5;
	right = center +half - line_width - 0.5;

	cairo_set_line_width(cr, line_width);

	cairo_move_to(cr, left + line_width, top + line_width);
	cairo_line_to(cr, right + line_width, top + line_width);
	cairo_line_to(cr, right + line_width, middle + line_width);
	cairo_line_to(cr, center + line_width, bottom + line_width);
	cairo_line_to(cr, left + line_width, middle + line_width);
	cairo_line_to(cr, left + line_width, top + line_width);
	cairo_close_path(cr);
	cairo_set_source_rgba(cr, 0, 0, 0, 0.5);
	cairo_fill(cr);

	cairo_move_to(cr, left, top);
	cairo_line_to(cr, center, top);
	cairo_line_to(cr, center, bottom);
	cairo_line_to(cr, left, middle);
	cairo_line_to(cr, left, top);
	cairo_close_path(cr);
	gdk_cairo_set_source_color(cr, &base_light);
	cairo_fill(cr);

	cairo_move_to(cr, center, top);
	cairo_line_to(cr, right, top);
	cairo_line_to(cr, right, middle);
	cairo_line_to(cr, center, bottom);
	cairo_line_to(cr, center, top);
	cairo_close_path(cr);
	gdk_cairo_set_source_color(cr, &base_light);
	cairo_fill_preserve(cr);
	cairo_set_source_rgba(cr,
	                      base_dark.red / 65535.0,
	                      base_dark.green / 65535.0,
	                      base_dark.blue / 65535.0,
	                      0.5);
	cairo_fill(cr);

	cairo_move_to(cr, left + line_width, top + line_width);
	cairo_line_to(cr, right - line_width, top + line_width);
	cairo_line_to(cr, right - line_width, middle);
	cairo_line_to(cr, center, bottom - line_width - 0.5);
	cairo_line_to(cr, left + line_width, middle);
	cairo_line_to(cr, left + line_width, top + line_width);
	cairo_close_path(cr);
	gdk_cairo_set_source_color(cr, &hl_light);
	cairo_stroke(cr);

	cairo_move_to(cr, left, top);
	cairo_line_to(cr, right, top);
	cairo_line_to(cr, right, middle);
	cairo_line_to(cr, center, bottom);
	cairo_line_to(cr, left, middle);
	cairo_line_to(cr, left, top);
	cairo_close_path(cr);
	gdk_cairo_set_source_color(cr, &base_dark);
	cairo_stroke(cr);

	cairo_destroy(cr);
}
コード例 #24
0
// This is only used to draw borders.
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
    if (paintingDisabled())
        return;

    StrokeStyle style = strokeStyle();
    if (style == NoStroke)
        return;

    cairo_t* cr = m_data->cr;
    cairo_save(cr);

    float width = strokeThickness();
    if (width < 1)
        width = 1;

    FloatPoint p1 = point1;
    FloatPoint p2 = point2;
    bool isVerticalLine = (p1.x() == p2.x());

    adjustLineToPixelBoundaries(p1, p2, width, style);
    cairo_set_line_width(cr, width);

    int patWidth = 0;
    switch (style) {
    case NoStroke:
    case SolidStroke:
        break;
    case DottedStroke:
        patWidth = static_cast<int>(width);
        break;
    case DashedStroke:
        patWidth = 3*static_cast<int>(width);
        break;
    }

    setColor(cr, strokeColor());

    cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);

    if (patWidth) {
        // Do a rect fill of our endpoints.  This ensures we always have the
        // appearance of being a border.  We then draw the actual dotted/dashed line.
        if (isVerticalLine) {
            fillRectSourceOver(cr, FloatRect(p1.x() - width/2, p1.y() - width, width, width), strokeColor());
            fillRectSourceOver(cr, FloatRect(p2.x() - width/2, p2.y(), width, width), strokeColor());
        } else {
            fillRectSourceOver(cr, FloatRect(p1.x() - width, p1.y() - width/2, width, width), strokeColor());
            fillRectSourceOver(cr, FloatRect(p2.x(), p2.y() - width/2, width, width), strokeColor());
        }

        // Example: 80 pixels with a width of 30 pixels.
        // Remainder is 20.  The maximum pixels of line we could paint
        // will be 50 pixels.
        int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*static_cast<int>(width);
        int remainder = distance%patWidth;
        int coverage = distance-remainder;
        int numSegments = coverage/patWidth;

        float patternOffset = 0;
        // Special case 1px dotted borders for speed.
        if (patWidth == 1)
            patternOffset = 1.0;
        else {
            bool evenNumberOfSegments = numSegments%2 == 0;
            if (remainder)
                evenNumberOfSegments = !evenNumberOfSegments;
            if (evenNumberOfSegments) {
                if (remainder) {
                    patternOffset += patWidth - remainder;
                    patternOffset += remainder/2;
                }
                else
                    patternOffset = patWidth/2;
            }
            else if (!evenNumberOfSegments) {
                if (remainder)
                    patternOffset = (patWidth - remainder)/2;
            }
        }

        double dash = patWidth;
        cairo_set_dash(cr, &dash, 1, patternOffset);
    }

    cairo_move_to(cr, p1.x(), p1.y());
    cairo_line_to(cr, p2.x(), p2.y());

    cairo_stroke(cr);
    cairo_restore(cr);
}
コード例 #25
0
ファイル: fo-doc-cairo.c プロジェクト: hrs-allbsd/xmlroff
/**
 * fo_doc_cairo_render_layout_lines:
 * @fo_doc: 
 * @area_layout: 
 * @x: 
 * @y: 
 * 
 * 
 **/
void
fo_doc_cairo_render_layout_lines (FoDoc   *fo_doc,
				  FoArea  *area_layout,
				  gdouble   x,
				  gdouble   y)
{
  g_return_if_fail (FO_IS_DOC_CAIRO (fo_doc));
  g_return_if_fail (FO_DOC_CAIRO (fo_doc)->cr != NULL);
  g_return_if_fail (FO_IS_AREA_LAYOUT (area_layout));

  /* Since Cairo doesn't support rendering only some lines from
   * a layout, firstly move the current point so the first line to be
   * rendered is positioned at (x, y) and, secondly, save the current
   * graphics state and then crop to only the area covered by the
   * lines that are to be rendered.
   */

  gdouble y1 = y;

  gint line_first = fo_area_layout_get_line_first (area_layout);
  if (line_first > 0)
    {
      y1 =
	y + fo_area_layout_get_line_height (area_layout,
					    line_first - 1);
    }

  gint line_last = fo_area_layout_get_line_last (area_layout);
#if ENABLE_CLIP
  gdouble y2 =
      y1 - fo_area_layout_get_line_height (area_layout,
					   line_last);

  gdouble x2 =
      x + fo_area_area_get_width (area_layout);

  cairo_save (FO_DOC_CAIRO (fo_doc)->cr);

  cairo_move_to (FO_DOC_CAIRO (fo_doc)->cr,
		 x, FO_DOC_CAIRO (fo_doc)->page_height - y);
  cairo_line_to (FO_DOC_CAIRO (fo_doc)->cr,
		 x2, FO_DOC_CAIRO (fo_doc)->page_height - y);
  cairo_line_to (FO_DOC_CAIRO (fo_doc)->cr,
		 x2, FO_DOC_CAIRO (fo_doc)->page_height - y2);
  cairo_line_to (FO_DOC_CAIRO(fo_doc)->cr,
		 x, FO_DOC_CAIRO (fo_doc)->page_height - y2);

  cairo_clip (FO_DOC_CAIRO (fo_doc)->cr);
#endif

  cairo_move_to (FO_DOC_CAIRO (fo_doc)->cr,
		 x,
		 FO_DOC_CAIRO (fo_doc)->page_height - y1);
  pango_cairo_show_layout (FO_DOC_CAIRO (fo_doc)->cr,
			   fo_layout_get_pango_layout (fo_area_layout_get_layout (area_layout)));

  fo_doc_cairo_do_callbacks (FO_DOC_CAIRO (fo_doc)->cr,
			     fo_layout_get_pango_layout (fo_area_layout_get_layout (area_layout)),
			     line_first,
			     line_last,
			     x * PANGO_SCALE,
			     y * PANGO_SCALE);

#if ENABLE_CLIP
  cairo_restore (FO_DOC_CAIRO(fo_doc)->cr);
#endif
}
コード例 #26
0
ファイル: gfxContext.cpp プロジェクト: typ4rk/mozilla-history
void
gfxContext::LineTo(const gfxPoint& pt)
{
    cairo_line_to(mCairo, pt.x, pt.y);
}
コード例 #27
0
ファイル: gen_image.c プロジェクト: x42/fil4.lv2
static void bw_knob (cairo_t* cr)
{
	const double GED_CY = 33.5;
	float xlp, ylp;
	CairoSetSouerceRGBA(c_dlf);
	cairo_set_line_width(cr, 1.25);
	cairo_move_to (cr,  1 + BWX, GZLINE);
	cairo_line_to (cr,  8 + BWX, GZLINE);
	cairo_line_to (cr, 10 + BWX, GZLINE - 4);
	cairo_line_to (cr, 12 + BWX, GZLINE);
	cairo_line_to (cr, 19 + BWX, GZLINE);
	cairo_move_to (cr, 12 + BWX, GZLINE);
	cairo_line_to (cr, 10 + BWX, GZLINE + 4);
	cairo_line_to (cr,  8 + BWX, GZLINE);
	cairo_stroke (cr);

	cairo_move_to (cr, GED_WIDTH - BWX -  1, GZLINE);
	cairo_line_to (cr, GED_WIDTH - BWX -  4, GZLINE);
	cairo_line_to (cr, GED_WIDTH - BWX - 10, GZLINE - 4);
	cairo_line_to (cr, GED_WIDTH - BWX - 16, GZLINE);
	cairo_line_to (cr, GED_WIDTH - BWX - 19, GZLINE);
	cairo_move_to (cr, GED_WIDTH - BWX - 16, GZLINE);
	cairo_line_to (cr, GED_WIDTH - BWX - 10, GZLINE + 4);
	cairo_line_to (cr, GED_WIDTH - BWX -  4, GZLINE);
	cairo_stroke (cr);

	{ DIALDOTS(bw_to_dial (powf(2.f,  4 / 2.f)), .0, .5) }
	{ DIALDOTS(bw_to_dial (powf(2.f,  2 / 2.f)), .0, .5) }
	{ DIALDOTS(bw_to_dial (powf(2.f,  0 / 2.f)), .0, .5) }
	{ DIALDOTS(bw_to_dial (powf(2.f, -2 / 2.f)), .0, .5) }
	{ DIALDOTS(bw_to_dial (powf(2.f, -4 / 2.f)), .0, .5) }
	{ DIALDOTS(bw_to_dial (powf(2.f, -6 / 2.f)), .0, .5) }
	{ DIALDOTS(bw_to_dial (powf(2.f, -8 / 2.f)), .0, .5) }
}
コード例 #28
0
ファイル: gfxContext.cpp プロジェクト: typ4rk/mozilla-history
void
gfxContext::RoundedRectangle(const gfxRect& rect,
                             const gfxCornerSizes& corners,
                             bool draw_clockwise)
{
    //
    // For CW drawing, this looks like:
    //
    //  ...******0**      1    C
    //              ****
    //                  ***    2
    //                     **
    //                       *
    //                        *
    //                         3
    //                         *
    //                         *
    //
    // Where 0, 1, 2, 3 are the control points of the Bezier curve for
    // the corner, and C is the actual corner point.
    //
    // At the start of the loop, the current point is assumed to be
    // the point adjacent to the top left corner on the top
    // horizontal.  Note that corner indices start at the top left and
    // continue clockwise, whereas in our loop i = 0 refers to the top
    // right corner.
    //
    // When going CCW, the control points are swapped, and the first
    // corner that's drawn is the top left (along with the top segment).
    //
    // There is considerable latitude in how one chooses the four
    // control points for a Bezier curve approximation to an ellipse.
    // For the overall path to be continuous and show no corner at the
    // endpoints of the arc, points 0 and 3 must be at the ends of the
    // straight segments of the rectangle; points 0, 1, and C must be
    // collinear; and points 3, 2, and C must also be collinear.  This
    // leaves only two free parameters: the ratio of the line segments
    // 01 and 0C, and the ratio of the line segments 32 and 3C.  See
    // the following papers for extensive discussion of how to choose
    // these ratios:
    //
    //   Dokken, Tor, et al. "Good approximation of circles by
    //      curvature-continuous Bezier curves."  Computer-Aided
    //      Geometric Design 7(1990) 33--41.
    //   Goldapp, Michael. "Approximation of circular arcs by cubic
    //      polynomials." Computer-Aided Geometric Design 8(1991) 227--238.
    //   Maisonobe, Luc. "Drawing an elliptical arc using polylines,
    //      quadratic, or cubic Bezier curves."
    //      http://www.spaceroots.org/documents/ellipse/elliptical-arc.pdf
    //
    // We follow the approach in section 2 of Goldapp (least-error,
    // Hermite-type approximation) and make both ratios equal to
    //
    //          2   2 + n - sqrt(2n + 28)
    //  alpha = - * ---------------------
    //          3           n - 4
    //
    // where n = 3( cbrt(sqrt(2)+1) - cbrt(sqrt(2)-1) ).
    //
    // This is the result of Goldapp's equation (10b) when the angle
    // swept out by the arc is pi/2, and the parameter "a-bar" is the
    // expression given immediately below equation (21).
    //
    // Using this value, the maximum radial error for a circle, as a
    // fraction of the radius, is on the order of 0.2 x 10^-3.
    // Neither Dokken nor Goldapp discusses error for a general
    // ellipse; Maisonobe does, but his choice of control points
    // follows different constraints, and Goldapp's expression for
    // 'alpha' gives much smaller radial error, even for very flat
    // ellipses, than Maisonobe's equivalent.
    //
    // For the various corners and for each axis, the sign of this
    // constant changes, or it might be 0 -- it's multiplied by the
    // appropriate multiplier from the list before using.
    const gfxFloat alpha = 0.55191497064665766025;

    typedef struct { gfxFloat a, b; } twoFloats;

    twoFloats cwCornerMults[4] = { { -1,  0 },
                                   {  0, -1 },
                                   { +1,  0 },
                                   {  0, +1 } };
    twoFloats ccwCornerMults[4] = { { +1,  0 },
                                    {  0, -1 },
                                    { -1,  0 },
                                    {  0, +1 } };

    twoFloats *cornerMults = draw_clockwise ? cwCornerMults : ccwCornerMults;

    gfxPoint pc, p0, p1, p2, p3;

    if (draw_clockwise)
        cairo_move_to(mCairo, rect.X() + corners[NS_CORNER_TOP_LEFT].width, rect.Y());
    else
        cairo_move_to(mCairo, rect.X() + rect.Width() - corners[NS_CORNER_TOP_RIGHT].width, rect.Y());

    NS_FOR_CSS_CORNERS(i) {
        // the corner index -- either 1 2 3 0 (cw) or 0 3 2 1 (ccw)
        mozilla::css::Corner c = mozilla::css::Corner(draw_clockwise ? ((i+1) % 4) : ((4-i) % 4));

        // i+2 and i+3 respectively.  These are used to index into the corner
        // multiplier table, and were deduced by calculating out the long form
        // of each corner and finding a pattern in the signs and values.
        int i2 = (i+2) % 4;
        int i3 = (i+3) % 4;

        pc = rect.AtCorner(c);

        if (corners[c].width > 0.0 && corners[c].height > 0.0) {
            p0.x = pc.x + cornerMults[i].a * corners[c].width;
            p0.y = pc.y + cornerMults[i].b * corners[c].height;

            p3.x = pc.x + cornerMults[i3].a * corners[c].width;
            p3.y = pc.y + cornerMults[i3].b * corners[c].height;

            p1.x = p0.x + alpha * cornerMults[i2].a * corners[c].width;
            p1.y = p0.y + alpha * cornerMults[i2].b * corners[c].height;

            p2.x = p3.x - alpha * cornerMults[i3].a * corners[c].width;
            p2.y = p3.y - alpha * cornerMults[i3].b * corners[c].height;

            cairo_line_to (mCairo, p0.x, p0.y);
            cairo_curve_to (mCairo,
                            p1.x, p1.y,
                            p2.x, p2.y,
                            p3.x, p3.y);
        } else {
            cairo_line_to (mCairo, pc.x, pc.y);
        }
    }

    cairo_close_path (mCairo);
}
コード例 #29
0
void dtgtk_cairo_paint_alignment(cairo_t *cr,gint x,gint y,gint w,gint h,gint flags)
{
  gint s=w<h?w:h;
  cairo_translate(cr, x+(w/2.0)-(s/2.0), y+(h/2.0)-(s/2.0));
  cairo_scale(cr,s,s);

  cairo_set_line_width(cr,0.3);
  cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND);
  switch (flags>>12)
  {
    case 1:     // Top left
      cairo_move_to(cr,0.9,0.1);
      cairo_line_to(cr,0.1,0.1);
      cairo_line_to(cr,0.1,0.9);
      break;

    case 2:     // Top center
      cairo_move_to(cr,0.1,0.1);
      cairo_line_to(cr,0.9,0.1);
      break;

    case 4:     // Top right
      cairo_move_to(cr,0.1,0.1);
      cairo_line_to(cr,0.9,0.1);
      cairo_line_to(cr,0.9,0.9);
      break;

    case 8:     // left
      cairo_move_to(cr,0.1,0.1);
      cairo_line_to(cr,0.1,0.9);
      break;
    case 16:     // center
      cairo_move_to(cr,0.1,0.5);
      cairo_line_to(cr,0.9,0.5);
      cairo_move_to(cr,0.5,0.1);
      cairo_line_to(cr,0.5,0.9);
      break;
    case 32:     // right
      cairo_move_to(cr,0.9,0.1);
      cairo_line_to(cr,0.9,0.9);
      break;

    case 64:     // bottom left
      cairo_move_to(cr,0.9,0.9);
      cairo_line_to(cr,0.1,0.9);
      cairo_line_to(cr,0.1,0.1);
      break;

    case 128:     // bottom center
      cairo_move_to(cr,0.1,0.9);
      cairo_line_to(cr,0.9,0.9);
      break;

    case 256:     // bottom right
      cairo_move_to(cr,0.1,0.9);
      cairo_line_to(cr,0.9,0.9);
      cairo_line_to(cr,0.9,0.1);
      break;

  }
  cairo_stroke(cr);
}
コード例 #30
0
void draw_background(LoadGraph *g) {
	double dash[2] = { 1.0, 2.0 };
	cairo_t *cr;
	guint i;
	unsigned num_bars;
	char *caption;
	cairo_text_extents_t extents;

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

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

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

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

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

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

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

	cairo_set_dash (cr, dash, 2, 1.5);

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

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

	cairo_stroke (cr);
	cairo_destroy (cr);
}