]> git.cworth.org Git - grrobot/blob - src/grr_icon.c
Update to 2020
[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     char *file, *buf;
131     int buflen;
132     GError *error = NULL;
133
134     icon->surface = NULL;
135     icon->surface_width = 0;
136     icon->surface_height = 0;
137
138     file = _grr_icon_find_file (name);
139     if (file) {
140             icon->rsvg = rsvg_handle_new_from_file(file, &error);
141             if (!icon->rsvg) {
142                     fprintf (stderr, "Error parsing SVG icon: %s\n", file);
143                     return RR_STATUS_PARSE_ERROR;
144             }
145     } else {
146             _grr_icon_find_buffer (name, &buf, &buflen);
147             icon->rsvg = rsvg_handle_new_from_data(buf, buflen, &error);
148             if (!icon->rsvg) {
149                     fprintf (stderr, "Error parsing built-in SVG icon for: %s\n", name);
150                     return RR_STATUS_PARSE_ERROR;
151             }
152     }
153     return RR_STATUS_SUCCESS;
154 }
155
156 /* XXX: This could be made more interesting, (eg. search in ~/.grrobot
157    or something). */
158 static char *
159 _grr_icon_find_file (char *name)
160 {
161     int err;
162     char *file;
163     struct stat stat_buf;
164
165     grr_sprintf_alloc (&file, "%s/%s.svg", GRR_ICON_DIR, name);
166     if (file == NULL)
167         return NULL;
168
169     err = stat (file, &stat_buf);
170     if (err == 0 && S_ISREG (stat_buf.st_mode))
171         return (file);
172     free (file);
173
174     return NULL;
175 }
176
177 static void
178 _grr_icon_find_buffer (char *name, char **buf, int *buflen)
179 {
180     int i;
181
182     for (i=0; i < NUM_BUILTINS; i++){
183         if (strcmp (builtins[i].name, name) == 0) {
184             *buf = builtins[i].svg;
185             *buflen = builtins[i].svg_len;
186             return;
187         }
188     }
189
190     *buf = "";
191     *buflen = 0;
192 }
193
194 static char *
195 _grr_icon_builtin_name (int type)
196 {
197     int i;
198
199     for (i=0; i < NUM_BUILTINS; i++)
200         if (builtins[i].type == type)
201             return builtins[i].name;
202
203     return "";
204 }
205
206 char *
207 grr_icon_robot_name (rr_robot_t robot)
208 {
209     return _grr_icon_builtin_name (robot);
210 }
211
212 char *
213 grr_icon_target_name (rr_target_t target)
214 {
215     return _grr_icon_builtin_name (target);
216 }
217
218 void
219 grr_icon_draw (grr_icon_t *icon, cairo_t *xrs)
220 {
221     rsvg_handle_render_cairo(icon->rsvg, xrs);
222 #if 0
223     if (status) {
224         fprintf (stderr, "svg_cairo_render error\n");
225         return;
226     }
227 #endif
228 }
229
230 void
231 grr_icon_predraw (grr_icon_t *icon, cairo_t *xrs, int width, int height)
232 {
233     cairo_t *xrs2;
234     cairo_matrix_t ctm;
235
236     if (icon->surface_width != width || icon->surface_height != height) {
237         if (icon->surface)
238             cairo_surface_destroy (icon->surface);
239         icon->surface_width = width;
240         icon->surface_height = height;
241         icon->surface = cairo_surface_create_similar (cairo_get_target (xrs),
242                                                       CAIRO_CONTENT_COLOR_ALPHA,
243                                                       width, height);
244     }
245
246     /* Need to copy the CTM from the original cairo_t to the new one */
247     xrs2 = cairo_create (icon->surface);
248     cairo_get_matrix (xrs, &ctm);
249     cairo_set_matrix (xrs2, &ctm);
250     grr_icon_draw (icon, xrs2);
251     cairo_destroy (xrs2);
252 }
253
254 void
255 grr_icon_draw_predrawn (grr_icon_t *icon, cairo_t *xrs, double alpha)
256 {
257     if (icon->surface) {
258         cairo_set_source_surface (xrs, icon->surface, 0.0, 0.0);
259         cairo_paint_with_alpha (xrs, alpha);
260     }
261 }