xref: /dragonfly/usr.bin/evtranalyze/svg.c (revision 6e278935)
1 /*
2  * Copyright (c) 2009, 2010 Aggelos Economopoulos.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  * 3. Neither the name of The DragonFly Project nor the names of its
15  *    contributors may be used to endorse or promote products derived
16  *    from this software without specific, prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <assert.h>
33 #include <math.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 
37 #include "xml.h"
38 #include "svg.h"
39 #include "trivial.h"
40 
41 enum {
42 	MAX_VALSTR_LEN = 30,
43 };
44 
45 struct svg_rect {
46 	struct xml_element el;
47 	struct xml_attribute x, y, w, h, cl;
48 	char x_val[MAX_VALSTR_LEN];
49 	char y_val[MAX_VALSTR_LEN];
50 	char w_val[MAX_VALSTR_LEN];
51 	char h_val[MAX_VALSTR_LEN];
52 };
53 
54 struct svg_text {
55 	struct xml_element el;
56 	struct xml_attribute x, y, cl;
57 	struct xml_attribute fontsize, transform;
58 	char x_val[MAX_VALSTR_LEN];
59 	char y_val[MAX_VALSTR_LEN];
60 	char fontsize_val[MAX_VALSTR_LEN];
61 	char transform_val[MAX_VALSTR_LEN * 4];
62 };
63 
64 struct svg_line {
65 	struct xml_element el;
66 	struct xml_attribute x1, y1, x2, y2, cl;
67 	struct xml_attribute transform;
68 	char x1_val[MAX_VALSTR_LEN], y1_val[MAX_VALSTR_LEN];
69 	char x2_val[MAX_VALSTR_LEN], y2_val[MAX_VALSTR_LEN];
70 	char transform_val[MAX_VALSTR_LEN * 6];
71 };
72 
73 struct svg_document {
74 	xml_document_t xml;
75 	const char *css;
76 	struct xml_element svg;
77 	struct xml_attribute svg_attrs[2];
78 	struct svg_text text;
79 };
80 
81 static char default_css[] =
82 	"<![CDATA["
83 	"rect.generic { fill: green; stroke: black; stroke-width: 0.01;}"
84 	"rect.thread { fill: yellow; stroke: black; stroke-width: 0.01;}"
85 	"rect.inactive { fill: grey; stroke: black; stroke-width: 0.01;}"
86 	"text.generic { fill: black; stroke: none;}]]>";
87 
88 static
89 int
90 svg_transform_print(svg_transform_t tf, char *buf, size_t len)
91 {
92 	static double eps = 0.0001;
93 	char *p;
94 	int c;
95 
96 	if (!tf) {
97 		assert(len >= 1);
98 		buf[0] = '\0';
99 		return 0;
100 	}
101 	p = buf;
102 	if ((fabs(tf->tx) > eps) && (fabs(tf->ty) > eps)) {
103 		c = snprintf(buf, len, "translate(%.20lf,%.20lf)", tf->tx,
104 			     tf->ty);
105 		len -= c;
106 		if (len <= 0)
107 			return !0;
108 		p += c;
109 	}
110 	if ((fabs(tf->sx - 1) > eps) && (fabs(tf->sy - 1) > eps)) {
111 		c = snprintf(p, len, "%sscale(%.20lf,%.20lf)",
112 			     (p == buf) ? "" : " ", tf->sx, tf->sy);
113 		len -= c;
114 		if (len <= 0)
115 			return !0;
116 		p += c;
117 	}
118 	if (fabs(tf->rot) > eps) {
119 		c = snprintf(p, len, "%srotate(%.2lf)",
120 			     (p == buf) ? "" : " ", tf->rot);
121 		len -= c;
122 		if (len <= 0)
123 			return !0;
124 		p += c;
125 	}
126 	return 0;
127 }
128 
129 static
130 void
131 svg_rect_init(struct svg_rect *rect, const char *cl)
132 {
133 	xml_elem_init(&rect->el, "rect");
134 	xml_attribute_init(&rect->x, "x", NULL);
135 	xml_elem_set_attribute(&rect->el, &rect->x);
136 	xml_attribute_init(&rect->y, "y", NULL);
137 	xml_elem_set_attribute(&rect->el, &rect->y);
138 	xml_attribute_init(&rect->w, "width", NULL);
139 	xml_elem_set_attribute(&rect->el, &rect->w);
140 	xml_attribute_init(&rect->h, "height", NULL);
141 	xml_elem_set_attribute(&rect->el, &rect->h);
142 	if (cl) {
143 		xml_attribute_init(&rect->cl, "class", cl);
144 		xml_elem_set_attribute(&rect->el, &rect->cl);
145 	}
146 }
147 
148 /*
149  * In the future, we might want to stick the rectangle in the
150  * <defs> element at this point and then <use> it in the rest
151  * of the document.
152  */
153 struct svg_rect *
154 svg_rect_new(const char *cl)
155 {
156 	struct svg_rect *r;
157 
158 	if (!(r = malloc(sizeof(*r))))
159 		return r;
160 	svg_rect_init(r, cl);
161 	return r;
162 }
163 
164 
165 int
166 svg_rect_draw(svg_document_t doc, struct svg_rect *rect, double x,
167 	      double y, double w, double h)
168 {
169 	snprintf(&rect->x_val[0], sizeof(rect->x_val), "%.20lf", x);
170 	xml_attribute_set_value(&rect->x, &rect->x_val[0]);
171 	snprintf(&rect->y_val[0], sizeof(rect->y_val), "%lf", y);
172 	xml_attribute_set_value(&rect->y, &rect->y_val[0]);
173 	snprintf(&rect->w_val[0], sizeof(rect->w_val), "%.20lf", w);
174 	xml_attribute_set_value(&rect->w, &rect->w_val[0]);
175 	snprintf(&rect->h_val[0], sizeof(rect->h_val), "%lf", h);
176 	xml_attribute_set_value(&rect->h, &rect->h_val[0]);
177 
178 	xml_elem_closed(doc->xml, &rect->el);
179 	return 0;
180 }
181 
182 static
183 void
184 svg_text_init(struct svg_text *text, const char *cl)
185 {
186 	xml_elem_init(&text->el, "text");
187 #if remove
188 	xml_attribute_init(&text->x, "x", NULL);
189 	xml_elem_set_attribute(&text->el, &text->x);
190 	xml_attribute_init(&text->y, "y", NULL);
191 	xml_elem_set_attribute(&text->el, &text->y);
192 #endif
193 	xml_attribute_init(&text->fontsize, "font-size", NULL);
194 	xml_elem_set_attribute(&text->el, &text->fontsize);
195 	xml_attribute_init(&text->transform, "transform", NULL);
196 	xml_elem_set_attribute(&text->el, &text->transform);
197 
198 	if (cl) {
199 		xml_attribute_init(&text->cl, "class", cl);
200 		xml_elem_set_attribute(&text->el, &text->cl);
201 	}
202 
203 }
204 
205 struct svg_text *
206 svg_text_new(const char *cl)
207 {
208 	svg_text_t text;
209 
210 	if (!(text = malloc(sizeof(*text))))
211 		return text;
212 	svg_text_init(text, cl);
213 	return text;
214 }
215 
216 int
217 svg_text_draw(svg_document_t doc, svg_text_t text, svg_transform_t tf,
218 	      const char *str, double fontsize)
219 {
220 #if remove
221 	snprintf(&text->x_val[0], sizeof(text->x_val), "%.20lf", x);
222 	xml_attribute_set_value(&text->x, &text->x_val[0]);
223 	snprintf(&text->y_val[0], sizeof(text->y_val), "%.20lf", y);
224 	xml_attribute_set_value(&text->y, &text->y_val[0]);
225 #endif
226 	snprintf(&text->fontsize_val[0], sizeof(text->fontsize_val), "%.20lf",
227 		 fontsize);
228 	xml_attribute_set_value(&text->fontsize, &text->fontsize_val[0]);
229 	if (svg_transform_print(tf, &text->transform_val[0],
230 				sizeof(text->transform_val)))
231 		return !0;
232 	xml_attribute_set_value(&text->transform, &text->transform_val[0]);
233 	xml_elem_set_value(&text->el, str);
234 
235 	xml_elem_closed(doc->xml, &text->el);
236 	return 0;
237 }
238 
239 static
240 void
241 svg_line_init(struct svg_line *line, const char *cl)
242 {
243 	xml_elem_init(&line->el, "line");
244 	xml_attribute_init(&line->x1, "x1", NULL);
245 	xml_elem_set_attribute(&line->el, &line->x1);
246 	xml_attribute_init(&line->x2, "x2", NULL);
247 	xml_elem_set_attribute(&line->el, &line->x2);
248 	xml_attribute_init(&line->y1, "y1", NULL);
249 	xml_elem_set_attribute(&line->el, &line->y1);
250 	xml_attribute_init(&line->y2, "y2", NULL);
251 	xml_elem_set_attribute(&line->el, &line->y2);
252 
253 	xml_attribute_init(&line->transform, "transform", NULL);
254 	xml_elem_set_attribute(&line->el, &line->transform);
255 
256 	if (cl) {
257 		xml_attribute_init(&line->cl, "class", cl);
258 		xml_elem_set_attribute(&line->el, &line->cl);
259 	}
260 
261 }
262 
263 struct svg_line *
264 svg_line_new(const char *cl)
265 {
266 	svg_line_t line;
267 
268 	if (!(line = malloc(sizeof(*line))))
269 		return line;
270 	svg_line_init(line, cl);
271 	return line;
272 }
273 
274 int
275 svg_line_draw(svg_document_t doc, svg_line_t line, double x1, double _y1,
276 	      double x2, double y2, svg_transform_t tf)
277 {
278 	snprintf(&line->x1_val[0], sizeof(line->x1_val), "%.20lf", x1);
279 	xml_attribute_set_value(&line->x1, &line->x1_val[0]);
280 
281 	snprintf(&line->x2_val[0], sizeof(line->x2_val), "%.20lf", x2);
282 	xml_attribute_set_value(&line->x2, &line->x2_val[0]);
283 
284 	snprintf(&line->y1_val[0], sizeof(line->y1_val), "%.10lf", _y1);
285 	xml_attribute_set_value(&line->y1, &line->y1_val[0]);
286 
287 	snprintf(&line->y2_val[0], sizeof(line->y2_val), "%.20lf", y2);
288 	xml_attribute_set_value(&line->y2, &line->y2_val[0]);
289 
290 	xml_attribute_set_value(&line->transform, &line->transform_val[0]);
291 	if (svg_transform_print(tf,
292 				&line->transform_val[0],
293 				sizeof(line->transform_val)))
294 		return !0;
295 	xml_elem_closed(doc->xml, &line->el);
296 	return 0;
297 }
298 
299 svg_document_t
300 svg_document_create(const char *path)
301 {
302 	svg_document_t svg;
303 	struct xml_element style, defs;
304 	struct xml_attribute type;
305 
306 	if (!(svg = malloc(sizeof(*svg))))
307 		return NULL;
308 	if (!(svg->xml = xml_document_create(path))) {
309 		free(svg);
310 		return NULL;
311 	}
312 	svg->css = &default_css[0];
313 	xml_attribute_init(&type, "type", "text/css");
314 	xml_elem_init(&defs, "defs");
315 	xml_elem_init(&style, "style");
316 	xml_elem_set_attribute(&style, &type);
317 	xml_elem_init(&svg->svg, "svg");
318 	xml_attribute_init(&svg->svg_attrs[0], "version", "1.1");
319 	xml_elem_set_attribute(&svg->svg, &svg->svg_attrs[0]);
320 	xml_attribute_init(&svg->svg_attrs[1], "xmlns",
321 			   "http://www.w3.org/2000/svg");
322 	xml_elem_set_attribute(&svg->svg, &svg->svg_attrs[1]);
323 	xml_elem_begin(svg->xml, &svg->svg);
324 	xml_elem_begin(svg->xml, &defs);
325 	xml_elem_set_value(&style, svg->css);
326 	xml_elem_closed(svg->xml, &style);
327 	xml_elem_close(svg->xml, &defs);
328 
329 	return svg;
330 }
331 
332 int
333 svg_document_close(svg_document_t svg)
334 {
335 	xml_elem_close(svg->xml, &svg->svg);
336 	xml_document_close(svg->xml);
337 	return 0;
338 }
339