1#include <VG/openvg.h>
2#include <VG/vgu.h>
3#include <math.h>
4#include <string.h>
5
6#include "eglut.h"
7
8#define ELEMENTS(x) (sizeof(x)/sizeof((x)[0]))
9
10struct object {
11   VGPath path;
12   VGPaint fill;
13   VGPaint stroke;
14   VGint draw_mode;
15   VGfloat matrix[9];
16   VGfloat stroke_width;
17};
18
19struct character {
20   struct object objects[32];
21   VGint num_objects;
22};
23VGfloat identity_matrix[] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
24
25struct character cartman;
26
27static void add_object_fill(const VGubyte *segments, VGint num_segments,
28                            const VGfloat *coords,
29                            VGuint color)
30{
31   struct object object;
32
33   object.path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
34                              1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
35   vgAppendPathData(object.path, num_segments, segments, coords);
36
37   object.fill = vgCreatePaint();
38   vgSetColor(object.fill, color);
39   memcpy(object.matrix, identity_matrix, 9 * sizeof(VGfloat));
40   object.draw_mode = VG_FILL_PATH;
41
42   cartman.objects[cartman.num_objects] = object;
43   ++cartman.num_objects;
44}
45
46
47static void add_object_stroke(const VGubyte *segments, VGint num_segments,
48                              const VGfloat *coords,
49                              VGuint color, VGfloat width)
50{
51   struct object object;
52
53   object.path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
54                              1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
55   vgAppendPathData(object.path, num_segments, segments, coords);
56
57   object.stroke = vgCreatePaint();
58   vgSetColor(object.stroke, color);
59   memcpy(object.matrix, identity_matrix, 9 * sizeof(VGfloat));
60   object.draw_mode = VG_STROKE_PATH;
61   object.stroke_width = width;
62
63   cartman.objects[cartman.num_objects] = object;
64   ++cartman.num_objects;
65}
66
67
68static void add_object_fillm(const VGubyte *segments, VGint num_segments,
69                             const VGfloat *coords,
70                             VGuint color,
71                             VGfloat *matrix)
72{
73   struct object object;
74
75   object.path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
76                              1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
77   vgAppendPathData(object.path, num_segments, segments, coords);
78
79   object.fill = vgCreatePaint();
80   vgSetColor(object.fill, color);
81   memcpy(object.matrix, matrix, 9 * sizeof(VGfloat));
82   object.draw_mode = VG_FILL_PATH;
83
84   cartman.objects[cartman.num_objects] = object;
85   ++cartman.num_objects;
86}
87
88
89static void add_object_m(const VGubyte *segments, VGint num_segments,
90                         const VGfloat *coords,
91                         VGuint fill_color,
92                         VGuint stroke_color, VGfloat stroke_width,
93                         VGfloat *matrix)
94{
95   struct object object;
96
97   object.path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F,
98                              1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
99   vgAppendPathData(object.path, num_segments, segments, coords);
100   memcpy(object.matrix, matrix, 9 * sizeof(VGfloat));
101
102   object.fill = vgCreatePaint();
103   vgSetColor(object.fill, fill_color);
104   object.draw_mode = VG_FILL_PATH | VG_STROKE_PATH;
105
106   object.stroke = vgCreatePaint();
107   vgSetColor(object.stroke, stroke_color);
108   object.stroke_width = stroke_width;
109
110   cartman.objects[cartman.num_objects] = object;
111   ++cartman.num_objects;
112}
113
114static void init_character()
115{
116   {
117      const VGubyte segments[] = {VG_MOVE_TO_ABS,
118                                  VG_CUBIC_TO_ABS,
119                                  VG_CUBIC_TO_ABS,
120                                  VG_CUBIC_TO_ABS,
121                                  VG_CUBIC_TO_ABS,
122                                  VG_CLOSE_PATH};
123      const VGfloat coords[] = {181.83267, 102.60408,
124                                181.83267,102.60408, 185.53793,114.5749, 186.5355,115.00243,
125                                187.53306,115.42996, 286.0073,115.00243, 286.0073,115.00243,
126                                286.0073,115.00243, 292.70526,103.45914, 290.85263,101.03648,
127                                289.00001,98.61381, 181.54765,102.31906, 181.83267,102.60408
128      };
129      VGuint color = 0x7c4e32ff;
130      add_object_fill(segments, ELEMENTS(segments),
131                      coords, color);
132   }
133   {
134      const VGubyte segments[] = {
135         VG_MOVE_TO_ABS,
136         VG_CUBIC_TO_ABS,
137         VG_CUBIC_TO_ABS,
138         VG_LINE_TO_ABS,
139         VG_CUBIC_TO_ABS,
140         VG_CUBIC_TO_ABS,
141         VG_CUBIC_TO_ABS,
142         VG_CUBIC_TO_ABS,
143         VG_CUBIC_TO_ABS,
144         VG_CUBIC_TO_ABS,
145         VG_CLOSE_PATH
146      };
147      const VGfloat coords[] = {188.62208,50.604156,
148                                188.62208,50.604156, 176.73127,60.479579, 170.68509,69.548844,
149                                164.63892,78.618109, 175.11895,79.827344, 175.11895,79.827344,
150                                176.52973,98.368952,
151                                176.52973,98.368952, 189.83131,110.05823, 208.97754,110.25976,
152                                228.12377,110.46131, 244.24691,111.67054, 247.06846,110.25976,
153                                249.89,108.849, 258.95927,106.8336, 260.16851,105.01975,
154                                261.37774,103.2059, 296.84865,106.43053, 297.05019,91.919698,
155                                297.25172,77.408874, 306.11945,64.308824, 282.13628,51.611853,
156                                258.15311,38.914882, 189.2267,49.999539, 188.62208,50.604156
157      };
158
159      VGuint color = 0xe30000ff;
160      add_object_fill(segments, ELEMENTS(segments),
161                      coords, color);
162   }
163   {
164      const VGubyte segments[] = {
165         VG_MOVE_TO_ABS,
166         VG_CUBIC_TO_ABS,
167         VG_CUBIC_TO_ABS,
168         VG_CUBIC_TO_ABS,
169         VG_CUBIC_TO_ABS,
170         VG_CLOSE_PATH
171      };
172      const VGfloat coords[] = {
173         68.25, 78.875,
174         68.25,93.296, 54.642,105, 37.875,105,
175         21.108,105, 7.5,93.296, 7.5,78.875,
176         7.5,64.454, 21.108,52.75, 37.875,52.75,
177         54.642,52.75, 68.25,64.454, 68.25,78.875
178      };
179
180      VGuint color = 0xffe1c4ff;
181      VGfloat matrix[] = {
182         1.6529, 0, 0,
183         0, 1.582037, 0,
184         172.9649,-90.0116, 1
185      };
186      add_object_fillm(segments, ELEMENTS(segments),
187                       coords, color, matrix);
188   }
189   {
190      const VGubyte segments[] = {
191         VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
192         VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CLOSE_PATH
193      };
194      const VGfloat coords[] = {
195         170.14687,71.536958,
196         173.53626,68.814326, 176.70232,68.971782, 180.55009,71.679467,
197         184.39785,74.387153, 199.19294,80.036105, 191.52334,86.500482,
198         189.02942,88.6025, 183.97032,85.787933, 180.26507,86.928011,
199         178.8737,87.356121, 174.71827,89.783259, 171.8028,87.494856,
200         166.95426,83.689139, 163.51779,76.861986, 170.14687,71.536958
201      };
202
203      VGuint color = 0xfff200ff;
204      add_object_fill(segments, ELEMENTS(segments),
205                      coords, color);
206   }
207   {
208      const VGubyte segments[] = {
209         VG_MOVE_TO_ABS,  VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
210         VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
211         VG_CUBIC_TO_ABS, VG_CLOSE_PATH
212      };
213      const VGfloat coords[] = {
214         299.83075,66.834136,
215         299.83075,66.834136, 287.85993,64.69649, 284.15467,72.962055,
216         280.44942,81.227621, 280.1644,78.234916, 280.1644,79.374994,
217         280.1644,80.515072, 278.16927,84.077816, 284.86722,83.792796,
218         291.56518,83.507777, 291.99271,86.785501, 294.84291,86.642991,
219         297.6931,86.500482, 303.536,85.645423, 303.67851,80.657582,
220         303.82102,75.66974, 302.68094,65.551548, 299.83075,66.834136
221      };
222
223      VGuint color = 0xfff200ff;
224      add_object_fill(segments, ELEMENTS(segments),
225                      coords, color);
226   }
227   {
228      const VGubyte segments[] = {
229         VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS
230      };
231      const VGfloat coords[] = {
232         240.83171,75.81225,
233         240.83171,75.81225, 241.54426,88.495618, 242.25681,91.488323,
234         242.96936,94.481028, 240.6892,108.01945, 240.83171,110.01459,
235         240.97422,112.00973, 240.97422,111.01216, 240.97422,111.01216
236      };
237      VGuint color = 0x000000ff;
238      VGfloat swidth = 1.14007807;
239      add_object_stroke(segments, ELEMENTS(segments), coords, color, swidth);
240   }
241   {
242      const VGubyte segments[] = {
243         VG_MOVE_TO_ABS,  VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
244         VG_CUBIC_TO_ABS, VG_LINE_TO_ABS,  VG_LINE_TO_ABS,  VG_CLOSE_PATH
245      };
246      const VGfloat coords[] = {
247         83.375, 95.5,
248         83.375,96.121, 83.067,96.625, 82.6875,96.625,
249         82.308,96.625, 82,96.121, 82,95.5,
250         82,94.879, 82.308,94.375, 82.6875,94.375,
251         83.066677,94.375, 83.374492,94.878024, 83.374999,95.498494,
252         82.6875,95.5,
253         83.375,95.5
254      };
255      VGuint fill_color = 0x000000ff;
256      VGuint stroke_color = 0x000000ff;
257      VGfloat swidth = 0.60000002;
258      VGfloat matrix1[] = {
259         1.140078, 0, 0,
260         0, 1.140078, 0,
261         145.4927, -15.10897, 1
262      };
263      VGfloat matrix2[] = {
264         1.140078,0, 0,
265         0,1.140078, 0,
266         144.2814,-27.93485, 1
267      };
268      VGfloat matrix3[] = {
269         1.140078,0, 0,
270         0,1.140078, 0,
271         144.1388,-3.70819, 1
272      };
273      add_object_m(segments, ELEMENTS(segments), coords,
274                   fill_color, stroke_color, swidth, matrix1);
275      add_object_m(segments, ELEMENTS(segments), coords,
276                   fill_color, stroke_color, swidth, matrix2);
277      add_object_m(segments, ELEMENTS(segments), coords,
278                   fill_color, stroke_color, swidth, matrix3);
279   }
280   {
281      const VGubyte segments[] = {
282         VG_MOVE_TO_ABS,
283         VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
284         VG_LINE_TO_ABS, VG_CLOSE_PATH
285      };
286      const VGfloat coords[] = {
287         179.41001,115.28745,
288         179.41001,115.28745, 207.48443,109.30204, 236.84144,115.14494,
289         236.84144,115.14494, 274.74903,109.87208, 291.8502,115.42996,
290         179.41001,115.28745
291      };
292
293      VGuint color = 0x000000ff;
294      add_object_fill(segments, ELEMENTS(segments),
295                      coords, color);
296   }
297   {
298      const VGubyte segments[] = {
299         VG_MOVE_TO_ABS,  VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
300         VG_CUBIC_TO_ABS, VG_LINE_TO_ABS, VG_LINE_TO_ABS,  VG_CLOSE_PATH
301      };
302      const VGfloat coords[] = {
303         83.792156,68.157364,
304         83.792156,69.669865, 82.72301,70.897403, 81.40567,70.897403,
305         80.08833,70.897403, 79.019185,69.669865, 79.019185,68.157364,
306         79.019185,66.644862, 80.08833,65.417325, 81.40567,65.417325,
307         82.721887,65.417325, 83.790391,66.642485, 83.792153,68.153696,
308         81.40567,68.157364,
309         83.792156,68.157364
310      };
311      VGuint fill_color = 0x000000ff;
312      VGuint stroke_color = 0x000000ff;
313      VGfloat swidth = 0.52891117;
314      VGfloat matrix1[] = {
315         1.140078,0, 0,
316         0,1.140078, 0,
317         145.2489,-15.58714, 1
318      };
319      add_object_m(segments, ELEMENTS(segments), coords,
320                   fill_color, stroke_color, swidth, matrix1);
321   }
322   {
323      const VGubyte segments[] = {
324         VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS
325      };
326      const VGfloat coords[] = {
327         232.28113,66.976646,
328         232.28113,66.976646, 237.98152,70.539389, 245.39202,66.549116
329      };
330      VGuint color = 0x000000ff;
331      VGfloat swidth = 0.60299999;
332      add_object_stroke(segments, ELEMENTS(segments), coords, color, swidth);
333   }
334   {
335      const VGubyte segments[] = {
336         VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
337         VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CLOSE_PATH
338      };
339      const VGfloat coords[] = {
340         185.96908,30.061986,
341         185.96908,30.061986, 187.76995,14.508377, 203.23909,3.7427917,
342         209.95028,-0.92779696, 219.37764,-4.9841866, 232.1078,-6.00046,
343         246.13578,-7.1203411, 256.92106,-2.8560739, 264.81774,1.9451947,
344         280.60485,11.543934, 284.31582,25.937274, 284.08015,26.526452,
345         283.7266,27.410336, 240.83461,1.9346323, 185.96908,30.061986
346      };
347      VGuint color = 0x8ed8f8ff;
348      add_object_fill(segments, ELEMENTS(segments), coords, color);
349   }
350   {
351      const VGubyte segments[] = {
352         VG_MOVE_TO_ABS, VG_LINE_TO_ABS, VG_CUBIC_TO_ABS,
353         VG_LINE_TO_ABS, VG_CUBIC_TO_ABS, VG_CLOSE_PATH
354      };
355      const VGfloat coords[] = {
356         185.39542,32.061757,
357         185.82295,29.211562,
358         185.82295,29.211562, 234.70379,2.277219, 284.01217,25.078779,
359         284.86722,27.643954,
360         284.86722,27.643954, 236.69893,4.5573746, 185.39542,32.061757
361      };
362      VGuint color = 0xfff200ff;
363      add_object_fill(segments, ELEMENTS(segments), coords, color);
364   }
365
366   {
367      const VGubyte segments[] = {
368         VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
369         VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
370         VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
371         VG_CUBIC_TO_ABS,  VG_CLOSE_PATH
372      };
373      const VGfloat coords[] = {
374         219.74027,-5.917093,
375         220.49206,-8.44929, 225.15564,-10.904934, 230.21473,-11.189954,
376         235.27383,-11.474973, 243.27521,-13.287236, 249.21385,-5.724198,
377         249.89961,-4.850868, 249.28247,-4.332166, 248.62298,-3.971398,
378         247.79117,-3.516361, 247.13703,-3.392737, 246.16222,-3.408047,
379         243.63973,-3.447664, 242.54183,-3.850701, 242.54183,-3.850701,
380         242.54183,-3.850701, 238.78367,-1.737343, 236.20014,-3.565682,
381         233.88436,-5.204544, 234.27626,-4.56325, 234.27626,-4.56325,
382         234.27626,-4.56325, 232.33303,-2.975658, 230.85603,-2.995643,
383         228.59433,-3.025282, 227.73672,-4.501857, 227.21966,-4.93027,
384         226.76318,-4.932008, 226.50948,-4.491995, 226.50948,-4.491995,
385         226.50948,-4.491995, 224.53199,-2.085883, 222.51431,-2.467064,
386         221.48814,-2.66093, 218.91968,-3.15318, 219.74027,-5.917093
387      };
388      VGuint color = 0xfff200ff;
389      add_object_fill(segments, ELEMENTS(segments), coords, color);
390   }
391   {
392      const VGubyte segments[] = {
393         VG_MOVE_TO_ABS,  VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
394         VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,  VG_CLOSE_PATH
395      };
396      const VGfloat coords[] = {
397         178.97347,166.06432,
398         178.97347,181.2154, 168.0245,193.51193, 154.53381,193.51193,
399         141.04312,193.51193, 130.09416,181.2154, 130.09416,166.06432,
400         130.09416,150.91323, 141.04312,138.6167, 154.53381,138.6167,
401         168.0245,138.6167, 178.97347,150.91323, 178.97347,166.06432
402      };
403      VGuint color = 0xffffffff;
404      VGfloat matrix1[] = {
405         0.466614,-0.23492,  0,
406         0.108683,0.436638,  0,
407         134.5504,-0.901632, 1
408      };
409      VGfloat matrix2[] = {
410         -0.466614,-0.23492, 0,
411         -0.108683,0.436638, 0,
412         338.4496,-0.512182, 1
413      };
414      add_object_fillm(segments, ELEMENTS(segments), coords, color, matrix1);
415      add_object_fillm(segments, ELEMENTS(segments), coords, color, matrix2);
416   }
417   {
418      const VGubyte segments[] = {
419         VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
420         VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,  VG_CLOSE_PATH
421      };
422      const VGfloat coords[] = {
423         123.82758,165.06168,
424         123.82758,166.79125, 122.59232,168.19497, 121.07029,168.19497,
425         119.54826,168.19497, 118.313,166.79125, 118.313,165.06168,
426         118.313,163.3321, 119.54826,161.92839, 121.07029,161.92839,
427         122.59232,161.92839, 123.82758,163.3321, 123.82758,165.06168
428      };
429      VGuint color = 0x000000ff;
430      VGfloat matrix1[] = {
431         0.525719,0, 0,
432         0,0.479931, 0,
433         178.9702,-43.3532, 1
434      };
435      VGfloat matrix2[] = {
436         0.525719,0, 0,
437         0,0.479931, 0,
438         165.258,-43.46162, 1
439      };
440      add_object_fillm(segments, ELEMENTS(segments), coords, color, matrix1);
441      add_object_fillm(segments, ELEMENTS(segments), coords, color, matrix2);
442   }
443   {
444      const VGubyte segments[] = {
445         VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS
446      };
447      const VGfloat coords[] = {
448         197.25,54.5,
449         197.25,54.5, 211.75,71.5, 229.25,71.5,
450         246.75,71.5, 261.74147,71.132714, 277.75,50.75
451      };
452      VGuint color = 0x000000ff;
453      VGfloat swidth = 0.60299999;
454      add_object_stroke(segments, ELEMENTS(segments), coords, color, swidth);
455   }
456}
457
458
459static void
460init(void)
461{
462   float clear_color[4] = {1.0, 1.0, 1.0, 1.0};
463   vgSetfv(VG_CLEAR_COLOR, 4, clear_color);
464
465   init_character();
466}
467
468/* new window size or exposure */
469static void
470reshape(int w, int h)
471{
472}
473
474static void
475draw(void)
476{
477   VGint i;
478   VGfloat save_matrix[9];
479
480   vgClear(0, 0, eglutGetWindowWidth(), eglutGetWindowHeight());
481
482   vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
483   vgLoadIdentity();
484   vgScale(2, 2);
485   vgTranslate(160, 60);
486   vgRotate(180);
487   vgTranslate(-160, -100);
488   vgGetMatrix(save_matrix);
489   for (i = 0; i < cartman.num_objects; ++i) {
490      struct object object = cartman.objects[i];
491      if ((object.draw_mode & VG_STROKE_PATH)) {
492         vgSetf(VG_STROKE_LINE_WIDTH, object.stroke_width);
493         vgSetPaint(object.stroke, VG_STROKE_PATH);
494      }
495      if ((object.draw_mode & VG_FILL_PATH))
496         vgSetPaint(object.fill, VG_FILL_PATH);
497      vgMultMatrix(object.matrix);
498      vgDrawPath(object.path, object.draw_mode);
499      vgLoadMatrix(save_matrix);
500   }
501
502   vgFlush();
503}
504
505
506int main(int argc, char **argv)
507{
508   eglutInitWindowSize(400, 400);
509   eglutInitAPIMask(EGLUT_OPENVG_BIT);
510   eglutInit(argc, argv);
511
512   eglutCreateWindow("sp");
513
514   eglutReshapeFunc(reshape);
515   eglutDisplayFunc(draw);
516
517   init();
518
519   eglutMainLoop();
520
521   return 0;
522}
523