diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-10-06 15:12:09 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-10-06 15:12:09 -0400 |
commit | 5a9547da414bd11e678baf244aa26e48a7289800 (patch) | |
tree | e55dcd1909a993685a0f7bdb30646bd7300847bc | |
parent | 25cbc1a15a028feb404405854add02974544c203 (diff) | |
download | gtk+-svg-demo.tar.gz |
gtk-demo: Add an svg paintable demosvg-demo
It is a little annoying that this demo will not show up
if we don't find librsvg, but I think showing how easy
this paintable is outweights the annoyance.
-rw-r--r-- | demos/gtk-demo/demo.gresource.xml | 4 | ||||
-rw-r--r-- | demos/gtk-demo/meson.build | 7 | ||||
-rw-r--r-- | demos/gtk-demo/org.gtk.gtk4.NodeEditor.Devel.svg | 88 | ||||
-rw-r--r-- | demos/gtk-demo/paintable_svg.c | 241 |
4 files changed, 340 insertions, 0 deletions
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml index fa03214cc5..e3f0a034c3 100644 --- a/demos/gtk-demo/demo.gresource.xml +++ b/demos/gtk-demo/demo.gresource.xml @@ -204,6 +204,9 @@ <file>demo3widget.h</file> <file>demo3widget.ui</file> </gresource> + <gresource prefix="/paintable_svg"> + <file>org.gtk.gtk4.NodeEditor.Devel.svg</file> + </gresource> <gresource prefix="/shortcuts"> <file>shortcuts.ui</file> <file>shortcuts-builder.ui</file> @@ -299,6 +302,7 @@ <file>paintable_animated.c</file> <file>paintable_emblem.c</file> <file>paintable_mediastream.c</file> + <file>paintable_svg.c</file> <file>panes.c</file> <file>password_entry.c</file> <file>peg_solitaire.c</file> diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build index 095a64ed63..2d1efc4170 100644 --- a/demos/gtk-demo/meson.build +++ b/demos/gtk-demo/meson.build @@ -130,6 +130,13 @@ if os_unix demos += files('pagesetup.c') endif +librsvg_dep = dependency('librsvg-2.0', version: '>= 2.46.0', required: false) + +if librsvg_dep.found() + demos += files('paintable_svg.c') + gtkdemo_deps += [ librsvg_dep ] +endif + gtkdemo_args = [ '-DGDK_DISABLE_DEPRECATED', '-DGTK_DISABLE_DEPRECATED', ] demos_h = custom_target('gtk4 demo header', diff --git a/demos/gtk-demo/org.gtk.gtk4.NodeEditor.Devel.svg b/demos/gtk-demo/org.gtk.gtk4.NodeEditor.Devel.svg new file mode 100644 index 0000000000..7d693fa8c6 --- /dev/null +++ b/demos/gtk-demo/org.gtk.gtk4.NodeEditor.Devel.svg @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <linearGradient id="a" gradientUnits="userSpaceOnUse" x1="43.000351" x2="85.000351" y1="39.000164" y2="39.000164"> + <stop offset="0" stop-color="#26a269"/> + <stop offset="0.0934161" stop-color="#84e3b7"/> + <stop offset="0.330831" stop-color="#26a269"/> + <stop offset="0.686952" stop-color="#26a269"/> + <stop offset="0.89736" stop-color="#175e3c"/> + <stop offset="1" stop-color="#26a269"/> + </linearGradient> + <linearGradient id="b" gradientUnits="userSpaceOnUse"> + <stop offset="0" stop-color="#c0bfbc"/> + <stop offset="0.154754" stop-color="#ffffff"/> + <stop offset="0.433722" stop-color="#bdbbb5"/> + <stop offset="0.650505" stop-color="#c1c0ba"/> + <stop offset="0.825253" stop-color="#ffffff"/> + <stop offset="1" stop-color="#c0bfbc"/> + </linearGradient> + <linearGradient id="c" gradientTransform="matrix(0.0811899 -0.046875 0.069079 0.119648 307.03142 127.069456)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/> + <linearGradient id="d" gradientTransform="matrix(-0.0811899 -0.046875 -0.069079 0.119648 -177.242852 127.069447)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/> + <linearGradient id="e" gradientUnits="userSpaceOnUse" x1="14" x2="56" y1="94.999964" y2="94.999964"> + <stop offset="0" stop-color="#813d9c"/> + <stop offset="0.109119" stop-color="#b378ca"/> + <stop offset="0.241583" stop-color="#813d9c"/> + <stop offset="0.731841" stop-color="#813d9c"/> + <stop offset="0.872163" stop-color="#4d255d"/> + <stop offset="1" stop-color="#813d9c"/> + </linearGradient> + <linearGradient id="f" gradientUnits="userSpaceOnUse" x1="72" x2="114" y1="94.999964" y2="94.999964"> + <stop offset="0" stop-color="#e66100"/> + <stop offset="0.0678478" stop-color="#ff903e"/> + <stop offset="0.168852" stop-color="#e66100"/> + <stop offset="0.886626" stop-color="#e66100"/> + <stop offset="1" stop-color="#9d4200"/> + </linearGradient> + <clipPath id="g"> + <rect height="128" width="128"/> + </clipPath> + <clipPath id="h"> + <rect height="128" width="128"/> + </clipPath> + <filter id="i" height="100%" width="100%" x="0%" y="0%"> + <feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/> + </filter> + <mask id="j"> + <g clip-path="url(#h)" filter="url(#i)"> + <g clip-path="url(#g)"> + <path d="m 51 18 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/> + <path d="m 51 12 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#57e389"/> + <path d="m 76.976562 55.453125 c 1.480469 -0.855469 3.371094 -0.347656 4.226563 1.132813 l 6.742187 11.679687 c 0.855469 1.480469 0.347657 3.371094 -1.132812 4.226563 c -1.480469 0.851562 -3.371094 0.347656 -4.226562 -1.132813 l -6.742188 -11.679687 c -0.855469 -1.480469 -0.347656 -3.371094 1.132812 -4.226563 z m 0 0" fill="url(#c)"/> + <path d="m 52.8125 55.453125 c -1.480469 -0.855469 -3.371094 -0.347656 -4.226562 1.132813 l -6.742188 11.679687 c -0.855469 1.480469 -0.347656 3.371094 1.132812 4.226563 c 1.480469 0.851562 3.371094 0.347656 4.226563 -1.132813 l 6.742187 -11.679687 c 0.855469 -1.480469 0.347657 -3.371094 -1.132812 -4.226563 z m 0 0" fill="url(#d)"/> + <path d="m 22 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#e)"/> + <path d="m 22 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#dc8add"/> + <path d="m 80 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#f)"/> + <path d="m 80 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#ffa348"/> + </g> + </g> + </mask> + <mask id="k"> + <g filter="url(#i)"> + <rect fill-opacity="0.8" height="128" width="128"/> + </g> + </mask> + <linearGradient id="l" gradientTransform="matrix(0 0.37 -0.98462 0 295.38501 -30.360001)" gradientUnits="userSpaceOnUse" x1="300" x2="428" y1="235" y2="235"> + <stop offset="0" stop-color="#f9f06b"/> + <stop offset="1" stop-color="#f5c211"/> + </linearGradient> + <clipPath id="m"> + <rect height="128" width="128"/> + </clipPath> + <clipPath id="n"> + <rect height="128" width="128"/> + </clipPath> + <path d="m 51 18 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/> + <path d="m 51 12 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#57e389"/> + <path d="m 76.976562 55.453125 c 1.480469 -0.855469 3.371094 -0.347656 4.226563 1.132813 l 6.742187 11.679687 c 0.855469 1.480469 0.347657 3.371094 -1.132812 4.226563 c -1.480469 0.851562 -3.371094 0.347656 -4.226562 -1.132813 l -6.742188 -11.679687 c -0.855469 -1.480469 -0.347656 -3.371094 1.132812 -4.226563 z m 0 0" fill="url(#c)"/> + <path d="m 52.8125 55.453125 c -1.480469 -0.855469 -3.371094 -0.347656 -4.226562 1.132813 l -6.742188 11.679687 c -0.855469 1.480469 -0.347656 3.371094 1.132812 4.226563 c 1.480469 0.851562 3.371094 0.347656 4.226563 -1.132813 l 6.742187 -11.679687 c 0.855469 -1.480469 0.347657 -3.371094 -1.132812 -4.226563 z m 0 0" fill="url(#d)"/> + <path d="m 22 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#e)"/> + <path d="m 22 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#dc8add"/> + <path d="m 80 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#f)"/> + <path d="m 80 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#ffa348"/> + <g clip-path="url(#n)" mask="url(#j)"> + <g clip-path="url(#m)" mask="url(#k)"> + <path d="m 128 80.640625 v 47.359375 h -128 v -47.359375 z m 0 0" fill="url(#l)"/> + <path d="m 13.308594 80.640625 l 47.355468 47.359375 h 21.214844 l -47.359375 -47.359375 z m 42.421875 0 l 47.363281 47.359375 h 21.214844 l -47.363282 -47.359375 z m 42.429687 0 l 29.839844 29.839844 v -21.210938 l -8.628906 -8.628906 z m -98.160156 7.90625 v 21.214844 l 18.238281 18.238281 h 21.214844 z m 0 0"/> + </g> + </g> +</svg> diff --git a/demos/gtk-demo/paintable_svg.c b/demos/gtk-demo/paintable_svg.c new file mode 100644 index 0000000000..b2254a2348 --- /dev/null +++ b/demos/gtk-demo/paintable_svg.c @@ -0,0 +1,241 @@ +/* Paintable/SVG + * + * This demo shows wrapping a librsvg RsvgHandle in a GdkPaintable + * to display an SVG image that can be scaled by resizing the window. + * + * This demo relies on librsvg, which GTK itself does not link against. + */ + +#include <gtk/gtk.h> +#include <librsvg/rsvg.h> + +#define SVG_TYPE_PAINTABLE (svg_paintable_get_type ()) + +G_DECLARE_FINAL_TYPE (SvgPaintable, svg_paintable, SVG, PAINTABLE, GObject) + +struct _SvgPaintable +{ + GObject parent_instance; + GFile *file; + RsvgHandle *handle; +}; + +struct _SvgPaintableClass +{ + GObjectClass parent_class; +}; + +enum { + PROP_FILE = 1, + NUM_PROPERTIES +}; + +static void +svg_paintable_snapshot (GdkPaintable *paintable, + GdkSnapshot *snapshot, + double width, + double height) +{ + SvgPaintable *self = SVG_PAINTABLE (paintable); + cairo_t *cr; + GError *error = NULL; + + cr = gtk_snapshot_append_cairo (GTK_SNAPSHOT (snapshot), + &GRAPHENE_RECT_INIT (0, 0, width, height)); + + if (!rsvg_handle_render_document (self->handle, cr, + &(RsvgRectangle) {0, 0, width, height}, + &error)) + { + g_error ("%s", error->message); + } + + cairo_destroy (cr); +} + +static int +svg_paintable_get_intrinsic_width (GdkPaintable *paintable) +{ + SvgPaintable *self = SVG_PAINTABLE (paintable); + RsvgDimensionData data; + + rsvg_handle_get_dimensions (self->handle, &data); + + return data.width; +} + +static int +svg_paintable_get_intrinsic_height (GdkPaintable *paintable) +{ + SvgPaintable *self = SVG_PAINTABLE (paintable); + RsvgDimensionData data; + + rsvg_handle_get_dimensions (self->handle, &data); + + return data.height; +} + +static void +svg_paintable_init_interface (GdkPaintableInterface *iface) +{ + iface->snapshot = svg_paintable_snapshot; + iface->get_intrinsic_width = svg_paintable_get_intrinsic_width; + iface->get_intrinsic_height = svg_paintable_get_intrinsic_height; +} + +G_DEFINE_TYPE_WITH_CODE (SvgPaintable, svg_paintable, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, + svg_paintable_init_interface)) + +static void +svg_paintable_init (SvgPaintable *self) +{ +} + +static void +svg_paintable_dispose (GObject *object) +{ + SvgPaintable *self = SVG_PAINTABLE (object); + + g_clear_object (&self->file); + g_clear_object (&self->handle); + + G_OBJECT_CLASS (svg_paintable_parent_class)->dispose (object); +} + +static void +svg_paintable_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SvgPaintable *self = SVG_PAINTABLE (object); + + switch (prop_id) + { + case PROP_FILE: + { + GFile *file = g_value_get_object (value); + RsvgHandle *handle = rsvg_handle_new_from_gfile_sync (file, + RSVG_HANDLE_FLAGS_NONE, + NULL, + NULL); + rsvg_handle_set_dpi (handle, 90); + + g_set_object (&self->file, file); + g_set_object (&self->handle, handle); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +svg_paintable_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SvgPaintable *self = SVG_PAINTABLE (object); + + switch (prop_id) + { + case PROP_FILE: + g_value_set_object (value, self->file); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + + +static void +svg_paintable_class_init (SvgPaintableClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->dispose = svg_paintable_dispose; + object_class->set_property = svg_paintable_set_property; + object_class->get_property = svg_paintable_get_property; + + g_object_class_install_property (object_class, PROP_FILE, + g_param_spec_object ("file", "File", "File", + G_TYPE_FILE, + G_PARAM_READWRITE)); +} + +static SvgPaintable * +svg_paintable_new (GFile *file) +{ + return g_object_new (SVG_TYPE_PAINTABLE, + "file", file, + NULL); +} + +static void +file_set (GtkFileChooserButton *button, + GtkWidget *picture) +{ + GFile *file; + SvgPaintable *paintable; + + file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button)); + + paintable = svg_paintable_new (file); + gtk_picture_set_paintable (GTK_PICTURE (picture), GDK_PAINTABLE (paintable)); + + g_object_unref (paintable); + g_object_unref (file); +} + +static GtkWidget *window; + +GtkWidget * +do_paintable_svg (GtkWidget *do_widget) +{ + GtkWidget *header; + GtkWidget *picture; + GtkFileFilter *filter; + GtkWidget *button; + GFile *file; + SvgPaintable *paintable; + + if (!window) + { + window = gtk_window_new (); + header = gtk_header_bar_new (); + gtk_window_set_titlebar (GTK_WINDOW (window), header); + gtk_window_set_default_size (GTK_WINDOW (window), 300, 200); + g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); + + button = gtk_file_chooser_button_new ("Select an SVG file", GTK_FILE_CHOOSER_ACTION_OPEN); + filter = gtk_file_filter_new (); + gtk_file_filter_add_mime_type (filter, "image/svg+xml"); + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (button), filter); + gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button); + + picture = gtk_picture_new (); + gtk_picture_set_can_shrink (GTK_PICTURE (picture), TRUE); + gtk_widget_set_size_request (picture, 16, 16); + + g_signal_connect (button, "file-set", G_CALLBACK (file_set), picture); + + gtk_window_set_child (GTK_WINDOW (window), picture); + + file = g_file_new_for_uri ("resource:///paintable_svg/org.gtk.gtk4.NodeEditor.Devel.svg"); + paintable = svg_paintable_new (file); + gtk_picture_set_paintable (GTK_PICTURE (picture), GDK_PAINTABLE (paintable)); + g_object_unref (paintable); + g_object_unref (file); + } + + if (!gtk_widget_get_visible (window)) + gtk_window_present (GTK_WINDOW (window)); + else + gtk_window_destroy (GTK_WINDOW (window)); + + return window; +} |