add packaging files
[platform/upstream/edje.git] / utils / inkscape2edc
1 #!/usr/bin/env python
2
3 import os
4 import os.path
5 import subprocess
6 import logging as log
7 import re
8
9
10 class Inkscape2Edc(object):
11     cmd = "inkscape --without-gui"
12     def __init__(self, infile, outfile, group,
13                  relative1_x=None, relative2_x=None,
14                  relative1_y=None, relative2_y=None,
15                  images_dir="",
16                  show_max=True, show_min=True, show_mouse_events=True):
17         self.infile = infile
18         self.outfile = outfile
19         self.group = group
20         self.relative1_x = relative1_x
21         self.relative2_x = relative2_x
22         self.relative1_y = relative1_y
23         self.relative2_y = relative2_y
24         self.images_dir = images_dir
25         self.show_max = show_max
26         self.show_min = show_min
27         self.show_mouse_events = show_mouse_events
28
29         self.images = {}
30         self.sizes = {}
31         self.known_ids = tuple()
32         self.w = 0
33         self.h = 0
34
35         self.out = open(self.outfile, "wb")
36         self.basedir = os.path.dirname(self.outfile)
37
38     def _exec_cmd(self, *args):
39         s = " ".join(args)
40         cmd = "%s --file=%r %s" % (self.cmd, self.infile, s)
41         try:
42             p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
43                                  stderr=subprocess.PIPE, shell=True)
44         except Exception, e:
45             log.error("cmd=%r exception: %s", cmd, e)
46             return ""
47
48         out, err = p.communicate()
49         if err:
50             log.error("cmd=%r error: %s", cmd, err)
51
52         return out
53
54     def load_sizes(self):
55         sizes = self._exec_cmd("--query-all").split('\n')
56
57         self.sizes = {}
58         order = []
59         for line in sizes:
60             if not line:
61                 continue
62             try:
63                 oid, x, y, w, h = line.split(',')
64             except ValueError:
65                 log.warn("could not parse size line: %r", line)
66                 continue
67             x = float(x)
68             y = float(y)
69             w = float(w)
70             h = float(h)
71             self.sizes[oid] = (x, y, w, h)
72             order.append(oid)
73
74         self.known_ids = tuple(order)
75
76         self.w = float(self._exec_cmd("--query-width"))
77         self.h = float(self._exec_cmd("--query-height"))
78
79     def output_file_header(self):
80         self.out.write("""\
81 collections {
82    group {
83       name: "%(group)s";
84 """ % self.__dict__)
85
86         if self.show_min:
87             self.out.write("      min: %(w)d %(h)d;\n" % self.__dict__)
88
89         if self.show_max:
90             self.out.write("      max: %(w)d %(h)d;\n" % self.__dict__)
91
92     def output_file_section_parts_begin(self):
93         self.out.write("      parts {\n")
94
95     def output_file_section_parts_end(self):
96         self.out.write("      }\n")
97
98     def output_file_section_images_begin(self):
99         self.out.write("      images {\n")
100
101     def output_file_section_images_end(self):
102         self.out.write("      }\n")
103
104     def output_file_foot(self):
105         self.out.write("""\
106    }
107 }
108 """)
109
110     def output_image(self, oid):
111         img = os.path.join(self.images_dir, oid)
112         img += ".png"
113
114         self._exec_cmd("--export-id='%s'" % oid,
115                        "--export-id-only",
116                        "--export-png='%s'" % os.path.join(self.basedir, img))
117
118         self.out.write('         image: "%s" COMP;\n' % img)
119         self.images[oid] = img
120
121     def output_part_desc_rel(self, x, y, w, h):
122         def choose_rel(relative, value, value_max):
123             if relative is not None:
124                 return relative
125             elif value <= abs(value_max - value):
126                 return 0.0
127             else:
128                 return 1.0
129
130         x2 = x + w - 1
131         y2 = y + h - 1
132
133         rx1 = choose_rel(self.relative1_x, x, w)
134         rx2 = choose_rel(self.relative2_x, x2, w)
135         ry1 = choose_rel(self.relative1_y, y, h)
136         ry2 = choose_rel(self.relative2_y, y2, h)
137
138         ox1 = x - self.w * rx1
139         ox2 = x2 - self.w * rx2
140
141         oy1 = y - self.h * ry1
142         oy2 = y2 - self.h * ry2
143
144         self.out.write("""\
145                rel1 {
146                   relative: %03.1f %03.1f;
147                   offset: %d %d;
148                }
149                rel2 {
150                   relative: %03.1f %03.1f;
151                   offset: %d %d;
152                }
153 """ % (rx1, ry1, ox1, oy1, rx2, ry2, ox2, oy2))
154
155
156     def output_part(self, oid):
157         try:
158             x, y, w, h = self.sizes[oid]
159         except KeyError:
160             log.error("no such object id: %s", oid)
161             return
162
163         info = {
164             "name": oid,
165             "x": x,
166             "y": y,
167             "w": w,
168             "h": h,
169             }
170
171         self.out.write("""
172          part {
173             name: "%(name)s";
174             type: IMAGE;
175 """ % info)
176
177         if self.show_mouse_events:
178             self.out.write("            mouse_events: 0;\n")
179
180         self.out.write("""\
181             description {
182                state: "default" 0.0;
183 """)
184
185         if self.show_min:
186             self.out.write("               min: %(w)d %(h)d;\n" % info)
187
188         if self.show_max:
189             self.out.write("               max: %(w)d %(h)d;\n" % info)
190
191         self.output_part_desc_rel(x, y, w, h)
192         self.out.write("""\
193                image.normal: "%s";
194             }
195          }
196 """ % (self.images[oid],))
197
198
199 def foreach_id(inkscape2edc, ids=None, re_exclude=None):
200     if ids:
201         for oid in inkscape2edc.known_ids:
202             if oid in ids:
203                 yield oid
204     else:
205         for oid in inkscape2edc.known_ids:
206             if re_exclude is not None and re_exclude.match(oid):
207                 continue
208             yield oid
209
210
211 if __name__ == "__main__":
212     import optparse
213
214     usage = "usage: %prog [options] <input.svg>"
215     parser = optparse.OptionParser(usage=usage)
216
217     parser.add_option("-i", "--id", action="append", default=[],
218                       help=("Object ID to use, it will be the part name. "
219                             "Multiple usage to use more object ids."))
220     parser.add_option("-e", "--exclude", action="store", default=None,
221                       help=("Exclude regular expression."
222                             "Matching IDs will be ignored."))
223     parser.add_option("-o", "--output", action="store", default=None,
224                       help="Output file to use")
225     parser.add_option("-g", "--group", action="store", default=None,
226                       help="Group name")
227     parser.add_option("-d", "--images-dir", action="store", default="",
228                       help="Directory where to output images.")
229     parser.add_option("--no-min", action="store_true",
230                       help="Do not output min values")
231     parser.add_option("--no-max", action="store_true",
232                       help="Do not output max values")
233     parser.add_option("--no-mouse_events", action="store_true",
234                       help="Do not output mouse_events lines")
235     parser.add_option("--relative1-y", action="store",
236                       choices=("top", "bottom", "auto"),
237                       default="auto",
238                       help=("Choose what to use as base for rel1 y values, "
239                             "top=0.0, bottom=1.0, auto=nearest"))
240     parser.add_option("--relative2-y", action="store",
241                       choices=("top", "bottom", "auto"),
242                       default="auto",
243                       help=("Choose what to use as base for rel2 y values, "
244                             "top=0.0, bottom=1.0, auto=nearest"))
245     parser.add_option("--relative1-x", action="store",
246                       choices=("left", "right", "auto"),
247                       default="auto",
248                       help=("Choose what to use as base for rel1 x values, "
249                             "left=0.0, right=1.0, auto=nearest"))
250     parser.add_option("--relative2-x", action="store",
251                       choices=("left", "right", "auto"),
252                       default="auto",
253                       help=("Choose what to use as base for rel2 x values, "
254                             "left=0.0, right=1.0, auto=nearest"))
255
256
257     options, args = parser.parse_args()
258
259     try:
260         infile = args[0]
261     except IndexError:
262         parser.print_help()
263         raise SystemExit("missing input file name")
264
265     fname = os.path.splitext(infile)[0]
266     if not options.output:
267         options.output = fname + ".edc"
268
269     if not options.group:
270         options.group = fname
271
272     rx_map = {"left": 0.0, "right": 1.0}
273     options.relative1_x = rx_map.get(options.relative1_x, None)
274     options.relative2_x = rx_map.get(options.relative2_x, None)
275
276     ry_map = {"top": 0.0, "bottom": 1.0}
277     options.relative1_y = ry_map.get(options.relative1_y, None)
278     options.relative2_y = ry_map.get(options.relative2_y, None)
279
280     o = Inkscape2Edc(infile, options.output, options.group,
281                      relative1_x=options.relative1_x,
282                      relative2_x=options.relative2_x,
283                      relative1_y=options.relative1_y,
284                      relative2_y=options.relative2_y,
285                      images_dir=options.images_dir,
286                      show_max=not options.no_max, show_min=not options.no_min,
287                      show_mouse_events=not options.no_mouse_events)
288
289     re_exclude = None
290     if options.exclude:
291         re_exclude = re.compile(options.exclude)
292
293     if options.images_dir:
294         os.makedirs(options.images_dir)
295
296     o.load_sizes()
297     o.output_file_header()
298
299     o.output_file_section_images_begin()
300     for oid in foreach_id(o, options.id, re_exclude):
301         o.output_image(oid)
302     o.output_file_section_images_end()
303
304     o.output_file_section_parts_begin()
305     for oid in foreach_id(o, options.id, re_exclude):
306         o.output_part(oid)
307     o.output_file_section_parts_end()
308
309     o.output_file_foot()