]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Support svg buttons
authorJohan Malm <jgm323@gmail.com>
Mon, 21 Aug 2023 20:26:08 +0000 (21:26 +0100)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sun, 17 Sep 2023 18:26:41 +0000 (19:26 +0100)
In the theme directory add close-{active,inactive}.svg instead of
close.xbm - and similarly for iconify, menu and max.

.github/workflows/build.yml
README.md
docs/labwc-theme.5.scd
include/button/button-svg.h [new file with mode: 0644]
meson.build
scripts/checkpatch.pl
src/button/button-png.c
src/button/button-svg.c [new file with mode: 0644]
src/button/meson.build
src/theme.c

index 80d9e473891f6aecd6513c4033217f6eef429e2b..caa5d020608b7418fc60578287b28ec0fc7b32be 100644 (file)
@@ -67,7 +67,7 @@ jobs:
           pacman-key --init
           pacman -Syu --noconfirm
           pacman -S --noconfirm git meson clang wlroots libdrm libinput \
-            wayland-protocols cairo pango libxml2 xorg-xwayland
+            wayland-protocols cairo pango libxml2 xorg-xwayland librsvg
 
       - name: Install Debian Testing dependencies
         if: matrix.name == 'Debian'
@@ -77,7 +77,8 @@ jobs:
           apt-get upgrade -y
           apt-get install -y git clang \
             hwdata \
-            libxml2-dev libcairo2-dev libpango1.0-dev
+            libxml2-dev libcairo2-dev libpango1.0-dev \
+            librsvg2-dev
           apt-get build-dep -y wlroots
 
       - name: Install FreeBSD dependencies
@@ -108,6 +109,7 @@ jobs:
             xcb-util-cursor-devel xcb-util-devel xcb-util-image-devel \
             xcb-util-keysyms-devel xcb-util-xrm-devel xorg-server-xwayland \
             hwids \
+            librsvg-devel \
             libglib-devel cairo-devel pango-devel
 
       - name: Build with gcc
index 90ab81c1fcdf4532ea02a6319b8d3f21fd09a113..076221a0d00221abfb5ad840cb8543e80293490a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -151,6 +151,7 @@ Run-time dependencies include:
 
 - wlroots, wayland, libinput, xkbcommon
 - libxml2, cairo, pango, glib-2.0
+- libpng, librsvg-2.0
 - xwayland, xcb (optional)
 
 Build dependencies include:
index 6de7f1cd3e7cd86f541f3aa36f8cd7cf22a86be4..91264acdfc800e81bfbd15809f2a957f386c3acd 100644 (file)
@@ -182,6 +182,7 @@ The image formats listed below are supported. They are listed in order of
 precedence, where the first format in the list is searched for first.
 
 - png
+- svg
 - xbm
 
 By default, buttons are 1-bit xbm (X Bitmaps). These are masks where 0=clear and
diff --git a/include/button/button-svg.h b/include/button/button-svg.h
new file mode 100644 (file)
index 0000000..884a884
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LABWC_BUTTON_SVG_H
+#define LABWC_BUTTON_SVG_H
+
+struct lab_data_buffer;
+
+void button_svg_load(const char *button_name, struct lab_data_buffer **buffer,
+       int size);
+
+#endif /* LABWC_BUTTON_SVG_H */
index b26e2b50c8642d41b96506a5e3218a4f3fa6da4f..53cfc5d04e3ec18009afa61d06df50062be70cef 100644 (file)
@@ -70,6 +70,7 @@ pangocairo = dependency('pangocairo')
 input = dependency('libinput', version: '>=1.14')
 math = cc.find_library('m')
 png = dependency('libpng')
+svg = dependency('librsvg-2.0', version: '>=2.46', required: false)
 
 if get_option('xwayland').enabled() and not wlroots_has_xwayland
        error('no wlroots Xwayland support')
@@ -78,6 +79,8 @@ have_xwayland = xcb.found() and wlroots_has_xwayland
 conf_data = configuration_data()
 conf_data.set10('HAVE_XWAYLAND', have_xwayland)
 
+conf_data.set10('HAVE_RSVG', svg.found())
+
 msgfmt = find_program('msgfmt', required: get_option('nls'))
 if msgfmt.found()
   source_root = meson.current_source_dir()
@@ -106,6 +109,11 @@ labwc_deps = [
   math,
   png,
 ]
+if svg.found()
+  labwc_deps += [
+    svg,
+  ]
+endif
 
 subdir('include')
 subdir('src')
index 98cba37f133c58e757a550e1125f489d183abe39..72b1fba4aa82ada9c87295466850bb2ab5a40fcd 100755 (executable)
@@ -5653,7 +5653,7 @@ sub process {
 #Ignore Page<foo> variants
                            $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
 
-#Ignore some pango and libxml2 CamelCase variants
+#labwc-custom check to ignore some pango/libxml2/etc CamelCase variants
                            $var !~ /^(?:PangoLayout|PangoFontDescription)/ &&
                            $var !~ /^(?:PangoTabArray|PangoRectangle)/ &&
                            $var !~ /^(?:PangoWeight|_PangoFontDescription)/ &&
@@ -5664,6 +5664,7 @@ sub process {
                            $var !~ /^(?:xmlParseMemory)/ &&
                            $var !~ /^(?:xmlFree)/ &&
                            $var !~ /^(?:GString|GError)/ &&
+                           $var !~ /^(?:RsvgRectangle|RsvgHandle)/ &&
                            $var !~ /^(?:XKB_KEY_XF86Switch_VT_1)/ &&
 
 #Ignore SI style variants like nS, mV and dB
index 66cf55352bbbd23a4811c7c02b6474d6e687f085..feceb7ec51dcb4808f1825e1ba846ec0d492a9bf 100644 (file)
@@ -54,7 +54,7 @@ png_load(const char *button_name, struct lab_data_buffer **buffer)
 
        char path[4096] = { 0 };
        button_filename(button_name, path, sizeof(path));
-       if (!file_exists(path) || !ispng(path)) {
+       if (!ispng(path)) {
                return;
        }
 
diff --git a/src/button/button-svg.c b/src/button/button-svg.c
new file mode 100644 (file)
index 0000000..3dab05d
--- /dev/null
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) Johan Malm 2023
+ */
+#define _POSIX_C_SOURCE 200809L
+#include <cairo.h>
+#include <librsvg/rsvg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wlr/util/log.h>
+#include "buffer.h"
+#include "button/button-svg.h"
+#include "button/common.h"
+#include "common/file-helpers.h"
+#include "labwc.h"
+#include "theme.h"
+
+void
+button_svg_load(const char *button_name, struct lab_data_buffer **buffer,
+               int size)
+{
+       if (*buffer) {
+               wlr_buffer_drop(&(*buffer)->base);
+               *buffer = NULL;
+       }
+
+       char filename[4096] = { 0 };
+       button_filename(button_name, filename, sizeof(filename));
+
+       GError *err = NULL;
+       RsvgRectangle viewport = { .width = size, .height = size };
+       RsvgHandle *svg = rsvg_handle_new_from_file(filename, &err);
+       if (err) {
+               wlr_log(WLR_DEBUG, "error reading svg %s-%s\n", filename, err->message);
+               g_error_free(err);
+               /*
+                * rsvg_handle_new_from_file() returns NULL if an error occurs,
+                * so there is no need to free svg here.
+                */
+               return;
+       }
+
+       cairo_surface_t *image = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size, size);
+       cairo_t *cr = cairo_create(image);
+
+       rsvg_handle_render_document(svg, cr, &viewport, &err);
+       if (err) {
+               wlr_log(WLR_ERROR, "error rendering svg %s-%s\n", filename, err->message);
+               g_error_free(err);
+               goto error;
+       }
+
+       if (cairo_surface_status(image)) {
+               wlr_log(WLR_ERROR, "error reading svg button '%s'", filename);
+               goto error;
+       }
+       cairo_surface_flush(image);
+
+       double w = cairo_image_surface_get_width(image);
+       double h = cairo_image_surface_get_height(image);
+       *buffer = buffer_create_cairo((int)w, (int)h, 1.0, /* free_on_destroy */ true);
+       cairo_t *cairo = (*buffer)->cairo;
+       cairo_set_source_surface(cairo, image, 0, 0);
+       cairo_paint_with_alpha(cairo, 1.0);
+
+error:
+       cairo_destroy(cr);
+       cairo_surface_destroy(image);
+       g_object_unref(svg);
+}
index b5b10d2b6703a199d2d73aed1144e9023a08e17a..f0f24e96d26c3868f98c38d183422b020e5e0e49 100644 (file)
@@ -3,3 +3,10 @@ labwc_sources += files(
   'button-xbm.c',
   'common.c',
 )
+
+if svg.found()
+  labwc_sources += files(
+    'button-svg.c',
+  )
+endif
+
index 30d50ebe7cdd5045bffd325405bd5a4eb72e9030..55d6a2b22f5aed3567cd33f7469ecaf4fc152c63 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #define _POSIX_C_SOURCE 200809L
+#include "config.h"
 #include <cairo.h>
 #include <ctype.h>
 #include <drm_fourcc.h>
 #include "common/string-helpers.h"
 #include "config/rcxml.h"
 #include "button/button-png.h"
+
+#if HAVE_RSVG
+#include "button/button-svg.h"
+#endif
+
 #include "button/button-xbm.h"
 #include "theme.h"
 #include "buffer.h"
@@ -39,6 +45,15 @@ struct button {
        } active, inactive;
 };
 
+static void
+drop(struct lab_data_buffer **buffer)
+{
+       if (*buffer) {
+               wlr_buffer_drop(&(*buffer)->base);
+               *buffer = NULL;
+       }
+}
+
 static void
 load_buttons(struct theme *theme)
 {
@@ -97,13 +112,29 @@ load_buttons(struct theme *theme)
        for (size_t i = 0; i < sizeof(buttons) / sizeof(buttons[0]); ++i) {
                struct button *b = &buttons[i];
 
+               drop(b->active.buffer);
+               drop(b->inactive.buffer);
+
                /* Try png icon first */
                snprintf(filename, sizeof(filename), "%s-active.png", b->name);
                png_load(filename, b->active.buffer);
                snprintf(filename, sizeof(filename), "%s-inactive.png", b->name);
                png_load(filename, b->inactive.buffer);
 
-               /* If there were no png buttons, use xbm */
+#if HAVE_RSVG
+               /* Then try svg icon */
+               int size = theme->title_height - 2 * theme->padding_height;
+               if (!*b->active.buffer) {
+                       snprintf(filename, sizeof(filename), "%s-active.svg", b->name);
+                       button_svg_load(filename, b->active.buffer, size);
+               }
+               if (!*b->inactive.buffer) {
+                       snprintf(filename, sizeof(filename), "%s-inactive.svg", b->name);
+                       button_svg_load(filename, b->inactive.buffer, size);
+               }
+#endif
+
+               /* If there were no png/svg buttons, use xbm */
                snprintf(filename, sizeof(filename), "%s.xbm", b->name);
                if (!*b->active.buffer) {
                        button_xbm_load(filename, b->active.buffer,