Beispiel #1
0
def add_table(fig, x, y, name, fields):
    '''draw tabletop'''

    #  (NB: y grows downward)
    txt = TextElement(x, y, name, True)
    tt = TabletopElement(x, y)
    image_map[name] = {'coord': (x, y), 'def': '', 'descr': ''}
    fig.append(sg.GroupElement([tt, txt]))
    for f in fields:
        y += RECT_HEIGHT
        fig.append(add_field(x, y, f, name))
Beispiel #2
0
def add_field(x, y, f, table_name):
    '''draw a rectangle with field name, return group'''
    name = f[0]
    x_shift = 63.150 if table_name == 'message_in' and name == 'id' else 0
    txt = TextElement(x + x_shift, y, name)
    green_key = (table_name.startswith('message_')
                 and name in {'ino', 'mtime', 'pid'}
                 or table_name == name and name == 'domain')
    rect = RectElement(x, y, green_key)
    image_map[table_name + '-' + name] = {
        'coord': (x, y),
        'def': f[1],
        'descr': ''
    }
    return sg.GroupElement([rect, txt])
Beispiel #3
0
    def saveSVG(self, drawing, filename=None, path=None):
        # compute canvas size
        [xMin, yMin, width, height], strokeWidth = drawing.getViewBox()

        # create SVG
        svg = sg.SVGFigure(str(width) + "mm", str(height) + "mm")
        svg.root.set("viewBox", "%s %s %s %s" % (xMin, yMin, width, height))
        svgLines = []
        for line in drawing.polylines:
            # custom path creation
            points = " ".join(
                map(lambda x: "{:.3f},{:.3f}".format(x[0], -x[1]),
                    line.getPoints()))
            linedata = etree.Element(
                sg.SVG + "polyline", {
                    "points": points,
                    "stroke-width": str(strokeWidth),
                    "stroke-linecap": "square",
                    "stroke": line.color,
                    "fill": "none"
                })
            svgLines.append(sg.FigureElement(linedata))
        g = sg.GroupElement(svgLines, {'id': "root"})
        svg.append(g)

        # save generated SVG files
        if not (path):
            path = self.rootPath
        if not (filename):
            filename = drawing.filename

        filename = re.sub(
            r"[^(a-zA-Z0-9\-_)]+", "_", filename
        )  # make sure that only safe characters are used for filename
        mkpath(path)
        filepath = os.path.join(path, filename) + ".svg"
        drawing.filename = filename
        drawing.path = path
        drawing.url = self.pathToURL(filepath)
        logging.info("drawing.path: " + drawing.path)
        logging.info("drawing.url: " + drawing.url)
        svg.save(filepath)
Beispiel #4
0
 def __init__(self, dx, dy, size=8):
     self.size = size
     lines = self._gen_grid(dx, dy)
     element = _transform.GroupElement(lines)
     Element.__init__(self, element.root)
Beispiel #5
0
 def __init__(self, *svgelements):
     element = _transform.GroupElement(svgelements)
     Element.__init__(self, element.root)
Beispiel #6
0
def compose_view(bg_svgs, fg_svgs, ref=0, out_file='report.svg'):
    """
    Composes the input svgs into one standalone svg and inserts
    the CSS code for the flickering animation
    """
    import svgutils.transform as svgt

    if fg_svgs is None:
        fg_svgs = []

    # Merge SVGs and get roots
    svgs = bg_svgs + fg_svgs
    roots = [f.getroot() for f in svgs]

    # Query the size of each
    sizes = []
    for f in svgs:
        viewbox = [float(v) for v in f.root.get("viewBox").split(" ")]
        width = int(viewbox[2])
        height = int(viewbox[3])
        sizes.append((width, height))
    nsvgs = len(bg_svgs)

    sizes = np.array(sizes)

    # Calculate the scale to fit all widths
    width = sizes[ref, 0]
    scales = width / sizes[:, 0]
    heights = sizes[:, 1] * scales

    # Compose the views panel: total size is the width of
    # any element (used the first here) and the sum of heights
    fig = svgt.SVGFigure(width, heights[:nsvgs].sum())

    yoffset = 0
    for i, r in enumerate(roots):
        r.moveto(0, yoffset, scale=scales[i])
        if i == (nsvgs - 1):
            yoffset = 0
        else:
            yoffset += heights[i]

    # Group background and foreground panels in two groups
    if fg_svgs:
        newroots = [
            svgt.GroupElement(roots[:nsvgs], {'class': 'background-svg'}),
            svgt.GroupElement(roots[nsvgs:], {'class': 'foreground-svg'})
        ]
    else:
        newroots = roots
    fig.append(newroots)
    fig.root.attrib.pop("width")
    fig.root.attrib.pop("height")
    fig.root.set("preserveAspectRatio", "xMidYMid meet")
    out_file = op.abspath(out_file)
    fig.save(out_file)

    # Post processing
    with open(out_file, 'r' if PY3 else 'rb') as f:
        svg = f.read().split('\n')

    # Remove <?xml... line
    if svg[0].startswith("<?xml"):
        svg = svg[1:]

    # Add styles for the flicker animation
    if fg_svgs:
        svg.insert(
            2, """\
<style type="text/css">
@keyframes flickerAnimation%s { 0%% {opacity: 1;} 100%% { opacity: 0; }}
.foreground-svg { animation: 1s ease-in-out 0s alternate none infinite paused flickerAnimation%s;}
.foreground-svg:hover { animation-play-state: running;}
</style>""" % tuple([uuid4()] * 2))

    with open(out_file, 'w' if PY3 else 'wb') as f:
        f.write('\n'.join(svg))
    return out_file