f1973303eec676b1125ec6f0ecf58b03b355cdc1
[platform/upstream/efl.git] / src / generic / evas / svg / main.c
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 #include <stdio.h>
5 #include "shmfile.h"
6 #include "timeout.h"
7
8 #include <Eina.h>
9
10 #include <librsvg/rsvg.h>
11 #ifndef LIBRSVG_CHECK_VERSION
12 # include <librsvg/librsvg-features.h>
13 #endif
14 #if LIBRSVG_CHECK_VERSION(2,36,2)
15 #else
16 # include <librsvg/rsvg-cairo.h>
17 #endif
18
19 #define DATA32 unsigned int
20
21 static RsvgHandle *rsvg = NULL;
22 static int width = 0;
23 static int height = 0;
24 static RsvgDimensionData dim;
25
26 static inline Eina_Bool evas_image_load_file_is_svg(const char *file)
27 {
28    int i, len = strlen(file);
29    Eina_Bool is_gz = EINA_FALSE;
30
31    for (i = len - 1; i > 0; i--)
32      {
33         if (file[i] == '.')
34           {
35              if (is_gz)
36                break;
37              else if (strcasecmp(file + i + 1, "gz") == 0)
38                is_gz = EINA_TRUE;
39              else
40                break;
41           }
42      }
43
44    if (i < 1) return EINA_FALSE;
45    i++;
46    if (i >= len) return EINA_FALSE;
47    if (strncasecmp(file + i, "svg", 3) != 0) return EINA_FALSE;
48    i += 3;
49    if (is_gz)
50      {
51         if (file[i] == '.') return EINA_TRUE;
52         else return EINA_FALSE;
53      }
54    else
55      {
56         if (file[i] == '\0') return EINA_TRUE;
57         else if (((file[i] == 'z') || (file[i] == 'Z')) && (!file[i + 1])) return EINA_TRUE;
58         else return EINA_FALSE;
59      }
60 }
61
62 static int
63 _svg_init(const char *file)
64 {
65 #ifdef HAVE_SVG_2_36
66 # if !defined(GLIB_VERSION_2_36)
67    g_type_init();
68 # endif
69 #else
70    rsvg_init();
71 #endif
72
73    if (!evas_image_load_file_is_svg(file)) return 0;
74
75    rsvg = rsvg_handle_new_from_file(file, NULL);
76    if (!rsvg) return 0;
77
78    return 1;
79 }
80
81 static void
82 _svg_shutdown(void)
83 {
84    if (rsvg)
85      {
86         rsvg_handle_close(rsvg, NULL);
87         g_object_unref(rsvg);
88      }
89    // Maybe it's not crashing anymore, let's try it.
90 #ifndef HAVE_SVG_2_36
91    rsvg_term();
92 #endif
93 }
94
95 static int
96 read_svg_header(int scale_down, double dpi, int size_w, int size_h)
97 {
98    rsvg_handle_set_dpi(rsvg, 75.0);
99    rsvg_handle_get_dimensions(rsvg, &dim);
100    width = dim.width;
101    height = dim.height;
102
103    if ((width < 1) || (height < 1)) return 0;
104
105    if (scale_down > 1)
106      {
107         width /= scale_down;
108         height /= scale_down;
109      }
110    else if (dpi > 0.0)
111      {
112         width = (width * dpi) / 75;
113         height = (height * dpi) / 75;
114      }
115    else if (size_w > 0 && size_h > 0)
116      {
117         int w, h;
118
119         w = size_w;
120         h = (size_w * height) / width;
121         if (h > size_h)
122           {
123              h = size_h;
124              w = (size_h * width) / height;
125           }
126         width = w;
127         height = h;
128      }
129    if (width < 1) width = 1;
130    if (height < 1) height = 1;
131
132    return 1;
133 }
134
135 static int
136 read_svg_data(void)
137 {
138    cairo_surface_t *surface;
139    cairo_t *cr;
140
141    shm_alloc(width * height * (sizeof(DATA32)));
142    if (!shm_addr) return 0;
143
144    memset(shm_addr, 0, width * height * sizeof (DATA32));
145    surface = cairo_image_surface_create_for_data((unsigned char *)shm_addr, CAIRO_FORMAT_ARGB32,
146                                                  width, height, width * sizeof(DATA32));;
147    if (!surface) return 0;
148
149    cr = cairo_create(surface);
150    if (!cr) return 0;
151
152    cairo_scale(cr, (double) width / dim.em, (double) height / dim.ex);
153    rsvg_handle_render_cairo(rsvg, cr);
154    cairo_surface_destroy(surface);
155    cairo_destroy(cr);
156
157    return 1;
158 }
159
160 int main(int argc, char **argv)
161 {
162    char *file;
163    int i;
164    int head_only = 0;
165    int scale_down = 0;
166    double dpi = 0.0;
167    int size_w = 0, size_h = 0;
168
169    if (argc < 2) return -1;
170    file = argv[1];
171
172    for (i = 2; i < argc; ++i)
173      {
174         if (!strcmp(argv[i], "-head"))
175           head_only = 1;
176         else if (!strcmp(argv[i], "-key"))
177           { // not used by svg loader
178              i++;
179              // const char *key = argv[i];
180           }
181         else if (!strcmp(argv[i], "-opt-scale-down-by"))
182           {
183              i++;
184              scale_down = atoi(argv[i]);
185           }
186         else if (!strcmp(argv[i], "-opt-dpi"))
187           {
188              i++;
189              dpi = ((double)atoi(argv[i])) / 1000.0;
190           }
191         else if (!strcmp(argv[i], "-opt-size"))
192           {
193              i++;
194              size_w = atoi(argv[i]);
195              i++;
196              size_h = atoi(argv[i]);
197           }
198      }
199
200    timeout_init(5);
201    
202    if (!_svg_init(file)) return -1;
203    if (!read_svg_header(scale_down, dpi, size_w, size_h)) return -1;
204
205    if (head_only != 0)
206      {
207         printf("size %d %d\n", width, height);
208         printf("alpha 1\n");
209         printf("done\n");
210      }
211    else
212      {
213         if (read_svg_data())
214           {
215              printf("size %d %d\n", width, height);
216              printf("alpha 1\n");
217              if (shm_fd >= 0) printf("shmfile %s\n", shmfile);
218              else
219                {
220                   printf("data\n");
221                   if (fwrite(shm_addr, width * height * sizeof(DATA32), 1, stdout) != 1)
222                     {
223                        // nothing much to do, the receiver will simply ignore the
224                        // data as it's too short
225                        //D("fwrite failed (%d bytes): %m\n", width * height * sizeof(DATA32));
226                     }
227                }
228              shm_free();
229           }
230      }
231    _svg_shutdown();
232    fflush(stdout);
233    return 0;
234
235 }
236