Coverage for /media/ldata/code/tendril/tendril/gedaif/gschem.py : 0%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# Copyright (C) 2015 Chintalagiri Shashank # # This file is part of Tendril. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. """ gEDA gschem module documentation (:mod:`gedaif.gschem`) ======================================================= """
import re import os import subprocess from collections import deque
import tendril.utils.log logger = tendril.utils.log.get_logger(__name__, tendril.utils.log.INFO)
rex_vstring = re.compile(ur'^v (?P<gsch_ver>\d+) (?P<file_ver>\d+)$')
rex_el_line = re.compile(ur'^L (?P<x1>-?\d+) (?P<y1>-?\d+) (?P<x2>-?\d+) (?P<y2>-?\d+) (?P<color>\d+) (?P<width>\d+) (?P<capstyle>\d+) (?P<dashstyle>-?\d+) (?P<dashlength>-?\d+) (?P<dashspace>-?\d+)$') # noqa rex_el_picture = re.compile(ur'^G (?P<x1>-?\d+) (?P<y1>-?\d+) (?P<width>\d+) (?P<height>\d+) (?P<angle>\d+) (?P<mirrored>[01]) (?P<embedded>[01])$') # noqa rex_el_box = re.compile(ur'^B (?P<x>-?\d+) (?P<y>-?\d+) (?P<boxwidth>-?\d+) (?P<boxheight>-?\d+) (?P<color>\d+) (?P<width>\d+) (?P<capstyle>[012]) (?P<dashstyle>[01234]) (?P<dashlength>-?\d+) (?P<dashspace>-?\d+) (?P<filltype>[01234]) (?P<fillwidth>-?\d+) (?P<angle1>-?\d+) (?P<pitch1>-?\d+) (?P<angle2>-?\d+) (?P<pitch2>-?\d+)$') # noqa rex_el_circle = re.compile(ur'^V (?P<x>-?\d+) (?P<y>-?\d+) (?P<radius>-?\d+) (?P<color>\d+) (?P<width>\d+) (?P<capstyle>[0]) (?P<dashstyle>[01234]) (?P<dashlength>-?\d+) (?P<dashspace>-?\d+) (?P<filltype>[01234]) (?P<fillwidth>-?\d+) (?P<angle1>-?\d+) (?P<pitch1>-?\d+) (?P<angle2>-?\d+) (?P<pitch2>-?\d+)$') # noqa rex_el_arc = re.compile(ur'^A (?P<x>-?\d+) (?P<y>-?\d+) (?P<radius>-?\d+) (?P<startangle>-?\d+) (?P<sweepangle>-?\d+) (?P<color>\d+) (?P<width>\d+) (?P<capstyle>[0]) (?P<dashstyle>[01234]) (?P<dashlength>-?\d+) (?P<dashspace>-?\d+)$') # noqa rex_el_text = re.compile(ur'^T (?P<x>-?\d+) (?P<y>-?\d+) (?P<color>\d+) (?P<size>\d+) (?P<visibility>[01]) (?P<show_name_value>[012]) (?P<angle>\d+) (?P<alignment>[0-8]) (?P<num_lines>\d+)$') # noqa rex_el_net = re.compile(ur'^N (?P<x1>-?\d+) (?P<y1>-?\d+) (?P<x2>-?\d+) (?P<y2>-?\d+) (?P<color>\d+)$') # noqa rex_el_bus = re.compile(ur'^U (?P<x1>-?\d+) (?P<y1>-?\d+) (?P<x2>-?\d+) (?P<y2>-?\d+) (?P<color>\d+) (?P<ripperdir>-?\d)$') # noqa rex_el_pin = re.compile(ur'^P (?P<x1>-?\d+) (?P<y1>-?\d+) (?P<x2>-?\d+) (?P<y2>-?\d+) (?P<color>\d+) (?P<pintype>[01]) (?P<whichend>[01])$') # noqa rex_el_component = re.compile(ur'^C (?P<x>-?\d+) (?P<y>-?\d+) (?P<selectable>[01]) (?P<angle>\d+) (?P<mirror>[01]) (?P<basename>[\w.+ -]*)$') # noqa rex_el_path = re.compile(ur'^H (?P<color>\d+) (?P<width>\d+) (?P<capstyle>[012]) (?P<dashstyle>[01234]) (?P<dashlength>-?\d+) (?P<dashspace>-?\d+) (?P<filltype>[01234]) (?P<fillwidth>-?\d+) (?P<angle1>-?\d+) (?P<pitch1>-?\d+) (?P<angle2>-?\d+) (?P<pitch2>-?\d+) (?P<num_lines>[\d]+)$') # noqa
rex_block_start = re.compile(ur'^\s*[{]\s*$') rex_block_end = re.compile(ur'^\s*[}]\s*$')
map_color = {0: 'BACKGROUND_COLOR', 1: 'PIN_COLOR', 2: 'NET_ENDPOINT_COLOR', 3: 'GRAPHIC_COLOR', 4: 'NET_COLOR', 5: 'ATTRIBUTE_COLOR', 6: 'LOGIC_BUBBLE_COLOR', 7: 'DOTS_GRID_COLOR', 8: 'DETACHED_ATTRIBUTE_COLOR', 9: 'TEXT_COLOR', 10: 'BUS_COLOR', 11: 'SELECT_COLOR', 12: 'BOUNDINGBOX_COLOR', 13: 'ZOOM_BOX_COLOR', 14: 'STROKE_COLOR', 15: 'LOCK_COLOR', 16: 'OUTPUT_BACKGROUND_COLOR', 17: 'FREESTYLE1_COLOR', 18: 'FREESTYLE2_COLOR', 19: 'FREESTYLE3_COLOR', 20: 'FREESTYLE4_COLOR', 21: 'JUNCTION_COLOR', 22: 'MESH_GRID_MAJOR_COLOR', 23: 'MESH_GRID_MINOR_COLOR' }
map_capstyle = {0: 'END NONE', 1: 'END SQUARE', 2: 'END ROUND' }
map_dashstyle = {0: 'TYPE SOLID', 1: 'TYPE DOTTED', 2: 'TYPE DASHED', 3: 'TYPE CENTER', 4: 'TYPE PHANTOM' }
map_filltype = {0: 'FILLING HOLLOW', 1: 'FILLING FILL', 2: 'FILLING MESH', 3: 'FILLING HATCH', 4: 'FILLING VOID' }
map_pintype = {0: 'NORMAL PIN', 1: 'BUS PIN' }
map_shownamevalue = {0: 'SHOW NAME VALUE', 1: 'SHOW VALUE', 2: 'SHOW NAME' }
import tendril.utils.pdf from tendril.utils.types.cartesian import CartesianPoint from tendril.utils.types.cartesian import CartesianLineSegment
from tendril.utils.config import GEDA_SCHEME_DIR from tendril.utils.config import USE_SYSTEM_GAF_BIN from tendril.utils.config import GAF_BIN_ROOT
import sym2eps
class GschPoint(CartesianPoint): unit = 'mil'
def __init__(self, parent, x, y): super(GschPoint, self).__init__(x, y) self._parent = parent
@property def parent(self): return self._parent
class GschLine(CartesianLineSegment): def __init__(self, parent, p1, p2): super(GschLine, self).__init__(p1, p2) self._parent = parent
@property def parent(self): return self._parent
class GschElementBase(object): def __init__(self, parent, lines, **kwargs): for k, v in kwargs.items(): try: setattr(self, k, int(v)) except ValueError: setattr(self, k, v) self._parent = parent self._elements = [] self._get_multiline(lines)
def add_element(self, element): self._elements.append(element)
def _get_multiline(self, lines): return
@property def parent(self): return self._parent
@property def active_point(self): return []
@property def active_points(self): rval = self.active_point for element in self._elements: rval += element.active_points return rval
@property def passive_line(self): return []
@property def passive_lines(self): rval = self.passive_line for element in self._elements: rval += element.passive_lines return rval
def write_out(self, f): raise NotImplementedError
class GschElementComponent(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementComponent, self).__init__(parent, lines, **kwargs)
class GschElementNet(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementNet, self).__init__(parent, lines, **kwargs)
class GschElementBus(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementBus, self).__init__(parent, lines, **kwargs)
class GschElementPin(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementPin, self).__init__(parent, lines, **kwargs)
class GschElementLine(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementLine, self).__init__(parent, lines, **kwargs)
class GschElementBox(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementBox, self).__init__(parent, lines, **kwargs)
class GschElementCircle(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementCircle, self).__init__(parent, lines, **kwargs)
class GschElementArc(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementArc, self).__init__(parent, lines, **kwargs)
class GschElementText(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementText, self).__init__(parent, lines, **kwargs)
def _get_multiline(self, lines): self._lines = [] for i in range(int(self.num_lines)): self._lines.append(lines.popleft())
class GschElementPicture(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementPicture, self).__init__(parent, lines, **kwargs)
def _get_multiline(self, lines): self.fpath = lines.popleft() self._encoded = [] if self.embedded == 1: line = None while line.strip() != '.': self._encoded.append(lines.popleft())
class GschElementPath(GschElementBase): def __init__(self, parent=None, lines=None, **kwargs): super(GschElementPath, self).__init__(parent, lines, **kwargs)
def _get_multiline(self, lines): self._segments = [] for i in range(int(self.num_lines)): self._segments.append(lines.popleft())
class GschFile(object): def __init__(self, fpath): self.fpath = fpath self._elements = [] self._load_file()
def add_element(self, element): self._elements.append(element)
def _get_version(self, lines): m = None while not m: m = rex_vstring.match(lines.popleft()) self._gschver = m.group('gsch_ver') self._filever = m.group('file_ver')
@staticmethod def _get_next_element(parent, lines): line = None while not line: line = lines.popleft() if line.startswith('L'): return GschElementLine(parent, lines=lines, **rex_el_line.match(line).groupdict()) # noqa elif line.startswith('G'): return GschElementPicture(parent, lines=lines, **rex_el_picture.match(line).groupdict()) # noqa elif line.startswith('B'): return GschElementBox(parent, lines=lines, **rex_el_box.match(line).groupdict()) # noqa elif line.startswith('V'): return GschElementCircle(parent, lines=lines, **rex_el_circle.match(line).groupdict()) # noqa elif line.startswith('A'): return GschElementArc(parent, lines=lines, **rex_el_arc.match(line).groupdict()) # noqa elif line.startswith('T'): return GschElementText(parent, lines=lines, **rex_el_text.match(line).groupdict()) # noqa elif line.startswith('N'): return GschElementNet(parent, lines=lines, **rex_el_net.match(line).groupdict()) # noqa elif line.startswith('U'): return GschElementBus(parent, lines=lines, **rex_el_bus.match(line).groupdict()) # noqa elif line.startswith('P'): return GschElementPin(parent, lines=lines, **rex_el_pin.match(line).groupdict()) # noqa elif line.startswith('C'): return GschElementComponent(parent, lines=lines, **rex_el_component.match(line).groupdict()) # noqa elif line.startswith('H'): return GschElementPath(parent, lines=lines, **rex_el_path.match(line).groupdict()) # noqa else: raise AttributeError(line)
def _load_file(self): with open(self.fpath, 'r') as f: lines = deque(f.readlines()) self._get_version(lines) block_level = 0 targets = {0: self} element = None while len(lines): if rex_block_start.match(lines[0]): if not element: raise Exception block_level += 1 targets[block_level] = element lines.popleft() elif rex_block_end.match(lines[0]): block_level -= 1 lines.popleft() element = self._get_next_element(targets[block_level], lines) targets[block_level].add_element(element)
def write_out(self, f): raise NotImplementedError
def conv_gsch2pdf(schpath, docfolder): schpath = os.path.normpath(schpath) schfname = os.path.splitext(os.path.split(schpath)[1])[0] pspath = os.path.join(docfolder, schfname + '.ps') pdfpath = os.path.join(docfolder, schfname + '.pdf') # TODO fix this if USE_SYSTEM_GAF_BIN: gschem_pscmd = "gschem -o" + pspath + \ " -s" + GEDA_SCHEME_DIR + '/print.scm ' + schpath subprocess.call(gschem_pscmd.split(' ')) tendril.utils.pdf.conv_ps2pdf(pspath, pdfpath) os.remove(pspath) else: gaf_pdfcmd = [os.path.join(GAF_BIN_ROOT, 'gaf'), 'export', '-o', pdfpath, schpath] subprocess.call(gaf_pdfcmd) return pdfpath
def conv_gsch2png(schpath, outfolder): schpath = os.path.normpath(schpath) schfname, ext = os.path.splitext(os.path.split(schpath)[1])
outpath = os.path.join(outfolder, schfname + '.png') epspath = os.path.join(outfolder, schfname + '.eps')
if ext == '.sym': try: sym2eps.convert(schpath, epspath) except RuntimeError: logger.error("SYM2EPS Segmentation Fault on symbol : " + schpath) gschem_pngcmd = [ "convert", epspath, "-transparent", "white", outpath ] subprocess.call(gschem_pngcmd) try: os.remove(epspath) except OSError: logger.warning("Temporary .eps file not found to remove : " + epspath) elif ext == '.sch': gschem_pngcmd = "gschem -p -o" + outpath + " -s" + GEDA_SCHEME_DIR + '/image.scm ' + schpath # noqa subprocess.call(gschem_pngcmd) return outpath
if __name__ == "__main__": pass |