[gnome-robots/snapshot] Migrate drawing to snapshot API




commit c9d71eafb3a46910d3663263ef8956811e7f5e67
Author: Andrey Kutejko <andy128k gmail com>
Date:   Sun Mar 27 17:03:28 2022 +0200

    Migrate drawing to snapshot API

 src/bubble.vala        |  49 +++++++-----
 src/game-area.vala     |  77 +++++++------------
 src/graphics.vala      |   1 -
 src/image.vala         |  33 ++++++++
 src/meson.build        |   3 +-
 src/preimage.vala      | 200 -------------------------------------------------
 src/scores.vala        |   1 -
 src/svg-paintable.vala |  77 +++++++++++++++++++
 src/theme.vala         |  37 +++++----
 9 files changed, 189 insertions(+), 289 deletions(-)
---
diff --git a/src/bubble.vala b/src/bubble.vala
index 762f408..6a5963c 100644
--- a/src/bubble.vala
+++ b/src/bubble.vala
@@ -17,32 +17,43 @@
  * For more details see the file COPYING.
  */
 
-using Gtk;
 using Gdk;
-using Cairo;
+using Graphene;
 
 public class Bubble {
-    private Pixbuf pixbuf;
-
-    public int width {
-        get { return pixbuf.width / 2; }
-    }
-
-    public int height {
-        get { return pixbuf.height / 2; }
-    }
+    private Paintable paintable;
 
     public Bubble.from_file (string filename) throws Error {
-        pixbuf = new Pixbuf.from_file (filename);
+        paintable = image_from_file (filename);
     }
 
-    public void draw (Context cr, int x, int y) {
-        int clip_x = x < width ? x : x - width;
-        int clip_y = y < height ? y : y - height;
-
-        cairo_set_source_pixbuf (cr, pixbuf, x - width, y - height);
-        cr.rectangle (clip_x, clip_y, width, height);
-        cr.fill ();
+    public void draw (Gtk.Snapshot snapshot, float x, float y) {
+        var width = paintable.get_intrinsic_width ();
+        var height = paintable.get_intrinsic_height ();
+
+        var bubble_width = width / 2;
+        var bubble_height = height / 2;
+
+        var clip_rect = Rect () {
+            origin = Point () {
+                x = x < bubble_width ? x : x - bubble_width,
+                y = y < bubble_height ? y : y - bubble_height,
+            },
+            size = Size () {
+                width = bubble_width,
+                height = bubble_height,
+            },
+        };
+
+        snapshot.push_clip (clip_rect);
+        snapshot.save ();
+        snapshot.translate (Point () {
+            x = x - bubble_width,
+            y = y - bubble_height,
+        });
+        paintable.snapshot (snapshot, width, height);
+        snapshot.restore ();
+        snapshot.pop ();
     }
 }
 
diff --git a/src/game-area.vala b/src/game-area.vala
index c64ea66..61a5f90 100644
--- a/src/game-area.vala
+++ b/src/game-area.vala
@@ -19,9 +19,9 @@
 
 using Gtk;
 using Gdk;
-using Cairo;
+using Graphene;
 
-public class GameArea : DrawingArea {
+public class GameArea : Widget {
 
     const int MINIMUM_TILE_WIDTH = 8;
     const int MINIMUM_TILE_HEIGHT = 8;
@@ -95,8 +95,6 @@ public class GameArea : DrawingArea {
 
         game.config = game_configs.find_by_name (properties.selected_config) ?? game_configs[0];
 
-        set_draw_func ((_area, cr, width, height) => draw_cb (cr, width, height));
-
         click_controller = new GestureClick ();
         click_controller.pressed.connect ((n_pressed, x, y) => mouse_cb (n_pressed, x, y));
         add_controller (click_controller);
@@ -145,92 +143,75 @@ public class GameArea : DrawingArea {
         Source.remove (timer_id);
     }
 
-    private struct Size {
-        int width;
-        int height;
-    }
-
     private Size tile_size () {
-        Allocation allocation;
-        get_allocation (out allocation);
         return Size () {
-            width = allocation.width / game.arena.width,
-            height = allocation.height / game.arena.height
+            width = get_width () / game.arena.width,
+            height = get_height () / game.arena.height
         };
     }
 
-    private bool draw_cb (Context cr, int _width, int _height) {
+    public override void snapshot (Gtk.Snapshot snapshot) {
         Size tile_size = tile_size ();
 
         for (int j = 0; j < game.arena.height; j++) {
             for (int i = 0; i < game.arena.width; i++) {
-                draw_object (i, j, game.arena[i, j], tile_size, cr);
+                var tile_rect = Rect () {
+                    origin = Point () { x = i * tile_size.width, y = j * tile_size.height },
+                    size = tile_size,
+                };
+
+                var color = ((i + j) % 2 != 0) ? dark_background : light_background;
+                snapshot.append_color (color, tile_rect);
+
+                draw_object (i, j, game.arena[i, j], snapshot, tile_rect);
             }
         }
 
         if (game.splat != null) {
-            assets.splat_bubble.draw (cr,
+            assets.splat_bubble.draw (snapshot,
                                       game.splat.x * tile_size.width + 8,
                                       game.splat.y * tile_size.height + 8);
         }
 
         switch (game.state) {
         case Game.State.DEAD:
-            assets.aieee_bubble.draw (cr,
+            assets.aieee_bubble.draw (snapshot,
                                       game.player.x * tile_size.width + 8,
                                       game.player.y * tile_size.height + 4);
             break;
         case Game.State.COMPLETE:
-            assets.yahoo_bubble.draw (cr,
+            assets.yahoo_bubble.draw (snapshot,
                                       game.player.x * tile_size.width + 8,
                                       game.player.y * tile_size.height + 4);
             break;
         default:
             break;
         }
-
-        return true;
     }
 
-    private void draw_object (int x, int y, ObjectType type, Size tile_size, Context cr) {
-        if ((x + y) % 2 != 0) {
-            cairo_set_source_rgba (cr, dark_background);
-        } else {
-            cairo_set_source_rgba (cr, light_background);
-        }
-
-        x *= tile_size.width;
-        y *= tile_size.height;
-
-        cr.rectangle (x, y, tile_size.width, tile_size.height);
-        cr.fill ();
+    private void draw_object (int x, int y, ObjectType type, Gtk.Snapshot snapshot, Rect tile_rect) {
+        int animation = object_animation_frame (type);
+        theme.draw_object (type, animation, snapshot, tile_rect);
+    }
 
-        int animation = 0;
+    private int object_animation_frame (ObjectType type) {
         switch (type) {
         case ObjectType.PLAYER:
             if (game.state != Game.State.DEAD) {
-                animation = player_animation.frame;
+                return player_animation.frame;
             } else {
-                animation = player_dead_animation.frame;
+                return player_dead_animation.frame;
             }
-            break;
         case ObjectType.ROBOT1:
-            animation = robot1_animation.frame;
-            break;
+            return robot1_animation.frame;
         case ObjectType.ROBOT2:
-            animation = robot2_animation.frame;
-            break;
+            return robot2_animation.frame;
         case ObjectType.HEAP:
-            animation = 0;
-            break;
+            return 0;
         case ObjectType.NONE:
-            break;
+        default:
+            return 0;
         }
-
-        cr.save ();
-        cr.translate (x, y);
-        theme.draw_object (type, animation, cr, tile_size.width, tile_size.height);
-        cr.restore ();
     }
 
     private bool timer_cb () {
diff --git a/src/graphics.vala b/src/graphics.vala
index 83dd8e3..e1eea67 100644
--- a/src/graphics.vala
+++ b/src/graphics.vala
@@ -18,7 +18,6 @@
  */
 
 using Gdk;
-using Cairo;
 
 public RGBA string_to_rgba (string color) {
     RGBA rgba = RGBA ();
diff --git a/src/image.vala b/src/image.vala
new file mode 100644
index 0000000..a4f5c7e
--- /dev/null
+++ b/src/image.vala
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2022 Andrey Kutejko <andy128k gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more details see the file COPYING.
+ */
+
+using Graphene;
+using Gdk;
+using Rsvg;
+
+public Paintable image_from_file (string filename) throws GLib.Error {
+    try {
+        var rsvg_handle = new Handle.from_file (filename);
+        return new SvgPaintable (rsvg_handle);
+    } catch (GLib.Error e) {
+        var pixbuf = new Pixbuf.from_file (filename);
+        return Texture.for_pixbuf (pixbuf);
+    }
+}
+
diff --git a/src/meson.build b/src/meson.build
index 6e341da..9cfad12 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -14,7 +14,8 @@ sources = files(
     'image-suffix-list.vala',
     'themes.vala',
     'theme.vala',
-    'preimage.vala',
+    'svg-paintable.vala',
+    'image.vala',
     'animation.vala',
     'controls.vala',
     'game-config.vala',
diff --git a/src/scores.vala b/src/scores.vala
index 576dd84..bfa2c39 100644
--- a/src/scores.vala
+++ b/src/scores.vala
@@ -18,7 +18,6 @@
  */
 
 using Gtk;
-using Cairo;
 using Games;
 
 public class RobotsScoresContext : Games.Scores.Context {
diff --git a/src/svg-paintable.vala b/src/svg-paintable.vala
new file mode 100644
index 0000000..21cef2e
--- /dev/null
+++ b/src/svg-paintable.vala
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2022 Andrey Kutejko <andy128k gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more details see the file COPYING.
+ */
+
+using Gdk;
+using Graphene;
+using Rsvg;
+
+class SvgPaintable : Object, Gdk.Paintable {
+
+    private Handle rsvg_handle;
+
+    public SvgPaintable (Handle rsvg_handle) {
+        this.rsvg_handle = rsvg_handle;
+    }
+
+    public void snapshot (Gdk.Snapshot snapshot,
+                          double width,
+                          double height
+    ) {
+        var rect = Rect () {
+            origin = Point.zero (),
+            size = Size () { width = (float) width, height = (float) height },
+        };
+
+        var gtk_snapshot = (Gtk.Snapshot) snapshot;
+        var cr = gtk_snapshot.append_cairo (rect);
+
+        try {
+            var rsvg_rect = Rsvg.Rectangle () {
+                x = 0,
+                y = 0,
+                width = width,
+                height = height,
+            };
+            rsvg_handle.render_document (cr, rsvg_rect);
+        } catch (GLib.Error error) {
+            critical ("%s", error.message);
+        }
+    }
+
+    public override int get_intrinsic_width () {
+        double width;
+        double height;
+
+        if (!rsvg_handle.get_intrinsic_size_in_pixels (out width, out height)) {
+            return 0;
+        }
+        return (int) Math.ceil (width);
+    }
+
+    public override int get_intrinsic_height () {
+        double width;
+        double height;
+
+        if (!rsvg_handle.get_intrinsic_size_in_pixels (out width, out height)) {
+            return 0;
+        }
+        return (int) Math.ceil (height);
+    }
+}
+
diff --git a/src/theme.vala b/src/theme.vala
index 7918e62..7b22249 100644
--- a/src/theme.vala
+++ b/src/theme.vala
@@ -17,8 +17,10 @@
  * For more details see the file COPYING.
  */
 
+using Gtk;
+using Graphene;
 using Gdk;
-using Cairo;
+using Rsvg;
 
 public class Theme {
 
@@ -38,25 +40,20 @@ public class Theme {
         NUM_HEAP_ANIMATIONS = COUNT - HEAP_START,
     }
 
-    private GamesPreimage preimage;
-    private Pixbuf pixbuf;
-    private int tile_width;
-    private int tile_height;
+    private Paintable paintable;
     public string path { get; private set; }
     public string name { get; private set; }
 
-    public Theme.from_file (string path, string name) throws Error {
-        preimage = new GamesPreimage.from_file (path);
-        pixbuf = null;
+    public Theme.from_file (string path, string name) throws GLib.Error {
+        paintable = image_from_file (path);
         this.path = path;
         this.name = name;
     }
 
     public void draw_object (ObjectType type,
                              int frame_no,
-                             Context cr,
-                             int width,
-                             int height
+                             Gtk.Snapshot snapshot,
+                             Rect rect
     ) {
         int tile_no = -1;
         switch (type) {
@@ -76,15 +73,17 @@ public class Theme {
             return;
         }
 
-        if (pixbuf == null || tile_width != width || tile_height != height) {
-            tile_width = width;
-            tile_height = height;
-            pixbuf = preimage.render (Frames.COUNT * tile_width, tile_height);
-        }
+        snapshot.push_clip (rect);
+
+        snapshot.save ();
+        snapshot.translate (Point () {
+            x = rect.origin.x - tile_no * rect.size.width,
+            y = rect.origin.y,
+        });
+        paintable.snapshot (snapshot, rect.size.width * Frames.COUNT, rect.size.height);
+        snapshot.restore ();
 
-        cairo_set_source_pixbuf (cr, pixbuf, - tile_no * tile_width, 0);
-        cr.rectangle (0, 0, tile_width, tile_height);
-        cr.fill ();
+        snapshot.pop ();
     }
 }
 


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