Skip to content

Instantly share code, notes, and snippets.

@larscwallin
Last active December 16, 2015 19:59
Show Gist options
  • Select an option

  • Save larscwallin/5489140 to your computer and use it in GitHub Desktop.

Select an option

Save larscwallin/5489140 to your computer and use it in GitHub Desktop.

Revisions

  1. larscwallin revised this gist May 10, 2013. 3 changed files with 38 additions and 21 deletions.
    20 changes: 14 additions & 6 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,19 @@
    A README
    | A README

    larscwallin.inx.extractelements version 0.1 extracts all selected SVG Elements to file and/or displayed as a string in the Inkscape GUI.
    | larscwallin.inx.extractelements version 0.1 extracts all selected SVG Elements to file and/or displayed as a string in the
    | Inkscape GUI.

    || UPDATE 130506
    Added movePath method which moves all paths to 0,0 coordinates regardless of their original placement.

    If no elements are selected, the extension now defaults to exporting any visible layers. Precondition for this is that layers have been hidden and then shown again at some point as Inkscape currently does not add this meta data by default.
    || UPDATE 130510
    |||| Added option to keep the canvas size of the original drawing when exporting.
    (Previously each exported drawing was sized according to its elements bounding box)
    |||| Bug fixes

    || UPDATE 130506
    |||| Added movePath method which moves all paths to 0,0 coordinates regardless of their original placement.
    |||| If no elements are selected, the extension now defaults to exporting any visible layers.
    Precondition for this is that layers have been hidden and then shown again at some point as Inkscape currently does not
    add meta data by default.

    || UPDATE 130503
    Added calculation of bounding box and width and height attributes for the resulting SVG doc.
    |||| Added calculation of bounding box and width and height attributes for the resulting SVG doc.
    4 changes: 3 additions & 1 deletion larscwallin.inx.extractelements.inx
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,9 @@
    <dependency type="executable" location="extensions">inkex.py</dependency>
    <param name="where" type="string" _gui-text="Output path"></param>
    <param name="encode" type="boolean" _gui-text="Do you wish to Base64 encode the SVG?">false</param>
    <param name="viewresult" type="boolean" _gui-text="Do you wish to view the resulting?">true</param>
    <param name="viewresult" type="boolean" _gui-text="Do you wish to view the result?">true</param>
    <param name="resize" type="boolean" _gui-text="Resize the drawing canvas for each element?">false</param>

    <effect>
    <object-type>all</object-type>
    <effects-menu>
    35 changes: 21 additions & 14 deletions larscwallin.inx.extractelements.py
    Original file line number Diff line number Diff line change
    @@ -39,12 +39,15 @@ def __init__(self):

    self.OptionParser.add_option('--encode', action = 'store',
    type = 'inkbool', dest = 'encode', default = False,
    help = 'Do you want to Base64 encode the result?')
    help = 'Base64 encode the result?')

    self.OptionParser.add_option('--viewresult', action = 'store',
    type = 'inkbool', dest = 'viewresult', default = False,
    help = 'Do you want to view the resulting document?')
    help = 'View resulting?')

    self.OptionParser.add_option('--resize', action = 'store',
    type = 'inkbool', dest = 'resize', default = False,
    help = 'Resize the drawing canvas to the elements?')


    def effect(self):
    @@ -53,7 +56,9 @@ def effect(self):
    """
    self.where = self.options.where
    self.base64Encode = self.options.encode
    self.viewResult = self.options.encode
    self.viewResult = self.options.viewresult
    self.resizeDrawing = self.options.resize


    self.getselected()

    @@ -104,8 +109,13 @@ def effect(self):

    if(elementSource!=''):
    # Wrap the node in an SVG doc
    tplResult = string.replace(self.exportTemplate,'{{element.width}}',str(elementWidth))
    tplResult = string.replace(tplResult,'{{element.height}}',str(elementHeight))
    if(self.resizeDrawing):
    tplResult = string.replace(self.exportTemplate,'{{element.width}}',str(elementWidth))
    tplResult = string.replace(tplResult,'{{element.height}}',str(elementHeight))
    else:
    tplResult = string.replace(self.exportTemplate,'{{element.width}}',str(self.svgWidth))
    tplResult = string.replace(tplResult,'{{element.height}}',str(self.svgHeight))

    tplResult = string.replace(tplResult,'{{element.source}}',elementSource)

    # If the result of the operation is valid, add the SVG source to the selected array
    @@ -126,7 +136,7 @@ def effect(self):
    if(content!=''):

    if(self.base64Encode):
    content = (base64.b64encode(content))
    content = ('data:image/svg+xml;base64,'+(base64.b64encode(content)))

    if(self.where!=''):

    @@ -135,25 +145,22 @@ def effect(self):
    filename = os.path.join(self.where, (node['id']+node['label']+'.svg'))
    success = self.saveToFile(content,filename)

    if(success and self.viewResult):
    self.viewOutput(filename)
    if(success):
    if(self.viewResult):
    self.viewOutput(filename)
    else:
    inkex.debug('Unable to write to file "' + filename + '"')

    else:
    if(self.viewResult):
    if(self.base64Encode):
    inkex.debug('data:image/svg+xml;base64,'+content)
    inkex.debug(content)
    #self.viewOutput('data:image/svg+xml;base64,'+content)
    else:
    inkex.debug(content)
    #self.viewOutput('data:image/svg+xml,'+content)

    else:
    if(self.base64Encode):
    inkex.debug('data:image/svg+xml;base64,'+content)
    else:
    inkex.debug(content)
    inkex.debug(content)

    else:
    inkex.debug('No SVG source available for element ' + node['id'])
  2. larscwallin revised this gist May 6, 2013. No changes.
  3. larscwallin revised this gist May 6, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion larscwallin.inx.extractelements.py
    Original file line number Diff line number Diff line change
    @@ -93,7 +93,7 @@ def effect(self):
    elementBox[1] = (elementBox[1]-elementBox[0])
    elementBox[3] = (elementBox[3]-elementBox[2])

    if(overideElementDim):
    if(overideElementDim == False):
    elementWidth = elementBox[1]
    elementHeight = elementBox[3]
    else:
  4. larscwallin revised this gist May 6, 2013. No changes.
  5. larscwallin revised this gist May 6, 2013. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    A README

    larscwallin.inx.extractelements version 0.1 extracts all selected SVG Elements to file and/or displayed as a string in the Inkscape GUI.

    || UPDATE 130506
    Added movePath method which moves all paths to 0,0 coordinates regardless of their original placement.

    If no elements are selected, the extension now defaults to exporting any visible layers. Precondition for this is that layers have been hidden and then shown again at some point as Inkscape currently does not add this meta data by default.

    || UPDATE 130503
    Added calculation of bounding box and width and height attributes for the resulting SVG doc.
  6. larscwallin revised this gist May 6, 2013. 1 changed file with 40 additions and 13 deletions.
    53 changes: 40 additions & 13 deletions larscwallin.inx.extractelements.py
    Original file line number Diff line number Diff line change
    @@ -57,17 +57,34 @@ def effect(self):

    self.getselected()

    self.svgDoc = self.document.xpath('//svg:svg',namespaces=inkex.NSS)[0]
    self.svgWidth = inkex.unittouu(self.svgDoc.get('width'))
    self.svgHeight = inkex.unittouu(self.svgDoc.get('height'))

    overideElementDim = False

    layers = self.document.xpath('//svg:svg/svg:g[@style!="display:none"]',namespaces=inkex.NSS)

    # If no elements where selected we default to exporting every visible layer in the drawing
    if(self.selected.__len__() <= 0):
    self.selected = layers
    # As we are exporting whole layers we assume that the resulting SVG drawings has the
    # same dimensions as the source document and thus overide the elements bounding box.
    overideElementDim = True
    else:
    self.selected = self.selected.values()

    if(self.selected.__len__() > 0):
    selected = []

    # Iterate through all selected elements
    for element in self.selected.values():
    # Iterate through all elements
    for element in self.selected:

    elementLabel = str(element.get(inkex.addNS('label', 'inkscape'),''))
    elementId = element.get('id')

    tag_name = self.getTagName(element)
    if(tag_name == 'path'):
    tagName= self.getTagName(element)
    if(tagName== 'path'):
    pathData = self.movePath(element,0,0,'tl')
    if(pathData):
    element.set('d',pathData)
    @@ -76,12 +93,19 @@ def effect(self):
    elementBox[1] = (elementBox[1]-elementBox[0])
    elementBox[3] = (elementBox[3]-elementBox[2])

    if(overideElementDim):
    elementWidth = elementBox[1]
    elementHeight = elementBox[3]
    else:
    elementWidth = self.svgWidth
    elementHeight = self.svgHeight

    elementSource = inkex.etree.tostring(element)

    if(elementSource!=''):
    # Wrap the node in an SVG doc
    tplResult = string.replace(self.exportTemplate,'{{element.width}}',str(elementBox[1]))
    tplResult = string.replace(tplResult,'{{element.height}}',str(elementBox[3]))
    tplResult = string.replace(self.exportTemplate,'{{element.width}}',str(elementWidth))
    tplResult = string.replace(tplResult,'{{element.height}}',str(elementHeight))
    tplResult = string.replace(tplResult,'{{element.source}}',elementSource)

    # If the result of the operation is valid, add the SVG source to the selected array
    @@ -133,25 +157,28 @@ def effect(self):

    else:
    inkex.debug('No SVG source available for element ' + node['id'])
    else:
    inkex.debug('No SVG elements or layers to extract.')


    def getTagName(self,node):
    type = node.get(inkex.addNS('type', 'sodipodi'))

    if(type == None):
    #remove namespace data {....}
    tag_name = node.tag
    tag_name = tag_name.split('}')[1]
    tagName= node.tag
    tagName= tagName.split('}')[1]
    else:
    tag_name = str(type)
    tagName= str(type)

    return tag_name
    return tagName


    def movePath(self,node,x,y,origin):
    tag_name = self.getTagName(node)
    tagName= self.getTagName(node)

    if(tag_name != 'path'):
    inkex.debug('movePath only works on SVG Path elements. Argument was of type "' + tag_name + '"')
    if(tagName!= 'path'):
    inkex.debug('movePath only works on SVG Path elements. Argument was of type "' + tagName+ '"')
    return False

    path = simplepath.parsePath(node.get('d'))
  7. larscwallin revised this gist May 6, 2013. 1 changed file with 34 additions and 6 deletions.
    40 changes: 34 additions & 6 deletions larscwallin.inx.extractelements.py
    Original file line number Diff line number Diff line change
    @@ -13,8 +13,8 @@
    import SvgDocument
    import inkex
    import simpletransform

    from simplestyle import *
    import simplepath
    import simplestyle

    class ElementsToSVG(inkex.Effect):

    @@ -65,6 +65,13 @@ def effect(self):

    elementLabel = str(element.get(inkex.addNS('label', 'inkscape'),''))
    elementId = element.get('id')

    tag_name = self.getTagName(element)
    if(tag_name == 'path'):
    pathData = self.movePath(element,0,0,'tl')
    if(pathData):
    element.set('d',pathData)

    elementBox = list(simpletransform.computeBBox([element]))
    elementBox[1] = (elementBox[1]-elementBox[0])
    elementBox[3] = (elementBox[3]-elementBox[2])
    @@ -127,11 +134,32 @@ def effect(self):
    else:
    inkex.debug('No SVG source available for element ' + node['id'])

    def getTagName(self,node):
    type = node.get(inkex.addNS('type', 'sodipodi'))

    if(type == None):
    #remove namespace data {....}
    tag_name = node.tag
    tag_name = tag_name.split('}')[1]
    else:
    tag_name = str(type)

    return tag_name


    def movePath(self,node,x,y,origin):
    path = node.get('path')
    box = node.get('box')
    tag_name = self.getTagName(node)

    if(tag_name != 'path'):
    inkex.debug('movePath only works on SVG Path elements. Argument was of type "' + tag_name + '"')
    return False

    path = simplepath.parsePath(node.get('d'))
    id = node.get('id')

    box = list(simpletransform.computeBBox([node]))

    #inkex.debug(box)
    #inkex.debug(path)

    offset_x = (box[0] - x)
    offset_y = (box[2] - (y))
    @@ -189,6 +217,6 @@ def run(self):

    # Create effect instance and apply it.
    effect = ElementsToSVG()
    effect.affect()
    effect.affect(output=False)

    #inkex.errormsg(_("This will be written to Python stderr"))
  8. larscwallin revised this gist May 3, 2013. 1 changed file with 65 additions and 16 deletions.
    81 changes: 65 additions & 16 deletions larscwallin.inx.extractelements.py
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,4 @@
    #!/usr/bin/env python
    #inkex.errormsg(_("This will be written to Python stderr"))
    # These two lines are only needed if you don't put the script directly into
    # the installation directory
    import sys
    @@ -11,18 +10,19 @@

    sys.path.append('/usr/share/inkscape/extensions')

    import SvgDocument
    import inkex
    from simplestyle import *
    import simpletransform

    # The simplestyle module provides functions for style parsing.
    from simplestyle import *

    class ElementsToSVG(inkex.Effect):

    exportTemplate = """<?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    {{placeholder}}
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="{{element.width}}" height="{{element.height}}">
    {{element.source}}
    </svg>"""

    def __init__(self):
    @@ -51,7 +51,6 @@ def effect(self):
    """
    Effect behaviour.
    """
    # Get script's "--what" option value.
    self.where = self.options.where
    self.base64Encode = self.options.encode
    self.viewResult = self.options.encode
    @@ -64,21 +63,34 @@ def effect(self):
    # Iterate through all selected elements
    for element in self.selected.values():

    currentNodeLabel = str(element.get(inkex.addNS('label', 'inkscape'),''))
    currentNodeId = element.get('id')
    currentNodeSource = inkex.etree.tostring(element)
    elementLabel = str(element.get(inkex.addNS('label', 'inkscape'),''))
    elementId = element.get('id')
    elementBox = list(simpletransform.computeBBox([element]))
    elementBox[1] = (elementBox[1]-elementBox[0])
    elementBox[3] = (elementBox[3]-elementBox[2])

    if(currentNodeSource!=''):
    elementSource = inkex.etree.tostring(element)

    if(elementSource!=''):
    # Wrap the node in an SVG doc
    tplResult = string.replace(self.exportTemplate,'{{placeholder}}',currentNodeSource)
    tplResult = string.replace(self.exportTemplate,'{{element.width}}',str(elementBox[1]))
    tplResult = string.replace(tplResult,'{{element.height}}',str(elementBox[3]))
    tplResult = string.replace(tplResult,'{{element.source}}',elementSource)

    # If the result of the operation is valid, add the SVG source to the selected array
    if(tplResult):
    selected.append([currentNodeId,currentNodeLabel,tplResult])
    selected.append({
    'id':elementId,
    'label':elementLabel,
    'source':tplResult,
    'box':elementBox
    })

    for node in selected:
    #'data:image/svg+xml;base64,'+

    content = node[2]
    # Cache this in a local var
    content = node['source']

    if(content!=''):

    @@ -89,7 +101,7 @@ def effect(self):

    # The easiest way to name rendered elements is by using their id since we can trust that this is always unique.

    filename = os.path.join(self.where, (node[1]+node[0]+'.svg'))
    filename = os.path.join(self.where, (node['id']+node['label']+'.svg'))
    success = self.saveToFile(content,filename)

    if(success and self.viewResult):
    @@ -113,7 +125,42 @@ def effect(self):
    inkex.debug(content)

    else:
    inkex.debug('No SVG source available for element ' + node[0])
    inkex.debug('No SVG source available for element ' + node['id'])

    def movePath(self,node,x,y,origin):
    path = node.get('path')
    box = node.get('box')

    #inkex.debug(box)

    offset_x = (box[0] - x)
    offset_y = (box[2] - (y))

    #inkex.debug('Will move path "'+id+'" from x, y ' + str(box[0]) + ', ' + str(box[2]))
    #inkex.debug('to x, y ' + str(x) + ', ' + str(y))

    #inkex.debug('The x offset is ' + str(offset_x))
    #inkex.debug('The y offset is = ' + str(offset_y))


    for cmd in path:
    params = cmd[1]
    i = 0

    while(i < len(params)):
    if(i % 2 == 0):
    #inkex.debug('x point at ' + str( round( params[i] )))
    params[i] = (params[i] - offset_x)
    #inkex.debug('moved to ' + str( round( params[i] )))
    else:
    #inkex.debug('y point at ' + str( round( params[i]) ))
    params[i] = (params[i] - offset_y)
    #inkex.debug('moved to ' + str( round( params[i] )))
    i = i + 1


    #inkex.debug(simplepath.formatPath(path))
    return simplepath.formatPath(path)


    def saveToFile(self,content,filename):
    @@ -142,4 +189,6 @@ def run(self):

    # Create effect instance and apply it.
    effect = ElementsToSVG()
    effect.affect()
    effect.affect()

    #inkex.errormsg(_("This will be written to Python stderr"))
  9. larscwallin revised this gist Apr 30, 2013. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion larscwallin.inx.extractelements.py
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,6 @@

    sys.path.append('/usr/share/inkscape/extensions')

    import SvgDocument
    import inkex
    from simplestyle import *

  10. larscwallin created this gist Apr 30, 2013.
    18 changes: 18 additions & 0 deletions larscwallin.inx.extractelements.inx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,18 @@
    <inkscape-extension>
    <_name>Extract Elements</_name>
    <id>com.larscwallin.inx.extractelements</id>
    <dependency type="executable" location="extensions">larscwallin.inx.extractelements.py</dependency>
    <dependency type="executable" location="extensions">inkex.py</dependency>
    <param name="where" type="string" _gui-text="Output path"></param>
    <param name="encode" type="boolean" _gui-text="Do you wish to Base64 encode the SVG?">false</param>
    <param name="viewresult" type="boolean" _gui-text="Do you wish to view the resulting?">true</param>
    <effect>
    <object-type>all</object-type>
    <effects-menu>
    <submenu _name="Export"/>
    </effects-menu>
    </effect>
    <script>
    <command reldir="extensions" interpreter="python">larscwallin.inx.extractelements.py</command>
    </script>
    </inkscape-extension>
    146 changes: 146 additions & 0 deletions larscwallin.inx.extractelements.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,146 @@
    #!/usr/bin/env python
    #inkex.errormsg(_("This will be written to Python stderr"))
    # These two lines are only needed if you don't put the script directly into
    # the installation directory
    import sys
    import base64
    import string
    import webbrowser
    import threading
    import os.path

    sys.path.append('/usr/share/inkscape/extensions')

    import SvgDocument
    import inkex
    from simplestyle import *

    # The simplestyle module provides functions for style parsing.

    class ElementsToSVG(inkex.Effect):

    exportTemplate = """<?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    {{placeholder}}
    </svg>"""

    def __init__(self):
    """
    Constructor.
    Defines the "--what" option of a script.
    """
    # Call the base class constructor.
    inkex.Effect.__init__(self)

    self.OptionParser.add_option('-w', '--where', action = 'store',
    type = 'string', dest = 'where', default = '',
    help = '')

    self.OptionParser.add_option('--encode', action = 'store',
    type = 'inkbool', dest = 'encode', default = False,
    help = 'Do you want to Base64 encode the result?')

    self.OptionParser.add_option('--viewresult', action = 'store',
    type = 'inkbool', dest = 'viewresult', default = False,
    help = 'Do you want to view the resulting document?')



    def effect(self):
    """
    Effect behaviour.
    """
    # Get script's "--what" option value.
    self.where = self.options.where
    self.base64Encode = self.options.encode
    self.viewResult = self.options.encode

    self.getselected()

    if(self.selected.__len__() > 0):
    selected = []

    # Iterate through all selected elements
    for element in self.selected.values():

    currentNodeLabel = str(element.get(inkex.addNS('label', 'inkscape'),''))
    currentNodeId = element.get('id')
    currentNodeSource = inkex.etree.tostring(element)

    if(currentNodeSource!=''):
    # Wrap the node in an SVG doc
    tplResult = string.replace(self.exportTemplate,'{{placeholder}}',currentNodeSource)
    # If the result of the operation is valid, add the SVG source to the selected array
    if(tplResult):
    selected.append([currentNodeId,currentNodeLabel,tplResult])

    for node in selected:
    #'data:image/svg+xml;base64,'+

    content = node[2]

    if(content!=''):

    if(self.base64Encode):
    content = (base64.b64encode(content))

    if(self.where!=''):

    # The easiest way to name rendered elements is by using their id since we can trust that this is always unique.

    filename = os.path.join(self.where, (node[1]+node[0]+'.svg'))
    success = self.saveToFile(content,filename)

    if(success and self.viewResult):
    self.viewOutput(filename)
    else:
    inkex.debug('Unable to write to file "' + filename + '"')

    else:
    if(self.viewResult):
    if(self.base64Encode):
    inkex.debug('data:image/svg+xml;base64,'+content)
    #self.viewOutput('data:image/svg+xml;base64,'+content)
    else:
    inkex.debug(content)
    #self.viewOutput('data:image/svg+xml,'+content)

    else:
    if(self.base64Encode):
    inkex.debug('data:image/svg+xml;base64,'+content)
    else:
    inkex.debug(content)

    else:
    inkex.debug('No SVG source available for element ' + node[0])


    def saveToFile(self,content,filename):

    FILE = open(filename,'w')

    if(FILE):
    FILE.write(content)
    FILE.close()
    return True
    else:
    return False

    def viewOutput(self,url):
    runner = BrowserRunner()
    runner.url = url
    runner.start()

    class BrowserRunner(threading.Thread):
    url = ''
    def __init__(self):
    threading.Thread.__init__ (self)

    def run(self):
    webbrowser.open('file://' + self.url)

    # Create effect instance and apply it.
    effect = ElementsToSVG()
    effect.affect()