]> git.cworth.org Git - grrobot/blob - src/grr_icon.c
grrobot will now load SVG icons from /share/grrobot/*.svg
[grrobot] / src / grr_icon.c
1 /* grrobot - Ricochet Robot using GTK+ and Xr
2  *
3  * Copyright © 2003 Carl Worth
4  *
5  * Permission to use, copy, modify, distribute, and sell this software
6  * and its documentation for any purpose is hereby granted without
7  * fee, provided that the above copyright notice appear in all copies
8  * and that both that copyright notice and this permission notice
9  * appear in supporting documentation, and that the name of Carl Worth
10  * not be used in advertising or publicity pertaining to distribution
11  * of the software without specific, written prior permission.
12  * Carl Worth makes no representations about the suitability of this
13  * software for any purpose.  It is provided "as is" without express
14  * or implied warranty.
15  * 
16  * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
18  * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
20  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Author: Carl Worth <carl@theworths.org>
25  */
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32
33 #include "grr_icon.h"
34 #include "grr_util.h"
35 #include "svg/grr_icon_svg.h"
36
37 struct {
38     int type;
39     char *name;
40     char *svg;
41     int svg_len;
42 } builtins[] = {
43     { RR_ROBOT_BLUE, "robot_blue",
44       GRR_ICON_SVG_ROBOT_BLUE, sizeof (GRR_ICON_SVG_ROBOT_BLUE) },
45     { RR_ROBOT_GREEN, "robot_green",
46       GRR_ICON_SVG_ROBOT_GREEN, sizeof (GRR_ICON_SVG_ROBOT_GREEN) },
47     { RR_ROBOT_RED, "robot_red",
48       GRR_ICON_SVG_ROBOT_RED, sizeof (GRR_ICON_SVG_ROBOT_RED) },
49     { RR_ROBOT_YELLOW, "robot_yellow",
50       GRR_ICON_SVG_ROBOT_YELLOW, sizeof (GRR_ICON_SVG_ROBOT_YELLOW) },
51
52     { RR_TARGET_BLUE_CIRCLE, "target_blue_circle",
53       GRR_ICON_SVG_TARGET_BLUE_CIRCLE, sizeof (GRR_ICON_SVG_TARGET_BLUE_CIRCLE) },
54     { RR_TARGET_BLUE_OCTAGON, "target_blue_octagon",
55       GRR_ICON_SVG_TARGET_BLUE_OCTAGON, sizeof (GRR_ICON_SVG_TARGET_BLUE_OCTAGON) },
56     { RR_TARGET_BLUE_SQUARE, "target_blue_square",
57       GRR_ICON_SVG_TARGET_BLUE_SQUARE, sizeof (GRR_ICON_SVG_TARGET_BLUE_SQUARE) },
58     { RR_TARGET_BLUE_TRIANGLE, "target_blue_triangle",
59       GRR_ICON_SVG_TARGET_BLUE_TRIANGLE, sizeof (GRR_ICON_SVG_TARGET_BLUE_TRIANGLE) },
60
61     { RR_TARGET_GREEN_CIRCLE, "target_green_circle",
62       GRR_ICON_SVG_TARGET_GREEN_CIRCLE, sizeof (GRR_ICON_SVG_TARGET_GREEN_CIRCLE) },
63     { RR_TARGET_GREEN_OCTAGON, "target_green_octagon",
64       GRR_ICON_SVG_TARGET_GREEN_OCTAGON, sizeof (GRR_ICON_SVG_TARGET_GREEN_OCTAGON) },
65     { RR_TARGET_GREEN_SQUARE, "target_green_square",
66       GRR_ICON_SVG_TARGET_GREEN_SQUARE, sizeof (GRR_ICON_SVG_TARGET_GREEN_SQUARE) },
67     { RR_TARGET_GREEN_TRIANGLE, "target_green_triangle",
68       GRR_ICON_SVG_TARGET_GREEN_TRIANGLE, sizeof (GRR_ICON_SVG_TARGET_GREEN_TRIANGLE) },
69
70     { RR_TARGET_RED_CIRCLE, "target_red_circle",
71       GRR_ICON_SVG_TARGET_RED_CIRCLE, sizeof (GRR_ICON_SVG_TARGET_RED_CIRCLE) },
72     { RR_TARGET_RED_OCTAGON, "target_red_octagon",
73       GRR_ICON_SVG_TARGET_RED_OCTAGON, sizeof (GRR_ICON_SVG_TARGET_RED_OCTAGON) },
74     { RR_TARGET_RED_SQUARE, "target_red_square",
75       GRR_ICON_SVG_TARGET_RED_SQUARE, sizeof (GRR_ICON_SVG_TARGET_RED_SQUARE) },
76     { RR_TARGET_RED_TRIANGLE, "target_red_triangle",
77       GRR_ICON_SVG_TARGET_RED_TRIANGLE, sizeof (GRR_ICON_SVG_TARGET_RED_TRIANGLE) },
78
79     { RR_TARGET_YELLOW_CIRCLE, "target_yellow_circle",
80       GRR_ICON_SVG_TARGET_YELLOW_CIRCLE, sizeof (GRR_ICON_SVG_TARGET_YELLOW_CIRCLE) },
81     { RR_TARGET_YELLOW_OCTAGON, "target_yellow_octagon",
82       GRR_ICON_SVG_TARGET_YELLOW_OCTAGON, sizeof (GRR_ICON_SVG_TARGET_YELLOW_OCTAGON) },
83     { RR_TARGET_YELLOW_SQUARE, "target_yellow_square",
84       GRR_ICON_SVG_TARGET_YELLOW_SQUARE, sizeof (GRR_ICON_SVG_TARGET_YELLOW_SQUARE) },
85     { RR_TARGET_YELLOW_TRIANGLE, "target_yellow_triangle",
86       GRR_ICON_SVG_TARGET_YELLOW_TRIANGLE, sizeof (GRR_ICON_SVG_TARGET_YELLOW_TRIANGLE) },
87
88     { RR_TARGET_WHIRL, "whirl",
89       GRR_ICON_SVG_TARGET_WHIRL, sizeof (GRR_ICON_SVG_TARGET_WHIRL) },
90
91     { RR_WALL_ABOVE, "wall",
92       GRR_ICON_SVG_WALL, sizeof (GRR_ICON_SVG_WALL) },
93
94     { RR_WALL_NONE, "cell",
95       GRR_ICON_SVG_CELL, sizeof (GRR_ICON_SVG_CELL) }
96 };
97 #define NUM_BUILTINS (sizeof (builtins) / sizeof (builtins[0]))
98
99 static char *
100 _grr_icon_builtin_name (int type);
101
102 static rr_status_t
103 _grr_icon_init (grr_icon_t *icon, char *name);
104
105 static char *
106 _grr_icon_find_file (char *name);
107
108 static void
109 _grr_icon_find_buffer (char *name, char **buf, int *buflen);
110
111 grr_icon_t *
112 grr_icon_create (char *name)
113 {
114     grr_icon_t *icon;
115
116     icon = malloc (sizeof (grr_icon_t));
117     if (icon == NULL)
118         return NULL;
119
120     _grr_icon_init (icon, name);
121
122     return icon;
123 }
124
125 static rr_status_t
126 _grr_icon_init (grr_icon_t *icon, char *name)
127 {
128     xsvg_status_t status;
129     char *file, *buf;
130     int buflen;
131
132     status = xsvg_create (&icon->xsvg);
133     if (status)
134         return RR_STATUS_NO_MEMORY;
135
136     file = _grr_icon_find_file (name);
137
138     if (file) {
139         status = xsvg_parse_file (icon->xsvg, file);
140         if (status == XSVG_STATUS_SUCCESS) {
141             free (file);
142             return RR_STATUS_SUCCESS;
143         }
144         fprintf (stderr, "Error parsing SVG icon: %s\n", file);
145         free (file);
146     }
147
148     _grr_icon_find_buffer (name, &buf, &buflen);
149     status = xsvg_parse_buffer (icon->xsvg, buf, buflen);
150     if (status) {
151         fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name);
152         return RR_STATUS_PARSE_ERROR;
153     }
154
155     icon->surface = NULL;
156
157     return RR_STATUS_SUCCESS;
158 }
159
160 /* XXX: This could be made more interesting, (eg. search in ~/.grrobot
161    or something). */
162 static char *
163 _grr_icon_find_file (char *name)
164 {
165     int err;
166     char *file;
167     struct stat stat_buf;
168
169     grr_sprintf_alloc (&file, "%s/%s.svg", GRR_ICON_DIR, name);
170     if (file == NULL)
171         return NULL;
172
173     err = stat (file, &stat_buf);
174     if (err == 0 && S_ISREG (stat_buf.st_mode))
175         return (file);
176     free (file);
177
178     return NULL;
179 }
180
181 static void
182 _grr_icon_find_buffer (char *name, char **buf, int *buflen)
183 {
184     int i;
185
186     for (i=0; i < NUM_BUILTINS; i++){
187         if (strcmp (builtins[i].name, name) == 0) {
188             *buf = builtins[i].svg;
189             *buflen = builtins[i].svg_len;
190             return;
191         }
192     }
193
194     *buf = "";
195     *buflen = 0;
196 }
197
198 static char *
199 _grr_icon_builtin_name (int type)
200 {
201     int i;
202
203     for (i=0; i < NUM_BUILTINS; i++)
204         if (builtins[i].type == type)
205             return builtins[i].name;
206
207     return "";
208 }
209
210 char *
211 grr_icon_robot_name (rr_robot_t robot)
212 {
213     return _grr_icon_builtin_name (robot);
214 }
215
216 char *
217 grr_icon_target_name (rr_target_t target)
218 {
219     return _grr_icon_builtin_name (target);
220 }
221
222 void
223 grr_icon_draw (grr_icon_t *icon, XrState *xrs)
224 {
225     xsvg_status_t status;
226
227     status =  xsvg_render (icon->xsvg, xrs);
228     if (status) {
229         fprintf (stderr, "xsvg_render error\n");
230         return;
231     }
232 }
233
234 void
235 grr_icon_predraw (grr_icon_t *icon, XrState *xrs, int width, int height)
236 {
237     if (icon->surface_width != width || icon->surface_height != height) {
238         if (icon->surface)
239             XrSurfaceDestroy (icon->surface);
240         icon->surface_width = width;
241         icon->surface_height = height;
242         icon->surface = XrSurfaceCreateNextTo (XrGetTargetSurface (xrs),
243                                                XrFormatARGB32,
244                                                width, height);
245     }
246
247     XrSave (xrs);
248     XrSetTargetSurface (xrs, icon->surface);
249     grr_icon_draw (icon, xrs);
250     XrRestore (xrs);
251 }
252
253 void
254 grr_icon_draw_predrawn (grr_icon_t *icon, XrState *xrs)
255 {
256     if (icon->surface)
257         XrShowSurface (xrs, icon->surface, icon->surface_width, icon->surface_height);
258 }