Giter Site home page Giter Site logo

svg_stack's Introduction

svg_stack - combine multiple SVG elements into a single SVG element

Overview

svg_stack combines multiple SVG elements into a single SVG element. It can be called from the command line (less flexible) or called from the Python interface (more flexible).

This tool primarily exists to automatically composite SVG files into a single SVG file that remains compatible with Inkscape. If compatibility with Inkscape is not required, one can create an svg file with multiple, nested <svg> elements. Inkscape, however, doesn't seem to handle nested <svg> elements particularly well. Thus, this tool was born.

Example command line usage

For example, given the files red_ball.svg and blue_triangle.svg:

svg_stack.py --direction=h --margin=100 red_ball.svg blue_triangle.svg > shapes.svg

will stack them horizontally with a 100 px margin between them. The result will be in a file called shapes.svg.

Example Python usage

A Qt like API provides more advanced layout capabilities. For example:

#!/usr/bin/env python

import svg_stack as ss

doc = ss.Document()

layout1 = ss.HBoxLayout()
layout1.addSVG('red_ball.svg',alignment=ss.AlignTop|ss.AlignHCenter)
layout1.addSVG('blue_triangle.svg',alignment=ss.AlignCenter)

layout2 = ss.VBoxLayout()

layout2.addSVG('red_ball.svg',alignment=ss.AlignCenter)
layout2.addSVG('red_ball.svg',alignment=ss.AlignCenter)
layout2.addSVG('red_ball.svg',alignment=ss.AlignCenter)
layout1.addLayout(layout2)

doc.setLayout(layout1)

doc.save('qt_api_test.svg')

See also

Meta-data

Command-line usage

Usage: svg_stack.py FILE1 [FILE2] [...] [options]

concatenate SVG files

This will concatenate FILE1, FILE2, ... to a new svg file printed to
stdout.



Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  --margin=MARGIN       size of margin (in any units, px default)
  --direction=DIRECTION
                        horizontal or vertical (or h or v)

svg_stack's People

Contributors

astraw avatar atharvashukla avatar eointravers avatar swinman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

svg_stack's Issues

Undefined variable name `file` in Document.save()

Expected behavior

The example script from the README.rst file runs without error, creating the .svg file named qt_api_test.svg.

Actual behavior

Running the example script produces a NameError due to an undefined variable named file:

#!/usr/bin/env python

import svg_stack as ss
import sys

print("Python version:\n{}\n".format(sys.version))
print('svg_stack version: {}'.format(ss.VERSION))

doc = ss.Document()

layout1 = ss.HBoxLayout()
layout1.addSVG('red_ball.svg',alignment=ss.AlignTop|ss.AlignHCenter)
layout1.addSVG('blue_triangle.svg',alignment=ss.AlignCenter)

layout2 = ss.VBoxLayout()

layout2.addSVG('red_ball.svg',alignment=ss.AlignCenter)
layout2.addSVG('red_ball.svg',alignment=ss.AlignCenter)
layout2.addSVG('red_ball.svg',alignment=ss.AlignCenter)
layout1.addLayout(layout2)

doc.setLayout(layout1)

doc.save('qt_api_test.svg')

Output from the above

Python version:
3.5.2 |Continuum Analytics, Inc.| (default, Jul  2 2016, 17:53:06) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]

svg_stack version: 0.0.1

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-2f37d519097d> in <module>()
     22 doc.setLayout(layout1)
     23 
---> 24 doc.save('qt_api_test.svg')

/home/douglass/anaconda3/envs/bstore/lib/python3.5/site-packages/svg_stack.py in save(self, fileobj, debug_boxes, **kwargs)
    159         accum = LayoutAccumulator(**kwargs)
    160         self._layout.render(accum,debug_boxes=debug_boxes)
--> 161         if isinstance(fileobj,file):
    162             fd = fileobj
    163             close = False

NameError: name 'file' is not defined

Current commit

git log

commit 06f8ce8efe159e9724696e74b4f3a8b1820e9a46
Merge: a5d0864 836b6f0
Author: Andrew Straw <[email protected]>
Date:   Fri Feb 5 20:43:05 2016 +0100

    Merge pull request #6 from pascal-git/master

    added cm as accepted units

Stack SVGs on top of one another

The tool can put SVG next to each other. I am looking for something that puts SVGs on top of one another. Would it be possible to do this with this tool or do you know another tool that can do it?

Special characters throw exception

exception content :

Traceback (most recent call last): File "/dat/svgStack/svg_stack.py", line 713, in <module> main() File "/dat/svgStack/svg_stack.py", line 706, in main layout.addSVG(fname,alignment=AlignCenter) File "/dat/svgStack/svg_stack.py", line 632, in addSVG svg_file = SVGFile(svg_file) File "/dat/svgStack/svg_stack.py", line 177, in __init__ self._root = etree.parse(fname).getroot() File "lxml.etree.pyx", line 3197, in lxml.etree.parse (src/lxml/lxml.etree.c:64816) File "parser.pxi", line 1571, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:92729) File "parser.pxi", line 1600, in lxml.etree._parseDocumentFromURL (src/lxml/lxml.etree.c:93013) File "parser.pxi", line 1500, in lxml.etree._parseDocFromFile (src/lxml/lxml.etree.c:92076) File "parser.pxi", line 1047, in lxml.etree._BaseParser._parseDocFromFile (src/lxml/lxml.etree.c:88976) File "parser.pxi", line 577, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:84385) File "parser.pxi", line 676, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:85488) File "parser.pxi", line 616, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:84811) lxml.etree.XMLSyntaxError: PCDATA invalid Char value 3, line 565, column 70

exception Svg fragment:
<text alignment-baseline="auto" font-size="14" style="" x="843.5224609375" y="13.02" >�</text>

Requirements.txt: Add "six" module

Traceback (most recent call last):
  File "/home/user/code/svg_stack/./svg_stack.py", line 28, in <module>
    from six import string_types
ModuleNotFoundError: No module named 'six'

scaling issue 90dpi 96dpi

I'm running into scaling issues using svg_stack which seem to be caused by the change from 90dpi to 96dpi as the default for svg files.

I have a python3 script which takes various svgs, sorts them, and uses svg_stack to put them together onto a single page, saves it as an svg, and then uses inkscape to export to pdf.

On some machines the scale in my final svg / pdf is correct. On other machines the output is scaled down by 90/96 (93.75%).

The machines that work correctly are running older version of Linux Mint, the ones that fail are running newer versions of Ubuntu.

The base svgs are created and saved in Inkscape. I can get them to output at the correct scale if inside Inkscape I change the "Custom Size" units from mm to px in the Document Properties. The problem is that I've got lots of base svgs and I want them to be in mm so it's easier for users to create and save them.

I previously opened this issue and incorrectly closed it thinking it was a windows / Inkscape error
#10

I'd love some help to have these scale correctly!!

AttributeError: 'NoneType' object has no attribute 'endswith'

Traceback (most recent call last):
File "./svg_stack.py", line 713, in
main()
File "./svg_stack.py", line 706, in main
layout.addSVG(fname,alignment=AlignCenter)
File "./svg_stack.py", line 632, in addSVG
svg_file = SVGFile(svg_file)
File "./svg_stack.py", line 181, in init
height, height_units = get_unit_attr(self._root.get('height'))
File "./svg_stack.py", line 44, in get_unit_attr
if value.endswith(unit_name):
AttributeError: 'NoneType' object has no attribute 'endswith'

I'm getting this error when running svg_stack via the following commands:
python2 ./svg_stack.py --direction=h --margin=100 virus.svg web-interface.svg > shapes.svg
python ./svg_stack.py --direction=h --margin=100 virus.svg web-interface.svg > shapes.svg
./svg_stack.py --direction=h --margin=100 virus.svg web-interface.svg > shapes.svg

I also tried running ./setup.py install and
svg_stack.py --direction=h --margin=100 virus.svg web-interface.svg > shapes.svg

gives same error.

I've also installed python-lxml and python3-lxml to no avail. Any idea what I'm doing wrong here?

addSVGNoLayout not working

Rather than concatenating different .svg files like in the example. I would like to insert .svg files into a larger main figure. For that purpose, I have used the addSVGNoLayout() function in the past. However, I cannot get it to work using the current repository version.

When running the code below, I get the output that the width of the two added figures is scales to zero. Might that be the problem?
Output :

Changing width of blue_triangle.svg from 235.29 to 0.00
Changing height of blue_triangle.svg from 141.00 to 1122.52
Changing width of red_ball.svg from 198.14 to 0.00
Changing height of red_ball.svg from 198.14 to 1122.52

And here is the example code.

#!/usr/bin/env python

import svg_stack as svgs
import os

doc = svgs.Document()

layout1 = svgs.HBoxLayout() # VBoxLayout()
layout1.addSVG('page.svg' ,alignment=svgs.AlignTop|svgs.AlignHCenter)
layout1.addSVGNoLayout('blue_triangle.svg',x=100,y=100)
layout1.addSVGNoLayout('red_ball.svg',x=100,y=100)

doc.setLayout(layout1)

fignameCompose = 'qt_api_test2'
doc.save('%s.svg' % fignameCompose)

Thanks in advance.

For interactive SVG pictures (generated by pygal), black boxes are displayed after splicing

import pygal # 导入 pygal

bar_chart1 = pygal.Bar() # 创建一个换图对象
bar_chart1.add("FirsrtTry", [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]) # 添加一些值和对应的序列
bar_chart1.add("SecondTry", [55, 34, 21, 13, 8, 5, 3, 2, 1, 1, 0]) # 再添加另一个序列
bar_chart1.render_to_file("./graph1.svg")

bar_chart2 = pygal.Bar() # 创建一个换图对象
bar_chart2.add("FirsrtTry", [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]) # 添加一些值和对应的序列
bar_chart2.add("SecondTry", [55, 34, 21, 13, 8, 5, 3, 2, 1, 1, 0]) # 再添加另一个序列
bar_chart1.render_to_file("./graph2.svg")

import svg_stack as ss

doc = ss.Document()

layout1 = ss.HBoxLayout()
layout1.addSVG("graph1.svg", alignment=ss.AlignTop | ss.AlignHCenter)
layout1.addSVG("graph2.svg", alignment=ss.AlignCenter)

layout2 = ss.VBoxLayout()

layout2.addSVG("graph1.svg", alignment=ss.AlignCenter)
layout2.addSVG("graph1.svg", alignment=ss.AlignCenter)
layout2.addSVG("graph1.svg", alignment=ss.AlignCenter)
layout1.addLayout(layout2)

doc.setLayout(layout1)

image

image

image

"Advanced" layout options need documenting

There's not enough in the README to get started using the Python layout features.

For instance, combing/concatenating layouts.

In the CLI usage, you can definitely do

svg_stack.py --direction=h margin=0 a.svg b.svg c.svg d.svg > row1.svg
svg_stack.py --direction=h margin=0 e.svg f.svg g.svg h.svg > row2.svg

svg_stack.py --direction=v margin=0 row1.svg row2.svg > grid.svg

and get a little

a b c d
e f g h

matrix out.

Trying to replicate that from two ss.HBoxLayouts either doesn't work or else there's some syntax about combining them that isn't clear.

Just trying it straight, making a couple of HBoxLayouts and adding them to a VBoxLayout raises NotImplementedError: rescaling width not implemented (hint: set alignment on file SVGFile('grid.svg'))

...which itself is confusing in two respects: first, I don't ask for any rescaling, so it'd be good to know where that enters into it (and how to configure it), and second, how/where to set an alignment on the output file.

I think this is a fairly straightforward potential use-case, and showing how to do it would help a lot of new users move beyond the 1D example of the CLI.

Globing possible?

Is it possible to do globbing?

For example, where there are 50 images in a folder called 'svgs':

svg_stack.py --direction=h --margin=100 svgs/* > sprite.svg

Make installation requirements explicit in setup.py

I just "successfully installed" svg_stack, only to find that the svg_stack.py script would not run without first installing lxml (which was easy to do with pip install lxml). It would be nice if installation failed without this dependency, for the sake of clarity.

A thank you

Thanks for svg_stack! It is the one I am looking for for so long.

Although javascript can do the job as well, I am really happy to find a python solution!

Many thanks,
Jun

AttributeError: 'NoneType' object has no attribute 'endswith'

Hi,

I run into the following error when I want to concatenate a bunch of svg files as follows

svg_stack.py --direction=v --margin=100 Figure\ S1.svg Figure\ S2.svg Figure\ S3.svg Figure\ S4.svg Figure\ S5.svg Figure\ S6.svg Figure\ S7.svg Figure\ S8.svg Figure\ S9.svg Figure\ S10.svg Figure\ S11.svg Figure\ S12.svg Figure\ S13.svg Figure\ S14 Figure\ S15.svg Figure\ S16 > Figures_SI.svg
Traceback (most recent call last):
File "/home/.conda/envs/svg/bin/svg_stack.py", line 713, in
main()
File "/home/.conda/envs/svg/bin/svg_stack.py", line 706, in main
layout.addSVG(fname,alignment=AlignCenter)
File "/home/janssetk/.conda/envs/svg/bin/svg_stack.py", line 632, in addSVG
svg_file = SVGFile(svg_file)
File "/home/.conda/envs/svg/bin/svg_stack.py", line 181, in init
height, height_units = get_unit_attr(self._root.get('height'))
File "/home/.conda/envs/svg/bin/svg_stack.py", line 44, in get_unit_attr
if value.endswith(unit_name):
AttributeError: 'NoneType' object has no attribute 'endswith'

Wierd color changes

Some images get wierd color changes when stacked. I had this with plain Inkscape when copying and pasting grouped items, works fine when ungrouped, tho. Behaves same both when original svgs are grouped and ungrouped.
Original:
original

Result:
result
Svgs: svgs.zip

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.