]> git.cworth.org Git - grrobot/blobdiff - src/grr_icon.c
grrobot will now load SVG icons from /share/grrobot/*.svg
[grrobot] / src / grr_icon.c
index 999f2a6845e7ec69181e7b59b13bc03e267dc6f2..405dfb08e7ff11469491190f600a6e1987dfda3d 100644 (file)
  * Author: Carl Worth <carl@theworths.org>
  */
 
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include "grr_icon.h"
-#include "grr_icon_svg.h"
+#include "grr_util.h"
+#include "svg/grr_icon_svg.h"
 
 struct {
     int type;
     char *name;
     char *svg;
-} icons[] = {
-    { RR_ROBOT_BLUE,
-      "robot_blue",            GRR_ICON_SVG_ROBOT_BLUE },
-    { RR_ROBOT_GREEN,
-      "robot_green",           GRR_ICON_SVG_ROBOT_GREEN },
-    { RR_ROBOT_RED,
-      "robot_red",             GRR_ICON_SVG_ROBOT_RED },
-    { RR_ROBOT_YELLOW,
-      "robot_yellow",          GRR_ICON_SVG_ROBOT_YELLOW },
-
-    { RR_TARGET_BLUE_CIRCLE,
-      "target_blue_circle",    GRR_ICON_SVG_TARGET_BLUE_CIRCLE },
-    { RR_TARGET_BLUE_OCTAGON,
-      "target_blue_octagon",   GRR_ICON_SVG_TARGET_BLUE_OCTAGON },
-    { RR_TARGET_BLUE_SQUARE,
-      "target_blue_square",    GRR_ICON_SVG_TARGET_BLUE_SQUARE },
-    { RR_TARGET_BLUE_TRIANGLE,
-      "target_blue_triangle",  GRR_ICON_SVG_TARGET_BLUE_TRIANGLE },
-
-    { RR_TARGET_GREEN_CIRCLE,
-      "target_green_circle",   GRR_ICON_SVG_TARGET_GREEN_CIRCLE },
-    { RR_TARGET_GREEN_OCTAGON,
-      "target_green_octagon",  GRR_ICON_SVG_TARGET_GREEN_OCTAGON },
-    { RR_TARGET_GREEN_SQUARE,
-      "target_green_square",   GRR_ICON_SVG_TARGET_GREEN_SQUARE },
-    { RR_TARGET_GREEN_TRIANGLE,
-      "target_green_triangle", GRR_ICON_SVG_TARGET_GREEN_TRIANGLE },
-
-    { RR_TARGET_RED_CIRCLE,
-      "target_red_circle",     GRR_ICON_SVG_TARGET_RED_CIRCLE },
-    { RR_TARGET_RED_OCTAGON,
-      "target_red_octagon",    GRR_ICON_SVG_TARGET_RED_OCTAGON },
-    { RR_TARGET_RED_SQUARE,
-      "target_red_square",     GRR_ICON_SVG_TARGET_RED_SQUARE },
-    { RR_TARGET_RED_TRIANGLE,
-      "target_red_triangle",   GRR_ICON_SVG_TARGET_RED_TRIANGLE },
-
-    { RR_TARGET_YELLOW_CIRCLE,
-      "target_yellow_circle",  GRR_ICON_SVG_TARGET_YELLOW_CIRCLE },
-    { RR_TARGET_YELLOW_OCTAGON,
-      "target_yellow_octagon", GRR_ICON_SVG_TARGET_YELLOW_OCTAGON },
-    { RR_TARGET_YELLOW_SQUARE,
-      "target_yellow_square",  GRR_ICON_SVG_TARGET_YELLOW_SQUARE },
-    { RR_TARGET_YELLOW_TRIANGLE,
-      "target_yellow_triangle",        GRR_ICON_SVG_TARGET_YELLOW_TRIANGLE },
-
-    { RR_TARGET_WHIRL,
-      "whirl",                 GRR_ICON_SVG_TARGET_WHIRL },
-
-    { RR_WALL_ABOVE,
-      "wall",                  GRR_ICON_SVG_WALL },
-
-    { RR_CELL,
-      "cell",                  GRR_ICON_SVG_CELL }
+    int svg_len;
+} builtins[] = {
+    { RR_ROBOT_BLUE, "robot_blue",
+      GRR_ICON_SVG_ROBOT_BLUE, sizeof (GRR_ICON_SVG_ROBOT_BLUE) },
+    { RR_ROBOT_GREEN, "robot_green",
+      GRR_ICON_SVG_ROBOT_GREEN, sizeof (GRR_ICON_SVG_ROBOT_GREEN) },
+    { RR_ROBOT_RED, "robot_red",
+      GRR_ICON_SVG_ROBOT_RED, sizeof (GRR_ICON_SVG_ROBOT_RED) },
+    { RR_ROBOT_YELLOW, "robot_yellow",
+      GRR_ICON_SVG_ROBOT_YELLOW, sizeof (GRR_ICON_SVG_ROBOT_YELLOW) },
+
+    { RR_TARGET_BLUE_CIRCLE, "target_blue_circle",
+      GRR_ICON_SVG_TARGET_BLUE_CIRCLE, sizeof (GRR_ICON_SVG_TARGET_BLUE_CIRCLE) },
+    { RR_TARGET_BLUE_OCTAGON, "target_blue_octagon",
+      GRR_ICON_SVG_TARGET_BLUE_OCTAGON, sizeof (GRR_ICON_SVG_TARGET_BLUE_OCTAGON) },
+    { RR_TARGET_BLUE_SQUARE, "target_blue_square",
+      GRR_ICON_SVG_TARGET_BLUE_SQUARE, sizeof (GRR_ICON_SVG_TARGET_BLUE_SQUARE) },
+    { RR_TARGET_BLUE_TRIANGLE, "target_blue_triangle",
+      GRR_ICON_SVG_TARGET_BLUE_TRIANGLE, sizeof (GRR_ICON_SVG_TARGET_BLUE_TRIANGLE) },
+
+    { RR_TARGET_GREEN_CIRCLE, "target_green_circle",
+      GRR_ICON_SVG_TARGET_GREEN_CIRCLE, sizeof (GRR_ICON_SVG_TARGET_GREEN_CIRCLE) },
+    { RR_TARGET_GREEN_OCTAGON, "target_green_octagon",
+      GRR_ICON_SVG_TARGET_GREEN_OCTAGON, sizeof (GRR_ICON_SVG_TARGET_GREEN_OCTAGON) },
+    { RR_TARGET_GREEN_SQUARE, "target_green_square",
+      GRR_ICON_SVG_TARGET_GREEN_SQUARE, sizeof (GRR_ICON_SVG_TARGET_GREEN_SQUARE) },
+    { RR_TARGET_GREEN_TRIANGLE, "target_green_triangle",
+      GRR_ICON_SVG_TARGET_GREEN_TRIANGLE, sizeof (GRR_ICON_SVG_TARGET_GREEN_TRIANGLE) },
+
+    { RR_TARGET_RED_CIRCLE, "target_red_circle",
+      GRR_ICON_SVG_TARGET_RED_CIRCLE, sizeof (GRR_ICON_SVG_TARGET_RED_CIRCLE) },
+    { RR_TARGET_RED_OCTAGON, "target_red_octagon",
+      GRR_ICON_SVG_TARGET_RED_OCTAGON, sizeof (GRR_ICON_SVG_TARGET_RED_OCTAGON) },
+    { RR_TARGET_RED_SQUARE, "target_red_square",
+      GRR_ICON_SVG_TARGET_RED_SQUARE, sizeof (GRR_ICON_SVG_TARGET_RED_SQUARE) },
+    { RR_TARGET_RED_TRIANGLE, "target_red_triangle",
+      GRR_ICON_SVG_TARGET_RED_TRIANGLE, sizeof (GRR_ICON_SVG_TARGET_RED_TRIANGLE) },
+
+    { RR_TARGET_YELLOW_CIRCLE, "target_yellow_circle",
+      GRR_ICON_SVG_TARGET_YELLOW_CIRCLE, sizeof (GRR_ICON_SVG_TARGET_YELLOW_CIRCLE) },
+    { RR_TARGET_YELLOW_OCTAGON, "target_yellow_octagon",
+      GRR_ICON_SVG_TARGET_YELLOW_OCTAGON, sizeof (GRR_ICON_SVG_TARGET_YELLOW_OCTAGON) },
+    { RR_TARGET_YELLOW_SQUARE, "target_yellow_square",
+      GRR_ICON_SVG_TARGET_YELLOW_SQUARE, sizeof (GRR_ICON_SVG_TARGET_YELLOW_SQUARE) },
+    { RR_TARGET_YELLOW_TRIANGLE, "target_yellow_triangle",
+      GRR_ICON_SVG_TARGET_YELLOW_TRIANGLE, sizeof (GRR_ICON_SVG_TARGET_YELLOW_TRIANGLE) },
+
+    { RR_TARGET_WHIRL, "whirl",
+      GRR_ICON_SVG_TARGET_WHIRL, sizeof (GRR_ICON_SVG_TARGET_WHIRL) },
+
+    { RR_WALL_ABOVE, "wall",
+      GRR_ICON_SVG_WALL, sizeof (GRR_ICON_SVG_WALL) },
+
+    { RR_WALL_NONE, "cell",
+      GRR_ICON_SVG_CELL, sizeof (GRR_ICON_SVG_CELL) }
 };
+#define NUM_BUILTINS (sizeof (builtins) / sizeof (builtins[0]))
+
+static char *
+_grr_icon_builtin_name (int type);
 
-typedef struct grr_icon {
-    xsvg_t *xsvg;
-} grr_icon_t;
+static rr_status_t
+_grr_icon_init (grr_icon_t *icon, char *name);
+
+static char *
+_grr_icon_find_file (char *name);
+
+static void
+_grr_icon_find_buffer (char *name, char **buf, int *buflen);
 
 grr_icon_t *
 grr_icon_create (char *name)
 {
-    grr_icon *icon;
+    grr_icon_t *icon;
 
     icon = malloc (sizeof (grr_icon_t));
     if (icon == NULL)
@@ -110,12 +127,13 @@ _grr_icon_init (grr_icon_t *icon, char *name)
 {
     xsvg_status_t status;
     char *file, *buf;
+    int buflen;
 
     status = xsvg_create (&icon->xsvg);
     if (status)
        return RR_STATUS_NO_MEMORY;
 
-    file = grr_icon_find_file (name);
+    file = _grr_icon_find_file (name);
 
     if (file) {
        status = xsvg_parse_file (icon->xsvg, file);
@@ -127,13 +145,15 @@ _grr_icon_init (grr_icon_t *icon, char *name)
        free (file);
     }
 
-    buf = grr_icon_find_buffer (name);
-    status = xsvg_parse_buffer (icon->xsvg, buf, strlen (buf));
+    _grr_icon_find_buffer (name, &buf, &buflen);
+    status = xsvg_parse_buffer (icon->xsvg, buf, buflen);
     if (status) {
        fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name);
        return RR_STATUS_PARSE_ERROR;
     }
 
+    icon->surface = NULL;
+
     return RR_STATUS_SUCCESS;
 }
 
@@ -146,12 +166,93 @@ _grr_icon_find_file (char *name)
     char *file;
     struct stat stat_buf;
 
-    rr_string_sprintf_alloc (&file, "%s/%s", GRR_ICON_DIR, name);
+    grr_sprintf_alloc (&file, "%s/%s.svg", GRR_ICON_DIR, name);
     if (file == NULL)
        return NULL;
 
     err = stat (file, &stat_buf);
-    if (err == 0 && S_ISREG (state.st_mode))
+    if (err == 0 && S_ISREG (stat_buf.st_mode))
        return (file);
     free (file);
+
+    return NULL;
+}
+
+static void
+_grr_icon_find_buffer (char *name, char **buf, int *buflen)
+{
+    int i;
+
+    for (i=0; i < NUM_BUILTINS; i++){
+       if (strcmp (builtins[i].name, name) == 0) {
+           *buf = builtins[i].svg;
+           *buflen = builtins[i].svg_len;
+           return;
+       }
+    }
+
+    *buf = "";
+    *buflen = 0;
+}
+
+static char *
+_grr_icon_builtin_name (int type)
+{
+    int i;
+
+    for (i=0; i < NUM_BUILTINS; i++)
+       if (builtins[i].type == type)
+           return builtins[i].name;
+
+    return "";
+}
+
+char *
+grr_icon_robot_name (rr_robot_t robot)
+{
+    return _grr_icon_builtin_name (robot);
+}
+
+char *
+grr_icon_target_name (rr_target_t target)
+{
+    return _grr_icon_builtin_name (target);
+}
+
+void
+grr_icon_draw (grr_icon_t *icon, XrState *xrs)
+{
+    xsvg_status_t status;
+
+    status =  xsvg_render (icon->xsvg, xrs);
+    if (status) {
+       fprintf (stderr, "xsvg_render error\n");
+       return;
+    }
+}
+
+void
+grr_icon_predraw (grr_icon_t *icon, XrState *xrs, int width, int height)
+{
+    if (icon->surface_width != width || icon->surface_height != height) {
+       if (icon->surface)
+           XrSurfaceDestroy (icon->surface);
+       icon->surface_width = width;
+       icon->surface_height = height;
+       icon->surface = XrSurfaceCreateNextTo (XrGetTargetSurface (xrs),
+                                              XrFormatARGB32,
+                                              width, height);
+    }
+
+    XrSave (xrs);
+    XrSetTargetSurface (xrs, icon->surface);
+    grr_icon_draw (icon, xrs);
+    XrRestore (xrs);
+}
+
+void
+grr_icon_draw_predrawn (grr_icon_t *icon, XrState *xrs)
+{
+    if (icon->surface)
+       XrShowSurface (xrs, icon->surface, icon->surface_width, icon->surface_height);
 }