[libadwaita/wip/exalm/screenshots: 1/2] doc: Add a screenshot generator




commit 97ab4fa38545c8670bffea237d01852376da23e2
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Fri Dec 17 00:33:08 2021 +0500

    doc: Add a screenshot generator

 doc/meson.build                     |   2 +
 doc/tools/README.md                 |   7 ++
 doc/tools/meson.build               |  17 +++
 doc/tools/screenshot.c              | 211 ++++++++++++++++++++++++++++++++++++
 doc/tools/screenshot.gresources.xml |   6 +
 doc/tools/style.css                 |   0
 6 files changed, 243 insertions(+)
---
diff --git a/doc/meson.build b/doc/meson.build
index b5ae25eb..46c49564 100644
--- a/doc/meson.build
+++ b/doc/meson.build
@@ -1,5 +1,7 @@
 if get_option('gtk_doc')
 
+subdir('tools')
+
 expand_content_md_files = [
   'build-howto.md',
   'migrating-between-development-versions.md',
diff --git a/doc/tools/README.md b/doc/tools/README.md
new file mode 100644
index 00000000..ea3b1f36
--- /dev/null
+++ b/doc/tools/README.md
@@ -0,0 +1,7 @@
+To regenerate doc screenshots, run:
+
+```c
+./doc/tools/screenshot ../doc/images/
+```
+
+from the build directory.
diff --git a/doc/tools/meson.build b/doc/tools/meson.build
new file mode 100644
index 00000000..b78296d6
--- /dev/null
+++ b/doc/tools/meson.build
@@ -0,0 +1,17 @@
+screenshot_resources = gnome.compile_resources(
+   'screenshot-resources',
+   'screenshot.gresources.xml',
+
+   c_name: 'adw',
+)
+
+screenshot_sources = [
+  screenshot_resources,
+  'screenshot.c',
+  libadwaita_generated_headers,
+]
+
+screenshot = executable('screenshot'.format(apiversion),
+  screenshot_sources,
+  dependencies: libadwaita_dep,
+)
diff --git a/doc/tools/screenshot.c b/doc/tools/screenshot.c
new file mode 100644
index 00000000..aa00288b
--- /dev/null
+++ b/doc/tools/screenshot.c
@@ -0,0 +1,211 @@
+#include <adwaita.h>
+
+#define RESOURCE_PATH "/org/gnome/Adwaita/Screenshot/"
+
+static GMainLoop *loop;
+
+typedef struct {
+  GtkWidget *widget;
+  GdkPaintable *paintable;
+  char *name;
+  GtkCssProvider *provider;
+} ScreenshotData;
+
+static void
+screenshot_data_free (ScreenshotData *data)
+{
+  g_object_unref (data->paintable);
+  gtk_window_destroy (GTK_WINDOW (gtk_widget_get_root (data->widget)));
+  g_object_unref (data->provider);
+  g_free (data->name);
+  g_free (data);
+}
+
+static void
+draw_paintable (ScreenshotData *data)
+{
+  GtkSnapshot *snapshot;
+  GskRenderer *renderer;
+  g_autoptr (GdkTexture) texture = NULL;
+  g_autoptr (GskRenderNode) node = NULL;
+  int width, height;
+
+  g_signal_handlers_disconnect_by_func (data->paintable,
+                                        G_CALLBACK (draw_paintable),
+                                        data);
+
+  width = gtk_widget_get_allocated_width (data->widget);
+  height = gtk_widget_get_allocated_height (data->widget);
+
+  snapshot = gtk_snapshot_new ();
+  gdk_paintable_snapshot (data->paintable, snapshot, width, height);
+
+  node = gtk_snapshot_free_to_node (snapshot);
+  renderer = gtk_native_get_renderer (gtk_widget_get_native (data->widget));
+
+  texture = gsk_renderer_render_texture (renderer, node,
+                                         &GRAPHENE_RECT_INIT (0, 0, width, height));
+
+  gdk_texture_save_to_png (texture, data->name);
+
+  screenshot_data_free (data);
+
+  g_main_loop_quit (loop);
+}
+
+static GtkCssProvider *
+load_css (const char *name)
+{
+  GtkCssProvider *provider = gtk_css_provider_new ();
+  g_autofree char *path = g_strdup_printf (RESOURCE_PATH "%s.css", name);
+
+  gtk_css_provider_load_from_resource (provider, path);
+
+  gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+                                              GTK_STYLE_PROVIDER (provider),
+                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+  return provider;
+}
+
+static void
+take_screenshot (const char *name,
+                 gboolean    dark,
+                 GFile      *output_dir)
+{
+  g_autofree char *ui_path = NULL;
+  g_autofree char *output_name = NULL;
+  g_autoptr (GtkBuilder) builder = NULL;
+  g_autoptr (GFile) output_file = NULL;
+  GObject *object;
+  ScreenshotData *data;
+  GtkWidget *window;
+
+  ui_path = g_strdup_printf (RESOURCE_PATH "data/%s.ui", name);
+
+  if (dark)
+    output_name = g_strdup_printf ("%s-dark.png", name);
+  else
+    output_name = g_strdup_printf ("%s.png", name);
+
+  output_file = g_file_get_child (output_dir, output_name);
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  if (dark)
+    adw_style_manager_set_color_scheme (adw_style_manager_get_default (),
+                                        ADW_COLOR_SCHEME_FORCE_DARK);
+  else
+    adw_style_manager_set_color_scheme (adw_style_manager_get_default (),
+                                        ADW_COLOR_SCHEME_FORCE_LIGHT);
+
+  builder = gtk_builder_new_from_resource (ui_path);
+  object = gtk_builder_get_object (builder, "widget");
+
+  g_assert (GTK_IS_WIDGET (object));
+
+  data = g_new (ScreenshotData, 1);
+  data->widget = GTK_WIDGET (object);
+
+  if (GTK_IS_WINDOW (object)) {
+    window = GTK_WIDGET (object);
+  } else {
+    window = gtk_window_new ();
+    gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
+    gtk_window_set_child (GTK_WINDOW (window), data->widget);
+  }
+
+  data->paintable = gtk_widget_paintable_new (data->widget);
+  data->name = g_file_get_path (output_file);
+  data->provider = load_css ("style");
+
+  g_signal_connect_swapped (data->paintable, "invalidate-contents",
+                            G_CALLBACK (draw_paintable), data);
+
+  gtk_window_present (GTK_WINDOW (window));
+
+  g_main_loop_run (loop);
+  g_main_loop_unref (loop);
+}
+
+static inline char *
+get_shortname (const char *basename)
+{
+  const char *first_period = strstr (basename, ".");
+
+  if (first_period)
+    return g_strndup (basename, first_period - basename);
+
+  return g_strdup (basename);
+}
+
+static void
+init_libadwaita (void)
+{
+  adw_init ();
+
+  g_object_set (gtk_settings_get_default (),
+                "gtk-font-name", "Cantarell 11",
+                "gtk-icon-theme-name", "Adwaita",
+                "gtk-decoration-layout", ":close",
+                "gtk-hint-font-metrics", TRUE,
+                NULL);
+}
+
+static void
+run_screenshot (GFile *output_dir)
+{
+  g_autoptr (GError) error = NULL;
+  g_auto (GStrv) children = NULL;
+  int i = -1;
+
+  children =
+    g_resources_enumerate_children (RESOURCE_PATH "data",
+                                    G_RESOURCE_LOOKUP_FLAGS_NONE,
+                                    &error);
+  if (error) {
+    g_critical ("Couldn't enumerate children: %s", error->message);
+    return;
+  }
+
+  while (children[++i]) {
+    g_autofree char *shortname = get_shortname (children[i]);
+
+    g_print ("Processing %s\n", shortname);
+    take_screenshot (shortname, FALSE, output_dir);
+    take_screenshot (shortname, TRUE, output_dir);
+  }
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  GOptionContext *context = g_option_context_new ("PATH");
+  g_autoptr (GFile) output_dir = NULL;
+  g_autoptr (GError) error = NULL;
+
+  g_option_context_parse (context, &argc, &argv, NULL);
+
+  if (argc < 2 || !argv[1]) {
+    g_printerr ("%s\n", g_option_context_get_help (context, FALSE, NULL));
+
+    return 1;
+  }
+
+  output_dir = g_file_new_for_path (argv[1]);
+
+  if (!g_file_query_exists (output_dir, NULL)) {
+    g_file_make_directory_with_parents (output_dir, NULL, &error);
+    if (G_UNLIKELY (error != NULL)) {
+      g_critical ("Failed to create output directory: %s", error->message);
+
+      return 1;
+    }
+  }
+
+  init_libadwaita ();
+  run_screenshot (output_dir);
+
+  return 0;
+}
diff --git a/doc/tools/screenshot.gresources.xml b/doc/tools/screenshot.gresources.xml
new file mode 100644
index 00000000..2df7b63a
--- /dev/null
+++ b/doc/tools/screenshot.gresources.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/Adwaita/Screenshot">
+    <file compressed="true">style.css</file>
+  </gresource>
+</gresources>
diff --git a/doc/tools/style.css b/doc/tools/style.css
new file mode 100644
index 00000000..e69de29b


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]