static gboolean dt_iop_zonesystem_preview_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self) { const int inset = DT_PIXEL_APPLY_DPI(2); GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; dt_iop_zonesystem_gui_data_t *g = (dt_iop_zonesystem_gui_data_t *)self->gui_data; dt_iop_zonesystem_params_t *p = (dt_iop_zonesystem_params_t *)self->params; cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); /* clear background */ GtkStyleContext *context = gtk_widget_get_style_context(self->expander); gtk_render_background(context, cr, 0, 0, allocation.width, allocation.height); width -= 2 * inset; height -= 2 * inset; cairo_translate(cr, inset, inset); dt_pthread_mutex_lock(&g->lock); if(g->in_preview_buffer && g->out_preview_buffer && self->enabled) { /* calculate the zonemap */ float zonemap[MAX_ZONE_SYSTEM_SIZE] = { -1 }; _iop_zonesystem_calculate_zonemap(p, zonemap); /* let's generate a pixbuf from pixel zone buffer */ guchar *image = g_malloc_n((size_t)4 * g->preview_width * g->preview_height, sizeof(guchar)); guchar *buffer = g->mouse_over_output_zones ? g->out_preview_buffer : g->in_preview_buffer; for(int k = 0; k < g->preview_width * g->preview_height; k++) { int zone = 255 * CLIP(((1.0 / (p->size - 1)) * buffer[k])); image[4 * k + 2] = (g->hilite_zone && buffer[k] == g->zone_under_mouse) ? 255 : zone; image[4 * k + 1] = (g->hilite_zone && buffer[k] == g->zone_under_mouse) ? 255 : zone; image[4 * k + 0] = (g->hilite_zone && buffer[k] == g->zone_under_mouse) ? 0 : zone; } dt_pthread_mutex_unlock(&g->lock); const int wd = g->preview_width, ht = g->preview_height; const float scale = fminf(width / (float)wd, height / (float)ht); const int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wd); cairo_surface_t *surface = cairo_image_surface_create_for_data(image, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width / 2.0, height / 2.0f); cairo_scale(cr, scale, scale); cairo_translate(cr, -.5f * wd, -.5f * ht); cairo_rectangle(cr, DT_PIXEL_APPLY_DPI(1), DT_PIXEL_APPLY_DPI(1), wd - DT_PIXEL_APPLY_DPI(2), ht - DT_PIXEL_APPLY_DPI(2)); cairo_set_source_surface(cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_GOOD); cairo_fill_preserve(cr); cairo_surface_destroy(surface); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.0)); cairo_set_source_rgb(cr, .1, .1, .1); cairo_stroke(cr); g_free(image); } else { dt_pthread_mutex_unlock(&g->lock); // draw a big, subdued dt logo if(g->image) { GdkRGBA *color; gtk_style_context_get(context, gtk_widget_get_state_flags(self->expander), "background-color", &color, NULL); cairo_set_source_surface(cr, g->image, (width - g->image_width) * 0.5, (height - g->image_height) * 0.5); cairo_rectangle(cr, 0, 0, width, height); cairo_set_operator(cr, CAIRO_OPERATOR_HSL_LUMINOSITY); cairo_fill_preserve(cr); cairo_set_operator(cr, CAIRO_OPERATOR_DARKEN); cairo_set_source_rgb(cr, color->red + 0.02, color->green + 0.02, color->blue + 0.02); cairo_fill_preserve(cr); cairo_set_operator(cr, CAIRO_OPERATOR_LIGHTEN); cairo_set_source_rgb(cr, color->red - 0.02, color->green - 0.02, color->blue - 0.02); cairo_fill(cr); gdk_rgba_free(color); } } cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }
static gboolean path_test_convert_to_cairo_path (CallbackData *data) { cairo_surface_t *surface; cairo_t *cr; cairo_path_t *cpath; guint i, j; ClutterKnot path_start = { 0, 0 }, last_point = { 0, 0 }; /* Create a temporary image surface and context to hold the cairo path */ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10); cr = cairo_create (surface); /* Convert to a cairo path */ clutter_path_to_cairo_path (data->path, cr); /* Get a copy of the cairo path data */ cpath = cairo_copy_path (cr); /* Convert back to a clutter path */ clutter_path_clear (data->path); clutter_path_add_cairo_path (data->path, cpath); /* The relative nodes will have been converted to absolute so we need to reflect this in the node array for comparison */ for (i = 0; i < data->n_nodes; i++) { switch (data->nodes[i].type) { case CLUTTER_PATH_MOVE_TO: path_start = last_point = data->nodes[i].points[0]; break; case CLUTTER_PATH_LINE_TO: last_point = data->nodes[i].points[0]; break; case CLUTTER_PATH_CURVE_TO: last_point = data->nodes[i].points[2]; break; case CLUTTER_PATH_REL_MOVE_TO: last_point.x += data->nodes[i].points[0].x; last_point.y += data->nodes[i].points[0].y; data->nodes[i].points[0] = last_point; data->nodes[i].type = CLUTTER_PATH_MOVE_TO; path_start = last_point; break; case CLUTTER_PATH_REL_LINE_TO: last_point.x += data->nodes[i].points[0].x; last_point.y += data->nodes[i].points[0].y; data->nodes[i].points[0] = last_point; data->nodes[i].type = CLUTTER_PATH_LINE_TO; break; case CLUTTER_PATH_REL_CURVE_TO: for (j = 0; j < 3; j++) { data->nodes[i].points[j].x += last_point.x; data->nodes[i].points[j].y += last_point.y; } last_point = data->nodes[i].points[2]; data->nodes[i].type = CLUTTER_PATH_CURVE_TO; break; case CLUTTER_PATH_CLOSE: last_point = path_start; /* Cairo always adds a move to after every close so we need to insert one here */ memmove (data->nodes + i + 2, data->nodes + i + 1, (data->n_nodes - i - 1) * sizeof (ClutterPathNode)); data->nodes[i + 1].type = CLUTTER_PATH_MOVE_TO; data->nodes[i + 1].points[0] = last_point; data->n_nodes++; break; } } /* Free the cairo resources */ cairo_path_destroy (cpath); cairo_destroy (cr); cairo_surface_destroy (surface); return TRUE; }
static void draw_sack_graph(struct sctp_udata *u_data) { GdkRGBA red_color = {1.0, 0.0, 0.0, 1.0}; GdkRGBA green_color = {0.0, 1.0, 0.0, 1.0}; gint diff; GPtrArray *array = NULL; guint32 i, size = 0, start=0, end; gboolean more = FALSE; gint width; cairo_t *cr; if (u_data->dir == 1) { array = u_data->assoc->sort_sack1; size=u_data->assoc->n_sack_chunks_ep1; if (u_data->io->tmp == FALSE) { min_tsn = 0; max_tsn = u_data->assoc->max_bytes1; } else { min_tsn = u_data->io->tmp_min_tsn1; max_tsn = u_data->io->tmp_max_tsn1; } } else if (u_data->dir == 2) { array = u_data->assoc->sort_sack2; size = u_data->assoc->n_sack_chunks_ep2; if (u_data->io->tmp == FALSE) { min_tsn = 0; max_tsn = u_data->assoc->max_bytes2; } else { min_tsn = u_data->io->tmp_min_tsn2; max_tsn = u_data->io->tmp_max_tsn2; } } width = u_data->io->max_x - u_data->io->min_x; for (i=0; i<size; i++) { if (u_data->io->uoff) diff = (gint)((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs - u_data->io->min_x; else diff = (gint)((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs * 1000000 + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->usecs - u_data->io->min_x; end = start + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->length; if (end>max_tsn) { end = max_tsn; more = TRUE; } if (start >= min_tsn && diff > 0 && diff <= width) { #if GTK_CHECK_VERSION(2,22,0) cr = cairo_create (u_data->io->surface); #else cr = gdk_cairo_create (u_data->io->pixmap); #endif gdk_cairo_set_source_rgba (cr, &red_color); cairo_set_line_width (cr, 1.0); cairo_move_to(cr, LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff+0.5, u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(start,min_tsn))*u_data->io->y_interval)+0.5); cairo_line_to(cr, LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff+0.5, u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)+0.5); cairo_stroke(cr); cairo_destroy(cr); if (more == TRUE) { #if GTK_CHECK_VERSION(2,22,0) cr = cairo_create (u_data->io->surface); #else cr = gdk_cairo_create (u_data->io->pixmap); #endif gdk_cairo_set_source_rgba (cr, &green_color); cairo_set_line_width (cr, 1.0); cairo_move_to(cr, LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff+0.5, u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)+0.5); cairo_line_to(cr, LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff, u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end+10,min_tsn))*u_data->io->y_interval)+0.5); cairo_stroke(cr); cairo_destroy(cr); more = FALSE; } } } }
static cairo_test_status_t cairo_test_for_target (cairo_test_context_t *ctx, const cairo_boilerplate_target_t *target, int dev_offset, cairo_bool_t similar) { cairo_test_status_t status; cairo_surface_t *surface = NULL; cairo_t *cr; const char *empty_str = ""; char *offset_str; char *base_name, *base_path; char *out_png_path; char *ref_path = NULL, *ref_png_path, *cmp_png_path = NULL; char *new_path = NULL, *new_png_path; char *xfail_path = NULL, *xfail_png_path; char *base_ref_png_path; char *base_new_png_path; char *base_xfail_png_path; char *diff_png_path; char *test_filename = NULL, *pass_filename = NULL, *fail_filename = NULL; cairo_test_status_t ret; cairo_content_t expected_content; cairo_font_options_t *font_options; const char *format; cairo_bool_t have_output = FALSE; cairo_bool_t have_result = FALSE; void *closure; double width, height; cairo_bool_t have_output_dir; #if HAVE_MEMFAULT int malloc_failure_iterations = ctx->malloc_failure; int last_fault_count = 0; #endif /* Get the strings ready that we'll need. */ format = cairo_boilerplate_content_name (target->content); if (dev_offset) xasprintf (&offset_str, ".%d", dev_offset); else offset_str = (char *) empty_str; xasprintf (&base_name, "%s.%s.%s%s%s", ctx->test_name, target->name, format, similar ? ".similar" : "", offset_str); if (offset_str != empty_str) free (offset_str); ref_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_REF_SUFFIX, CAIRO_TEST_PNG_EXTENSION); new_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_NEW_SUFFIX, CAIRO_TEST_PNG_EXTENSION); xfail_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_XFAIL_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_ref_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_REF_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_new_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_NEW_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_xfail_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_XFAIL_SUFFIX, CAIRO_TEST_PNG_EXTENSION); if (target->file_extension != NULL) { ref_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_REF_SUFFIX, target->file_extension); new_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_NEW_SUFFIX, target->file_extension); xfail_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_XFAIL_SUFFIX, target->file_extension); } have_output_dir = _cairo_test_mkdir (ctx->output); xasprintf (&base_path, "%s/%s", have_output_dir ? ctx->output : ".", base_name); xasprintf (&out_png_path, "%s" CAIRO_TEST_OUT_PNG, base_path); xasprintf (&diff_png_path, "%s" CAIRO_TEST_DIFF_PNG, base_path); if (ctx->test->requirements != NULL) { const char *required; required = target->is_vector ? "target=raster" : "target=vector"; if (strstr (ctx->test->requirements, required) != NULL) { cairo_test_log (ctx, "Error: Skipping for %s target %s\n", target->is_vector ? "vector" : "raster", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } required = target->is_recording ? "target=!recording" : "target=recording"; if (strstr (ctx->test->requirements, required) != NULL) { cairo_test_log (ctx, "Error: Skipping for %s target %s\n", target->is_recording ? "recording" : "non-recording", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } } width = ctx->test->width; height = ctx->test->height; if (width && height) { width += dev_offset; height += dev_offset; } #if HAVE_MEMFAULT REPEAT: MEMFAULT_CLEAR_FAULTS (); MEMFAULT_RESET_LEAKS (); ctx->last_fault_count = 0; last_fault_count = MEMFAULT_COUNT_FAULTS (); /* Pre-initialise fontconfig so that the configuration is loaded without * malloc failures (our primary goal is to test cairo fault tolerance). */ #if HAVE_FCINIT FcInit (); #endif MEMFAULT_ENABLE_FAULTS (); #endif have_output = FALSE; have_result = FALSE; /* Run the actual drawing code. */ ret = CAIRO_TEST_SUCCESS; surface = (target->create_surface) (base_path, target->content, width, height, ctx->test->width + 25 * NUM_DEVICE_OFFSETS, ctx->test->height + 25 * NUM_DEVICE_OFFSETS, CAIRO_BOILERPLATE_MODE_TEST, &closure); if (surface == NULL) { cairo_test_log (ctx, "Error: Failed to set %s target\n", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } #if HAVE_MEMFAULT if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY) { goto REPEAT; } #endif if (cairo_surface_status (surface)) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created an error surface: %s\n", cairo_status_to_string (cairo_surface_status (surface))); ret = CAIRO_TEST_FAILURE; goto UNWIND_STRINGS; } /* Check that we created a surface of the expected type. */ if (cairo_surface_get_type (surface) != target->expected_type) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created surface is of type %d (expected %d)\n", cairo_surface_get_type (surface), target->expected_type); ret = CAIRO_TEST_UNTESTED; goto UNWIND_SURFACE; } /* Check that we created a surface of the expected content, * (ignore the artificial CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value). */ expected_content = cairo_boilerplate_content (target->content); if (cairo_surface_get_content (surface) != expected_content) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created surface has content %d (expected %d)\n", cairo_surface_get_content (surface), expected_content); ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; } if (cairo_surface_set_user_data (surface, &cairo_boilerplate_output_basename_key, base_path, NULL)) { #if HAVE_MEMFAULT cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); goto REPEAT; #else ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; #endif } cairo_surface_set_device_offset (surface, dev_offset, dev_offset); cr = cairo_create (surface); if (cairo_set_user_data (cr, &_cairo_test_context_key, (void*) ctx, NULL)) { #if HAVE_MEMFAULT cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); goto REPEAT; #else ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; #endif } if (similar) cairo_push_group_with_content (cr, expected_content); /* Clear to transparent (or black) depending on whether the target * surface supports alpha. */ cairo_save (cr); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_restore (cr); /* Set all components of font_options to avoid backend differences * and reduce number of needed reference images. */ font_options = cairo_font_options_create (); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON); cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY); cairo_set_font_options (cr, font_options); cairo_font_options_destroy (font_options); cairo_save (cr); alarm (ctx->timeout); status = (ctx->test->draw) (cr, ctx->test->width, ctx->test->height); alarm (0); cairo_restore (cr); if (similar) { cairo_pop_group_to_source (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); } #if HAVE_MEMFAULT MEMFAULT_DISABLE_FAULTS (); /* repeat test after malloc failure injection */ if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && (status == CAIRO_TEST_NO_MEMORY || cairo_status (cr) == CAIRO_STATUS_NO_MEMORY || cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY)) { cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } goto REPEAT; } #endif /* Then, check all the different ways it could fail. */ if (status) { cairo_test_log (ctx, "Error: Function under test failed\n"); ret = status; goto UNWIND_CAIRO; } #if HAVE_MEMFAULT if (MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && MEMFAULT_HAS_FAULTS ()) { VALGRIND_PRINTF ("Unreported memfaults..."); MEMFAULT_PRINT_FAULTS (); } #endif if (target->finish_surface != NULL) { #if HAVE_MEMFAULT /* We need to re-enable faults as most recording-surface processing * is done during cairo_surface_finish(). */ MEMFAULT_CLEAR_FAULTS (); last_fault_count = MEMFAULT_COUNT_FAULTS (); MEMFAULT_ENABLE_FAULTS (); #endif /* also check for infinite loops whilst replaying */ alarm (ctx->timeout); status = target->finish_surface (surface); alarm (0); #if HAVE_MEMFAULT MEMFAULT_DISABLE_FAULTS (); if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && status == CAIRO_STATUS_NO_MEMORY) { cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } goto REPEAT; } #endif if (status) { cairo_test_log (ctx, "Error: Failed to finish surface: %s\n", cairo_status_to_string (status)); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } /* Skip image check for tests with no image (width,height == 0,0) */ if (ctx->test->width != 0 && ctx->test->height != 0) { cairo_surface_t *ref_image; cairo_surface_t *test_image; cairo_surface_t *diff_image; buffer_diff_result_t result; cairo_status_t diff_status; if (ref_png_path == NULL) { cairo_test_log (ctx, "Error: Cannot find reference image for %s\n", base_name); /* we may be running this test to generate reference images */ _xunlink (ctx, out_png_path); /* be more generous as we may need to use external renderers */ alarm (4 * ctx->timeout); test_image = target->get_image_surface (surface, 0, ctx->test->width, ctx->test->height); alarm (0); diff_status = cairo_surface_write_to_png (test_image, out_png_path); cairo_surface_destroy (test_image); if (diff_status) { if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS) ret = CAIRO_TEST_CRASHED; else ret = CAIRO_TEST_FAILURE; cairo_test_log (ctx, "Error: Failed to write output image: %s\n", cairo_status_to_string (diff_status)); } have_output = TRUE; ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (target->file_extension != NULL) { /* compare vector surfaces */ char *filenames[] = { ref_png_path, ref_path, new_png_path, new_path, xfail_png_path, xfail_path, base_ref_png_path, base_new_png_path, base_xfail_png_path, }; xasprintf (&test_filename, "%s.out%s", base_path, target->file_extension); xasprintf (&pass_filename, "%s.pass%s", base_path, target->file_extension); xasprintf (&fail_filename, "%s.fail%s", base_path, target->file_extension); if (cairo_test_file_is_older (pass_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, pass_filename); } if (cairo_test_file_is_older (fail_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, fail_filename); } if (cairo_test_files_equal (out_png_path, ref_path)) { cairo_test_log (ctx, "Vector surface matches reference.\n"); have_output = FALSE; ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_path)) { cairo_test_log (ctx, "Vector surface matches current failure.\n"); have_output = FALSE; ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_path)) { cairo_test_log (ctx, "Vector surface matches known failure.\n"); have_output = FALSE; ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, pass_filename)) { /* identical output as last known PASS */ cairo_test_log (ctx, "Vector surface matches last pass.\n"); have_output = TRUE; ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, fail_filename)) { /* identical output as last known FAIL, fail */ cairo_test_log (ctx, "Vector surface matches last fail.\n"); have_result = TRUE; /* presume these were kept around as well */ have_output = TRUE; ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } /* be more generous as we may need to use external renderers */ alarm (4 * ctx->timeout); test_image = target->get_image_surface (surface, 0, ctx->test->width, ctx->test->height); alarm (0); if (cairo_surface_status (test_image)) { cairo_test_log (ctx, "Error: Failed to extract image: %s\n", cairo_status_to_string (cairo_surface_status (test_image))); if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS) ret = CAIRO_TEST_CRASHED; else ret = CAIRO_TEST_FAILURE; cairo_surface_destroy (test_image); goto UNWIND_CAIRO; } _xunlink (ctx, out_png_path); diff_status = cairo_surface_write_to_png (test_image, out_png_path); if (diff_status) { cairo_test_log (ctx, "Error: Failed to write output image: %s\n", cairo_status_to_string (diff_status)); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } have_output = TRUE; /* binary compare png files (no decompression) */ if (target->file_extension == NULL) { char *filenames[] = { ref_png_path, new_png_path, xfail_png_path, base_ref_png_path, base_new_png_path, base_xfail_png_path, }; xasprintf (&test_filename, "%s", out_png_path); xasprintf (&pass_filename, "%s.pass.png", base_path); xasprintf (&fail_filename, "%s.fail.png", base_path); if (cairo_test_file_is_older (pass_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, pass_filename); } if (cairo_test_file_is_older (fail_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, fail_filename); } if (cairo_test_files_equal (test_filename, pass_filename)) { cairo_test_log (ctx, "PNG file exactly matches last pass.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, ref_png_path)) { cairo_test_log (ctx, "PNG file exactly matches reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_png_path)) { cairo_test_log (ctx, "PNG file exactly matches current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly matches known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, fail_filename)) { cairo_test_log (ctx, "PNG file exactly matches last fail.\n"); have_result = TRUE; /* presume these were kept around as well */ cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } else { if (cairo_test_files_equal (out_png_path, ref_png_path)) { cairo_test_log (ctx, "PNG file exactly matches reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_png_path)) { cairo_test_log (ctx, "PNG file exactly matches current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly matches known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } } if (cairo_test_files_equal (out_png_path, base_ref_png_path)) { cairo_test_log (ctx, "PNG file exactly reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, base_new_png_path)) { cairo_test_log (ctx, "PNG file exactly current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, base_xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } /* first compare against the ideal reference */ ref_image = cairo_test_get_reference_image (ctx, base_ref_png_path, target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED); if (cairo_surface_status (ref_image)) { cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n", base_ref_png_path, cairo_status_to_string (cairo_surface_status (ref_image))); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ctx->test->width, ctx->test->height); cmp_png_path = base_ref_png_path; diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); _xunlink (ctx, diff_png_path); if (diff_status || image_diff_is_failure (&result, target->error_tolerance)) { /* that failed, so check against the specific backend */ ref_image = cairo_test_get_reference_image (ctx, ref_png_path, target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED); if (cairo_surface_status (ref_image)) { cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n", ref_png_path, cairo_status_to_string (cairo_surface_status (ref_image))); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } cmp_png_path = ref_png_path; diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); if (diff_status) { cairo_test_log (ctx, "Error: Failed to compare images: %s\n", cairo_status_to_string (diff_status)); ret = CAIRO_TEST_FAILURE; } else if (image_diff_is_failure (&result, target->error_tolerance)) { ret = CAIRO_TEST_FAILURE; diff_status = cairo_surface_write_to_png (diff_image, diff_png_path); if (diff_status) { cairo_test_log (ctx, "Error: Failed to write differences image: %s\n", cairo_status_to_string (diff_status)); } else { have_result = TRUE; } cairo_test_copy_file (test_filename, fail_filename); } else { /* success */ cairo_test_copy_file (test_filename, pass_filename); } } else { /* success */ cairo_test_copy_file (test_filename, pass_filename); } /* If failed, compare against the current image output, * and attempt to detect systematic failures. */ if (ret == CAIRO_TEST_FAILURE) { char *image_out_path; image_out_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, "image", "image", format, CAIRO_TEST_OUT_SUFFIX, CAIRO_TEST_PNG_EXTENSION); if (image_out_path != NULL) { if (cairo_test_files_equal (out_png_path, image_out_path)) { ret = CAIRO_TEST_XFAILURE; } else { ref_image = cairo_image_surface_create_from_png (image_out_path); if (cairo_surface_status (ref_image) == CAIRO_STATUS_SUCCESS) { diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); if (diff_status == CAIRO_STATUS_SUCCESS && !image_diff_is_failure (&result, target->error_tolerance)) { ret = CAIRO_TEST_XFAILURE; } cairo_surface_destroy (ref_image); } } free (image_out_path); } } cairo_surface_destroy (test_image); cairo_surface_destroy (diff_image); } if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_test_log (ctx, "Error: Function under test left cairo status in an error state: %s\n", cairo_status_to_string (cairo_status (cr))); ret = CAIRO_TEST_ERROR; goto UNWIND_CAIRO; } UNWIND_CAIRO: free (test_filename); free (fail_filename); free (pass_filename); test_filename = fail_filename = pass_filename = NULL; #if HAVE_MEMFAULT if (ret == CAIRO_TEST_FAILURE) MEMFAULT_PRINT_FAULTS (); #endif cairo_destroy (cr); UNWIND_SURFACE: cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); #if HAVE_MEMFAULT cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { if (ret != CAIRO_TEST_FAILURE) MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } if (ret == CAIRO_TEST_SUCCESS && --malloc_failure_iterations > 0) goto REPEAT; #endif if (have_output) cairo_test_log (ctx, "OUTPUT: %s\n", out_png_path); if (have_result) { if (cmp_png_path == NULL) { /* XXX presume we matched the normal ref last time */ cmp_png_path = ref_png_path; } cairo_test_log (ctx, "REFERENCE: %s\nDIFFERENCE: %s\n", cmp_png_path, diff_png_path); } UNWIND_STRINGS: free (out_png_path); free (ref_png_path); free (base_ref_png_path); free (ref_path); free (new_png_path); free (base_new_png_path); free (new_path); free (xfail_png_path); free (base_xfail_png_path); free (xfail_path); free (diff_png_path); free (base_path); free (base_name); return ret; }
static gboolean _lib_navigation_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { const int inset = DT_NAVIGATION_INSET; int width = widget->allocation.width, height = widget->allocation.height; dt_develop_t *dev = darktable.develop; if (dev->preview_dirty) return FALSE; /* get the current style */ GtkStyle *style=gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL,"GtkWidget", GTK_TYPE_WIDGET); if(!style) style = gtk_rc_get_style(widget); cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); /* fill background */ cairo_set_source_rgb(cr, style->bg[0].red/65535.0, style->bg[0].green/65535.0, style->bg[0].blue/65535.0); cairo_paint(cr); width -= 2*inset; height -= 2*inset; cairo_translate(cr, inset, inset); /* draw navigation image if available */ if(dev->preview_pipe->backbuf && !dev->preview_dirty) { dt_pthread_mutex_t *mutex = &dev->preview_pipe->backbuf_mutex; dt_pthread_mutex_lock(mutex); const int wd = dev->preview_pipe->backbuf_width; const int ht = dev->preview_pipe->backbuf_height; const float scale = fminf(width/(float)wd, height/(float)ht); const int stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, wd); cairo_surface_t *surface = cairo_image_surface_create_for_data (dev->preview_pipe->backbuf, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width/2.0, height/2.0f); cairo_scale(cr, scale, scale); cairo_translate(cr, -.5f*wd, -.5f*ht); // draw shadow around float alpha = 1.0f; for(int k=0; k<4; k++) { cairo_rectangle(cr, -k/scale, -k/scale, wd + 2*k/scale, ht + 2*k/scale); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } cairo_rectangle(cr, 0, 0, wd-2, ht-1); cairo_set_source_surface (cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST); cairo_fill(cr); cairo_surface_destroy (surface); dt_pthread_mutex_unlock(mutex); // draw box where we are dt_dev_zoom_t zoom; int closeup; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); const float min_scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, closeup ? 2.0 : 1.0, 0); const float cur_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0); // avoid numerical instability for small resolutions: if(cur_scale > min_scale+0.001) { float boxw = 1, boxh = 1; dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, &boxw, &boxh); cairo_translate(cr, wd*(.5f+zoom_x), ht*(.5f+zoom_y)); cairo_set_source_rgb(cr, 0., 0., 0.); cairo_set_line_width(cr, 1.f/scale); boxw *= wd; boxh *= ht; cairo_rectangle(cr, -boxw/2-1, -boxh/2-1, boxw+2, boxh+2); cairo_stroke(cr); cairo_set_source_rgb(cr, 1., 1., 1.); cairo_rectangle(cr, -boxw/2, -boxh/2, boxw, boxh); cairo_stroke(cr); } } /* blit memsurface into widget */ cairo_destroy(cr); cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget)); cairo_set_source_surface (cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return TRUE; }
int main(int argc, char **argv) { cairo_surface_t *surface; cairo_t *context; int x, y, i, width, height, depth, screen, pressed_key, png; double r, b, v; QTnode *tree; bool rendering; struct XWin **xwin; /* Get the arguments */ if(argc != 3) { printf("Usage: nbody rendering resultsdir\n"); exit(1); } if(*argv[1] == '0') { rendering = false; } else { rendering = true; } char buf[strlen(argv[2]) + 10]; /* Set window size */ width = 1024; height = 1024; depth = 32; tree = init_tree(10, NULL); for (i = 0; i < 100000; i++) { tree->insert(phys_gen_particle()); if (i % 10000 == 0) printf("%d\n", i); } /* Create the drawing surface */ if(rendering) { /* Create the X11 window */ xwin = (struct XWin **)calloc(sizeof(struct XWin *), 1); xwindow_init(width, height, depth, xwin); surface = cairo_xlib_surface_create((*xwin)->dsp, (*xwin)->win, DefaultVisual((*xwin)->dsp, screen), width, height); cairo_xlib_surface_set_size(surface, width, height); } else { surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); } context = cairo_create(surface); cairo_scale(context, width, height); png = 0; while(1) { if(rendering) { if((*xwin)->should_close) { break; } /* Wait on the input (also sync up to disable flickering) */ if(input_ready(xwin)) { pressed_key = get_key(xwin); } } /* Clear the surface with black */ cairo_set_source_rgb(context, 0.0, 0.0, 0.0); cairo_paint(context); std::queue <QTnode *> nodes; QTnode *t; nodes.push(tree); while (!nodes.empty()) { t = nodes.front(); nodes.pop(); if (!t->children.empty()) { for (i = 0; i < t->children.size(); i++) { nodes.push(t->children[i]); } } else { for (std::list <Particle>::iterator p = t->particles.begin(); p != t->particles.end(); p++) { v = f2_norm((*p).vel); if(v >= 0.4) { r = 1.0; b = 0.0; } else if(v < 0.5) { b = 1.0; r = 0.0; } cairo_set_source_rgba(context, (double)r, 0.0, (double)b, 1.0); cairo_rectangle(context, (*p).pos.x, (*p).pos.y, 2e-3, 2e-3); cairo_fill(context); cairo_set_source_rgba(context, (double)r, 0.0, (double)b, 0.2); cairo_rectangle(context, (*p).pos.x - 1e-3, (*p).pos.y - 1e-3, 4e-3, 4e-3); cairo_fill(context); } } } if(rendering) { /* Flush the X window */ flush_input(xwin); update_screen(xwin); } else { mkdir(argv[2], S_IRWXU | S_IRWXG); sprintf(buf, "%s/%05d.png", argv[2], png++); printf("Making %s\n", buf); cairo_surface_write_to_png (surface, buf); } /* Get the new particles */ timing( tree->calc_global_accel(); tree->move_shit(); ); }
wxRegion::wxRegion( size_t n, const wxPoint *points, wxPolygonFillMode fillStyle ) { #ifdef __WXGTK3__ // Make a cairo path from the points, draw it onto an image surface, use // gdk_cairo_region_create_from_surface() to get a cairo region // need at least 3 points to make a useful polygon if (n < 3) return; // get bounding rect int min_x = points[0].x; int max_x = min_x; int min_y = points[0].y; int max_y = min_y; size_t i; for (i = 1; i < n; i++) { const int x = points[i].x; if (min_x > x) min_x = x; else if (max_x < x) max_x = x; const int y = points[i].y; if (min_y > y) min_y = y; else if (max_y < y) max_y = y; } const int w = max_x - min_x + 1; const int h = max_y - min_y + 1; // make surface just big enough to contain polygon (A1 is native format // for gdk_cairo_region_create_from_surface) cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_A1, w, h); memset(cairo_image_surface_get_data(surface), 0, cairo_image_surface_get_stride(surface) * h); cairo_surface_mark_dirty(surface); cairo_surface_set_device_offset(surface, -min_x, -min_y); cairo_t* cr = cairo_create(surface); cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); if (fillStyle == wxODDEVEN_RULE) cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); // make path cairo_move_to(cr, points[0].x, points[0].y); for (i = 1; i < n; i++) cairo_line_to(cr, points[i].x, points[i].y); cairo_close_path(cr); cairo_fill(cr); cairo_destroy(cr); cairo_surface_flush(surface); m_refData = new wxRegionRefData; M_REGIONDATA->m_region = gdk_cairo_region_create_from_surface(surface); cairo_surface_destroy(surface); #else GdkPoint *gdkpoints = new GdkPoint[n]; for ( size_t i = 0 ; i < n ; i++ ) { gdkpoints[i].x = points[i].x; gdkpoints[i].y = points[i].y; } m_refData = new wxRegionRefData(); GdkRegion* reg = gdk_region_polygon ( gdkpoints, n, fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE : GDK_EVEN_ODD_RULE ); M_REGIONDATA->m_region = reg; delete [] gdkpoints; #endif }
void draw_shadow (cairo_t* cr, gdouble width, gdouble height, gint shadow_radius, gint corner_radius) { cairo_surface_t* tmp_surface = NULL; cairo_surface_t* new_surface = NULL; cairo_pattern_t* pattern = NULL; cairo_t* cr_surf = NULL; cairo_matrix_t matrix; raico_blur_t* blur = NULL; tmp_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 4 * shadow_radius, 4 * shadow_radius); if (cairo_surface_status (tmp_surface) != CAIRO_STATUS_SUCCESS) return; cr_surf = cairo_create (tmp_surface); if (cairo_status (cr_surf) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (tmp_surface); return; } cairo_scale (cr_surf, 1.0f, 1.0f); cairo_set_operator (cr_surf, CAIRO_OPERATOR_CLEAR); cairo_paint (cr_surf); cairo_set_operator (cr_surf, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (cr_surf, 0.0f, 0.0f, 0.0f, 0.75f); cairo_arc (cr_surf, 2 * shadow_radius, 2 * shadow_radius, 2.0f * corner_radius, 0.0f, 360.0f * (G_PI / 180.f)); cairo_fill (cr_surf); cairo_destroy (cr_surf); // create and setup blur blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW); raico_blur_set_radius (blur, shadow_radius); // now blur it raico_blur_apply (blur, tmp_surface); // blur no longer needed raico_blur_destroy (blur); new_surface = cairo_image_surface_create_for_data ( cairo_image_surface_get_data (tmp_surface), cairo_image_surface_get_format (tmp_surface), cairo_image_surface_get_width (tmp_surface) / 2, cairo_image_surface_get_height (tmp_surface) / 2, cairo_image_surface_get_stride (tmp_surface)); pattern = cairo_pattern_create_for_surface (new_surface); if (cairo_pattern_status (pattern) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (tmp_surface); cairo_surface_destroy (new_surface); return; } // top left cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); cairo_set_source (cr, pattern); cairo_rectangle (cr, 0.0f, 0.0f, width - 2 * shadow_radius, 2 * shadow_radius); cairo_fill (cr); // bottom left cairo_matrix_init_scale (&matrix, 1.0f, -1.0f); cairo_matrix_translate (&matrix, 0.0f, -height); cairo_pattern_set_matrix (pattern, &matrix); cairo_rectangle (cr, 0.0f, 2 * shadow_radius, 2 * shadow_radius, height - 2 * shadow_radius); cairo_fill (cr); // top right cairo_matrix_init_scale (&matrix, -1.0f, 1.0f); cairo_matrix_translate (&matrix, -width, 0.0f); cairo_pattern_set_matrix (pattern, &matrix); cairo_rectangle (cr, width - 2 * shadow_radius, 0.0f, 2 * shadow_radius, height - 2 * shadow_radius); cairo_fill (cr); // bottom right cairo_matrix_init_scale (&matrix, -1.0f, -1.0f); cairo_matrix_translate (&matrix, -width, -height); cairo_pattern_set_matrix (pattern, &matrix); cairo_rectangle (cr, 2 * shadow_radius, height - 2 * shadow_radius, width - 2 * shadow_radius, 2 * shadow_radius); cairo_fill (cr); // clean up cairo_pattern_destroy (pattern); cairo_surface_destroy (tmp_surface); cairo_surface_destroy (new_surface); }
void setup_tile (gint w, gint h) { cairo_status_t status; cairo_t* cr = NULL; cairo_surface_t* cr_surf = NULL; cairo_surface_t* tmp = NULL; cairo_surface_t* dummy_surf = NULL; cairo_surface_t* norm_surf = NULL; cairo_surface_t* blur_surf = NULL; gdouble width = (gdouble) w; gdouble height = (gdouble) h; raico_blur_t* blur = NULL; cr_surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 3 * BUBBLE_SHADOW_SIZE, 3 * BUBBLE_SHADOW_SIZE); status = cairo_surface_status (cr_surf); if (status != CAIRO_STATUS_SUCCESS) g_print ("Error: \"%s\"\n", cairo_status_to_string (status)); cr = cairo_create (cr_surf); status = cairo_status (cr); if (status != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (cr_surf); g_print ("Error: \"%s\"\n", cairo_status_to_string (status)); } // clear and render drop-shadow and bubble-background cairo_scale (cr, 1.0f, 1.0f); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); if (g_composited) { draw_shadow (cr, width, height, BUBBLE_SHADOW_SIZE, CORNER_RADIUS); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); draw_round_rect (cr, 1.0f, (gdouble) BUBBLE_SHADOW_SIZE, (gdouble) BUBBLE_SHADOW_SIZE, (gdouble) CORNER_RADIUS, (gdouble) (width - 2.0f * BUBBLE_SHADOW_SIZE), (gdouble) (height - 2.0f* BUBBLE_SHADOW_SIZE)); cairo_fill (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (cr, BUBBLE_BG_COLOR_R, BUBBLE_BG_COLOR_G, BUBBLE_BG_COLOR_B, 0.95f); } else cairo_set_source_rgb (cr, BUBBLE_BG_COLOR_R, BUBBLE_BG_COLOR_G, BUBBLE_BG_COLOR_B); draw_round_rect (cr, 1.0f, BUBBLE_SHADOW_SIZE, BUBBLE_SHADOW_SIZE, CORNER_RADIUS, (gdouble) (width - 2.0f * BUBBLE_SHADOW_SIZE), (gdouble) (height - 2.0f * BUBBLE_SHADOW_SIZE)); cairo_fill (cr); tmp = cairo_image_surface_create_for_data ( cairo_image_surface_get_data (cr_surf), cairo_image_surface_get_format (cr_surf), 3 * BUBBLE_SHADOW_SIZE, 3 * BUBBLE_SHADOW_SIZE, cairo_image_surface_get_stride (cr_surf)); dummy_surf = copy_surface (tmp); cairo_surface_destroy (tmp); tmp = cairo_image_surface_create_for_data ( cairo_image_surface_get_data (dummy_surf), cairo_image_surface_get_format (dummy_surf), 2 * BUBBLE_SHADOW_SIZE, 2 * BUBBLE_SHADOW_SIZE, cairo_image_surface_get_stride (dummy_surf)); norm_surf = copy_surface (tmp); cairo_surface_destroy (tmp); blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW); raico_blur_set_radius (blur, 6); raico_blur_apply (blur, dummy_surf); raico_blur_destroy (blur); tmp = cairo_image_surface_create_for_data ( cairo_image_surface_get_data (dummy_surf), cairo_image_surface_get_format (dummy_surf), 2 * BUBBLE_SHADOW_SIZE, 2 * BUBBLE_SHADOW_SIZE, cairo_image_surface_get_stride (dummy_surf)); blur_surf = copy_surface (tmp); cairo_surface_destroy (tmp); cairo_surface_destroy (dummy_surf); g_tile = tile_new_for_padding (norm_surf, blur_surf); cairo_surface_destroy (norm_surf); cairo_surface_destroy (blur_surf); cairo_surface_destroy (cr_surf); cairo_destroy (cr); }
/* estimate_textsize: * Estimate width of text, for given face and size, in points. * Value is stored textline->width. * NOTE: Tables are based on a font of size 1. Need to multiply by * fontsize to get appropriate value. */ static void estimate_textsize(textline_t * textline, char *fontname, double fontsz, char **fontpath) { double *Fontwidth; char c, *p; textline->width = 0.0; textline->xshow = NULL; #if !defined(DISABLE_CODEGENS) && !defined(HAVE_GD_FREETYPE) && !defined(ONLY_PLAIN_GEN) //maks if (Output_codegen == &GD_CodeGen) { int cwidth; double fsize = (fontsz * _dpi) / POINTS_PER_INCH; /* in pixels */ *fontpath = "[internal gd]"; cwidth = builtinFontWd(fsize); if ((p = textline->str)) { textline->width = strlen(p) * cwidth * POINTS_PER_INCH / _dpi; } return; } else if (!strncasecmp(fontname, "cour", 4)) { #else if (!strncasecmp(fontname, "cour", 4)) { #endif *fontpath = "[internal courier]"; Fontwidth = courFontWidth; } else if (!strncasecmp(fontname, "arial", 5) || !strncasecmp(fontname, "helvetica", 9)) { *fontpath = "[internal arial]"; Fontwidth = arialFontWidth; } else { *fontpath = "[internal times]"; Fontwidth = timesFontWidth; } if ((p = textline->str)) { while ((c = *p++)) textline->width += Fontwidth[(unsigned char) c]; textline->width *= fontsz; } } #endif double textwidth(textline_t * textline, char *fontname, double fontsize) { char *fontpath = NULL; int freeFontpath = 0; #ifdef CAIRO_HAS_FT_FONT cairo_t *cr; cairo_text_extents_t extents; cr = cairo_create(); cairo_select_font(cr, fontname, 0, 0); cairo_scale_font(cr, fontsize); cairo_text_extents(cr, textline->str, &extents); cairo_destroy(cr); textline->width = extents.width; textline->xshow = NULL; fontpath = "[cairo]"; #else if (gd_textsize(textline, fontname, fontsize, &fontpath)) estimate_textsize(textline, fontname, fontsize, &fontpath); else freeFontpath = 1; /* libgd mallocs space for fontpath */ #endif if (Verbose) { if (emit_once(fontname)) { fprintf(stderr, "%s: fontname=%s fontpath=%s\n", CmdName, fontname, fontpath); } } if (freeFontpath) free (fontpath); return textline->width; }
TemporaryRef<Path> ScaledFontBase::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) { #ifdef USE_SKIA if (aTarget->GetType() == BACKEND_SKIA) { SkPaint paint; paint.setTypeface(GetSkTypeface()); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); paint.setTextSize(SkFloatToScalar(mSize)); std::vector<uint16_t> indices; std::vector<SkPoint> offsets; indices.resize(aBuffer.mNumGlyphs); offsets.resize(aBuffer.mNumGlyphs); for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) { indices[i] = aBuffer.mGlyphs[i].mIndex; offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x); offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y); } SkPath path; paint.getPosTextPath(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), &path); return new PathSkia(path, FILL_WINDING); } #endif #ifdef USE_CAIRO if (aTarget->GetType() == BACKEND_CAIRO) { MOZ_ASSERT(mScaledFont); DrawTarget *dt = const_cast<DrawTarget*>(aTarget); cairo_t *ctx = static_cast<cairo_t*>(dt->GetNativeSurface(NATIVE_SURFACE_CAIRO_CONTEXT)); bool isNewContext = !ctx; if (!ctx) { ctx = cairo_create(DrawTargetCairo::GetDummySurface()); cairo_matrix_t mat; GfxMatrixToCairoMatrix(aTarget->GetTransform(), mat); cairo_set_matrix(ctx, &mat); } cairo_set_scaled_font(ctx, mScaledFont); // Convert our GlyphBuffer into an array of Cairo glyphs. std::vector<cairo_glyph_t> glyphs(aBuffer.mNumGlyphs); for (uint32_t i = 0; i < aBuffer.mNumGlyphs; ++i) { glyphs[i].index = aBuffer.mGlyphs[i].mIndex; glyphs[i].x = aBuffer.mGlyphs[i].mPosition.x; glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y; } cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs); RefPtr<PathCairo> newPath = new PathCairo(ctx); if (isNewContext) { cairo_destroy(ctx); } return newPath; } #endif return nullptr; }
static void gnc_header_draw_offscreen (GncHeader *header) { SheetBlockStyle *style = header->style; Table *table = header->sheet->table; VirtualLocation virt_loc; VirtualCell *vcell; guint32 color_type; GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(header)); GdkRGBA color; int row_offset; CellBlock *cb; int i; cairo_t *cr; virt_loc.vcell_loc.virt_row = 0; virt_loc.vcell_loc.virt_col = 0; virt_loc.phys_row_offset = 0; virt_loc.phys_col_offset = 0; gtk_style_context_save (stylectxt); // Get the background color type and apply the css class color_type = gnc_table_get_bg_color (table, virt_loc, NULL); gnucash_get_style_classes (header->sheet, stylectxt, color_type); if (header->surface) cairo_surface_destroy (header->surface); header->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, header->width, header->height); cr = cairo_create (header->surface); // Fill background color of header gtk_render_background (stylectxt, cr, 0, 0, header->width, header->height); gdk_rgba_parse (&color, "black"); cairo_set_source_rgb (cr, color.red, color.green, color.blue); cairo_rectangle (cr, 0.5, 0.5, header->width - 1.0, header->height - 1.0); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); // Draw bottom horizontal line, makes bottom line thicker cairo_move_to (cr, 0.5, header->height - 1.5); cairo_line_to (cr, header->width - 1.0, header->height - 1.5); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); /*font = gnucash_register_font;*/ vcell = gnc_table_get_virtual_cell (table, table->current_cursor_loc.vcell_loc); cb = vcell ? vcell->cellblock : NULL; row_offset = 0; for (i = 0; i < style->nrows; i++) { int col_offset = 0; int h = 0, j; virt_loc.phys_row_offset = i; /* TODO: This routine is duplicated in several places. Can we abstract at least the cell drawing routine? That way we'll be sure everything is drawn consistently, and cut down on maintenance issues. */ for (j = 0; j < style->ncols; j++) { CellDimensions *cd; double text_x, text_y, text_w, text_h; BasicCell *cell; const char *text; int w; PangoLayout *layout; virt_loc.phys_col_offset = j; cd = gnucash_style_get_cell_dimensions (style, i, j); h = cd->pixel_height; if (header->in_resize && (j == header->resize_col)) w = header->resize_col_width; else w = cd->pixel_width; cell = gnc_cellblock_get_cell (cb, i, j); if (!cell || !cell->cell_name) { col_offset += w; continue; } cairo_rectangle (cr, col_offset - 0.5, row_offset + 0.5, w, h); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); virt_loc.vcell_loc = table->current_cursor_loc.vcell_loc; text = gnc_table_get_label (table, virt_loc); if (!text) text = ""; layout = gtk_widget_create_pango_layout (GTK_WIDGET (header->sheet), text); switch (gnc_table_get_align (table, virt_loc)) { default: case CELL_ALIGN_LEFT: pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; case CELL_ALIGN_RIGHT: pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; case CELL_ALIGN_CENTER: pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; } text_x = col_offset + CELL_HPADDING; text_y = row_offset + 1; text_w = MAX (0, w - (2 * CELL_HPADDING)); text_h = h - 2; cairo_save (cr); cairo_rectangle (cr, text_x, text_y, text_w, text_h); cairo_clip (cr); gtk_render_layout (stylectxt, cr, text_x, text_y, layout); cairo_restore (cr); g_object_unref (layout); col_offset += w; } row_offset += h; } gtk_style_context_restore (stylectxt); cairo_destroy (cr); }
static GstFlowReturn gst_rsvg_overlay_transform_ip (GstBaseTransform * btrans, GstBuffer * buf) { GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (btrans); cairo_surface_t *surface; cairo_t *cr; double applied_x_offset = (double) overlay->x_offset; double applied_y_offset = (double) overlay->y_offset; int applied_width = overlay->width; int applied_height = overlay->height; GST_RSVG_LOCK (overlay); if (!overlay->handle) { GST_RSVG_UNLOCK (overlay); return GST_FLOW_OK; } surface = cairo_image_surface_create_for_data (GST_BUFFER_DATA (buf), CAIRO_FORMAT_ARGB32, overlay->caps_width, overlay->caps_height, overlay->caps_width * 4); if (G_UNLIKELY (!surface)) return GST_FLOW_ERROR; cr = cairo_create (surface); if (G_UNLIKELY (!cr)) { cairo_surface_destroy (surface); return GST_FLOW_ERROR; } /* Compute relative dimensions if absolute dimensions are not set */ if (!applied_x_offset && overlay->x_relative) { applied_x_offset = overlay->x_relative * overlay->caps_width; } if (!applied_y_offset && overlay->y_relative) { applied_y_offset = overlay->y_relative * overlay->caps_height; } if (!applied_width && overlay->width_relative) { applied_width = (int) (overlay->width_relative * overlay->caps_width); } if (!applied_height && overlay->height_relative) { applied_height = (int) (overlay->height_relative * overlay->caps_height); } if (applied_x_offset || applied_y_offset) { cairo_translate (cr, applied_x_offset, applied_y_offset); } /* Scale when necessary, i.e. an absolute or relative dimension has been specified. */ if ((applied_width || applied_height) && overlay->svg_width && overlay->svg_height) { /* If may happen that only one of the dimension is specified. Use the original SVG size for the other dimension. */ if (!applied_width) applied_width = overlay->svg_width; if (!applied_height) applied_height = overlay->svg_height; cairo_scale (cr, (double) applied_width / overlay->svg_width, (double) applied_height / overlay->svg_height); } rsvg_handle_render_cairo (overlay->handle, cr); GST_RSVG_UNLOCK (overlay); cairo_destroy (cr); cairo_surface_destroy (surface); return GST_FLOW_OK; }
int main (int argc, char *argv[]) { cairo_surface_t *surface = //Sets the Cairo surface context cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 421, 615); //Creates Cairo image surface, sets image resolution. cairo_t *cr = //Declare *cr as a Cairo context. cairo_create (surface); //Sets the Cairo context as a pointer, *cr. /* Declaration of first triangle pointer */ cairo_surface_t *one; /* Declaration of second triangle pointer */ cairo_surface_t *two; /* Declaration of third triangle pointer */ cairo_surface_t *three; /* Declaration of fourth triangle pointer */ cairo_surface_t *four; /* Declaration of fifth triangle pointer */ cairo_surface_t *five; /* Declaration of sixth triangle pointer */ cairo_surface_t *six; /* Declaration of seventh triangle pointer */ cairo_surface_t *seven; /* Declaration of text triangle pointer */ cairo_surface_t *text; /* Assigns the image of first triangle to the declared pointer */ cairo_push_group (cr); //Push the image to a surface one = cairo_image_surface_create_from_png ("../images/triangle1-color.png"); //Assign generated image to the pointer declared above cairo_pop_group_to_source (cr); //Pop it to the image you see /* Assigns the image of second triangle to the declared pointer */ cairo_push_group (cr); //Push the image to a surface two = cairo_image_surface_create_from_png ("../images/triangle2-color.png"); //Assign generated image to the pointer declared above cairo_pop_group_to_source (cr); //Pop it to the image you see /* Assigns the image of third triangle to the declared pointer */ cairo_push_group (cr); //Push the image to a surface three = cairo_image_surface_create_from_png ("../images/triangle3-color.png"); //Assign generated image to the pointer declared above cairo_pop_group_to_source (cr); //Pop it to the image you see /* Assigns the image of fourth triangle to the declared pointer */ cairo_push_group (cr); //Push the image to a surface four = cairo_image_surface_create_from_png ("../images/triangle4-color.png"); //Assign generated image to the pointer declared above cairo_pop_group_to_source (cr); //Pop it to the image you see /* Assigns the image of fifth triangle to the declared pointer */ cairo_push_group (cr); //Push the image to a surface five = cairo_image_surface_create_from_png ("../images/triangle5-color.png"); //Assign generated image to the pointer declared above cairo_pop_group_to_source (cr); //Pop it to the image you see /* Assigns the image of sixth triangle to the declared pointer */ cairo_push_group (cr); //Push the image to a surface six = cairo_image_surface_create_from_png ("../images/triangle6-color.png"); //Assign generated image to the pointer declared above cairo_pop_group_to_source (cr); //Pop it to the image you see /* Assigns the image of seventh triangle to the declared pointer */ cairo_push_group (cr); //Push the image to a surface seven = cairo_image_surface_create_from_png ("../images/triangle7-color.png"); //Assign generated image to the pointer declared above cairo_pop_group_to_source (cr); //Pop it to the image you see /* Assigns the image of the generated logo's text to the declared pointer */ cairo_push_group (cr); //Push the image to a surface text = cairo_image_surface_create_from_png ("../images/text.png"); //Assign generated image to the pointer declared above cairo_pop_group_to_source (cr); //Pop it to the image you see /* Assign pointer to source */ cairo_set_source_surface (cr, one, 0, 0); //Makes sure the pointers appear all together and make the image using their assigned file cairo_paint (cr); //Transfers these images to the final output that you see, it paints the image that you see when compiled/outpuuted /* Assign pointer to source */ cairo_set_source_surface (cr, two, 0, 0); //Makes sure the pointers appear all together and make the image using their assigned file cairo_paint (cr); //Transfers these images to the final output that you see, it paints the image that you see when compiled/outpuuted /* Assign pointer to source */ cairo_set_source_surface (cr, three, 0, 0); //Makes sure the pointers appear all together and make the image using their assigned file cairo_paint (cr); //Transfers these images to the final output that you see, it paints the image that you see when compiled/outpuuted /* Assign pointer to source */ cairo_set_source_surface (cr, four, 0, 0); //Makes sure the pointers appear all together and make the image using their assigned file cairo_paint (cr); //Transfers these images to the final output that you see, it paints the image that you see when compiled/outpuuted /* Assign pointer to source */ cairo_set_source_surface (cr, five, 0, 0); //Makes sure the pointers appear all together and make the image using their assigned file cairo_paint (cr); //Transfers these images to the final output that you see, it paints the image that you see when compiled/outpuuted /* Assign pointer to source */ cairo_set_source_surface (cr, six, 0, 0); //Makes sure the pointers appear all together and make the image using their assigned file cairo_paint (cr); //Transfers these images to the final output that you see, it paints the image that you see when compiled/outpuuted /* Assign pointer to source */ cairo_set_source_surface (cr, seven, 0, 0); //Makes sure the pointers appear all together and make the image using their assigned file cairo_paint (cr); //Transfers these images to the final output that you see, it paints the image that you see when compiled/outpuuted /* Assign pointer to source */ cairo_set_source_surface (cr, text, 0, 0); //Makes sure the pointers appear all together and make the image using their assigned file cairo_paint (cr); //Transfers these images to the final output that you see, it paints the image that you see when compiled/outpuuted /* Destroy the first triangle surface to free up memory and/or lag */ cairo_surface_destroy (one); /* Destroy the second triangle surface to free up memory and/or lag */ cairo_surface_destroy (two); /* Destroy the third triangle surface to free up memory and/or lag */ cairo_surface_destroy (three); /* Destroy the fourth triangle surface to free up memory and/or lag */ cairo_surface_destroy (four); /* Destroy the first triangle surface to free up memory and/or lag */ cairo_surface_destroy (five); /* Destroy the first triangle surface to free up memory and/or lag */ cairo_surface_destroy (six); /* Destroy the first triangle surface to free up memory and/or lag */ cairo_surface_destroy (seven); /* Destroy the first triangle surface to free up memory and/or lag */ cairo_surface_destroy (text); /* Write output and clean up */ cairo_surface_write_to_png (surface, "../images/crstfn-color-text.png"); //Name the resulting image as crstfn-color-text.png cairo_destroy (cr); //Destroy the context pointer, frees up memory and/or lag cairo_surface_destroy (surface); //Destroy the surface pointer, frees up memory and/or lag return 0; //No numbers needed!! }
/* * render functions */ static void begin_render(DiaRenderer *self, const Rectangle *update) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); real onedu = 0.0; real lmargin = 0.0, tmargin = 0.0; gboolean paginated = renderer->surface && /* only with our own pagination, not GtkPrint */ cairo_surface_get_type (renderer->surface) == CAIRO_SURFACE_TYPE_PDF && !renderer->skip_show_page; if (renderer->surface && !renderer->cr) renderer->cr = cairo_create (renderer->surface); else g_assert (renderer->cr); /* remember current state, so we can start from new with every page */ cairo_save (renderer->cr); if (paginated && renderer->dia) { DiagramData *data = renderer->dia; /* Dia's paper.width already contains the scale, cairo needs it without * Similar for margins, Dia's without, but cairo wants them? */ real width = (data->paper.lmargin + data->paper.width * data->paper.scaling + data->paper.rmargin) * (72.0 / 2.54) + 0.5; real height = (data->paper.tmargin + data->paper.height * data->paper.scaling + data->paper.bmargin) * (72.0 / 2.54) + 0.5; /* "Changes the size of a PDF surface for the current (and * subsequent) pages." Pagination setup? */ cairo_pdf_surface_set_size (renderer->surface, width, height); lmargin = data->paper.lmargin / data->paper.scaling; tmargin = data->paper.tmargin / data->paper.scaling; } cairo_scale (renderer->cr, renderer->scale, renderer->scale); /* to ensure no clipping at top/left we need some extra gymnastics, * otherwise a box with a line witdh one one pixel might loose the * top/left border as in bug #147386 */ ensure_minimum_one_device_unit (renderer, &onedu); if (update && paginated) { cairo_rectangle (renderer->cr, lmargin, tmargin, update->right - update->left, update->bottom - update->top); cairo_clip (renderer->cr); cairo_translate (renderer->cr, -update->left + lmargin, -update->top + tmargin); } else cairo_translate (renderer->cr, -renderer->dia->extents.left + onedu, -renderer->dia->extents.top + onedu); /* no more blurred UML diagrams */ cairo_set_antialias (renderer->cr, CAIRO_ANTIALIAS_NONE); /* clear background */ if (renderer->with_alpha) { cairo_set_operator (renderer->cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 0.0); } else { cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } cairo_paint (renderer->cr); if (renderer->with_alpha) { /* restore to default drawing */ cairo_set_operator (renderer->cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } #ifdef HAVE_PANGOCAIRO_H if (!renderer->layout) renderer->layout = pango_cairo_create_layout (renderer->cr); #endif cairo_set_fill_rule (renderer->cr, CAIRO_FILL_RULE_EVEN_ODD); #if 0 /* try to work around bug #341481 - no luck */ { cairo_font_options_t *fo = cairo_font_options_create (); cairo_get_font_options (renderer->cr, fo); /* try to switch off kerning */ cairo_font_options_set_hint_style (fo, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (fo, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (renderer->cr, fo); cairo_font_options_destroy (fo); #ifdef HAVE_PANGOCAIRO_H pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout)); pango_layout_context_changed (renderer->layout); #endif } #endif DIAG_STATE(renderer->cr) }
/** * _st_create_shadow_cairo_pattern: * @shadow_spec: the definition of the shadow * @src_pattern: surface pattern for which we create the shadow * (must be a surface pattern) * * This is a utility function for creating shadows used by * st-theme-node.c; it's in this file to share the gaussian * blur implementation. The usage of this function is quite different * depending on whether shadow_spec->inset is %TRUE or not. If * shadow_spec->inset is %TRUE, the caller should pass in a @src_pattern * which is the <i>inverse</i> of what they want shadowed, and must take * care of the spread and offset from the shadow spec themselves. If * shadow_spec->inset is %FALSE then the caller should pass in what they * want shadowed directly, and this function takes care of the spread and * the offset. */ cairo_pattern_t * _st_create_shadow_cairo_pattern (StShadow *shadow_spec, cairo_pattern_t *src_pattern) { static cairo_user_data_key_t shadow_pattern_user_data; cairo_t *cr; cairo_surface_t *src_surface; cairo_surface_t *surface_in; cairo_surface_t *surface_out; cairo_pattern_t *dst_pattern; guchar *pixels_in, *pixels_out; gint width_in, height_in, rowstride_in; gint width_out, height_out, rowstride_out; cairo_matrix_t shadow_matrix; int i, j; g_return_val_if_fail (shadow_spec != NULL, NULL); g_return_val_if_fail (src_pattern != NULL, NULL); if (cairo_pattern_get_surface (src_pattern, &src_surface) != CAIRO_STATUS_SUCCESS) /* The most likely reason we can't get the pattern is that sizing went hairwire * and the caller tried to create a surface too big for memory, leaving us with * a pattern in an error state; we return a transparent pattern for the shadow. */ return cairo_pattern_create_rgba(1.0, 1.0, 1.0, 0.0); width_in = cairo_image_surface_get_width (src_surface); height_in = cairo_image_surface_get_height (src_surface); /* We want the output to be a color agnostic alpha mask, * so we need to strip the color channels from the input */ if (cairo_image_surface_get_format (src_surface) != CAIRO_FORMAT_A8) { surface_in = cairo_image_surface_create (CAIRO_FORMAT_A8, width_in, height_in); cr = cairo_create (surface_in); cairo_set_source_surface (cr, src_surface, 0, 0); cairo_paint (cr); cairo_destroy (cr); } else { surface_in = cairo_surface_reference (src_surface); } pixels_in = cairo_image_surface_get_data (surface_in); rowstride_in = cairo_image_surface_get_stride (surface_in); pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in, shadow_spec->blur, &width_out, &height_out, &rowstride_out); cairo_surface_destroy (surface_in); /* Invert pixels for inset shadows */ if (shadow_spec->inset) { for (j = 0; j < height_out; j++) { guchar *p = pixels_out + rowstride_out * j; for (i = 0; i < width_out; i++, p++) *p = ~*p; } } surface_out = cairo_image_surface_create_for_data (pixels_out, CAIRO_FORMAT_A8, width_out, height_out, rowstride_out); cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data, pixels_out, (cairo_destroy_func_t) g_free); dst_pattern = cairo_pattern_create_for_surface (surface_out); cairo_surface_destroy (surface_out); cairo_pattern_get_matrix (src_pattern, &shadow_matrix); if (shadow_spec->inset) { /* For inset shadows, offsets and spread radius have already been * applied to the original pattern, so all left to do is shift the * blurred image left, so that it aligns centered under the * unblurred one */ cairo_matrix_translate (&shadow_matrix, (width_out - width_in) / 2.0, (height_out - height_in) / 2.0); cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); return dst_pattern; } /* Read all the code from the cairo_pattern_set_matrix call * at the end of this function to here from bottom to top, * because each new affine transformation is applied in * front of all the previous ones */ /* 6. Invert the matrix back */ cairo_matrix_invert (&shadow_matrix); /* 5. Adjust based on specified offsets */ cairo_matrix_translate (&shadow_matrix, shadow_spec->xoffset, shadow_spec->yoffset); /* 4. Recenter the newly scaled image */ cairo_matrix_translate (&shadow_matrix, - shadow_spec->spread, - shadow_spec->spread); /* 3. Scale up the blurred image to fill the spread */ cairo_matrix_scale (&shadow_matrix, (width_in + 2.0 * shadow_spec->spread) / width_in, (height_in + 2.0 * shadow_spec->spread) / height_in); /* 2. Shift the blurred image left, so that it aligns centered * under the unblurred one */ cairo_matrix_translate (&shadow_matrix, - (width_out - width_in) / 2.0, - (height_out - height_in) / 2.0); /* 1. Invert the matrix so we can work with it in pattern space */ cairo_matrix_invert (&shadow_matrix); cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); return dst_pattern; }
static gboolean dt_iop_basecurve_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; dt_iop_basecurve_gui_data_t *c = (dt_iop_basecurve_gui_data_t *)self->gui_data; dt_iop_basecurve_params_t *p = (dt_iop_basecurve_params_t *)self->params; int nodes = p->basecurve_nodes[0]; dt_iop_basecurve_node_t *basecurve = p->basecurve[0]; if(c->minmax_curve_type != p->basecurve_type[0] || c->minmax_curve_nodes != p->basecurve_nodes[0]) { dt_draw_curve_destroy(c->minmax_curve); c->minmax_curve = dt_draw_curve_new(0.0, 1.0, p->basecurve_type[0]); c->minmax_curve_nodes = p->basecurve_nodes[0]; c->minmax_curve_type = p->basecurve_type[0]; for(int k=0; k<p->basecurve_nodes[0]; k++) (void)dt_draw_curve_add_point(c->minmax_curve, p->basecurve[0][k].x, p->basecurve[0][k].y); } else { for(int k=0; k<p->basecurve_nodes[0]; k++) dt_draw_curve_set_point(c->minmax_curve, k, p->basecurve[0][k].x, p->basecurve[0][k].y); } dt_draw_curve_t *minmax_curve = c->minmax_curve; dt_draw_curve_calc_values(minmax_curve, 0.0, 1.0, DT_IOP_TONECURVE_RES, c->draw_xs, c->draw_ys); const float xm = basecurve[nodes-1].x; const float x[4] = {0.7f*xm, 0.8f*xm, 0.9f*xm, 1.0f*xm}; const float y[4] = {c->draw_ys[CLAMP((int)(x[0]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)], c->draw_ys[CLAMP((int)(x[1]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)], c->draw_ys[CLAMP((int)(x[2]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)], c->draw_ys[CLAMP((int)(x[3]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)] }; float unbounded_coeffs[3]; dt_iop_estimate_exp(x, y, 4, unbounded_coeffs); const int inset = DT_GUI_CURVE_EDITOR_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); // clear bg cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); cairo_translate(cr, inset, inset); width -= 2*inset; height -= 2*inset; #if 0 // draw shadow around float alpha = 1.0f; for(int k=0; k<inset; k++) { cairo_rectangle(cr, -k, -k, width + 2*k, height + 2*k); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } #else cairo_set_line_width(cr, 1.0); cairo_set_source_rgb (cr, .1, .1, .1); cairo_rectangle(cr, 0, 0, width, height); cairo_stroke(cr); #endif cairo_set_source_rgb (cr, .3, .3, .3); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); cairo_translate(cr, 0, height); cairo_scale(cr, 1.0f, -1.0f); // draw grid cairo_set_line_width(cr, .4); cairo_set_source_rgb (cr, .1, .1, .1); if(c->loglogscale) dt_draw_loglog_grid(cr, 4, 0, 0, width, height, c->loglogscale); else dt_draw_grid(cr, 4, 0, 0, width, height); // draw nodes positions cairo_set_line_width(cr, 1.); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); for(int k=0; k<nodes; k++) { const float x = to_log(basecurve[k].x, c->loglogscale), y = to_log(basecurve[k].y, c->loglogscale); cairo_arc(cr, x*width, y*height, 3, 0, 2.*M_PI); cairo_stroke(cr); } // draw selected cursor cairo_set_line_width(cr, 1.); if(c->selected >= 0) { cairo_set_source_rgb(cr, .9, .9, .9); const float x = to_log(basecurve[c->selected].x, c->loglogscale), y = to_log(basecurve[c->selected].y, c->loglogscale); cairo_arc(cr, x*width, y*height, 4, 0, 2.*M_PI); cairo_stroke(cr); } // draw curve cairo_set_line_width(cr, 2.); cairo_set_source_rgb(cr, .9, .9, .9); // cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_move_to(cr, 0, height*to_log(c->draw_ys[0], c->loglogscale)); for(int k=1; k<DT_IOP_TONECURVE_RES; k++) { const float xx = k/(DT_IOP_TONECURVE_RES-1.0); if(xx > xm) { const float yy = dt_iop_eval_exp(unbounded_coeffs, xx); const float x = to_log(xx, c->loglogscale), y = to_log(yy, c->loglogscale); cairo_line_to(cr, x*width, height*y); } else { const float yy = c->draw_ys[k]; const float x = to_log(xx, c->loglogscale), y = to_log(yy, c->loglogscale); cairo_line_to(cr, x*width, height*y); } } cairo_stroke(cr); cairo_destroy(cr); cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget)); cairo_set_source_surface (cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return TRUE; }
static Eina_Bool _ewk_view_single_smart_repaints_process(Ewk_View_Smart_Data *sd) { Ewk_View_Paint_Context *ctxt; Evas_Coord ow, oh; void *pixels; Eina_Rectangle r = {0, 0, 0, 0}; const Eina_Rectangle *pr; const Eina_Rectangle *pr_end; Eina_Tiler *tiler; Eina_Iterator *itr; cairo_status_t status; cairo_surface_t *surface; cairo_format_t format; cairo_t *cairo; size_t count; Eina_Bool ret = EINA_TRUE; if (sd->animated_zoom.zoom.current < 0.00001) { Evas_Object *clip = evas_object_clip_get(sd->backing_store); Evas_Coord w, h, cw, ch; // reset effects of zoom_weak_set() evas_object_image_fill_set (sd->backing_store, 0, 0, sd->view.w, sd->view.h); evas_object_move(clip, sd->view.x, sd->view.y); w = sd->view.w; h = sd->view.h; ewk_frame_contents_size_get(sd->main_frame, &cw, &ch); if (w > cw) w = cw; if (h > ch) h = ch; evas_object_resize(clip, w, h); } pixels = evas_object_image_data_get(sd->backing_store, 1); evas_object_image_size_get(sd->backing_store, &ow, &oh); if (sd->bg_color.a < 255) format = CAIRO_FORMAT_ARGB32; else format = CAIRO_FORMAT_RGB24; surface = cairo_image_surface_create_for_data ((unsigned char*)pixels, format, ow, oh, ow * 4); status = cairo_surface_status(surface); if (status != CAIRO_STATUS_SUCCESS) { ERR("could not create surface from data %dx%d: %s", ow, oh, cairo_status_to_string(status)); ret = EINA_FALSE; goto error_cairo_surface; } cairo = cairo_create(surface); status = cairo_status(cairo); if (status != CAIRO_STATUS_SUCCESS) { ERR("could not create cairo from surface %dx%d: %s", ow, oh, cairo_status_to_string(status)); ret = EINA_FALSE; goto error_cairo; } ctxt = ewk_view_paint_context_new(sd->_priv, cairo); if (!ctxt) { ERR("could not create paint context"); ret = EINA_FALSE; goto error_paint_context; } tiler = eina_tiler_new(ow, oh); if (!tiler) { ERR("could not create tiler %dx%d", ow, oh); ret = EINA_FALSE; goto error_tiler; } pr = ewk_view_repaints_get(sd->_priv, &count); pr_end = pr + count; for (; pr < pr_end; pr++) eina_tiler_rect_add(tiler, pr); itr = eina_tiler_iterator_new(tiler); if (!itr) { ERR("could not get iterator for tiler"); ret = EINA_FALSE; goto error_iterator; } int sx, sy; ewk_frame_scroll_pos_get(sd->main_frame, &sx, &sy); EINA_ITERATOR_FOREACH(itr, r) { Eina_Rectangle scrolled_rect = { r.x + sx, r.y + sy, r.w, r.h }; ewk_view_paint_context_save(ctxt); if ((sx) || (sy)) ewk_view_paint_context_translate(ctxt, -sx, -sy); ewk_view_paint_context_clip(ctxt, &scrolled_rect); ewk_view_paint_context_paint_contents(ctxt, &scrolled_rect); ewk_view_paint_context_restore(ctxt); evas_object_image_data_update_add (sd->backing_store, r.x, r.y, r.w, r.h); }
/* * Draws global image with fill color onto a pixmap with the given * resolution and returns it. * */ xcb_pixmap_t draw_image(uint32_t *resolution) { xcb_pixmap_t bg_pixmap = XCB_NONE; int button_diameter_physical = ceil(scaling_factor() * BUTTON_DIAMETER); DEBUG("scaling_factor is %.f, physical diameter is %d px\n", scaling_factor(), button_diameter_physical); if (!vistype) vistype = get_root_visual_type(screen); bg_pixmap = create_bg_pixmap(conn, screen, resolution, color); /* Initialize cairo: Create one in-memory surface to render the unlock * indicator on, create one XCB surface to actually draw (one or more, * depending on the amount of screens) unlock indicators on. */ cairo_surface_t *output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, button_diameter_physical, button_diameter_physical); cairo_t *ctx = cairo_create(output); cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]); cairo_t *xcb_ctx = cairo_create(xcb_output); if (img) { if (!tile) { cairo_set_source_surface(xcb_ctx, img, 0, 0); cairo_paint(xcb_ctx); } else { /* create a pattern and fill a rectangle as big as the screen */ cairo_pattern_t *pattern; pattern = cairo_pattern_create_for_surface(img); cairo_set_source(xcb_ctx, pattern); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); cairo_pattern_destroy(pattern); } } else { char strgroups[3][3] = {{color[0], color[1], '\0'}, {color[2], color[3], '\0'}, {color[4], color[5], '\0'} }; uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)), (strtol(strgroups[1], NULL, 16)), (strtol(strgroups[2], NULL, 16)) }; cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); } if (unlock_indicator) { cairo_scale(ctx, scaling_factor(), scaling_factor()); /* Draw a (centered) circle with transparent background. */ cairo_set_line_width(ctx, 3.0); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, 0 /* start */, 2 * M_PI /* end */); /* Use the appropriate color for the different PAM states * (currently verifying, wrong password, or default) * Basic function so we don't have to use this code * repeatedly for objects of the same color */ void get_color(void) { switch (pam_state) { case STATE_PAM_VERIFY: cairo_set_source_rgba(ctx, 68.0/255, 80.0/255, 41.0/255, 0.8); break; case STATE_PAM_WRONG: cairo_set_source_rgba(ctx, 143.0/255, 53.0/255, 53.0/255, 0.8); break; case STATE_PAM_IDLE: if (unlock_state == STATE_BACKSPACE_ACTIVE) { cairo_set_source_rgba(ctx, 143.0/255, 53.0/255, 53.0/255, 0.8); } else { cairo_set_source_rgba(ctx, 1, 1, 1, 0.8); } break; } } /* Circle fill */ switch (pam_state) { case STATE_PAM_VERIFY: cairo_set_source_rgba(ctx, 144.0/255, 169.0/255, 89.0/255, 0.2); break; case STATE_PAM_WRONG: cairo_set_source_rgba(ctx, 172.0/255, 65.0/255, 66.0/255, 0.2); break; default: cairo_set_source_rgba(ctx, 0, 0, 0, 0); break; } cairo_fill_preserve(ctx); /* Circle border */ get_color(); cairo_stroke(ctx); /* Display (centered) Time */ char *timetext = malloc(6); time_t curtime = time(NULL); struct tm *tm = localtime(&curtime); strftime(timetext, 100, TIME_FORMAT, tm); /* Color text, same as border */ get_color(); cairo_set_font_size(ctx, 32.0); cairo_text_extents_t time_extents; double time_x, time_y; cairo_text_extents(ctx, timetext, &time_extents); time_x = BUTTON_CENTER - ((time_extents.width / 2) + time_extents.x_bearing); time_y = BUTTON_CENTER - ((time_extents.height / 2) + time_extents.y_bearing); cairo_move_to(ctx, time_x, time_y); cairo_show_text(ctx, timetext); cairo_close_path(ctx); free(timetext); /* After the user pressed any valid key or the backspace key, we * highlight a random part of the unlock indicator to confirm this * keypress. */ if (unlock_state == STATE_KEY_ACTIVE || unlock_state == STATE_BACKSPACE_ACTIVE) { cairo_set_line_width(ctx, 4); cairo_new_sub_path(ctx); double highlight_start = (rand() % (int)(2 * M_PI * 100)) / 100.0; cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start, highlight_start + (M_PI / 2.5)); cairo_set_operator(ctx,CAIRO_OPERATOR_CLEAR); /* Set newly drawn lines to erase what they're drawn over*/ cairo_stroke(ctx); /* Draw two little separators for the highlighted part of the * unlock indicator. */ cairo_set_operator(ctx,CAIRO_OPERATOR_OVER); /* back to normal operator */ cairo_set_line_width(ctx, 10); /* Change color of separators based on backspace/active keypress */ get_color(); /* separator 1 */ cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start /* start */, highlight_start + (M_PI / 128.0) /* end */); cairo_stroke(ctx); /* separator 2 */ cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start + (M_PI / 2.5) /* start */, (highlight_start + (M_PI / 2.5)) + (M_PI / 128.0) /* end */); cairo_stroke(ctx); } } if (xr_screens > 0) { /* Composite the unlock indicator in the middle of each screen. */ for (int screen = 0; screen < xr_screens; screen++) { int x = (xr_resolutions[screen].x + ((xr_resolutions[screen].width / 2) - (button_diameter_physical / 2))); int y = (xr_resolutions[screen].y + ((xr_resolutions[screen].height / 2) - (button_diameter_physical / 2))); cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); } } else { /* We have no information about the screen sizes/positions, so we just * place the unlock indicator in the middle of the X root window and * hope for the best. */ int x = (last_resolution[0] / 2) - (button_diameter_physical / 2); int y = (last_resolution[1] / 2) - (button_diameter_physical / 2); cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); } cairo_surface_destroy(xcb_output); cairo_surface_destroy(output); cairo_destroy(ctx); cairo_destroy(xcb_ctx); return bg_pixmap; }
static gboolean calf_tube_expose (GtkWidget *widget, GdkEventExpose *event) { g_assert(CALF_IS_TUBE(widget)); CalfTube *self = CALF_TUBE(widget); GdkWindow *window = widget->window; GtkStyle *style = gtk_widget_get_style(widget); cairo_t *c = gdk_cairo_create(GDK_DRAWABLE(window)); int ox = 4, oy = 4, inner = 1, pad; int sx = widget->allocation.width - (ox * 2), sy = widget->allocation.height - (oy * 2); if( self->cache_surface == NULL ) { // looks like its either first call or the widget has been resized. // create the cache_surface. cairo_surface_t *window_surface = cairo_get_target( c ); self->cache_surface = cairo_surface_create_similar( window_surface, CAIRO_CONTENT_COLOR, widget->allocation.width, widget->allocation.height ); // And render the meterstuff again. cairo_t *cache_cr = cairo_create( self->cache_surface ); // theme background for reduced width and round borders // if(widget->style->bg_pixmap[0] == NULL) { gdk_cairo_set_source_color(cache_cr,&style->bg[GTK_STATE_NORMAL]); // } else { // gdk_cairo_set_source_pixbuf(cache_cr, GDK_PIXBUF(widget->style->bg_pixmap[0]), widget->allocation.x, widget->allocation.y + 20); // } cairo_paint(cache_cr); // outer (black) pad = 0; cairo_rectangle(cache_cr, pad, pad, sx + ox * 2 - pad * 2, sy + oy * 2 - pad * 2); cairo_set_source_rgb(cache_cr, 0, 0, 0); cairo_fill(cache_cr); // inner (bevel) pad = 1; cairo_rectangle(cache_cr, pad, pad, sx + ox * 2 - pad * 2, sy + oy * 2 - pad * 2); cairo_pattern_t *pat2 = cairo_pattern_create_linear (0, 0, 0, sy + oy * 2 - pad * 2); cairo_pattern_add_color_stop_rgba (pat2, 0, 0.23, 0.23, 0.23, 1); cairo_pattern_add_color_stop_rgba (pat2, 0.5, 0, 0, 0, 1); cairo_set_source (cache_cr, pat2); cairo_fill(cache_cr); cairo_pattern_destroy(pat2); cairo_rectangle(cache_cr, ox, oy, sx, sy); cairo_set_source_rgb (cache_cr, 0, 0, 0); cairo_fill(cache_cr); cairo_surface_t *image; switch(self->direction) { case 1: // vertical switch(self->size) { default: case 1: image = cairo_image_surface_create_from_png (PKGLIBDIR "tubeV1.png"); break; case 2: image = cairo_image_surface_create_from_png (PKGLIBDIR "tubeV2.png"); break; } break; default: case 2: // horizontal switch(self->size) { default: case 1: image = cairo_image_surface_create_from_png (PKGLIBDIR "tubeH1.png"); break; case 2: image = cairo_image_surface_create_from_png (PKGLIBDIR "tubeH2.png"); break; } break; } cairo_set_source_surface (cache_cr, image, widget->allocation.width / 2 - sx / 2 + inner, widget->allocation.height / 2 - sy / 2 + inner); cairo_paint (cache_cr); cairo_surface_destroy (image); cairo_destroy( cache_cr ); } cairo_set_source_surface( c, self->cache_surface, 0,0 ); cairo_paint( c ); // get microseconds timeval tv; gettimeofday(&tv, 0); long time = tv.tv_sec * 1000 * 1000 + tv.tv_usec; // limit to 1.f float value_orig = self->value > 1.f ? 1.f : self->value; value_orig = value_orig < 0.f ? 0.f : value_orig; float value = 0.f; float s = ((float)(time - self->last_falltime) / 1000000.0); float m = self->last_falloff * s * 2.5; self->last_falloff -= m; // new max value? if(value_orig > self->last_falloff) { self->last_falloff = value_orig; } value = self->last_falloff; self->last_falltime = time; self->falling = self->last_falloff > 0.000001; cairo_pattern_t *pat; // draw upper light switch(self->direction) { case 1: // vertical cairo_arc(c, ox + sx * 0.5, oy + sy * 0.2, sx, 0, 2 * M_PI); pat = cairo_pattern_create_radial (ox + sx * 0.5, oy + sy * 0.2, 3, ox + sx * 0.5, oy + sy * 0.2, sx); break; default: case 2: // horizontal cairo_arc(c, ox + sx * 0.8, oy + sy * 0.5, sy, 0, 2 * M_PI); pat = cairo_pattern_create_radial (ox + sx * 0.8, oy + sy * 0.5, 3, ox + sx * 0.8, oy + sy * 0.5, sy); break; } cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, value); cairo_pattern_add_color_stop_rgba (pat, 0.3, 1, 0.8, 0.3, value * 0.4); cairo_pattern_add_color_stop_rgba (pat, 0.31, 0.9, 0.5, 0.1, value * 0.5); cairo_pattern_add_color_stop_rgba (pat, 1, 0.0, 0.2, 0.7, 0); cairo_set_source (c, pat); cairo_fill(c); // draw lower light switch(self->direction) { case 1: // vertical cairo_arc(c, ox + sx * 0.5, oy + sy * 0.75, sx / 2, 0, 2 * M_PI); pat = cairo_pattern_create_radial (ox + sx * 0.5, oy + sy * 0.75, 2, ox + sx * 0.5, oy + sy * 0.75, sx / 2); break; default: case 2: // horizontal cairo_arc(c, ox + sx * 0.25, oy + sy * 0.5, sy / 2, 0, 2 * M_PI); pat = cairo_pattern_create_radial (ox + sx * 0.25, oy + sy * 0.5, 2, ox + sx * 0.25, oy + sy * 0.5, sy / 2); break; } cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, value); cairo_pattern_add_color_stop_rgba (pat, 0.3, 1, 0.8, 0.3, value * 0.4); cairo_pattern_add_color_stop_rgba (pat, 0.31, 0.9, 0.5, 0.1, value * 0.5); cairo_pattern_add_color_stop_rgba (pat, 1, 0.0, 0.2, 0.7, 0); cairo_set_source (c, pat); cairo_fill(c); cairo_destroy(c); return TRUE; }
cairo_test_similar_t cairo_test_target_has_similar (const cairo_test_context_t *ctx, const cairo_boilerplate_target_t *target) { cairo_surface_t *surface; cairo_test_similar_t has_similar; cairo_t * cr; cairo_surface_t *similar; cairo_status_t status; void *closure; char *path; /* ignore image intermediate targets */ if (target->expected_type == CAIRO_SURFACE_TYPE_IMAGE) return DIRECT; if (getenv ("CAIRO_TEST_IGNORE_SIMILAR")) return DIRECT; xasprintf (&path, "%s/%s", _cairo_test_mkdir (ctx->output) ? ctx->output : ".", ctx->test_name); has_similar = DIRECT; do { do { surface = (target->create_surface) (path, target->content, ctx->test->width, ctx->test->height, ctx->test->width + 25 * NUM_DEVICE_OFFSETS, ctx->test->height + 25 * NUM_DEVICE_OFFSETS, CAIRO_BOILERPLATE_MODE_TEST, &closure); if (surface == NULL) goto out; } while (cairo_test_malloc_failure (ctx, cairo_surface_status (surface))); if (cairo_surface_status (surface)) goto out; cr = cairo_create (surface); cairo_push_group_with_content (cr, cairo_boilerplate_content (target->content)); similar = cairo_get_group_target (cr); status = cairo_surface_status (similar); if (cairo_surface_get_type (similar) == cairo_surface_get_type (surface)) has_similar = SIMILAR; else has_similar = DIRECT; cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); } while (! has_similar && cairo_test_malloc_failure (ctx, status)); out: free (path); return has_similar; }
static void gimp_text_layer_render_layout (GimpTextLayer *layer, GimpTextLayout *layout) { GimpDrawable *drawable = GIMP_DRAWABLE (layer); GimpItem *item = GIMP_ITEM (layer); GimpImage *image = gimp_item_get_image (item); cairo_t *cr; cairo_surface_t *surface; PixelRegion layerPR; const guchar *data; GimpImageType layer_type; gint layer_alpha_byte; gint rowstride; gint width; gint height; gpointer pr; g_return_if_fail (gimp_drawable_has_alpha (drawable)); width = gimp_item_get_width (item); height = gimp_item_get_height (item); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); cr = cairo_create (surface); gimp_text_layout_render (layout, cr, layer->text->base_dir, FALSE); cairo_destroy (cr); pixel_region_init (&layerPR, gimp_drawable_get_tiles (drawable), 0, 0, width, height, TRUE); layer_type = gimp_drawable_type (drawable); layer_alpha_byte = layerPR.bytes - 1; cairo_surface_flush (surface); data = cairo_image_surface_get_data (surface); rowstride = cairo_image_surface_get_stride (surface); for (pr = pixel_regions_register (1, &layerPR); pr != NULL; pr = pixel_regions_process (pr)) { const guchar *src = data + layerPR.y * rowstride + layerPR.x * 4; guchar *dest = layerPR.data; gint rows = layerPR.h; while (rows--) { const guchar *s = src; guchar *d = dest; gint w = layerPR.w; while (w--) { guchar color[4]; GIMP_CAIRO_ARGB32_GET_PIXEL (s, color[0], color[1], color[2], color[3]); gimp_image_transform_color (image, layer_type, d, GIMP_RGB, color); d[layer_alpha_byte] = color[3]; s += 4; d += layerPR.bytes; } src += rowstride; dest += layerPR.rowstride; } } cairo_surface_destroy (surface); gimp_drawable_update (drawable, 0, 0, width, height); }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); cairo_surface_t *surface; cairo_pattern_t *pattern; cairo_t *cr2; /* * 1. Test file-not-found from surface->pattern->cairo_t */ /* Make a custom context to not interfere with the one passed in. */ cr2 = cairo_create (cairo_get_target (cr)); /* First, let's make a nil surface. */ surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___"); /* Let the error propagate into a nil pattern. */ pattern = cairo_pattern_create_for_surface (surface); /* Then let it propagate into the cairo_t. */ cairo_set_source (cr2, pattern); cairo_paint (cr2); cairo_pattern_destroy (pattern); cairo_surface_destroy (surface); /* Check that the error made it all that way. */ if (cairo_status (cr2) != CAIRO_STATUS_FILE_NOT_FOUND) { cairo_test_log (ctx, "Error: Received status of \"%s\" rather than expected \"%s\"\n", cairo_status_to_string (cairo_status (cr2)), cairo_status_to_string (CAIRO_STATUS_FILE_NOT_FOUND)); cairo_destroy (cr2); return CAIRO_TEST_FAILURE; } cairo_destroy (cr2); /* * 2. Test NULL pointer pattern->cairo_t */ cr2 = cairo_create (cairo_get_target (cr)); /* First, trigger the NULL pointer status. */ pattern = cairo_pattern_create_for_surface (NULL); /* Then let it propagate into the cairo_t. */ cairo_set_source (cr2, pattern); cairo_paint (cr2); cairo_pattern_destroy (pattern); /* Check that the error made it all that way. */ if (cairo_status (cr2) != CAIRO_STATUS_NULL_POINTER) { cairo_test_log (ctx, "Error: Received status of \"%s\" rather than expected \"%s\"\n", cairo_status_to_string (cairo_status (cr2)), cairo_status_to_string (CAIRO_STATUS_NULL_POINTER)); cairo_destroy (cr2); return CAIRO_TEST_FAILURE; } cairo_destroy (cr2); /* * 3. Test that cairo_surface_finish can accept NULL or a nil * surface without crashing. */ cairo_surface_finish (NULL); surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___"); cairo_surface_finish (surface); cairo_surface_destroy (surface); /* * 4. OK, we're straying from the original name, but it's still a * similar kind of testing of error paths. Here we're making sure * we can still call a cairo_get_* function after triggering an * INVALID_RESTORE error. */ cr2 = cairo_create (cairo_get_target (cr)); /* Trigger invalid restore. */ cairo_restore (cr2); if (cairo_status (cr2) != CAIRO_STATUS_INVALID_RESTORE) { cairo_test_log (ctx, "Error: Received status of \"%s\" rather than expected \"%s\"\n", cairo_status_to_string (cairo_status (cr2)), cairo_status_to_string (CAIRO_STATUS_INVALID_RESTORE)); cairo_destroy (cr2); return CAIRO_TEST_FAILURE; } /* Test that we can still call cairo_get_fill_rule without crashing. */ cairo_get_fill_rule (cr2); cairo_destroy (cr2); /* * 5. Create a cairo_t for the NULL surface. */ cr2 = cairo_create (NULL); if (cairo_status (cr2) != CAIRO_STATUS_NULL_POINTER) { cairo_test_log (ctx, "Error: Received status of \"%s\" rather than expected \"%s\"\n", cairo_status_to_string (cairo_status (cr2)), cairo_status_to_string (CAIRO_STATUS_NULL_POINTER)); cairo_destroy (cr2); return CAIRO_TEST_FAILURE; } /* Test that get_target returns something valid */ if (cairo_get_target (cr2) == NULL) { cairo_test_log (ctx, "Error: cairo_get_target() returned NULL\n"); cairo_destroy (cr2); return CAIRO_TEST_FAILURE; } /* Test that push_group doesn't crash */ cairo_push_group (cr2); cairo_stroke (cr2); cairo_pop_group (cr2); cairo_destroy (cr2); return CAIRO_TEST_SUCCESS; }
static bool rsvg_convert(struct content *c) { rsvg_content *d = (rsvg_content *) c; union content_msg_data msg_data; RsvgDimensionData rsvgsize; GError *err = NULL; if (rsvg_handle_close(d->rsvgh, &err) == FALSE) { LOG(("rsvg_handle_close returned an error: %s", err->message)); msg_data.error = err->message; content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } assert(err == NULL); /* we should now be able to query librsvg for the natural size of the * graphic, so we can create our bitmap. */ rsvg_handle_get_dimensions(d->rsvgh, &rsvgsize); c->width = rsvgsize.width; c->height = rsvgsize.height; if ((d->bitmap = bitmap_create(c->width, c->height, BITMAP_NEW)) == NULL) { LOG(("Failed to create bitmap for rsvg render.")); msg_data.error = messages_get("NoMemory"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } if ((d->cs = cairo_image_surface_create_for_data( (unsigned char *)bitmap_get_buffer(d->bitmap), CAIRO_FORMAT_ARGB32, c->width, c->height, bitmap_get_rowstride(d->bitmap))) == NULL) { LOG(("Failed to create Cairo image surface for rsvg render.")); msg_data.error = messages_get("NoMemory"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } if ((d->ct = cairo_create(d->cs)) == NULL) { LOG(("Failed to create Cairo drawing context for rsvg render.")); msg_data.error = messages_get("NoMemory"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } rsvg_handle_render_cairo(d->rsvgh, d->ct); rsvg_argb_to_abgr(bitmap_get_buffer(d->bitmap), c->width, c->height, bitmap_get_rowstride(d->bitmap)); bitmap_modified(d->bitmap); content_set_ready(c); content_set_done(c); /* Done: update status bar */ content_set_status(c, ""); return true; }
static GstFlowReturn gst_rsvg_decode_image (GstRsvgDec * rsvg, const guint8 * data, guint size, GstBuffer ** buffer) { GstFlowReturn ret = GST_FLOW_OK; cairo_t *cr; cairo_surface_t *surface; RsvgHandle *handle; GError *error = NULL; RsvgDimensionData dimension; gdouble scalex, scaley; const gchar *title = NULL, *comment = NULL; handle = rsvg_handle_new_from_data (data, size, &error); if (!handle) { GST_ERROR_OBJECT (rsvg, "Failed to parse SVG image: %s", error->message); g_error_free (error); return GST_FLOW_ERROR; } title = rsvg_handle_get_title (handle); comment = rsvg_handle_get_desc (handle); if (title || comment) { if (!rsvg->pending_tags) rsvg->pending_tags = gst_tag_list_new (); if (title && *title) gst_tag_list_add (rsvg->pending_tags, GST_TAG_MERGE_REPLACE_ALL, GST_TAG_TITLE, title, NULL); if (comment && *comment) gst_tag_list_add (rsvg->pending_tags, GST_TAG_MERGE_REPLACE_ALL, GST_TAG_COMMENT, comment, NULL); } rsvg_handle_get_dimensions (handle, &dimension); if (rsvg->width != dimension.width || rsvg->height != dimension.height) { GstCaps *caps1, *caps2, *caps3; GstStructure *s; caps1 = gst_caps_copy (gst_pad_get_pad_template_caps (rsvg->srcpad)); caps2 = gst_pad_peer_get_caps (rsvg->srcpad); if (caps2) { caps3 = gst_caps_intersect (caps1, caps2); gst_caps_unref (caps1); gst_caps_unref (caps2); caps1 = caps3; caps3 = NULL; } if (gst_caps_is_empty (caps1)) { GST_ERROR_OBJECT (rsvg, "Unable to negotiate a format"); gst_caps_unref (caps1); g_object_unref (handle); return GST_FLOW_NOT_NEGOTIATED; } caps2 = gst_caps_copy (gst_pad_get_pad_template_caps (rsvg->srcpad)); s = gst_caps_get_structure (caps2, 0); gst_structure_set (s, "width", G_TYPE_INT, dimension.width, "height", G_TYPE_INT, dimension.height, "framerate", GST_TYPE_FRACTION, 0, 1, NULL); caps3 = gst_caps_intersect (caps1, caps2); if (!gst_caps_is_empty (caps3)) { gst_caps_truncate (caps3); gst_pad_set_caps (rsvg->srcpad, caps3); gst_caps_unref (caps1); gst_caps_unref (caps2); gst_caps_unref (caps3); rsvg->width = dimension.width; rsvg->height = dimension.height; } else { gst_caps_unref (caps2); gst_caps_unref (caps3); gst_caps_truncate (caps1); s = gst_caps_get_structure (caps1, 0); gst_structure_set (s, "framerate", GST_TYPE_FRACTION, 0, 1, NULL); if (!gst_caps_is_fixed (caps1) && (!gst_structure_fixate_field_nearest_int (s, "width", dimension.width) || !gst_structure_fixate_field_nearest_int (s, "height", dimension.height))) { g_object_unref (handle); GST_ERROR_OBJECT (rsvg, "Failed to fixate caps"); return GST_FLOW_NOT_NEGOTIATED; } gst_pad_set_caps (rsvg->srcpad, caps1); gst_structure_get_int (s, "width", &rsvg->width); gst_structure_get_int (s, "height", &rsvg->height); gst_caps_unref (caps1); } } if ((ret = gst_pad_alloc_buffer_and_set_caps (rsvg->srcpad, GST_BUFFER_OFFSET_NONE, rsvg->width * rsvg->height * 4, GST_PAD_CAPS (rsvg->srcpad), buffer)) != GST_FLOW_OK) { g_object_unref (handle); GST_ERROR_OBJECT (rsvg, "Buffer allocation failed %s", gst_flow_get_name (ret)); return ret; } surface = cairo_image_surface_create_for_data (GST_BUFFER_DATA (*buffer), CAIRO_FORMAT_ARGB32, rsvg->width, rsvg->height, rsvg->width * 4); cr = cairo_create (surface); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); scalex = scaley = 1.0; if (rsvg->width != dimension.width) { scalex = ((gdouble) rsvg->width) / ((gdouble) dimension.width); } if (rsvg->height != dimension.height) { scaley = ((gdouble) rsvg->height) / ((gdouble) dimension.height); } cairo_scale (cr, scalex, scaley); rsvg_handle_render_cairo (handle, cr); g_object_unref (handle); cairo_destroy (cr); cairo_surface_destroy (surface); return ret; }
static void gimp_ruler_draw_ticks (GimpRuler *ruler) { GtkWidget *widget = GTK_WIDGET (ruler); GtkStyle *style = gtk_widget_get_style (widget); GimpRulerPrivate *priv = GIMP_RULER_GET_PRIVATE (ruler); GtkStateType state = gtk_widget_get_state (widget); GtkAllocation allocation; cairo_t *cr; gint i; gint width, height; gint xthickness; gint ythickness; gint length, ideal_length; gdouble lower, upper; /* Upper and lower limits, in ruler units */ gdouble increment; /* Number of pixels per unit */ gint scale; /* Number of units per major unit */ gdouble start, end, cur; gchar unit_str[32]; gint digit_height; gint digit_offset; gint text_size; gint pos; gdouble max_size; GimpUnit unit; PangoLayout *layout; PangoRectangle logical_rect, ink_rect; if (! gtk_widget_is_drawable (widget)) return; gtk_widget_get_allocation (widget, &allocation); xthickness = style->xthickness; ythickness = style->ythickness; layout = gimp_ruler_get_layout (widget, "0123456789"); pango_layout_get_extents (layout, &ink_rect, &logical_rect); digit_height = PANGO_PIXELS (ink_rect.height) + 2; digit_offset = ink_rect.y; if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { width = allocation.width; height = allocation.height - ythickness * 2; } else { width = allocation.height; height = allocation.width - ythickness * 2; } cr = cairo_create (priv->backing_store); gdk_cairo_set_source_color (cr, &style->bg[state]); #if 0 gtk_paint_box (style, priv->backing_store, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, widget, priv->orientation == GTK_ORIENTATION_HORIZONTAL ? "hruler" : "vruler", 0, 0, allocation.width, allocation.height); #else cairo_paint (cr); #endif gdk_cairo_set_source_color (cr, &style->fg[state]); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_rectangle (cr, xthickness, height + ythickness, allocation.width - 2 * xthickness, 1); } else { cairo_rectangle (cr, height + xthickness, ythickness, 1, allocation.height - 2 * ythickness); } gimp_ruler_get_range (ruler, &lower, &upper, &max_size); if ((upper - lower) == 0) goto out; increment = (gdouble) width / (upper - lower); /* determine the scale * use the maximum extents of the ruler to determine the largest * possible number to be displayed. Calculate the height in pixels * of this displayed text. Use this height to find a scale which * leaves sufficient room for drawing the ruler. * * We calculate the text size as for the vruler instead of * actually measuring the text width, so that the result for the * scale looks consistent with an accompanying vruler. */ scale = ceil (max_size); g_snprintf (unit_str, sizeof (unit_str), "%d", scale); text_size = strlen (unit_str) * digit_height + 1; for (scale = 0; scale < G_N_ELEMENTS (ruler_metric.ruler_scale); scale++) if (ruler_metric.ruler_scale[scale] * fabs (increment) > 2 * text_size) break; if (scale == G_N_ELEMENTS (ruler_metric.ruler_scale)) scale = G_N_ELEMENTS (ruler_metric.ruler_scale) - 1; unit = gimp_ruler_get_unit (ruler); /* drawing starts here */ length = 0; for (i = G_N_ELEMENTS (ruler_metric.subdivide) - 1; i >= 0; i--) { gdouble subd_incr; /* hack to get proper subdivisions at full pixels */ if (unit == GIMP_UNIT_PIXEL && scale == 1 && i == 1) subd_incr = 1.0; else subd_incr = ((gdouble) ruler_metric.ruler_scale[scale] / (gdouble) ruler_metric.subdivide[i]); if (subd_incr * fabs (increment) <= MINIMUM_INCR) continue; /* don't subdivide pixels */ if (unit == GIMP_UNIT_PIXEL && subd_incr < 1.0) continue; /* Calculate the length of the tickmarks. Make sure that * this length increases for each set of ticks */ ideal_length = height / (i + 1) - 1; if (ideal_length > ++length) length = ideal_length; if (lower < upper) { start = floor (lower / subd_incr) * subd_incr; end = ceil (upper / subd_incr) * subd_incr; } else { start = floor (upper / subd_incr) * subd_incr; end = ceil (lower / subd_incr) * subd_incr; } for (cur = start; cur <= end; cur += subd_incr) { pos = ROUND ((cur - lower) * increment); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_rectangle (cr, pos, height + ythickness - length, 1, length); } else { cairo_rectangle (cr, height + xthickness - length, pos, length, 1); } /* draw label */ if (i == 0) { g_snprintf (unit_str, sizeof (unit_str), "%d", (int) cur); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { pango_layout_set_text (layout, unit_str, -1); pango_layout_get_extents (layout, &logical_rect, NULL); #if 0 gtk_paint_layout (style, priv->backing_store, state, FALSE, NULL, widget, "hruler", pos + 2, ythickness + PANGO_PIXELS (logical_rect.y - digit_offset), layout); #else cairo_move_to (cr, pos + 2, ythickness + PANGO_PIXELS (logical_rect.y - digit_offset)); pango_cairo_show_layout (cr, layout); #endif } else { gint j; for (j = 0; j < (int) strlen (unit_str); j++) { pango_layout_set_text (layout, unit_str + j, 1); pango_layout_get_extents (layout, NULL, &logical_rect); #if 0 gtk_paint_layout (style, priv->backing_store, state, FALSE, NULL, widget, "vruler", xthickness + 1, pos + digit_height * j + 2 + PANGO_PIXELS (logical_rect.y - digit_offset), layout); #else cairo_move_to (cr, xthickness + 1, pos + digit_height * j + 2 + PANGO_PIXELS (logical_rect.y - digit_offset)); pango_cairo_show_layout (cr, layout); #endif } } } } } cairo_fill (cr); priv->backing_store_valid = TRUE; out: cairo_destroy (cr); }
static gboolean _lib_histogram_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_histogram_t *d = (dt_lib_histogram_t *)self->data; dt_develop_t *dev = darktable.develop; uint32_t *hist = dev->histogram; float hist_max = dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR ? dev->histogram_max : logf(1.0 + dev->histogram_max); const int inset = DT_HIST_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0, allocation.width, allocation.height); cairo_translate(cr, 4 * inset, inset); width -= 2 * 4 * inset; height -= 2 * inset; if(d->mode_x == 0) { d->color_w = 0.06 * width; d->button_spacing = 0.01 * width; d->button_h = 0.06 * width; d->button_y = d->button_spacing; d->mode_w = d->color_w; d->mode_x = width - 3 * (d->color_w + d->button_spacing) - (d->mode_w + d->button_spacing); d->red_x = width - 3 * (d->color_w + d->button_spacing); d->green_x = width - 2 * (d->color_w + d->button_spacing); d->blue_x = width - (d->color_w + d->button_spacing); } // TODO: probably this should move to the configure-event callback! That would be future proof if we ever // (again) allow to resize the side panels. const gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); // this code assumes that the first expose comes before the first (preview) pipe is processed and that the // size of the widget doesn't change! if(dev->histogram_waveform_width == 0) { dev->histogram_waveform = (uint32_t *)calloc(height * stride / 4, sizeof(uint32_t)); dev->histogram_waveform_stride = stride; dev->histogram_waveform_height = height; dev->histogram_waveform_width = width; // return TRUE; // there are enough expose events following ... } #if 1 // draw shadow around float alpha = 1.0f; cairo_set_line_width(cr, 0.2); for(int k = 0; k < inset; k++) { cairo_rectangle(cr, -k, -k, width + 2 * k, height + 2 * k); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.5f; cairo_fill(cr); } cairo_set_line_width(cr, 1.0); #else cairo_set_line_width(cr, 1.0); cairo_set_source_rgb(cr, .1, .1, .1); cairo_rectangle(cr, 0, 0, width, height); cairo_stroke(cr); #endif cairo_rectangle(cr, 0, 0, width, height); cairo_clip(cr); cairo_set_source_rgb(cr, .3, .3, .3); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); if(d->highlight == 1) { cairo_set_source_rgb(cr, .5, .5, .5); cairo_rectangle(cr, 0, 0, .2 * width, height); cairo_fill(cr); } else if(d->highlight == 2) { cairo_set_source_rgb(cr, .5, .5, .5); cairo_rectangle(cr, 0.2 * width, 0, width, height); cairo_fill(cr); } // draw grid cairo_set_line_width(cr, .4); cairo_set_source_rgb(cr, .1, .1, .1); if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM) dt_draw_waveform_lines(cr, 0, 0, width, height); else dt_draw_grid(cr, 4, 0, 0, width, height); if(hist_max > 0.0f) { cairo_save(cr); if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM) { // make the color channel selector work: uint8_t *buf = (uint8_t *)malloc(sizeof(uint8_t) * height * stride); uint8_t mask[3] = { d->blue, d->green, d->red }; memcpy(buf, dev->histogram_waveform, sizeof(uint8_t) * height * stride); for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) for(int k = 0; k < 3; k++) { buf[y * stride + x * 4 + k] *= mask[k]; } cairo_surface_t *source = cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32, width, height, stride); cairo_set_source_surface(cr, source, 0.0, 0.0); cairo_set_operator(cr, CAIRO_OPERATOR_ADD); cairo_paint(cr); cairo_surface_destroy(source); free(buf); } else { // cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); cairo_translate(cr, 0, height); cairo_scale(cr, width / 255.0, -(height - 10) / hist_max); cairo_set_operator(cr, CAIRO_OPERATOR_ADD); // cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_line_width(cr, 1.); if(d->red) { cairo_set_source_rgba(cr, 1., 0., 0., 0.2); dt_draw_histogram_8(cr, hist, 0, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR); } if(d->green) { cairo_set_source_rgba(cr, 0., 1., 0., 0.2); dt_draw_histogram_8(cr, hist, 1, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR); } if(d->blue) { cairo_set_source_rgba(cr, 0., 0., 1., 0.2); dt_draw_histogram_8(cr, hist, 2, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR); } cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); // cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); } cairo_restore(cr); } cairo_set_source_rgb(cr, .25, .25, .25); cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); PangoLayout *layout; PangoRectangle ink; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_font_description_set_absolute_size(desc, .1 * height * PANGO_SCALE); pango_layout_set_font_description(layout, desc); char exifline[50]; dt_image_print_exif(&dev->image_storage, exifline, sizeof(exifline)); pango_layout_set_text(layout, exifline, -1); pango_layout_get_pixel_extents(layout, &ink, NULL); cairo_move_to(cr, .02 * width, .98 * height - ink.height - ink.y); cairo_save(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0)); cairo_set_source_rgba(cr, 1, 1, 1, 0.3); pango_cairo_layout_path(cr, layout); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, .25, .25, .25); cairo_fill(cr); cairo_restore(cr); // buttons to control the display of the histogram: linear/log, r, g, b if(d->highlight != 0) { _draw_mode_toggle(cr, d->mode_x, d->button_y, d->mode_w, d->button_h, dev->histogram_type); cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.4); _draw_color_toggle(cr, d->red_x, d->button_y, d->color_w, d->button_h, d->red); cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.4); _draw_color_toggle(cr, d->green_x, d->button_y, d->color_w, d->button_h, d->green); cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.4); _draw_color_toggle(cr, d->blue_x, d->button_y, d->color_w, d->button_h, d->blue); } cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); pango_font_description_free(desc); g_object_unref(layout); return TRUE; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); cairo_surface_t *surface; cairo_t *cr2; cairo_rectangle_list_t *rectangle_list; const char *phase; cairo_bool_t uses_clip_rects; surface = cairo_surface_create_similar (cairo_get_group_target (cr), CAIRO_CONTENT_COLOR, 100, 100); /* don't use cr accidentally */ cr = NULL; cr2 = cairo_create (surface); cairo_surface_destroy (surface); /* Check the surface type so we ignore cairo_copy_clip_rectangle_list failures * on surface types that don't use rectangle lists for clipping. * Default to FALSE for the internal surface types, (meta, test-fallback, etc.) */ switch (cairo_surface_get_type (surface)) { case CAIRO_SURFACE_TYPE_IMAGE: case CAIRO_SURFACE_TYPE_XLIB: case CAIRO_SURFACE_TYPE_XCB: case CAIRO_SURFACE_TYPE_GLITZ: case CAIRO_SURFACE_TYPE_WIN32: case CAIRO_SURFACE_TYPE_BEOS: case CAIRO_SURFACE_TYPE_DIRECTFB: uses_clip_rects = TRUE; break; case CAIRO_SURFACE_TYPE_QUARTZ: case CAIRO_SURFACE_TYPE_PDF: case CAIRO_SURFACE_TYPE_PS: case CAIRO_SURFACE_TYPE_SVG: case CAIRO_SURFACE_TYPE_OS2: default: uses_clip_rects = FALSE; break; } /* first, test basic stuff. This should not be clipped, it should return the surface rectangle. */ phase = "No clip set"; rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 0, 0, 100, 100) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 0, 0, 100, 100)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); /* Test simple clip rect. */ phase = "Simple clip rect"; cairo_save (cr2); cairo_rectangle (cr2, 10, 10, 80, 80); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 10, 10, 80, 80) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* Test everything clipped out. */ phase = "All clipped out"; cairo_save (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 0)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* test two clip rects */ phase = "Two clip rects"; cairo_save (cr2); cairo_rectangle (cr2, 10, 10, 10, 10); cairo_rectangle (cr2, 20, 20, 10, 10); cairo_clip (cr2); cairo_rectangle (cr2, 15, 15, 10, 10); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 2) || !check_clip_extents (ctx, phase, cr2, 15, 15, 10, 10) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 15, 15, 5, 5) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 20, 20, 5, 5)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* test non-rectangular clip */ phase = "Nonrectangular clip"; cairo_save (cr2); cairo_move_to (cr2, 0, 0); cairo_line_to (cr2, 100, 100); cairo_line_to (cr2, 100, 0); cairo_close_path (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); /* can't get this in one tight user-space rectangle */ if (!check_unrepresentable (ctx, phase, rectangle_list) || !check_clip_extents (ctx, phase, cr2, 0, 0, 100, 100)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, simple scale, getting clip with same transform"; cairo_save (cr2); cairo_scale (cr2, 2, 2); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 5, 5, 40, 40) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 5, 5, 40, 40)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, simple scale, getting clip with no transform"; cairo_save (cr2); cairo_save (cr2); cairo_scale (cr2, 2, 2); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_restore (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 10, 10, 80, 80) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, rotation, getting clip with no transform"; cairo_save (cr2); cairo_save (cr2); cairo_rotate (cr2, 12); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_restore (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_unrepresentable (ctx, phase, rectangle_list)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); cairo_destroy (cr2); return CAIRO_TEST_SUCCESS; }
static void draw_tsn_graph(struct sctp_udata *u_data) { GPtrArray *array = NULL; guint32 i, size = 0, start, end; gint diff, width; cairo_t *cr; if (u_data->dir == 1) { array = u_data->assoc->sort_tsn1; size = u_data->assoc->n_data_chunks_ep1; if (u_data->io->tmp == FALSE) { min_tsn = 0; max_tsn = u_data->assoc->max_bytes1; } else { min_tsn = u_data->io->tmp_min_tsn1; max_tsn = u_data->io->tmp_max_tsn1; } } else if (u_data->dir == 2) { array = u_data->assoc->sort_tsn2; size = u_data->assoc->n_data_chunks_ep2; if (u_data->io->tmp == FALSE) { min_tsn = 0; max_tsn = u_data->assoc->max_bytes2; } else { min_tsn = u_data->io->tmp_min_tsn2; max_tsn = u_data->io->tmp_max_tsn2; } } width = u_data->io->max_x - u_data->io->min_x; for (i=0; i<size; i++) { if (u_data->io->uoff) diff = (gint)((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs -u_data->io->min_x; else diff = (gint)((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs*1000000 + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->usecs-u_data->io->min_x; start = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset; end = start + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->length; if (start >= min_tsn && diff > 0 && diff <= width){ #if GTK_CHECK_VERSION(2,22,0) cr = cairo_create (u_data->io->surface); #else cr = gdk_cairo_create (u_data->io->pixmap); #endif cairo_set_line_width (cr, 1.0); cairo_move_to(cr, (LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff)+0.5, (u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(start,min_tsn))*u_data->io->y_interval))+0.5); cairo_line_to(cr, (LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff)+0.5, (u_data->io->surface_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval))+0.5); cairo_stroke(cr); cairo_destroy(cr); } } }
static gboolean dt_iop_zonesystem_bar_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self) { dt_iop_zonesystem_gui_data_t *g = (dt_iop_zonesystem_gui_data_t *)self->gui_data; dt_iop_zonesystem_params_t *p = (dt_iop_zonesystem_params_t *)self->params; const int inset = DT_ZONESYSTEM_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); /* clear background */ cairo_set_source_rgb(cr, .15, .15, .15); cairo_paint(cr); /* translate and scale */ width -= 2 * inset; height -= 2 * inset; cairo_save(cr); cairo_translate(cr, inset, inset); cairo_scale(cr, width, height); /* render the bars */ float zonemap[MAX_ZONE_SYSTEM_SIZE] = { 0 }; _iop_zonesystem_calculate_zonemap(p, zonemap); float s = (1. / (p->size - 2)); cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); for(int i = 0; i < p->size - 1; i++) { /* draw the reference zone */ float z = s * i; cairo_rectangle(cr, (1. / (p->size - 1)) * i, 0, (1. / (p->size - 1)), DT_ZONESYSTEM_REFERENCE_SPLIT - DT_ZONESYSTEM_BAR_SPLIT_WIDTH); cairo_set_source_rgb(cr, z, z, z); cairo_fill(cr); /* draw zone mappings */ cairo_rectangle(cr, zonemap[i], DT_ZONESYSTEM_REFERENCE_SPLIT + DT_ZONESYSTEM_BAR_SPLIT_WIDTH, (zonemap[i + 1] - zonemap[i]), 1.0 - DT_ZONESYSTEM_REFERENCE_SPLIT); cairo_set_source_rgb(cr, z, z, z); cairo_fill(cr); } cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); cairo_restore(cr); /* render zonebar control lines */ cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); cairo_set_line_width(cr, 1.); cairo_rectangle(cr, inset, inset, width, height); cairo_set_source_rgb(cr, .1, .1, .1); cairo_stroke(cr); cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); /* render control points handles */ cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.)); const float arrw = DT_PIXEL_APPLY_DPI(7.0f); for(int k = 1; k < p->size - 1; k++) { float nzw = zonemap[k + 1] - zonemap[k]; float pzw = zonemap[k] - zonemap[k - 1]; if((((g->mouse_x / width) > (zonemap[k] - (pzw / 2.0))) && ((g->mouse_x / width) < (zonemap[k] + (nzw / 2.0)))) || p->zone[k] != -1) { gboolean is_under_mouse = ((width * zonemap[k]) - arrw * .5f < g->mouse_x && (width * zonemap[k]) + arrw * .5f > g->mouse_x); cairo_move_to(cr, inset + (width * zonemap[k]), height + (2 * inset) - 1); cairo_rel_line_to(cr, -arrw * .5f, 0); cairo_rel_line_to(cr, arrw * .5f, -arrw); cairo_rel_line_to(cr, arrw * .5f, arrw); cairo_close_path(cr); if(is_under_mouse) cairo_fill(cr); else cairo_stroke(cr); } } /* push mem surface into widget */ cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }