]> git.cworth.org Git - grrobot/blob - src/grr_icon.c
f4515fe581deb04ce6ebcf96cbb61440fc5c024c
[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     { 0, "cell1",
95       GRR_ICON_SVG_CELL1, sizeof (GRR_ICON_SVG_CELL1) },
96     { 0, "cell2",
97       GRR_ICON_SVG_CELL2, sizeof (GRR_ICON_SVG_CELL2) }
98 };
99 #define NUM_BUILTINS (sizeof (builtins) / sizeof (builtins[0]))
100
101 static char *
102 _grr_icon_builtin_name (int type);
103
104 static rr_status_t
105 _grr_icon_init (grr_icon_t *icon, char *name);
106
107 static char *
108 _grr_icon_find_file (char *name);
109
110 static void
111 _grr_icon_find_buffer (char *name, char **buf, int *buflen);
112
113 grr_icon_t *
114 grr_icon_create (char *name)
115 {
116     grr_icon_t *icon;
117
118     icon = malloc (sizeof (grr_icon_t));
119     if (icon == NULL)
120         return NULL;
121
122     _grr_icon_init (icon, name);
123
124     return icon;
125 }
126
127 static rr_status_t
128 _grr_icon_init (grr_icon_t *icon, char *name)
129 {
130     xsvg_status_t status;
131     char *file, *buf;
132     int buflen;
133
134     icon->surface = NULL;
135     icon->surface_width = 0;
136     icon->surface_height = 0;
137
138     status = xsvg_create (&icon->xsvg);
139     if (status)
140         return RR_STATUS_NO_MEMORY;
141
142     file = _grr_icon_find_file (name);
143
144     if (file) {
145         status = xsvg_parse_file (icon->xsvg, file);
146         if (status == XSVG_STATUS_SUCCESS) {
147             free (file);
148             return RR_STATUS_SUCCESS;
149         }
150         fprintf (stderr, "Error parsing SVG icon: %s\n", file);
151         free (file);
152     }
153
154     _grr_icon_find_buffer (name, &buf, &buflen);
155     status = xsvg_parse_buffer (icon->xsvg, buf, buflen);
156     if (status) {
157         fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name);
158         return RR_STATUS_PARSE_ERROR;
159     }
160     return RR_STATUS_SUCCESS;
161 }
162
163 /* XXX: This could be made more interesting, (eg. search in ~/.grrobot
164    or something). */
165 static char *
166 _grr_icon_find_file (char *name)
167 {
168     int err;
169     char *file;
170     struct stat stat_buf;
171
172     grr_sprintf_alloc (&file, "%s/%s.svg", GRR_ICON_DIR, name);
173     if (file == NULL)
174         return NULL;
175
176     err = stat (file, &stat_buf);
177     if (err == 0 && S_ISREG (stat_buf.st_mode))
178         return (file);
179     free (file);
180
181     return NULL;
182 }
183
184 static void
185 _grr_icon_find_buffer (char *name, char **buf, int *buflen)
186 {
187     int i;
188
189     for (i=0; i < NUM_BUILTINS; i++){
190         if (strcmp (builtins[i].name, name) == 0) {
191             *buf = builtins[i].svg;
192             *buflen = builtins[i].svg_len;
193             return;
194         }
195     }
196
197     *buf = "";
198     *buflen = 0;
199 }
200
201 static char *
202 _grr_icon_builtin_name (int type)
203 {
204     int i;
205
206     for (i=0; i < NUM_BUILTINS; i++)
207         if (builtins[i].type == type)
208             return builtins[i].name;
209
210     return "";
211 }
212
213 char *
214 grr_icon_robot_name (rr_robot_t robot)
215 {
216     return _grr_icon_builtin_name (robot);
217 }
218
219 char *
220 grr_icon_target_name (rr_target_t target)
221 {
222     return _grr_icon_builtin_name (target);
223 }
224
225 void
226 grr_icon_draw (grr_icon_t *icon, cairo_t *xrs)
227 {
228     xsvg_status_t status;
229
230     status =  xsvg_render (icon->xsvg, xrs);
231     if (status) {
232         fprintf (stderr, "xsvg_render error\n");
233         return;
234     }
235 }
236
237 void
238 grr_icon_predraw (grr_icon_t *icon, cairo_t *xrs, int width, int height)
239 {
240     if (icon->surface_width != width || icon->surface_height != height) {
241         if (icon->surface)
242             cairo_surface_destroy (icon->surface);
243         icon->surface_width = width;
244         icon->surface_height = height;
245         icon->surface = cairo_surface_create_similar (cairo_current_target_surface (xrs),
246                                                       CAIRO_FORMAT_ARGB32,
247                                                       width, height);
248     }
249
250     cairo_save (xrs);
251     cairo_set_target_surface (xrs, icon->surface);
252     grr_icon_draw (icon, xrs);
253     cairo_restore (xrs);
254 }
255
256 void
257 grr_icon_draw_predrawn (grr_icon_t *icon, cairo_t *xrs)
258 {
259     if (icon->surface)
260         cairo_show_surface (xrs, icon->surface, icon->surface_width, icon->surface_height);
261 }