void draw_set_fg_color (drawctx_t *ctx, float *rgb) { cairo_set_source_rgb (ctx->drawable, rgb[0], rgb[1], rgb[2]); }
void set_color_arc(cairo_t *cr){ cairo_set_source_rgb(cr, 0.2, 0.5, 0.4); }
static void draw (cairo_t *cr, int width, int height) { cairo_surface_t *overlay, *punch, *circles; cairo_t *overlay_cr, *punch_cr, *circles_cr; /* Fill the background */ double radius = 0.5 * (width < height ? width : height) - 10; double xc = width / 2.; double yc = height / 2.; overlay = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, width, height); if (overlay == NULL) return; punch = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_ALPHA, width, height); if (punch == NULL) return; circles = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, width, height); if (circles == NULL) return; fill_checks (cr, 0, 0, width, height); /* Draw a black circle on the overlay */ overlay_cr = cairo_create (overlay); cairo_set_source_rgb (overlay_cr, 0., 0., 0.); oval_path (overlay_cr, xc, yc, radius, radius); cairo_fill (overlay_cr); /* Draw 3 circles to the punch surface, then cut * that out of the main circle in the overlay */ punch_cr = cairo_create (punch); draw_3circles (punch_cr, xc, yc, radius, 1.0); cairo_destroy (punch_cr); cairo_set_operator (overlay_cr, CAIRO_OPERATOR_DEST_OUT); cairo_set_source_surface (overlay_cr, punch, 0, 0); cairo_paint (overlay_cr); /* Now draw the 3 circles in a subgroup again * at half intensity, and use OperatorAdd to join up * without seams. */ circles_cr = cairo_create (circles); cairo_set_operator (circles_cr, CAIRO_OPERATOR_OVER); draw_3circles (circles_cr, xc, yc, radius, 0.5); cairo_destroy (circles_cr); cairo_set_operator (overlay_cr, CAIRO_OPERATOR_ADD); cairo_set_source_surface (overlay_cr, circles, 0, 0); cairo_paint (overlay_cr); cairo_destroy (overlay_cr); cairo_set_source_surface (cr, overlay, 0, 0); cairo_paint (cr); cairo_surface_destroy (overlay); cairo_surface_destroy (punch); cairo_surface_destroy (circles); }
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); }
/* TODO: Split each ppi case out to its own CAIRO_TEST() test case */ static cairo_test_status_t preamble (cairo_test_context_t *ctx) { cairo_t *cr; cairo_test_status_t ret = CAIRO_TEST_UNTESTED; struct { double x, y; } ppi[] = { { 576, 576 }, { 576, 72 }, { 288, 288 }, { 288, 72 }, { 144, 144 }, { 144, 72 }, { 72, 576 }, { 72, 288 }, { 72, 144 }, { 72, 72 }, }; unsigned int i; int n, num_ppi; const char *path = _cairo_test_mkdir (CAIRO_TEST_OUTPUT_DIR) ? CAIRO_TEST_OUTPUT_DIR : "."; num_ppi = ARRAY_LENGTH (ppi); #if GENERATE_REFERENCE for (n = 0; n < num_ppi; n++) { char *ref_name; xasprintf (&ref_name, "reference/fallback-resolution.ppi%gx%g.ref.png", ppi[n].x, ppi[n].y); generate_reference (ppi[n].x, ppi[n].y, ref_name); free (ref_name); } #endif for (i = 0; i < ctx->num_targets; i++) { const cairo_boilerplate_target_t *target = ctx->targets_to_test[i]; cairo_surface_t *surface = NULL; char *base_name; void *closure; const char *format; cairo_status_t status; if (! target->is_vector) continue; if (! cairo_test_is_target_enabled (ctx, target->name)) continue; format = cairo_boilerplate_content_name (target->content); xasprintf (&base_name, "%s/fallback-resolution.%s.%s", path, target->name, format); surface = (target->create_surface) (base_name, target->content, SIZE, SIZE, SIZE, SIZE, CAIRO_BOILERPLATE_MODE_TEST, &closure); if (surface == NULL) { free (base_name); continue; } if (ret == CAIRO_TEST_UNTESTED) ret = CAIRO_TEST_SUCCESS; cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); free (base_name); /* we need to recreate the surface for each resolution as we include * SVG in testing which does not support the paginated interface. */ for (n = 0; n < num_ppi; n++) { char *test_name; cairo_bool_t pass; xasprintf (&test_name, "fallback-resolution.ppi%gx%g", ppi[n].x, ppi[n].y); xasprintf (&base_name, "%s/%s.%s.%s", path, test_name, target->name, format); surface = (target->create_surface) (base_name, target->content, SIZE + 25, SIZE + 25, SIZE + 25, SIZE + 25, CAIRO_BOILERPLATE_MODE_TEST, &closure); if (surface == NULL || cairo_surface_status (surface)) { cairo_test_log (ctx, "Failed to generate surface: %s.%s\n", target->name, format); free (base_name); free (test_name); ret = CAIRO_TEST_FAILURE; continue; } cairo_test_log (ctx, "Testing fallback-resolution %gx%g with %s target\n", ppi[n].x, ppi[n].y, target->name); printf ("%s:\t", base_name); fflush (stdout); if (target->force_fallbacks != NULL) target->force_fallbacks (surface, ppi[n].x, ppi[n].y); cr = cairo_create (surface); #if SET_TOLERANCE cairo_set_tolerance (cr, 3.0); #endif cairo_surface_set_device_offset (surface, 25, 25); cairo_save (cr); { cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); } cairo_restore (cr); /* First draw the top half in a conventional way. */ cairo_save (cr); { cairo_rectangle (cr, 0, 0, SIZE, SIZE / 2.0); cairo_clip (cr); draw (cr, SIZE, SIZE); } cairo_restore (cr); /* Then draw the bottom half in a separate group, * (exposing a bug in 1.6.4 with the group not being * rendered with the correct fallback resolution). */ cairo_save (cr); { cairo_rectangle (cr, 0, SIZE / 2.0, SIZE, SIZE / 2.0); cairo_clip (cr); cairo_push_group (cr); { draw (cr, SIZE, SIZE); } cairo_pop_group_to_source (cr); cairo_paint (cr); } cairo_restore (cr); status = cairo_status (cr); cairo_destroy (cr); pass = FALSE; if (status) { cairo_test_log (ctx, "Error: Failed to create target surface: %s\n", cairo_status_to_string (status)); ret = CAIRO_TEST_FAILURE; } else { /* extract the image and compare it to our reference */ if (! check_result (ctx, target, test_name, base_name, surface)) ret = CAIRO_TEST_FAILURE; else pass = TRUE; } cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); free (base_name); free (test_name); if (pass) { printf ("PASS\n"); } else { printf ("FAIL\n"); } fflush (stdout); } } return ret; }
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; }
static void set_color(cairo_t *cr, GdkColor color) { cairo_set_source_rgb(cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0); }
void status_render(struct status *status, cairo_t *cairo) { cairo_font_extents_t exfont; cairo_text_extents_t extext; color_t color; double size; int width, height; const char *font; char *text; font = settings_get_string("status.font"); size = settings_get_double("status.font.size"); cairo_reset_clip(cairo); cairo_identity_matrix(cairo); cairo_select_font_face(cairo, font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cairo, size); cairo_font_extents(cairo, &exfont); width = cairo_image_surface_get_width(cairo_get_target(cairo)); height = cairo_image_surface_get_height(cairo_get_target(cairo)); if (!settings_get_bool("status.transparent")) { color = settings_get_color("status.color"); cairo_set_source_rgb(cairo, color.r, color.g, color.b); cairo_rectangle(cairo, 0, height - exfont.height - 10, width, exfont.height + 10); cairo_fill(cairo); } color = settings_get_color("status.text.color"); cairo_set_source_rgb(cairo, color.r, color.g, color.b); cairo_text_extents(cairo, status->info, &extext); cairo_move_to(cairo, width - extext.x_advance - 5, height - exfont.descent - 5); cairo_show_text(cairo, status->info); cairo_rectangle(cairo, 0, height - exfont.height - 10, width - extext.x_advance - 10, exfont.height + 10); cairo_clip(cairo); if (status->is_error) { color = settings_get_color("status.error.color"); cairo_set_source_rgb(cairo, color.r, color.g, color.b); } cairo_move_to(cairo, 5, height - exfont.descent - 5); cairo_show_text(cairo, status->text); if (status->cursor_pos > -1) { text = xstrndup(status->text, (size_t)status->cursor_pos); cairo_text_extents(cairo, text, &extext); cairo_move_to(cairo, extext.x_advance + 5, height - exfont.descent - 5); cairo_show_text(cairo, "_"); free(text); } }
/* * Draws global image with fill color onto a pixmap with the given * resolution and returns it. * */ xcb_pixmap_t draw_image(uint32_t *resolution) { xcb_pixmap_t bg_pixmap = XCB_NONE; int button_diameter_physical = ceil(scaling_factor() * BUTTON_DIAMETER); DEBUG("scaling_factor is %.f, physical diameter is %d px\n", scaling_factor(), button_diameter_physical); if (!vistype) vistype = get_root_visual_type(screen); bg_pixmap = create_bg_pixmap(conn, screen, resolution, color); /* Initialize cairo: Create one in-memory surface to render the unlock * indicator on, create one XCB surface to actually draw (one or more, * depending on the amount of screens) unlock indicators on. */ cairo_surface_t *output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, button_diameter_physical, button_diameter_physical); cairo_t *ctx = cairo_create(output); cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]); cairo_t *xcb_ctx = cairo_create(xcb_output); if (img) { if (!tile) { cairo_set_source_surface(xcb_ctx, img, 0, 0); cairo_paint(xcb_ctx); } else { /* create a pattern and fill a rectangle as big as the screen */ cairo_pattern_t *pattern; pattern = cairo_pattern_create_for_surface(img); cairo_set_source(xcb_ctx, pattern); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); cairo_pattern_destroy(pattern); } } else { char strgroups[3][3] = {{color[0], color[1], '\0'}, {color[2], color[3], '\0'}, {color[4], color[5], '\0'}}; uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)), (strtol(strgroups[1], NULL, 16)), (strtol(strgroups[2], NULL, 16))}; cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); } if (unlock_state >= STATE_KEY_PRESSED && unlock_indicator) { cairo_scale(ctx, scaling_factor(), scaling_factor()); /* Draw a (centered) circle with transparent background. */ cairo_set_line_width(ctx, 10.0); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, 0 /* start */, 2 * M_PI /* end */); /* Use the appropriate color for the different PAM states */ /* (currently verifying, wrong password, or default) */ switch (pam_state) { case STATE_PAM_VERIFY: cairo_set_source_rgba(ctx, 0.5, 0.5, 0.5, 0.25); break; case STATE_PAM_WRONG: cairo_set_source_rgba(ctx, 1, 0.5, 0, 0.25); break; default: cairo_set_source_rgba(ctx, 0.25, 0.25, 1, 0.25); break; } cairo_fill_preserve(ctx); switch (pam_state) { case STATE_PAM_VERIFY: cairo_set_source_rgba(ctx, 0.5, 0.5, 0.5, 0.50); break; case STATE_PAM_WRONG: cairo_set_source_rgba(ctx, 1, 0.5, 0, 0.50); break; case STATE_PAM_IDLE: cairo_set_source_rgba(ctx, 0.25, 0.25, 1, 0.50); break; } cairo_stroke(ctx); cairo_set_line_width(ctx, 10.0); /* Display a (centered) text of the current PAM state. */ char *text = NULL; /* We don't want to show more than a 3-digit number. */ char buf[4]; cairo_set_source_rgb(ctx, 0, 0, 0); cairo_set_font_size(ctx, 28.0); if (show_failed_attempts && failed_attempts > 0) { if (failed_attempts > 999) { text = "> 999"; } else { snprintf(buf, sizeof(buf), "%d", failed_attempts); text = buf; } cairo_set_source_rgb(ctx, 1, 0, 0); cairo_set_font_size(ctx, 32.0); } if (text) { cairo_text_extents_t extents; double x, y; cairo_text_extents(ctx, text, &extents); x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing); y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing); cairo_move_to(ctx, x, y); cairo_show_text(ctx, text); cairo_close_path(ctx); } if (pam_state == STATE_PAM_WRONG && (modifier_string != NULL)) { cairo_text_extents_t extents; double x, y; cairo_set_font_size(ctx, 14.0); cairo_text_extents(ctx, modifier_string, &extents); x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing); y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing) + 1.0; cairo_move_to(ctx, x, y); cairo_show_text(ctx, modifier_string); cairo_close_path(ctx); } /* After the user pressed any valid key or the backspace key, we * highlight a random part of the unlock indicator to confirm this * keypress. */ if (unlock_state == STATE_KEY_ACTIVE || unlock_state == STATE_BACKSPACE_ACTIVE) { cairo_new_sub_path(ctx); double highlight_start = (rand() % (int)(2 * M_PI * 100)) / 100.0; cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start, highlight_start + (M_PI / 3.0)); if (unlock_state == STATE_KEY_ACTIVE) { /* For normal keys, we use a lighter blue. */ cairo_set_source_rgba(ctx, 0.25, 0.25, 1, 0.5); } else { /* For backspace, we use orange. */ cairo_set_source_rgba(ctx, 1, 0.5, 0, 0.5); } cairo_stroke(ctx); } } if (xr_screens > 0) { /* Composite the unlock indicator in the middle of each screen. */ for (int screen = 0; screen < xr_screens; screen++) { int x = (xr_resolutions[screen].x + ((xr_resolutions[screen].width / 2) - (button_diameter_physical / 2))); int y = (xr_resolutions[screen].y + ((xr_resolutions[screen].height / 2) - (button_diameter_physical / 2))); cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); } } else { /* We have no information about the screen sizes/positions, so we just * place the unlock indicator in the middle of the X root window and * hope for the best. */ int x = (last_resolution[0] / 2) - (button_diameter_physical / 2); int y = (last_resolution[1] / 2) - (button_diameter_physical / 2); cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); } cairo_surface_destroy(xcb_output); cairo_surface_destroy(output); cairo_destroy(ctx); cairo_destroy(xcb_ctx); return bg_pixmap; }
static void update_surface (FishApplet *fish) { GtkWidget *widget = fish->drawing_area; GtkRequisition prev_requisition; GtkAllocation allocation; int width = -1; int height = -1; int pixbuf_width = -1; int pixbuf_height = -1; gboolean rotate = FALSE; cairo_t *cr; cairo_matrix_t matrix; cairo_pattern_t *pattern; gtk_widget_get_allocation (widget, &allocation); if (!gtk_widget_get_realized (widget) || allocation.width <= 0 || allocation.height <= 0) return; if (!fish->pixbuf && !load_fish_image (fish)) return; if (fish->rotate && (fish->orientation == PANEL_APPLET_ORIENT_LEFT || fish->orientation == PANEL_APPLET_ORIENT_RIGHT)) rotate = TRUE; pixbuf_width = gdk_pixbuf_get_width (fish->pixbuf); pixbuf_height = gdk_pixbuf_get_height (fish->pixbuf); prev_requisition = fish->requisition; if (fish->orientation == PANEL_APPLET_ORIENT_UP || fish->orientation == PANEL_APPLET_ORIENT_DOWN) { height = allocation.height; width = pixbuf_width * ((gdouble) height / pixbuf_height); fish->requisition.width = width / fish->n_frames; fish->requisition.height = height; } else { if (!rotate) { width = allocation.width * fish->n_frames; height = pixbuf_height * ((gdouble) width / pixbuf_width); fish->requisition.width = allocation.width; fish->requisition.height = height; } else { width = allocation.width; height = pixbuf_width * ((gdouble) width / pixbuf_height); fish->requisition.width = width; fish->requisition.height = height / fish->n_frames; } } if (prev_requisition.width != fish->requisition.width || prev_requisition.height != fish->requisition.height) { gtk_widget_set_size_request (widget, fish->requisition.width, fish->requisition.height); } g_assert (width != -1 && height != -1); if (width == 0 || height == 0) return; if (fish->surface) cairo_surface_destroy (fish->surface); fish->surface = gdk_window_create_similar_surface ( gtk_widget_get_window (widget), CAIRO_CONTENT_COLOR_ALPHA, width, height); gtk_widget_queue_resize (widget); g_assert (pixbuf_width != -1 && pixbuf_height != -1); cr = cairo_create (fish->surface); cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); gdk_cairo_set_source_pixbuf (cr, fish->pixbuf, 0, 0); pattern = cairo_get_source (cr); cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST); cairo_matrix_init_identity (&matrix); if (fish->april_fools) { cairo_matrix_translate (&matrix, pixbuf_width - 1, pixbuf_height - 1); cairo_matrix_rotate (&matrix, M_PI); } if (rotate) { if (fish->orientation == PANEL_APPLET_ORIENT_RIGHT) { cairo_matrix_translate (&matrix, pixbuf_width - 1, 0); cairo_matrix_rotate (&matrix, M_PI * 0.5); } else { cairo_matrix_translate (&matrix, 0, pixbuf_height - 1); cairo_matrix_rotate (&matrix, M_PI * 1.5); } cairo_matrix_scale (&matrix, (double) (pixbuf_height - 1) / width, (double) (pixbuf_width - 1) / height); } else { cairo_matrix_scale (&matrix, (double) (pixbuf_width - 1) / width, (double) (pixbuf_height - 1) / height); } cairo_pattern_set_matrix (pattern, &matrix); cairo_rectangle (cr, 0, 0, width, height); cairo_fill (cr); if (fish->april_fools) { cairo_set_source_rgb (cr, 1, 0.5, 0); cairo_paint_with_alpha (cr, 0.25); } cairo_destroy (cr); }
GdkCursor* Cursor::getPenCursor() { XOJ_CHECK_TYPE(Cursor); ToolHandler* handler = control->getToolHandler(); bool big = control->getSettings()->isShowBigCursor(); int height = 3; int width = 3; if (big) { height = 22; width = 15; } cairo_surface_t* crCursor = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t* cr = cairo_create(crCursor); Util::cairo_set_source_rgbi(cr, handler->getColor()); if (big) { cairo_set_source_rgb(cr, 1, 1, 1); cairo_set_line_width(cr, 1.2); cairo_move_to(cr, 1.5, 1.5); cairo_line_to(cr, 2, 19); cairo_line_to(cr, 5.5, 15.5); cairo_line_to(cr, 8.5, 20.5); cairo_line_to(cr, 10.5, 19); cairo_line_to(cr, 8.5, 14); cairo_line_to(cr, 13, 14); cairo_close_path(cr); cairo_fill_preserve(cr); cairo_set_source_rgb(cr, 0, 0, 0); cairo_stroke(cr); Util::cairo_set_source_rgbi(cr, handler->getColor()); cairo_rectangle(cr, 0, 0, 3, 3); cairo_fill(cr); } else { cairo_rectangle(cr, 0, 0, 3, 3); cairo_fill(cr); } cairo_destroy(cr); GdkPixbuf* pixbuf = xoj_pixbuf_get_from_surface(crCursor, 0, 0, width, height); // cairo_surface_write_to_png(crCursor, "/home/andreas/xoj-cursor-orig.png"); // gdk_pixbuf_save(pixbuf, "/home/andreas/xoj-cursor.png", "png", NULL, NULL); cairo_surface_destroy(crCursor); GdkCursor* cursor = gdk_cursor_new_from_pixbuf(gtk_widget_get_display( control->getWindow()->getXournal()->getWidget()), pixbuf, 1, 1); gdk_pixbuf_unref(pixbuf); return cursor; }
void expose(dt_view_t *self, cairo_t *cri, int32_t width_i, int32_t height_i, int32_t pointerx, int32_t pointery) { // startup-time conf parameter: const int32_t capwd = darktable.thumbnail_width; const int32_t capht = darktable.thumbnail_height; // if width or height > max pipeline pixels: center the view and clamp. int32_t width = MIN(width_i, capwd); int32_t height = MIN(height_i, capht); cairo_set_source_rgb (cri, .2, .2, .2); cairo_save(cri); cairo_set_fill_rule(cri, CAIRO_FILL_RULE_EVEN_ODD); cairo_rectangle(cri, 0, 0, width_i, height_i); cairo_rectangle(cri, MAX(1.0, width_i -capwd) *.5f, MAX(1.0, height_i-capht) *.5f, MIN(width, width_i-1), MIN(height, height_i-1)); cairo_fill (cri); cairo_restore(cri); if(width_i > capwd) cairo_translate(cri, -(capwd-width_i) *.5f, 0.0f); if(height_i > capht) cairo_translate(cri, 0.0f, -(capht-height_i)*.5f); cairo_save(cri); dt_develop_t *dev = (dt_develop_t *)self->data; if(dev->gui_synch && !dev->image_loading) { // synch module guis from gtk thread: darktable.gui->reset = 1; GList *modules = dev->iop; while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); dt_iop_gui_update(module); modules = g_list_next(modules); } darktable.gui->reset = 0; dev->gui_synch = 0; } if(dev->image_dirty || dev->pipe->input_timestamp < dev->preview_pipe->input_timestamp) dt_dev_process_image(dev); if(dev->preview_dirty || dev->pipe->input_timestamp > dev->preview_pipe->input_timestamp) dt_dev_process_preview(dev); dt_pthread_mutex_t *mutex = NULL; int wd, ht, stride, closeup; int32_t zoom; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); static cairo_surface_t *image_surface = NULL; static int image_surface_width = 0, image_surface_height = 0, image_surface_imgid = -1; if(image_surface_width != width || image_surface_height != height || image_surface == NULL) { // create double-buffered image to draw on, to make modules draw more fluently. image_surface_width = width; image_surface_height = height; if(image_surface) cairo_surface_destroy(image_surface); image_surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height); image_surface_imgid = -1; // invalidate old stuff } cairo_surface_t *surface; cairo_t *cr = cairo_create(image_surface); // adjust scroll bars { float zx = zoom_x, zy = zoom_y, boxw = 1., boxh = 1.; dt_dev_check_zoom_bounds(dev, &zx, &zy, zoom, closeup, &boxw, &boxh); dt_view_set_scrollbar(self, zx+.5-boxw*.5, 1.0, boxw, zy+.5-boxh*.5, 1.0, boxh); } if(!dev->image_dirty && dev->pipe->input_timestamp >= dev->preview_pipe->input_timestamp) { // draw image mutex = &dev->pipe->backbuf_mutex; dt_pthread_mutex_lock(mutex); wd = dev->pipe->backbuf_width; ht = dev->pipe->backbuf_height; stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, wd); surface = cairo_image_surface_create_for_data (dev->pipe->backbuf, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); cairo_translate(cr, .5f*(width-wd), .5f*(height-ht)); if(closeup) { const float closeup_scale = 2.0; cairo_scale(cr, closeup_scale, closeup_scale); float boxw = 1, boxh = 1, zx0 = zoom_x, zy0 = zoom_y, zx1 = zoom_x, zy1 = zoom_y, zxm = -1.0, zym = -1.0; dt_dev_check_zoom_bounds(dev, &zx0, &zy0, zoom, 0, &boxw, &boxh); dt_dev_check_zoom_bounds(dev, &zx1, &zy1, zoom, 1, &boxw, &boxh); dt_dev_check_zoom_bounds(dev, &zxm, &zym, zoom, 1, &boxw, &boxh); const float fx = 1.0 - fmaxf(0.0, (zx0 - zx1)/(zx0 - zxm)), fy = 1.0 - fmaxf(0.0, (zy0 - zy1)/(zy0 - zym)); cairo_translate(cr, -wd/(2.0*closeup_scale) * fx, -ht/(2.0*closeup_scale) * fy); } cairo_rectangle(cr, 0, 0, wd, ht); cairo_set_source_surface (cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST); cairo_fill_preserve(cr); cairo_set_line_width(cr, 1.0); cairo_set_source_rgb (cr, .3, .3, .3); cairo_stroke(cr); cairo_surface_destroy (surface); dt_pthread_mutex_unlock(mutex); image_surface_imgid = dev->image_storage.id; } else if(!dev->preview_dirty) { // draw preview mutex = &dev->preview_pipe->backbuf_mutex; dt_pthread_mutex_lock(mutex); wd = dev->preview_pipe->backbuf_width; ht = dev->preview_pipe->backbuf_height; float zoom_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 1); cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); cairo_rectangle(cr, 0, 0, width, height); cairo_clip(cr); stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, wd); surface = cairo_image_surface_create_for_data (dev->preview_pipe->backbuf, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width/2.0, height/2.0f); cairo_scale(cr, zoom_scale, zoom_scale); cairo_translate(cr, -.5f*wd-zoom_x*wd, -.5f*ht-zoom_y*ht); // avoid to draw the 1px garbage that sometimes shows up in the preview :( cairo_rectangle(cr, 0, 0, wd-1, ht-1); cairo_set_source_surface (cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST); cairo_fill(cr); cairo_surface_destroy (surface); dt_pthread_mutex_unlock(mutex); image_surface_imgid = dev->image_storage.id; } cairo_restore(cri); if(image_surface_imgid == dev->image_storage.id) { cairo_destroy(cr); cairo_set_source_surface(cri, image_surface, 0, 0); cairo_paint(cri); } /* check if we should create a snapshot of view */ if(darktable.develop->proxy.snapshot.request) { /* reset the request */ darktable.develop->proxy.snapshot.request = FALSE; /* validation of snapshot filename */ g_assert(darktable.develop->proxy.snapshot.filename != NULL); /* Store current image surface to snapshot file. FIXME: add checks so that we dont make snapshots of preview pipe image surface. */ cairo_surface_write_to_png(image_surface, darktable.develop->proxy.snapshot.filename); } // Displaying sample areas if enabled if(darktable.lib->proxy.colorpicker.live_samples && darktable.lib->proxy.colorpicker.display_samples) { GSList *samples = darktable.lib->proxy.colorpicker.live_samples; dt_colorpicker_sample_t *sample = NULL; cairo_save(cri); int32_t zoom, closeup; float zoom_x, zoom_y; float wd = dev->preview_pipe->backbuf_width; float ht = dev->preview_pipe->backbuf_height; DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); float zoom_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 1); cairo_translate(cri, width/2.0, height/2.0f); cairo_scale(cri, zoom_scale, zoom_scale); cairo_translate(cri, -.5f*wd-zoom_x*wd, -.5f*ht-zoom_y*ht); while(samples) { sample = samples->data; cairo_set_line_width(cri, 1.0/zoom_scale); if(sample == darktable.lib->proxy.colorpicker.selected_sample) cairo_set_source_rgb(cri, .2, 0, 0); else cairo_set_source_rgb(cri, 0, 0, .2); float *box = sample->box; float *point = sample->point; if(sample->size == DT_COLORPICKER_SIZE_BOX) { cairo_rectangle(cri, box[0]*wd, box[1]*ht, (box[2] - box[0])*wd, (box[3] - box[1])*ht); cairo_stroke(cri); cairo_translate(cri, 1.0/zoom_scale, 1.0/zoom_scale); if(sample == darktable.lib->proxy.colorpicker.selected_sample) cairo_set_source_rgb(cri, .8, 0, 0); else cairo_set_source_rgb(cri, 0, 0, .8); cairo_rectangle(cri, box[0]*wd + 1.0/zoom_scale, box[1]*ht, (box[2] - box[0])*wd - 3./zoom_scale, (box[3] - box[1])*ht - 2./zoom_scale); cairo_stroke(cri); } else { cairo_rectangle(cri, point[0] * wd - .01 * wd, point[1] * ht - .01 * wd, .02 * wd, .02 * wd); cairo_stroke(cri); if(sample == darktable.lib->proxy.colorpicker.selected_sample) cairo_set_source_rgb(cri, .8, 0, 0); else cairo_set_source_rgb(cri, 0, 0, .8); cairo_rectangle(cri, (point[0] - 0.01) * wd + 1.0/zoom_scale, point[1] * ht - 0.01 * wd + 1.0/zoom_scale, .02 * wd - 2./zoom_scale, .02 * wd - 2./zoom_scale); cairo_move_to(cri, point[0] * wd, point[1] * ht - .01 * wd + 1./zoom_scale); cairo_line_to(cri, point[0] * wd, point[1] * ht + .01 * wd - 1./zoom_scale); cairo_move_to(cri, point[0] * wd - .01 * wd + 1./zoom_scale, point[1] * ht); cairo_line_to(cri, point[0] * wd + .01 * wd - 1./zoom_scale, point[1] * ht); cairo_stroke(cri); } samples = g_slist_next(samples); } cairo_restore(cri); } // execute module callback hook. if(dev->gui_module && dev->gui_module->request_color_pick) { int32_t zoom, closeup; float zoom_x, zoom_y; float wd = dev->preview_pipe->backbuf_width; float ht = dev->preview_pipe->backbuf_height; DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); float zoom_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 1); cairo_translate(cri, width/2.0, height/2.0f); cairo_scale(cri, zoom_scale, zoom_scale); cairo_translate(cri, -.5f*wd-zoom_x*wd, -.5f*ht-zoom_y*ht); // cairo_set_operator(cri, CAIRO_OPERATOR_XOR); cairo_set_line_width(cri, 1.0/zoom_scale); cairo_set_source_rgb(cri, .2, .2, .2); float *box = dev->gui_module->color_picker_box; float *point = dev->gui_module->color_picker_point; if(darktable.lib->proxy.colorpicker.size) { cairo_rectangle(cri, box[0]*wd, box[1]*ht, (box[2] - box[0])*wd, (box[3] - box[1])*ht); cairo_stroke(cri); cairo_translate(cri, 1.0/zoom_scale, 1.0/zoom_scale); cairo_set_source_rgb(cri, .8, .8, .8); cairo_rectangle(cri, box[0]*wd + 1.0/zoom_scale, box[1]*ht, (box[2] - box[0])*wd - 3./zoom_scale, (box[3] - box[1])*ht - 2./zoom_scale); cairo_stroke(cri); } else { cairo_rectangle(cri, point[0] * wd - .01 * wd, point[1] * ht - .01 * wd, .02 * wd, .02 * wd); cairo_stroke(cri); cairo_set_source_rgb(cri, .8, .8, .8); cairo_rectangle(cri, (point[0] - 0.01) * wd + 1.0/zoom_scale, point[1] * ht - 0.01 * wd + 1.0/zoom_scale, .02 * wd - 2./zoom_scale, .02 * wd - 2./zoom_scale); cairo_move_to(cri, point[0] * wd, point[1] * ht - .01 * wd + 1./zoom_scale); cairo_line_to(cri, point[0] * wd, point[1] * ht + .01 * wd - 1./zoom_scale); cairo_move_to(cri, point[0] * wd - .01 * wd + 1./zoom_scale, point[1] * ht); cairo_line_to(cri, point[0] * wd + .01 * wd - 1./zoom_scale, point[1] * ht); cairo_stroke(cri); } } else if(dev->gui_module && dev->gui_module->gui_post_expose) { if(width_i > capwd) pointerx += (capwd-width_i) *.5f; if(height_i > capht) pointery += (capht-height_i)*.5f; dev->gui_module->gui_post_expose(dev->gui_module, cri, width, height, pointerx, pointery); } }
static void cb_print_draw_page(GtkPrintOperation* print_operation, GtkPrintContext* context, gint page_number, zathura_t* zathura) { if (context == NULL || zathura == NULL || zathura->document == NULL || zathura->ui.session == NULL || zathura->ui.statusbar.file == NULL) { gtk_print_operation_cancel(print_operation); return; } /* Update statusbar. */ char* tmp = g_strdup_printf("Printing %d...", page_number); girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, tmp); g_free(tmp); /* Get the page and cairo handle. */ cairo_t* cairo = gtk_print_context_get_cairo_context(context); zathura_page_t* page = zathura_document_get_page(zathura->document, page_number); if (cairo == NULL || page == NULL) { gtk_print_operation_cancel(print_operation); return; } /* Try to render the page without a temporary surface. This only works with * plugins that support rendering to any surface. */ girara_debug("printing page %d ...", page_number); zathura_renderer_lock(zathura->sync.render_thread); int err = zathura_page_render(page, cairo, true); zathura_renderer_unlock(zathura->sync.render_thread); if (err == ZATHURA_ERROR_OK) { return; } /* Try to render the page on a temporary image surface. */ const gdouble width = gtk_print_context_get_width(context); const gdouble height = gtk_print_context_get_height(context); /* Render to a surface that is 5 times larger to workaround quality issues. */ const double page_height = zathura_page_get_height(page) * 5; const double page_width = zathura_page_get_width(page) * 5; cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, page_width, page_height); if (surface == NULL) { gtk_print_operation_cancel(print_operation); return; } cairo_t* temp_cairo = cairo_create(surface); if (cairo == NULL) { gtk_print_operation_cancel(print_operation); cairo_surface_destroy(surface); return; } /* Draw a white background. */ cairo_save(temp_cairo); cairo_set_source_rgb(temp_cairo, 1, 1, 1); cairo_rectangle(temp_cairo, 0, 0, page_width, page_height); cairo_fill(temp_cairo); cairo_restore(temp_cairo); /* Render the page to the temporary surface */ girara_debug("printing page %d (fallback) ...", page_number); zathura_renderer_lock(zathura->sync.render_thread); err = zathura_page_render(page, temp_cairo, true); zathura_renderer_unlock(zathura->sync.render_thread); if (err != ZATHURA_ERROR_OK) { cairo_destroy(temp_cairo); cairo_surface_destroy(surface); gtk_print_operation_cancel(print_operation); return; } /* Rescale the page and keep the aspect ratio */ const gdouble scale = MIN(width / page_width, height / page_height); cairo_scale(cairo, scale, scale); /* Blit temporary surface to original cairo object. */ cairo_set_source_surface(cairo, surface, 0.0, 0.0); cairo_paint(cairo); cairo_destroy(temp_cairo); cairo_surface_destroy(surface); }
static gboolean _lib_filmstrip_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; int32_t width = widget->allocation.width; int32_t height = widget->allocation.height; gdouble pointerx = strip->pointerx; gdouble pointery = strip->pointery; if(darktable.gui->center_tooltip == 1) darktable.gui->center_tooltip++; strip->image_over = DT_VIEW_DESERT; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); /* create cairo surface */ cairo_t *cr = gdk_cairo_create(widget->window); /* fill background */ cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); int offset = strip->offset; const float wd = height; const float ht = height; int max_cols = (int)(width/(float)wd) + 2; if (max_cols%2 == 0) max_cols += 1; const int col_start = max_cols/2 - strip->offset; const int empty_edge = (width - (max_cols * wd))/2; int step_res = SQLITE_ROW; sqlite3_stmt *stmt = NULL; /* mouse over image position in filmstrip */ pointerx -= empty_edge; const int seli = (pointery > 0 && pointery <= ht) ? pointerx / (float)wd : -1; const int img_pointerx = (int)fmodf(pointerx, wd); const int img_pointery = (int)pointery; /* get the count of current collection */ strip->collection_count = dt_collection_get_count (darktable.collection); /* get the collection query */ const gchar *query=dt_collection_get_query (darktable.collection); if(!query) return FALSE; if(offset < 0) strip->offset = offset = 0; if(offset > strip->collection_count-1) strip->offset = offset = strip->collection_count-1; // dt_view_set_scrollbar(self, offset, count, max_cols, 0, 1, 1); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, offset - max_cols/2); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, max_cols); cairo_save(cr); cairo_translate(cr, empty_edge, 0.0f); for(int col = 0; col < max_cols; col++) { if(col < col_start) { cairo_translate(cr, wd, 0.0f); continue; } if(step_res != SQLITE_DONE) { step_res = sqlite3_step(stmt); } if(step_res == SQLITE_ROW) { int id = sqlite3_column_int(stmt, 0); // set mouse over id if(seli == col) { strip->mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, strip->mouse_over_id); } cairo_save(cr); // FIXME find out where the y translation is done, how big the value is and use it directly instead of getting it from the matrix ... cairo_matrix_t m; cairo_get_matrix(cr, &m); dt_view_image_expose(&(strip->image_over), id, cr, wd, ht, max_cols, img_pointerx, img_pointery, FALSE); cairo_restore(cr); } else if (step_res == SQLITE_DONE) { /* do nothing, just add some empty thumb frames */ } else goto failure; cairo_translate(cr, wd, 0.0f); } failure: cairo_restore(cr); sqlite3_finalize(stmt); if(darktable.gui->center_tooltip == 1) // set in this round { char* tooltip = dt_history_get_items_as_string(strip->mouse_over_id); if(tooltip != NULL) { g_object_set(G_OBJECT(strip->filmstrip), "tooltip-text", tooltip, (char *)NULL); g_free(tooltip); } } else if(darktable.gui->center_tooltip == 2) // not set in this round { darktable.gui->center_tooltip = 0; g_object_set(G_OBJECT(strip->filmstrip), "tooltip-text", "", (char *)NULL); } #ifdef _DEBUG if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); #endif /* cleanup */ cairo_destroy(cr); return TRUE; }
/* void layout_paint(GtkWidget *widget, cairo_t *cr, GtkRange *range) */ extern gboolean layout_expose(GtkWidget *widget, GdkEventExpose *event, Score_t *score) { cairo_t *cr = gdk_cairo_create(widget->window); GList * listrunner_staff = NULL; GList * listrunner_object = NULL; gint width, height; gint i; g_assert( score ); width = widget->allocation.width; height = widget->allocation.height; /* * enclosing the painting function in a save/restore pair is a * good idea since we'll return to a sane state then */ cairo_save (cr); /* clear background */ cairo_rectangle (cr, 0, 0, width, height); cairo_set_source_rgb (cr, 1,1,1); cairo_fill (cr); /* enclosing in a save/restore pair since we alter the * font size */ cairo_save (cr); /*************** * Draw Staves * ***************/ /* We walk through staves */ listrunner_staff = g_list_first(score->Staff_list); while ( listrunner_staff ) { measure_number = 1; Staff_t *staff; staff = (Staff_t *)listrunner_staff->data; object_x = staff->extremity_begin_x + Spacings.Clefs.sb + (score->zoom * TREBLE_CLEF_WIDTH_FACTOR) + Spacings.Clefs.sa + get_key_signature_spacing(score, staff) + Spacings.KeySignatures.saks + Spacings.TimeSignatures.width + Spacings.TimeSignatures.sats; draw_staff(score, cr, staff->nb_lines, staff->space_btw_lines, staff->extremity_begin_x, staff->extremity_begin_y, score->staff_extremity_end_x, staff->is_selected); /* if ( display->clefs ) */ draw_key(score, staff, cr, FALSE); /* if ( display->key_signature ) */ draw_key_signature(score, staff, cr, FALSE); /* if ( display->time_signature ) */ draw_time_signature(score, staff, cr, FALSE); listrunner_object = g_list_first(staff->Object_list); while ( listrunner_object ) { Object_t *object = NULL; object = (Object_t *)listrunner_object->data; /* g_print("object->pitch = %d \n", object->pitch); */ /* g_print("%s:%d: x = %f\n", __FILE__, __LINE__, object_x); */ if (object) { draw_staff_extension(score, staff, cr, object->pitch, object_x); /* g_print("layout engine, object_type = %d\n", object->type); */ switch(object->type) { case PITCH_CURSOR: object_x = draw_pitch_cursor(score, staff, cr, object_x, object->pitch); break; case BARLINE_SINGLE: object_x = draw_barline_single(score, staff, object, cr, object_x); break; case DOUBLEWHOLE: case DOUBLEWHOLEREST: case WHOLE: case WHOLEREST: case HALF: case HALFREST: case QUARTER: case QUARTERREST: case EIGHTH: case EIGHTHREST: case SIXTEENTH: case SIXTEENTHREST: object_x = draw_note_rest(score, staff, object, cr, object_x); break; default: g_print("Unknown object type: %d\n", object->type); } } listrunner_object = g_list_next(listrunner_object); } listrunner_staff = g_list_next(listrunner_staff); } /* while ( listrunner_staff ) */ cairo_set_source_rgb (cr, 0, 0, 0); /* Show the quarter note head */ /* cairo_select_font (cr, "gscore", CAIRO_FONT_SLANT_NORMAL, */ /* CAIRO_FONT_WEIGHT_BOLD); */ /* cairo_save (cr); */ /* cairo_scale_font (cr, 30); */ /* cairo_move_to (cr, 100.5, 54); */ /* cairo_set_rgb_color (cr, 0,0,0); */ /* cairo_show_text (cr, QUARTER_GLYPH); */ /* Show the stem */ /* Line */ /* cairo_move_to(cr, 100.5, 54); */ /* cairo_rel_line_to(cr, 0, 30.5); */ /* cairo_stroke(cr); */ /* /\* Sixteenth *\/ */ /* cairo_move_to (cr, 101, 84.5); */ /* cairo_show_text (cr, SIXTEENTH_STEM_DOWN_GLYPH); */ /* /\* Add a sharp to the note *\/ */ /* cairo_move_to (cr, 90, 54); */ /* cairo_scale_font (cr, 1); */ /* cairo_set_rgb_color (cr, 0,0,0); */ /* cairo_show_text (cr, SHARP_GLYPH); */ /* cairo_stroke(cr); */ /* /\* Show the key *\/ */ /* cairo_move_to (cr, 15.5, 75); */ /* cairo_scale_font (cr, 1); */ /* cairo_set_rgb_color (cr, 0,0,0); */ /* cairo_show_text (cr, TREBLE_GLYPH); */ /* cairo_stroke(cr); */ /* /\* Add 2/4 *\/ */ /* cairo_move_to (cr, 40, 66.5); */ /* cairo_scale_font (cr, 0.5); */ /* cairo_show_text (cr, "2"); */ /* cairo_move_to (cr, 40, 82.5); */ /* cairo_show_text (cr, "4"); */ /* cairo_restore (cr); */ /* cairo_set_rgb_color (cr, 1,0,0); */ /* cairo_scale_font (cr, 15); */ /* cairo_move_to (cr, 50, 100); */ cairo_stroke (cr); cairo_restore (cr); selection_paint(cr, score); }
static void clear_surface ( void ) { cairo_t *cr = cairo_create( surface ); cairo_set_source_rgb( cr, 1, 1, 1 ); cairo_paint( cr ); cairo_destroy( cr ); }
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); } } }
static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context, gint page_nr, gpointer user_data) { DocInfo *dinfo = user_data; GeanyEditor *editor; cairo_t *cr; gdouble width, height; gdouble x, y; /*gint layout_h;*/ gint count; GString *str; if (dinfo == NULL || page_nr >= dinfo->n_pages) return; editor = dinfo->doc->editor; if (dinfo->n_pages > 0) { gdouble fraction = (page_nr + 1) / (gdouble) dinfo->n_pages; gchar *text = g_strdup_printf(_("Page %d of %d"), page_nr, dinfo->n_pages); gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(main_widgets.progressbar), fraction); gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets.progressbar), text); g_free(text); } #ifdef GEANY_PRINT_DEBUG geany_debug("draw_page = %d, pages = %d, (real) lines_per_page = %d", page_nr, dinfo->n_pages, dinfo->lines_per_page); #endif str = g_string_sized_new(256); cr = gtk_print_context_get_cairo_context(context); width = gtk_print_context_get_width(context); height = gtk_print_context_get_height(context); cairo_set_source_rgb(cr, 0, 0, 0); #ifdef GEANY_PRINT_DEBUG cairo_set_line_width(cr, 0.2); cairo_rectangle(cr, 0, 0, width, height); cairo_stroke(cr); #endif cairo_move_to(cr, 0, 0); pango_layout_set_width(dinfo->layout, width * PANGO_SCALE); pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_LEFT); pango_layout_set_ellipsize(dinfo->layout, FALSE); pango_layout_set_justify(dinfo->layout, FALSE); if (printing_prefs.print_page_header) add_page_header(dinfo, cr, width, page_nr); count = 0; /* the actual line counter for the current page, might be different from * dinfo->cur_line due to possible line breaks */ while (count < dinfo->lines_per_page) { gchar c = 'a'; gint style = -1; PangoAttrList *layout_attr; PangoAttribute *attr; gint colours[3] = { 0 }; gboolean add_linenumber = TRUE; gboolean at_eol; while (count < dinfo->lines_per_page && c != '\0') { at_eol = FALSE; g_string_erase(str, 0, str->len); /* clear the string */ /* line numbers */ if (printing_prefs.print_line_numbers && add_linenumber) { /* if we had a wrapped line on the last page which needs to be continued, don't * add a line number */ if (dinfo->long_line) { add_linenumber = FALSE; } else { gchar *line_number = NULL; gint cur_line_number_margin = get_line_numbers_arity(dinfo->cur_line + 1); gchar *fill = g_strnfill( dinfo->max_line_number_margin - cur_line_number_margin - 1, ' '); line_number = g_strdup_printf("%s%d ", fill, dinfo->cur_line + 1); g_string_append(str, line_number); dinfo->cur_line++; /* increase document line */ add_linenumber = FALSE; style = STYLE_LINENUMBER; c = 'a'; /* dummy value */ g_free(fill); g_free(line_number); } } /* data */ else { style = sci_get_style_at(dinfo->doc->editor->sci, dinfo->cur_pos); c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos); if (c == '\0' || style == -1) { /* if c gets 0, we are probably out of document boundaries, * so stop to break out of outer loop */ count = dinfo->lines_per_page; break; } dinfo->cur_pos++; /* convert tabs to spaces which seems to be better than using Pango tabs */ if (c == '\t') { gint tab_width = sci_get_tab_width(editor->sci); gchar *s = g_strnfill(tab_width, ' '); g_string_append(str, s); g_free(s); } /* don't add line breaks, they are handled manually below */ else if (c == '\r' || c == '\n') { gchar c_next = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos); at_eol = TRUE; if (c == '\r' && c_next == '\n') dinfo->cur_pos++; /* skip LF part of CR/LF */ } else { g_string_append_c(str, c); /* finally add the character */ /* handle UTF-8: since we add char by char (better: byte by byte), we need to * keep UTF-8 characters together(e.g. two bytes for one character) * the input is always UTF-8 and c is signed, so all non-Ascii * characters are less than 0 and consist of all bytes less than 0. * style doesn't change since it is only one character with multiple bytes. */ while (c < 0) { c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos); if (c < 0) { /* only add the byte when it is part of the UTF-8 character * otherwise we could add e.g. a '\n' and it won't be visible in the * printed document */ g_string_append_c(str, c); dinfo->cur_pos++; } } } } if (! at_eol) { /* set text */ pango_layout_set_text(dinfo->layout, str->str, -1); /* attributes */ layout_attr = pango_attr_list_new(); /* foreground colour */ get_rgb_values(dinfo->styles[style][FORE], &colours[0], &colours[1], &colours[2]); attr = pango_attr_foreground_new(colours[0], colours[1], colours[2]); ADD_ATTR(layout_attr, attr); /* background colour */ get_rgb_values(dinfo->styles[style][BACK], &colours[0], &colours[1], &colours[2]); attr = pango_attr_background_new(colours[0], colours[1], colours[2]); ADD_ATTR(layout_attr, attr); /* bold text */ if (dinfo->styles[style][BOLD]) { attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD); ADD_ATTR(layout_attr, attr); } /* italic text */ if (dinfo->styles[style][ITALIC]) { attr = pango_attr_style_new(PANGO_STYLE_ITALIC); ADD_ATTR(layout_attr, attr); } pango_layout_set_attributes(dinfo->layout, layout_attr); pango_layout_context_changed(dinfo->layout); pango_attr_list_unref(layout_attr); } cairo_get_current_point(cr, &x, &y); /* normal line break at eol character in document */ if (at_eol) { /*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/ /*cairo_move_to(cr, 0, y + (gdouble)layout_h / PANGO_SCALE);*/ cairo_move_to(cr, 0, y + dinfo->line_height); count++; /* we added a new document line so request a new line number */ add_linenumber = TRUE; } else { gint x_offset = 0; /* maybe we need to force a line break because of too long line */ if (x >= (width - dinfo->font_width)) { /* don't start the line at horizontal origin because we need to skip the * line number margin */ if (printing_prefs.print_line_numbers) { x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width; } /*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/ /*cairo_move_to(cr, x_offset, y + (gdouble)layout_h / PANGO_SCALE);*/ /* this is faster but not exactly the same as above */ cairo_move_to(cr, x_offset, y + dinfo->line_height); cairo_get_current_point(cr, &x, &y); count++; } if (count < dinfo->lines_per_page) { /* str->len is counted in bytes not characters, so use g_utf8_strlen() */ x_offset = (g_utf8_strlen(str->str, -1) * dinfo->font_width); if (dinfo->long_line && count == 0) { x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width; dinfo->long_line = FALSE; } pango_cairo_show_layout(cr, dinfo->layout); cairo_move_to(cr, x + x_offset, y); } else /* we are on a wrapped line but we are out of lines on this page, so continue * the current line on the next page and remember to continue in current line */ dinfo->long_line = TRUE; } } } if (printing_prefs.print_line_numbers) { /* print a thin line between the line number margin and the data */ gint y_start = 0; if (printing_prefs.print_page_header) y_start = (dinfo->line_height * 3) - 2; /* "- 2": to connect the line number line to * the page header frame */ cairo_set_line_width(cr, 0.3); cairo_move_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1, y_start); cairo_line_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1, y + dinfo->line_height); /* y is last added line, we reuse it */ cairo_stroke(cr); } if (printing_prefs.print_page_numbers) { gchar *line = g_strdup_printf("<small>- %d -</small>", page_nr + 1); pango_layout_set_markup(dinfo->layout, line, -1); pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_CENTER); cairo_move_to(cr, 0, height - dinfo->line_height); pango_cairo_show_layout(cr, dinfo->layout); g_free(line); #ifdef GEANY_PRINT_DEBUG cairo_set_line_width(cr, 0.3); cairo_move_to(cr, 0, height - (1.25 * dinfo->line_height)); cairo_line_to(cr, width - 1, height - (1.25 * dinfo->line_height)); cairo_stroke(cr); #endif } g_string_free(str, TRUE); }
gboolean cd_do_render_listing_notification (gpointer pUserData, CDListing *pListing, cairo_t *pCairoContext) { //g_print ("%s ()\n", __func__); int iWidth = pListing->container.iWidth, iHeight = pListing->container.iHeight; int iLeftMargin = myDialogs.dialogTextDescription.iSize + 2, iRightMargin = (myDialogs.dialogTextDescription.iSize + 2) / 2; int iTopMargin = (myDialogs.dialogTextDescription.iSize + 2) + GAP, iBottomMargin = (myDialogs.dialogTextDescription.iSize + 2) * 4 + GAP; CDEntry *pEntry; // on dessine un cadre et un fond double fRadius = MIN (6, myDialogs.dialogTextDescription.iSize/2+1); double fLineWidth = 1.; cairo_set_line_width (pCairoContext, fLineWidth); cairo_save (pCairoContext); cairo_translate (pCairoContext, 0, fLineWidth); cairo_dock_draw_rounded_rectangle (pCairoContext, fRadius, fLineWidth, iWidth - 2 * fRadius - fLineWidth, iTopMargin - GAP); cairo_set_source_rgba (pCairoContext, .8, .8, 1., 1.); cairo_stroke_preserve (pCairoContext); cairo_set_source_rgba (pCairoContext, 1., 1., 1., .7); cairo_fill (pCairoContext); cairo_translate (pCairoContext, 0, iTopMargin + fLineWidth); cairo_dock_draw_rounded_rectangle (pCairoContext, fRadius, fLineWidth, iWidth - 2 * fRadius - fLineWidth, iHeight - iTopMargin - iBottomMargin - GAP); cairo_set_source_rgba (pCairoContext, .8, .8, 1., 1.); cairo_stroke_preserve (pCairoContext); cairo_set_source_rgba (pCairoContext, 1., 1., 1., .7); cairo_fill (pCairoContext); cairo_translate (pCairoContext, 0, iHeight - iTopMargin - 2*fLineWidth - iBottomMargin + GAP); cairo_dock_draw_rounded_rectangle (pCairoContext, fRadius, fLineWidth, iWidth - 2 * fRadius - fLineWidth, iBottomMargin - GAP - fLineWidth); cairo_set_source_rgba (pCairoContext, .8, .8, 1., 1.); cairo_stroke_preserve (pCairoContext); cairo_set_source_rgba (pCairoContext, 1., 1., 1., .7); cairo_fill (pCairoContext); cairo_restore (pCairoContext); PangoLayout *pLayout = pango_cairo_create_layout (pCairoContext); PangoFontDescription *pDesc = pango_font_description_new (); pango_font_description_set_absolute_size (pDesc, myDialogs.dialogTextDescription.iSize * PANGO_SCALE); pango_font_description_set_family_static (pDesc, myDialogs.dialogTextDescription.cFont); pango_font_description_set_weight (pDesc, myDialogs.dialogTextDescription.iWeight); pango_font_description_set_style (pDesc, myLabels.iconTextDescription.iStyle); pango_layout_set_font_description (pLayout, pDesc); pango_font_description_free (pDesc); // on dessine les entrees. if (pListing->pEntries != NULL) { // on dessine chaque entree. int iNbSteps = _listing_compute_nb_steps (pListing); // nb d'etapes pour l'apparition du texte. int iOffsetX = NB_STEPS_FOR_1_ENTRY - (iNbSteps - pListing->iAppearanceAnimationCount) - 1; if (pListing->iNbEntries >= myConfig.iNbLinesInListing) iOffsetX += myConfig.iNbLinesInListing/4*NB_STEPS_LATE; // permet de donner une transparence aux 25% dernieres lignes. double dx, dy, dm = myConfig.iNbLinesInListing * (myDialogs.dialogTextDescription.iSize + 2) / 2; dm = 0; dy = iTopMargin - pListing->fCurrentOffset + 1 + dm; double ymax = MIN (iTopMargin + pListing->iNbEntries * (myDialogs.dialogTextDescription.iSize + 2), iHeight - iBottomMargin); GList *e; for (e = pListing->pEntries; e != NULL; e = e->next) { if (iOffsetX >= NB_STEPS_FOR_1_ENTRY) // en dehors a droite a partir de celui-ci. break ; pEntry = e->data; if (pEntry->bHidden) continue ; dx = myDialogs.dialogTextDescription.iSize + 2; // marge a gauche. //if (iOffsetX > 0 && pListing->iAppearanceAnimationCount > 0) // dx += (double) iOffsetX * (iWidth - (myDialogs.dialogTextDescription.iSize + 2)) / NB_STEPS_FOR_1_ENTRY; dy += (myDialogs.dialogTextDescription.iSize + 2); while (dy + myDialogs.dialogTextDescription.iSize + 2 <= iTopMargin + 1) dy += pListing->iNbEntries * (myDialogs.dialogTextDescription.iSize + 2); while (dy > ymax) dy -= pListing->iNbEntries * (myDialogs.dialogTextDescription.iSize + 2); if (dy > ymax || dy + myDialogs.dialogTextDescription.iSize + 2 <= iTopMargin + 1) continue; cairo_save (pCairoContext); cairo_translate (pCairoContext, dx, dy); // on fait un clip si necessaire. if (dy + myDialogs.dialogTextDescription.iSize + 2 > iHeight - iBottomMargin || dy < iTopMargin) // cette entree n'est que partiellement visible. { if (dy < iTopMargin) // elle depasse en haut. cairo_rectangle (pCairoContext, -iLeftMargin, iTopMargin - dy, iWidth, myDialogs.dialogTextDescription.iSize + 2 -(iTopMargin - dy)); else // elle depasse en bas. cairo_rectangle (pCairoContext, -iLeftMargin, 0, iWidth, iHeight - iBottomMargin - dy); cairo_clip (pCairoContext); } // on dessine l'icone. if (pEntry->pIconSurface != NULL) { cairo_set_source_surface (pCairoContext, pEntry->pIconSurface, - iLeftMargin + 1, 0.); cairo_paint (pCairoContext); } // on souligne l'entree courante. if (e == pListing->pCurrentEntry) { double f = 1. - (double) pListing->iCurrentEntryAnimationCount / NB_STEPS_FOR_CURRENT_ENTRY; if (f != 0) { cairo_save (pCairoContext); double rx = .5*(iWidth - iLeftMargin - iRightMargin); double ry = .5*(myDialogs.dialogTextDescription.iSize + 2); cairo_pattern_t *pPattern = cairo_pattern_create_radial (ry, ry, 0., ry, ry, f * ry); cairo_pattern_set_extend (pPattern, CAIRO_EXTEND_NONE); cairo_pattern_add_color_stop_rgba (pPattern, 0., 0., 0., 1., .3); cairo_pattern_add_color_stop_rgba (pPattern, 1., 0., 0., 0., 0.); cairo_scale (pCairoContext, rx/ry, 1.); cairo_set_source (pCairoContext, pPattern); cairo_paint (pCairoContext); cairo_pattern_destroy (pPattern); cairo_restore (pCairoContext); // on dessine l'indicateur de sous-listing. if (pEntry->list != NULL) { cairo_set_source_rgba (pCairoContext, 0., 0., 0., f); cairo_move_to (pCairoContext, iWidth - iLeftMargin - iRightMargin, myDialogs.dialogTextDescription.iSize/4); cairo_rel_line_to (pCairoContext, iRightMargin, myDialogs.dialogTextDescription.iSize/4); cairo_rel_line_to (pCairoContext, -iRightMargin, myDialogs.dialogTextDescription.iSize/4); cairo_close_path (pCairoContext); cairo_stroke (pCairoContext); } } } // on dessine le texte. cairo_set_source_rgba (pCairoContext, 0., 0., 0., 1. - (double) iOffsetX / NB_STEPS_FOR_1_ENTRY); pango_layout_set_text (pLayout, pEntry->cName, -1); pango_cairo_show_layout (pCairoContext, pLayout); // on separe la 1ere entree de la derniere. if (e->prev == NULL) { cairo_set_source_rgba (pCairoContext, 0., 0., 0., .5); cairo_move_to (pCairoContext, 0., 1.); cairo_rel_line_to (pCairoContext, iWidth - iLeftMargin - iRightMargin, 0.); double dashes = 2.; cairo_set_dash (pCairoContext, &dashes, 1, 0.); cairo_stroke (pCairoContext); cairo_set_dash (pCairoContext, &dashes, 0, 0.); } cairo_restore (pCairoContext); iOffsetX += NB_STEPS_LATE; } // on dessine le chemin de l'entree courante. if (pListing->pCurrentEntry) { pEntry = pListing->pCurrentEntry->data; cairo_save (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); cairo_translate (pCairoContext, fRadius - pListing->iTitleOffset, 0.); pango_layout_set_text (pLayout, pEntry->cPath ? pEntry->cPath : pEntry->cName, -1); PangoRectangle ink, log; pango_layout_get_pixel_extents (pLayout, &ink, &log); pListing->iTitleWidth = ink.width; pango_cairo_show_layout (pCairoContext, pLayout); cairo_restore (pCairoContext); } } // on dessine l'etat de la recherche. cairo_translate (pCairoContext, 0, iHeight - iBottomMargin); cairo_set_source_surface (pCairoContext, myData.pScoobySurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); cairo_translate (pCairoContext, 2 * (myDialogs.dialogTextDescription.iSize + 2), GAP); if (myData.cStatus != NULL) { pango_layout_set_text (pLayout, myData.cStatus, -1); } pango_cairo_show_layout (pCairoContext, pLayout); // on dessine le filtre. cairo_translate (pCairoContext, 0., myDialogs.dialogTextDescription.iSize + 2); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_MATCH_CASE) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F1) Match case"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, iWidth/3, 0.); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_MUSIC) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F2) Music"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, iWidth/3, 0.); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_IMAGE) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F3) Image"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, -2*iWidth/3, myDialogs.dialogTextDescription.iSize + 2); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_VIDEO) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F4) Video"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, iWidth/3, 0.); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_TEXT) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F5) Text"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, iWidth/3, 0.); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_HTML) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F6) Html"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, -2*iWidth/3, myDialogs.dialogTextDescription.iSize + 2); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_SOURCE) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F7) Sources"), -1); pango_cairo_show_layout (pCairoContext, pLayout); g_object_unref (pLayout); }
void html_engine_draw_cursor_in_area (HTMLEngine *engine, gint x, gint y, gint width, gint height) { HTMLObject *obj; guint offset; gint x1, y1, x2, y2, sc_x, sc_y; GdkRectangle pos; GtkAdjustment *hadj, *vadj; if ((engine->editable || engine->caret_mode) && (engine->cursor_hide_count <= 0 && !engine->thaw_idle_id)) { html_engine_draw_table_cursor (engine); html_engine_draw_cell_cursor (engine); html_engine_draw_image_cursor (engine); } if (!cursor_enabled || engine->cursor_hide_count > 0 || !(engine->editable || engine->caret_mode) || engine->thaw_idle_id) return; obj = engine->cursor->object; if (obj == NULL || engine->window == NULL) return; offset = engine->cursor->offset; if (width < 0 || height < 0) { width = html_engine_get_doc_width (engine); height = html_engine_get_doc_height (engine); x = 0; y = 0; } html_object_get_cursor (obj, engine->painter, offset, &x1, &y1, &x2, &y2); while (obj) { if (html_object_is_frame (obj)) { x1 -= HTML_EMBEDDED (obj)->abs_x; x2 -= HTML_EMBEDDED (obj)->abs_x; y1 -= HTML_EMBEDDED (obj)->abs_y; y2 -= HTML_EMBEDDED (obj)->abs_y; break; } obj = obj->parent; } /* get scroll offset */ hadj = gtk_layout_get_hadjustment (GTK_LAYOUT (engine->widget)); vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (engine->widget)); sc_x = (gint) gtk_adjustment_get_value (hadj); sc_y = (gint) gtk_adjustment_get_value (vadj); pos.x = x1 - sc_x; pos.y = y1 - sc_y; pos.width = x2 - x1; pos.height = y2 - y1; gtk_im_context_set_cursor_location (GTK_HTML (engine->widget)->priv->im_context, &pos); if (clip_cursor (engine, x, y, width, height, &x1, &y1, &x2, &y2)) { cairo_t *cr; gboolean using_painter_cr; using_painter_cr = engine->painter && HTML_IS_GDK_PAINTER (engine->painter) && HTML_GDK_PAINTER (engine->painter)->cr != NULL; if (using_painter_cr) { HTMLGdkPainter *gdk_painter = HTML_GDK_PAINTER (engine->painter); cr = gdk_painter->cr; cairo_save (cr); x1 -= gdk_painter->x1; y1 -= gdk_painter->y1; x2 -= gdk_painter->x1; y2 -= gdk_painter->y1; } else { cr = gdk_cairo_create (engine->window); } cairo_set_source_rgb (cr, 1, 1, 1); cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_move_to (cr, x1 + 0.5, y1 + 0.5); cairo_line_to (cr, x2 + 0.5, y2 - 0.5); cairo_set_line_width (cr, 1); cairo_stroke (cr); if (using_painter_cr) cairo_restore (cr); else cairo_destroy (cr); } }
static void set_color(cairo_t *cr, GdkRGBA color) { cairo_set_source_rgb(cr, color.red, color.green, color.blue); }
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); }
static void generate_reference (double ppi_x, double ppi_y, const char *filename) { cairo_surface_t *surface, *target; cairo_t *cr; cairo_status_t status; surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, SIZE*ppi_x/72, SIZE*ppi_y/72); cr = cairo_create (surface); cairo_surface_destroy (surface); /* As we wish to mimic a PDF surface, copy across the default font options * from the PDF backend. */ { cairo_surface_t *pdf; cairo_font_options_t *options; options = cairo_font_options_create (); #if CAIRO_HAS_PDF_SURFACE pdf = cairo_pdf_surface_create ("tmp.pdf", 1, 1); cairo_surface_get_font_options (pdf, options); cairo_surface_destroy (pdf); #endif cairo_set_font_options (cr, options); cairo_font_options_destroy (options); } #if SET_TOLERANCE cairo_set_tolerance (cr, 3.0); #endif cairo_save (cr); { cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); } cairo_restore (cr); cairo_scale (cr, ppi_x/72., ppi_y/72.); draw (cr, SIZE, SIZE); surface = cairo_surface_reference (cairo_get_target (cr)); cairo_destroy (cr); target = cairo_image_surface_create (CAIRO_FORMAT_RGB24, SIZE, SIZE); cr = cairo_create (target); cairo_scale (cr, 72./ppi_x, 72./ppi_y); cairo_set_source_surface (cr, surface, 0, 0); cairo_paint (cr); status = cairo_surface_write_to_png (cairo_get_target (cr), filename); cairo_destroy (cr); if (status) { fprintf (stderr, "Failed to generate reference image '%s': %s\n", filename, cairo_status_to_string (status)); exit (1); } }
void clear_surface(cairo_surface_t *cs){ cairo_t *c = cairo_create(cs); cairo_set_source_rgb(c,1.,1.,1.); cairo_paint(c); cairo_destroy(c); }
static void draw (cairo_t *cr, double width, double height) { const char *text = "cairo"; cairo_text_extents_t extents; const double dash[2] = { 8, 16 }; cairo_pattern_t *pattern; cairo_save (cr); cairo_new_path (cr); cairo_set_line_width (cr, .05 * SIZE / 2.0); cairo_arc (cr, SIZE / 2.0, SIZE / 2.0, 0.875 * SIZE / 2.0, 0, 2.0 * M_PI); cairo_stroke (cr); /* use dashes to demonstrate bugs: * https://bugs.freedesktop.org/show_bug.cgi?id=9189 * https://bugs.freedesktop.org/show_bug.cgi?id=17223 */ cairo_save (cr); cairo_set_dash (cr, dash, 2, 0); cairo_arc (cr, SIZE / 2.0, SIZE / 2.0, 0.75 * SIZE / 2.0, 0, 2.0 * M_PI); cairo_stroke (cr); cairo_restore (cr); cairo_save (cr); cairo_rectangle (cr, 0, 0, SIZE/2, SIZE); cairo_clip (cr); cairo_arc (cr, SIZE / 2.0, SIZE / 2.0, 0.6 * SIZE / 2.0, 0, 2.0 * M_PI); cairo_fill (cr); cairo_restore (cr); /* use a pattern to exercise bug: * https://bugs.launchpad.net/inkscape/+bug/234546 */ cairo_save (cr); cairo_rectangle (cr, SIZE/2, 0, SIZE/2, SIZE); cairo_clip (cr); pattern = cairo_pattern_create_linear (SIZE/2, 0, SIZE, 0); cairo_pattern_add_color_stop_rgba (pattern, 0, 0, 0, 0, 1.); cairo_pattern_add_color_stop_rgba (pattern, 1, 0, 0, 0, 0.); cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); cairo_arc (cr, SIZE / 2.0, SIZE / 2.0, 0.6 * SIZE / 2.0, 0, 2.0 * M_PI); cairo_fill (cr); cairo_restore (cr); cairo_set_source_rgb (cr, 1, 1, 1); /* white */ cairo_set_font_size (cr, .25 * SIZE / 2.0); cairo_text_extents (cr, text, &extents); cairo_move_to (cr, (SIZE-extents.width)/2.0-extents.x_bearing, (SIZE-extents.height)/2.0-extents.y_bearing); cairo_show_text (cr, text); cairo_restore (cr); }
/** * 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 void gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer, GtkWidget *widget, GimpTempBuf *temp_buf, gint temp_buf_x, gint temp_buf_y, gint channel, GimpViewBG inside_bg, GimpViewBG outside_bg, cairo_surface_t *surface, gint surface_width, gint surface_height) { cairo_t *cr; gint x, y; gint width, height; const Babl *temp_buf_format; gint temp_buf_width; gint temp_buf_height; g_return_if_fail (temp_buf != NULL); g_return_if_fail (surface != NULL); temp_buf_format = gimp_temp_buf_get_format (temp_buf); temp_buf_width = gimp_temp_buf_get_width (temp_buf); temp_buf_height = gimp_temp_buf_get_height (temp_buf); /* Here are the different cases this functions handles correctly: * 1) Offset temp_buf which does not necessarily cover full image area * 2) Color conversion of temp_buf if it is gray and image is color * 3) Background check buffer for transparent temp_bufs * 4) Using the optional "channel" argument, one channel can be extracted * from a multi-channel temp_buf and composited as a grayscale * Prereqs: * 1) Grayscale temp_bufs have bytes == {1, 2} * 2) Color temp_bufs have bytes == {3, 4} * 3) If image is gray, then temp_buf should have bytes == {1, 2} */ cr = cairo_create (surface); if (outside_bg == GIMP_VIEW_BG_CHECKS || inside_bg == GIMP_VIEW_BG_CHECKS) { if (! renderer->pattern) renderer->pattern = gimp_cairo_checkerboard_create (cr, GIMP_CHECK_SIZE_SM, gimp_render_light_check_color (), gimp_render_dark_check_color ()); } switch (outside_bg) { case GIMP_VIEW_BG_CHECKS: cairo_set_source (cr, renderer->pattern); break; case GIMP_VIEW_BG_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); break; } cairo_paint (cr); if (! gimp_rectangle_intersect (0, 0, surface_width, surface_height, temp_buf_x, temp_buf_y, temp_buf_width, temp_buf_height, &x, &y, &width, &height)) { cairo_destroy (cr); return; } if (inside_bg != outside_bg && babl_format_has_alpha (temp_buf_format) && channel == -1) { cairo_rectangle (cr, x, y, width, height); switch (inside_bg) { case GIMP_VIEW_BG_CHECKS: cairo_set_source (cr, renderer->pattern); break; case GIMP_VIEW_BG_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); break; } cairo_fill (cr); } if (babl_format_has_alpha (temp_buf_format) && channel == -1) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; cairo_surface_t *alpha_surface; alpha_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); src_buffer = gimp_temp_buf_create_buffer (temp_buf); dest_buffer = gimp_cairo_surface_create_buffer (alpha_surface); if (! renderer->profile_transform) gimp_view_renderer_transform_create (renderer, widget, src_buffer, dest_buffer); if (renderer->profile_transform) { gimp_gegl_convert_color_transform (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), renderer->profile_src_format, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0), renderer->profile_dest_format, renderer->profile_transform); } else { gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); } g_object_unref (src_buffer); g_object_unref (dest_buffer); cairo_surface_mark_dirty (alpha_surface); cairo_translate (cr, x, y); cairo_rectangle (cr, 0, 0, width, height); cairo_set_source_surface (cr, alpha_surface, 0, 0); cairo_fill (cr); cairo_surface_destroy (alpha_surface); } else if (channel == -1) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; cairo_surface_flush (surface); src_buffer = gimp_temp_buf_create_buffer (temp_buf); dest_buffer = gimp_cairo_surface_create_buffer (surface); if (! renderer->profile_transform) gimp_view_renderer_transform_create (renderer, widget, src_buffer, dest_buffer); if (renderer->profile_transform) { gimp_gegl_convert_color_transform (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), renderer->profile_src_format, dest_buffer, GEGL_RECTANGLE (x, y, 0, 0), renderer->profile_dest_format, renderer->profile_transform); } else { gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (x, y, 0, 0)); } g_object_unref (src_buffer); g_object_unref (dest_buffer); cairo_surface_mark_dirty (surface); } else { const Babl *fish; const guchar *src; guchar *dest; gint dest_stride; gint bytes; gint rowstride; gint i; cairo_surface_flush (surface); bytes = babl_format_get_bytes_per_pixel (temp_buf_format); rowstride = temp_buf_width * bytes; src = gimp_temp_buf_get_data (temp_buf) + ((y - temp_buf_y) * rowstride + (x - temp_buf_x) * bytes); dest = cairo_image_surface_get_data (surface); dest_stride = cairo_image_surface_get_stride (surface); dest += y * dest_stride + x * 4; fish = babl_fish (temp_buf_format, babl_format ("cairo-RGB24")); for (i = y; i < (y + height); i++) { const guchar *s = src; guchar *d = dest; gint j; for (j = x; j < (x + width); j++, d += 4, s += bytes) { if (bytes > 2) { guchar pixel[4] = { s[channel], s[channel], s[channel], 255 }; babl_process (fish, pixel, d, 1); } else { guchar pixel[2] = { s[channel], 255 }; babl_process (fish, pixel, d, 1); } } src += rowstride; dest += dest_stride; } cairo_surface_mark_dirty (surface); } cairo_destroy (cr); }
/** * ags_note_edit_draw_notation: * @note_edit: the #AgsNoteEdit * @cr: the #cairo_t surface * * Draw the #AgsNotation of selected #AgsMachine on @note_edit. * * Since: 0.4 */ void ags_note_edit_draw_notation(AgsNoteEdit *note_edit, cairo_t *cr) { AgsMachine *machine; AgsEditor *editor; GtkWidget *widget; AgsNote *note; GList *list_notation, *list_note; guint x_offset; guint control_height; guint x, y, width, height; gint selected_channel; gint i; editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit), AGS_TYPE_EDITOR); if(editor->selected_machine == NULL || (machine = editor->selected_machine) == NULL || machine->audio->notation == NULL) return; widget = (GtkWidget *) note_edit->drawing_area; cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); i = 0; while((selected_channel = ags_notebook_next_active_tab(editor->notebook, i)) != -1){ list_notation = g_list_nth(machine->audio->notation, selected_channel); list_note = AGS_NOTATION(list_notation->data)->notes; control_height = note_edit->control_height - 2 * note_edit->control_margin_y; x_offset = (guint) GTK_RANGE(note_edit->hscrollbar)->adjustment->value; /* draw controls smaller than note_edit->nth_x */ while(list_note != NULL && (note = (AgsNote *) list_note->data)->x[0] < note_edit->control_unit.nth_x){ if(note->x[1] >= note_edit->control_unit.nth_x){ if(note->y >= note_edit->nth_y && note->y <= note_edit->stop_y){ x = 0; y = (note->y - note_edit->nth_y) * note_edit->control_height + note_edit->y0 + note_edit->control_margin_y; width = (guint) ((double) note->x[1] * note_edit->control_unit.control_width - (double) x_offset); if(width > widget->allocation.width) width = widget->allocation.width; height = control_height; /* draw note */ cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_fill(cr); /* check if note is selected */ if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7); cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_stroke(cr); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); } }else if(note->y == (note_edit->nth_y - 1) && note_edit->y0 != 0){ if(note_edit->y0 > note_edit->control_margin_y){ x = 0; width = (guint) ((double) note->x[1] * (double) note_edit->control_unit.control_width - x_offset); if(width > widget->allocation.width) width = widget->allocation.width; if(note_edit->y0 > control_height + note_edit->control_margin_y){ y = note_edit->y0 - (control_height + note_edit->control_margin_y); height = control_height; }else{ y = 0; height = note_edit->y0 - note_edit->control_margin_y; } /* draw note */ cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_fill(cr); /* check if note is selected */ if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7); cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_stroke(cr); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); } } }else if(note->y == (note_edit->stop_y + 1) && note_edit->y1 != 0){ if(note_edit->y1 > note_edit->control_margin_y){ x = 0; width = note->x[1] * note_edit->control_unit.control_width - x_offset; if(width > widget->allocation.width) width = widget->allocation.width; y = (note->y - note_edit->nth_y) * note_edit->control_height + note_edit->control_margin_y; if(note_edit->y1 > control_height + note_edit->control_margin_y){ height = control_height; }else{ height = note_edit->y1 - note_edit->control_margin_y; } /* draw note */ cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_fill(cr); /* check if note is selected */ if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7); cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_stroke(cr); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); } } } } list_note = list_note->next; } /* draw controls equal or greater than note_edit->nth_x */ while(list_note != NULL && (note = (AgsNote *) list_note->data)->x[0] <= note_edit->control_unit.stop_x){ if(note->y >= note_edit->nth_y && note->y <= note_edit->stop_y){ x = (guint) note->x[0] * note_edit->control_unit.control_width; y = (note->y - note_edit->nth_y) * note_edit->control_height + note_edit->y0 + note_edit->control_margin_y; width = note->x[1] * note_edit->control_unit.control_width - x; x -= x_offset; if(x + width > widget->allocation.width) width = widget->allocation.width - x; height = control_height; /* draw note*/ cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_fill(cr); /* check if note is selected */ if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7); cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_stroke(cr); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); } }else if(note->y == (note_edit->nth_y - 1) && note_edit->y0 != 0){ if(note_edit->y0 > note_edit->control_margin_y){ x = note->x[0] * note_edit->control_unit.control_width - x_offset; width = note->x[1] * note_edit->control_unit.control_width - x_offset - x; if(x + width > widget->allocation.width) width = widget->allocation.width - x; if(note_edit->y0 > control_height + note_edit->control_margin_y){ y = note_edit->y0 - (control_height + note_edit->control_margin_y); height = control_height; }else{ y = 0; height = note_edit->y0 - note_edit->control_margin_y; } /* draw note */ cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_fill(cr); /* check if note is selected */ if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7); cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_stroke(cr); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); } } }else if(note->y == (note_edit->stop_y + 1) && note_edit->y1 != 0){ if(note_edit->y1 > note_edit->control_margin_y){ x = note->x[0] * note_edit->control_unit.control_width - x_offset; width = note->x[1] * note_edit->control_unit.control_width - x_offset - x; if(x + width > widget->allocation.width) width = widget->allocation.width - x; y = (note->y - note_edit->nth_y) * note_edit->control_height + note_edit->control_margin_y; if(note_edit->y1 > control_height + note_edit->control_margin_y){ height = control_height; }else{ height = note_edit->y1 - note_edit->control_margin_y; } /* draw note */ cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_fill(cr); /* check if note is selected */ if((AGS_NOTE_IS_SELECTED & (note->flags)) != 0){ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.7); cairo_rectangle(cr, (double) x, (double) y, (double) width, (double) height); cairo_stroke(cr); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); } } } list_note = list_note->next; } i++; } }
/* 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); }
void set_color_black(cairo_t *cr){ cairo_set_source_rgb (cr, 0, 0, 0); }