Xorn
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
plainwrite.py
Go to the documentation of this file.
1 # xorn.geda - Python library for manipulating gEDA files
2 # Copyright (C) 1998-2010 Ales Hvezda
3 # Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
4 # Copyright (C) 2013-2016 Roland Lutz
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software Foundation,
18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ## \namespace xorn.geda.plainwrite
21 ## Writing gEDA schematic/symbol files.
22 
23 from gettext import gettext as _
24 import xorn.fileutils
25 import xorn.proxy
26 import xorn.storage
27 import xorn.base64
29 
30 ## Current gEDA \c PACKAGE_DATE_VERSION.
31 
32 RELEASE_VERSION = 20121203
33 
34 ## Current schematic/symbol file format version.
35 
36 FILEFORMAT_VERSION = 2
37 
38 ## Return the gEDA file header string.
39 #
40 # This function simply returns the DATE_VERSION and FILEFORMAT_VERSION
41 # formatted as a gEDA file header.
42 
44  return 'v %s %u\n' % (RELEASE_VERSION, FILEFORMAT_VERSION)
45 
46 ## Write a symbol or schematic to a file in libgeda format.
47 #
48 # \param [in] f A file-like object to which to write
49 # \param [in] rev The symbol or schematic which should be written
50 #
51 # \returns \c None
52 #
53 # \throws ValueError if an object with an unknown type is encountered
54 
55 def write_file(f, rev):
56  f.write(file_format_header())
57  for ob in rev.toplevel_objects():
58  write_object(f, ob, 0, 0)
59 
60 ## Format a line style to a string.
61 
62 def format_line(data):
63  return '%d %d %d %d %d' % (data.width,
64  data.cap_style,
65  data.dash_style,
66  data.dash_length,
67  data.dash_space)
68 
69 ## Format a fill style to a string.
70 
71 def format_fill(data):
72  return '%d %d %d %d %d %d' % (data.type,
73  data.width,
74  data.angle0,
75  data.pitch0,
76  data.angle1,
77  data.pitch1)
78 
79 ## Return the libgeda ripper direction of a bus object.
80 #
81 # Search the schematic for ripper components connecting to the bus.
82 # If rippers are found and are oriented in the same direction, return
83 # \c -1 or \c 1 depending on the orientation, otherwise return \c 0.
84 
86  bus_data = bus_ob.data()
87  found_neg = False
88  found_pos = False
89  for ob in xorn.proxy.RevisionProxy(bus_ob.rev).toplevel_objects():
90  data = ob.data()
91  if not isinstance(data, xorn.storage.Component) \
92  or data.symbol.basename != 'busripper-1.sym':
93  continue
94 
95  if data.angle == 0:
96  x = data.x + 200.
97  y = data.y + 200.
98  elif data.angle == 90:
99  x = data.x - 200.
100  y = data.y + 200.
101  elif data.angle == 180:
102  x = data.x - 200.
103  y = data.y - 200.
104  elif data.angle == 270:
105  x = data.x + 200.
106  y = data.y - 200.
107  else:
108  continue # invalid angle
109 
110  # check for vertical bus
111  if bus_data.width == 0 and bus_data.x == x \
112  and y >= min(bus_data.y, bus_data.y + bus_data.height) \
113  and y <= max(bus_data.y, bus_data.y + bus_data.height):
114  if data.angle == 0 or data.angle == 90:
115  found_pos = 1
116  else:
117  found_neg = 1
118 
119  # check for horizontal bus
120  if bus_data.height == 0 and bus_data.y == y \
121  and x >= min(bus_data.x, bus_data.x + bus_data.width) \
122  and x <= max(bus_data.x, bus_data.x + bus_data.width):
123  if data.angle == 0 or data.angle == 270:
124  found_pos = 1
125  else:
126  found_neg = 1
127 
128  if found_neg and found_pos:
129  # Found inconsistent ripperdir for bus. Setting to 0.
130  return 0
131  if found_neg:
132  return -1
133  if found_pos:
134  return 1
135  return 0
136 
137 ## Write an object to a file in libgeda format.
138 #
139 # It follows the post-20000704 release file format that handles the
140 # line type and fill options.
141 #
142 # \param [in] f A file-like object to which to write.
143 # \param [in] ob The object which should be written.
144 # \param [in] offset_x, offset_y Coordinate offset for embedded symbols.
145 #
146 # \return \c None.
147 #
148 # \throw ValueError if an object with an unknown type is encountered
149 
150 def write_object(f, ob, offset_x, offset_y):
151  data = ob.data()
152 
153  if isinstance(data, xorn.storage.Line):
154  f.write('%c %d %d %d %d %d %s\n' % (
155  xorn.geda.plainformat.OBJ_LINE,
156  offset_x + data.x,
157  offset_y + data.y,
158  offset_x + data.x + data.width,
159  offset_y + data.y + data.height,
160  data.color,
161  format_line(data.line)))
162  elif isinstance(data, xorn.storage.Net):
163  if data.is_pin:
164  if data.is_inverted:
165  x0, y0 = data.x + data.width, data.y + data.height
166  x1, y1 = data.x, data.y
167  else:
168  x0, y0 = data.x, data.y
169  x1, y1 = data.x + data.width, data.y + data.height
170 
171  f.write('%c %d %d %d %d %d %d %d\n' % (
172  xorn.geda.plainformat.OBJ_PIN,
173  offset_x + x0, offset_y + y0,
174  offset_x + x1, offset_y + y1,
175  data.color,
176  data.is_bus,
177  data.is_inverted))
178  elif data.is_bus:
179  f.write('%c %d %d %d %d %d %d\n' % (
180  xorn.geda.plainformat.OBJ_BUS,
181  offset_x + data.x,
182  offset_y + data.y,
183  offset_x + data.x + data.width,
184  offset_y + data.y + data.height,
185  data.color,
187  else:
188  f.write('%c %d %d %d %d %d\n' % (
189  xorn.geda.plainformat.OBJ_NET,
190  offset_x + data.x,
191  offset_y + data.y,
192  offset_x + data.x + data.width,
193  offset_y + data.y + data.height,
194  data.color))
195  elif isinstance(data, xorn.storage.Box):
196  f.write('%c %d %d %d %d %d %s %s\n' % (
197  xorn.geda.plainformat.OBJ_BOX,
198  offset_x + data.x,
199  offset_y + data.y,
200  data.width,
201  data.height,
202  data.color,
203  format_line(data.line),
204  format_fill(data.fill)))
205  elif isinstance(data, xorn.storage.Circle):
206  f.write('%c %d %d %d %d %s %s\n' % (
207  xorn.geda.plainformat.OBJ_CIRCLE,
208  offset_x + data.x,
209  offset_y + data.y,
210  data.radius,
211  data.color,
212  format_line(data.line),
213  format_fill(data.fill)))
214  elif isinstance(data, xorn.storage.Component):
215  if data.symbol.embedded:
216  basename = 'EMBEDDED' + data.symbol.basename
217  else:
218  basename = data.symbol.basename
219 
220  f.write('%c %d %d %d %d %d %s\n' % (
221  xorn.geda.plainformat.OBJ_COMPLEX,
222  offset_x + data.x,
223  offset_y + data.y,
224  data.selectable,
225  data.angle,
226  data.mirror,
227  basename))
228 
229  if data.symbol.embedded:
230  f.write('[\n')
231  for ob_ in xorn.proxy.RevisionProxy(
232  data.symbol.prim_objs).toplevel_objects():
233  write_object(f, ob_, offset_x + data.x, offset_y + data.y)
234  f.write(']\n')
235  elif isinstance(data, xorn.storage.Text):
236  # string can have multiple lines (seperated by \n's)
237  f.write('%c %d %d %d %d %d %d %d %d %d\n' % (
238  xorn.geda.plainformat.OBJ_TEXT,
239  offset_x + data.x,
240  offset_y + data.y,
241  data.color,
242  data.text_size,
243  data.visibility,
244  data.show_name_value,
245  data.angle,
246  data.alignment,
247  data.text.count('\n') + 1))
248  f.write(data.text + '\n')
249  elif isinstance(data, xorn.storage.Path):
250  f.write('%c %d %s %s %d\n' % (
251  xorn.geda.plainformat.OBJ_PATH,
252  data.color,
253  format_line(data.line),
254  format_fill(data.fill),
255  data.pathdata.count('\n') + 1))
256  f.write(data.pathdata + '\n')
257  elif isinstance(data, xorn.storage.Arc):
258  f.write('%c %d %d %d %d %d %d %s\n' % (
259  xorn.geda.plainformat.OBJ_ARC,
260  offset_x + data.x,
261  offset_y + data.y,
262  data.radius,
263  data.startangle,
264  data.sweepangle,
265  data.color,
266  format_line(data.line)))
267  elif isinstance(data, xorn.storage.Picture):
268  f.write('%c %d %d %d %d %d %d %d\n%s\n' % (
269  xorn.geda.plainformat.OBJ_PICTURE,
270  offset_x + data.x,
271  offset_y + data.y,
272  data.width,
273  data.height,
274  data.angle,
275  data.mirror,
276  data.pixmap.embedded,
277  data.pixmap.filename))
278 
279  if data.pixmap.embedded:
280  xorn.base64.encode(f, data.pixmap.data, delim = '.')
281  else:
282  raise ValueError, \
283  _("Encountered an object with unknown type %s") % type(data)
284 
285  # save any attributes
286  attribs = ob.attached_objects()
287  if attribs:
288  f.write('{\n')
289  for attrib in attribs:
290  write_object(f, attrib, offset_x, offset_y)
291  f.write('}\n')
def file_format_header
Return the gEDA file header string.
Definition: plainwrite.py:43
Reading and writing base64-encoded data.
Definition: base64.py:1
Schematic net segment, bus segment, or pin.
Definition: storage.py:549
Schematic arc.
Definition: storage.py:492
def write_object
Write an object to a file in libgeda format.
Definition: plainwrite.py:150
def encode
Write a binary string to a file in base64 representation.
Definition: base64.py:68
def bus_ripper_direction
Return the libgeda ripper direction of a bus object.
Definition: plainwrite.py:85
Writing files in a safe way.
Definition: fileutils.py:1
High-level revision proxy class.
Definition: proxy.py:24
def write_file
Write a symbol or schematic to a file in libgeda format.
Definition: plainwrite.py:55
Schematic picture.
Definition: storage.py:571
gEDA schematic/symbol file format constants
Definition: plainformat.py:1
Schematic path.
Definition: storage.py:562
Schematic box.
Definition: storage.py:504
Schematic component.
Definition: storage.py:527
Schematic circle.
Definition: storage.py:516
def format_fill
Format a fill style to a string.
Definition: plainwrite.py:71
Schematic text or attribute.
Definition: storage.py:583
High-level proxy classes for the storage backend.
Definition: proxy.py:1
def format_line
Format a line style to a string.
Definition: plainwrite.py:62
Xorn storage backend.
Definition: storage.py:1
Schematic line.
Definition: storage.py:538