dm(4): Fix kernel compilation with 'device dm' in the config.
[dragonfly.git] / usr.bin / evtranalyze / svg.c
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 }