/** * 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; } } }
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; }
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); } }
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); }
/** * 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); }
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; }
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 }
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; }
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); }
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); } } }
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; }
//----------------------------------------------------------------------------------- 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); } }
//----------------------------------------------------------------------------------- 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(); }
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); }
/* 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); }
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]); } }
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); } }
void Path::addLineTo(const FloatPoint& p) { cairo_t* cr = platformPath()->context(); cairo_line_to(cr, p.x(), p.y()); }
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; }
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); }
/*! \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; }
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); }
/** * 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); }
// 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); }
/** * 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 }
void gfxContext::LineTo(const gfxPoint& pt) { cairo_line_to(mCairo, pt.x, pt.y); }
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) } }
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); }
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); }
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); }