[gnome-shell] screenshot: Add API to get PNG stream from a texture
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] screenshot: Add API to get PNG stream from a texture
- Date: Thu, 27 Jan 2022 22:30:53 +0000 (UTC)
commit 71c6918588042e878b325af1735d9a792b490b69
Author: Ivan Molodetskikh <yalterz gmail com>
Date: Sat Jan 15 18:20:51 2022 +0300
screenshot: Add API to get PNG stream from a texture
With the new screenshot UI we're introducing, we'll be capturing all
screenshots to textures on the GPU at first, and then create a PNG
stream from those textures at a later point. This will allow us to
present screenshots immediately to the user so they can inspect them and
select the right area before actually saving them to disk.
As a first step to make this work, introduce a new ShellScreenshot API
that writes an existing CoglTexture to a PNG output stream:
shell_screenshot_composite_to_stream ()
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1954>
src/shell-screenshot.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++
src/shell-screenshot.h | 11 +++++
2 files changed, 129 insertions(+)
---
diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c
index 100429f217..34494185a6 100644
--- a/src/shell-screenshot.c
+++ b/src/shell-screenshot.c
@@ -804,6 +804,124 @@ shell_screenshot_pick_color_finish (ShellScreenshot *screenshot,
#undef INDEX_G
#undef INDEX_B
+static void
+composite_to_stream_on_png_saved (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GTask *task = G_TASK (user_data);
+ GError *error = NULL;
+
+ if (!gdk_pixbuf_save_to_stream_finish (result, &error))
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+
+ g_object_unref (task);
+}
+
+/**
+ * shell_screenshot_composite_to_stream:
+ * @texture: the source texture
+ * @x: x coordinate of the rectangle
+ * @y: y coordinate of the rectangle
+ * @width: width of the rectangle, or -1 to use the full texture
+ * @height: height of the rectangle, or -1 to use the full texture
+ * @stream: the stream to write the PNG image into
+ * @callback: (scope async): function to call returning success or failure
+ * @user_data: the data to pass to callback function
+ *
+ * Composite a rectangle defined by x, y, width, height from the texture to a
+ * pixbuf and write it as a PNG image into the stream.
+ *
+ */
+void
+shell_screenshot_composite_to_stream (CoglTexture *texture,
+ int x,
+ int y,
+ int width,
+ int height,
+ GOutputStream *stream,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CoglContext *ctx;
+ CoglTexture *sub_texture;
+ cairo_surface_t *surface;
+ g_autoptr (GTask) task = NULL;
+ g_autoptr (GdkPixbuf) pixbuf = NULL;
+ g_autofree char *creation_time = NULL;
+ g_autoptr (GDateTime) date_time = NULL;
+
+ task = g_task_new (NULL, NULL, callback, user_data);
+ g_task_set_source_tag (task, shell_screenshot_composite_to_stream);
+
+ if (width == -1 || height == -1)
+ {
+ x = 0;
+ y = 0;
+ width = cogl_texture_get_width (texture);
+ height = cogl_texture_get_height (texture);
+ }
+
+ ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+ sub_texture = cogl_sub_texture_new (ctx, texture, x, y, width, height);
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ cogl_texture_get_width (sub_texture),
+ cogl_texture_get_height (sub_texture));
+
+ cogl_texture_get_data (sub_texture, CLUTTER_CAIRO_FORMAT_ARGB32,
+ cairo_image_surface_get_stride (surface),
+ cairo_image_surface_get_data (surface));
+ cairo_surface_mark_dirty (surface);
+
+ cogl_object_unref (sub_texture);
+
+ // Save to an image.
+ pixbuf = gdk_pixbuf_get_from_surface (surface,
+ 0, 0,
+ cairo_image_surface_get_width (surface),
+ cairo_image_surface_get_height (surface));
+ cairo_surface_destroy (surface);
+
+ date_time = g_date_time_new_now_local ();
+ creation_time = g_date_time_format (date_time, "%c");
+
+ if (!creation_time)
+ creation_time = g_date_time_format (date_time, "%FT%T%z");
+
+ gdk_pixbuf_save_to_stream_async (pixbuf, stream, "png", NULL,
+ composite_to_stream_on_png_saved,
+ g_steal_pointer (&task),
+ "tEXt::Software", "gnome-screenshot",
+ "tEXt::Creation Time", creation_time,
+ NULL);
+}
+
+/**
+ * shell_screenshot_composite_to_stream_finish:
+ * @result: the #GAsyncResult that was provided to the callback
+ * @error: #GError for error reporting
+ *
+ * Finish the asynchronous operation started by
+ * shell_screenshot_composite_to_stream () and obtain its result.
+ *
+ * Returns: whether the operation was successful
+ *
+ */
+gboolean
+shell_screenshot_composite_to_stream_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+ g_return_val_if_fail (g_async_result_is_tagged (result,
+ shell_screenshot_composite_to_stream),
+ FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
ShellScreenshot *
shell_screenshot_new (void)
{
diff --git a/src/shell-screenshot.h b/src/shell-screenshot.h
index 18c6667e1b..838e910a7e 100644
--- a/src/shell-screenshot.h
+++ b/src/shell-screenshot.h
@@ -60,4 +60,15 @@ gboolean shell_screenshot_pick_color_finish (ShellScreenshot *screenshot,
ClutterColor *color,
GError **error);
+void shell_screenshot_composite_to_stream (CoglTexture *texture,
+ int x,
+ int y,
+ int width,
+ int height,
+ GOutputStream *stream,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean shell_screenshot_composite_to_stream_finish (GAsyncResult *result,
+ GError **error);
+
#endif /* ___SHELL_SCREENSHOT_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]