diff --git a/docs/reference/gtk/gtk4-rendernode-tool.rst b/docs/reference/gtk/gtk4-rendernode-tool.rst index c9188de329..12d268ba4e 100644 --- a/docs/reference/gtk/gtk4-rendernode-tool.rst +++ b/docs/reference/gtk/gtk4-rendernode-tool.rst @@ -14,7 +14,7 @@ SYNOPSIS | | **gtk4-rendernode-tool** info [OPTIONS...] | **gtk4-rendernode-tool** show [OPTIONS...] -| **gtk4-rendernode-tool** render [OPTIONS...] +| **gtk4-rendernode-tool** render [OPTIONS...] [] DESCRIPTION ----------- @@ -43,9 +43,5 @@ The name of the file to write can be specified as a second FILE argument. ``--renderer=RENDERER`` - Use the given renderer. This option accepts the same values as the - ``GSK_RENDERER`` environment variable. - -``--force`` - - Overwrite an existing file. + Use the given renderer. Use ``--renderer=help`` to get a information + about poassible values for the ``RENDERER``. diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c index 85d9ba0a25..0e8e2cc78d 100644 --- a/gdk/gdkmemorytexture.c +++ b/gdk/gdkmemorytexture.c @@ -151,6 +151,8 @@ gdk_memory_texture_new (int width, g_return_val_if_fail (height > 0, NULL); g_return_val_if_fail (bytes != NULL, NULL); g_return_val_if_fail (stride >= width * gdk_memory_format_bytes_per_pixel (format), NULL); + /* needs to be this complex to support subtexture of the bottom right part */ + g_return_val_if_fail (g_bytes_get_size (bytes) >= stride * (height - 1) + width * gdk_memory_format_bytes_per_pixel (format), NULL); bytes = gdk_memory_sanitize (bytes, width, height, format, stride, &stride); diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 4034833603..49e461ef0f 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -1009,6 +1009,7 @@ gdk_display_load_pipeline_cache (GdkDisplay *display) &result) != VK_SUCCESS) result = VK_NULL_HANDLE; + g_object_unref (cache_file); g_free (data); g_free (display->vk_pipeline_cache_etag); display->vk_pipeline_cache_etag = etag; @@ -1644,7 +1645,6 @@ gdk_display_unref_vulkan (GdkDisplay *display) if (display->vulkan_refcount > 0) return; - display->vk_shader_modules = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_iter_init (&iter, display->vk_shader_modules); while (g_hash_table_iter_next (&iter, &key, &value)) { @@ -1653,9 +1653,11 @@ gdk_display_unref_vulkan (GdkDisplay *display) value, NULL); } + g_hash_table_unref (display->vk_shader_modules); if (display->vk_save_pipeline_cache_source) { + g_clear_handle_id (&display->vk_save_pipeline_cache_source, g_source_remove); gdk_vulkan_save_pipeline_cache_cb (display); g_assert (display->vk_save_pipeline_cache_source == 0); } diff --git a/gsk/vulkan/gskvulkancommandpool.c b/gsk/vulkan/gskvulkancommandpool.c index 197e0aec2a..0da12c0b0e 100644 --- a/gsk/vulkan/gskvulkancommandpool.c +++ b/gsk/vulkan/gskvulkancommandpool.c @@ -56,6 +56,7 @@ gsk_vulkan_command_pool_free (GskVulkanCommandPool *self) self->vk_command_pool, NULL); + g_object_unref (self->vulkan); g_free (self); } diff --git a/gsk/vulkan/gskvulkanglyphcache.c b/gsk/vulkan/gskvulkanglyphcache.c index a86d197e06..693e3b6166 100644 --- a/gsk/vulkan/gskvulkanglyphcache.c +++ b/gsk/vulkan/gskvulkanglyphcache.c @@ -30,7 +30,6 @@ typedef struct { GskVulkanImage *image; int width, height; int x, y, y0; - int num_glyphs; guint old_pixels; } Atlas; @@ -70,7 +69,6 @@ create_atlas (GskVulkanGlyphCache *cache) atlas->y = 0; atlas->x = 0; atlas->image = NULL; - atlas->num_glyphs = 0; atlas->image = gsk_vulkan_image_new_for_atlas (cache->vulkan, atlas->width, atlas->height); @@ -213,8 +211,6 @@ add_to_cache (GskVulkanGlyphCache *cache, atlas->x = atlas->x + width_with_padding; atlas->y = MAX (atlas->y, atlas->y0 + height_with_padding); - atlas->num_glyphs++; - gsk_vulkan_upload_glyph_op (render, atlas->image, &(cairo_rectangle_int_t) { @@ -239,9 +235,8 @@ add_to_cache (GskVulkanGlyphCache *cache, for (i = 0; i < cache->atlases->len; i++) { atlas = g_ptr_array_index (cache->atlases, i); - g_print ("\tAtlas %d (%dx%d): %d glyphs, %.2g%% old pixels, filled to %d, %d / %d\n", + g_print ("\tAtlas %d (%dx%d): %.2g%% old pixels, filled to %d, %d / %d\n", i, atlas->width, atlas->height, - atlas->num_glyphs, 100.0 * (double)atlas->old_pixels / (double)(atlas->width * atlas->height), atlas->x, atlas->y0, atlas->y); } diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index 9e3c0cbca9..8637ed5f64 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -483,7 +483,7 @@ gsk_vulkan_render_add_node (GskVulkanRender *self, cairo_region_get_extents (self->clip, &extents); gsk_vulkan_render_pass_begin_op (self, - g_object_ref (self->target), + self->target, &extents, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); @@ -499,7 +499,7 @@ gsk_vulkan_render_add_node (GskVulkanRender *self, gsk_vulkan_render_pass_free (render_pass); gsk_vulkan_render_pass_end_op (self, - g_object_ref (self->target), + self->target, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); if (download_func) diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 56f190580c..2bd3367f44 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -162,7 +162,7 @@ gsk_vulkan_render_pass_upload_texture (GskVulkanRender *render, gdk_texture_get_format (texture), width, height); gsk_vulkan_render_pass_begin_op (render, - g_object_ref (better_image), + better_image, &(cairo_rectangle_int_t) { 0, 0, width, height }, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); diff --git a/gsk/vulkan/gskvulkanuploadop.c b/gsk/vulkan/gskvulkanuploadop.c index 428590f559..afb0904456 100644 --- a/gsk/vulkan/gskvulkanuploadop.c +++ b/gsk/vulkan/gskvulkanuploadop.c @@ -287,6 +287,9 @@ gsk_vulkan_upload_cairo_op_draw (GskVulkanOp *op, width / self->viewport.size.width, height / self->viewport.size.height); cr = cairo_create (surface); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_translate (cr, -self->viewport.origin.x, -self->viewport.origin.y); gsk_render_node_draw (self->node, cr); @@ -402,6 +405,9 @@ gsk_vulkan_upload_glyph_op_draw (GskVulkanOp *op, cairo_surface_set_device_scale (surface, self->scale, self->scale); cr = cairo_create (surface); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); /* Make sure the entire surface is initialized to black */ cairo_set_source_rgba (cr, 0, 0, 0, 0); diff --git a/tools/gtk-rendernode-tool-render.c b/tools/gtk-rendernode-tool-render.c index 77be8ea412..c8d98da3f8 100644 --- a/tools/gtk-rendernode-tool-render.c +++ b/tools/gtk-rendernode-tool-render.c @@ -28,6 +28,9 @@ #include #include #include "gtk-rendernode-tool.h" +#ifdef CAIRO_HAS_SVG_SURFACE +#include +#endif static char * get_save_filename (const char *filename) @@ -48,6 +51,58 @@ get_save_filename (const char *filename) return result; } +#ifdef CAIRO_HAS_SVG_SURFACE +static cairo_status_t +cairo_serializer_write (gpointer user_data, + const unsigned char *data, + unsigned int length) +{ + g_byte_array_append (user_data, data, length); + + return CAIRO_STATUS_SUCCESS; +} + +static GBytes * +create_svg (GskRenderNode *node, + GError **error) +{ + cairo_surface_t *surface; + cairo_t *cr; + graphene_rect_t bounds; + GByteArray *array; + + gsk_render_node_get_bounds (node, &bounds); + array = g_byte_array_new (); + + surface = cairo_svg_surface_create_for_stream (cairo_serializer_write, + array, + bounds.size.width, + bounds.size.height); + cairo_svg_surface_set_document_unit (surface, CAIRO_SVG_UNIT_PX); + cairo_surface_set_device_offset (surface, -bounds.origin.x, -bounds.origin.y); + + cr = cairo_create (surface); + gsk_render_node_draw (node, cr); + cairo_destroy (cr); + + cairo_surface_finish (surface); + if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS) + { + cairo_surface_destroy (surface); + return g_byte_array_free_to_bytes (array); + } + else + { + g_set_error (error, + G_IO_ERROR, G_IO_ERROR_FAILED, + "%s", cairo_status_to_string (cairo_surface_status (surface))); + cairo_surface_destroy (surface); + g_byte_array_unref (array); + return NULL; + } +} +#endif + static void render_file (const char *filename, const char *renderer_name, @@ -55,24 +110,10 @@ render_file (const char *filename, { GskRenderNode *node; GBytes *bytes; - GdkTexture *texture; char *save_to; - GskRenderer *renderer; - GdkSurface *window; GError *error = NULL; - node = load_node_file (filename); - - if (renderer_name) - g_object_set_data_full (G_OBJECT (gdk_display_get_default ()), "gsk-renderer", - g_strdup (renderer_name), g_free); - - window = gdk_surface_new_toplevel (gdk_display_get_default ()); - renderer = gsk_renderer_new_for_surface (window); - - texture = gsk_renderer_render_texture (renderer, node, NULL); - - save_to = (char *)save_file; + save_to = (char *) save_file; if (save_to == NULL) { @@ -85,11 +126,42 @@ render_file (const char *filename, } } - if (g_str_has_suffix (save_to, ".tif") || - g_str_has_suffix (save_to, ".tiff")) - bytes = gdk_texture_save_to_tiff_bytes (texture); + node = load_node_file (filename); + +#ifdef CAIRO_HAS_SVG_SURFACE + if (g_str_has_suffix (save_to, ".svg")) + { + bytes = create_svg (node, &error); + if (bytes == NULL) + { + g_printerr (_("Failed to generate SVG: %s\n"), error->message); + exit (1); + } + } else - bytes = gdk_texture_save_to_png_bytes (texture); +#endif + { + GdkTexture *texture; + GskRenderer *renderer; + GdkSurface *window; + + if (renderer_name) + g_object_set_data_full (G_OBJECT (gdk_display_get_default ()), "gsk-renderer", + g_strdup (renderer_name), g_free); + + window = gdk_surface_new_toplevel (gdk_display_get_default ()); + renderer = gsk_renderer_new_for_surface (window); + + texture = gsk_renderer_render_texture (renderer, node, NULL); + + if (g_str_has_suffix (save_to, ".tif") || + g_str_has_suffix (save_to, ".tiff")) + bytes = gdk_texture_save_to_tiff_bytes (texture); + else + bytes = gdk_texture_save_to_png_bytes (texture); + + g_object_unref (texture); + } if (g_file_set_contents (save_to, g_bytes_get_data (bytes, NULL), @@ -110,7 +182,6 @@ render_file (const char *filename, if (save_to != save_file) g_free (save_to); - g_object_unref (texture); gsk_render_node_unref (node); }