]> git.cworth.org Git - grrobot/blob - src/grr_icon.c
Fixed select handling. Added two of Richard's fancy logos.
[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     icon->surface = NULL;
133     icon->surface_width = 0;
134     icon->surface_height = 0;
135
136     status = xsvg_create (&icon->xsvg);
137     if (status)
138         return RR_STATUS_NO_MEMORY;
139
140     file = _grr_icon_find_file (name);
141
142     if (file) {
143         status = xsvg_parse_file (icon->xsvg, file);
144         if (status == XSVG_STATUS_SUCCESS) {
145             free (file);
146             return RR_STATUS_SUCCESS;
147         }
148         fprintf (stderr, "Error parsing SVG icon: %s\n", file);
149         free (file);
150     }
151
152     _grr_icon_find_buffer (name, &buf, &buflen);
153     status = xsvg_parse_buffer (icon->xsvg, buf, buflen);
154     if (status) {
155         fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name);
156         return RR_STATUS_PARSE_ERROR;
157     }
158     return RR_STATUS_SUCCESS;
159 }
160
161 /* XXX: This could be made more interesting, (eg. search in ~/.grrobot
162    or something). */
163 static char *
164 _grr_icon_find_file (char *name)
165 {
166     int err;
167     char *file;
168     struct stat stat_buf;
169
170     grr_sprintf_alloc (&file, "%s/%s.svg", GRR_ICON_DIR, name);
171     if (file == NULL)
172         return NULL;
173
174     err = stat (file, &stat_buf);
175     if (err == 0 && S_ISREG (stat_buf.st_mode))
176         return (file);
177     free (file);
178
179     return NULL;
180 }
181
182 static void
183 _grr_icon_find_buffer (char *name, char **buf, int *buflen)
184 {
185     int i;
186
187     for (i=0; i < NUM_BUILTINS; i++){
188         if (strcmp (builtins[i].name, name) == 0) {
189             *buf = builtins[i].svg;
190             *buflen = builtins[i].svg_len;
191             return;
192         }
193     }
194
195     *buf = "";
196     *buflen = 0;
197 }
198
199 static char *
200 _grr_icon_builtin_name (int type)
201 {
202     int i;
203
204     for (i=0; i < NUM_BUILTINS; i++)
205         if (builtins[i].type == type)
206             return builtins[i].name;
207
208     return "";
209 }
210
211 char *
212 grr_icon_robot_name (rr_robot_t robot)
213 {
214     return _grr_icon_builtin_name (robot);
215 }
216
217 char *
218 grr_icon_target_name (rr_target_t target)
219 {
220     return _grr_icon_builtin_name (target);
221 }
222
223 void
224 grr_icon_draw (grr_icon_t *icon, cairo_t *xrs)
225 {
226     xsvg_status_t status;
227
228     status =  xsvg_render (icon->xsvg, xrs);
229     if (status) {
230         fprintf (stderr, "xsvg_render error\n");
231         return;
232     }
233 }
234
235 void
236 grr_icon_predraw (grr_icon_t *icon, cairo_t *xrs, int width, int height)
237 {
238     if (icon->surface_width != width || icon->surface_height != height) {
239         if (icon->surface)
240             cairo_surface_destroy (icon->surface);
241         icon->surface_width = width;
242         icon->surface_height = height;
243         icon->surface = cairo_surface_create_similar (cairo_get_target_surface (xrs),
244                                                       CAIRO_FORMAT_ARGB32,
245                                                       width, height);
246     }
247
248     cairo_save (xrs);
249     cairo_set_target_surface (xrs, icon->surface);
250     grr_icon_draw (icon, xrs);
251     cairo_restore (xrs);
252 }
253
254 void
255 grr_icon_draw_predrawn (grr_icon_t *icon, cairo_t *xrs)
256 {
257     if (icon->surface)
258         cairo_show_surface (xrs, icon->surface, icon->surface_width, icon->surface_height);
259 }